@@ -607,3 +607,114 @@ func verifyNumPorts(t *testing.T, b []byte, n int) {
607
607
t .Fatalf ("expected %v ports but got %v:\n %v" , expected , actual , string (b ))
608
608
}
609
609
}
610
+
611
+ // TestApplyCRDUnhandledSchema tests that when a CRD has a schema that kube-openapi ToProtoModels cannot handle correctly,
612
+ // apply falls back to non-schema behavior
613
+ func TestApplyCRDUnhandledSchema (t * testing.T ) {
614
+ defer featuregatetesting .SetFeatureGateDuringTest (t , utilfeature .DefaultFeatureGate , genericfeatures .ServerSideApply , true )()
615
+
616
+ server , err := apiservertesting .StartTestServer (t , apiservertesting .NewDefaultTestServerOptions (), nil , framework .SharedEtcd ())
617
+ if err != nil {
618
+ t .Fatal (err )
619
+ }
620
+ defer server .TearDownFn ()
621
+ config := server .ClientConfig
622
+
623
+ apiExtensionClient , err := clientset .NewForConfig (config )
624
+ if err != nil {
625
+ t .Fatal (err )
626
+ }
627
+ dynamicClient , err := dynamic .NewForConfig (config )
628
+ if err != nil {
629
+ t .Fatal (err )
630
+ }
631
+
632
+ noxuDefinition := fixtures .NewNoxuCustomResourceDefinition (apiextensionsv1beta1 .ClusterScoped )
633
+
634
+ // This is a schema that kube-openapi ToProtoModels does not handle correctly.
635
+ // https://github.com/kubernetes/kubernetes/blob/38752f7f99869ed65fb44378360a517649dc2f83/vendor/k8s.io/kube-openapi/pkg/util/proto/document.go#L184
636
+ var c apiextensionsv1beta1.CustomResourceValidation
637
+ err = json .Unmarshal ([]byte (`{
638
+ "openAPIV3Schema": {
639
+ "properties": {
640
+ "TypeFooBar": {
641
+ "type": "array"
642
+ }
643
+ }
644
+ }
645
+ }` ), & c )
646
+ if err != nil {
647
+ t .Fatal (err )
648
+ }
649
+ noxuDefinition .Spec .Validation = & c
650
+
651
+ noxuDefinition , err = fixtures .CreateNewCustomResourceDefinition (noxuDefinition , apiExtensionClient , dynamicClient )
652
+ if err != nil {
653
+ t .Fatal (err )
654
+ }
655
+
656
+ kind := noxuDefinition .Spec .Names .Kind
657
+ apiVersion := noxuDefinition .Spec .Group + "/" + noxuDefinition .Spec .Version
658
+ name := "mytest"
659
+
660
+ rest := apiExtensionClient .Discovery ().RESTClient ()
661
+ yamlBody := []byte (fmt .Sprintf (`
662
+ apiVersion: %s
663
+ kind: %s
664
+ metadata:
665
+ name: %s
666
+ spec:
667
+ replicas: 1` , apiVersion , kind , name ))
668
+ result , err := rest .Patch (types .ApplyPatchType ).
669
+ AbsPath ("/apis" , noxuDefinition .Spec .Group , noxuDefinition .Spec .Version , noxuDefinition .Spec .Names .Plural ).
670
+ Name (name ).
671
+ Param ("fieldManager" , "apply_test" ).
672
+ Body (yamlBody ).
673
+ DoRaw ()
674
+ if err != nil {
675
+ t .Fatalf ("failed to create custom resource with apply: %v:\n %v" , err , string (result ))
676
+ }
677
+ verifyReplicas (t , result , 1 )
678
+
679
+ // Patch object to change the number of replicas
680
+ result , err = rest .Patch (types .MergePatchType ).
681
+ AbsPath ("/apis" , noxuDefinition .Spec .Group , noxuDefinition .Spec .Version , noxuDefinition .Spec .Names .Plural ).
682
+ Name (name ).
683
+ Body ([]byte (`{"spec":{"replicas": 5}}` )).
684
+ DoRaw ()
685
+ if err != nil {
686
+ t .Fatalf ("failed to update number of replicas with merge patch: %v:\n %v" , err , string (result ))
687
+ }
688
+ verifyReplicas (t , result , 5 )
689
+
690
+ // Re-apply, we should get conflicts now, since the number of replicas was changed.
691
+ result , err = rest .Patch (types .ApplyPatchType ).
692
+ AbsPath ("/apis" , noxuDefinition .Spec .Group , noxuDefinition .Spec .Version , noxuDefinition .Spec .Names .Plural ).
693
+ Name (name ).
694
+ Param ("fieldManager" , "apply_test" ).
695
+ Body (yamlBody ).
696
+ DoRaw ()
697
+ if err == nil {
698
+ t .Fatalf ("Expecting to get conflicts when applying object after updating replicas, got no error: %s" , result )
699
+ }
700
+ status , ok := err .(* errors.StatusError )
701
+ if ! ok {
702
+ t .Fatalf ("Expecting to get conflicts as API error" )
703
+ }
704
+ if len (status .Status ().Details .Causes ) != 1 {
705
+ t .Fatalf ("Expecting to get one conflict when applying object after updating replicas, got: %v" , status .Status ().Details .Causes )
706
+ }
707
+
708
+ // Re-apply with force, should work fine.
709
+ result , err = rest .Patch (types .ApplyPatchType ).
710
+ AbsPath ("/apis" , noxuDefinition .Spec .Group , noxuDefinition .Spec .Version , noxuDefinition .Spec .Names .Plural ).
711
+ Name (name ).
712
+ Param ("force" , "true" ).
713
+ Param ("fieldManager" , "apply_test" ).
714
+ Body (yamlBody ).
715
+ DoRaw ()
716
+ if err != nil {
717
+ t .Fatalf ("failed to apply object with force after updating replicas: %v:\n %v" , err , string (result ))
718
+ }
719
+ verifyReplicas (t , result , 1 )
720
+ }
0 commit comments