Skip to content

Commit 8f7adb2

Browse files
feat: add support for direct vpc in Cloud Functions v2 beta provider (#15539) (#10971)
[upstream:4debc82de75ec8d994dee3c3de7ecef98280f488] Signed-off-by: Modular Magician <[email protected]>
1 parent 8d17cf4 commit 8f7adb2

File tree

6 files changed

+456
-1
lines changed

6 files changed

+456
-1
lines changed

.changelog/15539.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
cloudfunctions2: added `directVpcNetworkInterface` and `directVpcEgress` field to `google_cloudfunctions2_function` resource
3+
```

google-beta/services/cloudfunctions2/resource_cloudfunctions2_function.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,40 @@ supplied the value is interpreted as bytes.`,
372372
Optional: true,
373373
Description: `The binary authorization policy to be checked when deploying the Cloud Run service.`,
374374
},
375+
"direct_vpc_egress": {
376+
Type: schema.TypeString,
377+
Computed: true,
378+
Optional: true,
379+
ValidateFunc: verify.ValidateEnum([]string{"VPC_EGRESS_ALL_TRAFFIC", "VPC_EGRESS_PRIVATE_RANGES_ONLY", ""}),
380+
Description: `Egress settings for direct VPC. If not provided, it defaults to VPC_EGRESS_PRIVATE_RANGES_ONLY. Possible values: ["VPC_EGRESS_ALL_TRAFFIC", "VPC_EGRESS_PRIVATE_RANGES_ONLY"]`,
381+
},
382+
"direct_vpc_network_interface": {
383+
Type: schema.TypeList,
384+
Optional: true,
385+
Description: `The Direct VPC network interface for the Cloud Function. Currently only a single Direct VPC is supported.`,
386+
Elem: &schema.Resource{
387+
Schema: map[string]*schema.Schema{
388+
"network": {
389+
Type: schema.TypeString,
390+
Optional: true,
391+
Description: `The name of the VPC network to which the function will be connected. Specify either a VPC network or a subnet, or both. If you specify only a network, the subnet uses the same name as the network.`,
392+
},
393+
"subnetwork": {
394+
Type: schema.TypeString,
395+
Optional: true,
396+
Description: `The name of the VPC subnetwork that the Cloud Function resource will get IPs from. Specify either a VPC network or a subnet, or both. 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.`,
397+
},
398+
"tags": {
399+
Type: schema.TypeList,
400+
Optional: true,
401+
Description: `Network tags applied to this Cloud Function resource.`,
402+
Elem: &schema.Schema{
403+
Type: schema.TypeString,
404+
},
405+
},
406+
},
407+
},
408+
},
375409
"environment_variables": {
376410
Type: schema.TypeMap,
377411
Computed: true,
@@ -1280,6 +1314,10 @@ func flattenCloudfunctions2functionServiceConfig(v interface{}, d *schema.Resour
12801314
flattenCloudfunctions2functionServiceConfigVpcConnector(original["vpcConnector"], d, config)
12811315
transformed["vpc_connector_egress_settings"] =
12821316
flattenCloudfunctions2functionServiceConfigVpcConnectorEgressSettings(original["vpcConnectorEgressSettings"], d, config)
1317+
transformed["direct_vpc_network_interface"] =
1318+
flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterface(original["directVpcNetworkInterface"], d, config)
1319+
transformed["direct_vpc_egress"] =
1320+
flattenCloudfunctions2functionServiceConfigDirectVpcEgress(original["directVpcEgress"], d, config)
12831321
transformed["ingress_settings"] =
12841322
flattenCloudfunctions2functionServiceConfigIngressSettings(original["ingressSettings"], d, config)
12851323
transformed["uri"] =
@@ -1390,6 +1428,42 @@ func flattenCloudfunctions2functionServiceConfigVpcConnectorEgressSettings(v int
13901428
return v
13911429
}
13921430

1431+
func flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterface(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1432+
if v == nil {
1433+
return v
1434+
}
1435+
l := v.([]interface{})
1436+
transformed := make([]interface{}, 0, len(l))
1437+
for _, raw := range l {
1438+
original := raw.(map[string]interface{})
1439+
if len(original) < 1 {
1440+
// Do not include empty json objects coming back from the api
1441+
continue
1442+
}
1443+
transformed = append(transformed, map[string]interface{}{
1444+
"network": flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceNetwork(original["network"], d, config),
1445+
"subnetwork": flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceSubnetwork(original["subnetwork"], d, config),
1446+
"tags": flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceTags(original["tags"], d, config),
1447+
})
1448+
}
1449+
return transformed
1450+
}
1451+
func flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1452+
return v
1453+
}
1454+
1455+
func flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1456+
return v
1457+
}
1458+
1459+
func flattenCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceTags(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1460+
return v
1461+
}
1462+
1463+
func flattenCloudfunctions2functionServiceConfigDirectVpcEgress(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1464+
return v
1465+
}
1466+
13931467
func flattenCloudfunctions2functionServiceConfigIngressSettings(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
13941468
return v
13951469
}
@@ -2062,6 +2136,20 @@ func expandCloudfunctions2functionServiceConfig(v interface{}, d tpgresource.Ter
20622136
transformed["vpcConnectorEgressSettings"] = transformedVpcConnectorEgressSettings
20632137
}
20642138

