Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

r/aws_datasync_task: add task_report_config argument #33861

Merged
merged 18 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/33861.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_datasync_task: Add `task_report_config` argument
```
188 changes: 186 additions & 2 deletions internal/service/datasync/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,82 @@ func ResourceTask() *schema.Resource {
},
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
"task_report_config": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"s3_destination": {
Type: schema.TypeList,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"bucket_access_role_arn": {
Type: schema.TypeString,
Required: true,
ValidateFunc: verify.ValidARN,
},
"s3_bucket_arn": {
Type: schema.TypeString,
Required: true,
ValidateFunc: verify.ValidARN,
},
"subdirectory": {
Type: schema.TypeString,
Optional: true,
},
},
},
},
"s3_object_versioning": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ObjectVersionIds_Values(), false),
},
"output_type": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ReportOutputType_Values(), false),
},
"report_overrides": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"deleted_override": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ReportLevel_Values(), false),
},
"skipped_override": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ReportLevel_Values(), false),
},
"transferred_override": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ReportLevel_Values(), false),
},
"verified_override": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ReportLevel_Values(), false),
},
},
},
},
"report_level": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice(datasync.ReportLevel_Values(), false),
},
},
},
},
},

CustomizeDiff: verify.SetTagsDiff,
Expand Down Expand Up @@ -255,6 +331,10 @@ func resourceTaskCreate(ctx context.Context, d *schema.ResourceData, meta interf
input.Name = aws.String(v.(string))
}

if v, ok := d.GetOk("task_report_config"); ok {
input.TaskReportConfig = expandTaskReportConfig(v.([]interface{}))
}

if v, ok := d.GetOk("schedule"); ok {
input.Schedule = expandTaskSchedule(v.([]interface{}))
}
Expand Down Expand Up @@ -306,6 +386,9 @@ func resourceTaskRead(ctx context.Context, d *schema.ResourceData, meta interfac
if err := d.Set("schedule", flattenTaskSchedule(output.Schedule)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting schedule: %s", err)
}
if err := d.Set("task_report_config", flattenTaskReportConfig(output.TaskReportConfig)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting task_report_config: %s", err)
}
d.Set("source_location_arn", output.SourceLocationArn)

return diags
Expand Down Expand Up @@ -344,9 +427,11 @@ func resourceTaskUpdate(ctx context.Context, d *schema.ResourceData, meta interf
input.Schedule = expandTaskSchedule(d.Get("schedule").([]interface{}))
}

_, err := conn.UpdateTaskWithContext(ctx, input)
if d.HasChanges("task_report_config") {
input.TaskReportConfig = expandTaskReportConfig(d.Get("task_report_config").([]interface{}))
}

if err != nil {
if _, err := conn.UpdateTaskWithContext(ctx, input); err != nil {
return sdkdiag.AppendErrorf(diags, "updating DataSync Task (%s): %s", d.Id(), err)
}
}
Expand Down Expand Up @@ -462,6 +547,51 @@ func flattenOptions(options *datasync.Options) []interface{} {
return []interface{}{m}
}

func flattenTaskReportConfig(options *datasync.TaskReportConfig) []interface{} {
if options == nil {
return []interface{}{}
}

m := map[string]interface{}{
"s3_object_versioning": aws.StringValue(options.ObjectVersionIds),
"output_type": aws.StringValue(options.OutputType),
"report_level": aws.StringValue(options.ReportLevel),
"s3_destination": flattenTaskReportConfigS3Destination(options.Destination.S3),
"report_overrides": flattenTaskReportConfigReportOverrides(options.Overrides),
}

return []interface{}{m}
}

func flattenTaskReportConfigReportOverrides(options *datasync.ReportOverrides) []interface{} {
if options == nil {
return []interface{}{}
}

m := map[string]interface{}{
"deleted_override": aws.StringValue(options.Deleted.ReportLevel),
"skipped_override": aws.StringValue(options.Skipped.ReportLevel),
"transferred_override": aws.StringValue(options.Transferred.ReportLevel),
"verified_override": aws.StringValue(options.Verified.ReportLevel),
}

return []interface{}{m}
}

func flattenTaskReportConfigS3Destination(options *datasync.ReportDestinationS3) []interface{} {
if options == nil {
return []interface{}{}
}

m := map[string]interface{}{
"bucket_access_role_arn": aws.StringValue(options.BucketAccessRoleArn),
"s3_bucket_arn": aws.StringValue(options.S3BucketArn),
"subdirectory": aws.StringValue(options.Subdirectory),
}

return []interface{}{m}
}

func expandOptions(l []interface{}) *datasync.Options {
if len(l) == 0 || l[0] == nil {
return nil
Expand Down Expand Up @@ -522,6 +652,60 @@ func flattenTaskSchedule(schedule *datasync.TaskSchedule) []interface{} {
return []interface{}{m}
}

func expandTaskReportConfig(l []interface{}) *datasync.TaskReportConfig {
if len(l) == 0 || l[0] == nil {
return nil
}
reportConfig := &datasync.TaskReportConfig{}

m := l[0].(map[string]interface{})

dest := m["s3_destination"].([]interface{})
reportConfig = reportConfig.SetDestination(expandTaskReportDestination(dest))
reportConfig = reportConfig.SetObjectVersionIds(m["s3_object_versioning"].(string))
reportConfig = reportConfig.SetOutputType(m["output_type"].(string))
reportConfig = reportConfig.SetReportLevel(m["report_level"].(string))
o := m["report_overrides"].([]interface{})
reportConfig = reportConfig.SetOverrides(expandTaskReportOverrides(o))

return reportConfig
}

func expandTaskReportDestination(l []interface{}) *datasync.ReportDestination {
if len(l) == 0 || l[0] == nil {
return nil
}
m := l[0].(map[string]interface{})
return &datasync.ReportDestination{
S3: &datasync.ReportDestinationS3{
BucketAccessRoleArn: aws.String(m["bucket_access_role_arn"].(string)),
S3BucketArn: aws.String(m["s3_bucket_arn"].(string)),
Subdirectory: aws.String(m["subdirectory"].(string)),
},
}
}

func expandTaskReportOverrides(l []interface{}) *datasync.ReportOverrides {
if len(l) == 0 || l[0] == nil {
return nil
}
m := l[0].(map[string]interface{})
return &datasync.ReportOverrides{
Deleted: &datasync.ReportOverride{
ReportLevel: aws.String(m["deleted_override"].(string)),
},
Skipped: &datasync.ReportOverride{
ReportLevel: aws.String(m["skipped_override"].(string)),
},
Transferred: &datasync.ReportOverride{
ReportLevel: aws.String(m["transferred_override"].(string)),
},
Verified: &datasync.ReportOverride{
ReportLevel: aws.String(m["verified_override"].(string)),
},
}
}

func expandFilterRules(l []interface{}) []*datasync.FilterRule {
filterRules := []*datasync.FilterRule{}

Expand Down
112 changes: 112 additions & 0 deletions internal/service/datasync/task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,46 @@ func TestAccDataSyncTask_DefaultSyncOptions_verifyMode(t *testing.T) {
})
}

func TestAccDataSyncTask_taskReportConfig(t *testing.T) {
ctx := acctest.Context(t)
var task1 datasync.DescribeTaskOutput
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_datasync_task.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, datasync.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckTaskDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccTaskConfig_taskReportConfig(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckTaskExists(ctx, resourceName, &task1),
resource.TestCheckResourceAttr(resourceName, "task_report_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.output_type", "STANDARD"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.report_level", "SUCCESSES_AND_ERRORS"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.s3_destination.#", "1"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.s3_object_versioning", "INCLUDE"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.s3_destination.0.subdirectory", "test/"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.report_overrides.#", "1"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.report_overrides.0.deleted_override", "ERRORS_ONLY"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.report_overrides.0.skipped_override", "ERRORS_ONLY"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.report_overrides.0.transferred_override", "ERRORS_ONLY"),
resource.TestCheckResourceAttr(resourceName, "task_report_config.0.report_overrides.0.verified_override", "ERRORS_ONLY"),
resource.TestCheckResourceAttrPair(resourceName, "task_report_config.0.s3_destination.0.bucket_access_role_arn", "aws_iam_role.report_test", "arn"),
resource.TestCheckResourceAttrPair(resourceName, "task_report_config.0.s3_destination.0.s3_bucket_arn", "aws_s3_bucket.report_test", "arn"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccDataSyncTask_tags(t *testing.T) {
ctx := acctest.Context(t)
var task1, task2, task3 datasync.DescribeTaskOutput
Expand Down Expand Up @@ -1463,3 +1503,75 @@ resource "aws_datasync_task" "test" {
}
`, rName, key1, value1, key2, value2))
}

