Skip to content

Commit 1ed9de9

Browse files
compute_external_vpn_gateway - allow updating labels (#8297) (#15134)
Signed-off-by: Modular Magician <[email protected]>
1 parent 0c36b15 commit 1ed9de9

File tree

4 files changed

+171
-1
lines changed

4 files changed

+171
-1
lines changed

.changelog/8297.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: added support for updating labels in `google_compute_external_vpn_gateway`
3+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
package google
4+
5+
import (
6+
"fmt"
7+
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
10+
"github.com/hashicorp/terraform-provider-google/google/acctest"
11+
)
12+
13+
func TestAccComputeExternalVPNGateway_updateLabels(t *testing.T) {
14+
t.Parallel()
15+
16+
rnd := acctest.RandString(t, 10)
17+
resourceName := "google_compute_external_vpn_gateway.external_gateway"
18+
19+
acctest.VcrTest(t, resource.TestCase{
20+
PreCheck: func() { acctest.AccTestPreCheck(t) },
21+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccComputeExternalVPNGateway_updateLabels(rnd, "test", "test"),
25+
Check: resource.ComposeTestCheckFunc(
26+
resource.TestCheckResourceAttr(resourceName, "labels.%", "1"),
27+
resource.TestCheckResourceAttr(resourceName, "labels.test", "test"),
28+
),
29+
},
30+
{
31+
ResourceName: resourceName,
32+
ImportState: true,
33+
ImportStateVerify: true,
34+
},
35+
{
36+
Config: testAccComputeExternalVPNGateway_updateLabels(rnd, "test-updated", "test-updated"),
37+
Check: resource.ComposeTestCheckFunc(
38+
resource.TestCheckResourceAttr(resourceName, "labels.%", "1"),
39+
resource.TestCheckResourceAttr(resourceName, "labels.test-updated", "test-updated"),
40+
),
41+
},
42+
{
43+
ResourceName: resourceName,
44+
ImportState: true,
45+
ImportStateVerify: true,
46+
},
47+
},
48+
})
49+
}
50+
51+
func testAccComputeExternalVPNGateway_updateLabels(suffix, key, value string) string {
52+
return fmt.Sprintf(`
53+
resource "google_compute_external_vpn_gateway" "external_gateway" {
54+
name = "tf-test-external-gateway-%s"
55+
redundancy_type = "SINGLE_IP_INTERNALLY_REDUNDANT"
56+
description = "An externally managed VPN gateway"
57+
interface {
58+
id = 0
59+
ip_address = "8.8.8.8"
60+
}
61+
62+
labels = {
63+
%s = "%s"
64+
}
65+
}
66+
`, suffix, key, value)
67+
}

google/services/compute/resource_compute_external_vpn_gateway.go

