Skip to content

Commit

Permalink
add support for available_secrets to google_cloudbuild_trigger (#4977) (
Browse files Browse the repository at this point in the history
#10714)

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Dec 8, 2021
1 parent 8bc672d commit 2b0db24
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .changelog/4977.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
cloudbuild: added support for available_secrets to google_cloudbuild_trigger
```
136 changes: 136 additions & 0 deletions google/resource_cloudbuild_trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,37 @@ nine fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:2
},
},
},
"available_secrets": {
Type: schema.TypeList,
Optional: true,
Description: `Secrets and secret environment variables.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"secret_manager": {
Type: schema.TypeList,
Required: true,
Description: `Pairs a secret environment variable with a SecretVersion in Secret Manager.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"env": {
Type: schema.TypeString,
Required: true,
Description: `Environment variable name to associate with the secret. Secret environment
variables must be unique across all of a build's secrets, and must be used
by at least one build step.`,
},
"version_name": {
Type: schema.TypeString,
Required: true,
Description: `Resource name of the SecretVersion. In format: projects/*/secrets/*/versions/*`,
},
},
},
},
},
},
},
"images": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -1615,6 +1646,8 @@ func flattenCloudBuildTriggerBuild(v interface{}, d *schema.ResourceData, config
flattenCloudBuildTriggerBuildTimeout(original["timeout"], d, config)
transformed["secret"] =
flattenCloudBuildTriggerBuildSecret(original["secrets"], d, config)
transformed["available_secrets"] =
flattenCloudBuildTriggerBuildAvailableSecrets(original["availableSecrets"], d, config)
transformed["step"] =
flattenCloudBuildTriggerBuildStep(original["steps"], d, config)
transformed["artifacts"] =
Expand Down Expand Up @@ -1777,6 +1810,46 @@ func flattenCloudBuildTriggerBuildSecretSecretEnv(v interface{}, d *schema.Resou
return v
}

func flattenCloudBuildTriggerBuildAvailableSecrets(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["secret_manager"] =
flattenCloudBuildTriggerBuildAvailableSecretsSecretManager(original["secretManager"], d, config)
return []interface{}{transformed}
}
func flattenCloudBuildTriggerBuildAvailableSecretsSecretManager(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"version_name": flattenCloudBuildTriggerBuildAvailableSecretsSecretManagerVersionName(original["versionName"], d, config),
"env": flattenCloudBuildTriggerBuildAvailableSecretsSecretManagerEnv(original["env"], d, config),
})
}
return transformed
}
func flattenCloudBuildTriggerBuildAvailableSecretsSecretManagerVersionName(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenCloudBuildTriggerBuildAvailableSecretsSecretManagerEnv(v interface{}, d *schema.ResourceData, config *Config) interface{} {
return v
}

func flattenCloudBuildTriggerBuildStep(v interface{}, d *schema.ResourceData, config *Config) interface{} {
if v == nil {
return v
Expand Down Expand Up @@ -2483,6 +2556,13 @@ func expandCloudBuildTriggerBuild(v interface{}, d TerraformResourceData, config
transformed["secrets"] = transformedSecret
}

transformedAvailableSecrets, err := expandCloudBuildTriggerBuildAvailableSecrets(original["available_secrets"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAvailableSecrets); val.IsValid() && !isEmptyValue(val) {
transformed["availableSecrets"] = transformedAvailableSecrets
}

transformedStep, err := expandCloudBuildTriggerBuildStep(original["step"], d, config)
if err != nil {
return nil, err
Expand Down Expand Up @@ -2760,6 +2840,62 @@ func expandCloudBuildTriggerBuildSecretSecretEnv(v interface{}, d TerraformResou
return m, nil
}

func expandCloudBuildTriggerBuildAvailableSecrets(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedSecretManager, err := expandCloudBuildTriggerBuildAvailableSecretsSecretManager(original["secret_manager"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedSecretManager); val.IsValid() && !isEmptyValue(val) {
transformed["secretManager"] = transformedSecretManager
}

return transformed, nil
}

func expandCloudBuildTriggerBuildAvailableSecretsSecretManager(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedVersionName, err := expandCloudBuildTriggerBuildAvailableSecretsSecretManagerVersionName(original["version_name"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedVersionName); val.IsValid() && !isEmptyValue(val) {
transformed["versionName"] = transformedVersionName
}

transformedEnv, err := expandCloudBuildTriggerBuildAvailableSecretsSecretManagerEnv(original["env"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedEnv); val.IsValid() && !isEmptyValue(val) {
transformed["env"] = transformedEnv
}

req = append(req, transformed)
}
return req, nil
}

func expandCloudBuildTriggerBuildAvailableSecretsSecretManagerVersionName(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandCloudBuildTriggerBuildAvailableSecretsSecretManagerEnv(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
return v, nil
}

func expandCloudBuildTriggerBuildStep(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
Expand Down
11 changes: 9 additions & 2 deletions google/resource_cloudbuild_trigger_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,13 @@ resource "google_cloudbuild_trigger" "build-trigger" {
branch_name = "master"
repo_name = "my-repo"
}
build {
step {
name = "gcr.io/cloud-builders/gsutil"
args = ["cp", "gs://mybucket/remotefile.zip", "localfile.zip"]
timeout = "120s"
secret_env = ["MY_SECRET"]
}
source {
Expand All @@ -123,6 +124,12 @@ resource "google_cloudbuild_trigger" "build-trigger" {
PASSWORD = "ZW5jcnlwdGVkLXBhc3N3b3JkCg=="
}
}
available_secrets {
secret_manager {
env = "MY_SECRET"
version_name = "projects/myProject/secrets/mySecret/versions/latest"
}
}
artifacts {
images = ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"]
objects {
Expand All @@ -147,7 +154,7 @@ resource "google_cloudbuild_trigger" "build-trigger" {
path = "v1"
}
}
}
}
}
`, context)
}
Expand Down
79 changes: 79 additions & 0 deletions google/resource_cloudbuild_trigger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,35 @@ func TestAccCloudBuildTrigger_basic(t *testing.T) {
})
}

func TestAccCloudBuildTrigger_available_secrets_config(t *testing.T) {
t.Parallel()
name := fmt.Sprintf("tf-test-%d", randInt(t))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudBuildTriggerDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccCloudBuildTrigger_available_secrets_config(name),
},
{
ResourceName: "google_cloudbuild_trigger.build_trigger",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccCloudBuildTrigger_available_secrets_config_update(name),
},
{
ResourceName: "google_cloudbuild_trigger.build_trigger",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccCloudBuildTrigger_pubsub_config(t *testing.T) {
t.Parallel()
name := fmt.Sprintf("tf-test-%d", randInt(t))
Expand Down Expand Up @@ -339,6 +368,56 @@ resource "google_cloudbuild_trigger" "build_trigger" {
`, name)
}

func testAccCloudBuildTrigger_available_secrets_config(name string) string {
return fmt.Sprintf(`
resource "google_cloudbuild_trigger" "build_trigger" {
name = "%s"
description = "acceptance test build trigger"
trigger_template {
branch_name = "master"
repo_name = "some-repo"
}
build {
tags = ["team-a", "service-b"]
timeout = "1800s"
step {
name = "gcr.io/cloud-builders/gsutil"
args = ["cp", "gs://mybucket/remotefile.zip", "localfile.zip"]
timeout = "300s"
}
available_secrets {
secret_manager {
env = "MY_SECRET"
version_name = "projects/myProject/secrets/mySecret/versions/latest"
}
}
}
}
`, name)
}

func testAccCloudBuildTrigger_available_secrets_config_update(name string) string {
return fmt.Sprintf(`
resource "google_cloudbuild_trigger" "build_trigger" {
name = "%s"
description = "acceptance test build trigger updated"
trigger_template {
branch_name = "master"
repo_name = "some-repo"
}
build {
tags = ["team-a", "service-b"]
timeout = "1800s"
step {
name = "gcr.io/cloud-builders/gsutil"
args = ["cp", "gs://mybucket/remotefile.zip", "localfile.zip"]
timeout = "300s"
}
}
}
`, name)
}

func testAccCloudBuildTrigger_pubsub_config(name string) string {
return fmt.Sprintf(`
resource "google_pubsub_topic" "build-trigger" {
Expand Down
36 changes: 34 additions & 2 deletions website/docs/r/cloudbuild_trigger.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,13 @@ resource "google_cloudbuild_trigger" "build-trigger" {
branch_name = "master"
repo_name = "my-repo"
}
build {
step {
name = "gcr.io/cloud-builders/gsutil"
args = ["cp", "gs://mybucket/remotefile.zip", "localfile.zip"]
timeout = "120s"
secret_env = ["MY_SECRET"]
}
source {
Expand All @@ -97,6 +98,12 @@ resource "google_cloudbuild_trigger" "build-trigger" {
PASSWORD = "ZW5jcnlwdGVkLXBhc3N3b3JkCg=="
}
}
available_secrets {
secret_manager {
env = "MY_SECRET"
version_name = "projects/myProject/secrets/mySecret/versions/latest"
}
}
artifacts {
images = ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"]
objects {
Expand All @@ -121,7 +128,7 @@ resource "google_cloudbuild_trigger" "build-trigger" {
path = "v1"
}
}
}
}
}
```
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
Expand Down Expand Up @@ -430,6 +437,11 @@ The following arguments are supported:
Secrets to decrypt using Cloud Key Management Service.
Structure is [documented below](#nested_secret).

* `available_secrets` -
(Optional)
Secrets and secret environment variables.
Structure is [documented below](#nested_available_secrets).

* `step` -
(Required)
The operations to be performed on the workspace.
Expand Down Expand Up @@ -529,6 +541,26 @@ The following arguments are supported:
and must be used by at least one build step. Values can be at most 64 KB in size.
There can be at most 100 secret values across all of a build's secrets.

<a name="nested_available_secrets"></a>The `available_secrets` block supports:

* `secret_manager` -
(Required)
Pairs a secret environment variable with a SecretVersion in Secret Manager.
Structure is [documented below](#nested_secret_manager).


<a name="nested_secret_manager"></a>The `secret_manager` block supports:

* `version_name` -
(Required)
Resource name of the SecretVersion. In format: projects/*/secrets/*/versions/*

* `env` -
(Required)
Environment variable name to associate with the secret. Secret environment
variables must be unique across all of a build's secrets, and must be used
by at least one build step.

<a name="nested_step"></a>The `step` block supports:

* `name` -
Expand Down

0 comments on commit 2b0db24

Please sign in to comment.