diff --git a/.changelog/23515.txt b/.changelog/23515.txt new file mode 100644 index 000000000000..52aeb23c4f8c --- /dev/null +++ b/.changelog/23515.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +resource/aws_ssm_association: Add `sync_compliance` attribute +``` diff --git a/internal/service/ssm/association.go b/internal/service/ssm/association.go index f620c021b64a..b3a8f702918b 100644 --- a/internal/service/ssm/association.go +++ b/internal/service/ssm/association.go @@ -43,6 +43,11 @@ func ResourceAssociation() *schema.Resource { Default: false, Optional: true, }, + "sync_compliance": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"AUTO", "MANUAL"}, false), + }, "association_name": { Type: schema.TypeString, Optional: true, @@ -166,6 +171,10 @@ func resourceAssociationCreate(ctx context.Context, d *schema.ResourceData, meta Name: aws.String(d.Get("name").(string)), } + if v, ok := d.GetOk("sync_compliance"); ok { + associationInput.SyncCompliance = aws.String(v.(string)) + } + if v, ok := d.GetOk("apply_only_at_cron_interval"); ok { associationInput.ApplyOnlyAtCronInterval = aws.Bool(v.(bool)) } @@ -260,6 +269,7 @@ func resourceAssociationRead(ctx context.Context, d *schema.ResourceData, meta i Resource: fmt.Sprintf("association/%s", aws.StringValue(association.AssociationId)), }.String() d.Set("arn", arn) + d.Set("sync_compliance", association.SyncCompliance) d.Set("apply_only_at_cron_interval", association.ApplyOnlyAtCronInterval) d.Set("association_name", association.AssociationName) d.Set("instance_id", association.InstanceId) diff --git a/internal/service/ssm/association_test.go b/internal/service/ssm/association_test.go index 5a776894fbf8..676767698010 100644 --- a/internal/service/ssm/association_test.go +++ b/internal/service/ssm/association_test.go @@ -608,6 +608,32 @@ func TestAccSSMAssociation_rateControl(t *testing.T) { }) } +func TestAccSSMAssociation_syncCompliance(t *testing.T) { + rName := "AWS-RunPatchBaselineAssociation" + resourceName := "aws_ssm_association.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest.PreCheck(t) }, + ErrorCheck: acctest.ErrorCheck(t, ssm.EndpointsID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAssociationSyncComplianceConfig(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAssociationExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "sync_compliance", "MANUAL"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testAccCheckAssociationExists(ctx context.Context, n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -1569,6 +1595,30 @@ resource "aws_ssm_association" "test" { `, rName, rate) } +func testAccAssociationSyncComplianceConfig(rName string) string { + return fmt.Sprintf(` +resource "aws_ssm_association" "test" { + name = %[1]q + targets { + key = "InstanceIds" + values = ["*"] + } + apply_only_at_cron_interval = false + sync_compliance = "MANUAL" + parameters = { + Operation = "Scan" + RebootOption = "NoReboot" + } + schedule_expression = "cron(0 6 ? * * *)" + lifecycle { + ignore_changes = [ + parameters["AssociationId"] + ] + } +} +`, rName) +} + func testAccAssociationConfig_outputLocationAndWaitForSuccess(rName string) string { return acctest.ConfigCompose( testAccAssociationWithOutputLocationS3RegionConfigBase(rName), diff --git a/website/docs/r/ssm_association.html.markdown b/website/docs/r/ssm_association.html.markdown index 4e4aca7b1ce1..05642c5bd37c 100644 --- a/website/docs/r/ssm_association.html.markdown +++ b/website/docs/r/ssm_association.html.markdown @@ -84,6 +84,7 @@ resource "aws_ssm_association" "example" { The following arguments are supported: * `name` - (Required) The name of the SSM document to apply. +* `sync_compliance` - (Optional) The mode for generating association compliance. You can specify `AUTO` or `MANUAL`. * `apply_only_at_cron_interval` - (Optional) By default, when you create a new or update associations, the system runs it immediately and then according to the schedule you specified. Enable this option if you do not want an association to run immediately after you create or update it. This parameter is not supported for rate expressions. Default: `false`. * `association_name` - (Optional) The descriptive name for the association. * `document_version` - (Optional) The document version you want to associate with the target(s). Can be a specific version or the default version.