Reading JSON file to use with ERB templating

Hi BoltOps Community,

I don’t have any background on Ruby/ERB, and would like some pointers/help in doing perhaps something basic with ERB templating…

I am trying to do some ERB templating with terraspace, and would like to read data from a JSON file. E.g. content of vpc_config.json

{
    "network": {
        "vpcs": {
            "main": {
                "name": "main",
                "vpc_cidr": "10.98.20.0/22",
                "subnets": {
                    "public": {
                        "az1": {
                            "subnet_type": "external",
                            "subnet_name": "public",
                            "subnet_az"  : "1",
                            "subnet_cidr": "10.98.20.0/26"
                        },
                        "az2": {
                            "subnet_type": "external",
                            "subnet_name": "public",
                            "subnet_az"  : "2",
                            "subnet_cidr": "10.98.20.64/26"
                        }
                    },
                    "private": {
                        "az1": {
                            "subnet_type": "internal",
                            "subnet_name": "private",
                            "subnet_az"  : "1",
                            "subnet_cidr": "10.98.21.0/26"
                        },
                        "az2": {
                            "subnet_type": "internal",
                            "subnet_name": "private",
                            "subnet_az"  : "2",
                            "subnet_cidr": "10.98.21.64/26"
                        }
                    },
                    "database": {
                        "az1": {
                            "subnet_type": "internal",
                            "subnet_name": "database",
                            "subnet_az"  : "1",
                            "subnet_cidr": "10.98.22.0/26"
                        },
                        "az2": {
                            "subnet_type": "internal",
                            "subnet_name": "database",
                            "subnet_az"  : "2",
                            "subnet_cidr": "10.98.22.64/26"
                        }
                    }
                }
            }
        }
    }
}

If I want to read the vpc_config.json and try to use ERB templating to loop through the subnets (rather than using terraform’s for_each loop), would it correct to assume that I will need to create a customer helper file to do this?

I have tried creating a custom helper file by doing terraspace new helper custom --type project
(which config/helpers/custom_helper.rb for me).

And in the custom_helper.rb, when I tried to do

require 'json'

file = File.read('path_to_vpc_config.json')
data_hash = JSON.parse(file)

module Terraspace::Project::CustomHelpers
  def app_name
    "#{@mod.name}-#{Terraspace.env}"
  end
end

running terraspace build against the stack gives an error saying that vpc_config.json is the wrong constant name (or something along the lines of that). Any pointers on how I would be able read the JSON file so that I can reference it in my .tf files?

Many thanks,
James

Hello,

I think I managed to find out what’s causing my issue and resolve the problem. I.e. When I try to run terraspace build, I was encountering

/home/ubuntu/.rvm/gems/ruby-2.6.3/gems/activesupport-6.1.4.1/lib/active_support/inflector/methods.rb:288:in const_get’: wrong constant name VpcConfig.json (NameError)`

That error came about because I placed vpc_config.json in the config/helpers folder. I’ve now moved it to the base directory of the project, and I am able to call/use it by doing:

Content of /home/ubuntu/environment/infra/config/helpers/custom_helper.rb:

require 'json'

module Terraspace::Project::CustomHelper
  def app_name
    "#{@mod.name}-#{Terraspace.env}"
  end

  def app_name2
    file = File.read("/home/ubuntu/environment/infra/vpc_config.json")
    data_hash = JSON.parse(file)
  end
end

Call it in the terraform file using e.g. (to get the vpc_cidr for the “main” VPC)
# "<%= app_name2['network']['vpcs']['main']['vpc_cidr'] %>"

Not sure if this is the right way to do it, but it worked for me :slight_smile:

Many thanks,
James

I have something similar which resides in the config directory and is sourced by the helper like so:

vpc_config_file = "config/vpc_config.#{Terraspace.env}.json"

You could also add a helper method to return just the ‘main’ data by:

def main_vpc
    data_hash['network']['vpcs']['main']
end

( Also not a Ruby expert I discovered the fetch() method for hash/map access )

Use the helper in your TF like:

vpc_cidr = "<%= main_vpc['vpc_cidr'] %>"

Hi pilchkinstein,

Nice one, thanks for the tips! :slight_smile:

Cheers,
James