diff options
author | Daniel DeLeo <dan@opscode.com> | 2010-06-07 12:37:25 -0700 |
---|---|---|
committer | Daniel DeLeo <dan@opscode.com> | 2010-06-07 12:37:25 -0700 |
commit | 788105202f46fff9d3ecfeed0228e2cca9b6ac1d (patch) | |
tree | dddc6461991e5678a34462483c22ba9e612b1575 | |
parent | a3be6343c8363a161899fb34a67fe056210c8d3f (diff) | |
parent | b6cb4042af0309d123fc61554e11908d8f16ebae (diff) | |
download | chef-788105202f46fff9d3ecfeed0228e2cca9b6ac1d.tar.gz |
Merge branch 'CHEF-1269'
-rw-r--r-- | chef-server-api/app/controllers/cookbooks.rb | 34 | ||||
-rw-r--r-- | chef-server-api/config/router.rb | 2 | ||||
-rw-r--r-- | chef-server-webui/app/controllers/application.rb | 36 | ||||
-rw-r--r-- | chef-server-webui/app/controllers/cookbooks.rb | 7 | ||||
-rw-r--r-- | chef-server-webui/app/controllers/nodes.rb | 6 | ||||
-rw-r--r-- | chef-server-webui/app/views/cookbooks/show.html.haml | 32 | ||||
-rwxr-xr-x | chef-server-webui/bin/chef-server-webui | 11 | ||||
-rw-r--r-- | chef-server-webui/public/stylesheets/chef.css | 32 | ||||
-rw-r--r-- | chef/lib/chef/cookbook_version.rb | 81 | ||||
-rw-r--r-- | chef/lib/chef/couchdb.rb | 3 | ||||
-rw-r--r-- | chef/lib/chef/provider/remote_file.rb | 2 | ||||
-rw-r--r-- | chef/lib/chef/provider/template.rb | 4 |
12 files changed, 171 insertions, 79 deletions
diff --git a/chef-server-api/app/controllers/cookbooks.rb b/chef-server-api/app/controllers/cookbooks.rb index 2088c809d4..50c83e0203 100644 --- a/chef-server-api/app/controllers/cookbooks.rb +++ b/chef-server-api/app/controllers/cookbooks.rb @@ -19,8 +19,8 @@ # limitations under the License. # -require 'chef' / 'cookbook_loader' -require 'chef' / 'cookbook' / 'metadata' +require 'chef/cookbook_loader' +require 'chef/cookbook/metadata' class Cookbooks < Application @@ -40,13 +40,33 @@ class Cookbooks < Application include Merb::TarballHelper def index - cookbook_list = Chef::CookbookVersion.cdb_list + cookbook_list = Chef::CookbookVersion.cdb_list_latest.keys.sort response = Hash.new - cookbook_list.each do |cookbook_name| - cookbook_name =~ /^(.+)-(\d+\.\d+\.\d+)$/ - response[$1] = absolute_url(:cookbook, :cookbook_name => $1) + cookbook_list.map! do |cookbook_name| + response[cookbook_name] = absolute_url(:cookbook, :cookbook_name => cookbook_name) end - display response + display response + end + + #FIXME: this is different from the rest of our API, but in a useful way... + def index_latest + cookbook_list = Chef::CookbookVersion.cdb_list_latest(true) + response = Hash.new + cookbook_list.map! do |cookbook_name, cookbook_version| + response[cookbook_name]={ :url=>absolute_url(:cookbook, :cookbook_name => cookbook_name, :cookbook_version => cookbook_version), + :cookbook_name => cookbook_name, :cookbook_version=>cookbook_version} + end + display response + end + + def index_recipes #FIXME: is this cool to do w/ access control on platform? + all_cookbooks = Array(Chef::CookbookVersion.cdb_list_latest(true)) + all_cookbooks.map! do |cookbook| + cookbook.manifest["recipes"].map { |r| "#{cookbook.name}::#{r['name']}" } + end + all_cookbooks.flatten! + all_cookbooks.sort! + display all_cookbooks end def show_versions diff --git a/chef-server-api/config/router.rb b/chef-server-api/config/router.rb index 6bcf8ca9cf..2fa72ee627 100644 --- a/chef-server-api/config/router.rb +++ b/chef-server-api/config/router.rb @@ -31,6 +31,8 @@ Merb::Router.prepare do :method => 'get' ).to(:controller => "cookbooks", :action => "index") + match("/cookbooks/_recipes", :method=>'get').to(:controller=>'cookbooks',:action=>'index_recipes') + match("/cookbooks/:cookbook_name/:cookbook_version", :method => 'put', :cookbook_name => /[\w\.]+/, diff --git a/chef-server-webui/app/controllers/application.rb b/chef-server-webui/app/controllers/application.rb index f35f9732fd..1d616d30a4 100644 --- a/chef-server-webui/app/controllers/application.rb +++ b/chef-server-webui/app/controllers/application.rb @@ -209,19 +209,15 @@ class Application < Merb::Controller count end - def syntax_highlight(code) - tokens = File.exists?(code) ? CodeRay.scan_file(code, :ruby) : CodeRay.scan(code, :ruby) - CodeRay.encode_tokens(tokens, :span) - end - - def get_file(uri) + def syntax_highlight(file_url) + Chef::Log.debug("fetching file from '#{file_url}' for highlighting") r = Chef::REST.new(Chef::Config[:chef_server_url]) - content = r.get_rest(uri) - a = Tempfile.new("cookbook_temp_file") - File.open(a.path, 'w'){|f| f.write(content)} - path = a.path - a.close - path + highlighted_file = nil + r.fetch(file_url) do |tempfile| + tokens = CodeRay.scan_file(tempfile.path, :ruby) + highlighted_file = CodeRay.encode_tokens(tokens, :span) + end + highlighted_file end def str_to_bool(str) @@ -240,21 +236,7 @@ class Application < Merb::Controller def get_available_recipes r = Chef::REST.new(Chef::Config[:chef_server_url]) - result = Array.new - cookbooks = r.get_rest("cookbooks") - cookbooks.keys.sort.each do |key| - cb = r.get_rest(cookbooks[key]) - cb["recipes"].each do |recipe| - recipe["name"] =~ /(.+)\.rb/ - r_name = $1; - if r_name == "default" - result << key - else - result << "#{key}::#{r_name}" - end - end - end - result + r.get_rest('cookbooks/_recipes') end def convert_newline_to_br(string) diff --git a/chef-server-webui/app/controllers/cookbooks.rb b/chef-server-webui/app/controllers/cookbooks.rb index 7fa04da587..8e1a85f150 100644 --- a/chef-server-webui/app/controllers/cookbooks.rb +++ b/chef-server-webui/app/controllers/cookbooks.rb @@ -18,11 +18,12 @@ # limitations under the License. # -require 'chef' / 'cookbook_loader' +require 'chef/cookbook_loader' +require 'chef/cookbook_version' class Cookbooks < Application - provides :html, :json + provides :html before :login_required before :params_helper @@ -58,6 +59,8 @@ class Cookbooks < Application # by default always show the largest version number (assuming largest means most recent) @other_versions = versions - [version] raise NotFound unless @cookbook + + @manifest = @cookbook.manifest display @cookbook rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") diff --git a/chef-server-webui/app/controllers/nodes.rb b/chef-server-webui/app/controllers/nodes.rb index 3e0d876386..c804e3ee94 100644 --- a/chef-server-webui/app/controllers/nodes.rb +++ b/chef-server-webui/app/controllers/nodes.rb @@ -18,7 +18,7 @@ # limitations under the License. # -require 'chef' / 'node' +require 'chef/node' class Nodes < Application @@ -29,7 +29,9 @@ class Nodes < Application def index begin node_hash = Chef::Node.list - @node_list = node_hash.keys.sort_by {|a,b| node_hash[a] <=> node_hash[b]} + require 'pp' + pp node_hash + @node_list = node_hash.keys.sort rescue => e Chef::Log.error("#{e}\n#{e.backtrace.join("\n")}") @_message = {:error => "Could not list nodes"} diff --git a/chef-server-webui/app/views/cookbooks/show.html.haml b/chef-server-webui/app/views/cookbooks/show.html.haml index c328aec95b..85779ad25a 100644 --- a/chef-server-webui/app/views/cookbooks/show.html.haml +++ b/chef-server-webui/app/views/cookbooks/show.html.haml @@ -3,7 +3,7 @@ .content %h2 .title - = "Cookbook: #{h @cookbook.manifest["name"]}" + = "Cookbook: #{h @manifest["name"]}" - unless @other_versions.nil? || @other_versions.empty? %select{:name => "choice", :onchange => "jump(this)", :size => "1"} %option{:value => ""} Other Versions @@ -12,38 +12,38 @@ %option{:value => url(:show_specific_version_cookbook, :cookbook_id => @cookbook_id, :cb_version => v)} "#{v}" .inner .accordion - - unless @cookbook.manifest["libraries"].empty? + - unless @manifest["libraries"].empty? %h2.head= link_to "Library Files", "JavaScript:void(0);" .files - - @cookbook.manifest["libraries"].each do |f| + - @manifest["libraries"].each do |f| .code %h4.head= link_to File.basename(f["name"]), "JavaScript:void(0);" - %pre.ruby= syntax_highlight(get_file(f["uri"])) - - unless @cookbook.manifest["attributes"].empty? + %pre.ruby= syntax_highlight(f["url"]) + - unless @manifest["attributes"].empty? %h2.head= link_to "Attribute Files", "JavaScript:void(0);" .files - - @cookbook.manifest["attributes"].each do |f| + - @manifest["attributes"].each do |f| .code %h4.head= link_to File.basename(f["name"]), "JavaScript:void(0);" - %pre.ruby= syntax_highlight(get_file(f["uri"])) - - unless @cookbook.manifest["definitions"].empty? + %pre.ruby= syntax_highlight(f["url"]) + - unless @manifest["definitions"].empty? %h2.head= link_to "Definition Files", "JavaScript:void(0);" .files - - @cookbook.manifest["definitions"].each do |f| + - @manifest["definitions"].each do |f| .code %h4.head= link_to File.basename(f["name"]), "JavaScript:void(0);" - %pre.ruby= syntax_highlight(get_file(f["uri"])) - - unless @cookbook.manifest["recipes"].empty? + %pre.ruby= syntax_highlight(f["url"]) + - unless @manifest["recipes"].empty? %h2.head= link_to "Recipe Files", "JavaScript:void(0);" .files - - @cookbook.manifest["recipes"].each do |f| + - @manifest["recipes"].each do |f| .code %h4.head= link_to File.basename(f["name"]), "JavaScript:void(0);" - %pre.ruby= syntax_highlight(get_file(f["uri"])) - - unless @cookbook.manifest["templates"].empty? + %pre.ruby= syntax_highlight(f["url"]) + - unless @manifest["templates"].empty? %h2.head= link_to "Template Files", "JavaScript:void(0);" .files - - @cookbook.manifest["templates"].each do |f| + - @manifest["templates"].each do |f| .code %h4.head= link_to File.basename(f["name"]), "JavaScript:void(0);" - %pre.ruby= syntax_highlight(get_file(f["uri"]))
\ No newline at end of file + %pre.ruby= syntax_highlight(f["url"])
\ No newline at end of file diff --git a/chef-server-webui/bin/chef-server-webui b/chef-server-webui/bin/chef-server-webui index eeeae35b7e..7c135b6575 100755 --- a/chef-server-webui/bin/chef-server-webui +++ b/chef-server-webui/bin/chef-server-webui @@ -27,21 +27,12 @@ require "rubygems" require "merb-core" # Load chef and chef-server-api from source rather than gem, if present -$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef/lib/chef')) +$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef/lib')) $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) require 'chef' require 'chef-server-webui' -# Ensure the chef gem we load is the same version as the chef server -unless defined?(Chef) - gem "chef", "=" + CHEF_SERVER_WEBUI_VERSION - require 'chef' -end - -#Dir.chdir File.join(File.dirname(__FILE__),"..") -#__DIR__ = Dir.getwd - if ARGV[0] && ARGV[0] =~ /^[^-]/ ARGV.push "-H" end diff --git a/chef-server-webui/public/stylesheets/chef.css b/chef-server-webui/public/stylesheets/chef.css index 52a06d056c..0fc6b70f41 100644 --- a/chef-server-webui/public/stylesheets/chef.css +++ b/chef-server-webui/public/stylesheets/chef.css @@ -51,22 +51,27 @@ dl dt { font-weight: bold; } div.sortable { height: 200px; - width: 225px; + width: 350px; margin-right: 10px; border: 1px solid black; - overflow: scroll; + overflow-y: scroll; background: #777777; } div.sortable.run-list { height: 430px; - width: 225px; + width: 350px; margin-right: 10px; border: 1px solid black; - overflow: scroll; + overflow-y: scroll; background: #777777; } +div.run-list ul.ui-sortable#for_node, div.run-list ul.ui-sortable#for_role { + min-height: 420px; +} + + div.clear { clear: left; } @@ -125,9 +130,24 @@ div.editor { border: 1px solid black; } -#node_available_roles, #node_available_recipes, #for_node, #for_role, #available_recipes { list-style-type: none; margin: 0; padding: 0; float: left; margin-right: 10px; background: #eee; padding: 5px; width: 200px;} +#node_available_roles, #node_available_recipes, #for_node, #for_role, #available_recipes { + list-style-type: none; + margin: 0; + padding: 0; + float: left; + margin-right: 10px; + background: #eee; + padding: 5px; + width: 325px; + min-height:200px; +} -#node_available_roles li, #node_available_recipes li, #for_node li, #for_role li, #available_recipes li { margin: 0 5px 5px 5px; padding: 5px; width: 175px; } +#node_available_roles li, #node_available_recipes li, #for_node li, #for_role li, #available_recipes li { + margin: 0 5px 5px 5px; + padding: 5px; + width: 310px; + overflow:hidden; +} #sidebar_block { display: none; diff --git a/chef/lib/chef/cookbook_version.rb b/chef/lib/chef/cookbook_version.rb index cc498da77e..420b50e103 100644 --- a/chef/lib/chef/cookbook_version.rb +++ b/chef/lib/chef/cookbook_version.rb @@ -123,6 +123,49 @@ class Chef } @ }, + "all_latest_version_by_id" => { + "map" => %q@ + function(doc) { + if (doc.chef_type == "cookbook_version") { + emit(doc.cookbook_name, doc.version); + } + } + @, + "reduce" => %q@ + function(keys, values, rereduce) { + var result = null; + + for (var idx in values) { + var value = values[idx]; + + if (idx == 0) { + result = value; + continue; + } + + var valueParts = value[1].split('.').map(function(v) { return parseInt(v); }); + var resultParts = result[1].split('.').map(function(v) { return parseInt(v); }); + + if (valueParts[0] != resultParts[0]) { + if (valueParts[0] > resultParts[0]) { + result = value; + } + } + else if (valueParts[1] != resultParts[1]) { + if (valueParts[1] > resultParts[1]) { + result = value; + } + } + else if (valueParts[2] != resultParts[2]) { + if (valueParts[2] > resultParts[2]) { + result = value; + } + } + } + return keys[idx][1]; + } + @ + }, } } @@ -595,10 +638,14 @@ class Chef ## # REST API ## - def chef_server_rest + def self.chef_server_rest Chef::REST.new(Chef::Config[:chef_server_url]) end + def chef_server_rest + self.class.chef_server_rest + end + def save chef_server_rest.put_rest("cookbooks/#{name}/#{version}", self) self @@ -612,7 +659,16 @@ class Chef def self.load(name, version="_latest") version = "_latest" if version == "latest" - Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("cookbooks/#{name}/#{version}") + chef_server_rest.get_rest("cookbooks/#{name}/#{version}") + end + + def self.list + chef_server_rest.get_rest('cookbooks') + end + + # Get the newest version of all cookbooks + def self.latest_cookbooks + chef_server_rest.get_rest('cookbooks/_latest') end ## @@ -620,7 +676,7 @@ class Chef ## def self.cdb_by_name(cookbook_name, couchdb=nil) - cdb = couchdb || Chef::CouchDB.new + cdb = (couchdb || Chef::CouchDB.new) options = { :startkey => cookbook_name, :endkey => cookbook_name } rs = cdb.get_view("cookbooks", "all_with_version", options) rs["rows"].inject({}) { |memo, row| memo.has_key?(row["key"]) ? memo[row["key"]] << row["value"] : memo[row["key"]] = [ row["value"] ]; memo } @@ -629,7 +685,24 @@ class Chef def self.create_design_document(couchdb=nil) (couchdb || Chef::CouchDB.new).create_design_document("cookbooks", DESIGN_DOCUMENT) end - + + def self.cdb_list_latest(inflate=false, couchdb=nil) + couchdb ||= Chef::CouchDB.new + if inflate + doc_ids = cdb_list_latest_ids + couchdb.bulk_get(doc_ids) + else + results = couchdb.get_view("cookbooks", "all_latest_version", :group=>true)["rows"] + results.inject({}) { |mapped, row| mapped[row["key"]] = row["value"]; mapped} + end + end + + def self.cdb_list_latest_ids(inflate=false, couchdb=nil) + couchdb ||= Chef::CouchDB.new + results = couchdb.get_view("cookbooks", "all_latest_version_by_id", :group=>true)["rows"] + results.map { |name_and_id| name_and_id["value"]} + end + def self.cdb_list(inflate=false, couchdb=nil) rs = (couchdb || Chef::CouchDB.new).list("cookbooks", inflate) lookup = (inflate ? "value" : "key") diff --git a/chef/lib/chef/couchdb.rb b/chef/lib/chef/couchdb.rb index 3ae95cac1b..61f1c8b312 100644 --- a/chef/lib/chef/couchdb.rb +++ b/chef/lib/chef/couchdb.rb @@ -220,8 +220,7 @@ class Chef def get_view(design, view, options={}) view_string = view_uri(design, view) view_string << "?" if options.length != 0 - first = true; - options.each { |k,v| view_string << "#{first ? '' : '&'}#{k}=#{URI.escape(v.to_json)}"; first = false } + view_string << options.map { |k,v| "#{k}=#{URI.escape(v.to_json)}"}.join('&') @rest.get_rest(view_string) end diff --git a/chef/lib/chef/provider/remote_file.rb b/chef/lib/chef/provider/remote_file.rb index 0a74555990..29c485a8f4 100644 --- a/chef/lib/chef/provider/remote_file.rb +++ b/chef/lib/chef/provider/remote_file.rb @@ -31,7 +31,7 @@ class Chef def load_current_resource super - @current_resource.checksum(checksum(@current_resource.path)) + @current_resource.checksum(checksum(@current_resource.path)) if ::File.exist?(@current_resource.path) end def action_create diff --git a/chef/lib/chef/provider/template.rb b/chef/lib/chef/provider/template.rb index 7dd5971f3e..256d56f8fc 100644 --- a/chef/lib/chef/provider/template.rb +++ b/chef/lib/chef/provider/template.rb @@ -33,13 +33,13 @@ class Chef class Template < Chef::Provider::File - #include Chef::Mixin::Checksum + include Chef::Mixin::Checksum include Chef::Mixin::Template #include Chef::Mixin::FindPreferredFile def load_current_resource super - @current_resource.checksum(checksum(@current_resource.path)) + @current_resource.checksum(checksum(@current_resource.path)) if ::File.exist?(@current_resource.path) end def action_create |