Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Random string generator #5

Merged
merged 2 commits into from
Sep 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions random/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func Provider() terraform.ResourceProvider {
"random_id": resourceId(),
"random_shuffle": resourceShuffle(),
"random_pet": resourcePet(),
"random_string": resourceString(),
},
}
}
2 changes: 1 addition & 1 deletion random/resource_id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type idLens struct {
}

func TestAccResourceID(t *testing.T) {
resource.Test(t, resource.TestCase{
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand Down
8 changes: 4 additions & 4 deletions random/resource_pet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
)

func TestAccResourcePet_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand All @@ -26,7 +26,7 @@ func TestAccResourcePet_basic(t *testing.T) {
}

func TestAccResourcePet_length(t *testing.T) {
resource.Test(t, resource.TestCase{
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand All @@ -41,7 +41,7 @@ func TestAccResourcePet_length(t *testing.T) {
}

func TestAccResourcePet_prefix(t *testing.T) {
resource.Test(t, resource.TestCase{
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand All @@ -58,7 +58,7 @@ func TestAccResourcePet_prefix(t *testing.T) {
}

func TestAccResourcePet_separator(t *testing.T) {
resource.Test(t, resource.TestCase{
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand Down
2 changes: 1 addition & 1 deletion random/resource_shuffle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

func TestAccResourceShuffle(t *testing.T) {
resource.Test(t, resource.TestCase{
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
Expand Down
116 changes: 116 additions & 0 deletions random/resource_string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package random

import (
"crypto/rand"

"github.com/hashicorp/terraform/helper/schema"
)

func resourceString() *schema.Resource {
return &schema.Resource{
Create: CreateString,
Read: ReadString,
Delete: schema.RemoveFromState,

Schema: map[string]*schema.Schema{
"keepers": {
Type: schema.TypeMap,
Optional: true,
ForceNew: true,
},

"length": {
Type: schema.TypeInt,
Required: true,
ForceNew: true,
},

"special": {
Type: schema.TypeBool,
Optional: true,
Default: true,
ForceNew: true,
},

"upper": {
Type: schema.TypeBool,
Optional: true,
Default: true,
ForceNew: true,
},

"lower": {
Type: schema.TypeBool,
Optional: true,
Default: true,
ForceNew: true,
},

"number": {
Type: schema.TypeBool,
Optional: true,
Default: true,
ForceNew: true,
},

"override_special": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
},

"result": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func CreateString(d *schema.ResourceData, meta interface{}) error {
const numChars = "0123456789"
const lowerChars = "abcdefghijklmnopqrstuvwxyz"
const upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var specialChars = "!@#$%&*()-_=+[]{}<>:?"

length := d.Get("length").(int)
upper := d.Get("upper").(bool)
lower := d.Get("lower").(bool)
number := d.Get("number").(bool)
special := d.Get("special").(bool)
overrideSpecial := d.Get("override_special").(string)

if overrideSpecial != "" {
specialChars = overrideSpecial
}

var chars = string("")
if upper {
chars += upperChars
}
if lower {
chars += lowerChars
}
if number {
chars += numChars
}
if special {
chars += specialChars
}

var bytes = make([]byte, length)
var l = byte(len(chars))

rand.Read(bytes)

for i, b := range bytes {
bytes[i] = chars[b%l]
}
d.Set("result", string(bytes))
d.SetId(string(bytes))
return nil
}

func ReadString(d *schema.ResourceData, meta interface{}) error {
return nil
}
97 changes: 97 additions & 0 deletions random/resource_string_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package random

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

type customLens struct {
customLen int
}

func TestAccResourceString(t *testing.T) {
resource.UnitTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccResourceStringConfig,
Check: resource.ComposeTestCheckFunc(
testAccResourceStringCheck("random_string.foo", &customLens{
customLen: 12,
}),
testAccResourceStringCheck("random_string.bar", &customLens{
customLen: 32,
}),
testAccResourceStringCheck("random_string.three", &customLens{
customLen: 4,
}),
patternMatch("random_string.three", "!!!!"),
),
},
},
})
}

func testAccResourceStringCheck(id string, want *customLens) 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")
}

customStr := rs.Primary.Attributes["result"]

if got, want := len(customStr), want.customLen; got != want {
return fmt.Errorf("custom string length is %d; want %d", got, want)
}

return nil
}
}

func patternMatch(id string, want 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")
}
customStr := rs.Primary.Attributes["result"]

if got, want := customStr, want; got != want {
return fmt.Errorf("custom string is %s; want %s", got, want)
}

return nil
}
}

const (
testAccResourceStringConfig = `
resource "random_string" "foo" {
length = 12
}

resource "random_string" "bar" {
length = 32
}

resource "random_string" "three" {
length = 4
override_special = "!"
lower = false
upper = false
number = false
}

`
)
65 changes: 65 additions & 0 deletions website/docs/r/string.html.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
layout: "random"
page_title: "Random: random_string"
sidebar_current: "docs-random-resource-string"
description: |-
Produces a random string of a length using alphanumeric characters and optionally special characters.
---

# random\_string

The resource `random_string` generates a random permutation of alphanumeric
characters and optionally special characters. This resource does not provide
any guarantee that the random string will contain specific characters.
ie. if length = 4 and special = true, output could be 'Aa0#' or '1111'


## Example Usage

```hcl
resource "random_string" "password" {
length = 16
special = true
}

resource "aws_db_instance" "example" {
master_password = ${random_string.result}

# ... and other aws_db_instance arguments ...
}
```

## Argument Reference

The following arguments are supported:

* `length` - (Required) The length of the string desired

* `upper` - (Optional) (default true) Include uppercase alphabet characters
in random string.

* `lower` - (Optional) (default true) Include lowercase alphabet characters
in random string.

* `number` - (Optional) (default true) Include numeric characters in random
string.

* `special` - (Optional) (default false) Include special characters in random
string. These are '!@#$%&*()-_=+[]{}<>:?'

* `override_special` - (Optional) Supply your own list of special characters to
use for string generation. This overrides characters list in the special
argument. The special argument must still be set to true for any overwritten
characters to be used in generation.

* `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:

* `result` - Random string generated.

3 changes: 3 additions & 0 deletions website/random.erb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
<li<%= sidebar_current("docs-random-resource-shuffle") %>>
<a href="/docs/providers/random/r/shuffle.html">random_shuffle</a>
</li>
<li<%= sidebar_current("docs-random-resource-string") %>>
<a href="/docs/providers/random/r/string.html">random_string</a>
</li>
</ul>
</li>
</ul>
Expand Down