diff --git a/builtin/providers/aws/resource_aws_security_group.go b/builtin/providers/aws/resource_aws_security_group.go index 5bfdf3612..b0cabec2b 100644 --- a/builtin/providers/aws/resource_aws_security_group.go +++ b/builtin/providers/aws/resource_aws_security_group.go @@ -28,6 +28,7 @@ func resourceAwsSecurityGroup() *schema.Resource { Optional: true, Computed: true, ForceNew: true, + ConflictsWith: []string{"name_prefix"}, ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { value := v.(string) if len(value) > 255 { @@ -38,6 +39,20 @@ func resourceAwsSecurityGroup() *schema.Resource { }, }, + "name_prefix": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { + value := v.(string) + if len(value) > 100 { + errors = append(errors, fmt.Errorf( + "%q cannot be longer than 100 characters, name is limited to 255", k)) + } + return + }, + }, + "description": &schema.Schema{ Type: schema.TypeString, Optional: true, @@ -178,6 +193,8 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er var groupName string if v, ok := d.GetOk("name"); ok { groupName = v.(string) + } else if v, ok := d.GetOk("name_prefix"); ok { + groupName = resource.PrefixedUniqueId(v.(string)) } else { groupName = resource.UniqueId() } diff --git a/builtin/providers/aws/resource_aws_security_group_test.go b/builtin/providers/aws/resource_aws_security_group_test.go index e6b520d95..d5142c68e 100644 --- a/builtin/providers/aws/resource_aws_security_group_test.go +++ b/builtin/providers/aws/resource_aws_security_group_test.go @@ -46,6 +46,26 @@ func TestAccAWSSecurityGroup_basic(t *testing.T) { }) } +func TestAccAWSSecurityGroup_namePrefix( t *testing.T) { + var group ec2.SecurityGroup + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAWSSecurityGroupDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSSecurityGroupPrefixNameConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckAWSSecurityGroupExists("aws_security_group.baz", &group), + testAccCheckAWSSecurityGroupGeneratedNamePrefix( + "aws_security_group.baz", "baz-"), + ), + }, + }, + }) +} + func TestAccAWSSecurityGroup_self(t *testing.T) { var group ec2.SecurityGroup @@ -324,6 +344,24 @@ func testAccCheckAWSSecurityGroupDestroy(s *terraform.State) error { return nil } +func testAccCheckAWSSecurityGroupGeneratedNamePrefix( +resource, prefix string) resource.TestCheckFunc { + return func(s *terraform.State) error { + r, ok := s.RootModule().Resources[resource] + if !ok { + return fmt.Errorf("Resource not found") + } + name, ok := r.Primary.Attributes["name"] + if !ok { + return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes) + } + if !strings.HasPrefix(name, prefix) { + return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix) + } + return nil + } +} + func testAccCheckAWSSecurityGroupExists(n string, group *ec2.SecurityGroup) resource.TestCheckFunc { return func(s *terraform.State) error { rs, ok := s.RootModule().Resources[n] @@ -809,3 +847,14 @@ resource "aws_security_group" "web" { description = "Used in the terraform acceptance tests" } ` + +const testAccAWSSecurityGroupPrefixNameConfig = ` +provider "aws" { + region = "us-east-1" +} + +resource "aws_security_group" "baz" { + name_prefix = "baz-" + description = "Used in the terraform acceptance tests" +} +` diff --git a/website/source/docs/providers/aws/r/security_group.html.markdown b/website/source/docs/providers/aws/r/security_group.html.markdown index b045b01f8..860d6a4b9 100644 --- a/website/source/docs/providers/aws/r/security_group.html.markdown +++ b/website/source/docs/providers/aws/r/security_group.html.markdown @@ -68,6 +68,8 @@ The following arguments are supported: * `name` - (Optional) The name of the security group. If omitted, Terraform will assign a random, unique name +* `name_prefix` - (Optional) Creates a unique name beginning with the specified + prefix. Conflicts with `name`. * `description` - (Optional) The security group description. Defaults to "Managed by Terraform". Cannot be "". * `ingress` - (Optional) Can be specified multiple times for each ingress rule. Each ingress block supports fields documented below.