diff --git a/.changelog/6534.txt b/.changelog/6534.txt new file mode 100644 index 00000000000..2a19405d68b --- /dev/null +++ b/.changelog/6534.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +google_eventarc_google_channel_config +``` diff --git a/google/provider_dcl_resources.go b/google/provider_dcl_resources.go index 9be0c77e907..33582872cc9 100644 --- a/google/provider_dcl_resources.go +++ b/google/provider_dcl_resources.go @@ -45,6 +45,7 @@ var dclResources = map[string]*schema.Resource{ "google_dataplex_zone": resourceDataplexZone(), "google_dataproc_workflow_template": resourceDataprocWorkflowTemplate(), "google_eventarc_channel": resourceEventarcChannel(), + "google_eventarc_google_channel_config": resourceEventarcGoogleChannelConfig(), "google_eventarc_trigger": resourceEventarcTrigger(), "google_firebaserules_release": resourceFirebaserulesRelease(), "google_firebaserules_ruleset": resourceFirebaserulesRuleset(), diff --git a/google/resource_eventarc_google_channel_config.go b/google/resource_eventarc_google_channel_config.go new file mode 100644 index 00000000000..bb09ddf1870 --- /dev/null +++ b/google/resource_eventarc_google_channel_config.go @@ -0,0 +1,297 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: DCL *** +// +// ---------------------------------------------------------------------------- +// +// This file is managed by Magic Modules (https://github.com/GoogleCloudPlatform/magic-modules) +// and is based on the DCL (https://github.com/GoogleCloudPlatform/declarative-resource-client-library). +// Changes will need to be made to the DCL or Magic Modules instead of here. +// +// We are not currently able to accept contributions to this file. If changes +// are required, please file an issue at https://github.com/hashicorp/terraform-provider-google/issues/new/choose +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "context" + "fmt" + "log" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + eventarc "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/eventarc" +) + +func resourceEventarcGoogleChannelConfig() *schema.Resource { + return &schema.Resource{ + Create: resourceEventarcGoogleChannelConfigCreate, + Read: resourceEventarcGoogleChannelConfigRead, + Update: resourceEventarcGoogleChannelConfigUpdate, + Delete: resourceEventarcGoogleChannelConfigDelete, + + Importer: &schema.ResourceImporter{ + State: resourceEventarcGoogleChannelConfigImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(20 * time.Minute), + Update: schema.DefaultTimeout(20 * time.Minute), + Delete: schema.DefaultTimeout(20 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "location": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "The location for the resource", + }, + + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "Required. The resource name of the config. Must be in the format of, `projects/{project}/locations/{location}/googleChannelConfig`.", + }, + + "crypto_key_name": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "Optional. Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt their event data. It must match the pattern `projects/*/locations/*/keyRings/*/cryptoKeys/*`.", + }, + + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: "The project for the resource", + }, + + "update_time": { + Type: schema.TypeString, + Computed: true, + Description: "Output only. The last-modified time.", + }, + }, + } +} + +func resourceEventarcGoogleChannelConfigCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &eventarc.GoogleChannelConfig{ + Location: dcl.String(d.Get("location").(string)), + Name: dcl.String(d.Get("name").(string)), + CryptoKeyName: dcl.String(d.Get("crypto_key_name").(string)), + Project: dcl.String(project), + } + + id, err := obj.ID() + if err != nil { + return fmt.Errorf("error constructing id: %s", err) + } + d.SetId(id) + + directive := UpdateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLEventarcClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutCreate)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.ApplyGoogleChannelConfig(context.Background(), obj, directive...) + + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error creating GoogleChannelConfig: %s", err) + } + + log.Printf("[DEBUG] Finished creating GoogleChannelConfig %q: %#v", d.Id(), res) + + return resourceEventarcGoogleChannelConfigRead(d, meta) +} + +func resourceEventarcGoogleChannelConfigRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &eventarc.GoogleChannelConfig{ + Location: dcl.String(d.Get("location").(string)), + Name: dcl.String(d.Get("name").(string)), + CryptoKeyName: dcl.String(d.Get("crypto_key_name").(string)), + Project: dcl.String(project), + } + + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLEventarcClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutRead)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.GetGoogleChannelConfig(context.Background(), obj) + if err != nil { + resourceName := fmt.Sprintf("EventarcGoogleChannelConfig %q", d.Id()) + return handleNotFoundDCLError(err, d, resourceName) + } + + if err = d.Set("location", res.Location); err != nil { + return fmt.Errorf("error setting location in state: %s", err) + } + if err = d.Set("name", res.Name); err != nil { + return fmt.Errorf("error setting name in state: %s", err) + } + if err = d.Set("crypto_key_name", res.CryptoKeyName); err != nil { + return fmt.Errorf("error setting crypto_key_name in state: %s", err) + } + if err = d.Set("project", res.Project); err != nil { + return fmt.Errorf("error setting project in state: %s", err) + } + if err = d.Set("update_time", res.UpdateTime); err != nil { + return fmt.Errorf("error setting update_time in state: %s", err) + } + + return nil +} +func resourceEventarcGoogleChannelConfigUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &eventarc.GoogleChannelConfig{ + Location: dcl.String(d.Get("location").(string)), + Name: dcl.String(d.Get("name").(string)), + CryptoKeyName: dcl.String(d.Get("crypto_key_name").(string)), + Project: dcl.String(project), + } + directive := UpdateDirective + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + + billingProject := "" + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLEventarcClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutUpdate)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + res, err := client.ApplyGoogleChannelConfig(context.Background(), obj, directive...) + + if _, ok := err.(dcl.DiffAfterApplyError); ok { + log.Printf("[DEBUG] Diff after apply returned from the DCL: %s", err) + } else if err != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error updating GoogleChannelConfig: %s", err) + } + + log.Printf("[DEBUG] Finished creating GoogleChannelConfig %q: %#v", d.Id(), res) + + return resourceEventarcGoogleChannelConfigRead(d, meta) +} + +func resourceEventarcGoogleChannelConfigDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + project, err := getProject(d, config) + if err != nil { + return err + } + + obj := &eventarc.GoogleChannelConfig{ + Location: dcl.String(d.Get("location").(string)), + Name: dcl.String(d.Get("name").(string)), + CryptoKeyName: dcl.String(d.Get("crypto_key_name").(string)), + Project: dcl.String(project), + } + + log.Printf("[DEBUG] Deleting GoogleChannelConfig %q", d.Id()) + userAgent, err := generateUserAgentString(d, config.userAgent) + if err != nil { + return err + } + billingProject := project + // err == nil indicates that the billing_project value was found + if bp, err := getBillingProject(d, config); err == nil { + billingProject = bp + } + client := NewDCLEventarcClient(config, userAgent, billingProject, d.Timeout(schema.TimeoutDelete)) + if bp, err := replaceVars(d, config, client.Config.BasePath); err != nil { + d.SetId("") + return fmt.Errorf("Could not format %q: %w", client.Config.BasePath, err) + } else { + client.Config.BasePath = bp + } + if err := client.DeleteGoogleChannelConfig(context.Background(), obj); err != nil { + return fmt.Errorf("Error deleting GoogleChannelConfig: %s", err) + } + + log.Printf("[DEBUG] Finished deleting GoogleChannelConfig %q", d.Id()) + return nil +} + +func resourceEventarcGoogleChannelConfigImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + + if err := parseImportId([]string{ + "projects/(?P[^/]+)/locations/(?P[^/]+)/googleChannelConfig", + "(?P[^/]+)/(?P[^/]+)", + "(?P[^/]+)", + }, d, config); err != nil { + return nil, err + } + + // Replace import id for the resource id + id, err := replaceVarsForId(d, config, "projects/{{project}}/locations/{{location}}/googleChannelConfig") + if err != nil { + return nil, fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + return []*schema.ResourceData{d}, nil +} diff --git a/google/resource_eventarc_google_channel_config_test.go b/google/resource_eventarc_google_channel_config_test.go new file mode 100644 index 00000000000..5a71a679c91 --- /dev/null +++ b/google/resource_eventarc_google_channel_config_test.go @@ -0,0 +1,192 @@ +package google + +import ( + "context" + "fmt" + "strings" + "testing" + + dcl "github.com/GoogleCloudPlatform/declarative-resource-client-library/dcl" + eventarc "github.com/GoogleCloudPlatform/declarative-resource-client-library/services/google/eventarc" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccEventarcGoogleChannelConfig_basic(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "project_name": getTestProjectFromEnv(), + "region": getTestRegionFromEnv(), + "random_suffix": randString(t, 10), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckEventarcGoogleChannelConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccEventarcGoogleChannelConfig_basic(context), + }, + { + ResourceName: "google_eventarc_google_channel_config.primary", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccEventarcGoogleChannelConfig_cryptoKeyUpdate(t *testing.T) { + t.Parallel() + + region := getTestRegionFromEnv() + key1 := BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", region, "tf-bootstrap-key1") + key2 := BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", region, "tf-bootstrap-key2") + + context := map[string]interface{}{ + "project_name": getTestProjectFromEnv(), + "region": getTestRegionFromEnv(), + "random_suffix": randString(t, 10), + "key_ring": GetResourceNameFromSelfLink(key1.KeyRing.Name), + "key1": GetResourceNameFromSelfLink(key1.CryptoKey.Name), + "key2": GetResourceNameFromSelfLink(key2.CryptoKey.Name), + } + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckEventarcGoogleChannelConfigDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccEventarcGoogleChannelConfig_setCryptoKey(context), + }, + { + ResourceName: "google_eventarc_google_channel_config.primary", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccEventarcGoogleChannelConfig_cryptoKeyUpdate(context), + }, + { + ResourceName: "google_eventarc_google_channel_config.primary", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccEventarcGoogleChannelConfig_basic(context map[string]interface{}) string { + return Nprintf(` +resource "google_eventarc_google_channel_config" "primary" { + location = "%{region}" + name = "projects/%{project_name}/locations/%{region}/googleChannelConfig" +} + `, context) +} + +func testAccEventarcGoogleChannelConfig_setCryptoKey(context map[string]interface{}) string { + return Nprintf(` +data "google_project" "test_project" { + project_id = "%{project_name}" +} + +data "google_kms_key_ring" "test_key_ring" { + name = "%{key_ring}" + location = "us-central1" +} + +data "google_kms_crypto_key" "key1" { + name = "%{key1}" + key_ring = data.google_kms_key_ring.test_key_ring.id +} + +resource "google_kms_crypto_key_iam_binding" "key1_binding" { + crypto_key_id = data.google_kms_crypto_key.key1.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.test_project.number}@gcp-sa-eventarc.iam.gserviceaccount.com", + ] +} + +resource "google_eventarc_google_channel_config" "primary" { + location = "%{region}" + name = "projects/%{project_name}/locations/%{region}/googleChannelConfig" + crypto_key_name = data.google_kms_crypto_key.key1.id + depends_on =[google_kms_crypto_key_iam_binding.key1_binding] +} + `, context) +} + +func testAccEventarcGoogleChannelConfig_cryptoKeyUpdate(context map[string]interface{}) string { + return Nprintf(` +data "google_project" "test_project" { + project_id = "%{project_name}" +} + +data "google_kms_key_ring" "test_key_ring" { + name = "%{key_ring}" + location = "us-central1" +} + +data "google_kms_crypto_key" "key2" { + name = "%{key2}" + key_ring = data.google_kms_key_ring.test_key_ring.id +} + +resource "google_kms_crypto_key_iam_binding" "key2_binding" { + crypto_key_id = data.google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.test_project.number}@gcp-sa-eventarc.iam.gserviceaccount.com", + ] +} + +resource "google_eventarc_google_channel_config" "primary" { + location = "%{region}" + name = "projects/%{project_name}/locations/%{region}/googleChannelConfig" + crypto_key_name = data.google_kms_crypto_key.key2.id + depends_on =[google_kms_crypto_key_iam_binding.key2_binding] +} + `, context) +} + +func testAccCheckEventarcGoogleChannelConfigDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for name, rs := range s.RootModule().Resources { + if rs.Type != "rs.google_eventarc_google_channel_config" { + continue + } + if strings.HasPrefix(name, "data.") { + continue + } + + config := googleProviderConfig(t) + + billingProject := "" + if config.BillingProject != "" { + billingProject = config.BillingProject + } + + obj := &eventarc.GoogleChannelConfig{ + Location: dcl.String(rs.Primary.Attributes["location"]), + Name: dcl.String(rs.Primary.Attributes["name"]), + CryptoKeyName: dcl.String(rs.Primary.Attributes["crypto_key_name"]), + Project: dcl.StringOrNil(rs.Primary.Attributes["project"]), + UpdateTime: dcl.StringOrNil(rs.Primary.Attributes["update_time"]), + } + + client := NewDCLEventarcClient(config, config.userAgent, billingProject, 0) + _, err := client.GetGoogleChannelConfig(context.Background(), obj) + if err == nil { + return fmt.Errorf("google_eventarc_google_channel_config still exists %v", obj) + } + } + return nil + } +} diff --git a/website/docs/r/eventarc_google_channel_config.html.markdown b/website/docs/r/eventarc_google_channel_config.html.markdown new file mode 100644 index 00000000000..2b4b4849601 --- /dev/null +++ b/website/docs/r/eventarc_google_channel_config.html.markdown @@ -0,0 +1,116 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: DCL *** +# +# ---------------------------------------------------------------------------- +# +# This file is managed by Magic Modules (https:#github.com/GoogleCloudPlatform/magic-modules) +# and is based on the DCL (https:#github.com/GoogleCloudPlatform/declarative-resource-client-library). +# Changes will need to be made to the DCL or Magic Modules instead of here. +# +# We are not currently able to accept contributions to this file. If changes +# are required, please file an issue at https:#github.com/hashicorp/terraform-provider-google/issues/new/choose +# +# ---------------------------------------------------------------------------- +subcategory: "Eventarc" +page_title: "Google: google_eventarc_google_channel_config" +description: |- + The Eventarc GoogleChannelConfig resource +--- + +# google_eventarc_google_channel_config + +The Eventarc GoogleChannelConfig resource + +## Example Usage - basic +```hcl +data "google_project" "test_project" { + project_id = "my-project-name" +} + +data "google_kms_key_ring" "test_key_ring" { + name = "keyring" + location = "us-west1" +} + +data "google_kms_crypto_key" "key" { + name = "key" + key_ring = data.google_kms_key_ring.test_key_ring.id +} + +resource "google_kms_crypto_key_iam_binding" "key1_binding" { + crypto_key_id = data.google_kms_crypto_key.key1.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + + members = [ + "serviceAccount:service-${data.google_project.test_project.number}@gcp-sa-eventarc.iam.gserviceaccount.com", + ] +} + +resource "google_eventarc_google_channel_config" "primary" { + location = "us-west1" + name = "channel" + project = "${data.google_project.test_project.project_id}" + crypto_key_name = "${data.google_kms_crypto_key.key1.id}" + third_party_provider = "projects/${data.google_project.test_project.project_id}/locations/us-west1/providers/datadog" + depends_on = [google_kms_crypto_key_iam_binding.key1_binding] +} +``` + +## Argument Reference + +The following arguments are supported: + +* `location` - + (Required) + The location for the resource + +* `name` - + (Required) + Required. The resource name of the config. Must be in the format of, `projects/{project}/locations/{location}/googleChannelConfig`. + + + +- - - + +* `crypto_key_name` - + (Optional) + Optional. Resource name of a KMS crypto key (managed by the user) used to encrypt/decrypt their event data. It must match the pattern `projects/*/locations/*/keyRings/*/cryptoKeys/*`. + +* `project` - + (Optional) + The project for the resource + + + +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are exported: + +* `id` - an identifier for the resource with format `projects/{{project}}/locations/{{location}}/googleChannelConfig` + +* `update_time` - + Output only. The last-modified time. + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 20 minutes. +- `update` - Default is 20 minutes. +- `delete` - Default is 20 minutes. + +## Import + +GoogleChannelConfig can be imported using any of these accepted formats: + +``` +$ terraform import google_eventarc_google_channel_config.default projects/{{project}}/locations/{{location}}/googleChannelConfig +$ terraform import google_eventarc_google_channel_config.default {{project}}/{{location}} +$ terraform import google_eventarc_google_channel_config.default {{location}} +``` + + +