Skip to content

Commit

Permalink
Adds Direct VPC egress support for Cloud Run V2 resources (#8932) (#6287
Browse files Browse the repository at this point in the history
)

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Sep 15, 2023
1 parent 1986749 commit de48ec0
Show file tree
Hide file tree
Showing 9 changed files with 638 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .changelog/8932.txt
Original file line number Diff line number Diff line change
@@ -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.
```
123 changes: 123 additions & 0 deletions google-beta/services/cloudrunv2/resource_cloud_run_v2_job.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
},
},
},
},
},
},
},
Expand Down Expand Up @@ -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{} {
Expand All @@ -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 {
Expand Down Expand Up @@ -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
}

Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
94 changes: 94 additions & 0 deletions google-beta/services/cloudrunv2/resource_cloud_run_v2_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package cloudrunv2_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
Expand Down Expand Up @@ -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)
}
Loading

0 comments on commit de48ec0

Please sign in to comment.