chef-solr 0.9.18 → 0.10.0.beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/{chef-solr-indexer → chef-solr-installer} +4 -7
- data/lib/chef/solr.rb +1 -234
- data/lib/chef/solr/application/solr.rb +71 -43
- data/lib/chef/solr/solr_installer.rb +385 -0
- data/lib/chef/solr/version.rb +7 -1
- data/solr/solr-home.tar.gz +0 -0
- data/solr/solr-jetty.tar.gz +0 -0
- metadata +11 -41
- data/lib/chef/solr/application/indexer.rb +0 -148
- data/lib/chef/solr/index.rb +0 -103
- data/lib/chef/solr/index_queue_consumer.rb +0 -82
- data/lib/chef/solr/query.rb +0 -99
- data/spec/chef/solr/index_spec.rb +0 -187
- data/spec/chef/solr/query_spec.rb +0 -14
- data/spec/chef/solr_spec.rb +0 -301
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +0 -14
    
        data/lib/chef/solr/query.rb
    DELETED
    
    | @@ -1,99 +0,0 @@ | |
| 1 | 
            -
            #
         | 
| 2 | 
            -
            # Author:: Adam Jacob (<adam@opscode.com>)
         | 
| 3 | 
            -
            # Author:: Nuo Yan (<nuo@opscode.com>)
         | 
| 4 | 
            -
            # Copyright:: Copyright (c) 2010 Opscode, Inc.
         | 
| 5 | 
            -
            # License:: Apache License, Version 2.0
         | 
| 6 | 
            -
            #
         | 
| 7 | 
            -
            # Licensed under the Apache License, Version 2.0 (the "License");
         | 
| 8 | 
            -
            # you may not use this file except in compliance with the License.
         | 
| 9 | 
            -
            # You may obtain a copy of the License at
         | 
| 10 | 
            -
            # 
         | 
| 11 | 
            -
            #     http://www.apache.org/licenses/LICENSE-2.0
         | 
| 12 | 
            -
            # 
         | 
| 13 | 
            -
            # Unless required by applicable law or agreed to in writing, software
         | 
| 14 | 
            -
            # distributed under the License is distributed on an "AS IS" BASIS,
         | 
| 15 | 
            -
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 16 | 
            -
            # See the License for the specific language governing permissions and
         | 
| 17 | 
            -
            # limitations under the License.
         | 
| 18 | 
            -
            #
         | 
| 19 | 
            -
             | 
| 20 | 
            -
            require 'chef/couchdb'
         | 
| 21 | 
            -
            require 'chef/node'
         | 
| 22 | 
            -
            require 'chef/role'
         | 
| 23 | 
            -
            require 'chef/data_bag'
         | 
| 24 | 
            -
            require 'chef/data_bag_item'
         | 
| 25 | 
            -
            require 'chef/solr'
         | 
| 26 | 
            -
            require 'chef/log'
         | 
| 27 | 
            -
            require 'chef/config'
         | 
| 28 | 
            -
             | 
| 29 | 
            -
            class Chef
         | 
| 30 | 
            -
              class Solr
         | 
| 31 | 
            -
                class Query < Chef::Solr
         | 
| 32 | 
            -
                  
         | 
| 33 | 
            -
                  # Create a new Query object - takes the solr_url and optional
         | 
| 34 | 
            -
                  # Chef::CouchDB object to inflate objects into.
         | 
| 35 | 
            -
                  def initialize(solr_url=Chef::Config[:solr_url], couchdb = nil)
         | 
| 36 | 
            -
                    super(solr_url)
         | 
| 37 | 
            -
                    if couchdb.nil?
         | 
| 38 | 
            -
                      @database = Chef::Config[:couchdb_database]
         | 
| 39 | 
            -
                      @couchdb = Chef::CouchDB.new(nil, Chef::Config[:couchdb_database])
         | 
| 40 | 
            -
                    else
         | 
| 41 | 
            -
                      unless couchdb.kind_of?(Chef::CouchDB)
         | 
| 42 | 
            -
                        Chef::Log.warn("Passing the database name to Chef::Solr::Query initialization is deprecated. Please pass in the Chef::CouchDB object instead.")
         | 
| 43 | 
            -
                        @database = couchdb
         | 
| 44 | 
            -
                        @couchdb = Chef::CouchDB.new(nil, couchdb)
         | 
| 45 | 
            -
                      else
         | 
| 46 | 
            -
                        @database = couchdb.couchdb_database
         | 
| 47 | 
            -
                        @couchdb = couchdb
         | 
| 48 | 
            -
                      end
         | 
| 49 | 
            -
                    end 
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  # A raw query against CouchDB - takes the type of object to find, and raw
         | 
| 53 | 
            -
                  # Solr options.
         | 
| 54 | 
            -
                  #
         | 
| 55 | 
            -
                  # You'll wind up having to page things yourself.
         | 
| 56 | 
            -
                  def raw(type, options={})
         | 
| 57 | 
            -
                    qtype = case type
         | 
| 58 | 
            -
                            when "role",:role,"node",:node,"client",:client
         | 
| 59 | 
            -
                              type
         | 
| 60 | 
            -
                            else
         | 
| 61 | 
            -
                              [ "data_bag_item", type ]
         | 
| 62 | 
            -
                            end
         | 
| 63 | 
            -
                    results = solr_select(@database, qtype, options)
         | 
