summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAdam Jacob <adam@hjksolutions.com>2008-07-10 19:58:43 -0700
committerAdam Jacob <adam@hjksolutions.com>2008-07-10 19:58:43 -0700
commitd734c714c1e7598ddba40b47c26d10f002e06420 (patch)
treef45f547500cc1bcb10a1fad4bb5af5213736c2e9 /lib
parentc4e77b13c03d4d43b94b051cc819ff83a42f0ab5 (diff)
downloadchef-d734c714c1e7598ddba40b47c26d10f002e06420.tar.gz
Adding functional search support
Diffstat (limited to 'lib')
-rw-r--r--lib/chef/exceptions.rb25
-rw-r--r--lib/chef/node.rb19
-rw-r--r--lib/chef/recipe.rb6
-rw-r--r--lib/chef/resource.rb5
-rw-r--r--lib/chef/resource/directory.rb4
-rw-r--r--lib/chef/resource/file.rb4
-rw-r--r--lib/chef/resource/link.rb4
-rw-r--r--lib/chef/rest.rb1
-rw-r--r--lib/chef/search.rb34
-rw-r--r--lib/chef/search_index.rb72
-rw-r--r--lib/chef_server/controllers/search.rb53
-rw-r--r--lib/chef_server/controllers/search_entries.rb50
-rw-r--r--lib/chef_server/init.rb3
-rw-r--r--lib/chef_server/views/layout/application.html.haml2
-rw-r--r--lib/chef_server/views/search/_search_form.html.haml6
-rw-r--r--lib/chef_server/views/search/index.html.haml9
-rw-r--r--lib/chef_server/views/search/show.html.haml13
-rw-r--r--lib/chef_server/views/search_entries/index.html.haml9
-rw-r--r--lib/chef_server/views/search_entries/show.html.haml8
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