2139+
transformedDirectVpcNetworkInterface, err := expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterface(original["direct_vpc_network_interface"], d, config)
2140+
if err != nil {
2141+
return nil, err
2142+
} else if val := reflect.ValueOf(transformedDirectVpcNetworkInterface); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2143+
transformed["directVpcNetworkInterface"] = transformedDirectVpcNetworkInterface
2144+
}
2145+
2146+
transformedDirectVpcEgress, err := expandCloudfunctions2functionServiceConfigDirectVpcEgress(original["direct_vpc_egress"], d, config)
2147+
if err != nil {
2148+
return nil, err
2149+
} else if val := reflect.ValueOf(transformedDirectVpcEgress); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2150+
transformed["directVpcEgress"] = transformedDirectVpcEgress
2151+
}
2152+
20652153
transformedIngressSettings, err := expandCloudfunctions2functionServiceConfigIngressSettings(original["ingress_settings"], d, config)
20662154
if err != nil {
20672155
return nil, err
@@ -2168,6 +2256,61 @@ func expandCloudfunctions2functionServiceConfigVpcConnectorEgressSettings(v inte
21682256
return v, nil
21692257
}
21702258

2259+
func expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterface(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2260+
if v == nil {
2261+
return nil, nil
2262+
}
2263+
l := v.([]interface{})
2264+
req := make([]interface{}, 0, len(l))
2265+
for _, raw := range l {
2266+
if raw == nil {
2267+
continue
2268+
}
2269+
original := raw.(map[string]interface{})
2270+
transformed := make(map[string]interface{})
2271+
2272+
transformedNetwork, err := expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceNetwork(original["network"], d, config)
2273+
if err != nil {
2274+
return nil, err
2275+
} else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2276+
transformed["network"] = transformedNetwork
2277+
}
2278+
2279+
transformedSubnetwork, err := expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceSubnetwork(original["subnetwork"], d, config)
2280+
if err != nil {
2281+
return nil, err
2282+
} else if val := reflect.ValueOf(transformedSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2283+
transformed["subnetwork"] = transformedSubnetwork
2284+
}
2285+
2286+
transformedTags, err := expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceTags(original["tags"], d, config)
2287+
if err != nil {
2288+
return nil, err
2289+
} else if val := reflect.ValueOf(transformedTags); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2290+
transformed["tags"] = transformedTags
2291+
}
2292+
2293+
req = append(req, transformed)
2294+
}
2295+
return req, nil
2296+
}
2297+
2298+
func expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2299+
return v, nil
2300+
}
2301+
2302+
func expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2303+
return v, nil
2304+
}
2305+
2306+
func expandCloudfunctions2functionServiceConfigDirectVpcNetworkInterfaceTags(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2307+
return v, nil
2308+
}
2309+
2310+
func expandCloudfunctions2functionServiceConfigDirectVpcEgress(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2311+
return v, nil
2312+
}
2313+
21712314
func expandCloudfunctions2functionServiceConfigIngressSettings(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
21722315
return v, nil
21732316
}