| 64 | 
            -
                    Chef::Log.debug("Searching #{@database} #{qtype.inspect} for #{options.inspect} with results:\n#{results.inspect}") 
         | 
| 65 | 
            -
                    objects = if results["response"]["docs"].length > 0
         | 
| 66 | 
            -
                                bulk_objects = @couchdb.bulk_get( results["response"]["docs"].collect { |d| d["X_CHEF_id_CHEF_X"] } )
         | 
| 67 | 
            -
                                Chef::Log.debug("bulk get of objects: #{bulk_objects.inspect}")
         | 
| 68 | 
            -
                                bulk_objects
         | 
| 69 | 
            -
                              else
         | 
| 70 | 
            -
                                []
         | 
| 71 | 
            -
                              end
         | 
| 72 | 
            -
                    [ objects, results["response"]["start"], results["response"]["numFound"], results["responseHeader"] ] 
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  # Search Solr for objects of a given type, for a given query. If you give
         | 
| 76 | 
            -
                  # it a block, it will handle the paging for you dynamically.
         | 
| 77 | 
            -
                  def search(type, query="*:*", sort='X_CHEF_id_CHEF_X asc', start=0, rows=1000, &block)
         | 
| 78 | 
            -
                    options = {
         | 
| 79 | 
            -
                      :q => query,
         | 
| 80 | 
            -
                      :start => start,
         | 
| 81 | 
            -
                      :rows => rows 
         | 
| 82 | 
            -
                    }
         | 
| 83 | 
            -
                    options[:sort] = sort if sort && ! sort.empty?
         | 
| 84 | 
            -
                    objects, start, total, response_header = raw(type, options)
         | 
| 85 | 
            -
                    if block
         | 
| 86 | 
            -
                      objects.each { |o| block.call(o) }
         | 
| 87 | 
            -
                      unless (start + objects.length) >= total
         | 
| 88 | 
            -
                        nstart = start + rows
         | 
| 89 | 
            -
                        search(type, query, sort, nstart, rows, &block)
         | 
| 90 | 
            -
                      end
         | 
| 91 | 
            -
                      true
         | 
| 92 | 
            -
                    else
         | 
| 93 | 
            -
                      [ objects, start, total ]
         | 
| 94 | 
            -
                    end
         | 
| 95 | 
            -
                  end
         | 
| 96 | 
            -
                end
         | 
| 97 | 
            -
              end
         | 
| 98 | 
            -
            end
         | 
| 99 | 
            -
             | 
| @@ -1,187 +0,0 @@ | |
| 1 | 
            -
            require File.expand_path(File.join("#{File.dirname(__FILE__)}", '..', '..', 'spec_helper'))
         | 
| 2 | 
            -
             | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
            describe Chef::Solr::Index do
         | 
| 6 | 
            -
              before(:each) do
         | 
| 7 | 
            -
                @index = Chef::Solr::Index.new
         | 
| 8 | 
            -
              end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
              describe "initialize" do
         | 
| 11 | 
            -
                it "should return a Chef::Solr::Index" do
         | 
| 12 | 
            -
                  @index.should be_a_kind_of(Chef::Solr::Index)
         | 
| 13 | 
            -
                end
         | 
| 14 | 
            -
              end
         | 
| 15 | 
            -
             | 
| 16 | 
            -
              describe "add" do
         | 
| 17 | 
            -
                before(:each) do
         | 
| 18 | 
            -
                  @index.stub!(:solr_add).and_return(true)
         | 
| 19 | 
            -
                  @index.stub!(:solr_commit).and_return(true)
         | 
| 20 | 
            -
                end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                it "should take an object that responds to .keys as it's argument" do
         | 
| 23 | 
            -
                  lambda { @index.add(1, "chef_opscode", "node", { :one => :two }) }.should_not raise_error(ArgumentError)
         | 
| 24 | 
            -
                  lambda { @index.add(1, "chef_opscode", "node", "SOUP") }.should raise_error(ArgumentError)
         | 
| 25 | 
            -
                  lambda { @index.add(2, "chef_opscode", "node", mock("Foo", :keys => true)) }.should_not raise_error(ArgumentError)
         | 
| 26 | 
            -
                end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                it "should index the object as a single flat hash, with only strings or arrays as values" do
         | 
| 29 | 
            -
                  validate = {
         | 
| 30 | 
            -
                    "X_CHEF_id_CHEF_X" => [1],
         | 
| 31 | 
            -
                    "X_CHEF_database_CHEF_X" => ["monkey"],
         | 
| 32 | 
            -
                    "X_CHEF_type_CHEF_X" => ["snakes"],
         | 
| 33 | 
            -
                    "foo" => ["bar"],
         | 
| 34 | 
            -
                    "battles" => [ "often", "but", "for" ],
         | 
| 35 | 
            -
                    "battles_often" => ["sings like smurfs"],
         | 
| 36 | 
            -
                    "often" => ["sings like smurfs"],
         | 
| 37 | 
            -
                    "battles_but" => ["still has good records"],
         | 
| 38 | 
            -
                    "but" => ["still has good records"],
         | 
| 39 | 
            -
                    "battles_for" => [ "all", "of", "that" ],
         | 
| 40 | 
            -
                    "for" => [ "all", "of", "that" ],
         | 
| 41 | 
            -
                    "snoopy" => ["sits-in-a-barn"],
         | 
| 42 | 
            -
                    "battles_X" => [ "sings like smurfs", "still has good records", "all", "of", "that" ],
         | 
| 43 | 
            -
                    "X_often" =>[ "sings like smurfs"],
         | 
| 44 | 
            -
                    "X_but" => ["still has good records"],
         | 
| 45 | 
            -
                    "X_for" => [ "all", "of", "that" ]
         | 
| 46 | 
            -
                  }
         | 
