Skip to content

Commit bd38076

Browse files
Add labels property to HA VPN Gateway (#12866) (#9309)
[upstream:2346615efcf8e86f961bf6b92987f574682e11fb] Signed-off-by: Modular Magician <[email protected]>
1 parent 17338fb commit bd38076

5 files changed

+227
-2
lines changed

.changelog/12866.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: added `labels` field to `google_compute_ha_vpn_gateway` resource
3+
```

google-beta/services/compute/resource_compute_ha_vpn_gateway.go

+187
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func ResourceComputeHaVpnGateway() *schema.Resource {
3737
return &schema.Resource{
3838
Create: resourceComputeHaVpnGatewayCreate,
3939
Read: resourceComputeHaVpnGatewayRead,
40+
Update: resourceComputeHaVpnGatewayUpdate,
4041
Delete: resourceComputeHaVpnGatewayDelete,
4142

4243
Importer: &schema.ResourceImporter{
@@ -45,6 +46,7 @@ func ResourceComputeHaVpnGateway() *schema.Resource {
4546

4647
Timeouts: &schema.ResourceTimeout{
4748
Create: schema.DefaultTimeout(20 * time.Minute),
49+
Update: schema.DefaultTimeout(20 * time.Minute),
4850
Delete: schema.DefaultTimeout(20 * time.Minute),
4951
},
5052

@@ -58,6 +60,7 @@ func ResourceComputeHaVpnGateway() *schema.Resource {
5860
},
5961
},
6062
CustomizeDiff: customdiff.All(
63+
tpgresource.SetLabelsDiff,
6164
tpgresource.DefaultProviderProject,
6265
),
6366

@@ -96,6 +99,17 @@ character, which cannot be a dash.`,
9699
Description: `The IP family of the gateway IPs for the HA-VPN gateway interfaces. If not specified, IPV4 will be used. Default value: "IPV4" Possible values: ["IPV4", "IPV6"]`,
97100
Default: "IPV4",
98101
},
102+
"labels": {
103+
Type: schema.TypeMap,
104+
Optional: true,
105+
Description: `Labels for this resource. These can only be added or modified by the setLabels method.
106+
Each label key/value pair must comply with RFC1035. Label values may be empty.
107+
108+
109+
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
110+
Please refer to the field 'effective_labels' for all of the labels present on the resource.`,
111+
Elem: &schema.Schema{Type: schema.TypeString},
112+
},
99113
"region": {
100114
Type: schema.TypeString,
101115
Computed: true,
@@ -148,6 +162,28 @@ Not currently available publicly.`,
148162
},
149163
},
150164
},
165+
"effective_labels": {
166+
Type: schema.TypeMap,
167+
Computed: true,
168+
Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
169+
Elem: &schema.Schema{Type: schema.TypeString},
170+
},
171+
"label_fingerprint": {
172+
Type: schema.TypeString,
173+
Computed: true,
174+
Description: `A fingerprint for the labels being applied to this VpnGateway, which is essentially a hash
175+
of the labels set used for optimistic locking. The fingerprint is initially generated by
176+
Compute Engine and changes after every request to modify or update labels.
177+
You must always provide an up-to-date fingerprint hash in order to update or change labels,
178+
otherwise the request will fail with error 412 conditionNotMet.`,
179+
},
180+
"terraform_labels": {
181+
Type: schema.TypeMap,
182+
Computed: true,
183+
Description: `The combination of labels configured directly on the resource
184+
and default labels configured on the provider.`,
185+
Elem: &schema.Schema{Type: schema.TypeString},
186+
},
151187
"project": {
152188
Type: schema.TypeString,
153189
Optional: true,
@@ -207,6 +243,18 @@ func resourceComputeHaVpnGatewayCreate(d *schema.ResourceData, meta interface{})
207243
} else if v, ok := d.GetOkExists("vpn_interfaces"); !tpgresource.IsEmptyValue(reflect.ValueOf(vpnInterfacesProp)) && (ok || !reflect.DeepEqual(v, vpnInterfacesProp)) {
208244
obj["vpnInterfaces"] = vpnInterfacesProp
209245
}
246+
labelFingerprintProp, err := expandComputeHaVpnGatewayLabelFingerprint(d.Get("label_fingerprint"), d, config)
247+
if err != nil {
248+
return err
249+
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
250+
obj["labelFingerprint"] = labelFingerprintProp
251+
}
252+
labelsProp, err := expandComputeHaVpnGatewayEffectiveLabels(d.Get("effective_labels"), d, config)
253+
if err != nil {
254+
return err
255+
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
256+
obj["labels"] = labelsProp
257+
}
210258
regionProp, err := expandComputeHaVpnGatewayRegion(d.Get("region"), d, config)
211259
if err != nil {
212260
return err
@@ -330,6 +378,18 @@ func resourceComputeHaVpnGatewayRead(d *schema.ResourceData, meta interface{}) e
330378
if err := d.Set("vpn_interfaces", flattenComputeHaVpnGatewayVpnInterfaces(res["vpnInterfaces"], d, config)); err != nil {
331379
return fmt.Errorf("Error reading HaVpnGateway: %s", err)
332380
}
381+
if err := d.Set("labels", flattenComputeHaVpnGatewayLabels(res["labels"], d, config)); err != nil {
382+
return fmt.Errorf("Error reading HaVpnGateway: %s", err)
383+
}
384+
if err := d.Set("label_fingerprint", flattenComputeHaVpnGatewayLabelFingerprint(res["labelFingerprint"], d, config)); err != nil {
385+
return fmt.Errorf("Error reading HaVpnGateway: %s", err)
386+
}
387+
if err := d.Set("terraform_labels", flattenComputeHaVpnGatewayTerraformLabels(res["labels"], d, config)); err != nil {
388+
return fmt.Errorf("Error reading HaVpnGateway: %s", err)
389+
}
390+
if err := d.Set("effective_labels", flattenComputeHaVpnGatewayEffectiveLabels(res["labels"], d, config)); err != nil {
391+
return fmt.Errorf("Error reading HaVpnGateway: %s", err)
392+
}
333393
if err := d.Set("region", flattenComputeHaVpnGatewayRegion(res["region"], d, config)); err != nil {
334394
return fmt.Errorf("Error reading HaVpnGateway: %s", err)
335395
}
@@ -340,6 +400,80 @@ func resourceComputeHaVpnGatewayRead(d *schema.ResourceData, meta interface{}) e
340400
return nil
341401
}
342402

403+
func resourceComputeHaVpnGatewayUpdate(d *schema.ResourceData, meta interface{}) error {
404+
config := meta.(*transport_tpg.Config)
405+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
406+
if err != nil {
407+
return err
408+
}
409+
410+
billingProject := ""
411+
412+
project, err := tpgresource.GetProject(d, config)
413+
if err != nil {
414+
return fmt.Errorf("Error fetching project for HaVpnGateway: %s", err)
415+
}
416+
billingProject = project
417+
418+
d.Partial(true)
419+
420+
if d.HasChange("label_fingerprint") || d.HasChange("effective_labels") {
421+
obj := make(map[string]interface{})
422+
423+
labelFingerprintProp, err := expandComputeHaVpnGatewayLabelFingerprint(d.Get("label_fingerprint"), d, config)
424+
if err != nil {
425+
return err
426+
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
427+
obj["labelFingerprint"] = labelFingerprintProp
428+
}
429+
labelsProp, err := expandComputeHaVpnGatewayEffectiveLabels(d.Get("effective_labels"), d, config)
430+
if err != nil {
431+
return err
432+
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
433+
obj["labels"] = labelsProp
434+
}
435+
436+
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/vpnGateways/{{name}}/setLabels")
437+
if err != nil {
438+
return err
439+
}
440+
441+
headers := make(http.Header)
442+
443+
// err == nil indicates that the billing_project value was found
444+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
445+
billingProject = bp
446+
}
447+
448+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
449+
Config: config,
450+
Method: "POST",
451+
Project: billingProject,
452+
RawURL: url,
453+
UserAgent: userAgent,
454+
Body: obj,
455+
Timeout: d.Timeout(schema.TimeoutUpdate),
456+
Headers: headers,
457+
})
458+
if err != nil {
459+
return fmt.Errorf("Error updating HaVpnGateway %q: %s", d.Id(), err)
460+
} else {
461+
log.Printf("[DEBUG] Finished updating HaVpnGateway %q: %#v", d.Id(), res)
462+
}
463+
464+
err = ComputeOperationWaitTime(
465+
config, res, project, "Updating HaVpnGateway", userAgent,
466+
d.Timeout(schema.TimeoutUpdate))
467+
if err != nil {
468+
return err
469+
}
470+
}
471+
472+
d.Partial(false)
473+
474+
return resourceComputeHaVpnGatewayRead(d, meta)
475+
}
476+
343477
func resourceComputeHaVpnGatewayDelete(d *schema.ResourceData, meta interface{}) error {
344478
config := meta.(*transport_tpg.Config)
345479
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
@@ -496,6 +630,44 @@ func flattenComputeHaVpnGatewayVpnInterfacesInterconnectAttachment(v interface{}
496630
return tpgresource.ConvertSelfLinkToV1(v.(string))
497631
}
498632

633+
func flattenComputeHaVpnGatewayLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
634+
if v == nil {
635+
return v
636+
}
637+
638+
transformed := make(map[string]interface{})
639+
if l, ok := d.GetOkExists("labels"); ok {
640+
for k := range l.(map[string]interface{}) {
641+
transformed[k] = v.(map[string]interface{})[k]
642+
}
643+
}
644+
645+
return transformed
646+
}
647+
648+
func flattenComputeHaVpnGatewayLabelFingerprint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
649+
return v
650+
}
651+
652+
func flattenComputeHaVpnGatewayTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
653+
if v == nil {
654+
return v
655+
}
656+
657+
transformed := make(map[string]interface{})
658+
if l, ok := d.GetOkExists("terraform_labels"); ok {
659+
for k := range l.(map[string]interface{}) {
660+
transformed[k] = v.(map[string]interface{})[k]
661+
}
662+
}
663+
664+
return transformed
665+
}
666+
667+
func flattenComputeHaVpnGatewayEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
668+
return v
669+
}
670+
499671
func flattenComputeHaVpnGatewayRegion(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
500672
if v == nil {
501673
return v
@@ -579,6 +751,21 @@ func expandComputeHaVpnGatewayVpnInterfacesInterconnectAttachment(v interface{},
579751
return f.RelativeLink(), nil
580752
}
581753

754+
func expandComputeHaVpnGatewayLabelFingerprint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
755+
return v, nil
756+
}
757+
758+
func expandComputeHaVpnGatewayEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
759+
if v == nil {
760+
return map[string]string{}, nil
761+
}
762+
m := make(map[string]string)
763+
for k, val := range v.(map[string]interface{}) {
764+
m[k] = val.(string)
765+
}
766+
return m, nil
767+
}
768+
582769
func expandComputeHaVpnGatewayRegion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
583770
f, err := tpgresource.ParseGlobalFieldValue("regions", v.(string), "project", d, config, true)
584771
if err != nil {

google-beta/services/compute/resource_compute_ha_vpn_gateway_generated_meta.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@ api_version: 'beta'
66
api_resource_type_kind: 'VpnGateway'
77
fields:
88
- field: 'description'
9+
- field: 'effective_labels'
10+
provider_only: true
911
- field: 'gateway_ip_version'
12+
- field: 'label_fingerprint'
13+
- field: 'labels'
1014
- field: 'name'
1115
- field: 'network'
1216
- field: 'region'
1317
- field: 'stack_type'
18+
- field: 'terraform_labels'
19+
provider_only: true
1420
- field: 'vpn_interfaces.id'
1521
- field: 'vpn_interfaces.interconnect_attachment'
1622
- field: 'vpn_interfaces.ip_address'

google-beta/services/compute/resource_compute_ha_vpn_gateway_generated_test.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestAccComputeHaVpnGateway_haVpnGatewayBasicExample(t *testing.T) {
4949
ResourceName: "google_compute_ha_vpn_gateway.ha_gateway1",
5050
ImportState: true,
5151
ImportStateVerify: true,
52-
ImportStateVerifyIgnore: []string{"network", "region"},
52+
ImportStateVerifyIgnore: []string{"labels", "network", "region", "terraform_labels"},
5353
},
5454
},
5555
})
@@ -89,7 +89,7 @@ func TestAccComputeHaVpnGateway_haVpnGatewayIpv6Example(t *testing.T) {
8989
ResourceName: "google_compute_ha_vpn_gateway.ha_gateway1",
9090
ImportState: true,
9191
ImportStateVerify: true,
92-
ImportStateVerifyIgnore: []string{"network", "region"},
92+
ImportStateVerifyIgnore: []string{"labels", "network", "region", "terraform_labels"},
9393
},
9494
},
9595
})
@@ -102,6 +102,9 @@ resource "google_compute_ha_vpn_gateway" "ha_gateway1" {
102102
name = "tf-test-ha-vpn-1%{random_suffix}"
103103
network = google_compute_network.network1.id
104104
stack_type = "IPV4_IPV6"
105+
labels = {
106+
mykey = "myvalue"
107+
}
105108
}
106109
107110
resource "google_compute_network" "network1" {

website/docs/r/compute_ha_vpn_gateway.html.markdown

+26
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ resource "google_compute_ha_vpn_gateway" "ha_gateway1" {
6565
name = "ha-vpn-1"
6666
network = google_compute_network.network1.id
6767
stack_type = "IPV4_IPV6"
68+
labels = {
69+
mykey = "myvalue"
70+
}
6871
}
6972
7073
resource "google_compute_network" "network1" {
@@ -189,6 +192,14 @@ The following arguments are supported:
189192
A list of interfaces on this VPN gateway.
190193
Structure is [documented below](#nested_vpn_interfaces).
191194

195+
* `labels` -
196+
(Optional)
197+
Labels for this resource. These can only be added or modified by the setLabels method.
198+
Each label key/value pair must comply with RFC1035. Label values may be empty.
199+
200+
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
201+
Please refer to the field `effective_labels` for all of the labels present on the resource.
202+
192203
* `region` -
193204
(Optional)
194205
The region this gateway should sit in.
@@ -221,6 +232,20 @@ The following arguments are supported:
221232
In addition to the arguments listed above, the following computed attributes are exported:
222233

223234
* `id` - an identifier for the resource with format `projects/{{project}}/regions/{{region}}/vpnGateways/{{name}}`
235+
236+
* `label_fingerprint` -
237+
A fingerprint for the labels being applied to this VpnGateway, which is essentially a hash
238+
of the labels set used for optimistic locking. The fingerprint is initially generated by
239+
Compute Engine and changes after every request to modify or update labels.
240+
You must always provide an up-to-date fingerprint hash in order to update or change labels,
241+
otherwise the request will fail with error 412 conditionNotMet.
242+
243+
* `terraform_labels` -
244+
The combination of labels configured directly on the resource
245+
and default labels configured on the provider.
246+
247+
* `effective_labels` -
248+
All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.
224249
* `self_link` - The URI of the created resource.
225250

226251

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

232257
- `create` - Default is 20 minutes.
258+
- `update` - Default is 20 minutes.
233259
- `delete` - Default is 20 minutes.
234260

235261
## Import

0 commit comments

Comments
 (0)