Skip to content

Commit e931738

Browse files
Add Update Connector Support for VPC Access Connectors (#8205) (#15176)
* Add Update Connetor Support for VPC Access Connectors * fix lint * fix go lint * fix tests Signed-off-by: Modular Magician <[email protected]>
1 parent 815e532 commit e931738

8 files changed

+197
-11
lines changed

.changelog/8205.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
vpcaccess: added support for updates to `google_vpc_access_connector` resource
3+
```

google/data_source_vpc_access_connector_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ resource "google_vpc_access_connector" "connector" {
4242
ip_cidr_range = "10.8.0.0/28"
4343
network = "default"
4444
region = "us-central1"
45+
min_instances = 2
46+
max_instances = 3
4547
}
4648
4749
data "google_vpc_access_connector" "connector" {

google/resource_app_engine_standard_app_version_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ resource "google_vpc_access_connector" "bar" {
179179
region = "us-central1"
180180
ip_cidr_range = "10.8.0.0/28"
181181
network = "default"
182+
min_instances = 3
183+
max_instances = 10
182184
}
183185
184186
resource "google_app_engine_standard_app_version" "foo" {

google/resource_cloudfunctions_function_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,8 @@ resource "google_vpc_access_connector" "%s" {
955955
region = "us-central1"
956956
ip_cidr_range = "%s"
957957
network = google_compute_network.vpc.name
958+
min_instances = 3
959+
max_instances = 10
958960
}
959961
960962
resource "google_storage_bucket" "bucket" {

google/resource_vpc_access_connector_generated_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ func testAccVPCAccessConnector_vpcAccessConnectorExample(context map[string]inte
5959
return acctest.Nprintf(`
6060
resource "google_vpc_access_connector" "connector" {
6161
name = "tf-test-vpc-con%{random_suffix}"
62-
ip_cidr_range = "10.8.0.0/28"
62+
ip_cidr_range = "10.18.0.0/28"
6363
network = "default"
64+
min_instances = 2
65+
max_instances = 3
6466
}
6567
`, context)
6668
}
@@ -98,6 +100,8 @@ resource "google_vpc_access_connector" "connector" {
98100
name = google_compute_subnetwork.custom_test.name
99101
}
100102
machine_type = "e2-standard-4"
103+
min_instances = 2
104+
max_instances = 3
101105
}
102106
103107
resource "google_compute_subnetwork" "custom_test" {

google/resource_vpc_access_connector_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,38 @@ func TestAccVPCAccessConnector_vpcAccessConnectorThroughput(t *testing.T) {
3333
})
3434
}
3535

36+
func TestAccVPCAccessConnector_vpcAccessConnectorMachineAndInstancesChanged(t *testing.T) {
37+
t.Parallel()
38+
39+
context := map[string]interface{}{
40+
"random_suffix": RandString(t, 10),
41+
}
42+
43+
VcrTest(t, resource.TestCase{
44+
PreCheck: func() { acctest.AccTestPreCheck(t) },
45+
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
46+
CheckDestroy: testAccCheckVPCAccessConnectorDestroyProducer(t),
47+
Steps: []resource.TestStep{
48+
{
49+
Config: testAccVPCAccessConnector_vpcAccessConnectorThroughput(context),
50+
},
51+
{
52+
ResourceName: "google_vpc_access_connector.connector",
53+
ImportState: true,
54+
ImportStateVerify: true,
55+
},
56+
{
57+
Config: testAccVPCAccessConnector_vpcAccessConnectorMachineAndInstancesChanged(context),
58+
},
59+
{
60+
ResourceName: "google_vpc_access_connector.connector",
61+
ImportState: true,
62+
ImportStateVerify: true,
63+
},
64+
},
65+
})
66+
}
67+
3668
func testAccVPCAccessConnector_vpcAccessConnectorThroughput(context map[string]interface{}) string {
3769
return acctest.Nprintf(`
3870
resource "google_vpc_access_connector" "connector" {
@@ -59,3 +91,30 @@ resource "google_compute_network" "custom_test" {
5991
}
6092
`, context)
6193
}
94+
95+
func testAccVPCAccessConnector_vpcAccessConnectorMachineAndInstancesChanged(context map[string]interface{}) string {
96+
return Nprintf(`
97+
resource "google_vpc_access_connector" "connector" {
98+
name = "tf-test-vpc-con%{random_suffix}"
99+
subnet {
100+
name = google_compute_subnetwork.custom_test.name
101+
}
102+
machine_type = "e2-micro"
103+
min_instances = 3
104+
max_instances = 5
105+
region = "us-central1"
106+
}
107+
108+
resource "google_compute_subnetwork" "custom_test" {
109+
name = "tf-test-vpc-con%{random_suffix}"
110+
ip_cidr_range = "10.2.0.0/28"
111+
region = "us-central1"
112+
network = google_compute_network.custom_test.id
113+
}
114+
115+
resource "google_compute_network" "custom_test" {
116+
name = "tf-test-vpc-con%{random_suffix}"
117+
auto_create_subnetworks = false
118+
}
119+
`, context)
120+
}

google/services/vpcaccess/resource_vpc_access_connector.go

+117-8
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,31 @@
1818
package vpcaccess
1919

2020
import (
21+
"context"
2122
"fmt"
2223
"log"
2324
"reflect"
25+
"strings"
2426
"time"
2527

28+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
2629
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
2730
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
2831

2932
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
3033
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
3134
)
3235

36+
// Are the number of min/max instances reduced?
37+
func AreInstancesReduced(_ context.Context, old, new, _ interface{}) bool {
38+
return new.(int) < old.(int)
39+
}
40+
3341
func ResourceVPCAccessConnector() *schema.Resource {
3442
return &schema.Resource{
3543
Create: resourceVPCAccessConnectorCreate,
3644
Read: resourceVPCAccessConnectorRead,
45+
Update: resourceVPCAccessConnectorUpdate,
3746
Delete: resourceVPCAccessConnectorDelete,
3847

3948
Importer: &schema.ResourceImporter{
@@ -42,9 +51,14 @@ func ResourceVPCAccessConnector() *schema.Resource {
4251

4352
Timeouts: &schema.ResourceTimeout{
4453
Create: schema.DefaultTimeout(20 * time.Minute),
54+
Update: schema.DefaultTimeout(20 * time.Minute),
4555
Delete: schema.DefaultTimeout(20 * time.Minute),
4656
},
4757

58+
CustomizeDiff: customdiff.All(
59+
customdiff.ForceNewIfChange("min_instances", AreInstancesReduced),
60+
customdiff.ForceNewIfChange("max_instances", AreInstancesReduced)),
61+
4862
Schema: map[string]*schema.Schema{
4963
"name": {
5064
Type: schema.TypeString,
@@ -62,39 +76,36 @@ func ResourceVPCAccessConnector() *schema.Resource {
6276
"machine_type": {
6377
Type: schema.TypeString,
6478
Optional: true,
65-
ForceNew: true,
6679
Description: `Machine type of VM Instance underlying connector. Default is e2-micro`,
6780
Default: "e2-micro",
6881
},
6982
"max_instances": {
7083
Type: schema.TypeInt,
7184
Computed: true,
7285
Optional: true,
73-
ForceNew: true,
7486
Description: `Maximum value of instances in autoscaling group underlying the connector.`,
7587
},
7688
"max_throughput": {
7789
Type: schema.TypeInt,
90+
Computed: true,
7891
Optional: true,
7992
ForceNew: true,
80-
ValidateFunc: validation.IntBetween(200, 1000),
81-
Description: `Maximum throughput of the connector in Mbps, must be greater than 'min_throughput'. Default is 300.`,
82-
Default: 300,
93+
ValidateFunc: validation.IntBetween(300, 1000),
94+
Description: `Maximum throughput of the connector in Mbps, must be greater than 'min_throughput'. Default is 1000.`,
8395
},
8496
"min_instances": {
8597
Type: schema.TypeInt,
8698
Computed: true,
8799
Optional: true,
88-
ForceNew: true,
89100
Description: `Minimum value of instances in autoscaling group underlying the connector.`,
90101
},
91102
"min_throughput": {
92103
Type: schema.TypeInt,
104+
Computed: true,
93105
Optional: true,
94106
ForceNew: true,
95-
ValidateFunc: validation.IntBetween(200, 1000),
107+
ValidateFunc: validation.IntBetween(200, 900),
96108
Description: `Minimum throughput of the connector in Mbps. Default and min is 200.`,
97-
Default: 200,
98109
},
99110
"network": {
100111
Type: schema.TypeString,
@@ -405,6 +416,104 @@ func resourceVPCAccessConnectorRead(d *schema.ResourceData, meta interface{}) er
405416
return nil
406417
}
407418

419+
func resourceVPCAccessConnectorUpdate(d *schema.ResourceData, meta interface{}) error {
420+
config := meta.(*transport_tpg.Config)
421+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
422+
if err != nil {
423+
return err
424+
}
425+
426+
billingProject := ""
427+
428+
project, err := tpgresource.GetProject(d, config)
429+
if err != nil {
430+
return fmt.Errorf("Error fetching project for Connector: %s", err)
431+
}
432+
billingProject = project
433+
434+
obj := make(map[string]interface{})
435+
machineTypeProp, err := expandVPCAccessConnectorMachineType(d.Get("machine_type"), d, config)
436+
if err != nil {
437+
return err
438+
} else if v, ok := d.GetOkExists("machine_type"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, machineTypeProp)) {
439+
obj["machineType"] = machineTypeProp
440+
}
441+
minInstancesProp, err := expandVPCAccessConnectorMinInstances(d.Get("min_instances"), d, config)
442+
if err != nil {
443+
return err
444+
} else if v, ok := d.GetOkExists("min_instances"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, minInstancesProp)) {
445+
obj["minInstances"] = minInstancesProp
446+
}
447+
maxInstancesProp, err := expandVPCAccessConnectorMaxInstances(d.Get("max_instances"), d, config)
448+
if err != nil {
449+
return err
450+
} else if v, ok := d.GetOkExists("max_instances"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, maxInstancesProp)) {
451+
obj["maxInstances"] = maxInstancesProp
452+
}
453+
454+
obj, err = resourceVPCAccessConnectorEncoder(d, meta, obj)
455+
if err != nil {
456+
return err
457+
}
458+
459+
url, err := tpgresource.ReplaceVars(d, config, "{{VPCAccessBasePath}}projects/{{project}}/locations/{{region}}/connectors/{{name}}")
460+
if err != nil {
461+
return err
462+
}
463+
464+
log.Printf("[DEBUG] Updating Connector %q: %#v", d.Id(), obj)
465+
updateMask := []string{}
466+
467+
if d.HasChange("machine_type") {
468+
updateMask = append(updateMask, "machineType")
469+
}
470+
471+
if d.HasChange("min_instances") {
472+
updateMask = append(updateMask, "minInstances")
473+
}
474+
475+
if d.HasChange("max_instances") {
476+
updateMask = append(updateMask, "maxInstances")
477+
}
478+
// updateMask is a URL parameter but not present in the schema, so ReplaceVars
479+
// won't set it
480+
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
481+
if err != nil {
482+
return err
483+
}
484+
485+
// err == nil indicates that the billing_project value was found
486+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
487+
billingProject = bp
488+
}
489+
490+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
491+
Config: config,
492+
Method: "PATCH",
493+
Project: billingProject,
494+
RawURL: url,
495+
UserAgent: userAgent,
496+
Body: obj,
497+
Timeout: d.Timeout(schema.TimeoutUpdate),
498+
})
499+
500+
if err != nil {
501+
return fmt.Errorf("Error updating Connector %q: %s", d.Id(), err)
502+
} else {
503+
log.Printf("[DEBUG] Finished updating Connector %q: %#v", d.Id(), res)
504+
}
505+
506+
err = VPCAccessOperationWaitTime(
507+
config, res, project, "Updating Connector", userAgent,
508+
d.Timeout(schema.TimeoutUpdate))
509+
510+
if err != nil {
511+
return err
512+
}
513+
514+
return resourceVPCAccessConnectorRead(d, meta)
515+
}
516+
408517
func resourceVPCAccessConnectorDelete(d *schema.ResourceData, meta interface{}) error {
409518
config := meta.(*transport_tpg.Config)
410519
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)

website/docs/r/vpc_access_connector.html.markdown

+7-2
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ To get more information about Connector, see:
3939
```hcl
4040
resource "google_vpc_access_connector" "connector" {
4141
name = "vpc-con"
42-
ip_cidr_range = "10.8.0.0/28"
42+
ip_cidr_range = "10.18.0.0/28"
4343
network = "default"
44+
min_instances = 2
45+
max_instances = 3
4446
}
4547
```
4648
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
@@ -58,6 +60,8 @@ resource "google_vpc_access_connector" "connector" {
5860
name = google_compute_subnetwork.custom_test.name
5961
}
6062
machine_type = "e2-standard-4"
63+
min_instances = 2
64+
max_instances = 3
6165
}
6266
6367
resource "google_compute_subnetwork" "custom_test" {
@@ -112,7 +116,7 @@ The following arguments are supported:
112116

113117
* `max_throughput` -
114118
(Optional)
115-
Maximum throughput of the connector in Mbps, must be greater than `min_throughput`. Default is 300.
119+
Maximum throughput of the connector in Mbps, must be greater than `min_throughput`. Default is 1000.
116120

117121
* `subnet` -
118122
(Optional)
@@ -160,6 +164,7 @@ This resource provides the following
160164
[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options:
161165

162166
- `create` - Default is 20 minutes.
167+
- `update` - Default is 20 minutes.
163168
- `delete` - Default is 20 minutes.
164169

165170
## Import

0 commit comments

Comments
 (0)