From de48ec083d7f163eae53774a6cfd7b5ed8090479 Mon Sep 17 00:00:00 2001 From: The Magician Date: Fri, 15 Sep 2023 16:01:39 -0400 Subject: [PATCH] Adds Direct VPC egress support for Cloud Run V2 resources (#8932) (#6287) Signed-off-by: Modular Magician --- .changelog/8932.txt | 6 + .../cloudrunv2/resource_cloud_run_v2_job.go | 123 ++++++++++++++++++ ...esource_cloud_run_v2_job_generated_test.go | 56 ++++++++ .../resource_cloud_run_v2_job_test.go | 94 +++++++++++++ .../resource_cloud_run_v2_service.go | 123 ++++++++++++++++++ ...rce_cloud_run_v2_service_generated_test.go | 48 +++++++ .../resource_cloud_run_v2_service_test.go | 76 +++++++++++ website/docs/r/cloud_run_v2_job.html.markdown | 60 +++++++++ .../docs/r/cloud_run_v2_service.html.markdown | 52 ++++++++ 9 files changed, 638 insertions(+) create mode 100644 .changelog/8932.txt diff --git a/.changelog/8932.txt b/.changelog/8932.txt new file mode 100644 index 0000000000..3ee0f9d218 --- /dev/null +++ b/.changelog/8932.txt @@ -0,0 +1,6 @@ +```release-note:enhancement +cloudrunv2: added fields `network_interfaces` to resource `google_cloud_run_v2_job` to support Direct VPC egress. +``` +```release-note:enhancement +cloudrunv2: added fields `network_interfaces` to resource `google_cloud_run_v2_service` to support Direct VPC egress. +``` diff --git a/google-beta/services/cloudrunv2/resource_cloud_run_v2_job.go b/google-beta/services/cloudrunv2/resource_cloud_run_v2_job.go index 941e1048a5..6fca5d0eba 100644 --- a/google-beta/services/cloudrunv2/resource_cloud_run_v2_job.go +++ b/google-beta/services/cloudrunv2/resource_cloud_run_v2_job.go @@ -537,10 +537,44 @@ A duration in seconds with up to nine fractional digits, ending with 's'. Exampl }, "egress": { Type: schema.TypeString, + Computed: true, Optional: true, ValidateFunc: verify.ValidateEnum([]string{"ALL_TRAFFIC", "PRIVATE_RANGES_ONLY", ""}), Description: `Traffic VPC egress settings. Possible values: ["ALL_TRAFFIC", "PRIVATE_RANGES_ONLY"]`, }, + "network_interfaces": { + Type: schema.TypeList, + Optional: true, + Description: `Direct VPC egress settings. Currently only single network interface is supported.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The VPC network that the Cloud Run resource will be able to send traffic to. At least one of network or subnetwork must be specified. If both +network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If network is not specified, it will be +looked up from the subnetwork.`, + }, + "subnetwork": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The VPC subnetwork that the Cloud Run resource will get IPs from. At least one of network or subnetwork must be specified. If both +network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If subnetwork is not specified, the +subnetwork with the same name with the network will be used.`, + }, + "tags": { + Type: schema.TypeList, + Optional: true, + Description: `Network tags applied to this Cloud Run job.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, }, }, }, @@ -2114,6 +2148,8 @@ func flattenCloudRunV2JobTemplateTemplateVpcAccess(v interface{}, d *schema.Reso flattenCloudRunV2JobTemplateTemplateVpcAccessConnector(original["connector"], d, config) transformed["egress"] = flattenCloudRunV2JobTemplateTemplateVpcAccessEgress(original["egress"], d, config) + transformed["network_interfaces"] = + flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfaces(original["networkInterfaces"], d, config) return []interface{}{transformed} } func flattenCloudRunV2JobTemplateTemplateVpcAccessConnector(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -2124,6 +2160,38 @@ func flattenCloudRunV2JobTemplateTemplateVpcAccessEgress(v interface{}, d *schem return v } +func flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfaces(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": flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesNetwork(original["network"], d, config), + "subnetwork": flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesSubnetwork(original["subnetwork"], d, config), + "tags": flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesTags(original["tags"], d, config), + }) + } + return transformed +} +func flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesTags(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenCloudRunV2JobTemplateTemplateMaxRetries(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { // Handles the string fixed64 format if strVal, ok := v.(string); ok { @@ -3413,6 +3481,13 @@ func expandCloudRunV2JobTemplateTemplateVpcAccess(v interface{}, d tpgresource.T transformed["egress"] = transformedEgress } + transformedNetworkInterfaces, err := expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfaces(original["network_interfaces"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkInterfaces); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["networkInterfaces"] = transformedNetworkInterfaces + } + return transformed, nil } @@ -3424,6 +3499,54 @@ func expandCloudRunV2JobTemplateTemplateVpcAccessEgress(v interface{}, d tpgreso return v, nil } +func expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfaces(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{}) + + transformedNetwork, err := expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedSubnetwork, err := expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesSubnetwork(original["subnetwork"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["subnetwork"] = transformedSubnetwork + } + + transformedTags, err := expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesTags(original["tags"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTags); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["tags"] = transformedTags + } + + req = append(req, transformed) + } + return req, nil +} + +func expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandCloudRunV2JobTemplateTemplateVpcAccessNetworkInterfacesTags(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandCloudRunV2JobTemplateTemplateMaxRetries(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_generated_test.go b/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_generated_test.go index 27abbd080c..8ab3fcc8cf 100644 --- a/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_generated_test.go +++ b/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_generated_test.go @@ -258,6 +258,62 @@ resource "google_compute_network" "custom_test" { `, context) } +func TestAccCloudRunV2Job_cloudrunv2JobDirectvpcExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Job_cloudrunv2JobDirectvpcExample(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccCloudRunV2Job_cloudrunv2JobDirectvpcExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_job" "default" { + name = "tf-test-cloudrun-job%{random_suffix}" + location = "us-central1" + launch_stage = "BETA" + template { + template{ + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + vpc_access { + network_interfaces { + network = "default" + subnetwork = "default" + tags = ["tag1", "tag2", "tag3"] + } + egress = "ALL_TRAFFIC" + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } +} +`, context) +} + func TestAccCloudRunV2Job_cloudrunv2JobSecretExample(t *testing.T) { t.Parallel() diff --git a/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_test.go b/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_test.go index 254e9d2ade..ebcb843013 100644 --- a/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_test.go +++ b/google-beta/services/cloudrunv2/resource_cloud_run_v2_job_test.go @@ -3,6 +3,7 @@ package cloudrunv2_test import ( + "fmt" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -206,3 +207,96 @@ resource "google_compute_network" "custom_test" { } `, context) } + +func TestAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(t *testing.T) { + t.Parallel() + + jobName := fmt.Sprintf("tf-test-cloudrun-service%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "job_name": jobName, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2JobDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithDirectVPC(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + { + Config: testAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(context), + }, + { + ResourceName: "google_cloud_run_v2_job.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"location", "launch_stage"}, + }, + }, + }) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithDirectVPC(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + vpc_access { + network_interfaces { + network = "default" + } + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } + } +`, context) +} + +func testAccCloudRunV2Job_cloudrunv2JobWithDirectVPCUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` + resource "google_cloud_run_v2_job" "default" { + name = "%{job_name}" + location = "us-central1" + launch_stage = "BETA" + template { + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + vpc_access { + network_interfaces { + network = "my-network" + subnetwork = "my-network" + tags = ["tag1", "tag2", "tag3"] + } + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } + } +`, context) +} diff --git a/google-beta/services/cloudrunv2/resource_cloud_run_v2_service.go b/google-beta/services/cloudrunv2/resource_cloud_run_v2_service.go index 90fbb0e73a..b4e0aad63f 100644 --- a/google-beta/services/cloudrunv2/resource_cloud_run_v2_service.go +++ b/google-beta/services/cloudrunv2/resource_cloud_run_v2_service.go @@ -661,10 +661,44 @@ A duration in seconds with up to nine fractional digits, ending with 's'. Exampl }, "egress": { Type: schema.TypeString, + Computed: true, Optional: true, ValidateFunc: verify.ValidateEnum([]string{"ALL_TRAFFIC", "PRIVATE_RANGES_ONLY", ""}), Description: `Traffic VPC egress settings. Possible values: ["ALL_TRAFFIC", "PRIVATE_RANGES_ONLY"]`, }, + "network_interfaces": { + Type: schema.TypeList, + Optional: true, + Description: `Direct VPC egress settings. Currently only single network interface is supported.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The VPC network that the Cloud Run resource will be able to send traffic to. At least one of network or subnetwork must be specified. If both +network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If network is not specified, it will be +looked up from the subnetwork.`, + }, + "subnetwork": { + Type: schema.TypeString, + Computed: true, + Optional: true, + Description: `The VPC subnetwork that the Cloud Run resource will get IPs from. At least one of network or subnetwork must be specified. If both +network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If subnetwork is not specified, the +subnetwork with the same name with the network will be used.`, + }, + "tags": { + Type: schema.TypeList, + Optional: true, + Description: `Network tags applied to this Cloud Run service.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, }, }, }, @@ -1672,6 +1706,8 @@ func flattenCloudRunV2ServiceTemplateVpcAccess(v interface{}, d *schema.Resource flattenCloudRunV2ServiceTemplateVpcAccessConnector(original["connector"], d, config) transformed["egress"] = flattenCloudRunV2ServiceTemplateVpcAccessEgress(original["egress"], d, config) + transformed["network_interfaces"] = + flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfaces(original["networkInterfaces"], d, config) return []interface{}{transformed} } func flattenCloudRunV2ServiceTemplateVpcAccessConnector(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -1682,6 +1718,38 @@ func flattenCloudRunV2ServiceTemplateVpcAccessEgress(v interface{}, d *schema.Re return v } +func flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfaces(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": flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesNetwork(original["network"], d, config), + "subnetwork": flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesSubnetwork(original["subnetwork"], d, config), + "tags": flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesTags(original["tags"], d, config), + }) + } + return transformed +} +func flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesTags(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenCloudRunV2ServiceTemplateTimeout(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { return v } @@ -3021,6 +3089,13 @@ func expandCloudRunV2ServiceTemplateVpcAccess(v interface{}, d tpgresource.Terra transformed["egress"] = transformedEgress } + transformedNetworkInterfaces, err := expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfaces(original["network_interfaces"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetworkInterfaces); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["networkInterfaces"] = transformedNetworkInterfaces + } + return transformed, nil } @@ -3032,6 +3107,54 @@ func expandCloudRunV2ServiceTemplateVpcAccessEgress(v interface{}, d tpgresource return v, nil } +func expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfaces(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{}) + + transformedNetwork, err := expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedSubnetwork, err := expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesSubnetwork(original["subnetwork"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["subnetwork"] = transformedSubnetwork + } + + transformedTags, err := expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesTags(original["tags"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTags); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["tags"] = transformedTags + } + + req = append(req, transformed) + } + return req, nil +} + +func expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandCloudRunV2ServiceTemplateVpcAccessNetworkInterfacesTags(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandCloudRunV2ServiceTemplateTimeout(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } diff --git a/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_generated_test.go b/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_generated_test.go index 69654603b4..6919ca90ae 100644 --- a/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_generated_test.go +++ b/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_generated_test.go @@ -246,6 +246,54 @@ resource "google_compute_network" "custom_test" { `, context) } +func TestAccCloudRunV2Service_cloudrunv2ServiceDirectvpcExample(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2ServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Service_cloudrunv2ServiceDirectvpcExample(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccCloudRunV2Service_cloudrunv2ServiceDirectvpcExample(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "tf-test-cloudrun-service%{random_suffix}" + location = "us-central1" + launch_stage = "BETA" + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + vpc_access{ + network_interfaces { + network = "default" + subnetwork = "default" + tags = ["tag1", "tag2", "tag3"] + } + egress = "ALL_TRAFFIC" + } + } +} +`, context) +} + func TestAccCloudRunV2Service_cloudrunv2ServiceProbesExample(t *testing.T) { t.Parallel() diff --git a/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_test.go b/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_test.go index edab5f73f2..7b8bafcf9a 100644 --- a/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_test.go +++ b/google-beta/services/cloudrunv2/resource_cloud_run_v2_service_test.go @@ -592,3 +592,79 @@ resource "google_cloud_run_v2_service" "default" { } `, context) } + +func TestAccCloudRunV2Service_cloudrunv2ServiceWithDirectVPCUpdate(t *testing.T) { + t.Parallel() + + serviceName := fmt.Sprintf("tf-test-cloudrun-service%s", acctest.RandString(t, 10)) + context := map[string]interface{}{ + "service_name": serviceName, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckCloudRunV2ServiceDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccCloudRunV2Service_cloudRunServiceWithDirectVPC(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + { + Config: testAccCloudRunV2Service_cloudRunServiceWithDirectVPCUpdate(context), + }, + { + ResourceName: "google_cloud_run_v2_service.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"name", "location"}, + }, + }, + }) +} + +func testAccCloudRunV2Service_cloudRunServiceWithDirectVPC(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "%{service_name}" + location = "us-central1" + launch_stage = "BETA" + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + vpc_access { + network_interfaces { + network = "default" + } + } + } +} +`, context) +} + +func testAccCloudRunV2Service_cloudRunServiceWithDirectVPCUpdate(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_cloud_run_v2_service" "default" { + name = "%{service_name}" + location = "us-central1" + launch_stage = "BETA" + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + vpc_access { + network_interfaces { + subnetwork = "default" + tags = ["foo", "bar"] + } + } + } +} +`, context) +} diff --git a/website/docs/r/cloud_run_v2_job.html.markdown b/website/docs/r/cloud_run_v2_job.html.markdown index 95d71dda83..95e4a5e77c 100644 --- a/website/docs/r/cloud_run_v2_job.html.markdown +++ b/website/docs/r/cloud_run_v2_job.html.markdown @@ -195,6 +195,42 @@ resource "google_compute_network" "custom_test" { auto_create_subnetworks = false } ``` + +## Example Usage - Cloudrunv2 Job Directvpc + + +```hcl +resource "google_cloud_run_v2_job" "default" { + name = "cloudrun-job" + location = "us-central1" + launch_stage = "BETA" + template { + template{ + containers { + image = "us-docker.pkg.dev/cloudrun/container/job" + } + vpc_access { + network_interfaces { + network = "default" + subnetwork = "default" + tags = ["tag1", "tag2", "tag3"] + } + egress = "ALL_TRAFFIC" + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } +} +```
Open in Cloud Shell @@ -708,6 +744,30 @@ The following arguments are supported: Traffic VPC egress settings. Possible values are: `ALL_TRAFFIC`, `PRIVATE_RANGES_ONLY`. +* `network_interfaces` - + (Optional) + Direct VPC egress settings. Currently only single network interface is supported. + Structure is [documented below](#nested_network_interfaces). + + +The `network_interfaces` block supports: + +* `network` - + (Optional) + The VPC network that the Cloud Run resource will be able to send traffic to. At least one of network or subnetwork must be specified. If both + network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If network is not specified, it will be + looked up from the subnetwork. + +* `subnetwork` - + (Optional) + The VPC subnetwork that the Cloud Run resource will get IPs from. At least one of network or subnetwork must be specified. If both + network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If subnetwork is not specified, the + subnetwork with the same name with the network will be used. + +* `tags` - + (Optional) + Network tags applied to this Cloud Run job. + - - - diff --git a/website/docs/r/cloud_run_v2_service.html.markdown b/website/docs/r/cloud_run_v2_service.html.markdown index 33ea6c12fc..1379a5ffd1 100644 --- a/website/docs/r/cloud_run_v2_service.html.markdown +++ b/website/docs/r/cloud_run_v2_service.html.markdown @@ -183,6 +183,34 @@ resource "google_compute_network" "custom_test" { auto_create_subnetworks = false } ``` + +## Example Usage - Cloudrunv2 Service Directvpc + + +```hcl +resource "google_cloud_run_v2_service" "default" { + name = "cloudrun-service" + location = "us-central1" + launch_stage = "BETA" + template { + containers { + image = "us-docker.pkg.dev/cloudrun/container/hello" + } + vpc_access{ + network_interfaces { + network = "default" + subnetwork = "default" + tags = ["tag1", "tag2", "tag3"] + } + egress = "ALL_TRAFFIC" + } + } +} +```
Open in Cloud Shell @@ -428,6 +456,30 @@ The following arguments are supported: Traffic VPC egress settings. Possible values are: `ALL_TRAFFIC`, `PRIVATE_RANGES_ONLY`. +* `network_interfaces` - + (Optional) + Direct VPC egress settings. Currently only single network interface is supported. + Structure is [documented below](#nested_network_interfaces). + + +The `network_interfaces` block supports: + +* `network` - + (Optional) + The VPC network that the Cloud Run resource will be able to send traffic to. At least one of network or subnetwork must be specified. If both + network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If network is not specified, it will be + looked up from the subnetwork. + +* `subnetwork` - + (Optional) + The VPC subnetwork that the Cloud Run resource will get IPs from. At least one of network or subnetwork must be specified. If both + network and subnetwork are specified, the given VPC subnetwork must belong to the given VPC network. If subnetwork is not specified, the + subnetwork with the same name with the network will be used. + +* `tags` - + (Optional) + Network tags applied to this Cloud Run service. + The `containers` block supports: * `name` -