From d7cc6d9ed81d10574ff86fbd7a13a0d62b61bfc6 Mon Sep 17 00:00:00 2001 From: Keisuke Nishida Date: Fri, 7 Feb 2020 01:12:23 +0900 Subject: [PATCH 1/5] Add aws_amplify_backend_environment resource --- aws/provider.go | 1 + ...esource_aws_amplify_backend_environment.go | 145 ++++++++++++++++ ...ce_aws_amplify_backend_environment_test.go | 156 ++++++++++++++++++ .../amplify_backend_environment.html.markdown | 50 ++++++ 4 files changed, 352 insertions(+) create mode 100644 aws/resource_aws_amplify_backend_environment.go create mode 100644 aws/resource_aws_amplify_backend_environment_test.go create mode 100644 website/docs/r/amplify_backend_environment.html.markdown diff --git a/aws/provider.go b/aws/provider.go index a66754c0123..847612d67a5 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -451,6 +451,7 @@ func Provider() *schema.Provider { "aws_ami_from_instance": resourceAwsAmiFromInstance(), "aws_ami_launch_permission": resourceAwsAmiLaunchPermission(), "aws_amplify_app": resourceAwsAmplifyApp(), + "aws_amplify_backend_environment": resourceAwsAmplifyBackendEnvironment(), "aws_api_gateway_account": resourceAwsApiGatewayAccount(), "aws_api_gateway_api_key": resourceAwsApiGatewayApiKey(), "aws_api_gateway_authorizer": resourceAwsApiGatewayAuthorizer(), diff --git a/aws/resource_aws_amplify_backend_environment.go b/aws/resource_aws_amplify_backend_environment.go new file mode 100644 index 00000000000..c4cca6f4a33 --- /dev/null +++ b/aws/resource_aws_amplify_backend_environment.go @@ -0,0 +1,145 @@ +package aws + +import ( + "fmt" + "log" + "regexp" + "strings" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/awserr" + "github.com/aws/aws-sdk-go/service/amplify" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" +) + +func resourceAwsAmplifyBackendEnvironment() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsAmplifyBackendEnvironmentCreate, + Read: resourceAwsAmplifyBackendEnvironmentRead, + Delete: resourceAwsAmplifyBackendEnvironmentDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "arn": { + Type: schema.TypeString, + Computed: true, + }, + "app_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "deployment_artifacts": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 100), + validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9-]+$`), "should not contain special characters"), + ), + }, + "environment_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(2, 10), + validation.StringMatch(regexp.MustCompile(`^[a-z]+$`), "should only contain lowercase alphabets"), + ), + }, + "stack_name": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.All( + validation.StringLenBetween(1, 100), + validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9-]+$`), "should not contain special characters"), + ), + }, + }, + } +} + +func resourceAwsAmplifyBackendEnvironmentCreate(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).amplifyconn + log.Print("[DEBUG] Creating Amplify BackendEnvironment") + + params := &lify.CreateBackendEnvironmentInput{ + AppId: aws.String(d.Get("app_id").(string)), + EnvironmentName: aws.String(d.Get("environment_name").(string)), + } + + if v, ok := d.GetOk("deployment_artifacts"); ok { + params.DeploymentArtifacts = aws.String(v.(string)) + } + + if v, ok := d.GetOk("stack_name"); ok { + params.StackName = aws.String(v.(string)) + } + + resp, err := conn.CreateBackendEnvironment(params) + if err != nil { + return fmt.Errorf("Error creating Amplify BackendEnvironment: %s", err) + } + + arn := *resp.BackendEnvironment.BackendEnvironmentArn + d.SetId(arn[strings.Index(arn, ":apps/")+len(":apps/"):]) + + return resourceAwsAmplifyBackendEnvironmentRead(d, meta) +} + +func resourceAwsAmplifyBackendEnvironmentRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).amplifyconn + log.Printf("[DEBUG] Reading Amplify BackendEnvironment: %s", d.Id()) + + s := strings.Split(d.Id(), "/") + app_id := s[0] + environment_name := s[2] + + resp, err := conn.GetBackendEnvironment(&lify.GetBackendEnvironmentInput{ + AppId: aws.String(app_id), + EnvironmentName: aws.String(environment_name), + }) + if err != nil { + if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == amplify.ErrCodeNotFoundException { + log.Printf("[WARN] Amplify BackendEnvironment (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } + return err + } + + d.Set("app_id", app_id) + d.Set("arn", resp.BackendEnvironment.BackendEnvironmentArn) + d.Set("deployment_artifacts", resp.BackendEnvironment.DeploymentArtifacts) + d.Set("environment_name", resp.BackendEnvironment.EnvironmentName) + d.Set("stack_name", resp.BackendEnvironment.StackName) + + return nil +} + +func resourceAwsAmplifyBackendEnvironmentDelete(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).amplifyconn + log.Printf("[DEBUG] Deleting Amplify BackendEnvironment: %s", d.Id()) + + s := strings.Split(d.Id(), "/") + app_id := s[0] + environment_name := s[2] + + params := &lify.DeleteBackendEnvironmentInput{ + AppId: aws.String(app_id), + EnvironmentName: aws.String(environment_name), + } + + _, err := conn.DeleteBackendEnvironment(params) + if err != nil { + return fmt.Errorf("Error deleting Amplify BackendEnvironment: %s", err) + } + + return nil +} diff --git a/aws/resource_aws_amplify_backend_environment_test.go b/aws/resource_aws_amplify_backend_environment_test.go new file mode 100644 index 00000000000..902eda55b15 --- /dev/null +++ b/aws/resource_aws_amplify_backend_environment_test.go @@ -0,0 +1,156 @@ +package aws + +import ( + "errors" + "fmt" + "regexp" + "strings" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/amplify" + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" +) + +func TestAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { + var env1, env2 amplify.BackendEnvironment + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_amplify_backend_environment.test" + + envName := "backend" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAmplifyBackendEnvironmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAmplifyBackendEnvironmentConfig_Required(rName, envName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env1), + resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile("^arn:[^:]+:amplify:[^:]+:[^:]+:apps/[^/]+/backendenvironments/"+envName)), + resource.TestCheckResourceAttr(resourceName, "environment_name", envName), + resource.TestMatchResourceAttr(resourceName, "deployment_artifacts", regexp.MustCompile(fmt.Sprintf("^tf-acc-test-.*-%s-.*-deployment$", envName))), + resource.TestMatchResourceAttr(resourceName, "stack_name", regexp.MustCompile(fmt.Sprintf("^amplify-tf-acc-test-.*-%s-.*$", envName))), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAWSAmplifyBackendEnvironmentConfigAll(rName, envName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env2), + testAccCheckAWSAmplifyBackendEnvironmentRecreated(&env1, &env2), + resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile("^arn:[^:]+:amplify:[^:]+:[^:]+:apps/[^/]+/backendenvironments/"+envName)), + resource.TestCheckResourceAttr(resourceName, "environment_name", envName), + resource.TestCheckResourceAttr(resourceName, "deployment_artifacts", rName), + resource.TestCheckResourceAttr(resourceName, "stack_name", rName), + ), + }, + }, + }) +} + +func testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName string, v *amplify.BackendEnvironment) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + conn := testAccProvider.Meta().(*AWSClient).amplifyconn + + id := strings.Split(rs.Primary.ID, "/") + app_id := id[0] + environment_name := id[2] + + output, err := conn.GetBackendEnvironment(&lify.GetBackendEnvironmentInput{ + AppId: aws.String(app_id), + EnvironmentName: aws.String(environment_name), + }) + if err != nil { + return err + } + + if output == nil || output.BackendEnvironment == nil { + return fmt.Errorf("Amplify BackendEnvironment (%s) not found", rs.Primary.ID) + } + + *v = *output.BackendEnvironment + + return nil + } +} + +func testAccCheckAWSAmplifyBackendEnvironmentDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_amplify_backend_environment" { + continue + } + + conn := testAccProvider.Meta().(*AWSClient).amplifyconn + + id := strings.Split(rs.Primary.ID, "/") + app_id := id[0] + environment_name := id[2] + + _, err := conn.GetBackendEnvironment(&lify.GetBackendEnvironmentInput{ + AppId: aws.String(app_id), + EnvironmentName: aws.String(environment_name), + }) + + if isAWSErr(err, amplify.ErrCodeNotFoundException, "") { + continue + } + + if err != nil { + return err + } + } + + return nil +} + +func testAccCheckAWSAmplifyBackendEnvironmentRecreated(i, j *amplify.BackendEnvironment) resource.TestCheckFunc { + return func(s *terraform.State) error { + if aws.TimeValue(i.CreateTime) == aws.TimeValue(j.CreateTime) { + return errors.New("Amplify BackendEnvironment was not recreated") + } + + return nil + } +} + +func testAccAWSAmplifyBackendEnvironmentConfig_Required(rName string, envName string) string { + return fmt.Sprintf(` +resource "aws_amplify_app" "test" { + name = "%s" +} + +resource "aws_amplify_backend_environment" "test" { + app_id = aws_amplify_app.test.id + environment_name = "%s" +} +`, rName, envName) +} + +func testAccAWSAmplifyBackendEnvironmentConfigAll(rName string, envName string) string { + return fmt.Sprintf(` +resource "aws_amplify_app" "test" { + name = "%s" +} + +resource "aws_amplify_backend_environment" "test" { + app_id = aws_amplify_app.test.id + environment_name = "%s" + + deployment_artifacts = "%s" + stack_name = "%s" +} +`, rName, envName, rName, rName) +} diff --git a/website/docs/r/amplify_backend_environment.html.markdown b/website/docs/r/amplify_backend_environment.html.markdown new file mode 100644 index 00000000000..bf8a1782673 --- /dev/null +++ b/website/docs/r/amplify_backend_environment.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "Amplify" +layout: "aws" +page_title: "AWS: aws_amplify_backend_environment" +description: |- + Provides an Amplify backend environment resource. +--- + +# Resource: aws_amplify_backend_environment + +Provides an Amplify backend environment resource. + +## Example Usage + +```hcl +resource "aws_amplify_app" "app" { + name = "app" +} + +resource "aws_amplify_backend_environment" "prod" { + app_id = aws_amplify_app.app.id + environment_name = "prod" + + deployment_artifacts = "app-prod-deployment" + stack_name = "amplify-app-prod" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `app_id` - (Required) Unique Id for an Amplify App. +* `environment_name` - (Required) Name for the backend environment. +* `deployment_artifacts` - (Optional) Name of deployment artifacts. +* `stack_name` - (Optional) CloudFormation stack name of backend environment. + +## Attribute Reference + +The following attributes are exported: + +* `arn` - Arn for the backend environment. + +## Import + +Amplify backend environment can be imported using `app_id` and `environment_name`, e.g. + +``` +$ terraform import aws_amplify_backend_environment.prod d2ypk4k47z8u6/backendenvironments/prod +``` From 0bc8527bdcf879d256d087b67f01aafb3d601a0f Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 May 2021 15:05:29 -0400 Subject: [PATCH 2/5] r/aws_amplify_backend_environment: First compiling version. --- aws/internal/service/amplify/finder/finder.go | 29 ++++ aws/internal/service/amplify/id.go | 25 +++ ...esource_aws_amplify_backend_environment.go | 143 +++++++++--------- ...ce_aws_amplify_backend_environment_test.go | 72 ++++----- aws/resource_aws_amplify_test.go | 3 + website/docs/r/amplify_app.html.markdown | 2 +- .../amplify_backend_environment.html.markdown | 37 ++--- 7 files changed, 182 insertions(+), 129 deletions(-) create mode 100644 aws/internal/service/amplify/id.go diff --git a/aws/internal/service/amplify/finder/finder.go b/aws/internal/service/amplify/finder/finder.go index 8f67fbb18f1..46c91eac887 100644 --- a/aws/internal/service/amplify/finder/finder.go +++ b/aws/internal/service/amplify/finder/finder.go @@ -34,3 +34,32 @@ func AppByID(conn *amplify.Amplify, id string) (*amplify.App, error) { return output.App, nil } + +func BackendEnvironmentByAppIDAndEnvironmentName(conn *amplify.Amplify, appID, environmentName string) (*amplify.BackendEnvironment, error) { + input := &lify.GetBackendEnvironmentInput{ + AppId: aws.String(appID), + EnvironmentName: aws.String(environmentName), + } + + output, err := conn.GetBackendEnvironment(input) + + if tfawserr.ErrCodeEquals(err, amplify.ErrCodeNotFoundException) { + return nil, &resource.NotFoundError{ + LastError: err, + LastRequest: input, + } + } + + if err != nil { + return nil, err + } + + if output == nil || output.BackendEnvironment == nil { + return nil, &resource.NotFoundError{ + Message: "Empty result", + LastRequest: input, + } + } + + return output.BackendEnvironment, nil +} diff --git a/aws/internal/service/amplify/id.go b/aws/internal/service/amplify/id.go new file mode 100644 index 00000000000..a6c3210b0f2 --- /dev/null +++ b/aws/internal/service/amplify/id.go @@ -0,0 +1,25 @@ +package amplify + +import ( + "fmt" + "strings" +) + +const backendEnvironmentResourceIDSeparator = "/" + +func BackendEnvironmentCreateResourceID(appID, environmentName string) string { + parts := []string{appID, environmentName} + id := strings.Join(parts, backendEnvironmentResourceIDSeparator) + + return id +} + +func BackendEnvironmentParseResourceID(id string) (string, string, error) { + parts := strings.Split(id, backendEnvironmentResourceIDSeparator) + + if len(parts) == 2 && parts[0] != "" && parts[1] != "" { + return parts[0], parts[1], nil + } + + return "", "", fmt.Errorf("unexpected format for ID (%[1]s), expected APPID%[2]sENVIRONMENTNAME", id, backendEnvironmentResourceIDSeparator) +} diff --git a/aws/resource_aws_amplify_backend_environment.go b/aws/resource_aws_amplify_backend_environment.go index c4cca6f4a33..e1221b0bb27 100644 --- a/aws/resource_aws_amplify_backend_environment.go +++ b/aws/resource_aws_amplify_backend_environment.go @@ -3,14 +3,15 @@ package aws import ( "fmt" "log" - "regexp" - "strings" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/amplify" - "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "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" + tfamplify "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/amplify" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/amplify/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) func resourceAwsAmplifyBackendEnvironment() *schema.Resource { @@ -23,43 +24,38 @@ func resourceAwsAmplifyBackendEnvironment() *schema.Resource { }, Schema: map[string]*schema.Schema{ - "arn": { - Type: schema.TypeString, - Computed: true, - }, "app_id": { Type: schema.TypeString, Required: true, ForceNew: true, }, - "deployment_artifacts": { + + "arn": { Type: schema.TypeString, - Optional: true, Computed: true, - ForceNew: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 100), - validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9-]+$`), "should not contain special characters"), - ), }, + + "deployment_artifacts": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 1000), + }, + "environment_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.All( - validation.StringLenBetween(2, 10), - validation.StringMatch(regexp.MustCompile(`^[a-z]+$`), "should only contain lowercase alphabets"), - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 255), }, + "stack_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ForceNew: true, - ValidateFunc: validation.All( - validation.StringLenBetween(1, 100), - validation.StringMatch(regexp.MustCompile(`^[a-zA-Z0-9-]+$`), "should not contain special characters"), - ), + Type: schema.TypeString, + Optional: true, + Computed: true, + ForceNew: true, + ValidateFunc: validation.StringLenBetween(1, 255), }, }, } @@ -67,78 +63,87 @@ func resourceAwsAmplifyBackendEnvironment() *schema.Resource { func resourceAwsAmplifyBackendEnvironmentCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).amplifyconn - log.Print("[DEBUG] Creating Amplify BackendEnvironment") - params := &lify.CreateBackendEnvironmentInput{ - AppId: aws.String(d.Get("app_id").(string)), - EnvironmentName: aws.String(d.Get("environment_name").(string)), + appID := d.Get("app_id").(string) + environmentName := d.Get("environment_name").(string) + id := tfamplify.BackendEnvironmentCreateResourceID(appID, environmentName) + + input := &lify.CreateBackendEnvironmentInput{ + AppId: aws.String(appID), + EnvironmentName: aws.String(environmentName), } if v, ok := d.GetOk("deployment_artifacts"); ok { - params.DeploymentArtifacts = aws.String(v.(string)) + input.DeploymentArtifacts = aws.String(v.(string)) } if v, ok := d.GetOk("stack_name"); ok { - params.StackName = aws.String(v.(string)) + input.StackName = aws.String(v.(string)) } - resp, err := conn.CreateBackendEnvironment(params) + log.Printf("[DEBUG] Creating Amplify Backend Environment: %s", input) + _, err := conn.CreateBackendEnvironment(input) + if err != nil { - return fmt.Errorf("Error creating Amplify BackendEnvironment: %s", err) + return fmt.Errorf("error creating Amplify Backend Environment (%s): %w", id, err) } - arn := *resp.BackendEnvironment.BackendEnvironmentArn - d.SetId(arn[strings.Index(arn, ":apps/")+len(":apps/"):]) + d.SetId(id) return resourceAwsAmplifyBackendEnvironmentRead(d, meta) } func resourceAwsAmplifyBackendEnvironmentRead(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).amplifyconn - log.Printf("[DEBUG] Reading Amplify BackendEnvironment: %s", d.Id()) - s := strings.Split(d.Id(), "/") - app_id := s[0] - environment_name := s[2] + appID, environmentName, err := tfamplify.BackendEnvironmentParseResourceID(d.Id()) + + if err != nil { + return fmt.Errorf("error parsing Amplify Backend Environment ID: %w", err) + } + + backendEnvironment, err := finder.BackendEnvironmentByAppIDAndEnvironmentName(conn, appID, environmentName) + + if !d.IsNewResource() && tfresource.NotFound(err) { + log.Printf("[WARN] Amplify Backend Environment (%s) not found, removing from state", d.Id()) + d.SetId("") + return nil + } - resp, err := conn.GetBackendEnvironment(&lify.GetBackendEnvironmentInput{ - AppId: aws.String(app_id), - EnvironmentName: aws.String(environment_name), - }) if err != nil { - if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == amplify.ErrCodeNotFoundException { - log.Printf("[WARN] Amplify BackendEnvironment (%s) not found, removing from state", d.Id()) - d.SetId("") - return nil - } - return err + return fmt.Errorf("error reading Amplify Backend Environment (%s): %w", d.Id(), err) } - d.Set("app_id", app_id) - d.Set("arn", resp.BackendEnvironment.BackendEnvironmentArn) - d.Set("deployment_artifacts", resp.BackendEnvironment.DeploymentArtifacts) - d.Set("environment_name", resp.BackendEnvironment.EnvironmentName) - d.Set("stack_name", resp.BackendEnvironment.StackName) + d.Set("app_id", appID) + d.Set("arn", backendEnvironment.BackendEnvironmentArn) + d.Set("deployment_artifacts", backendEnvironment.DeploymentArtifacts) + d.Set("environment_name", backendEnvironment.EnvironmentName) + d.Set("stack_name", backendEnvironment.StackName) return nil } func resourceAwsAmplifyBackendEnvironmentDelete(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).amplifyconn - log.Printf("[DEBUG] Deleting Amplify BackendEnvironment: %s", d.Id()) - s := strings.Split(d.Id(), "/") - app_id := s[0] - environment_name := s[2] + appID, environmentName, err := tfamplify.BackendEnvironmentParseResourceID(d.Id()) + + if err != nil { + return fmt.Errorf("error parsing Amplify Backend Environment ID: %w", err) + } + + log.Printf("[DEBUG] Deleting Amplify Backend Environment: %s", d.Id()) + _, err = conn.DeleteBackendEnvironment(&lify.DeleteBackendEnvironmentInput{ + AppId: aws.String(appID), + EnvironmentName: aws.String(environmentName), + }) - params := &lify.DeleteBackendEnvironmentInput{ - AppId: aws.String(app_id), - EnvironmentName: aws.String(environment_name), + if tfawserr.ErrCodeEquals(err, amplify.ErrCodeNotFoundException) { + return nil } - _, err := conn.DeleteBackendEnvironment(params) if err != nil { - return fmt.Errorf("Error deleting Amplify BackendEnvironment: %s", err) + return fmt.Errorf("error deleting Amplify Backend Environment (%s): %w", d.Id(), err) } return nil diff --git a/aws/resource_aws_amplify_backend_environment_test.go b/aws/resource_aws_amplify_backend_environment_test.go index 902eda55b15..d2c194c5004 100644 --- a/aws/resource_aws_amplify_backend_environment_test.go +++ b/aws/resource_aws_amplify_backend_environment_test.go @@ -1,20 +1,20 @@ package aws import ( - "errors" "fmt" "regexp" - "strings" "testing" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/amplify" - "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" - "github.com/hashicorp/terraform-plugin-sdk/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/terraform" + "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" + tfamplify "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/amplify" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/service/amplify/finder" + "github.com/terraform-providers/terraform-provider-aws/aws/internal/tfresource" ) -func TestAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { +func testAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { var env1, env2 amplify.BackendEnvironment rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_amplify_backend_environment.test" @@ -22,7 +22,8 @@ func TestAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { envName := "backend" resource.ParallelTest(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSAmplify(t) }, + ErrorCheck: testAccErrorCheck(t, amplify.EndpointsID), Providers: testAccProviders, CheckDestroy: testAccCheckAWSAmplifyBackendEnvironmentDestroy, Steps: []resource.TestStep{ @@ -30,7 +31,7 @@ func TestAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { Config: testAccAWSAmplifyBackendEnvironmentConfig_Required(rName, envName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env1), - resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile("^arn:[^:]+:amplify:[^:]+:[^:]+:apps/[^/]+/backendenvironments/"+envName)), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "amplify", regexp.MustCompile(`apps/[^/]+/backendenvironments/.+`)), resource.TestCheckResourceAttr(resourceName, "environment_name", envName), resource.TestMatchResourceAttr(resourceName, "deployment_artifacts", regexp.MustCompile(fmt.Sprintf("^tf-acc-test-.*-%s-.*-deployment$", envName))), resource.TestMatchResourceAttr(resourceName, "stack_name", regexp.MustCompile(fmt.Sprintf("^amplify-tf-acc-test-.*-%s-.*$", envName))), @@ -45,8 +46,6 @@ func TestAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { Config: testAccAWSAmplifyBackendEnvironmentConfigAll(rName, envName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env2), - testAccCheckAWSAmplifyBackendEnvironmentRecreated(&env1, &env2), - resource.TestMatchResourceAttr(resourceName, "arn", regexp.MustCompile("^arn:[^:]+:amplify:[^:]+:[^:]+:apps/[^/]+/backendenvironments/"+envName)), resource.TestCheckResourceAttr(resourceName, "environment_name", envName), resource.TestCheckResourceAttr(resourceName, "deployment_artifacts", rName), resource.TestCheckResourceAttr(resourceName, "stack_name", rName), @@ -63,69 +62,60 @@ func testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName string, v *ampl return fmt.Errorf("Not found: %s", resourceName) } - conn := testAccProvider.Meta().(*AWSClient).amplifyconn + if rs.Primary.ID == "" { + return fmt.Errorf("No Amplify Backend Environment ID is set") + } - id := strings.Split(rs.Primary.ID, "/") - app_id := id[0] - environment_name := id[2] + appID, environmentName, err := tfamplify.BackendEnvironmentParseResourceID(rs.Primary.ID) - output, err := conn.GetBackendEnvironment(&lify.GetBackendEnvironmentInput{ - AppId: aws.String(app_id), - EnvironmentName: aws.String(environment_name), - }) if err != nil { return err } - if output == nil || output.BackendEnvironment == nil { - return fmt.Errorf("Amplify BackendEnvironment (%s) not found", rs.Primary.ID) + conn := testAccProvider.Meta().(*AWSClient).amplifyconn + + backendEnvironment, err := finder.BackendEnvironmentByAppIDAndEnvironmentName(conn, appID, environmentName) + + if err != nil { + return err } - *v = *output.BackendEnvironment + *v = *backendEnvironment return nil } } func testAccCheckAWSAmplifyBackendEnvironmentDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*AWSClient).amplifyconn + for _, rs := range s.RootModule().Resources { if rs.Type != "aws_amplify_backend_environment" { continue } - conn := testAccProvider.Meta().(*AWSClient).amplifyconn + appID, environmentName, err := tfamplify.BackendEnvironmentParseResourceID(rs.Primary.ID) - id := strings.Split(rs.Primary.ID, "/") - app_id := id[0] - environment_name := id[2] + if err != nil { + return err + } - _, err := conn.GetBackendEnvironment(&lify.GetBackendEnvironmentInput{ - AppId: aws.String(app_id), - EnvironmentName: aws.String(environment_name), - }) + _, err = finder.BackendEnvironmentByAppIDAndEnvironmentName(conn, appID, environmentName) - if isAWSErr(err, amplify.ErrCodeNotFoundException, "") { + if tfresource.NotFound(err) { continue } if err != nil { return err } + + return fmt.Errorf("Amplify BackendEnvironment %s still exists", rs.Primary.ID) } return nil } -func testAccCheckAWSAmplifyBackendEnvironmentRecreated(i, j *amplify.BackendEnvironment) resource.TestCheckFunc { - return func(s *terraform.State) error { - if aws.TimeValue(i.CreateTime) == aws.TimeValue(j.CreateTime) { - return errors.New("Amplify BackendEnvironment was not recreated") - } - - return nil - } -} - func testAccAWSAmplifyBackendEnvironmentConfig_Required(rName string, envName string) string { return fmt.Sprintf(` resource "aws_amplify_app" "test" { diff --git a/aws/resource_aws_amplify_test.go b/aws/resource_aws_amplify_test.go index 4907084c10e..1ff9c18bcf5 100644 --- a/aws/resource_aws_amplify_test.go +++ b/aws/resource_aws_amplify_test.go @@ -22,6 +22,9 @@ func TestAccAWSAmplify_serial(t *testing.T) { "Name": testAccAWSAmplifyApp_Name, "Repository": testAccAWSAmplifyApp_Repository, }, + "BackendEnvironment": { + "basic": testAccAWSAmplifyBackendEnvironment_basic, + }, } for group, m := range testCases { diff --git a/website/docs/r/amplify_app.html.markdown b/website/docs/r/amplify_app.html.markdown index 3da86a70893..a6012598850 100644 --- a/website/docs/r/amplify_app.html.markdown +++ b/website/docs/r/amplify_app.html.markdown @@ -190,7 +190,7 @@ A `production_branch` block supports the following attributes: Amplify App can be imported using Amplify App ID (appId), e.g. ``` -$ terraform import aws_amplify_app.app d2ypk4k47z8u6 +$ terraform import aws_amplify_app.example d2ypk4k47z8u6 ``` App ID can be obtained from App ARN (e.g. `arn:aws:amplify:us-east-1:12345678:apps/d2ypk4k47z8u6`). diff --git a/website/docs/r/amplify_backend_environment.html.markdown b/website/docs/r/amplify_backend_environment.html.markdown index bf8a1782673..6ba43271abb 100644 --- a/website/docs/r/amplify_backend_environment.html.markdown +++ b/website/docs/r/amplify_backend_environment.html.markdown @@ -1,28 +1,28 @@ --- -subcategory: "Amplify" +subcategory: "Amplify Console" layout: "aws" page_title: "AWS: aws_amplify_backend_environment" description: |- - Provides an Amplify backend environment resource. + Provides an Amplify Backend Environment resource. --- # Resource: aws_amplify_backend_environment -Provides an Amplify backend environment resource. +Provides an Amplify Backend Environment resource. ## Example Usage -```hcl -resource "aws_amplify_app" "app" { - name = "app" +```terraform +resource "aws_amplify_app" "example" { + name = "example" } -resource "aws_amplify_backend_environment" "prod" { - app_id = aws_amplify_app.app.id - environment_name = "prod" +resource "aws_amplify_backend_environment" "example" { + app_id = aws_amplify_app.example.id + environment_name = "example" - deployment_artifacts = "app-prod-deployment" - stack_name = "amplify-app-prod" + deployment_artifacts = "app-example-deployment" + stack_name = "amplify-app-example" } ``` @@ -30,21 +30,22 @@ resource "aws_amplify_backend_environment" "prod" { The following arguments are supported: -* `app_id` - (Required) Unique Id for an Amplify App. -* `environment_name` - (Required) Name for the backend environment. -* `deployment_artifacts` - (Optional) Name of deployment artifacts. -* `stack_name` - (Optional) CloudFormation stack name of backend environment. +* `app_id` - (Required) The unique ID for an Amplify app. +* `environment_name` - (Required) The name for the backend environment. +* `deployment_artifacts` - (Optional) The name of deployment artifacts. +* `stack_name` - (Optional) The AWS CloudFormation stack name of a backend environment. -## Attribute Reference +## Attributes Reference The following attributes are exported: -* `arn` - Arn for the backend environment. +* `arn` - The Amazon Resource Name (ARN) for a backend environment that is part of an Amplify app. +* `id` - The unique ID of the Amplify backend environment. ## Import Amplify backend environment can be imported using `app_id` and `environment_name`, e.g. ``` -$ terraform import aws_amplify_backend_environment.prod d2ypk4k47z8u6/backendenvironments/prod +$ terraform import aws_amplify_backend_environment.example d2ypk4k47z8u6/example ``` From 55c2161185ecf4d1a487d896ced97a12c1f893c8 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 May 2021 15:49:14 -0400 Subject: [PATCH 3/5] r/aws_amplify_backend_environment: Fix 'tfproviderdocs' errors. --- website/docs/r/amplify_app.html.markdown | 2 +- website/docs/r/amplify_backend_environment.html.markdown | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/r/amplify_app.html.markdown b/website/docs/r/amplify_app.html.markdown index a6012598850..5847a16116c 100644 --- a/website/docs/r/amplify_app.html.markdown +++ b/website/docs/r/amplify_app.html.markdown @@ -170,7 +170,7 @@ A `custom_rule` block supports the following arguments: ## Attributes Reference -The following attributes are exported: +In addition to all arguments above, the following attributes are exported: * `arn` - The Amazon Resource Name (ARN) of the Amplify app. * `default_domain` - The default domain for the Amplify app. diff --git a/website/docs/r/amplify_backend_environment.html.markdown b/website/docs/r/amplify_backend_environment.html.markdown index 6ba43271abb..83a7c1f1d68 100644 --- a/website/docs/r/amplify_backend_environment.html.markdown +++ b/website/docs/r/amplify_backend_environment.html.markdown @@ -37,7 +37,7 @@ The following arguments are supported: ## Attributes Reference -The following attributes are exported: +In addition to all arguments above, the following attributes are exported: * `arn` - The Amazon Resource Name (ARN) for a backend environment that is part of an Amplify app. * `id` - The unique ID of the Amplify backend environment. From 7ae70e4536dce3d2aae9f642e22a5398ce4cfaef Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 May 2021 17:28:16 -0400 Subject: [PATCH 4/5] Add CHANGELOG entry. --- .changelog/11936.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/11936.txt diff --git a/.changelog/11936.txt b/.changelog/11936.txt new file mode 100644 index 00000000000..0657ce4442c --- /dev/null +++ b/.changelog/11936.txt @@ -0,0 +1,3 @@ +```release-note:new-resource +aws_amplify_backend_environment +``` \ No newline at end of file From f14bb422f0daa22d122e190e1a67ba01d4cf9396 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Fri, 21 May 2021 17:29:02 -0400 Subject: [PATCH 5/5] r/aws_amplify_backend_environment: Get all tests passing. --- ...esource_aws_amplify_backend_environment.go | 7 +- ...ce_aws_amplify_backend_environment_test.go | 90 ++++++++++++++----- aws/resource_aws_amplify_test.go | 4 +- 3 files changed, 77 insertions(+), 24 deletions(-) diff --git a/aws/resource_aws_amplify_backend_environment.go b/aws/resource_aws_amplify_backend_environment.go index e1221b0bb27..d6bbc90950f 100644 --- a/aws/resource_aws_amplify_backend_environment.go +++ b/aws/resource_aws_amplify_backend_environment.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/amplify" @@ -40,14 +41,14 @@ func resourceAwsAmplifyBackendEnvironment() *schema.Resource { Optional: true, Computed: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 1000), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[0-9A-Za-z-]{1,100}$`), "should be not be more than 100 alphanumeric or hyphen characters"), }, "environment_name": { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 255), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[a-z]{2,10}$`), "should be between 2 and 10 characters (only lowercase alphabetic)"), }, "stack_name": { @@ -55,7 +56,7 @@ func resourceAwsAmplifyBackendEnvironment() *schema.Resource { Optional: true, Computed: true, ForceNew: true, - ValidateFunc: validation.StringLenBetween(1, 255), + ValidateFunc: validation.StringMatch(regexp.MustCompile(`^[0-9A-Za-z-]{1,100}$`), "should be not be more than 100 alphanumeric or hyphen characters"), }, }, } diff --git a/aws/resource_aws_amplify_backend_environment_test.go b/aws/resource_aws_amplify_backend_environment_test.go index d2c194c5004..8d3b590463b 100644 --- a/aws/resource_aws_amplify_backend_environment_test.go +++ b/aws/resource_aws_amplify_backend_environment_test.go @@ -15,11 +15,11 @@ import ( ) func testAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { - var env1, env2 amplify.BackendEnvironment + var env amplify.BackendEnvironment rName := acctest.RandomWithPrefix("tf-acc-test") resourceName := "aws_amplify_backend_environment.test" - envName := "backend" + environmentName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSAmplify(t) }, @@ -28,13 +28,13 @@ func testAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { CheckDestroy: testAccCheckAWSAmplifyBackendEnvironmentDestroy, Steps: []resource.TestStep{ { - Config: testAccAWSAmplifyBackendEnvironmentConfig_Required(rName, envName), + Config: testAccAWSAmplifyBackendEnvironmentConfigBasic(rName, environmentName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env1), + testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env), testAccMatchResourceAttrRegionalARN(resourceName, "arn", "amplify", regexp.MustCompile(`apps/[^/]+/backendenvironments/.+`)), - resource.TestCheckResourceAttr(resourceName, "environment_name", envName), - resource.TestMatchResourceAttr(resourceName, "deployment_artifacts", regexp.MustCompile(fmt.Sprintf("^tf-acc-test-.*-%s-.*-deployment$", envName))), - resource.TestMatchResourceAttr(resourceName, "stack_name", regexp.MustCompile(fmt.Sprintf("^amplify-tf-acc-test-.*-%s-.*$", envName))), + resource.TestCheckResourceAttrSet(resourceName, "deployment_artifacts"), + resource.TestCheckResourceAttr(resourceName, "environment_name", environmentName), + resource.TestCheckResourceAttrSet(resourceName, "stack_name"), ), }, { @@ -42,19 +42,69 @@ func testAccAWSAmplifyBackendEnvironment_basic(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + }, + }) +} + +func testAccAWSAmplifyBackendEnvironment_disappears(t *testing.T) { + var env amplify.BackendEnvironment + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_amplify_backend_environment.test" + + environmentName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSAmplify(t) }, + ErrorCheck: testAccErrorCheck(t, amplify.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAmplifyBackendEnvironmentDestroy, + Steps: []resource.TestStep{ { - Config: testAccAWSAmplifyBackendEnvironmentConfigAll(rName, envName), + Config: testAccAWSAmplifyBackendEnvironmentConfigBasic(rName, environmentName), Check: resource.ComposeTestCheckFunc( - testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env2), - resource.TestCheckResourceAttr(resourceName, "environment_name", envName), + testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env), + testAccCheckResourceDisappears(testAccProvider, resourceAwsAmplifyBackendEnvironment(), resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testAccAWSAmplifyBackendEnvironment_DeploymentArtifacts_StackName(t *testing.T) { + var env amplify.BackendEnvironment + rName := acctest.RandomWithPrefix("tf-acc-test") + resourceName := "aws_amplify_backend_environment.test" + + environmentName := acctest.RandStringFromCharSet(10, acctest.CharSetAlpha) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t); testAccPreCheckAWSAmplify(t) }, + ErrorCheck: testAccErrorCheck(t, amplify.EndpointsID), + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSAmplifyBackendEnvironmentDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAWSAmplifyBackendEnvironmentConfigDeploymentArtifactsAndStackName(rName, environmentName), + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName, &env), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "amplify", regexp.MustCompile(`apps/[^/]+/backendenvironments/.+`)), resource.TestCheckResourceAttr(resourceName, "deployment_artifacts", rName), + resource.TestCheckResourceAttr(resourceName, "environment_name", environmentName), resource.TestCheckResourceAttr(resourceName, "stack_name", rName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } +// testAccAWSAmplifyBackendEnvironmentConfigDeploymentArtifactsAndStackName(rname, environmentName) + func testAccCheckAWSAmplifyBackendEnvironmentExists(resourceName string, v *amplify.BackendEnvironment) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[resourceName] @@ -116,31 +166,31 @@ func testAccCheckAWSAmplifyBackendEnvironmentDestroy(s *terraform.State) error { return nil } -func testAccAWSAmplifyBackendEnvironmentConfig_Required(rName string, envName string) string { +func testAccAWSAmplifyBackendEnvironmentConfigBasic(rName string, environmentName string) string { return fmt.Sprintf(` resource "aws_amplify_app" "test" { - name = "%s" + name = %[1]q } resource "aws_amplify_backend_environment" "test" { app_id = aws_amplify_app.test.id - environment_name = "%s" + environment_name = %[2]q } -`, rName, envName) +`, rName, environmentName) } -func testAccAWSAmplifyBackendEnvironmentConfigAll(rName string, envName string) string { +func testAccAWSAmplifyBackendEnvironmentConfigDeploymentArtifactsAndStackName(rName string, environmentName string) string { return fmt.Sprintf(` resource "aws_amplify_app" "test" { - name = "%s" + name = %[1]q } resource "aws_amplify_backend_environment" "test" { app_id = aws_amplify_app.test.id - environment_name = "%s" + environment_name = %[2]q - deployment_artifacts = "%s" - stack_name = "%s" + deployment_artifacts = %[1]q + stack_name = %[1]q } -`, rName, envName, rName, rName) +`, rName, environmentName) } diff --git a/aws/resource_aws_amplify_test.go b/aws/resource_aws_amplify_test.go index 1ff9c18bcf5..46f5fab6279 100644 --- a/aws/resource_aws_amplify_test.go +++ b/aws/resource_aws_amplify_test.go @@ -23,7 +23,9 @@ func TestAccAWSAmplify_serial(t *testing.T) { "Repository": testAccAWSAmplifyApp_Repository, }, "BackendEnvironment": { - "basic": testAccAWSAmplifyBackendEnvironment_basic, + "basic": testAccAWSAmplifyBackendEnvironment_basic, + "disappears": testAccAWSAmplifyBackendEnvironment_disappears, + "DeploymentArtifacts_StackName": testAccAWSAmplifyBackendEnvironment_DeploymentArtifacts_StackName, }, }