mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
apiextensions: set 'metadata.generation: 1' during read from etcd if not set
This commit is contained in:
parent
533daf6624
commit
84d29fc8fa
@ -1020,6 +1020,7 @@ func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupReso
|
|||||||
d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{
|
d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{
|
||||||
// drop invalid fields while decoding old CRs (before we haven't had any ObjectMeta validation)
|
// drop invalid fields while decoding old CRs (before we haven't had any ObjectMeta validation)
|
||||||
dropInvalidMetadata: true,
|
dropInvalidMetadata: true,
|
||||||
|
repairGeneration: true,
|
||||||
structuralSchemas: t.structuralSchemas,
|
structuralSchemas: t.structuralSchemas,
|
||||||
structuralSchemaGK: t.structuralSchemaGK,
|
structuralSchemaGK: t.structuralSchemaGK,
|
||||||
preserveUnknownFields: t.preserveUnknownFields,
|
preserveUnknownFields: t.preserveUnknownFields,
|
||||||
@ -1120,6 +1121,7 @@ func (v schemaCoercingConverter) ConvertFieldLabel(gvk schema.GroupVersionKind,
|
|||||||
// - generic pruning of unknown fields following a structural schema.
|
// - generic pruning of unknown fields following a structural schema.
|
||||||
type unstructuredSchemaCoercer struct {
|
type unstructuredSchemaCoercer struct {
|
||||||
dropInvalidMetadata bool
|
dropInvalidMetadata bool
|
||||||
|
repairGeneration bool
|
||||||
|
|
||||||
structuralSchemas map[string]*structuralschema.Structural
|
structuralSchemas map[string]*structuralschema.Structural
|
||||||
structuralSchemaGK schema.GroupKind
|
structuralSchemaGK schema.GroupKind
|
||||||
@ -1154,6 +1156,10 @@ func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error {
|
|||||||
if err := schemaobjectmeta.Coerce(nil, u.Object, v.structuralSchemas[gv.Version], false, v.dropInvalidMetadata); err != nil {
|
if err := schemaobjectmeta.Coerce(nil, u.Object, v.structuralSchemas[gv.Version], false, v.dropInvalidMetadata); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// fixup missing generation in very old CRs
|
||||||
|
if v.repairGeneration && objectMeta.Generation == 0 {
|
||||||
|
objectMeta.Generation = 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore meta fields, starting clean
|
// restore meta fields, starting clean
|
||||||
|
@ -167,6 +167,7 @@ func TestGetObjectMetaNils(t *testing.T) {
|
|||||||
"apiVersion": "v1",
|
"apiVersion": "v1",
|
||||||
"metadata": map[string]interface{}{
|
"metadata": map[string]interface{}{
|
||||||
"generateName": nil,
|
"generateName": nil,
|
||||||
|
"generation": nil,
|
||||||
"labels": map[string]interface{}{
|
"labels": map[string]interface{}{
|
||||||
"foo": nil,
|
"foo": nil,
|
||||||
},
|
},
|
||||||
@ -179,7 +180,10 @@ func TestGetObjectMetaNils(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if o.GenerateName != "" {
|
if o.GenerateName != "" {
|
||||||
t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName)
|
t.Errorf("expected null json generateName value to be read as \"\" string, but got: %q", o.GenerateName)
|
||||||
|
}
|
||||||
|
if o.Generation != 0 {
|
||||||
|
t.Errorf("expected null json generation value to be read as zero, but got: %q", o.Generation)
|
||||||
}
|
}
|
||||||
if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) {
|
if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) {
|
||||||
t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got)
|
t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got)
|
||||||
@ -198,6 +202,9 @@ func TestGetObjectMetaNils(t *testing.T) {
|
|||||||
if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected {
|
if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected {
|
||||||
t.Errorf("expected generatedName to be %q, got %q", expected, got)
|
t.Errorf("expected generatedName to be %q, got %q", expected, got)
|
||||||
}
|
}
|
||||||
|
if got, expected := o.Generation, pod.ObjectMeta.Generation; got != expected {
|
||||||
|
t.Errorf("expected generation to be %q, got %q", expected, got)
|
||||||
|
}
|
||||||
if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) {
|
if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) {
|
||||||
t.Errorf("expected labels to be %v, got %v", expected, got)
|
t.Errorf("expected labels to be %v, got %v", expected, got)
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ func TestPostInvalidObjectMeta(t *testing.T) {
|
|||||||
|
|
||||||
obj := fixtures.NewNoxuInstance("default", "foo")
|
obj := fixtures.NewNoxuInstance("default", "foo")
|
||||||
unstructured.SetNestedField(obj.UnstructuredContent(), int64(42), "metadata", "unknown")
|
unstructured.SetNestedField(obj.UnstructuredContent(), int64(42), "metadata", "unknown")
|
||||||
|
unstructured.SetNestedField(obj.UnstructuredContent(), nil, "metadata", "generation")
|
||||||
unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels")
|
unstructured.SetNestedField(obj.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "labels")
|
||||||
_, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition)
|
_, err = instantiateCustomResource(t, obj, noxuResourceClient, noxuDefinition)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -86,6 +87,14 @@ func TestPostInvalidObjectMeta(t *testing.T) {
|
|||||||
} else if found {
|
} else if found {
|
||||||
t.Errorf("unexpected metadata.unknown=%#v: expected this to be pruned", unknown)
|
t.Errorf("unexpected metadata.unknown=%#v: expected this to be pruned", unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if generation, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "generation"); err != nil {
|
||||||
|
t.Errorf("unexpected error getting metadata.generation: %v", err)
|
||||||
|
} else if !found {
|
||||||
|
t.Errorf("expected metadata.generation=1: got: %d", generation)
|
||||||
|
} else if generation != 1 {
|
||||||
|
t.Errorf("unexpected metadata.generation=%d: expected this to be set to 1", generation)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidObjectMetaInStorage(t *testing.T) {
|
func TestInvalidObjectMetaInStorage(t *testing.T) {
|
||||||
@ -150,6 +159,8 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
|
|||||||
|
|
||||||
original := fixtures.NewNoxuInstance("default", "foo")
|
original := fixtures.NewNoxuInstance("default", "foo")
|
||||||
unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "metadata", "unknown")
|
unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "metadata", "unknown")
|
||||||
|
unstructured.SetNestedField(original.UnstructuredContent(), nil, "metadata", "generation")
|
||||||
|
|
||||||
unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "annotations")
|
unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"foo": int64(42), "bar": "abc"}, "metadata", "annotations")
|
||||||
unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"invalid": "x y"}, "metadata", "labels")
|
unstructured.SetNestedField(original.UnstructuredContent(), map[string]interface{}{"invalid": "x y"}, "metadata", "labels")
|
||||||
unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "embedded", "metadata", "unknown")
|
unstructured.SetNestedField(original.UnstructuredContent(), int64(42), "embedded", "metadata", "unknown")
|
||||||
@ -193,6 +204,16 @@ func TestInvalidObjectMetaInStorage(t *testing.T) {
|
|||||||
t.Errorf("Unexpected to find embedded.metadata.unknown=%#v", unknown)
|
t.Errorf("Unexpected to find embedded.metadata.unknown=%#v", unknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t.Logf("Checking that metadata.generation=1")
|
||||||
|
|
||||||
|
if generation, found, err := unstructured.NestedInt64(obj.UnstructuredContent(), "metadata", "generation"); err != nil {
|
||||||
|
t.Errorf("unexpected error getting metadata.generation: %v", err)
|
||||||
|
} else if !found {
|
||||||
|
t.Errorf("expected metadata.generation=1: got: %d", generation)
|
||||||
|
} else if generation != 1 {
|
||||||
|
t.Errorf("unexpected metadata.generation=%d: expected this to be set to 1", generation)
|
||||||
|
}
|
||||||
|
|
||||||
t.Logf("Checking that ObjectMeta is pruned from wrongly-typed annotations")
|
t.Logf("Checking that ObjectMeta is pruned from wrongly-typed annotations")
|
||||||
|
|
||||||
if annotations, found, err := unstructured.NestedStringMap(obj.UnstructuredContent(), "metadata", "annotations"); err != nil {
|
if annotations, found, err := unstructured.NestedStringMap(obj.UnstructuredContent(), "metadata", "annotations"); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user