gruntwork-io / boilerplate

A tool for generating files and folders ("boilerplate") from a set of templates
https://www.gruntwork.io
Mozilla Public License 2.0
158 stars 12 forks source link

Handle map types better for toJson #84

Open yorinasub17 opened 2 years ago

yorinasub17 commented 2 years ago

Describe the bug For certain map types, toJson fails to render valid json.

To Reproduce

boilerplate.yml

variables:
  - name: FirewallRules
    description: List of firewall rule.
    type: list
    default: [] 

_input_vars.yml

FirewallRules:
  - "name"                   : "densbx-allow-internal"
    "deny"                   : [ ]
    "log_config":
      - "metadata : INCLUDE_ALL_METADATA"
    "allow":
      - protocol: "tcp"
        ports:
          - 22
          - 443
      - protocol: "udp"
        ports:
          - 53
      - protocol: "icmp"
        ports:
  - "name"                   : "densbx-allow-internal"
    "deny"                   : [ ]
    "log_config":
      - "metadata : INCLUDE_ALL_METADATA"
    "allow":
      - protocol: "tcp"
        ports:
          - 22
          - 443
      - protocol: "udp"
        ports:
          - 53
      - protocol: "icmp"
        ports:

template.hcl

inputs = {
  rules = [    
    {{- range $rule, $config := .FirewallRules }}
    {
      {{ range $key, $value := $config }}      
      {{ $key }} = jsondecode("{{ $value | toJson }}")     
      {{- end }}
    },
    {{- end -}}
  ]
}

Expected behavior When rendering this out, we should get valid json output for each entry, but the allow key results in an empty list:

actual rendered:

inputs = {
  rules = [
    {
      allow = jsondecode("")      
      deny = jsondecode("[]")      
      log_config = jsondecode("["metadata : INCLUDE_ALL_METADATA"]")      
      name = jsondecode(""densbx-allow-internal"")
    },
    {
      allow = jsondecode("")      
      deny = jsondecode("[]")      
      log_config = jsondecode("["metadata : INCLUDE_ALL_METADATA"]")      
      name = jsondecode(""densbx-allow-internal"")
    },]
}

Currently we can work around it by using yaml at the top e.g.

inputs = {
  rules = yamldecode(<<EOF
{{ .FirewallRules | toYaml }}
EOF
)
}

But we should figure out why json rendering doesn't work.