test.sh 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  1. #!/usr/bin/env bash
  2. # Copyright 2015 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. # shellcheck disable=SC2034 # Variables sourced in other scripts.
  16. # A set of helpers for tests
  17. readonly reset=$(tput sgr0)
  18. readonly bold=$(tput bold)
  19. readonly black=$(tput setaf 0)
  20. readonly red=$(tput setaf 1)
  21. readonly green=$(tput setaf 2)
  22. kube::test::clear_all() {
  23. if kube::test::if_supports_resource "rc" ; then
  24. # shellcheck disable=SC2154
  25. # Disabling because "kube_flags" is set in a parent script
  26. kubectl delete "${kube_flags[@]}" rc --all --grace-period=0 --force
  27. fi
  28. if kube::test::if_supports_resource "pods" ; then
  29. kubectl delete "${kube_flags[@]}" pods --all --grace-period=0 --force
  30. fi
  31. }
  32. # Prints the calling file and line number $1 levels deep
  33. # Defaults to 2 levels so you can call this to find your own caller
  34. kube::test::get_caller() {
  35. local levels=${1:-2}
  36. local caller_file="${BASH_SOURCE[${levels}]}"
  37. local caller_line="${BASH_LINENO[${levels}-1]}"
  38. echo "$(basename "${caller_file}"):${caller_line}"
  39. }
  40. # Force exact match of a returned result for a object query. Wrap this with || to support multiple
  41. # valid return types.
  42. # This runs `kubectl get` once and asserts that the result is as expected.
  43. # $1: Object on which get should be run
  44. # $2: The go-template to run on the result
  45. # $3: The expected output
  46. # $4: Additional args to be passed to kubectl
  47. kube::test::get_object_assert() {
  48. kube::test::object_assert 1 "$@"
  49. }
  50. # Asserts that the output of a given get query is as expected.
  51. # Runs the query multiple times before failing it.
  52. # $1: Object on which get should be run
  53. # $2: The go-template to run on the result
  54. # $3: The expected output
  55. # $4: Additional args to be passed to kubectl
  56. kube::test::wait_object_assert() {
  57. kube::test::object_assert 10 "$@"
  58. }
  59. # Asserts that the output of a given get query is as expected.
  60. # Can run the query multiple times before failing it.
  61. # $1: Number of times the query should be run before failing it.
  62. # $2: Object on which get should be run
  63. # $3: The go-template to run on the result
  64. # $4: The expected output
  65. # $5: Additional args to be passed to kubectl
  66. kube::test::object_assert() {
  67. local tries=$1
  68. local object=$2
  69. local request=$3
  70. local expected=$4
  71. local args=${5:-}
  72. for j in $(seq 1 "${tries}"); do
  73. # shellcheck disable=SC2086
  74. # Disabling because "args" needs to allow for expansion here
  75. res=$(eval kubectl get "${kube_flags[@]}" ${args} "${object}" -o go-template=\""${request}"\")
  76. if [[ "${res}" =~ ^$expected$ ]]; then
  77. echo -n "${green}"
  78. echo "$(kube::test::get_caller 3): Successful get ${object} ${request}: ${res}"
  79. echo -n "${reset}"
  80. return 0
  81. fi
  82. echo "Waiting for Get ${object} ${request} ${args}: expected: ${expected}, got: ${res}"
  83. sleep $((j-1))
  84. done
  85. echo "${bold}${red}"
  86. echo "$(kube::test::get_caller 3): FAIL!"
  87. echo "Get ${object} ${request}"
  88. echo " Expected: ${expected}"
  89. echo " Got: ${res}"
  90. echo "${reset}${red}"
  91. caller
  92. echo "${reset}"
  93. return 1
  94. }
  95. kube::test::get_object_jsonpath_assert() {
  96. local object=$1
  97. local request=$2
  98. local expected=$3
  99. res=$(eval kubectl get "${kube_flags[@]}" "${object}" -o jsonpath=\""${request}"\")
  100. if [[ "${res}" =~ ^$expected$ ]]; then
  101. echo -n "${green}"
  102. echo "$(kube::test::get_caller): Successful get ${object} ${request}: ${res}"
  103. echo -n "${reset}"
  104. return 0
  105. else
  106. echo "${bold}${red}"
  107. echo "$(kube::test::get_caller): FAIL!"
  108. echo "Get ${object} ${request}"
  109. echo " Expected: ${expected}"
  110. echo " Got: ${res}"
  111. echo "${reset}${red}"
  112. caller
  113. echo "${reset}"
  114. return 1
  115. fi
  116. }
  117. kube::test::describe_object_assert() {
  118. local resource=$1
  119. local object=$2
  120. local matches=( "${@:3}" )
  121. result=$(eval kubectl describe "${kube_flags[@]}" "${resource}" "${object}")
  122. for match in "${matches[@]}"; do
  123. if grep -q "${match}" <<< "${result}"; then
  124. echo "matched ${match}"
  125. else
  126. echo "${bold}${red}"
  127. echo "$(kube::test::get_caller): FAIL!"
  128. echo "Describe ${resource} ${object}"
  129. echo " Expected Match: ${match}"
  130. echo " Not found in:"
  131. echo "${result}"
  132. echo "${reset}${red}"
  133. caller
  134. echo "${reset}"
  135. return 1
  136. fi
  137. done
  138. echo -n "${green}"
  139. echo "$(kube::test::get_caller): Successful describe ${resource} ${object}:"
  140. echo "${result}"
  141. echo -n "${reset}"
  142. return 0
  143. }
  144. kube::test::describe_object_events_assert() {
  145. local resource=$1
  146. local object=$2
  147. local showevents=${3:-"true"}
  148. if [[ -z "${3:-}" ]]; then
  149. result=$(eval kubectl describe "${kube_flags[@]}" "${resource}" "${object}")
  150. else
  151. result=$(eval kubectl describe "${kube_flags[@]}" "--show-events=${showevents}" "${resource}" "${object}")
  152. fi
  153. if grep -q "No events.\|Events:" <<< "${result}"; then
  154. local has_events="true"
  155. else
  156. local has_events="false"
  157. fi
  158. if [[ "${showevents}" == "${has_events}" ]]; then
  159. echo -n "${green}"
  160. echo "$(kube::test::get_caller): Successful describe"
  161. echo "${result}"
  162. echo "${reset}"
  163. return 0
  164. else
  165. echo "${bold}${red}"
  166. echo "$(kube::test::get_caller): FAIL"
  167. if [[ "${showevents}" == "false" ]]; then
  168. echo " Events information should not be described in:"
  169. else
  170. echo " Events information not found in:"
  171. fi
  172. echo "${result}"
  173. echo "${reset}${red}"
  174. caller
  175. echo "${reset}"
  176. return 1
  177. fi
  178. }
  179. kube::test::describe_resource_assert() {
  180. local resource=$1
  181. local matches=( "${@:2}" )
  182. result=$(eval kubectl describe "${kube_flags[@]}" "${resource}")
  183. for match in "${matches[@]}"; do
  184. if grep -q "${match}" <<< "${result}"; then
  185. echo "matched ${match}"
  186. else
  187. echo "${bold}${red}"
  188. echo "FAIL!"
  189. echo "Describe ${resource}"
  190. echo " Expected Match: ${match}"
  191. echo " Not found in:"
  192. echo "${result}"
  193. echo "${reset}${red}"
  194. caller
  195. echo "${reset}"
  196. return 1
  197. fi
  198. done
  199. echo -n "${green}"
  200. echo "Successful describe ${resource}:"
  201. echo "${result}"
  202. echo -n "${reset}"
  203. return 0
  204. }
  205. kube::test::describe_resource_events_assert() {
  206. local resource=$1
  207. local showevents=${2:-"true"}
  208. result=$(eval kubectl describe "${kube_flags[@]}" "--show-events=${showevents}" "${resource}")
  209. if grep -q "No events.\|Events:" <<< "${result}"; then
  210. local has_events="true"
  211. else
  212. local has_events="false"
  213. fi
  214. if [[ "${showevents}" == "${has_events}" ]]; then
  215. echo -n "${green}"
  216. echo "Successful describe"
  217. echo "${result}"
  218. echo -n "${reset}"
  219. return 0
  220. else
  221. echo "${bold}${red}"
  222. echo "FAIL"
  223. if [[ "${showevents}" == "false" ]]; then
  224. echo " Events information should not be described in:"
  225. else
  226. echo " Events information not found in:"
  227. fi
  228. echo "${result}"
  229. caller
  230. echo "${reset}"
  231. return 1
  232. fi
  233. }
  234. # Compare sort-by resource name output (first column, skipping first line) with expected order specify in the last parameter
  235. kube::test::if_sort_by_has_correct_order() {
  236. local var
  237. var="$(echo "$1" | awk '{if(NR!=1) print $1}' | tr '\n' ':')"
  238. kube::test::if_has_string "${var}" "${@:$#}"
  239. }
  240. kube::test::if_has_string() {
  241. local message=$1
  242. local match=$2
  243. if grep -q "${match}" <<< "${message}"; then
  244. echo "Successful"
  245. echo "message:${message}"
  246. echo "has:${match}"
  247. return 0
  248. else
  249. echo "FAIL!"
  250. echo "message:${message}"
  251. echo "has not:${match}"
  252. caller
  253. return 1
  254. fi
  255. }
  256. kube::test::if_has_not_string() {
  257. local message=$1
  258. local match=$2
  259. if grep -q "${match}" <<< "${message}"; then
  260. echo "FAIL!"
  261. echo "message:${message}"
  262. echo "has:${match}"
  263. caller
  264. return 1
  265. else
  266. echo "Successful"
  267. echo "message:${message}"
  268. echo "has not:${match}"
  269. return 0
  270. fi
  271. }
  272. kube::test::if_empty_string() {
  273. local match=$1
  274. if [ -n "${match}" ]; then
  275. echo "${match} is not empty"
  276. caller
  277. return 1
  278. else
  279. echo "Successful"
  280. return 0
  281. fi
  282. }
  283. # Returns true if the required resource is part of supported resources.
  284. # Expects env vars:
  285. # SUPPORTED_RESOURCES: Array of all resources supported by the apiserver. "*"
  286. # means it supports all resources. For ex: ("*") or ("rc" "*") both mean that
  287. # all resources are supported.
  288. # $1: Name of the resource to be tested.
  289. kube::test::if_supports_resource() {
  290. SUPPORTED_RESOURCES=${SUPPORTED_RESOURCES:-""}
  291. REQUIRED_RESOURCE=${1:-""}
  292. for r in "${SUPPORTED_RESOURCES[@]}"; do
  293. if [[ "${r}" == "*" || "${r}" == "${REQUIRED_RESOURCE}" ]]; then
  294. return 0
  295. fi
  296. done
  297. return 1
  298. }
  299. kube::test::version::object_to_file() {
  300. name=$1
  301. flags=${2:-""}
  302. file=$3
  303. # shellcheck disable=SC2086
  304. # Disabling because "flags" needs to allow for expansion here
  305. kubectl version ${flags} | grep "${name} Version:" | sed -e s/"${name} Version: version.Info{"/'/' -e s/'}'/'/' -e s/', '/','/g -e s/':'/'=/g' -e s/'"'/""/g | tr , '\n' > "${file}"
  306. }
  307. kube::test::version::json_object_to_file() {
  308. flags=$1
  309. file=$2
  310. # shellcheck disable=SC2086
  311. # Disabling because "flags" needs to allow for expansion here
  312. kubectl version ${flags} --output json | sed -e s/' '/''/g -e s/'\"'/''/g -e s/'}'/''/g -e s/'{'/''/g -e s/'clientVersion:'/'clientVersion:,'/ -e s/'serverVersion:'/'serverVersion:,'/ | tr , '\n' > "${file}"
  313. }
  314. kube::test::version::json_client_server_object_to_file() {
  315. flags=$1
  316. name=$2
  317. file=$3
  318. # shellcheck disable=SC2086
  319. # Disabling because "flags" needs to allow for expansion here
  320. kubectl version ${flags} --output json | jq -r ".${name}" | sed -e s/'\"'/''/g -e s/'}'/''/g -e s/'{'/''/g -e /^$/d -e s/','/''/g -e s/':'/'='/g > "${file}"
  321. }
  322. kube::test::version::yaml_object_to_file() {
  323. flags=$1
  324. file=$2
  325. # shellcheck disable=SC2086
  326. # Disabling because "flags" needs to allow for expansion here
  327. kubectl version ${flags} --output yaml | sed -e s/' '/''/g -e s/'\"'/''/g -e /^$/d > "${file}"
  328. }
  329. kube::test::version::diff_assert() {
  330. local original=$1
  331. local comparator=${2:-"eq"}
  332. local latest=$3
  333. local diff_msg=${4:-""}
  334. local res=""
  335. if [ ! -f "${original}" ]; then
  336. echo "${bold}${red}"
  337. echo "FAIL! ${diff_msg}"
  338. echo "the file '${original}' does not exit"
  339. echo "${reset}${red}"
  340. caller
  341. echo "${reset}"
  342. return 1
  343. fi
  344. if [ ! -f "${latest}" ]; then
  345. echo "${bold}${red}"
  346. echo "FAIL! ${diff_msg}"
  347. echo "the file '${latest}' does not exit"
  348. echo "${reset}${red}"
  349. caller
  350. echo "${reset}"
  351. return 1
  352. fi
  353. sort "${original}" > "${original}.sorted"
  354. sort "${latest}" > "${latest}.sorted"
  355. if [ "${comparator}" == "eq" ]; then
  356. if [ "$(diff -iwB "${original}".sorted "${latest}".sorted)" == "" ] ; then
  357. echo -n "${green}"
  358. echo "Successful: ${diff_msg}"
  359. echo -n "${reset}"
  360. return 0
  361. else
  362. echo "${bold}${red}"
  363. echo "FAIL! ${diff_msg}"
  364. echo " Expected: "
  365. cat "${original}"
  366. echo " Got: "
  367. cat "${latest}"
  368. echo "${reset}${red}"
  369. caller
  370. echo "${reset}"
  371. return 1
  372. fi
  373. else
  374. if [ -n "$(diff -iwB "${original}".sorted "${latest}".sorted)" ] ; then
  375. echo -n "${green}"
  376. echo "Successful: ${diff_msg}"
  377. echo -n "${reset}"
  378. return 0
  379. else
  380. echo "${bold}${red}"
  381. echo "FAIL! ${diff_msg}"
  382. echo " Expected: "
  383. cat "${original}"
  384. echo " Got: "
  385. cat "${latest}"
  386. echo "${reset}${red}"
  387. caller
  388. echo "${reset}"
  389. return 1
  390. fi
  391. fi
  392. }