@@ -70,6 +70,7 @@ func ResourceComputeInterconnectAttachment() *schema.Resource {
70
70
},
71
71
72
72
CustomizeDiff : customdiff .All (
73
+ tpgresource .SetLabelsDiff ,
73
74
tpgresource .DefaultProviderProject ,
74
75
),
75
76
@@ -197,6 +198,17 @@ allocated from regional external IP address pool.`,
197
198
DiffSuppressFunc : tpgresource .CompareSelfLinkOrResourceName ,
198
199
},
199
200
},
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
+ },
200
212
"mtu" : {
201
213
Type : schema .TypeString ,
202
214
Computed : true ,
@@ -278,11 +290,26 @@ router subinterface for this interconnect attachment.`,
278
290
Description : `IPv6 address + prefix length to be configured on the customer
279
291
router subinterface for this interconnect attachment.` ,
280
292
},
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
+ },
281
299
"google_reference_id" : {
282
300
Type : schema .TypeString ,
283
301
Computed : true ,
284
302
Description : `Google reference ID, to be used when raising support tickets with
285
303
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.` ,
286
313
},
287
314
"pairing_key" : {
288
315
Type : schema .TypeString ,
@@ -319,6 +346,13 @@ Google and the customer, going to and from this network and region.`,
319
346
Computed : true ,
320
347
Description : `[Output Only] The current state of this attachment's functionality.` ,
321
348
},
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
+ },
322
356
"project" : {
323
357
Type : schema .TypeString ,
324
358
Optional : true ,
@@ -432,6 +466,18 @@ func resourceComputeInterconnectAttachmentCreate(d *schema.ResourceData, meta in
432
466
} else if v , ok := d .GetOkExists ("subnet_length" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (subnetLengthProp )) && (ok || ! reflect .DeepEqual (v , subnetLengthProp )) {
433
467
obj ["subnetLength" ] = subnetLengthProp
434
468
}
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
+ }
435
481
regionProp , err := expandComputeInterconnectAttachmentRegion (d .Get ("region" ), d , config )
436
482
if err != nil {
437
483
return err
@@ -490,6 +536,66 @@ func resourceComputeInterconnectAttachmentCreate(d *schema.ResourceData, meta in
490
536
return fmt .Errorf ("Error waiting to create InterconnectAttachment: %s" , err )
491
537
}
492
538
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
+
493
599
if err := waitForAttachmentToBeProvisioned (d , config , d .Timeout (schema .TimeoutCreate )); err != nil {
494
600
return fmt .Errorf ("Error waiting for InterconnectAttachment %q to be provisioned: %q" , d .Get ("name" ).(string ), err )
495
601
}
@@ -610,6 +716,18 @@ func resourceComputeInterconnectAttachmentRead(d *schema.ResourceData, meta inte
610
716
if err := d .Set ("customer_router_ipv6_address" , flattenComputeInterconnectAttachmentCustomerRouterIpv6Address (res ["customerRouterIpv6Address" ], d , config )); err != nil {
611
717
return fmt .Errorf ("Error reading InterconnectAttachment: %s" , err )
612
718
}
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
+ }
613
731
if err := d .Set ("region" , flattenComputeInterconnectAttachmentRegion (res ["region" ], d , config )); err != nil {
614
732
return fmt .Errorf ("Error reading InterconnectAttachment: %s" , err )
615
733
}
@@ -710,6 +828,61 @@ func resourceComputeInterconnectAttachmentUpdate(d *schema.ResourceData, meta in
710
828
if err != nil {
711
829
return err
712
830
}
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 )
713
886
714
887
return resourceComputeInterconnectAttachmentRead (d , meta )
715
888
}
@@ -939,6 +1112,44 @@ func flattenComputeInterconnectAttachmentCustomerRouterIpv6Address(v interface{}
939
1112
return v
940
1113
}
941
1114
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
+
942
1153
func flattenComputeInterconnectAttachmentRegion (v interface {}, d * schema.ResourceData , config * transport_tpg.Config ) interface {} {
943
1154
if v == nil {
944
1155
return v
@@ -1022,6 +1233,21 @@ func expandComputeInterconnectAttachmentSubnetLength(v interface{}, d tpgresourc
1022
1233
return v , nil
1023
1234
}
1024
1235
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
+
1025
1251
func expandComputeInterconnectAttachmentRegion (v interface {}, d tpgresource.TerraformResourceData , config * transport_tpg.Config ) (interface {}, error ) {
1026
1252
f , err := tpgresource .ParseGlobalFieldValue ("regions" , v .(string ), "project" , d , config , true )
1027
1253
if err != nil {
0 commit comments