Repository: GoogleCloudPlatform/terraform-validator
Pull request #298 (2021-09-01 15:50:34)

windows release needs .exe extension
It turns out that windows requires executables to end in .exe. (But the .tar.gz should not include that in the name.) I also fixed an issue with duplicative uploads. I've used this to retroactively fix the windows release for 0.6.0.


Patch:
diff --git a/cmd/convert.go b/cmd/convert.go
index b35f95fe..9f087e97 100644
--- a/cmd/convert.go
+++ b/cmd/convert.go
@@ -52,6 +52,7 @@ func newConvertCmd() *cobra.Command {
 		Use:   "convert TFPLAN_JSON",
 		Short: "convert a Terraform plan to Google CAI assets",
 		Long:  convertDesc,
+		SilenceUsage: os.Getenv("COBRA_SILENCE_USAGE") == "true",
 		PreRunE: func(c *cobra.Command, args []string) error {
 			return o.validateArgs(args)
 		},
diff --git a/cmd/list_supported_resources.go b/cmd/list_supported_resources.go
index 3745a465..285ea8de 100644
--- a/cmd/list_supported_resources.go
+++ b/cmd/list_supported_resources.go
@@ -16,6 +16,7 @@ package cmd
 
 import (
 	"fmt"
+	"os"
 
 	converter "github.com/GoogleCloudPlatform/terraform-google-conversion/google"
 	"github.com/spf13/cobra"
@@ -29,6 +30,7 @@ func newListSupportedResourcesCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "list-supported-resources",
 		Short: "List supported terraform resources.",
+		SilenceUsage: os.Getenv("COBRA_SILENCE_USAGE") == "true",
 		RunE: func(c *cobra.Command, args []string) error {
 			return o.run()
 		},
diff --git a/cmd/validate.go b/cmd/validate.go
index 88e62ff4..05e3ea13 100644
--- a/cmd/validate.go
+++ b/cmd/validate.go
@@ -57,6 +57,7 @@ func newValidateCmd() *cobra.Command {
 		Use:   "validate TFPLAN_JSON --policy-path=/path/to/policy/library",
 		Short: "Validate that a terraform plan conforms to Constraint Framework policies",
 		Long: validateDesc,
+		SilenceUsage: os.Getenv("COBRA_SILENCE_USAGE") == "true",
 		PreRunE: func(c *cobra.Command, args []string) error {
 			return o.validateArgs(args)
 		},
diff --git a/cmd/version.go b/cmd/version.go
index e877aefd..6492771b 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -16,6 +16,7 @@ package cmd
 
 import (
 	"fmt"
+	"os"
 
 	"github.com/GoogleCloudPlatform/terraform-validator/tfgcv"
 
@@ -30,6 +31,7 @@ func newVersionCmd() *cobra.Command {
 	cmd := &cobra.Command{
 		Use:   "version",
 		Short: "Display Terraform Validator version.",
+		SilenceUsage: os.Getenv("COBRA_SILENCE_USAGE") == "true",
 		RunE: func(c *cobra.Command, args []string) error {
 			return o.run()
 		},
diff --git a/cnvconfig/getconfig.go b/cnvconfig/getconfig.go
index 70f029e4..7416b49f 100644
--- a/cnvconfig/getconfig.go
+++ b/cnvconfig/getconfig.go
@@ -37,6 +37,10 @@ func GetConfig(ctx context.Context, project string, offline bool) (*converter.Co
 		"GOOGLE_OAUTH_ACCESS_TOKEN",
 	})
 
+	cfg.ImpersonateServiceAccount = multiEnvSearch([]string{
+		"GOOGLE_IMPERSONATE_SERVICE_ACCOUNT",
+	})
+
 	if !offline {
 		converter.ConfigureBasePaths(cfg)
 		if err := cfg.LoadAndValidate(ctx); err != nil {
diff --git a/docs/user_guide.md b/docs/user_guide.md
index 2bba6291..f283400e 100644
--- a/docs/user_guide.md
+++ b/docs/user_guide.md
@@ -33,6 +33,10 @@ gcloud auth application-default login  # local development only
 GOOGLE_APPLICATION_CREDENTIALS=~/.config/gcloud/application_default_credentials.json
 ```
 
+### Service account impersonation
+
+You can specify a [service account to impersonate](https://cloud.google.com/iam/docs/impersonating-service-accounts) for all Google API calls with the `GOOGLE_IMPERSONATE_SERVICE_ACCOUNT` environment variable.
+
 ## `terraform-validator validate`
 
 This command allows you to validate your terraform plan JSON against a specific policy library.
diff --git a/release.sh b/release.sh
index 37588b22..068a830a 100755
--- a/release.sh
+++ b/release.sh
@@ -37,12 +37,17 @@ architectures="amd64 arm64"
 platforms="linux windows darwin"
 skip_platform_arch_pairs=" windows/arm64 "
 
-binary_name=terraform-validator
+tar_gz_name=terraform-validator
 ldflags="-X github.com/GoogleCloudPlatform/terraform-validator/tfgcv.buildVersion=v${version}"
 release_bucket=terraform-validator
 
 # Build release versions
 for platform in ${platforms}; do
+	if [[ "$platform" == "windows" ]]; then
+		binary_name=terraform-validator.exe
+	else
+		binary_name=terraform-validator
+	fi
 	for arch in ${architectures}; do
 		if [[ " ${skip_platform_arch_pairs[@]} " =~ " ${platform}/${arch} " ]]; then
 			echo "Skipped unsupported platform/arch pair ${platform}/${arch}"
@@ -51,9 +56,9 @@ for platform in ${platforms}; do
 
 		echo "Building ${binary_name} v${version} for platform ${platform} / arch ${arch}..."
 		GO111MODULE=on GOOS=${platform} GOARCH=${arch} CGO_ENABLED=0 go build -ldflags "${ldflags}" -o "${release_dir}/${binary_name}" .
-		echo "Creating ${release_dir}/${binary_name}_${platform}_${arch}-${version}.tar.gz"
+		echo "Creating ${release_dir}/${tar_gz_name}_${platform}_${arch}-${version}.tar.gz"
 		pushd "${release_dir}" > /dev/null
-		tar -czf "${binary_name}_${platform}_${arch}-${version}.tar.gz" "${binary_name}" "THIRD_PARTY_NOTICES.zip"
+		tar -czf "${tar_gz_name}_${platform}_${arch}-${version}.tar.gz" "${binary_name}" "THIRD_PARTY_NOTICES.zip"
 		popd > /dev/null
 	done
 done
@@ -65,9 +70,7 @@ echo "Github tag ${version} created"
 
 # Publish release versions
 echo "Pushing releases to Google Storage"
-for arch in ${architectures}; do
-	gsutil cp ${release_dir}/*.tar.gz gs://${release_bucket}/releases/v${version}
-done
+gsutil cp ${release_dir}/*.tar.gz gs://${release_bucket}/releases/v${version}
 echo "Releases pushed to Google Storage"
 
 echo "Create a new release by visiting https://github.com/GoogleCloudPlatform/terraform-validator/releases/new?tag=${version}&title=${version}"


Test patch:
diff --git a/cnvconfig/getconfig_test.go b/cnvconfig/getconfig_test.go
index 68888ad5..c5584f28 100644
--- a/cnvconfig/getconfig_test.go
+++ b/cnvconfig/getconfig_test.go
@@ -17,8 +17,11 @@ func getCredentials(cfg *converter.Config) string {
 func getAccessToken(cfg *converter.Config) string {
 	return cfg.AccessToken
 }
+func getImpersonateServiceAccount(cfg *converter.Config) string {
+	return cfg.ImpersonateServiceAccount
+}
 
-func TestNewConverterCredentials(t *testing.T) {
+func TestGetConfigExtractsEnvVars(t *testing.T) {
 	ctx := context.Background()
 	offline := true
 	cases := []struct {
@@ -51,6 +54,12 @@ func TestNewConverterCredentials(t *testing.T) {
 			envValue:       "whatever",
 			getConfigValue: getAccessToken,
 		},
+		{
+			name:           "GOOGLE_IMPERSONATE_SERVICE_ACCOUNT",
+			envKey:         "GOOGLE_IMPERSONATE_SERVICE_ACCOUNT",
+			envValue:       "whatever",
+			getConfigValue: getImpersonateServiceAccount,
+		},
 	}
 
 	for _, c := range cases {