Travis Austin
Travis Austin

Reputation: 439

Chef Recipe to create template with nested data

I am trying to create a chef recipe for my Amazon OpsWorks stack. I'd like to pass custom JSON data into the stack, and have the recipe create an .ini file for use with PHP's parse_ini_file() command.

What I Have Working

Currently, I can create a flat .ini file with the following:

JSON:

{
    "settings_ini": {
        "quantity": 1,
        "width": 10,
        "height": 20
    }
}

The resulting settings.ini file is:

quantity = 1
width = 10
height = 20

Chef recipe:

template "/my/path/here/settings.ini" do
    owner  "www_data"
    group  "www_data"
    mode   "0644"
    source "settings.ini.erb"
    variables({
        :settings_ini => node[:settings_ini]
    })
end

Chef template "settings.ini.erb":

<% @settings_ini.each do |name, value| -%>
<%= name %> = <%= value %>
<% end -%>

What I'm Trying to Make Work

I'd like to change my JSON data to be this:

{
    "settings_ini": {
        "quantity": 1,
        "attributes": {
            "width": 10,
            "height": 20
        }
    }
}

And I want my resulting settings.ini file to be this:

quantity = 1

[attributes]
width = 10
height = 20

Or, it could also be this:

quantity = 1
[attributes]width = 10
[attributes]height = 20

I need help modifying my settings.ini.erb template file to use the nested JSON data correctly.

Upvotes: 0

Views: 1638

Answers (2)

cassianoleal
cassianoleal

Reputation: 2566

You could use a recursive function.

Stick this into libraries/hash_to_ini.rb:

def hash_to_ini(hash, lines = [])
  hash.each do |name, value|
    unless value.is_a? Hash
      lines << "#{name} = #{value}"
    else
      lines << "[#{name}]"
      lines = hash_to_ini(value, lines)
    end
  end
  return lines
end

Then in your template:

<% hash_to_ini(@settings_ini).each do |line| -%>
<%= line %>
<% end -%>

Upvotes: 1

StephenKing
StephenKing

Reputation: 37640

Why not just a second each loop?

<% @settings_ini.each do |section, data| -%>
[<%= section %>]
<% data.each do |name, value| -%>
<%= name %> = <%= value %>
<% end -%>
<% end -%>

This code is untested.. but I guess it should work.

You could also add some safety like done e.g. here and here

Upvotes: 0

Related Questions