1
16
17 package apiserver
18
19 import (
20 "context"
21 "fmt"
22 "reflect"
23 "testing"
24
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
27 apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
28 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
29 "k8s.io/apiextensions-apiserver/test/integration/fixtures"
30 apierrors "k8s.io/apimachinery/pkg/api/errors"
31 "k8s.io/apimachinery/pkg/types"
32 "k8s.io/client-go/dynamic"
33 apiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
34 "k8s.io/kubernetes/test/integration/framework"
35 )
36
37
38
39 func TestApplyCRDNoSchema(t *testing.T) {
40 server, err := apiservertesting.StartTestServer(t, apiservertesting.NewDefaultTestServerOptions(), nil, framework.SharedEtcd())
41 if err != nil {
42 t.Fatal(err)
43 }
44 defer server.TearDownFn()
45 config := server.ClientConfig
46
47 apiExtensionClient, err := clientset.NewForConfig(config)
48 if err != nil {
49 t.Fatal(err)
50 }
51 dynamicClient, err := dynamic.NewForConfig(config)
52 if err != nil {
53 t.Fatal(err)
54 }
55
56 noxuBetaDefinition := nearlyRemovedBetaMultipleVersionNoxuCRD(apiextensionsv1beta1.ClusterScoped)
57
58 noxuDefinition, err := fixtures.CreateCRDUsingRemovedAPI(server.EtcdClient, server.EtcdStoragePrefix, noxuBetaDefinition, apiExtensionClient, dynamicClient)
59 if err != nil {
60 t.Fatal(err)
61 }
62
63 kind := noxuDefinition.Spec.Names.Kind
64 apiVersion := noxuDefinition.Spec.Group + "/" + noxuDefinition.Spec.Versions[0].Name
65 name := "mytest"
66
67 rest := apiExtensionClient.Discovery().RESTClient()
68 yamlBody := []byte(fmt.Sprintf(`
69 apiVersion: %s
70 kind: %s
71 metadata:
72 name: %s
73 spec:
74 replicas: 1`, apiVersion, kind, name))
75 result, err := rest.Patch(types.ApplyPatchType).
76 AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
77 Name(name).
78 Param("fieldManager", "apply_test").
79 Body(yamlBody).
80 DoRaw(context.TODO())
81 if err != nil {
82 t.Fatalf("failed to create custom resource with apply: %v:\n%v", err, string(result))
83 }
84 verifyReplicas(t, result, 1)
85
86
87 result, err = rest.Patch(types.MergePatchType).
88 AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
89 Name(name).
90 Body([]byte(`{"spec":{"replicas": 5}}`)).
91 DoRaw(context.TODO())
92 if err != nil {
93 t.Fatalf("failed to update number of replicas with merge patch: %v:\n%v", err, string(result))
94 }
95 verifyReplicas(t, result, 5)
96
97
98 result, err = rest.Patch(types.ApplyPatchType).
99 AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
100 Name(name).
101 Param("fieldManager", "apply_test").
102 Body(yamlBody).
103 DoRaw(context.TODO())
104 if err == nil {
105 t.Fatalf("Expecting to get conflicts when applying object after updating replicas, got no error: %s", result)
106 }
107 status, ok := err.(*apierrors.StatusError)
108 if !ok {
109 t.Fatalf("Expecting to get conflicts as API error")
110 }
111 if len(status.Status().Details.Causes) != 1 {
112 t.Fatalf("Expecting to get one conflict when applying object after updating replicas, got: %v", status.Status().Details.Causes)
113 }
114
115
116 result, err = rest.Patch(types.ApplyPatchType).
117 AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
118 Name(name).
119 Param("force", "true").
120 Param("fieldManager", "apply_test").
121 Body(yamlBody).
122 DoRaw(context.TODO())
123 if err != nil {
124 t.Fatalf("failed to apply object with force after updating replicas: %v:\n%v", err, string(result))
125 }
126 verifyReplicas(t, result, 1)
127
128
129 existingManagedFields, err := getManagedFields(result)
130 if err != nil {
131 t.Fatalf("failed to get managedFields from response: %v", err)
132 }
133 updateBytes := []byte(`{
134 "metadata": {
135 "managedFields": [{
136 "manager":"testing",
137 "operation":"Update",
138 "apiVersion":"v1",
139 "fieldsType":"FieldsV1",
140 "fieldsV1":{
141 "f:spec":{
142 "f:containers":{
143 "k:{\"name\":\"testing\"}":{
144 ".":{},
145 "f:image":{},
146 "f:name":{}
147 }
148 }
149 }
150 }
151 }]
152 }
153 }`)
154 result, err = rest.Patch(types.MergePatchType).
155 AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
156 SubResource("status").
157 Name(name).
158 Param("fieldManager", "subresource_test").
159 Body(updateBytes).
160 DoRaw(context.TODO())
161 if err != nil {
162 t.Fatalf("Error updating subresource: %v ", err)
163 }
164 newManagedFields, err := getManagedFields(result)
165 if err != nil {
166 t.Fatalf("failed to get managedFields from response: %v", err)
167 }
168 if !reflect.DeepEqual(existingManagedFields, newManagedFields) {
169 t.Fatalf("Expected managed fields to not have changed when trying manually setting them via subresoures.\n\nExpected: %#v\n\nGot: %#v", existingManagedFields, newManagedFields)
170 }
171
172
173 result, err = rest.Patch(types.MergePatchType).
174 AbsPath("/apis", noxuDefinition.Spec.Group, noxuDefinition.Spec.Versions[0].Name, noxuDefinition.Spec.Names.Plural).
175 Name(name).
176 Param("fieldManager", "subresource_test").
177 Body([]byte(`{"metadata":{"managedFields":[{}]}}`)).
178 DoRaw(context.TODO())
179 if err != nil {
180 t.Fatalf("Error updating managed fields of the main resource: %v ", err)
181 }
182 newManagedFields, err = getManagedFields(result)
183 if err != nil {
184 t.Fatalf("failed to get managedFields from response: %v", err)
185 }
186
187 if len(newManagedFields) != 0 {
188 t.Fatalf("Expected managed fields to have been reset, but got: %v", newManagedFields)
189 }
190 }
191
192 func nearlyRemovedBetaMultipleVersionNoxuCRD(scope apiextensionsv1beta1.ResourceScope) *apiextensionsv1beta1.CustomResourceDefinition {
193 return &apiextensionsv1beta1.CustomResourceDefinition{
194 ObjectMeta: metav1.ObjectMeta{Name: "noxus.mygroup.example.com"},
195 Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
196 Group: "mygroup.example.com",
197 Version: "v1beta1",
198 Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
199 Plural: "noxus",
200 Singular: "nonenglishnoxu",
201 Kind: "WishIHadChosenNoxu",
202 ShortNames: []string{"foo", "bar", "abc", "def"},
203 ListKind: "NoxuItemList",
204 Categories: []string{"all"},
205 },
206 Scope: scope,
207 Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{
208 {
209 Name: "v1beta1",
210 Served: true,
211 Storage: false,
212 },
213 {
214 Name: "v1beta2",
215 Served: true,
216 Storage: true,
217 },
218 {
219 Name: "v0",
220 Served: false,
221 Storage: false,
222 },
223 },
224 Subresources: &apiextensionsv1beta1.CustomResourceSubresources{
225 Status: &apiextensionsv1beta1.CustomResourceSubresourceStatus{},
226 },
227 },
228 }
229 }
230
View as plain text