diff options
author | Adam Jacob <adam@hjksolutions.com> | 2008-07-10 19:58:43 -0700 |
---|---|---|
committer | Adam Jacob <adam@hjksolutions.com> | 2008-07-10 19:58:43 -0700 |
commit | d734c714c1e7598ddba40b47c26d10f002e06420 (patch) | |
tree | f45f547500cc1bcb10a1fad4bb5af5213736c2e9 /lib | |
parent | c4e77b13c03d4d43b94b051cc819ff83a42f0ab5 (diff) | |
download | chef-d734c714c1e7598ddba40b47c26d10f002e06420.tar.gz |
Adding functional search support
Diffstat (limited to 'lib')
-rw-r--r-- | lib/chef/exceptions.rb | 25 | ||||
-rw-r--r-- | lib/chef/node.rb | 19 | ||||
-rw-r--r-- | lib/chef/recipe.rb | 6 | ||||
-rw-r--r-- | lib/chef/resource.rb | 5 | ||||
-rw-r--r-- | lib/chef/resource/directory.rb | 4 | ||||
-rw-r--r-- | lib/chef/resource/file.rb | 4 | ||||
-rw-r--r-- | lib/chef/resource/link.rb | 4 | ||||
-rw-r--r-- | lib/chef/rest.rb | 1 | ||||
-rw-r--r-- | lib/chef/search.rb | 34 | ||||
-rw-r--r-- | lib/chef/search_index.rb | 72 | ||||
-rw-r--r-- | lib/chef_server/controllers/search.rb | 53 | ||||
-rw-r--r-- | lib/chef_server/controllers/search_entries.rb | 50 | ||||
-rw-r--r-- | lib/chef_server/init.rb | 3 | ||||
-rw-r--r-- | lib/chef_server/views/layout/application.html.haml | 2 | ||||
-rw-r--r-- | lib/chef_server/views/search/_search_form.html.haml | 6 | ||||
-rw-r--r-- | lib/chef_server/views/search/index.html.haml | 9 | ||||
-rw-r--r-- | lib/chef_server/views/search/show.html.haml | 13 | ||||
-rw-r--r-- | lib/chef_server/views/search_entries/index.html.haml | 9 | ||||
-rw-r--r-- | lib/chef_server/views/search_entries/show.html.haml | 8 |
19 files changed, 282 insertions, 45 deletions
diff --git a/lib/chef/exceptions.rb b/lib/chef/exceptions.rb new file mode 100644 index 0000000000..687b962b0e --- /dev/null +++ b/lib/chef/exceptions.rb @@ -0,0 +1,25 @@ +# +# 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 Exception + class SearchIndex < RuntimeError; end + end +end
\ No newline at end of file diff --git a/lib/chef/node.rb b/lib/chef/node.rb index d7350ac2fa..38b8ccc5d4 100644 --- a/lib/chef/node.rb +++ b/lib/chef/node.rb @@ -173,10 +173,21 @@ class Chef end end + def to_index + index_hash = { + :index_name => "node", + :id => "node_#{@name}", + :name => @name, + } + @attribute.each do |key, value| + index_hash[key] = value + end + index_hash[:recipe] = @recipe_list if @recipe_list.length > 0 + index_hash + end + # Serialize this object as a hash def to_json(*a) - attributes = Hash.new - recipes = Array.new result = { "name" => @name, 'json_class' => self.class.name, @@ -220,13 +231,13 @@ class Chef # Remove this node from the CouchDB def destroy - Chef::Queue.send_msg(:queue, :node_remove, self) + Chef::Queue.send_msg(:queue, :remove, self) @couchdb.delete("node", @name, @couchdb_rev) end # Save this node to the CouchDB def save - Chef::Queue.send_msg(:queue, :node_index, self) + Chef::Queue.send_msg(:queue, :index, self) results = @couchdb.store("node", @name, self) @couchdb_rev = results["rev"] end diff --git a/lib/chef/recipe.rb b/lib/chef/recipe.rb index d7d1435eb4..47a194eda7 100644 --- a/lib/chef/recipe.rb +++ b/lib/chef/recipe.rb @@ -70,6 +70,11 @@ class Chef def resources(*args) @collection.resources(*args) end + + def search(type, query, &block) + s = Chef::Search.new + s.search(type, query, &block) + end def method_missing(method_symbol, *args, &block) resource = nil @@ -98,6 +103,7 @@ class Chef end begin args << @collection + args << @node resource = eval(rname).new(*args) resource.params = @params resource.instance_eval(&block) diff --git a/lib/chef/resource.rb b/lib/chef/resource.rb index 74f27bcb82..e42b791b1d 100644 --- a/lib/chef/resource.rb +++ b/lib/chef/resource.rb @@ -29,15 +29,16 @@ class Chef include Chef::Mixin::ParamsValidate attr_accessor :actions, :params, :provider, :updated, :allowed_actions, :collection - attr_reader :resource_name, :source_line + attr_reader :resource_name, :source_line, :node - def initialize(name, collection=nil) + def initialize(name, collection=nil, node=nil) @name = name if collection @collection = collection else @collection = Chef::ResourceCollection.new() end + @node = node ? node : Chef::Node.new @noop = nil @before = nil @actions = Hash.new diff --git a/lib/chef/resource/directory.rb b/lib/chef/resource/directory.rb index 24e683bef9..1e13891fae 100644 --- a/lib/chef/resource/directory.rb +++ b/lib/chef/resource/directory.rb @@ -22,9 +22,9 @@ class Chef class Resource class Directory < Chef::Resource - def initialize(name, collection=nil) + def initialize(name, collection=nil, node=nil) @resource_name = :directory - super(name, collection) + super(name, collection, node) @path = name @action = :create @allowed_actions.push(:create, :delete) diff --git a/lib/chef/resource/file.rb b/lib/chef/resource/file.rb index ce8b2f35f9..f1cfa86f9a 100644 --- a/lib/chef/resource/file.rb +++ b/lib/chef/resource/file.rb @@ -23,9 +23,9 @@ class Chef class Resource class File < Chef::Resource - def initialize(name, collection=nil) + def initialize(name, collection=nil, node=nil) @resource_name = :file - super(name, collection) + super(name, collection, node) @path = name @backup = true @action = "create" diff --git a/lib/chef/resource/link.rb b/lib/chef/resource/link.rb index 743ef5ea73..5ec3b39b25 100644 --- a/lib/chef/resource/link.rb +++ b/lib/chef/resource/link.rb @@ -22,9 +22,9 @@ class Chef class Resource class Link < Chef::Resource - def initialize(name, collection=nil) + def initialize(name, collection=nil, node=nil) @resource_name = :link - super(name, collection) + super(name, collection, node) @source_file = name @action = :create @link_type = :symbolic diff --git a/lib/chef/rest.rb b/lib/chef/rest.rb index f71c203b3a..e4474fb9eb 100644 --- a/lib/chef/rest.rb +++ b/lib/chef/rest.rb @@ -106,6 +106,7 @@ class Chef else raise ArgumentError, "You must provide :GET, :PUT, :POST or :DELETE as the method" end + Chef::Log.debug("Sending HTTP Request via #{req.method} to #{req.path}") res = http.request(req) if res.kind_of?(Net::HTTPSuccess) if res['set-cookie'] diff --git a/lib/chef/search.rb b/lib/chef/search.rb index fe7e774e1b..dba38f79e9 100644 --- a/lib/chef/search.rb +++ b/lib/chef/search.rb @@ -24,6 +24,8 @@ require 'ferret' class Chef class Search + attr_reader :index + def initialize @index = Ferret::Index::Index.new(:path => Chef::Config[:search_index_path]) end @@ -31,18 +33,44 @@ class Chef def search(type, query, &block) search_query = build_search_query(type, query) start_time = Time.now + result = Array.new + if Kernel.block_given? - @index.search_each(search_query, &block) + result = @index.search_each(search_query, :limit => :all) do |id, score| + block.call(build_hash(@index.doc(id))) + end else - @index.search(search_query) + @index.search_each(search_query, :limit => :all) do |id, score| + result << build_hash(@index.doc(id)) + end end Chef::Log.debug("Search #{search_query} complete in #{Time.now - start_time} seconds") + result + end + + def list_indexes + indexes = Hash.new + @index.search_each("index_name:*", :limit => :all) do |id, score| + indexes[@index.doc(id)["index_name"]] = true + end + indexes.keys + end + + def has_index?(index) + list_indexes.detect { |i| i == index } end private def build_search_query(type, query) - "type:#{type} AND (#{query})" + "index_name:#{type} AND (#{query})" end + def build_hash(doc) + result = Hash.new + doc.fields.each do |f| + result[f] = doc[f] + end + result + end end end
\ No newline at end of file diff --git a/lib/chef/search_index.rb b/lib/chef/search_index.rb index 6af408b68c..d4d4f77042 100644 --- a/lib/chef/search_index.rb +++ b/lib/chef/search_index.rb @@ -24,6 +24,8 @@ require 'ferret' class Chef class SearchIndex + attr_reader :index + def initialize @index = Ferret::Index::Index.new( :path => Chef::Config[:search_index_path], @@ -31,40 +33,50 @@ class Chef ) 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) + def add(new_object) + index_hash = create_index_object(new_object) + Chef::Log.debug("Indexing #{index_hash[:index_name]} with #{index_hash.inspect}") + @index.add_document(index_hash) end + def create_index_object(new_object) + index_hash = nil + + if new_object.respond_to?(:to_index) + index_hash = new_object.to_index + elsif new_object.kind_of?(Hash) + index_hash = new_object + else + raise Chef::Exception::SearchIndex, "Cannot transform argument to a Hash!" + end + + unless index_hash.has_key?(:index_name) || index_hash.has_key?("index_name") + raise Chef::Exception::SearchIndex, "Cannot index without an index_name key: #{index_hash.inspect}" + end + + unless index_hash.has_key?(:id) || index_hash.has_key?("id") + raise Chef::Exception::SearchIndex, "Cannot index without an id key: #{index_hash.inspect}" + end + + index_hash.each do |k,v| + unless k.kind_of?(Symbol) + index_hash[k.to_sym] = v + index_hash.delete(k) + end + end + + index_hash + 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]}") + to_delete = create_index_object(index_obj) + Chef::Log.debug("Removing #{to_delete.inspect} from the #{to_delete[:index_name]} index") + @index.delete(to_delete[:id]) end - private - - def check_type(to_check) - type = nil - case to_check - when Chef::Node - type = "node" - end - end + def commit + @index.commit + 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 +end diff --git a/lib/chef_server/controllers/search.rb b/lib/chef_server/controllers/search.rb new file mode 100644 index 0000000000..17c0d553a4 --- /dev/null +++ b/lib/chef_server/controllers/search.rb @@ -0,0 +1,53 @@ +class Search < Application + + provides :html, :json + + def index + @s = Chef::Search.new + @search_indexes = @s.list_indexes + display @search_indexes + end + + def show + @s = Chef::Search.new + @results = nil + if params[:q] + @results = @s.search(params[:id], params[:q] == "" ? "?*" : params[:q]) + else + @results = @s.search(params[:id], "?*") + end + # Boy, this should move to the search function + if params[:a] + attributes = params[:a].split(",").collect { |a| a.to_sym } + unless attributes.length == 0 + @results = @results.collect do |r| + nr = Hash.new + nr[:index_name] = r[:index_name] + nr[:id] = r[:id] + attributes.each do |attrib| + if r.has_key?(attrib) + nr[attrib] = r[attrib] + end + end + nr + end + end + end + display @results + end + + def destroy + @s = Chef::Search.new + @entries = @s.search(params[:id], "?*") + @entries.each do |entry| + Chef::Queue.send_msg(:queue, :remove, entry) + end + @status = 202 + if content_type == :html + redirect url(:search) + else + display @entries + end + end + +end diff --git a/lib/chef_server/controllers/search_entries.rb b/lib/chef_server/controllers/search_entries.rb new file mode 100644 index 0000000000..ab79b57b3c --- /dev/null +++ b/lib/chef_server/controllers/search_entries.rb @@ -0,0 +1,50 @@ +class SearchEntries < Application + + provides :html, :json + + def index + @s = Chef::Search.new + @entries = @s.search(params[:search_id], "?*") + display @entries + end + + def show + @s = Chef::Search.new + @entry = @s.search(params[:search_id], "id:'#{params[:search_id]}_#{params[:id]}'").first + display @entry + end + + def create + @to_index = params + @to_index.delete(:controller) + @to_index["index_name"] = params[:search_id] + @to_index["id"] = "#{params[:search_id]}_#{params[:id]}" + @to_index.delete(:search_id) + Chef::Queue.send_msg(:queue, :index, @to_index) + if content_type == :html + redirect url(:search) + else + @status = 202 + display @to_index + end + end + + def update + create + end + + def destroy + @s = Chef::Search.new + @entries = @s.search(params[:id], "?*") + @entries.each do |entry| + Chef::Queue.send_msg(:queue, :remove, entry) + end + @status = 202 + if content_type == :html + redirect url(:search) + else + display @entries + end + end + +end diff --git a/lib/chef_server/init.rb b/lib/chef_server/init.rb index 136ad55e26..ca1692b6cf 100644 --- a/lib/chef_server/init.rb +++ b/lib/chef_server/init.rb @@ -135,6 +135,9 @@ Merb::Router.prepare do |r| r.resources :nodes r.resources :nodes, :member => { :compile => :get } + r.resources :search do |res| + res.resources :entries, :controller => "search_entries" + end #r.resources :openid do |res| # res.resources :register, :controller => "openid_register" diff --git a/lib/chef_server/views/layout/application.html.haml b/lib/chef_server/views/layout/application.html.haml index f04f299d2c..4e4d235e78 100644 --- a/lib/chef_server/views/layout/application.html.haml +++ b/lib/chef_server/views/layout/application.html.haml @@ -7,6 +7,8 @@ %link{:rel => "stylesheet", :href => "/stylesheets/master.css", :type => "text/css", :media => "screen", :charset => "utf-8" } %body .header + %a{:href => url(:search) } Search + | %a{:href => url(:nodes) } Nodes | %a{:href => url(:registrations)} Registrations diff --git a/lib/chef_server/views/search/_search_form.html.haml b/lib/chef_server/views/search/_search_form.html.haml new file mode 100644 index 0000000000..99303e1714 --- /dev/null +++ b/lib/chef_server/views/search/_search_form.html.haml @@ -0,0 +1,6 @@ +%form{ :method => "get", :action => url(:search, { :id => index_name }) } + Q: + %input{ :type => "text", :name => "q" } + A: + %input{ :type => "text", :name => "a" } + %input{ :type => "submit", :value => "Search #{index_name}" } diff --git a/lib/chef_server/views/search/index.html.haml b/lib/chef_server/views/search/index.html.haml new file mode 100644 index 0000000000..742c1110b0 --- /dev/null +++ b/lib/chef_server/views/search/index.html.haml @@ -0,0 +1,9 @@ +%h1 Search Indexes +- @search_indexes.each do |index| + .index + %table + %tr + %td + %a{ :href => url(:search, { :id => index }) }= index + %td + = partial(:search_form, :index_name => index) diff --git a/lib/chef_server/views/search/show.html.haml b/lib/chef_server/views/search/show.html.haml new file mode 100644 index 0000000000..5380a7477a --- /dev/null +++ b/lib/chef_server/views/search/show.html.haml @@ -0,0 +1,13 @@ +%h1 Search Results +.search + = partial(:search_form, :index_name => params[:id]) +.query + %h2= "Search Query was #{params[:q] ? params[:q] : '*'}" +- @results.each do |result| + .search_result + %h3= "#{h result[:index_name]} (#{h result[:id]})" + %table + - result.each do |k, v| + %tr.attr_group + %td.attr_name= k + %td.attr_value= v.kind_of?(Array) ? v.join(",") : v
\ No newline at end of file diff --git a/lib/chef_server/views/search_entries/index.html.haml b/lib/chef_server/views/search_entries/index.html.haml new file mode 100644 index 0000000000..77d140242e --- /dev/null +++ b/lib/chef_server/views/search_entries/index.html.haml @@ -0,0 +1,9 @@ +%h1= "Search Index #{h params[:search_id]}" +- @entries.each do |result| + .search_result + %h3= "#{h result[:index_name]} (#{h result[:id]})" + %table + - result.each do |k, v| + %tr.attr_group + %td.attr_name= k + %td.attr_value= v.kind_of?(Array) ? v.join(",") : v
\ No newline at end of file diff --git a/lib/chef_server/views/search_entries/show.html.haml b/lib/chef_server/views/search_entries/show.html.haml new file mode 100644 index 0000000000..7ca34b32ab --- /dev/null +++ b/lib/chef_server/views/search_entries/show.html.haml @@ -0,0 +1,8 @@ +%h1= "Search Index #{h params[:search_id]} entry #{h params[:id]}" +.search_result + %h3= "#{h @entry[:index_name]} (#{h @entry[:id]})" + %table + - @entry.each do |k, v| + %tr.attr_group + %td.attr_name= k + %td.attr_value= v.kind_of?(Array) ? v.join(",") : v
\ No newline at end of file |