-
Notifications
You must be signed in to change notification settings - Fork 9.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
provider/aws: Elastic Beanstalk Application Version (#5770)
* Added new resource aws_elastic_beanstalk_application_version. * Changing bucket and key to required. * Update to use d.Id() directly in DescribeApplicationVersions. * Checking err to make sure that the application version is successfully deleted. * Update `version_label` to `Computed: true`. * provider/aws: Updating to python solution stack * provider/aws: Beanstalk App Version delete source The Elastic Beanstalk API call to delete `application_version` resource should not delete the s3 bundle, as this object is managed by another Terraform resource * provider/aws: Update application version docs * Fix application version test * Add `version_label` update test Adds test that fails after rebasing branch onto v0.8.x. `version_label` changes do not update the `aws_elastic_beanstalk_environment` resource. * `version_label` changes to update environment * Prevent unintended delete of `application_version` Prevents an `application_version` used by multiple environments from being deleted. * Add `force_delete` attribute * Update documentation
- Loading branch information
Showing
9 changed files
with
536 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
202 changes: 202 additions & 0 deletions
202
builtin/providers/aws/resource_aws_elastic_beanstalk_application_version.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
"github.com/aws/aws-sdk-go/service/elasticbeanstalk" | ||
"time" | ||
) | ||
|
||
func resourceAwsElasticBeanstalkApplicationVersion() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsElasticBeanstalkApplicationVersionCreate, | ||
Read: resourceAwsElasticBeanstalkApplicationVersionRead, | ||
Update: resourceAwsElasticBeanstalkApplicationVersionUpdate, | ||
Delete: resourceAwsElasticBeanstalkApplicationVersionDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"application": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"description": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
"bucket": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"key": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"force_delete": &schema.Schema{ | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsElasticBeanstalkApplicationVersionCreate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).elasticbeanstalkconn | ||
|
||
application := d.Get("application").(string) | ||
description := d.Get("description").(string) | ||
bucket := d.Get("bucket").(string) | ||
key := d.Get("key").(string) | ||
name := d.Get("name").(string) | ||
|
||
s3Location := elasticbeanstalk.S3Location{ | ||
S3Bucket: aws.String(bucket), | ||
S3Key: aws.String(key), | ||
} | ||
|
||
createOpts := elasticbeanstalk.CreateApplicationVersionInput{ | ||
ApplicationName: aws.String(application), | ||
Description: aws.String(description), | ||
SourceBundle: &s3Location, | ||
VersionLabel: aws.String(name), | ||
} | ||
|
||
log.Printf("[DEBUG] Elastic Beanstalk Application Version create opts: %s", createOpts) | ||
_, err := conn.CreateApplicationVersion(&createOpts) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.SetId(name) | ||
log.Printf("[INFO] Elastic Beanstalk Application Version Label: %s", name) | ||
|
||
return resourceAwsElasticBeanstalkApplicationVersionRead(d, meta) | ||
} | ||
|
||
func resourceAwsElasticBeanstalkApplicationVersionRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).elasticbeanstalkconn | ||
|
||
resp, err := conn.DescribeApplicationVersions(&elasticbeanstalk.DescribeApplicationVersionsInput{ | ||
VersionLabels: []*string{aws.String(d.Id())}, | ||
}) | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(resp.ApplicationVersions) == 0 { | ||
log.Printf("[DEBUG] Elastic Beanstalk application version read: application version not found") | ||
|
||
d.SetId("") | ||
|
||
return nil | ||
} else if len(resp.ApplicationVersions) != 1 { | ||
return fmt.Errorf("Error reading application version properties: found %d application versions, expected 1", len(resp.ApplicationVersions)) | ||
} | ||
|
||
if err := d.Set("description", resp.ApplicationVersions[0].Description); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsElasticBeanstalkApplicationVersionUpdate(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).elasticbeanstalkconn | ||
|
||
if d.HasChange("description") { | ||
if err := resourceAwsElasticBeanstalkApplicationVersionDescriptionUpdate(conn, d); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return resourceAwsElasticBeanstalkApplicationVersionRead(d, meta) | ||
|
||
} | ||
|
||
func resourceAwsElasticBeanstalkApplicationVersionDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).elasticbeanstalkconn | ||
|
||
application := d.Get("application").(string) | ||
name := d.Id() | ||
|
||
if d.Get("force_delete").(bool) == false { | ||
environments, err := versionUsedBy(application, name, conn) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if len(environments) > 1 { | ||
return fmt.Errorf("Unable to delete Application Version, it is currently in use by the following environments: %s.", environments) | ||
} | ||
} | ||
_, err := conn.DeleteApplicationVersion(&elasticbeanstalk.DeleteApplicationVersionInput{ | ||
ApplicationName: aws.String(application), | ||
VersionLabel: aws.String(name), | ||
DeleteSourceBundle: aws.Bool(false), | ||
}) | ||
|
||
if err != nil { | ||
if awserr, ok := err.(awserr.Error); ok { | ||
// application version is pending delete, or no longer exists. | ||
if awserr.Code() == "InvalidParameterValue" { | ||
d.SetId("") | ||
return nil | ||
} | ||
} | ||
return err | ||
} | ||
|
||
d.SetId("") | ||
return nil | ||
} | ||
|
||
func resourceAwsElasticBeanstalkApplicationVersionDescriptionUpdate(conn *elasticbeanstalk.ElasticBeanstalk, d *schema.ResourceData) error { | ||
application := d.Get("application").(string) | ||
description := d.Get("description").(string) | ||
name := d.Get("name").(string) | ||
|
||
log.Printf("[DEBUG] Elastic Beanstalk application version: %s, update description: %s", name, description) | ||
|
||
_, err := conn.UpdateApplicationVersion(&elasticbeanstalk.UpdateApplicationVersionInput{ | ||
ApplicationName: aws.String(application), | ||
Description: aws.String(description), | ||
VersionLabel: aws.String(name), | ||
}) | ||
|
||
return err | ||
} | ||
|
||
func versionUsedBy(applicationName, versionLabel string, conn *elasticbeanstalk.ElasticBeanstalk) ([]string, error) { | ||
now := time.Now() | ||
resp, err := conn.DescribeEnvironments(&elasticbeanstalk.DescribeEnvironmentsInput{ | ||
ApplicationName: aws.String(applicationName), | ||
VersionLabel: aws.String(versionLabel), | ||
IncludeDeleted: aws.Bool(true), | ||
IncludedDeletedBackTo: aws.Time(now.Add(-1 * time.Minute)), | ||
}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var environmentIDs []string | ||
for _, environment := range resp.Environments { | ||
environmentIDs = append(environmentIDs, *environment.EnvironmentId) | ||
} | ||
|
||
return environmentIDs, nil | ||
} |
122 changes: 122 additions & 0 deletions
122
builtin/providers/aws/resource_aws_elastic_beanstalk_application_version_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
"github.com/aws/aws-sdk-go/service/elasticbeanstalk" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSBeanstalkAppVersion_basic(t *testing.T) { | ||
|
||
var appVersion elasticbeanstalk.ApplicationVersionDescription | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckApplicationVersionDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testAccBeanstalkApplicationVersionConfig(acctest.RandInt()), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckApplicationVersionExists("aws_elastic_beanstalk_application_version.default", &appVersion), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckApplicationVersionDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).elasticbeanstalkconn | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_elastic_beanstalk_application_version" { | ||
continue | ||
} | ||
|
||
describeApplicationVersionOpts := &elasticbeanstalk.DescribeApplicationVersionsInput{ | ||
VersionLabels: []*string{aws.String(rs.Primary.ID)}, | ||
} | ||
resp, err := conn.DescribeApplicationVersions(describeApplicationVersionOpts) | ||
if err == nil { | ||
if len(resp.ApplicationVersions) > 0 { | ||
return fmt.Errorf("Elastic Beanstalk Application Verson still exists.") | ||
} | ||
|
||
return nil | ||
} | ||
ec2err, ok := err.(awserr.Error) | ||
if !ok { | ||
return err | ||
} | ||
if ec2err.Code() != "InvalidParameterValue" { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccCheckApplicationVersionExists(n string, app *elasticbeanstalk.ApplicationVersionDescription) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("Elastic Beanstalk Application Version is not set") | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).elasticbeanstalkconn | ||
describeApplicationVersionOpts := &elasticbeanstalk.DescribeApplicationVersionsInput{ | ||
VersionLabels: []*string{aws.String(rs.Primary.ID)}, | ||
} | ||
|
||
log.Printf("[DEBUG] Elastic Beanstalk Application Version TEST describe opts: %s", describeApplicationVersionOpts) | ||
|
||
resp, err := conn.DescribeApplicationVersions(describeApplicationVersionOpts) | ||
if err != nil { | ||
return err | ||
} | ||
if len(resp.ApplicationVersions) == 0 { | ||
return fmt.Errorf("Elastic Beanstalk Application Version not found.") | ||
} | ||
|
||
*app = *resp.ApplicationVersions[0] | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccBeanstalkApplicationVersionConfig(randInt int) string { | ||
return fmt.Sprintf(` | ||
resource "aws_s3_bucket" "default" { | ||
bucket = "tftest.applicationversion.bucket-%d" | ||
} | ||
resource "aws_s3_bucket_object" "default" { | ||
bucket = "${aws_s3_bucket.default.id}" | ||
key = "beanstalk/python-v1.zip" | ||
source = "test-fixtures/python-v1.zip" | ||
} | ||
resource "aws_elastic_beanstalk_application" "default" { | ||
name = "tf-test-name" | ||
description = "tf-test-desc" | ||
} | ||
resource "aws_elastic_beanstalk_application_version" "default" { | ||
application = "tf-test-name" | ||
name = "tf-test-version-label" | ||
bucket = "${aws_s3_bucket.default.id}" | ||
key = "${aws_s3_bucket_object.default.id}" | ||
} | ||
`, randInt) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.