Skip to content

Commit

Permalink
Add yaml_list_of_strings and rename yaml to yaml_map_of_strings
Browse files Browse the repository at this point in the history
  • Loading branch information
ashald committed Jun 28, 2018
1 parent 7554265 commit f73539b
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 78 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
release
terraform-provider-stateful*
.terraform/
*.tfstate*
terraform-provider-*
*.yaml
*.tf

11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
# Change Log

## 2.0 - 2018-06-28

### Added

- A new data source to de-serialize a list of strings - `yaml_list_of_strings`

### Changed

- `yaml` renamed to `yaml_map_of_strings`


## 1.0 - 2018-06-20

### Added
Expand Down
46 changes: 32 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ Please note that JSON is subset of YAML and therefore this data source can be us
## Data Sources

This plugin defines following data sources:
* `yaml`
* `yaml_map_of_strings`
* `yaml_list_of_strings`

## Reference

Expand All @@ -21,14 +22,14 @@ This plugin defines following data sources:
The following arguments are supported:

* `input` - (Required) A string that will be parsed. Should be a valid YAML, YAML flow or JSON.
* `flatten` - (Optional) A string that should be used as a separator in order to flatten nested maps. If set to a
non-empty value nested maps going to be flattened.
* `flatten` - (Optional) [**only** `yaml_map_of_strings`] A string that should be used as a separator in order to flatten
nested maps. If set to a non-empty value nested maps going to be flattened.

### Attributes

The following attribute is exported:

* `output` - Map with keys and values as strings.
* `output` - Map with keys and values as strings for `yaml_map_of_strings` and list of strings for `yaml_list_of_strings`.

## Limitations

