|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +# shellcheck source=includer.sh |
| 4 | +source "$(dirname "${BASH_SOURCE[0]}")/includer.sh" |
| 5 | + |
| 6 | +@include exec |
| 7 | +@include log |
| 8 | +@include options |
| 9 | +@include git |
| 10 | + |
| 11 | +ADDITIONAL_NAMESPACES="storage" |
| 12 | +function ::add_ns { |
| 13 | + local ns=${1:?} |
| 14 | + ADDITIONAL_NAMESPACES="$ADDITIONAL_NAMESPACES,$ns" |
| 15 | +} |
| 16 | + |
| 17 | +function ::use_dind { |
| 18 | + docker run -d --privileged -p 2375:2375 -p 6443:6443 -e DOCKER_TLS_CERTDIR="" \ |
| 19 | + docker:dind --tls=false |
| 20 | + DOCKER_HOST=tcp://localhost:2375 |
| 21 | +} |
| 22 | + |
| 23 | +ADD_HELM_REPOS+=("openebs,https://openebs.github.io/charts/") |
| 24 | +ADD_HELM_REPOS+=("bitnami,https://charts.bitnami.com/bitnami") |
| 25 | +ADD_HELM_REPOS+=("emissary-ingress,https://app.getambassador.io") |
| 26 | + |
| 27 | +log::level 2 |
| 28 | +options::standard |
| 29 | +options::description "This script creates a kind cluster suitable for testing" |
| 30 | +options::add -o n -d "then name of the kind cluster to create" -a -e CLUSTER_NAME |
| 31 | +options::add -o f -d "kind config file" -a -m -e KIND_CONFIG |
| 32 | +options::add -o c -d "command: create, delete" -a -m -e COMMAND |
| 33 | +options::add -o t -d "namespaces to add" -a -f ::add_ns |
| 34 | +options::add -o d -d "address of a remote docker daemon" -a -e DOCKER_HOST |
| 35 | +options::add -o D -d "Use DinD(Docker in Docker)" -x USE_DIND |
| 36 | +options::add -o P -d "Use the specified port fo::add_ingress_providerr the DinD daemon" -a -e DIND_PORT |
| 37 | +options::parse "$@" |
| 38 | + |
| 39 | +CLUSTER_NAME=${CLUSTER_NAME:-test} |
| 40 | +COMMAND=${COMMAND:-create} |
| 41 | +DOCKER_PORT=${DIND_PORT:-2375} |
| 42 | + |
| 43 | +if [ -r "$HOME/.asdf/asdf.sh" ]; then |
| 44 | + source "$HOME/.asdf/asdf.sh" |
| 45 | +fi |
| 46 | + |
| 47 | +function ::is_dind_running { |
| 48 | + local container_name=${1:?} |
| 49 | + local is_running |
| 50 | + is_running=$(docker inspect --format "{{.State.Running}}" "$container_name" 2>/dev/null) |
| 51 | + [ "$is_running" = "true" ] |
| 52 | +} |
| 53 | + |
| 54 | +function ::use_dind { |
| 55 | + local name="$CLUSTER_NAME-dind" |
| 56 | + if [ "$USE_DIND" = "true" ]; then |
| 57 | + if ::is_dind_running "$name"; then |
| 58 | + log::info "Using pre-existing DinD container $name" |
| 59 | + export DOCKER_HOST=tcp://localhost:2375 |
| 60 | + else |
| 61 | + log::info "Starting DinD container $name" |
| 62 | + export DOCKER_PORT=2375 |
| 63 | + docker run -d --name "$name" --privileged -p $DOCKER_PORT:2375 -p 6443:6443 -p 8080:80 -p 8443:443 \ |
| 64 | + -e DOCKER_TLS_CERTDIR="" \ |
| 65 | + docker:dind --tls=false >/dev/null |
| 66 | + export DOCKER_HOST=tcp://localhost:$DOCKER_PORT |
| 67 | + sleep 30 |
| 68 | + fi |
| 69 | + fi |
| 70 | +} |
| 71 | + |
| 72 | +function ::delete_dind { |
| 73 | + local name="$CLUSTER_NAME-dind" |
| 74 | + if [ "$USE_DIND" = "true" ]; then |
| 75 | + docker rm -f "$name" |
| 76 | + fi |
| 77 | +} |
| 78 | + |
| 79 | +function ::check_cmd { |
| 80 | + local cmd=${1:?} |
| 81 | + if ! command -v "${cmd}" >/dev/null 2>&1; then |
| 82 | + return 1 |
| 83 | + else |
| 84 | + return 0 |
| 85 | + fi |
| 86 | +} |
| 87 | + |
| 88 | +function ::ensure_asdf { |
| 89 | + if ::check_cmd asdf; then |
| 90 | + log::info "ASDF is already installed here" |
| 91 | + return 0 |
| 92 | + else |
| 93 | + if ! ::check_cmd git; then |
| 94 | + log::error "Command[git] is not installed!" |
| 95 | + log::error "See here for necessary tools installation https://git-scm.com/book/en/v2/Getting-Started-Installing-Git" |
| 96 | + exit 1 |
| 97 | + fi |
| 98 | + if ! ::check_cmd curl; then |
| 99 | + log::error "Command[curl] is not installed!" |
| 100 | + log::error "See here for necessary tools installation https://curl.haxx.se/docs/install.html" |
| 101 | + exit 1 |
| 102 | + fi |
| 103 | + if git::cmd clone https://github.com/asdf-vm/asdf.git "$HOME/.asdf" --branch v0.9.0; then |
| 104 | + source "$HOME/.asdf/asdf.sh" |
| 105 | + return 0 |
| 106 | + else |
| 107 | + return 1 |
| 108 | + fi |
| 109 | + fi |
| 110 | +} |
| 111 | + |
| 112 | +function ::asdf { |
| 113 | + local plugin=${1:?} |
| 114 | + local version=${2:-latest} |
| 115 | + _asdf=$(command -v asdf) |
| 116 | + if _where=$($_asdf which "$plugin"); then |
| 117 | + log::info "Using $_where" |
| 118 | + return 0 |
| 119 | + fi |
| 120 | + $_asdf plugin add "$plugin" |
| 121 | + ret=$? |
| 122 | + if [ $ret -ne 0 ] && [ $ret -ne 2 ]; then |
| 123 | + log::error "Failed to add plugin $plugin" |
| 124 | + exit 1 |
| 125 | + fi |
| 126 | + $_asdf install "$plugin" "$version" |
| 127 | + $_asdf local "$plugin" "$version" |
| 128 | + return $? |
| 129 | +} |
| 130 | +kubectl create secret generic regcred \ |
| 131 | + -n "$ns" \ |
| 132 | + "--from-file=.dockerconfigjson=$HOME/.docker/config.json" \ |
| 133 | + --type=kubernetes.io/dockerconfigjson 2>/dev/null || true |
| 134 | +function kind::preflight { |
| 135 | + ::ensure_asdf |
| 136 | + ::asdf kind |
| 137 | + ::asdf kubectl |
| 138 | + ::check_cmd docker || error::exit "Command[docker] is not installed!" |
| 139 | +} |
| 140 | + |
| 141 | +function kind::create { |
| 142 | + local _config=${1:?} |
| 143 | + local _name=${2:?} |
| 144 | + if [ -r "$_config" ]; then |
| 145 | + log::info "Using kind config file $_config" |
| 146 | + kind create cluster --name "$_name" --config "$_config" |
| 147 | + else |
| 148 | + log::warn "Cannot find kind config file $_config" |
| 149 | + return 1 |
| 150 | + fi |
| 151 | +} |
| 152 | + |
| 153 | +function kind::delete { |
| 154 | + local _name=${1:?} |
| 155 | + kind delete cluster --name "$_name" |
| 156 | +} |
| 157 | + |
| 158 | +function ::add_namespaces { |
| 159 | + # shellcheck disable=SC2001 |
| 160 | + for ns in $(echo "${ADDITIONAL_NAMESPACES}" | sed -e 's/,/ /g'); do |
| 161 | + log::info "Adding namespace $ns" |
| 162 | + kubectl create ns "$ns" 2>/dev/null |
| 163 | + kubectl create secret generic regcred \ |
| 164 | + -n "$ns" \ |
| 165 | + "--from-file=.dockerconfigjson=$HOME/.docker/config.json" \ |
| 166 | + --type=kubernetes.io/dockerconfigjson 2>/dev/null || true |
| 167 | + done |
| 168 | +} |
| 169 | + |
| 170 | +function ::add_helm_repos { |
| 171 | + for repo in "${ADD_HELM_REPOS[@]}"; do |
| 172 | + repo_name=$(echo "$repo" | awk -F, '{print $1}') |
| 173 | + repo_url=$(echo "$repo" | awk -F, '{print $2}') |
| 174 | + helm repo add "$repo_name" "$repo_url" |
| 175 | + done |
| 176 | + helm repo update |
| 177 | +} |
| 178 | + |
| 179 | +function ::add_storage_provider { |
| 180 | + helm upgrade --install -n storage \ |
| 181 | + openebs openebs/openebs --set ndm.enabled=false \ |
| 182 | + --set legacy.enabled=false \ |
| 183 | + --set ndmOperator.enabled=false |
| 184 | +} |
| 185 | + |
| 186 | +function ::add_ingress_provider { |
| 187 | + ## WIP |
| 188 | + kubectl apply -f https://projectcontour.io/quickstart/contour.yaml |
| 189 | + kubectl patch daemonsets -n projectcontour envoy \ |
| 190 | + -p '{"spec":{"template":{"spec":{"nodeSelector":{"ingress-ready":"true"}, |
| 191 | + "tolerations":[{"key":"node-role.kubernetes.io/master","operator":"Equal", |
| 192 | + "effect":"NoSchedule"}]}}}}' |
| 193 | +} |
| 194 | + |
| 195 | +function create { |
| 196 | + # set -e |
| 197 | + kind::preflight |
| 198 | + ::use_dind |
| 199 | + kind::create "$KIND_CONFIG" "$CLUSTER_NAME" |
| 200 | + ::add_namespaces |
| 201 | + ::add_helm_repos |
| 202 | + ::add_storage_provider |
| 203 | + ::add_ingress_provider |
| 204 | + # set +e |
| 205 | +} |
| 206 | + |
| 207 | +function delete { |
| 208 | + set -e |
| 209 | + kind::preflight |
| 210 | + kind::delete "$CLUSTER_NAME" |
| 211 | + ::delete_dind |
| 212 | + set +e |
| 213 | +} |
| 214 | + |
| 215 | +"$COMMAND" |
0 commit comments