| 47 | 
            -
                  to_index = @index.add(1, "monkey", "snakes", {
         | 
| 48 | 
            -
                    "foo" => :bar,
         | 
| 49 | 
            -
                    "battles" => {
         | 
| 50 | 
            -
                      "often" => "sings like smurfs",
         | 
| 51 | 
            -
                      "but" => "still has good records",
         | 
| 52 | 
            -
                      "for" => [ "all", "of", "that" ]
         | 
| 53 | 
            -
                    },
         | 
| 54 | 
            -
                    "snoopy" => "sits-in-a-barn"
         | 
| 55 | 
            -
                  })
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                  validate.each do |k, v|
         | 
| 58 | 
            -
                    if v.kind_of?(Array)
         | 
| 59 | 
            -
                      to_index[k].sort.should == v.sort
         | 
| 60 | 
            -
                    else
         | 
| 61 | 
            -
                      to_index[k].should == v
         | 
| 62 | 
            -
                    end
         | 
| 63 | 
            -
                  end
         | 
| 64 | 
            -
                end
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                it "should send the document to solr" do
         | 
| 67 | 
            -
                  @index.should_receive(:solr_add)
         | 
| 68 | 
            -
                  @index.add(1, "monkey", "snakes", { "foo" => "bar" })
         | 
| 69 | 
            -
                end
         | 
| 70 | 
            -
              end
         | 
| 71 | 
            -
             | 
| 72 | 
            -
              describe "delete" do
         | 
| 73 | 
            -
                it "should delete by id" do
         | 
| 74 | 
            -
                  @index.should_receive(:solr_delete_by_id).with(1)
         | 
| 75 | 
            -
                  @index.delete(1)
         | 
| 76 | 
            -
                end
         | 
| 77 | 
            -
              end
         | 
| 78 | 
            -
             | 
| 79 | 
            -
              describe "delete_by_query" do
         | 
| 80 | 
            -
                it "should delete by query" do
         | 
| 81 | 
            -
                  @index.should_receive(:solr_delete_by_query).with("foo:bar")
         | 
| 82 | 
            -
                  @index.delete_by_query("foo:bar")
         | 
| 83 | 
            -
                end
         | 
| 84 | 
            -
              end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
              describe "flatten_and_expand" do
         | 
| 87 | 
            -
                before(:each) do
         | 
| 88 | 
            -
                  @fields = Hash.new
         | 
| 89 | 
            -
                end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
                it "should set a value for the parent as key, with the key as the value" do
         | 
| 92 | 
            -
                  @fields = @index.flatten_and_expand("omerta" => { "one" => "woot" })
         | 
| 93 | 
            -
                  @fields["omerta"].should == ["one"]
         | 
| 94 | 
            -
                end
         | 
| 95 | 
            -
             | 
| 96 | 
            -
                it "should call itself recursively for values that are hashes" do
         | 
| 97 | 
            -
                  @fields = @index.flatten_and_expand({ "one" => { "two" => "three", "four" => { "five" => "six" } }})
         | 
| 98 | 
            -
                  expected = {"one" => [ "two", "four" ],
         | 
| 99 | 
            -
                              "one_two" => ["three"],
         | 
| 100 | 
            -
                              "X_two" => ["three"],
         | 
| 101 | 
            -
                              "two" => ["three"],
         | 
| 102 | 
            -
                              "one_four" => ["five"],
         | 
| 103 | 
            -
                              "X_four" => ["five"],
         | 
| 104 | 
            -
                              "one_X" => [ "three", "five" ],
         | 
| 105 | 
            -
                              "one_four_five" => ["six"],
         | 
| 106 | 
            -
                              "X_four_five" => ["six"],
         | 
| 107 | 
            -
                              "one_X_five" => ["six"],
         | 
| 108 | 
            -
                              "one_four_X" => ["six"],
         | 
| 109 | 
            -
                              "five" => ["six"]}
         | 
| 110 | 
            -
                  expected.each do |k, v|
         | 
| 111 | 
            -
                    @fields[k].should == v
         | 
| 112 | 
            -
                  end
         | 
| 113 | 
            -
                end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
                it "should call itself recursively for hashes nested in arrays" do
         | 
| 116 | 
            -
                  @fields = @index.flatten_and_expand({ :one => [ { :two => "three" }, { :four => { :five => "six" } } ] })
         | 
| 117 | 
            -
                  expected = {"one_X_five" => ["six"],
         | 
| 118 | 
            -
                              "one_four" => ["five"],
         | 
| 119 | 
            -
                              "one_X" => [ "three", "five" ],
         | 
| 120 | 
            -
                              "two" => ["three"],
         | 
| 121 | 
            -
                              "one_four_X" => ["six"],
         | 
| 122 | 
            -
                              "X_four" => ["five"],
         | 
| 123 | 
            -
                              "X_four_five" => ["six"],
         | 
| 124 | 
            -
                              "one" => [ "two", "four" ],
         | 
| 125 | 
            -
                              "one_four_five" => ["six"],
         | 
| 126 | 
            -
                              "five" => ["six"],
         | 
| 127 | 
            -
                              "X_two" => ["three"],
         | 
| 128 | 
            -
                              "one_two" => ["three"]}
         | 