Expand Down Expand Up @@ -61,29 +62,41 @@ or it can be [installed system-wide](https://www.terraform.io/docs/configuration
```hcl
locals {input="input.yaml"}
data "yaml" "normal" { input = "${file(local.input)}" }
data "yaml" "flat" { input = "${file(local.input)}" flatten="/" }
data "yaml_map_of_strings" "normal" { input = "${file(local.input)}" }
data "yaml_map_of_strings" "flat" { input = "${file(local.input)}" flatten="/" }
data "yaml_list_of_strings" "list" { input = "${data.yaml_map_of_strings.normal.output["list"]}" }
output "normal" { value = "${data.yaml.normal.output}" }
output "flat" { value = "${data.yaml.flat.output}" }
output "normal" { value = "${data.yaml_map_of_strings.normal.output}" }
output "flat" { value = "${data.yaml_map_of_strings.flat.output}" }
output "list" { value = "${data.yaml_list_of_strings.list.output}" }
```

### Download
```bash
$ wget "https://github.com/ashald/terraform-provider-yaml/releases/download/v1.0.0/terraform-provider-yaml_v1.0.0-$(uname -s | tr '[:upper:]' '[:lower:]')-amd64"
$ wget "https://github.com/ashald/terraform-provider-yaml/releases/download/v2.0.0/terraform-provider-yaml_v2.0.0-$(uname -s | tr '[:upper:]' '[:lower:]')-amd64"
$ chmod +x ./terraform-provider-yaml*
```

### Init
```bash
$ ls -1
main.tf
terraform-provider-yaml_v1.0.0-linux-amd64
terraform-provider-yaml_v2.0.0-linux-amd64

$ terraform init

Initializing provider plugins...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.yaml: version = "~> 2.0"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
Expand All @@ -108,8 +121,9 @@ list:
EOF

$ terraform apply
data.yaml.normal: Refreshing state...
data.yaml.flat: Refreshing state...
data.yaml_map_of_strings.normal: Refreshing state...
data.yaml_map_of_strings.flat: Refreshing state...
data.yaml_list_of_strings.list: Refreshing state...

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Expand All @@ -119,6 +133,10 @@ $ terraform apply
a/b/c = foobar
list = [foo, bar]
}
list = [
foo,
bar
]
normal = {
a = {b: {c: foobar}}
list = [foo, bar]
Expand Down Expand Up @@ -185,8 +203,8 @@ executed against a configuration in the same directory.
In order to prepare provider binaries for all platforms:
```bash
$ make release
GOOS=darwin GOARCH=amd64 go build -o './release/terraform-provider-yaml_v1.0.0-darwin-amd64'
GOOS=linux GOARCH=amd64 go build -o './release/terraform-provider-yaml_v1.0.0-linux-amd64'
GOOS=darwin GOARCH=amd64 go build -o './release/terraform-provider-yaml_v2.0.0-darwin-amd64'
GOOS=linux GOARCH=amd64 go build -o './release/terraform-provider-yaml_v2.0.0-linux-amd64'
```
### Versioning
Expand Down
49 changes: 49 additions & 0 deletions yaml/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package yaml

import (
"crypto/sha256"
"fmt"
yml "github.com/ashald/yaml"
"reflect"
"strings"
)

const FieldInput = "input"
const FieldFlatten = "flatten"

const FieldOutput = "output"

func serializeToFlowStyleYaml(input interface{}) (string, error) {
inputRef := reflect.ValueOf(input)

if inputRef.Kind() == reflect.Interface {
inputRef = inputRef.Elem()
}

if inputRef.Kind() == reflect.String {
return input.(string), nil
}

var builder strings.Builder
encoder := yml.NewEncoder(&builder)
encoder.SetFlowStyle(true)
encoder.SetLineWidth(-1)

err := encoder.Encode(inputRef.Interface())
if err != nil {
return "", err
}

err = encoder.Close()
if err != nil {
return "", err
}

return strings.TrimSpace(builder.String()), nil
}

func getSHA256(src string) string {
h := sha256.New()
h.Write([]byte(src))
return fmt.Sprintf("%x", h.Sum(nil))
}
54 changes: 54 additions & 0 deletions yaml/data_source_yaml_list_of_strings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package yaml

import (
yml "github.com/ashald/yaml"
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceList() *schema.Resource {
return &schema.Resource{
Read: readYamlList,

Schema: map[string]*schema.Schema{
// "Inputs"
FieldInput: {
Type: schema.TypeString,
Required: true,
},
// "Outputs"
FieldOutput: {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
}
}

func readYamlList(d *schema.ResourceData, m interface{}) error {
input := d.Get(FieldInput).(string)

var parsed []string

err := yml.Unmarshal([]byte(input), &parsed)
if err != nil {
return err
}

var result []string

for _, value := range parsed {
serialized, err := serializeToFlowStyleYaml(value)
if err != nil {
return err
}
result = append(result, serialized)
}

d.Set(FieldOutput, result)
d.SetId(getSHA256(input))

return nil
}
59 changes: 59 additions & 0 deletions yaml/data_source_yaml_list_of_strings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package yaml

import (
"testing"

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

const listInput = `
output "result" { value="${data.yaml_list_of_strings.doc.output}" }
data "yaml_list_of_strings" "doc" {
input = <<EOF
- foo
- bar
EOF
}
`

func TestListOfStringsDataSource(t *testing.T) {
expected := []string{"foo", "bar"}

resource.Test(t, resource.TestCase{
IsUnitTest: true,
Providers: testProviders,
Steps: []resource.TestStep{
{
Config: listInput,
Check: resource.ComposeTestCheckFunc(
testListOutputEquals("result", expected),
),
},
},
})
}

func testListOutputEquals(name string, expected []string) resource.TestCheckFunc {
return func(state *terraform.State) error {
output := state.RootModule().Outputs[name]

if output == nil {
return fmt.Errorf("missing '%s' output", name)
}

var outputList []string

for _, v := range output.Value.([]interface{}) {
outputList = append(outputList, v.(string))
}

if !reflect.DeepEqual(outputList, expected) {
return fmt.Errorf("output '%s' value '%v' does not match expected '%v'", name, output.Value, expected)
}
return nil
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
package yaml

import (
"crypto/sha256"
"fmt"
yml "github.com/ashald/yaml"
"github.com/hashicorp/terraform/helper/schema"
"reflect"
"strings"
)

const FieldInput = "input"
const FieldFlatten = "flatten"

const FieldOutput = "output"

func dataSourceYAML() *schema.Resource {
func dataSourceMap() *schema.Resource {
return &schema.Resource{
Read: readYaml,
Read: readYamlMap,

Schema: map[string]*schema.Schema{
// "Inputs"
Expand All @@ -37,12 +30,14 @@ func dataSourceYAML() *schema.Resource {
}
}

func readYaml(d *schema.ResourceData, m interface{}) error {
func readYamlMap(d *schema.ResourceData, m interface{}) error {
input := d.Get(FieldInput).(string)
separatorRaw, shouldFlatten := d.GetOk(FieldFlatten)
separator := separatorRaw.(string)

parsed, err := deserializeYaml(input)
parsed := make(map[string]interface{})

err := yml.Unmarshal([]byte(input), &parsed)
if err != nil {
return err
}
Expand Down Expand Up @@ -72,35 +67,6 @@ func readYaml(d *schema.ResourceData, m interface{}) error {
return nil
}

func deserializeYaml(input string) (map[string]interface{}, error) {
parsed := make(map[string]interface{})

err := yml.Unmarshal([]byte(input), &parsed)
if err != nil {
return nil, err
}
return parsed, nil
}

func serializeToFlowStyleYaml(input interface{}) (string, error) {
var builder strings.Builder
encoder := yml.NewEncoder(&builder)
encoder.SetFlowStyle(true)
encoder.SetLineWidth(-1)

err := encoder.Encode(input)
if err != nil {
return "", err
}

err = encoder.Close()
if err != nil {
return "", err
}

return strings.TrimSpace(builder.String()), nil
}

func flattenValue(result map[string]string, v reflect.Value, prefix string, separator string) error {
if v.Kind() == reflect.Interface {
v = v.Elem()
Expand Down Expand Up @@ -133,9 +99,3 @@ func flattenMap(result map[string]string, v reflect.Value, prefix string, separa
flattenValue(result, v.MapIndex(k), newPrefix, separator)
}
}

func getSHA256(src string) string {
h := sha256.New()
h.Write([]byte(src))
return fmt.Sprintf("%x", h.Sum(nil))
}
Loading

0 comments on commit f73539b

Please sign in to comment.