From aebd0fd9ece3a167bb499a23b855bac4693747af Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Tue, 4 Mar 2025 20:39:33 +0000 Subject: [PATCH] [AlloyDB] PSC Outbound Connectivity Support (#13223) [upstream:5be776873ae9bc044f8a486649321dbd5817625b] Signed-off-by: Modular Magician --- .changelog/13223.txt | 3 + .../alloydb/resource_alloydb_instance.go | 74 +++++++++++++++++ ...ource_alloydb_instance_generated_meta.yaml | 1 + .../alloydb/resource_alloydb_instance_test.go | 81 +++++++++++++++++++ website/docs/r/alloydb_instance.html.markdown | 15 ++++ 5 files changed, 174 insertions(+) create mode 100644 .changelog/13223.txt diff --git a/.changelog/13223.txt b/.changelog/13223.txt new file mode 100644 index 00000000000..d4ed206c06e --- /dev/null +++ b/.changelog/13223.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +alloydb: added `psc_instance_config.psc_interface_configs` field to ``google_alloydb_instance` resource +``` \ No newline at end of file diff --git a/google/services/alloydb/resource_alloydb_instance.go b/google/services/alloydb/resource_alloydb_instance.go index 465c962c771..b80f47f9b59 100644 --- a/google/services/alloydb/resource_alloydb_instance.go +++ b/google/services/alloydb/resource_alloydb_instance.go @@ -240,6 +240,23 @@ These should be specified as project numbers only.`, ValidateFunc: verify.ValidateRegexp(`^\d+$`), }, }, + "psc_interface_configs": { + Type: schema.TypeList, + Optional: true, + Description: `Configurations for setting up PSC interfaces attached to the instance +which are used for outbound connectivity. Currently, AlloyDB supports only 0 or 1 PSC interface.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network_attachment_resource": { + Type: schema.TypeString, + Optional: true, + Description: `The network attachment resource created in the consumer project to which the PSC interface will be linked. +This is of the format: "projects/${CONSUMER_PROJECT}/regions/${REGION}/networkAttachments/${NETWORK_ATTACHMENT_NAME}". +The network attachment must be in the same region as the instance.`, + }, + }, + }, + }, "psc_dns_name": { Type: schema.TypeString, Computed: true, @@ -1147,6 +1164,8 @@ func flattenAlloydbInstancePscInstanceConfig(v interface{}, d *schema.ResourceDa flattenAlloydbInstancePscInstanceConfigAllowedConsumerProjects(original["allowedConsumerProjects"], d, config) transformed["psc_dns_name"] = flattenAlloydbInstancePscInstanceConfigPscDnsName(original["pscDnsName"], d, config) + transformed["psc_interface_configs"] = + flattenAlloydbInstancePscInstanceConfigPscInterfaceConfigs(original["pscInterfaceConfigs"], d, config) return []interface{}{transformed} } func flattenAlloydbInstancePscInstanceConfigServiceAttachmentLink(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -1161,6 +1180,28 @@ func flattenAlloydbInstancePscInstanceConfigPscDnsName(v interface{}, d *schema. return v } +func flattenAlloydbInstancePscInstanceConfigPscInterfaceConfigs(v interface{}, d *schema.ResourceData, config *transport_tpg.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{}{ + "network_attachment_resource": flattenAlloydbInstancePscInstanceConfigPscInterfaceConfigsNetworkAttachmentResource(original["networkAttachmentResource"], d, config), + }) + } + return transformed +} +func flattenAlloydbInstancePscInstanceConfigPscInterfaceConfigsNetworkAttachmentResource(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAlloydbInstanceNetworkConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -1451,6 +1492,13 @@ func expandAlloydbInstancePscInstanceConfig(v interface{}, d tpgresource.Terrafo transformed["pscDnsName"] = transformedPscDnsName } + transformedPscInterfaceConfigs, err := expandAlloydbInstancePscInstanceConfigPscInterfaceConfigs(original["psc_interface_configs"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPscInterfaceConfigs); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["pscInterfaceConfigs"] = transformedPscInterfaceConfigs + } + return transformed, nil } @@ -1466,6 +1514,32 @@ func expandAlloydbInstancePscInstanceConfigPscDnsName(v interface{}, d tpgresour return v, nil } +func expandAlloydbInstancePscInstanceConfigPscInterfaceConfigs(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.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{}) + + transformedNetworkAttachmentResource, err := expandAlloydbInstancePscInstanceConfigPscInterfaceConfigsNetworkAttachmentResource(original["network_attachment_resource"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkAttachmentResource); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["networkAttachmentResource"] = transformedNetworkAttachmentResource + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAlloydbInstancePscInstanceConfigPscInterfaceConfigsNetworkAttachmentResource(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAlloydbInstanceNetworkConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google/services/alloydb/resource_alloydb_instance_generated_meta.yaml b/google/services/alloydb/resource_alloydb_instance_generated_meta.yaml index 44446ad9b22..5460d63786d 100644 --- a/google/services/alloydb/resource_alloydb_instance_generated_meta.yaml +++ b/google/services/alloydb/resource_alloydb_instance_generated_meta.yaml @@ -32,6 +32,7 @@ fields: - field: 'outbound_public_ip_addresses' - field: 'psc_instance_config.allowed_consumer_projects' - field: 'psc_instance_config.psc_dns_name' + - field: 'psc_instance_config.psc_interface_configs.network_attachment_resource' - field: 'psc_instance_config.service_attachment_link' - field: 'public_ip_address' - field: 'query_insights_config.query_plans_per_minute' diff --git a/google/services/alloydb/resource_alloydb_instance_test.go b/google/services/alloydb/resource_alloydb_instance_test.go index 682fe493baa..6a829e6231f 100644 --- a/google/services/alloydb/resource_alloydb_instance_test.go +++ b/google/services/alloydb/resource_alloydb_instance_test.go @@ -829,3 +829,84 @@ resource "google_alloydb_cluster" "default" { data "google_project" "project" {} `, context) } + +func TestAccAlloydbInstance_createInstanceWithPscInterfaceConfigs(t *testing.T) { + t.Parallel() + + networkName := acctest.BootstrapSharedTestNetwork(t, "tf-test-alloydb-network") + subnetworkName := acctest.BootstrapSubnet(t, "tf-test-alloydb-subnetwork", networkName) + + random_suffix := acctest.RandString(t, 10) + context := map[string]interface{}{ + "random_suffix": random_suffix, + "networkAttachmentName": acctest.BootstrapNetworkAttachment(t, "tf-test-alloydb-create-na", subnetworkName), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbInstance_pscInterfaceConfigs(context), + }, + }, + }) +} + +func testAccAlloydbInstance_pscInterfaceConfigs(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_alloydb_instance" "default" { + cluster = google_alloydb_cluster.default.name + instance_id = "tf-test-alloydb-instance%{random_suffix}" + instance_type = "PRIMARY" + machine_config { + cpu_count = 2 + } + psc_instance_config { + allowed_consumer_projects = ["${data.google_project.project.number}"] + psc_interface_configs { + network_attachment_resource = "projects/${data.google_project.project.number}/regions/${google_alloydb_cluster.default.location}/networkAttachments/%{networkAttachmentName}" + } + } +} +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + psc_config { + psc_enabled = true + } + initial_user { + password = "tf-test-alloydb-cluster%{random_suffix}" + } +} +data "google_project" "project" {} +`, context) +} + +func TestAccAlloydbInstance_updateInstanceWithPscInterfaceConfigs(t *testing.T) { + t.Parallel() + + networkName := acctest.BootstrapSharedTestNetwork(t, "tf-test-alloydb-network") + subnetworkName := acctest.BootstrapSubnet(t, "tf-test-alloydb-subnetwork", networkName) + + random_suffix := acctest.RandString(t, 10) + context := map[string]interface{}{ + "random_suffix": random_suffix, + "networkAttachmentName": acctest.BootstrapNetworkAttachment(t, "tf-test-alloydb-update-na", subnetworkName), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbInstanceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbInstance_pscInstanceConfig(context), + }, + { + Config: testAccAlloydbInstance_pscInterfaceConfigs(context), + }, + }, + }) +} diff --git a/website/docs/r/alloydb_instance.html.markdown b/website/docs/r/alloydb_instance.html.markdown index fae53921a7a..166c2ccbbbb 100644 --- a/website/docs/r/alloydb_instance.html.markdown +++ b/website/docs/r/alloydb_instance.html.markdown @@ -367,6 +367,21 @@ The following arguments are supported: The DNS name of the instance for PSC connectivity. Name convention: ...alloydb-psc.goog +* `psc_interface_configs` - + (Optional) + Configurations for setting up PSC interfaces attached to the instance + which are used for outbound connectivity. Currently, AlloyDB supports only 0 or 1 PSC interface. + Structure is [documented below](#nested_psc_instance_config_psc_interface_configs). + + +The `psc_interface_configs` block supports: + +* `network_attachment_resource` - + (Optional) + The network attachment resource created in the consumer project to which the PSC interface will be linked. + This is of the format: "projects/${CONSUMER_PROJECT}/regions/${REGION}/networkAttachments/${NETWORK_ATTACHMENT_NAME}". + The network attachment must be in the same region as the instance. + The `network_config` block supports: * `authorized_external_networks` -