Skip to content

Commit efa5964

Browse files
Adding Labels to Interconnect Attachments (#12755) (#9095)
[upstream:80c24b192a0d78bbe80f848304329d8127963483] Signed-off-by: Modular Magician <[email protected]>
1 parent 62fdb1c commit efa5964

File tree

4 files changed

+257
-3
lines changed

4 files changed

+257
-3
lines changed

.changelog/12755.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: adding Labels field to resource_compute_interconnect_attachment
3+
```

google-beta/services/compute/resource_compute_interconnect_attachment.go

+226
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func ResourceComputeInterconnectAttachment() *schema.Resource {
7070
},
7171

7272
CustomizeDiff: customdiff.All(
73+
tpgresource.SetLabelsDiff,
7374
tpgresource.DefaultProviderProject,
7475
),
7576

@@ -197,6 +198,17 @@ allocated from regional external IP address pool.`,
197198
DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName,
198199
},
199200
},
201+
"labels": {
202+
Type: schema.TypeMap,
203+
Optional: true,
204+
Description: `Labels for this resource. These can only be added or modified by the setLabels
205+
method. Each label key/value pair must comply with RFC1035. Label values may be empty.
206+
207+
208+
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
209+
Please refer to the field 'effective_labels' for all of the labels present on the resource.`,
210+
Elem: &schema.Schema{Type: schema.TypeString},
211+
},
200212
"mtu": {
201213
Type: schema.TypeString,
202214
Computed: true,
@@ -278,11 +290,26 @@ router subinterface for this interconnect attachment.`,
278290
Description: `IPv6 address + prefix length to be configured on the customer
279291
router subinterface for this interconnect attachment.`,
280292
},
293+
"effective_labels": {
294+
Type: schema.TypeMap,
295+
Computed: true,
296+
Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
297+
Elem: &schema.Schema{Type: schema.TypeString},
298+
},
281299
"google_reference_id": {
282300
Type: schema.TypeString,
283301
Computed: true,
284302
Description: `Google reference ID, to be used when raising support tickets with
285303
Google or otherwise to debug backend connectivity issues.`,
304+
},
305+
"label_fingerprint": {
306+
Type: schema.TypeString,
307+
Computed: true,
308+
Description: `A fingerprint for the labels being applied to this Interconnect, which is essentially a hash
309+
of the labels set used for optimistic locking. The fingerprint is initially generated by
310+
Compute Engine and changes after every request to modify or update labels.
311+
You must always provide an up-to-date fingerprint hash in order to update or change labels,
312+
otherwise the request will fail with error 412 conditionNotMet.`,
286313
},
287314
"pairing_key": {
288315
Type: schema.TypeString,
@@ -319,6 +346,13 @@ Google and the customer, going to and from this network and region.`,
319346
Computed: true,
320347
Description: `[Output Only] The current state of this attachment's functionality.`,
321348
},
349+
"terraform_labels": {
350+
Type: schema.TypeMap,
351+
Computed: true,
352+
Description: `The combination of labels configured directly on the resource
353+
and default labels configured on the provider.`,
354+
Elem: &schema.Schema{Type: schema.TypeString},
355+
},
322356
"project": {
323357
Type: schema.TypeString,
324358
Optional: true,
@@ -432,6 +466,18 @@ func resourceComputeInterconnectAttachmentCreate(d *schema.ResourceData, meta in
432466
} else if v, ok := d.GetOkExists("subnet_length"); !tpgresource.IsEmptyValue(reflect.ValueOf(subnetLengthProp)) && (ok || !reflect.DeepEqual(v, subnetLengthProp)) {
433467
obj["subnetLength"] = subnetLengthProp
434468
}
469+
labelFingerprintProp, err := expandComputeInterconnectAttachmentLabelFingerprint(d.Get("label_fingerprint"), d, config)
470+
if err != nil {
471+
return err
472+
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelFingerprintProp)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
473+
obj["labelFingerprint"] = labelFingerprintProp
474+
}
475+
labelsProp, err := expandComputeInterconnectAttachmentEffectiveLabels(d.Get("effective_labels"), d, config)
476+
if err != nil {
477+
return err
478+
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
479+
obj["labels"] = labelsProp
480+
}
435481
regionProp, err := expandComputeInterconnectAttachmentRegion(d.Get("region"), d, config)
436482
if err != nil {
437483
return err
@@ -490,6 +536,66 @@ func resourceComputeInterconnectAttachmentCreate(d *schema.ResourceData, meta in
490536
return fmt.Errorf("Error waiting to create InterconnectAttachment: %s", err)
491537
}
492538

539+
if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
540+
labels := d.Get("labels")
541+
terraformLables := d.Get("terraform_labels")
542+
543+
// Labels cannot be set in a create. We'll have to set them here.
544+
err = resourceComputeInterconnectAttachmentRead(d, meta)
545+
if err != nil {
546+
return err
547+
}
548+
549+
obj := make(map[string]interface{})
550+
// d.Get("effective_labels") will have been overridden by the Read call.
551+
labelsProp, err := expandComputeInterconnectAttachmentEffectiveLabels(v, d, config)
552+
if err != nil {
553+
return err
554+
}
555+
obj["labels"] = labelsProp
556+
labelFingerprintProp := d.Get("label_fingerprint")
557+
obj["labelFingerprint"] = labelFingerprintProp
558+
559+
url, err = tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/interconnectAttachments/{{name}}/setLabels")
560+
if err != nil {
561+
return err
562+
}
563+
res, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
564+
Config: config,
565+
Method: "POST",
566+
Project: project,
567+
RawURL: url,
568+
UserAgent: userAgent,
569+
Body: obj,
570+
})
571+
if err != nil {
572+
return fmt.Errorf("Error adding labels to ComputeInterconnectAttachment %q: %s", d.Id(), err)
573+
}
574+
575+
err = ComputeOperationWaitTime(
576+
config, res, project, "Updating ComputeInterconnectAttachment Labels", userAgent,
577+
d.Timeout(schema.TimeoutUpdate))
578+
579+
if err != nil {
580+
return err
581+
}
582+
583+
// Set back the labels field, as it is needed to decide the value of "labels" in the state in the read function.
584+
if err := d.Set("labels", labels); err != nil {
585+
return fmt.Errorf("Error setting back labels: %s", err)
586+
}
587+
588+
// Set back the terraform_labels field, as it is needed to decide the value of "terraform_labels" in the state in the read function.
589+
if err := d.Set("terraform_labels", terraformLables); err != nil {
590+
return fmt.Errorf("Error setting back terraform_labels: %s", err)
591+
}
592+
593+
// Set back the effective_labels field, as it is needed to decide the value of "effective_labels" in the state in the read function.
594+
if err := d.Set("effective_labels", v); err != nil {
595+
return fmt.Errorf("Error setting back effective_labels: %s", err)
596+
}
597+
}
598+
493599
if err := waitForAttachmentToBeProvisioned(d, config, d.Timeout(schema.TimeoutCreate)); err != nil {
494600
return fmt.Errorf("Error waiting for InterconnectAttachment %q to be provisioned: %q", d.Get("name").(string), err)
495601
}
@@ -610,6 +716,18 @@ func resourceComputeInterconnectAttachmentRead(d *schema.ResourceData, meta inte
610716
if err := d.Set("customer_router_ipv6_address", flattenComputeInterconnectAttachmentCustomerRouterIpv6Address(res["customerRouterIpv6Address"], d, config)); err != nil {
611717
return fmt.Errorf("Error reading InterconnectAttachment: %s", err)
612718
}
719+
if err := d.Set("labels", flattenComputeInterconnectAttachmentLabels(res["labels"], d, config)); err != nil {
720+
return fmt.Errorf("Error reading InterconnectAttachment: %s", err)
721+
}
722+
if err := d.Set("label_fingerprint", flattenComputeInterconnectAttachmentLabelFingerprint(res["labelFingerprint"], d, config)); err != nil {
723+
return fmt.Errorf("Error reading InterconnectAttachment: %s", err)
724+
}
725+
if err := d.Set("terraform_labels", flattenComputeInterconnectAttachmentTerraformLabels(res["labels"], d, config)); err != nil {
726+
return fmt.Errorf("Error reading InterconnectAttachment: %s", err)
727+
}
728+
if err := d.Set("effective_labels", flattenComputeInterconnectAttachmentEffectiveLabels(res["labels"], d, config)); err != nil {
729+
return fmt.Errorf("Error reading InterconnectAttachment: %s", err)
730+
}
613731
if err := d.Set("region", flattenComputeInterconnectAttachmentRegion(res["region"], d, config)); err != nil {
614732
return fmt.Errorf("Error reading InterconnectAttachment: %s", err)
615733
}
@@ -710,6 +828,61 @@ func resourceComputeInterconnectAttachmentUpdate(d *schema.ResourceData, meta in
710828
if err != nil {
711829
return err
712830
}
831+
d.Partial(true)
832+
833+
if d.HasChange("label_fingerprint") || d.HasChange("effective_labels") {
834+
obj := make(map[string]interface{})
835+
836+
labelFingerprintProp, err := expandComputeInterconnectAttachmentLabelFingerprint(d.Get("label_fingerprint"), d, config)
837+
if err != nil {
838+
return err
839+
} else if v, ok := d.GetOkExists("label_fingerprint"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelFingerprintProp)) {
840+
obj["labelFingerprint"] = labelFingerprintProp
841+
}
842+
labelsProp, err := expandComputeInterconnectAttachmentEffectiveLabels(d.Get("effective_labels"), d, config)
843+
if err != nil {
844+
return err
845+
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
846+
obj["labels"] = labelsProp
847+
}
848+
849+
url, err := tpgresource.ReplaceVars(d, config, "{{ComputeBasePath}}projects/{{project}}/regions/{{region}}/interconnectAttachments/{{name}}/setLabels")
850+
if err != nil {
851+
return err
852+
}
853+
854+
headers := make(http.Header)
855+
856+
// err == nil indicates that the billing_project value was found
857+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
858+
billingProject = bp
859+
}
860+
861+
res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{
862+
Config: config,
863+
Method: "POST",
864+
Project: billingProject,
865+
RawURL: url,
866+
UserAgent: userAgent,
867+
Body: obj,
868+
Timeout: d.Timeout(schema.TimeoutUpdate),
869+
Headers: headers,
870+
})
871+
if err != nil {
872+
return fmt.Errorf("Error updating InterconnectAttachment %q: %s", d.Id(), err)
873+
} else {
874+
log.Printf("[DEBUG] Finished updating InterconnectAttachment %q: %#v", d.Id(), res)
875+
}
876+
877+
err = ComputeOperationWaitTime(
878+
config, res, project, "Updating InterconnectAttachment", userAgent,
879+
d.Timeout(schema.TimeoutUpdate))
880+
if err != nil {
881+
return err
882+
}
883+
}
884+
885+
d.Partial(false)
713886

