diff --git a/.changelog/6275.txt b/.changelog/6275.txt new file mode 100644 index 0000000000..e020f51be2 --- /dev/null +++ b/.changelog/6275.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +compute: Added `network` and `subnetwork` fields to `google_compute_region_network_endpoint_group` for PSC. +``` diff --git a/google-beta/resource_compute_region_network_endpoint_group.go b/google-beta/resource_compute_region_network_endpoint_group.go index b74616faf5..12f0eab80a 100644 --- a/google-beta/resource_compute_region_network_endpoint_group.go +++ b/google-beta/resource_compute_region_network_endpoint_group.go @@ -187,6 +187,15 @@ and { service="bar2", tag="foo2" } respectively.`, ForceNew: true, Description: `An optional description of this resource. Provide this property when you create the resource.`, + }, + "network": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `This field is only used for PSC. +The URL of the network to which all network endpoints in the NEG belong. Uses +"default" project network if unspecified.`, }, "network_endpoint_type": { Type: schema.TypeString, @@ -247,6 +256,14 @@ API Gateway: Unused, App Engine: The service version, Cloud Functions: Unused, C }, ConflictsWith: []string{"cloud_run", "cloud_function", "app_engine"}, }, + "subnetwork": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + DiffSuppressFunc: compareSelfLinkOrResourceName, + Description: `This field is only used for PSC. +Optional URL of the subnetwork to which all network endpoints in the NEG belong.`, + }, "project": { Type: schema.TypeString, Optional: true, @@ -294,6 +311,18 @@ func resourceComputeRegionNetworkEndpointGroupCreate(d *schema.ResourceData, met } else if v, ok := d.GetOkExists("psc_target_service"); !isEmptyValue(reflect.ValueOf(pscTargetServiceProp)) && (ok || !reflect.DeepEqual(v, pscTargetServiceProp)) { obj["pscTargetService"] = pscTargetServiceProp } + networkProp, err := expandComputeRegionNetworkEndpointGroupNetwork(d.Get("network"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("network"); !isEmptyValue(reflect.ValueOf(networkProp)) && (ok || !reflect.DeepEqual(v, networkProp)) { + obj["network"] = networkProp + } + subnetworkProp, err := expandComputeRegionNetworkEndpointGroupSubnetwork(d.Get("subnetwork"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("subnetwork"); !isEmptyValue(reflect.ValueOf(subnetworkProp)) && (ok || !reflect.DeepEqual(v, subnetworkProp)) { + obj["subnetwork"] = subnetworkProp + } cloudRunProp, err := expandComputeRegionNetworkEndpointGroupCloudRun(d.Get("cloud_run"), d, config) if err != nil { return err @@ -417,6 +446,12 @@ func resourceComputeRegionNetworkEndpointGroupRead(d *schema.ResourceData, meta if err := d.Set("psc_target_service", flattenComputeRegionNetworkEndpointGroupPscTargetService(res["pscTargetService"], d, config)); err != nil { return fmt.Errorf("Error reading RegionNetworkEndpointGroup: %s", err) } + if err := d.Set("network", flattenComputeRegionNetworkEndpointGroupNetwork(res["network"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionNetworkEndpointGroup: %s", err) + } + if err := d.Set("subnetwork", flattenComputeRegionNetworkEndpointGroupSubnetwork(res["subnetwork"], d, config)); err != nil { + return fmt.Errorf("Error reading RegionNetworkEndpointGroup: %s", err) + } if err := d.Set("cloud_run", flattenComputeRegionNetworkEndpointGroupCloudRun(res["cloudRun"], d, config)); err != nil { return fmt.Errorf("Error reading RegionNetworkEndpointGroup: %s", err) } @@ -521,6 +556,20 @@ func flattenComputeRegionNetworkEndpointGroupPscTargetService(v interface{}, d * return v } +func flattenComputeRegionNetworkEndpointGroupNetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + +func flattenComputeRegionNetworkEndpointGroupSubnetwork(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return ConvertSelfLinkToV1(v.(string)) +} + func flattenComputeRegionNetworkEndpointGroupCloudRun(v interface{}, d *schema.ResourceData, config *Config) interface{} { if v == nil { return nil @@ -654,6 +703,22 @@ func expandComputeRegionNetworkEndpointGroupPscTargetService(v interface{}, d Te return v, nil } +func expandComputeRegionNetworkEndpointGroupNetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + f, err := parseGlobalFieldValue("networks", v.(string), "project", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for network: %s", err) + } + return f.RelativeLink(), nil +} + +func expandComputeRegionNetworkEndpointGroupSubnetwork(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + f, err := parseRegionalFieldValue("subnetworks", v.(string), "project", "region", "zone", d, config, true) + if err != nil { + return nil, fmt.Errorf("Invalid value for subnetwork: %s", err) + } + return f.RelativeLink(), nil +} + func expandComputeRegionNetworkEndpointGroupCloudRun(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google-beta/resource_compute_region_network_endpoint_group_generated_test.go b/google-beta/resource_compute_region_network_endpoint_group_generated_test.go index ac7be93192..3fdf91df4b 100644 --- a/google-beta/resource_compute_region_network_endpoint_group_generated_test.go +++ b/google-beta/resource_compute_region_network_endpoint_group_generated_test.go @@ -43,7 +43,7 @@ func TestAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupFunction ResourceName: "google_compute_region_network_endpoint_group.function_neg", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region"}, + ImportStateVerifyIgnore: []string{"network", "subnetwork", "region"}, }, }, }) @@ -106,7 +106,7 @@ func TestAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupCloudrun ResourceName: "google_compute_region_network_endpoint_group.cloudrun_neg", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region"}, + ImportStateVerifyIgnore: []string{"network", "subnetwork", "region"}, }, }, }) @@ -163,7 +163,7 @@ func TestAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupAppengin ResourceName: "google_compute_region_network_endpoint_group.appengine_neg", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region"}, + ImportStateVerifyIgnore: []string{"network", "subnetwork", "region"}, }, }, }) @@ -263,7 +263,7 @@ func TestAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupPscExamp ResourceName: "google_compute_region_network_endpoint_group.psc_neg", ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"region"}, + ImportStateVerifyIgnore: []string{"network", "subnetwork", "region"}, }, }, }) @@ -281,6 +281,103 @@ resource "google_compute_region_network_endpoint_group" "psc_neg" { `, context) } +func TestAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupPscServiceAttachmentExample(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: testAccCheckComputeRegionNetworkEndpointGroupDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupPscServiceAttachmentExample(context), + }, + { + ResourceName: "google_compute_region_network_endpoint_group.psc_neg_service_attachment", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"network", "subnetwork", "region"}, + }, + }, + }) +} + +func testAccComputeRegionNetworkEndpointGroup_regionNetworkEndpointGroupPscServiceAttachmentExample(context map[string]interface{}) string { + return Nprintf(` +resource "google_compute_network" "default" { + name = "tf-test-psc-network%{random_suffix}" +} + +resource "google_compute_subnetwork" "default" { + name = "tf-test-psc-subnetwork%{random_suffix}" + ip_cidr_range = "10.0.0.0/16" + region = "europe-west4" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "psc_subnetwork" { + name = "tf-test-psc-subnetwork-nat%{random_suffix}" + ip_cidr_range = "10.1.0.0/16" + region = "europe-west4" + purpose = "PRIVATE_SERVICE_CONNECT" + network = google_compute_network.default.id +} + +resource "google_compute_health_check" "default" { + name = "tf-test-psc-healthcheck%{random_suffix}" + + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } +} +resource "google_compute_region_backend_service" "default" { + name = "tf-test-psc-backend%{random_suffix}" + region = "europe-west4" + + health_checks = [google_compute_health_check.default.id] +} + +resource "google_compute_forwarding_rule" "default" { + name = "tf-test-psc-forwarding-rule%{random_suffix}" + region = "europe-west4" + + load_balancing_scheme = "INTERNAL" + backend_service = google_compute_region_backend_service.default.id + all_ports = true + network = google_compute_network.default.name + subnetwork = google_compute_subnetwork.default.name +} + +resource "google_compute_service_attachment" "default" { + name = "tf-test-psc-service-attachment%{random_suffix}" + region = "europe-west4" + description = "A service attachment configured with Terraform" + + enable_proxy_protocol = false + connection_preference = "ACCEPT_AUTOMATIC" + nat_subnets = [google_compute_subnetwork.psc_subnetwork.self_link] + target_service = google_compute_forwarding_rule.default.self_link +} + +resource "google_compute_region_network_endpoint_group" "psc_neg_service_attachment" { + name = "tf-test-psc-neg%{random_suffix}" + region = "europe-west4" + + network_endpoint_type = "PRIVATE_SERVICE_CONNECT" + psc_target_service = google_compute_service_attachment.default.self_link + + network = google_compute_network.default.self_link + subnetwork = google_compute_subnetwork.default.self_link +} +`, context) +} + func testAccCheckComputeRegionNetworkEndpointGroupDestroyProducer(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/compute_region_network_endpoint_group.html.markdown b/website/docs/r/compute_region_network_endpoint_group.html.markdown index 8deac9f44d..4fdd64e275 100644 --- a/website/docs/r/compute_region_network_endpoint_group.html.markdown +++ b/website/docs/r/compute_region_network_endpoint_group.html.markdown @@ -210,6 +210,83 @@ resource "google_compute_region_network_endpoint_group" "psc_neg" { psc_target_service = "asia-northeast3-cloudkms.googleapis.com" } ``` +
+ + Open in Cloud Shell + +
+## Example Usage - Region Network Endpoint Group Psc Service Attachment + + +```hcl +resource "google_compute_network" "default" { + name = "psc-network" +} + +resource "google_compute_subnetwork" "default" { + name = "psc-subnetwork" + ip_cidr_range = "10.0.0.0/16" + region = "europe-west4" + network = google_compute_network.default.id +} + +resource "google_compute_subnetwork" "psc_subnetwork" { + name = "psc-subnetwork-nat" + ip_cidr_range = "10.1.0.0/16" + region = "europe-west4" + purpose = "PRIVATE_SERVICE_CONNECT" + network = google_compute_network.default.id +} + +resource "google_compute_health_check" "default" { + name = "psc-healthcheck" + + check_interval_sec = 1 + timeout_sec = 1 + tcp_health_check { + port = "80" + } +} +resource "google_compute_region_backend_service" "default" { + name = "psc-backend" + region = "europe-west4" + + health_checks = [google_compute_health_check.default.id] +} + +resource "google_compute_forwarding_rule" "default" { + name = "psc-forwarding-rule" + region = "europe-west4" + + load_balancing_scheme = "INTERNAL" + backend_service = google_compute_region_backend_service.default.id + all_ports = true + network = google_compute_network.default.name + subnetwork = google_compute_subnetwork.default.name +} + +resource "google_compute_service_attachment" "default" { + name = "psc-service-attachment" + region = "europe-west4" + description = "A service attachment configured with Terraform" + + enable_proxy_protocol = false + connection_preference = "ACCEPT_AUTOMATIC" + nat_subnets = [google_compute_subnetwork.psc_subnetwork.self_link] + target_service = google_compute_forwarding_rule.default.self_link +} + +resource "google_compute_region_network_endpoint_group" "psc_neg_service_attachment" { + name = "psc-neg" + region = "europe-west4" + + network_endpoint_type = "PRIVATE_SERVICE_CONNECT" + psc_target_service = google_compute_service_attachment.default.self_link + + network = google_compute_network.default.self_link + subnetwork = google_compute_subnetwork.default.self_link +} +``` ## Argument Reference @@ -250,6 +327,17 @@ The following arguments are supported: The target service url used to set up private service connection to a Google API or a PSC Producer Service Attachment. +* `network` - + (Optional) + This field is only used for PSC. + The URL of the network to which all network endpoints in the NEG belong. Uses + "default" project network if unspecified. + +* `subnetwork` - + (Optional) + This field is only used for PSC. + Optional URL of the subnetwork to which all network endpoints in the NEG belong. + * `cloud_run` - (Optional) Only valid when networkEndpointType is "SERVERLESS".