custom-targets/git-ops/git-deployer/cmd.go (50 lines of code) (raw):

// Copyright 2023 Google LLC // 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 ( "bytes" "fmt" "io" "os" "os/exec" "regexp" ) const ( kubectlBin = "kubectl" gcloudBin = "gcloud" ) // gkeClusterRegex represents the regex that a GKE cluster resource name needs to match. var gkeClusterRegex = regexp.MustCompile("^projects/([^/]+)/locations/([^/]+)/clusters/([^/]+)$") // gcloudClusterCredentials runs `gcloud container clusters get-crendetials` to set up // the cluster credentials. func gcloudClusterCredentials(gkeCluster string) ([]byte, error) { m := gkeClusterRegex.FindStringSubmatch(gkeCluster) if len(m) == 0 { return nil, fmt.Errorf("invalid GKE cluster name: %s", gkeCluster) } args := []string{"container", "clusters", "get-credentials", m[3], fmt.Sprintf("--region=%s", m[2]), fmt.Sprintf("--project=%s", m[1])} return runCmd(gcloudBin, args, "", true) } // verifyResourceExists gets the Kubernetes resource if it exists. func verifyResourceExists(rt, rn, ns string) ([]byte, error) { args := []string{"get", rt, rn, fmt.Sprintf("-n=%s", ns)} return runCmd(kubectlBin, args, "", true) } // queryPath queries the JSON path of a Kubernetes resource. func queryPath(rt, rn, ns, path string) ([]byte, error) { args := []string{"get", rt, rn, fmt.Sprintf("-n=%s", ns), fmt.Sprintf("-o=jsonpath=%s", path)} return runCmd(kubectlBin, args, "", true) } // runCmd starts and waits for the provided command with args to complete. If the command // succeeds it returns the stdout of the command. func runCmd(binPath string, args []string, dir string, logCmd bool) ([]byte, error) { if logCmd { fmt.Printf("Running the following command: %s %s\n", binPath, args) } cmd := exec.Command(binPath, args...) cmd.Dir = dir var stderr bytes.Buffer errWriter := io.MultiWriter(&stderr, os.Stderr) cmd.Stderr = errWriter var stdout bytes.Buffer outWriter := io.MultiWriter(&stdout, os.Stdout) cmd.Stdout = outWriter if err := cmd.Start(); err != nil { return nil, fmt.Errorf("failed to start command: %v", err) } if err := cmd.Wait(); err != nil { return nil, fmt.Errorf("error running command: %v\n%s", err, stderr.Bytes()) } return stdout.Bytes(), nil }