} } } <ins> const listTypeResourceSchema = ` apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: foos.test spec: group: test names: kind: Foo listKind: FooList plural: foos singular: foo scope: Cluster versions: - name: v1 schema: openAPIV3Schema: type: object properties: numArray: type: array x-kubernetes-list-type: set items: type: object served: true storage: true - name: v2 schema: openAPIV3Schema: type: object properties: numArray2: type: array ` func TestStatusStrategyValidateUpdate(t *testing.T) { crdV1 := &apiextensionsv1.CustomResourceDefinition{} err := yaml.Unmarshal([]byte(listTypeResourceSchema), &crdV1) if err != nil { t.Fatalf("unexpected decoding error: %v", err) } t.Logf("crd v1 details: %v", crdV1) crd := &apiextensions.CustomResourceDefinition{} if err = apiextensionsv1.Convert_v1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(crdV1, crd, nil); err != nil { t.Fatalf("unexpected convert error: %v", err) } t.Logf("crd details: %v", crd) strategy := statusStrategy{} kind := schema.GroupVersionKind{ Version: crd.Spec.Versions[0].Name, Kind:    crd.Spec.Names.Kind, Group:   crd.Spec.Group, } strategy.customResourceStrategy.validator.kind = kind ss, _ := structuralschema.NewStructural(crd.Spec.Versions[0].Schema.OpenAPIV3Schema) strategy.structuralSchemas = map[string]*structuralschema.Structural{ crd.Spec.Versions[0].Name: ss, } ctx := context.TODO() tcs := []struct { name    string old     *unstructured.Unstructured obj     *unstructured.Unstructured isValid bool }{ { name:    "bothValid", old:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "numArray": []interface{}{1, 2}}}, obj:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "numArray": []interface{}{1, 3}, "metadata": map[string]interface{}{"resourceVersion": "1"}}}, isValid: true, }, { name:    "change to invalid", old:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "spec": "old", "numArray": []interface{}{1, 2}}}, obj:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "spec": "new", "numArray": []interface{}{1, 1}, "metadata": map[string]interface{}{"resourceVersion": "1"}}}, isValid: false, }, { name:    "change to valid", old:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "spec": "new", "numArray": []interface{}{1, 1}}}, obj:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "spec": "old", "numArray": []interface{}{1, 2}, "metadata": map[string]interface{}{"resourceVersion": "1"}}}, isValid: true, }, { name:    "keeps invalid", old:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "spec": "new", "numArray": []interface{}{1, 1}}}, obj:     &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "test/v1", "kind": "Foo", "spec": "old", "numArray": []interface{}{1, 1}, "metadata": map[string]interface{}{"resourceVersion": "1"}}}, isValid: true, }, } for _, tc := range tcs { errs := strategy.ValidateUpdate(ctx, tc.obj, tc.old) if tc.isValid && len(errs) > 0 { t.Errorf("%v: unexpected error: %v", tc.name, errs) } if !tc.isValid && len(errs) == 0 { t.Errorf("%v: unexpected non-error", tc.name) } } } </ins>