Skip to content

Commit

Permalink
Merge pull request #1632 from hashicorp/f-generate-sg-names
Browse files Browse the repository at this point in the history
unique identifier helper for resources / generate AWS security group names
  • Loading branch information
phinze committed Apr 23, 2015
2 parents a4cfa2e + 0798566 commit 69ef012
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 13 deletions.
13 changes: 5 additions & 8 deletions builtin/providers/aws/resource_aws_launch_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,16 +364,13 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface
createLaunchConfigurationOpts.BlockDeviceMappings = blockDevices
}

var id string
var lcName string
if v, ok := d.GetOk("name"); ok {
id = v.(string)
lcName = v.(string)
} else {
hash := sha1.Sum([]byte(fmt.Sprintf("%#v", createLaunchConfigurationOpts)))
configName := fmt.Sprintf("terraform-%s", base64.URLEncoding.EncodeToString(hash[:]))
log.Printf("[DEBUG] Computed Launch config name: %s", configName)
id = configName
lcName = resource.UniqueId()
}
createLaunchConfigurationOpts.LaunchConfigurationName = aws.String(id)
createLaunchConfigurationOpts.LaunchConfigurationName = aws.String(lcName)

log.Printf(
"[DEBUG] autoscaling create launch configuration: %#v", createLaunchConfigurationOpts)
Expand All @@ -382,7 +379,7 @@ func resourceAwsLaunchConfigurationCreate(d *schema.ResourceData, meta interface
return fmt.Errorf("Error creating launch configuration: %s", err)
}

d.SetId(id)
d.SetId(lcName)
log.Printf("[INFO] launch configuration ID: %s", d.Id())

// We put a Retry here since sometimes eventual consistency bites
Expand Down
18 changes: 13 additions & 5 deletions builtin/providers/aws/resource_aws_security_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ func resourceAwsSecurityGroup() *schema.Resource {
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Optional: true,
Computed: true,
ForceNew: true,
},

"description": &schema.Schema{
Type: schema.TypeString,
Required: true,
Optional: true,
Default: "Managed by Terraform",
},

"vpc_id": &schema.Schema{
Expand Down Expand Up @@ -144,9 +146,7 @@ func resourceAwsSecurityGroup() *schema.Resource {
func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).ec2conn

securityGroupOpts := &ec2.CreateSecurityGroupInput{
GroupName: aws.String(d.Get("name").(string)),
}
securityGroupOpts := &ec2.CreateSecurityGroupInput{}

if v := d.Get("vpc_id"); v != nil {
securityGroupOpts.VPCID = aws.String(v.(string))
Expand All @@ -156,6 +156,14 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er
securityGroupOpts.Description = aws.String(v.(string))
}

var groupName string
if v, ok := d.GetOk("name"); ok {
groupName = v.(string)
} else {
groupName = resource.UniqueId()
}
securityGroupOpts.GroupName = aws.String(groupName)

log.Printf(
"[DEBUG] Security Group create configuration: %#v", securityGroupOpts)
createResp, err := conn.CreateSecurityGroup(securityGroupOpts)
Expand Down
45 changes: 45 additions & 0 deletions builtin/providers/aws/resource_aws_security_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aws
import (
"fmt"
"reflect"
"strings"
"testing"

"github.com/awslabs/aws-sdk-go/aws"
Expand Down Expand Up @@ -184,6 +185,35 @@ func TestAccAWSSecurityGroup_Change(t *testing.T) {
})
}

func TestAccAWSSecurityGroup_generatedName(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: testAccAWSSecurityGroupConfig_generatedName,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupExists("aws_security_group.web", &group),
resource.TestCheckResourceAttr(
"aws_security_group.web", "description", "Managed by Terraform"),
func(s *terraform.State) error {
if group.GroupName == nil {
return fmt.Errorf("bad: No SG name")
}
if !strings.HasPrefix(*group.GroupName, "terraform-") {
return fmt.Errorf("No terraform- prefix: %s", *group.GroupName)
}
return nil
},
),
},
},
})
}

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

Expand Down Expand Up @@ -518,3 +548,18 @@ resource "aws_security_group" "foo" {
}
}
`

const testAccAWSSecurityGroupConfig_generatedName = `
resource "aws_security_group" "web" {
ingress {
protocol = "tcp"
from_port = 80
to_port = 8000
cidr_blocks = ["10.0.0.0/8"]
}
tags {
Name = "tf-acc-test"
}
}
`
41 changes: 41 additions & 0 deletions helper/resource/id.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package resource

import (
"crypto/rand"
"encoding/base32"
"fmt"
"strings"
)

const UniqueIdPrefix = `terraform-`

// Helper for a resource to generate a unique identifier
//
// This uses a simple RFC 4122 v4 UUID with some basic cosmetic filters
// applied (base32, remove padding, downcase) to make visually distinguishing
// identifiers easier.
func UniqueId() string {
return fmt.Sprintf("%s%s", UniqueIdPrefix,
strings.ToLower(
strings.Replace(
base32.StdEncoding.EncodeToString(uuidV4()),
"=", "", -1)))
}

func uuidV4() []byte {
var uuid [16]byte

// Set all the other bits to randomly (or pseudo-randomly) chosen
// values.
rand.Read(uuid[:])

// Set the two most significant bits (bits 6 and 7) of the
// clock_seq_hi_and_reserved to zero and one, respectively.
uuid[8] = (uuid[8] | 0x80) & 0x8f

// Set the four most significant bits (bits 12 through 15) of the
// time_hi_and_version field to the 4-bit version number from Section 4.1.3.
uuid[6] = (uuid[6] | 0x40) & 0x4f

return uuid[:]
}
25 changes: 25 additions & 0 deletions helper/resource/id_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package resource

import (
"strings"
"testing"
)

func TestUniqueId(t *testing.T) {
iterations := 10000
ids := make(map[string]struct{})
var id string
for i := 0; i < iterations; i++ {
id = UniqueId()

if _, ok := ids[id]; ok {
t.Fatalf("Got duplicated id! %s", id)
}

if !strings.HasPrefix(id, "terraform-") {
t.Fatalf("Unique ID didn't have terraform- prefix! %s", id)
}

ids[id] = struct{}{}
}
}

0 comments on commit 69ef012

Please sign in to comment.