From 509de661d8700317102621713ddb3c63e4c0ca69 Mon Sep 17 00:00:00 2001 From: The Magician Date: Wed, 30 Mar 2022 16:26:15 -0500 Subject: [PATCH] Added support for approval when build is run (#5837) (#4162) Signed-off-by: Modular Magician --- .changelog/5837.txt | 3 + google-beta/resource_cloudbuild_trigger.go | 77 ++++++++++++++++++- ...ource_cloudbuild_trigger_generated_test.go | 9 +++ .../docs/r/cloudbuild_trigger.html.markdown | 27 ++++++- 4 files changed, 113 insertions(+), 3 deletions(-) create mode 100644 .changelog/5837.txt diff --git a/.changelog/5837.txt b/.changelog/5837.txt new file mode 100644 index 0000000000..290d838718 --- /dev/null +++ b/.changelog/5837.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +cloudbuild: Add approval config +``` diff --git a/google-beta/resource_cloudbuild_trigger.go b/google-beta/resource_cloudbuild_trigger.go index 605bc693ee..0a5d509708 100644 --- a/google-beta/resource_cloudbuild_trigger.go +++ b/google-beta/resource_cloudbuild_trigger.go @@ -82,6 +82,26 @@ func resourceCloudBuildTrigger() *schema.Resource { CustomizeDiff: stepTimeoutCustomizeDiff, Schema: map[string]*schema.Schema{ + "approval_config": { + Type: schema.TypeList, + Computed: true, + Optional: true, + Description: `Configuration for manual approval to start a build invocation of this BuildTrigger. +Builds created by this trigger will require approval before they execute. +Any user with a Cloud Build Approver role for the project can approve a build.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "approval_required": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether or not approval is needed. If this is set on a build, it will become pending when run, +and will need to be explicitly approved to start.`, + Default: false, + }, + }, + }, + }, "build": { Type: schema.TypeList, Optional: true, @@ -698,7 +718,8 @@ When using Pub/Sub, Webhook or Manual set the file name using git_file_source in Type: schema.TypeString, Required: true, ValidateFunc: validateEnum([]string{"UNKNOWN", "CLOUD_SOURCE_REPOSITORIES", "GITHUB"}), - Description: `The type of the repo, since it may not be explicit from the repo field (e.g from a URL). Possible values: ["UNKNOWN", "CLOUD_SOURCE_REPOSITORIES", "GITHUB"]`, + Description: `The type of the repo, since it may not be explicit from the repo field (e.g from a URL). +Values can be UNKNOWN, CLOUD_SOURCE_REPOSITORIES, GITHUB Possible values: ["UNKNOWN", "CLOUD_SOURCE_REPOSITORIES", "GITHUB"]`, }, "revision": { Type: schema.TypeString, @@ -904,7 +925,8 @@ One of 'trigger_template', 'github', 'pubsub_config' 'webhook_config' or 'source Type: schema.TypeString, Required: true, ValidateFunc: validateEnum([]string{"UNKNOWN", "CLOUD_SOURCE_REPOSITORIES", "GITHUB"}), - Description: `The type of the repo, since it may not be explicit from the repo field (e.g from a URL). Possible values: ["UNKNOWN", "CLOUD_SOURCE_REPOSITORIES", "GITHUB"]`, + Description: `The type of the repo, since it may not be explicit from the repo field (e.g from a URL). +Values can be UNKNOWN, CLOUD_SOURCE_REPOSITORIES, GITHUB Possible values: ["UNKNOWN", "CLOUD_SOURCE_REPOSITORIES", "GITHUB"]`, }, "uri": { Type: schema.TypeString, @@ -1143,6 +1165,12 @@ func resourceCloudBuildTriggerCreate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("webhook_config"); !isEmptyValue(reflect.ValueOf(webhookConfigProp)) && (ok || !reflect.DeepEqual(v, webhookConfigProp)) { obj["webhookConfig"] = webhookConfigProp } + approvalConfigProp, err := expandCloudBuildTriggerApprovalConfig(d.Get("approval_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("approval_config"); !isEmptyValue(reflect.ValueOf(approvalConfigProp)) && (ok || !reflect.DeepEqual(v, approvalConfigProp)) { + obj["approvalConfig"] = approvalConfigProp + } buildProp, err := expandCloudBuildTriggerBuild(d.Get("build"), d, config) if err != nil { return err @@ -1291,6 +1319,9 @@ func resourceCloudBuildTriggerRead(d *schema.ResourceData, meta interface{}) err if err := d.Set("webhook_config", flattenCloudBuildTriggerWebhookConfig(res["webhookConfig"], d, config)); err != nil { return fmt.Errorf("Error reading Trigger: %s", err) } + if err := d.Set("approval_config", flattenCloudBuildTriggerApprovalConfig(res["approvalConfig"], d, config)); err != nil { + return fmt.Errorf("Error reading Trigger: %s", err) + } if err := d.Set("build", flattenCloudBuildTriggerBuild(res["build"], d, config)); err != nil { return fmt.Errorf("Error reading Trigger: %s", err) } @@ -1410,6 +1441,12 @@ func resourceCloudBuildTriggerUpdate(d *schema.ResourceData, meta interface{}) e } else if v, ok := d.GetOkExists("webhook_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, webhookConfigProp)) { obj["webhookConfig"] = webhookConfigProp } + approvalConfigProp, err := expandCloudBuildTriggerApprovalConfig(d.Get("approval_config"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("approval_config"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, approvalConfigProp)) { + obj["approvalConfig"] = approvalConfigProp + } buildProp, err := expandCloudBuildTriggerBuild(d.Get("build"), d, config) if err != nil { return err @@ -1806,6 +1843,19 @@ func flattenCloudBuildTriggerWebhookConfigState(v interface{}, d *schema.Resourc return v } +func flattenCloudBuildTriggerApprovalConfig(v interface{}, d *schema.ResourceData, config *Config) interface{} { + transformed := make(map[string]interface{}) + if v == nil { + // Disabled by default, but API will not return object if value is false + transformed["approval_required"] = false + return []interface{}{transformed} + } + + original := v.(map[string]interface{}) + transformed["approval_required"] = original["approvalRequired"] + return []interface{}{transformed} +} + func flattenCloudBuildTriggerBuild(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return nil @@ -2781,6 +2831,29 @@ func expandCloudBuildTriggerWebhookConfigState(v interface{}, d TerraformResourc return v, nil } +func expandCloudBuildTriggerApprovalConfig(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{}) + + transformedApprovalRequired, err := expandCloudBuildTriggerApprovalConfigApprovalRequired(original["approval_required"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedApprovalRequired); val.IsValid() && !isEmptyValue(val) { + transformed["approvalRequired"] = transformedApprovalRequired + } + + return transformed, nil +} + +func expandCloudBuildTriggerApprovalConfigApprovalRequired(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + func expandCloudBuildTriggerBuild(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google-beta/resource_cloudbuild_trigger_generated_test.go b/google-beta/resource_cloudbuild_trigger_generated_test.go index d96a16f67e..7277fde12f 100644 --- a/google-beta/resource_cloudbuild_trigger_generated_test.go +++ b/google-beta/resource_cloudbuild_trigger_generated_test.go @@ -409,6 +409,15 @@ resource "google_cloudbuild_trigger" "manual-trigger" { revision = "refs/heads/main" repo_type = "GITHUB" } + + + // If this is set on a build, it will become pending when it is run, + // and will need to be explicitly approved to start. + approval_config { + approval_required = true + } + + } `, context) } diff --git a/website/docs/r/cloudbuild_trigger.html.markdown b/website/docs/r/cloudbuild_trigger.html.markdown index 97d23f4ede..ef7034f97c 100644 --- a/website/docs/r/cloudbuild_trigger.html.markdown +++ b/website/docs/r/cloudbuild_trigger.html.markdown @@ -307,6 +307,15 @@ resource "google_cloudbuild_trigger" "manual-trigger" { revision = "refs/heads/main" repo_type = "GITHUB" } + + + // If this is set on a build, it will become pending when it is run, + // and will need to be explicitly approved to start. + approval_config { + approval_required = true + } + + } ``` @@ -422,6 +431,13 @@ The following arguments are supported: One of `trigger_template`, `github`, `pubsub_config` `webhook_config` or `source_to_build` must be provided. Structure is [documented below](#nested_webhook_config). +* `approval_config` - + (Optional) + Configuration for manual approval to start a build invocation of this BuildTrigger. + Builds created by this trigger will require approval before they execute. + Any user with a Cloud Build Approver role for the project can approve a build. + Structure is [documented below](#nested_approval_config). + * `build` - (Optional) Contents of the build template. Either a filename or build template must be provided. @@ -444,7 +460,8 @@ The following arguments are supported: * `repo_type` - (Required) - The type of the repo, since it may not be explicit from the repo field (e.g from a URL). + The type of the repo, since it may not be explicit from the repo field (e.g from a URL). + Values can be UNKNOWN, CLOUD_SOURCE_REPOSITORIES, GITHUB Possible values are `UNKNOWN`, `CLOUD_SOURCE_REPOSITORIES`, and `GITHUB`. * `revision` - @@ -466,6 +483,7 @@ The following arguments are supported: * `repo_type` - (Required) The type of the repo, since it may not be explicit from the repo field (e.g from a URL). + Values can be UNKNOWN, CLOUD_SOURCE_REPOSITORIES, GITHUB Possible values are `UNKNOWN`, `CLOUD_SOURCE_REPOSITORIES`, and `GITHUB`. The `trigger_template` block supports: @@ -583,6 +601,13 @@ The following arguments are supported: Potential issues with the underlying Pub/Sub subscription configuration. Only populated on get requests. +The `approval_config` block supports: + +* `approval_required` - + (Optional) + Whether or not approval is needed. If this is set on a build, it will become pending when run, + and will need to be explicitly approved to start. + The `build` block supports: * `source` -