Skip to content

Commit 6fa696d

Browse files
authored
Merge pull request #422 from jiachengxu/preserveunknownfields-dupmarkers
✨Deprecate the duplicated kubebuilder:validation:XPreserveUnknownFields marker.
2 parents d9cb41e + 72b140e commit 6fa696d

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

Diff for: pkg/crd/markers/validation.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,20 @@ var FieldOnlyMarkers = []*definitionWithHelp{
8080
must(markers.MakeAnyTypeDefinition("kubebuilder:default", markers.DescribesField, Default{})).
8181
WithHelp(Default{}.Help()),
8282

83-
must(markers.MakeDefinition("kubebuilder:pruning:PreserveUnknownFields", markers.DescribesField, XPreserveUnknownFields{})).
84-
WithHelp(XPreserveUnknownFields{}.Help()),
8583
must(markers.MakeDefinition("kubebuilder:validation:EmbeddedResource", markers.DescribesField, XEmbeddedResource{})).
8684
WithHelp(XEmbeddedResource{}.Help()),
8785
}
8886

87+
// ValidationIshMarkers are field-and-type markers that don't fall under the
88+
// :validation: prefix, and/or don't have a name that directly matches their
89+
// type.
90+
var ValidationIshMarkers = []*definitionWithHelp{
91+
must(markers.MakeDefinition("kubebuilder:pruning:PreserveUnknownFields", markers.DescribesField, XPreserveUnknownFields{})).
92+
WithHelp(XPreserveUnknownFields{}.Help()),
93+
must(markers.MakeDefinition("kubebuilder:pruning:PreserveUnknownFields", markers.DescribesType, XPreserveUnknownFields{})).
94+
WithHelp(XPreserveUnknownFields{}.Help()),
95+
}
96+
8997
func init() {
9098
AllDefinitions = append(AllDefinitions, ValidationMarkers...)
9199

@@ -101,6 +109,7 @@ func init() {
101109
}
102110

103111
AllDefinitions = append(AllDefinitions, FieldOnlyMarkers...)
112+
AllDefinitions = append(AllDefinitions, ValidationIshMarkers...)
104113
}
105114

106115
// +controllertools:marker:generateHelp:category="CRD validation"
@@ -201,6 +210,10 @@ type Default struct {
201210
// if nested properties or additionalProperties are specified in the schema.
202211
// This can either be true or undefined. False
203212
// is forbidden.
213+
//
214+
// NB: The kubebuilder:validation:XPreserveUnknownFields variant is deprecated
215+
// in favor of the kubebuilder:pruning:PreserveUnknownFields variant. They function
216+
// identically.
204217
type XPreserveUnknownFields struct{}
205218

206219
// +controllertools:marker:generateHelp:category="CRD validation"

Diff for: pkg/crd/markers/zz_generated.markerhelp.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: pkg/crd/testdata/cronjob_types.go

+35
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ limitations under the License.
2323
package cronjob
2424

2525
import (
26+
"encoding/json"
2627
"fmt"
2728

2829
batchv1beta1 "k8s.io/api/batch/v1beta1"
@@ -130,6 +131,9 @@ type CronJobSpec struct {
130131
// +kubebuilder:validation:nullable
131132
UnprunedEmbeddedResource runtime.RawExtension `json:"unprunedEmbeddedResource"`
132133

134+
// This tests that a type-level pruning maker works.
135+
UnprunedFromType Preserved `json:"unprunedFomType"`
136+
133137
// This tests that associative lists work.
134138
// +listType=map
135139
// +listMapKey=name
@@ -152,6 +156,37 @@ type CronJobSpec struct {
152156
MinMaxProperties MinMaxObject `json:"minMaxProperties,omitempty"`
153157
}
154158

159+
// +kubebuilder:validation:Type=object
160+
// +kubebuilder:pruning:PreserveUnknownFields
161+
type Preserved struct {
162+
ConcreteField string `json:"concreteField"`
163+
Rest map[string]interface{} `json:"-"`
164+
}
165+
func (p *Preserved) UnmarshalJSON(data []byte) error {
166+
if err := json.Unmarshal(data, &p.Rest); err != nil {
167+
return err
168+
}
169+
conc, found := p.Rest["concreteField"]
170+
if !found {
171+
return nil
172+
}
173+
concStr, isStr := conc.(string)
174+
if !isStr {
175+
return fmt.Errorf("concreteField was not string")
176+
}
177+
delete(p.Rest, "concreteField")
178+
p.ConcreteField = concStr
179+
return nil
180+
}
181+
func (p *Preserved) MarshalJSON() ([]byte, error) {
182+
full := make(map[string]interface{}, len(p.Rest)+1)
183+
for k, v := range p.Rest {
184+
full[k] = v
185+
}
186+
full["concreteField"] = p.ConcreteField
187+
return json.Marshal(full)
188+
}
189+
155190
type NestedObject struct {
156191
Foo string `json:"foo"`
157192
Bar bool `json:"bar"`

Diff for: pkg/crd/testdata/testdata.kubebuilder.io_cronjobs.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -5120,6 +5120,15 @@ spec:
51205120
type: object
51215121
x-kubernetes-embedded-resource: true
51225122
x-kubernetes-preserve-unknown-fields: true
5123+
unprunedFomType:
5124+
description: This tests that a type-level pruning maker works.
5125+
properties:
5126+
concreteField:
5127+
type: string
5128+
required:
5129+
- concreteField
5130+
type: object
5131+
x-kubernetes-preserve-unknown-fields: true
51235132
unprunedJSON:
51245133
properties:
51255134
bar:
@@ -5147,6 +5156,7 @@ spec:
51475156
- twoOfAKindPart0
51485157
- twoOfAKindPart1
51495158
- unprunedEmbeddedResource
5159+
- unprunedFomType
51505160
- unprunedJSON
51515161
type: object
51525162
status:

0 commit comments

Comments
 (0)