|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# This script captures the steps required to successfully |
| 4 | +# deploy the hostpath plugin driver. This should be considered |
| 5 | +# authoritative and all updates for this process should be |
| 6 | +# done here and referenced elsewhere. |
| 7 | + |
| 8 | +# The script assumes that kubectl is available on the OS path |
| 9 | +# where it is executed. |
| 10 | + |
| 11 | +set -e |
| 12 | +set -o pipefail |
| 13 | + |
| 14 | +BASE_DIR=$(dirname "$0") |
| 15 | + |
| 16 | +# If set, the following env variables override image registry and/or tag for each of the images. |
| 17 | +# They are named after the image name, with hyphen replaced by underscore and in upper case. |
| 18 | +# |
| 19 | +# - CSI_ATTACHER_REGISTRY |
| 20 | +# - CSI_ATTACHER_TAG |
| 21 | +# - CSI_NODE_DRIVER_REGISTRAR_REGISTRY |
| 22 | +# - CSI_NODE_DRIVER_REGISTRAR_TAG |
| 23 | +# - CSI_PROVISIONER_REGISTRY |
| 24 | +# - CSI_PROVISIONER_TAG |
| 25 | +# - CSI_SNAPSHOTTER_REGISTRY |
| 26 | +# - CSI_SNAPSHOTTER_TAG |
| 27 | +# - HOSTPATHPLUGIN_REGISTRY |
| 28 | +# - HOSTPATHPLUGIN_TAG |
| 29 | +# |
| 30 | +# Alternatively, it is possible to override all registries or tags with: |
| 31 | +# - IMAGE_REGISTRY |
| 32 | +# - IMAGE_TAG |
| 33 | +# These are used as fallback when the more specific variables are unset or empty. |
| 34 | +# |
| 35 | +# IMAGE_TAG=canary is ignored for images that are blacklisted in the |
| 36 | +# deployment's optional canary-blacklist.txt file. This is meant for |
| 37 | +# images which have known API breakages and thus cannot work in those |
| 38 | +# deployments anymore. That text file must have the name of the blacklisted |
| 39 | +# image on a line by itself, other lines are ignored. Example: |
| 40 | +# |
| 41 | +# # The following canary images are known to be incompatible with this |
| 42 | +# # deployment: |
| 43 | +# csi-snapshotter |
| 44 | +# |
| 45 | +# Beware that the .yaml files do not have "imagePullPolicy: Always". That means that |
| 46 | +# also the "canary" images will only be pulled once. This is good for testing |
| 47 | +# (starting a pod multiple times will always run with the same canary image), but |
| 48 | +# implies that refreshing that image has to be done manually. |
| 49 | +# |
| 50 | +# As a special case, 'none' as registry removes the registry name. |
| 51 | + |
| 52 | +# The default is to use the RBAC rules that match the image that is |
| 53 | +# being used, also in the case that the image gets overridden. This |
| 54 | +# way if there are breaking changes in the RBAC rules, the deployment |
| 55 | +# will continue to work. |
| 56 | +# |
| 57 | +# However, such breaking changes should be rare and only occur when updating |
| 58 | +# to a new major version of a sidecar. Nonetheless, to allow testing the scenario |
| 59 | +# where the image gets overridden but not the RBAC rules, updating the RBAC |
| 60 | +# rules can be disabled. |
| 61 | +: ${UPDATE_RBAC_RULES:=true} |
| 62 | +function rbac_version () { |
| 63 | + yaml="$1" |
| 64 | + image="$2" |
| 65 | + update_rbac="$3" |
| 66 | + |
| 67 | + # get version from `image: quay.io/k8scsi/csi-attacher:v1.0.1`, ignoring comments |
| 68 | + version="$(sed -e 's/ *#.*$//' "$yaml" | grep "image:.*$image" | sed -e 's/ *#.*//' -e 's/.*://')" |
| 69 | + |
| 70 | + if $update_rbac; then |
| 71 | + # apply overrides |
| 72 | + varname=$(echo $image | tr - _ | tr a-z A-Z) |
| 73 | + eval version=\${${varname}_TAG:-\${IMAGE_TAG:-\$version}} |
| 74 | + fi |
| 75 | + |
| 76 | + # When using canary images, we have to assume that the |
| 77 | + # canary images were built from the corresponding branch. |
| 78 | + case "$version" in canary) version=master;; |
| 79 | + *-canary) version="$(echo "$version" | sed -e 's/\(.*\)-canary/release-\1/')";; |
| 80 | + esac |
| 81 | + |
| 82 | + echo "$version" |
| 83 | +} |
| 84 | + |
| 85 | +# version_gt returns true if arg1 is greater than arg2. |
| 86 | +# |
| 87 | +# This function expects versions to be one of the following formats: |
| 88 | +# X.Y.Z, release-X.Y.Z, vX.Y.Z |
| 89 | +# |
| 90 | +# where X,Y, and Z are any number. |
| 91 | +# |
| 92 | +# Partial versions (1.2, release-1.2) work as well. |
| 93 | +# The follow substrings are stripped before version comparison: |
| 94 | +# - "v" |
| 95 | +# - "release-" |
| 96 | +# |
| 97 | +# Usage: |
| 98 | +# version_gt release-1.3 v1.2.0 (returns true) |
| 99 | +# version_gt v1.1.1 v1.2.0 (returns false) |
| 100 | +# version_gt 1.1.1 v1.2.0 (returns false) |
| 101 | +# version_gt 1.3.1 v1.2.0 (returns true) |
| 102 | +# version_gt 1.1.1 release-1.2.0 (returns false) |
| 103 | +# version_gt 1.2.0 1.2.2 (returns false) |
| 104 | +function version_gt() { |
| 105 | + versions=$(for ver in "$@"; do ver=${ver#release-}; ver=${ver#kubernetes-}; echo ${ver#v}; done) |
| 106 | + greaterVersion=${1#"release-"}; |
| 107 | + greaterVersion=${greaterVersion#"kubernetes-"}; |
| 108 | + greaterVersion=${greaterVersion#"v"}; |
| 109 | + test "$(printf '%s' "$versions" | sort -V | head -n 1)" != "$greaterVersion" |
| 110 | +} |
| 111 | + |
| 112 | +# In addition, the RBAC rules can be overridden separately. |
| 113 | +# For snapshotter 2.0+, the directory has changed. |
| 114 | +SNAPSHOTTER_RBAC_RELATIVE_PATH="rbac.yaml" |
| 115 | +if version_gt $(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-snapshotter.yaml" csi-snapshotter "${UPDATE_RBAC_RULES}") "v1.255.255"; then |
| 116 | + SNAPSHOTTER_RBAC_RELATIVE_PATH="csi-snapshotter/rbac-csi-snapshotter.yaml" |
| 117 | +fi |
| 118 | + |
| 119 | +CSI_PROVISIONER_RBAC_YAML="https://raw.githubusercontent.com/kubernetes-csi/external-provisioner/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-provisioner.yaml" csi-provisioner false)/deploy/kubernetes/rbac.yaml" |
| 120 | +: ${CSI_PROVISIONER_RBAC:=https://raw.githubusercontent.com/kubernetes-csi/external-provisioner/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-provisioner.yaml" csi-provisioner "${UPDATE_RBAC_RULES}")/deploy/kubernetes/rbac.yaml} |
| 121 | +CSI_ATTACHER_RBAC_YAML="https://raw.githubusercontent.com/kubernetes-csi/external-attacher/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-attacher.yaml" csi-attacher false)/deploy/kubernetes/rbac.yaml" |
| 122 | +: ${CSI_ATTACHER_RBAC:=https://raw.githubusercontent.com/kubernetes-csi/external-attacher/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-attacher.yaml" csi-attacher "${UPDATE_RBAC_RULES}")/deploy/kubernetes/rbac.yaml} |
| 123 | +CSI_SNAPSHOTTER_RBAC_YAML="https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-snapshotter.yaml" csi-snapshotter false)/deploy/kubernetes/${SNAPSHOTTER_RBAC_RELATIVE_PATH}" |
| 124 | +: ${CSI_SNAPSHOTTER_RBAC:=https://raw.githubusercontent.com/kubernetes-csi/external-snapshotter/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-snapshotter.yaml" csi-snapshotter "${UPDATE_RBAC_RULES}")/deploy/kubernetes/${SNAPSHOTTER_RBAC_RELATIVE_PATH}} |
| 125 | +CSI_RESIZER_RBAC_YAML="https://raw.githubusercontent.com/kubernetes-csi/external-resizer/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-resizer.yaml" csi-resizer false)/deploy/kubernetes/rbac.yaml" |
| 126 | +: ${CSI_RESIZER_RBAC:=https://raw.githubusercontent.com/kubernetes-csi/external-resizer/$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-resizer.yaml" csi-resizer "${UPDATE_RBAC_RULES}")/deploy/kubernetes/rbac.yaml} |
| 127 | + |
| 128 | +INSTALL_CRD=${INSTALL_CRD:-"false"} |
| 129 | + |
| 130 | +# Some images are not affected by *_REGISTRY/*_TAG and IMAGE_* variables. |
| 131 | +# The default is to update unless explicitly excluded. |
| 132 | +update_image () { |
| 133 | + case "$1" in socat) return 1;; esac |
| 134 | +} |
| 135 | + |
| 136 | +run () { |
| 137 | + echo "$@" >&2 |
| 138 | + "$@" |
| 139 | +} |
| 140 | + |
| 141 | +# rbac rules |
| 142 | +echo "applying RBAC rules" |
| 143 | +for component in CSI_PROVISIONER CSI_ATTACHER CSI_SNAPSHOTTER CSI_RESIZER; do |
| 144 | + eval current="\${${component}_RBAC}" |
| 145 | + eval original="\${${component}_RBAC_YAML}" |
| 146 | + if [ "$current" != "$original" ]; then |
| 147 | + echo "Using non-default RBAC rules for $component. Changes from $original to $current are:" |
| 148 | + diff -c <(wget --quiet -O - "$original") <(if [[ "$current" =~ ^http ]]; then wget --quiet -O - "$current"; else cat "$current"; fi) || true |
| 149 | + fi |
| 150 | + run kubectl apply -f "${current}" |
| 151 | +done |
| 152 | + |
| 153 | +# deploy hostpath plugin and registrar sidecar |
| 154 | +echo "deploying hostpath components" |
| 155 | +for i in $(ls ${BASE_DIR}/hostpath/*.yaml | sort); do |
| 156 | + echo " $i" |
| 157 | + modified="$(cat "$i" | while IFS= read -r line; do |
| 158 | + nocomments="$(echo "$line" | sed -e 's/ *#.*$//')" |
| 159 | + if echo "$nocomments" | grep -q '^[[:space:]]*image:[[:space:]]*'; then |
| 160 | + # Split 'image: quay.io/k8scsi/csi-attacher:v1.0.1' |
| 161 | + # into image (quay.io/k8scsi/csi-attacher:v1.0.1), |
| 162 | + # registry (quay.io/k8scsi), |
| 163 | + # name (csi-attacher), |
| 164 | + # tag (v1.0.1). |
| 165 | + image=$(echo "$nocomments" | sed -e 's;.*image:[[:space:]]*;;') |
| 166 | + registry=$(echo "$image" | sed -e 's;\(.*\)/.*;\1;') |
| 167 | + name=$(echo "$image" | sed -e 's;.*/\([^:]*\).*;\1;') |
| 168 | + tag=$(echo "$image" | sed -e 's;.*:;;') |
| 169 | +
|
| 170 | + # Variables are with underscores and upper case. |
| 171 | + varname=$(echo $name | tr - _ | tr a-z A-Z) |
| 172 | +
|
| 173 | + # Now replace registry and/or tag, if set as env variables. |
| 174 | + # If not set, the replacement is the same as the original value. |
| 175 | + # Only do this for the images which are meant to be configurable. |
| 176 | + if update_image "$name"; then |
| 177 | + prefix=$(eval echo \${${varname}_REGISTRY:-${IMAGE_REGISTRY:-${registry}}}/ | sed -e 's;none/;;') |
| 178 | + if [ "$IMAGE_TAG" = "canary" ] && |
| 179 | + [ -f ${BASE_DIR}/canary-blacklist.txt ] && |
| 180 | + grep -q "^$name\$" ${BASE_DIR}/canary-blacklist.txt; then |
| 181 | + # Ignore IMAGE_TAG=canary for this particular image because its |
| 182 | + # canary image is blacklisted in the deployment blacklist. |
| 183 | + suffix=$(eval echo :\${${varname}_TAG:-${tag}}) |
| 184 | + else |
| 185 | + suffix=$(eval echo :\${${varname}_TAG:-${IMAGE_TAG:-${tag}}}) |
| 186 | + fi |
| 187 | + line="$(echo "$nocomments" | sed -e "s;$image;${prefix}${name}${suffix};")" |
| 188 | + fi |
| 189 | + echo " using $line" >&2 |
| 190 | + fi |
| 191 | + echo "$line" |
| 192 | + done)" |
| 193 | + if ! echo "$modified" | kubectl apply -f -; then |
| 194 | + echo "modified version of $i:" |
| 195 | + echo "$modified" |
| 196 | + exit 1 |
| 197 | + fi |
| 198 | +done |
| 199 | +
|
| 200 | +# Wait until all pods are running. We have to make some assumptions |
| 201 | +# about the deployment here, otherwise we wouldn't know what to wait |
| 202 | +# for: the expectation is that we run attacher, provisioner, |
| 203 | +# snapshotter, resizer, socat and hostpath plugin in the default namespace. |
| 204 | +expected_running_pods=6 |
| 205 | +cnt=0 |
| 206 | +while [ $(kubectl get pods 2>/dev/null | grep '^csi-hostpath.* Running ' | wc -l) -lt ${expected_running_pods} ]; do |
| 207 | + if [ $cnt -gt 30 ]; then |
| 208 | + echo "$(kubectl get pods 2>/dev/null | grep '^csi-hostpath.* Running ' | wc -l) running pods:" |
| 209 | + kubectl describe pods |
| 210 | +
|
| 211 | + echo >&2 "ERROR: hostpath deployment not ready after over 5min" |
| 212 | + exit 1 |
| 213 | + fi |
| 214 | + echo $(date +%H:%M:%S) "waiting for hostpath deployment to complete, attempt #$cnt" |
| 215 | + cnt=$(($cnt + 1)) |
| 216 | + sleep 10 |
| 217 | +done |
| 218 | +
|
| 219 | +# deploy snapshotclass |
| 220 | +echo "deploying snapshotclass based on snapshotter version" |
| 221 | +snapshotter_version="$(rbac_version "${BASE_DIR}/hostpath/csi-hostpath-snapshotter.yaml" csi-snapshotter false)" |
| 222 | +driver_version="$(basename "${BASE_DIR}")" |
| 223 | +if version_gt "$driver_version" "1.16"; then |
| 224 | + kubectl apply -f "${BASE_DIR}/snapshotter/csi-hostpath-snapshotclass.yaml" |
| 225 | +fi |
| 226 | +
|
| 227 | +# Create a test driver configuration in the place where the prow job |
| 228 | +# expects it? |
| 229 | +if [ "${CSI_PROW_TEST_DRIVER}" ]; then |
| 230 | + cp "${BASE_DIR}/test-driver.yaml" "${CSI_PROW_TEST_DRIVER}" |
| 231 | +fi |
0 commit comments