in custom-targets/terraform/terraform-deployer/render.go [110:199]
func (r *renderer) render(ctx context.Context) (*clouddeploy.RenderResult, error) {
fmt.Printf("Downloading render input archive to %s and unarchiving to %s\n", srcArchivePath, srcPath)
inURI, err := r.req.DownloadAndUnarchiveInput(ctx, r.gcsClient, srcArchivePath, srcPath)
if err != nil {
return nil, fmt.Errorf("unable to download and unarchive render input: %v", err)
}
fmt.Printf("Downloaded render input archive from %s\n", inURI)
// Determine the path to the Terraform configuration. This will be the working directory for Terraform initialization.
terraformConfigPath := path.Join(srcPath, r.params.configPath)
if _, err := terraformInit(terraformConfigPath, &terraformInitOptions{}); err != nil {
return nil, fmt.Errorf("error running terraform init: %v", err)
}
backendPath := path.Join(terraformConfigPath, backendFileName)
fmt.Printf("Generating Terraform backend configuration file: %s\n", backendPath)
if err := generateBackendFile(backendPath, r.params); err != nil {
return nil, fmt.Errorf("error generating backend configuration file: %v", err)
}
fmt.Printf("Finished generating Terraform backend configuration file: %s\n", backendPath)
autoVarsPath := path.Join(terraformConfigPath, autoTFVarsFileName)
fmt.Printf("Generating auto variable definitions file: %s\n", autoVarsPath)
if err := generateAutoTFVarsFile(autoVarsPath, r.params); err != nil {
return nil, fmt.Errorf("error generating variable definitions file: %v", err)
}
fmt.Printf("Finished generating auto variable definitions file: %s\n", autoVarsPath)
if _, err := terraformInit(terraformConfigPath, &terraformInitOptions{}); err != nil {
return nil, fmt.Errorf("error initializing terraform: %v", err)
}
if _, err := terraformValidate(terraformConfigPath); err != nil {
return nil, fmt.Errorf("error validating terraform: %v", err)
}
specPlan := []byte{}
// Only generate the Terraform plan if enabled since this requires the service account to
// have permissions on the Cloud Storage bucket backend.
if r.params.enableRenderPlan {
fmt.Println("Generating speculative Terraform plan for informational purposes")
if _, err := terraformPlan(terraformConfigPath, speculativePlanFileName); err != nil {
return nil, fmt.Errorf("error generating terraform plan: %v", err)
}
var err error
specPlan, err = terraformShowPlan(terraformConfigPath, speculativePlanFileName)
if err != nil {
return nil, fmt.Errorf("error showing terraform plan: %v", err)
}
fmt.Println("Finished generating Terraform plan")
}
fmt.Printf("Creating Cloud Deploy Release inspector artifact: %s\n", inspectorArtifactPath)
if err := createReleaseInspectorArtifact(autoVarsPath, specPlan, inspectorArtifactPath); err != nil {
return nil, fmt.Errorf("error creating cloud deploy release inspector artifact: %v", err)
}
fmt.Println("Uploading Cloud Deploy Release inspector artifact")
planGCSURI, err := r.req.UploadArtifact(ctx, r.gcsClient, inspectorArtifactName, &clouddeploy.GCSUploadContent{LocalPath: inspectorArtifactPath})
if err != nil {
return nil, fmt.Errorf("error uploading speculative plan: %v", err)
}
fmt.Printf("Uploaded Cloud Deploy Release inspector artifact to %s\n", planGCSURI)
// Delete the downloaded providers to save storage space in GCS. The provider versions are stored in the
// .terraform.lock.hcl file, so the correct versions will be redownloaded at deploy time.
os.RemoveAll(path.Join(terraformConfigPath, providersDirName))
// We need to archive all the configuration provided (and generated) instead of just the configuration
// in the terraformConfigPath in case the Terraform configuration in terraformConfigPath has child modules
// in a parent directory.
fmt.Printf("Archiving Terraform configuration in %s for use at deploy time\n", srcPath)
if err := tarArchiveDir(srcPath, renderedArchiveName); err != nil {
return nil, fmt.Errorf("error archiving terraform configuration: %v", err)
}
fmt.Println("Uploading archived Terraform configuration")
atURI, err := r.req.UploadArtifact(ctx, r.gcsClient, renderedArchiveName, &clouddeploy.GCSUploadContent{LocalPath: renderedArchiveName})
if err != nil {
return nil, fmt.Errorf("error uploading archived terraform configuration: %v", err)
}
fmt.Printf("Uploaded archived Terraform configuration to %s\n", atURI)
renderResult := &clouddeploy.RenderResult{
ResultStatus: clouddeploy.RenderSucceeded,
ManifestFile: planGCSURI,
Metadata: map[string]string{
clouddeploy.CustomTargetSourceMetadataKey: tfDeployerSampleName,
clouddeploy.CustomTargetSourceSHAMetadataKey: clouddeploy.GitCommit,
},
}
return renderResult, nil
}