| 129 | 
            -
             | 
| 130 | 
            -
                  expected.each do |key, expected_value|
         | 
| 131 | 
            -
                    @fields[key].should == expected_value
         | 
| 132 | 
            -
                  end
         | 
| 133 | 
            -
                end
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                it "generates unlimited levels of expando fields when expanding" do
         | 
| 136 | 
            -
                  expected_keys = ["one",
         | 
| 137 | 
            -
                                   "one_two",
         | 
| 138 | 
            -
                                   "X_two",
         | 
| 139 | 
            -
                                   "one_X",
         | 
| 140 | 
            -
                                   "one_two_three",
         | 
| 141 | 
            -
                                   "X_two_three",
         | 
| 142 | 
            -
                                   "one_X_three",
         | 
| 143 | 
            -
                                   "one_two_X",
         | 
| 144 | 
            -
                                   "one_two_three_four",
         | 
| 145 | 
            -
                                   "X_two_three_four",
         | 
| 146 | 
            -
                                   "one_X_three_four",
         | 
| 147 | 
            -
                                   "one_two_X_four",
         | 
| 148 | 
            -
                                   "one_two_three_X",
         | 
| 149 | 
            -
                                   "one_two_three_four_five",
         | 
| 150 | 
            -
                                   "X_two_three_four_five",
         | 
| 151 | 
            -
                                   "one_X_three_four_five",
         | 
| 152 | 
            -
                                   "one_two_X_four_five",
         | 
| 153 | 
            -
                                   "one_two_three_X_five",
         | 
| 154 | 
            -
                                   "one_two_three_four_X",
         | 
| 155 | 
            -
                                   "six",
         | 
| 156 | 
            -
                                   "one_two_three_four_five_six",
         | 
| 157 | 
            -
                                   "X_two_three_four_five_six",
         | 
| 158 | 
            -
                                   "one_X_three_four_five_six",
         | 
| 159 | 
            -
                                   "one_two_X_four_five_six",
         | 
| 160 | 
            -
                                   "one_two_three_X_five_six",
         | 
| 161 | 
            -
                                   "one_two_three_four_X_six",
         | 
| 162 | 
            -
                                   "one_two_three_four_five_X"].sort
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                  nested = {:one => {:two => {:three => {:four => {:five => {:six => :end}}}}}}
         | 
| 165 | 
            -
                  @fields = @index.flatten_and_expand(nested)
         | 
| 166 | 
            -
             | 
| 167 | 
            -
                  @fields.keys.sort.should include(*expected_keys)
         | 
| 168 | 
            -
                end
         | 
| 169 | 
            -
             | 
| 170 | 
            -
              end
         | 
| 171 | 
            -
             | 
| 172 | 
            -
              describe "creating expando fields" do
         | 
| 173 | 
            -
                def make_expando_fields(parts)
         | 
| 174 | 
            -
                  expando_fields = []
         | 
| 175 | 
            -
                  @index.each_expando_field(parts) { |ex| expando_fields << ex }
         | 
| 176 | 
            -
                  expando_fields
         | 
| 177 | 
            -
                end
         | 
| 178 | 
            -
             | 
| 179 | 
            -
                it "joins the fields with a big X" do
         | 
| 180 | 
            -
                  make_expando_fields(%w{foo bar baz qux}).should == ["X_bar_baz_qux", "foo_X_baz_qux", "foo_bar_X_qux", "foo_bar_baz_X"]
         | 
| 181 | 
            -
                  make_expando_fields(%w{foo bar baz}).should == ["X_bar_baz", "foo_X_baz", "foo_bar_X"]
         | 
| 182 | 
            -
                  make_expando_fields(%w{foo bar}).should == ["X_bar", "foo_X"]
         | 
| 183 | 
            -
                  make_expando_fields(%w{foo}).should == []
         | 
| 184 | 
            -
                end
         | 
| 185 | 
            -
              end
         | 
| 186 | 
            -
             | 
| 187 | 
            -
            end
         | 
| @@ -1,14 +0,0 @@ | |
| 1 | 
            -
            require File.expand_path(File.join("#{File.dirname(__FILE__)}", '..', '..', 'spec_helper'))
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            describe Chef::Solr::Query do
         | 
| 4 | 
            -
              before(:each) do
         | 
| 5 | 
            -
                @query = Chef::Solr::Query.new
         | 
| 6 | 
            -
              end
         | 
| 7 | 
            -
             | 
| 8 | 
            -
              describe "initialize" do
         | 
| 9 | 
            -
                it "should return a Chef::Solr::Query" do
         | 
| 10 | 
            -
                  @query.should be_a_kind_of(Chef::Solr::Query)
         | 
| 11 | 
            -
                end
         | 
| 12 | 
            -
              end
         | 
| 13 | 
            -
            end
         | 
| 14 | 
            -
             | 
    
        data/spec/chef/solr_spec.rb
    DELETED
    
    | @@ -1,301 +0,0 @@ | |
| 1 | 
            -
            require File.expand_path(File.join("#{File.dirname(__FILE__)}", '..', 'spec_helper'))
         | 
