1
1
package s3control
2
2
3
3
import (
4
+ "context"
4
5
"fmt"
5
6
"log"
6
7
"strings"
@@ -11,18 +12,24 @@ import (
11
12
"github.com/aws/aws-sdk-go/aws/endpoints"
12
13
"github.com/aws/aws-sdk-go/service/s3control"
13
14
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
15
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
16
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
14
17
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
15
18
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
16
19
"github.com/hashicorp/terraform-provider-aws/internal/conns"
17
20
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
18
21
"github.com/hashicorp/terraform-provider-aws/internal/verify"
19
22
)
20
23
21
- func ResourceMultiRegionAccessPoint () * schema.Resource {
24
+ func init () {
25
+ _sp .registerSDKResourceFactory ("aws_s3control_multi_region_access_point" , resourceMultiRegionAccessPoint )
26
+ }
27
+
28
+ func resourceMultiRegionAccessPoint () * schema.Resource {
22
29
return & schema.Resource {
23
- Create : resourceMultiRegionAccessPointCreate ,
24
- Read : resourceMultiRegionAccessPointRead ,
25
- Delete : resourceMultiRegionAccessPointDelete ,
30
+ CreateWithoutTimeout : resourceMultiRegionAccessPointCreate ,
31
+ ReadWithoutTimeout : resourceMultiRegionAccessPointRead ,
32
+ DeleteWithoutTimeout : resourceMultiRegionAccessPointDelete ,
26
33
27
34
Importer : & schema.ResourceImporter {
28
35
State : schema .ImportStatePassthrough ,
@@ -131,11 +138,11 @@ func ResourceMultiRegionAccessPoint() *schema.Resource {
131
138
}
132
139
}
133
140
134
- func resourceMultiRegionAccessPointCreate (d * schema.ResourceData , meta interface {}) error {
141
+ func resourceMultiRegionAccessPointCreate (ctx context. Context , d * schema.ResourceData , meta interface {}) diag. Diagnostics {
135
142
conn , err := ConnForMRAP (meta .(* conns.AWSClient ))
136
143
137
144
if err != nil {
138
- return err
145
+ return diag . FromErr ( err )
139
146
}
140
147
141
148
accountID := meta .(* conns.AWSClient ).AccountID
@@ -153,38 +160,37 @@ func resourceMultiRegionAccessPointCreate(d *schema.ResourceData, meta interface
153
160
154
161
resourceID := MultiRegionAccessPointCreateResourceID (accountID , aws .StringValue (input .Details .Name ))
155
162
156
- log .Printf ("[DEBUG] Creating S3 Multi-Region Access Point: %s" , input )
157
- output , err := conn .CreateMultiRegionAccessPoint (input )
163
+ output , err := conn .CreateMultiRegionAccessPointWithContext (ctx , input )
158
164
159
165
if err != nil {
160
- return fmt .Errorf ("error creating S3 Multi-Region Access Point (%s): %w " , resourceID , err )
166
+ return diag .Errorf ("creating S3 Multi-Region Access Point (%s): %s " , resourceID , err )
161
167
}
162
168
163
169
d .SetId (resourceID )
164
170
165
- _ , err = waitMultiRegionAccessPointRequestSucceeded (conn , accountID , aws .StringValue (output .RequestTokenARN ), d .Timeout (schema .TimeoutCreate ))
171
+ _ , err = waitMultiRegionAccessPointRequestSucceeded (ctx , conn , accountID , aws .StringValue (output .RequestTokenARN ), d .Timeout (schema .TimeoutCreate ))
166
172
167
173
if err != nil {
168
- return fmt .Errorf ("error waiting for Multi-Region Access Point (%s) create: %s" , d .Id (), err )
174
+ return diag .Errorf ("waiting for Multi-Region Access Point (%s) create: %s" , d .Id (), err )
169
175
}
170
176
171
- return resourceMultiRegionAccessPointRead (d , meta )
177
+ return resourceMultiRegionAccessPointRead (ctx , d , meta )
172
178
}
173
179
174
- func resourceMultiRegionAccessPointRead (d * schema.ResourceData , meta interface {}) error {
180
+ func resourceMultiRegionAccessPointRead (ctx context. Context , d * schema.ResourceData , meta interface {}) diag. Diagnostics {
175
181
conn , err := ConnForMRAP (meta .(* conns.AWSClient ))
176
182
177
183
if err != nil {
178
- return err
184
+ return diag . FromErr ( err )
179
185
}
180
186
181
187
accountID , name , err := MultiRegionAccessPointParseResourceID (d .Id ())
182
188
183
189
if err != nil {
184
- return err
190
+ return diag . FromErr ( err )
185
191
}
186
192
187
- accessPoint , err := FindMultiRegionAccessPointByAccountIDAndName ( conn , accountID , name )
193
+ accessPoint , err := FindMultiRegionAccessPointByTwoPartKey ( ctx , conn , accountID , name )
188
194
189
195
if ! d .IsNewResource () && tfresource .NotFound (err ) {
190
196
log .Printf ("[WARN] S3 Multi-Region Access Point (%s) not found, removing from state" , d .Id ())
@@ -193,7 +199,7 @@ func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}
193
199
}
194
200
195
201
if err != nil {
196
- return fmt .Errorf ("error reading S3 Multi-Region Access Point (%s): %w " , d .Id (), err )
202
+ return diag .Errorf ("reading S3 Multi-Region Access Point (%s): %s " , d .Id (), err )
197
203
}
198
204
199
205
alias := aws .StringValue (accessPoint .Alias )
@@ -207,7 +213,7 @@ func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}
207
213
d .Set ("alias" , alias )
208
214
d .Set ("arn" , arn )
209
215
if err := d .Set ("details" , []interface {}{flattenMultiRegionAccessPointReport (accessPoint )}); err != nil {
210
- return fmt .Errorf ("error setting details: %w " , err )
216
+ return diag .Errorf ("setting details: %s " , err )
211
217
}
212
218
// https://docs.aws.amazon.com/AmazonS3/latest/userguide//MultiRegionAccessPointRequests.html#MultiRegionAccessPointHostnames.
213
219
d .Set ("domain_name" , meta .(* conns.AWSClient ).PartitionHostname (fmt .Sprintf ("%s.accesspoint.s3-global" , alias )))
@@ -216,21 +222,21 @@ func resourceMultiRegionAccessPointRead(d *schema.ResourceData, meta interface{}
216
222
return nil
217
223
}
218
224
219
- func resourceMultiRegionAccessPointDelete (d * schema.ResourceData , meta interface {}) error {
225
+ func resourceMultiRegionAccessPointDelete (ctx context. Context , d * schema.ResourceData , meta interface {}) diag. Diagnostics {
220
226
conn , err := ConnForMRAP (meta .(* conns.AWSClient ))
221
227
222
228
if err != nil {
223
- return err
229
+ return diag . FromErr ( err )
224
230
}
225
231
226
232
accountID , name , err := MultiRegionAccessPointParseResourceID (d .Id ())
227
233
228
234
if err != nil {
229
- return err
235
+ return diag . FromErr ( err )
230
236
}
231
237
232
238
log .Printf ("[DEBUG] Deleting S3 Multi-Region Access Point: %s" , d .Id ())
233
- output , err := conn .DeleteMultiRegionAccessPoint ( & s3control.DeleteMultiRegionAccessPointInput {
239
+ output , err := conn .DeleteMultiRegionAccessPointWithContext ( ctx , & s3control.DeleteMultiRegionAccessPointInput {
234
240
AccountId : aws .String (accountID ),
235
241
Details : & s3control.DeleteMultiRegionAccessPointInput_ {
236
242
Name : aws .String (name ),
@@ -242,13 +248,13 @@ func resourceMultiRegionAccessPointDelete(d *schema.ResourceData, meta interface
242
248
}
243
249
244
250
if err != nil {
245
- return fmt .Errorf ("error deleting S3 Multi-Region Access Point (%s): %w " , d .Id (), err )
251
+ return diag .Errorf ("deleting S3 Multi-Region Access Point (%s): %s " , d .Id (), err )
246
252
}
247
253
248
- _ , err = waitMultiRegionAccessPointRequestSucceeded (conn , accountID , aws .StringValue (output .RequestTokenARN ), d .Timeout (schema .TimeoutDelete ))
254
+ _ , err = waitMultiRegionAccessPointRequestSucceeded (ctx , conn , accountID , aws .StringValue (output .RequestTokenARN ), d .Timeout (schema .TimeoutDelete ))
249
255
250
256
if err != nil {
251
- return fmt .Errorf ("error waiting for S3 Multi-Region Access Point (%s) delete: %w " , d .Id (), err )
257
+ return diag .Errorf ("error waiting for S3 Multi-Region Access Point (%s) delete: %s " , d .Id (), err )
252
258
}
253
259
254
260
return nil
@@ -266,12 +272,117 @@ func ConnForMRAP(client *conns.AWSClient) (*s3control.S3Control, error) {
266
272
sess , err := conns .NewSessionForRegion (& originalConn .Config , region , client .TerraformVersion )
267
273
268
274
if err != nil {
269
- return nil , fmt .Errorf ("error creating AWS session: %w" , err )
275
+ return nil , fmt .Errorf ("creating AWS session: %w" , err )
270
276
}
271
277
272
278
return s3control .New (sess ), nil
273
279
}
274
280
281
+ func FindMultiRegionAccessPointByTwoPartKey (ctx context.Context , conn * s3control.S3Control , accountID string , name string ) (* s3control.MultiRegionAccessPointReport , error ) {
282
+ input := & s3control.GetMultiRegionAccessPointInput {
283
+ AccountId : aws .String (accountID ),
284
+ Name : aws .String (name ),
285
+ }
286
+
287
+ output , err := conn .GetMultiRegionAccessPointWithContext (ctx , input )
288
+
289
+ if tfawserr .ErrCodeEquals (err , errCodeNoSuchMultiRegionAccessPoint ) {
290
+ return nil , & resource.NotFoundError {
291
+ LastError : err ,
292
+ LastRequest : input ,
293
+ }
294
+ }
295
+
296
+ if err != nil {
297
+ return nil , err
298
+ }
299
+
300
+ if output == nil || output .AccessPoint == nil {
301
+ return nil , tfresource .NewEmptyResultError (input )
302
+ }
303
+
304
+ return output .AccessPoint , nil
305
+ }
306
+
307
+ func findMultiRegionAccessPointOperationByAccountIDAndTokenARN (ctx context.Context , conn * s3control.S3Control , accountID string , requestTokenARN string ) (* s3control.AsyncOperation , error ) {
308
+ input := & s3control.DescribeMultiRegionAccessPointOperationInput {
309
+ AccountId : aws .String (accountID ),
310
+ RequestTokenARN : aws .String (requestTokenARN ),
311
+ }
312
+
313
+ output , err := conn .DescribeMultiRegionAccessPointOperationWithContext (ctx , input )
314
+
315
+ if tfawserr .ErrCodeEquals (err , errCodeNoSuchAsyncRequest ) {
316
+ return nil , & resource.NotFoundError {
317
+ LastError : err ,
318
+ LastRequest : input ,
319
+ }
320
+ }
321
+
322
+ if err != nil {
323
+ return nil , err
324
+ }
325
+
326
+ if output == nil || output .AsyncOperation == nil {
327
+ return nil , tfresource .NewEmptyResultError (input )
328
+ }
329
+
330
+ return output .AsyncOperation , nil
331
+ }
332
+
333
+ func statusMultiRegionAccessPointRequest (ctx context.Context , conn * s3control.S3Control , accountID string , requestTokenARN string ) resource.StateRefreshFunc {
334
+ return func () (interface {}, string , error ) {
335
+ output , err := findMultiRegionAccessPointOperationByAccountIDAndTokenARN (ctx , conn , accountID , requestTokenARN )
336
+
337
+ if tfresource .NotFound (err ) {
338
+ return nil , "" , nil
339
+ }
340
+
341
+ if err != nil {
342
+ return nil , "" , err
343
+ }
344
+
345
+ return output , aws .StringValue (output .RequestStatus ), nil
346
+ }
347
+ }
348
+
349
+ const (
350
+ // Minimum amount of times to verify change propagation
351
+ propagationContinuousTargetOccurence = 2
352
+
353
+ // Minimum amount of time to wait between S3control change polls
354
+ propagationMinTimeout = 5 * time .Second
355
+
356
+ // Maximum amount of time to wait for S3control changes to propagate
357
+ propagationTimeout = 1 * time .Minute
358
+
359
+ multiRegionAccessPointRequestSucceededMinTimeout = 5 * time .Second
360
+
361
+ multiRegionAccessPointRequestSucceededDelay = 15 * time .Second
362
+ )
363
+
364
+ func waitMultiRegionAccessPointRequestSucceeded (ctx context.Context , conn * s3control.S3Control , accountID string , requestTokenArn string , timeout time.Duration ) (* s3control.AsyncOperation , error ) { //nolint:unparam
365
+ stateConf := & resource.StateChangeConf {
366
+ Target : []string {RequestStatusSucceeded },
367
+ Timeout : timeout ,
368
+ Refresh : statusMultiRegionAccessPointRequest (ctx , conn , accountID , requestTokenArn ),
369
+ MinTimeout : multiRegionAccessPointRequestSucceededMinTimeout ,
370
+ Delay : multiRegionAccessPointRequestSucceededDelay ,
371
+ }
372
+
373
+ outputRaw , err := stateConf .WaitForStateContext (ctx )
374
+
375
+ if output , ok := outputRaw .(* s3control.AsyncOperation ); ok {
376
+ if status , responseDetails := aws .StringValue (output .RequestStatus ), output .ResponseDetails ; status == RequestStatusFailed && responseDetails != nil && responseDetails .ErrorDetails != nil {
377
+ tfresource .SetLastError (err , fmt .Errorf ("%s: %s" , aws .StringValue (responseDetails .ErrorDetails .Code ), aws .StringValue (responseDetails .ErrorDetails .Message )))
378
+ }
379
+
380
+ return output , err
381
+ }
382
+
383
+ return nil , err
384
+ }
385
+
275
386
const multiRegionAccessPointResourceIDSeparator = ":"
276
387
277
388
func MultiRegionAccessPointCreateResourceID (accountID , accessPointName string ) string {
0 commit comments