714887
return resourceComputeInterconnectAttachmentRead(d, meta)
715888
}
@@ -939,6 +1112,44 @@ func flattenComputeInterconnectAttachmentCustomerRouterIpv6Address(v interface{}
9391112
return v
9401113
}
9411114

1115+
func flattenComputeInterconnectAttachmentLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1116+
if v == nil {
1117+
return v
1118+
}
1119+
1120+
transformed := make(map[string]interface{})
1121+
if l, ok := d.GetOkExists("labels"); ok {
1122+
for k := range l.(map[string]interface{}) {
1123+
transformed[k] = v.(map[string]interface{})[k]
1124+
}
1125+
}
1126+
1127+
return transformed
1128+
}
1129+
1130+
func flattenComputeInterconnectAttachmentLabelFingerprint(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1131+
return v
1132+
}
1133+
1134+
func flattenComputeInterconnectAttachmentTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1135+
if v == nil {
1136+
return v
1137+
}
1138+
1139+
transformed := make(map[string]interface{})
1140+
if l, ok := d.GetOkExists("terraform_labels"); ok {
1141+
for k := range l.(map[string]interface{}) {
1142+
transformed[k] = v.(map[string]interface{})[k]
1143+
}
1144+
}
1145+
1146+
return transformed
1147+
}
1148+
1149+
func flattenComputeInterconnectAttachmentEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1150+
return v
1151+
}
1152+
9421153
func flattenComputeInterconnectAttachmentRegion(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
9431154
if v == nil {
9441155
return v
@@ -1022,6 +1233,21 @@ func expandComputeInterconnectAttachmentSubnetLength(v interface{}, d tpgresourc
10221233
return v, nil
10231234
}
10241235

1236+
func expandComputeInterconnectAttachmentLabelFingerprint(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
1237+
return v, nil
1238+
}
1239+
1240+
func expandComputeInterconnectAttachmentEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
1241+
if v == nil {
1242+
return map[string]string{}, nil
1243+
}
1244+
m := make(map[string]string)
1245+
for k, val := range v.(map[string]interface{}) {
1246+
m[k] = val.(string)
1247+
}
1248+
return m, nil
1249+
}
1250+
10251251
func expandComputeInterconnectAttachmentRegion(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
10261252
f, err := tpgresource.ParseGlobalFieldValue("regions", v.(string), "project", d, config, true)
10271253
if err != nil {

google-beta/services/compute/resource_compute_interconnect_attachment_generated_test.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestAccComputeInterconnectAttachment_interconnectAttachmentBasicExample(t *
4949
ResourceName: "google_compute_interconnect_attachment.on_prem",
5050
ImportState: true,
5151
ImportStateVerify: true,
52-
ImportStateVerifyIgnore: []string{"candidate_subnets", "region", "router", "subnet_length"},
52+
ImportStateVerifyIgnore: []string{"candidate_subnets", "labels", "region", "router", "subnet_length", "terraform_labels"},
5353
},
5454
},
5555
})
@@ -63,6 +63,7 @@ resource "google_compute_interconnect_attachment" "on_prem" {
6363
type = "PARTNER"
6464
router = google_compute_router.foobar.id
6565
mtu = 1500
66+
labels = { mykey = "myvalue" }
6667
}
6768
6869
resource "google_compute_router" "foobar" {
@@ -99,7 +100,7 @@ func TestAccComputeInterconnectAttachment_interconnectAttachmentDedicatedExample
99100
ResourceName: "google_compute_interconnect_attachment.on_prem",
100101
ImportState: true,
101102
ImportStateVerify: true,
102-
ImportStateVerifyIgnore: []string{"candidate_subnets", "region", "router", "subnet_length"},
103+
ImportStateVerifyIgnore: []string{"candidate_subnets", "labels", "region", "router", "subnet_length", "terraform_labels"},
103104
},
104105
},
105106
})
@@ -128,6 +129,7 @@ resource "google_compute_interconnect_attachment" "on_prem" {
128129
vlan_tag8021q = 1000
129130
region = "https://www.googleapis.com/compute/v1/projects/${data.google_project.project.name}/regions/us-east4"
130131
stack_type = "IPV4_ONLY"
132+
labels = { mykey = "myvalue" }
131133
}
132134
133135
resource "google_compute_router" "foobar" {
@@ -165,7 +167,7 @@ func TestAccComputeInterconnectAttachment_computeInterconnectAttachmentIpsecEncr
165167
ResourceName: "google_compute_interconnect_attachment.ipsec-encrypted-interconnect-attachment",
166168
ImportState: true,
167169
ImportStateVerify: true,
168-
ImportStateVerifyIgnore: []string{"candidate_subnets", "region", "router", "subnet_length"},
170+
ImportStateVerifyIgnore: []string{"candidate_subnets", "labels", "region", "router", "subnet_length", "terraform_labels"},
169171
},
170172
},
171173
})

