Search code examples
chef-infrachef-solo

Chef: Use attribute in different cookbook


I'm trying to use an attribute defined in one cookbook, say foo, in another cookbook,say bar. I get the error "undefined method `[]' for nil:NilClass"

Chef
    solo.rb
    cookbooks
        foo
            attributes
                default.rb
            recipes
                default.rb
            metadata.rb
        bar
            attributes
                default.rb
            recipes
                default.rb
            metadata.rb
    roles
        roles.json

Above is the structure of my chef.

solo.rb

cookbook_path File.expand_path("../chef/cookbooks", __FILE__)
json_attribs File.expand_path("../chef/roles/roles.json", __FILE__)
log_location STDOUT
log_level :debug

roles.json

{
    "run_list": ["recipe[foo::default]"]
}

foo/attributes/default.rb

default['foo']['var1'] = "Hello"

bar/attributes/default.rb

default['bar']['var1'] = node['foo']['var1']

foo/metadata.rb

name 'foo'
depends 'bar'

When I run the query chef-solo -c solo.rb I get the error as below

================================================================================
Recipe Compile Error in ../chef/cookbooks/bar/attributes/default.rb
================================================================================

NoMethodError
-------------
undefined method `[]' for nil:NilClass

Relevant File Content:
----------------------
Recipe Compile Error in ../chef/cookbooks/bar/attributes/default.rb:
1>> default['bar']['var1'] = node['foo']['var1']

Here foo is my application and bar is Chef Maven. How do I import the attribute??


Solution

  • You have the cookbook dependency reversed. If you want to use the node['foo']['var1'] attribute in the bar cookbook, then the bar cookbook should depend on the foo cookbook, and not the other way round.

    Get rid of the depends 'bar' in foo/metadata.rb and create bar/metadata.rb

    name 'bar'
    depends 'foo'
    

    Complete example:

    |____cookbooks
    | |____foo
    | | |____attributes
    | | | |____default.rb
    | |____bar
    | | |____recipes
    | | | |____default.rb
    | | |____attributes
    | | | |____default.rb
    | | |____metadata.rb
    

    cookbooks/foo/attributes/default.rb

    default['foo']['var1'] = "Hello"
    

    cookbooks/bar/attributes/default.rb

    default['bar']['var1'] = node['foo']['var1']
    

    cookbooks/bar/recipes/default.rb

    log "The value of ['bar']['var1'] is #{node['bar']['var1']}. The value of ['foo']['var1'] is also #{node['foo']['var1']}"
    

    cookbooks/bar/metadata.rb

    name 'bar'
    depends 'foo'
    

    Sample output

    # chef-client -z -o 'recipe[bar]'    
    ...
    resolving cookbooks for run list: ["bar"]
    Synchronizing Cookbooks:
      - foo (0.0.0)
      - bar (0.0.0)
    Compiling Cookbooks...
    Converging 1 resources
    Recipe: bar::default
      * log[The value of ['bar']['var1'] is Hello. The value of ['foo']['var1'] is also Hello] action write