@@ -24,16 +24,39 @@ import (
24
24
"reflect"
25
25
"time"
26
26
27
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
27
28
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
28
29
29
30
"github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource"
30
31
transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport"
31
32
)
32
33
34
+ // waitForNatAddressReady waits for an NatAddress to leave the
35
+ // "CREATING" state and become "RESERVED", to indicate that it's ready.
36
+ func waitForNatAddressReserved (d * schema.ResourceData , config * transport_tpg.Config , timeout time.Duration ) error {
37
+ return retry .Retry (timeout , func () * retry.RetryError {
38
+ if err := resourceApigeeNatAddressRead (d , config ); err != nil {
39
+ return retry .NonRetryableError (err )
40
+ }
41
+
42
+ id := d .Id ()
43
+ state := d .Get ("state" ).(string )
44
+ if state == "CREATING" {
45
+ return retry .RetryableError (fmt .Errorf ("NatAddress %q has state %q." , id , state ))
46
+ } else if state == "RESERVED" {
47
+ log .Printf ("[DEBUG] NatAddress %q has state %q." , id , state )
48
+ return nil
49
+ } else {
50
+ return retry .NonRetryableError (fmt .Errorf ("NatAddress %q has state %q." , id , state ))
51
+ }
52
+ })
53
+ }
54
+
33
55
func ResourceApigeeNatAddress () * schema.Resource {
34
56
return & schema.Resource {
35
57
Create : resourceApigeeNatAddressCreate ,
36
58
Read : resourceApigeeNatAddressRead ,
59
+ Update : resourceApigeeNatAddressUpdate ,
37
60
Delete : resourceApigeeNatAddressDelete ,
38
61
39
62
Importer : & schema.ResourceImporter {
@@ -42,6 +65,7 @@ func ResourceApigeeNatAddress() *schema.Resource {
42
65
43
66
Timeouts : & schema.ResourceTimeout {
44
67
Create : schema .DefaultTimeout (30 * time .Minute ),
68
+ Update : schema .DefaultTimeout (30 * time .Minute ),
45
69
Delete : schema .DefaultTimeout (30 * time .Minute ),
46
70
},
47
71
@@ -59,6 +83,12 @@ in the format 'organizations/{{org_name}}/instances/{{instance_name}}'.`,
59
83
ForceNew : true ,
60
84
Description : `Resource ID of the NAT address.` ,
61
85
},
86
+ "activate" : {
87
+ Type : schema .TypeBool ,
88
+ Optional : true ,
89
+ Description : `Flag that specifies whether the reserved NAT address should be activate.` ,
90
+ Default : false ,
91
+ },
62
92
"ip_address" : {
63
93
Type : schema .TypeString ,
64
94
Computed : true ,
@@ -88,6 +118,17 @@ func resourceApigeeNatAddressCreate(d *schema.ResourceData, meta interface{}) er
88
118
} else if v , ok := d .GetOkExists ("name" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (nameProp )) && (ok || ! reflect .DeepEqual (v , nameProp )) {
89
119
obj ["name" ] = nameProp
90
120
}
121
+ activateProp , err := expandApigeeNatAddressActivate (d .Get ("activate" ), d , config )
122
+ if err != nil {
123
+ return err
124
+ } else if v , ok := d .GetOkExists ("activate" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (activateProp )) && (ok || ! reflect .DeepEqual (v , activateProp )) {
125
+ obj ["activate" ] = activateProp
126
+ }
127
+
128
+ obj , err = resourceApigeeNatAddressEncoder (d , meta , obj )
129
+ if err != nil {
130
+ return err
131
+ }
91
132
92
133
url , err := tpgresource .ReplaceVars (d , config , "{{ApigeeBasePath}}{{instance_id}}/natAddresses" )
93
134
if err != nil {
@@ -137,6 +178,14 @@ func resourceApigeeNatAddressCreate(d *schema.ResourceData, meta interface{}) er
137
178
return fmt .Errorf ("Error waiting to create NatAddress: %s" , err )
138
179
}
139
180
181
+ opRes , err = resourceApigeeNatAddressDecoder (d , meta , opRes )
182
+ if err != nil {
183
+ return fmt .Errorf ("Error decoding response from operation: %s" , err )
184
+ }
185
+ if opRes == nil {
186
+ return fmt .Errorf ("Error decoding response from operation, could not find object" )
187
+ }
188
+
140
189
if err := d .Set ("name" , flattenApigeeNatAddressName (opRes ["name" ], d , config )); err != nil {
141
190
return err
142
191
}
@@ -148,6 +197,17 @@ func resourceApigeeNatAddressCreate(d *schema.ResourceData, meta interface{}) er
148
197
}
149
198
d .SetId (id )
150
199
200
+ if d .Get ("activate" ).(bool ) {
201
+ if err := waitForNatAddressReserved (d , config , d .Timeout (schema .TimeoutCreate )- time .Minute ); err != nil {
202
+ return fmt .Errorf ("Error waiting for NatAddress %q to be RESERVED during creation: %q" , d .Id (), err )
203
+ }
204
+
205
+ log .Printf ("[DEBUG] Activating for NatAddress %q to become ACTIVE" , d .Id ())
206
+ if err := resourceApigeeNatAddressActivate (config , d , billingProject , userAgent ); err != nil {
207
+ return fmt .Errorf ("Error activating NatAddress: %s" , err )
208
+ }
209
+ }
210
+
151
211
log .Printf ("[DEBUG] Finished creating NatAddress %q: %#v" , d .Id (), res )
152
212
153
213
return resourceApigeeNatAddressRead (d , meta )
@@ -185,9 +245,24 @@ func resourceApigeeNatAddressRead(d *schema.ResourceData, meta interface{}) erro
185
245
return transport_tpg .HandleNotFoundError (err , d , fmt .Sprintf ("ApigeeNatAddress %q" , d .Id ()))
186
246
}
187
247
248
+ res , err = resourceApigeeNatAddressDecoder (d , meta , res )
249
+ if err != nil {
250
+ return err
251
+ }
252
+
253
+ if res == nil {
254
+ // Decoding the object has resulted in it being gone. It may be marked deleted
255
+ log .Printf ("[DEBUG] Removing ApigeeNatAddress because it no longer exists." )
256
+ d .SetId ("" )
257
+ return nil
258
+ }
259
+
188
260
if err := d .Set ("name" , flattenApigeeNatAddressName (res ["name" ], d , config )); err != nil {
189
261
return fmt .Errorf ("Error reading NatAddress: %s" , err )
190
262
}
263
+ if err := d .Set ("activate" , flattenApigeeNatAddressActivate (res ["activate" ], d , config )); err != nil {
264
+ return fmt .Errorf ("Error reading NatAddress: %s" , err )
265
+ }
191
266
if err := d .Set ("ip_address" , flattenApigeeNatAddressIpAddress (res ["ipAddress" ], d , config )); err != nil {
192
267
return fmt .Errorf ("Error reading NatAddress: %s" , err )
193
268
}
@@ -198,6 +273,44 @@ func resourceApigeeNatAddressRead(d *schema.ResourceData, meta interface{}) erro
198
273
return nil
199
274
}
200
275
276
+ func resourceApigeeNatAddressUpdate (d * schema.ResourceData , meta interface {}) error {
277
+ config := meta .(* transport_tpg.Config )
278
+ userAgent , err := tpgresource .GenerateUserAgentString (d , config .UserAgent )
279
+ if err != nil {
280
+ return err
281
+ }
282
+
283
+ billingProject := ""
284
+
285
+ obj := make (map [string ]interface {})
286
+ nameProp , err := expandApigeeNatAddressName (d .Get ("name" ), d , config )
287
+ if err != nil {
288
+ return err
289
+ } else if v , ok := d .GetOkExists ("name" ); ! tpgresource .IsEmptyValue (reflect .ValueOf (v )) && (ok || ! reflect .DeepEqual (v , nameProp )) {
290
+ obj ["name" ] = nameProp
291
+ }
292
+
293
+ log .Printf ("[DEBUG] Updating NatAddress %q: %#v" , d .Id (), obj )
294
+
295
+ // err == nil indicates that the billing_project value was found
296
+ if bp , err := tpgresource .GetBillingProject (d , config ); err == nil {
297
+ billingProject = bp
298
+ }
299
+
300
+ if d .HasChange ("activate" ) {
301
+ if ! d .Get ("activate" ).(bool ) {
302
+ return fmt .Errorf ("NatAddress %q allows only the activation action" , d .Id ())
303
+ } else if d .Get ("state" ).(string ) == "RESERVED" {
304
+ log .Printf ("[DEBUG] Activating for NatAddress %q to become ACTIVE" , d .Id ())
305
+ if err := resourceApigeeNatAddressActivate (config , d , billingProject , userAgent ); err != nil {
306
+ return fmt .Errorf ("Error activating NatAddress: %s" , err )
307
+ }
308
+ }
309
+ }
310
+
311
+ return resourceApigeeNatAddressRead (d , meta )
312
+ }
313
+
201
314
func resourceApigeeNatAddressDelete (d * schema.ResourceData , meta interface {}) error {
202
315
config := meta .(* transport_tpg.Config )
203
316
userAgent , err := tpgresource .GenerateUserAgentString (d , config .UserAgent )
@@ -273,6 +386,10 @@ func flattenApigeeNatAddressName(v interface{}, d *schema.ResourceData, config *
273
386
return v
274
387
}
275
388
389
+ func flattenApigeeNatAddressActivate (v interface {}, d * schema.ResourceData , config * transport_tpg.Config ) interface {} {
390
+ return v
391
+ }
392
+
276
393
func flattenApigeeNatAddressIpAddress (v interface {}, d * schema.ResourceData , config * transport_tpg.Config ) interface {} {
277
394
return v
278
395
}
@@ -284,3 +401,18 @@ func flattenApigeeNatAddressState(v interface{}, d *schema.ResourceData, config
284
401
func expandApigeeNatAddressName (v interface {}, d tpgresource.TerraformResourceData , config * transport_tpg.Config ) (interface {}, error ) {
285
402
return v , nil
286
403
}
404
+
405
+ func expandApigeeNatAddressActivate (v interface {}, d tpgresource.TerraformResourceData , config * transport_tpg.Config ) (interface {}, error ) {
406
+ return v , nil
407
+ }
408
+
409
+ func resourceApigeeNatAddressEncoder (d * schema.ResourceData , meta interface {}, obj map [string ]interface {}) (map [string ]interface {}, error ) {
410
+ // cannot include activate prop in the body
411
+ delete (obj , "activate" )
412
+ return obj , nil
413
+ }
414
+
415
+ func resourceApigeeNatAddressDecoder (d * schema.ResourceData , meta interface {}, res map [string ]interface {}) (map [string ]interface {}, error ) {
416
+ res ["activate" ] = res ["state" ].(string ) == "ACTIVE"
417
+ return res , nil
418
+ }
0 commit comments