20
20
package vpcaccess
21
21
22
22
import (
23
+ "context"
23
24
"fmt"
24
25
"log"
25
26
"net/http"
26
27
"reflect"
28
+ "strings"
27
29
"time"
28
30
29
31
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
@@ -34,10 +36,20 @@ import (
34
36
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
35
37
)
36
38
39
+ func isInstanceShrinkage (_ context.Context , old , new , _ interface {}) bool {
40
+ // max and min instances can only increase in-place,
41
+ // so we must create a new resource if it is decreased.
42
+ if old == nil || new == nil {
43
+ return false
44
+ }
45
+ return new .(int ) < old .(int )
46
+ }
47
+
37
48
func ResourceVPCAccessConnector () * schema.Resource {
38
49
return & schema.Resource {
39
50
Create : resourceVPCAccessConnectorCreate ,
40
51
Read : resourceVPCAccessConnectorRead ,
52
+ Update : resourceVPCAccessConnectorUpdate ,
41
53
Delete : resourceVPCAccessConnectorDelete ,
42
54
43
55
Importer : & schema.ResourceImporter {
@@ -46,10 +58,13 @@ func ResourceVPCAccessConnector() *schema.Resource {
46
58
47
59
Timeouts : & schema.ResourceTimeout {
48
60
Create : schema .DefaultTimeout (20 * time .Minute ),
61
+ Update : schema .DefaultTimeout (20 * time .Minute ),
49
62
Delete : schema .DefaultTimeout (20 * time .Minute ),
50
63
},
51
64
52
65
CustomizeDiff : customdiff .All (
66
+ customdiff .ForceNewIfChange ("min_instances" , isInstanceShrinkage ),
67
+ customdiff .ForceNewIfChange ("max_instances" , isInstanceShrinkage ),
53
68
tpgresource .DefaultProviderProject ,
54
69
),
55
70
@@ -70,18 +85,17 @@ func ResourceVPCAccessConnector() *schema.Resource {
70
85
"machine_type" : {
71
86
Type : schema .TypeString ,
72
87
Optional : true ,
73
- ForceNew : true ,
74
88
Description : `Machine type of VM Instance underlying connector. Default is e2-micro` ,
75
89
Default : "e2-micro" ,
76
90
},
77
91
"max_instances" : {
78
92
Type : schema .TypeInt ,
79
93
Computed : true ,
80
94
Optional : true ,
81
- ForceNew : true ,
82
95
Description : `Maximum value of instances in autoscaling group underlying the connector. Value must be between 3 and 10, inclusive. Must be
83
96
higher than the value specified by min_instances.` ,
84
97
ConflictsWith : []string {"max_throughput" },
98
+ RequiredWith : []string {"min_instances" },
85
99
},
86
100
"max_throughput" : {
87
101
Type : schema .TypeInt ,
@@ -98,10 +112,10 @@ min_throughput. Only one of 'max_throughput' and 'max_instances' can be specifie
98
112
Type : schema .TypeInt ,
99
113
Computed : true ,
100
114
Optional : true ,
101
- ForceNew : true ,
102
115
Description : `Minimum value of instances in autoscaling group underlying the connector. Value must be between 2 and 9, inclusive. Must be
103
116
lower than the value specified by max_instances.` ,
104
117
ConflictsWith : []string {"min_throughput" },
118
+ RequiredWith : []string {"max_instances" },
105
119
},
106
120
"min_throughput" : {
107
121
Type : schema .TypeInt ,
@@ -427,6 +441,124 @@ func resourceVPCAccessConnectorRead(d *schema.ResourceData, meta interface{}) er
427
441
return nil
428
442
}
429
443
444
+ func resourceVPCAccessConnectorUpdate (d * schema.ResourceData , meta interface {}) error {
445
+ config := meta .(* transport_tpg.Config )
446
+ userAgent , err := tpgresource .GenerateUserAgentString (d , config .UserAgent )
447
+ if err != nil {
448
+ return err
449
+ }
450
+
451
+ billingProject := ""
452
+
453
+ project , err := tpgresource .GetProject (d , config )
454
+ if err != nil {
455
+ return fmt .Errorf ("Error fetching project for Connector: %s" , err )
456
+ }
457
+ billingProject = project
458
+
459
+ obj := make (map [string ]interface {})
460
+ machineTypeProp , err := expandVPCAccessConnectorMachineType (d .Get ("machine_type" ), d , config )
461
+ if err != nil {
462
+ return err
463
+ } else if v , ok := d .GetOkExists ("machine_type" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , machineTypeProp )) {
464
+ obj ["machineType" ] = machineTypeProp
465
+ }
466
+ minInstancesProp , err := expandVPCAccessConnectorMinInstances (d .Get ("min_instances" ), d , config )
467
+ if err != nil {
468
+ return err
469
+ } else if v , ok := d .GetOkExists ("min_instances" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , minInstancesProp )) {
470
+ obj ["minInstances" ] = minInstancesProp
471
+ }
472
+ maxInstancesProp , err := expandVPCAccessConnectorMaxInstances (d .Get ("max_instances" ), d , config )
473
+ if err != nil {
474
+ return err
475
+ } else if v , ok := d .GetOkExists ("max_instances" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , maxInstancesProp )) {
476
+ obj ["maxInstances" ] = maxInstancesProp
477
+ }
478
+
479
+ obj , err = resourceVPCAccessConnectorEncoder (d , meta , obj )
480
+ if err != nil {
481
+ return err
482
+ }
483
+
484
+ url , err := tpgresource .ReplaceVars (d , config , "{{VPCAccessBasePath}}projects/{{project}}/locations/{{region}}/connectors/{{name}}" )
485
+ if err != nil {
486
+ return err
487
+ }
488
+
489
+ log .Printf ("[DEBUG] Updating Connector %q: %#v" , d .Id (), obj )
490
+ headers := make (http.Header )
491
+ updateMask := []string {}
492
+
493
+ if d .HasChange ("machine_type" ) {
494
+ updateMask = append (updateMask , "machineType" )
495
+ }
496
+
497
+ if d .HasChange ("min_instances" ) {
498
+ updateMask = append (updateMask , "minInstances" )
499
+ }
500
+
501
+ if d .HasChange ("max_instances" ) {
502
+ updateMask = append (updateMask , "maxInstances" )
503
+ }
504
+ // updateMask is a URL parameter but not present in the schema, so ReplaceVars
505
+ // won't set it
506
+ url , err = transport_tpg .AddQueryParams (url , map [string ]string {"updateMask" : strings .Join (updateMask , "," )})
507
+ if err != nil {
508
+ return err
509
+ }
510
+ if d .HasChange ("min_instances" ) && ! d .HasChange ("max_instances" ) {
511
+ obj ["maxInstances" ] = d .Get ("max_instances" ).(int )
512
+ updateMask = append (updateMask , "maxInstances" , "minInstances" )
513
+ }
514
+
515
+ if d .HasChange ("max_instances" ) && ! d .HasChange ("min_instances" ) {
516
+ obj ["minInstances" ] = d .Get ("min_instances" ).(int )
517
+ updateMask = append (updateMask , "maxInstances" , "minInstances" )
518
+ }
519
+
520
+ // Overwrite the previously set mask.
521
+ url , err = transport_tpg .AddQueryParams (url , map [string ]string {"updateMask" : strings .Join (updateMask , "," )})
522
+ if err != nil {
523
+ return err
524
+ }
525
+
526
+ // err == nil indicates that the billing_project value was found
527
+ if bp , err := tpgresource .GetBillingProject (d , config ); err == nil {
528
+ billingProject = bp
529
+ }
530
+
531
+ // if updateMask is empty we are not updating anything so skip the post
532
+ if len (updateMask ) > 0 {
533
+ res , err := transport_tpg .SendRequest (transport_tpg.SendRequestOptions {
534
+ Config : config ,
535
+ Method : "PATCH" ,
536
+ Project : billingProject ,
537
+ RawURL : url ,
538
+ UserAgent : userAgent ,
539
+ Body : obj ,
540
+ Timeout : d .Timeout (schema .TimeoutUpdate ),
541
+ Headers : headers ,
542
+ })
543
+
544
+ if err != nil {
545
+ return fmt .Errorf ("Error updating Connector %q: %s" , d .Id (), err )
546
+ } else {
547
+ log .Printf ("[DEBUG] Finished updating Connector %q: %#v" , d .Id (), res )
548
+ }
549
+
550
+ err = VPCAccessOperationWaitTime (
551
+ config , res , project , "Updating Connector" , userAgent ,
552
+ d .Timeout (schema .TimeoutUpdate ))
553
+
554
+ if err != nil {
555
+ return err
556
+ }
557
+ }
558
+
559
+ return resourceVPCAccessConnectorRead (d , meta )
560
+ }
561
+
430
562
func resourceVPCAccessConnectorDelete (d * schema.ResourceData , meta interface {}) error {
431
563
config := meta .(* transport_tpg.Config )
432
564
userAgent , err := tpgresource .GenerateUserAgentString (d , config .UserAgent )
0 commit comments