| 2 | 
            -
            require 'net/http'
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            describe Chef::Solr do
         | 
| 5 | 
            -
              before(:each) do 
         | 
| 6 | 
            -
                @solr = Chef::Solr.new
         | 
| 7 | 
            -
              end
         | 
| 8 | 
            -
             | 
| 9 | 
            -
              describe "initialize" do
         | 
| 10 | 
            -
                it "should create a new Chef::Solr object" do
         | 
| 11 | 
            -
                  @solr.should be_a_kind_of(Chef::Solr)
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                it "should accept an alternate solr url" do
         | 
| 15 | 
            -
                  solr = Chef::Solr.new("http://example.com")
         | 
| 16 | 
            -
                  solr.solr_url.should eql("http://example.com")
         | 
| 17 | 
            -
                end
         | 
| 18 | 
            -
              end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
              describe "solr_select" do
         | 
| 21 | 
            -
                before(:each) do
         | 
| 22 | 
            -
                  @http_response = mock(
         | 
| 23 | 
            -
                    "Net::HTTP::Response", 
         | 
| 24 | 
            -
                    :kind_of? => Net::HTTPSuccess,
         | 
| 25 | 
            -
                    :body => "{ :some => :hash }"
         | 
| 26 | 
            -
                  )
         | 
| 27 | 
            -
                  @http = mock("Net::HTTP", :request => @http_response)
         | 
| 28 | 
            -
                  @solr.http = @http
         | 
| 29 | 
            -
                end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                describe "when the HTTP call is successful" do
         | 
| 32 | 
            -
                  it "should call get to /solr/select with the escaped query" do
         | 
| 33 | 
            -
                    Net::HTTP::Get.should_receive(:new).with(%r(q=hostname%3Alatte))
         | 
| 34 | 
            -
                    @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
                  it "should call get to /solr/select with wt=ruby" do
         | 
| 38 | 
            -
                    Net::HTTP::Get.should_receive(:new).with(%r(wt=ruby))
         | 
| 39 | 
            -
                    @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 40 | 
            -
                  end
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                  it "should call get to /solr/select with indent=off" do
         | 
| 43 | 
            -
                    Net::HTTP::Get.should_receive(:new).with(%r(indent=off))
         | 
| 44 | 
            -
                    @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 45 | 
            -
                  end
         | 
| 46 | 
            -
             | 
| 47 | 
            -
                  it "should call get to /solr/select with filter query" do
         | 
| 48 | 
            -
                    Net::HTTP::Get.should_receive(:new).with(/fq=%2BX_CHEF_database_CHEF_X%3Achef_opscode\+%2BX_CHEF_type_CHEF_X%3Anode/)
         | 
| 49 | 
            -
                    @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 50 | 
            -
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  it "should return the evaluated response body" do
         | 
| 53 | 
            -
                    res = @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 54 | 
            -
                    res.should == { :some => :hash }
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
                end
         | 
| 57 | 
            -
             | 
| 58 | 
            -
                describe "when the HTTP call is unsuccessful" do
         | 
| 59 | 
            -
                  [Timeout::Error, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EINVAL].each do |exception|
         | 
| 60 | 
            -
                    it "should rescue, log an error message, and raise a SolrConnectionError encountering exception #{exception}" do
         | 
