From e64f9e9831dbd115f773abf2e258162b883e7314 Mon Sep 17 00:00:00 2001 From: The Magician Date: Fri, 24 Sep 2021 16:04:12 -0500 Subject: [PATCH] Add service_account to google_cloudbuild_trigger (#5237) (#10159) Signed-off-by: Modular Magician --- .changelog/5237.txt | 3 + google/resource_cloudbuild_trigger.go | 34 +++++++++++ ...ource_cloudbuild_trigger_generated_test.go | 56 +++++++++++++++++++ .../docs/r/cloudbuild_trigger.html.markdown | 45 +++++++++++++++ 4 files changed, 138 insertions(+) create mode 100644 .changelog/5237.txt diff --git a/.changelog/5237.txt b/.changelog/5237.txt new file mode 100644 index 00000000000..d4cb71735ad --- /dev/null +++ b/.changelog/5237.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +cloudbuild: added field `service_account` to `google_cloudbuild_trigger` +``` diff --git a/google/resource_cloudbuild_trigger.go b/google/resource_cloudbuild_trigger.go index c4bfdb89305..9dac5de5ffd 100644 --- a/google/resource_cloudbuild_trigger.go +++ b/google/resource_cloudbuild_trigger.go @@ -801,6 +801,17 @@ Only populated on get requests.`, }, ExactlyOneOf: []string{"trigger_template", "github", "pubsub_config", "webhook_config"}, }, + "service_account": { + Type: schema.TypeString, + Optional: true, + Description: `The service account used for all user-controlled operations including +triggers.patch, triggers.run, builds.create, and builds.cancel. + +If no service account is set, then the standard Cloud Build service account +([PROJECT_NUM]@system.gserviceaccount.com) will be used instead. + +Format: projects/{PROJECT_ID}/serviceAccounts/{ACCOUNT_ID_OR_EMAIL}`, + }, "substitutions": { Type: schema.TypeMap, Optional: true, @@ -963,6 +974,12 @@ func resourceCloudBuildTriggerCreate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("substitutions"); !isEmptyValue(reflect.ValueOf(substitutionsProp)) && (ok || !reflect.DeepEqual(v, substitutionsProp)) { obj["substitutions"] = substitutionsProp } + serviceAccountProp, err := expandCloudBuildTriggerServiceAccount(d.Get("service_account"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("service_account"); !isEmptyValue(reflect.ValueOf(serviceAccountProp)) && (ok || !reflect.DeepEqual(v, serviceAccountProp)) { + obj["serviceAccount"] = serviceAccountProp + } filenameProp, err := expandCloudBuildTriggerFilename(d.Get("filename"), d, config) if err != nil { return err @@ -1120,6 +1137,9 @@ func resourceCloudBuildTriggerRead(d *schema.ResourceData, meta interface{}) err if err := d.Set("substitutions", flattenCloudBuildTriggerSubstitutions(res["substitutions"], d, config)); err != nil { return fmt.Errorf("Error reading Trigger: %s", err) } + if err := d.Set("service_account", flattenCloudBuildTriggerServiceAccount(res["serviceAccount"], d, config)); err != nil { + return fmt.Errorf("Error reading Trigger: %s", err) + } if err := d.Set("filename", flattenCloudBuildTriggerFilename(res["filename"], d, config)); err != nil { return fmt.Errorf("Error reading Trigger: %s", err) } @@ -1194,6 +1214,12 @@ func resourceCloudBuildTriggerUpdate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("substitutions"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, substitutionsProp)) { obj["substitutions"] = substitutionsProp } + serviceAccountProp, err := expandCloudBuildTriggerServiceAccount(d.Get("service_account"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("service_account"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, serviceAccountProp)) { + obj["serviceAccount"] = serviceAccountProp + } filenameProp, err := expandCloudBuildTriggerFilename(d.Get("filename"), d, config) if err != nil { return err @@ -1352,6 +1378,10 @@ func flattenCloudBuildTriggerSubstitutions(v interface{}, d *schema.ResourceData return v } +func flattenCloudBuildTriggerServiceAccount(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + func flattenCloudBuildTriggerFilename(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } @@ -2055,6 +2085,10 @@ func expandCloudBuildTriggerSubstitutions(v interface{}, d TerraformResourceData return m, nil } +func expandCloudBuildTriggerServiceAccount(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandCloudBuildTriggerFilename(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_cloudbuild_trigger_generated_test.go b/google/resource_cloudbuild_trigger_generated_test.go index 7605a9c2ca6..2b6b2c56e87 100644 --- a/google/resource_cloudbuild_trigger_generated_test.go +++ b/google/resource_cloudbuild_trigger_generated_test.go @@ -152,6 +152,62 @@ resource "google_cloudbuild_trigger" "build-trigger" { `, context) } +func TestAccCloudBuildTrigger_cloudbuildTriggerServiceAccountExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckCloudBuildTriggerDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudBuildTrigger_cloudbuildTriggerServiceAccountExample(context), + }, + { + ResourceName: "google_cloudbuild_trigger.service-account-trigger", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCloudBuildTrigger_cloudbuildTriggerServiceAccountExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_cloudbuild_trigger" "service-account-trigger" { + trigger_template { + branch_name = "master" + repo_name = "my-repo" + } + + service_account = google_service_account.cloudbuild_service_account.id + filename = "cloudbuild.yaml" + depends_on = [ + google_project_iam_member.act_as, + google_project_iam_member.logs_writer + ] +} + +resource "google_service_account" "cloudbuild_service_account" { + account_id = "my-service-account" +} + +resource "google_project_iam_member" "act_as" { + role = "roles/iam.serviceAccountUser" + member = "serviceAccount:${google_service_account.cloudbuild_service_account.email}" +} + +resource "google_project_iam_member" "logs_writer" { + role = "roles/logging.logWriter" + member = "serviceAccount:${google_service_account.cloudbuild_service_account.email}" +} +`, context) +} + func testAccCheckCloudBuildTriggerDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for name, rs := range s.RootModule().Resources { diff --git a/website/docs/r/cloudbuild_trigger.html.markdown b/website/docs/r/cloudbuild_trigger.html.markdown index df3e6e118db..395e385cd17 100644 --- a/website/docs/r/cloudbuild_trigger.html.markdown +++ b/website/docs/r/cloudbuild_trigger.html.markdown @@ -124,6 +124,43 @@ resource "google_cloudbuild_trigger" "build-trigger" { } } ``` + +## Example Usage - Cloudbuild Trigger Service Account + + +```hcl +resource "google_cloudbuild_trigger" "service-account-trigger" { + trigger_template { + branch_name = "master" + repo_name = "my-repo" + } + + service_account = google_service_account.cloudbuild_service_account.id + filename = "cloudbuild.yaml" + depends_on = [ + google_project_iam_member.act_as, + google_project_iam_member.logs_writer + ] +} + +resource "google_service_account" "cloudbuild_service_account" { + account_id = "my-service-account" +} + +resource "google_project_iam_member" "act_as" { + role = "roles/iam.serviceAccountUser" + member = "serviceAccount:${google_service_account.cloudbuild_service_account.email}" +} + +resource "google_project_iam_member" "logs_writer" { + role = "roles/logging.logWriter" + member = "serviceAccount:${google_service_account.cloudbuild_service_account.email}" +} +``` ## Argument Reference @@ -154,6 +191,14 @@ The following arguments are supported: (Optional) Substitutions data for Build resource. +* `service_account` - + (Optional) + The service account used for all user-controlled operations including + triggers.patch, triggers.run, builds.create, and builds.cancel. + If no service account is set, then the standard Cloud Build service account + ([PROJECT_NUM]@system.gserviceaccount.com) will be used instead. + Format: projects/{PROJECT_ID}/serviceAccounts/{ACCOUNT_ID_OR_EMAIL} + * `filename` - (Optional) Path, from the source root, to a file whose contents is used for the template. Either a filename or build template must be provided.