provider/random: random_id resource

This resource generates a cryptographically-strong set of bytes and
provides them as base64, hexadecimal and decimal string representations.
It is intended to be used for generating unique ids for resources
elsewhere in the configuration, and thus the "keepers" would be set to
any ForceNew attributes of the target resources, so that a new id is
generated each time a new resource is generated.
This commit is contained in:
Martin Atkins 2016-05-14 14:00:58 -07:00
parent 3e34ddbf38
commit b1de477691
3 changed files with 135 additions and 1 deletions

View File

@ -11,7 +11,7 @@ func Provider() terraform.ResourceProvider {
Schema: map[string]*schema.Schema{}, Schema: map[string]*schema.Schema{},
ResourcesMap: map[string]*schema.Resource{ ResourcesMap: map[string]*schema.Resource{
//"random_id": resourceId(), "random_id": resourceId(),
//"random_shuffle": resourceShuffle(), //"random_shuffle": resourceShuffle(),
}, },
} }

View File

@ -0,0 +1,76 @@
package random
import (
"crypto/rand"
"encoding/base64"
"encoding/hex"
"fmt"
"math/big"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceId() *schema.Resource {
return &schema.Resource{
Create: CreateID,
Read: stubRead,
Delete: stubDelete,
Schema: map[string]*schema.Schema{
"keepers": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},
"byte_length": &schema.Schema{
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},
"b64": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"hex": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"dec": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
func CreateID(d *schema.ResourceData, meta interface{}) error {
byteLength := d.Get("byte_length").(int)
bytes := make([]byte, byteLength)
n, err := rand.Reader.Read(bytes)
if n != byteLength {
return fmt.Errorf("generated insufficient random bytes")
}
if err != nil {
return fmt.Errorf("error generating random bytes: %s", err)
}
b64Str := base64.RawURLEncoding.EncodeToString(bytes)
hexStr := hex.EncodeToString(bytes)
int := big.Int{}
int.SetBytes(bytes)
decStr := int.String()
d.SetId(b64Str)
d.Set("b64", b64Str)
d.Set("hex", hexStr)
d.Set("dec", decStr)
return nil
}

View File

@ -0,0 +1,58 @@
package random
import (
"fmt"
"testing"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccResourceID(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccResourceIDConfig,
Check: resource.ComposeTestCheckFunc(
testAccResourceIDCheck("random_id.foo"),
),
},
},
})
}
func testAccResourceIDCheck(id string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[id]
if !ok {
return fmt.Errorf("Not found: %s", id)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}
b64Str := rs.Primary.Attributes["b64"]
hexStr := rs.Primary.Attributes["hex"]
decStr := rs.Primary.Attributes["dec"]
if got, want := len(b64Str), 6; got != want {
return fmt.Errorf("base64 string length is %d; want %d", got, want)
}
if got, want := len(hexStr), 8; got != want {
return fmt.Errorf("hex string length is %d; want %d", got, want)
}
if len(decStr) < 1 {
return fmt.Errorf("decimal string is empty; want at least one digit")
}
return nil
}
}
const testAccResourceIDConfig = `
resource "random_id" "foo" {
byte_length = 4
}
`