| 61 | 
            -
                      lambda {
         | 
| 62 | 
            -
                        @http.should_receive(:request).with(instance_of(Net::HTTP::Get)).and_raise(exception)
         | 
| 63 | 
            -
                        Chef::Log.should_receive(:fatal).with(/Search Query to Solr '(.+?)' failed.  Chef::Exceptions::SolrConnectionError exception: #{exception}:.+/)
         | 
| 64 | 
            -
                        @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 65 | 
            -
                      }.should raise_error(Chef::Exceptions::SolrConnectionError)
         | 
| 66 | 
            -
                    end
         | 
| 67 | 
            -
                  end
         | 
| 68 | 
            -
             | 
| 69 | 
            -
                  it "should rescue, log an error message, and raise a SolrConnectionError when encountering exception NoMethodError and net/http closed? bug" do
         | 
| 70 | 
            -
                    lambda {
         | 
| 71 | 
            -
                      @no_method_error = NoMethodError.new("undefined method 'closed\?' for nil:NilClass")
         | 
| 72 | 
            -
                      @http.should_receive(:request).with(instance_of(Net::HTTP::Get)).and_raise(@no_method_error)
         | 
| 73 | 
            -
                      Chef::Log.should_receive(:fatal).with(/Search Query to Solr '(.+?)' failed.  Chef::Exceptions::SolrConnectionError exception: Errno::ECONNREFUSED.+net\/http undefined method closed.+/)
         | 
| 74 | 
            -
                      @solr.solr_select("chef_opscode", "node", :q => "hostname:latte")
         | 
| 75 | 
            -
                    }.should raise_error(Chef::Exceptions::SolrConnectionError)
         | 
| 76 | 
            -
                  end
         | 
| 77 | 
            -
                end
         | 
| 78 | 
            -
              end
         | 
| 79 | 
            -
             | 
| 80 | 
            -
              describe "post_to_solr" do
         | 
| 81 | 
            -
                before(:each) do
         | 
| 82 | 
            -
                  @http_response = mock(
         | 
| 83 | 
            -
                    "Net::HTTP::Response", 
         | 
| 84 | 
            -
                    :kind_of? => Net::HTTPSuccess,
         | 
| 85 | 
            -
                    :body => "{ :some => :hash }"
         | 
| 86 | 
            -
                  )
         | 
| 87 | 
            -
                  @http_request = mock(
         | 
| 88 | 
            -
                    "Net::HTTP::Request",
         | 
| 89 | 
            -
                    :body= => true
         | 
| 90 | 
            -
                  )
         | 
| 91 | 
            -
                  @http = mock("Net::HTTP", :request => @http_response)
         | 
| 92 | 
            -
                  @solr.http = @http
         | 
| 93 | 
            -
                  Net::HTTP::Post.stub!(:new).and_return(@http_request)
         | 
| 94 | 
            -
                  @doc = { "foo" => "bar" }
         | 
| 95 | 
            -
                end
         | 
| 96 | 
            -
             | 
| 97 | 
            -
                describe 'when the HTTP call is successful' do
         | 
| 98 | 
            -
                  it "should post to /solr/update" do
         | 
| 99 | 
            -
                    Net::HTTP::Post.should_receive(:new).with("/solr/update", "Content-Type" => "text/xml").and_return(@http_request)
         | 
| 100 | 
            -
                    @solr.post_to_solr(@doc)
         | 
| 101 | 
            -
                  end
         | 
| 102 | 
            -
             | 
| 103 | 
            -
                  it "should set the body of the request to the stringified doc" do
         | 
| 104 | 
            -
                    @http_request.should_receive(:body=).with("foo")
         | 
| 105 | 
            -
                    @solr.post_to_solr(:foo)
         | 
| 106 | 
            -
                  end
         | 
| 107 | 
            -
             | 
| 108 | 
            -
                  it "should send the request to solr" do
         | 
| 109 | 
            -
                    @http.should_receive(:request).with(@http_request).and_return(@http_response)
         | 
| 110 | 
            -
                    @solr.post_to_solr(:foo).should
         | 
| 111 | 
            -
                  end
         | 
| 112 | 
            -
                end
         | 
| 113 | 
            -
             | 
| 114 | 
            -
                describe "when the HTTP call is unsuccessful due to an exception" do
         | 
| 115 | 
            -
                  it "should post to /solr/update" do
         | 
| 116 | 
            -
                    Net::HTTP::Post.should_receive(:new).with("/solr/update", "Content-Type" => "text/xml").and_return(@http_request)
         | 
| 117 | 
            -
                    @solr.post_to_solr(@doc)
         | 
| 118 | 
            -
                  end
         | 
| 119 | 
            -
             | 
| 120 | 
            -
                  it "should set the body of the request to the stringified doc" do
         | 
| 121 | 
            -
                    @http_request.should_receive(:body=).with("foo")
         | 
| 122 | 
            -
                    @solr.post_to_solr(:foo)
         | 
| 123 | 
            -
                  end
         | 
| 124 | 
            -
             | 
| 125 | 
            -
                  [Timeout::Error, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EINVAL].each do |exception|
         | 
| 126 | 
            -
                    it "should rescue and log an error message when encountering exception #{exception} and then re-raise it" do
         | 
| 127 | 
            -
                      lambda {
         | 
| 128 | 
            -
                        @http.should_receive(:request).with(@http_request).and_raise(exception)
         | 
| 129 | 
            -
                        Chef::Log.should_receive(:fatal).with(/POST to Solr '(.+?)' failed.  Chef::Exceptions::SolrConnectionError exception: #{exception}:.+/)
         | 
| 130 | 
            -
                        @solr.post_to_solr(:foo)
         | 
| 131 | 
            -
                      }.should raise_error(Chef::Exceptions::SolrConnectionError)
         | 
| 132 | 
            -
                    end
         | 
| 133 | 
            -
                  end
         | 
| 134 | 
            -
             | 
| 135 | 
            -
                  it "should rescue and log an error message when encountering exception NoMethodError and net/http closed? bug" do
         | 
| 136 | 
            -
                    lambda {
         | 
| 137 | 
            -
                      @no_method_error = NoMethodError.new("undefined method 'closed\?' for nil:NilClass")
         | 
| 138 | 
            -
                      @http.should_receive(:request).with(@http_request).and_raise(@no_method_error)
         | 
| 139 | 
            -
                      Chef::Log.should_receive(:fatal).with(/POST to Solr '(.+?)' failed.  Chef::Exceptions::SolrConnectionError exception: Errno::ECONNREFUSED.+net\/http undefined method closed.+/)
         | 
| 140 | 
            -
                      @solr.post_to_solr(:foo)
         | 
| 141 | 
            -
                    }.should raise_error(Chef::Exceptions::SolrConnectionError)
         | 
| 142 | 
            -
                  end
         | 
| 143 | 
            -
                end
         | 
| 144 | 
            -
              end
         | 
| 145 | 
            -
             | 
| 146 | 
            -
              describe "solr_add" do
         | 
| 147 | 
            -
                before(:each) do
         | 
| 148 | 
            -
                  @solr.stub!(:post_to_solr).and_return(true)
         | 
| 149 | 
            -
                  @data = { "foo" => ["bar"] }
         | 
| 150 | 
            -
                end
         | 
| 151 | 
            -
             | 
| 152 | 
            -
                it "should send valid XML to solr" do
         | 
| 153 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<add><doc><field name=\"foo\">bar</field></doc></add>\n")
         | 
| 154 | 
            -
                  @solr.solr_add(@data)
         | 
| 155 | 
            -
                end
         | 
| 156 | 
            -
             | 
| 157 | 
            -
                it "XML escapes content before sending to SOLR" do
         | 
| 158 | 
            -
                  @data["foo"] = ["<&>"]
         | 
| 159 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<add><doc><field name=\"foo\"><&></field></doc></add>\n")
         | 
