diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef.rb | 2 | ||||
-rw-r--r-- | lib/chef/compile.rb | 1 | ||||
-rw-r--r-- | lib/chef/config.rb | 6 | ||||
-rw-r--r-- | lib/chef/cookbook.rb | 1 | ||||
-rw-r--r-- | lib/chef/cookbook_loader.rb | 6 | ||||
-rw-r--r-- | lib/chef/file_store.rb | 99 | ||||
-rw-r--r-- | lib/chef/mixin/params_validate.rb | 2 | ||||
-rw-r--r-- | lib/chef/node.rb | 32 | ||||
-rw-r--r-- | lib/chef/queue.rb | 109 | ||||
-rw-r--r-- | lib/chef/resource.rb | 26 | ||||
-rw-r--r-- | lib/chef/resource_collection.rb | 20 | ||||
-rw-r--r-- | lib/chef/search_index.rb | 70 |
12 files changed, 356 insertions, 18 deletions
diff --git a/lib/chef.rb b/lib/chef.rb index dc61e950a0..18e34e0ffb 100644 --- a/lib/chef.rb +++ b/lib/chef.rb @@ -19,7 +19,7 @@ require 'rubygems' -Dir[File.join(File.dirname(__FILE__), 'chef/**/*.rb')].sort.each { |lib| require lib } +Dir[File.join(File.dirname(__FILE__), 'chef/**/*.rb')].sort.each { |lib| require lib unless lib =~ /server/ } class Chef VERSION = '0.0.1' diff --git a/lib/chef/compile.rb b/lib/chef/compile.rb index e974852426..5cd200b098 100644 --- a/lib/chef/compile.rb +++ b/lib/chef/compile.rb @@ -35,6 +35,7 @@ class Chef end def load_node(name) + Chef::Log.debug("Loading Chef Node #{name}") @node = Chef::Node.find(name) end diff --git a/lib/chef/config.rb b/lib/chef/config.rb index 4793011fb4..807631aedb 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -39,6 +39,8 @@ class Chef @configuration = { :cookbook_path => [ "/etc/chef/site-cookbook", "/etc/chef/cookbook" ], :node_path => "/etc/chef/node", + :file_store_path => "/var/lib/chef/store", + :search_index_path => "/var/lib/chef/search_index", :log_level => :info, :log_location => STDOUT } @@ -61,6 +63,10 @@ class Chef def []=(config_option, value) @configuration[config_option.to_sym] = value end + + def has_key?(key) + @configuration.has_key?(key.to_sym) + end def method_missing(method_symbol, *args) if @configuration.has_key?(method_symbol) diff --git a/lib/chef/cookbook.rb b/lib/chef/cookbook.rb index 39013069ca..ed9b75a1d9 100644 --- a/lib/chef/cookbook.rb +++ b/lib/chef/cookbook.rb @@ -47,6 +47,7 @@ class Chef def load_definitions results = Hash.new @definition_files.each do |file| + Chef::Log.debug("Loading cookbook #{name}'s definitions from #{file}") resourcedef = Chef::ResourceDefinition.new resourcedef.from_file(file) results[resourcedef.name] = resourcedef diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb index 24ec01e574..95edecfab8 100644 --- a/lib/chef/cookbook_loader.rb +++ b/lib/chef/cookbook_loader.rb @@ -72,7 +72,11 @@ class Chef end def [](cookbook) - @cookbook[cookbook.to_sym] + if @cookbook.has_key?(cookbook.to_sym) + @cookbook[cookbook.to_sym] + else + raise ArgumentError, "Cannot find a cookbook named #{cookbook.to_s}" + end end def each diff --git a/lib/chef/file_store.rb b/lib/chef/file_store.rb new file mode 100644 index 0000000000..b834624090 --- /dev/null +++ b/lib/chef/file_store.rb @@ -0,0 +1,99 @@ +require File.join(File.dirname(__FILE__), "mixin", "params_validate") +require 'digest/sha2' +require 'json' + +class Chef + class FileStore + class << self + include Chef::Mixin::ParamsValidate + + def store(obj_type, name, object) + validate( + { + :obj_type => obj_type, + :name => name, + :object => object, + }, + { + :object => { :respond_to => :to_json }, + } + ) + + store_path = create_store_path(obj_type, name) + io = File.open(store_path, "w") + io.puts object.to_json + io.close + end + + def load(obj_type, name) + validate( + { + :obj_type => obj_type, + :name => name, + }, + { + :obj_type => { :kind_of => String }, + :name => { :kind_of => String }, + } + ) + store_path = create_store_path(obj_type, name) + raise "Cannot find #{store_path} for #{obj_type} #{name}!" unless File.exists?(store_path) + + object = JSON.parse(IO.read(store_path)) + end + + def delete(obj_type, name) + validate( + { + :obj_type => obj_type, + :name => name, + }, + { + :obj_type => { :kind_of => String }, + :name => { :kind_of => String }, + } + ) + store_path = create_store_path(obj_type, name) + if File.exists?(store_path) + File.unlink(store_path) + end + end + + def list(obj_type) + validate( + { + :obj_type => obj_type, + }, + { + :obj_type => { :kind_of => String } + } + ) + keys = Array.new + Dir[File.join(Chef::Config[:file_store_path], obj_type, '**', '*')].each do |f| + if File.file?(f) + keys << File.basename(f) + end + end + keys + end + + def create_store_path(obj_type, key) + shadigest = Digest::SHA2.hexdigest("#{obj_type}#{key}") + + file_path = [ + Chef::Config[:file_store_path], + obj_type, + shadigest[0,1], + shadigest[1,3] + ] + file_path.each_index do |i| + create_path = File.join(file_path[0, i + 1]) + Dir.mkdir(create_path) unless File.directory?(create_path) + end + file_path << key + File.join(*file_path) + end + + end + end +end
\ No newline at end of file diff --git a/lib/chef/mixin/params_validate.rb b/lib/chef/mixin/params_validate.rb index 741e932006..2f6e432024 100644 --- a/lib/chef/mixin/params_validate.rb +++ b/lib/chef/mixin/params_validate.rb @@ -155,7 +155,7 @@ class Chef def _pv_respond_to(opts, key, method_name_list) value = _pv_opts_lookup(opts, key) if value != nil - method_name_list.to_a.each do |method_name| + [ method_name_list ].flatten.each do |method_name| unless value.respond_to?(method_name) raise ArgumentError, "Option #{key} must have a #{method_name} method!" end diff --git a/lib/chef/node.rb b/lib/chef/node.rb index f8adf5983f..236bd2f9e1 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -165,21 +165,29 @@ class Chef end end - # Serialize this Node as json - def to_json() - result_object = { + # Serialize this object as a hash + def to_json(*a) + attributes = Hash.new + recipes = Array.new + { "name" => @name, - "type" => "Chef::Node", - "attributes" => Hash.new, - "recipes" => Array.new - } - each_attribute do |a,v| - result_object["attributes"][a] = v + 'json_class' => self.class.name, + "attributes" => @attribute, + "recipes" => @recipe_list, + }.to_json(*a) + end + + def self.json_create(o) + node = new + node.name(o["name"]) + o["attributes"].each do |k,v| + node[k] = v end - recipes.each do |r| - result_object["recipes"] << r + o["recipes"].each do |r| + node.recipes << r end - result_object.to_json + + node end # As a string diff --git a/lib/chef/queue.rb b/lib/chef/queue.rb new file mode 100644 index 0000000000..795670d79a --- /dev/null +++ b/lib/chef/queue.rb @@ -0,0 +1,109 @@ +# +# Author:: Adam Jacob (<adam@hjksolutions.com>) +# Copyright:: Copyright (c) 2008 HJK Solutions, LLC +# License:: GNU General Public License version 2 or later +# +# This program and entire repository is free software; you can +# redistribute it and/or modify it under the terms of the GNU +# General Public License as published by the Free Software +# Foundation; either version 2 of the License, or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +require File.join(File.dirname(__FILE__), "mixin", "params_validate") + +class Chef + class Queue + require 'stomp' + + @client = nil + + class << self + include Chef::Mixin::ParamsValidate + + def connect + @client = Stomp::Connection.open( + Chef::Config.has_key?(:queue_user) ? Chef::Config[:queue_user] : "", + Chef::Config.has_key?(:queue_password) ? Chef::Config[:queue_password] : "", + Chef::Config.has_key?(:queue_host) ? Chef::Config[:queue_host] : "localhost", + Chef::Config.has_key?(:queue_port) ? Chef::Config[:queue_port] : 61613, + false + ) + end + + def make_url(type, name) + validate( + { + :queue_type => type.to_sym, + :queue_name => name.to_sym, + }, + { + :queue_type => { + :equal_to => [ :topic, :queue ], + }, + :queue_name => { + :kind_of => [ String, Symbol ], + } + } + ) + queue_url = "/#{type}/chef/#{name}" + end + + def subscribe(type, name) + queue_url = make_url(type, name) + Chef::Log.debug("Subscribing to #{queue_url}") + connect if @client == nil + @client.subscribe(queue_url) + end + + def send_msg(type, name, msg) + validate( + { + :message => msg, + }, + { + :message => { + :respond_to => :to_json + } + } + ) + queue_url = make_url(type, name) + json = msg.to_json + connect if @client == nil + Chef::Log.debug("Sending to #{queue_url}: #{json}") + @client.send(queue_url, json) + end + + def receive_msg + connect if @client == nil + raw_msg = @client.receive() + Chef::Log.debug("Received Message from #{raw_msg.headers["destination"]} containing: #{raw_msg.body}") + msg = JSON.parse(raw_msg.body) + return msg, raw_msg.headers + end + + def poll_msg + connect if @client == nil + raw_msg = @client.poll() + if raw_msg + msg = JSON.parse(raw_msg.body) + else + nil + end + end + + def disconnect + raise ArgumentError, "You must call connect before you can disconnect!" unless @client + @client.disconnect + end + end + end +end
\ No newline at end of file diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index afff713ba6..705738fe59 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -28,8 +28,8 @@ class Chef include Chef::Mixin::CheckHelper include Chef::Mixin::ParamsValidate - attr_accessor :tag, :actions, :params, :provider, :updated, :allowed_actions - attr_reader :resource_name, :collection + attr_accessor :actions, :params, :provider, :updated, :allowed_actions + attr_reader :resource_name, :collection, :source_line def initialize(name, collection=nil) @name = name @@ -38,7 +38,6 @@ class Chef else @collection = Chef::ResourceCollection.new() end - @tag = [ name.to_s ] @noop = nil @before = nil @actions = Hash.new @@ -47,6 +46,7 @@ class Chef @allowed_actions = [ :nothing ] @action = :nothing @updated = false + @source_line = caller(4).shift.gsub!(/^(.+):(.+):.+$/, '\1 line \2') end def action(arg=nil) @@ -118,6 +118,26 @@ class Chef "#{@resource_name}[#{@name}]" end + # Serialize this object as a hash + def to_json(*a) + instance_vars = Hash.new + self.instance_variables.each do |iv| + instance_vars[iv] = self.instance_variable_get(iv) unless iv == "@collection" + end + { + 'json_class' => self.class.name, + 'instance_vars' => instance_vars + }.to_json(*a) + end + + def self.json_create(o) + resource = self.new(o["instance_vars"]["@name"]) + o["instance_vars"].each do |k,v| + resource.instance_variable_set(k.to_sym, v) + end + resource + end + private def check_timing(timing) diff --git a/lib/chef/resource_collection.rb b/lib/chef/resource_collection.rb index 5728fdd3e9..362781ea0e 100644 --- a/lib/chef/resource_collection.rb +++ b/lib/chef/resource_collection.rb @@ -111,6 +111,26 @@ class Chef flat_results = results.flatten flat_results.length == 1 ? flat_results[0] : flat_results end + + # Serialize this object as a hash + def to_json(*a) + instance_vars = Hash.new + self.instance_variables.each do |iv| + instance_vars[iv] = self.instance_variable_get(iv) + end + { + 'json_class' => self.class.name, + 'instance_vars' => instance_vars + }.to_json(*a) + end + + def self.json_create(o) + collection = self.new() + o["instance_vars"].each do |k,v| + collection.instance_variable_set(k.to_sym, v) + end + collection + end private diff --git a/lib/chef/search_index.rb b/lib/chef/search_index.rb new file mode 100644 index 0000000000..6af408b68c --- /dev/null +++ b/lib/chef/search_index.rb @@ -0,0 +1,70 @@ +# +# Author:: Adam Jacob (<adam@hjksolutions.com>) +# Copyright:: Copyright (c) 2008 HJK Solutions, LLC +# License:: GNU General Public License version 2 or later +# +# This program and entire repository is free software; you can +# redistribute it and/or modify it under the terms of the GNU +# General Public License as published by the Free Software +# Foundation; either version 2 of the License, or any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +require File.join(File.dirname(__FILE__), "mixin", "params_validate") +require 'ferret' + +class Chef + class SearchIndex + + def initialize + @index = Ferret::Index::Index.new( + :path => Chef::Config[:search_index_path], + :key => [ :id ] + ) + end + + def add(to_index) + type = check_type(to_index) + result = self.send("_prepare_#{type}", to_index) + Chef::Log.debug("Indexing #{type} with #{result.inspect}") + @index.add_document(result) + end + + def delete(index_obj) + type = check_type(index_obj) + to_index = self.send("_prepare_#{type}", index_obj) + Chef::Log.debug("Removing #{type} with #{to_index.inspect}") + @index.delete(:id => "#{to_index[:id]}") + end + + private + + def check_type(to_check) + type = nil + case to_check + when Chef::Node + type = "node" + end + end + + def _prepare_node(node) + result = Hash.new + result[:id] = "node-#{node.name}" + result[:type] = "node" + result[:name] = node.name + node.each_attribute do |k,v| + result[k.to_sym] = v + end + result[:recipe] = node.recipes + result + end + end +end
\ No newline at end of file |