|
| 1 | +#!/usr/bin/env bash |
| 2 | + |
| 3 | +# Copyright 2025 The Kubernetes Authors. |
| 4 | +# |
| 5 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | +# you may not use this file except in compliance with the License. |
| 7 | +# You may obtain a copy of the License at |
| 8 | +# |
| 9 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +# |
| 11 | +# Unless required by applicable law or agreed to in writing, software |
| 12 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | +# See the License for the specific language governing permissions and |
| 15 | +# limitations under the License. |
| 16 | + |
| 17 | +# tools/kops-common.sh |
| 18 | +# Shared functions for Kops deployment scripts |
| 19 | + |
| 20 | +# Configures the KOPS_STATE_STORE bucket. |
| 21 | +# Requires: GCP_PROJECT, GCP_LOCATION |
| 22 | +# Sets/Exports: KOPS_STATE_STORE |
| 23 | +function setup_kops_state_store() { |
| 24 | + if [[ -z "${KOPS_STATE_STORE:-}" ]]; then |
| 25 | + KOPS_STATE_STORE="gs://kops-state-${GCP_PROJECT}" |
| 26 | + echo "KOPS_STATE_STORE not set, using default: ${KOPS_STATE_STORE}" |
| 27 | + fi |
| 28 | + export KOPS_STATE_STORE |
| 29 | + |
| 30 | + # Ensure bucket exists |
| 31 | + if ! gsutil ls -p "${GCP_PROJECT}" "${KOPS_STATE_STORE}" >/dev/null 2>&1; then |
| 32 | + echo "Creating state store bucket: ${KOPS_STATE_STORE}" |
| 33 | + gsutil mb -p "${GCP_PROJECT}" -l "${GCP_LOCATION}" "${KOPS_STATE_STORE}" |
| 34 | + gsutil ubla set off "${KOPS_STATE_STORE}" |
| 35 | + |
| 36 | + # Grant storage.admin to the current service account (useful for CI/Boskos) |
| 37 | + local SA |
| 38 | + SA=$(gcloud config list --format 'value(core.account)') |
| 39 | + if [[ -n "${SA}" ]]; then |
| 40 | + echo "Granting admin access to ${SA}" |
| 41 | + gsutil iam ch serviceAccount:${SA}:admin "${KOPS_STATE_STORE}" || echo "Warning: Failed to grant IAM, possibly already owner or not a service account." |
| 42 | + fi |
| 43 | + fi |
| 44 | +} |
| 45 | + |
| 46 | +# Configures SSH keys for cluster access. |
| 47 | +# Requires: GCP_PROJECT, WORKDIR/REPO_ROOT |
| 48 | +# Sets/Exports: KUBE_SSH_USER, SSH_PRIVATE_KEY_PATH (or SSH_PRIVATE_KEY for kubetest2 compatibility) |
| 49 | +function setup_ssh_key() { |
| 50 | + # Accept SSH_PRIVATE_KEY_PATH (dev script) or SSH_PRIVATE_KEY (CI script) |
| 51 | + local KEY_PATH="${SSH_PRIVATE_KEY_PATH:-${SSH_PRIVATE_KEY:-}}" |
| 52 | + |
| 53 | + if [[ -z "${KEY_PATH}" ]]; then |
| 54 | + # Default location |
| 55 | + KEY_PATH="${REPO_ROOT}/google_compute_engine" |
| 56 | + echo "SSH key path not set, using default: ${KEY_PATH}" |
| 57 | + |
| 58 | + if [[ ! -f "${KEY_PATH}" ]]; then |
| 59 | + echo "Generaing/Configuring SSH key..." |
| 60 | + gcloud compute config-ssh --project="${GCP_PROJECT}" --ssh-key-file="${KEY_PATH}" --quiet |
| 61 | + fi |
| 62 | + export KUBE_SSH_USER="${USER}" |
| 63 | + fi |
| 64 | + |
| 65 | + # Normalize variables for both scripts |
| 66 | + export SSH_PRIVATE_KEY="${KEY_PATH}" |
| 67 | + export SSH_PRIVATE_KEY_PATH="${KEY_PATH}" |
| 68 | + export KUBE_SSH_PUBLIC_KEY_PATH="${KEY_PATH}.pub" |
| 69 | + |
| 70 | + echo "SSH Key configured: ${KEY_PATH}" |
| 71 | +} |
| 72 | + |
| 73 | +# Builds CCM image and generates the manifest with arguments. |
| 74 | +# Requires: REPO_ROOT, GCP_PROJECT, CLUSTER_NAME, WORKDIR |
| 75 | +# Sets/Exports: ADD_MANIFEST_ARG, KOPS_FEATURE_FLAGS |
| 76 | +function build_and_push_ccm() { |
| 77 | + echo "Building Local CCM..." |
| 78 | + |
| 79 | + # Setup image tags |
| 80 | + if [[ -z "${IMAGE_REPO:-}" ]]; then |
| 81 | + IMAGE_REPO="gcr.io/${GCP_PROJECT}" |
| 82 | + fi |
| 83 | + if [[ -z "${IMAGE_TAG:-}" ]]; then |
| 84 | + IMAGE_TAG=$(git rev-parse --short HEAD)-$(date +%Y%m%dT%H%M%S) |
| 85 | + fi |
| 86 | + |
| 87 | + # Configure docker auth |
| 88 | + gcloud auth configure-docker --quiet |
| 89 | + |
| 90 | + # Build and Push |
| 91 | + echo "Pushing image to ${IMAGE_REPO}/cloud-controller-manager:${IMAGE_TAG}" |
| 92 | + IMAGE_REPO=${IMAGE_REPO} IMAGE_TAG=${IMAGE_TAG} "${REPO_ROOT}/tools/push-images" |
| 93 | + |
| 94 | + # Prepare Manifest |
| 95 | + local MANIFEST_DIR="${WORKDIR:-${REPO_ROOT}/_tmp/${CLUSTER_NAME}}" |
| 96 | + if [[ ! -d "${MANIFEST_DIR}" ]]; then |
| 97 | + mkdir -p "${MANIFEST_DIR}" |
| 98 | + fi |
| 99 | + |
| 100 | + echo "Generating manifest in ${MANIFEST_DIR}..." |
| 101 | + cp "${REPO_ROOT}/deploy/packages/default/manifest.yaml" "${MANIFEST_DIR}/cloud-provider-gcp.yaml" |
| 102 | + sed -i -e "s@k8scloudprovidergcp/cloud-controller-manager:latest@${IMAGE_REPO}/cloud-controller-manager:${IMAGE_TAG}@g" "${MANIFEST_DIR}/cloud-provider-gcp.yaml" |
| 103 | + |
| 104 | + # Inject CCM args |
| 105 | + # We replace "args: [] ..." with the actual list of arguments required for CCM to run. |
| 106 | + sed -i -e "s|args: \[\] .*|args:\n - --cloud-provider=gcp\n - --leader-elect=true\n - --use-service-account-credentials\n - --allocate-node-cidrs=true\n - --configure-cloud-routes=true\n - --cluster-name=${CLUSTER_NAME}|" "${MANIFEST_DIR}/cloud-provider-gcp.yaml" |
| 107 | + |
| 108 | + echo "Manifest generated at ${MANIFEST_DIR}/cloud-provider-gcp.yaml" |
| 109 | + |
| 110 | + # Export for use in calling script |
| 111 | + export ADD_MANIFEST_ARG="--add=${MANIFEST_DIR}/cloud-provider-gcp.yaml" |
| 112 | + export KOPS_FEATURE_FLAGS="ClusterAddons,${KOPS_FEATURE_FLAGS:-}" |
| 113 | +} |
0 commit comments