Skip to content

Commit 1698765

Browse files
authored
Merge pull request kubernetes#82005 from sttts/sttts-crds-coerce-generation
apiextensions: set 'metadata.generation: 1' on read from etcd if not set
2 parents 28e8002 + 84d29fc commit 1698765

File tree

3 files changed

+35
-1
lines changed

3 files changed

+35
-1
lines changed

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,7 @@ func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupReso
10201020
d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{
10211021
// drop invalid fields while decoding old CRs (before we haven't had any ObjectMeta validation)
10221022
dropInvalidMetadata: true,
1023+
repairGeneration: true,
10231024
structuralSchemas: t.structuralSchemas,
10241025
structuralSchemaGK: t.structuralSchemaGK,
10251026
preserveUnknownFields: t.preserveUnknownFields,
@@ -1120,6 +1121,7 @@ func (v schemaCoercingConverter) ConvertFieldLabel(gvk schema.GroupVersionKind,
11201121
// - generic pruning of unknown fields following a structural schema.
11211122
type unstructuredSchemaCoercer struct {
11221123
dropInvalidMetadata bool
1124+
repairGeneration bool
11231125

11241126
structuralSchemas map[string]*structuralschema.Structural
11251127
structuralSchemaGK schema.GroupKind
@@ -1154,6 +1156,10 @@ func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error {
11541156
if err := schemaobjectmeta.Coerce(nil, u.Object, v.structuralSchemas[gv.Version], false, v.dropInvalidMetadata); err != nil {
11551157
return err
11561158
}
1159+
// fixup missing generation in very old CRs
1160+
if v.repairGeneration && objectMeta.Generation == 0 {
1161+
objectMeta.Generation = 1
1162+
}
11571163
}
11581164

11591165
// restore meta fields, starting clean

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/schema/objectmeta/coerce_test.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ func TestGetObjectMetaNils(t *testing.T) {
167167
"apiVersion": "v1",
168168
"metadata": map[string]interface{}{
169169
"generateName": nil,
170+
"generation": nil,
170171
"labels": map[string]interface{}{
171172
"foo": nil,
172173
},
@@ -179,7 +180,10 @@ func TestGetObjectMetaNils(t *testing.T) {
179180
t.Fatal(err)
180181
}
181182
if o.GenerateName != "" {
182-
t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName)
183+
t.Errorf("expected null json generateName value to be read as \"\" string, but got: %q", o.GenerateName)
184+
}
185+
if o.Generation != 0 {
186+
t.Errorf("expected null json generation value to be read as zero, but got: %q", o.Generation)
183187
}
184188
if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) {
185189
t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got)
@@ -198,6 +202,9 @@ func TestGetObjectMetaNils(t *testing.T) {
198202
if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected {
199203
t.Errorf("expected generatedName to be %q, got %q", expected, got)
200204
}
205+
if got, expected := o.Generation, pod.ObjectMeta.Generation; got != expected {
206+
t.Errorf("expected generation to be %q, got %q", expected, got)
207+
}
201208
if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) {
202209
t.Errorf("expected labels to be %v, got %v", expected, got)
203210
}

staging/src/k8s.io/apiextensions-apiserver/test/integration/objectmeta_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ func TestPostInvalidObjectMeta(t *testing.T) {
6262

6363
obj := fixtures.NewNoxuInstance("default", "foo")
6464
unstructured.SetNestedField(obj.UnstructuredContent(), int64(42), "metadata", "unknown")
65+
unstructured.SetNestedField(obj.UnstructuredContent(), nil, "metadata", "generation")
6566
unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels")
6667
_, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition)
6768
if err == nil {
@@ -86,6 +87,14 @@ func TestPostInvalidObjectMeta(t *testing.T) {
8687
} else if found {
8788
t.Errorf("unexpected metadata.unknown=%#v: expected this to be pruned", unknown)
8889
}
90+
91+
if generation, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "generation"); err != nil {
92+
t.Errorf("unexpected error getting metadata.generation: %v", err)
93+
} else if !found {
94+
t.Errorf("expected metadata.generation=1: got: %d", generation)
95+
} else if generation != 1 {
96+
t.Errorf("unexpected metadata.generation=%d: expected this to be set to 1", generation)
97+
}
8998
}
9099

91100
func TestInvalidObjectMetaInStorage(t *testing.T) {
@@ -150,6 +159,8 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
150159

151160
original := fixtures.NewNoxuInstance("default", "foo")
152161
unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "metadata", "unknown")
162+
unstructured.SetNestedField(original.UnstructuredContent(), nil, "metadata", "generation")
163+
153164
unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "annotations")
154165
unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"invalid": "x y"}, "metadata", "labels")
155166
unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "embedded", "metadata", "unknown")
@@ -193,6 +204,16 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
193204
t.Errorf("Unexpected to find embedded.metadata.unknown=%#v", unknown)
194205
}
195206

207+
t.Logf("Checking that metadata.generation=1")
208+
209+
if generation, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "generation"); err != nil {
210+
t.Errorf("unexpected error getting metadata.generation: %v", err)
211+
} else if !found {
212+
t.Errorf("expected metadata.generation=1: got: %d", generation)
213+
} else if generation != 1 {
214+
t.Errorf("unexpected metadata.generation=%d: expected this to be set to 1", generation)
215+
}
216+
196217
t.Logf("Checking that ObjectMeta is pruned from wrongly-typed annotations")
197218

198219
if annotations, found, err := unstructured.NestedStringMap(obj.UnstructuredContent(), "metadata", "annotations"); err != nil {

0 commit comments

Comments
 (0)