1#!/usr/bin/env bash
2
3# Copyright 2018 The Kubernetes Authors.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17set -o errexit
18set -o nounset
19set -o pipefail
20
21run_configmap_tests() {
22 set -o nounset
23 set -o errexit
24
25 create_and_use_new_namespace
26 kube::log::status "Testing configmaps"
27 kubectl create -f test/fixtures/doc-yaml/user-guide/configmap/configmap.yaml
28 kube::test::get_object_assert 'configmap/test-configmap' "{{${id_field:?}}}" 'test-configmap'
29 kubectl delete configmap test-configmap "${kube_flags[@]:?}"
30
31 ### Create a new namespace
32 # Pre-condition: the test-configmaps namespace does not exist
33 kube::test::get_object_assert 'namespaces' "{{range.items}}{{ if eq $id_field \"test-configmaps\" }}found{{end}}{{end}}:" ':'
34 # Command
35 kubectl create namespace test-configmaps
36 # Post-condition: namespace 'test-configmaps' is created.
37 kube::test::get_object_assert 'namespaces/test-configmaps' "{{$id_field}}" 'test-configmaps'
38
39 ### Create a generic configmap in a specific namespace
40 # Pre-condition: configmap test-configmap and test-binary-configmap does not exist
41 kube::test::get_object_assert 'configmaps' "{{range.items}}{{ if eq $id_field \"test-configmap\" }}found{{end}}{{end}}:" ':'
42 kube::test::get_object_assert 'configmaps' "{{range.items}}{{ if eq $id_field \"test-binary-configmap\" }}found{{end}}{{end}}:" ':'
43 # Dry-run command
44 kubectl create configmap test-configmap --dry-run=client --from-literal=key1=value1 --namespace=test-configmaps
45 kubectl create configmap test-configmap --dry-run=server --from-literal=key1=value1 --namespace=test-configmaps
46 kube::test::get_object_assert 'configmaps' "{{range.items}}{{ if eq $id_field \"test-configmap\" }}found{{end}}{{end}}:" ':'
47 # Command
48 kubectl create configmap test-configmap --from-literal=key1=value1 --namespace=test-configmaps
49 kubectl create configmap test-binary-configmap --from-file <( head -c 256 /dev/urandom ) --namespace=test-configmaps
50 # Post-condition: configmap exists and has expected values
51 kube::test::get_object_assert 'configmap/test-configmap --namespace=test-configmaps' "{{$id_field}}" 'test-configmap'
52 kube::test::get_object_assert 'configmap/test-binary-configmap --namespace=test-configmaps' "{{$id_field}}" 'test-binary-configmap'
53 grep -q "key1: value1" <<< "$(kubectl get configmap/test-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}")"
54 grep -q "binaryData" <<< "$(kubectl get configmap/test-binary-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}")"
55 # Describe command should respect the chunk size parameter
56 kube::test::describe_resource_chunk_size_assert configmaps events "--namespace=test-configmaps"
57 # Clean-up
58 kubectl delete configmap test-configmap --namespace=test-configmaps
59 kubectl delete configmap test-binary-configmap --namespace=test-configmaps
60 kubectl delete namespace test-configmaps
61
62 set +o nounset
63 set +o errexit
64}
65
66# Runs all pod related tests.
67run_pod_tests() {
68 set -o nounset
69 set -o errexit
70
71 kube::log::status "Testing kubectl(v1:pods)"
72
73 ### Create POD valid-pod from JSON
74 # Pre-condition: no POD exists
75 create_and_use_new_namespace
76 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
77 # Command
78 kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
79 # Post-condition: valid-pod POD is created
80 kubectl get "${kube_flags[@]}" pods -o json
81 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
82 kube::test::get_object_assert 'pod valid-pod' "{{$id_field}}" 'valid-pod'
83 kube::test::get_object_assert 'pod/valid-pod' "{{$id_field}}" 'valid-pod'
84 kube::test::get_object_assert 'pods/valid-pod' "{{$id_field}}" 'valid-pod'
85 # pod has field manager for kubectl create
86 output_message=$(kubectl get --show-managed-fields -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
87 kube::test::if_has_string "${output_message}" 'kubectl-create'
88 # Repeat above test using jsonpath template
89 kube::test::get_object_jsonpath_assert pods "{.items[*]$id_field}" 'valid-pod'
90 kube::test::get_object_jsonpath_assert 'pod valid-pod' "{$id_field}" 'valid-pod'
91 kube::test::get_object_jsonpath_assert 'pod/valid-pod' "{$id_field}" 'valid-pod'
92 kube::test::get_object_jsonpath_assert 'pods/valid-pod' "{$id_field}" 'valid-pod'
93 # Describe command should print detailed information
94 kube::test::describe_object_assert pods 'valid-pod' "Name:" "Image:" "Node:" "Labels:" "Status:"
95 # Describe command should print events information by default
96 kube::test::describe_object_events_assert pods 'valid-pod'
97 # Describe command should not print events information when show-events=false
98 kube::test::describe_object_events_assert pods 'valid-pod' false
99 # Describe command should print events information when show-events=true
100 kube::test::describe_object_events_assert pods 'valid-pod' true
101 # Describe command (resource only) should print detailed information
102 kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:"
103
104 # Describe command should print events information by default
105 kube::test::describe_resource_events_assert pods
106 # Describe command should not print events information when show-events=false
107 kube::test::describe_resource_events_assert pods false
108 # Describe command should print events information when show-events=true
109 kube::test::describe_resource_events_assert pods true
110 # Describe command should respect the chunk size parameter
111 kube::test::describe_resource_chunk_size_assert pods events
112
113 ### Dump current valid-pod POD
114 output_pod=$(kubectl get pod valid-pod -o yaml "${kube_flags[@]}")
115
116 ### Delete POD valid-pod by id
117 # Pre-condition: valid-pod POD exists
118 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
119 # Command
120 kubectl delete pod valid-pod "${kube_flags[@]}" --grace-period=0 --force
121 # Post-condition: valid-pod POD doesn't exist
122 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
123
124 ### Delete POD valid-pod by id with --now
125 # Pre-condition: valid-pod POD exists
126 kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
127 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
128 # Command
129 kubectl delete pod valid-pod "${kube_flags[@]}" --now
130 # Post-condition: valid-pod POD doesn't exist
131 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
132
133 ### Delete POD valid-pod by id with --grace-period=0
134 # Pre-condition: valid-pod POD exists
135 kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
136 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
137 # Command succeeds without --force by waiting
138 kubectl delete pod valid-pod "${kube_flags[@]}" --grace-period=0
139 # Post-condition: valid-pod POD doesn't exist
140 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
141
142 ### Create POD valid-pod from dumped YAML
143 # Pre-condition: no POD exists
144 create_and_use_new_namespace
145 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
146 # Command
147 echo "${output_pod}" | ${SED} '/namespace:/d' | kubectl create -f - "${kube_flags[@]}"
148 # Post-condition: valid-pod POD is created
149 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
150
151 ### Delete POD valid-pod from JSON
152 # Pre-condition: valid-pod POD exists
153 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
154 # Command
155 kubectl delete -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}" --grace-period=0 --force
156 # Post-condition: valid-pod POD doesn't exist
157 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
158
159 ### Create POD valid-pod from JSON
160 # Pre-condition: no POD exists
161 create_and_use_new_namespace
162 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
163 # Command
164 kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
165 # Post-condition: valid-pod POD is created
166 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" "valid-pod:"
167
168 ### Delete POD valid-pod with label
169 # Pre-condition: valid-pod POD exists
170 kube::test::get_object_assert "pods -lname=valid-pod" "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
171 # Command
172 kubectl delete pods -lname=valid-pod "${kube_flags[@]}" --grace-period=0 --force
173 # Post-condition: valid-pod POD doesn't exist
174 kube::test::get_object_assert "pods -lname=valid-pod" "{{range.items}}{{$id_field}}:{{end}}" ''
175
176 ### Create POD valid-pod from YAML
177 # Pre-condition: no POD exists
178 create_and_use_new_namespace
179 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
180 # Command
181 kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
182 # Post-condition: valid-pod POD is created
183 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
184 # Command
185 output_message=$(kubectl get pods --field-selector metadata.name=valid-pod "${kube_flags[@]}")
186 kube::test::if_has_string "${output_message}" "valid-pod"
187 # Command
188 phase=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .status.phase }}')
189 output_message=$(kubectl get pods --field-selector status.phase="${phase}" "${kube_flags[@]}")
190 kube::test::if_has_string "${output_message}" "valid-pod"
191
192 ### Delete PODs with no parameter mustn't kill everything
193 # Pre-condition: valid-pod POD exists
194 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
195 # Command
196 ! kubectl delete pods "${kube_flags[@]}" || exit 1
197 # Post-condition: valid-pod POD exists
198 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
199
200 ### Delete PODs with --all and a label selector is not permitted
201 # Pre-condition: valid-pod POD exists
202 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
203 # Command
204 ! kubectl delete --all pods -lname=valid-pod "${kube_flags[@]}" || exit 1
205 # Post-condition: valid-pod POD exists
206 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
207
208 ### Delete all PODs
209 # Pre-condition: valid-pod POD exists
210 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
211 # Command
212 kubectl delete --all pods "${kube_flags[@]}" --grace-period=0 --force # --all remove all the pods
213 # Post-condition: no POD exists
214 kube::test::get_object_assert "pods -lname=valid-pod" "{{range.items}}{{$id_field}}:{{end}}" ''
215
216 # Detailed tests for describe pod output
217 ### Create a new namespace
218 # Pre-condition: the test-secrets namespace does not exist
219 kube::test::get_object_assert 'namespaces' "{{range.items}}{{ if eq $id_field \"test-kubectl-describe-pod\" }}found{{end}}{{end}}:" ':'
220 # Command
221 kubectl create namespace test-kubectl-describe-pod
222 # Post-condition: namespace 'test-secrets' is created.
223 kube::test::get_object_assert 'namespaces/test-kubectl-describe-pod' "{{$id_field}}" 'test-kubectl-describe-pod'
224
225 ### Create a generic secret
226 # Pre-condition: no SECRET exists
227 kube::test::get_object_assert 'secrets --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
228 # Dry-run command
229 kubectl create secret generic test-secret --dry-run=client --from-literal=key-1=value1 --type=test-type --namespace=test-kubectl-describe-pod
230 kubectl create secret generic test-secret --dry-run=server --from-literal=key-1=value1 --type=test-type --namespace=test-kubectl-describe-pod
231 kube::test::get_object_assert 'secrets --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
232 # Command
233 kubectl create secret generic test-secret --from-literal=key-1=value1 --type=test-type --namespace=test-kubectl-describe-pod
234 # Post-condition: secret exists and has expected values
235 kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{$id_field}}" 'test-secret'
236 kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{${secret_type:?}}}" 'test-type'
237
238 ### Create a generic configmap
239 # Pre-condition: CONFIGMAP test-configmap does not exist
240 #kube::test::get_object_assert 'configmap/test-configmap --namespace=test-kubectl-describe-pod' "{{$id_field}}" ''
241 kube::test::get_object_assert 'configmaps --namespace=test-kubectl-describe-pod' "{{range.items}}{{ if eq $id_field \"test-configmap\" }}found{{end}}{{end}}:" ':'
242
243 #kube::test::get_object_assert 'configmaps --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
244 # Command
245 kubectl create configmap test-configmap --from-literal=key-2=value2 --namespace=test-kubectl-describe-pod
246 # Post-condition: configmap exists and has expected values
247 kube::test::get_object_assert 'configmap/test-configmap --namespace=test-kubectl-describe-pod' "{{$id_field}}" 'test-configmap'
248
249 ### Create a pod disruption budget with minAvailable
250 # Pre-condition: pdb does not exist
251 kube::test::get_object_assert 'pdb --namespace=test-kubectl-describe-pod' "{{range.items}}{{ if eq $id_field \"test-pdb-1\" }}found{{end}}{{end}}:" ':'
252 # Dry-run command
253 kubectl create pdb test-pdb-1 --dry-run=client --selector=app=rails --min-available=2 --namespace=test-kubectl-describe-pod
254 kubectl create pdb test-pdb-1 --dry-run=server --selector=app=rails --min-available=2 --namespace=test-kubectl-describe-pod
255 kube::test::get_object_assert 'pdb --namespace=test-kubectl-describe-pod' "{{range.items}}{{ if eq $id_field \"test-pdb-1\" }}found{{end}}{{end}}:" ':'
256 # Command
257 kubectl create pdb test-pdb-1 --selector=app=rails --min-available=2 --namespace=test-kubectl-describe-pod
258 # Post-condition: pdb exists and has expected values
259 kube::test::get_object_assert 'pdb/test-pdb-1 --namespace=test-kubectl-describe-pod' "{{${pdb_min_available:?}}}" '2'
260 # Command
261 kubectl create pdb test-pdb-2 --selector=app=rails --min-available=50% --namespace=test-kubectl-describe-pod
262 # Post-condition: pdb exists and has expected values
263 kube::test::get_object_assert 'pdb/test-pdb-2 --namespace=test-kubectl-describe-pod' "{{$pdb_min_available}}" '50%'
264 # Describe command should respect the chunk size parameter
265 kube::test::describe_resource_chunk_size_assert poddisruptionbudgets events "--namespace=test-kubectl-describe-pod"
266
267 ### Create a pod disruption budget with maxUnavailable
268 # Command
269 kubectl create pdb test-pdb-3 --selector=app=rails --max-unavailable=2 --namespace=test-kubectl-describe-pod
270 # Post-condition: pdb exists and has expected values
271 kube::test::get_object_assert 'pdb/test-pdb-3 --namespace=test-kubectl-describe-pod' "{{${pdb_max_unavailable:?}}}" '2'
272 # Command
273 kubectl create pdb test-pdb-4 --selector=app=rails --max-unavailable=50% --namespace=test-kubectl-describe-pod
274 # Post-condition: pdb exists and has expected values
275 kube::test::get_object_assert 'pdb/test-pdb-4 --namespace=test-kubectl-describe-pod' "{{$pdb_max_unavailable}}" '50%'
276
277 ### Fail creating a pod disruption budget if both maxUnavailable and minAvailable specified
278 ! kubectl create pdb test-pdb --selector=app=rails --min-available=2 --max-unavailable=3 --namespace=test-kubectl-describe-pod || exit 1
279
280 # Create a pod that consumes secret, configmap, and downward API keys as envs
281 kube::test::get_object_assert 'pods --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
282 kubectl create -f hack/testdata/pod-with-api-env.yaml --namespace=test-kubectl-describe-pod
283
284 kube::test::describe_object_assert 'pods --namespace=test-kubectl-describe-pod' 'env-test-pod' "TEST_CMD_1" "<set to the key 'key-1' in secret 'test-secret'>" "TEST_CMD_2" "<set to the key 'key-2' of config map 'test-configmap'>" "TEST_CMD_3" "env-test-pod (v1:metadata.name)"
285 # Describe command (resource only) should print detailed information about environment variables
286 kube::test::describe_resource_assert 'pods --namespace=test-kubectl-describe-pod' "TEST_CMD_1" "<set to the key 'key-1' in secret 'test-secret'>" "TEST_CMD_2" "<set to the key 'key-2' of config map 'test-configmap'>" "TEST_CMD_3" "env-test-pod (v1:metadata.name)"
287
288 # Clean-up
289 kubectl delete pod env-test-pod --namespace=test-kubectl-describe-pod
290 kubectl delete secret test-secret --namespace=test-kubectl-describe-pod
291 kubectl delete configmap test-configmap --namespace=test-kubectl-describe-pod
292 kubectl delete pdb/test-pdb-1 pdb/test-pdb-2 pdb/test-pdb-3 pdb/test-pdb-4 --namespace=test-kubectl-describe-pod
293 kubectl delete namespace test-kubectl-describe-pod
294
295 ### Priority Class
296 kube::test::get_object_assert 'priorityclasses' "{{range.items}}{{ if eq $id_field \"test-priorityclass\" }}found{{end}}{{end}}:" ':'
297 # Dry-run command
298 kubectl create priorityclass test-priorityclass --dry-run=client
299 kubectl create priorityclass test-priorityclass --dry-run=server
300 kube::test::get_object_assert 'priorityclasses' "{{range.items}}{{ if eq $id_field \"test-priorityclass\" }}found{{end}}{{end}}:" ':'
301 # Command
302 kubectl create priorityclass test-priorityclass
303 kube::test::get_object_assert 'priorityclasses' "{{range.items}}{{ if eq $id_field \"test-priorityclass\" }}found{{end}}{{end}}:" 'found:'
304 # Describe command should respect the chunk size parameter
305 kube::test::describe_resource_chunk_size_assert priorityclasses events
306 kubectl delete priorityclass test-priorityclass
307
308 ### Create two PODs
309 # Pre-condition: no POD exists
310 create_and_use_new_namespace
311 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
312 # Command
313 kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
314 kubectl create -f test/e2e/testing-manifests/kubectl/agnhost-primary-pod.yaml "${kube_flags[@]}"
315 # Post-condition: valid-pod and agnhost-primary PODs are created
316 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'agnhost-primary:valid-pod:'
317
318 ### Delete multiple PODs at once
319 # Pre-condition: valid-pod and agnhost-primary PODs exist
320 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'agnhost-primary:valid-pod:'
321 # Command
322 kubectl delete pods valid-pod agnhost-primary "${kube_flags[@]}" --grace-period=0 --force # delete multiple pods at once
323 # Post-condition: no POD exists
324 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
325
326 ### Create valid-pod POD
327 # Pre-condition: no POD exists
328 create_and_use_new_namespace
329 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
330 # Command
331 kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
332 # Post-condition: valid-pod POD is created
333 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
334
335 ### Dry-run label the valid-pod POD
336 # Pre-condition: valid-pod is not labelled
337 kube::test::get_object_assert 'pod valid-pod' "{{range${labels_field:?}}}{{.}}:{{end}}" 'valid-pod:'
338 # Command
339 kubectl label pods valid-pod new-name=new-valid-pod --dry-run=client "${kube_flags[@]}"
340 kubectl label pods valid-pod new-name=new-valid-pod --dry-run=server "${kube_flags[@]}"
341 # Post-condition: valid-pod is not labelled
342 kube::test::get_object_assert 'pod valid-pod' "{{range${labels_field:?}}}{{.}}:{{end}}" 'valid-pod:'
343
344 ### Label the valid-pod POD
345 # Pre-condition: valid-pod is not labelled
346 kube::test::get_object_assert 'pod valid-pod' "{{range${labels_field:?}}}{{.}}:{{end}}" 'valid-pod:'
347 # Command
348 kubectl label pods valid-pod new-name=new-valid-pod "${kube_flags[@]}"
349 # Post-condition: valid-pod is labelled
350 kube::test::get_object_assert 'pod valid-pod' "{{range$labels_field}}{{.}}:{{end}}" 'valid-pod:new-valid-pod:'
351
352 ### Label the valid-pod POD with empty label value
353 # Pre-condition: valid-pod does not have label "emptylabel"
354 kube::test::get_object_assert 'pod valid-pod' "{{range$labels_field}}{{.}}:{{end}}" 'valid-pod:new-valid-pod:'
355 # Command
356 kubectl label pods valid-pod emptylabel="" "${kube_flags[@]}"
357 # Post-condition: valid pod contains "emptylabel" with no value
358 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.emptylabel}}" ''
359
360 ### Dry-run annotate the valid-pod POD with empty annotation value
361 # Pre-condition: valid-pod does not have annotation "emptyannotation"
362 kube::test::get_object_assert 'pod valid-pod' "{{${annotations_field:?}.emptyannotation}}" '<no value>'
363 # Command
364 kubectl annotate pods valid-pod emptyannotation="" --dry-run=client "${kube_flags[@]}"
365 kubectl annotate pods valid-pod emptyannotation="" --dry-run=server "${kube_flags[@]}"
366 # Post-condition: valid-pod does not have annotation "emptyannotation"
367 kube::test::get_object_assert 'pod valid-pod' "{{${annotations_field:?}.emptyannotation}}" '<no value>'
368
369 ### Annotate the valid-pod POD with empty annotation value
370 # Pre-condition: valid-pod does not have annotation "emptyannotation"
371 kube::test::get_object_assert 'pod valid-pod' "{{${annotations_field:?}.emptyannotation}}" '<no value>'
372 # Command
373 kubectl annotate pods valid-pod emptyannotation="" "${kube_flags[@]}"
374 # Post-condition: valid pod contains "emptyannotation" with no value
375 kube::test::get_object_assert 'pod valid-pod' "{{${annotations_field}.emptyannotation}}" ''
376 # pod has field for kubectl annotate field manager
377 output_message=$(kubectl get pod valid-pod -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
378 kube::test::if_has_string "${output_message}" 'kubectl-annotate'
379
380 ### Record label change
381 # Pre-condition: valid-pod does not have record annotation
382 kube::test::get_object_assert 'pod valid-pod' "{{range.items}}{{$annotations_field}}:{{end}}" ''
383 # Command
384 kubectl label pods valid-pod record-change=true --record=true "${kube_flags[@]}"
385 # Post-condition: valid-pod has record annotation
386 kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*--record=true.*"
387 # pod has field for kubectl label field manager
388 output_message=$(kubectl get pod valid-pod -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
389 kube::test::if_has_string "${output_message}" 'kubectl-label'
390
391 ### Do not record label change
392 # Command
393 kubectl label pods valid-pod no-record-change=true --record=false "${kube_flags[@]}"
394 # Post-condition: valid-pod's record annotation still contains command with --record=true
395 kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*--record=true.*"
396
397 ### Record label change with specified flag and previous change already recorded
398 ### we are no longer tricked by data from another user into revealing more information about our client
399 # Command
400 kubectl label pods valid-pod new-record-change=true --record=true "${kube_flags[@]}"
401 # Post-condition: valid-pod's record annotation contains new change
402 kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*new-record-change=true.*"
403
404
405 ### Delete POD by label
406 # Pre-condition: valid-pod POD exists
407 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
408 # Command
409 kubectl delete pods -lnew-name=new-valid-pod --grace-period=0 --force "${kube_flags[@]}"
410 # Post-condition: valid-pod POD doesn't exist
411 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
412
413 ### Create pod-with-precision POD
414 # Pre-condition: no POD is running
415 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
416 # Command
417 kubectl create -f hack/testdata/pod-with-precision.json "${kube_flags[@]}"
418 # Post-condition: valid-pod POD is running
419 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'pod-with-precision:'
420
421 ## Patch preserves precision
422 # Command
423 kubectl patch "${kube_flags[@]}" pod pod-with-precision -p='{"metadata":{"annotations":{"patchkey": "patchvalue"}}}'
424 # Post-condition: pod-with-precision POD has patched annotation
425 kube::test::get_object_assert 'pod pod-with-precision' "{{${annotations_field}.patchkey}}" 'patchvalue'
426 # Command
427 kubectl label pods pod-with-precision labelkey=labelvalue "${kube_flags[@]}"
428 # Post-condition: pod-with-precision POD has label
429 kube::test::get_object_assert 'pod pod-with-precision' "{{${labels_field}.labelkey}}" 'labelvalue'
430 # Command
431 kubectl annotate pods pod-with-precision annotatekey=annotatevalue "${kube_flags[@]}"
432 # Post-condition: pod-with-precision POD has annotation
433 kube::test::get_object_assert 'pod pod-with-precision' "{{${annotations_field}.annotatekey}}" 'annotatevalue'
434 # Cleanup
435 kubectl delete pod pod-with-precision "${kube_flags[@]}"
436
437 ### Annotate POD YAML file locally without effecting the live pod.
438 kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
439 # Command
440 kubectl annotate -f hack/testdata/pod.yaml annotatekey=annotatevalue "${kube_flags[@]}"
441
442 # Pre-condition: annotationkey is annotationvalue
443 kube::test::get_object_assert 'pod test-pod' "{{${annotations_field}.annotatekey}}" 'annotatevalue'
444
445 # Command
446 output_message=$(kubectl annotate --local -f hack/testdata/pod.yaml annotatekey=localvalue -o yaml "${kube_flags[@]}")
447 echo "$output_message"
448
449 # Post-condition: annotationkey is still annotationvalue in the live pod, but command output is the new value
450 kube::test::get_object_assert 'pod test-pod' "{{${annotations_field}.annotatekey}}" 'annotatevalue'
451 kube::test::if_has_string "${output_message}" "localvalue"
452
453 # Cleanup
454 kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
455
456 ### Create valid-pod POD
457 # Pre-condition: no services and no rcs exist
458 kube::test::get_object_assert service "{{range.items}}{{$id_field}}:{{end}}" ''
459 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
460 ## kubectl create --edit can update the label filed of multiple resources. tmp-editor.sh is a fake editor
461 TEMP=$(mktemp /tmp/tmp-editor-XXXXXXXX.sh)
462 echo -e "#!/usr/bin/env bash\n${SED} -i \"s/mock/modified/g\" \$1" > "${TEMP}"
463 chmod +x "${TEMP}"
464 # Command
465 EDITOR=${TEMP} kubectl create --edit -f hack/testdata/multi-resource-json.json "${kube_flags[@]}"
466 # Post-condition: service named modified and rc named modified are created
467 kube::test::get_object_assert service "{{range.items}}{{$id_field}}:{{end}}" 'modified:'
468 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'modified:'
469 # resources have field manager for kubectl create
470 output_message=$(kubectl get service/modified -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
471 kube::test::if_has_string "${output_message}" 'kubectl-create'
472 output_message=$(kubectl get rc/modified -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
473 kube::test::if_has_string "${output_message}" 'kubectl-create'
474 # Clean up
475 kubectl delete service/modified "${kube_flags[@]}"
476 kubectl delete rc/modified "${kube_flags[@]}"
477
478 # Pre-condition: no services and no rcs exist
479 kube::test::get_object_assert service "{{range.items}}{{$id_field}}:{{end}}" ''
480 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
481 # Command
482 EDITOR=${TEMP} kubectl create --edit -f hack/testdata/multi-resource-list.json "${kube_flags[@]}"
483 # Post-condition: service named modified and rc named modified are created
484 kube::test::get_object_assert service "{{range.items}}{{$id_field}}:{{end}}" 'modified:'
485 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'modified:'
486 # Clean up
487 rm "${TEMP}"
488 kubectl delete service/modified "${kube_flags[@]}"
489 kubectl delete rc/modified "${kube_flags[@]}"
490
491 ## kubectl create --edit won't create anything if user makes no changes
492 grep -q 'Edit cancelled' <<< "$(EDITOR="cat" kubectl create --edit -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -o json 2>&1)"
493
494 ## Create valid-pod POD
495 # Pre-condition: no POD exists
496 kube::test::wait_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
497 # Command
498 kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
499 # Post-condition: valid-pod POD is created
500 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
501
502 ## Patch can modify a local object
503 kubectl patch --local -f test/fixtures/pkg/kubectl/cmd/patch/validPod.yaml --patch='{"spec": {"restartPolicy":"Never"}}' -o yaml | grep -q "Never"
504
505 ## Patch fails with type restore error and exit code 1
506 output_message=$(! kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"metadata":{"labels":"invalid"}}' 2>&1)
507 kube::test::if_has_string "${output_message}" 'cannot restore map from string'
508
509 ## Patch exits with error message "patched (no change)" and exit code 0 when no-op occurs
510 output_message=$(kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"metadata":{"labels":{"name":"valid-pod"}}}' 2>&1)
511 kube::test::if_has_string "${output_message}" 'patched (no change)'
512
513 ## Patch pod can change image
514 # Command
515 kubectl patch "${kube_flags[@]}" pod valid-pod --record -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}'
516 # Post-condition: valid-pod POD has image nginx
517 kube::test::get_object_assert pods "{{range.items}}{{${image_field:?}}}:{{end}}" 'nginx:'
518 # Post-condition: valid-pod has the record annotation
519 kube::test::get_object_assert pods "{{range.items}}{{$annotations_field}}:{{end}}" "${change_cause_annotation:?}"
520 # prove that patch can use different types
521 kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx2"}]'
522 # Post-condition: valid-pod POD has image nginx
523 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx2:'
524 # prove that patch can use different types
525 kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx"}]'
526 # Post-condition: valid-pod POD has image nginx
527 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
528 # Dry-run change image
529 kubectl patch "${kube_flags[@]}" pod valid-pod --record --dry-run=client -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "not-nginx"}]}}'
530 kubectl patch "${kube_flags[@]}" pod valid-pod --record --dry-run=server -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "not-nginx"}]}}'
531 # Post-condition: valid-pod POD has image nginx
532 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
533 # prove that yaml input works too
534 YAML_PATCH=$'spec:\n containers:\n - name: kubernetes-serve-hostname\n image: changed-with-yaml\n'
535 kubectl patch "${kube_flags[@]}" pod valid-pod -p="${YAML_PATCH}"
536 # Post-condition: valid-pod POD has image nginx
537 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'changed-with-yaml:'
538 ## Patch pod from JSON can change image
539 # Command
540 kubectl patch "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "registry.k8s.io/pause:3.9"}]}}'
541 # Post-condition: valid-pod POD has expected image
542 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'registry.k8s.io/pause:3.9:'
543
544 # pod has field for kubectl patch field manager
545 output_message=$(kubectl get pod valid-pod -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
546 kube::test::if_has_string "${output_message}" 'kubectl-patch'
547
548 ## If resourceVersion is specified in the patch, it will be treated as a precondition, i.e., if the resourceVersion is different from that is stored in the server, the Patch should be rejected
549 ERROR_FILE="${KUBE_TEMP}/conflict-error"
550 ## If the resourceVersion is the same as the one stored in the server, the patch will be applied.
551 # Command
552 # Needs to retry because other party may change the resource.
553 for count in {0..3}; do
554 resourceVersion=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .metadata.resourceVersion }}')
555 kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'"${resourceVersion}"'"}}' 2> "${ERROR_FILE}" || true
556 if grep -q "the object has been modified" "${ERROR_FILE}"; then
557 kube::log::status "retry $1, error: $(cat "${ERROR_FILE}")"
558 rm "${ERROR_FILE}"
559 sleep $((2**count))
560 else
561 rm "${ERROR_FILE}"
562 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
563 break
564 fi
565 done
566
567 ## If the resourceVersion is the different from the one stored in the server, the patch will be rejected.
568 resourceVersion=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .metadata.resourceVersion }}')
569 ((resourceVersion+=100))
570 # Command
571 kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'"$resourceVersion"'"}}' 2> "${ERROR_FILE}" || true
572 # Post-condition: should get an error reporting the conflict
573 if grep -q "please apply your changes to the latest version and try again" "${ERROR_FILE}"; then
574 kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns error as expected: $(cat "${ERROR_FILE}")"
575 else
576 kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns unexpected error or non-error: $(cat "${ERROR_FILE}")"
577 exit 1
578 fi
579 rm "${ERROR_FILE}"
580
581 ## --force replace pod can change other field, e.g., spec.container.name
582 # Command
583 kubectl get "${kube_flags[@]}" pod valid-pod -o json | ${SED} 's/"kubernetes-serve-hostname"/"replaced-k8s-serve-hostname"/g' > /tmp/tmp-valid-pod.json
584 kubectl replace "${kube_flags[@]}" --force -f /tmp/tmp-valid-pod.json
585 # Post-condition: spec.container.name = "replaced-k8s-serve-hostname"
586 kube::test::get_object_assert 'pod valid-pod' "{{(index .spec.containers 0).name}}" 'replaced-k8s-serve-hostname'
587
588 # Pod has field manager for kubectl replace
589 output_message=$(kubectl get pod valid-pod -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
590 kube::test::if_has_string "${output_message}" 'kubectl-replace'
591
592 ## check replace --grace-period requires --force
593 output_message=$(! kubectl replace "${kube_flags[@]}" --grace-period=1 -f /tmp/tmp-valid-pod.json 2>&1)
594 kube::test::if_has_string "${output_message}" '\-\-grace-period must have \-\-force specified'
595
596 ## check replace --timeout requires --force
597 output_message=$(! kubectl replace "${kube_flags[@]}" --timeout=1s -f /tmp/tmp-valid-pod.json 2>&1)
598 kube::test::if_has_string "${output_message}" '\-\-timeout must have \-\-force specified'
599
600 #cleaning
601 rm /tmp/tmp-valid-pod.json
602
603 ## replace of a cluster scoped resource can succeed
604 # Pre-condition: a node exists
605 kubectl create -f - "${kube_flags[@]}" << __EOF__
606{
607 "kind": "Node",
608 "apiVersion": "v1",
609 "metadata": {
610 "name": "node-v1-test"
611 }
612}
613__EOF__
614 kube::test::get_object_assert "node node-v1-test" "{{range.items}}{{if .metadata.annotations.a}}found{{end}}{{end}}:" ':'
615
616 # Dry-run command
617 kubectl replace --dry-run=server -f - "${kube_flags[@]}" << __EOF__
618{
619 "kind": "Node",
620 "apiVersion": "v1",
621 "metadata": {
622 "name": "node-v1-test",
623 "annotations": {"a":"b"},
624 "resourceVersion": "0"
625 }
626}
627__EOF__
628 kubectl replace --dry-run=client -f - "${kube_flags[@]}" << __EOF__
629{
630 "kind": "Node",
631 "apiVersion": "v1",
632 "metadata": {
633 "name": "node-v1-test",
634 "annotations": {"a":"b"},
635 "resourceVersion": "0"
636 }
637}
638__EOF__
639 kube::test::get_object_assert "node node-v1-test" "{{range.items}}{{if .metadata.annotations.a}}found{{end}}{{end}}:" ':'
640
641 # Command
642 kubectl replace -f - "${kube_flags[@]}" << __EOF__
643{
644 "kind": "Node",
645 "apiVersion": "v1",
646 "metadata": {
647 "name": "node-v1-test",
648 "annotations": {"a":"b"},
649 "resourceVersion": "0"
650 }
651}
652__EOF__
653
654 # Post-condition: the node command succeeds
655 kube::test::get_object_assert "node node-v1-test" "{{.metadata.annotations.a}}" 'b'
656 kubectl delete node node-v1-test "${kube_flags[@]}"
657
658 ## kubectl edit can update the image field of a POD. tmp-editor.sh is a fake editor
659 echo -e "#!/usr/bin/env bash\n${SED} -i \"s/nginx/registry.k8s.io\/serve_hostname/g\" \$1" > /tmp/tmp-editor.sh
660 chmod +x /tmp/tmp-editor.sh
661 # Pre-condition: valid-pod POD has image nginx
662 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
663 grep -q 'Patch:' <<< "$(EDITOR=/tmp/tmp-editor.sh kubectl edit "${kube_flags[@]}" pods/valid-pod --output-patch=true)"
664 # Post-condition: valid-pod POD has image registry.k8s.io/serve_hostname
665 kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'registry.k8s.io/serve_hostname:'
666 # pod has field for kubectl edit field manager
667 output_message=$(kubectl get pod valid-pod -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
668 kube::test::if_has_string "${output_message}" 'kubectl-edit'
669 # cleaning
670 rm /tmp/tmp-editor.sh
671
672 ## kubectl edit should work on Windows
673 grep -q 'Edit cancelled' <<< "$(EDITOR="cat" kubectl edit pod/valid-pod 2>&1)"
674 grep -q 'name: valid-pod' <<< "$(EDITOR="cat" kubectl edit pod/valid-pod)"
675 grep -q CRLF <<< "$(EDITOR="cat" kubectl edit --windows-line-endings pod/valid-pod | file - )"
676 ! grep -q CRLF <<< "$(EDITOR="cat" kubectl edit --windows-line-endings=false pod/valid-pod | file - )" || exit 1
677 grep -q 'kind: List' <<< "$(EDITOR="cat" kubectl edit ns)"
678
679 ### Label POD YAML file locally without effecting the live pod.
680 # Pre-condition: name is valid-pod
681 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
682 # Command
683 output_message=$(kubectl label --local --overwrite -f hack/testdata/pod.yaml name=localonlyvalue -o yaml "${kube_flags[@]}")
684 echo "$output_message"
685 # Post-condition: name is still valid-pod in the live pod, but command output is the new value
686 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
687 kube::test::if_has_string "${output_message}" "localonlyvalue"
688
689 ### Overwriting an existing label is not permitted
690 # Pre-condition: name is valid-pod
691 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
692 # Command
693 ! kubectl label pods valid-pod name=valid-pod-super-sayan "${kube_flags[@]}" || exit 1
694 # Post-condition: name is still valid-pod
695 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
696
697 ### --overwrite must be used to overwrite existing label, can be applied to all resources
698 # Pre-condition: name is valid-pod
699 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
700 # Command
701 kubectl label --overwrite pods --all name=valid-pod-super-sayan "${kube_flags[@]}"
702 # Post-condition: name is valid-pod-super-sayan
703 kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod-super-sayan'
704
705 ### Delete POD by label
706 # Pre-condition: valid-pod POD exists
707 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
708 # Command
709 kubectl delete pods -lname=valid-pod-super-sayan --grace-period=0 --force "${kube_flags[@]}"
710 # Post-condition: valid-pod POD doesn't exist
711 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
712
713 ### Create two PODs from 1 yaml file
714 # Pre-condition: no POD exists
715 create_and_use_new_namespace
716 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
717 # Command
718 kubectl create -f test/fixtures/doc-yaml/user-guide/multi-pod.yaml "${kube_flags[@]}"
719 # Post-condition: redis-master and valid-pod PODs exist
720 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-master:valid-pod:'
721
722 ### Delete two PODs from 1 yaml file
723 # Pre-condition: redis-master and valid-pod PODs exist
724 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-master:valid-pod:'
725 # Command
726 kubectl delete -f test/fixtures/doc-yaml/user-guide/multi-pod.yaml "${kube_flags[@]}"
727 # Post-condition: no PODs exist
728 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
729
730 ## kubectl apply should update configuration annotations only if apply is already called
731 ## 1. kubectl create doesn't set the annotation
732 # Pre-Condition: no POD exists
733 create_and_use_new_namespace
734 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
735 # Command: create a pod "test-pod"
736 kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
737 # Post-Condition: pod "test-pod" is created
738 kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-label'
739 # Post-Condition: pod "test-pod" doesn't have configuration annotation
740 ! grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" )" || exit 1
741 ## 2. kubectl replace doesn't set the annotation
742 kubectl get pods test-pod -o yaml "${kube_flags[@]}" | ${SED} 's/test-pod-label/test-pod-replaced/g' > "${KUBE_TEMP}"/test-pod-replace.yaml
743 # Command: replace the pod "test-pod"
744 kubectl replace -f "${KUBE_TEMP}"/test-pod-replace.yaml "${kube_flags[@]}"
745 # Post-Condition: pod "test-pod" is replaced
746 kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-replaced'
747 # Post-Condition: pod "test-pod" doesn't have configuration annotation
748 ! grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}")" || exit 1
749 ## 3. kubectl apply does set the annotation
750 # Command: apply the pod "test-pod"
751 kubectl apply -f hack/testdata/pod-apply.yaml "${kube_flags[@]}"
752 # Post-Condition: pod "test-pod" is applied
753 kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-applied'
754 # Post-Condition: pod "test-pod" has configuration annotation
755 grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}")"
756 kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration > "${KUBE_TEMP}"/annotation-configuration
757 ## 4. kubectl replace updates an existing annotation
758 kubectl get pods test-pod -o yaml "${kube_flags[@]}" | ${SED} 's/test-pod-applied/test-pod-replaced/g' > "${KUBE_TEMP}"/test-pod-replace.yaml
759 # Command: replace the pod "test-pod"
760 kubectl replace -f "${KUBE_TEMP}"/test-pod-replace.yaml "${kube_flags[@]}"
761 # Post-Condition: pod "test-pod" is replaced
762 kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-replaced'
763 # Post-Condition: pod "test-pod" has configuration annotation, and it's updated (different from the annotation when it's applied)
764 grep -q kubectl.kubernetes.io/last-applied-configuration <<< "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" )"
765 kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration > "${KUBE_TEMP}"/annotation-configuration-replaced
766 ! [[ $(diff -q "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced > /dev/null) ]] || exit 1
767 # Clean up
768 rm "${KUBE_TEMP}"/test-pod-replace.yaml "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced
769 kubectl delete pods test-pod "${kube_flags[@]}"
770
771 set +o nounset
772 set +o errexit
773}
774
775# runs specific kubectl create tests
776run_create_secret_tests() {
777 set -o nounset
778 set -o errexit
779
780 ### Create generic secret with explicit namespace
781 # Pre-condition: secret 'mysecret' does not exist
782 output_message=$(! kubectl get secrets mysecret 2>&1 "${kube_flags[@]}")
783 kube::test::if_has_string "${output_message}" 'secrets "mysecret" not found'
784 # Command
785 output_message=$(kubectl create "${kube_flags[@]}" secret generic mysecret --dry-run=client --from-literal=foo=bar -o jsonpath='{.metadata.namespace}' --namespace=user-specified)
786 kube::test::if_has_string "${output_message}" 'user-specified'
787 # Post-condition: mysecret still not created since --dry-run was used
788 # Output from 'create' command should contain the specified --namespace value
789 failure_message=$(! kubectl get secrets mysecret 2>&1 "${kube_flags[@]}")
790 kube::test::if_has_string "${failure_message}" 'secrets "mysecret" not found'
791 # Command
792 output_message=$(kubectl create "${kube_flags[@]}" secret generic mysecret --dry-run=client --from-literal=foo=bar -o jsonpath='{.metadata.namespace}')
793 # Post-condition: jsonpath for .metadata.namespace should be empty for object since --namespace was not explicitly specified
794 kube::test::if_empty_string "${output_message}"
795
796
797 # check to make sure that replace correctly PUTs to a URL
798 kubectl create configmap tester-update-cm -o json --dry-run=client | kubectl create "${kube_flags[@]}" --raw /api/v1/namespaces/default/configmaps -f -
799 output_message=$(kubectl create configmap tester-update-cm --from-literal=key1=config1 -o json --dry-run=client | kubectl replace "${kube_flags[@]}" --raw /api/v1/namespaces/default/configmaps/tester-update-cm -f -)
800 # the message should show the body returned which will include a UID not present in the input
801 kube::test::if_has_string "${output_message}" 'uid'
802 # if the PUT was well-formed, the server will now have a key and value we can retrieve on GET
803 output_message=$(kubectl get "${kube_flags[@]}" --raw /api/v1/namespaces/default/configmaps/tester-update-cm 2>&1 "${kube_flags[@]}")
804 kube::test::if_has_string "${output_message}" 'config1'
805
806 # if DELETE raw works correctly, this will delete the configmap
807 kubectl delete "${kube_flags[@]}" --raw /api/v1/namespaces/default/configmaps/tester-update-cm
808 output_message=$(! kubectl get "${kube_flags[@]}" configmap tester-update-cm 2>&1 "${kube_flags[@]}")
809 kube::test::if_has_string "${output_message}" 'configmaps "tester-update-cm" not found'
810
811 set +o nounset
812 set +o errexit
813}
814
815run_secrets_test() {
816 set -o nounset
817 set -o errexit
818
819 create_and_use_new_namespace
820 kube::log::status "Testing secrets"
821
822 # Ensure dry run succeeds and includes kind, apiVersion and data, and doesn't require a server connection
823 output_message=$(kubectl create secret generic test --from-literal=key1=value1 --dry-run=client -o yaml --server=example.com --v=6)
824 kube::test::if_has_string "${output_message}" 'kind: Secret'
825 kube::test::if_has_string "${output_message}" 'apiVersion: v1'
826 kube::test::if_has_string "${output_message}" 'key1: dmFsdWUx'
827 kube::test::if_has_not_string "${output_message}" 'example.com'
828
829 ### Create a new namespace
830 # Pre-condition: the test-secrets namespace does not exist
831 kube::test::get_object_assert 'namespaces' "{{range.items}}{{ if eq $id_field \"test-secrets\" }}found{{end}}{{end}}:" ':'
832 # Command
833 kubectl create namespace test-secrets
834 # Post-condition: namespace 'test-secrets' is created.
835 kube::test::get_object_assert 'namespaces/test-secrets' "{{$id_field}}" 'test-secrets'
836
837 ### Create a generic secret in a specific namespace
838 # Pre-condition: no SECRET exists
839 kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
840 # Command
841 kubectl create secret generic test-secret --from-literal=key1=value1 --type=test-type --namespace=test-secrets
842 # Post-condition: secret exists and has expected values
843 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
844 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'test-type'
845 grep -q 'key1: dmFsdWUx' <<< "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}")"
846 # Describe command should respect the chunk size parameter
847 kube::test::describe_resource_chunk_size_assert secrets "" "--namespace=test-secrets"
848 # Clean-up
849 kubectl delete secret test-secret --namespace=test-secrets
850
851 ### Create a docker-registry secret in a specific namespace
852 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
853 kube::test::wait_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
854 fi
855 # Pre-condition: no SECRET exists
856 kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
857 # Command
858 kubectl create secret docker-registry test-secret --docker-username=test-user --docker-password=test-password --docker-email='test-user@test.com' --namespace=test-secrets
859 # Post-condition: secret exists and has expected values
860 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
861 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/dockerconfigjson'
862 grep -q '.dockerconfigjson: eyJhdXRocyI6eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsidXNlcm5hbWUiOiJ0ZXN0LXVzZXIiLCJwYXNzd29yZCI6InRlc3QtcGFzc3dvcmQiLCJlbWFpbCI6InRlc3QtdXNlckB0ZXN0LmNvbSIsImF1dGgiOiJkR1Z6ZEMxMWMyVnlPblJsYzNRdGNHRnpjM2R2Y21RPSJ9fX0=' <<< "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}")"
863 # Clean-up
864 kubectl delete secret test-secret --namespace=test-secrets
865
866 ### Create a docker-registry secret in a specific namespace with docker config file
867 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
868 kube::test::wait_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
869 fi
870 # Pre-condition: no SECRET exists
871 kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
872 # Command
873 kubectl create secret docker-registry test-secret --from-file=.dockerconfigjson=hack/testdata/dockerconfig.json --namespace=test-secrets
874 # Post-condition: secret exists and has expected values
875 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
876 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/dockerconfigjson'
877 grep -q '.dockerconfigjson: ewogICAgImF1dGhzIjp7CiAgICAgICAgImh0dHA6Ly9mb28uZXhhbXBsZS5jb20iOnsKICAgICAgICAgICAgInVzZXJuYW1lIjoiZm9vIiwKICAgICAgICAgICAgInBhc3N3b3JkIjoiYmFyIiwKICAgICAgICAgICAgImVtYWlsIjoiZm9vQGV4YW1wbGUuY29tIgogICAgICAgIH0sCiAgICAgICAgImh0dHA6Ly9iYXIuZXhhbXBsZS5jb20iOnsKICAgICAgICAgICAgInVzZXJuYW1lIjoiYmFyIiwKICAgICAgICAgICAgInBhc3N3b3JkIjoiYmF6IiwKICAgICAgICAgICAgImVtYWlsIjoiYmFyQGV4YW1wbGUuY29tIgogICAgICAgIH0KICAgIH0KfQo=' <<< "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}")"
878 # Clean-up
879 kubectl delete secret test-secret --namespace=test-secrets
880
881 ### Create a tls secret
882 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
883 kube::test::wait_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
884 fi
885 # Pre-condition: no SECRET exists
886 kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
887 # Command
888 kubectl create secret tls test-secret --namespace=test-secrets --key=hack/testdata/tls.key --cert=hack/testdata/tls.crt
889 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
890 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/tls'
891 # Clean-up
892 kubectl delete secret test-secret --namespace=test-secrets
893
894 # Command with process substitution
895 kubectl create secret tls test-secret --namespace=test-secrets --key <(cat hack/testdata/tls.key) --cert <(cat hack/testdata/tls.crt)
896 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
897 kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/tls'
898 # Clean-up
899 kubectl delete secret test-secret --namespace=test-secrets
900
901 # Create a secret using stringData
902 kubectl create --namespace=test-secrets -f - "${kube_flags[@]}" << __EOF__
903{
904 "kind": "Secret",
905 "apiVersion": "v1",
906 "metadata": {
907 "name": "secret-string-data"
908 },
909 "data": {
910 "k1":"djE=",
911 "k2":""
912 },
913 "stringData": {
914 "k2":"v2"
915 }
916}
917__EOF__
918 # Post-condition: secret-string-data secret is created with expected data, merged/overridden data from stringData, and a cleared stringData field
919 kube::test::get_object_assert 'secret/secret-string-data --namespace=test-secrets ' '{{.data}}' '.*k1:djE=.*'
920 kube::test::get_object_assert 'secret/secret-string-data --namespace=test-secrets ' '{{.data}}' '.*k2:djI=.*'
921 kube::test::get_object_assert 'secret/secret-string-data --namespace=test-secrets ' '{{.stringData}}' '<no value>'
922 # Clean up
923 kubectl delete secret secret-string-data --namespace=test-secrets
924
925 ### Create a secret using output flags
926 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
927 kube::test::wait_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
928 fi
929 # Pre-condition: no secret exists
930 kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
931 # Command
932 grep -q 'test-secret:' <<< "$(kubectl create secret generic test-secret --namespace=test-secrets --from-literal=key1=value1 --output=go-template --template="{{.metadata.name}}:")"
933 ## Clean-up
934 kubectl delete secret test-secret --namespace=test-secrets
935 # Clean up
936 kubectl delete namespace test-secrets
937
938 set +o nounset
939 set +o errexit
940}
941
942run_service_accounts_tests() {
943 set -o nounset
944 set -o errexit
945
946 create_and_use_new_namespace
947 kube::log::status "Testing service accounts"
948
949 ### Create a new namespace
950 # Pre-condition: the test-service-accounts namespace does not exist
951 kube::test::get_object_assert 'namespaces' "{{range.items}}{{ if eq $id_field \"test-service-accounts\" }}found{{end}}{{end}}:" ':'
952 # Command
953 kubectl create namespace test-service-accounts
954 # Post-condition: namespace 'test-service-accounts' is created.
955 kube::test::get_object_assert 'namespaces/test-service-accounts' "{{$id_field}}" 'test-service-accounts'
956
957 ### Create a service account in a specific namespace
958 # Pre-condition: service account does not exist
959 kube::test::get_object_assert 'serviceaccount --namespace=test-service-accounts' "{{range.items}}{{ if eq $id_field \"test-service-account\" }}found{{end}}{{end}}:" ':'
960 # Dry-run command
961 kubectl create serviceaccount test-service-account --dry-run=client --namespace=test-service-accounts
962 kubectl create serviceaccount test-service-account --dry-run=server --namespace=test-service-accounts
963 kube::test::get_object_assert 'serviceaccount --namespace=test-service-accounts' "{{range.items}}{{ if eq $id_field \"test-service-account\" }}found{{end}}{{end}}:" ':'
964 # Command
965 kubectl create serviceaccount test-service-account --namespace=test-service-accounts
966 # Post-condition: secret exists and has expected values
967 kube::test::get_object_assert 'serviceaccount/test-service-account --namespace=test-service-accounts' "{{$id_field}}" 'test-service-account'
968 # Describe command should respect the chunk size parameter
969 kube::test::describe_resource_chunk_size_assert serviceaccounts secrets,events "--namespace=test-service-accounts"
970 # Clean-up
971 kubectl delete serviceaccount test-service-account --namespace=test-service-accounts
972 # Clean up
973 kubectl delete namespace test-service-accounts
974
975 set +o nounset
976 set +o errexit
977}
978
979run_service_tests() {
980 set -o nounset
981 set -o errexit
982
983 # switch back to the default namespace
984 kubectl config set-context "${CONTEXT}" --namespace=""
985 kube::log::status "Testing kubectl(v1:services)"
986
987 ### Create redis-master service from JSON
988 # Pre-condition: Only the default kubernetes services exist
989 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
990 # Command
991 kubectl create -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml "${kube_flags[@]}"
992 # Post-condition: redis-master service exists
993 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
994 # Describe command should print detailed information
995 kube::test::describe_object_assert services 'redis-master' "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:"
996 # Describe command should print events information by default
997 kube::test::describe_object_events_assert services 'redis-master'
998 # Describe command should not print events information when show-events=false
999 kube::test::describe_object_events_assert services 'redis-master' false
1000 # Describe command should print events information when show-events=true
1001 kube::test::describe_object_events_assert services 'redis-master' true
1002 # Describe command (resource only) should print detailed information
1003 kube::test::describe_resource_assert services "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:"
1004 # Describe command should print events information by default
1005 kube::test::describe_resource_events_assert services
1006 # Describe command should not print events information when show-events=false
1007 kube::test::describe_resource_events_assert services false
1008 # Describe command should print events information when show-events=true
1009 kube::test::describe_resource_events_assert services true
1010 # Describe command should respect the chunk size parameter
1011 kube::test::describe_resource_chunk_size_assert services events
1012
1013 ### set selector
1014 # prove role=master
1015 kube::test::get_object_assert 'services redis-master' "{{range${service_selector_field:?}}}{{.}}:{{end}}" "redis:master:backend:"
1016
1017 # Set selector of a local file without talking to the server
1018 kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan --local -o yaml "${kube_flags[@]}"
1019 kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan --dry-run=client -o yaml "${kube_flags[@]}"
1020 # Set command to change the selector.
1021 kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml role=padawan
1022 # prove role=padawan
1023 kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "padawan:"
1024 # Set command to reset the selector back to the original one.
1025 kubectl set selector -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml app=redis,role=master,tier=backend
1026 # prove role=master
1027 kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "redis:master:backend:"
1028 # Show dry-run works on running selector
1029 kubectl set selector services redis-master role=padawan --dry-run=client -o yaml "${kube_flags[@]}"
1030 kubectl set selector services redis-master role=padawan --dry-run=server -o yaml "${kube_flags[@]}"
1031 output_message=$(kubectl get services redis-master --show-managed-fields -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
1032 kube::test::if_has_string "${output_message}" 'kubectl-set'
1033 ! kubectl set selector services redis-master role=padawan --local -o yaml "${kube_flags[@]}" || exit 1
1034 kube::test::get_object_assert 'services redis-master' "{{range$service_selector_field}}{{.}}:{{end}}" "redis:master:backend:"
1035 # --resource-version=<current-resource-version> succeeds
1036 rv=$(kubectl get services redis-master -o jsonpath='{.metadata.resourceVersion}' "${kube_flags[@]}")
1037 kubectl set selector services redis-master rvtest1=true "--resource-version=${rv}" "${kube_flags[@]}"
1038 # --resource-version=<non-current-resource-version> fails
1039 output_message=$(! kubectl set selector services redis-master rvtest1=true --resource-version=1 2>&1 "${kube_flags[@]}")
1040 kube::test::if_has_string "${output_message}" 'Conflict'
1041
1042 ### Dump current redis-master service
1043 output_service=$(kubectl get service redis-master -o json "${kube_flags[@]}")
1044
1045 ### Delete redis-master-service by id
1046 # Pre-condition: redis-master service exists
1047 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
1048 # Command
1049 kubectl delete service redis-master "${kube_flags[@]}"
1050 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
1051 kube::test::wait_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1052 fi
1053 # Post-condition: Only the default kubernetes services exist
1054 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1055
1056 ### Create redis-master-service from dumped JSON
1057 # Pre-condition: Only the default kubernetes services exist
1058 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1059 # Command
1060 echo "${output_service}" | kubectl create -f - "${kube_flags[@]}"
1061 # Post-condition: redis-master service is created
1062 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
1063
1064 ### Create redis-master-v1-test service
1065 # Pre-condition: redis-master-service service exists
1066 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
1067 # Command
1068 kubectl create -f - "${kube_flags[@]}" << __EOF__
1069{
1070 "kind": "Service",
1071 "apiVersion": "v1",
1072 "metadata": {
1073 "name": "service-v1-test"
1074 },
1075 "spec": {
1076 "ports": [
1077 {
1078 "protocol": "TCP",
1079 "port": 80,
1080 "targetPort": 80
1081 }
1082 ]
1083 }
1084}
1085__EOF__
1086 # Post-condition: service-v1-test service is created
1087 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:service-.*-test:'
1088
1089 ### Identity
1090 kubectl get service "${kube_flags[@]}" service-v1-test -o json | kubectl replace "${kube_flags[@]}" -f -
1091
1092 ### Delete services by id
1093 # Pre-condition: service-v1-test exists
1094 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:service-.*-test:'
1095 # Command
1096 kubectl delete service redis-master "${kube_flags[@]}"
1097 kubectl delete service "service-v1-test" "${kube_flags[@]}"
1098 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
1099 kube::test::wait_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1100 fi
1101 # Post-condition: Only the default kubernetes services exist
1102 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1103
1104 ### Create two services
1105 # Pre-condition: Only the default kubernetes services exist
1106 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1107 # Command
1108 kubectl create -f test/e2e/testing-manifests/guestbook/redis-master-service.yaml "${kube_flags[@]}"
1109 kubectl create -f test/e2e/testing-manifests/guestbook/redis-slave-service.yaml "${kube_flags[@]}"
1110 # Post-condition: redis-master and redis-slave services are created
1111 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:'
1112
1113 ### Custom columns can be specified
1114 # Pre-condition: generate output using custom columns
1115 output_message=$(kubectl get services -o=custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion 2>&1 "${kube_flags[@]}")
1116 # Post-condition: should contain name column
1117 kube::test::if_has_string "${output_message}" 'redis-master'
1118
1119 ### Delete multiple services at once
1120 # Pre-condition: redis-master and redis-slave services exist
1121 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:'
1122 # Command
1123 kubectl delete services redis-master redis-slave "${kube_flags[@]}" # delete multiple services at once
1124 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
1125 kube::test::wait_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1126 fi
1127 # Post-condition: Only the default kubernetes services exist
1128 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1129
1130 ### Create an ExternalName service
1131 # Pre-condition: Only the default kubernetes service exist
1132 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1133 # Dry-run command
1134 kubectl create service externalname beep-boop --dry-run=client --external-name bar.com
1135 kubectl create service externalname beep-boop --dry-run=server --external-name bar.com
1136 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1137 # Command
1138 kubectl create service externalname beep-boop --external-name bar.com
1139 # Post-condition: beep-boop service is created
1140 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'beep-boop:kubernetes:'
1141
1142 ### Delete beep-boop service by id
1143 # Pre-condition: beep-boop service exists
1144 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'beep-boop:kubernetes:'
1145 # Command
1146 kubectl delete service beep-boop "${kube_flags[@]}"
1147 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
1148 kube::test::wait_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1149 fi
1150 # Post-condition: Only the default kubernetes services exist
1151 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1152
1153 ### Create pod and service
1154 # Pre-condition: no pod exists
1155 kube::test::wait_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
1156 # Pre-condition: Only the default kubernetes services exist
1157 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1158 # Dry-run command
1159 kubectl run testmetadata --image=nginx --port=80 --expose --dry-run=client
1160 kubectl run testmetadata --image=nginx --port=80 --expose --dry-run=server
1161 # Check only the default kubernetes services exist
1162 kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1163 # Command
1164 kubectl run testmetadata --image=nginx --port=80 --expose
1165 # Check result
1166 kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'testmetadata:'
1167 kube::test::get_object_assert 'service testmetadata' "{{${port_field:?}}}" '80'
1168 # pod has field for kubectl run field manager
1169 output_message=$(kubectl get pod testmetadata -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
1170 kube::test::if_has_string "${output_message}" 'kubectl-run'
1171
1172 ### Expose pod as a new service
1173 # Command
1174 kubectl expose pod testmetadata --port=1000 --target-port=80 --type=NodePort --name=exposemetadata --overrides='{ "metadata": { "annotations": { "zone-context": "work" } } } '
1175 # Check result
1176 kube::test::get_object_assert 'service exposemetadata' "{{.metadata.annotations}}" "map\[zone-context:work\]"
1177 # Service has field manager for kubectl expose
1178 output_message=$(kubectl get service exposemetadata -o=jsonpath='{.metadata.managedFields[*].manager}' "${kube_flags[@]:?}" 2>&1)
1179 kube::test::if_has_string "${output_message}" 'kubectl-expose'
1180
1181 # Clean-Up
1182 # Command
1183 kubectl delete service exposemetadata testmetadata "${kube_flags[@]}"
1184 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
1185 kube::test::wait_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
1186 fi
1187 kubectl delete pod testmetadata "${kube_flags[@]}"
1188 if [[ "${WAIT_FOR_DELETION:-}" == "true" ]]; then
1189 kube::test::wait_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
1190 fi
1191
1192 set +o nounset
1193 set +o errexit
1194}
1195
1196run_rc_tests() {
1197 set -o nounset
1198 set -o errexit
1199
1200 create_and_use_new_namespace
1201 kube::log::status "Testing kubectl(v1:replicationcontrollers)"
1202
1203 ### Create and stop controller, make sure it doesn't leak pods
1204 # Pre-condition: no replication controller exists
1205 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
1206 # Command
1207 kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
1208 kubectl delete rc frontend "${kube_flags[@]}"
1209 # Post-condition: no pods from frontend controller
1210 kube::test::wait_object_assert "pods -l name=frontend" "{{range.items}}{{$id_field}}:{{end}}" ''
1211
1212 ### Create replication controller frontend from JSON
1213 # Pre-condition: no replication controller exists
1214 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
1215 # Command
1216 kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
1217 # Post-condition: frontend replication controller is created
1218 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
1219 # Describe command should print detailed information
1220 kube::test::describe_object_assert rc 'frontend' "Name:" "Pod Template:" "Labels:" "Selector:" "Replicas:" "Pods Status:" "Volumes:" "GET_HOSTS_FROM:"
1221 # Describe command should print events information by default
1222 kube::test::describe_object_events_assert rc 'frontend'
1223 # Describe command should not print events information when show-events=false
1224 kube::test::describe_object_events_assert rc 'frontend' false
1225 # Describe command should print events information when show-events=true
1226 kube::test::describe_object_events_assert rc 'frontend' true
1227 # Describe command (resource only) should print detailed information
1228 kube::test::describe_resource_assert rc "Name:" "Name:" "Pod Template:" "Labels:" "Selector:" "Replicas:" "Pods Status:" "Volumes:" "GET_HOSTS_FROM:"
1229 # Describe command should print events information by default
1230 kube::test::describe_resource_events_assert rc
1231 # Describe command should not print events information when show-events=false
1232 kube::test::describe_resource_events_assert rc false
1233 # Describe command should print events information when show-events=true
1234 kube::test::describe_resource_events_assert rc true
1235 # Describe command should respect the chunk size parameter
1236 kube::test::describe_resource_chunk_size_assert replicationcontrollers events
1237
1238 ### Scale replication controller frontend with current-replicas and replicas
1239 # Pre-condition: 3 replicas
1240 kube::test::get_object_assert 'rc frontend' "{{${rc_replicas_field:?}}}" '3'
1241 # Command
1242 kubectl scale --current-replicas=3 --replicas=2 replicationcontrollers frontend "${kube_flags[@]}"
1243 # Post-condition: 2 replicas
1244 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
1245
1246 ### Scale replication controller frontend with (wrong) current-replicas and replicas
1247 # Pre-condition: 2 replicas
1248 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
1249 # Command
1250 ! kubectl scale --current-replicas=3 --replicas=2 replicationcontrollers frontend "${kube_flags[@]}" || exit 1
1251 # Post-condition: nothing changed
1252 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
1253
1254 ### Scale replication controller frontend with replicas only
1255 # Pre-condition: 2 replicas
1256 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
1257 # Command
1258 kubectl scale --replicas=3 replicationcontrollers frontend "${kube_flags[@]}"
1259 # Post-condition: 3 replicas
1260 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
1261
1262 ### Scale replication controller from JSON with replicas only
1263 # Pre-condition: 3 replicas
1264 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
1265 # Command
1266 kubectl scale --replicas=2 -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
1267 # Post-condition: 2 replicas
1268 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
1269 # Clean-up
1270 kubectl delete rc frontend "${kube_flags[@]}"
1271
1272 ### Scale multiple replication controllers
1273 kubectl create -f test/e2e/testing-manifests/guestbook/legacy/redis-master-controller.yaml "${kube_flags[@]}"
1274 kubectl create -f test/e2e/testing-manifests/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}"
1275 # Command dry-run client
1276 output_message=$(kubectl scale rc/redis-master rc/redis-slave --replicas=4 --dry-run=client "${kube_flags[@]}")
1277 # Post-condition dry-run client: 1 replicas each
1278 kube::test::if_has_string "${output_message}" 'replicationcontroller/redis-master scaled (dry run)'
1279 kube::test::if_has_string "${output_message}" 'replicationcontroller/redis-slave scaled (dry run)'
1280 kube::test::get_object_assert 'rc redis-master' "{{$rc_replicas_field}}" '1'
1281 kube::test::get_object_assert 'rc redis-slave' "{{$rc_replicas_field}}" '2'
1282 # Command dry-run server
1283 output_message=$(kubectl scale rc/redis-master rc/redis-slave --replicas=4 --dry-run=server "${kube_flags[@]}")
1284 # Post-condition dry-run server: 1 replicas each
1285 kube::test::if_has_string "${output_message}" 'replicationcontroller/redis-master scaled (server dry run)'
1286 kube::test::if_has_string "${output_message}" 'replicationcontroller/redis-slave scaled (server dry run)'
1287 kube::test::get_object_assert 'rc redis-master' "{{$rc_replicas_field}}" '1'
1288 kube::test::get_object_assert 'rc redis-slave' "{{$rc_replicas_field}}" '2'
1289 # Command
1290 kubectl scale rc/redis-master rc/redis-slave --replicas=4 "${kube_flags[@]}"
1291 # Post-condition: 4 replicas each
1292 kube::test::get_object_assert 'rc redis-master' "{{$rc_replicas_field}}" '4'
1293 kube::test::get_object_assert 'rc redis-slave' "{{$rc_replicas_field}}" '4'
1294 # Clean-up
1295 kubectl delete rc redis-{master,slave} "${kube_flags[@]}"
1296
1297 ### Scale a deployment
1298 kubectl create -f test/fixtures/doc-yaml/user-guide/deployment.yaml "${kube_flags[@]}"
1299 # Command dry-run client
1300 output_message=$(kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment --dry-run=client)
1301 # Post-condition: 3 replica for nginx-deployment dry-run client
1302 kube::test::if_has_string "${output_message}" 'nginx-deployment scaled (dry run)'
1303 kube::test::get_object_assert 'deployment nginx-deployment' "{{${deployment_replicas:?}}}" '3'
1304 # Command dry-run server
1305 output_message=$(kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment --dry-run=server)
1306 # Post-condition: 3 replica for nginx-deployment dry-run server
1307 kube::test::if_has_string "${output_message}" 'nginx-deployment scaled (server dry run)'
1308 kube::test::get_object_assert 'deployment nginx-deployment' "{{${deployment_replicas:?}}}" '3'
1309 # Command
1310 kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment
1311 # Post-condition: 1 replica for nginx-deployment
1312 kube::test::get_object_assert 'deployment nginx-deployment' "{{${deployment_replicas:?}}}" '1'
1313 # Clean-up
1314 kubectl delete deployment/nginx-deployment "${kube_flags[@]}"
1315
1316 ### Scale a deployment with piped input
1317 kubectl create -f test/fixtures/doc-yaml/user-guide/deployment.yaml "${kube_flags[@]}"
1318 # Command
1319 kubectl get deployment/nginx-deployment -o json | kubectl scale --replicas=2 -f -
1320 # Post-condition: 2 replica for nginx-deployment
1321 kube::test::get_object_assert 'deployment nginx-deployment' "{{${deployment_replicas:?}}}" '2'
1322 # Clean-up
1323 kubectl delete deployment/nginx-deployment "${kube_flags[@]}"
1324
1325 ### Expose deployments by creating a service
1326 # Uses deployment selectors for created service
1327 output_message=$(kubectl expose -f test/fixtures/pkg/kubectl/cmd/expose/appsv1deployment.yaml --port 80 2>&1 "${kube_flags[@]}")
1328 # Post-condition: service created for deployment.
1329 kube::test::if_has_string "${output_message}" 'service/expose-test-deployment exposed'
1330 # Clean-up
1331 kubectl delete service/expose-test-deployment "${kube_flags[@]}"
1332 # Contains no selectors, should fail.
1333 output_message=$(! kubectl expose -f test/fixtures/pkg/kubectl/cmd/expose/appsv1deployment-no-selectors.yaml --port 80 2>&1 "${kube_flags[@]}")
1334 # Post-condition: service created for deployment.
1335 kube::test::if_has_string "${output_message}" 'invalid deployment: no selectors'
1336
1337 ### Expose a deployment as a service
1338 kubectl create -f test/fixtures/doc-yaml/user-guide/deployment.yaml "${kube_flags[@]}"
1339 # Pre-condition: 3 replicas
1340 kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '3'
1341 # Command
1342 kubectl expose deployment/nginx-deployment
1343 # Post-condition: service exists and exposes deployment port (80)
1344 kube::test::get_object_assert 'service nginx-deployment' "{{${port_field:?}}}" '80'
1345 # Clean-up
1346 kubectl delete deployment/nginx-deployment service/nginx-deployment "${kube_flags[@]}"
1347
1348 ### Expose replication controller as service
1349 kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
1350 # Pre-condition: 3 replicas
1351 kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
1352 # Command
1353 kubectl expose rc frontend --port=80 "${kube_flags[@]}"
1354 # Post-condition: service exists and the port is unnamed
1355 kube::test::get_object_assert 'service frontend' "{{${port_name:?}}} {{$port_field}}" '<no value> 80'
1356 # Command
1357 kubectl expose service frontend --port=443 --name=frontend-2 "${kube_flags[@]}"
1358 # Post-condition: service exists and the port is unnamed
1359 kube::test::get_object_assert 'service frontend-2' "{{$port_name}} {{$port_field}}" '<no value> 443'
1360 # Command
1361 kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
1362 kubectl expose pod valid-pod --port=444 --name=frontend-3 "${kube_flags[@]}"
1363 # Post-condition: service exists and the port is unnamed
1364 kube::test::get_object_assert 'service frontend-3' "{{$port_name}} {{$port_field}}" '<no value> 444'
1365 # Verify that expose service works without specifying a port.
1366 kubectl expose service frontend --name=frontend-4 "${kube_flags[@]}"
1367 # Post-condition: service exists with the same port as the original service.
1368 kube::test::get_object_assert 'service frontend-4' "{{$port_field}}" '80'
1369 # Cleanup services
1370 kubectl delete pod valid-pod "${kube_flags[@]}"
1371 kubectl delete service frontend{,-2,-3,-4} "${kube_flags[@]}"
1372
1373 ### Expose negative invalid resource test
1374 # Pre-condition: don't need
1375 # Command
1376 output_message=$(! kubectl expose nodes 127.0.0.1 2>&1 "${kube_flags[@]}")
1377 # Post-condition: the error message has "cannot expose" string
1378 kube::test::if_has_string "${output_message}" 'cannot expose'
1379
1380 ### Try to generate a service with invalid name (exceeding maximum valid size)
1381 # Pre-condition: use --name flag
1382 output_message=$(! kubectl expose -f hack/testdata/pod-with-large-name.yaml --name=invalid-large-service-name-that-has-more-than-sixty-three-characters --port=8081 2>&1 "${kube_flags[@]}")
1383 # Post-condition: should fail due to invalid name
1384 kube::test::if_has_string "${output_message}" 'metadata.name: Invalid value'
1385 # Pre-condition: default run without --name flag; should succeed by truncating the inherited name
1386 output_message=$(kubectl expose -f hack/testdata/pod-with-large-name.yaml --port=8081 2>&1 "${kube_flags[@]}")
1387 # Post-condition: inherited name from pod has been truncated
1388 kube::test::if_has_string "${output_message}" 'kubernetes-serve-hostname-testing-sixty-three-characters-in-len exposed'
1389 # Clean-up
1390 kubectl delete svc kubernetes-serve-hostname-testing-sixty-three-characters-in-len "${kube_flags[@]}"
1391
1392 ### Expose multiport object as a new service
1393 # Pre-condition: don't use --port flag
1394 output_message=$(kubectl expose -f test/fixtures/doc-yaml/admin/high-availability/etcd.yaml --selector=test=etcd 2>&1 "${kube_flags[@]}")
1395 # Post-condition: expose succeeded
1396 kube::test::if_has_string "${output_message}" 'etcd-server exposed'
1397 # Post-condition: generated service has both ports from the exposed pod
1398 kube::test::get_object_assert 'service etcd-server' "{{$port_name}} {{$port_field}}" 'port-1 2380'
1399 kube::test::get_object_assert 'service etcd-server' "{{${second_port_name:?}}} {{${second_port_field:?}}}" 'port-2 2379'
1400 # Clean-up
1401 kubectl delete svc etcd-server "${kube_flags[@]}"
1402
1403 ### Delete replication controller with id
1404 # Pre-condition: frontend replication controller exists
1405 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
1406 # Command
1407 kubectl delete rc frontend "${kube_flags[@]}"
1408 # Post-condition: no replication controller exists
1409 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
1410
1411 ### Create two replication controllers
1412 # Pre-condition: no replication controller exists
1413 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
1414 # Command
1415 kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
1416 kubectl create -f test/e2e/testing-manifests/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}"
1417 # Post-condition: frontend and redis-slave
1418 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:'
1419
1420 ### Delete multiple controllers at once
1421 # Pre-condition: frontend and redis-slave
1422 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:'
1423 # Command
1424 kubectl delete rc frontend redis-slave "${kube_flags[@]}" # delete multiple controllers at once
1425 # Post-condition: no replication controller exists
1426 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
1427
1428 ### Auto scale replication controller
1429 # Pre-condition: no replication controller exists
1430 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
1431 # Command
1432 kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
1433 kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
1434 # autoscale 1~2 pods, CPU utilization 70%, rc specified by file
1435 kubectl autoscale -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}" --max=2 --cpu-percent=70
1436 kube::test::get_object_assert 'hpa frontend' "{{${hpa_min_field:?}}} {{${hpa_max_field:?}}} {{${hpa_cpu_field:?}}}" '1 2 70'
1437 kubectl delete hpa frontend "${kube_flags[@]}"
1438 # autoscale 2~3 pods, no CPU utilization specified, rc specified by name
1439 kubectl autoscale rc frontend "${kube_flags[@]}" --min=2 --max=3
1440 kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '2 3 80'
1441 kubectl delete hpa frontend "${kube_flags[@]}"
1442 # autoscale without specifying --max should fail
1443 ! kubectl autoscale rc frontend "${kube_flags[@]}" || exit 1
1444 # Clean up
1445 kubectl delete rc frontend "${kube_flags[@]}"
1446
1447 ## Set resource limits/request of a deployment
1448 # Pre-condition: no deployment exists
1449 kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
1450 # Set resources of a local file without talking to the server
1451 kubectl set resources -f hack/testdata/deployment-multicontainer-resources.yaml -c=perl --limits=cpu=300m --requests=cpu=300m --local -o yaml "${kube_flags[@]}"
1452 ! kubectl set resources -f hack/testdata/deployment-multicontainer-resources.yaml -c=perl --limits=cpu=300m --requests=cpu=300m --dry-run=client -o yaml "${kube_flags[@]}" || exit 1
1453 # Create a deployment
1454 kubectl create -f hack/testdata/deployment-multicontainer-resources.yaml "${kube_flags[@]}"
1455 kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx-deployment-resources:'
1456 kube::test::get_object_assert deployment "{{range.items}}{{${image_field0:?}}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
1457 kube::test::get_object_assert deployment "{{range.items}}{{${image_field1:?}}}:{{end}}" "${IMAGE_PERL}:"
1458 # Set the deployment's cpu limits
1459 kubectl set resources deployment nginx-deployment-resources --limits=cpu=100m "${kube_flags[@]}"
1460 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 0).resources.limits.cpu}}:{{end}}" "100m:"
1461 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 1).resources.limits.cpu}}:{{end}}" "100m:"
1462 # Set a non-existing container should fail
1463 ! kubectl set resources deployment nginx-deployment-resources -c=redis --limits=cpu=100m || exit 1
1464 # Set the limit of a specific container in deployment
1465 kubectl set resources deployment nginx-deployment-resources -c=nginx --limits=cpu=200m "${kube_flags[@]}"
1466 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 0).resources.limits.cpu}}:{{end}}" "200m:"
1467 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 1).resources.limits.cpu}}:{{end}}" "100m:"
1468 # Set limits/requests of a deployment specified by a file
1469 kubectl set resources -f hack/testdata/deployment-multicontainer-resources.yaml -c=perl --limits=cpu=300m --requests=cpu=300m "${kube_flags[@]}"
1470 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 0).resources.limits.cpu}}:{{end}}" "200m:"
1471 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 1).resources.limits.cpu}}:{{end}}" "300m:"
1472 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 1).resources.requests.cpu}}:{{end}}" "300m:"
1473 # Show dry-run works on running deployments
1474 kubectl set resources deployment nginx-deployment-resources -c=perl --limits=cpu=400m --requests=cpu=400m --dry-run=client -o yaml "${kube_flags[@]}"
1475 kubectl set resources deployment nginx-deployment-resources -c=perl --limits=cpu=400m --requests=cpu=400m --dry-run=server -o yaml "${kube_flags[@]}"
1476 ! kubectl set resources deployment nginx-deployment-resources -c=perl --limits=cpu=400m --requests=cpu=400m --local -o yaml "${kube_flags[@]}" || exit 1
1477 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 0).resources.limits.cpu}}:{{end}}" "200m:"
1478 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 1).resources.limits.cpu}}:{{end}}" "300m:"
1479 kube::test::get_object_assert deployment "{{range.items}}{{(index .spec.template.spec.containers 1).resources.requests.cpu}}:{{end}}" "300m:"
1480 # Clean up
1481 kubectl delete deployment nginx-deployment-resources "${kube_flags[@]}"
1482
1483 set +o nounset
1484 set +o errexit
1485}
1486
1487run_namespace_tests() {
1488 set -o nounset
1489 set -o errexit
1490
1491 kube::log::status "Testing kubectl(v1:namespaces)"
1492 ### Create a new namespace
1493 # Pre-condition: test namespace does not exist
1494 output_message=$(! kubectl get ns/my-namespace 2>&1 "${kube_flags[@]}")
1495 kube::test::if_has_string "${output_message}" ' not found'
1496 # Dry-run command
1497 kubectl create namespace my-namespace --dry-run=client
1498 kubectl create namespace my-namespace --dry-run=server
1499 output_message=$(! kubectl get ns/my-namespace 2>&1 "${kube_flags[@]}")
1500 kube::test::if_has_string "${output_message}" ' not found'
1501 # Command
1502 kubectl create namespace my-namespace
1503 # Post-condition: namespace 'my-namespace' is created.
1504 kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace'
1505 # Describe command should respect the chunk size parameter
1506 kube::test::describe_resource_chunk_size_assert namespaces resourcequotas,limitranges
1507 # Clean up
1508 kubectl delete namespace my-namespace --wait=false
1509 # make sure that wait properly waits for finalization
1510 kubectl wait --for=delete ns/my-namespace
1511 output_message=$(! kubectl get ns/my-namespace 2>&1 "${kube_flags[@]}")
1512 kube::test::if_has_string "${output_message}" ' not found'
1513
1514 kubectl create namespace my-namespace
1515 kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace'
1516 output_message=$(! kubectl delete namespace -n my-namespace --all 2>&1 "${kube_flags[@]}")
1517 kube::test::if_has_string "${output_message}" 'Warning: deleting cluster-scoped resources'
1518 kube::test::if_has_string "${output_message}" 'namespace "my-namespace" deleted'
1519
1520 ### Quota
1521 kubectl create namespace quotas
1522 kube::test::get_object_assert 'namespaces/quotas' "{{$id_field}}" 'quotas'
1523 kube::test::get_object_assert 'quota --namespace=quotas' "{{range.items}}{{ if eq $id_field \"test-quota\" }}found{{end}}{{end}}:" ':'
1524 # Dry-run command
1525 kubectl create quota test-quota --dry-run=client --namespace=quotas
1526 kubectl create quota test-quota --dry-run=server --namespace=quotas
1527 kube::test::get_object_assert 'quota --namespace=quotas' "{{range.items}}{{ if eq $id_field \"test-quota\" }}found{{end}}{{end}}:" ':'
1528 # Command
1529 kubectl create quota test-quota --namespace=quotas
1530 kube::test::get_object_assert 'quota --namespace=quotas' "{{range.items}}{{ if eq $id_field \"test-quota\" }}found{{end}}{{end}}:" 'found:'
1531 # Describe command should respect the chunk size parameter
1532 kube::test::describe_resource_chunk_size_assert resourcequotas "" "--namespace=quotas"
1533 # Clean up
1534 kubectl delete quota test-quota --namespace=quotas
1535 kubectl delete namespace quotas
1536
1537 ######################
1538 # Pods in Namespaces #
1539 ######################
1540
1541 if kube::test::if_supports_resource "${pods:?}" ; then
1542 ### Create a new namespace
1543 # Pre-condition: the other namespace does not exist
1544 kube::test::get_object_assert 'namespaces' "{{range.items}}{{ if eq $id_field \"other\" }}found{{end}}{{end}}:" ':'
1545 # Command
1546 kubectl create namespace other
1547 # Post-condition: namespace 'other' is created.
1548 kube::test::get_object_assert 'namespaces/other' "{{$id_field}}" 'other'
1549
1550 ### Create POD valid-pod in specific namespace
1551 # Pre-condition: no POD exists
1552 kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
1553 # Command
1554 kubectl create "${kube_flags[@]}" --namespace=other -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
1555 # Post-condition: valid-pod POD is created
1556 kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
1557 # Post-condition: verify shorthand `-n other` has the same results as `--namespace=other`
1558 kube::test::get_object_assert 'pods -n other' "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
1559 # Post-condition: a resource cannot be retrieved by name across all namespaces
1560 output_message=$(! kubectl get "${kube_flags[@]}" pod valid-pod --all-namespaces 2>&1)
1561 kube::test::if_has_string "${output_message}" "a resource cannot be retrieved by name across all namespaces"
1562
1563 ### Delete POD valid-pod in specific namespace
1564 # Pre-condition: valid-pod POD exists
1565 kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
1566 # Command
1567 kubectl delete "${kube_flags[@]}" pod --namespace=other valid-pod --grace-period=0 --force
1568 # Post-condition: valid-pod POD doesn't exist
1569 kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
1570 # Clean up
1571 kubectl delete namespace other
1572 fi
1573
1574 set +o nounset
1575 set +o errexit
1576}
1577
1578run_nodes_tests() {
1579 set -o nounset
1580 set -o errexit
1581
1582 kube::log::status "Testing kubectl(v1:nodes)"
1583
1584 kube::test::get_object_assert nodes "{{range.items}}{{$id_field}}:{{end}}" '127.0.0.1:'
1585
1586 kube::test::describe_object_assert nodes "127.0.0.1" "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:"
1587 # Describe command should print events information by default
1588 kube::test::describe_object_events_assert nodes "127.0.0.1"
1589 # Describe command should not print events information when show-events=false
1590 kube::test::describe_object_events_assert nodes "127.0.0.1" false
1591 # Describe command should print events information when show-events=true
1592 kube::test::describe_object_events_assert nodes "127.0.0.1" true
1593 # Describe command (resource only) should print detailed information
1594 kube::test::describe_resource_assert nodes "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:"
1595 # Describe command should print events information by default
1596 kube::test::describe_resource_events_assert nodes
1597 # Describe command should not print events information when show-events=false
1598 kube::test::describe_resource_events_assert nodes false
1599 # Describe command should print events information when show-events=true
1600 kube::test::describe_resource_events_assert nodes true
1601 # Describe command should respect the chunk size parameter
1602 kube::test::describe_resource_chunk_size_assert nodes pods,events
1603
1604 ### kubectl patch update can mark node unschedulable
1605 # Pre-condition: node is schedulable
1606 kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '<no value>'
1607 kubectl patch "${kube_flags[@]}" nodes "127.0.0.1" -p='{"spec":{"unschedulable":true}}'
1608 # Post-condition: node is unschedulable
1609 kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" 'true'
1610 kubectl patch "${kube_flags[@]}" nodes "127.0.0.1" -p='{"spec":{"unschedulable":null}}'
1611 # Post-condition: node is schedulable
1612 kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '<no value>'
1613
1614 # check webhook token authentication endpoint, kubectl doesn't actually display the returned object so this isn't super useful
1615 # but it proves that works
1616 kubectl create -f test/fixtures/pkg/kubectl/cmd/create/tokenreview-v1.json --validate=false
1617
1618 set +o nounset
1619 set +o errexit
1620}
1621
1622run_pod_templates_tests() {
1623 set -o nounset
1624 set -o errexit
1625
1626 create_and_use_new_namespace
1627 kube::log::status "Testing pod templates"
1628
1629 ### Create PODTEMPLATE
1630 # Pre-condition: no PODTEMPLATE
1631 kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" ''
1632 # Command
1633 kubectl create -f test/fixtures/doc-yaml/user-guide/walkthrough/podtemplate.json "${kube_flags[@]}"
1634 # Post-condition: nginx PODTEMPLATE is available
1635 kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" 'nginx:'
1636
1637 ### Printing pod templates works
1638 kubectl get podtemplates "${kube_flags[@]}"
1639 grep -q nginx <<< "$(kubectl get podtemplates -o yaml "${kube_flags[@]}")"
1640
1641 ### Delete nginx pod template by name
1642 # Pre-condition: nginx pod template is available
1643 kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" 'nginx:'
1644 # Describe command should respect the chunk size parameter
1645 kube::test::describe_resource_chunk_size_assert podtemplates events
1646 # Command
1647 kubectl delete podtemplate nginx "${kube_flags[@]}"
1648 # Post-condition: No templates exist
1649 kube::test::get_object_assert podtemplate "{{range.items}}{{.metadata.name}}:{{end}}" ''
1650
1651 set +o nounset
1652 set +o errexit
1653}
View as plain text