3

Is there a way to access a Chef data bag from within the default.rb attributes file?

My use case is I need to represent a collection of operating system environment variables as a hash of attributes which are ultimately passed through to a template. Some of these environment variables are credentials that I'm storing in an encrypted data bag. Unfortunately Chef won't let me access the recipe DSL from within the attributes file, so the data_bag_item method I'd normally use isn't available.

Thanks in advance.

John Topley
  • 113,588
  • 46
  • 195
  • 237
  • 1
    While you may not have the recipe DSL, I don't think there's any prohibition on calling the various methods, e.g. [Chef::DataBagItem.load](http://www.rubydoc.info/github/opscode/chef/Chef/DataBagItem#load-class_method). As the other posters say, it's probably better to give defaults in your attributes file and use the recipe to load a data bag. – Martin May 25 '16 at 16:10

2 Answers2

4

Why cannot you set the attribute in the recipe, from the data bag, and use as expected. Normally, I would set a default value in the attributes/default.rb for the very same value just in case the data bag does not exist at runtime.

In the attributes file:

default['cookbook_name']['secret_value'] = '__UNDEFINED__'

Then in the recipe you fill in and reference the attribute as expected:

node.default['cookbook_name']['secret_value'] = data_bag_item('something', 'else')

The attributes files is used as a location to store the attributes. Once the recipe is compiled the end result is scheduled to run. Where the value came from is not important at that point.

Michael Küller
  • 3,982
  • 4
  • 22
  • 42
Ken Brittain
  • 2,255
  • 17
  • 21
  • A good answer but it's because the recipe is generalised. It loops round a list of things to deploy, only some of which require the credentials environment variables. So I was hoping to keep the specialisation in the attributes file. – John Topley May 25 '16 at 12:38
  • What about lambdas for each attribute and then invoke in the recipe. That would keep the code, logically, in the attributes file even though it was executing in the recipe. Thinking along the lines of `default['cookbook_name']['secret_value'] = lambda { data_bag_item('something', 'else') }`. Attributes files is still Ruby so it should function if evaluation happens in recipe with `.call` when needed. – Ken Brittain May 25 '16 at 13:38
  • `node['whatever'] = value` will throw an error in chef 12.8 (at least), prefer `node.default['whatever'] = value` – Tensibai May 25 '16 at 15:36
  • @KenBrittain how to decrypt databag item using secret key ?? – shiv455 Mar 24 '17 at 16:44
  • IIRC, we usually drop the secret file in `/etc/chef/secret` and use the 3rd param to `data_bag_item` example here: https://docs.chef.io/data_bags.html#load-with-recipe-dsl – Ken Brittain Mar 27 '17 at 19:04
3

You can't use the DSL helpers but you can directly use Chef::DataBagItem.load yourself. Check the Chef code to see how to use it (we don't document those APIs AFAIK).

coderanger
  • 52,400
  • 4
  • 52
  • 75