func testAccCheckAWSELBAttributesHealthCheck(conf *elb.LoadBalancerDescription) resource.TestCheckFunc { return func(s *terraform.State) error { zones := []string{"us-west-2a", "us-west-2b", "us-west-2c"} sort.StringSlice(conf.AvailabilityZones).Sort() if !reflect.DeepEqual(conf.AvailabilityZones, zones) { return fmt.Errorf("bad availability_zones") } if *conf.LoadBalancerName != "foobar-terraform-test" { return fmt.Errorf("bad name") } check := elb.HealthCheck{ Timeout: aws.Integer(30), UnhealthyThreshold: aws.Integer(5), HealthyThreshold: aws.Integer(5), Interval: aws.Integer(60), Target: aws.String("HTTP:8000/"), } if !reflect.DeepEqual(conf.HealthCheck, &check) { return fmt.Errorf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", conf.HealthCheck, check) } if *conf.DNSName == "" { return fmt.Errorf("empty dns_name") } return nil } }
func testAccCheckAWSELBAttributes(conf *elb.LoadBalancerDescription) resource.TestCheckFunc { return func(s *terraform.State) error { zones := []string{"us-west-2a", "us-west-2b", "us-west-2c"} sort.StringSlice(conf.AvailabilityZones).Sort() if !reflect.DeepEqual(conf.AvailabilityZones, zones) { return fmt.Errorf("bad availability_zones") } if *conf.LoadBalancerName != "foobar-terraform-test" { return fmt.Errorf("bad name") } l := elb.Listener{ InstancePort: aws.Integer(8000), InstanceProtocol: aws.String("HTTP"), LoadBalancerPort: aws.Integer(80), Protocol: aws.String("HTTP"), } if !reflect.DeepEqual(conf.ListenerDescriptions[0].Listener, &l) { return fmt.Errorf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", conf.ListenerDescriptions[0].Listener, l) } if *conf.DNSName == "" { return fmt.Errorf("empty dns_name") } return nil } }
func resourceAwsAutoscalingGroupDrain(d *schema.ResourceData, meta interface{}) error { autoscalingconn := meta.(*AWSClient).autoscalingconn // First, set the capacity to zero so the group will drain log.Printf("[DEBUG] Reducing autoscaling group capacity to zero") opts := autoscaling.UpdateAutoScalingGroupType{ AutoScalingGroupName: aws.String(d.Id()), DesiredCapacity: aws.Integer(0), MinSize: aws.Integer(0), MaxSize: aws.Integer(0), } if err := autoscalingconn.UpdateAutoScalingGroup(&opts); err != nil { return fmt.Errorf("Error setting capacity to zero to drain: %s", err) } // Next, wait for the autoscale group to drain log.Printf("[DEBUG] Waiting for group to have zero instances") return resource.Retry(10*time.Minute, func() error { g, err := getAwsAutoscalingGroup(d, meta) if err != nil { return resource.RetryError{Err: err} } if g == nil { return nil } if len(g.Instances) == 0 { return nil } return fmt.Errorf("group still has %d instances", len(g.Instances)) }) }
func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroup) resource.TestCheckFunc { return func(s *terraform.State) error { p := ec2.IPPermission{ FromPort: aws.Integer(80), ToPort: aws.Integer(8000), IPProtocol: aws.String("tcp"), IPRanges: []ec2.IPRange{ec2.IPRange{aws.String("10.0.0.0/8")}}, } if *group.GroupName != "terraform_acceptance_test_example" { return fmt.Errorf("Bad name: %s", *group.GroupName) } if *group.Description != "Used in the terraform acceptance tests" { return fmt.Errorf("Bad description: %s", *group.Description) } if len(group.IPPermissions) == 0 { return fmt.Errorf("No IPPerms") } // Compare our ingress if !reflect.DeepEqual(group.IPPermissions[0], p) { return fmt.Errorf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", group.IPPermissions[0], p) } return nil } }
func expandNetworkAclEntries(configured []interface{}, entryType string) ([]ec2.NetworkACLEntry, error) { entries := make([]ec2.NetworkACLEntry, 0, len(configured)) for _, eRaw := range configured { data := eRaw.(map[string]interface{}) protocol := data["protocol"].(string) _, ok := protocolIntegers()[protocol] if !ok { return nil, fmt.Errorf("Invalid Protocol %s for rule %#v", protocol, data) } p := extractProtocolInteger(data["protocol"].(string)) e := ec2.NetworkACLEntry{ Protocol: aws.String(strconv.Itoa(p)), PortRange: &ec2.PortRange{ From: aws.Integer(data["from_port"].(int)), To: aws.Integer(data["to_port"].(int)), }, Egress: aws.Boolean((entryType == "egress")), RuleAction: aws.String(data["action"].(string)), RuleNumber: aws.Integer(data["rule_no"].(int)), CIDRBlock: aws.String(data["cidr_block"].(string)), } entries = append(entries, e) } return entries, nil }
func resourceAwsAutoscalingGroupCreate(d *schema.ResourceData, meta interface{}) error { autoscalingconn := meta.(*AWSClient).autoscalingconn var autoScalingGroupOpts autoscaling.CreateAutoScalingGroupType autoScalingGroupOpts.AutoScalingGroupName = aws.String(d.Get("name").(string)) autoScalingGroupOpts.LaunchConfigurationName = aws.String(d.Get("launch_configuration").(string)) autoScalingGroupOpts.MinSize = aws.Integer(d.Get("min_size").(int)) autoScalingGroupOpts.MaxSize = aws.Integer(d.Get("max_size").(int)) autoScalingGroupOpts.AvailabilityZones = expandStringList( d.Get("availability_zones").(*schema.Set).List()) if v, ok := d.GetOk("tag"); ok { autoScalingGroupOpts.Tags = autoscalingTagsFromMap( setToMapByKey(v.(*schema.Set), "key"), d.Get("name").(string)) } if v, ok := d.GetOk("default_cooldown"); ok { autoScalingGroupOpts.DefaultCooldown = aws.Integer(v.(int)) } if v, ok := d.GetOk("health_check_type"); ok && v.(string) != "" { autoScalingGroupOpts.HealthCheckType = aws.String(v.(string)) } if v, ok := d.GetOk("desired_capacity"); ok { autoScalingGroupOpts.DesiredCapacity = aws.Integer(v.(int)) } if v, ok := d.GetOk("health_check_grace_period"); ok { autoScalingGroupOpts.HealthCheckGracePeriod = aws.Integer(v.(int)) } if v, ok := d.GetOk("load_balancers"); ok && v.(*schema.Set).Len() > 0 { autoScalingGroupOpts.LoadBalancerNames = expandStringList( v.(*schema.Set).List()) } if v, ok := d.GetOk("vpc_zone_identifier"); ok && v.(*schema.Set).Len() > 0 { exp := expandStringList(v.(*schema.Set).List()) autoScalingGroupOpts.VPCZoneIdentifier = aws.String(strings.Join(exp, ",")) } if v, ok := d.GetOk("termination_policies"); ok && v.(*schema.Set).Len() > 0 { autoScalingGroupOpts.TerminationPolicies = expandStringList( v.(*schema.Set).List()) } log.Printf("[DEBUG] AutoScaling Group create configuration: %#v", autoScalingGroupOpts) err := autoscalingconn.CreateAutoScalingGroup(&autoScalingGroupOpts) if err != nil { return fmt.Errorf("Error creating Autoscaling Group: %s", err) } d.SetId(d.Get("name").(string)) log.Printf("[INFO] AutoScaling Group ID: %s", d.Id()) return resourceAwsAutoscalingGroupRead(d, meta) }
func resourceAwsNetworkInterfaceUpdate(d *schema.ResourceData, meta interface{}) error { ec2conn := meta.(*AWSClient).ec2conn d.Partial(true) if d.HasChange("attachment") { ec2conn := meta.(*AWSClient).ec2conn oa, na := d.GetChange("attachment") detach_err := resourceAwsNetworkInterfaceDetach(oa.(*schema.Set), meta, d.Id()) if detach_err != nil { return detach_err } // if there is a new attachment, attach it if na != nil && len(na.(*schema.Set).List()) > 0 { new_attachment := na.(*schema.Set).List()[0].(map[string]interface{}) attach_request := &ec2.AttachNetworkInterfaceRequest{ DeviceIndex: aws.Integer(new_attachment["device_index"].(int)), InstanceID: aws.String(new_attachment["instance"].(string)), NetworkInterfaceID: aws.String(d.Id()), } _, attach_err := ec2conn.AttachNetworkInterface(attach_request) if attach_err != nil { return fmt.Errorf("Error attaching ENI: %s", attach_err) } } d.SetPartial("attachment") } if d.HasChange("security_groups") { request := &ec2.ModifyNetworkInterfaceAttributeRequest{ NetworkInterfaceID: aws.String(d.Id()), Groups: expandStringList(d.Get("security_groups").(*schema.Set).List()), } err := ec2conn.ModifyNetworkInterfaceAttribute(request) if err != nil { return fmt.Errorf("Failure updating ENI: %s", err) } d.SetPartial("security_groups") } if err := setTags(ec2conn, d); err != nil { return err } else { d.SetPartial("tags") } d.Partial(false) return resourceAwsNetworkInterfaceRead(d, meta) }
func resourceAwsAutoscalingGroupUpdate(d *schema.ResourceData, meta interface{}) error { autoscalingconn := meta.(*AWSClient).autoscalingconn opts := autoscaling.UpdateAutoScalingGroupType{ AutoScalingGroupName: aws.String(d.Id()), } if d.HasChange("desired_capacity") { opts.DesiredCapacity = aws.Integer(d.Get("desired_capacity").(int)) } if d.HasChange("launch_configuration") { opts.LaunchConfigurationName = aws.String(d.Get("launch_configuration").(string)) } if d.HasChange("min_size") { opts.MinSize = aws.Integer(d.Get("min_size").(int)) } if d.HasChange("max_size") { opts.MaxSize = aws.Integer(d.Get("max_size").(int)) } if err := setAutoscalingTags(autoscalingconn, d); err != nil { return err } else { d.SetPartial("tag") } log.Printf("[DEBUG] AutoScaling Group update configuration: %#v", opts) err := autoscalingconn.UpdateAutoScalingGroup(&opts) if err != nil { d.Partial(true) return fmt.Errorf("Error updating Autoscaling group: %s", err) } return resourceAwsAutoscalingGroupRead(d, meta) }
func TestMarshalingXML(t *testing.T) { r := &XMLRequest{ Integer: aws.Integer(0), DangerZone: "a zone of danger", } out, err := xml.Marshal(r) if err != nil { t.Fatal(err) } if v, want := string(out), `<Request xmlns="http://whatever"><Integer>0</Integer></Request>`; v != want { t.Errorf("XML was \n%s\n but expected \n%s", v, want) } }
func Test_expandNetworkACLEntry(t *testing.T) { input := []interface{}{ map[string]interface{}{ "protocol": "tcp", "from_port": 22, "to_port": 22, "cidr_block": "0.0.0.0/0", "action": "deny", "rule_no": 1, }, map[string]interface{}{ "protocol": "tcp", "from_port": 443, "to_port": 443, "cidr_block": "0.0.0.0/0", "action": "deny", "rule_no": 2, }, } expanded, _ := expandNetworkAclEntries(input, "egress") expected := []ec2.NetworkACLEntry{ ec2.NetworkACLEntry{ Protocol: aws.String("6"), PortRange: &ec2.PortRange{ From: aws.Integer(22), To: aws.Integer(22), }, RuleAction: aws.String("deny"), RuleNumber: aws.Integer(1), CIDRBlock: aws.String("0.0.0.0/0"), Egress: aws.Boolean(true), }, ec2.NetworkACLEntry{ Protocol: aws.String("6"), PortRange: &ec2.PortRange{ From: aws.Integer(443), To: aws.Integer(443), }, RuleAction: aws.String("deny"), RuleNumber: aws.Integer(2), CIDRBlock: aws.String("0.0.0.0/0"), Egress: aws.Boolean(true), }, } if !reflect.DeepEqual(expanded, expected) { t.Fatalf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", expanded, expected) } }
func Test_flattenNetworkACLEntry(t *testing.T) { apiInput := []ec2.NetworkACLEntry{ ec2.NetworkACLEntry{ Protocol: aws.String("tcp"), PortRange: &ec2.PortRange{ From: aws.Integer(22), To: aws.Integer(22), }, RuleAction: aws.String("deny"), RuleNumber: aws.Integer(1), CIDRBlock: aws.String("0.0.0.0/0"), }, ec2.NetworkACLEntry{ Protocol: aws.String("tcp"), PortRange: &ec2.PortRange{ From: aws.Integer(443), To: aws.Integer(443), }, RuleAction: aws.String("deny"), RuleNumber: aws.Integer(2), CIDRBlock: aws.String("0.0.0.0/0"), }, } flattened := flattenNetworkAclEntries(apiInput) expected := []map[string]interface{}{ map[string]interface{}{ "protocol": "tcp", "from_port": 22, "to_port": 22, "cidr_block": "0.0.0.0/0", "action": "deny", "rule_no": 1, }, map[string]interface{}{ "protocol": "tcp", "from_port": 443, "to_port": 443, "cidr_block": "0.0.0.0/0", "action": "deny", "rule_no": 2, }, } if !reflect.DeepEqual(flattened, expected) { t.Fatalf( "Got:\n\n%#v\n\nExpected:\n\n%#v\n", flattened[0], expected) } }
func resourceAwsElbUpdate(d *schema.ResourceData, meta interface{}) error { elbconn := meta.(*AWSClient).elbconn d.Partial(true) // If we currently have instances, or did have instances, // we want to figure out what to add and remove from the load // balancer if d.HasChange("instances") { o, n := d.GetChange("instances") os := o.(*schema.Set) ns := n.(*schema.Set) remove := expandInstanceString(os.Difference(ns).List()) add := expandInstanceString(ns.Difference(os).List()) if len(add) > 0 { registerInstancesOpts := elb.RegisterEndPointsInput{ LoadBalancerName: aws.String(d.Id()), Instances: add, } _, err := elbconn.RegisterInstancesWithLoadBalancer(®isterInstancesOpts) if err != nil { return fmt.Errorf("Failure registering instances: %s", err) } } if len(remove) > 0 { deRegisterInstancesOpts := elb.DeregisterEndPointsInput{ LoadBalancerName: aws.String(d.Id()), Instances: remove, } _, err := elbconn.DeregisterInstancesFromLoadBalancer(&deRegisterInstancesOpts) if err != nil { return fmt.Errorf("Failure deregistering instances: %s", err) } } d.SetPartial("instances") } log.Println("[INFO] outside modify attributes") if d.HasChange("cross_zone_load_balancing") { log.Println("[INFO] inside modify attributes") attrs := elb.ModifyLoadBalancerAttributesInput{ LoadBalancerName: aws.String(d.Get("name").(string)), LoadBalancerAttributes: &elb.LoadBalancerAttributes{ CrossZoneLoadBalancing: &elb.CrossZoneLoadBalancing{ aws.Boolean(d.Get("cross_zone_load_balancing").(bool)), }, }, } _, err := elbconn.ModifyLoadBalancerAttributes(&attrs) if err != nil { return fmt.Errorf("Failure configuring cross zone balancing: %s", err) } d.SetPartial("cross_zone_load_balancing") } if d.HasChange("health_check") { vs := d.Get("health_check").(*schema.Set).List() if len(vs) > 0 { check := vs[0].(map[string]interface{}) configureHealthCheckOpts := elb.ConfigureHealthCheckInput{ LoadBalancerName: aws.String(d.Id()), HealthCheck: &elb.HealthCheck{ HealthyThreshold: aws.Integer(check["healthy_threshold"].(int)), UnhealthyThreshold: aws.Integer(check["unhealthy_threshold"].(int)), Interval: aws.Integer(check["interval"].(int)), Target: aws.String(check["target"].(string)), Timeout: aws.Integer(check["timeout"].(int)), }, } _, err := elbconn.ConfigureHealthCheck(&configureHealthCheckOpts) if err != nil { return fmt.Errorf("Failure configuring health check: %s", err) } d.SetPartial("health_check") } } if err := setTagsELB(elbconn, d); err != nil { return err } else { d.SetPartial("tags") } d.Partial(false) return resourceAwsElbRead(d, meta) }
func TestQueryRequest(t *testing.T) { var m sync.Mutex var httpReq *http.Request var form url.Values server := httptest.NewServer(http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { m.Lock() defer m.Unlock() httpReq = r if err := r.ParseForm(); err != nil { t.Fatal(err) } form = r.Form fmt.Fprintln(w, `<Thing><IpAddress>woo</IpAddress></Thing>`) }, )) defer server.Close() client := aws.QueryClient{ Context: aws.Context{ Service: "animals", Region: "us-west-2", Credentials: aws.Creds( "accessKeyID", "secretAccessKey", "securityToken", ), }, Client: http.DefaultClient, Endpoint: server.URL, APIVersion: "1.1", } req := fakeQueryRequest{ PresentString: aws.String("string"), PresentBoolean: aws.True(), PresentInteger: aws.Integer(1), PresentLong: aws.Long(2), PresentDouble: aws.Double(1.2), PresentFloat: aws.Float(2.3), PresentTime: time.Date(2001, 1, 1, 2, 1, 1, 0, time.FixedZone("UTC+1", 3600)), PresentSlice: []string{"one", "two"}, PresentStruct: &EmbeddedStruct{Value: aws.String("v")}, PresentStructSlice: []EmbeddedStruct{ {Value: aws.String("p")}, {Value: aws.String("q")}, }, PresentMap: map[string]EmbeddedStruct{ "aa": EmbeddedStruct{Value: aws.String("AA")}, "bb": EmbeddedStruct{Value: aws.String("BB")}, }, } var resp fakeQueryResponse if err := client.Do("GetIP", "POST", "/", &req, &resp); err != nil { t.Fatal(err) } m.Lock() defer m.Unlock() if v, want := httpReq.Method, "POST"; v != want { t.Errorf("Method was %v but expected %v", v, want) } if httpReq.Header.Get("Authorization") == "" { t.Error("Authorization header is missing") } if v, want := httpReq.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; v != want { t.Errorf("Content-Type was %v but expected %v", v, want) } if v, want := httpReq.Header.Get("User-Agent"), "aws-go"; v != want { t.Errorf("User-Agent was %v but expected %v", v, want) } if err := httpReq.ParseForm(); err != nil { t.Fatal(err) } expectedForm := url.Values{ "Action": []string{"GetIP"}, "Version": []string{"1.1"}, "PresentString": []string{"string"}, "PresentBoolean": []string{"true"}, "PresentInteger": []string{"1"}, "PresentLong": []string{"2"}, "PresentDouble": []string{"1.2"}, "PresentFloat": []string{"2.3"}, "PresentTime": []string{"2001-01-01T01:01:01Z"}, "PresentSlice.1": []string{"one"}, "PresentSlice.2": []string{"two"}, "PresentStruct.Value": []string{"v"}, "PresentStructSlice.1.Value": []string{"p"}, "PresentStructSlice.2.Value": []string{"q"}, "PresentMap.1.Name": []string{"aa"}, "PresentMap.1.Value.Value": []string{"AA"}, "PresentMap.2.Name": []string{"bb"}, "PresentMap.2.Value.Value": []string{"BB"}, } if !reflect.DeepEqual(form, expectedForm) { t.Errorf("Post body was \n%s\n but expected \n%s", form.Encode(), expectedForm.Encode()) } if want := (fakeQueryResponse{IPAddress: "woo"}); want != resp { t.Errorf("Response was %#v, but expected %#v", resp, want) } }
func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { ec2conn := meta.(*AWSClient).ec2conn // Figure out user data userData := "" if v := d.Get("user_data"); v != nil { userData = base64.StdEncoding.EncodeToString([]byte(v.(string))) } // check for non-default Subnet, and cast it to a String var hasSubnet bool subnet, hasSubnet := d.GetOk("subnet_id") subnetID := subnet.(string) placement := &ec2.Placement{ AvailabilityZone: aws.String(d.Get("availability_zone").(string)), } if hasSubnet { // Tenancy is only valid inside a VPC // See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Placement.html if v := d.Get("tenancy").(string); v != "" { placement.Tenancy = aws.String(v) } } iam := &ec2.IAMInstanceProfileSpecification{ Name: aws.String(d.Get("iam_instance_profile").(string)), } // Build the creation struct runOpts := &ec2.RunInstancesRequest{ ImageID: aws.String(d.Get("ami").(string)), Placement: placement, InstanceType: aws.String(d.Get("instance_type").(string)), MaxCount: aws.Integer(1), MinCount: aws.Integer(1), UserData: aws.String(userData), EBSOptimized: aws.Boolean(d.Get("ebs_optimized").(bool)), IAMInstanceProfile: iam, } associatePublicIPAddress := false if v := d.Get("associate_public_ip_address"); v != nil { associatePublicIPAddress = v.(bool) } var groups []string if v := d.Get("security_groups"); v != nil { // Security group names. // For a nondefault VPC, you must use security group IDs instead. // See http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RunInstances.html for _, v := range v.(*schema.Set).List() { str := v.(string) groups = append(groups, str) } } if hasSubnet && associatePublicIPAddress { // If we have a non-default VPC / Subnet specified, we can flag // AssociatePublicIpAddress to get a Public IP assigned. By default these are not provided. // You cannot specify both SubnetId and the NetworkInterface.0.* parameters though, otherwise // you get: Network interfaces and an instance-level subnet ID may not be specified on the same request // You also need to attach Security Groups to the NetworkInterface instead of the instance, // to avoid: Network interfaces and an instance-level security groups may not be specified on // the same request ni := ec2.InstanceNetworkInterfaceSpecification{ AssociatePublicIPAddress: aws.Boolean(associatePublicIPAddress), DeviceIndex: aws.Integer(0), SubnetID: aws.String(subnetID), } if v, ok := d.GetOk("private_ip"); ok { ni.PrivateIPAddress = aws.String(v.(string)) } if len(groups) > 0 { ni.Groups = groups } runOpts.NetworkInterfaces = []ec2.InstanceNetworkInterfaceSpecification{ni} } else { if subnetID != "" { runOpts.SubnetID = aws.String(subnetID) } if v, ok := d.GetOk("private_ip"); ok { runOpts.PrivateIPAddress = aws.String(v.(string)) } if runOpts.SubnetID != nil && *runOpts.SubnetID != "" { runOpts.SecurityGroupIDs = groups } else { runOpts.SecurityGroups = groups } } if v, ok := d.GetOk("key_name"); ok { runOpts.KeyName = aws.String(v.(string)) } blockDevices := make([]ec2.BlockDeviceMapping, 0) if v, ok := d.GetOk("ebs_block_device"); ok { vL := v.(*schema.Set).List() for _, v := range vL { bd := v.(map[string]interface{}) ebs := &ec2.EBSBlockDevice{ DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)), } if v, ok := bd["snapshot_id"].(string); ok && v != "" { ebs.SnapshotID = aws.String(v) } if v, ok := bd["volume_size"].(int); ok && v != 0 { ebs.VolumeSize = aws.Integer(v) } if v, ok := bd["volume_type"].(string); ok && v != "" { ebs.VolumeType = aws.String(v) } if v, ok := bd["iops"].(int); ok && v > 0 { ebs.IOPS = aws.Integer(v) } blockDevices = append(blockDevices, ec2.BlockDeviceMapping{ DeviceName: aws.String(bd["device_name"].(string)), EBS: ebs, }) } } if v, ok := d.GetOk("ephemeral_block_device"); ok { vL := v.(*schema.Set).List() for _, v := range vL { bd := v.(map[string]interface{}) blockDevices = append(blockDevices, ec2.BlockDeviceMapping{ DeviceName: aws.String(bd["device_name"].(string)), VirtualName: aws.String(bd["virtual_name"].(string)), }) } } if v, ok := d.GetOk("root_block_device"); ok { vL := v.(*schema.Set).List() if len(vL) > 1 { return fmt.Errorf("Cannot specify more than one root_block_device.") } for _, v := range vL { bd := v.(map[string]interface{}) ebs := &ec2.EBSBlockDevice{ DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)), } if v, ok := bd["volume_size"].(int); ok && v != 0 { ebs.VolumeSize = aws.Integer(v) } if v, ok := bd["volume_type"].(string); ok && v != "" { ebs.VolumeType = aws.String(v) } if v, ok := bd["iops"].(int); ok && v > 0 { ebs.IOPS = aws.Integer(v) } if dn, err := fetchRootDeviceName(d.Get("ami").(string), ec2conn); err == nil { blockDevices = append(blockDevices, ec2.BlockDeviceMapping{ DeviceName: dn, EBS: ebs, }) } else { return err } } } if len(blockDevices) > 0 { runOpts.BlockDeviceMappings = blockDevices } // Create the instance log.Printf("[DEBUG] Run configuration: %#v", runOpts) runResp, err := ec2conn.RunInstances(runOpts) if err != nil { return fmt.Errorf("Error launching source instance: %s", err) } instance := &runResp.Instances[0] log.Printf("[INFO] Instance ID: %s", *instance.InstanceID) // Store the resulting ID so we can look this up later d.SetId(*instance.InstanceID) // Wait for the instance to become running so we can get some attributes // that aren't available until later. log.Printf( "[DEBUG] Waiting for instance (%s) to become running", *instance.InstanceID) stateConf := &resource.StateChangeConf{ Pending: []string{"pending"}, Target: "running", Refresh: InstanceStateRefreshFunc(ec2conn, *instance.InstanceID), Timeout: 10 * time.Minute, Delay: 10 * time.Second, MinTimeout: 3 * time.Second, } instanceRaw, err := stateConf.WaitForState() if err != nil { return fmt.Errorf( "Error waiting for instance (%s) to become ready: %s", *instance.InstanceID, err) } instance = instanceRaw.(*ec2.Instance) // Initialize the connection info if instance.PublicIPAddress != nil { d.SetConnInfo(map[string]string{ "type": "ssh", "host": *instance.PublicIPAddress, }) } // Set our attributes if err := resourceAwsInstanceRead(d, meta); err != nil { return err } // Update if we need to return resourceAwsInstanceUpdate(d, meta) }
func TestAccAWSInstance_normal(t *testing.T) { var v ec2.Instance var vol *ec2.Volume testCheck := func(*terraform.State) error { if *v.Placement.AvailabilityZone != "us-west-2a" { return fmt.Errorf("bad availability zone: %#v", *v.Placement.AvailabilityZone) } if len(v.SecurityGroups) == 0 { return fmt.Errorf("no security groups: %#v", v.SecurityGroups) } if *v.SecurityGroups[0].GroupName != "tf_test_foo" { return fmt.Errorf("no security groups: %#v", v.SecurityGroups) } return nil } resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckInstanceDestroy, Steps: []resource.TestStep{ // Create a volume to cover #1249 resource.TestStep{ // Need a resource in this config so the provisioner will be available Config: testAccInstanceConfig_pre, Check: func(*terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn var err error vol, err = conn.CreateVolume(&ec2.CreateVolumeRequest{ AvailabilityZone: aws.String("us-west-2a"), Size: aws.Integer(5), }) return err }, }, resource.TestStep{ Config: testAccInstanceConfig, Check: resource.ComposeTestCheckFunc( testAccCheckInstanceExists( "aws_instance.foo", &v), testCheck, resource.TestCheckResourceAttr( "aws_instance.foo", "user_data", "3dc39dda39be1205215e776bad998da361a5955d"), resource.TestCheckResourceAttr( "aws_instance.foo", "ebs_block_device.#", "0"), ), }, // We repeat the exact same test so that we can be sure // that the user data hash stuff is working without generating // an incorrect diff. resource.TestStep{ Config: testAccInstanceConfig, Check: resource.ComposeTestCheckFunc( testAccCheckInstanceExists( "aws_instance.foo", &v), testCheck, resource.TestCheckResourceAttr( "aws_instance.foo", "user_data", "3dc39dda39be1205215e776bad998da361a5955d"), resource.TestCheckResourceAttr( "aws_instance.foo", "ebs_block_device.#", "0"), ), }, // Clean up volume created above resource.TestStep{ Config: testAccInstanceConfig, Check: func(*terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).ec2conn return conn.DeleteVolume(&ec2.DeleteVolumeRequest{VolumeID: vol.VolumeID}) }, }, }, }) }
func resourceAwsDbInstanceUpdate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).rdsconn d.Partial(true) req := &rds.ModifyDBInstanceMessage{ ApplyImmediately: aws.Boolean(d.Get("apply_immediately").(bool)), DBInstanceIdentifier: aws.String(d.Id()), } d.SetPartial("apply_immediately") if d.HasChange("allocated_storage") { d.SetPartial("allocated_storage") req.AllocatedStorage = aws.Integer(d.Get("allocated_storage").(int)) } if d.HasChange("backup_retention_period") { d.SetPartial("backup_retention_period") req.BackupRetentionPeriod = aws.Integer(d.Get("backup_retention_period").(int)) } if d.HasChange("instance_class") { d.SetPartial("instance_class") req.DBInstanceClass = aws.String(d.Get("instance_class").(string)) } if d.HasChange("parameter_group_name") { d.SetPartial("parameter_group_name") req.DBParameterGroupName = aws.String(d.Get("parameter_group_name").(string)) } if d.HasChange("engine_version") { d.SetPartial("engine_version") req.EngineVersion = aws.String(d.Get("engine_version").(string)) } if d.HasChange("iops") { d.SetPartial("iops") req.IOPS = aws.Integer(d.Get("iops").(int)) } if d.HasChange("backup_window") { d.SetPartial("backup_window") req.PreferredBackupWindow = aws.String(d.Get("backup_window").(string)) } if d.HasChange("maintenance_window") { d.SetPartial("maintenance_window") req.PreferredMaintenanceWindow = aws.String(d.Get("maintenance_window").(string)) } if d.HasChange("password") { d.SetPartial("password") req.MasterUserPassword = aws.String(d.Get("password").(string)) } if d.HasChange("multi_az") { d.SetPartial("multi_az") req.MultiAZ = aws.Boolean(d.Get("multi_az").(bool)) } if d.HasChange("storage_type") { d.SetPartial("storage_type") req.StorageType = aws.String(d.Get("storage_type").(string)) } if d.HasChange("vpc_security_group_ids") { if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { var s []string for _, v := range attr.List() { s = append(s, v.(string)) } req.VPCSecurityGroupIDs = s } } if d.HasChange("vpc_security_group_ids") { if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 { var s []string for _, v := range attr.List() { s = append(s, v.(string)) } req.DBSecurityGroups = s } } log.Printf("[DEBUG] DB Instance Modification request: %#v", req) _, err := conn.ModifyDBInstance(req) if err != nil { return fmt.Errorf("Error modifying DB Instance %s: %s", d.Id(), err) } if arn, err := buildRDSARN(d, meta); err == nil { if err := setTagsRDS(conn, d, arn); err != nil { return err } else { d.SetPartial("tags") } } d.Partial(false) return resourceAwsDbInstanceRead(d, meta) }
func pathUserRollback(req *logical.Request, _kind string, data interface{}) error { var entry walUser if err := mapstructure.Decode(data, &entry); err != nil { return err } username := entry.UserName // Get the client client, err := clientIAM(req.Storage) if err != nil { return err } // Get information about this user groupsResp, err := client.ListGroupsForUser(&iam.ListGroupsForUserRequest{ UserName: aws.String(username), MaxItems: aws.Integer(1000), }) if err != nil { return err } groups := groupsResp.Groups policiesResp, err := client.ListUserPolicies(&iam.ListUserPoliciesRequest{ UserName: aws.String(username), MaxItems: aws.Integer(1000), }) if err != nil { return err } policies := policiesResp.PolicyNames keysResp, err := client.ListAccessKeys(&iam.ListAccessKeysRequest{ UserName: aws.String(username), MaxItems: aws.Integer(1000), }) if err != nil { return err } keys := keysResp.AccessKeyMetadata // Revoke all keys for _, k := range keys { err = client.DeleteAccessKey(&iam.DeleteAccessKeyRequest{ AccessKeyID: k.AccessKeyID, UserName: aws.String(username), }) if err != nil { return err } } // Delete any policies for _, p := range policies { err = client.DeleteUserPolicy(&iam.DeleteUserPolicyRequest{ UserName: aws.String(username), PolicyName: aws.String(p), }) if err != nil { return err } } // Remove the user from all their groups for _, g := range groups { err = client.RemoveUserFromGroup(&iam.RemoveUserFromGroupRequest{ GroupName: g.GroupName, UserName: aws.String(username), }) if err != nil { return err } } // Delete the user err = client.DeleteUser(&iam.DeleteUserRequest{ UserName: aws.String(username), }) if err != nil { return err } return nil }
func resourceAwsElbCreate(d *schema.ResourceData, meta interface{}) error { elbconn := meta.(*AWSClient).elbconn // Expand the "listener" set to aws-sdk-go compat []elb.Listener listeners, err := expandListeners(d.Get("listener").(*schema.Set).List()) if err != nil { return err } tags := tagsFromMapELB(d.Get("tags").(map[string]interface{})) // Provision the elb elbOpts := &elb.CreateAccessPointInput{ LoadBalancerName: aws.String(d.Get("name").(string)), Listeners: listeners, Tags: tags, } if scheme, ok := d.GetOk("internal"); ok && scheme.(bool) { elbOpts.Scheme = aws.String("internal") } if v, ok := d.GetOk("availability_zones"); ok { elbOpts.AvailabilityZones = expandStringList(v.(*schema.Set).List()) } if v, ok := d.GetOk("security_groups"); ok { elbOpts.SecurityGroups = expandStringList(v.(*schema.Set).List()) } if v, ok := d.GetOk("subnets"); ok { elbOpts.Subnets = expandStringList(v.(*schema.Set).List()) } log.Printf("[DEBUG] ELB create configuration: %#v", elbOpts) if _, err := elbconn.CreateLoadBalancer(elbOpts); err != nil { return fmt.Errorf("Error creating ELB: %s", err) } // Assign the elb's unique identifier for use later d.SetId(d.Get("name").(string)) log.Printf("[INFO] ELB ID: %s", d.Id()) // Enable partial mode and record what we set d.Partial(true) d.SetPartial("name") d.SetPartial("internal") d.SetPartial("availability_zones") d.SetPartial("listener") d.SetPartial("security_groups") d.SetPartial("subnets") d.Set("tags", tagsToMapELB(tags)) if d.HasChange("health_check") { vs := d.Get("health_check").(*schema.Set).List() if len(vs) > 0 { check := vs[0].(map[string]interface{}) configureHealthCheckOpts := elb.ConfigureHealthCheckInput{ LoadBalancerName: aws.String(d.Id()), HealthCheck: &elb.HealthCheck{ HealthyThreshold: aws.Integer(check["healthy_threshold"].(int)), UnhealthyThreshold: aws.Integer(check["unhealthy_threshold"].(int)), Interval: aws.Integer(check["interval"].(int)), Target: aws.String(check["target"].(string)), Timeout: aws.Integer(check["timeout"].(int)), }, } _, err = elbconn.ConfigureHealthCheck(&configureHealthCheckOpts) if err != nil { return fmt.Errorf("Failure configuring health check: %s", err) } } } return resourceAwsElbUpdate(d, meta) }
func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface{}) error { autoscalingconn := meta.(*AWSClient).autoscalingconn ec2conn := meta.(*AWSClient).ec2conn createLaunchConfigurationOpts := autoscaling.CreateLaunchConfigurationType{ LaunchConfigurationName: aws.String(d.Get("name").(string)), ImageID: aws.String(d.Get("image_id").(string)), InstanceType: aws.String(d.Get("instance_type").(string)), EBSOptimized: aws.Boolean(d.Get("ebs_optimized").(bool)), } if v, ok := d.GetOk("user_data"); ok { userData := base64.StdEncoding.EncodeToString([]byte(v.(string))) createLaunchConfigurationOpts.UserData = aws.String(userData) } if v, ok := d.GetOk("iam_instance_profile"); ok { createLaunchConfigurationOpts.IAMInstanceProfile = aws.String(v.(string)) } if v, ok := d.GetOk("placement_tenancy"); ok { createLaunchConfigurationOpts.PlacementTenancy = aws.String(v.(string)) } if v := d.Get("associate_public_ip_address"); v != nil { createLaunchConfigurationOpts.AssociatePublicIPAddress = aws.Boolean(v.(bool)) } else { createLaunchConfigurationOpts.AssociatePublicIPAddress = aws.Boolean(false) } if v, ok := d.GetOk("key_name"); ok { createLaunchConfigurationOpts.KeyName = aws.String(v.(string)) } if v, ok := d.GetOk("spot_price"); ok { createLaunchConfigurationOpts.SpotPrice = aws.String(v.(string)) } if v, ok := d.GetOk("security_groups"); ok { createLaunchConfigurationOpts.SecurityGroups = expandStringList( v.(*schema.Set).List(), ) } var blockDevices []autoscaling.BlockDeviceMapping if v, ok := d.GetOk("ebs_block_device"); ok { vL := v.(*schema.Set).List() for _, v := range vL { bd := v.(map[string]interface{}) ebs := &autoscaling.EBS{ DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)), } if v, ok := bd["snapshot_id"].(string); ok && v != "" { ebs.SnapshotID = aws.String(v) } if v, ok := bd["volume_size"].(int); ok && v != 0 { ebs.VolumeSize = aws.Integer(v) } if v, ok := bd["volume_type"].(string); ok && v != "" { ebs.VolumeType = aws.String(v) } if v, ok := bd["iops"].(int); ok && v > 0 { ebs.IOPS = aws.Integer(v) } blockDevices = append(blockDevices, autoscaling.BlockDeviceMapping{ DeviceName: aws.String(bd["device_name"].(string)), EBS: ebs, }) } } if v, ok := d.GetOk("ephemeral_block_device"); ok { vL := v.(*schema.Set).List() for _, v := range vL { bd := v.(map[string]interface{}) blockDevices = append(blockDevices, autoscaling.BlockDeviceMapping{ DeviceName: aws.String(bd["device_name"].(string)), VirtualName: aws.String(bd["virtual_name"].(string)), }) } } if v, ok := d.GetOk("root_block_device"); ok { vL := v.(*schema.Set).List() if len(vL) > 1 { return fmt.Errorf("Cannot specify more than one root_block_device.") } for _, v := range vL { bd := v.(map[string]interface{}) ebs := &autoscaling.EBS{ DeleteOnTermination: aws.Boolean(bd["delete_on_termination"].(bool)), } if v, ok := bd["volume_size"].(int); ok && v != 0 { ebs.VolumeSize = aws.Integer(v) } if v, ok := bd["volume_type"].(string); ok && v != "" { ebs.VolumeType = aws.String(v) } if v, ok := bd["iops"].(int); ok && v > 0 { ebs.IOPS = aws.Integer(v) } if dn, err := fetchRootDeviceName(d.Get("image_id").(string), ec2conn); err == nil { blockDevices = append(blockDevices, autoscaling.BlockDeviceMapping{ DeviceName: dn, EBS: ebs, }) } else { return err } } } if len(blockDevices) > 0 { createLaunchConfigurationOpts.BlockDeviceMappings = blockDevices } if v, ok := d.GetOk("name"); ok { createLaunchConfigurationOpts.LaunchConfigurationName = aws.String(v.(string)) d.SetId(d.Get("name").(string)) } else { hash := sha1.Sum([]byte(fmt.Sprintf("%#v", createLaunchConfigurationOpts))) config_name := fmt.Sprintf("terraform-%s", base64.URLEncoding.EncodeToString(hash[:])) log.Printf("[DEBUG] Computed Launch config name: %s", config_name) createLaunchConfigurationOpts.LaunchConfigurationName = aws.String(config_name) d.SetId(config_name) } log.Printf("[DEBUG] autoscaling create launch configuration: %#v", createLaunchConfigurationOpts) err := autoscalingconn.CreateLaunchConfiguration(&createLaunchConfigurationOpts) if err != nil { return fmt.Errorf("Error creating launch configuration: %s", err) } log.Printf("[INFO] launch configuration ID: %s", d.Id()) // We put a Retry here since sometimes eventual consistency bites // us and we need to retry a few times to get the LC to load properly return resource.Retry(30*time.Second, func() error { return resourceAwsLaunchConfigurationRead(d, meta) }) }
func resourceAwsDbInstanceCreate(d *schema.ResourceData, meta interface{}) error { conn := meta.(*AWSClient).rdsconn tags := tagsFromMapRDS(d.Get("tags").(map[string]interface{})) opts := rds.CreateDBInstanceMessage{ AllocatedStorage: aws.Integer(d.Get("allocated_storage").(int)), DBInstanceClass: aws.String(d.Get("instance_class").(string)), DBInstanceIdentifier: aws.String(d.Get("identifier").(string)), DBName: aws.String(d.Get("name").(string)), MasterUsername: aws.String(d.Get("username").(string)), MasterUserPassword: aws.String(d.Get("password").(string)), Engine: aws.String(d.Get("engine").(string)), EngineVersion: aws.String(d.Get("engine_version").(string)), StorageEncrypted: aws.Boolean(d.Get("storage_encrypted").(bool)), Tags: tags, } if attr, ok := d.GetOk("storage_type"); ok { opts.StorageType = aws.String(attr.(string)) } attr := d.Get("backup_retention_period") opts.BackupRetentionPeriod = aws.Integer(attr.(int)) if attr, ok := d.GetOk("iops"); ok { opts.IOPS = aws.Integer(attr.(int)) } if attr, ok := d.GetOk("port"); ok { opts.Port = aws.Integer(attr.(int)) } if attr, ok := d.GetOk("multi_az"); ok { opts.MultiAZ = aws.Boolean(attr.(bool)) } if attr, ok := d.GetOk("availability_zone"); ok { opts.AvailabilityZone = aws.String(attr.(string)) } if attr, ok := d.GetOk("maintenance_window"); ok { opts.PreferredMaintenanceWindow = aws.String(attr.(string)) } if attr, ok := d.GetOk("backup_window"); ok { opts.PreferredBackupWindow = aws.String(attr.(string)) } if attr, ok := d.GetOk("publicly_accessible"); ok { opts.PubliclyAccessible = aws.Boolean(attr.(bool)) } if attr, ok := d.GetOk("db_subnet_group_name"); ok { opts.DBSubnetGroupName = aws.String(attr.(string)) } if attr, ok := d.GetOk("parameter_group_name"); ok { opts.DBParameterGroupName = aws.String(attr.(string)) } if attr := d.Get("vpc_security_group_ids").(*schema.Set); attr.Len() > 0 { var s []string for _, v := range attr.List() { s = append(s, v.(string)) } opts.VPCSecurityGroupIDs = s } if attr := d.Get("security_group_names").(*schema.Set); attr.Len() > 0 { var s []string for _, v := range attr.List() { s = append(s, v.(string)) } opts.DBSecurityGroups = s } log.Printf("[DEBUG] DB Instance create configuration: %#v", opts) _, err := conn.CreateDBInstance(&opts) if err != nil { return fmt.Errorf("Error creating DB Instance: %s", err) } d.SetId(d.Get("identifier").(string)) log.Printf("[INFO] DB Instance ID: %s", d.Id()) log.Println( "[INFO] Waiting for DB Instance to be available") stateConf := &resource.StateChangeConf{ Pending: []string{"creating", "backing-up", "modifying"}, Target: "available", Refresh: resourceAwsDbInstanceStateRefreshFunc(d, meta), Timeout: 40 * time.Minute, MinTimeout: 10 * time.Second, Delay: 30 * time.Second, // Wait 30 secs before starting } // Wait, catching any errors _, err = stateConf.WaitForState() if err != nil { return err } return resourceAwsDbInstanceRead(d, meta) }