diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index a6bbce76d..c6eb88e95 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -190,6 +190,7 @@ func Provider() terraform.ResourceProvider { "aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(), "aws_appautoscaling_target": resourceAwsAppautoscalingTarget(), "aws_appautoscaling_policy": resourceAwsAppautoscalingPolicy(), + "aws_autoscaling_attachment": resourceAwsAutoscalingAttachment(), "aws_autoscaling_group": resourceAwsAutoscalingGroup(), "aws_autoscaling_notification": resourceAwsAutoscalingNotification(), "aws_autoscaling_policy": resourceAwsAutoscalingPolicy(), diff --git a/builtin/providers/aws/resource_aws_autoscaling_attachment.go b/builtin/providers/aws/resource_aws_autoscaling_attachment.go new file mode 100644 index 000000000..d3921d9ba --- /dev/null +++ b/builtin/providers/aws/resource_aws_autoscaling_attachment.go @@ -0,0 +1,108 @@ +package aws + +import ( + "fmt" + "log" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" +) + +func resourceAwsAutoscalingAttachment() *schema.Resource { + return &schema.Resource{ + Create: resourceAwsAutoscalingAttachmentCreate, + Read: resourceAwsAutoscalingAttachmentRead, + Delete: resourceAwsAutoscalingAttachmentDelete, + + Schema: map[string]*schema.Schema{ + "autoscaling_group_name": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + + "elb": &schema.Schema{ + Type: schema.TypeString, + ForceNew: true, + Required: true, + }, + }, + } +} + +func resourceAwsAutoscalingAttachmentCreate(d *schema.ResourceData, meta interface{}) error { + asgconn := meta.(*AWSClient).autoscalingconn + asgName := d.Get("autoscaling_group_name").(string) + elbName := d.Get("elb").(string) + + attachElbInput := &autoscaling.AttachLoadBalancersInput{ + AutoScalingGroupName: aws.String(asgName), + LoadBalancerNames: []*string{aws.String(elbName)}, + } + + log.Printf("[INFO] registering asg %s with ELBs %s", asgName, elbName) + + if _, err := asgconn.AttachLoadBalancers(attachElbInput); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Failure attaching AutoScaling Group %s with Elastic Load Balancer: %s: {{err}}", asgName, elbName), err) + } + + d.SetId(resource.PrefixedUniqueId(fmt.Sprintf("%s-", asgName))) + + return resourceAwsAutoscalingAttachmentRead(d, meta) +} + +func resourceAwsAutoscalingAttachmentRead(d *schema.ResourceData, meta interface{}) error { + asgconn := meta.(*AWSClient).autoscalingconn + asgName := d.Get("autoscaling_group_name").(string) + elbName := d.Get("elb").(string) + + // Retrieve the ASG properites to get list of associated ELBs + asg, err := getAwsAutoscalingGroup(asgName, asgconn) + + if err != nil { + return err + } + if asg == nil { + log.Printf("[INFO] Autoscaling Group %q not found", asgName) + d.SetId("") + return nil + } + + found := false + for _, i := range asg.LoadBalancerNames { + if elbName == *i { + d.Set("elb", elbName) + found = true + break + } + } + + if !found { + log.Printf("[WARN] Association for %s was not found in ASG assocation", elbName) + d.SetId("") + } + + return nil +} + +func resourceAwsAutoscalingAttachmentDelete(d *schema.ResourceData, meta interface{}) error { + asgconn := meta.(*AWSClient).autoscalingconn + asgName := d.Get("autoscaling_group_name").(string) + elbName := d.Get("elb").(string) + + log.Printf("[INFO] Deleting ELB %s association from: %s", elbName, asgName) + + detachOpts := &autoscaling.DetachLoadBalancersInput{ + AutoScalingGroupName: aws.String(asgName), + LoadBalancerNames: []*string{aws.String(elbName)}, + } + + if _, err := asgconn.DetachLoadBalancers(detachOpts); err != nil { + return errwrap.Wrapf(fmt.Sprintf("Failure detaching AutoScaling Group %s with Elastic Load Balancer: %s: {{err}}", asgName, elbName), err) + } + + return nil +} diff --git a/builtin/providers/aws/resource_aws_autoscaling_attachment_test.go b/builtin/providers/aws/resource_aws_autoscaling_attachment_test.go new file mode 100644 index 000000000..c9eb2c951 --- /dev/null +++ b/builtin/providers/aws/resource_aws_autoscaling_attachment_test.go @@ -0,0 +1,144 @@ +package aws + +import ( + "fmt" + "testing" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/autoscaling" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAwsAutoscalingAttachment_basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSAutoscalingAttachment_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutocalingAttachmentExists("aws_autoscaling_group.asg", 0), + ), + }, + // Add in one association + resource.TestStep{ + Config: testAccAWSAutoscalingAttachment_associated, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutocalingAttachmentExists("aws_autoscaling_group.asg", 1), + ), + }, + // Test adding a 2nd + resource.TestStep{ + Config: testAccAWSAutoscalingAttachment_double_associated, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutocalingAttachmentExists("aws_autoscaling_group.asg", 2), + ), + }, + // Now remove that newest one + resource.TestStep{ + Config: testAccAWSAutoscalingAttachment_associated, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutocalingAttachmentExists("aws_autoscaling_group.asg", 1), + ), + }, + // Now remove them both + resource.TestStep{ + Config: testAccAWSAutoscalingAttachment_basic, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSAutocalingAttachmentExists("aws_autoscaling_group.asg", 0), + ), + }, + }, + }) +} + +func testAccCheckAWSAutocalingAttachmentExists(asgname string, loadBalancerCount int) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[asgname] + if !ok { + return fmt.Errorf("Not found: %s", asgname) + } + + conn := testAccProvider.Meta().(*AWSClient).autoscalingconn + asg := rs.Primary.ID + + actual, err := conn.DescribeAutoScalingGroups(&autoscaling.DescribeAutoScalingGroupsInput{ + AutoScalingGroupNames: []*string{aws.String(asg)}, + }) + + if err != nil { + return fmt.Errorf("Recieved an error when attempting to load %s: %s", asg, err) + } + + if loadBalancerCount != len(actual.AutoScalingGroups[0].LoadBalancerNames) { + return fmt.Errorf("Error: ASG has the wrong number of load balacners associated. Expected [%d] but got [%d]", loadBalancerCount, len(actual.AutoScalingGroups[0].LoadBalancerNames)) + } + + return nil + } +} + +const testAccAWSAutoscalingAttachment_basic = ` +resource "aws_elb" "foo" { + availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"] + + listener { + instance_port = 8000 + instance_protocol = "http" + lb_port = 80 + lb_protocol = "http" + } +} + +resource "aws_elb" "bar" { + availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"] + + listener { + instance_port = 8000 + instance_protocol = "http" + lb_port = 80 + lb_protocol = "http" + } +} + +resource "aws_launch_configuration" "as_conf" { + name = "test_config" + image_id = "ami-f34032c3" + instance_type = "t1.micro" +} + +resource "aws_autoscaling_group" "asg" { + availability_zones = ["us-west-2a", "us-west-2b", "us-west-2c"] + name = "asg-lb-assoc-terraform-test" + max_size = 1 + min_size = 0 + desired_capacity = 0 + health_check_grace_period = 300 + force_delete = true + launch_configuration = "${aws_launch_configuration.as_conf.name}" + + tag { + key = "Name" + value = "terraform-asg-lg-assoc-test" + propagate_at_launch = true + } +} + +` + +const testAccAWSAutoscalingAttachment_associated = testAccAWSAutoscalingAttachment_basic + ` +resource "aws_autoscaling_attachment" "asg_attachment_foo" { + autoscaling_group_name = "${aws_autoscaling_group.asg.id}" + elb = "${aws_elb.foo.id}" +} + +` + +const testAccAWSAutoscalingAttachment_double_associated = testAccAWSAutoscalingAttachment_associated + ` +resource "aws_autoscaling_attachment" "asg_attachment_bar" { + autoscaling_group_name = "${aws_autoscaling_group.asg.id}" + elb = "${aws_elb.bar.id}" +} + +` diff --git a/builtin/providers/aws/resource_aws_autoscaling_group.go b/builtin/providers/aws/resource_aws_autoscaling_group.go index c35552605..ea29685f7 100644 --- a/builtin/providers/aws/resource_aws_autoscaling_group.go +++ b/builtin/providers/aws/resource_aws_autoscaling_group.go @@ -109,6 +109,7 @@ func resourceAwsAutoscalingGroup() *schema.Resource { "load_balancers": &schema.Schema{ Type: schema.TypeSet, Optional: true, + Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, Set: schema.HashString, }, diff --git a/website/source/docs/providers/aws/r/autoscaling_attachment.html.markdown b/website/source/docs/providers/aws/r/autoscaling_attachment.html.markdown new file mode 100644 index 000000000..6e966bade --- /dev/null +++ b/website/source/docs/providers/aws/r/autoscaling_attachment.html.markdown @@ -0,0 +1,35 @@ +--- +layout: "aws" +page_title: "AWS: aws_autoscaling_attachment" +sidebar_current: "docs-aws-resource-autoscaling-attachment" +description: |- + Provides an AutoScaling Group Attachment resource. +--- + +# aws\_autoscaling\_attachment + +Provides an AutoScaling Attachment resource. + +~> **NOTE on AutoScaling Groups and ASG Attachments:** Terraform currently provides +both a standalone ASG Attachment resource (describing an ASG attached to +an ELB), and an [AutoScaling Group resource](autoscaling_group.html) with +`load_balancers` defined in-line. At this time you cannot use an ASG with in-line +load balancers in conjunction with an ASG Attachment resource. Doing so will cause a +conflict and will overwrite attachments. +## Example Usage + +``` +# Create a new load balancer attachment +resource "aws_autoscaling_attachment" "asg_attachment_bar" { + autoscaling_group_name = "${aws_autoscaling_group.asg.id}" + elb = "${aws_elb.bar.id}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `autoscaling_group_name` - (Required) Name of ASG to associate with the ELB. +* `elb` - (Required) The name of the ELB. + diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index c70c9c2a9..0b9fd7a82 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -295,6 +295,10 @@ aws_autoscaling_group +