diff --git a/builtin/providers/aws/resource_aws_instance.go b/builtin/providers/aws/resource_aws_instance.go index 00124700579f..85a35e41aa6f 100644 --- a/builtin/providers/aws/resource_aws_instance.go +++ b/builtin/providers/aws/resource_aws_instance.go @@ -105,6 +105,16 @@ func resourceAwsInstance() *schema.Resource { }, }, + "vpc_security_group_ids": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + Set: func(v interface{}) int { + return hashcode.String(v.(string)) + }, + }, + "public_dns": &schema.Schema{ Type: schema.TypeString, Computed: true, @@ -340,6 +350,9 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { // 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 + if hasSubnet { + log.Printf("[WARN] Deprecated. Attempting to use 'security_groups' within a VPC instance. Use 'vpc_security_group_ids' instead.") + } for _, v := range v.(*schema.Set).List() { str := v.(string) groups = append(groups, str) @@ -364,8 +377,10 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { ni.PrivateIPAddress = aws.String(v.(string)) } - if len(groups) > 0 { - ni.Groups = groups + if v := d.Get("vpc_security_group_ids"); v != nil { + for _, v := range v.(*schema.Set).List() { + ni.Groups = append(ni.Groups, v.(string)) + } } runOpts.NetworkInterfaces = []ec2.InstanceNetworkInterfaceSpecification{ni} @@ -383,6 +398,12 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error { } else { runOpts.SecurityGroups = groups } + + if v := d.Get("vpc_security_group_ids"); v != nil { + for _, v := range v.(*schema.Set).List() { + runOpts.SecurityGroupIDs = append(runOpts.SecurityGroupIDs, v.(string)) + } + } } if v, ok := d.GetOk("key_name"); ok { @@ -596,15 +617,24 @@ func resourceAwsInstanceRead(d *schema.ResourceData, meta interface{}) error { } // Build up the security groups - sgs := make([]string, len(instance.SecurityGroups)) - for i, sg := range instance.SecurityGroups { - if useID { - sgs[i] = *sg.GroupID - } else { - sgs[i] = *sg.GroupName + sgs := make([]string, 0, len(instance.SecurityGroups)) + if useID { + for _, sg := range instance.SecurityGroups { + sgs = append(sgs, *sg.GroupID) + } + log.Printf("[DEBUG] Setting Security Group IDs: %#v", sgs) + if err := d.Set("vpc_security_group_ids", sgs); err != nil { + return err + } + } else { + for _, sg := range instance.SecurityGroups { + sgs = append(sgs, *sg.GroupName) + } + log.Printf("[DEBUG] Setting Security Group Names: %#v", sgs) + if err := d.Set("security_groups", sgs); err != nil { + return err } } - d.Set("security_groups", sgs) if err := readBlockDevices(d, instance, ec2conn); err != nil { return err diff --git a/builtin/providers/aws/resource_aws_instance_test.go b/builtin/providers/aws/resource_aws_instance_test.go index 2dd863c10df4..d03bb7159dff 100644 --- a/builtin/providers/aws/resource_aws_instance_test.go +++ b/builtin/providers/aws/resource_aws_instance_test.go @@ -255,6 +255,25 @@ func TestAccAWSInstance_NetworkInstanceSecurityGroups(t *testing.T) { }) } +func TestAccAWSInstance_NetworkInstanceVPCSecurityGroupIDs(t *testing.T) { + var v ec2.Instance + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckInstanceDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccInstanceNetworkInstanceVPCSecurityGroupIDs, + Check: resource.ComposeTestCheckFunc( + testAccCheckInstanceExists( + "aws_instance.foo_instance", &v), + ), + }, + }, + }) +} + func TestAccAWSInstance_tags(t *testing.T) { var v ec2.Instance @@ -645,3 +664,48 @@ resource "aws_eip" "foo_eip" { depends_on = ["aws_internet_gateway.gw"] } ` + +const testAccInstanceNetworkInstanceVPCSecurityGroupIDs = ` +resource "aws_internet_gateway" "gw" { + vpc_id = "${aws_vpc.foo.id}" +} + +resource "aws_vpc" "foo" { + cidr_block = "10.1.0.0/16" + tags { + Name = "tf-network-test" + } +} + +resource "aws_security_group" "tf_test_foo" { + name = "tf_test_foo" + description = "foo" + vpc_id="${aws_vpc.foo.id}" + + ingress { + protocol = "icmp" + from_port = -1 + to_port = -1 + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_subnet" "foo" { + cidr_block = "10.1.1.0/24" + vpc_id = "${aws_vpc.foo.id}" +} + +resource "aws_instance" "foo_instance" { + ami = "ami-21f78e11" + instance_type = "t1.micro" + vpc_security_group_ids = ["${aws_security_group.tf_test_foo.id}"] + subnet_id = "${aws_subnet.foo.id}" + depends_on = ["aws_internet_gateway.gw"] +} + +resource "aws_eip" "foo_eip" { + instance = "${aws_instance.foo_instance.id}" + vpc = true + depends_on = ["aws_internet_gateway.gw"] +} +` diff --git a/website/source/docs/providers/aws/r/instance.html.markdown b/website/source/docs/providers/aws/r/instance.html.markdown index 6720424190fc..7a0f441b02ba 100644 --- a/website/source/docs/providers/aws/r/instance.html.markdown +++ b/website/source/docs/providers/aws/r/instance.html.markdown @@ -35,9 +35,9 @@ The following arguments are supported: EBS-optimized. * `instance_type` - (Required) The type of instance to start * `key_name` - (Optional) The key name to use for the instance. -* `security_groups` - (Optional) A list of security group IDs or names to associate with. - If you are within a non-default VPC, you'll need to use the security group ID. Otherwise, - for EC2 and the default VPC, use the security group name. +* `security_groups` - (Optional) A list of security group names to associate with. + If you are within a non-default VPC, you'll need to use `vpc_security_group_ids` instead. +* `vpc_security_group_ids` - (Optional) A list of security group IDs to associate with. * `subnet_id` - (Optional) The VPC Subnet ID to launch in. * `associate_public_ip_address` - (Optional) Associate a public ip address with an instance in a VPC. * `private_ip` - (Optional) Private IP address to associate with the @@ -126,4 +126,5 @@ The following attributes are exported: * `public_dns` - The public DNS name of the instance * `public_ip` - The public IP address. * `security_groups` - The associated security groups. +* `vpc_security_group_ids` - The associated security groups in non-default VPC * `subnet_id` - The VPC subnet ID.