func testAccTaskConfig_taskReportConfig(rName string) string {
return acctest.ConfigCompose(
testAccTaskConfig_baseLocationS3(rName),
testAccTaskConfig_baseLocationNFS(rName),
fmt.Sprintf(`
resource "aws_s3_bucket" "report_test" {
bucket = "%[1]s-report-test"
force_destroy = true
}

resource "aws_iam_role" "report_test" {
name = "%[1]s-report-test"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "datasync.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
POLICY
}

resource "aws_iam_role_policy" "report_test" {
role = aws_iam_role.report_test.id
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"s3:*"
],
"Effect": "Allow",
"Resource": [
"${aws_s3_bucket.report_test.arn}",
"${aws_s3_bucket.report_test.arn}/*"
]
}]
}
POLICY
}

resource "aws_datasync_task" "test" {
destination_location_arn = aws_datasync_location_s3.test.arn
name = %[1]q
source_location_arn = aws_datasync_location_nfs.test.arn

task_report_config {
s3_destination {
bucket_access_role_arn = aws_iam_role.report_test.arn
s3_bucket_arn = aws_s3_bucket.report_test.arn
subdirectory = "test/"
}
report_overrides {
deleted_override = "ERRORS_ONLY"
skipped_override = "ERRORS_ONLY"
transferred_override = "ERRORS_ONLY"
verified_override = "ERRORS_ONLY"
}
s3_object_versioning = "INCLUDE"
output_type = "STANDARD"
report_level = "SUCCESSES_AND_ERRORS"
}
}
`, rName))
}
Loading
Loading