Merge pull request #6672 from apparentlymart/random-provider
Logical Resources for Random Values
This commit is contained in:
commit
5a0f6565d3
|
@ -0,0 +1,15 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/builtin/providers/random"
|
||||||
|
"github.com/hashicorp/terraform/plugin"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
plugin.Serve(&plugin.ServeOpts{
|
||||||
|
ProviderFunc: func() terraform.ResourceProvider {
|
||||||
|
return random.Provider()
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
package main
|
|
@ -0,0 +1,31 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider returns a terraform.ResourceProvider.
|
||||||
|
func Provider() terraform.ResourceProvider {
|
||||||
|
return &schema.Provider{
|
||||||
|
Schema: map[string]*schema.Schema{},
|
||||||
|
|
||||||
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
"random_id": resourceId(),
|
||||||
|
"random_shuffle": resourceShuffle(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stubRead is a do-nothing Read implementation used for our resources,
|
||||||
|
// which don't actually need to do anything on read.
|
||||||
|
func stubRead(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// stubDelete is a do-nothing Dete implementation used for our resources,
|
||||||
|
// which don't actually need to do anything unusual on delete.
|
||||||
|
func stubDelete(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
var testAccProviders map[string]terraform.ResourceProvider
|
||||||
|
var testAccProvider *schema.Provider
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
testAccProvider = Provider().(*schema.Provider)
|
||||||
|
testAccProviders = map[string]terraform.ResourceProvider{
|
||||||
|
"random": testAccProvider,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider(t *testing.T) {
|
||||||
|
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestProvider_impl(t *testing.T) {
|
||||||
|
var _ terraform.ResourceProvider = Provider()
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccPreCheck(t *testing.T) {
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,82 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceShuffle() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: CreateShuffle,
|
||||||
|
Read: stubRead,
|
||||||
|
Delete: stubDelete,
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"keepers": &schema.Schema{
|
||||||
|
Type: schema.TypeMap,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"seed": &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
"input": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Required: true,
|
||||||
|
ForceNew: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"result": &schema.Schema{
|
||||||
|
Type: schema.TypeList,
|
||||||
|
Computed: true,
|
||||||
|
Elem: &schema.Schema{
|
||||||
|
Type: schema.TypeString,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
"result_count": &schema.Schema{
|
||||||
|
Type: schema.TypeInt,
|
||||||
|
Optional: true,
|
||||||
|
ForceNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateShuffle(d *schema.ResourceData, meta interface{}) error {
|
||||||
|
input := d.Get("input").([]interface{})
|
||||||
|
seed := d.Get("seed").(string)
|
||||||
|
|
||||||
|
resultCount := d.Get("result_count").(int)
|
||||||
|
if resultCount == 0 {
|
||||||
|
resultCount = len(input)
|
||||||
|
}
|
||||||
|
result := make([]interface{}, 0, resultCount)
|
||||||
|
|
||||||
|
rand := NewRand(seed)
|
||||||
|
|
||||||
|
// Keep producing permutations until we fill our result
|
||||||
|
Batches:
|
||||||
|
for {
|
||||||
|
perm := rand.Perm(len(input))
|
||||||
|
|
||||||
|
for _, i := range perm {
|
||||||
|
result = append(result, input[i])
|
||||||
|
|
||||||
|
if len(result) >= resultCount {
|
||||||
|
break Batches
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId("-")
|
||||||
|
d.Set("result", result)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccResourceShuffle(t *testing.T) {
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccResourceShuffleConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
// These results are current as of Go 1.6. The Go
|
||||||
|
// "rand" package does not guarantee that the random
|
||||||
|
// number generator will generate the same results
|
||||||
|
// forever, but the maintainers endeavor not to change
|
||||||
|
// it gratuitously.
|
||||||
|
// These tests allow us to detect such changes and
|
||||||
|
// document them when they arise, but the docs for this
|
||||||
|
// resource specifically warn that results are not
|
||||||
|
// guaranteed consistent across Terraform releases.
|
||||||
|
testAccResourceShuffleCheck(
|
||||||
|
"random_shuffle.default_length",
|
||||||
|
[]string{"a", "c", "b", "e", "d"},
|
||||||
|
),
|
||||||
|
testAccResourceShuffleCheck(
|
||||||
|
"random_shuffle.shorter_length",
|
||||||
|
[]string{"a", "c", "b"},
|
||||||
|
),
|
||||||
|
testAccResourceShuffleCheck(
|
||||||
|
"random_shuffle.longer_length",
|
||||||
|
[]string{"a", "c", "b", "e", "d", "a", "e", "d", "c", "b", "a", "b"},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccResourceShuffleCheck(id string, wants []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")
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs := rs.Primary.Attributes
|
||||||
|
|
||||||
|
gotLen := attrs["result.#"]
|
||||||
|
wantLen := strconv.Itoa(len(wants))
|
||||||
|
if gotLen != wantLen {
|
||||||
|
return fmt.Errorf("got %s result items; want %s", gotLen, wantLen)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, want := range wants {
|
||||||
|
key := fmt.Sprintf("result.%d", i)
|
||||||
|
if got := attrs[key]; got != want {
|
||||||
|
return fmt.Errorf("index %d is %q; want %q", i, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const testAccResourceShuffleConfig = `
|
||||||
|
resource "random_shuffle" "default_length" {
|
||||||
|
input = ["a", "b", "c", "d", "e"]
|
||||||
|
seed = "-"
|
||||||
|
}
|
||||||
|
resource "random_shuffle" "shorter_length" {
|
||||||
|
input = ["a", "b", "c", "d", "e"]
|
||||||
|
seed = "-"
|
||||||
|
result_count = 3
|
||||||
|
}
|
||||||
|
resource "random_shuffle" "longer_length" {
|
||||||
|
input = ["a", "b", "c", "d", "e"]
|
||||||
|
seed = "-"
|
||||||
|
result_count = 12
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,24 @@
|
||||||
|
package random
|
||||||
|
|
||||||
|
import (
|
||||||
|
"hash/crc64"
|
||||||
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewRand returns a seeded random number generator, using a seed derived
|
||||||
|
// from the provided string.
|
||||||
|
//
|
||||||
|
// If the seed string is empty, the current time is used as a seed.
|
||||||
|
func NewRand(seed string) *rand.Rand {
|
||||||
|
var seedInt int64
|
||||||
|
if seed != "" {
|
||||||
|
crcTable := crc64.MakeTable(crc64.ISO)
|
||||||
|
seedInt = int64(crc64.Checksum([]byte(seed), crcTable))
|
||||||
|
} else {
|
||||||
|
seedInt = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
randSource := rand.NewSource(seedInt)
|
||||||
|
return rand.New(randSource)
|
||||||
|
}
|
|
@ -36,6 +36,7 @@ import (
|
||||||
packetprovider "github.com/hashicorp/terraform/builtin/providers/packet"
|
packetprovider "github.com/hashicorp/terraform/builtin/providers/packet"
|
||||||
postgresqlprovider "github.com/hashicorp/terraform/builtin/providers/postgresql"
|
postgresqlprovider "github.com/hashicorp/terraform/builtin/providers/postgresql"
|
||||||
powerdnsprovider "github.com/hashicorp/terraform/builtin/providers/powerdns"
|
powerdnsprovider "github.com/hashicorp/terraform/builtin/providers/powerdns"
|
||||||
|
randomprovider "github.com/hashicorp/terraform/builtin/providers/random"
|
||||||
rundeckprovider "github.com/hashicorp/terraform/builtin/providers/rundeck"
|
rundeckprovider "github.com/hashicorp/terraform/builtin/providers/rundeck"
|
||||||
softlayerprovider "github.com/hashicorp/terraform/builtin/providers/softlayer"
|
softlayerprovider "github.com/hashicorp/terraform/builtin/providers/softlayer"
|
||||||
statuscakeprovider "github.com/hashicorp/terraform/builtin/providers/statuscake"
|
statuscakeprovider "github.com/hashicorp/terraform/builtin/providers/statuscake"
|
||||||
|
@ -87,6 +88,7 @@ var InternalProviders = map[string]plugin.ProviderFunc{
|
||||||
"packet": packetprovider.Provider,
|
"packet": packetprovider.Provider,
|
||||||
"postgresql": postgresqlprovider.Provider,
|
"postgresql": postgresqlprovider.Provider,
|
||||||
"powerdns": powerdnsprovider.Provider,
|
"powerdns": powerdnsprovider.Provider,
|
||||||
|
"random": randomprovider.Provider,
|
||||||
"rundeck": rundeckprovider.Provider,
|
"rundeck": rundeckprovider.Provider,
|
||||||
"softlayer": softlayerprovider.Provider,
|
"softlayer": softlayerprovider.Provider,
|
||||||
"statuscake": statuscakeprovider.Provider,
|
"statuscake": statuscakeprovider.Provider,
|
||||||
|
|
|
@ -36,6 +36,7 @@ body.layout-openstack,
|
||||||
body.layout-packet,
|
body.layout-packet,
|
||||||
body.layout-postgresql,
|
body.layout-postgresql,
|
||||||
body.layout-powerdns,
|
body.layout-powerdns,
|
||||||
|
body.layout-random,
|
||||||
body.layout-rundeck,
|
body.layout-rundeck,
|
||||||
body.layout-statuscake,
|
body.layout-statuscake,
|
||||||
body.layout-softlayer,
|
body.layout-softlayer,
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
---
|
||||||
|
layout: "random"
|
||||||
|
page_title: "Provider: Random"
|
||||||
|
sidebar_current: "docs-random-index"
|
||||||
|
description: |-
|
||||||
|
The Random provider is used to generate randomness.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Random Provider
|
||||||
|
|
||||||
|
The "random" provider allows the use of randomness within Terraform
|
||||||
|
configurations. This is a *logical provider*, which means that it works
|
||||||
|
entirely within Terraform's logic, and doesn't interact with any other
|
||||||
|
services.
|
||||||
|
|
||||||
|
Unconstrained randomness within a Terraform configuration would not be very
|
||||||
|
useful, since Terraform's goal is to converge on a fixed configuration by
|
||||||
|
applying a diff. Because of this, the "random" provider provides an idea of
|
||||||
|
*managed randomness*: it provides resources that generate random values during
|
||||||
|
their creation and then hold those values steady until the inputs are changed.
|
||||||
|
|
||||||
|
Even with these resources, it is advisable to keep the use of randomness within
|
||||||
|
Terraform configuration to a minimum, and retain it for special cases only;
|
||||||
|
Terraform works best when the configuration is well-defined, since its behavior
|
||||||
|
can then be more readily predicted.
|
||||||
|
|
||||||
|
Unless otherwise stated within the documentation of a specific resource, this
|
||||||
|
provider's results are **not** sufficiently random for cryptographic use.
|
||||||
|
|
||||||
|
For more information on the specific resources available, see the links in the
|
||||||
|
navigation bar. Read on for information on the general patterns that apply
|
||||||
|
to this provider's resources.
|
||||||
|
|
||||||
|
## Resource "Keepers"
|
||||||
|
|
||||||
|
As noted above, the random resources generate randomness only when they are
|
||||||
|
created; the results produced are stored in the Terraform state and re-used
|
||||||
|
until the inputs change, prompting the resource to be recreated.
|
||||||
|
|
||||||
|
The resources all provide a map argument called `keepers` that can be populated
|
||||||
|
with arbitrary key/value pairs that should be selected such that they remain
|
||||||
|
the same until new random values are desired.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "random_id" "server" {
|
||||||
|
keepers = {
|
||||||
|
# Generate a new id each time we switch to a new AMI id
|
||||||
|
ami_id = "${var.ami_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_length = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
tags = {
|
||||||
|
Name = "web-server ${random_id.server.hex}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the AMI id "through" the random_id resource to ensure that
|
||||||
|
# both will change together.
|
||||||
|
ami = "${random_id.server.keepers.ami_id}"
|
||||||
|
|
||||||
|
# ... (other aws_instance arguments) ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Resource "keepers" are optional. The other arguments to each resource must
|
||||||
|
*also* remain constant in order to retain a random result.
|
||||||
|
|
||||||
|
To force a random result to be replaced, the `taint` command can be used to
|
||||||
|
produce a new result on the next run.
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
layout: "random"
|
||||||
|
page_title: "Random: random_id"
|
||||||
|
sidebar_current: "docs-random-resource-id"
|
||||||
|
description: |-
|
||||||
|
Generates a random identifier.
|
||||||
|
---
|
||||||
|
|
||||||
|
# random\_id
|
||||||
|
|
||||||
|
The resource `random_id` generates random numbers that are intended to be
|
||||||
|
used as unique identifiers for other resources.
|
||||||
|
|
||||||
|
Unlike other resources in the "random" provider, this resource *does* use a
|
||||||
|
cryptographic random number generator in order to minimize the chance of
|
||||||
|
collisions, making the results of this resource when a 32-byte identifier
|
||||||
|
is requested of equivalent uniqueness to a type-4 UUID.
|
||||||
|
|
||||||
|
This resource can be used in conjunction with resources that have,
|
||||||
|
the `create_before_destroy` lifecycle flag set, to avoid conflicts with
|
||||||
|
unique names during the brief period where both the old and new resources
|
||||||
|
exist concurrently.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
The following example shows how to generate a unique name for an AWS EC2
|
||||||
|
instance that changes each time a new AMI id is selected.
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "random_id" "server" {
|
||||||
|
keepers = {
|
||||||
|
# Generate a new id each time we switch to a new AMI id
|
||||||
|
ami_id = "${var.ami_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
byte_length = 8
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
tags = {
|
||||||
|
Name = "web-server ${random_id.server.hex}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the AMI id "through" the random_id resource to ensure that
|
||||||
|
# both will change together.
|
||||||
|
ami = "${random_id.server.keepers.ami_id}"
|
||||||
|
|
||||||
|
# ... (other aws_instance arguments) ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `byte_length` - (Required) The number of random bytes to produce. The
|
||||||
|
minimum value is 1, which produces eight bits of randomness.
|
||||||
|
|
||||||
|
* `keepers` - (Optional) Arbitrary map of values that, when changed, will
|
||||||
|
trigger a new id to be generated. See
|
||||||
|
[the main provider documentation](../index.html) for more information.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `b64` - The generated id presented in base64, using the URL-friendly character set: case-sensitive letters, digits and the characters `_` and `-`.
|
||||||
|
* `hex` - The generated id presented in padded hexadecimal digits. This result will always be twice as long as the requested byte length.
|
||||||
|
* `decimal` - The generated id presented in non-padded decimal digits.
|
|
@ -0,0 +1,59 @@
|
||||||
|
---
|
||||||
|
layout: "random"
|
||||||
|
page_title: "Random: random_shuffle"
|
||||||
|
sidebar_current: "docs-random-resource-shuffle"
|
||||||
|
description: |-
|
||||||
|
Produces a random permutation of a given list.
|
||||||
|
---
|
||||||
|
|
||||||
|
# random\_shuffle
|
||||||
|
|
||||||
|
The resource `random_shuffle` generates a random permutation of a list
|
||||||
|
of strings given as an argument.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```
|
||||||
|
resource "random_shuffle" "az" {
|
||||||
|
input = ["us-west-1a", "us-west-1c", "us-west-1d", "us-west-1e"]
|
||||||
|
result_count = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_elb" "example" {
|
||||||
|
# Place the ELB in any two of the given availability zones, selected
|
||||||
|
# at random.
|
||||||
|
availability_zones = ["${random_shuffle.az.result}"]
|
||||||
|
|
||||||
|
# ... and other aws_elb arguments ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Argument Reference
|
||||||
|
|
||||||
|
The following arguments are supported:
|
||||||
|
|
||||||
|
* `input` - (Required) The list of strings to shuffle.
|
||||||
|
|
||||||
|
* `result_count` - (Optional) The number of results to return. Defaults to
|
||||||
|
the number of items in the `input` list. If fewer items are requested,
|
||||||
|
some elements will be excluded from the result. If more items are requested,
|
||||||
|
items will be repeated in the result but not more frequently than the number
|
||||||
|
of items in the input list.
|
||||||
|
|
||||||
|
* `keepers` - (Optional) Arbitrary map of values that, when changed, will
|
||||||
|
trigger a new id to be generated. See
|
||||||
|
[the main provider documentation](../index.html) for more information.
|
||||||
|
|
||||||
|
* `seed` - (Optional) Arbitrary string with which to seed the random number
|
||||||
|
generator, in order to produce less-volatile permutations of the list.
|
||||||
|
**Important:** Even with an identical seed, it is not guaranteed that the
|
||||||
|
same permutation will be produced across different versions of Terraform.
|
||||||
|
This argument causes the result to be *less volatile*, but not fixed for
|
||||||
|
all time.
|
||||||
|
|
||||||
|
## Attributes Reference
|
||||||
|
|
||||||
|
The following attributes are exported:
|
||||||
|
|
||||||
|
* `result` - Random permutation of the list of strings given in `input`.
|
||||||
|
|
|
@ -278,6 +278,10 @@
|
||||||
<a href="/docs/providers/powerdns/index.html">PowerDNS</a>
|
<a href="/docs/providers/powerdns/index.html">PowerDNS</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-providers-random") %>>
|
||||||
|
<a href="/docs/providers/random/index.html">Random</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-providers-rundeck") %>>
|
<li<%= sidebar_current("docs-providers-rundeck") %>>
|
||||||
<a href="/docs/providers/rundeck/index.html">Rundeck</a>
|
<a href="/docs/providers/rundeck/index.html">Rundeck</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<% wrap_layout :inner do %>
|
||||||
|
<% content_for :sidebar do %>
|
||||||
|
<div class="docs-sidebar hidden-print affix-top" role="complementary">
|
||||||
|
<ul class="nav docs-sidenav">
|
||||||
|
<li<%= sidebar_current("docs-home") %>>
|
||||||
|
<a href="/docs/providers/index.html">« Documentation Home</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-random-index") %>>
|
||||||
|
<a href="/docs/providers/random/index.html">Random Provider</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current(/^docs-random-resource/) %>>
|
||||||
|
<a href="#">Resources</a>
|
||||||
|
<ul class="nav nav-visible">
|
||||||
|
<li<%= sidebar_current("docs-random-resource-id") %>>
|
||||||
|
<a href="/docs/providers/random/r/id.html">random_id</a>
|
||||||
|
</li>
|
||||||
|
<li<%= sidebar_current("docs-random-resource-shuffle") %>>
|
||||||
|
<a href="/docs/providers/random/r/shuffle.html">random_shuffle</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= yield %>
|
||||||
|
<% end %>
|
Loading…
Reference in New Issue