We use a yaml data file to drive some of our terraspace .tf generation, however, we’ve noticed that the yaml for string values “yes”, “no”, “on”, “off” are getting converted to boolean true, false. We believe this is behaviour compliant with YAML 1.1 that has been changed in the YAML 1.2 specification. This is breaking the generation of parameters that are going into terraform resources.
Is there any way to get terraspace to use the YAML 1.2 specification rather than YAML 1.1?
Unsure. A snippet of code with how you’re grabbing the YAML and building the tf file would be helpful. Guessing you’re just using ERB and calling YAML.load
This seems to be what you’re looking for
Basically, the options:
quote the values in the YAML file so they’re not casted to booleans
monkey patch - person does not recommend. For probably good reasons
create your own custom YAML method and use that instead. It would load the on and off as strings, the old behavior
Thanks @tung - yes, we’re using YAML.load and ERB.
We’d seen that but we have an issue though in that the YAML is being generated from multiple sources - including conversion from JSON for some of it and that strips the quotes.
The later YAML 1.2 spec removes using yes, no, on, off, y, n, etc, etc as boolean so I just wondered if it was an option.
I’ll see if I can work around via another method anyway. Thanks for the response.
Here you go. It’s the #3 approach. It traverses the nodes and uses the clever trick node.quoted = true from the stackoverflow link above. Did it only for on and off. You can customize it to your needs.
Code
config/helpers/yaml_helper.rb
require "yaml"
module Terraspace::Project::YamlHelper
# Thanks https://stackoverflow.com/questions/28507195/yaml-ruby-loading-on-as-true
def yaml_load(path)
nodes = YAML.parse_file(path)
nodes.each do |node|
yaml_load_tranverse(node)
end
nodes.to_ruby
end
def yaml_load_tranverse(node)
if node.is_a?(Psych::Nodes::Scalar) && %w(on off).include?(node.value)
node.quoted = true
end
node.children do |child|
yaml_load_tranverse(child)
end
end
end
---
test_true: true
test_false: false
test_yes: yes
test_no: no
test_on: on # should load as "on" string instead of boolean true
test_off: off # should load as "off" string instead of boolean false
test_y: y
test_n: n
test_Y: Y
test_N: N
Debugging
$ terraspace build demo
Building .terraspace-cache/us-west-2/dev/stacks/demo
$ cat .terraspace-cache/us-west-2/dev/stacks/demo/main.tf
resource "random_pet" "this" {
keepers = {
test_true = "on"
test_false = "false"
test_yes = "true"
test_no = "false"
test_on = "on" # should load as "on" string instead of boolean true
test_off = "off" # should load as "off" string instead of boolean false
test_y = "y"
test_n = "n"
test_Y = "Y"
test_N = "N"
}
}
$