Vlad Cenan Vlad Cenan - 10 months ago 37
Ruby Question

Generate Templates from Json variables

I want to generate some zabbix templates for some local microservices (variables stored in a json file), please see the code below:

def self.haproxyTemplates
file = File.read('./services.json')
data_hash = JSON.parse(file)

service = data_hash.keys
service.each do |microservice|
puts "Microservice: #{microservice}"
httpport = data_hash["#{microservice}"]['httpport']
puts "httpPort: #{httpport}"

open("./haproxy.xml", 'w+') { |f| f.chmod(0755)
x = ERB.new(template).result(binding)
f << "#{x}\n"

And this is my services.json file:

....... ,
"httpport": "27200"
"httpport": "25201"

Basically in this method when I'm doing the loop for each microservice it run successfully until it ends the loop. When it creates the haproxy.xml it shows
" undefined local variable or method `httpport' for main:Object (NameError)"
I tried to put httpport variable outside the loop and it's shows the same error.

Please also see a part of the erb file(if I replace the <%= httpport %> with 25201, the file is generated corectly):

<items><% service.each do |microservice| %>
<name>haproxy <%= microservice %> - <%= httpport %></name>
</item><% end %>


Here is a working example, if you paste this into a ".rb" file, then you can run it.

Problem with your version: binding does not contain httport (and even if it would contain it, it would be the same for all microservices because it does not get re-assigned.): solution: access the the JSON (ruby hash) data in the template and then loop from there.

require 'erb'

# data = parse JSON from file, inline here as example

data = {
  'microservice1' => {
    'httpport' => '27200'
  'microservice2' => {
    'httpport' => '27201'

open("haproxy.xml", 'w+') do |file|
  template = ERB.new(DATA.read)
  file << template.result(binding)
  file << "\n"

  <% data.each do |name, info| %>
      <name>haproxy <%= name %> - <%= info['httpport'] %></name>
  <% end %>