From eb91b315aa816f1a4f0d54563e08ab79fb0145d4 Mon Sep 17 00:00:00 2001 From: Atsushi Ishibashi Date: Sun, 17 Mar 2019 02:28:37 +0900 Subject: [PATCH 1/3] resource/ssm_association: Support MaxConcurrency and MaxErrors --- aws/resource_aws_ssm_association.go | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/aws/resource_aws_ssm_association.go b/aws/resource_aws_ssm_association.go index 2cb8d04ba6d..322dcb5765c 100644 --- a/aws/resource_aws_ssm_association.go +++ b/aws/resource_aws_ssm_association.go @@ -3,6 +3,7 @@ package aws import ( "fmt" "log" + "regexp" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ssm" @@ -39,6 +40,30 @@ func resourceAwsSsmAssociation() *schema.Resource { Optional: true, Computed: true, }, + "max_concurrency": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { + value := v.(string) + if !regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`).MatchString(value) { + es = append(es, fmt.Errorf( + "%q invalid format", k)) + } + return + }, + }, + "max_errors": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { + value := v.(string) + if !regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`).MatchString(value) { + es = append(es, fmt.Errorf( + "%q invalid format", k)) + } + return + }, + }, "name": { Type: schema.TypeString, ForceNew: true, From 9066433b7ef528716b2f9afb78f33c5c5c6cecd2 Mon Sep 17 00:00:00 2001 From: Atsushi Ishibashi Date: Sun, 17 Mar 2019 13:13:43 +0900 Subject: [PATCH 2/3] Fix conflicts, modfiy validateFunc and docs --- aws/resource_aws_ssm_association.go | 44 +++++++------ aws/resource_aws_ssm_association_test.go | 67 ++++++++++++++++++++ website/docs/r/ssm_association.html.markdown | 2 + 3 files changed, 93 insertions(+), 20 deletions(-) diff --git a/aws/resource_aws_ssm_association.go b/aws/resource_aws_ssm_association.go index 322dcb5765c..e9be06ed684 100644 --- a/aws/resource_aws_ssm_association.go +++ b/aws/resource_aws_ssm_association.go @@ -41,28 +41,14 @@ func resourceAwsSsmAssociation() *schema.Resource { Computed: true, }, "max_concurrency": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { - value := v.(string) - if !regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`).MatchString(value) { - es = append(es, fmt.Errorf( - "%q invalid format", k)) - } - return - }, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[1-9][0-9]%|[1-9]%|100%)$`), "must be a valid number (e.g. 10) or percentage including the percent sign (e.g. 10%)"), }, "max_errors": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: func(v interface{}, k string) (ws []string, es []error) { - value := v.(string) - if !regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`).MatchString(value) { - es = append(es, fmt.Errorf( - "%q invalid format", k)) - } - return - }, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[1-9][0-9]%|[1-9]%|100%)$`), "must be a valid number (e.g. 10) or percentage including the percent sign (e.g. 10%)"), }, "name": { Type: schema.TypeString, @@ -170,6 +156,14 @@ func resourceAwsSsmAssociationCreate(d *schema.ResourceData, meta interface{}) e associationInput.ComplianceSeverity = aws.String(v.(string)) } + if v, ok := d.GetOk("max_concurrency"); ok { + associationInput.MaxConcurrency = aws.String(v.(string)) + } + + if v, ok := d.GetOk("max_errors"); ok { + associationInput.MaxErrors = aws.String(v.(string)) + } + resp, err := ssmconn.CreateAssociation(associationInput) if err != nil { return fmt.Errorf("Error creating SSM association: %s", err) @@ -216,6 +210,8 @@ func resourceAwsSsmAssociationRead(d *schema.ResourceData, meta interface{}) err d.Set("schedule_expression", association.ScheduleExpression) d.Set("document_version", association.DocumentVersion) d.Set("compliance_severity", association.ComplianceSeverity) + d.Set("max_concurrency", association.MaxConcurrency) + d.Set("max_errors", association.MaxErrors) if err := d.Set("targets", flattenAwsSsmTargets(association.Targets)); err != nil { return fmt.Errorf("Error setting targets error: %#v", err) @@ -266,6 +262,14 @@ func resourceAwsSsmAssociationUpdate(d *schema.ResourceData, meta interface{}) e associationInput.ComplianceSeverity = aws.String(v.(string)) } + if v, ok := d.GetOk("max_concurrency"); ok { + associationInput.MaxConcurrency = aws.String(v.(string)) + } + + if v, ok := d.GetOk("max_errors"); ok { + associationInput.MaxErrors = aws.String(v.(string)) + } + _, err := ssmconn.UpdateAssociation(associationInput) if err != nil { return fmt.Errorf("Error updating SSM association: %s", err) diff --git a/aws/resource_aws_ssm_association_test.go b/aws/resource_aws_ssm_association_test.go index 7fb626830b7..869b2b9a973 100644 --- a/aws/resource_aws_ssm_association_test.go +++ b/aws/resource_aws_ssm_association_test.go @@ -342,6 +342,37 @@ func TestAccAWSSSMAssociation_withComplianceSeverity(t *testing.T) { }) } +func TestAccAWSSSMAssociation_rateControl(t *testing.T) { + name := acctest.RandString(10) + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSSMAssociationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSSSMAssociationRateControlConfig(name, "10%"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMAssociationExists("aws_ssm_association.foo"), + resource.TestCheckResourceAttr( + "aws_ssm_association.foo", "max_concurrency", "10%"), + resource.TestCheckResourceAttr( + "aws_ssm_association.foo", "max_errors", "10%"), + ), + }, + { + Config: testAccAWSSSMAssociationRateControlConfig(name, "20%"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSSMAssociationExists("aws_ssm_association.foo"), + resource.TestCheckResourceAttr( + "aws_ssm_association.foo", "max_concurrency", "20%"), + resource.TestCheckResourceAttr( + "aws_ssm_association.foo", "max_errors", "20%"), + ), + }, + }, + }) +} + func testAccCheckAWSSSMAssociationExists(n string) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -959,3 +990,39 @@ resource "aws_ssm_association" "foo" { } `, rName, assocName, compSeverity) } + +func testAccAWSSSMAssociationRateControlConfig(rName, rate string) string { + return fmt.Sprintf(` +resource "aws_ssm_document" "foo_document" { + name = "tf-test-ssm-document-%s" + document_type = "Command" + content = < Date: Mon, 18 Mar 2019 07:47:16 +0900 Subject: [PATCH 3/3] Update aws/resource_aws_ssm_association.go Co-Authored-By: atsushi-ishibashi --- aws/resource_aws_ssm_association.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws/resource_aws_ssm_association.go b/aws/resource_aws_ssm_association.go index e9be06ed684..397570d075b 100644 --- a/aws/resource_aws_ssm_association.go +++ b/aws/resource_aws_ssm_association.go @@ -48,7 +48,7 @@ func resourceAwsSsmAssociation() *schema.Resource { "max_errors": { Type: schema.TypeString, Optional: true, - ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[1-9][0-9]%|[1-9]%|100%)$`), "must be a valid number (e.g. 10) or percentage including the percent sign (e.g. 10%)"), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^([1-9][0-9]*|[0]|[1-9][0-9]%|[0-9]%|100%)$`), "must be a valid number (e.g. 10) or percentage including the percent sign (e.g. 10%)"), }, "name": { Type: schema.TypeString,