|
| 1 | +#!/usr/bin/env bash |
| 2 | +# Copyright 2024 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 | + |
| 16 | +set -o errexit # exit immediately if a command exits with a non-zero status. |
| 17 | +set -o nounset # exit when script tries to use undeclared variables. |
| 18 | +set -o pipefail # make the pipeline fail if any command in it fails. |
| 19 | + |
| 20 | +REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. |
| 21 | +# shellcheck source=hack/ensure-azcli.sh |
| 22 | +source "${REPO_ROOT}/hack/ensure-azcli.sh" # install az cli and login using WI |
| 23 | +# shellcheck source=hack/ensure-tags.sh |
| 24 | +source "${REPO_ROOT}/hack/ensure-tags.sh" # set the right timestamp and job name |
| 25 | + |
| 26 | +KUBECTL="${REPO_ROOT}/hack/tools/bin/kubectl" |
| 27 | +KIND="${REPO_ROOT}/hack/tools/bin/kind" |
| 28 | +AZWI="${REPO_ROOT}/hack/tools/bin/azwi" |
| 29 | +make --directory="${REPO_ROOT}" "${KUBECTL##*/}" "${KIND##*/}" "${AZWI##*/}" |
| 30 | + |
| 31 | +export MGMT_CLUSTER_NAME="${MGMT_CLUSTER_NAME:-aks-mgmt-capz}-${RANDOM_SUFFIX}" # management cluster name |
| 32 | +export AKS_RESOURCE_GROUP="${AKS_RESOURCE_GROUP:-aks-mgmt-capz}-${RANDOM_SUFFIX}" # resource group name |
| 33 | +export AKS_NODE_RESOURCE_GROUP="node-${AKS_RESOURCE_GROUP}" |
| 34 | +export KUBERNETES_VERSION="${KUBERNETES_VERSION:-v1.30.2}" |
| 35 | +export AZURE_LOCATION="${AZURE_LOCATION:-westus2}" |
| 36 | +export AKS_NODE_VM_SIZE="${AKS_NODE_VM_SIZE:-"Standard_B2s"}" |
| 37 | +export AKS_NODE_COUNT="${AKS_NODE_COUNT:-1}" |
| 38 | +export MGMT_CLUSTER_KUBECONFIG="${MGMT_CLUSTER_KUBECONFIG:-$REPO_ROOT/aks-mgmt.config}" |
| 39 | +export AZURE_IDENTITY_ID_FILEPATH="${AZURE_IDENTITY_ID_FILEPATH:-$REPO_ROOT/azure_identity_id}" |
| 40 | +export AZWI_STORAGE_ACCOUNT="capzcioidcissuer${RANDOM_SUFFIX}" |
| 41 | +export AZWI_STORAGE_CONTAINER="\$web" |
| 42 | +export SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH="${SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH:-}" |
| 43 | +export SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH="${SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH:-}" |
| 44 | +export REGISTRY="${REGISTRY:-}" |
| 45 | + |
| 46 | +export AZURE_SUBSCRIPTION_ID="${AZURE_SUBSCRIPTION_ID:-}" |
| 47 | +export AZURE_CLIENT_ID="${AZURE_CLIENT_ID:-}" |
| 48 | +export AZURE_TENANT_ID="${AZURE_TENANT_ID:-}" |
| 49 | + |
| 50 | +main() { |
| 51 | + |
| 52 | + echo "--------------------------------" |
| 53 | + echo "MGMT_CLUSTER_NAME: $MGMT_CLUSTER_NAME" |
| 54 | + echo "AKS_RESOURCE_GROUP: $AKS_RESOURCE_GROUP" |
| 55 | + echo "AKS_NODE_RESOURCE_GROUP: $AKS_NODE_RESOURCE_GROUP" |
| 56 | + echo "KUBERNETES_VERSION: $KUBERNETES_VERSION" |
| 57 | + echo "AZURE_LOCATION: $AZURE_LOCATION" |
| 58 | + echo "AKS_NODE_VM_SIZE: $AKS_NODE_VM_SIZE" |
| 59 | + echo "AZURE_NODE_MACHINE_TYPE: $AZURE_NODE_MACHINE_TYPE" |
| 60 | + echo "AKS_NODE_COUNT: $AKS_NODE_COUNT" |
| 61 | + echo "MGMT_CLUSTER_KUBECONFIG: $MGMT_CLUSTER_KUBECONFIG" |
| 62 | + echo "AZURE_IDENTITY_ID_FILEPATH: $AZURE_IDENTITY_ID_FILEPATH" |
| 63 | + echo "AZWI_STORAGE_ACCOUNT: $AZWI_STORAGE_ACCOUNT" |
| 64 | + echo "AZWI_STORAGE_CONTAINER: $AZWI_STORAGE_CONTAINER" |
| 65 | + echo "SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH: $SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH" |
| 66 | + echo "SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH: $SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH" |
| 67 | + echo "REGISTRY: $REGISTRY" |
| 68 | + |
| 69 | + echo "AZURE_SUBSCRIPTION_ID: $AZURE_SUBSCRIPTION_ID" |
| 70 | + echo "AZURE_CLIENT_ID: $AZURE_CLIENT_ID" |
| 71 | + echo "AZURE_TENANT_ID: $AZURE_TENANT_ID" |
| 72 | + echo "--------------------------------" |
| 73 | + |
| 74 | + create_aks_cluster |
| 75 | + set_env_varaibles |
| 76 | +} |
| 77 | + |
| 78 | +create_aks_cluster() { |
| 79 | + resource_group_exists=$(az group exists --name "${AKS_RESOURCE_GROUP}" --output tsv) |
| 80 | + if [ "${resource_group_exists}" == 'true' ]; then |
| 81 | + echo "resource group \"${AKS_RESOURCE_GROUP}\" already exists, moving on" |
| 82 | + else |
| 83 | + echo "creating resource group ${AKS_RESOURCE_GROUP}" |
| 84 | + az group create --name "${AKS_RESOURCE_GROUP}" \ |
| 85 | + --location "${AZURE_LOCATION}" \ |
| 86 | + --output none --only-show-errors \ |
| 87 | + --tags creationTimestamp="${TIMESTAMP}" jobName="${JOB_NAME}" buildProvenance="${BUILD_PROVENANCE}" |
| 88 | + fi |
| 89 | + |
| 90 | + aks_exists=$(az aks show --name "${MGMT_CLUSTER_NAME}" --resource-group "${AKS_RESOURCE_GROUP}" 2>&1 || true) # true because we want to continue if the command fails |
| 91 | + if echo "$aks_exists" | grep -E -q "Resource(NotFound|GroupNotFound)"; then |
| 92 | + echo "creating aks cluster ${MGMT_CLUSTER_NAME} in the resource group ${AKS_RESOURCE_GROUP}" |
| 93 | + az aks create --name "${MGMT_CLUSTER_NAME}" \ |
| 94 | + --resource-group "${AKS_RESOURCE_GROUP}" \ |
| 95 | + --location "${AZURE_LOCATION}" \ |
| 96 | + --kubernetes-version "${KUBERNETES_VERSION}" \ |
| 97 | + --node-count "${AKS_NODE_COUNT}" \ |
| 98 | + --node-vm-size "${AKS_NODE_VM_SIZE}" \ |
| 99 | + --node-resource-group "${AKS_NODE_RESOURCE_GROUP}" \ |
| 100 | + --vm-set-type VirtualMachineScaleSets \ |
| 101 | + --generate-ssh-keys \ |
| 102 | + --network-plugin azure \ |
| 103 | + --tags creationTimestamp="${TIMESTAMP}" jobName="${JOB_NAME}" buildProvenance="${BUILD_PROVENANCE}" \ |
| 104 | + --output none --only-show-errors; |
| 105 | + elif echo "$aks_exists" | grep -q "${MGMT_CLUSTER_NAME}"; then |
| 106 | + echo "cluster ${MGMT_CLUSTER_NAME} already exists in RG ${AKS_RESOURCE_GROUP}, moving on" |
| 107 | + else |
| 108 | + echo "error : ${aks_exists}" |
| 109 | + exit 1 |
| 110 | + fi |
| 111 | + |
| 112 | + # check and save kubeconfig |
| 113 | + echo "saving credentials of cluster ${MGMT_CLUSTER_NAME} in ${REPO_ROOT}/${MGMT_CLUSTER_KUBECONFIG}" |
| 114 | + az aks get-credentials --name "${MGMT_CLUSTER_NAME}" --resource-group "${AKS_RESOURCE_GROUP}" \ |
| 115 | + --file "${REPO_ROOT}/${MGMT_CLUSTER_KUBECONFIG}" --only-show-errors |
| 116 | + |
| 117 | + az aks get-credentials --name "${MGMT_CLUSTER_NAME}" --resource-group "${AKS_RESOURCE_GROUP}" \ |
| 118 | + --overwrite-existing --only-show-errors |
| 119 | + |
| 120 | + # echo "fetching Client ID for ${MGMT_CLUSTER_NAME}" |
| 121 | + AKS_MI_CLIENT_ID=$(az aks show -n "${MGMT_CLUSTER_NAME}" -g "${AKS_RESOURCE_GROUP}" --output json \ |
| 122 | + --only-show-errors | jq -r '.identityProfile.kubeletidentity.clientId') |
| 123 | + export AKS_MI_CLIENT_ID |
| 124 | + echo "mgmt client identity: ${AKS_MI_CLIENT_ID}" |
| 125 | + echo "${AKS_MI_CLIENT_ID}" > "${AZURE_IDENTITY_ID_FILEPATH}" |
| 126 | + |
| 127 | + # echo "fetching Object ID for ${MGMT_CLUSTER_NAME}" |
| 128 | + AKS_MI_OBJECT_ID=$(az aks show -n "${MGMT_CLUSTER_NAME}" -g "${AKS_RESOURCE_GROUP}" --output json \ |
| 129 | + --only-show-errors | jq -r '.identityProfile.kubeletidentity.objectId') |
| 130 | + export AKS_MI_OBJECT_ID |
| 131 | + echo "mgmt object identity: ${AKS_MI_OBJECT_ID}" |
| 132 | + |
| 133 | + # echo "fetching Resource ID for ${MGMT_CLUSTER_NAME}" |
| 134 | + AKS_MI_RESOURCE_ID=$(az aks show -n "${MGMT_CLUSTER_NAME}" -g "${AKS_RESOURCE_GROUP}" --output json \ |
| 135 | + --only-show-errors | jq -r '.identityProfile.kubeletidentity.resourceId') |
| 136 | + export AKS_MI_RESOURCE_ID |
| 137 | + echo "mgmt resource identity: ${AKS_MI_RESOURCE_ID}" |
| 138 | + |
| 139 | + # save resource identity name and resource group |
| 140 | + MANAGED_IDENTITY_NAME=$(az identity show --ids "${AKS_MI_RESOURCE_ID}" | jq -r '.name') |
| 141 | + # export MANAGED_IDENTITY_NAME |
| 142 | + echo "mgmt resource identity name: ${MANAGED_IDENTITY_NAME}" |
| 143 | + USER_IDENTITY=$MANAGED_IDENTITY_NAME |
| 144 | + export USER_IDENTITY |
| 145 | + |
| 146 | + MANAGED_IDENTITY_RG=$(az identity show --ids "${AKS_MI_RESOURCE_ID}" | jq -r '.resourceGroup') |
| 147 | + export MANAGED_IDENTITY_RG |
| 148 | + echo "mgmt resource identity resource group: ${MANAGED_IDENTITY_RG}" |
| 149 | + |
| 150 | + echo "assigning contributor role to the service principal" |
| 151 | + until az role assignment create --assignee-object-id "${AKS_MI_OBJECT_ID}" --role "Contributor" \ |
| 152 | + --scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}" --assignee-principal-type ServicePrincipal --output none \ |
| 153 | + --only-show-errors; do |
| 154 | + echo "retrying to assign role to the service principal" |
| 155 | + sleep 5 |
| 156 | + done |
| 157 | + |
| 158 | + echo "using ASO_CREDENTIAL_SECRET_MODE as podidentity" |
| 159 | + ASO_CREDENTIAL_SECRET_MODE="podidentity" |
| 160 | +} |
| 161 | + |
| 162 | +set_env_varaibles(){ |
| 163 | + cat <<EOF > tilt-settings-temp.yaml |
| 164 | +kustomize_substitutions: |
| 165 | + MGMT_CLUSTER_NAME: "${MGMT_CLUSTER_NAME}" |
| 166 | + AKS_RESOURCE_GROUP: "${AKS_RESOURCE_GROUP}" |
| 167 | + AKS_NODE_RESOURCE_GROUP: "${AKS_NODE_RESOURCE_GROUP}" |
| 168 | + MGMT_CLUSTER_KUBECONFIG: "${MGMT_CLUSTER_KUBECONFIG}" |
| 169 | + AKS_MI_CLIENT_ID: "${AKS_MI_CLIENT_ID}" |
| 170 | + AKS_MI_OBJECT_ID: "${AKS_MI_OBJECT_ID}" |
| 171 | + AKS_MI_RESOURCE_ID: "${AKS_MI_RESOURCE_ID}" |
| 172 | + MANAGED_IDENTITY_NAME: "${MANAGED_IDENTITY_NAME}" |
| 173 | + MANAGED_IDENTITY_RG: "${MANAGED_IDENTITY_RG}" |
| 174 | + AZURE_CLIENT_ID_USER_ASSIGNED_IDENTITY: "${AKS_MI_CLIENT_ID}" |
| 175 | + CI_RG: "${MANAGED_IDENTITY_RG}" |
| 176 | + USER_IDENTITY: "${MANAGED_IDENTITY_NAME}" |
| 177 | + CLUSTER_IDENTITY_TYPE: "UserAssignedMSI" |
| 178 | + ASO_CREDENTIAL_SECRET_MODE: "${ASO_CREDENTIAL_SECRET_MODE}" |
| 179 | + REGISTRY: "${REGISTRY}" |
| 180 | +allowed_contexts: |
| 181 | + - "$MGMT_CLUSTER_NAME" |
| 182 | + - "kind-capz" |
| 183 | +azure_location: "${AZURE_LOCATION}" |
| 184 | +EOF |
| 185 | + |
| 186 | +# create tilt-settings.yaml if it does not exist |
| 187 | +if [ -f tilt-settings.yaml ]; then |
| 188 | + echo "tilt-settings.yaml exists" |
| 189 | +else |
| 190 | + echo "tilt-settings.yaml does not exist, creating one" |
| 191 | + touch tilt-settings.yaml |
| 192 | +fi |
| 193 | + |
| 194 | +# copy over the existing allowed_contexts to tilt-settings.yaml if it does not exist |
| 195 | +allowed_contexts_exists=$(yq eval '.allowed_contexts' tilt-settings.yaml) |
| 196 | +if [ "$allowed_contexts_exists" == "null" ]; then |
| 197 | + yq eval '.allowed_contexts = load("tilt-settings-temp.yaml") | .allowed_contexts' tilt-settings-temp.yaml > tilt-settings.yaml |
| 198 | +fi |
| 199 | + |
| 200 | +# extract allowed_contexts from tilt-settings.yaml |
| 201 | +current_contexts=$(yq eval '.allowed_contexts' tilt-settings.yaml | sort -u) |
| 202 | + |
| 203 | +# extract allowed_contexts from tilt-settings-new.yaml |
| 204 | +new_contexts=$(yq eval '.allowed_contexts' tilt-settings-temp.yaml | sort -u) |
| 205 | + |
| 206 | +# combine current and new contexts, keeping the union of both |
| 207 | +combined_contexts=$(echo "$current_contexts"$'\n'"$new_contexts" | sort -u) |
| 208 | + |
| 209 | +# create a temporary file since env($combined_contexts) is not supported in yq |
| 210 | +echo "$combined_contexts" > combined_contexts.yaml |
| 211 | + |
| 212 | +# update allowed_contexts in tilt-settings.yaml with the combined contexts |
| 213 | +yq eval --inplace ".allowed_contexts = load(\"combined_contexts.yaml\")" tilt-settings.yaml |
| 214 | + |
| 215 | +# merge the updated kustomize_substitution and azure_location with the existing one in tilt-settings.yaml |
| 216 | +yq eval-all 'select(fileIndex == 0) *+ {"kustomize_substitutions": select(fileIndex == 1).kustomize_substitutions, "azure_location": select(fileIndex == 1).azure_location}' tilt-settings.yaml tilt-settings-temp.yaml > tilt-settings-new.yaml |
| 217 | + |
| 218 | +mv tilt-settings-new.yaml tilt-settings.yaml |
| 219 | +rm -r combined_contexts.yaml |
| 220 | +rm -f tilt-settings-temp.yaml |
| 221 | +} |
| 222 | + |
| 223 | +main |
0 commit comments