Ruby [SOLVED]: Chef, ruby hashes and templates

Ruby [SOLVED]: Chef, ruby hashes and templates

Home Forums Scripting Ruby Tutorials Ruby [SOLVED]: Chef, ruby hashes and templates

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #197919

    Cloudy Point
    Keymaster

    QuestionQuestion

    I know this is more a ruby question than chef, but…

    I have some attributes like:

    default['my_cookbook']['some_namespace1']['some_attribute1'] = 'some_value1'
    default['my_cookbook']['some_namespace1']['some_attribute2'] = 'some_value2'
    default['my_cookbook']['some_namespace1']['some_attribute2'] = 'some_value3'
    ...
    default['my_cookbook']['some_namespace2']['some_attribute1'] = 'some_value1'
    default['my_cookbook']['some_namespace2']['some_attribute2'] = 'some_value2'
    default['my_cookbook']['some_namespace2']['some_attribute2'] = 'some_value3'
    ...
    

    On the other hand, I am creating a template resource like this:

    template 'template_name' do
      source 'template_source.erb'
      variables (
        my_namespace_1: node['my_cookbook']['some_namespace1'],
        my_namespace_2: node['my_cookbook']['some_namespace2']
      )
    end
    

    Then in the template_source.erb I try:

    ...
    <%= @my_namespace_1['some_attribute1'] %> #=> 'some_value1'
    ...
    

    However when I run Kitchen I get this, instead of 'some_value1':

    Chef::Mixin::Template::TemplateError
    ------------------------------------
    undefined method `[]' for nil:NilClass
    

    How should I send the template variable to use it this way?

    #197920

    Cloudy Point
    Keymaster

    Accepted AnswerAnswer

    EDIT: This applies only to Ruby in general and not to Chef in particular.

    Pass a nested hash:

    template 'template_name' do
      source 'template_source.erb'
      variables (
        my_namespace_1: {
          some_attribute1: node['my_cookbook']['some_namespace1']['some_attribute1']
        }
      )
    end
    

    But rather than copying the values verbatim you can use the full power of the Hash class to slice, dice and merge together whatever you want:

    template 'template_name' do
      source 'template_source.erb'
      variables (
        node['my_cookbook'].slice('some_namespace1', 'some_namespace2')
      )
    end
    

    One gotcha in Ruby that you have tripped on is that symbols are usually used as hash keys:

    # newer literal syntax
    a_hash = {
      foo: 'bar'
    }
    
    # or with the older hash-rocket syntax
    a_hash = {
      :foo => 'bar'
    }
    

    Symbols are extemly efficient since they are interned strings that are stored in table – when comparing symbols you compare the object ID instead of comparing each character in the string.

    In fact strings are only really used when you want keys in the hash that are not valid Ruby symbols – like when building a hash of HTTP headers.

    Ruby does not treat symbol and string keys indifferently:

    {
      foo: 'bar'
    }[:foo] 
    # => bar
    
    {
      foo: 'bar'
    }['foo'] 
    # => nil
    

    So to access the passed variable in the template you would use:

    <%= @my_namespace_1[:some_attribute1] %>
    

    Source: https://stackoverflow.com/questions/46582408/chef-ruby-hashes-and-templates
    Author: max
    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.