| 160 | 
            -
             | 
| 161 | 
            -
                  @solr.solr_add(@data)
         | 
| 162 | 
            -
                end
         | 
| 163 | 
            -
             | 
| 164 | 
            -
                it "XML escapes keys before sending to SOLR" do
         | 
| 165 | 
            -
                  @data.delete("foo")
         | 
| 166 | 
            -
                  @data["foo&bar"] = ["baz"]
         | 
| 167 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<add><doc><field name=\"foo&bar\">baz</field></doc></add>\n")
         | 
| 168 | 
            -
             | 
| 169 | 
            -
                  @solr.solr_add(@data)
         | 
| 170 | 
            -
                end
         | 
| 171 | 
            -
              end
         | 
| 172 | 
            -
             | 
| 173 | 
            -
              describe "solr_commit" do
         | 
| 174 | 
            -
                before(:each) do
         | 
| 175 | 
            -
                  @solr.stub!(:post_to_solr).and_return(true)
         | 
| 176 | 
            -
                end
         | 
| 177 | 
            -
             | 
| 178 | 
            -
                it "should send valid commit xml to solr" do
         | 
| 179 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<commit/>\n")
         | 
| 180 | 
            -
                  @solr.solr_commit
         | 
| 181 | 
            -
                end
         | 
| 182 | 
            -
              end
         | 
| 183 | 
            -
             | 
| 184 | 
            -
              describe "solr_optimize" do
         | 
| 185 | 
            -
                before(:each) do
         | 
| 186 | 
            -
                  @solr.stub!(:post_to_solr).and_return(true)
         | 
| 187 | 
            -
                end
         | 
| 188 | 
            -
             | 
| 189 | 
            -
                it "should send valid commit xml to solr" do
         | 
| 190 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<optimize/>\n")
         | 
| 191 | 
            -
                  @solr.solr_optimize
         | 
| 192 | 
            -
                end
         | 
| 193 | 
            -
              end
         | 
| 194 | 
            -
             | 
| 195 | 
            -
              describe "solr_rollback" do
         | 
| 196 | 
            -
                before(:each) do
         | 
| 197 | 
            -
                  @solr.stub!(:post_to_solr).and_return(true)
         | 
| 198 | 
            -
                end
         | 
| 199 | 
            -
             | 
| 200 | 
            -
                it "should send valid commit xml to solr" do
         | 
| 201 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rollback/>\n")
         | 
| 202 | 
            -
                  @solr.solr_rollback
         | 
| 203 | 
            -
                end
         | 
| 204 | 
            -
              end
         | 
| 205 | 
            -
             | 
| 206 | 
            -
              describe "solr_delete_by_id" do
         | 
| 207 | 
            -
                before(:each) do
         | 
| 208 | 
            -
                  @solr.stub!(:post_to_solr).and_return(true)
         | 
| 209 | 
            -
                end
         | 
| 210 | 
            -
             | 
| 211 | 
            -
                it "should send valid delete id xml to solr" do
         | 
| 212 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<delete><id>1</id></delete>\n")
         | 
| 213 | 
            -
                  @solr.solr_delete_by_id(1)
         | 
| 214 | 
            -
                end
         | 
| 215 | 
            -
             | 
| 216 | 
            -
                it "should accept multiple ids" do
         | 
| 217 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<delete><id>1</id><id>2</id></delete>\n")
         | 
| 218 | 
            -
                  @solr.solr_delete_by_id([ 1, 2 ])
         | 
| 219 | 
            -
                end
         | 
| 220 | 
            -
              end
         | 
| 221 | 
            -
             | 
| 222 | 
            -
              describe "solr_delete_by_query" do
         | 
| 223 | 
            -
                before(:each) do
         | 
| 224 | 
            -
                  @solr.stub!(:post_to_solr).and_return(true)
         | 
| 225 | 
            -
                end
         | 
| 226 | 
            -
             | 
| 227 | 
            -
                it "should send valid delete id xml to solr" do
         | 
| 228 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<delete><query>foo:bar</query></delete>\n")
         | 
| 229 | 
            -
                  @solr.solr_delete_by_query("foo:bar")
         | 
| 230 | 
            -
                end
         | 
| 231 | 
            -
             | 
| 232 | 
            -
                it "should accept multiple ids" do
         | 
| 233 | 
            -
                  @solr.should_receive(:post_to_solr).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<delete><query>foo:bar</query><query>baz:bum</query></delete>\n")
         | 
| 234 | 
            -
                  @solr.solr_delete_by_query([ "foo:bar", "baz:bum" ])
         | 
| 235 | 
            -
                end
         | 
| 236 | 
            -
              end
         | 
| 237 | 
            -
              
         | 
| 238 | 
            -
              describe "rebuilding the index" do
         | 
| 239 | 
            -
                before do
         | 
| 240 | 
            -
                  Chef::Config[:couchdb_database] = "chunky_bacon"
         | 
