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