Skip to content

Instantly share code, notes, and snippets.

@phrawzty
Created February 15, 2012 15:52
Show Gist options
  • Save phrawzty/1836833 to your computer and use it in GitHub Desktop.
Save phrawzty/1836833 to your computer and use it in GitHub Desktop.
Puppet plugin in the style of extlookup or yamlvar, but with precedence-based merging of results.
# USAGE: $variable = dilly(key, [order])
# Where order is an optional array of the order of precedence of the YAML files.
# If array $dillyorder exists in the scope, that will work too.
# Passing 'nodefault' in the order array will prevent default.yaml from being considered.
module Puppet::Parser::Functions
require 'yaml'
require 'deep_merge'
newfunction(:dilly, :type => :rvalue) do |args|
if args[1] and not args[1].is_a?(Array) then
raise Puppet::ParseError, "Dilly 'order' must be an array"
end
key = args[0]
order = []
# By default we only consider "default.yaml"; others must be specified somehow.
if args[1] then
order = args[1]
elsif lookupvar('dillyorder').is_a?(Array) then
order = lookupvar('dillyorder')
end
order.push('default') unless order.include?('nodefault')
order.delete('nodefault')
# Dilly YAMLs are stored in puppet/dillydata/
dillydata = File.join(File.dirname(Puppet.settings[:config]), 'dillydata')
raise Puppet::ParseError, "#{dillydata} is not a directory" unless File.directory?(dillydata)
result = {}
# Merge the YAMLs in order of precedence to produce the final result.
order.each do |x|
f = "#{dillydata}/#{x}.yaml"
current = {}
current = YAML.load_file(f) unless not File.exists?(f)
if current[key] then
result = result.deep_merge(key=>current[key])
end
end
raise Puppet::ParseError, "Could not find '#{key}' in dillydata" unless not result.empty?
# There should only be one key at the first level of the result hash,
# and that key will be the name of the requested variable, which is not
# interesting. :P
return result[result.keys[0]]
end
end
@phrawzty
Copy link
Author

So here's what would happen :

# dev.yaml

---
database:
  host: 'db-dev.company.int'
# default.yaml

---
database:
  host: 'db.company.int'
  port: 3306
# manifest.pp
$dillyorder = ['dev']
$database = dilly('database')
notice($database)

Results in :

notice: Scope(Class[manifest]): {"host"=>"db-dev.company.int", "port"=>3306}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment