lib/vagabond/vagabondfile.rb in vagabond-0.2.8 vs lib/vagabond/vagabondfile.rb in vagabond-0.2.10
- old
+ new
@@ -1,22 +1,70 @@
+#encoding: utf-8
require 'chef/mash'
+require 'attribute_struct'
module Vagabond
class Vagabondfile
+ class << self
+ def describe(&block)
+ inst = AttributeStruct.new
+ if(block.arity != 1)
+ inst.instance_exec(&block)
+ else
+ inst.instance_exec(inst, &block)
+ end
+ inst
+ end
+ end
+
attr_reader :path
attr_reader :config
- DEFAULT_KEYS = %w(boxes mappings test_mappings spec_mappings local_chef_server)
- ALIASES = Mash.new(:boxes => :nodes, :nodes => :boxes)
-
+ DEFAULT_KEYS = %w(defaults definitions nodes clusters specs server callbacks)
+ ALIASES = Mash.new(
+ :boxes => :nodes,
+ :nodes => :boxes,
+ :local_chef_server => :server,
+ :server => :local_chef_server
+ )
+
def initialize(path=nil, *args)
path = discover_path(Dir.pwd) unless path
@path = path
load_configuration!(args.include?(:allow_missing))
end
+ def callbacks_for(name)
+ callbacks = self[:callbacks] || Mash.new
+ callbacks = Chef::Mixin::DeepMerge.merge(callbacks, for_node(name, :allow_missing)[:callbacks])
+ callbacks
+ end
+
+ def for_node(name, *args)
+ unless(self[:nodes][name])
+ return Mash.new if args.include?(:allow_missing)
+ raise VagabondError::InvalidName.new("Requested name is not a valid node name: #{name}")
+ end
+ if(self[:nodes][name][:definition])
+ base = for_definition(self[:nodes][name][:definition])
+ else
+ base = self[:defaults]
+ end
+ base = Chef::Mixin::DeepMerge.merge(base, self[:nodes][name])
+ base
+ end
+
+ def for_definition(name)
+ base = self[:defaults]
+ unless(self[:definitions][name])
+ raise VagabondError::InvalidName.new("Requested name is not a valid definition name: #{name}")
+ end
+ base = Chef::Mixin::DeepMerge.merge(base, self[:definitions][name])
+ base
+ end
+
def [](k)
if(DEFAULT_KEYS.include?(k.to_s))
@config[k] ||= Mash.new
end
aliased(k) || @config[k]
@@ -38,32 +86,48 @@
else
v.first
end
end
end
-
+
def load_configuration!(*args)
unless(args.empty?)
no_raise = args.first == true
force_store = args.include?(:force_store_path)
no_raise ||= force_store
end
if(@path && File.exists?(@path))
- @config = Mash.new(self.instance_eval(IO.read(@path), @path, 1))
+ thing = self.instance_eval(IO.read(@path), @path, 1)
+ if(thing.is_a?(AttributeStruct))
+ @config = Mash.new(thing._dump)
+ else
+ @config = Mash.new(thing)
+ end
end
if(!@config || force_store)
raise 'No Vagabondfile file found!' unless no_raise
generate_store_path
@config = Mash[*DEFAULT_KEYS.map{|k| [k, Mash.new]}.flatten]
end
end
+ def build_private_store
+ unless(@_private_store_path)
+ @_private_store_path = File.join('/tmp/vagabond-solos', directory.gsub(%r{[^0-9a-zA-Z]}, '-'), 'Vagabondfile')
+ @_private_store_path = File.expand_path(@_private_store_path.gsub('-', '/'))
+ FileUtils.mkdir_p(File.dirname(@_private_store_path))
+ File.dirname(@_private_store_path)
+ end
+ File.dirname(@_private_store_path)
+ end
+
def generate_store_path
@path ||= File.expand_path(File.join(Dir.pwd, 'Vagabondfile'))
- @store_path = File.join('/tmp/vagabond-solos', directory.gsub(%r{[^0-9a-zA-Z]}, '-'), 'Vagabondfile')
- @store_path = File.expand_path(@store_path.gsub('-', '/'))
- FileUtils.mkdir_p(File.dirname(@store_path))
+ unless(@store_path)
+ build_private_store
+ @store_path = @_private_store_path
+ end
File.dirname(@store_path)
end
def store_path
@store_path || @path
@@ -74,10 +138,10 @@
end
def store_directory
File.dirname(@store_path || @path)
end
-
+
def discover_path(path)
d_path = Dir.glob(File.join(path, 'Vagabondfile')).first
unless(d_path)
cut_path = path.split(File::SEPARATOR)
cut_path.pop