1
16
17 package replace
18
19 import (
20 "net/http"
21 "strings"
22 "testing"
23
24 corev1 "k8s.io/api/core/v1"
25 "k8s.io/cli-runtime/pkg/genericiooptions"
26 "k8s.io/cli-runtime/pkg/resource"
27 "k8s.io/client-go/rest/fake"
28 cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
29 "k8s.io/kubectl/pkg/scheme"
30 )
31
32 func TestReplaceObject(t *testing.T) {
33 _, _, rc := cmdtesting.TestData()
34
35 tf := cmdtesting.NewTestFactory().WithNamespace("test")
36 defer tf.Cleanup()
37 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
38
39 deleted := false
40 tf.UnstructuredClient = &fake.RESTClient{
41 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
42 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
43 switch p, m := req.URL.Path, req.Method; {
44 case p == "/api/v1/namespaces/test" && m == http.MethodGet:
45 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
46 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete:
47 deleted = true
48 fallthrough
49 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut:
50 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
51 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet:
52 statusCode := http.StatusOK
53 if deleted {
54 statusCode = http.StatusNotFound
55 }
56 return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
57 case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
58 return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
59 default:
60 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
61 return nil, nil
62 }
63 }),
64 }
65 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
66
67 cmd := NewCmdReplace(tf, streams)
68 cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
69 cmd.Flags().Set("output", "name")
70 cmd.Run(cmd, []string{})
71
72
73 if buf.String() != "replicationcontroller/rc1\n" {
74 t.Errorf("unexpected output: %s", buf.String())
75 }
76
77 buf.Reset()
78 cmd.Flags().Set("force", "true")
79 cmd.Flags().Set("cascade", "false")
80 cmd.Flags().Set("output", "name")
81 cmd.Run(cmd, []string{})
82
83 if buf.String() != "replicationcontroller/redis-master\nreplicationcontroller/rc1\n" {
84 t.Errorf("unexpected output: %s", buf.String())
85 }
86 }
87
88 func TestReplaceMultipleObject(t *testing.T) {
89 _, svc, rc := cmdtesting.TestData()
90
91 tf := cmdtesting.NewTestFactory().WithNamespace("test")
92 defer tf.Cleanup()
93 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
94
95 redisMasterDeleted := false
96 frontendDeleted := false
97 tf.UnstructuredClient = &fake.RESTClient{
98 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
99 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
100 switch p, m := req.URL.Path, req.Method; {
101 case p == "/api/v1/namespaces/test" && m == http.MethodGet:
102 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
103 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodDelete:
104 redisMasterDeleted = true
105 fallthrough
106 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodPut:
107 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
108 case p == "/namespaces/test/replicationcontrollers/redis-master" && m == http.MethodGet:
109 statusCode := http.StatusOK
110 if redisMasterDeleted {
111 statusCode = http.StatusNotFound
112 }
113 return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
114 case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
115 return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
116 case p == "/namespaces/test/services/frontend" && m == http.MethodDelete:
117 frontendDeleted = true
118 fallthrough
119 case p == "/namespaces/test/services/frontend" && m == http.MethodPut:
120 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
121 case p == "/namespaces/test/services/frontend" && m == http.MethodGet:
122 statusCode := http.StatusOK
123 if frontendDeleted {
124 statusCode = http.StatusNotFound
125 }
126 return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
127 case p == "/namespaces/test/services" && m == http.MethodPost:
128 return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &svc.Items[0])}, nil
129 default:
130 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
131 return nil, nil
132 }
133 }),
134 }
135 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
136
137 cmd := NewCmdReplace(tf, streams)
138 cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
139 cmd.Flags().Set("filename", "../../../testdata/frontend-service.yaml")
140 cmd.Flags().Set("output", "name")
141 cmd.Run(cmd, []string{})
142
143 if buf.String() != "replicationcontroller/rc1\nservice/baz\n" {
144 t.Errorf("unexpected output: %s", buf.String())
145 }
146
147 buf.Reset()
148 cmd.Flags().Set("force", "true")
149 cmd.Flags().Set("cascade", "false")
150 cmd.Flags().Set("output", "name")
151 cmd.Run(cmd, []string{})
152
153 if buf.String() != "replicationcontroller/redis-master\nservice/frontend\nreplicationcontroller/rc1\nservice/baz\n" {
154 t.Errorf("unexpected output: %s", buf.String())
155 }
156 }
157
158 func TestReplaceDirectory(t *testing.T) {
159 _, _, rc := cmdtesting.TestData()
160
161 tf := cmdtesting.NewTestFactory().WithNamespace("test")
162 defer tf.Cleanup()
163 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
164
165 created := map[string]bool{}
166 tf.UnstructuredClient = &fake.RESTClient{
167 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
168 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
169 switch p, m := req.URL.Path, req.Method; {
170 case p == "/api/v1/namespaces/test" && m == http.MethodGet:
171 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
172 case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodPut:
173 created[p] = true
174 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
175 case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodGet:
176 statusCode := http.StatusNotFound
177 if created[p] {
178 statusCode = http.StatusOK
179 }
180 return &http.Response{StatusCode: statusCode, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
181 case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers/") && m == http.MethodDelete:
182 delete(created, p)
183 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
184 case strings.HasPrefix(p, "/namespaces/test/replicationcontrollers") && m == http.MethodPost:
185 return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
186 default:
187 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
188 return nil, nil
189 }
190 }),
191 }
192 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
193
194 cmd := NewCmdReplace(tf, streams)
195 cmd.Flags().Set("filename", "../../../testdata/replace/legacy")
196 cmd.Flags().Set("namespace", "test")
197 cmd.Flags().Set("output", "name")
198 cmd.Run(cmd, []string{})
199
200 if buf.String() != "replicationcontroller/rc1\nreplicationcontroller/rc1\nreplicationcontroller/rc1\n" {
201 t.Errorf("unexpected output: %s", buf.String())
202 }
203
204 buf.Reset()
205 cmd.Flags().Set("force", "true")
206 cmd.Flags().Set("cascade", "false")
207 cmd.Run(cmd, []string{})
208
209 if buf.String() != "replicationcontroller/frontend\nreplicationcontroller/redis-master\nreplicationcontroller/redis-slave\n"+
210 "replicationcontroller/rc1\nreplicationcontroller/rc1\nreplicationcontroller/rc1\n" {
211 t.Errorf("unexpected output: %s", buf.String())
212 }
213 }
214
215 func TestForceReplaceObjectNotFound(t *testing.T) {
216 _, _, rc := cmdtesting.TestData()
217
218 tf := cmdtesting.NewTestFactory().WithNamespace("test")
219 defer tf.Cleanup()
220 codec := scheme.Codecs.LegacyCodec(scheme.Scheme.PrioritizedVersionsAllGroups()...)
221
222 tf.UnstructuredClient = &fake.RESTClient{
223 NegotiatedSerializer: resource.UnstructuredPlusDefaultContentConfig().NegotiatedSerializer,
224 Client: fake.CreateHTTPClient(func(req *http.Request) (*http.Response, error) {
225 switch p, m := req.URL.Path, req.Method; {
226 case p == "/api/v1/namespaces/test" && m == http.MethodGet:
227 return &http.Response{StatusCode: http.StatusOK, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &corev1.Namespace{})}, nil
228 case p == "/namespaces/test/replicationcontrollers/redis-master" && (m == http.MethodGet || m == http.MethodDelete):
229 return &http.Response{StatusCode: http.StatusNotFound, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.StringBody("")}, nil
230 case p == "/namespaces/test/replicationcontrollers" && m == http.MethodPost:
231 return &http.Response{StatusCode: http.StatusCreated, Header: cmdtesting.DefaultHeader(), Body: cmdtesting.ObjBody(codec, &rc.Items[0])}, nil
232 default:
233 t.Fatalf("unexpected request: %#v\n%#v", req.URL, req)
234 return nil, nil
235 }
236 }),
237 }
238 streams, _, buf, _ := genericiooptions.NewTestIOStreams()
239
240 cmd := NewCmdReplace(tf, streams)
241 cmd.Flags().Set("filename", "../../../testdata/redis-master-controller.yaml")
242 cmd.Flags().Set("force", "true")
243 cmd.Flags().Set("cascade", "false")
244 cmd.Flags().Set("output", "name")
245 cmd.Run(cmd, []string{})
246
247 if buf.String() != "replicationcontroller/rc1\n" {
248 t.Errorf("unexpected output: %s", buf.String())
249 }
250 }
251
View as plain text