diff --git a/.changelog/19359.txt b/.changelog/19359.txt new file mode 100644 index 00000000000..d79ead83974 --- /dev/null +++ b/.changelog/19359.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_appconfig_deployment_strategy +``` diff --git a/aws/provider.go b/aws/provider.go index f8570bba6aa..bd2642be4db 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -508,6 +508,7 @@ func Provider() *schema.Provider { "aws_appautoscaling_scheduled_action": resourceAwsAppautoscalingScheduledAction(), "aws_appconfig_application": resourceAwsAppconfigApplication(), "aws_appconfig_configuration_profile": resourceAwsAppconfigConfigurationProfile(), + "aws_appconfig_deployment_strategy": resourceAwsAppconfigDeploymentStrategy(), "aws_appconfig_environment": resourceAwsAppconfigEnvironment(), "aws_appconfig_hosted_configuration_version": resourceAwsAppconfigHostedConfigurationVersion(), "aws_appmesh_gateway_route": resourceAwsAppmeshGatewayRoute(), diff --git a/aws/resource_aws_appconfig_deployment_strategy.go b/aws/resource_aws_appconfig_deployment_strategy.go new file mode 100644 index 00000000000..5f4140ecd67 --- /dev/null +++ b/aws/resource_aws_appconfig_deployment_strategy.go @@ -0,0 +1,236 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/arn" + "github.com/aws/aws-sdk-go/service/appconfig" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags" +) + +func resourceAwsAppconfigDeploymentStrategy() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsAppconfigDeploymentStrategyCreate, + Read: resourceAwsAppconfigDeploymentStrategyRead, + Update: resourceAwsAppconfigDeploymentStrategyUpdate, + Delete: resourceAwsAppconfigDeploymentStrategyDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "deployment_duration_in_minutes": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validation.IntBetween(0, 1440), + }, + "description": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(0, 1024), + }, + "final_bake_time_in_minutes": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(0, 1440), + }, + "growth_factor": { + Type: schema.TypeFloat, + Required: true, + ValidateFunc: validation.FloatBetween(1.0, 100.0), + }, + "growth_type": { + Type: schema.TypeString, + Optional: true, + Default: appconfig.GrowthTypeLinear, + ValidateFunc: validation.StringInSlice(appconfig.GrowthType_Values(), false), + }, + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 64), + }, + "replicate_to": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(appconfig.ReplicateTo_Values(), false), + }, + "tags": tagsSchema(), + "tags_all": tagsSchemaComputed(), + }, + CustomizeDiff: SetTagsDiff, + } +} + +func resourceAwsAppconfigDeploymentStrategyCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).appconfigconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig + tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{}))) + + name := d.Get("name").(string) + + input := &appconfig.CreateDeploymentStrategyInput{ + DeploymentDurationInMinutes: aws.Int64(int64(d.Get("deployment_duration_in_minutes").(int))), + GrowthFactor: aws.Float64(d.Get("growth_factor").(float64)), + GrowthType: aws.String(d.Get("growth_type").(string)), + Name: aws.String(name), + ReplicateTo: aws.String(d.Get("replicate_to").(string)), + Tags: tags.IgnoreAws().AppconfigTags(), + } + + if v, ok := d.GetOk("description"); ok { + input.Description = aws.String(v.(string)) + } + + if v, ok := d.GetOk("final_bake_time_in_minutes"); ok { + input.FinalBakeTimeInMinutes = aws.Int64(int64(v.(int))) + } + + strategy, err := conn.CreateDeploymentStrategy(input) + + if err != nil { + return fmt.Errorf("error creating AppConfig Deployment Strategy (%s): %w", name, err) + } + + d.SetId(aws.StringValue(strategy.Id)) + + return resourceAwsAppconfigDeploymentStrategyRead(d, meta) +} + +func resourceAwsAppconfigDeploymentStrategyRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).appconfigconn + defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig + ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig + + input := &appconfig.GetDeploymentStrategyInput{ + DeploymentStrategyId: aws.String(d.Id()), + } + + output, err := conn.GetDeploymentStrategy(input) + + if !d.IsNewResource() && tfawserr.ErrCodeEquals(err, appconfig.ErrCodeResourceNotFoundException) { + log.Printf("[WARN] Appconfig Deployment Strategy (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + + if err != nil { + return fmt.Errorf("error getting AppConfig Deployment Strategy (%s): %w", d.Id(), err) + } + + if output == nil { + return fmt.Errorf("error getting AppConfig Deployment Strategy (%s): empty response", d.Id()) + } + + d.Set("description", output.Description) + d.Set("deployment_duration_in_minutes", output.DeploymentDurationInMinutes) + d.Set("final_bake_time_in_minutes", output.FinalBakeTimeInMinutes) + d.Set("growth_factor", output.GrowthFactor) + d.Set("growth_type", output.GrowthType) + d.Set("name", output.Name) + d.Set("replicate_to", output.ReplicateTo) + + arn := arn.ARN{ + AccountID: meta.(*AWSClient).accountid, + Partition: meta.(*AWSClient).partition, + Region: meta.(*AWSClient).region, + Resource: fmt.Sprintf("deploymentstrategy/%s", d.Id()), + Service: "appconfig", + }.String() + d.Set("arn", arn) + + tags, err := keyvaluetags.AppconfigListTags(conn, arn) + + if err != nil { + return fmt.Errorf("error listing tags for AppConfig Deployment Strategy (%s): %w", d.Id(), err) + } + + tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig) + + //lintignore:AWSR002 + if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil { + return fmt.Errorf("error setting tags: %w", err) + } + + if err := d.Set("tags_all", tags.Map()); err != nil { + return fmt.Errorf("error setting tags_all: %w", err) + } + + return nil +} + +func resourceAwsAppconfigDeploymentStrategyUpdate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).appconfigconn + + if d.HasChangesExcept("tags", "tags_all") { + updateInput := &appconfig.UpdateDeploymentStrategyInput{ + DeploymentStrategyId: aws.String(d.Id()), + } + + if d.HasChange("deployment_duration_in_minutes") { + updateInput.DeploymentDurationInMinutes = aws.Int64(int64(d.Get("deployment_duration_in_minutes").(int))) + } + + if d.HasChange("description") { + updateInput.Description = aws.String(d.Get("description").(string)) + } + + if d.HasChange("final_bake_time_in_minutes") { + updateInput.FinalBakeTimeInMinutes = aws.Int64(int64(d.Get("final_bake_time_in_minutes").(int))) + } + + if d.HasChange("growth_factor") { + updateInput.GrowthFactor = aws.Float64(d.Get("growth_factor").(float64)) + } + + if d.HasChange("growth_type") { + updateInput.GrowthType = aws.String(d.Get("growth_type").(string)) + } + + _, err := conn.UpdateDeploymentStrategy(updateInput) + + if err != nil { + return fmt.Errorf("error updating AppConfig Deployment Strategy (%s): %w", d.Id(), err) + } + } + + if d.HasChange("tags_all") { + o, n := d.GetChange("tags_all") + if err := keyvaluetags.AppconfigUpdateTags(conn, d.Get("arn").(string), o, n); err != nil { + return fmt.Errorf("error updating AppConfig Deployment Strategy (%s) tags: %w", d.Id(), err) + } + } + + return resourceAwsAppconfigDeploymentStrategyRead(d, meta) +} + +func resourceAwsAppconfigDeploymentStrategyDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).appconfigconn + + input := &appconfig.DeleteDeploymentStrategyInput{ + DeploymentStrategyId: aws.String(d.Id()), + } + + _, err := conn.DeleteDeploymentStrategy(input) + + if tfawserr.ErrCodeEquals(err, appconfig.ErrCodeResourceNotFoundException) { + return nil + } + + if err != nil { + return fmt.Errorf("error deleting Appconfig Deployment Strategy (%s): %w", d.Id(), err) + } + + return nil +} diff --git a/aws/resource_aws_appconfig_deployment_strategy_test.go b/aws/resource_aws_appconfig_deployment_strategy_test.go new file mode 100644 index 00000000000..053a36d05c9 --- /dev/null +++ b/aws/resource_aws_appconfig_deployment_strategy_test.go @@ -0,0 +1,317 @@ +package aws + +import ( + "fmt" + "regexp" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/appconfig" + "github.com/hashicorp/aws-sdk-go-base/tfawserr" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func TestAccAWSAppConfigDeploymentStrategy_basic(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_appconfig_deployment_strategy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, appconfig.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAppConfigDeploymentStrategyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAppConfigDeploymentStrategyConfigName(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "appconfig", regexp.MustCompile(`deploymentstrategy/[a-z0-9]{4,7}`)), + resource.TestCheckResourceAttr(resourceName, "deployment_duration_in_minutes", "3"), + resource.TestCheckResourceAttr(resourceName, "growth_factor", "10"), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttr(resourceName, "replicate_to", appconfig.ReplicateToNone), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSAppConfigDeploymentStrategy_updateDescription(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + description := acctest.RandomWithPrefix("tf-acc-test-update") + resourceName := "aws_appconfig_deployment_strategy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, appconfig.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAppConfigDeploymentStrategyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAppConfigDeploymentStrategyConfigDescription(rName, rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", rName), + ), + }, + { + Config: testAccAWSAppConfigDeploymentStrategyConfigDescription(rName, description), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "description", description), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAWSAppConfigDeploymentStrategy_updateFinalBakeTime(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_appconfig_deployment_strategy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, appconfig.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAppConfigDeploymentStrategyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAppConfigDeploymentStrategyConfigFinalBakeTime(rName, 60), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "final_bake_time_in_minutes", "60"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAppConfigDeploymentStrategyConfigFinalBakeTime(rName, 30), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "final_bake_time_in_minutes", "30"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + // Test FinalBakeTimeInMinutes Removal + Config: testAccAWSAppConfigDeploymentStrategyConfigName(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + ), + }, + }, + }) +} + +func TestAccAWSAppConfigDeploymentStrategy_disappears(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_appconfig_deployment_strategy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, appconfig.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAppConfigDeploymentStrategyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAppConfigDeploymentStrategyConfigName(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + testAccCheckResourceDisappears(testAccProvider, resourceAwsAppconfigDeploymentStrategy(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccAWSAppConfigDeploymentStrategy_Tags(t *testing.T) { + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_appconfig_deployment_strategy.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ErrorCheck: testAccErrorCheck(t, appconfig.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAppConfigDeploymentStrategyDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAppConfigDeploymentStrategyTags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAppConfigDeploymentStrategyTags2(rName, "key1", "value1updated", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccAWSAppConfigDeploymentStrategyTags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func testAccCheckAppConfigDeploymentStrategyDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).appconfigconn + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_appconfig_deployment_strategy" { + continue + } + + input := &appconfig.GetDeploymentStrategyInput{ + DeploymentStrategyId: aws.String(rs.Primary.ID), + } + + output, err := conn.GetDeploymentStrategy(input) + + if tfawserr.ErrCodeEquals(err, appconfig.ErrCodeResourceNotFoundException) { + continue + } + + if err != nil { + return fmt.Errorf("error getting Appconfig Deployment Strategy (%s): %w", rs.Primary.ID, err) + } + + if output != nil { + return fmt.Errorf("AppConfig Deployment Strategy (%s) still exists", rs.Primary.ID) + } + } + + return nil +} + +func testAccCheckAWSAppConfigDeploymentStrategyExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Resource not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("Resource (%s) ID not set", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).appconfigconn + + input := &appconfig.GetDeploymentStrategyInput{ + DeploymentStrategyId: aws.String(rs.Primary.ID), + } + + output, err := conn.GetDeploymentStrategy(input) + + if err != nil { + return fmt.Errorf("error getting Appconfig Deployment Strategy (%s): %w", rs.Primary.ID, err) + } + + if output == nil { + return fmt.Errorf("AppConfig Deployment Strategy (%s) not found", rs.Primary.ID) + } + + return nil + } +} + +func testAccAWSAppConfigDeploymentStrategyConfigName(rName string) string { + return fmt.Sprintf(` +resource "aws_appconfig_deployment_strategy" "test" { + name = %[1]q + deployment_duration_in_minutes = 3 + growth_factor = 10 + replicate_to = "NONE" +} +`, rName) +} + +func testAccAWSAppConfigDeploymentStrategyConfigDescription(rName, description string) string { + return fmt.Sprintf(` +resource "aws_appconfig_deployment_strategy" "test" { + name = %[1]q + deployment_duration_in_minutes = 3 + description = %[2]q + growth_factor = 10 + replicate_to = "NONE" +} +`, rName, description) +} + +func testAccAWSAppConfigDeploymentStrategyConfigFinalBakeTime(rName string, time int) string { + return fmt.Sprintf(` +resource "aws_appconfig_deployment_strategy" "test" { + name = %[1]q + deployment_duration_in_minutes = 3 + final_bake_time_in_minutes = %[2]d + growth_factor = 10 + replicate_to = "NONE" +} +`, rName, time) +} + +func testAccAWSAppConfigDeploymentStrategyTags1(rName, tagKey1, tagValue1 string) string { + return fmt.Sprintf(` +resource "aws_appconfig_deployment_strategy" "test" { + name = %[1]q + deployment_duration_in_minutes = 3 + growth_factor = 10 + replicate_to = "NONE" + + tags = { + %[2]q = %[3]q + } +} +`, rName, tagKey1, tagValue1) +} + +func testAccAWSAppConfigDeploymentStrategyTags2(rName, tagKey1, tagValue1, tagKey2, tagValue2 string) string { + return fmt.Sprintf(` +resource "aws_appconfig_deployment_strategy" "test" { + name = %[1]q + deployment_duration_in_minutes = 3 + growth_factor = 10 + replicate_to = "NONE" + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, tagKey1, tagValue1, tagKey2, tagValue2) +} diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 9f38e67fa0f..570f08ad738 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -253,6 +253,7 @@ for more information about connecting to alternate AWS endpoints or AWS compatib - [`aws_apigatewayv2_stage` resource](/docs/providers/aws/r/apigatewayv2_stage.html) - [`aws_appconfig_application` resource](/docs/providers/aws/r/appconfig_application.html) - [`aws_appconfig_configuration_profile` resource](/docs/providers/aws/r/appconfig_configuration_profile.html) + - [`aws_appconfig_deployment_strategy` resource](/docs/providers/aws/r/appconfig_deployment_strategy.html) - [`aws_appconfig_environment` resource](/docs/providers/aws/r/appconfig_environment.html) - [`aws_appconfig_hosted_configuration_version` resource](/docs/providers/aws/r/appconfig_hosted_configuration_version.html) - [`aws_athena_workgroup` resource](/docs/providers/aws/r/athena_workgroup.html) diff --git a/website/docs/r/appconfig_deployment_strategy.html.markdown b/website/docs/r/appconfig_deployment_strategy.html.markdown new file mode 100644 index 00000000000..139672745bd --- /dev/null +++ b/website/docs/r/appconfig_deployment_strategy.html.markdown @@ -0,0 +1,58 @@ +--- +subcategory: "AppConfig" +layout: "aws" +page_title: "AWS: aws_appconfig_deployment_strategy" +description: |- + Provides an AppConfig Deployment Strategy resource. +--- + +# Resource: aws_appconfig_deployment_strategy + +Provides an AppConfig Deployment Strategy resource. + +## Example Usage + +```terraform +resource "aws_appconfig_deployment_strategy" "example" { + name = "example-deployment-strategy-tf" + description = "Example Deployment Strategy" + deployment_duration_in_minutes = 3 + final_bake_time_in_minutes = 4 + growth_factor = 10 + growth_type = "LINEAR" + replicate_to = "NONE" + + tags = { + Type = "AppConfig Deployment Strategy" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `deployment_duration_in_minutes` - (Required) Total amount of time for a deployment to last. Minimum value of 0, maximum value of 1440. +* `growth_factor` - (Required) The percentage of targets to receive a deployed configuration during each interval. Minimum value of 1.0, maximum value of 100.0. +* `name` - (Required, Forces new resource) A name for the deployment strategy. Must be between 1 and 64 characters in length. +* `replicate_to` - (Required, Forces new resource) Where to save the deployment strategy. Valid values: `NONE` and `SSM_DOCUMENT`. +* `description` - (Optional) A description of the deployment strategy. Can be at most 1024 characters. +* `final_bake_time_in_minutes` - (Optional) The amount of time AWS AppConfig monitors for alarms before considering the deployment to be complete and no longer eligible for automatic roll back. Minimum value of 0, maximum value of 1440. +* `growth_type` - (Optional) The algorithm used to define how percentage grows over time. Valid value: `LINEAR` and `EXPONENTIAL`. Defaults to `LINEAR`. +* `tags` - (Optional) A map of tags to assign to the resource. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The AppConfig deployment strategy ID. +* `arn` - The Amazon Resource Name (ARN) of the AppConfig Deployment Strategy. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block). + +## Import + +AppConfig Deployment Strategies can be imported by using their deployment strategy ID, e.g. + +``` +$ terraform import aws_appconfig_deployment_strategy.example 11xxxxx +```