Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provider/aws: Elastic Beanstalk Application and Environment #3157

Closed
wants to merge 42 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f81984c
provider/aws: Elastic Beanstalk WIP
catsby Sep 2, 2015
58bfa55
document elastic beanstalk env
catsby Oct 8, 2015
8da6634
tolerate Beanstalk App not found in read method
catsby Oct 9, 2015
3d177cc
update beanstalk configuration template a bit
catsby Oct 12, 2015
138cc13
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Oct 27, 2015
cbc010d
fixes for Elastic Beanstalk after feedback
catsby Oct 27, 2015
c257708
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Nov 6, 2015
781c22b
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Nov 10, 2015
0cbf79d
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Nov 13, 2015
0083c8d
Fix issue with recurring plans. For some option setting values the El…
dharrisio Jan 9, 2016
675f6b7
Updating solution_stack_name for new accounts that don't have "64bit…
dharrisio Jan 9, 2016
148aea0
Update optionSettingKeyHash function to hash setting key, not setting…
dharrisio Jan 13, 2016
5df8dfa
Merge pull request #4596 from dharrisio/aws-elastic-beanstalk-recurri…
catsby Jan 14, 2016
2dde588
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Jan 14, 2016
458d7de
Fix security group problem
Bowbaq Jan 15, 2016
6a836e8
Properly detect terminated environments
Bowbaq Jan 11, 2016
e1d4d67
Delete configuration template instead of application.
dharrisio Jan 20, 2016
4ddf94f
Fixing resource_aws_elastic_beanstalk_application.go to pass TestAccA…
dharrisio Jan 20, 2016
6a0fba4
Fixing testAccCheckBeanstalkConfigurationTemplateDestroy to handle In…
dharrisio Jan 20, 2016
b751f39
Rewrite if/else as switch.
dharrisio Jan 20, 2016
e3c5b2e
Updating testAccCheckBeanstalkEnvDestroy to consider an environment i…
dharrisio Jan 20, 2016
1220efd
Merge pull request #4764 from dharrisio/aws-elastic-beanstalk-failing…
catsby Jan 21, 2016
e775ae0
Merge pull request #4691 from Originate/mb-fix-generated-security-group
catsby Jan 21, 2016
77c36fe
Merge pull request #4692 from Originate/mb-fix-terminated-env-detection
catsby Jan 21, 2016
38c4bbe
Fixing panic in TestAccAWSBeanstalkEnv_basic. When splitting the valu…
dharrisio Jan 21, 2016
528303e
Merge pull request #4791 from dharrisio/mb-fix-generated-security-gro…
catsby Jan 22, 2016
abf10d3
Update to accomodate 47ac10d6
Bowbaq Jan 25, 2016
533d579
Merge pull request #4832 from Originate/mb-aws-elasticbeanstalk-multi…
jen20 Jan 26, 2016
d449ef4
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Feb 1, 2016
2b8410c
update godeps
catsby Feb 1, 2016
d73e41c
add vendored elasticbeanstalk code
catsby Feb 1, 2016
ee5f4d1
Adding tier attribute and associated test to aws_elastic_beanstalk_en…
dharrisio Feb 18, 2016
afee005
Sort subnets to avoid spurious diffs
Bowbaq Feb 19, 2016
ddc2ca2
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Mar 7, 2016
199c3a4
update beanstalk env for test
catsby Mar 7, 2016
226bc2a
Merge pull request #5208 from Originate/mb-fix-subnet-ordering
catsby Mar 7, 2016
3713f0a
Merge branch 'f-aws-elastic-beanstalk' of github.com:hashicorp/terraf…
catsby Mar 7, 2016
832a190
Merge pull request #5209 from dharrisio/f-aws-elastic-beanstalk-tier
catsby Mar 7, 2016
c736fff
Merge branch 'f-aws-elastic-beanstalk' of github.com:hashicorp/terraf…
catsby Mar 7, 2016
6a4b50e
update config template test stack name
catsby Mar 7, 2016
6aa848b
update beanstalk documentation
catsby Mar 7, 2016
592da4e
Merge branch 'master' into f-aws-elastic-beanstalk
catsby Mar 7, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions builtin/providers/aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/aws/aws-sdk-go/service/ecs"
"github.com/aws/aws-sdk-go/service/efs"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/elasticbeanstalk"
elasticsearch "github.com/aws/aws-sdk-go/service/elasticsearchservice"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/firehose"
Expand Down Expand Up @@ -98,6 +99,7 @@ type AWSClient struct {
kinesisconn *kinesis.Kinesis
firehoseconn *firehose.Firehose
elasticacheconn *elasticache.ElastiCache
elasticbeanstalkconn *elasticbeanstalk.ElasticBeanstalk
lambdaconn *lambda.Lambda
opsworksconn *opsworks.OpsWorks
glacierconn *glacier.Glacier
Expand Down Expand Up @@ -213,6 +215,9 @@ func (c *Config) Client() (interface{}, error) {
kinesisSess := session.New(&awsKinesisConfig)
client.kinesisconn = kinesis.New(kinesisSess)

log.Println("[INFO] Initializing Elastic Beanstalk Connection")
client.elasticbeanstalkconn = elasticbeanstalk.New(sess)

authErr := c.ValidateAccountId(client.iamconn)
if authErr != nil {
errs = append(errs, authErr)
Expand Down
255 changes: 129 additions & 126 deletions builtin/providers/aws/provider.go

Large diffs are not rendered by default.

147 changes: 147 additions & 0 deletions builtin/providers/aws/resource_aws_elastic_beanstalk_application.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package aws

import (
"fmt"
"log"
"time"

"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"
"github.com/hashicorp/terraform/helper/resource"
)

func resourceAwsElasticBeanstalkApplication() *schema.Resource {
return &schema.Resource{
Create: resourceAwsElasticBeanstalkApplicationCreate,
Read: resourceAwsElasticBeanstalkApplicationRead,
Update: resourceAwsElasticBeanstalkApplicationUpdate,
Delete: resourceAwsElasticBeanstalkApplicationDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: false,
},
},
}
}

func resourceAwsElasticBeanstalkApplicationCreate(d *schema.ResourceData, meta interface{}) error {
beanstalkConn := meta.(*AWSClient).elasticbeanstalkconn

// Get the name and description
name := d.Get("name").(string)
description := d.Get("description").(string)

log.Printf("[DEBUG] Elastic Beanstalk application create: %s, description: %s", name, description)

req := &elasticbeanstalk.CreateApplicationInput{
ApplicationName: aws.String(name),
Description: aws.String(description),
}

_, err := beanstalkConn.CreateApplication(req)
if err != nil {
return err
}

d.SetId(name)

return resourceAwsElasticBeanstalkApplicationRead(d, meta)
}

func resourceAwsElasticBeanstalkApplicationUpdate(d *schema.ResourceData, meta interface{}) error {
beanstalkConn := meta.(*AWSClient).elasticbeanstalkconn

if d.HasChange("description") {
if err := resourceAwsElasticBeanstalkApplicationDescriptionUpdate(beanstalkConn, d); err != nil {
return err
}
}

return resourceAwsElasticBeanstalkApplicationRead(d, meta)
}

func resourceAwsElasticBeanstalkApplicationDescriptionUpdate(beanstalkConn *elasticbeanstalk.ElasticBeanstalk, d *schema.ResourceData) error {
name := d.Get("name").(string)
description := d.Get("description").(string)

log.Printf("[DEBUG] Elastic Beanstalk application: %s, update description: %s", name, description)

_, err := beanstalkConn.UpdateApplication(&elasticbeanstalk.UpdateApplicationInput{
ApplicationName: aws.String(name),
Description: aws.String(description),
})

return err
}

func resourceAwsElasticBeanstalkApplicationRead(d *schema.ResourceData, meta interface{}) error {
a, err := getBeanstalkApplication(d, meta)
if err != nil {
return err
}
if a == nil {
return err
}

d.Set("description", a.Description)
return nil
}

func resourceAwsElasticBeanstalkApplicationDelete(d *schema.ResourceData, meta interface{}) error {
beanstalkConn := meta.(*AWSClient).elasticbeanstalkconn

a, err := getBeanstalkApplication(d, meta)
if err != nil {
return err
}
_, err = beanstalkConn.DeleteApplication(&elasticbeanstalk.DeleteApplicationInput{
ApplicationName: aws.String(d.Id()),
})

return resource.Retry(10*time.Second, func() error {
if a, _ = getBeanstalkApplication(d, meta); a != nil {
return fmt.Errorf("Beanstalk Application still exists")
}
return nil
})
}

func getBeanstalkApplication(
d *schema.ResourceData,
meta interface{}) (*elasticbeanstalk.ApplicationDescription, error) {
conn := meta.(*AWSClient).elasticbeanstalkconn

resp, err := conn.DescribeApplications(&elasticbeanstalk.DescribeApplicationsInput{
ApplicationNames: []*string{aws.String(d.Id())},
})

if err != nil {
if ec2err, ok := err.(awserr.Error); ok && ec2err.Code() != "InvalidBeanstalkAppID.NotFound" {
log.Printf("[Err] Error reading Elastic Beanstalk Application (%s): Application not found", d.Id())
d.SetId("")
return nil, nil
}
return nil, err
}

switch {
case len(resp.Applications) > 1:
return nil, fmt.Errorf("Error %d Applications matched, expected 1", len(resp.Applications))
case len(resp.Applications) == 0:
d.SetId("")
return nil, nil
default:
return resp.Applications[0], nil
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package aws

import (
"fmt"
"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/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSBeanstalkApp_basic(t *testing.T) {
var app elasticbeanstalk.ApplicationDescription

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckBeanstalkAppDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccBeanstalkAppConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckBeanstalkAppExists("aws_elastic_beanstalk_application.tftest", &app),
),
},
},
})
}

func testAccCheckBeanstalkAppDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).elasticbeanstalkconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_elastic_beanstalk_application" {
continue
}

// Try to find the application
DescribeBeanstalkAppOpts := &elasticbeanstalk.DescribeApplicationsInput{
ApplicationNames: []*string{aws.String(rs.Primary.ID)},
}
resp, err := conn.DescribeApplications(DescribeBeanstalkAppOpts)
if err == nil {
if len(resp.Applications) > 0 {
return fmt.Errorf("Elastic Beanstalk Application still exists.")
}

return nil
}

// Verify the error is what we want
ec2err, ok := err.(awserr.Error)
if !ok {
return err
}
if ec2err.Code() != "InvalidBeanstalkAppID.NotFound" {
return err
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that this error is expected here makes me feel like we should also be catching it up in Read too - instead of just a response where len(Applications) == 0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 8da6634

}

return nil
}

func testAccCheckBeanstalkAppExists(n string, app *elasticbeanstalk.ApplicationDescription) 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 app ID is not set")
}

conn := testAccProvider.Meta().(*AWSClient).elasticbeanstalkconn
DescribeBeanstalkAppOpts := &elasticbeanstalk.DescribeApplicationsInput{
ApplicationNames: []*string{aws.String(rs.Primary.ID)},
}
resp, err := conn.DescribeApplications(DescribeBeanstalkAppOpts)
if err != nil {
return err
}
if len(resp.Applications) == 0 {
return fmt.Errorf("Elastic Beanstalk Application not found.")
}

*app = *resp.Applications[0]

return nil
}
}

const testAccBeanstalkAppConfig = `
resource "aws_elastic_beanstalk_application" "tftest" {
name = "tf-test-name"
description = "tf-test-desc"
}
`
Loading