Skip to content

Commit

Permalink
r/aws_datasync_task: add task_report_config argument (#33861)
Browse files Browse the repository at this point in the history
* upd: introduced functionality to configure datasync task reports

* upd: WIP testing for datasync task reports

* upd: updated registry documentation for datasync task reports

* upd: bumping aws-sdk-go to 1.45.x for datasync task report config options

* Revert "upd: bumping aws-sdk-go to 1.45.x for datasync task report config options"

This reverts commit 89036cd.

* update go.mod

* go.mod updated

* build out acc test

* test case works, need assertions

* add additonal test cases

* fix test formatting

* remove trailing newline

* chore: go mod tidy

* chore: changelog

* r/aws_datasync_task(doc): link to argument reference headers

* r/aws_datasync_task: rm update input log

* r/aws_datasync_task(test): standardize task report config test naming

---------

Co-authored-by: rizkybiz <justin.defrank@hashicorp.com>
Co-authored-by: Bruce Harrison <bruce.harrison@hashicorp.com>
Co-authored-by: Jared Baker <jared.baker@hashicorp.com>
  • Loading branch information
4 people authored Nov 3, 2023
1 parent 8f5191d commit d4b1dc3
Show file tree
Hide file tree
Showing 4 changed files with 330 additions and 3 deletions.
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

0 comments on commit d4b1dc3

Please sign in to comment.