k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/experiment/create-build-project.sh (about)

     1  #!/usr/bin/env bash
     2  
     3  # Copyright 2019 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  # This script will:
    18  #   Create a new GCP project
    19  #   Link a billing account
    20  #   Enable GKE
    21  #   Create a default build cluster
    22  
    23  # e.g.
    24  #  create-build-cluster.sh "Test Prow Build" --interactive
    25  
    26  # TODO(clarketm): upgrade this to a Python script.
    27  
    28  set -euo pipefail
    29  
    30  ######################################################################
    31  
    32  SCRIPT_NAME=$(basename "$0")
    33  
    34  # Save current kube context
    35  CURRENT_CONTEXT="$(kubectl config current-context)"
    36  
    37  PROJECT_NAME=
    38  PROJECT_ID=
    39  INTERACTIVE=
    40  
    41  CLUSTER_NAME="prow"
    42  MACHINE_TYPE="n1-standard-1"
    43  NUM_NODES="3"
    44  ZONE="us-west1-a"
    45  POD_NAMESPACE="test-pods"
    46  FOLDER_ID="396521612403"               # google-default
    47  BILLING_ACCOUNT="00E7A7-4928AF-F1C514" # Cloud Kubernetes Development
    48  
    49  declare -A IAM_ROLES=(
    50    ["group:mdb.cloud-kubernetes-engprod-oncall@google.com"]="roles/owner"
    51  )
    52  
    53  ######################################################################
    54  
    55  prompt() {
    56    local msg="$1" cmd="$2"
    57  
    58    if [ -z "$INTERACTIVE" ]; then
    59      "$cmd"
    60      return
    61    fi
    62  
    63    echo
    64    read -r -n1 -p "$msg ? [y/n] "
    65    echo
    66  
    67    if [[ $REPLY =~ ^[Yy]$ ]]; then
    68      "$cmd"
    69    fi
    70  }
    71  
    72  # GNU getopt compatibility check
    73  check_getopt() {
    74    if getopt --test &>/dev/null; then
    75      {
    76        echo
    77        echo "$SCRIPT_NAME requires the use of the \"GNU getopt\" command."
    78        echo
    79        echo "brew install gnu-getopt"
    80        echo "brew link --force gnu-getopt"
    81        exit 1
    82      } >&2
    83    fi
    84  }
    85  
    86  get_options() {
    87    check_getopt
    88  
    89    if opt=$(getopt -o i -l machine-type:,num-nodes:,cluster-name:,zone:,pod-namespace:,interactive -n "$SCRIPT_NAME" -- "$@"); then
    90      eval set -- "$opt"
    91    else
    92      {
    93        echo
    94        echo "unable to parse options"
    95        exit 1
    96      } >&2
    97    fi
    98  
    99    while [ $# -gt 0 ]; do
   100      case "$1" in
   101      --machine-type)
   102        MACHINE_TYPE="$2"
   103        shift 2
   104        ;;
   105      --num-nodes)
   106        NUM_NODES="$2"
   107        shift 2
   108        ;;
   109      --cluster-name)
   110        CLUSTER_NAME="$2"
   111        shift 2
   112        ;;
   113      --zone)
   114        ZONE="$2"
   115        shift 2
   116        ;;
   117      --pod-namespace)
   118        POD_NAMESPACE="$2"
   119        shift 2
   120        ;;
   121      -i | --interactive)
   122        INTERACTIVE=1
   123        shift
   124        ;;
   125      --)
   126        shift
   127        get_params "$@"
   128        break
   129        ;;
   130      *)
   131        {
   132          echo
   133          echo "unknown option: $1"
   134          exit 1
   135        } >&2
   136        ;;
   137      esac
   138    done
   139  }
   140  
   141  get_params() {
   142    if [ $# -eq 0 ]; then
   143      {
   144        echo
   145        echo "project name required"
   146        exit 1
   147      } >&2
   148    fi
   149  
   150    PROJECT_NAME="$1"
   151    PROJECT_ID="$(echo "$PROJECT_NAME" | tr '[A-Z]' '[a-z]' | tr ' ' '-')"
   152  }
   153  
   154  # Create GCP project.
   155  create_project() {
   156    gcloud projects create "$PROJECT_ID" --name="$PROJECT_NAME" --folder="$FOLDER_ID"
   157  }
   158  
   159  # Link project to billing account.
   160  link_billing() {
   161    gcloud beta billing projects link "$PROJECT_ID" --billing-account="$BILLING_ACCOUNT"
   162  }
   163  
   164  # Enable Kubernetes Engine API.
   165  enable_kube_api() {
   166    gcloud services enable "container.googleapis.com" --project="$PROJECT_ID"
   167  }
   168  
   169  # Add iam policy bindings.
   170  add_iam() {
   171    for member in "${!IAM_ROLES[@]}"; do
   172      gcloud projects add-iam-policy-binding "$PROJECT_ID" --member="$member" --role="${IAM_ROLES[$member]}"
   173    done
   174  }
   175  
   176  # Create cluster.
   177  create_cluster() {
   178    gcloud container clusters create "$CLUSTER_NAME" --project="$PROJECT_ID" --zone="$ZONE" --machine-type="$MACHINE_TYPE" --num-nodes="$NUM_NODES"
   179  }
   180  
   181  # Create pod namespace in cluster.
   182  create_namespace() {
   183    kubectl create namespace "$POD_NAMESPACE"
   184  }
   185  
   186  # Restore kube context.
   187  restore_kube_context() {
   188    kubectl config use-context "$CURRENT_CONTEXT" &>/dev/null
   189  }
   190  
   191  # Authenticate to cluster.
   192  get_creds() {
   193    gcloud container clusters get-credentials "$CLUSTER_NAME" --project="$PROJECT_ID" --zone="$ZONE"
   194  }
   195  
   196  main() {
   197    get_options "$@"
   198  
   199    # gcloud
   200    prompt "Create project" create_project
   201    prompt "Link billing account" link_billing
   202    prompt "Enable Kubernetes API" enable_kube_api
   203    prompt "Add IAM bindings" add_iam
   204    prompt "Create cluster" create_cluster
   205  
   206    get_creds
   207  
   208    # kubectl
   209    prompt "Create namespace" create_namespace
   210  }
   211  
   212  trap 'restore_kube_context' EXIT
   213  main "$@"