custom-targets/helm/helm-deployer/deploy.go (88 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 ( "context" "fmt" "os" "cloud.google.com/go/storage" "github.com/GoogleCloudPlatform/cloud-deploy-samples/custom-targets/util/clouddeploy" "github.com/mholt/archiver/v3" ) // deployer implements the requestHandler interface for deploy requests. type deployer struct { req *clouddeploy.DeployRequest params *params gcsClient *storage.Client } // process processes a deploy request and uploads succeeded or failed results to GCS for Cloud Deploy. func (d *deployer) process(ctx context.Context) error { fmt.Println("Processing deploy request") res, err := d.deploy(ctx) if err != nil { fmt.Printf("Deploy failed: %v\n", err) dr := &clouddeploy.DeployResult{ ResultStatus: clouddeploy.DeployFailed, FailureMessage: err.Error(), Metadata: map[string]string{ clouddeploy.CustomTargetSourceMetadataKey: helmDeployerSampleName, clouddeploy.CustomTargetSourceSHAMetadataKey: clouddeploy.GitCommit, }, } fmt.Println("Uploading failed deploy results") rURI, err := d.req.UploadResult(ctx, d.gcsClient, dr) if err != nil { return fmt.Errorf("error uploading failed deploy results: %v", err) } fmt.Printf("Uploaded failed deploy results to %s\n", rURI) return err } fmt.Println("Uploading deploy results") rURI, err := d.req.UploadResult(ctx, d.gcsClient, res) if err != nil { return fmt.Errorf("error uploading deploy results: %v", err) } fmt.Printf("Uploaded deploy results to %s\n", rURI) return nil } // deploy performs the following steps: // 1. Run helm upgrade for the provided helm chart // 2. Get the helm release manifest and upload to GCS as a deploy artifact. // // Returns either the deploy results or an error if the deploy failed. func (d *deployer) deploy(ctx context.Context) (*clouddeploy.DeployResult, error) { fmt.Printf("Downloading helm configuration archive to %s\n", srcArchivePath) inURI, err := d.req.DownloadInput(ctx, d.gcsClient, renderedArchiveName, srcArchivePath) if err != nil { return nil, fmt.Errorf("unable to download deploy input with object suffix %s: %v", renderedArchiveName, err) } fmt.Printf("Downloaded helm configuration archive from %s\n", inURI) archiveFile, err := os.Open(srcArchivePath) if err != nil { return nil, fmt.Errorf("unable to open archive file %s: %v", srcArchivePath, err) } fmt.Printf("Unarchiving helm configuration in %s to %s\n", srcArchivePath, srcPath) if err := archiver.NewTarGz().Unarchive(archiveFile.Name(), srcPath); err != nil { return nil, fmt.Errorf("unable to unarchive helm configuration: %v", err) } fmt.Printf("Setting up cluster credentials for %s\n", d.params.gkeCluster) if _, err := gcloudClusterCredentials(d.params.gkeCluster); err != nil { return nil, fmt.Errorf("unable to set up cluster credentials: %v", err) } fmt.Printf("Finished setting up cluster credentials for %s\n", d.params.gkeCluster) // Use the pipeline ID as the helm release since this should be consistent. helmRelease := d.req.Pipeline chartPath := determineChartPath(d.params) hOpts := helmOptions{namespace: d.params.namespace} if _, err := helmUpgrade(helmRelease, chartPath, &helmUpgradeOptions{helmOptions: hOpts, timeout: d.params.upgradeTimeout}); err != nil { return nil, fmt.Errorf("error running helm upgrade: %v", err) } // After `helm upgrade` succeeds get the manifest to upload as the deploy artifact. manifest, err := helmGetManifest(helmRelease, &helmOptions{namespace: d.params.namespace}) if err != nil { return nil, fmt.Errorf("error running helm get manifest aft upgrade: %v", err) } fmt.Println("Uploading helm release manifest as a deploy artifact") mURI, err := d.req.UploadArtifact(ctx, d.gcsClient, "manifest.yaml", &clouddeploy.GCSUploadContent{Data: manifest}) if err != nil { return nil, fmt.Errorf("error uploading helm release manifest deploy artifact: %v", err) } dr := &clouddeploy.DeployResult{ ResultStatus: clouddeploy.DeploySucceeded, ArtifactFiles: []string{mURI}, Metadata: map[string]string{ clouddeploy.CustomTargetSourceMetadataKey: helmDeployerSampleName, clouddeploy.CustomTargetSourceSHAMetadataKey: clouddeploy.GitCommit, }, } return dr, nil }