I'm trying to create a recipe which pulls in variables which are defined in a YAML configuration file and then uses their values as recipe attributes.
A couple points:
My config.yml
file resides in the root of my chef directory (that is, outside of my cookbooks
directory, and on the same level as my Vagrantfile
which drives the provisioning process.
I use a similar approach to populate values into my Vagrantfile
, which is what gave me the idea for this solution. I want to maintain a list of user-configurable values which need to be used in both my Vagrantfile
as well as various recipes inside various cookbooks.
As an example, here are two values from config.yml
:
---
basics:
vm_ip: 192.168.56.11
vm_hostname: luma.com
I use the following in my Vagrantfile
to read these values:
require 'yaml'
config_file = "config.yml"
settings = YAML.load_file(File.dirname(File.expand_path(__FILE__)) + "/#{config_file}")
And I reference them as such elsewhere in the Vagrantfile
(Syntax abbreviated):
machine.vm.network 'private_network', ip: settings['basics']['vm_ip']
machine.vm.hostname = settings['basics']['vm_hostname']
This approach works great for the Vagrantfile
, but of course, that's outside of Chef's purview.
From a Chef perspective, I thought I could perhaps follow a similar approach, since Chef is Ruby-based. I have a cookbook base
with an attributes
folder, and a default.rb
attributes file. My initial attempt was to simply duplicate the approach in default.rb
:
require 'yaml'
config_file = "config.yml"
settings = YAML.load_file(File.dirname(File.expand_path("../../../", __FILE__)) + "/#{config_file}")
And then reference the config.yml
values as attributes like so:
default['vm']['ip'] = settings['basics']['vm_ip']
default['vm']['hostname'] = settings['basics']['vm_hostname']
This fails because, as I've (naively) learned, the __FILE__
value refers to a path on the node rather than to a file in the local directory, as this attributes file is used during convergence, etc. Stupid me.
So, my thought now is to dynamically populate the attributes file as part of the Vagrantfile
, since that's outside of Chef's process. Before I go through the effort of writing that, I'm wondering if there's a more appropriate chef-based approach I should consider.
i might be wrong, but it seems you are trying to invent the wheel. let me elaborate...
from vagrant perspective, you should leverage test-kitchen in conjunection with vagrant
driver.
once you set it up, take advantage of custom kitchen configuration -- use general configuration and (user) custom configuration (each user might have a different custom conifugration, corresponding to the config.yml
you mentioned`)
note also, that kitchen.yml
supports erb. you can use it to do things dynamically.
from chef perspective, is a configuration management and you should use it correctly. that is, rather than using an external file (config.yml
) to feed chef with values, take advantage of recipe attributes, json attributes or even data bags to store values which will be used during your recipe.
note that attributes can be generated dynamically, you will just have to put some logic for that (same as you did for config.yml
)