commit aa624ce27c006d665937d39cd9654cb013d9ed50 Author: Sidney Shiba Date: Wed Sep 16 14:26:53 2020 -0500 Bootstrap container code for GCP This commit provides the Go code and scripts for the Bootstrap container for GCP. The Bootstrap container (bootstrap_capg) for Google Cloud is designed to accept three commands: create, delete and help. - create - will create an Ephemeral GKE cluster in Google Cloud - delete - will delete the Ephemeral GKE cluster from the Google Cloud - help - Stdout the help text for using this container. Please, refer to the bootstrap_capg/README.md for further details. Change-Id: Ifad7c7a7fede0230029716c9e093449f5886e859 diff --git a/.gitignore b/.gitignore index c2f3501..12c2a1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ *build/ +bootstrap_capg/.vscode/launch.json +bootstrap_capg/go.mod diff --git a/bootstrap_capg/Dockerfile b/bootstrap_capg/Dockerfile new file mode 100644 index 0000000..f03a014 --- /dev/null +++ b/bootstrap_capg/Dockerfile @@ -0,0 +1,56 @@ +# Copyright 2018 AT&T Intellectual Property. All other rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +ARG GCP_SDK=gcr.io/google.com/cloudsdktool/cloud-sdk:308.0.0 +ARG GOLANG=golang:1.14.4 + +############################################ +# Build GCP Bootstrap Container application +############################################ +FROM ${GOLANG} as builder +WORKDIR /home/build +# copy the capg bootstrap container app code +COPY main.go . +COPY config/ config/ +# Build capg bootstrap container application +RUN go mod init opendev.org/airship/images/bootstrap_capg && \ + go get -d -v ./... && \ + go install . && \ + CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o capg-ephemeral . + +############################################ +# Run GCP Bootstrap Container +############################################ +FROM ${GCP_SDK} +LABEL org.opencontainers.image.authors='airship-discuss@lists.airshipit.org, irc://#airshipit@freenode' \ + org.opencontainers.image.url='https://airshipit.org' \ + org.opencontainers.image.documentation='https://opendev.org/airship/images/src/branch/master/bootstrap_capg/README.md' \ + org.opencontainers.image.source='https://opendev.org/airship/images' \ + org.opencontainers.image.vendor='The Airship Authors' \ + org.opencontainers.image.licenses='Apache-2.0' + +RUN adduser --disabled-password bootstrap +USER bootstrap + +WORKDIR /home/bootstrap +ENV HOME=/home/bootstrap +ENV PATH="${PATH}:${HOME}" + +# Copy the Google Cloud Bootstrap Container command +COPY --from=builder /home/build/capg-ephemeral . +# Copy help file +COPY assets/help.txt . + +# # Executes the script to create the GKE cluster +CMD ["capg-ephemeral"] diff --git a/bootstrap_capg/Makefile b/bootstrap_capg/Makefile new file mode 100644 index 0000000..7a71ac2 --- /dev/null +++ b/bootstrap_capg/Makefile @@ -0,0 +1,56 @@ +SHELL := /bin/bash +PUSH_IMAGE ?= false +GIT_VERSION ?= v0.1.0 +GIT_MODULE ?= opendev.org/airship/airshipctl/pkg/version + +GO_FLAGS := -ldflags '-extldflags "-static"' -tags=netgo +GO_FLAGS += -ldflags "-X ${GIT_MODULE}.gitVersion=${GIT_VERSION}" + +DOCKER_MAKE_TARGET := build + +# docker image options +DOCKER_REGISTRY ?= quay.io +DOCKER_FORCE_CLEAN ?= true +DOCKER_IMAGE_NAME ?= capg-bootstrap +DOCKER_IMAGE_PREFIX ?= airshipit +DOCKER_IMAGE_TAG ?= latest +DOCKER_IMAGE ?= $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG) +DOCKER_TARGET_STAGE ?= release + +PATH += :/usr/local/go/bin +HELP_FILE ?= /tmp/help.txt +ORIGINAL_HELP_FILE = ./assets/help.txt + +.PHONY: all +all: images + +.PHONY: images +images: Dockerfile \ + main.go \ + config/gke_cluster.go \ + config/gcp_cluster.go \ + config/gcp_config.go \ + assets/help.txt + @docker build . --network=host \ + --build-arg MAKE_TARGET=$(DOCKER_MAKE_TARGET) \ + --tag $(DOCKER_IMAGE) \ + --force-rm=$(DOCKER_FORCE_CLEAN) +ifeq ($(PUSH_IMAGE), true) + docker push $(IMAGE) +endif + +.PHONY: clean +clean: + @docker image rm $(DOCKER_IMAGE) + +.PHONY: lint +lint: + @echo TODO + +# style checks +.PHONY: tests +tests: images + if [ -f $(HELP_FILE) ]; then sudo rm $(HELP_FILE); fi + cp gcp-config.yaml /tmp + docker run -v /tmp:/kube --env-file bootstrap-env.list --name capg-test $(DOCKER_IMAGE) + cmp $(HELP_FILE) $(ORIGINAL_HELP_FILE) diff --git a/bootstrap_capg/README.md b/bootstrap_capg/README.md new file mode 100644 index 0000000..87e45c5 --- /dev/null +++ b/bootstrap_capg/README.md @@ -0,0 +1,32 @@ +# GCP Bootstrap Container + +This project contains the Go application and configuration files for +implementing the GCP Bootstrap container. + +The GCP Bootstrap container is responsible to create or delete a Kubernetes +(K8S) cluster on GCP Cloud platform using the GKE (Google Kubernetes Engine). + +## Go Application + +The Go application is the bootstrap container orchestrator that is responsible +for translating commands into actions: create, delete, help. + +This Go application uses the Ephemeral cluster configuration file +(e.g., gcp-config.yaml) to determine the Google Cloud credentials and +data to use to create or delete the ephemeral cluster. + +## Dockerfile + +The **Dockerfile** uses a multi-stage builds to first build the Go application +then create the GCP bootstrap container image. + +## Build + +To build the bootstrap container image, execute the following command: + +```bash +make images +``` + +This command will build the Go application and then create the bootstrap +container image. diff --git a/bootstrap_capg/assets/help.txt b/bootstrap_capg/assets/help.txt new file mode 100644 index 0000000..fcb4498 --- /dev/null +++ b/bootstrap_capg/assets/help.txt @@ -0,0 +1,66 @@ + +Google Cloud Ephemeral Configuration File Definition +----------------------------------------------------- +The GCP Bootstrap container creates an Ephemeral K8S cluster on the Google Cloud platform. +The container requires authentication credentials and other information about the cluster to deploy. +It requires a YAML configuration file with the format provided below. + + +apiVersion: v1 +kind: GoogleCloudConfig +metadata: + name: +credentials: + project: + account: + credential: +spec: + region: + Zone: + cluster: + k8sVersion: + machineSize: + diskSize: + replicas: + kubeconfig: + + +The JSON format is also a valid configuration file for this bootstrap container. + + +{ + "apiVersion": "v1", + "kind": "GoogleCloudConfig", + "metadata": { + "name": "" + }, + "credentials": { + "project": "", + "account": "", + "credential": "" + }, + "spec": { + "region": "", + "zone": "", + "cluster": { + "k8sVersion": "", + "machineSize": "", + "diskSize": , + "replicas": , + "kubeconfig": "" + } + } + } + + +The expected location for the GCP bootstrap configuration file is dictated by the "volume" mount +specified in the Airship config file (bootstrapInfo.ephemeral.container.volume). +For example, /home/esidshi/.airship folder as shown in the snippet below: + + +apiVersion: airshipit.org/v1alpha1 +bootstrapInfo: + ephemeral: + container: + volume: /home/esidshi/.airship:/kube + diff --git a/bootstrap_capg/bootstrap-env.list b/bootstrap_capg/bootstrap-env.list new file mode 100644 index 0000000..acabea9 --- /dev/null +++ b/bootstrap_capg/bootstrap-env.list @@ -0,0 +1,3 @@ +BOOTSTRAP_COMMAND=help +BOOTSTRAP_CONFIG=gcp-config.yaml +BOOTSTRAP_VOLUME=/tmp:/kube \ No newline at end of file diff --git a/bootstrap_capg/config/gcp_cluster.go b/bootstrap_capg/config/gcp_cluster.go new file mode 100644 index 0000000..3e6efe0 --- /dev/null +++ b/bootstrap_capg/config/gcp_cluster.go @@ -0,0 +1,101 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package config + +import ( + "io" + "log" + "os" + "os/exec" + "strings" +) + +const ( + bootstrapHelpFile = "help.txt" + + // BootstrapCommand environment variable + bootstrapHome = "HOME" + bootstrapCommand = "BOOTSTRAP_COMMAND" + bootstrapConfig = "BOOTSTRAP_CONFIG" + bootstrapVolume = "BOOTSTRAP_VOLUME" + bootstrapVolumeSep = ":" +) + +// GetVolumeMountPoints extracts the source and destination of a volume mount +func GetVolumeMountPoints(volumeMount string) (string, string) { + sepPos := strings.Index(volumeMount, bootstrapVolumeSep) + + srcMountPoint := volumeMount[:sepPos] + dstMountPoint := volumeMount[sepPos+1:] + + return srcMountPoint, dstMountPoint +} + +// execute - is used to invoke gcloud CLI commands +func execute(command string, arg ...string) error { + cmd := exec.Command(command, arg...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Start(); err != nil { + log.Printf("Error executing script %s\n", command) + return err + } + + if err := cmd.Wait(); err != nil { + log.Printf("Error waiting for command execution: %s", err.Error()) + return err + } + + return nil +} + +// CreateGKECluster creates the GKE cluster +func CreateGKECluster(gcpConfig *GcpConfig) error { + return prepareGCPCluster(gcpConfig, true) +} + +// DeleteGKECluster deletes the GKE cluster +func DeleteGKECluster(gcpConfig *GcpConfig) error { + return prepareGCPCluster(gcpConfig, false) +} + +// HelpGKECluster returns the help.txt for the GKE cluster +func HelpGKECluster() error { + homeDir := os.Getenv(bootstrapHome) + src := homeDir + "/" + bootstrapHelpFile + in, err := os.Open(src) + if err != nil { + log.Printf("Could not open %s file\n", src) + return err + } + defer in.Close() + + _, dstMountPoint := GetVolumeMountPoints(os.Getenv(bootstrapVolume)) + dst := dstMountPoint + "/" + bootstrapHelpFile + out, err := os.Create(dst) + if err != nil { + log.Printf("Could not create %s file\n", dst) + return err + } + defer out.Close() + + _, err = io.Copy(out, in) + if err != nil { + log.Printf("Failed to copy %s file to %s\n", src, dst) + return err + } + return out.Close() +} diff --git a/bootstrap_capg/config/gcp_config.go b/bootstrap_capg/config/gcp_config.go new file mode 100644 index 0000000..28dcbaa --- /dev/null +++ b/bootstrap_capg/config/gcp_config.go @@ -0,0 +1,117 @@ +/* +Copyright 2014 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "errors" + "io/ioutil" + "log" + + "gopkg.in/go-playground/validator.v9" + "sigs.k8s.io/yaml" +) + +// GcpConfig holds configurations for bootstrap steps +type GcpConfig struct { + // +optional + Kind string `yaml:"kind" validate:"required"` + + // +optional + APIVersion string `yaml:"apiVersion" validate:"required"` + + // Configuration parameters for metadata + Metadata *Metadata `yaml:"metadata" validate:"required"` + + // Configuration parameters for metadata + Credentials *Credentials `yaml:"credentials" validate:"required"` + + // Configuration parameters for spec + Spec *Spec `yaml:"spec"` +} + +// Metadata structure provides the cluster name to assign and labels to the k8s cluster +type Metadata struct { + Name string `yaml:"name" validate:"required"` + Labels []string `yaml:"labels,omitempty"` +} + +// Credentials structu provides the credentials to authenticate with Azure Cloud +type Credentials struct { + Project string `yaml:"project" validate:"required"` + Account string `yaml:"account" validate:"required"` + Credential string `yaml:"credential" validate:"required"` +} + +// Spec structure contains the info for the ck8s luster to deploy +type Spec struct { + Region string `yaml:"region,omitempty"` + Zone string `yaml:"zone,omitempty"` + Cluster Cluster `yaml:"cluster"` +} + +// Cluster struct provides data for the k8s cluster to deploy +type Cluster struct { + // Kubernetes version to deploy + K8SVersion string `yaml:"k8sVersion,omitempty"` + + // Google Cloud Compote VM size to use for the cluster + MachineSize string `yaml:"machineSize,omitempty"` + + // Google Cloud Compote disk size to use for the cluster + DiskSize uint8 `yaml:"diskSize,omitempty" validate:"gte=1"` + + // Number of nodes to deploy for the cluster + Replicas uint8 `yaml:"replicas,omitempty" validate:"gte=1,lte=100"` + + // Kubeconfig filename to save + Kubeconfig string `yaml:"kubeconfig,omitempty"` +} + +// ReadYAMLFile reads YAML-formatted configuration file and +// de-serializes it to a given object +func ReadYAMLFile(filePath string, cfg *GcpConfig) error { + data, err := ioutil.ReadFile(filePath) + if err != nil { + log.Printf("Failed to read GCP Ephemeral configuration file: err #%v ", err) + return err + } + return yaml.Unmarshal(data, cfg) +} + +// ValidateConfigFile validates GCP configuration file for the Ephemeral Cluster +func ValidateConfigFile(config *GcpConfig) error { + validate := validator.New() + err := validate.Struct(config) + if err != nil { + var invalidError *validator.InvalidValidationError + if errors.As(err, &invalidError) { + log.Println(err) + return err + } + + log.Printf("Ephemeral cluster configuration file validation failed") + for _, err := range err.(validator.ValidationErrors) { + log.Printf(" Namespace = %s\n", err.Namespace()) + log.Printf(" Tag = %s\n", err.Tag()) + log.Printf(" Type = %s\n", err.Type()) + log.Printf(" Value = %s\n", err.Value()) + log.Printf(" Param = %s\n\n", err.Param()) + } + return err + } + return nil +} diff --git a/bootstrap_capg/config/gke_cluster.go b/bootstrap_capg/config/gke_cluster.go new file mode 100644 index 0000000..2a47e5f --- /dev/null +++ b/bootstrap_capg/config/gke_cluster.go @@ -0,0 +1,159 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package config + +import ( + "log" + "os" + "strconv" +) + +const ( + gcloud = "gcloud" + auth = "auth" + activateServiceAccount = "activate-service-account" + config = "config" + set = "set" + project = "project" + container = "container" + clusters = "clusters" + create = "create" + delete = "delete" + getCredentials = "get-credentials" + + zoneP = "--zone" + nodeLocations = "--node-locations" + keyFileP = "--key-file" + clusterVersionP = "--cluster-version" + machineTypeP = "--machine-type" + numNodesP = "--num-nodes" + enableIPAlias = "--enable-ip-alias" + imageTypeP = "--image-type" + diskTypeP = "--disk-type" + diskSizeP = "--disk-size" + metadataP = "--metadata" + scopesP = "--scopes" + enableStackDriverKubernetesP = "--enable-stackdriver-kubernetes" + enableAutoUpgradeP = "--enable-autoupgrade" + enableAutoRepairP = "--enable-autorepair" + quietP = "--quiet" + + defaultClusterName = "capi-gcp" + defaultRegion = "us-central1" + defaultZone = "us-central1-c" + defaultMachineSize = "e2-medium" + defaultK8SVersion = "1.16.13-gke.401" + defaultKubeconfig = "kubeconfig" + + kubeconfigVar = "KUBECONFIG" +) + +// defaultGCPConfig verify if any optional config data is missing. +func defaultGCPConfig(gcpConfig *GcpConfig) error { + if gcpConfig.Spec.Region == "" { + gcpConfig.Spec.Region = defaultRegion + } + if gcpConfig.Spec.Zone == "" { + gcpConfig.Spec.Zone = defaultZone + } + if gcpConfig.Metadata.Name == "" { + gcpConfig.Metadata.Name = defaultClusterName + } + if gcpConfig.Spec.Cluster.MachineSize == "" { + gcpConfig.Spec.Cluster.MachineSize = defaultMachineSize + } + if gcpConfig.Spec.Cluster.K8SVersion == "" { + gcpConfig.Spec.Cluster.K8SVersion = defaultK8SVersion + } + if gcpConfig.Spec.Cluster.Kubeconfig == "" { + gcpConfig.Spec.Cluster.Kubeconfig = defaultKubeconfig + } + return nil +} + +// prepareGCPCluster logs in, create resource group, etc +func prepareGCPCluster(gcpConfig *GcpConfig, isCreate bool) error { + // Verify if Google Cloud config file provides all information needed for creating a cluster + err := defaultGCPConfig(gcpConfig) + if err != nil { + return err + } + + // Get Kubeconfig filename + volMount := os.Getenv("BOOTSTRAP_VOLUME") + _, dstMount := GetVolumeMountPoints(volMount) + + gcpProject := gcpConfig.Credentials.Project + gcpAccount := gcpConfig.Credentials.Account + gcpCredential := dstMount + "/" + gcpConfig.Credentials.Credential + + clusterName := gcpConfig.Metadata.Name + region := gcpConfig.Spec.Region + zone := gcpConfig.Spec.Zone + + machineSize := gcpConfig.Spec.Cluster.MachineSize + nodeCount := strconv.FormatInt(int64(gcpConfig.Spec.Cluster.Replicas), 10) + k8sVersion := gcpConfig.Spec.Cluster.K8SVersion + kubeconfigFile := gcpConfig.Spec.Cluster.Kubeconfig + + // login to GCP account using Service Principal + err = execute(gcloud, auth, activateServiceAccount, gcpAccount, keyFileP, gcpCredential) + if err != nil { + log.Printf("Failed to login into GCP using Service Account\n") + return err + } + + // Set project to use to the configuration + err = execute(gcloud, config, set, project, gcpProject) + if err != nil { + log.Printf("Failed to set GCP project to the configuration\n") + return err + } + + if isCreate { + // Creating Google GKE cluster + err = execute(gcloud, container, clusters, create, clusterName, + zoneP, zone, nodeLocations, zone, + numNodesP, nodeCount, machineTypeP, machineSize, + enableIPAlias, enableAutoUpgradeP, enableAutoRepairP, + clusterVersionP, k8sVersion) + if err != nil { + log.Printf("Failed to create GKE cluster %s in %s region.\n", clusterName, region) + return err + } + + // Retrieving the Kubeconfig file for the cluster + dstKubeconfig := dstMount + "/" + kubeconfigFile + os.Setenv(kubeconfigVar, dstKubeconfig) + err = execute(gcloud, container, clusters, getCredentials, clusterName, zoneP, zone) + if err != nil { + log.Printf("Failed to retrieve kubeconfig file for GCP cluster %s in %s region.\n", clusterName, region) + return err + } + + if _, err := os.Stat(dstKubeconfig); err != nil { + log.Printf("Failed to retrieve kubeconfig file for GCP cluster %s in %s region.\n", clusterName, region) + return err + } + } else { + // Delete GCP GKE cluster + err = execute(gcloud, container, clusters, delete, clusterName, zoneP, zone, quietP) + if err != nil { + log.Printf("Failed to delete GKE cluster %s in %s region.\n", clusterName, region) + return err + } + } + return nil +} diff --git a/bootstrap_capg/gcp-config.json b/bootstrap_capg/gcp-config.json new file mode 100644 index 0000000..3081a53 --- /dev/null +++ b/bootstrap_capg/gcp-config.json @@ -0,0 +1,23 @@ +{ + "apiVersion": "v1", + "kind": "GoogleCloudConfig", + "metadata": { + "name": "capi-google-zuul" + }, + "credentials": { + "project": "peak-vista-274815", + "account": "airship-kubernetes-account@peak-vista-274815.iam.gserviceaccount.com", + "credential": "gcp-credentials.json" + }, + "spec": { + "region": "us-central1", + "zone": "us-central1-c", + "cluster": { + "k8sVersion": "1.16.13-gke.1", + "machineSize": "e2-medium", + "diskSize": 100, + "replicas": 1, + "kubeconfig": "capg.kubeconfig" + } + } + } \ No newline at end of file diff --git a/bootstrap_capg/gcp-config.yaml b/bootstrap_capg/gcp-config.yaml new file mode 100644 index 0000000..826086b --- /dev/null +++ b/bootstrap_capg/gcp-config.yaml @@ -0,0 +1,29 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: v1 +kind: GoogleCloudConfig +metadata: + name: capi-google-zuul +credentials: + project: + account: + credential: gcp-credentials.json +spec: + region: us-central1 + zone: us-central1-c + cluster: + k8sVersion: 1.16.13-gke.401 + machineSize: e2-medium + diskSize: 100 + replicas: 1 + kubeconfig: capg.kubeconfig diff --git a/bootstrap_capg/gcp-credentials.json b/bootstrap_capg/gcp-credentials.json new file mode 100644 index 0000000..dd1755e --- /dev/null +++ b/bootstrap_capg/gcp-credentials.json @@ -0,0 +1,12 @@ +{ + "type": "service_account", + "project_id": ". NOTE: This file was generated by Google Cloud", + "private_key_id": "", + "private_key": "-----BEGIN PRIVATE KEY----------END PRIVATE KEY-----\n", + "client_email": "", + "client_id": "", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/airship-kubernetes-account%40peak-vista-274815.iam.gserviceaccount.com" +} diff --git a/bootstrap_capg/main.go b/bootstrap_capg/main.go new file mode 100644 index 0000000..ad298e6 --- /dev/null +++ b/bootstrap_capg/main.go @@ -0,0 +1,78 @@ +/* + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package main + +import ( + "flag" + "log" + "os" + + "opendev.org/airship/images/bootstrap_capg/config" +) + +const ( + createCmd = "create" + deleteCmd = "delete" + helpCmd = "help" +) + +func main() { + var configPath string + + flag.StringVar(&configPath, "c", "", "Path for the Google Cloud bootstrap configuration (yaml) file") + flag.Parse() + + if configPath == "" { + volMount := os.Getenv("BOOTSTRAP_VOLUME") + _, dstMount := config.GetVolumeMountPoints(volMount) + gcpConfigPath := dstMount + "/" + os.Getenv("BOOTSTRAP_CONFIG") + configPath = gcpConfigPath + } + + configYAML := &config.GcpConfig{} + err := config.ReadYAMLFile(configPath, configYAML) + if err != nil { + log.Printf("Failed to load Google Cloud Bootstrap config file") + os.Exit(1) + } + + err = config.ValidateConfigFile(configYAML) + if err != nil { + os.Exit(2) + } + + command := os.Getenv("BOOTSTRAP_COMMAND") + switch { + case command == createCmd: + err = config.CreateGKECluster(configYAML) + if err != nil { + os.Exit(5) + } + case command == deleteCmd: + err = config.DeleteGKECluster(configYAML) + if err != nil { + os.Exit(6) + } + case command == helpCmd: + err = config.HelpGKECluster() + if err != nil { + os.Exit(7) + } + default: + log.Printf("The --command parameter value shall be 'create', 'delete' or 'help'") + os.Exit(8) + } + os.Exit(0) +}