website/docs/r/compute_interconnect_attachment.html.markdown

+23
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ resource "google_compute_interconnect_attachment" "on_prem" {
3939
type = "PARTNER"
4040
router = google_compute_router.foobar.id
4141
mtu = 1500
42+
labels = { mykey = "myvalue" }
4243
}
4344
4445
resource "google_compute_router" "foobar" {
@@ -233,6 +234,14 @@ The following arguments are supported:
233234
requesting 29 returns an error. Where both 29 and 30 are allowed, 29 is preferred, because it
234235
gives Google Cloud Support more debugging visibility.
235236

237+
* `labels` -
238+
(Optional)
239+
Labels for this resource. These can only be added or modified by the setLabels
240+
method. Each label key/value pair must comply with RFC1035. Label values may be empty.
241+
242+
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
243+
Please refer to the field `effective_labels` for all of the labels present on the resource.
244+
236245
* `region` -
237246
(Optional)
238247
Region where the regional interconnect attachment resides.
@@ -287,6 +296,20 @@ In addition to the arguments listed above, the following computed attributes are
287296
* `customer_router_ipv6_address` -
288297
IPv6 address + prefix length to be configured on the customer
289298
router subinterface for this interconnect attachment.
299+
300+
* `label_fingerprint` -
301+
A fingerprint for the labels being applied to this Interconnect, which is essentially a hash
302+
of the labels set used for optimistic locking. The fingerprint is initially generated by
303+
Compute Engine and changes after every request to modify or update labels.
304+
You must always provide an up-to-date fingerprint hash in order to update or change labels,
305+
otherwise the request will fail with error 412 conditionNotMet.
306+
307+
* `terraform_labels` -
308+
The combination of labels configured directly on the resource
309+
and default labels configured on the provider.
310+
311+
* `effective_labels` -
312+
All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.
290313
* `self_link` - The URI of the created resource.
291314

292315

0 commit comments

Comments
 (0)