summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel DeLeo <dan@opscode.com>2010-06-07 12:37:25 -0700
committerDaniel DeLeo <dan@opscode.com>2010-06-07 12:37:25 -0700
commit788105202f46fff9d3ecfeed0228e2cca9b6ac1d (patch)
treedddc6461991e5678a34462483c22ba9e612b1575
parenta3be6343c8363a161899fb34a67fe056210c8d3f (diff)
parentb6cb4042af0309d123fc61554e11908d8f16ebae (diff)
downloadchef-788105202f46fff9d3ecfeed0228e2cca9b6ac1d.tar.gz
Merge branch 'CHEF-1269'
-rw-r--r--chef-server-api/app/controllers/cookbooks.rb34
-rw-r--r--chef-server-api/config/router.rb2
-rw-r--r--chef-server-webui/app/controllers/application.rb36
-rw-r--r--chef-server-webui/app/controllers/cookbooks.rb7
-rw-r--r--chef-server-webui/app/controllers/nodes.rb6
-rw-r--r--chef-server-webui/app/views/cookbooks/show.html.haml32
-rwxr-xr-xchef-server-webui/bin/chef-server-webui11
-rw-r--r--chef-server-webui/public/stylesheets/chef.css32
-rw-r--r--chef/lib/chef/cookbook_version.rb81
-rw-r--r--chef/lib/chef/couchdb.rb3
-rw-r--r--chef/lib/chef/provider/remote_file.rb2
-rw-r--r--chef/lib/chef/provider/template.rb4
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