| 241 | 
            -
                end
         | 
| 242 | 
            -
                
         | 
| 243 | 
            -
                it "deletes the index and commits" do
         | 
| 244 | 
            -
                  @solr.should_receive(:solr_delete_by_query).with("X_CHEF_database_CHEF_X:chunky_bacon")
         | 
| 245 | 
            -
                  @solr.should_receive(:solr_commit)
         | 
| 246 | 
            -
                  @solr.stub!(:reindex_all)
         | 
| 247 | 
            -
                  Chef::DataBag.stub!(:cdb_list).and_return([])
         | 
| 248 | 
            -
                  @solr.rebuild_index
         | 
| 249 | 
            -
                end
         | 
| 250 | 
            -
                
         | 
| 251 | 
            -
                it "reindexes Chef::ApiClient, Chef::Node, and Chef::Role objects, reporting the results as a hash" do
         | 
| 252 | 
            -
                  @solr.stub!(:solr_delete_by_query).with("X_CHEF_database_CHEF_X:chunky_bacon")
         | 
| 253 | 
            -
                  @solr.stub!(:solr_commit)
         | 
| 254 | 
            -
                  @solr.should_receive(:reindex_all).with(Chef::ApiClient).and_return(true)
         | 
| 255 | 
            -
                  @solr.should_receive(:reindex_all).with(Chef::Node).and_return(true)
         | 
| 256 | 
            -
                  @solr.should_receive(:reindex_all).with(Chef::Role).and_return(true)
         | 
| 257 | 
            -
                  Chef::DataBag.stub!(:cdb_list).and_return([])
         | 
| 258 | 
            -
                  
         | 
| 259 | 
            -
                  result = @solr.rebuild_index
         | 
| 260 | 
            -
                  result["Chef::ApiClient"].should == "success"
         | 
| 261 | 
            -
                  result["Chef::Node"].should == "success"
         | 
| 262 | 
            -
                  result["Chef::Role"].should == "success"
         | 
| 263 | 
            -
                end
         | 
| 264 | 
            -
                
         | 
| 265 | 
            -
                it "does not reindex Chef::OpenIDRegistration or Chef::WebUIUser objects" do
         | 
| 266 | 
            -
                  # hi there. the reason we're specifying this behavior is because these objects
         | 
| 267 | 
            -
                  # are not properly indexed in the first place and trying to reindex them
         | 
| 268 | 
            -
                  # tickles a bug in our CamelCase to snake_case code. See CHEF-1009.
         | 
| 269 | 
            -
                  @solr.stub!(:solr_delete_by_query).with("X_CHEF_database_CHEF_X:chunky_bacon")
         | 
| 270 | 
            -
                  @solr.stub!(:solr_commit)
         | 
| 271 | 
            -
                  @solr.stub!(:reindex_all).with(Chef::ApiClient)
         | 
| 272 | 
            -
                  @solr.stub!(:reindex_all).with(Chef::Node)
         | 
| 273 | 
            -
                  @solr.stub!(:reindex_all).with(Chef::Role)
         | 
| 274 | 
            -
                  @solr.should_not_receive(:reindex_all).with(Chef::OpenIDRegistration)
         | 
| 275 | 
            -
                  @solr.should_not_receive(:reindex_all).with(Chef::WebUIUser)
         | 
| 276 | 
            -
                  Chef::DataBag.stub!(:cdb_list).and_return([])
         | 
| 277 | 
            -
                  
         | 
| 278 | 
            -
                  @solr.rebuild_index
         | 
| 279 | 
            -
                end
         | 
| 280 | 
            -
                
         | 
| 281 | 
            -
                it "reindexes databags" do
         | 
| 282 | 
            -
                  one_data_item = Chef::DataBagItem.new
         | 
| 283 | 
            -
                  one_data_item.raw_data = {"maybe"=>"snakes actually are evil", "id" => "just_sayin"}
         | 
| 284 | 
            -
                  two_data_item = Chef::DataBagItem.new
         | 
| 285 | 
            -
                  two_data_item.raw_data = {"tone_depth"=>"rumble_fish", "id" => "eff_yes"}
         | 
| 286 | 
            -
                  data_bag = Chef::DataBag.new
         | 
| 287 | 
            -
                  data_bag.stub!(:list).and_return([one_data_item, two_data_item])
         | 
| 288 | 
            -
                  
         | 
| 289 | 
            -
                  @solr.stub!(:solr_delete_by_query).with("X_CHEF_database_CHEF_X:chunky_bacon")
         | 
| 290 | 
            -
                  @solr.stub!(:solr_commit)
         | 
| 291 | 
            -
                  @solr.stub!(:reindex_all)
         | 
| 292 | 
            -
                  Chef::DataBag.stub!(:cdb_list).and_return([data_bag])
         | 
| 293 | 
            -
                  
         | 
| 294 | 
            -
                  data_bag.should_receive(:add_to_index)
         | 
| 295 | 
            -
                  one_data_item.should_receive(:add_to_index)
         | 
| 296 | 
            -
                  two_data_item.should_receive(:add_to_index)
         | 
| 297 | 
            -
                  
         | 
| 298 | 
            -
                  @solr.rebuild_index["Chef::DataBag"].should == "success"
         | 
| 299 | 
            -
                end
         | 
| 300 | 
            -
              end
         | 
| 301 | 
            -
            end
         |