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: Add aws_codedeploy_app #2783

Merged
merged 6 commits into from
Oct 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 builtin/providers/aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/cloudwatchlogs"
"github.com/aws/aws-sdk-go/service/codedeploy"
"github.com/aws/aws-sdk-go/service/directoryservice"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/ec2"
Expand Down Expand Up @@ -70,6 +71,7 @@ type AWSClient struct {
lambdaconn *lambda.Lambda
opsworksconn *opsworks.OpsWorks
glacierconn *glacier.Glacier
codedeployconn *codedeploy.CodeDeploy
}

// Client configures and returns a fully initialized AWSClient
Expand Down Expand Up @@ -192,6 +194,9 @@ func (c *Config) Client() (interface{}, error) {

log.Println("[INFO] Initializing Glacier connection")
client.glacierconn = glacier.New(awsConfig)

log.Println("[INFO] Initializing CodeDeploy Connection")
client.codedeployconn = codedeploy.New(awsConfig)
}

if len(errs) > 0 {
Expand Down
2 changes: 2 additions & 0 deletions builtin/providers/aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ func Provider() terraform.ResourceProvider {
"aws_cloudwatch_log_group": resourceAwsCloudWatchLogGroup(),
"aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(),
"aws_cloudwatch_metric_alarm": resourceAwsCloudWatchMetricAlarm(),
"aws_codedeploy_app": resourceAwsCodeDeployApp(),
"aws_codedeploy_deployment_group": resourceAwsCodeDeployDeploymentGroup(),
"aws_customer_gateway": resourceAwsCustomerGateway(),
"aws_db_instance": resourceAwsDbInstance(),
"aws_db_parameter_group": resourceAwsDbParameterGroup(),
Expand Down
127 changes: 127 additions & 0 deletions builtin/providers/aws/resource_aws_codedeploy_app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package aws

import (
"fmt"
"log"
"strings"

"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/codedeploy"
)

func resourceAwsCodeDeployApp() *schema.Resource {
return &schema.Resource{
Create: resourceAwsCodeDeployAppCreate,
Read: resourceAwsCodeDeployAppRead,
Update: resourceAwsCodeDeployUpdate,
Delete: resourceAwsCodeDeployAppDelete,

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

// The unique ID is set by AWS on create.
"unique_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
}
}

func resourceAwsCodeDeployAppCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).codedeployconn

application := d.Get("name").(string)
log.Printf("[DEBUG] Creating CodeDeploy application %s", application)

resp, err := conn.CreateApplication(&codedeploy.CreateApplicationInput{
ApplicationName: aws.String(application),
})
if err != nil {
return err
}
log.Printf("[DEBUG] CodeDeploy application %s created", *resp.ApplicationId)

// Despite giving the application a unique ID, AWS doesn't actually use
// it in API calls. Use it and the app name to identify the resource in
// the state file. This allows us to reliably detect both when the TF
// config file changes and when the user deletes the app without removing
// it first from the TF config.
d.SetId(fmt.Sprintf("%s:%s", *resp.ApplicationId, application))

return resourceAwsCodeDeployAppRead(d, meta)
}

func resourceAwsCodeDeployAppRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).codedeployconn

_, application := resourceAwsCodeDeployAppParseId(d.Id())
log.Printf("[DEBUG] Reading CodeDeploy application %s", application)
resp, err := conn.GetApplication(&codedeploy.GetApplicationInput{
ApplicationName: aws.String(application),
})
if err != nil {
if codedeployerr, ok := err.(awserr.Error); ok && codedeployerr.Code() == "ApplicationDoesNotExistException" {
d.SetId("")
return nil
} else {
log.Printf("[ERROR] Error finding CodeDeploy application: %s", err)
return err
}
}

d.Set("name", *resp.Application.ApplicationName)

return nil
}

func resourceAwsCodeDeployUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).codedeployconn

o, n := d.GetChange("name")

_, err := conn.UpdateApplication(&codedeploy.UpdateApplicationInput{
ApplicationName: aws.String(o.(string)),
NewApplicationName: aws.String(n.(string)),
})
if err != nil {
return err
}
log.Printf("[DEBUG] CodeDeploy application %s updated", n)

d.Set("name", n)

return nil
}

func resourceAwsCodeDeployAppDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).codedeployconn

_, err := conn.DeleteApplication(&codedeploy.DeleteApplicationInput{
ApplicationName: aws.String(d.Get("name").(string)),
})
if err != nil {
if cderr, ok := err.(awserr.Error); ok && cderr.Code() == "InvalidApplicationNameException" {
d.SetId("")
return nil
} else {
log.Printf("[ERROR] Error deleting CodeDeploy application: %s", err)
return err
}
}

return nil
}

func resourceAwsCodeDeployAppParseId(id string) (string, string) {
parts := strings.SplitN(id, ":", 2)
return parts[0], parts[1]
}
78 changes: 78 additions & 0 deletions builtin/providers/aws/resource_aws_codedeploy_app_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package aws

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/codedeploy"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSCodeDeployApp_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCodeDeployAppDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSCodeDeployApp,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
),
},
resource.TestStep{
Config: testAccAWSCodeDeployAppModifier,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSCodeDeployAppExists("aws_codedeploy_app.foo"),
),
},
},
})
}

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

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

resp, err := conn.GetApplication(&codedeploy.GetApplicationInput{
ApplicationName: aws.String(rs.Primary.ID),
})

if err == nil {
if resp.Application != nil {
return fmt.Errorf("CodeDeploy app still exists:\n%#v", *resp.Application.ApplicationId)
}
}

return err
}

return nil
}

func testAccCheckAWSCodeDeployAppExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}

return nil
}
}

var testAccAWSCodeDeployApp = `
resource "aws_codedeploy_app" "foo" {
name = "foo"
}`

var testAccAWSCodeDeployAppModifier = `
resource "aws_codedeploy_app" "foo" {
name = "bar"
}`
Loading