Skip to content

Commit ceef4eb

Browse files
authored
feat(object): bucket lock configuration takes on bucket's region (#2271)
* test(object): acl: all tests OK on fr-par * test(object): acl: remove region attribute on the acl resource * test(object): acl: all tests OK on nl-ams * test(object): acl: remove retry * test(object): lock config: tests fail on fr-par, need ACL PR first * test(object): lock config: all tests OK on nl-ams
1 parent 1e549a1 commit ceef4eb

6 files changed

+2675
-1034
lines changed

docs/resources/object_bucket_object_lock_configuration.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ You should [contact Scaleway support](https://console.scaleway.com/support/ticke
4242

4343
The following arguments are supported:
4444

45-
- `bucket` - (Required, Forces new resource) The name of the bucket.
45+
- `bucket` - (Required, Forces new resource) The name of the bucket, or its Terraform ID.
4646

4747
- `rule` - (Optional) Specifies the Object Lock rule for the specified object.
4848

@@ -54,7 +54,7 @@ The following arguments are supported:
5454

5555
- `years` - (Optional) The number of years that you want to specify for the default retention period.
5656

57-
- `project_id` - (Defaults to [provider](../index.md#project_id) `project_id`) The ID of the project the bucket is associated with.
57+
- `project_id` - (Defaults to [provider](../index.md#arguments-reference) `project_id`) The ID of the project the bucket is associated with.
5858

5959
## Attributes Reference
6060

scaleway/resource_object_bucket_lock_configuration.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package scaleway
33
import (
44
"context"
55
"fmt"
6-
"time"
76

87
"github.com/aws/aws-sdk-go/aws"
98
"github.com/aws/aws-sdk-go/service/s3"
@@ -25,11 +24,12 @@ func resourceObjectLockConfiguration() *schema.Resource {
2524

2625
Schema: map[string]*schema.Schema{
2726
"bucket": {
28-
Type: schema.TypeString,
29-
Required: true,
30-
ForceNew: true,
31-
ValidateFunc: validation.StringLenBetween(1, 63),
32-
Description: "The bucket name.",
27+
Type: schema.TypeString,
28+
Required: true,
29+
ForceNew: true,
30+
ValidateFunc: validation.StringLenBetween(1, 63),
31+
Description: "The bucket's name or regional ID.",
32+
DiffSuppressFunc: diffSuppressFuncLocality,
3333
},
3434
"rule": {
3535
Type: schema.TypeList,
@@ -82,7 +82,17 @@ func resourceObjectLockConfigurationCreate(ctx context.Context, d *schema.Resour
8282
return diag.FromErr(err)
8383
}
8484

85-
bucket := expandID(d.Get("bucket").(string))
85+
regionalID := expandRegionalID(d.Get("bucket"))
86+
bucket := regionalID.ID
87+
bucketRegion := regionalID.Region
88+
89+
if bucketRegion != "" && bucketRegion != region {
90+
conn, err = s3ClientForceRegion(d, meta, bucketRegion.String())
91+
if err != nil {
92+
return diag.FromErr(err)
93+
}
94+
region = bucketRegion
95+
}
8696

8797
input := &s3.PutObjectLockConfigurationInput{
8898
Bucket: aws.String(bucket),
@@ -92,13 +102,7 @@ func resourceObjectLockConfigurationCreate(ctx context.Context, d *schema.Resour
92102
},
93103
}
94104

95-
_, err = retryWhenAWSErrCodeEquals(ctx, []string{s3.ErrCodeNoSuchBucket}, &RetryWhenConfig[*s3.PutObjectLockConfigurationOutput]{
96-
Timeout: d.Timeout(schema.TimeoutCreate),
97-
Interval: 5 * time.Second,
98-
Function: func() (*s3.PutObjectLockConfigurationOutput, error) {
99-
return conn.PutObjectLockConfigurationWithContext(ctx, input)
100-
},
101-
})
105+
_, err = conn.PutObjectLockConfigurationWithContext(ctx, input)
102106
if err != nil {
103107
return diag.FromErr(fmt.Errorf("error creating object bucket (%s) lock configuration: %w", bucket, err))
104108
}

scaleway/resource_object_bucket_lock_configuration_test.go

Lines changed: 125 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package scaleway
22

33
import (
44
"fmt"
5+
"regexp"
56
"testing"
67

78
"github.com/aws/aws-sdk-go/aws"
@@ -27,12 +28,16 @@ func TestAccScalewayObjectBucketLockConfiguration_Basic(t *testing.T) {
2728
PreCheck: func() { testAccPreCheck(t) },
2829
ErrorCheck: ErrorCheck(t, EndpointsID),
2930
ProviderFactories: tt.ProviderFactories,
30-
CheckDestroy: testAccCheckScalewayBucketLockConfigurationDestroy(tt),
31+
CheckDestroy: resource.ComposeTestCheckFunc(
32+
testAccCheckScalewayBucketLockConfigurationDestroy(tt),
33+
testAccCheckScalewayObjectBucketDestroy(tt),
34+
),
3135
Steps: []resource.TestStep{
3236
{
3337
Config: fmt.Sprintf(`
3438
resource "scaleway_object_bucket" "test" {
3539
name = %[1]q
40+
region = %[2]q
3641
tags = {
3742
TestName = "TestAccSCW_LockConfig_basic"
3843
}
@@ -41,22 +46,23 @@ func TestAccScalewayObjectBucketLockConfiguration_Basic(t *testing.T) {
4146
}
4247
4348
resource "scaleway_object_bucket_acl" "test" {
44-
bucket = scaleway_object_bucket.test.name
49+
bucket = scaleway_object_bucket.test.id
4550
acl = "public-read"
4651
}
4752
4853
resource "scaleway_object_bucket_lock_configuration" "test" {
49-
bucket = scaleway_object_bucket.test.name
54+
bucket = scaleway_object_bucket.test.id
5055
rule {
5156
default_retention {
5257
mode = "GOVERNANCE"
5358
days = 1
5459
}
5560
}
5661
}
57-
`, rName),
62+
`, rName, objectTestsMainRegion),
5863
Check: resource.ComposeTestCheckFunc(
5964
testAccCheckBucketLockConfigurationExists(tt, resourceName),
65+
testAccCheckScalewayObjectBucketExistsForceRegion(tt, "scaleway_object_bucket.test", true),
6066
resource.TestCheckResourceAttrPair(resourceName, "bucket", "scaleway_object_bucket.test", "name"),
6167
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
6268
resource.TestCheckResourceAttr(resourceName, "rule.0.default_retention.#", "1"),
@@ -68,6 +74,7 @@ func TestAccScalewayObjectBucketLockConfiguration_Basic(t *testing.T) {
6874
Config: fmt.Sprintf(`
6975
resource "scaleway_object_bucket" "test" {
7076
name = %[1]q
77+
region = %[2]q
7178
tags = {
7279
TestName = "TestAccSCW_LockConfig_basic"
7380
}
@@ -89,9 +96,10 @@ func TestAccScalewayObjectBucketLockConfiguration_Basic(t *testing.T) {
8996
}
9097
}
9198
}
92-
`, rName),
99+
`, rName, objectTestsMainRegion),
93100
Check: resource.ComposeTestCheckFunc(
94101
testAccCheckBucketLockConfigurationExists(tt, resourceName),
102+
testAccCheckScalewayObjectBucketExistsForceRegion(tt, "scaleway_object_bucket.test", true),
95103
resource.TestCheckResourceAttrPair(resourceName, "bucket", "scaleway_object_bucket.test", "name"),
96104
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
97105
resource.TestCheckResourceAttr(resourceName, "rule.0.default_retention.#", "1"),
@@ -119,42 +127,48 @@ func TestAccScalewayObjectBucketLockConfiguration_Update(t *testing.T) {
119127
PreCheck: func() { testAccPreCheck(t) },
120128
ErrorCheck: ErrorCheck(t, EndpointsID),
121129
ProviderFactories: tt.ProviderFactories,
122-
CheckDestroy: testAccCheckScalewayBucketLockConfigurationDestroy(tt),
130+
CheckDestroy: resource.ComposeTestCheckFunc(
131+
testAccCheckScalewayBucketLockConfigurationDestroy(tt),
132+
testAccCheckScalewayObjectBucketDestroy(tt),
133+
),
123134
Steps: []resource.TestStep{
124135
{
125136
Config: fmt.Sprintf(`
126137
resource "scaleway_object_bucket" "test" {
127138
name = %[1]q
139+
region = %[2]q
128140
tags = {
129-
TestName = "TestAccSCW_LockConfig_basic"
141+
TestName = "TestAccSCW_LockConfig_update"
130142
}
131143
132144
object_lock_enabled = true
133145
}
134146
135147
resource "scaleway_object_bucket_acl" "test" {
136-
bucket = scaleway_object_bucket.test.name
148+
bucket = scaleway_object_bucket.test.id
137149
acl = "public-read"
138150
}
139151
140152
resource "scaleway_object_bucket_lock_configuration" "test" {
141-
bucket = scaleway_object_bucket.test.name
153+
bucket = scaleway_object_bucket.test.id
142154
rule {
143155
default_retention {
144156
mode = "GOVERNANCE"
145157
days = 1
146158
}
147159
}
148160
}
149-
`, rName),
161+
`, rName, objectTestsMainRegion),
150162
Check: resource.ComposeTestCheckFunc(
151163
testAccCheckBucketLockConfigurationExists(tt, resourceName),
164+
testAccCheckScalewayObjectBucketExistsForceRegion(tt, "scaleway_object_bucket.test", true),
152165
),
153166
},
154167
{
155168
Config: fmt.Sprintf(`
156169
resource "scaleway_object_bucket" "test" {
157170
name = %[1]q
171+
region = %[2]q
158172
tags = {
159173
TestName = "TestAccSCW_LockConfig_basic"
160174
}
@@ -163,22 +177,23 @@ func TestAccScalewayObjectBucketLockConfiguration_Update(t *testing.T) {
163177
}
164178
165179
resource "scaleway_object_bucket_acl" "test" {
166-
bucket = scaleway_object_bucket.test.name
180+
bucket = scaleway_object_bucket.test.id
167181
acl = "public-read"
168182
}
169183
170184
resource "scaleway_object_bucket_lock_configuration" "test" {
171-
bucket = scaleway_object_bucket.test.name
185+
bucket = scaleway_object_bucket.test.id
172186
rule {
173187
default_retention {
174188
mode = "COMPLIANCE"
175189
days = 2
176190
}
177191
}
178192
}
179-
`, rName),
193+
`, rName, objectTestsMainRegion),
180194
Check: resource.ComposeTestCheckFunc(
181195
testAccCheckBucketLockConfigurationExists(tt, resourceName),
196+
testAccCheckScalewayObjectBucketExistsForceRegion(tt, "scaleway_object_bucket.test", true),
182197
resource.TestCheckResourceAttrPair(resourceName, "bucket", "scaleway_object_bucket.test", "name"),
183198
resource.TestCheckResourceAttr(resourceName, "rule.#", "1"),
184199
resource.TestCheckResourceAttr(resourceName, "rule.0.default_retention.#", "1"),
@@ -195,19 +210,103 @@ func TestAccScalewayObjectBucketLockConfiguration_Update(t *testing.T) {
195210
})
196211
}
197212

213+
func TestAccScalewayObjectBucketLockConfiguration_WithBucketName(t *testing.T) {
214+
rName := sdkacctest.RandomWithPrefix(LockResourcePrefix)
215+
resourceName := lockResourceTestName
216+
217+
tt := NewTestTools(t)
218+
defer tt.Cleanup()
219+
220+
resource.ParallelTest(t, resource.TestCase{
221+
PreCheck: func() { testAccPreCheck(t) },
222+
ErrorCheck: ErrorCheck(t, EndpointsID),
223+
ProviderFactories: tt.ProviderFactories,
224+
CheckDestroy: resource.ComposeTestCheckFunc(
225+
testAccCheckScalewayBucketLockConfigurationDestroy(tt),
226+
testAccCheckScalewayObjectBucketDestroy(tt),
227+
),
228+
Steps: []resource.TestStep{
229+
{
230+
Config: fmt.Sprintf(`
231+
resource "scaleway_object_bucket" "test" {
232+
name = %[1]q
233+
region = %[2]q
234+
tags = {
235+
TestName = "TestAccSCW_LockConfig_WithBucketName"
236+
}
237+
238+
object_lock_enabled = true
239+
}
240+
241+
resource "scaleway_object_bucket_acl" "test" {
242+
bucket = scaleway_object_bucket.test.id
243+
acl = "public-read"
244+
}
245+
246+
resource "scaleway_object_bucket_lock_configuration" "test" {
247+
bucket = scaleway_object_bucket.test.name
248+
rule {
249+
default_retention {
250+
mode = "GOVERNANCE"
251+
days = 1
252+
}
253+
}
254+
}
255+
`, rName, objectTestsMainRegion),
256+
ExpectError: regexp.MustCompile("NoSuchBucket: The specified bucket does not exist"),
257+
},
258+
{
259+
Config: fmt.Sprintf(`
260+
resource "scaleway_object_bucket" "test" {
261+
name = %[1]q
262+
region = %[2]q
263+
tags = {
264+
TestName = "TestAccSCW_LockConfig_WithBucketName"
265+
}
266+
267+
object_lock_enabled = true
268+
}
269+
270+
resource "scaleway_object_bucket_acl" "test" {
271+
bucket = scaleway_object_bucket.test.id
272+
acl = "public-read"
273+
}
274+
275+
resource "scaleway_object_bucket_lock_configuration" "test" {
276+
bucket = scaleway_object_bucket.test.name
277+
region = %[2]q
278+
rule {
279+
default_retention {
280+
mode = "GOVERNANCE"
281+
days = 1
282+
}
283+
}
284+
}
285+
`, rName, objectTestsMainRegion),
286+
Check: resource.ComposeTestCheckFunc(
287+
testAccCheckBucketLockConfigurationExists(tt, resourceName),
288+
testAccCheckScalewayObjectBucketExistsForceRegion(tt, "scaleway_object_bucket.test", true),
289+
resource.TestCheckResourceAttrPair(resourceName, "bucket", "scaleway_object_bucket.test", "name"),
290+
),
291+
},
292+
},
293+
})
294+
}
295+
198296
func testAccCheckScalewayBucketLockConfigurationDestroy(tt *TestTools) resource.TestCheckFunc {
199297
return func(s *terraform.State) error {
200-
conn, err := newS3ClientFromMeta(tt.Meta)
201-
if err != nil {
202-
return err
203-
}
204-
205298
for _, rs := range s.RootModule().Resources {
206299
if rs.Type != "scaleway_object_bucket_lock_configuration" {
207300
continue
208301
}
209302

210-
bucket := expandID(rs.Primary.ID)
303+
regionalID := expandRegionalID(rs.Primary.ID)
304+
bucketRegion := regionalID.Region
305+
bucket := regionalID.ID
306+
conn, err := newS3ClientFromMetaForceRegion(tt.Meta, bucketRegion.String())
307+
if err != nil {
308+
return err
309+
}
211310

212311
input := &s3.GetObjectLockConfigurationInput{
213312
Bucket: aws.String(bucket),
@@ -239,11 +338,6 @@ func testAccCheckBucketLockConfigurationExists(tt *TestTools, resourceName strin
239338
return fmt.Errorf("resource not found")
240339
}
241340

242-
conn, err := newS3ClientFromMeta(tt.Meta)
243-
if err != nil {
244-
return err
245-
}
246-
247341
rs, ok := s.RootModule().Resources[resourceName]
248342
if !ok {
249343
return fmt.Errorf("not found: %s", resourceName)
@@ -253,7 +347,13 @@ func testAccCheckBucketLockConfigurationExists(tt *TestTools, resourceName strin
253347
return fmt.Errorf("resource (%s) ID not set", resourceName)
254348
}
255349

256-
bucket := expandID(rs.Primary.ID)
350+
regionalID := expandRegionalID(rs.Primary.ID)
351+
bucketRegion := regionalID.Region
352+
bucket := regionalID.ID
353+
conn, err := newS3ClientFromMetaForceRegion(tt.Meta, bucketRegion.String())
354+
if err != nil {
355+
return err
356+
}
257357

258358
input := &s3.GetObjectLockConfigurationInput{
259359
Bucket: aws.String(bucket),

0 commit comments

Comments
 (0)