google-beta/services/cloudfunctions2/resource_cloudfunctions2_function_generated_meta.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ fields:
4646
- api_field: 'serviceConfig.availableCpu'
4747
- api_field: 'serviceConfig.availableMemory'
4848
- api_field: 'serviceConfig.binaryAuthorizationPolicy'
49+
- api_field: 'serviceConfig.directVpcEgress'
50+
- api_field: 'serviceConfig.directVpcNetworkInterface.network'
51+
- api_field: 'serviceConfig.directVpcNetworkInterface.subnetwork'
52+
- api_field: 'serviceConfig.directVpcNetworkInterface.tags'
4953
- api_field: 'serviceConfig.environmentVariables'
5054
- api_field: 'serviceConfig.gcfUri'
5155
- api_field: 'serviceConfig.ingressSettings'

google-beta/services/cloudfunctions2/resource_cloudfunctions2_function_generated_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,86 @@ resource "google_cloudfunctions2_function" "function" {
12841284
`, context)
12851285
}
12861286

1287+
func TestAccCloudfunctions2function_cloudfunctions2DirectvpcExample(t *testing.T) {
1288+
t.Parallel()
1289+
1290+
context := map[string]interface{}{
1291+
"project": envvar.GetTestProjectFromEnv(),
1292+
"location": "us-central1",
1293+
"zip_path": "./test-fixtures/function-source.zip",
1294+
"random_suffix": acctest.RandString(t, 10),
1295+
}
1296+
1297+
acctest.VcrTest(t, resource.TestCase{
1298+
PreCheck: func() { acctest.AccTestPreCheck(t) },
1299+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
1300+
CheckDestroy: testAccCheckCloudfunctions2functionDestroyProducer(t),
1301+
Steps: []resource.TestStep{
1302+
{
1303+
Config: testAccCloudfunctions2function_cloudfunctions2DirectvpcExample(context),
1304+
},
1305+
{
1306+
ResourceName: "google_cloudfunctions2_function.function",
1307+
ImportState: true,
1308+
ImportStateVerify: true,
1309+
ImportStateVerifyIgnore: []string{"build_config.0.source.0.storage_source.0.bucket", "build_config.0.source.0.storage_source.0.object", "labels", "location", "terraform_labels"},
1310+
},
1311+
},
1312+
})
1313+
}
1314+
1315+
func testAccCloudfunctions2function_cloudfunctions2DirectvpcExample(context map[string]interface{}) string {
1316+
return acctest.Nprintf(`
1317+
locals {
1318+
project = "%{project}" # Google Cloud Platform Project ID
1319+
}
1320+
1321+
resource "google_storage_bucket" "bucket" {
1322+
provider = google-beta
1323+
name = "${local.project}-tf-test-gcf-source%{random_suffix}" # Every bucket name must be globally unique
1324+
location = "US"
1325+
uniform_bucket_level_access = true
1326+
}
1327+
1328+
resource "google_storage_bucket_object" "object" {
1329+
provider = google-beta
1330+
name = "function-source.zip"
1331+
bucket = google_storage_bucket.bucket.name
1332+
source = "%{zip_path}" # Add path to the zipped function source code
1333+
}
1334+
1335+
resource "google_cloudfunctions2_function" "function" {
1336+
provider = google-beta
1337+
name = "tf-test-function-v2%{random_suffix}"
1338+
location = "us-central1"
1339+
description = "a new function"
1340+
1341+
build_config {
1342+
runtime = "nodejs20"
1343+
entry_point = "helloHttp" # Set the entry point
1344+
source {
1345+
storage_source {
1346+
bucket = google_storage_bucket.bucket.name
1347+
object = google_storage_bucket_object.object.name
1348+
}
1349+
}
1350+
}
1351+
1352+
service_config {
1353+
max_instance_count = 1
1354+
available_memory = "256M"
1355+
timeout_seconds = 60
1356+
direct_vpc_network_interface {
1357+
network = "default"
1358+
subnetwork = "default"
1359+
tags = ["tag1", "tag2"]
1360+
}
1361+
direct_vpc_egress = "VPC_EGRESS_ALL_TRAFFIC"
1362+
}
1363+
}
1364+
`, context)
1365+
}
1366+
12871367
func testAccCheckCloudfunctions2functionDestroyProducer(t *testing.T) func(s *terraform.State) error {
12881368
return func(s *terraform.State) error {
12891369
for name, rs := range s.RootModule().Resources {

0 commit comments

Comments
 (0)