# Defining dynamic global custom variables once for all recipes during chef run

**URL:** <https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531>\
**Category:** Chef Infra (archive)\
**Created:** [April 28, 2015, 5:28pm UTC](https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531 "2015-04-28T17:28:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mathew\_Crane](https://avatars.discourse-cdn.com/v4/letter/m/7ab992/32.png) [@Mathew\_Crane](https://discourse.chef.io/u/Mathew_Crane)\
**Post date:** [April 28, 2015, 5:28pm UTC](https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531/1 "2015-04-28T17:28:51Z")

</div>

Scenario:

- Two custom variables are dynamically assigned based on  
node.chef\_environment via a targeted search and subsequent for-loop against  
a max of 10 top-level data bag items.
- Both variables are a DataBagItem.
- They are defined within any recipe that needs these values.
- Setting this in every recipe doesn’t scale.

Is there a way to define these variables once in a separate, single-purpose  
cookbook recipe, and have them reliably made available to all recipes  
within the chef run?

What is the best direction for this? Setting attributes via  
attributes/default.rb or creating a custom library with a ruby block?

Thanks!  
-Mat

---

<div class="post-metadata">

**Author:** ![Ranjib](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/ranjib/32/1040_2.png) [@Ranjib](https://discourse.chef.io/u/Ranjib)\
**Post date:** [April 28, 2015, 9:15pm UTC](https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531/2 "2015-04-28T21:15:08Z")

</div>

You can use node.run\_state[:foo] ||= "bar" style code blocks to do this.  
i generally prefer to move this into a library, and if possible back it by  
a separate singleton class, this is a common requirement, like if you are  
using some data bag across recipes etc, this helps avoiding making multiple  
chef server api call during a single chef run.  
i have thought of raising an RFC for this, i.e. a global (chef-client),  
locally cached version of data store, but the ordering bit (where you'll  
define it, if recipe, how you ensure its executed in the beginning. should  
we introduce some like initializers.. etc?)

On Tue, Apr 28, 2015 at 10:28 AM, Mathew Crane [mathew.crane@gmail.com](mailto:mathew.crane@gmail.com)  
wrote:

> Scenario:
> 
> - Two custom variables are dynamically assigned based on  
> node.chef\_environment via a targeted search and subsequent for-loop against  
> a max of 10 top-level data bag items.
> - Both variables are a DataBagItem.
> - They are defined within any recipe that needs these values.
> - Setting this in every recipe doesn't scale.
> 
> Is there a way to define these variables once in a separate,  
> single-purpose cookbook recipe, and have them reliably made available to  
> all recipes within the chef run?
> 
> What is the best direction for this? Setting attributes via  
> attributes/default.rb or creating a custom library with a ruby block?
> 
> Thanks!  
> -Mat

---

<div class="post-metadata">

**Author:** ![Tensibai](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/tensibai/32/29_2.png) [@Tensibai](https://discourse.chef.io/u/Tensibai)\
**Post date:** [April 28, 2015, 9:21pm UTC](https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531/3 "2015-04-28T21:21:22Z")

</div>

I don't know if it's the best way but we so this with an Env cookbook with many attributes files, one common for all invariable values and one file per Env starting With 'return unless node.chef\_environment == "target\_env"'

Le 28 avr. 2015 19:28, Mathew Crane \<mathew.crane@gmail.com\> a écrit :

> Scenario:
> - Two custom variables are dynamically assigned based on node.chef\_environment via a targeted search and subsequent for-loop against a max of 10 top-level data bag items.- Both variables are a DataBagItem.- They are defined within any recipe that needs these values.
> 
> - Setting this in every recipe doesn't scale.
> 
> Is there a way to define these variables once in a separate, single-purpose cookbook recipe, and have them reliably made available to all recipes within the chef run?
> 
> What is the best direction for this? Setting attributes via attributes/default.rb or creating a custom library with a ruby block?
> 
> Thanks!-Mat

---

<div class="post-metadata">

**Author:** ![Mathew\_Crane](https://avatars.discourse-cdn.com/v4/letter/m/7ab992/32.png) [@Mathew\_Crane](https://discourse.chef.io/u/Mathew_Crane)\
**Post date:** [April 30, 2015, 2:08pm UTC](https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531/4 "2015-04-30T14:08:13Z")

</div>

Thanks. I made a library instance method to access these attributes  
dynamically. This solves the code duplication issue.

However, I'm still unaware of a good way to 'set' these variables  
automatically via a library so that they become available to all recipes  
within the Chef run. Ideally the variables become available to all  
cookbooks that have 'depend "helper-cookbook"' in metadata.rb, and  
redundant calls to the Chef API are eliminated. Is this even possible?

How it exists currently:

# cookbooks/helper-cookbook/libraries/helper-module.rb

module helper  
def my\_helper\_module  
...code...  
return env, server  
end  
end

reference:

> <https://stackoverflow.com/questions/22078318/access-node-attributes-in-chef-library>

# cookbooks/dependent-cookbook/metadata.rb:

depends "helper-cookbook"

# cookbooks/dependent-cookbook/recipes/default.rb:

env, server = my\_helper\_module

Any tips or suggestions?

On Tue, Apr 28, 2015 at 5:21 PM, Tensibai Zhaoying [tensibai@iabis.net](mailto:tensibai@iabis.net)  
wrote:

> I don't know if it's the best way but we so this with an Env cookbook with  
> many attributes files, one common for all invariable values and one file  
> per Env starting With 'return unless node.chef\_environment == "target\_env"'  
> Le 28 avr. 2015 19:28, Mathew Crane [mathew.crane@gmail.com](mailto:mathew.crane@gmail.com) a écrit :
> 
> Scenario:
> 
> - Two custom variables are dynamically assigned based on  
> node.chef\_environment via a targeted search and subsequent for-loop against  
> a max of 10 top-level data bag items.
> - Both variables are a DataBagItem.
> - They are defined within any recipe that needs these values.
> - Setting this in every recipe doesn't scale.
> 
> Is there a way to define these variables once in a separate,  
> single-purpose cookbook recipe, and have them reliably made available to  
> all recipes within the chef run?
> 
> What is the best direction for this? Setting attributes via  
> attributes/default.rb or creating a custom library with a ruby block?
> 
> Thanks!  
> -Mat

---

<div class="post-metadata">

**Author:** ![kallistec](https://sea2.discourse-cdn.com/flex016/user_avatar/discourse.chef.io/kallistec/32/23_2.png) [@kallistec](https://discourse.chef.io/u/kallistec)\
**Post date:** [April 30, 2015, 2:29pm UTC](https://discourse.chef.io/t/defining-dynamic-global-custom-variables-once-for-all-recipes-during-chef-run/6531/5 "2015-04-30T14:29:31Z")

</div>

On Thursday, April 30, 2015 at 7:08 AM, Mathew Crane wrote:

> Thanks. I made a library instance method to access these attributes dynamically. This solves the code duplication issue.
> 
> However, I'm still unaware of a good way to 'set' these variables automatically via a library so that they become available to all recipes within the Chef run. Ideally the variables become available to all cookbooks that have 'depend "helper-cookbook"' in metadata.rb, and redundant calls to the Chef API are eliminated. Is this even possible?
> 
> How it exists currently:
> 
> # cookbooks/helper-cookbook/libraries/helper-module.rb
> 
> module helper  
> def my\_helper\_module  
> ...code...  
> return env, server  
> end  
> end
> 
> reference: [ruby - Access Node attributes in Chef Library - Stack Overflow](http://stackoverflow.com/questions/22078318/access-node-attributes-in-chef-library)
> 
> # cookbooks/dependent-cookbook/metadata.rb:
> 
> depends "helper-cookbook"
> 
> # cookbooks/dependent-cookbook/recipes/default.rb:
> 
> env, server = my\_helper\_module
> 
> Any tips or suggestions?  
> The simplest way to go is to define your helper methods as class methods (actually module methods since they’d be defined on a module, but the difference is pedantic).

This blog post is a bit old and rails-centric but describes how they work well enough: [Class and Instance Methods in Ruby // RailsTips by John Nunemaker](http://www.railstips.org/blog/archives/2009/05/11/class-and-instance-methods-in-ruby/)

With a bit more work, it’s possible to mix your module in to Chef’s DSL, but this can be a bit confusing because the recipe DSL and resource DSLs are separate things, so you’ll probably stub your toe on that.

--  
Daniel DeLeo