+96-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ func ResourceComputeExternalVpnGateway() *schema.Resource {
3434
return &schema.Resource{
3535
Create: resourceComputeExternalVpnGatewayCreate,
3636
Read: resourceComputeExternalVpnGatewayRead,
37+
Update: resourceComputeExternalVpnGatewayUpdate,
3738
Delete: resourceComputeExternalVpnGatewayDelete,
3839

3940
Importer: &schema.ResourceImporter{
@@ -42,6 +43,7 @@ func ResourceComputeExternalVpnGateway() *schema.Resource {
4243

4344
Timeouts: &schema.ResourceTimeout{
4445
Create: schema.DefaultTimeout(20 * time.Minute),
46+
Update: schema.DefaultTimeout(20 * time.Minute),
4547
Delete: schema.DefaultTimeout(20 * time.Minute),
4648
},
4749

@@ -96,7 +98,6 @@ it cannot be an IP address from Google Compute Engine.`,
9698
"labels": {
9799
Type: schema.TypeMap,
98100
Optional: true,
99-
ForceNew: true,
100101
Description: `Labels for the external VPN gateway resource.`,
101102
Elem: &schema.Schema{Type: schema.TypeString},
102103
},
@@ -107,6 +108,12 @@ it cannot be an IP address from Google Compute Engine.`,
107108
ValidateFunc: verify.ValidateEnum([]string{"FOUR_IPS_REDUNDANCY", "SINGLE_IP_INTERNALLY_REDUNDANT", "TWO_IPS_REDUNDANCY", ""}),
108109
Description: `Indicates the redundancy type of this external VPN gateway Possible values: ["FOUR_IPS_REDUNDANCY", "SINGLE_IP_INTERNALLY_REDUNDANT", "TWO_IPS_REDUNDANCY"]`,
109110
},
111+
"label_fingerprint": {
112+
Type: schema.TypeString,
113+
Computed: true,
114+
Description: `The fingerprint used for optimistic locking of this resource. Used
115+
internally during updates.`,
116+
},
110117
"project": {
111118
Type: schema.TypeString,
112119
Optional: true,
@@ -142,6 +149,12 @@ func resourceComputeExternalVpnGatewayCreate(d *schema.ResourceData, meta interf
142149
} else if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
143150
obj["labels"] = labelsProp
144151
}
152+
labelFingerprintProp, err := expandComputeExternalVpnGatewayLabelFingerprint(d.Get("label_fingerprint"), d, config)
153+
if err != nil {
154+
return err
155+
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
156+
obj["labelFingerprint"] = labelFingerprintProp
157+
}
145158
nameProp, err := expandComputeExternalVpnGatewayName(d.Get("name"), d, config)
146159
if err != nil {
147160
return err
@@ -261,6 +274,9 @@ func resourceComputeExternalVpnGatewayRead(d *schema.ResourceData, meta interfac
261274
if err := d.Set("labels", flattenComputeExternalVpnGatewayLabels(res["labels"], d, config)); err != nil {
262275
return fmt.Errorf("Error reading ExternalVpnGateway: %s", err)
263276
}
277+
if err := d.Set("label_fingerprint", flattenComputeExternalVpnGatewayLabelFingerprint(res["labelFingerprint"], d, config)); err != nil {
278+
return fmt.Errorf("Error reading ExternalVpnGateway: %s", err)
279+
}
264280
if err := d.Set("name", flattenComputeExternalVpnGatewayName(res["name"], d, config)); err != nil {
265281
return fmt.Errorf("Error reading ExternalVpnGateway: %s", err)
266282
}
@@ -277,6 +293,77 @@ func resourceComputeExternalVpnGatewayRead(d *schema.ResourceData, meta interfac
277293
return nil
278294
}
279295

296+
func resourceComputeExternalVpnGatewayUpdate(d *schema.ResourceData, meta interface{}) error {
297+
config := meta.(*transport_tpg.Config)
298+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
299+
if err != nil {
300+
return err
301+
}
302+
303+
billingProject := ""
304+
305+
project, err := tpgresource.GetProject(d, config)
306+
if err != nil {
307+
return fmt.Errorf("Error fetching project for ExternalVpnGateway: %s", err)
308+
}
309+
billingProject = project
310+
311+
d.Partial(true)
312+
313+
if d.HasChange("labels") || d.HasChange("label_fingerprint") {
314+
obj := make(map[string]interface{})
315+
316+
labelsProp, err := expandComputeExternalVpnGatewayLabels(d.Get("labels"), d, config)
317+
if err != nil {
318+
return err
319+
} else if v, ok := d.GetOkExists("labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
320+
obj["labels"] = labelsProp
321+
}
322+
labelFingerprintProp, err := expandComputeExternalVpnGatewayLabelFingerprint(d.Get("label_fingerprint"), d, config)
323+
if err != nil {
324+
return err
325+
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
326+
obj["labelFingerprint"] = labelFingerprintProp
327+
}
328+
329+
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/global/externalVpnGateways/{{name}}/setLabels")
330+
if err != nil {
331+
return err
332+
}
333+
334+
// err == nil indicates that the billing_project value was found
335+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
336+
billingProject = bp
337+
}
338+
339+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
340+
Config: config,
341+
Method: "POST",
342+
Project: billingProject,
343+
RawURL: url,
344+
UserAgent: userAgent,
345+
Body: obj,
346+
Timeout: d.Timeout(schema.TimeoutUpdate),
347+
})
348+
if err != nil {
349+
return fmt.Errorf("Error updating ExternalVpnGateway %q: %s", d.Id(), err)
350+
} else {
351+
log.Printf("[DEBUG] Finished updating ExternalVpnGateway %q: %#v", d.Id(), res)
352+
}
353+
354+
err = ComputeOperationWaitTime(
355+
config, res, project, "Updating ExternalVpnGateway", userAgent,
356+
d.Timeout(schema.TimeoutUpdate))
357+
if err != nil {
358+
return err
359+
}
360+
}
361+
362+
d.Partial(false)
363+
364+
return resourceComputeExternalVpnGatewayRead(d, meta)
365+
}
366+
280367
func resourceComputeExternalVpnGatewayDelete(d *schema.ResourceData, meta interface{}) error {
281368
config := meta.(*transport_tpg.Config)
282369
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
@@ -358,6 +445,10 @@ func flattenComputeExternalVpnGatewayLabels(v interface{}, d *schema.ResourceDat
358445
return v
359446
}
360447

448+
func flattenComputeExternalVpnGatewayLabelFingerprint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
449+
return v
450+
}
451+
361452
func flattenComputeExternalVpnGatewayName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
362453
return v
363454
}
@@ -421,6 +512,10 @@ func expandComputeExternalVpnGatewayLabels(v interface{}, d tpgresource.Terrafor
421512
return m, nil
422513
}
423514

515+
func expandComputeExternalVpnGatewayLabelFingerprint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
516+
return v, nil
517+
}
518+
424519
func expandComputeExternalVpnGatewayName(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
425520
return v, nil
426521
}

website/docs/r/compute_external_vpn_gateway.html.markdown

+5
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ The following arguments are supported:
201201
In addition to the arguments listed above, the following computed attributes are exported:
202202

203203
* `id` - an identifier for the resource with format `projects/{{project}}/global/externalVpnGateways/{{name}}`
204+
205+
* `label_fingerprint` -
206+
The fingerprint used for optimistic locking of this resource. Used
207+
internally during updates.
204208
* `self_link` - The URI of the created resource.
205209

206210

@@ -210,6 +214,7 @@ This resource provides the following
210214
[Timeouts](https://developer.hashicorp.com/terraform/plugin/sdkv2/resources/retries-and-customizable-timeouts) configuration options:
211215

212216
- `create` - Default is 20 minutes.
217+
- `update` - Default is 20 minutes.
213218
- `delete` - Default is 20 minutes.
214219

215220
## Import

0 commit comments

Comments
 (0)