From 0bc1ca800e59a686955c0a9a0d1ef3e40d6774da Mon Sep 17 00:00:00 2001 From: Yanwei Guo Date: Fri, 15 Sep 2023 12:58:11 -0700 Subject: [PATCH] Adds Direct VPC egress support for Cloud Run V2 resources (#8932) --- mmv1/products/cloudrunv2/Job.yaml | 33 +++++++ mmv1/products/cloudrunv2/Service.yaml | 34 +++++++ .../examples/cloudrunv2_job_directvpc.tf.erb | 26 +++++ .../cloudrunv2_service_directvpc.tf.erb | 18 ++++ .../resource_cloud_run_v2_job_test.go | 94 +++++++++++++++++++ .../resource_cloud_run_v2_service_test.go | 76 +++++++++++++++ 6 files changed, 281 insertions(+) create mode 100644 mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb create mode 100644 mmv1/templates/terraform/examples/cloudrunv2_service_directvpc.tf.erb diff --git a/mmv1/products/cloudrunv2/Job.yaml b/mmv1/products/cloudrunv2/Job.yaml index d484d5e717c6..64fe831df7e9 100644 --- a/mmv1/products/cloudrunv2/Job.yaml +++ b/mmv1/products/cloudrunv2/Job.yaml @@ -84,6 +84,13 @@ examples: vpc_access_connector_name: 'run-vpc' vpc_compute_subnetwork_name: 'run-subnetwork' compute_network_name: 'run-network' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudrunv2_job_directvpc' + primary_resource_id: 'default' + primary_resource_name: "fmt.Sprintf(\"tf-test-cloudrun-job%s\", context[\"random_suffix\"\ + ])" + vars: + cloud_run_job_name: 'cloudrun-job' - !ruby/object:Provider::Terraform::Examples name: 'cloudrunv2_job_secret' primary_resource_id: 'default' @@ -645,6 +652,32 @@ properties: values: - :ALL_TRAFFIC - :PRIVATE_RANGES_ONLY + default_from_api: true + - !ruby/object:Api::Type::Array + name: 'networkInterfaces' + description: |- + Direct VPC egress settings. Currently only single network interface is supported. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'network' + 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. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'subnetwork' + 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. + default_from_api: true + - !ruby/object:Api::Type::Array + name: 'tags' + description: |- + Network tags applied to this Cloud Run job. + item_type: Api::Type::String - !ruby/object:Api::Type::Integer name: 'maxRetries' description: |- diff --git a/mmv1/products/cloudrunv2/Service.yaml b/mmv1/products/cloudrunv2/Service.yaml index ae586f92dabe..e51b29c9d7e2 100644 --- a/mmv1/products/cloudrunv2/Service.yaml +++ b/mmv1/products/cloudrunv2/Service.yaml @@ -87,6 +87,14 @@ examples: vpc_access_connector_name: 'run-vpc' vpc_compute_subnetwork_name: 'run-subnetwork' compute_network_name: 'run-network' + - !ruby/object:Provider::Terraform::Examples + name: 'cloudrunv2_service_directvpc' + primary_resource_id: 'default' + primary_resource_name: "fmt.Sprintf(\"tf-test-cloudrun-srv%s\", + context[\"random_suffix\"\ + ])" + vars: + cloud_run_service_name: 'cloudrun-service' - !ruby/object:Provider::Terraform::Examples name: 'cloudrunv2_service_probes' primary_resource_id: 'default' @@ -301,6 +309,32 @@ properties: values: - :ALL_TRAFFIC - :PRIVATE_RANGES_ONLY + default_from_api: true + - !ruby/object:Api::Type::Array + name: 'networkInterfaces' + description: |- + Direct VPC egress settings. Currently only single network interface is supported. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'network' + 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. + default_from_api: true + - !ruby/object:Api::Type::String + name: 'subnetwork' + 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. + default_from_api: true + - !ruby/object:Api::Type::Array + name: 'tags' + description: |- + Network tags applied to this Cloud Run service. + item_type: Api::Type::String - !ruby/object:Api::Type::String name: 'timeout' description: |- diff --git a/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb new file mode 100644 index 000000000000..a28913e7fc13 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudrunv2_job_directvpc.tf.erb @@ -0,0 +1,26 @@ +resource "google_cloud_run_v2_job" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['cloud_run_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" + subnetwork = "default" + tags = ["tag1", "tag2", "tag3"] + } + egress = "ALL_TRAFFIC" + } + } + } + + lifecycle { + ignore_changes = [ + launch_stage, + ] + } +} diff --git a/mmv1/templates/terraform/examples/cloudrunv2_service_directvpc.tf.erb b/mmv1/templates/terraform/examples/cloudrunv2_service_directvpc.tf.erb new file mode 100644 index 000000000000..626c979b98d7 --- /dev/null +++ b/mmv1/templates/terraform/examples/cloudrunv2_service_directvpc.tf.erb @@ -0,0 +1,18 @@ +resource "google_cloud_run_v2_service" "<%= ctx[:primary_resource_id] %>" { + name = "<%= ctx[:vars]['cloud_run_service_name'] %>" + 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" + } + } +} diff --git a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go index a874e89e16ff..6b35cff4101e 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_job_test.go @@ -1,6 +1,7 @@ package cloudrunv2_test import ( + "fmt" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -204,3 +205,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/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go index 00ddd0472239..803446aaf7ba 100644 --- a/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go +++ b/mmv1/third_party/terraform/services/cloudrunv2/resource_cloud_run_v2_service_test.go @@ -590,3 +590,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) +}