func()

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
}