Skip to content

Instantly share code, notes, and snippets.

@markolson
Created December 7, 2013 05:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save markolson/7837491 to your computer and use it in GitHub Desktop.
Save markolson/7837491 to your computer and use it in GitHub Desktop.
Pass a environment name, node name, and path to a JSON file with a run_list in it, and get back a node that you can call merged_attributes on to get (pretty dang close to) what the node will have as it's attributes during a run. Useful for updating docs to have up-to-date with a pre-commit hook.
# I'm sure this can all be replaced with a one liner, buried deep in chef somewhere.
# Actually, probably Chef::Client.
require 'json'
require 'chef'
require 'chef/application/solo'
require 'chef/knife/deps'
def setup_node(environment, name, node_config_path)
Chef::Config[:config_file] = ".chef/knife.rb"
Chef::Config[:solo] = true
# load the environment, which gives paths to cookbooks and environments
env = Chef::ConfigFetcher.new(Chef::Config[:config_file])
Chef::Config.from_string(env.read_config, Chef::Config[:config_file])
# setup some config after loading the config file..
Chef::Config[:environment] = environment
Chef::Config[:node_name] = name
# Loads up all the bookbooks in our path
cl = Chef::CookbookLoader.new(Chef::Config[:cookbook_path])
cl.load_cookbooks
# Create a node -- this also loads up environment config
node = Chef::Node.build(name)
# OHAI is needed. It will provide data from your laptop, but we don't
# show/use the data this provides in any of our attributes
ohai = ::Ohai::System.new
ohai.all_plugins
automatic = ohai.data
# lies
automatic['platform_family'] = 'debian'
# lies, lies
automatic['lsb'] = {'codename' => 'precise'}
automatic['memory'] = {'total' => '4096'} # awwyiss fake memory for our one node
node.automatic_attrs.merge! automatic
# This loads up the run list from the node file
node.consume_run_list(JSON.load(File.read(node_config_path)))
# And expands out the roles to all of their recipes
full_run_list = node.expand!('disk')
# Iterate over all the recipes in the runlist, which can be either "cookbook" or
# "cookbook::subrecipe" -- we only want "cookbook"
cookbooks = full_run_list.recipes.map {|recipe|
# sets the short cookbook name
original = recipe =~ /(.+)::[^:]*/ ? $1 : recipe
# load all the "depends" from metadata as well.
dependencies = cl[original].metadata.dependencies.keys
# return both
[original, dependencies]
}.flatten.uniq # flatten and uniq the array.
# do some bookkeeping to setup a run context, which is used to keep track of
# which dependencies have already been loaded.
events = Chef::EventDispatch::Dispatcher.new
cookbook_collection = Chef::CookbookCollection.new(cl)
run_context = Chef::RunContext.new(node, cookbook_collection, events)
# This loads the attributes for each cookbook into the node
compiler = Chef::RunContext::CookbookCompiler.new(run_context, full_run_list, events)
compiler.compile_libraries
compiler.compile_resource_definitions
compiler.compile_lwrps
compiler.compile_attributes
node
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment