Skip to content

Commit e40d97e

Browse files
committed
r/s3_bucket_lifecycle_configuration: make new_noncurrent_versions arguments nullable ints
1 parent 4604bb0 commit e40d97e

4 files changed

+298
-19
lines changed

internal/service/s3/bucket_lifecycle_configuration.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func ResourceBucketLifecycleConfiguration() *schema.Resource {
164164
Elem: &schema.Resource{
165165
Schema: map[string]*schema.Schema{
166166
"newer_noncurrent_versions": {
167-
Type: schema.TypeInt,
167+
Type: nullable.TypeNullableInt,
168168
Optional: true,
169169
ValidateFunc: validation.IntAtLeast(1),
170170
},
@@ -182,7 +182,7 @@ func ResourceBucketLifecycleConfiguration() *schema.Resource {
182182
Elem: &schema.Resource{
183183
Schema: map[string]*schema.Schema{
184184
"newer_noncurrent_versions": {
185-
Type: schema.TypeInt,
185+
Type: nullable.TypeNullableInt,
186186
Optional: true,
187187
ValidateFunc: validation.IntAtLeast(1),
188188
},

internal/service/s3/bucket_lifecycle_configuration_test.go

+276
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,151 @@ func TestAccS3BucketLifecycleConfiguration_filterWithPrefix(t *testing.T) {
128128
})
129129
}
130130

131+
func TestAccS3BucketLifecycleConfiguration_Filter_ObjectSizeGreaterThan(t *testing.T) {
132+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
133+
resourceName := "aws_s3_bucket_lifecycle_configuration.test"
134+
currTime := time.Now()
135+
date := time.Date(currTime.Year(), currTime.Month()+1, currTime.Day(), 0, 0, 0, 0, time.UTC).Format(time.RFC3339)
136+
137+
resource.ParallelTest(t, resource.TestCase{
138+
PreCheck: func() { acctest.PreCheck(t) },
139+
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
140+
Providers: acctest.Providers,
141+
CheckDestroy: testAccCheckBucketLifecycleConfigurationDestroy,
142+
Steps: []resource.TestStep{
143+
{
144+
Config: testAccBucketLifecycleConfiguration_filterWithObjectSizeGreaterThanConfig(rName, date, 100),
145+
Check: resource.ComposeTestCheckFunc(
146+
testAccCheckBucketLifecycleConfigurationExists(resourceName),
147+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
148+
"expiration.#": "1",
149+
"expiration.0.date": date,
150+
"filter.#": "1",
151+
"filter.0.object_size_greater_than": "100",
152+
"id": rName,
153+
"status": tfs3.LifecycleRuleStatusEnabled,
154+
}),
155+
),
156+
},
157+
{
158+
ResourceName: resourceName,
159+
ImportState: true,
160+
ImportStateVerify: true,
161+
},
162+
},
163+
})
164+
}
165+
166+
func TestAccS3BucketLifecycleConfiguration_Filter_ObjectSizeLessThan(t *testing.T) {
167+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
168+
resourceName := "aws_s3_bucket_lifecycle_configuration.test"
169+
currTime := time.Now()
170+
date := time.Date(currTime.Year(), currTime.Month()+1, currTime.Day(), 0, 0, 0, 0, time.UTC).Format(time.RFC3339)
171+
172+
resource.ParallelTest(t, resource.TestCase{
173+
PreCheck: func() { acctest.PreCheck(t) },
174+
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
175+
Providers: acctest.Providers,
176+
CheckDestroy: testAccCheckBucketLifecycleConfigurationDestroy,
177+
Steps: []resource.TestStep{
178+
{
179+
Config: testAccBucketLifecycleConfiguration_filterWithObjectSizeLessThanConfig(rName, date, 500),
180+
Check: resource.ComposeTestCheckFunc(
181+
testAccCheckBucketLifecycleConfigurationExists(resourceName),
182+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
183+
"expiration.#": "1",
184+
"expiration.0.date": date,
185+
"filter.#": "1",
186+
"filter.0.object_size_less_than": "500",
187+
"id": rName,
188+
"status": tfs3.LifecycleRuleStatusEnabled,
189+
}),
190+
),
191+
},
192+
{
193+
ResourceName: resourceName,
194+
ImportState: true,
195+
ImportStateVerify: true,
196+
},
197+
},
198+
})
199+
}
200+
201+
func TestAccS3BucketLifecycleConfiguration_Filter_ObjectSizeRange(t *testing.T) {
202+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
203+
resourceName := "aws_s3_bucket_lifecycle_configuration.test"
204+
currTime := time.Now()
205+
date := time.Date(currTime.Year(), currTime.Month()+1, currTime.Day(), 0, 0, 0, 0, time.UTC).Format(time.RFC3339)
206+
207+
resource.ParallelTest(t, resource.TestCase{
208+
PreCheck: func() { acctest.PreCheck(t) },
209+
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
210+
Providers: acctest.Providers,
211+
CheckDestroy: testAccCheckBucketLifecycleConfigurationDestroy,
212+
Steps: []resource.TestStep{
213+
{
214+
Config: testAccBucketLifecycleConfiguration_filterWithObjectSizeRangeConfig(rName, date, 500, 64000),
215+
Check: resource.ComposeTestCheckFunc(
216+
testAccCheckBucketLifecycleConfigurationExists(resourceName),
217+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
218+
"expiration.#": "1",
219+
"expiration.0.date": date,
220+
"filter.#": "1",
221+
"filter.0.and.#": "1",
222+
"filter.0.and.0.object_size_greater_than": "500",
223+
"filter.0.and.0.object_size_less_than": "64000",
224+
"id": rName,
225+
"status": tfs3.LifecycleRuleStatusEnabled,
226+
}),
227+
),
228+
},
229+
{
230+
ResourceName: resourceName,
231+
ImportState: true,
232+
ImportStateVerify: true,
233+
},
234+
},
235+
})
236+
}
237+
238+
func TestAccS3BucketLifecycleConfiguration_Filter_ObjectSizeRangeAndPrefix(t *testing.T) {
239+
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
240+
resourceName := "aws_s3_bucket_lifecycle_configuration.test"
241+
currTime := time.Now()
242+
date := time.Date(currTime.Year(), currTime.Month()+1, currTime.Day(), 0, 0, 0, 0, time.UTC).Format(time.RFC3339)
243+
244+
resource.ParallelTest(t, resource.TestCase{
245+
PreCheck: func() { acctest.PreCheck(t) },
246+
ErrorCheck: acctest.ErrorCheck(t, s3.EndpointsID),
247+
Providers: acctest.Providers,
248+
CheckDestroy: testAccCheckBucketLifecycleConfigurationDestroy,
249+
Steps: []resource.TestStep{
250+
{
251+
Config: testAccBucketLifecycleConfiguration_filterWithObjectSizeRangeAndPrefixConfig(rName, date, 500, 64000),
252+
Check: resource.ComposeTestCheckFunc(
253+
testAccCheckBucketLifecycleConfigurationExists(resourceName),
254+
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "rule.*", map[string]string{
255+
"expiration.#": "1",
256+
"expiration.0.date": date,
257+
"filter.#": "1",
258+
"filter.0.and.#": "1",
259+
"filter.0.and.0.object_size_greater_than": "500",
260+
"filter.0.and.0.object_size_less_than": "64000",
261+
"filter.0.and.0.prefix": rName,
262+
"id": rName,
263+
"status": tfs3.LifecycleRuleStatusEnabled,
264+
}),
265+
),
266+
},
267+
{
268+
ResourceName: resourceName,
269+
ImportState: true,
270+
ImportStateVerify: true,
271+
},
272+
},
273+
})
274+
}
275+
131276
func TestAccS3BucketLifecycleConfiguration_disableRule(t *testing.T) {
132277
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
133278
resourceName := "aws_s3_bucket_lifecycle_configuration.test"
@@ -1241,3 +1386,134 @@ resource "aws_s3_bucket_lifecycle_configuration" "test" {
12411386
}
12421387
`, rName)
12431388
}
1389+
1390+
func testAccBucketLifecycleConfiguration_filterWithObjectSizeGreaterThanConfig(rName, date string, sizeGreaterThan int) string {
1391+
return fmt.Sprintf(`
1392+
resource "aws_s3_bucket" "test" {
1393+
bucket = %[1]q
1394+
}
1395+
1396+
resource "aws_s3_bucket_acl" "test" {
1397+
bucket = aws_s3_bucket.test.id
1398+
acl = "private"
1399+
}
1400+
1401+
resource "aws_s3_bucket_lifecycle_configuration" "test" {
1402+
bucket = aws_s3_bucket.test.bucket
1403+
1404+
rule {
1405+
id = %[1]q
1406+
1407+
expiration {
1408+
date = %[2]q
1409+
}
1410+
1411+
filter {
1412+
object_size_greater_than = %[3]d
1413+
}
1414+
1415+
status = "Enabled"
1416+
}
1417+
}
1418+
`, rName, date, sizeGreaterThan)
1419+
}
1420+
1421+
func testAccBucketLifecycleConfiguration_filterWithObjectSizeLessThanConfig(rName, date string, sizeLessThan int) string {
1422+
return fmt.Sprintf(`
1423+
resource "aws_s3_bucket" "test" {
1424+
bucket = %[1]q
1425+
}
1426+
1427+
resource "aws_s3_bucket_acl" "test" {
1428+
bucket = aws_s3_bucket.test.id
1429+
acl = "private"
1430+
}
1431+
1432+
resource "aws_s3_bucket_lifecycle_configuration" "test" {
1433+
bucket = aws_s3_bucket.test.bucket
1434+
1435+
rule {
1436+
id = %[1]q
1437+
1438+
expiration {
1439+
date = %[2]q
1440+
}
1441+
1442+
filter {
1443+
object_size_less_than = %[3]d
1444+
}
1445+
1446+
status = "Enabled"
1447+
}
1448+
}
1449+
`, rName, date, sizeLessThan)
1450+
}
1451+
1452+
func testAccBucketLifecycleConfiguration_filterWithObjectSizeRangeConfig(rName, date string, sizeGreaterThan, sizeLessThan int) string {
1453+
return fmt.Sprintf(`
1454+
resource "aws_s3_bucket" "test" {
1455+
bucket = %[1]q
1456+
}
1457+
1458+
resource "aws_s3_bucket_acl" "test" {
1459+
bucket = aws_s3_bucket.test.id
1460+
acl = "private"
1461+
}
1462+
1463+
resource "aws_s3_bucket_lifecycle_configuration" "test" {
1464+
bucket = aws_s3_bucket.test.bucket
1465+
1466+
rule {
1467+
id = %[1]q
1468+
1469+
expiration {
1470+
date = %[2]q
1471+
}
1472+
1473+
filter {
1474+
and {
1475+
object_size_greater_than = %[3]d
1476+
object_size_less_than = %[4]d
1477+
}
1478+
}
1479+
1480+
status = "Enabled"
1481+
}
1482+
}
1483+
`, rName, date, sizeGreaterThan, sizeLessThan)
1484+
}
1485+
1486+
func testAccBucketLifecycleConfiguration_filterWithObjectSizeRangeAndPrefixConfig(rName, date string, sizeGreaterThan, sizeLessThan int) string {
1487+
return fmt.Sprintf(`
1488+
resource "aws_s3_bucket" "test" {
1489+
bucket = %[1]q
1490+
}
1491+
1492+
resource "aws_s3_bucket_acl" "test" {
1493+
bucket = aws_s3_bucket.test.id
1494+
acl = "private"
1495+
}
1496+
1497+
resource "aws_s3_bucket_lifecycle_configuration" "test" {
1498+
bucket = aws_s3_bucket.test.bucket
1499+
1500+
rule {
1501+
id = %[1]q
1502+
1503+
expiration {
1504+
date = %[2]q
1505+
}
1506+
1507+
filter {
1508+
and {
1509+
object_size_greater_than = %[3]d
1510+
object_size_less_than = %[4]d
1511+
prefix = %[1]q
1512+
}
1513+
}
1514+
1515+
status = "Enabled"
1516+
}
1517+
}
1518+
`, rName, date, sizeGreaterThan, sizeLessThan)
1519+
}

internal/service/s3/flex.go

+16-13
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@ package s3
22

33
import (
44
"fmt"
5+
"strconv"
56
"time"
67

78
"github.com/aws/aws-sdk-go/aws"
89
"github.com/aws/aws-sdk-go/service/s3"
910
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
11+
"github.com/hashicorp/terraform-provider-aws/internal/experimental/nullable"
1012
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
1113
)
1214

@@ -230,12 +232,12 @@ func ExpandLifecycleRuleFilter(l []interface{}) *s3.LifecycleRuleFilter {
230232
result.And = ExpandLifecycleRuleFilterAndOperator(v[0].(map[string]interface{}))
231233
}
232234

233-
if v, ok := m["object_size_greater_than"].(int); ok && v > 0 {
234-
result.ObjectSizeGreaterThan = aws.Int64(int64(v))
235+
if v, null, _ := nullable.Int(m["object_size_greater_than"].(string)).Value(); !null && v > 0 {
236+
result.ObjectSizeGreaterThan = aws.Int64(v)
235237
}
236238

237-
if v, ok := m["object_size_less_than"].(int); ok && v > 0 {
238-
result.ObjectSizeLessThan = aws.Int64(int64(v))
239+
if v, null, _ := nullable.Int(m["object_size_less_than"].(string)).Value(); !null && v > 0 {
240+
result.ObjectSizeLessThan = aws.Int64(v)
239241
}
240242

241243
if v, ok := m["tag"].([]interface{}); ok && len(v) > 0 && v[0] != nil {
@@ -244,7 +246,8 @@ func ExpandLifecycleRuleFilter(l []interface{}) *s3.LifecycleRuleFilter {
244246

245247
// Per AWS S3 API, "A Filter must have exactly one of Prefix, Tag, or And specified";
246248
// Specifying more than one of the listed parameters results in a MalformedXML error.
247-
if v, ok := m["prefix"].(string); ok && result.And == nil && result.Tag == nil {
249+
// In practice, this also includes ObjectSizeGreaterThan and ObjectSizeLessThan.
250+
if v, ok := m["prefix"].(string); ok && result.And == nil && result.Tag == nil && result.ObjectSizeGreaterThan == nil && result.ObjectSizeLessThan == nil {
248251
result.Prefix = aws.String(v)
249252
}
250253

@@ -305,8 +308,8 @@ func ExpandLifecycleRuleNoncurrentVersionExpiration(m map[string]interface{}) *s
305308

306309
result := &s3.NoncurrentVersionExpiration{}
307310

308-
if v, ok := m["newer_noncurrent_versions"].(int); ok && v > 0 {
309-
result.NewerNoncurrentVersions = aws.Int64(int64(v))
311+
if v, null, _ := nullable.Int(m["newer_noncurrent_versions"].(string)).Value(); !null && v > 0 {
312+
result.NewerNoncurrentVersions = aws.Int64(v)
310313
}
311314

312315
if v, ok := m["noncurrent_days"].(int); ok {
@@ -332,8 +335,8 @@ func ExpandLifecycleRuleNoncurrentVersionTransitions(l []interface{}) []*s3.Nonc
332335

333336
transition := &s3.NoncurrentVersionTransition{}
334337

335-
if v, ok := tfMap["newer_noncurrent_versions"].(int); ok && v > 0 {
336-
transition.NewerNoncurrentVersions = aws.Int64(int64(v))
338+
if v, null, _ := nullable.Int(tfMap["newer_noncurrent_versions"].(string)).Value(); !null && v > 0 {
339+
transition.NewerNoncurrentVersions = aws.Int64(v)
337340
}
338341

339342
if v, ok := tfMap["noncurrent_days"].(int); ok {
@@ -910,11 +913,11 @@ func FlattenLifecycleRuleFilter(filter *s3.LifecycleRuleFilter) []interface{} {
910913
}
911914

912915
if filter.ObjectSizeGreaterThan != nil {
913-
m["object_size_greater_than"] = int(aws.Int64Value(filter.ObjectSizeGreaterThan))
916+
m["object_size_greater_than"] = strconv.FormatInt(aws.Int64Value(filter.ObjectSizeGreaterThan), 10)
914917
}
915918

916919
if filter.ObjectSizeLessThan != nil {
917-
m["object_size_less_than"] = int(aws.Int64Value(filter.ObjectSizeLessThan))
920+
m["object_size_less_than"] = strconv.FormatInt(aws.Int64Value(filter.ObjectSizeLessThan), 10)
918921
}
919922

920923
if filter.Prefix != nil {
@@ -980,7 +983,7 @@ func FlattenLifecycleRuleNoncurrentVersionExpiration(expiration *s3.NoncurrentVe
980983
m := make(map[string]interface{})
981984

982985
if expiration.NewerNoncurrentVersions != nil {
983-
m["newer_noncurrent_versions"] = int(aws.Int64Value(expiration.NewerNoncurrentVersions))
986+
m["newer_noncurrent_versions"] = strconv.FormatInt(aws.Int64Value(expiration.NewerNoncurrentVersions), 10)
984987
}
985988

986989
if expiration.NoncurrentDays != nil {
@@ -1005,7 +1008,7 @@ func FlattenLifecycleRuleNoncurrentVersionTransitions(transitions []*s3.Noncurre
10051008
m := make(map[string]interface{})
10061009

10071010
if transition.NewerNoncurrentVersions != nil {
1008-
m["newer_noncurrent_versions"] = int(aws.Int64Value(transition.NewerNoncurrentVersions))
1011+
m["newer_noncurrent_versions"] = strconv.FormatInt(aws.Int64Value(transition.NewerNoncurrentVersions), 10)
10091012
}
10101013

10111014
if transition.NoncurrentDays != nil {

0 commit comments

Comments
 (0)