test-cmd.sh 125 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559
  1. #!/bin/bash
  2. # Copyright 2014 The Kubernetes Authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # This command checks that the built commands can function together for
  16. # simple scenarios. It does not require Docker.
  17. set -o errexit
  18. set -o nounset
  19. set -o pipefail
  20. KUBE_ROOT=$(dirname "${BASH_SOURCE}")/../..
  21. source "${KUBE_ROOT}/hack/lib/init.sh"
  22. source "${KUBE_ROOT}/hack/lib/test.sh"
  23. # Stops the running kubectl proxy, if there is one.
  24. function stop-proxy()
  25. {
  26. [[ -n "${PROXY_PORT-}" ]] && kube::log::status "Stopping proxy on port ${PROXY_PORT}"
  27. [[ -n "${PROXY_PID-}" ]] && kill "${PROXY_PID}" 1>&2 2>/dev/null
  28. [[ -n "${PROXY_PORT_FILE-}" ]] && rm -f ${PROXY_PORT_FILE}
  29. PROXY_PID=
  30. PROXY_PORT=
  31. PROXY_PORT_FILE=
  32. }
  33. # Starts "kubect proxy" to test the client proxy. $1: api_prefix
  34. function start-proxy()
  35. {
  36. stop-proxy
  37. PROXY_PORT_FILE=$(mktemp proxy-port.out.XXXXX)
  38. kube::log::status "Starting kubectl proxy on random port; output file in ${PROXY_PORT_FILE}; args: ${1-}"
  39. if [ $# -eq 0 ]; then
  40. kubectl proxy --port=0 --www=. 1>${PROXY_PORT_FILE} 2>&1 &
  41. else
  42. kubectl proxy --port=0 --www=. --api-prefix="$1" 1>${PROXY_PORT_FILE} 2>&1 &
  43. fi
  44. PROXY_PID=$!
  45. PROXY_PORT=
  46. local attempts=0
  47. while [[ -z ${PROXY_PORT} ]]; do
  48. if (( ${attempts} > 9 )); then
  49. kill "${PROXY_PID}"
  50. kube::log::error_exit "Couldn't start proxy. Failed to read port after ${attempts} tries. Got: $(cat ${PROXY_PORT_FILE})"
  51. fi
  52. sleep .5
  53. kube::log::status "Attempt ${attempts} to read ${PROXY_PORT_FILE}..."
  54. PROXY_PORT=$(sed 's/.*Starting to serve on 127.0.0.1:\([0-9]*\)$/\1/'< ${PROXY_PORT_FILE})
  55. attempts=$((attempts+1))
  56. done
  57. kube::log::status "kubectl proxy running on port ${PROXY_PORT}"
  58. # We try checking kubectl proxy 30 times with 1s delays to avoid occasional
  59. # failures.
  60. if [ $# -eq 0 ]; then
  61. kube::util::wait_for_url "http://127.0.0.1:${PROXY_PORT}/healthz" "kubectl proxy"
  62. else
  63. kube::util::wait_for_url "http://127.0.0.1:${PROXY_PORT}/$1/healthz" "kubectl proxy --api-prefix=$1"
  64. fi
  65. }
  66. function cleanup()
  67. {
  68. [[ -n "${APISERVER_PID-}" ]] && kill "${APISERVER_PID}" 1>&2 2>/dev/null
  69. [[ -n "${CTLRMGR_PID-}" ]] && kill "${CTLRMGR_PID}" 1>&2 2>/dev/null
  70. [[ -n "${KUBELET_PID-}" ]] && kill "${KUBELET_PID}" 1>&2 2>/dev/null
  71. stop-proxy
  72. kube::etcd::cleanup
  73. rm -rf "${KUBE_TEMP}"
  74. kube::log::status "Clean up complete"
  75. }
  76. # Executes curl against the proxy. $1 is the path to use, $2 is the desired
  77. # return code. Prints a helpful message on failure.
  78. function check-curl-proxy-code()
  79. {
  80. local status
  81. local -r address=$1
  82. local -r desired=$2
  83. local -r full_address="${PROXY_HOST}:${PROXY_PORT}${address}"
  84. status=$(curl -w "%{http_code}" --silent --output /dev/null "${full_address}")
  85. if [ "${status}" == "${desired}" ]; then
  86. return 0
  87. fi
  88. echo "For address ${full_address}, got ${status} but wanted ${desired}"
  89. return 1
  90. }
  91. # TODO: Remove this function when we do the retry inside the kubectl commands. See #15333.
  92. function kubectl-with-retry()
  93. {
  94. ERROR_FILE="${KUBE_TEMP}/kubectl-error"
  95. preserve_err_file=${PRESERVE_ERR_FILE-false}
  96. for count in {0..3}; do
  97. kubectl "$@" 2> ${ERROR_FILE} || true
  98. if grep -q "the object has been modified" "${ERROR_FILE}"; then
  99. kube::log::status "retry $1, error: $(cat ${ERROR_FILE})"
  100. rm "${ERROR_FILE}"
  101. sleep $((2**count))
  102. else
  103. if [ "$preserve_err_file" != true ] ; then
  104. rm "${ERROR_FILE}"
  105. fi
  106. break
  107. fi
  108. done
  109. }
  110. # Waits for the pods with the given label to match the list of names. Don't call
  111. # this function unless you know the exact pod names, or expect no pods.
  112. # $1: label to match
  113. # $2: list of pod names sorted by name
  114. # Example invocation:
  115. # wait-for-pods-with-label "app=foo" "nginx-0nginx-1"
  116. function wait-for-pods-with-label()
  117. {
  118. for i in $(seq 1 10); do
  119. kubeout=`kubectl get po -l $1 --template '{{range.items}}{{.metadata.name}}{{end}}' --sort-by metadata.name "${kube_flags[@]}"`
  120. if [[ $kubeout = $2 ]]; then
  121. return
  122. fi
  123. echo Waiting for pods: $2, found $kubeout
  124. sleep $i
  125. done
  126. kube::log::error_exit "Timeout waiting for pods with label $1"
  127. }
  128. kube::util::trap_add cleanup EXIT SIGINT
  129. kube::util::ensure-temp-dir
  130. BINS=(
  131. cmd/kubectl
  132. cmd/kube-apiserver
  133. cmd/kube-controller-manager
  134. )
  135. make -C "${KUBE_ROOT}" WHAT="${BINS[*]}"
  136. kube::etcd::start
  137. ETCD_HOST=${ETCD_HOST:-127.0.0.1}
  138. ETCD_PORT=${ETCD_PORT:-2379}
  139. API_PORT=${API_PORT:-8080}
  140. API_HOST=${API_HOST:-127.0.0.1}
  141. KUBELET_PORT=${KUBELET_PORT:-10250}
  142. KUBELET_HEALTHZ_PORT=${KUBELET_HEALTHZ_PORT:-10248}
  143. CTLRMGR_PORT=${CTLRMGR_PORT:-10252}
  144. PROXY_HOST=127.0.0.1 # kubectl only serves on localhost.
  145. IMAGE_NGINX="gcr.io/google-containers/nginx:1.7.9"
  146. IMAGE_DEPLOYMENT_R1="gcr.io/google-containers/nginx:test-cmd" # deployment-revision1.yaml
  147. IMAGE_DEPLOYMENT_R2="$IMAGE_NGINX" # deployment-revision2.yaml
  148. IMAGE_PERL="gcr.io/google-containers/perl"
  149. # ensure ~/.kube/config isn't loaded by tests
  150. HOME="${KUBE_TEMP}"
  151. # Find a standard sed instance for use with edit scripts
  152. SED=sed
  153. if which gsed &>/dev/null; then
  154. SED=gsed
  155. fi
  156. if ! ($SED --version 2>&1 | grep -q GNU); then
  157. echo "!!! GNU sed is required. If on OS X, use 'brew install gnu-sed'."
  158. exit 1
  159. fi
  160. # Check kubectl
  161. kube::log::status "Running kubectl with no options"
  162. "${KUBE_OUTPUT_HOSTBIN}/kubectl"
  163. # Only run kubelet on platforms it supports
  164. if [[ "$(go env GOHOSTOS)" == "linux" ]]; then
  165. BINS=(
  166. cmd/kubelet
  167. )
  168. make -C "${KUBE_ROOT}" WHAT="${BINS[*]}"
  169. kube::log::status "Starting kubelet in masterless mode"
  170. "${KUBE_OUTPUT_HOSTBIN}/kubelet" \
  171. --really-crash-for-testing=true \
  172. --root-dir=/tmp/kubelet.$$ \
  173. --cert-dir="${TMPDIR:-/tmp/}" \
  174. --docker-endpoint="fake://" \
  175. --hostname-override="127.0.0.1" \
  176. --address="127.0.0.1" \
  177. --port="$KUBELET_PORT" \
  178. --healthz-port="${KUBELET_HEALTHZ_PORT}" 1>&2 &
  179. KUBELET_PID=$!
  180. kube::util::wait_for_url "http://127.0.0.1:${KUBELET_HEALTHZ_PORT}/healthz" "kubelet(masterless)"
  181. kill ${KUBELET_PID} 1>&2 2>/dev/null
  182. kube::log::status "Starting kubelet in masterful mode"
  183. "${KUBE_OUTPUT_HOSTBIN}/kubelet" \
  184. --really-crash-for-testing=true \
  185. --root-dir=/tmp/kubelet.$$ \
  186. --cert-dir="${TMPDIR:-/tmp/}" \
  187. --docker-endpoint="fake://" \
  188. --hostname-override="127.0.0.1" \
  189. --address="127.0.0.1" \
  190. --api-servers="${API_HOST}:${API_PORT}" \
  191. --port="$KUBELET_PORT" \
  192. --healthz-port="${KUBELET_HEALTHZ_PORT}" 1>&2 &
  193. KUBELET_PID=$!
  194. kube::util::wait_for_url "http://127.0.0.1:${KUBELET_HEALTHZ_PORT}/healthz" "kubelet"
  195. fi
  196. # Start kube-apiserver
  197. kube::log::status "Starting kube-apiserver"
  198. # Admission Controllers to invoke prior to persisting objects in cluster
  199. ADMISSION_CONTROL="NamespaceLifecycle,LimitRanger,ResourceQuota"
  200. "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver" \
  201. --address="127.0.0.1" \
  202. --public-address-override="127.0.0.1" \
  203. --port="${API_PORT}" \
  204. --admission-control="${ADMISSION_CONTROL}" \
  205. --etcd-servers="http://${ETCD_HOST}:${ETCD_PORT}" \
  206. --public-address-override="127.0.0.1" \
  207. --kubelet-port=${KUBELET_PORT} \
  208. --runtime-config=api/v1 \
  209. --storage-media-type="${KUBE_TEST_API_STORAGE_TYPE-}" \
  210. --cert-dir="${TMPDIR:-/tmp/}" \
  211. --service-cluster-ip-range="10.0.0.0/24" 1>&2 &
  212. APISERVER_PID=$!
  213. kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/healthz" "apiserver"
  214. # Start controller manager
  215. kube::log::status "Starting controller-manager"
  216. "${KUBE_OUTPUT_HOSTBIN}/kube-controller-manager" \
  217. --port="${CTLRMGR_PORT}" \
  218. --kube-api-content-type="${KUBE_TEST_API_TYPE-}" \
  219. --master="127.0.0.1:${API_PORT}" 1>&2 &
  220. CTLRMGR_PID=$!
  221. kube::util::wait_for_url "http://127.0.0.1:${CTLRMGR_PORT}/healthz" "controller-manager"
  222. if [[ "$(go env GOHOSTOS)" == "linux" ]]; then
  223. kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/api/v1/nodes/127.0.0.1" "apiserver(nodes)"
  224. else
  225. # create a fake node
  226. kubectl create -f - -s "http://127.0.0.1:${API_PORT}" << __EOF__
  227. {
  228. "kind": "Node",
  229. "apiVersion": "v1",
  230. "metadata": {
  231. "name": "127.0.0.1"
  232. },
  233. "status": {
  234. "capacity": {
  235. "memory": "1Gi"
  236. }
  237. }
  238. }
  239. __EOF__
  240. fi
  241. # Expose kubectl directly for readability
  242. PATH="${KUBE_OUTPUT_HOSTBIN}":$PATH
  243. kube::log::status "Checking kubectl version"
  244. kubectl version
  245. # TODO: we need to note down the current default namespace and set back to this
  246. # namespace after the tests are done.
  247. kubectl config view
  248. CONTEXT="test"
  249. kubectl config set-context "${CONTEXT}"
  250. kubectl config use-context "${CONTEXT}"
  251. i=0
  252. create_and_use_new_namespace() {
  253. i=$(($i+1))
  254. kubectl create namespace "namespace${i}"
  255. kubectl config set-context "${CONTEXT}" --namespace="namespace${i}"
  256. }
  257. runTests() {
  258. version="$1"
  259. echo "Testing api version: $1"
  260. if [[ -z "${version}" ]]; then
  261. kube_flags=(
  262. -s "http://127.0.0.1:${API_PORT}"
  263. --match-server-version
  264. )
  265. [ "$(kubectl get nodes -o go-template='{{ .apiVersion }}' "${kube_flags[@]}")" == "v1" ]
  266. else
  267. kube_flags=(
  268. -s "http://127.0.0.1:${API_PORT}"
  269. --match-server-version
  270. )
  271. [ "$(kubectl get nodes -o go-template='{{ .apiVersion }}' "${kube_flags[@]}")" == "${version}" ]
  272. fi
  273. id_field=".metadata.name"
  274. labels_field=".metadata.labels"
  275. annotations_field=".metadata.annotations"
  276. service_selector_field=".spec.selector"
  277. rc_replicas_field=".spec.replicas"
  278. rc_status_replicas_field=".status.replicas"
  279. rc_container_image_field=".spec.template.spec.containers"
  280. rs_replicas_field=".spec.replicas"
  281. port_field="(index .spec.ports 0).port"
  282. port_name="(index .spec.ports 0).name"
  283. second_port_field="(index .spec.ports 1).port"
  284. second_port_name="(index .spec.ports 1).name"
  285. image_field="(index .spec.containers 0).image"
  286. hpa_min_field=".spec.minReplicas"
  287. hpa_max_field=".spec.maxReplicas"
  288. hpa_cpu_field=".spec.targetCPUUtilizationPercentage"
  289. petset_replicas_field=".spec.replicas"
  290. job_parallelism_field=".spec.parallelism"
  291. deployment_replicas=".spec.replicas"
  292. secret_data=".data"
  293. secret_type=".type"
  294. deployment_image_field="(index .spec.template.spec.containers 0).image"
  295. deployment_second_image_field="(index .spec.template.spec.containers 1).image"
  296. change_cause_annotation='.*kubernetes.io/change-cause.*'
  297. # Passing no arguments to create is an error
  298. ! kubectl create
  299. #######################
  300. # kubectl config set #
  301. #######################
  302. kube::log::status "Testing kubectl(${version}:config set)"
  303. kubectl config set-cluster test-cluster --server="https://does-not-work"
  304. # Get the api cert and add a comment to avoid flag parsing problems
  305. cert_data=$(echo "#Comment" && cat "${TMPDIR:-/tmp}/apiserver.crt")
  306. kubectl config set clusters.test-cluster.certificate-authority-data "$cert_data" --set-raw-bytes
  307. r_writen=$(kubectl config view --raw -o jsonpath='{.clusters[?(@.name == "test-cluster")].cluster.certificate-authority-data}')
  308. encoded=$(echo -n "$cert_data" | base64)
  309. kubectl config set clusters.test-cluster.certificate-authority-data "$encoded"
  310. e_writen=$(kubectl config view --raw -o jsonpath='{.clusters[?(@.name == "test-cluster")].cluster.certificate-authority-data}')
  311. test "$e_writen" == "$r_writen"
  312. #######################
  313. # kubectl local proxy #
  314. #######################
  315. # Make sure the UI can be proxied
  316. start-proxy
  317. check-curl-proxy-code /ui 301
  318. check-curl-proxy-code /metrics 200
  319. check-curl-proxy-code /api/ui 404
  320. if [[ -n "${version}" ]]; then
  321. check-curl-proxy-code /api/${version}/namespaces 200
  322. fi
  323. check-curl-proxy-code /static/ 200
  324. stop-proxy
  325. # Make sure the in-development api is accessible by default
  326. start-proxy
  327. check-curl-proxy-code /apis 200
  328. check-curl-proxy-code /apis/extensions/ 200
  329. stop-proxy
  330. # Custom paths let you see everything.
  331. start-proxy /custom
  332. check-curl-proxy-code /custom/ui 301
  333. check-curl-proxy-code /custom/metrics 200
  334. if [[ -n "${version}" ]]; then
  335. check-curl-proxy-code /custom/api/${version}/namespaces 200
  336. fi
  337. stop-proxy
  338. #########################
  339. # RESTMapper evaluation #
  340. #########################
  341. kube::log::status "Testing RESTMapper"
  342. RESTMAPPER_ERROR_FILE="${KUBE_TEMP}/restmapper-error"
  343. ### Non-existent resource type should give a recognizeable error
  344. # Pre-condition: None
  345. # Command
  346. kubectl get "${kube_flags[@]}" unknownresourcetype 2>${RESTMAPPER_ERROR_FILE} || true
  347. if grep -q "the server doesn't have a resource type" "${RESTMAPPER_ERROR_FILE}"; then
  348. kube::log::status "\"kubectl get unknownresourcetype\" returns error as expected: $(cat ${RESTMAPPER_ERROR_FILE})"
  349. else
  350. kube::log::status "\"kubectl get unknownresourcetype\" returns unexpected error or non-error: $(cat ${RESTMAPPER_ERROR_FILE})"
  351. exit 1
  352. fi
  353. rm "${RESTMAPPER_ERROR_FILE}"
  354. # Post-condition: None
  355. kubectl get "${kube_flags[@]}" --raw /version
  356. ###########################
  357. # POD creation / deletion #
  358. ###########################
  359. kube::log::status "Testing kubectl(${version}:pods)"
  360. ### Create POD valid-pod from JSON
  361. # Pre-condition: no POD exists
  362. create_and_use_new_namespace
  363. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  364. # Command
  365. kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
  366. # Post-condition: valid-pod POD is created
  367. kubectl get "${kube_flags[@]}" pods -o json
  368. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  369. kube::test::get_object_assert 'pod valid-pod' "{{$id_field}}" 'valid-pod'
  370. kube::test::get_object_assert 'pod/valid-pod' "{{$id_field}}" 'valid-pod'
  371. kube::test::get_object_assert 'pods/valid-pod' "{{$id_field}}" 'valid-pod'
  372. # Repeat above test using jsonpath template
  373. kube::test::get_object_jsonpath_assert pods "{.items[*]$id_field}" 'valid-pod'
  374. kube::test::get_object_jsonpath_assert 'pod valid-pod' "{$id_field}" 'valid-pod'
  375. kube::test::get_object_jsonpath_assert 'pod/valid-pod' "{$id_field}" 'valid-pod'
  376. kube::test::get_object_jsonpath_assert 'pods/valid-pod' "{$id_field}" 'valid-pod'
  377. # Describe command should print detailed information
  378. kube::test::describe_object_assert pods 'valid-pod' "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers"
  379. # Describe command should print events information by default
  380. kube::test::describe_object_events_assert pods 'valid-pod'
  381. # Describe command should not print events information when show-events=false
  382. kube::test::describe_object_events_assert pods 'valid-pod' false
  383. # Describe command should print events information when show-events=true
  384. kube::test::describe_object_events_assert pods 'valid-pod' true
  385. # Describe command (resource only) should print detailed information
  386. kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers"
  387. # Describe command should print events information by default
  388. kube::test::describe_resource_events_assert pods
  389. # Describe command should not print events information when show-events=false
  390. kube::test::describe_resource_events_assert pods false
  391. # Describe command should print events information when show-events=true
  392. kube::test::describe_resource_events_assert pods true
  393. ### Validate Export ###
  394. kube::test::get_object_assert 'pods/valid-pod' "{{.metadata.namespace}} {{.metadata.name}}" '<no value> valid-pod' "--export=true"
  395. ### Dump current valid-pod POD
  396. output_pod=$(kubectl get pod valid-pod -o yaml --output-version=v1 "${kube_flags[@]}")
  397. ### Delete POD valid-pod by id
  398. # Pre-condition: valid-pod POD exists
  399. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  400. # Command
  401. kubectl delete pod valid-pod "${kube_flags[@]}" --grace-period=0
  402. # Post-condition: valid-pod POD doesn't exist
  403. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  404. ### Delete POD valid-pod by id with --now
  405. # Pre-condition: valid-pod POD exists
  406. kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
  407. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  408. # Command
  409. kubectl delete pod valid-pod "${kube_flags[@]}" --now
  410. # Post-condition: valid-pod POD doesn't exist
  411. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  412. ### Create POD valid-pod from dumped YAML
  413. # Pre-condition: no POD exists
  414. create_and_use_new_namespace
  415. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  416. # Command
  417. echo "${output_pod}" | $SED '/namespace:/d' | kubectl create -f - "${kube_flags[@]}"
  418. # Post-condition: valid-pod POD is created
  419. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  420. ### Delete POD valid-pod from JSON
  421. # Pre-condition: valid-pod POD exists
  422. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  423. # Command
  424. kubectl delete -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}" --grace-period=0
  425. # Post-condition: valid-pod POD doesn't exist
  426. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  427. ### Create POD valid-pod from JSON
  428. # Pre-condition: no POD exists
  429. create_and_use_new_namespace
  430. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  431. # Command
  432. kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
  433. # Post-condition: valid-pod POD is created
  434. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  435. ### Delete POD valid-pod with label
  436. # Pre-condition: valid-pod POD exists
  437. kube::test::get_object_assert "pods -l'name in (valid-pod)'" '{{range.items}}{{$id_field}}:{{end}}' 'valid-pod:'
  438. # Command
  439. kubectl delete pods -l'name in (valid-pod)' "${kube_flags[@]}" --grace-period=0
  440. # Post-condition: valid-pod POD doesn't exist
  441. kube::test::get_object_assert "pods -l'name in (valid-pod)'" '{{range.items}}{{$id_field}}:{{end}}' ''
  442. ### Create POD valid-pod from YAML
  443. # Pre-condition: no POD exists
  444. create_and_use_new_namespace
  445. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  446. # Command
  447. kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
  448. # Post-condition: valid-pod POD is created
  449. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  450. ### Delete PODs with no parameter mustn't kill everything
  451. # Pre-condition: valid-pod POD exists
  452. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  453. # Command
  454. ! kubectl delete pods "${kube_flags[@]}"
  455. # Post-condition: valid-pod POD exists
  456. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  457. ### Delete PODs with --all and a label selector is not permitted
  458. # Pre-condition: valid-pod POD exists
  459. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  460. # Command
  461. ! kubectl delete --all pods -l'name in (valid-pod)' "${kube_flags[@]}"
  462. # Post-condition: valid-pod POD exists
  463. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  464. ### Delete all PODs
  465. # Pre-condition: valid-pod POD exists
  466. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  467. # Command
  468. kubectl delete --all pods "${kube_flags[@]}" --grace-period=0 # --all remove all the pods
  469. # Post-condition: no POD exists
  470. kube::test::get_object_assert "pods -l'name in (valid-pod)'" '{{range.items}}{{$id_field}}:{{end}}' ''
  471. # Detailed tests for describe pod output
  472. ### Create a new namespace
  473. # Pre-condition: the test-secrets namespace does not exist
  474. kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-kubectl-describe-pod\" }}found{{end}}{{end}}:' ':'
  475. # Command
  476. kubectl create namespace test-kubectl-describe-pod
  477. # Post-condition: namespace 'test-secrets' is created.
  478. kube::test::get_object_assert 'namespaces/test-kubectl-describe-pod' "{{$id_field}}" 'test-kubectl-describe-pod'
  479. ### Create a generic secret
  480. # Pre-condition: no SECRET exists
  481. kube::test::get_object_assert 'secrets --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
  482. # Command
  483. kubectl create secret generic test-secret --from-literal=key-1=value1 --type=test-type --namespace=test-kubectl-describe-pod
  484. # Post-condition: secret exists and has expected values
  485. kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{$id_field}}" 'test-secret'
  486. kube::test::get_object_assert 'secret/test-secret --namespace=test-kubectl-describe-pod' "{{$secret_type}}" 'test-type'
  487. ### Create a generic configmap
  488. # Pre-condition: no CONFIGMAP exists
  489. kube::test::get_object_assert 'configmaps --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
  490. # Command
  491. kubectl create configmap test-configmap --from-literal=key-2=value2 --namespace=test-kubectl-describe-pod
  492. # Post-condition: configmap exists and has expected values
  493. kube::test::get_object_assert 'configmap/test-configmap --namespace=test-kubectl-describe-pod' "{{$id_field}}" 'test-configmap'
  494. # Create a pod that consumes secret, configmap, and downward API keys as envs
  495. kube::test::get_object_assert 'pods --namespace=test-kubectl-describe-pod' "{{range.items}}{{$id_field}}:{{end}}" ''
  496. kubectl create -f hack/testdata/pod-with-api-env.yaml --namespace=test-kubectl-describe-pod
  497. 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)"
  498. # Describe command (resource only) should print detailed information about environment variables
  499. 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)"
  500. # Clean-up
  501. kubectl delete pod env-test-pod --namespace=test-kubectl-describe-pod
  502. kubectl delete secret test-secret --namespace=test-kubectl-describe-pod
  503. kubectl delete configmap test-configmap --namespace=test-kubectl-describe-pod
  504. kubectl delete namespace test-kubectl-describe-pod
  505. ### Create two PODs
  506. # Pre-condition: no POD exists
  507. create_and_use_new_namespace
  508. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  509. # Command
  510. kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
  511. kubectl create -f examples/storage/redis/redis-proxy.yaml "${kube_flags[@]}"
  512. # Post-condition: valid-pod and redis-proxy PODs are created
  513. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-proxy:valid-pod:'
  514. ### Delete multiple PODs at once
  515. # Pre-condition: valid-pod and redis-proxy PODs exist
  516. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-proxy:valid-pod:'
  517. # Command
  518. kubectl delete pods valid-pod redis-proxy "${kube_flags[@]}" --grace-period=0 # delete multiple pods at once
  519. # Post-condition: no POD exists
  520. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  521. ### Create valid-pod POD
  522. # Pre-condition: no POD exists
  523. create_and_use_new_namespace
  524. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  525. # Command
  526. kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
  527. # Post-condition: valid-pod POD is created
  528. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  529. ### Label the valid-pod POD
  530. # Pre-condition: valid-pod is not labelled
  531. kube::test::get_object_assert 'pod valid-pod' "{{range$labels_field}}{{.}}:{{end}}" 'valid-pod:'
  532. # Command
  533. kubectl label pods valid-pod new-name=new-valid-pod "${kube_flags[@]}"
  534. # Post-condition: valid-pod is labelled
  535. kube::test::get_object_assert 'pod valid-pod' "{{range$labels_field}}{{.}}:{{end}}" 'valid-pod:new-valid-pod:'
  536. ### Record label change
  537. # Pre-condition: valid-pod does not have record annotation
  538. kube::test::get_object_assert 'pod valid-pod' "{{range.items}}{{$annotations_field}}:{{end}}" ''
  539. # Command
  540. kubectl label pods valid-pod record-change=true --record=true "${kube_flags[@]}"
  541. # Post-condition: valid-pod has record annotation
  542. kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*--record=true.*"
  543. ### Do not record label change
  544. # Command
  545. kubectl label pods valid-pod no-record-change=true --record=false "${kube_flags[@]}"
  546. # Post-condition: valid-pod's record annotation still contains command with --record=true
  547. kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*--record=true.*"
  548. ### Record label change with unspecified flag and previous change already recorded
  549. # Command
  550. kubectl label pods valid-pod new-record-change=true "${kube_flags[@]}"
  551. # Post-condition: valid-pod's record annotation contains new change
  552. kube::test::get_object_assert 'pod valid-pod' "{{range$annotations_field}}{{.}}:{{end}}" ".*new-record-change=true.*"
  553. ### Delete POD by label
  554. # Pre-condition: valid-pod POD exists
  555. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  556. # Command
  557. kubectl delete pods -lnew-name=new-valid-pod --grace-period=0 "${kube_flags[@]}"
  558. # Post-condition: valid-pod POD doesn't exist
  559. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  560. ### Create pod-with-precision POD
  561. # Pre-condition: no POD is running
  562. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  563. # Command
  564. kubectl create -f hack/testdata/pod-with-precision.json "${kube_flags[@]}"
  565. # Post-condition: valid-pod POD is running
  566. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'pod-with-precision:'
  567. ## Patch preserves precision
  568. # Command
  569. kubectl patch "${kube_flags[@]}" pod pod-with-precision -p='{"metadata":{"annotations":{"patchkey": "patchvalue"}}}'
  570. # Post-condition: pod-with-precision POD has patched annotation
  571. kube::test::get_object_assert 'pod pod-with-precision' "{{${annotations_field}.patchkey}}" 'patchvalue'
  572. # Command
  573. kubectl label pods pod-with-precision labelkey=labelvalue "${kube_flags[@]}"
  574. # Post-condition: pod-with-precision POD has label
  575. kube::test::get_object_assert 'pod pod-with-precision' "{{${labels_field}.labelkey}}" 'labelvalue'
  576. # Command
  577. kubectl annotate pods pod-with-precision annotatekey=annotatevalue "${kube_flags[@]}"
  578. # Post-condition: pod-with-precision POD has annotation
  579. kube::test::get_object_assert 'pod pod-with-precision' "{{${annotations_field}.annotatekey}}" 'annotatevalue'
  580. # Cleanup
  581. kubectl delete pod pod-with-precision "${kube_flags[@]}"
  582. ### Create valid-pod POD
  583. # Pre-condition: no POD exists
  584. create_and_use_new_namespace
  585. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  586. # Command
  587. kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
  588. # Post-condition: valid-pod POD is created
  589. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  590. ## Patch can modify a local object
  591. kubectl patch --local -f pkg/api/validation/testdata/v1/validPod.yaml --patch='{"spec": {"restartPolicy":"Never"}}' -o jsonpath='{.spec.restartPolicy}' | grep -q "Never"
  592. ## Patch pod can change image
  593. # Command
  594. kubectl patch "${kube_flags[@]}" pod valid-pod --record -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]}}'
  595. # Post-condition: valid-pod POD has image nginx
  596. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
  597. # Post-condition: valid-pod has the record annotation
  598. kube::test::get_object_assert pods "{{range.items}}{{$annotations_field}}:{{end}}" "${change_cause_annotation}"
  599. # prove that patch can use different types
  600. kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx2"}]'
  601. # Post-condition: valid-pod POD has image nginx
  602. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx2:'
  603. # prove that patch can use different types
  604. kubectl patch "${kube_flags[@]}" pod valid-pod --type="json" -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"nginx"}]'
  605. # Post-condition: valid-pod POD has image nginx
  606. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
  607. # prove that yaml input works too
  608. YAML_PATCH=$'spec:\n containers:\n - name: kubernetes-serve-hostname\n image: changed-with-yaml\n'
  609. kubectl patch "${kube_flags[@]}" pod valid-pod -p="${YAML_PATCH}"
  610. # Post-condition: valid-pod POD has image nginx
  611. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'changed-with-yaml:'
  612. ## Patch pod from JSON can change image
  613. # Command
  614. kubectl patch "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "gcr.io/google_containers/pause-amd64:3.0"}]}}'
  615. # Post-condition: valid-pod POD has image gcr.io/google_containers/pause-amd64:3.0
  616. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'gcr.io/google_containers/pause-amd64:3.0:'
  617. ## 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
  618. ERROR_FILE="${KUBE_TEMP}/conflict-error"
  619. ## If the resourceVersion is the same as the one stored in the server, the patch will be applied.
  620. # Command
  621. # Needs to retry because other party may change the resource.
  622. for count in {0..3}; do
  623. resourceVersion=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .metadata.resourceVersion }}')
  624. kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'$resourceVersion'"}}' 2> "${ERROR_FILE}" || true
  625. if grep -q "the object has been modified" "${ERROR_FILE}"; then
  626. kube::log::status "retry $1, error: $(cat ${ERROR_FILE})"
  627. rm "${ERROR_FILE}"
  628. sleep $((2**count))
  629. else
  630. rm "${ERROR_FILE}"
  631. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
  632. break
  633. fi
  634. done
  635. ## If the resourceVersion is the different from the one stored in the server, the patch will be rejected.
  636. resourceVersion=$(kubectl get "${kube_flags[@]}" pod valid-pod -o go-template='{{ .metadata.resourceVersion }}')
  637. ((resourceVersion+=100))
  638. # Command
  639. kubectl patch "${kube_flags[@]}" pod valid-pod -p='{"spec":{"containers":[{"name": "kubernetes-serve-hostname", "image": "nginx"}]},"metadata":{"resourceVersion":"'$resourceVersion'"}}' 2> "${ERROR_FILE}" || true
  640. # Post-condition: should get an error reporting the conflict
  641. if grep -q "please apply your changes to the latest version and try again" "${ERROR_FILE}"; then
  642. kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns error as expected: $(cat ${ERROR_FILE})"
  643. else
  644. kube::log::status "\"kubectl patch with resourceVersion $resourceVersion\" returns unexpected error or non-error: $(cat ${ERROR_FILE})"
  645. exit 1
  646. fi
  647. rm "${ERROR_FILE}"
  648. ## --force replace pod can change other field, e.g., spec.container.name
  649. # Command
  650. kubectl get "${kube_flags[@]}" pod valid-pod -o json | $SED 's/"kubernetes-serve-hostname"/"replaced-k8s-serve-hostname"/g' > /tmp/tmp-valid-pod.json
  651. kubectl replace "${kube_flags[@]}" --force -f /tmp/tmp-valid-pod.json
  652. # Post-condition: spec.container.name = "replaced-k8s-serve-hostname"
  653. kube::test::get_object_assert 'pod valid-pod' "{{(index .spec.containers 0).name}}" 'replaced-k8s-serve-hostname'
  654. #cleaning
  655. rm /tmp/tmp-valid-pod.json
  656. ## replace of a cluster scoped resource can succeed
  657. # Pre-condition: a node exists
  658. kubectl create -f - "${kube_flags[@]}" << __EOF__
  659. {
  660. "kind": "Node",
  661. "apiVersion": "v1",
  662. "metadata": {
  663. "name": "node-${version}-test"
  664. }
  665. }
  666. __EOF__
  667. kubectl replace -f - "${kube_flags[@]}" << __EOF__
  668. {
  669. "kind": "Node",
  670. "apiVersion": "v1",
  671. "metadata": {
  672. "name": "node-${version}-test",
  673. "annotations": {"a":"b"}
  674. }
  675. }
  676. __EOF__
  677. # Post-condition: the node command succeeds
  678. kube::test::get_object_assert "node node-${version}-test" "{{.metadata.annotations.a}}" 'b'
  679. kubectl delete node node-${version}-test "${kube_flags[@]}"
  680. ## kubectl edit can update the image field of a POD. tmp-editor.sh is a fake editor
  681. echo -e "#!/bin/bash\n$SED -i \"s/nginx/gcr.io\/google_containers\/serve_hostname/g\" \$1" > /tmp/tmp-editor.sh
  682. chmod +x /tmp/tmp-editor.sh
  683. # Pre-condition: valid-pod POD has image nginx
  684. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'nginx:'
  685. EDITOR=/tmp/tmp-editor.sh kubectl edit "${kube_flags[@]}" pods/valid-pod
  686. # Post-condition: valid-pod POD has image gcr.io/google_containers/serve_hostname
  687. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'gcr.io/google_containers/serve_hostname:'
  688. # cleaning
  689. rm /tmp/tmp-editor.sh
  690. ## kubectl edit should work on Windows
  691. [ "$(EDITOR=cat kubectl edit pod/valid-pod 2>&1 | grep 'Edit cancelled')" ]
  692. [ "$(EDITOR=cat kubectl edit pod/valid-pod | grep 'name: valid-pod')" ]
  693. [ "$(EDITOR=cat kubectl edit --windows-line-endings pod/valid-pod | file - | grep CRLF)" ]
  694. [ ! "$(EDITOR=cat kubectl edit --windows-line-endings=false pod/valid-pod | file - | grep CRLF)" ]
  695. ### Overwriting an existing label is not permitted
  696. # Pre-condition: name is valid-pod
  697. kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
  698. # Command
  699. ! kubectl label pods valid-pod name=valid-pod-super-sayan "${kube_flags[@]}"
  700. # Post-condition: name is still valid-pod
  701. kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
  702. ### --overwrite must be used to overwrite existing label, can be applied to all resources
  703. # Pre-condition: name is valid-pod
  704. kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod'
  705. # Command
  706. kubectl label --overwrite pods --all name=valid-pod-super-sayan "${kube_flags[@]}"
  707. # Post-condition: name is valid-pod-super-sayan
  708. kube::test::get_object_assert 'pod valid-pod' "{{${labels_field}.name}}" 'valid-pod-super-sayan'
  709. ### Delete POD by label
  710. # Pre-condition: valid-pod POD exists
  711. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  712. # Command
  713. kubectl delete pods -l'name in (valid-pod-super-sayan)' --grace-period=0 "${kube_flags[@]}"
  714. # Post-condition: valid-pod POD doesn't exist
  715. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  716. ### Create two PODs from 1 yaml file
  717. # Pre-condition: no POD exists
  718. create_and_use_new_namespace
  719. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  720. # Command
  721. kubectl create -f test/fixtures/doc-yaml/user-guide/multi-pod.yaml "${kube_flags[@]}"
  722. # Post-condition: valid-pod and redis-proxy PODs exist
  723. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-master:redis-proxy:'
  724. ### Delete two PODs from 1 yaml file
  725. # Pre-condition: redis-master and redis-proxy PODs exist
  726. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'redis-master:redis-proxy:'
  727. # Command
  728. kubectl delete -f test/fixtures/doc-yaml/user-guide/multi-pod.yaml "${kube_flags[@]}"
  729. # Post-condition: no PODs exist
  730. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  731. ## kubectl apply should update configuration annotations only if apply is already called
  732. ## 1. kubectl create doesn't set the annotation
  733. # Pre-Condition: no POD exists
  734. create_and_use_new_namespace
  735. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  736. # Command: create a pod "test-pod"
  737. kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
  738. # Post-Condition: pod "test-pod" is created
  739. kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-label'
  740. # Post-Condition: pod "test-pod" doesn't have configuration annotation
  741. ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  742. ## 2. kubectl replace doesn't set the annotation
  743. kubectl get pods test-pod -o yaml "${kube_flags[@]}" | $SED 's/test-pod-label/test-pod-replaced/g' > "${KUBE_TEMP}"/test-pod-replace.yaml
  744. # Command: replace the pod "test-pod"
  745. kubectl replace -f "${KUBE_TEMP}"/test-pod-replace.yaml "${kube_flags[@]}"
  746. # Post-Condition: pod "test-pod" is replaced
  747. kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-replaced'
  748. # Post-Condition: pod "test-pod" doesn't have configuration annotation
  749. ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  750. ## 3. kubectl apply does set the annotation
  751. # Command: apply the pod "test-pod"
  752. kubectl apply -f hack/testdata/pod-apply.yaml "${kube_flags[@]}"
  753. # Post-Condition: pod "test-pod" is applied
  754. kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-applied'
  755. # Post-Condition: pod "test-pod" has configuration annotation
  756. [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  757. kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration > "${KUBE_TEMP}"/annotation-configuration
  758. ## 4. kubectl replace updates an existing annotation
  759. kubectl get pods test-pod -o yaml "${kube_flags[@]}" | $SED 's/test-pod-applied/test-pod-replaced/g' > "${KUBE_TEMP}"/test-pod-replace.yaml
  760. # Command: replace the pod "test-pod"
  761. kubectl replace -f "${KUBE_TEMP}"/test-pod-replace.yaml "${kube_flags[@]}"
  762. # Post-Condition: pod "test-pod" is replaced
  763. kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-replaced'
  764. # Post-Condition: pod "test-pod" has configuration annotation, and it's updated (different from the annotation when it's applied)
  765. [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  766. kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration > "${KUBE_TEMP}"/annotation-configuration-replaced
  767. ! [[ $(diff -q "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced > /dev/null) ]]
  768. # Clean up
  769. rm "${KUBE_TEMP}"/test-pod-replace.yaml "${KUBE_TEMP}"/annotation-configuration "${KUBE_TEMP}"/annotation-configuration-replaced
  770. kubectl delete pods test-pod "${kube_flags[@]}"
  771. ## Configuration annotations should be set when --save-config is enabled
  772. ## 1. kubectl create --save-config should generate configuration annotation
  773. # Pre-Condition: no POD exists
  774. create_and_use_new_namespace
  775. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  776. # Command: create a pod "test-pod"
  777. kubectl create -f hack/testdata/pod.yaml --save-config "${kube_flags[@]}"
  778. # Post-Condition: pod "test-pod" has configuration annotation
  779. [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  780. # Clean up
  781. kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
  782. ## 2. kubectl edit --save-config should generate configuration annotation
  783. # Pre-Condition: no POD exists, then create pod "test-pod", which shouldn't have configuration annotation
  784. create_and_use_new_namespace
  785. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  786. kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
  787. ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  788. # Command: edit the pod "test-pod"
  789. temp_editor="${KUBE_TEMP}/tmp-editor.sh"
  790. echo -e "#!/bin/bash\n$SED -i \"s/test-pod-label/test-pod-label-edited/g\" \$@" > "${temp_editor}"
  791. chmod +x "${temp_editor}"
  792. EDITOR=${temp_editor} kubectl edit pod test-pod --save-config "${kube_flags[@]}"
  793. # Post-Condition: pod "test-pod" has configuration annotation
  794. [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  795. # Clean up
  796. kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
  797. ## 3. kubectl replace --save-config should generate configuration annotation
  798. # Pre-Condition: no POD exists, then create pod "test-pod", which shouldn't have configuration annotation
  799. create_and_use_new_namespace
  800. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  801. kubectl create -f hack/testdata/pod.yaml "${kube_flags[@]}"
  802. ! [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  803. # Command: replace the pod "test-pod"
  804. kubectl replace -f hack/testdata/pod.yaml --save-config "${kube_flags[@]}"
  805. # Post-Condition: pod "test-pod" has configuration annotation
  806. [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  807. # Clean up
  808. kubectl delete -f hack/testdata/pod.yaml "${kube_flags[@]}"
  809. ## 4. kubectl run --save-config should generate configuration annotation
  810. # Pre-Condition: no RC exists
  811. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  812. # Command: create the rc "nginx" with image nginx
  813. kubectl run nginx "--image=$IMAGE_NGINX" --save-config --generator=run/v1 "${kube_flags[@]}"
  814. # Post-Condition: rc "nginx" has configuration annotation
  815. [[ "$(kubectl get rc nginx -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  816. ## 5. kubectl expose --save-config should generate configuration annotation
  817. # Pre-Condition: no service exists
  818. kube::test::get_object_assert svc "{{range.items}}{{$id_field}}:{{end}}" ''
  819. # Command: expose the rc "nginx"
  820. kubectl expose rc nginx --save-config --port=80 --target-port=8000 "${kube_flags[@]}"
  821. # Post-Condition: service "nginx" has configuration annotation
  822. [[ "$(kubectl get svc nginx -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  823. # Clean up
  824. kubectl delete rc,svc nginx
  825. ## 6. kubectl autoscale --save-config should generate configuration annotation
  826. # Pre-Condition: no RC exists, then create the rc "frontend", which shouldn't have configuration annotation
  827. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  828. kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  829. ! [[ "$(kubectl get rc frontend -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  830. # Command: autoscale rc "frontend"
  831. kubectl autoscale -f hack/testdata/frontend-controller.yaml --save-config "${kube_flags[@]}" --max=2
  832. # Post-Condition: hpa "frontend" has configuration annotation
  833. [[ "$(kubectl get hpa.v1beta1.extensions frontend -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  834. # Ensure we can interact with HPA objects in lists through both the extensions/v1beta1 and autoscaling/v1 APIs
  835. output_message=$(kubectl get hpa -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}")
  836. kube::test::if_has_string "${output_message}" 'autoscaling/v1'
  837. output_message=$(kubectl get hpa.extensions -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}")
  838. kube::test::if_has_string "${output_message}" 'extensions/v1beta1'
  839. output_message=$(kubectl get hpa.autoscaling -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}")
  840. kube::test::if_has_string "${output_message}" 'autoscaling/v1'
  841. # Clean up
  842. # Note that we should delete hpa first, otherwise it may fight with the rc reaper.
  843. kubectl delete hpa frontend "${kube_flags[@]}"
  844. kubectl delete rc frontend "${kube_flags[@]}"
  845. ## kubectl create should not panic on empty string lists in a template
  846. ERROR_FILE="${KUBE_TEMP}/validation-error"
  847. kubectl create -f hack/testdata/invalid-rc-with-empty-args.yaml "${kube_flags[@]}" 2> "${ERROR_FILE}" || true
  848. # Post-condition: should get an error reporting the empty string
  849. if grep -q "unexpected nil value for field" "${ERROR_FILE}"; then
  850. kube::log::status "\"kubectl create with empty string list returns error as expected: $(cat ${ERROR_FILE})"
  851. else
  852. kube::log::status "\"kubectl create with empty string list returns unexpected error or non-error: $(cat ${ERROR_FILE})"
  853. exit 1
  854. fi
  855. rm "${ERROR_FILE}"
  856. ## kubectl apply should create the resource that doesn't exist yet
  857. # Pre-Condition: no POD exists
  858. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  859. # Command: apply a pod "test-pod" (doesn't exist) should create this pod
  860. kubectl apply -f hack/testdata/pod.yaml "${kube_flags[@]}"
  861. # Post-Condition: pod "test-pod" is created
  862. kube::test::get_object_assert 'pods test-pod' "{{${labels_field}.name}}" 'test-pod-label'
  863. # Post-Condition: pod "test-pod" has configuration annotation
  864. [[ "$(kubectl get pods test-pod -o yaml "${kube_flags[@]}" | grep kubectl.kubernetes.io/last-applied-configuration)" ]]
  865. # Clean up
  866. kubectl delete pods test-pod "${kube_flags[@]}"
  867. ## kubectl run should create deployments or jobs
  868. # Pre-Condition: no Job exists
  869. kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" ''
  870. # Command
  871. kubectl run pi --generator=job/v1beta1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}"
  872. # Post-Condition: Job "pi" is created
  873. kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:'
  874. # Clean up
  875. kubectl delete jobs pi "${kube_flags[@]}"
  876. # Command
  877. kubectl run pi --generator=job/v1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}"
  878. # Post-Condition: Job "pi" is created
  879. kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:'
  880. # Clean up
  881. kubectl delete jobs pi "${kube_flags[@]}"
  882. # Post-condition: no pods exist.
  883. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  884. # Pre-Condition: no Deployment exists
  885. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
  886. # Command
  887. kubectl run nginx "--image=$IMAGE_NGINX" --generator=deployment/v1beta1 "${kube_flags[@]}"
  888. # Post-Condition: Deployment "nginx" is created
  889. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx:'
  890. # Clean up
  891. kubectl delete deployment nginx "${kube_flags[@]}"
  892. ###############
  893. # Kubectl get #
  894. ###############
  895. ### Test retrieval of non-existing pods
  896. # Pre-condition: no POD exists
  897. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  898. # Command
  899. output_message=$(! kubectl get pods abc 2>&1 "${kube_flags[@]}")
  900. # Post-condition: POD abc should error since it doesn't exist
  901. kube::test::if_has_string "${output_message}" 'pods "abc" not found'
  902. ### Test retrieval of non-existing POD with output flag specified
  903. # Pre-condition: no POD exists
  904. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  905. # Command
  906. output_message=$(! kubectl get pods abc 2>&1 "${kube_flags[@]}" -o name)
  907. # Post-condition: POD abc should error since it doesn't exist
  908. kube::test::if_has_string "${output_message}" 'pods "abc" not found'
  909. ### Test retrieval of non-existing POD with json output flag specified
  910. # Pre-condition: no POD exists
  911. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  912. # Command
  913. output_message=$(! kubectl get pods abc 2>&1 "${kube_flags[@]}" -o json)
  914. # Post-condition: POD abc should error since it doesn't exist
  915. kube::test::if_has_string "${output_message}" 'pods "abc" not found'
  916. # Post-condition: make sure we don't display an empty List
  917. if kube::test::if_has_string "${output_message}" 'List'; then
  918. echo 'Unexpected List output'
  919. echo "${LINENO} $(basename $0)"
  920. exit 1
  921. fi
  922. #####################################
  923. # Third Party Resources #
  924. #####################################
  925. create_and_use_new_namespace
  926. kubectl "${kube_flags[@]}" create -f - "${kube_flags[@]}" << __EOF__
  927. {
  928. "kind": "ThirdPartyResource",
  929. "apiVersion": "extensions/v1beta1",
  930. "metadata": {
  931. "name": "foo.company.com"
  932. },
  933. "versions": [
  934. {
  935. "name": "v1"
  936. }
  937. ]
  938. }
  939. __EOF__
  940. # Post-Condition: assertion object exist
  941. kube::test::get_object_assert thirdpartyresources "{{range.items}}{{$id_field}}:{{end}}" 'foo.company.com:'
  942. kubectl "${kube_flags[@]}" create -f - "${kube_flags[@]}" << __EOF__
  943. {
  944. "kind": "ThirdPartyResource",
  945. "apiVersion": "extensions/v1beta1",
  946. "metadata": {
  947. "name": "bar.company.com"
  948. },
  949. "versions": [
  950. {
  951. "name": "v1"
  952. }
  953. ]
  954. }
  955. __EOF__
  956. # Post-Condition: assertion object exist
  957. kube::test::get_object_assert thirdpartyresources "{{range.items}}{{$id_field}}:{{end}}" 'bar.company.com:foo.company.com:'
  958. kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/apis/company.com/v1" "third party api"
  959. kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/apis/company.com/v1/foos" "third party api Foo"
  960. kube::util::wait_for_url "http://127.0.0.1:${API_PORT}/apis/company.com/v1/bars" "third party api Bar"
  961. # Test that we can list this new third party resource (foos)
  962. kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
  963. # Test that we can list this new third party resource (bars)
  964. kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
  965. # Test that we can create a new resource of type Foo
  966. kubectl "${kube_flags[@]}" create -f - "${kube_flags[@]}" << __EOF__
  967. {
  968. "kind": "Foo",
  969. "apiVersion": "company.com/v1",
  970. "metadata": {
  971. "name": "test"
  972. },
  973. "some-field": "field1",
  974. "other-field": "field2"
  975. }
  976. __EOF__
  977. # Test that we can list this new third party resource
  978. kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" 'test:'
  979. # Delete the resource
  980. kubectl "${kube_flags[@]}" delete foos test
  981. # Make sure it's gone
  982. kube::test::get_object_assert foos "{{range.items}}{{$id_field}}:{{end}}" ''
  983. # Test that we can create a new resource of type Bar
  984. kubectl "${kube_flags[@]}" create -f - "${kube_flags[@]}" << __EOF__
  985. {
  986. "kind": "Bar",
  987. "apiVersion": "company.com/v1",
  988. "metadata": {
  989. "name": "test"
  990. },
  991. "some-field": "field1",
  992. "other-field": "field2"
  993. }
  994. __EOF__
  995. # Test that we can list this new third party resource
  996. kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" 'test:'
  997. # Delete the resource
  998. kubectl "${kube_flags[@]}" delete bars test
  999. # Make sure it's gone
  1000. kube::test::get_object_assert bars "{{range.items}}{{$id_field}}:{{end}}" ''
  1001. # teardown
  1002. kubectl delete thirdpartyresources foo.company.com "${kube_flags[@]}"
  1003. kubectl delete thirdpartyresources bar.company.com "${kube_flags[@]}"
  1004. #################
  1005. # Run cmd w img #
  1006. #################
  1007. # Test that a valid image reference value is provided as the value of --image in `kubectl run <name> --image`
  1008. output_message=$(kubectl run test1 --image=validname)
  1009. kube::test::if_has_string "${output_message}" 'deployment "test1" created'
  1010. # test invalid image name
  1011. output_message=$(! kubectl run test2 --image=InvalidImageName 2>&1)
  1012. kube::test::if_has_string "${output_message}" 'error: Invalid image name "InvalidImageName": invalid reference format'
  1013. #####################################
  1014. # Recursive Resources via directory #
  1015. #####################################
  1016. ### Create multiple busybox PODs recursively from directory of YAML files
  1017. # Pre-condition: no POD exists
  1018. create_and_use_new_namespace
  1019. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  1020. # Command
  1021. output_message=$(! kubectl create -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}")
  1022. # Post-condition: busybox0 & busybox1 PODs are created, and since busybox2 is malformed, it should error
  1023. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1024. kube::test::if_has_string "${output_message}" 'error validating data: kind not set'
  1025. ## Edit multiple busybox PODs by updating the image field of multiple PODs recursively from a directory. tmp-editor.sh is a fake editor
  1026. # Pre-condition: busybox0 & busybox1 PODs exist
  1027. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1028. # Command
  1029. echo -e '#!/bin/bash\nsed -i "s/image: busybox/image: prom\/busybox/g" $1' > /tmp/tmp-editor.sh
  1030. chmod +x /tmp/tmp-editor.sh
  1031. output_message=$(! EDITOR=/tmp/tmp-editor.sh kubectl edit -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}")
  1032. # Post-condition: busybox0 & busybox1 PODs are edited, and since busybox2 is malformed, it should error
  1033. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'prom/busybox:prom/busybox:'
  1034. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1035. # cleaning
  1036. rm /tmp/tmp-editor.sh
  1037. ## Replace multiple busybox PODs recursively from directory of YAML files
  1038. # Pre-condition: busybox0 & busybox1 PODs exist
  1039. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1040. # Command
  1041. output_message=$(! kubectl replace -f hack/testdata/recursive/pod-modify --recursive 2>&1 "${kube_flags[@]}")
  1042. # Post-condition: busybox0 & busybox1 PODs are replaced, and since busybox2 is malformed, it should error
  1043. kube::test::get_object_assert pods "{{range.items}}{{${labels_field}.status}}:{{end}}" 'replaced:replaced:'
  1044. kube::test::if_has_string "${output_message}" 'error validating data: kind not set'
  1045. ## Describe multiple busybox PODs recursively from directory of YAML files
  1046. # Pre-condition: busybox0 & busybox1 PODs exist
  1047. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1048. # Command
  1049. output_message=$(! kubectl describe -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}")
  1050. # Post-condition: busybox0 & busybox1 PODs are described, and since busybox2 is malformed, it should error
  1051. kube::test::if_has_string "${output_message}" "app=busybox0"
  1052. kube::test::if_has_string "${output_message}" "app=busybox1"
  1053. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1054. ## Annotate multiple busybox PODs recursively from directory of YAML files
  1055. # Pre-condition: busybox0 & busybox1 PODs exist
  1056. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1057. # Command
  1058. output_message=$(! kubectl annotate -f hack/testdata/recursive/pod annotatekey='annotatevalue' --recursive 2>&1 "${kube_flags[@]}")
  1059. # Post-condition: busybox0 & busybox1 PODs are annotated, and since busybox2 is malformed, it should error
  1060. kube::test::get_object_assert pods "{{range.items}}{{${annotations_field}.annotatekey}}:{{end}}" 'annotatevalue:annotatevalue:'
  1061. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1062. ## Apply multiple busybox PODs recursively from directory of YAML files
  1063. # Pre-condition: busybox0 & busybox1 PODs exist
  1064. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1065. # Command
  1066. output_message=$(! kubectl apply -f hack/testdata/recursive/pod-modify --recursive 2>&1 "${kube_flags[@]}")
  1067. # Post-condition: busybox0 & busybox1 PODs are updated, and since busybox2 is malformed, it should error
  1068. kube::test::get_object_assert pods "{{range.items}}{{${labels_field}.status}}:{{end}}" 'replaced:replaced:'
  1069. kube::test::if_has_string "${output_message}" 'error validating data: kind not set'
  1070. ## Convert multiple busybox PODs recursively from directory of YAML files
  1071. # Pre-condition: busybox0 & busybox1 PODs exist
  1072. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1073. # Command
  1074. output_message=$(! kubectl convert -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}")
  1075. # Post-condition: busybox0 & busybox1 PODs are converted, and since busybox2 is malformed, it should error
  1076. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1077. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1078. ## Get multiple busybox PODs recursively from directory of YAML files
  1079. # Pre-condition: busybox0 & busybox1 PODs exist
  1080. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1081. # Command
  1082. output_message=$(! kubectl get -f hack/testdata/recursive/pod --recursive 2>&1 "${kube_flags[@]}" -o go-template="{{range.items}}{{$id_field}}:{{end}}")
  1083. # Post-condition: busybox0 & busybox1 PODs are retrieved, but because busybox2 is malformed, it should not show up
  1084. kube::test::if_has_string "${output_message}" "busybox0:busybox1:"
  1085. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1086. ## Label multiple busybox PODs recursively from directory of YAML files
  1087. # Pre-condition: busybox0 & busybox1 PODs exist
  1088. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1089. # Command
  1090. output_message=$(! kubectl label -f hack/testdata/recursive/pod mylabel='myvalue' --recursive 2>&1 "${kube_flags[@]}")
  1091. echo $output_message
  1092. # Post-condition: busybox0 & busybox1 PODs are labeled, but because busybox2 is malformed, it should not show up
  1093. kube::test::get_object_assert pods "{{range.items}}{{${labels_field}.mylabel}}:{{end}}" 'myvalue:myvalue:'
  1094. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1095. ## Patch multiple busybox PODs recursively from directory of YAML files
  1096. # Pre-condition: busybox0 & busybox1 PODs exist
  1097. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1098. # Command
  1099. output_message=$(! kubectl patch -f hack/testdata/recursive/pod -p='{"spec":{"containers":[{"name":"busybox","image":"prom/busybox"}]}}' --recursive 2>&1 "${kube_flags[@]}")
  1100. echo $output_message
  1101. # Post-condition: busybox0 & busybox1 PODs are patched, but because busybox2 is malformed, it should not show up
  1102. kube::test::get_object_assert pods "{{range.items}}{{$image_field}}:{{end}}" 'prom/busybox:prom/busybox:'
  1103. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1104. ### Delete multiple busybox PODs recursively from directory of YAML files
  1105. # Pre-condition: busybox0 & busybox1 PODs exist
  1106. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1107. # Command
  1108. output_message=$(! kubectl delete -f hack/testdata/recursive/pod --recursive --grace-period=0 2>&1 "${kube_flags[@]}")
  1109. # Post-condition: busybox0 & busybox1 PODs are deleted, and since busybox2 is malformed, it should error
  1110. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  1111. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1112. ### Create replication controller recursively from directory of YAML files
  1113. # Pre-condition: no replication controller exists
  1114. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1115. # Command
  1116. ! kubectl create -f hack/testdata/recursive/rc --recursive "${kube_flags[@]}"
  1117. # Post-condition: frontend replication controller is created
  1118. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1119. ### Autoscale multiple replication controllers recursively from directory of YAML files
  1120. # Pre-condition: busybox0 & busybox1 replication controllers exist & 1
  1121. # replica each
  1122. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1123. kube::test::get_object_assert 'rc busybox0' "{{$rc_replicas_field}}" '1'
  1124. kube::test::get_object_assert 'rc busybox1' "{{$rc_replicas_field}}" '1'
  1125. # Command
  1126. output_message=$(! kubectl autoscale --min=1 --max=2 -f hack/testdata/recursive/rc --recursive 2>&1 "${kube_flags[@]}")
  1127. # Post-condition: busybox0 & busybox replication controllers are autoscaled
  1128. # with min. of 1 replica & max of 2 replicas, and since busybox2 is malformed, it should error
  1129. kube::test::get_object_assert 'hpa busybox0' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '1 2 <no value>'
  1130. kube::test::get_object_assert 'hpa busybox1' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '1 2 <no value>'
  1131. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1132. kubectl delete hpa busybox0 "${kube_flags[@]}"
  1133. kubectl delete hpa busybox1 "${kube_flags[@]}"
  1134. ### Expose multiple replication controllers as service recursively from directory of YAML files
  1135. # Pre-condition: busybox0 & busybox1 replication controllers exist & 1
  1136. # replica each
  1137. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1138. kube::test::get_object_assert 'rc busybox0' "{{$rc_replicas_field}}" '1'
  1139. kube::test::get_object_assert 'rc busybox1' "{{$rc_replicas_field}}" '1'
  1140. # Command
  1141. output_message=$(! kubectl expose -f hack/testdata/recursive/rc --recursive --port=80 2>&1 "${kube_flags[@]}")
  1142. # Post-condition: service exists and the port is unnamed
  1143. kube::test::get_object_assert 'service busybox0' "{{$port_name}} {{$port_field}}" '<no value> 80'
  1144. kube::test::get_object_assert 'service busybox1' "{{$port_name}} {{$port_field}}" '<no value> 80'
  1145. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1146. ### Scale multiple replication controllers recursively from directory of YAML files
  1147. # Pre-condition: busybox0 & busybox1 replication controllers exist & 1
  1148. # replica each
  1149. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1150. kube::test::get_object_assert 'rc busybox0' "{{$rc_replicas_field}}" '1'
  1151. kube::test::get_object_assert 'rc busybox1' "{{$rc_replicas_field}}" '1'
  1152. # Command
  1153. output_message=$(! kubectl scale --current-replicas=1 --replicas=2 -f hack/testdata/recursive/rc --recursive 2>&1 "${kube_flags[@]}")
  1154. # Post-condition: busybox0 & busybox1 replication controllers are scaled to 2 replicas, and since busybox2 is malformed, it should error
  1155. kube::test::get_object_assert 'rc busybox0' "{{$rc_replicas_field}}" '2'
  1156. kube::test::get_object_assert 'rc busybox1' "{{$rc_replicas_field}}" '2'
  1157. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1158. ### Delete multiple busybox replication controllers recursively from directory of YAML files
  1159. # Pre-condition: busybox0 & busybox1 PODs exist
  1160. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1161. # Command
  1162. output_message=$(! kubectl delete -f hack/testdata/recursive/rc --recursive --grace-period=0 2>&1 "${kube_flags[@]}")
  1163. # Post-condition: busybox0 & busybox1 replication controllers are deleted, and since busybox2 is malformed, it should error
  1164. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  1165. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1166. ### Rollout on multiple deployments recursively
  1167. # Pre-condition: no deployments exist
  1168. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
  1169. # Command
  1170. # Create deployments (revision 1) recursively from directory of YAML files
  1171. ! kubectl create -f hack/testdata/recursive/deployment --recursive "${kube_flags[@]}"
  1172. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx0-deployment:nginx1-deployment:'
  1173. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
  1174. ## Rollback the deployments to revision 1 recursively
  1175. output_message=$(! kubectl rollout undo -f hack/testdata/recursive/deployment --recursive --to-revision=1 2>&1 "${kube_flags[@]}")
  1176. # Post-condition: nginx0 & nginx1 should be a no-op, and since nginx2 is malformed, it should error
  1177. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_NGINX}:${IMAGE_NGINX}:"
  1178. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1179. ## Pause the deployments recursively
  1180. PRESERVE_ERR_FILE=true
  1181. kubectl-with-retry rollout pause -f hack/testdata/recursive/deployment --recursive "${kube_flags[@]}"
  1182. output_message=$(cat ${ERROR_FILE})
  1183. # Post-condition: nginx0 & nginx1 should both have paused set to true, and since nginx2 is malformed, it should error
  1184. kube::test::get_object_assert deployment "{{range.items}}{{.spec.paused}}:{{end}}" "true:true:"
  1185. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1186. ## Resume the deployments recursively
  1187. kubectl-with-retry rollout resume -f hack/testdata/recursive/deployment --recursive "${kube_flags[@]}"
  1188. output_message=$(cat ${ERROR_FILE})
  1189. # Post-condition: nginx0 & nginx1 should both have paused set to nothing, and since nginx2 is malformed, it should error
  1190. kube::test::get_object_assert deployment "{{range.items}}{{.spec.paused}}:{{end}}" "<no value>:<no value>:"
  1191. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1192. ## Retrieve the rollout history of the deployments recursively
  1193. output_message=$(! kubectl rollout history -f hack/testdata/recursive/deployment --recursive 2>&1 "${kube_flags[@]}")
  1194. # Post-condition: nginx0 & nginx1 should both have a history, and since nginx2 is malformed, it should error
  1195. kube::test::if_has_string "${output_message}" "nginx0-deployment"
  1196. kube::test::if_has_string "${output_message}" "nginx1-deployment"
  1197. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1198. # Clean up
  1199. unset PRESERVE_ERR_FILE
  1200. rm "${ERROR_FILE}"
  1201. ! kubectl delete -f hack/testdata/recursive/deployment --recursive "${kube_flags[@]}" --grace-period=0
  1202. sleep 1
  1203. ### Rollout on multiple replication controllers recursively - these tests ensure that rollouts cannot be performed on resources that don't support it
  1204. # Pre-condition: no replication controller exists
  1205. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1206. # Command
  1207. # Create replication controllers recursively from directory of YAML files
  1208. ! kubectl create -f hack/testdata/recursive/rc --recursive "${kube_flags[@]}"
  1209. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'busybox0:busybox1:'
  1210. # Command
  1211. ## Attempt to rollback the replication controllers to revision 1 recursively
  1212. output_message=$(! kubectl rollout undo -f hack/testdata/recursive/rc --recursive --to-revision=1 2>&1 "${kube_flags[@]}")
  1213. # Post-condition: busybox0 & busybox1 should error as they are RC's, and since busybox2 is malformed, it should error
  1214. kube::test::if_has_string "${output_message}" 'no rollbacker has been implemented for {"" "ReplicationController"}'
  1215. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1216. ## Attempt to pause the replication controllers recursively
  1217. output_message=$(! kubectl rollout pause -f hack/testdata/recursive/rc --recursive 2>&1 "${kube_flags[@]}")
  1218. # Post-condition: busybox0 & busybox1 should error as they are RC's, and since busybox2 is malformed, it should error
  1219. kube::test::if_has_string "${output_message}" 'error when pausing "hack/testdata/recursive/rc/busybox.yaml'
  1220. kube::test::if_has_string "${output_message}" 'error when pausing "hack/testdata/recursive/rc/rc/busybox.yaml'
  1221. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1222. ## Attempt to resume the replication controllers recursively
  1223. output_message=$(! kubectl rollout resume -f hack/testdata/recursive/rc --recursive 2>&1 "${kube_flags[@]}")
  1224. # Post-condition: busybox0 & busybox1 should error as they are RC's, and since busybox2 is malformed, it should error
  1225. kube::test::if_has_string "${output_message}" 'error when resuming "hack/testdata/recursive/rc/busybox.yaml'
  1226. kube::test::if_has_string "${output_message}" 'error when resuming "hack/testdata/recursive/rc/rc/busybox.yaml'
  1227. kube::test::if_has_string "${output_message}" "Object 'Kind' is missing"
  1228. # Clean up
  1229. ! kubectl delete -f hack/testdata/recursive/rc --recursive "${kube_flags[@]}" --grace-period=0
  1230. sleep 1
  1231. ##############
  1232. # Namespaces #
  1233. ##############
  1234. ### Create a new namespace
  1235. # Pre-condition: only the "default" namespace exists
  1236. # The Pre-condition doesn't hold anymore after we create and switch namespaces before creating pods with same name in the test.
  1237. # kube::test::get_object_assert namespaces "{{range.items}}{{$id_field}}:{{end}}" 'default:'
  1238. # Command
  1239. kubectl create namespace my-namespace
  1240. # Post-condition: namespace 'my-namespace' is created.
  1241. kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace'
  1242. # Clean up
  1243. kubectl delete namespace my-namespace
  1244. ##############
  1245. # Pods in Namespaces #
  1246. ##############
  1247. ### Create a new namespace
  1248. # Pre-condition: the other namespace does not exist
  1249. kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"other\" }}found{{end}}{{end}}:' ':'
  1250. # Command
  1251. kubectl create namespace other
  1252. # Post-condition: namespace 'other' is created.
  1253. kube::test::get_object_assert 'namespaces/other' "{{$id_field}}" 'other'
  1254. ### Create POD valid-pod in specific namespace
  1255. # Pre-condition: no POD exists
  1256. kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
  1257. # Command
  1258. kubectl create "${kube_flags[@]}" --namespace=other -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
  1259. # Post-condition: valid-pod POD is created
  1260. kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  1261. # Post-condition: verify shorthand `-n other` has the same results as `--namespace=other`
  1262. kube::test::get_object_assert 'pods -n other' "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  1263. ### Delete POD valid-pod in specific namespace
  1264. # Pre-condition: valid-pod POD exists
  1265. kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  1266. # Command
  1267. kubectl delete "${kube_flags[@]}" pod --namespace=other valid-pod --grace-period=0
  1268. # Post-condition: valid-pod POD doesn't exist
  1269. kube::test::get_object_assert 'pods --namespace=other' "{{range.items}}{{$id_field}}:{{end}}" ''
  1270. # Clean up
  1271. kubectl delete namespace other
  1272. ##############
  1273. # Secrets #
  1274. ##############
  1275. ### Create a new namespace
  1276. # Pre-condition: the test-secrets namespace does not exist
  1277. kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-secrets\" }}found{{end}}{{end}}:' ':'
  1278. # Command
  1279. kubectl create namespace test-secrets
  1280. # Post-condition: namespace 'test-secrets' is created.
  1281. kube::test::get_object_assert 'namespaces/test-secrets' "{{$id_field}}" 'test-secrets'
  1282. ### Create a generic secret in a specific namespace
  1283. # Pre-condition: no SECRET exists
  1284. kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
  1285. # Command
  1286. kubectl create secret generic test-secret --from-literal=key1=value1 --type=test-type --namespace=test-secrets
  1287. # Post-condition: secret exists and has expected values
  1288. kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
  1289. kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'test-type'
  1290. [[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep 'key1: dmFsdWUx')" ]]
  1291. # Clean-up
  1292. kubectl delete secret test-secret --namespace=test-secrets
  1293. ### Create a docker-registry secret in a specific namespace
  1294. # Pre-condition: no SECRET exists
  1295. kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
  1296. # Command
  1297. kubectl create secret docker-registry test-secret --docker-username=test-user --docker-password=test-password --docker-email='test-user@test.com' --namespace=test-secrets
  1298. # Post-condition: secret exists and has expected values
  1299. kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
  1300. kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/dockercfg'
  1301. [[ "$(kubectl get secret/test-secret --namespace=test-secrets -o yaml "${kube_flags[@]}" | grep '.dockercfg:')" ]]
  1302. # Clean-up
  1303. kubectl delete secret test-secret --namespace=test-secrets
  1304. ### Create a tls secret
  1305. # Pre-condition: no SECRET exists
  1306. kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
  1307. # Command
  1308. kubectl create secret tls test-secret --namespace=test-secrets --key=hack/testdata/tls.key --cert=hack/testdata/tls.crt
  1309. kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$id_field}}" 'test-secret'
  1310. kube::test::get_object_assert 'secret/test-secret --namespace=test-secrets' "{{$secret_type}}" 'kubernetes.io/tls'
  1311. # Clean-up
  1312. kubectl delete secret test-secret --namespace=test-secrets
  1313. # Create a secret using stringData
  1314. kubectl create --namespace=test-secrets -f - "${kube_flags[@]}" << __EOF__
  1315. {
  1316. "kind": "Secret",
  1317. "apiVersion": "v1",
  1318. "metadata": {
  1319. "name": "secret-string-data"
  1320. },
  1321. "data": {
  1322. "k1":"djE=",
  1323. "k2":""
  1324. },
  1325. "stringData": {
  1326. "k2":"v2"
  1327. }
  1328. }
  1329. __EOF__
  1330. # Post-condition: secret-string-data secret is created with expected data, merged/overridden data from stringData, and a cleared stringData field
  1331. kube::test::get_object_assert 'secret/secret-string-data --namespace=test-secrets ' '{{.data}}' '.*k1:djE=.*'
  1332. kube::test::get_object_assert 'secret/secret-string-data --namespace=test-secrets ' '{{.data}}' '.*k2:djI=.*'
  1333. kube::test::get_object_assert 'secret/secret-string-data --namespace=test-secrets ' '{{.stringData}}' '<no value>'
  1334. # Clean up
  1335. kubectl delete secret secret-string-data --namespace=test-secrets
  1336. ### Create a secret using output flags
  1337. # Pre-condition: no secret exists
  1338. kube::test::get_object_assert 'secrets --namespace=test-secrets' "{{range.items}}{{$id_field}}:{{end}}" ''
  1339. # Command
  1340. [[ "$(kubectl create secret generic test-secret --namespace=test-secrets --from-literal=key1=value1 --output=go-template --template=\"{{.metadata.name}}:\" | grep 'test-secret:')" ]]
  1341. ## Clean-up
  1342. kubectl delete secret test-secret --namespace=test-secrets
  1343. # Clean up
  1344. kubectl delete namespace test-secrets
  1345. ######################
  1346. # ConfigMap #
  1347. ######################
  1348. kubectl create -f test/fixtures/doc-yaml/user-guide/configmap/configmap.yaml
  1349. kube::test::get_object_assert configmap "{{range.items}}{{$id_field}}{{end}}" 'test-configmap'
  1350. kubectl delete configmap test-configmap "${kube_flags[@]}"
  1351. ### Create a new namespace
  1352. # Pre-condition: the test-configmaps namespace does not exist
  1353. kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-configmaps\" }}found{{end}}{{end}}:' ':'
  1354. # Command
  1355. kubectl create namespace test-configmaps
  1356. # Post-condition: namespace 'test-configmaps' is created.
  1357. kube::test::get_object_assert 'namespaces/test-configmaps' "{{$id_field}}" 'test-configmaps'
  1358. ### Create a generic configmap in a specific namespace
  1359. # Pre-condition: no configmaps namespace exists
  1360. kube::test::get_object_assert 'configmaps --namespace=test-configmaps' "{{range.items}}{{$id_field}}:{{end}}" ''
  1361. # Command
  1362. kubectl create configmap test-configmap --from-literal=key1=value1 --namespace=test-configmaps
  1363. # Post-condition: configmap exists and has expected values
  1364. kube::test::get_object_assert 'configmap/test-configmap --namespace=test-configmaps' "{{$id_field}}" 'test-configmap'
  1365. [[ "$(kubectl get configmap/test-configmap --namespace=test-configmaps -o yaml "${kube_flags[@]}" | grep 'key1: value1')" ]]
  1366. # Clean-up
  1367. kubectl delete configmap test-configmap --namespace=test-configmaps
  1368. kubectl delete namespace test-configmaps
  1369. ####################
  1370. # Service Accounts #
  1371. ####################
  1372. ### Create a new namespace
  1373. # Pre-condition: the test-service-accounts namespace does not exist
  1374. kube::test::get_object_assert 'namespaces' '{{range.items}}{{ if eq $id_field \"test-service-accounts\" }}found{{end}}{{end}}:' ':'
  1375. # Command
  1376. kubectl create namespace test-service-accounts
  1377. # Post-condition: namespace 'test-service-accounts' is created.
  1378. kube::test::get_object_assert 'namespaces/test-service-accounts' "{{$id_field}}" 'test-service-accounts'
  1379. ### Create a service account in a specific namespace
  1380. # Command
  1381. kubectl create serviceaccount test-service-account --namespace=test-service-accounts
  1382. # Post-condition: secret exists and has expected values
  1383. kube::test::get_object_assert 'serviceaccount/test-service-account --namespace=test-service-accounts' "{{$id_field}}" 'test-service-account'
  1384. # Clean-up
  1385. kubectl delete serviceaccount test-service-account --namespace=test-service-accounts
  1386. # Clean up
  1387. kubectl delete namespace test-service-accounts
  1388. #################
  1389. # Pod templates #
  1390. #################
  1391. ### Create PODTEMPLATE
  1392. # Pre-condition: no PODTEMPLATE
  1393. kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" ''
  1394. # Command
  1395. kubectl create -f test/fixtures/doc-yaml/user-guide/walkthrough/podtemplate.json "${kube_flags[@]}"
  1396. # Post-condition: nginx PODTEMPLATE is available
  1397. kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" 'nginx:'
  1398. ### Printing pod templates works
  1399. kubectl get podtemplates "${kube_flags[@]}"
  1400. [[ "$(kubectl get podtemplates -o yaml "${kube_flags[@]}" | grep nginx)" ]]
  1401. ### Delete nginx pod template by name
  1402. # Pre-condition: nginx pod template is available
  1403. kube::test::get_object_assert podtemplates "{{range.items}}{{.metadata.name}}:{{end}}" 'nginx:'
  1404. # Command
  1405. kubectl delete podtemplate nginx "${kube_flags[@]}"
  1406. # Post-condition: No templates exist
  1407. kube::test::get_object_assert podtemplate "{{range.items}}{{.metadata.name}}:{{end}}" ''
  1408. ############
  1409. # Services #
  1410. ############
  1411. # switch back to the default namespace
  1412. kubectl config set-context "${CONTEXT}" --namespace=""
  1413. kube::log::status "Testing kubectl(${version}:services)"
  1414. ### Create redis-master service from JSON
  1415. # Pre-condition: Only the default kubernetes services exist
  1416. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1417. # Command
  1418. kubectl create -f examples/guestbook/redis-master-service.yaml "${kube_flags[@]}"
  1419. # Post-condition: redis-master service exists
  1420. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
  1421. # Describe command should print detailed information
  1422. kube::test::describe_object_assert services 'redis-master' "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:"
  1423. # Describe command should print events information by default
  1424. kube::test::describe_object_events_assert services 'redis-master'
  1425. # Describe command should not print events information when show-events=false
  1426. kube::test::describe_object_events_assert services 'redis-master' false
  1427. # Describe command should print events information when show-events=true
  1428. kube::test::describe_object_events_assert services 'redis-master' true
  1429. # Describe command (resource only) should print detailed information
  1430. kube::test::describe_resource_assert services "Name:" "Labels:" "Selector:" "IP:" "Port:" "Endpoints:" "Session Affinity:"
  1431. # Describe command should print events information by default
  1432. kube::test::describe_resource_events_assert services
  1433. # Describe command should not print events information when show-events=false
  1434. kube::test::describe_resource_events_assert services false
  1435. # Describe command should print events information when show-events=true
  1436. kube::test::describe_resource_events_assert services true
  1437. ### Dump current redis-master service
  1438. output_service=$(kubectl get service redis-master -o json --output-version=v1 "${kube_flags[@]}")
  1439. ### Delete redis-master-service by id
  1440. # Pre-condition: redis-master service exists
  1441. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
  1442. # Command
  1443. kubectl delete service redis-master "${kube_flags[@]}"
  1444. # Post-condition: Only the default kubernetes services exist
  1445. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1446. ### Create redis-master-service from dumped JSON
  1447. # Pre-condition: Only the default kubernetes services exist
  1448. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1449. # Command
  1450. echo "${output_service}" | kubectl create -f - "${kube_flags[@]}"
  1451. # Post-condition: redis-master service is created
  1452. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
  1453. ### Create redis-master-${version}-test service
  1454. # Pre-condition: redis-master-service service exists
  1455. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:'
  1456. # Command
  1457. kubectl create -f - "${kube_flags[@]}" << __EOF__
  1458. {
  1459. "kind": "Service",
  1460. "apiVersion": "v1",
  1461. "metadata": {
  1462. "name": "service-${version}-test"
  1463. },
  1464. "spec": {
  1465. "ports": [
  1466. {
  1467. "protocol": "TCP",
  1468. "port": 80,
  1469. "targetPort": 80
  1470. }
  1471. ]
  1472. }
  1473. }
  1474. __EOF__
  1475. # Post-condition: service-${version}-test service is created
  1476. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:service-.*-test:'
  1477. ### Identity
  1478. kubectl get service "${kube_flags[@]}" service-${version}-test -o json | kubectl replace "${kube_flags[@]}" -f -
  1479. ### Delete services by id
  1480. # Pre-condition: service-${version}-test exists
  1481. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:service-.*-test:'
  1482. # Command
  1483. kubectl delete service redis-master "${kube_flags[@]}"
  1484. kubectl delete service "service-${version}-test" "${kube_flags[@]}"
  1485. # Post-condition: Only the default kubernetes services exist
  1486. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1487. ### Create two services
  1488. # Pre-condition: Only the default kubernetes services exist
  1489. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1490. # Command
  1491. kubectl create -f examples/guestbook/redis-master-service.yaml "${kube_flags[@]}"
  1492. kubectl create -f examples/guestbook/redis-slave-service.yaml "${kube_flags[@]}"
  1493. # Post-condition: redis-master and redis-slave services are created
  1494. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:'
  1495. ### Custom columns can be specified
  1496. # Pre-condition: generate output using custom columns
  1497. output_message=$(kubectl get services -o=custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion 2>&1 "${kube_flags[@]}")
  1498. # Post-condition: should contain name column
  1499. kube::test::if_has_string "${output_message}" 'redis-master'
  1500. ### Delete multiple services at once
  1501. # Pre-condition: redis-master and redis-slave services exist
  1502. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:redis-master:redis-slave:'
  1503. # Command
  1504. kubectl delete services redis-master redis-slave "${kube_flags[@]}" # delete multiple services at once
  1505. # Post-condition: Only the default kubernetes services exist
  1506. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1507. ###########################
  1508. # Replication controllers #
  1509. ###########################
  1510. kube::log::status "Testing kubectl(${version}:replicationcontrollers)"
  1511. ### Create and stop controller, make sure it doesn't leak pods
  1512. # Pre-condition: no replication controller exists
  1513. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1514. # Command
  1515. kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  1516. kubectl delete rc frontend "${kube_flags[@]}"
  1517. # Post-condition: no pods from frontend controller
  1518. kube::test::get_object_assert 'pods -l "name=frontend"' "{{range.items}}{{$id_field}}:{{end}}" ''
  1519. ### Create replication controller frontend from JSON
  1520. # Pre-condition: no replication controller exists
  1521. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1522. # Command
  1523. kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  1524. # Post-condition: frontend replication controller is created
  1525. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
  1526. # Describe command should print detailed information
  1527. kube::test::describe_object_assert rc 'frontend' "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:"
  1528. # Describe command should print events information by default
  1529. kube::test::describe_object_events_assert rc 'frontend'
  1530. # Describe command should not print events information when show-events=false
  1531. kube::test::describe_object_events_assert rc 'frontend' false
  1532. # Describe command should print events information when show-events=true
  1533. kube::test::describe_object_events_assert rc 'frontend' true
  1534. # Describe command (resource only) should print detailed information
  1535. kube::test::describe_resource_assert rc "Name:" "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:"
  1536. # Describe command should print events information by default
  1537. kube::test::describe_resource_events_assert rc
  1538. # Describe command should not print events information when show-events=false
  1539. kube::test::describe_resource_events_assert rc false
  1540. # Describe command should print events information when show-events=true
  1541. kube::test::describe_resource_events_assert rc true
  1542. ### Scale replication controller frontend with current-replicas and replicas
  1543. # Pre-condition: 3 replicas
  1544. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
  1545. # Command
  1546. kubectl scale --current-replicas=3 --replicas=2 replicationcontrollers frontend "${kube_flags[@]}"
  1547. # Post-condition: 2 replicas
  1548. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
  1549. ### Scale replication controller frontend with (wrong) current-replicas and replicas
  1550. # Pre-condition: 2 replicas
  1551. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
  1552. # Command
  1553. ! kubectl scale --current-replicas=3 --replicas=2 replicationcontrollers frontend "${kube_flags[@]}"
  1554. # Post-condition: nothing changed
  1555. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
  1556. ### Scale replication controller frontend with replicas only
  1557. # Pre-condition: 2 replicas
  1558. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
  1559. # Command
  1560. kubectl scale --replicas=3 replicationcontrollers frontend "${kube_flags[@]}"
  1561. # Post-condition: 3 replicas
  1562. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
  1563. ### Scale replication controller from JSON with replicas only
  1564. # Pre-condition: 3 replicas
  1565. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
  1566. # Command
  1567. kubectl scale --replicas=2 -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  1568. # Post-condition: 2 replicas
  1569. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '2'
  1570. # Clean-up
  1571. kubectl delete rc frontend "${kube_flags[@]}"
  1572. ### Scale multiple replication controllers
  1573. kubectl create -f examples/guestbook/legacy/redis-master-controller.yaml "${kube_flags[@]}"
  1574. kubectl create -f examples/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}"
  1575. # Command
  1576. kubectl scale rc/redis-master rc/redis-slave --replicas=4 "${kube_flags[@]}"
  1577. # Post-condition: 4 replicas each
  1578. kube::test::get_object_assert 'rc redis-master' "{{$rc_replicas_field}}" '4'
  1579. kube::test::get_object_assert 'rc redis-slave' "{{$rc_replicas_field}}" '4'
  1580. # Clean-up
  1581. kubectl delete rc redis-{master,slave} "${kube_flags[@]}"
  1582. ### Scale a job
  1583. kubectl create -f test/fixtures/doc-yaml/user-guide/job.yaml "${kube_flags[@]}"
  1584. # Command
  1585. kubectl scale --replicas=2 job/pi
  1586. # Post-condition: 2 replicas for pi
  1587. kube::test::get_object_assert 'job pi' "{{$job_parallelism_field}}" '2'
  1588. # Clean-up
  1589. kubectl delete job/pi "${kube_flags[@]}"
  1590. ### Scale a deployment
  1591. kubectl create -f test/fixtures/doc-yaml/user-guide/deployment.yaml "${kube_flags[@]}"
  1592. # Command
  1593. kubectl scale --current-replicas=3 --replicas=1 deployment/nginx-deployment
  1594. # Post-condition: 1 replica for nginx-deployment
  1595. kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '1'
  1596. # Clean-up
  1597. kubectl delete deployment/nginx-deployment "${kube_flags[@]}"
  1598. ### Expose a deployment as a service
  1599. kubectl create -f test/fixtures/doc-yaml/user-guide/deployment.yaml "${kube_flags[@]}"
  1600. # Pre-condition: 3 replicas
  1601. kube::test::get_object_assert 'deployment nginx-deployment' "{{$deployment_replicas}}" '3'
  1602. # Command
  1603. kubectl expose deployment/nginx-deployment
  1604. # Post-condition: service exists and exposes deployment port (80)
  1605. kube::test::get_object_assert 'service nginx-deployment' "{{$port_field}}" '80'
  1606. # Clean-up
  1607. kubectl delete deployment/nginx-deployment service/nginx-deployment "${kube_flags[@]}"
  1608. ### Expose replication controller as service
  1609. kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  1610. # Pre-condition: 3 replicas
  1611. kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
  1612. # Command
  1613. kubectl expose rc frontend --port=80 "${kube_flags[@]}"
  1614. # Post-condition: service exists and the port is unnamed
  1615. kube::test::get_object_assert 'service frontend' "{{$port_name}} {{$port_field}}" '<no value> 80'
  1616. # Command
  1617. kubectl expose service frontend --port=443 --name=frontend-2 "${kube_flags[@]}"
  1618. # Post-condition: service exists and the port is unnamed
  1619. kube::test::get_object_assert 'service frontend-2' "{{$port_name}} {{$port_field}}" '<no value> 443'
  1620. # Command
  1621. kubectl create -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml "${kube_flags[@]}"
  1622. kubectl expose pod valid-pod --port=444 --name=frontend-3 "${kube_flags[@]}"
  1623. # Post-condition: service exists and the port is unnamed
  1624. kube::test::get_object_assert 'service frontend-3' "{{$port_name}} {{$port_field}}" '<no value> 444'
  1625. # Create a service using service/v1 generator
  1626. kubectl expose rc frontend --port=80 --name=frontend-4 --generator=service/v1 "${kube_flags[@]}"
  1627. # Post-condition: service exists and the port is named default.
  1628. kube::test::get_object_assert 'service frontend-4' "{{$port_name}} {{$port_field}}" 'default 80'
  1629. # Verify that expose service works without specifying a port.
  1630. kubectl expose service frontend --name=frontend-5 "${kube_flags[@]}"
  1631. # Post-condition: service exists with the same port as the original service.
  1632. kube::test::get_object_assert 'service frontend-5' "{{$port_field}}" '80'
  1633. # Cleanup services
  1634. kubectl delete pod valid-pod "${kube_flags[@]}"
  1635. kubectl delete service frontend{,-2,-3,-4,-5} "${kube_flags[@]}"
  1636. ### Expose negative invalid resource test
  1637. # Pre-condition: don't need
  1638. # Command
  1639. output_message=$(! kubectl expose nodes 127.0.0.1 2>&1 "${kube_flags[@]}")
  1640. # Post-condition: the error message has "cannot expose" string
  1641. kube::test::if_has_string "${output_message}" 'cannot expose'
  1642. ### Try to generate a service with invalid name (exceeding maximum valid size)
  1643. # Pre-condition: use --name flag
  1644. 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[@]}")
  1645. # Post-condition: should fail due to invalid name
  1646. kube::test::if_has_string "${output_message}" 'metadata.name: Invalid value'
  1647. # Pre-condition: default run without --name flag; should succeed by truncating the inherited name
  1648. output_message=$(kubectl expose -f hack/testdata/pod-with-large-name.yaml --port=8081 2>&1 "${kube_flags[@]}")
  1649. # Post-condition: inherited name from pod has been truncated
  1650. kube::test::if_has_string "${output_message}" '\"kubernetes-serve-hostname-testing-sixty-three-characters-in-len\" exposed'
  1651. # Clean-up
  1652. kubectl delete svc kubernetes-serve-hostname-testing-sixty-three-characters-in-len "${kube_flags[@]}"
  1653. ### Expose multiport object as a new service
  1654. # Pre-condition: don't use --port flag
  1655. output_message=$(kubectl expose -f test/fixtures/doc-yaml/admin/high-availability/etcd.yaml --selector=test=etcd 2>&1 "${kube_flags[@]}")
  1656. # Post-condition: expose succeeded
  1657. kube::test::if_has_string "${output_message}" '\"etcd-server\" exposed'
  1658. # Post-condition: generated service has both ports from the exposed pod
  1659. kube::test::get_object_assert 'service etcd-server' "{{$port_name}} {{$port_field}}" 'port-1 2380'
  1660. kube::test::get_object_assert 'service etcd-server' "{{$second_port_name}} {{$second_port_field}}" 'port-2 2379'
  1661. # Clean-up
  1662. kubectl delete svc etcd-server "${kube_flags[@]}"
  1663. ### Delete replication controller with id
  1664. # Pre-condition: frontend replication controller exists
  1665. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
  1666. # Command
  1667. kubectl delete rc frontend "${kube_flags[@]}"
  1668. # Post-condition: no replication controller exists
  1669. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1670. ### Create two replication controllers
  1671. # Pre-condition: no replication controller exists
  1672. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1673. # Command
  1674. kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  1675. kubectl create -f examples/guestbook/legacy/redis-slave-controller.yaml "${kube_flags[@]}"
  1676. # Post-condition: frontend and redis-slave
  1677. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:'
  1678. ### Delete multiple controllers at once
  1679. # Pre-condition: frontend and redis-slave
  1680. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:'
  1681. # Command
  1682. kubectl delete rc frontend redis-slave "${kube_flags[@]}" # delete multiple controllers at once
  1683. # Post-condition: no replication controller exists
  1684. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1685. ### Auto scale replication controller
  1686. # Pre-condition: no replication controller exists
  1687. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1688. # Command
  1689. kubectl create -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}"
  1690. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
  1691. # autoscale 1~2 pods, CPU utilization 70%, rc specified by file
  1692. kubectl autoscale -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}" --max=2 --cpu-percent=70
  1693. kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '1 2 70'
  1694. kubectl delete hpa frontend "${kube_flags[@]}"
  1695. # autoscale 1~2 pods, CPU utilization 70%, rc specified by file, using old generator
  1696. kubectl autoscale -f hack/testdata/frontend-controller.yaml "${kube_flags[@]}" --max=2 --cpu-percent=70 --generator=horizontalpodautoscaler/v1beta1
  1697. kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '1 2 70'
  1698. kubectl delete hpa frontend "${kube_flags[@]}"
  1699. # autoscale 2~3 pods, no CPU utilization specified, rc specified by name
  1700. kubectl autoscale rc frontend "${kube_flags[@]}" --min=2 --max=3
  1701. kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '2 3 <no value>'
  1702. kubectl delete hpa frontend "${kube_flags[@]}"
  1703. # autoscale 2~3 pods, no CPU utilization specified, rc specified by name, using old generator
  1704. kubectl autoscale rc frontend "${kube_flags[@]}" --min=2 --max=3 --generator=horizontalpodautoscaler/v1beta1
  1705. kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '2 3 <no value>'
  1706. kubectl delete hpa frontend "${kube_flags[@]}"
  1707. # autoscale without specifying --max should fail
  1708. ! kubectl autoscale rc frontend "${kube_flags[@]}"
  1709. # Clean up
  1710. kubectl delete rc frontend "${kube_flags[@]}"
  1711. ######################
  1712. # Deployments #
  1713. ######################
  1714. ### Auto scale deployment
  1715. # Pre-condition: no deployment exists
  1716. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
  1717. # Command
  1718. kubectl create -f test/fixtures/doc-yaml/user-guide/deployment.yaml "${kube_flags[@]}"
  1719. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx-deployment:'
  1720. # autoscale 2~3 pods, no CPU utilization specified
  1721. kubectl-with-retry autoscale deployment nginx-deployment "${kube_flags[@]}" --min=2 --max=3
  1722. kube::test::get_object_assert 'hpa nginx-deployment' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '2 3 <no value>'
  1723. # Clean up
  1724. # Note that we should delete hpa first, otherwise it may fight with the deployment reaper.
  1725. kubectl delete hpa nginx-deployment "${kube_flags[@]}"
  1726. kubectl delete deployment.extensions nginx-deployment "${kube_flags[@]}"
  1727. ### Rollback a deployment
  1728. # Pre-condition: no deployment exists
  1729. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
  1730. # Command
  1731. # Create a deployment (revision 1)
  1732. kubectl create -f hack/testdata/deployment-revision1.yaml "${kube_flags[@]}"
  1733. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx:'
  1734. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1735. # Rollback to revision 1 - should be no-op
  1736. kubectl rollout undo deployment nginx --to-revision=1 "${kube_flags[@]}"
  1737. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1738. # Update the deployment (revision 2)
  1739. kubectl apply -f hack/testdata/deployment-revision2.yaml "${kube_flags[@]}"
  1740. kube::test::get_object_assert deployment.extensions "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
  1741. # Rollback to revision 1
  1742. kubectl rollout undo deployment nginx --to-revision=1 "${kube_flags[@]}"
  1743. sleep 1
  1744. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1745. # Rollback to revision 1000000 - should be no-op
  1746. kubectl rollout undo deployment nginx --to-revision=1000000 "${kube_flags[@]}"
  1747. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1748. # Rollback to last revision
  1749. kubectl rollout undo deployment nginx "${kube_flags[@]}"
  1750. sleep 1
  1751. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
  1752. # Pause the deployment
  1753. kubectl-with-retry rollout pause deployment nginx "${kube_flags[@]}"
  1754. # A paused deployment cannot be rolled back
  1755. ! kubectl rollout undo deployment nginx "${kube_flags[@]}"
  1756. # Resume the deployment
  1757. kubectl-with-retry rollout resume deployment nginx "${kube_flags[@]}"
  1758. # The resumed deployment can now be rolled back
  1759. kubectl rollout undo deployment nginx "${kube_flags[@]}"
  1760. # Clean up
  1761. kubectl delete deployment nginx "${kube_flags[@]}"
  1762. ### Set image of a deployment
  1763. # Pre-condition: no deployment exists
  1764. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" ''
  1765. # Create a deployment
  1766. kubectl create -f hack/testdata/deployment-multicontainer.yaml "${kube_flags[@]}"
  1767. kube::test::get_object_assert deployment "{{range.items}}{{$id_field}}:{{end}}" 'nginx-deployment:'
  1768. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1769. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
  1770. # Set the deployment's image
  1771. kubectl set image deployment nginx-deployment nginx="${IMAGE_DEPLOYMENT_R2}" "${kube_flags[@]}"
  1772. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
  1773. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
  1774. # Set non-existing container should fail
  1775. ! kubectl set image deployment nginx-deployment redis=redis "${kube_flags[@]}"
  1776. # Set image of deployments without specifying name
  1777. kubectl set image deployments --all nginx="${IMAGE_DEPLOYMENT_R1}" "${kube_flags[@]}"
  1778. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1779. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
  1780. # Set image of a deployment specified by file
  1781. kubectl set image -f hack/testdata/deployment-multicontainer.yaml nginx="${IMAGE_DEPLOYMENT_R2}" "${kube_flags[@]}"
  1782. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
  1783. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
  1784. # Set image of a local file without talking to the server
  1785. kubectl set image -f hack/testdata/deployment-multicontainer.yaml nginx="${IMAGE_DEPLOYMENT_R1}" "${kube_flags[@]}" --local -o yaml
  1786. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R2}:"
  1787. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_PERL}:"
  1788. # Set image of all containers of the deployment
  1789. kubectl set image deployment nginx-deployment "*"="${IMAGE_DEPLOYMENT_R1}" "${kube_flags[@]}"
  1790. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1791. kube::test::get_object_assert deployment "{{range.items}}{{$deployment_second_image_field}}:{{end}}" "${IMAGE_DEPLOYMENT_R1}:"
  1792. # Clean up
  1793. kubectl delete deployment nginx-deployment "${kube_flags[@]}"
  1794. ######################
  1795. # Replica Sets #
  1796. ######################
  1797. kube::log::status "Testing kubectl(${version}:replicasets)"
  1798. ### Create and stop a replica set, make sure it doesn't leak pods
  1799. # Pre-condition: no replica set exists
  1800. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" ''
  1801. # Command
  1802. kubectl create -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}"
  1803. kubectl delete rs frontend "${kube_flags[@]}"
  1804. # Post-condition: no pods from frontend replica set
  1805. kube::test::get_object_assert 'pods -l "tier=frontend"' "{{range.items}}{{$id_field}}:{{end}}" ''
  1806. ### Create replica set frontend from YAML
  1807. # Pre-condition: no replica set exists
  1808. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" ''
  1809. # Command
  1810. kubectl create -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}"
  1811. # Post-condition: frontend replica set is created
  1812. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
  1813. # Describe command should print detailed information
  1814. kube::test::describe_object_assert rs 'frontend' "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:"
  1815. # Describe command should print events information by default
  1816. kube::test::describe_object_events_assert rs 'frontend'
  1817. # Describe command should not print events information when show-events=false
  1818. kube::test::describe_object_events_assert rs 'frontend' false
  1819. # Describe command should print events information when show-events=true
  1820. kube::test::describe_object_events_assert rs 'frontend' true
  1821. # Describe command (resource only) should print detailed information
  1822. kube::test::describe_resource_assert rs "Name:" "Name:" "Image(s):" "Labels:" "Selector:" "Replicas:" "Pods Status:"
  1823. # Describe command should print events information by default
  1824. kube::test::describe_resource_events_assert rs
  1825. # Describe command should not print events information when show-events=false
  1826. kube::test::describe_resource_events_assert rs false
  1827. # Describe command should print events information when show-events=true
  1828. kube::test::describe_resource_events_assert rs true
  1829. ### Scale replica set frontend with current-replicas and replicas
  1830. # Pre-condition: 3 replicas
  1831. kube::test::get_object_assert 'rs frontend' "{{$rs_replicas_field}}" '3'
  1832. # Command
  1833. kubectl scale --current-replicas=3 --replicas=2 replicasets frontend "${kube_flags[@]}"
  1834. # Post-condition: 2 replicas
  1835. kube::test::get_object_assert 'rs frontend' "{{$rs_replicas_field}}" '2'
  1836. # Clean-up
  1837. kubectl delete rs frontend "${kube_flags[@]}"
  1838. ### Expose replica set as service
  1839. kubectl create -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}"
  1840. # Pre-condition: 3 replicas
  1841. kube::test::get_object_assert 'rs frontend' "{{$rs_replicas_field}}" '3'
  1842. # Command
  1843. kubectl expose rs frontend --port=80 "${kube_flags[@]}"
  1844. # Post-condition: service exists and the port is unnamed
  1845. kube::test::get_object_assert 'service frontend' "{{$port_name}} {{$port_field}}" '<no value> 80'
  1846. # Create a service using service/v1 generator
  1847. kubectl expose rs frontend --port=80 --name=frontend-2 --generator=service/v1 "${kube_flags[@]}"
  1848. # Post-condition: service exists and the port is named default.
  1849. kube::test::get_object_assert 'service frontend-2' "{{$port_name}} {{$port_field}}" 'default 80'
  1850. # Cleanup services
  1851. kubectl delete service frontend{,-2} "${kube_flags[@]}"
  1852. ### Delete replica set with id
  1853. # Pre-condition: frontend replica set exists
  1854. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
  1855. # Command
  1856. kubectl delete rs frontend "${kube_flags[@]}"
  1857. # Post-condition: no replica set exists
  1858. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" ''
  1859. ### Create two replica sets
  1860. # Pre-condition: no replica set exists
  1861. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" ''
  1862. # Command
  1863. kubectl create -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}"
  1864. kubectl create -f hack/testdata/redis-slave-replicaset.yaml "${kube_flags[@]}"
  1865. # Post-condition: frontend and redis-slave
  1866. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:'
  1867. ### Delete multiple replica sets at once
  1868. # Pre-condition: frontend and redis-slave
  1869. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:redis-slave:'
  1870. # Command
  1871. kubectl delete rs frontend redis-slave "${kube_flags[@]}" # delete multiple replica sets at once
  1872. # Post-condition: no replica set exists
  1873. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" ''
  1874. ### Auto scale replica set
  1875. # Pre-condition: no replica set exists
  1876. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" ''
  1877. # Command
  1878. kubectl create -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}"
  1879. kube::test::get_object_assert rs "{{range.items}}{{$id_field}}:{{end}}" 'frontend:'
  1880. # autoscale 1~2 pods, CPU utilization 70%, replica set specified by file
  1881. kubectl autoscale -f hack/testdata/frontend-replicaset.yaml "${kube_flags[@]}" --max=2 --cpu-percent=70
  1882. kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '1 2 70'
  1883. kubectl delete hpa frontend "${kube_flags[@]}"
  1884. # autoscale 2~3 pods, no CPU utilization specified, replica set specified by name
  1885. kubectl autoscale rs frontend "${kube_flags[@]}" --min=2 --max=3
  1886. kube::test::get_object_assert 'hpa frontend' "{{$hpa_min_field}} {{$hpa_max_field}} {{$hpa_cpu_field}}" '2 3 <no value>'
  1887. kubectl delete hpa frontend "${kube_flags[@]}"
  1888. # autoscale without specifying --max should fail
  1889. ! kubectl autoscale rs frontend "${kube_flags[@]}"
  1890. # Clean up
  1891. kubectl delete rs frontend "${kube_flags[@]}"
  1892. ############
  1893. # Pet Sets #
  1894. ############
  1895. kube::log::status "Testing kubectl(${version}:petsets)"
  1896. ### Create and stop petset, make sure it doesn't leak pods
  1897. # Pre-condition: no petset exists
  1898. kube::test::get_object_assert petset "{{range.items}}{{$id_field}}:{{end}}" ''
  1899. # Command: create petset
  1900. kubectl create -f hack/testdata/nginx-petset.yaml "${kube_flags[@]}"
  1901. ### Scale petset test with current-replicas and replicas
  1902. # Pre-condition: 0 replicas
  1903. kube::test::get_object_assert 'petset nginx' "{{$petset_replicas_field}}" '0'
  1904. # Command: Scale up
  1905. kubectl scale --current-replicas=0 --replicas=1 petset nginx "${kube_flags[@]}"
  1906. # Post-condition: 1 replica, named nginx-0
  1907. kube::test::get_object_assert 'petset nginx' "{{$petset_replicas_field}}" '1'
  1908. # Typically we'd wait and confirm that N>1 replicas are up, but this framework
  1909. # doesn't start the scheduler, so pet-0 will block all others.
  1910. # TODO: test robust scaling in an e2e.
  1911. wait-for-pods-with-label "app=nginx-petset" "nginx-0"
  1912. ### Clean up
  1913. kubectl delete -f hack/testdata/nginx-petset.yaml "${kube_flags[@]}"
  1914. # Post-condition: no pods from petset controller
  1915. wait-for-pods-with-label "app=nginx-petset" ""
  1916. ######################
  1917. # Lists #
  1918. ######################
  1919. kube::log::status "Testing kubectl(${version}:lists)"
  1920. ### Create a List with objects from multiple versions
  1921. # Command
  1922. kubectl create -f hack/testdata/list.yaml "${kube_flags[@]}"
  1923. ### Delete the List with objects from multiple versions
  1924. # Command
  1925. kubectl delete service/list-service-test deployment/list-deployment-test
  1926. ######################
  1927. # Multiple Resources #
  1928. ######################
  1929. kube::log::status "Testing kubectl(${version}:multiple resources)"
  1930. FILES="hack/testdata/multi-resource-yaml
  1931. hack/testdata/multi-resource-list
  1932. hack/testdata/multi-resource-json
  1933. hack/testdata/multi-resource-rclist
  1934. hack/testdata/multi-resource-svclist"
  1935. YAML=".yaml"
  1936. JSON=".json"
  1937. for file in $FILES; do
  1938. if [ -f $file$YAML ]
  1939. then
  1940. file=$file$YAML
  1941. replace_file="${file%.yaml}-modify.yaml"
  1942. else
  1943. file=$file$JSON
  1944. replace_file="${file%.json}-modify.json"
  1945. fi
  1946. has_svc=true
  1947. has_rc=true
  1948. two_rcs=false
  1949. two_svcs=false
  1950. if [[ "${file}" == *rclist* ]]; then
  1951. has_svc=false
  1952. two_rcs=true
  1953. fi
  1954. if [[ "${file}" == *svclist* ]]; then
  1955. has_rc=false
  1956. two_svcs=true
  1957. fi
  1958. ### Create, get, describe, replace, label, annotate, and then delete service nginxsvc and replication controller my-nginx from 5 types of files:
  1959. ### 1) YAML, separated by ---; 2) JSON, with a List type; 3) JSON, with JSON object concatenation
  1960. ### 4) JSON, with a ReplicationControllerList type; 5) JSON, with a ServiceList type
  1961. echo "Testing with file ${file} and replace with file ${replace_file}"
  1962. # Pre-condition: no service (other than default kubernetes services) or replication controller exists
  1963. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  1964. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  1965. # Command
  1966. kubectl create -f "${file}" "${kube_flags[@]}"
  1967. # Post-condition: mock service (and mock2) exists
  1968. if [ "$has_svc" = true ]; then
  1969. if [ "$two_svcs" = true ]; then
  1970. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:mock:mock2:'
  1971. else
  1972. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:mock:'
  1973. fi
  1974. fi
  1975. # Post-condition: mock rc (and mock2) exists
  1976. if [ "$has_rc" = true ]; then
  1977. if [ "$two_rcs" = true ]; then
  1978. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'mock:mock2:'
  1979. else
  1980. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'mock:'
  1981. fi
  1982. fi
  1983. # Command
  1984. kubectl get -f "${file}" "${kube_flags[@]}"
  1985. # Command: watching multiple resources should return "not supported" error
  1986. WATCH_ERROR_FILE="${KUBE_TEMP}/kubectl-watch-error"
  1987. kubectl get -f "${file}" "${kube_flags[@]}" "--watch" 2> ${WATCH_ERROR_FILE} || true
  1988. if ! grep -q "watch is only supported on individual resources and resource collections" "${WATCH_ERROR_FILE}"; then
  1989. kube::log::error_exit "kubectl watch multiple resource returns unexpected error or non-error: $(cat ${WATCH_ERROR_FILE})" "1"
  1990. fi
  1991. kubectl describe -f "${file}" "${kube_flags[@]}"
  1992. # Command
  1993. kubectl replace -f $replace_file --force --cascade "${kube_flags[@]}"
  1994. # Post-condition: mock service (and mock2) and mock rc (and mock2) are replaced
  1995. if [ "$has_svc" = true ]; then
  1996. kube::test::get_object_assert 'services mock' "{{${labels_field}.status}}" 'replaced'
  1997. if [ "$two_svcs" = true ]; then
  1998. kube::test::get_object_assert 'services mock2' "{{${labels_field}.status}}" 'replaced'
  1999. fi
  2000. fi
  2001. if [ "$has_rc" = true ]; then
  2002. kube::test::get_object_assert 'rc mock' "{{${labels_field}.status}}" 'replaced'
  2003. if [ "$two_rcs" = true ]; then
  2004. kube::test::get_object_assert 'rc mock2' "{{${labels_field}.status}}" 'replaced'
  2005. fi
  2006. fi
  2007. # Command: kubectl edit multiple resources
  2008. temp_editor="${KUBE_TEMP}/tmp-editor.sh"
  2009. echo -e "#!/bin/bash\n$SED -i \"s/status\:\ replaced/status\:\ edited/g\" \$@" > "${temp_editor}"
  2010. chmod +x "${temp_editor}"
  2011. EDITOR="${temp_editor}" kubectl edit "${kube_flags[@]}" -f "${file}"
  2012. # Post-condition: mock service (and mock2) and mock rc (and mock2) are edited
  2013. if [ "$has_svc" = true ]; then
  2014. kube::test::get_object_assert 'services mock' "{{${labels_field}.status}}" 'edited'
  2015. if [ "$two_svcs" = true ]; then
  2016. kube::test::get_object_assert 'services mock2' "{{${labels_field}.status}}" 'edited'
  2017. fi
  2018. fi
  2019. if [ "$has_rc" = true ]; then
  2020. kube::test::get_object_assert 'rc mock' "{{${labels_field}.status}}" 'edited'
  2021. if [ "$two_rcs" = true ]; then
  2022. kube::test::get_object_assert 'rc mock2' "{{${labels_field}.status}}" 'edited'
  2023. fi
  2024. fi
  2025. # cleaning
  2026. rm "${temp_editor}"
  2027. # Command
  2028. # We need to set --overwrite, because otherwise, if the first attempt to run "kubectl label"
  2029. # fails on some, but not all, of the resources, retries will fail because it tries to modify
  2030. # existing labels.
  2031. kubectl-with-retry label -f $file labeled=true --overwrite "${kube_flags[@]}"
  2032. # Post-condition: mock service and mock rc (and mock2) are labeled
  2033. if [ "$has_svc" = true ]; then
  2034. kube::test::get_object_assert 'services mock' "{{${labels_field}.labeled}}" 'true'
  2035. if [ "$two_svcs" = true ]; then
  2036. kube::test::get_object_assert 'services mock2' "{{${labels_field}.labeled}}" 'true'
  2037. fi
  2038. fi
  2039. if [ "$has_rc" = true ]; then
  2040. kube::test::get_object_assert 'rc mock' "{{${labels_field}.labeled}}" 'true'
  2041. if [ "$two_rcs" = true ]; then
  2042. kube::test::get_object_assert 'rc mock2' "{{${labels_field}.labeled}}" 'true'
  2043. fi
  2044. fi
  2045. # Command
  2046. # Command
  2047. # We need to set --overwrite, because otherwise, if the first attempt to run "kubectl annotate"
  2048. # fails on some, but not all, of the resources, retries will fail because it tries to modify
  2049. # existing annotations.
  2050. kubectl-with-retry annotate -f $file annotated=true --overwrite "${kube_flags[@]}"
  2051. # Post-condition: mock service (and mock2) and mock rc (and mock2) are annotated
  2052. if [ "$has_svc" = true ]; then
  2053. kube::test::get_object_assert 'services mock' "{{${annotations_field}.annotated}}" 'true'
  2054. if [ "$two_svcs" = true ]; then
  2055. kube::test::get_object_assert 'services mock2' "{{${annotations_field}.annotated}}" 'true'
  2056. fi
  2057. fi
  2058. if [ "$has_rc" = true ]; then
  2059. kube::test::get_object_assert 'rc mock' "{{${annotations_field}.annotated}}" 'true'
  2060. if [ "$two_rcs" = true ]; then
  2061. kube::test::get_object_assert 'rc mock2' "{{${annotations_field}.annotated}}" 'true'
  2062. fi
  2063. fi
  2064. # Cleanup resources created
  2065. kubectl delete -f "${file}" "${kube_flags[@]}"
  2066. done
  2067. #############################
  2068. # Multiple Resources via URL#
  2069. #############################
  2070. # Pre-condition: no service (other than default kubernetes services) or replication controller exists
  2071. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  2072. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  2073. # Command
  2074. kubectl create -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/hack/testdata/multi-resource-yaml.yaml "${kube_flags[@]}"
  2075. # Post-condition: service(mock) and rc(mock) exist
  2076. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:mock:'
  2077. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" 'mock:'
  2078. # Clean up
  2079. kubectl delete -f https://raw.githubusercontent.com/kubernetes/kubernetes/master/hack/testdata/multi-resource-yaml.yaml "${kube_flags[@]}"
  2080. # Post-condition: no service (other than default kubernetes services) or replication controller exists
  2081. kube::test::get_object_assert services "{{range.items}}{{$id_field}}:{{end}}" 'kubernetes:'
  2082. kube::test::get_object_assert rc "{{range.items}}{{$id_field}}:{{end}}" ''
  2083. ######################
  2084. # Persistent Volumes #
  2085. ######################
  2086. ### Create and delete persistent volume examples
  2087. # Pre-condition: no persistent volumes currently exist
  2088. kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" ''
  2089. # Command
  2090. kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/volumes/local-01.yaml "${kube_flags[@]}"
  2091. kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" 'pv0001:'
  2092. kubectl delete pv pv0001 "${kube_flags[@]}"
  2093. kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/volumes/local-02.yaml "${kube_flags[@]}"
  2094. kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" 'pv0002:'
  2095. kubectl delete pv pv0002 "${kube_flags[@]}"
  2096. kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/volumes/gce.yaml "${kube_flags[@]}"
  2097. kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" 'pv0003:'
  2098. kubectl delete pv pv0003 "${kube_flags[@]}"
  2099. # Post-condition: no PVs
  2100. kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" ''
  2101. ############################
  2102. # Persistent Volume Claims #
  2103. ############################
  2104. ### Create and delete persistent volume claim examples
  2105. # Pre-condition: no persistent volume claims currently exist
  2106. kube::test::get_object_assert pvc "{{range.items}}{{$id_field}}:{{end}}" ''
  2107. # Command
  2108. kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/claims/claim-01.yaml "${kube_flags[@]}"
  2109. kube::test::get_object_assert pvc "{{range.items}}{{$id_field}}:{{end}}" 'myclaim-1:'
  2110. kubectl delete pvc myclaim-1 "${kube_flags[@]}"
  2111. kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/claims/claim-02.yaml "${kube_flags[@]}"
  2112. kube::test::get_object_assert pvc "{{range.items}}{{$id_field}}:{{end}}" 'myclaim-2:'
  2113. kubectl delete pvc myclaim-2 "${kube_flags[@]}"
  2114. kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/claims/claim-03.json "${kube_flags[@]}"
  2115. kube::test::get_object_assert pvc "{{range.items}}{{$id_field}}:{{end}}" 'myclaim-3:'
  2116. kubectl delete pvc myclaim-3 "${kube_flags[@]}"
  2117. # Post-condition: no PVCs
  2118. kube::test::get_object_assert pvc "{{range.items}}{{$id_field}}:{{end}}" ''
  2119. ############################
  2120. # Storage Classes #
  2121. ############################
  2122. ### Create and delete storage class
  2123. # Pre-condition: no storage classes currently exist
  2124. kube::test::get_object_assert storageclass "{{range.items}}{{$id_field}}:{{end}}" ''
  2125. # Command
  2126. kubectl create -f - "${kube_flags[@]}" << __EOF__
  2127. {
  2128. "kind": "StorageClass",
  2129. "apiVersion": "extensions/v1beta1",
  2130. "metadata": {
  2131. "name": "storage-class-name"
  2132. },
  2133. "provisioner": "kubernetes.io/fake-provisioner-type",
  2134. "parameters": {
  2135. "zone":"us-east-1b",
  2136. "type":"ssd"
  2137. }
  2138. }
  2139. __EOF__
  2140. kube::test::get_object_assert storageclass "{{range.items}}{{$id_field}}:{{end}}" 'storage-class-name:'
  2141. kubectl delete storageclass storage-class-name "${kube_flags[@]}"
  2142. # Post-condition: no storage classes
  2143. kube::test::get_object_assert storageclass "{{range.items}}{{$id_field}}:{{end}}" ''
  2144. #########
  2145. # Nodes #
  2146. #########
  2147. kube::log::status "Testing kubectl(${version}:nodes)"
  2148. kube::test::get_object_assert nodes "{{range.items}}{{$id_field}}:{{end}}" '127.0.0.1:'
  2149. kube::test::describe_object_assert nodes "127.0.0.1" "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:"
  2150. # Describe command should print events information by default
  2151. kube::test::describe_object_events_assert nodes "127.0.0.1"
  2152. # Describe command should not print events information when show-events=false
  2153. kube::test::describe_object_events_assert nodes "127.0.0.1" false
  2154. # Describe command should print events information when show-events=true
  2155. kube::test::describe_object_events_assert nodes "127.0.0.1" true
  2156. # Describe command (resource only) should print detailed information
  2157. kube::test::describe_resource_assert nodes "Name:" "Labels:" "CreationTimestamp:" "Conditions:" "Addresses:" "Capacity:" "Pods:"
  2158. # Describe command should print events information by default
  2159. kube::test::describe_resource_events_assert nodes
  2160. # Describe command should not print events information when show-events=false
  2161. kube::test::describe_resource_events_assert nodes false
  2162. # Describe command should print events information when show-events=true
  2163. kube::test::describe_resource_events_assert nodes true
  2164. ### kubectl patch update can mark node unschedulable
  2165. # Pre-condition: node is schedulable
  2166. kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '<no value>'
  2167. kubectl patch "${kube_flags[@]}" nodes "127.0.0.1" -p='{"spec":{"unschedulable":true}}'
  2168. # Post-condition: node is unschedulable
  2169. kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" 'true'
  2170. kubectl patch "${kube_flags[@]}" nodes "127.0.0.1" -p='{"spec":{"unschedulable":null}}'
  2171. # Post-condition: node is schedulable
  2172. kube::test::get_object_assert "nodes 127.0.0.1" "{{.spec.unschedulable}}" '<no value>'
  2173. # check webhook token authentication endpoint, kubectl doesn't actually display the returned object so this isn't super useful
  2174. # but it proves that works
  2175. kubectl create -f test/fixtures/pkg/kubectl/cmd/create/tokenreview.json --validate=false
  2176. ########################
  2177. # authorization.k8s.io #
  2178. ########################
  2179. # check remote authorization endpoint, kubectl doesn't actually display the returned object so this isn't super useful
  2180. # but it proves that works
  2181. kubectl create -f test/fixtures/pkg/kubectl/cmd/create/sar.json --validate=false
  2182. SAR_RESULT_FILE="${KUBE_TEMP}/sar-result.json"
  2183. curl -k -H "Content-Type:" http://localhost:8080/apis/authorization.k8s.io/v1beta1/subjectaccessreviews -XPOST -d @test/fixtures/pkg/kubectl/cmd/create/sar.json > "${SAR_RESULT_FILE}"
  2184. if grep -q '"allowed": true' "${SAR_RESULT_FILE}"; then
  2185. kube::log::status "\"authorization.k8s.io/subjectaccessreviews\" returns as expected: $(cat "${SAR_RESULT_FILE}")"
  2186. else
  2187. kube::log::status "\"authorization.k8s.io/subjectaccessreviews\" does not return as expected: $(cat "${SAR_RESULT_FILE}")"
  2188. exit 1
  2189. fi
  2190. rm "${SAR_RESULT_FILE}"
  2191. #####################
  2192. # Retrieve multiple #
  2193. #####################
  2194. kube::log::status "Testing kubectl(${version}:multiget)"
  2195. kube::test::get_object_assert 'nodes/127.0.0.1 service/kubernetes' "{{range.items}}{{$id_field}}:{{end}}" '127.0.0.1:kubernetes:'
  2196. #####################
  2197. # Resource aliasing #
  2198. #####################
  2199. kube::log::status "Testing resource aliasing"
  2200. kubectl create -f examples/storage/cassandra/cassandra-controller.yaml "${kube_flags[@]}"
  2201. kubectl create -f examples/storage/cassandra/cassandra-service.yaml "${kube_flags[@]}"
  2202. object="all -l'app=cassandra'"
  2203. request="{{range.items}}{{range .metadata.labels}}{{.}}:{{end}}{{end}}"
  2204. # all 4 cassandra's might not be in the request immediately...
  2205. kube::test::get_object_assert "$object" "$request" 'cassandra:cassandra:cassandra:cassandra:' || \
  2206. kube::test::get_object_assert "$object" "$request" 'cassandra:cassandra:cassandra:' || \
  2207. kube::test::get_object_assert "$object" "$request" 'cassandra:cassandra:'
  2208. kubectl delete all -l app=cassandra "${kube_flags[@]}"
  2209. ###########
  2210. # Explain #
  2211. ###########
  2212. kube::log::status "Testing kubectl(${version}:explain)"
  2213. kubectl explain pods
  2214. # shortcuts work
  2215. kubectl explain po
  2216. kubectl explain po.status.message
  2217. ###########
  2218. # Swagger #
  2219. ###########
  2220. if [[ -n "${version}" ]]; then
  2221. # Verify schema
  2222. file="${KUBE_TEMP}/schema-${version}.json"
  2223. curl -s "http://127.0.0.1:${API_PORT}/swaggerapi/api/${version}" > "${file}"
  2224. [[ "$(grep "list of returned" "${file}")" ]]
  2225. [[ "$(grep "List of pods" "${file}")" ]]
  2226. [[ "$(grep "Watch for changes to the described resources" "${file}")" ]]
  2227. fi
  2228. #####################
  2229. # Kubectl --sort-by #
  2230. #####################
  2231. ### sort-by should not panic if no pod exists
  2232. # Pre-condition: no POD exists
  2233. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  2234. # Command
  2235. kubectl get pods --sort-by="{metadata.name}"
  2236. kubectl get pods --sort-by="{metadata.creationTimestamp}"
  2237. ############################
  2238. # Kubectl --all-namespaces #
  2239. ############################
  2240. # Pre-condition: the "default" namespace exists
  2241. kube::test::get_object_assert namespaces "{{range.items}}{{if eq $id_field \\\"default\\\"}}{{$id_field}}:{{end}}{{end}}" 'default:'
  2242. ### Create POD
  2243. # Pre-condition: no POD exists
  2244. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  2245. # Command
  2246. kubectl create "${kube_flags[@]}" -f test/fixtures/doc-yaml/admin/limitrange/valid-pod.yaml
  2247. # Post-condition: valid-pod is created
  2248. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  2249. ### Verify a specific namespace is ignored when all-namespaces is provided
  2250. # Command
  2251. kubectl get pods --all-namespaces --namespace=default
  2252. ### Clean up
  2253. # Pre-condition: valid-pod exists
  2254. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" 'valid-pod:'
  2255. # Command
  2256. kubectl delete "${kube_flags[@]}" pod valid-pod --grace-period=0
  2257. # Post-condition: valid-pod doesn't exist
  2258. kube::test::get_object_assert pods "{{range.items}}{{$id_field}}:{{end}}" ''
  2259. kube::test::clear_all
  2260. }
  2261. runTests "v1"
  2262. kube::log::status "TEST PASSED"