util.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. #!/usr/bin/env 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. # A library of helper functions and constant for the local config.
  16. # Use the config file specified in $KUBE_CONFIG_FILE, or default to
  17. # config-default.sh.
  18. set -e
  19. SOURCE="${BASH_SOURCE[0]}"
  20. while [ -h "$SOURCE" ]; do
  21. DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  22. SOURCE="$(readlink "$SOURCE")"
  23. [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
  24. done
  25. DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
  26. KUBE_ROOT="${DIR}/../.."
  27. KUBE_CONFIG_FILE="${KUBE_CONFIG_FILE:-"${DIR}/config-default.sh"}"
  28. source "${KUBE_CONFIG_FILE}"
  29. source "${KUBE_ROOT}/cluster/common.sh"
  30. AZKUBE_VERSION="v0.0.5"
  31. REGISTER_MASTER_KUBELET="true"
  32. function verify-prereqs() {
  33. required_binaries=("docker" "jq")
  34. for rb in "${required_binaries[@]}"; do
  35. if ! which "$rb" > /dev/null 2>&1; then
  36. echo "Couldn't find ${rb} in PATH"
  37. exit 1
  38. fi
  39. done
  40. if ! "${KUBE_ROOT}/cluster/kubectl.sh" >/dev/null 2>&1 ; then
  41. echo "kubectl is unavailable. Ensure ${KUBE_ROOT}/cluster/kubectl.sh runs with a successful exit."
  42. exit 1
  43. fi
  44. }
  45. function azure-ensure-config() {
  46. if [[ -z "${AZURE_SUBSCRIPTION_ID:-}" ]]; then
  47. echo "AZURE_SUBSCRIPTION_ID must be set"
  48. exit 1
  49. fi
  50. export AZURE_OUTPUT_RELDIR="_deployments/${AZURE_DEPLOY_ID}"
  51. export AZURE_OUTPUT_DIR="${DIR}/${AZURE_OUTPUT_RELDIR}"
  52. mkdir -p "${AZURE_OUTPUT_DIR}"
  53. case "${AZURE_AUTH_METHOD:-}" in
  54. "client_secret")
  55. if [[ -z "${AZURE_CLIENT_ID}" ]]; then
  56. echo "AZURE_CLIENT_ID must be set"
  57. exit 1
  58. fi
  59. if [[ -z "${AZURE_CLIENT_SECRET}" ]]; then
  60. echo "AZURE_CLIENT_SECRET must be set"
  61. exit 1
  62. fi
  63. ;;
  64. "")
  65. echo "AZURE_AUTH_METHOD not set, assuming \"device\"."
  66. ;;
  67. "device" | "")
  68. echo "This will be interactive. (export AZURE_AUTH_METHOD=client_secret to avoid the prompt)"
  69. export AZURE_AUTH_METHOD="device"
  70. ;;
  71. *)
  72. echo "AZURE_AUTH_METHOD is an unsupported value: \"${AZURE_AUTH_METHOD}\""
  73. exit 1
  74. ;;
  75. esac
  76. }
  77. function repo-contains-image() {
  78. registry="$1"
  79. repo="$2"
  80. image="$3"
  81. version="$4"
  82. prefix="${registry}"
  83. if [[ "${prefix}" == "docker.io" ]]; then
  84. prefix="registry.hub.docker.com/v2/repositories"
  85. tags_json=$(curl "https://registry.hub.docker.com/v2/repositories/${repo}/${image}/tags/${version}/" 2>/dev/null)
  86. tags_found="$(echo "${tags_json}" | jq ".v2?")"
  87. elif [[ "${prefix}" == "gcr.io" ]]; then
  88. tags_json=$(curl "https://gcr.io/v2/${repo}/${image}/tags/list" 2>/dev/null)
  89. tags_found="$(echo "${tags_json}" | jq ".tags | indices([\"${version}\"]) | any")"
  90. fi
  91. if [[ "${tags_found}" == "true" ]]; then
  92. return 0
  93. fi
  94. return 1
  95. }
  96. function ensure-hyperkube() {
  97. hyperkube="hyperkube-amd64"
  98. official_image_tag="gcr.io/google_containers/${hyperkube}:${KUBE_GIT_VERSION}"
  99. if repo-contains-image "gcr.io" "google_containers" "${hyperkube}" "${KUBE_GIT_VERSION}" ; then
  100. echo "${hyperkube}:${KUBE_GIT_VERSION} was found in the gcr.io/google_containers repository"
  101. export AZURE_HYPERKUBE_SPEC="${official_image_tag}"
  102. return 0
  103. fi
  104. echo "${hyperkube}:${KUBE_GIT_VERSION} was not found in the gcr.io/google_containers repository"
  105. if [[ -z "${AZURE_DOCKER_REGISTRY:-}" || -z "${AZURE_DOCKER_REPO:-}" ]]; then
  106. echo "AZURE_DOCKER_REGISTRY and AZURE_DOCKER_REPO must be set in order to push ${hyperkube}:${KUBE_GIT_VERSION}"
  107. return 1
  108. fi
  109. # check if it is already in the user owned docker hub
  110. local user_image_tag="${AZURE_DOCKER_REGISTRY}/${AZURE_DOCKER_REPO}/${hyperkube}:${KUBE_GIT_VERSION}"
  111. if repo-contains-image "${AZURE_DOCKER_REGISTRY}" "${AZURE_DOCKER_REPO}" "${hyperkube}" "${KUBE_GIT_VERSION}" ; then
  112. echo "${image}:${version} was found in ${repo} (success)"
  113. export AZURE_HYPERKUBE_SPEC="${user_image_tag}"
  114. return 0
  115. fi
  116. # should these steps tell them to just immediately tag it with the final user-specified repo?
  117. # for now just stick with the assumption that `make release` will eventually tag a hyperkube image on gcr.io
  118. # and then the existing code can re-tag that for the user's repo and then push
  119. if ! docker inspect "${user_image_tag}" ; then
  120. if ! docker inspect "${official_image_tag}" ; then
  121. REGISTRY="gcr.io/google_containers" \
  122. VERSION="${KUBE_GIT_VERSION}" \
  123. make -C "${KUBE_ROOT}/cluster/images/hyperkube" build
  124. fi
  125. docker tag "${official_image_tag}" "${user_image_tag}"
  126. fi
  127. docker push "${user_image_tag}"
  128. echo "${image}:${version} was pushed to ${repo}"
  129. export AZURE_HYPERKUBE_SPEC="${user_image_tag}"
  130. }
  131. function deploy-kube-system() {
  132. kubectl create -f - <<EOF
  133. apiVersion: v1
  134. kind: Namespace
  135. metadata:
  136. name: kube-system
  137. EOF
  138. }
  139. function get-common-params() {
  140. declare -ag AZKUBE_AUTH_PARAMS
  141. declare -ag AZKUBE_DOCKER_PARAMS
  142. declare -ag AZKUBE_RESOURCE_GROUP_PARAM
  143. case "${AZURE_AUTH_METHOD}" in
  144. "client_secret")
  145. AZKUBE_AUTH_PARAMS+=("--client-id=${AZURE_CLIENT_ID}" "--client-secret=${AZURE_CLIENT_SECRET}")
  146. ;;
  147. "device")
  148. AZKUBE_AUTH_PARAMS=()
  149. ;;
  150. esac
  151. if [[ ! -z "${AZURE_HTTPS_PROXY:-}" ]]; then
  152. AZKUBE_DOCKER_PARAMS+=("--net=host" "--env=https_proxy=${AZURE_HTTPS_PROXY}")
  153. fi
  154. if [[ ! -z "${AZURE_RESOURCE_GROUP:-}" ]]; then
  155. echo "Forcing use of resource group ${AZURE_RESOURCE_GROUP}"
  156. AZKUBE_RESOURCE_GROUP_PARAM+=("--resource-group=${AZURE_RESOURCE_GROUP}")
  157. fi
  158. }
  159. function azure-deploy(){
  160. get-common-params
  161. docker run -it \
  162. --user "$(id -u)" \
  163. "${AZKUBE_DOCKER_PARAMS[@]:+${AZKUBE_DOCKER_PARAMS[@]}}" \
  164. -v "$HOME/.azkube:/.azkube" -v "/tmp:/tmp" \
  165. -v "${AZURE_OUTPUT_DIR}:/opt/azkube/${AZURE_OUTPUT_RELDIR}" \
  166. "colemickens/azkube:${AZKUBE_VERSION}" /opt/azkube/azkube deploy \
  167. --kubernetes-hyperkube-spec="${AZURE_HYPERKUBE_SPEC}" \
  168. --deployment-name="${AZURE_DEPLOY_ID}" \
  169. --location="${AZURE_LOCATION}" \
  170. "${AZKUBE_RESOURCE_GROUP_PARAM[@]:+${AZKUBE_RESOURCE_GROUP_PARAM[@]}}" \
  171. --subscription-id="${AZURE_SUBSCRIPTION_ID}" \
  172. --auth-method="${AZURE_AUTH_METHOD}" "${AZKUBE_AUTH_PARAMS[@]:+${AZKUBE_AUTH_PARAMS[@]}}" \
  173. --master-size="${AZURE_MASTER_SIZE}" \
  174. --node-size="${AZURE_NODE_SIZE}" \
  175. --node-count="${NUM_NODES}" \
  176. --username="${AZURE_USERNAME}" \
  177. --output-directory="/opt/azkube/${AZURE_OUTPUT_RELDIR}" \
  178. --no-cloud-provider \
  179. "${AZURE_AZKUBE_ARGS[@]:+${AZURE_AZKUBE_ARGS[@]}}"
  180. }
  181. function kube-up {
  182. date_start="$(date)"
  183. startdate="$(date +%s)"
  184. echo "++> AZURE KUBE-UP STARTED: $(date)"
  185. verify-prereqs
  186. azure-ensure-config
  187. if [[ -z "${AZURE_HYPERKUBE_SPEC:-}" ]]; then
  188. find-release-version
  189. export KUBE_GIT_VERSION="${KUBE_GIT_VERSION//+/-}"
  190. # this will export AZURE_HYPERKUBE_SPEC based on whether an official image was found
  191. # or if it was uploaded to the user specified docker repository.
  192. if ! ensure-hyperkube; then
  193. echo "Failed to ensure hyperkube was available. Exitting."
  194. return 1
  195. fi
  196. else
  197. echo "Using user specified AZURE_HYPERKUBE_SPEC: ${AZURE_HYPERKUBE_SPEC}"
  198. echo "Note: The existence of this is not verified! (It might only be pullable from your DC)"
  199. fi
  200. azure-deploy
  201. kubectl config set-cluster "${AZURE_DEPLOY_ID}" --server="https://${AZURE_DEPLOY_ID}.${AZURE_LOCATION}.cloudapp.azure.com:6443" --certificate-authority="${AZURE_OUTPUT_DIR}/ca.crt" --api-version="v1"
  202. kubectl config set-credentials "${AZURE_DEPLOY_ID}_user" --client-certificate="${AZURE_OUTPUT_DIR}/client.crt" --client-key="${AZURE_OUTPUT_DIR}/client.key"
  203. kubectl config set-context "${AZURE_DEPLOY_ID}" --cluster="${AZURE_DEPLOY_ID}" --user="${AZURE_DEPLOY_ID}_user"
  204. kubectl config use-context "${AZURE_DEPLOY_ID}"
  205. deploy-kube-system
  206. enddate="$(date +%s)"
  207. duration="$(( (startdate - enddate) ))"
  208. echo "++> AZURE KUBE-UP FINISHED: $(date) (duration: ${duration} seconds)"
  209. }
  210. function kube-down {
  211. verify-prereqs
  212. # required
  213. if [[ -z "${AZURE_SUBSCRIPTION_ID:-}" ]]; then
  214. echo "AZURE_SUBSCRIPTION_ID must be set"
  215. exit 1
  216. fi
  217. if [[ -z "${AZURE_DEPLOY_ID:-}" ]]; then
  218. echo "AZURE_DEPLOY_ID must be set. This selects the deployment (and resource group) to delete."
  219. return -1
  220. fi
  221. #optional
  222. declare -a destroy_params
  223. declare -a docker_params
  224. if [[ ${AZURE_DOWN_SKIP_CONFIRM:-} == "true" ]]; then
  225. destroy_params+=("--skip-confirm")
  226. fi
  227. if [[ ! -z "${AZURE_HTTPS_PROXY:-}" ]]; then
  228. docker_params+=("--net=host" "--env=https_proxy=${AZURE_HTTPS_PROXY}")
  229. fi
  230. docker run -it \
  231. --user "$(id -u)" \
  232. -v "$HOME/.azkube:/.azkube" -v "/tmp:/tmp" \
  233. "${AZKUBE_DOCKER_PARAMS[@]:+${AZKUBE_DOCKER_PARAMS[@]}}" \
  234. "colemickens/azkube:${AZKUBE_VERSION}" /opt/azkube/azkube destroy \
  235. --deployment-name="${AZURE_DEPLOY_ID}" \
  236. --subscription-id="${AZURE_SUBSCRIPTION_ID}" \
  237. --auth-method="${AZURE_AUTH_METHOD}" "${AZKUBE_AUTH_PARAMS[@]:+${AZKUBE_AUTH_PARAMS[@]}}" \
  238. "${destroy_params[@]:+${destroy_params[@]}}" \
  239. "${AZURE_AZKUBE_ARGS[@]:+${AZURE_AZKUBE_ARGS[@]}}"
  240. }