diff options
author | Adam Jacob <adam@hjksolutions.com> | 2008-07-28 17:57:49 -0700 |
---|---|---|
committer | Adam Jacob <adam@hjksolutions.com> | 2008-07-28 17:57:49 -0700 |
commit | 8d4c3be22c5dbb030e96bcbac12679de7a09b0fe (patch) | |
tree | 6fd5282dccb98e63ce8fae5277e7cadf8acc204a /lib | |
parent | d734c714c1e7598ddba40b47c26d10f002e06420 (diff) | |
download | chef-8d4c3be22c5dbb030e96bcbac12679de7a09b0fe.tar.gz |
Updating search tickets
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/client.rb | 34 | ||||
-rw-r--r-- | lib/chef/compile.rb | 14 | ||||
-rw-r--r-- | lib/chef/config.rb | 2 | ||||
-rw-r--r-- | lib/chef/cookbook.rb | 4 | ||||
-rw-r--r-- | lib/chef/cookbook_loader.rb | 14 | ||||
-rw-r--r-- | lib/chef/platform.rb | 1 | ||||
-rw-r--r-- | lib/chef/provider/template.rb | 69 | ||||
-rw-r--r-- | lib/chef/recipe.rb | 2 | ||||
-rw-r--r-- | lib/chef/resource.rb | 2 | ||||
-rw-r--r-- | lib/chef/resource/template.rb | 52 | ||||
-rw-r--r-- | lib/chef_server/controllers/cookbook_templates.rb | 29 | ||||
-rw-r--r-- | lib/chef_server/controllers/cookbooks.rb | 33 | ||||
-rw-r--r-- | lib/chef_server/init.rb | 8 | ||||
-rw-r--r-- | lib/chef_server/public/stylesheets/master.css | 145 | ||||
-rw-r--r-- | lib/chef_server/views/cookbooks/_attribute_file.html.haml | 2 | ||||
-rw-r--r-- | lib/chef_server/views/cookbooks/attribute_files.html.haml | 4 | ||||
-rw-r--r-- | lib/chef_server/views/cookbooks/index.html.haml | 7 | ||||
-rw-r--r-- | lib/chef_server/views/cookbooks/show.html.haml | 18 | ||||
-rw-r--r-- | lib/chef_server/views/layout/application.html.haml | 2 | ||||
-rw-r--r-- | lib/chef_server/views/nodes/_action.html.haml | 2 |
20 files changed, 437 insertions, 7 deletions
diff --git a/lib/chef/client.rb b/lib/chef/client.rb index 0ae7ef70e6..681260eee2 100644 --- a/lib/chef/client.rb +++ b/lib/chef/client.rb @@ -28,6 +28,7 @@ class Chef attr_accessor :node, :registration, :safe_name + # Creates a new Chef::Client. def initialize() @node = nil @safe_name = nil @@ -35,14 +36,27 @@ class Chef @rest = Chef::REST.new(Chef::Config[:registration_url]) end + # Do a full run for this Chef::Client. Calls: + # + # * build_node + # * register + # * authenticate + # * do_attribute_files + # * save_node + # * converge + # + # In that order. def run build_node register authenticate + do_attribute_files save_node converge end + # Builds a new node object for this client. Starts with querying for the FQDN of the current + # host, then merges in the facts from Facter. def build_node(node_name=nil) node_name ||= Facter["fqdn"].value ? Facter["fqdn"].value : Facter["hostname"].value @safe_name = node_name.gsub(/\./, '_') @@ -63,6 +77,10 @@ class Chef @node end + # If this node has been registered before, this method will fetch the current registration + # data. + # + # If it has not, we register it by calling create_registration. def register @registration = nil begin @@ -81,12 +99,15 @@ class Chef end end + # Generates a random secret, stores it in the Chef::Filestore with the "registration" key, + # and posts our nodes registration information to the server. def create_registration @secret = random_password(40) Chef::FileStore.store("registration", @safe_name, { "secret" => @secret }) @rest.post_rest("registrations", { :id => @safe_name, :password => @secret }) end + # Authenticates the node via OpenID. def authenticate response = @rest.post_rest('openid/consumer/start', { "openid_identifier" => "#{Chef::Config[:openid_url]}/openid/server/node/#{@safe_name}", @@ -98,10 +119,22 @@ class Chef ) end + # Gets all the attribute files included in all the cookbooks available on the server, + # and executes them. + def do_attribute_files + af_list = @rest.get_rest('cookbooks/_attribute_files') + af_list.each do |af| + @node.instance_eval(af["contents"], "#{af['cookbook']}/#{af['name']}", 1) + end + end + + # Updates the current node configuration on the server. def save_node @rest.put_rest("nodes/#{@safe_name}", @node) end + # Compiles the full list of recipes for the server, and passes it to an instance of + # Chef::Runner.converge. def converge results = @rest.get_rest("nodes/#{@safe_name}/compile") results["collection"].resources.each do |r| @@ -112,6 +145,7 @@ class Chef end protected + # Generates a random password of "len" length. def random_password(len) chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a newpass = "" diff --git a/lib/chef/compile.rb b/lib/chef/compile.rb index 800d89c6b0..83192d4f26 100644 --- a/lib/chef/compile.rb +++ b/lib/chef/compile.rb @@ -27,6 +27,8 @@ class Chef attr_accessor :node, :cookbook_loader, :collection, :definitions + # Creates a new Chef::Compile object. This object gets used by the Chef Server to generate + # a fully compiled recipe list for a node. def initialize() @node = nil @cookbook_loader = Chef::CookbookLoader.new @@ -34,6 +36,10 @@ class Chef @definitions = Hash.new end + # Looks up the node via the "name" argument, first from CouchDB, then by calling + # Chef::Node.find_file(name) + # + # The first step in compiling the catalog. Results available via the node accessor. def load_node(name) Chef::Log.debug("Loading Chef Node #{name} from CouchDB") @node = Chef::Node.load(name) @@ -42,6 +48,10 @@ class Chef @node end + # Load all the definitions, from every cookbook, so they are available when we process + # the recipes. + # + # Results available via the definitions accessor. def load_definitions() @cookbook_loader.each do |cookbook| hash = cookbook.load_definitions @@ -49,6 +59,10 @@ class Chef end end + # Load all the recipes specified in the node data (loaded via load_node, above.) + # + # The results are available via the collection accessor (which returns a Chef::ResourceCollection + # object) def load_recipes @node.recipes.each do |recipe| rmatch = recipe.match(/(.+?)::(.+)/) diff --git a/lib/chef/config.rb b/lib/chef/config.rb index 5ad4cdb2af..cf4faf727e 100644 --- a/lib/chef/config.rb +++ b/lib/chef/config.rb @@ -50,6 +50,8 @@ class Chef :couchdb_url => "http://localhost:5984", :registration_url => "http://localhost:4000", :openid_url => "http://localhost:4001", + :template_url => "http://localhost:4000", + :remotefile_url => "http://localhost:4000", :couchdb_database => "chef", :openid_store_path => "/var/chef/openid/db", :openid_cstore_path => "/var/chef/openid/cstore", diff --git a/lib/chef/cookbook.rb b/lib/chef/cookbook.rb index 75ab8f4ad6..b7c6506a99 100644 --- a/lib/chef/cookbook.rb +++ b/lib/chef/cookbook.rb @@ -21,13 +21,15 @@ class Chef class Cookbook - attr_accessor :attribute_files, :definition_files, :name + attr_accessor :attribute_files, :definition_files, :template_files, :remote_files, :name attr_reader :recipe_files def initialize(name) @name = name @attribute_files = Array.new @definition_files = Array.new + @template_files = Array.new + @remote_files = Array.new @recipe_files = Array.new @recipe_names = Hash.new @loaded_attributes = false diff --git a/lib/chef/cookbook_loader.rb b/lib/chef/cookbook_loader.rb index 95edecfab8..ee4e1891e3 100644 --- a/lib/chef/cookbook_loader.rb +++ b/lib/chef/cookbook_loader.rb @@ -42,6 +42,8 @@ class Chef :attribute_files => Array.new, :definition_files => Array.new, :recipe_files => Array.new, + :template_files => Array.new, + :remote_files => Array.new, } end ignore_regexes = load_ignore_file(File.join(cookbook, "ignore")) @@ -61,6 +63,16 @@ class Chef cookbook_settings[cookbook_name][:recipe_files], cookbook_settings[cookbook_name][:ignore_regexes] ) + load_files_unless_basename( + File.join(cookbook, "templates", "*.erb"), + cookbook_settings[cookbook_name][:template_files], + cookbook_settings[cookbook_name][:ignore_regexes] + ) + load_files_unless_basename( + File.join(cookbook, "files", "*"), + cookbook_settings[cookbook_name][:remote_files], + cookbook_settings[cookbook_name][:ignore_regexes] + ) end end cookbook_settings.each_key do |cookbook| @@ -68,6 +80,8 @@ class Chef @cookbook[cookbook].attribute_files = cookbook_settings[cookbook][:attribute_files] @cookbook[cookbook].definition_files = cookbook_settings[cookbook][:definition_files] @cookbook[cookbook].recipe_files = cookbook_settings[cookbook][:recipe_files] + @cookbook[cookbook].template_files = cookbook_settings[cookbook][:template_files] + @cookbook[cookbook].remote_files = cookbook_settings[cookbook][:remote_files] end end diff --git a/lib/chef/platform.rb b/lib/chef/platform.rb index 55e85ae354..4114d5960b 100644 --- a/lib/chef/platform.rb +++ b/lib/chef/platform.rb @@ -35,6 +35,7 @@ class Chef :file => Chef::Provider::File, :directory => Chef::Provider::Directory, :link => Chef::Provider::Link, + :template => Chef::Provider::Template, } } diff --git a/lib/chef/provider/template.rb b/lib/chef/provider/template.rb new file mode 100644 index 0000000000..47ffc810bf --- /dev/null +++ b/lib/chef/provider/template.rb @@ -0,0 +1,69 @@ +# +# 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__), "file") +require 'uri' + +class Chef + class Provider + class Template < Chef::Provider::File + + def action_create + r = Chef::REST.new(Chef::Config[:template_url]) + template_url = nil + if @new_resource.template =~ /^http/ + template_url = @new_resource.template + else + template_url = "cookbooks/#{@new_resource.cookbook_name}/templates/#{@new_resource.template}" + end + template = r.get_rest(template_url) + + + unless ::File.exists?(@new_resource.path) + Chef::Log.info("Creating #{@new_resource} at #{@new_resource.path}") + ::File.open(@new_resource.path, "w+") { |f| } + @new_resource.updated = true + end + set_owner if @new_resource.owner != nil + set_group if @new_resource.group != nil + set_mode if @new_resource.mode != nil + end + + def action_delete + if ::File.exists?(@new_resource.path) && ::File.writable?(@new_resource.path) + Chef::Log.info("Deleting #{@new_resource} at #{@new_resource.path}") + ::File.delete(@new_resource.path) + @new_resource.updated = true + else + raise "Cannot delete #{@new_resource} at #{@new_resource_path}!" + end + end + + def action_touch + action_create + time = Time.now + Chef::Log.info("Updating #{@new_resource} with new atime/mtime of #{time}") + ::File.utime(time, time, @new_resource.path) + @new_resource.updated = true + end + + end + end +end
\ No newline at end of file diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb index 47a194eda7..c161bbdae6 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -105,6 +105,8 @@ class Chef args << @collection args << @node resource = eval(rname).new(*args) + resource.cookbook_name = @cookbook_name + resource.recipe_name = @recipe_name resource.params = @params resource.instance_eval(&block) rescue Exception => e diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index e42b791b1d..40d711f969 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -28,7 +28,7 @@ class Chef include Chef::Mixin::CheckHelper include Chef::Mixin::ParamsValidate - attr_accessor :actions, :params, :provider, :updated, :allowed_actions, :collection + attr_accessor :actions, :params, :provider, :updated, :allowed_actions, :collection, :cookbook_name, :recipe_name attr_reader :resource_name, :source_line, :node def initialize(name, collection=nil, node=nil) diff --git a/lib/chef/resource/template.rb b/lib/chef/resource/template.rb new file mode 100644 index 0000000000..25df8c712d --- /dev/null +++ b/lib/chef/resource/template.rb @@ -0,0 +1,52 @@ +# +# 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 +# + + +class Chef + class Resource + class Template < Chef::Resource::File + + def initialize(name, collection=nil, node=nil) + @resource_name = :template + super(name, collection, node) + @action = "create" + @template = nil + @variables = Hash.new + end + + def template(file=nil) + set_or_return( + :template, + file, + :kind_of => [ String ] + ) + end + + def variables(args=nil) + set_or_return( + :vars, + args, + :kind_of => [ Hash ] + ) + end + + end + end +end
\ No newline at end of file diff --git a/lib/chef_server/controllers/cookbook_templates.rb b/lib/chef_server/controllers/cookbook_templates.rb new file mode 100644 index 0000000000..56338ac3f5 --- /dev/null +++ b/lib/chef_server/controllers/cookbook_templates.rb @@ -0,0 +1,29 @@ +class CookbookTemplates < Application + + provides :html, :json + + def load_cookbook(with_content=false) + @cl = Chef::CookbookLoader.new + @cookbook = @cl[params[:cookbook_id]] + raise NotFound unless @cookbook + @templates = Hash.new + @cookbook.template_files.each do |tf| + @templates[File.basename(tf)] = { + :file => tf, + } + @templates[File.basename(tf)][:contents] = File.read(tf) if with_content + end + end + + def index + load_cookbook(false) + display @templates + end + + def show + load_cookbook(true) + @template = @templates[params[:id]] + display @template + end + +end diff --git a/lib/chef_server/controllers/cookbooks.rb b/lib/chef_server/controllers/cookbooks.rb new file mode 100644 index 0000000000..d18b3506a2 --- /dev/null +++ b/lib/chef_server/controllers/cookbooks.rb @@ -0,0 +1,33 @@ +class Cookbooks < Application + + provides :html, :json + + def index + @cl = Chef::CookbookLoader.new + display @cl + end + + def show + @cl = Chef::CookbookLoader.new + @cookbook = @cl[params[:id]] + raise NotFound unless @cookbook + display @cookbook + end + + def attribute_files + cl = Chef::CookbookLoader.new + @attribute_files = Array.new + cl.each do |cookbook| + cookbook.attribute_files.each do |af| + @attribute_files << { + :cookbook => cookbook.name, + :name => File.basename(af), + :path => af, + :contents => File.read(af) + } + end + end + display @attribute_files + end + +end diff --git a/lib/chef_server/init.rb b/lib/chef_server/init.rb index ca1692b6cf..cf1d17e224 100644 --- a/lib/chef_server/init.rb +++ b/lib/chef_server/init.rb @@ -90,6 +90,7 @@ Merb.push_path(:helper, File.join(File.dirname(__FILE__), "helpers")) Merb.push_path(:public, File.join(File.dirname(__FILE__), "public")) require 'merb-haml' +require 'uv' # @@ -137,7 +138,12 @@ Merb::Router.prepare do |r| r.resources :nodes, :member => { :compile => :get } r.resources :search do |res| res.resources :entries, :controller => "search_entries" - end + end + + r.match("/cookbooks/_attribute_files").to(:controller => "cookbooks", :action => "attribute_files") + r.resources :cookbooks do |cookbooks| + cookbooks.resources :templates, :controller => "cookbook_templates" + end #r.resources :openid do |res| # res.resources :register, :controller => "openid_register" diff --git a/lib/chef_server/public/stylesheets/master.css b/lib/chef_server/public/stylesheets/master.css index 70580148a7..13bdffbe1b 100644 --- a/lib/chef_server/public/stylesheets/master.css +++ b/lib/chef_server/public/stylesheets/master.css @@ -1,4 +1,4 @@ -body { +/* body { font-family: Arial, Verdana, sans-serif; font-size: 12px; background-color: #fff; @@ -7,7 +7,7 @@ body { html { height: 100%; margin-bottom: 1px; -} +} #container { width: 80%; text-align: left; @@ -150,4 +150,143 @@ div.node { margin: 10px; padding: 5px; border: 1px solid #999; -}
\ No newline at end of file +} +*/ + +pre.twilight .DiffInserted { + background-color: #253B22; + color: #F8F8F8; +} +pre.twilight .DiffHeader { + background-color: #0E2231; + color: #F8F8F8; + font-style: italic; +} +pre.twilight .CssPropertyValue { + color: #F9EE98; +} +pre.twilight .CCCPreprocessorDirective { + color: #AFC4DB; +} +pre.twilight .Constant { + color: #CF6A4C; +} +pre.twilight .DiffChanged { + background-color: #4A410D; + color: #F8F8F8; +} +pre.twilight .EmbeddedSource { + background-color: #A3A6AD; +} +pre.twilight .Support { + color: #9B859D; +} +pre.twilight .MarkupList { + color: #F9EE98; +} +pre.twilight .CssConstructorArgument { + color: #8F9D6A; +} +pre.twilight .Storage { + color: #F9EE98; +} +pre.twilight .line-numbers { + background-color: #DDF0FF; + color: #000000; +} +pre.twilight .CssClass { + color: #9B703F; +} +pre.twilight .StringConstant { + color: #DDF2A4; +} +pre.twilight .CssAtRule { + color: #8693A5; +} +pre.twilight .MetaTagInline { + color: #E0C589; +} +pre.twilight .MarkupHeading { + color: #CF6A4C; +} +pre.twilight .CssTagName { + color: #CDA869; +} +pre.twilight .SupportConstant { + color: #CF6A4C; +} +pre.twilight .DiffDeleted { + background-color: #420E09; + color: #F8F8F8; +} +pre.twilight .CCCPreprocessorLine { + color: #8996A8; +} +pre.twilight .StringRegexpSpecial { + color: #CF7D34; +} +pre.twilight .EmbeddedSourceBright { + background-color: #9C9EA4; +} +pre.twilight .InvalidIllegal { + background-color: #241A24; + color: #F8F8F8; +} +pre.twilight .SupportFunction { + color: #DAD085; +} +pre.twilight .CssAdditionalConstants { + color: #CA7840; +} +pre.twilight .MetaTagAll { + color: #AC885B; +} +pre.twilight .StringRegexp { + color: #E9C062; +} +pre.twilight .StringEmbeddedSource { + color: #DAEFA3; +} +pre.twilight .EntityInheritedClass { + color: #9B5C2E; + font-style: italic; +} +pre.twilight .CssId { + color: #8B98AB; +} +pre.twilight .CssPseudoClass { + color: #8F9D6A; +} +pre.twilight .StringVariable { + color: #8A9A95; +} +pre.twilight .String { + color: #8F9D6A; +} +pre.twilight .Keyword { + color: #CDA869; +} +pre.twilight { + background-color: #141414; + color: #F8F8F8; +} +pre.twilight .CssPropertyName { + color: #C5AF75; +} +pre.twilight .DoctypeXmlProcessing { + color: #494949; +} +pre.twilight .InvalidDeprecated { + color: #D2A8A1; + font-style: italic; +} +pre.twilight .Variable { + color: #7587A6; +} +pre.twilight .Entity { + color: #9B703F; +} +pre.twilight .Comment { + color: #5F5A60; + font-style: italic; +} diff --git a/lib/chef_server/views/cookbooks/_attribute_file.html.haml b/lib/chef_server/views/cookbooks/_attribute_file.html.haml new file mode 100644 index 0000000000..cfe773f3d1 --- /dev/null +++ b/lib/chef_server/views/cookbooks/_attribute_file.html.haml @@ -0,0 +1,2 @@ +%h3= name += Uv.parse(contents, "xhtml", "ruby", true, "twilight")
\ No newline at end of file diff --git a/lib/chef_server/views/cookbooks/attribute_files.html.haml b/lib/chef_server/views/cookbooks/attribute_files.html.haml new file mode 100644 index 0000000000..56fdcf7bee --- /dev/null +++ b/lib/chef_server/views/cookbooks/attribute_files.html.haml @@ -0,0 +1,4 @@ +%h1 All Attribute Files +- @attribute_files.each do |af_hash| + %h2= "#{af_hash[:cookbook]}" + = partial(:attribute_file, :name => af_hash[:name], :contents => af_hash[:contents])
\ No newline at end of file diff --git a/lib/chef_server/views/cookbooks/index.html.haml b/lib/chef_server/views/cookbooks/index.html.haml new file mode 100644 index 0000000000..008f74765c --- /dev/null +++ b/lib/chef_server/views/cookbooks/index.html.haml @@ -0,0 +1,7 @@ +%h1 Cookbooks +- @cl.each do |cookbook| + .index + %table + %tr + %td + %a{ :href => url(:cookbook, { :id => cookbook.name }) }= cookbook.name diff --git a/lib/chef_server/views/cookbooks/show.html.haml b/lib/chef_server/views/cookbooks/show.html.haml new file mode 100644 index 0000000000..58175c298c --- /dev/null +++ b/lib/chef_server/views/cookbooks/show.html.haml @@ -0,0 +1,18 @@ +%h1= "Cookbook #{h @cookbook.name}" +.cookbook +- if @cookbook.attribute_files.length > 0 + - @cookbook.attribute_files.each do |af| + = partial(:attribute_file, :name => File.basename(af), :contents => File.read(af)) + +- if @cookbook.definition_files.length > 0 + - @cookbook.definition_files.each do |df| + %h2 Definition Files + %h3= File.basename(df) + = Uv.parse(File.read(df), "xhtml", "ruby", true, "twilight") + +- if @cookbook.recipe_files.length > 0 + - @cookbook.recipe_files.each do |rf| + %h2 Recipe Files + %h3= File.basename(rf) + = Uv.parse(File.read(rf), "xhtml", "ruby", true, "twilight") +
\ No newline at end of file diff --git a/lib/chef_server/views/layout/application.html.haml b/lib/chef_server/views/layout/application.html.haml index 4e4d235e78..8e84c09006 100644 --- a/lib/chef_server/views/layout/application.html.haml +++ b/lib/chef_server/views/layout/application.html.haml @@ -11,6 +11,8 @@ | %a{:href => url(:nodes) } Nodes | + %a{:href => url(:cookbooks) } Cookbooks + | %a{:href => url(:registrations)} Registrations - if session[:openid] | diff --git a/lib/chef_server/views/nodes/_action.html.haml b/lib/chef_server/views/nodes/_action.html.haml index a809a6d70c..8adb39338d 100644 --- a/lib/chef_server/views/nodes/_action.html.haml +++ b/lib/chef_server/views/nodes/_action.html.haml @@ -10,4 +10,4 @@ %td - resource_hash[rk].each do |resource| = partial(:resource, :resource => resource) -
\ No newline at end of file +
\ No newline at end of file |