summaryrefslogtreecommitdiff
path: root/chef
diff options
context:
space:
mode:
Diffstat (limited to 'chef')
-rw-r--r--chef/Gemfile1
-rw-r--r--chef/README.rdoc76
-rw-r--r--chef/chef.gemspec2
-rw-r--r--chef/lib/chef.rb6
-rw-r--r--chef/lib/chef/api_client.rb92
-rw-r--r--chef/lib/chef/certificate.rb161
-rw-r--r--chef/lib/chef/checksum.rb167
-rw-r--r--chef/lib/chef/config.rb27
-rw-r--r--chef/lib/chef/cookbook_uploader.rb1
-rw-r--r--chef/lib/chef/cookbook_version.rb301
-rw-r--r--chef/lib/chef/cookbook_version_selector.rb168
-rw-r--r--chef/lib/chef/couchdb.rb246
-rw-r--r--chef/lib/chef/data_bag.rb96
-rw-r--r--chef/lib/chef/data_bag_item.rb67
-rw-r--r--chef/lib/chef/environment.rb181
-rw-r--r--chef/lib/chef/exceptions.rb3
-rw-r--r--chef/lib/chef/index_queue.rb29
-rw-r--r--chef/lib/chef/index_queue/amqp_client.rb116
-rw-r--r--chef/lib/chef/index_queue/consumer.rb76
-rw-r--r--chef/lib/chef/index_queue/indexable.rb109
-rw-r--r--chef/lib/chef/node.rb155
-rw-r--r--chef/lib/chef/openid_registration.rb187
-rw-r--r--chef/lib/chef/role.rb98
-rw-r--r--chef/lib/chef/run_list.rb2
-rw-r--r--chef/lib/chef/run_list/run_list_expansion.rb15
-rw-r--r--chef/lib/chef/sandbox.rb153
-rw-r--r--chef/lib/chef/solr_query.rb187
-rw-r--r--chef/lib/chef/solr_query/lucene.treetop150
-rw-r--r--chef/lib/chef/solr_query/lucene_nodes.rb285
-rw-r--r--chef/lib/chef/solr_query/query_transform.rb65
-rw-r--r--chef/lib/chef/solr_query/solr_http_request.rb132
-rw-r--r--chef/lib/chef/webui_user.rb156
-rw-r--r--chef/spec/unit/api_client_spec.rb35
-rw-r--r--chef/spec/unit/certificate_spec.rb76
-rw-r--r--chef/spec/unit/checksum_spec.rb94
-rw-r--r--chef/spec/unit/client_spec.rb13
-rw-r--r--chef/spec/unit/cookbook_version_spec.rb138
-rw-r--r--chef/spec/unit/couchdb_spec.rb274
-rw-r--r--chef/spec/unit/environment_spec.rb130
-rw-r--r--chef/spec/unit/exceptions_spec.rb5
-rw-r--r--chef/spec/unit/index_queue_spec.rb391
-rw-r--r--chef/spec/unit/knife/ssh_spec.rb6
-rw-r--r--chef/spec/unit/lwrp_spec.rb6
-rw-r--r--chef/spec/unit/mixin/params_validate_spec.rb6
-rw-r--r--chef/spec/unit/node_spec.rb76
-rw-r--r--chef/spec/unit/openid_registration_spec.rb153
-rw-r--r--chef/spec/unit/provider/ohai_spec.rb4
-rw-r--r--chef/spec/unit/run_list_spec.rb209
-rw-r--r--chef/spec/unit/solr_query/query_transform_spec.rb454
-rw-r--r--chef/spec/unit/solr_query/solr_http_request_spec.rb244
-rw-r--r--chef/spec/unit/solr_query_spec.rb203
51 files changed, 60 insertions, 5967 deletions
diff --git a/chef/Gemfile b/chef/Gemfile
index b538e0bc1f..40868b9677 100644
--- a/chef/Gemfile
+++ b/chef/Gemfile
@@ -2,7 +2,6 @@ source :rubygems
gemspec
-gem "dep_selector", :group => :server, :platform => "ruby"
gem "activesupport", :group => :compat_testing, :platform => "ruby"
gem "ronn"
diff --git a/chef/README.rdoc b/chef/README.rdoc
index 43feffebaf..4a1801643c 100644
--- a/chef/README.rdoc
+++ b/chef/README.rdoc
@@ -2,9 +2,9 @@
== DESCRIPTION:
-Chef is a configuration management tool designed to bring automation to your entire infrastructure.
+Chef is a configuration management tool designed to bring automation to your entire infrastructure.
-The Chef Wiki is the definitive source of user documentation.
+The Chef Wiki is the definitive source of user documentation.
* http://wiki.opscode.com/display/chef/Home
@@ -22,7 +22,7 @@ You will also need to set up the repository with the appropriate branches. We do
* http://wiki.opscode.com/display/opscode/Working+with+Git
-Once your repository is set up, you can start working on the code. We do use BDD/TDD with RSpec and Cucumber, so you'll need to get a development environment running.
+Once your repository is set up, you can start working on the code. We do use TDD with RSpec, so you'll need to get a development environment running.
== REQUIREMENTS:
@@ -39,16 +39,12 @@ In order to have a development environment where changes to the Chef code can be
Install these via your platform's preferred method; for example apt, yum, ports, emerge, etc.
* Git[http://git-scm.com/]
-* Erlang/OTP[http://www.erlang.org/]
-* CouchDB[http://couchdb.apache.org/]
-* RabbitMQ[http://www.rabbitmq.com/]
* GCC and C Standard Libraries, header files, etc. (i.e., build-essential on debian/ubuntu)
* Ruby development package
=== Runtime Rubygem Dependencies
==== Chef Client and Solo
* ohai
-* bunny
* erubis
* highline
* json (1.4.4 - 1.4.6)
@@ -63,61 +59,12 @@ Install these via your platform's preferred method; for example apt, yum, ports,
* net-ssh
* fog
-==== Chef Server, WebUI and Solr
-All of the above, plus the following:
-* coderay
-* haml
-* merb-assets
-* merb-core
-* merb-haml
-* merb-helpers
-* merb-param-protection
-* ruby-openid
-* thin
-
=== Development Rubygem Dependencies
* rake[http://rake.rubyforge.org/]
* rspec[http://rspec.info/]
-* cucumber[http://cukes.info/]
Ohai is also by Opscode and available on GitHub, http://github.com/opscode/ohai/tree/master.
-== Starting the Environment:
-
-=== On Mac OS X:
-For ease of debugging, Chef includes a script to start each of the required
-daemons in a separate Terminal.app tab via applescript:
-
- scripts/mac-dev-start features
-
-=== On Linux and BSD
-
-run the dev:features rake task. You may need to run it as root depending on how
-your system is configured.
-
- rake dev:features
-
-=== Daemons
-After starting the environment, you should have the following processes running:
-* couchdb listening on port 5984
-* rabbitmq listening on port 5672
-* solr listening on port 8983
-* chef-solr-indexer connected as a client to rabbitmq
-* chef-server listening on port 4000
-* chef-server-webui listening on port 4040
-
-You'll know its running when you see:
-
- merb : chef-server (api) : worker (port 4000) ~ Starting Thin at port 4000
- merb : chef-server (api) : worker (port 4000) ~ Using Thin adapter on host 0.0.0.0 and port 4000.
- merb : chef-server (api) : worker (port 4000) ~ Successfully bound to port 4000
-
-You'll want to leave this terminal running the dev environment.
-
-=== Web Interface:
-
-With the dev environment running, you can now access the web interface via http://localhost:4040/.
-
== Spec testing:
We use RSpec for unit/spec tests. It is not necessary to start the development
@@ -125,23 +72,6 @@ environment to run the specs--they are completely standalone.
rake spec
-== Integration testing:
-
-We test integration with Cucumber. To run the full suite, run the rake task:
-
- rake features
-
-Subsets of the integration tests can be run with the various tasks in the
-features namespace. To see the full list, run
-
- rake -T
-
-To run individual feature tests, you can take advantage of cucumber's tagging
-support. Tag the feature you wish to run (tags are denoted with a leading `@'
-sign), then use the cucumber command:
-
- cucumber -t @my_tag
-
== LINKS:
Source:
diff --git a/chef/chef.gemspec b/chef/chef.gemspec
index 732601cc79..c807a85bf2 100644
--- a/chef/chef.gemspec
+++ b/chef/chef.gemspec
@@ -21,10 +21,8 @@ Gem::Specification.new do |s|
s.add_dependency "ohai", ">= 0.6.0"
s.add_dependency "rest-client", ">= 1.0.4", "< 1.7.0"
- s.add_dependency "bunny", ">= 0.6.0", "< 0.8.0"
s.add_dependency "json", ">= 1.4.4", "<= 1.6.1"
s.add_dependency "yajl-ruby", "~> 1.1"
- s.add_dependency "treetop", "~> 1.4.9"
s.add_dependency "net-ssh", "~> 2.2.2"
s.add_dependency "net-ssh-multi", "~> 1.1.0"
# CHEF-3027: The knife-cloud plugins require newer features from highline, core chef should not.
diff --git a/chef/lib/chef.rb b/chef/lib/chef.rb
index e56e805dee..ef173c4212 100644
--- a/chef/lib/chef.rb
+++ b/chef/lib/chef.rb
@@ -6,9 +6,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -27,8 +27,6 @@ require 'chef/resources'
require 'chef/shell_out'
require 'chef/daemon'
-require 'chef/webui_user'
-require 'chef/openid_registration'
require 'chef/run_status'
require 'chef/handler'
diff --git a/chef/lib/chef/api_client.rb b/chef/lib/chef/api_client.rb
index f95978afba..da05939c24 100644
--- a/chef/lib/chef/api_client.rb
+++ b/chef/lib/chef/api_client.rb
@@ -20,9 +20,6 @@
require 'chef/config'
require 'chef/mixin/params_validate'
require 'chef/mixin/from_file'
-require 'chef/couchdb'
-require 'chef/certificate'
-require 'chef/index_queue'
require 'chef/mash'
require 'chef/json_compat'
require 'chef/search/query'
@@ -32,51 +29,13 @@ class Chef
include Chef::Mixin::FromFile
include Chef::Mixin::ParamsValidate
- include Chef::IndexQueue::Indexable
-
-
- DESIGN_DOCUMENT = {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "client") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "client") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- }
- }
- }
-
- INDEX_OBJECT_TYPE = 'client'.freeze
-
- def self.index_object_type
- INDEX_OBJECT_TYPE
- end
-
- attr_accessor :couchdb_rev, :couchdb_id, :couchdb
# Create a new Chef::ApiClient object.
- def initialize(couchdb=nil)
+ def initialize
@name = ''
@public_key = nil
@private_key = nil
- @couchdb_rev = nil
- @couchdb_id = nil
@admin = false
- @couchdb = (couchdb || Chef::CouchDB.new)
end
# Gets or sets the client name.
@@ -127,17 +86,6 @@ class Chef
)
end
- # Creates a new public/private key pair, and populates the public_key and
- # private_key attributes.
- #
- # @return [True]
- def create_keys
- results = Chef::Certificate.gen_keypair(self.name)
- self.public_key(results[0].to_s)
- self.private_key(results[1].to_s)
- true
- end
-
# The hash representation of the object. Includes the name and public_key,
# but never the private key.
#
@@ -150,7 +98,6 @@ class Chef
'json_class' => self.class.name,
"chef_type" => "client"
}
- result["_rev"] = @couchdb_rev if @couchdb_rev
result
end
@@ -166,20 +113,9 @@ class Chef
client.name(o["name"] || o["clientname"])
client.public_key(o["public_key"])
client.admin(o["admin"])
- client.couchdb_rev = o["_rev"]
- client.couchdb_id = o["_id"]
- client.index_id = client.couchdb_id
client
end
- # List all the Chef::ApiClient objects in the CouchDB. If inflate is set
- # to true, you will get the full list of all ApiClients, fully inflated.
- def self.cdb_list(inflate=false, couchdb=nil)
- rs = (couchdb || Chef::CouchDB.new).list("clients", inflate)
- lookup = (inflate ? "value" : "key")
- rs["rows"].collect { |r| r[lookup] }
- end
-
def self.list(inflate=false)
if inflate
response = Hash.new
@@ -193,14 +129,6 @@ class Chef
end
end
- # Load a client by name from CouchDB
- #
- # @params [String] The name of the client to load
- # @return [Chef::ApiClient] The resulting Chef::ApiClient object
- def self.cdb_load(name, couchdb=nil)
- (couchdb || Chef::CouchDB.new).load("client", name)
- end
-
# Load a client by name via the API
def self.load(name)
response = Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("clients/#{name}")
@@ -213,24 +141,11 @@ class Chef
end
end
- # Remove this client from the CouchDB
- #
- # @params [String] The name of the client to delete
- # @return [Chef::ApiClient] The last version of the object
- def cdb_destroy
- @couchdb.delete("client", @name, @couchdb_rev)
- end
-
# Remove this client via the REST API
def destroy
Chef::REST.new(Chef::Config[:chef_server_url]).delete_rest("clients/#{@name}")
end
- # Save this client to the CouchDB
- def cdb_save
- @couchdb_rev = @couchdb.store("client", @name, self)["rev"]
- end
-
# Save this client via the REST API, returns a hash including the private key
def save(new_key=false, validation=false)
if validation
@@ -256,11 +171,6 @@ class Chef
Chef::REST.new(Chef::Config[:chef_server_url]).post_rest("clients", self)
end
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- (couchdb ||= Chef::CouchDB.new).create_design_document("clients", DESIGN_DOCUMENT)
- end
-
# As a string
def to_s
"client[#{@name}]"
diff --git a/chef/lib/chef/certificate.rb b/chef/lib/chef/certificate.rb
deleted file mode 100644
index 7943589c8e..0000000000
--- a/chef/lib/chef/certificate.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Christopher Brown (<cb@opscode.com>)
-# Copyright:: Copyright (c) 2009 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'chef/log'
-require 'chef/config'
-require 'chef/api_client'
-require 'openssl'
-require 'fileutils'
-
-class Chef
- class Certificate
- class << self
-
- # Generates a new CA Certificate and Key, and writes them out to
- # Chef::Config[:signing_ca_cert] and Chef::Config[:signing_ca_key].
- def generate_signing_ca
- ca_cert_file = Chef::Config[:signing_ca_cert]
- ca_keypair_file = Chef::Config[:signing_ca_key]
-
- unless File.exists?(ca_cert_file) && File.exists?(ca_keypair_file)
- Chef::Log.info("Creating new signing certificate")
-
- [ ca_cert_file, ca_keypair_file ].each do |f|
- ca_basedir = File.dirname(f)
- FileUtils.mkdir_p ca_basedir
- end
-
- keypair = OpenSSL::PKey::RSA.generate(1024)
-
- ca_cert = OpenSSL::X509::Certificate.new
- ca_cert.version = 3
- ca_cert.serial = 1
- info = [
- ["C", Chef::Config[:signing_ca_country]],
- ["ST", Chef::Config[:signing_ca_state]],
- ["L", Chef::Config[:signing_ca_location]],
- ["O", Chef::Config[:signing_ca_org]],
- ["OU", "Certificate Service"],
- ["CN", "#{Chef::Config[:signing_ca_domain]}/emailAddress=#{Chef::Config[:signing_ca_email]}"]
- ]
- ca_cert.subject = ca_cert.issuer = OpenSSL::X509::Name.new(info)
- ca_cert.not_before = Time.now
- ca_cert.not_after = Time.now + 10 * 365 * 24 * 60 * 60 # 10 years
- ca_cert.public_key = keypair.public_key
-
- ef = OpenSSL::X509::ExtensionFactory.new
- ef.subject_certificate = ca_cert
- ef.issuer_certificate = ca_cert
- ca_cert.extensions = [
- ef.create_extension("basicConstraints", "CA:TRUE", true),
- ef.create_extension("subjectKeyIdentifier", "hash"),
- ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
- ]
- ca_cert.add_extension ef.create_extension("authorityKeyIdentifier", "keyid:always,issuer:always")
- ca_cert.sign keypair, OpenSSL::Digest::SHA1.new
-
- File.open(ca_cert_file, "w") { |f| f.write ca_cert.to_pem }
- File.open(ca_keypair_file, File::WRONLY|File::EXCL|File::CREAT, 0600) { |f| f.write keypair.to_pem }
- if (Chef::Config[:signing_ca_user] && Chef::Config[:signing_ca_group])
- FileUtils.chown(Chef::Config[:signing_ca_user], Chef::Config[:signing_ca_group], ca_keypair_file)
- end
- end
- self
- end
-
- # Creates a new key pair, and signs them with the signing certificate
- # and key generated from generate_signing_ca above.
- #
- # All arguments are unused, though two arguments are accepted for compatibility.
- #
- # returns an array of [public_key, private_key]
- def gen_keypair(common_name=nil, subject_alternative_name = nil)
-
- Chef::Log.info("Creating new key pair for #{common_name}")
-
- # generate client keypair
- client_keypair = OpenSSL::PKey::RSA.generate(2048)
-
- return client_keypair.public_key, client_keypair
- end
-
- def gen_validation_key(name=Chef::Config[:validation_client_name], key_file=Chef::Config[:validation_key], admin=false)
- # Create the validation key
- api_client = Chef::ApiClient.new
- api_client.name(name)
- api_client.admin(admin)
-
- begin
- # If both the couch record and file exist, don't do anything. Otherwise,
- # re-generate the validation key.
- Chef::ApiClient.cdb_load(name)
-
- # The couch document was loaded successfully if we got to here; if we
- # can't also load the file on the filesystem, we'll regenerate it all.
- File.open(key_file, "r") do |file|
- end
- rescue Chef::Exceptions::CouchDBNotFound
- create_validation_key(api_client, key_file)
- rescue
- if $!.class.name =~ /Errno::/
- Chef::Log.error("Error opening validation key: #{$!} -- destroying and regenerating")
- begin
- api_client.cdb_destroy
- rescue Bunny::ServerDownError => e
- # create_validation_key is gonna fail anyway, so let's just bail out.
- Chef::Log.fatal("Could not de-index (to rabbitmq) previous validation key - rabbitmq is down! Start rabbitmq then restart chef-server to re-generate it")
- raise
- end
-
- create_validation_key(api_client, key_file)
- else
- raise
- end
- end
- end
-
- private
- def create_validation_key(api_client, key_file)
- Chef::Log.info("Creating validation key...")
-
- api_client.create_keys
- begin
- api_client.cdb_save
- rescue Bunny::ServerDownError => e
- # If rabbitmq is down, the client will have been saved in CouchDB,
- # but not in the index.
- Chef::Log.fatal("Could not index (to rabbitmq) validation key - rabbitmq is down! Start rabbitmq then restart chef-server to re-generate it")
-
- # re-raise so the error bubbles out and nukes chef-server
- raise e
- end
-
- key_dir = File.dirname(key_file)
- FileUtils.mkdir_p(key_dir) unless File.directory?(key_dir)
- File.open(key_file, File::WRONLY|File::CREAT, 0600) do |f|
- f.print(api_client.private_key)
- end
- if (Chef::Config[:signing_ca_user] && Chef::Config[:signing_ca_group])
- FileUtils.chown(Chef::Config[:signing_ca_user], Chef::Config[:signing_ca_group], key_file)
- end
- end
-
- end
- end
-end
diff --git a/chef/lib/chef/checksum.rb b/chef/lib/chef/checksum.rb
deleted file mode 100644
index fc1931174b..0000000000
--- a/chef/lib/chef/checksum.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-#
-# Author:: Tim Hinderliter (<tim@opscode.com>)
-# Copyright:: Copyright (c) 2010 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'chef/log'
-require 'chef/checksum/storage'
-require 'uuidtools'
-
-class Chef
- # == Chef::Checksum
- # Checksum for an individual file; e.g., used for sandbox/cookbook uploading
- # to track which files the system already manages.
- class Checksum
- attr_accessor :checksum, :create_time
- attr_accessor :couchdb_id, :couchdb_rev
-
- attr_reader :storage
-
- # When a Checksum commits a sandboxed file to its final home in the checksum
- # repo, this attribute will have the original on-disk path where the file
- # was stored; it will be used if the commit is reverted to restore the sandbox
- # to the pre-commit state.
- attr_reader :original_committed_file_location
-
- DESIGN_DOCUMENT = {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "checksum") {
- emit(doc.checksum, doc);
- }
- }
- EOJS
- },
- }
- }
-
- # Creates a new Chef::Checksum object.
- # === Arguments
- # checksum::: the MD5 content hash of the file
- # couchdb::: An instance of Chef::CouchDB
- #
- # === Returns
- # object<Chef::Checksum>:: Duh. :)
- def initialize(checksum=nil, couchdb=nil)
- @create_time = Time.now.iso8601
- @checksum = checksum
- @original_committed_file_location = nil
- @storage = Storage::Filesystem.new(Chef::Config.checksum_path, checksum)
- end
-
- def to_json(*a)
- result = {
- :checksum => checksum,
- :create_time => create_time,
- :json_class => self.class.name,
- :chef_type => 'checksum',
-
- # For Chef::CouchDB (id_to_name, name_to_id)
- :name => checksum
- }
- result.to_json(*a)
- end
-
- def self.json_create(o)
- checksum = new(o['checksum'])
- checksum.create_time = o['create_time']
-
- if o.has_key?('_rev')
- checksum.couchdb_rev = o["_rev"]
- o.delete("_rev")
- end
- if o.has_key?("_id")
- checksum.couchdb_id = o["_id"]
- o.delete("_id")
- end
- checksum
- end
-
- # Moves the given +sandbox_file+ into the checksum repo using the path
- # given by +file_location+ and saves the Checksum to the database
- def commit_sandbox_file(sandbox_file)
- @original_committed_file_location = sandbox_file
- Chef::Log.info("Commiting sandbox file: move #{sandbox_file} to #{@storage}")
- @storage.commit(sandbox_file)
- cdb_save
- end
-
- # Moves the checksum file back to its pre-commit location and deletes
- # the checksum object from the database, effectively undoing +commit_sandbox_file+.
- # Raises Chef::Exceptions::IllegalChecksumRevert if the original file location
- # is unknown, which is will be the case if commit_sandbox_file was not
- # previously called
- def revert_sandbox_file_commit
- unless original_committed_file_location
- raise Chef::Exceptions::IllegalChecksumRevert, "Checksum #{self.inspect} cannot be reverted because the original sandbox file location is not known"
- end
-
- Chef::Log.warn("Reverting sandbox file commit: moving #{@storage} back to #{original_committed_file_location}")
- @storage.revert(original_committed_file_location)
- cdb_destroy
- end
-
- # Removes the on-disk file backing this checksum object, then removes it
- # from the database
- def purge
- purge_file
- cdb_destroy
- end
-
- ##
- # Couchdb
- ##
-
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("checksums", DESIGN_DOCUMENT)
- end
-
- def self.cdb_list(inflate=false, couchdb=nil)
- rs = (couchdb || Chef::CouchDB.new).list("checksums", inflate)
- lookup = (inflate ? "value" : "key")
- rs["rows"].collect { |r| r[lookup] }
- end
-
- def self.cdb_all_checksums(couchdb = nil)
- rs = (couchdb || Chef::CouchDB.new).list("checksums", true)
- rs["rows"].inject({}) { |hash_result, r| hash_result[r['key']] = 1; hash_result }
- end
-
- def self.cdb_load(checksum, couchdb=nil)
- # Probably want to look for a view here at some point
- (couchdb || Chef::CouchDB.new).load("checksum", checksum)
- end
-
- def cdb_destroy(couchdb=nil)
- (couchdb || Chef::CouchDB.new).delete("checksum", checksum, @couchdb_rev)
- end
-
- def cdb_save(couchdb=nil)
- @couchdb_rev = (couchdb || Chef::CouchDB.new).store("checksum", checksum, self)["rev"]
- end
-
-
- private
-
- def purge_file
- @storage.purge
- end
-
- end
-end
diff --git a/chef/lib/chef/config.rb b/chef/lib/chef/config.rb
index 924a20ab3b..61c8806a66 100644
--- a/chef/lib/chef/config.rb
+++ b/chef/lib/chef/config.rb
@@ -130,8 +130,6 @@ class Chef
# Used when OpenID authentication is enabled in the Web UI
authorized_openid_identifiers nil
authorized_openid_providers nil
- openid_cstore_couchdb false
- openid_cstore_path "/var/chef/openid/cstore"
# The number of times the client should retry when registering with the server
client_registration_retries 5
@@ -150,11 +148,6 @@ class Chef
# Where cookbook files are stored on the server (by content checksum)
checksum_path "/var/chef/checksums"
- # CouchDB database name to use
- couchdb_database "chef"
-
- couchdb_url "http://localhost:5984"
-
# Where chef's cache files should be stored
file_cache_path platform_specific_path("/var/chef/cache")
@@ -173,7 +166,6 @@ class Chef
## Daemonization Settings ##
# What user should Chef run as?
user nil
- # What group should the chef-server, -solr, -solr-indexer run as
group nil
umask 0022
@@ -212,7 +204,7 @@ class Chef
client_fork false
enable_reporting true
enable_reporting_url_fatals false
-
+
# Set these to enable SSL authentication / mutual-authentication
# with the server
ssl_client_cert nil
@@ -230,23 +222,6 @@ class Chef
# Where should chef-solo download recipes from?
recipe_url nil
- solr_url "http://localhost:8983/solr"
- solr_jetty_path "/var/chef/solr-jetty"
- solr_data_path "/var/chef/solr/data"
- solr_home_path "/var/chef/solr"
- solr_heap_size "256M"
- solr_java_opts nil
-
- # Parameters for connecting to RabbitMQ
- amqp_host '0.0.0.0'
- amqp_port '5672'
- amqp_user 'chef'
- amqp_pass 'testing'
- amqp_vhost '/chef'
- # Setting this to a UUID string also makes the queue durable
- # (persist across rabbitmq restarts)
- amqp_consumer_id "default"
-
# Sets the version of the signed header authentication protocol to use (see
# the 'mixlib-authorization' project for more detail). Currently, versions
# 1.0 and 1.1 are available; however, the chef-server must first be
diff --git a/chef/lib/chef/cookbook_uploader.rb b/chef/lib/chef/cookbook_uploader.rb
index 351a239bb8..8dd50ac043 100644
--- a/chef/lib/chef/cookbook_uploader.rb
+++ b/chef/lib/chef/cookbook_uploader.rb
@@ -4,7 +4,6 @@ require 'rest_client'
require 'chef/exceptions'
require 'chef/knife/cookbook_metadata'
require 'chef/checksum_cache'
-require 'chef/sandbox'
require 'chef/cookbook_version'
require 'chef/cookbook/syntax_check'
require 'chef/cookbook/file_system_file_vendor'
diff --git a/chef/lib/chef/cookbook_version.rb b/chef/lib/chef/cookbook_version.rb
index a6f95e2c3b..0e11174a07 100644
--- a/chef/lib/chef/cookbook_version.rb
+++ b/chef/lib/chef/cookbook_version.rb
@@ -24,86 +24,11 @@ require 'chef/node'
require 'chef/resource_definition_list'
require 'chef/recipe'
require 'chef/cookbook/file_vendor'
-require 'chef/checksum'
require 'chef/cookbook/metadata'
require 'chef/version_class'
class Chef
- #== Chef::MinimalCookbookVersion
- # MinimalCookbookVersion is a duck type of CookbookVersion, used
- # internally by Chef Server as an optimization when determining the
- # optimal cookbook set for a chef-client.
- #
- # MinimalCookbookVersion objects contain only enough information to
- # solve the cookbook collection for a given run list. They *do not*
- # contain enough information to generate the response.
- #
- # See also: Chef::CookbookVersionSelector
- class MinimalCookbookVersion
-
- include Comparable
-
- ID = "id".freeze
- NAME = 'name'.freeze
- KEY = 'key'.freeze
- VERSION = 'version'.freeze
- VALUE = 'value'.freeze
- DEPS = 'deps'.freeze
-
- DEPENDENCIES = 'dependencies'.freeze
-
- # Loads the full list of cookbooks, using a couchdb view to fetch
- # only the id, name, version, and dependency constraints. This is
- # enough information to solve for the cookbook collection for a
- # given run list. After solving for the cookbook collection, you
- # need to call +load_full_versions_of+ to convert
- # MinimalCookbookVersion objects to their non-minimal counterparts
- def self.load_all(couchdb)
- # Example:
- # {"id"=>"1a806f1c-b409-4d8e-abab-fa414ff5b96d", "key"=>"activemq", "value"=>{"version"=>"0.3.3", "deps"=>{"java"=>">= 0.0.0", "runit"=>">= 0.0.0"}}}
- couchdb ||= Chef::CouchDB.new
- couchdb.get_view("cookbooks", "all_with_version_and_deps")["rows"].map {|params| self.new(params) }
- end
-
- # Loads the non-minimal CookbookVersion objects corresponding to
- # +minimal_cookbook_versions+ from couchdb using a bulk GET.
- def self.load_full_versions_of(minimal_cookbook_versions, couchdb)
- database_ids = Array(minimal_cookbook_versions).map {|mcv| mcv.couchdb_id }
- couchdb ||= Chef::CouchDB.new
- couchdb.bulk_get(*database_ids)
- end
-
- attr_reader :couchdb_id
- attr_reader :name
- attr_reader :version
- attr_reader :deps
-
- def initialize(params)
- @couchdb_id = params[ID]
- @name = params[KEY]
- @version = params[VALUE][VERSION]
- @deps = params[VALUE][DEPS]
- end
-
- # Returns the Cookbook::MinimalMetadata object for this cookbook
- # version.
- def metadata
- @metadata ||= Cookbook::MinimalMetadata.new(@name, DEPENDENCIES => @deps)
- end
-
- def legit_version
- @legit_version ||= Chef::Version.new(@version)
- end
-
- def <=>(o)
- raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name
- raise "Unexpected comparison to #{o}" unless o.respond_to?(:legit_version)
- legit_version <=> o.legit_version
- end
- end
-
-
# == Chef::CookbookVersion
# CookbookVersion is a model object encapsulating the data about a Chef
# cookbook. Chef supports maintaining multiple versions of a cookbook on a
@@ -113,140 +38,10 @@ class Chef
# TODO: timh/cw: 5-24-2010: mutators for files (e.g., recipe_filenames=,
# recipe_filenames.insert) should dirty the manifest so it gets regenerated.
class CookbookVersion
- include Chef::IndexQueue::Indexable
include Comparable
COOKBOOK_SEGMENTS = [ :resources, :providers, :recipes, :definitions, :libraries, :attributes, :files, :templates, :root_files ]
- DESIGN_DOCUMENT = {
- "version" => 8,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "cookbook_version") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "cookbook_version") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- },
- "all_with_version" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "cookbook_version") {
- emit(doc.cookbook_name, doc.version);
- }
- }
- EOJS
- },
- "all_with_version_and_deps" => {
- "map" => <<-JS
- function(doc) {
- if (doc.chef_type == "cookbook_version") {
- emit(doc.cookbook_name, {version: doc.version, deps: doc.metadata.dependencies});
- }
- }
- JS
- },
- "all_latest_version" => {
- "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.split('.').map(function(v) { return parseInt(v); });
- var resultParts = result.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 result;
- }
- @
- },
- "all_latest_version_by_id" => {
- "map" => %q@
- function(doc) {
- if (doc.chef_type == "cookbook_version") {
- emit(doc.cookbook_name, {version: doc.version, id:doc._id});
- }
- }
- @,
- "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.version.split('.').map(function(v) { return parseInt(v); });
- var resultParts = result.version.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 result;
- }
- @
- },
- }
- }
-
attr_accessor :root_dir
attr_accessor :definition_filenames
attr_accessor :template_filenames
@@ -259,10 +54,6 @@ class Chef
attr_accessor :metadata
attr_accessor :metadata_filenames
attr_accessor :status
- attr_accessor :couchdb_rev
- attr_accessor :couchdb
-
- attr_reader :couchdb_id
# attribute_filenames also has a setter that has non-default
# functionality.
@@ -401,7 +192,7 @@ class Chef
#
# === Returns
# object<Chef::CookbookVersion>:: Duh. :)
- def initialize(name, couchdb=nil)
+ def initialize(name)
@name = name
@frozen = false
@attribute_filenames = Array.new
@@ -416,9 +207,6 @@ class Chef
@metadata_filenames = Array.new
@root_dir = nil
@root_filenames = Array.new
- @couchdb_id = nil
- @couchdb = couchdb || Chef::CouchDB.new
- @couchdb_rev = nil
@status = :ready
@manifest = nil
@file_vendor = nil
@@ -761,7 +549,6 @@ class Chef
result = manifest.dup
result['frozen?'] = frozen_version?
result['chef_type'] = 'cookbook_version'
- result["_rev"] = couchdb_rev if couchdb_rev
result.to_hash
end
@@ -773,15 +560,6 @@ class Chef
def self.json_create(o)
cookbook_version = new(o["cookbook_name"])
- if o.has_key?('_rev')
- cookbook_version.couchdb_rev = o["_rev"] if o.has_key?("_rev")
- o.delete("_rev")
- end
- if o.has_key?("_id")
- cookbook_version.couchdb_id = o["_id"] if o.has_key?("_id")
- cookbook_version.index_id = cookbook_version.couchdb_id
- o.delete("_id")
- end
# We want the Chef::Cookbook::Metadata object to always be inflated
cookbook_version.metadata = Chef::Cookbook::Metadata.from_hash(o["metadata"])
cookbook_version.manifest = o
@@ -888,83 +666,6 @@ class Chef
chef_server_rest.get_rest('cookbooks/_latest')
end
- ##
- # Couchdb
- ##
-
- def self.cdb_by_name(cookbook_name, couchdb=nil)
- 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 }
- end
-
- 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.map {|i|i["id"]}
- 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)
- couchdb ||= Chef::CouchDB.new
- if inflate
- couchdb.list("cookbooks", true)["rows"].collect{|r| r["value"]}
- else
- # If you modify this, please make sure the desc sorted order on the versions doesn't get broken.
- couchdb.get_view("cookbooks", "all_with_version")["rows"].inject({}) { |mapped, row| mapped[row["key"]]||=Array.new; mapped[row["key"]].push(Chef::Version.new(row["value"])); mapped[row["key"]].sort!.reverse!; mapped}
- end
- end
-
- def self.cdb_load(name, version='latest', couchdb=nil)
- cdb = couchdb || Chef::CouchDB.new
- if version == "latest" || version == "_latest"
- rs = cdb.get_view("cookbooks", "all_latest_version", :key => name, :descending => true, :group => true, :reduce => true)["rows"].first
- cdb.load("cookbook_version", "#{rs["key"]}-#{rs["value"]}")
- else
- cdb.load("cookbook_version", "#{name}-#{version}")
- end
- end
-
- def cdb_destroy
- (couchdb || Chef::CouchDB.new).delete("cookbook_version", full_name, couchdb_rev)
- end
-
- # Runs on Chef Server (API); deletes the cookbook from couchdb and also destroys associated
- # checksum documents
- def purge
- checksums.keys.each do |checksum|
- begin
- Chef::Checksum.cdb_load(checksum, couchdb).purge
- rescue Chef::Exceptions::CouchDBNotFound
- end
- end
- cdb_destroy
- end
-
- def cdb_save
- @couchdb_rev = couchdb.store("cookbook_version", full_name, self)["rev"]
- end
-
- def couchdb_id=(value)
- @couchdb_id = value
- @index_id = value
- end
-
def <=>(o)
raise Chef::Exceptions::CookbookVersionNameMismatch if self.name != o.name
# FIXME: can we change the interface to the Metadata class such
diff --git a/chef/lib/chef/cookbook_version_selector.rb b/chef/lib/chef/cookbook_version_selector.rb
deleted file mode 100644
index 9e60f85639..0000000000
--- a/chef/lib/chef/cookbook_version_selector.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-#
-# Author:: Tim Hinderliter (<tim@opscode.com>)
-# Copyright:: Copyright (c) 2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'dep_selector'
-
-class Chef
- module CookbookVersionSelector
- # This method replaces verbiage from DepSelector messages with
- # Chef-domain-specific verbiage, such as replacing package with
- # cookbook.
- #
- # TODO [cw, 2011/2/25]: this is a near-term hack. In the long run,
- # we'll do this better.
- def self.filter_dep_selector_message(message)
- m = message
- m.gsub!("Package", "Cookbook")
- m.gsub!("package", "cookbook")
- m.gsub!("Solution constraint", "Run list item")
- m.gsub!("solution constraint", "run list item")
- m
- end
-
- # all_cookbooks - a hash mapping cookbook names to an array of
- # available CookbookVersions.
- #
- # Creates a DependencyGraph from CookbookVersion objects
- def self.create_dependency_graph_from_cookbooks(all_cookbooks)
- dep_graph = DepSelector::DependencyGraph.new
-
- all_cookbooks.each do |cb_name, cb_versions|
- cb_versions.each do |cb_version|
- cb_version_deps = cb_version.metadata.dependencies
- # TODO [cw. 2011/2/10]: CookbookVersion#version returns a
- # String even though we're storing as a DepSelector::Version
- # object underneath. This should be changed so that we
- # return the object and handle proper serialization and
- # de-serialization. For now, I'm just going to create a
- # Version object from the String representation.
- pv = dep_graph.package(cb_name).add_version(Chef::Version.new(cb_version.version))
- cb_version_deps.each_pair do |dep_name, constraint_str|
- # if the dependency is specified as cookbook::recipe,
- # extract the cookbook component
- dep_cb_name = dep_name.split("::").first
- constraint = Chef::VersionConstraint.new(constraint_str)
- pv.dependencies << DepSelector::Dependency.new(dep_graph.package(dep_cb_name), constraint)
- end
- end
- end
-
- dep_graph
- end
-
- # Return a hash mapping cookbook names to a CookbookVersion
- # object. If there is no solution that satisfies the constraints,
- # the first run list item that caused unsatisfiability is
- # returned.
- #
- # This is the final version-resolved list of cookbooks for the
- # RunList.
- #
- # all_cookbooks - a hash mapping cookbook names to an array of
- # available CookbookVersions.
- #
- # recipe_constraints - an array of hashes describing the expanded
- # run list. Each element is a hash containing keys :name and
- # :version_constraint. The :name component is either the
- # fully-qualified recipe name (e.g. "cookbook1::non_default_recipe")
- # or just a cookbook name, indicating the default recipe is to be
- # run (e.g. "cookbook1").
- def self.constrain(all_cookbooks, recipe_constraints)
- dep_graph = create_dependency_graph_from_cookbooks(all_cookbooks)
-
- # extract cookbook names from (possibly) fully-qualified recipe names
- cookbook_constraints = recipe_constraints.map do |recipe_spec|
- cookbook_name = (recipe_spec[:name][/^(.+)::/, 1] || recipe_spec[:name])
- DepSelector::SolutionConstraint.new(dep_graph.package(cookbook_name),
- recipe_spec[:version_constraint])
- end
-
- # Pass in the list of all available cookbooks (packages) so that
- # DepSelector can distinguish between "no version available for
- # cookbook X" and "no such cookbook X" when an environment
- # filters out all versions for a given cookbook.
- all_packages = all_cookbooks.inject([]) do |acc, (cookbook_name, cookbook_versions)|
- acc << dep_graph.package(cookbook_name)
- acc
- end
-
- # find a valid assignment of CoookbookVersions. If no valid
- # assignment exists, indicate which run_list_item causes the
- # unsatisfiability and try to hint at what might be wrong.
- soln =
- begin
- DepSelector::Selector.new(dep_graph).find_solution(cookbook_constraints, all_packages)
- rescue DepSelector::Exceptions::InvalidSolutionConstraints => e
- non_existent_cookbooks = e.non_existent_packages.map {|constraint| constraint.package.name}
- cookbooks_with_no_matching_versions = e.constrained_to_no_versions.map {|constraint| constraint.package.name}
-
- # Spend a whole lot of effort for pluralizing and
- # prettifying the message.
- message = ""
- if non_existent_cookbooks.length > 0
- message += "no such " + (non_existent_cookbooks.length > 1 ? "cookbooks" : "cookbook")
- message += " #{non_existent_cookbooks.join(", ")}"
- end
-
- if cookbooks_with_no_matching_versions.length > 0
- if message.length > 0
- message += "; "
- end
-
- message += "no versions match the constraints on " + (cookbooks_with_no_matching_versions.length > 1 ? "cookbooks" : "cookbook")
- message += " #{cookbooks_with_no_matching_versions.join(", ")}"
- end
-
- message = "Run list contains invalid items: #{message}."
-
- raise Chef::Exceptions::CookbookVersionSelection::InvalidRunListItems.new(message, non_existent_cookbooks, cookbooks_with_no_matching_versions)
- rescue DepSelector::Exceptions::NoSolutionExists => e
- raise Chef::Exceptions::CookbookVersionSelection::UnsatisfiableRunListItem.new(filter_dep_selector_message(e.message), e.unsatisfiable_solution_constraint, e.disabled_non_existent_packages, e.disabled_most_constrained_packages)
- end
-
-
- # map assignment back to CookbookVersion objects
- selected_cookbooks = {}
- soln.each_pair do |cb_name, cb_version|
- # TODO [cw, 2011/2/10]: related to the TODO in
- # create_dependency_graph_from_cookbooks, cbv.version
- # currently returns a String, so we must compare to
- # cb_version.to_s, since it's a for-real Version object.
- selected_cookbooks[cb_name] = all_cookbooks[cb_name].find{|cbv| cbv.version == cb_version.to_s}
- end
- selected_cookbooks
- end
-
- # Expands the run_list, constrained to the environment's CookbookVersion
- # constraints.
- #
- # Returns:
- # Hash of: name to CookbookVersion
- def self.expand_to_cookbook_versions(run_list, environment, couchdb=nil)
- # expand any roles in this run_list.
- expanded_run_list = run_list.expand(environment, 'couchdb', :couchdb => couchdb).recipes.with_version_constraints
-
- cookbooks_for_environment = Chef::Environment.cdb_minimal_filtered_versions(environment, couchdb)
- cookbook_collection = constrain(cookbooks_for_environment, expanded_run_list)
- full_cookbooks = Chef::MinimalCookbookVersion.load_full_versions_of(cookbook_collection.values, couchdb)
- full_cookbooks.inject({}) do |cb_map, cookbook_version|
- cb_map[cookbook_version.name] = cookbook_version
- cb_map
- end
- end
- end
-end
diff --git a/chef/lib/chef/couchdb.rb b/chef/lib/chef/couchdb.rb
deleted file mode 100644
index 71ee196462..0000000000
--- a/chef/lib/chef/couchdb.rb
+++ /dev/null
@@ -1,246 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Christopher Brown (<cb@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'chef/mixin/params_validate'
-require 'chef/config'
-require 'chef/rest'
-require 'chef/log'
-require 'digest/sha2'
-require 'chef/json_compat'
-
-# We want to fail on create if uuidtools isn't installed
-begin
- require 'uuidtools'
-rescue LoadError
-end
-
-class Chef
- class CouchDB
- include Chef::Mixin::ParamsValidate
-
- def initialize(url=nil, db=Chef::Config[:couchdb_database])
- url ||= Chef::Config[:couchdb_url]
- @db = db
- @rest = Chef::REST.new(url, nil, nil)
- end
-
- def couchdb_database(args=nil)
- @db = args || @db
- end
-
- def create_id_map
- create_design_document(
- "id_map",
- {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "name_to_id" => {
- "map" => <<-EOJS
- function(doc) {
- emit([ doc.chef_type, doc.name], doc._id);
- }
- EOJS
- },
- "id_to_name" => {
- "map" => <<-EOJS
- function(doc) {
- emit(doc._id, [ doc.chef_type, doc.name ]);
- }
- EOJS
- }
- }
- }
- )
- end
-
- def create_db(check_for_existing=true)
- @database_list = @rest.get_rest("_all_dbs")
- if !check_for_existing || !@database_list.any? { |db| db == couchdb_database }
- response = @rest.put_rest(couchdb_database, Hash.new)
- end
- couchdb_database
- end
-
- def create_design_document(name, data)
- to_update = true
- begin
- old_doc = @rest.get_rest("#{couchdb_database}/_design/#{name}")
- if data["version"] != old_doc["version"]
- data["_rev"] = old_doc["_rev"]
- Chef::Log.debug("Updating #{name} views")
- else
- to_update = false
- end
- rescue
- Chef::Log.debug("Creating #{name} views for the first time because: #{$!}")
- end
- if to_update
- @rest.put_rest("#{couchdb_database}/_design%2F#{name}", data)
- end
- true
- end
-
- # Save the object to Couch. Add to index if the object supports it.
- def store(obj_type, name, object)
- validate(
- {
- :obj_type => obj_type,
- :name => name,
- :object => object,
- },
- {
- :object => { :respond_to => :to_json },
- }
- )
- rows = get_view("id_map", "name_to_id", :key => [ obj_type, name ])["rows"]
- uuid = rows.empty? ? UUIDTools::UUID.random_create.to_s : rows.first.fetch("id")
-
- db_put_response = @rest.put_rest("#{couchdb_database}/#{uuid}", object)
-
- if object.respond_to?(:add_to_index)
- Chef::Log.info("Sending #{obj_type}(#{uuid}) to the index queue for addition.")
- object.add_to_index(:database => couchdb_database, :id => uuid, :type => obj_type)
- end
-
- db_put_response
- end
-
- def load(obj_type, name)
- validate(
- {
- :obj_type => obj_type,
- :name => name,
- },
- {
- :obj_type => { :kind_of => String },
- :name => { :kind_of => String },
- }
- )
- doc = find_by_name(obj_type, name)
- doc.couchdb = self if doc.respond_to?(:couchdb)
- doc
- end
-
- def delete(obj_type, name, rev=nil)
- validate(
- {
- :obj_type => obj_type,
- :name => name,
- },
- {
- :obj_type => { :kind_of => String },
- :name => { :kind_of => String },
- }
- )
- del_id = nil
- object, uuid = find_by_name(obj_type, name, true)
- unless rev
- if object.respond_to?(:couchdb_rev)
- rev = object.couchdb_rev
- else
- rev = object['_rev']
- end
- end
- response = @rest.delete_rest("#{couchdb_database}/#{uuid}?rev=#{rev}")
- response.couchdb = self if response.respond_to?(:couchdb=)
-
- if object.respond_to?(:delete_from_index)
- Chef::Log.info("Sending #{obj_type}(#{uuid}) to the index queue for deletion..")
- object.delete_from_index(:database => couchdb_database, :id => uuid, :type => obj_type)
- end
-
- response
- end
-
- def list(view, inflate=false)
- validate(
- {
- :view => view,
- },
- {
- :view => { :kind_of => String }
- }
- )
- if inflate
- r = @rest.get_rest(view_uri(view, "all"))
- r["rows"].each { |i| i["value"].couchdb = self if i["value"].respond_to?(:couchdb=) }
- r
- else
- r = @rest.get_rest(view_uri(view, "all_id"))
- end
- r
- end
-
- def has_key?(obj_type, name)
- validate(
- {
- :obj_type => obj_type,
- :name => name,
- },
- {
- :obj_type => { :kind_of => String },
- :name => { :kind_of => String },
- }
- )
- begin
- find_by_name(obj_type, name)
- true
- rescue
- false
- end
- end
-
- def find_by_name(obj_type, name, with_id=false)
- r = get_view("id_map", "name_to_id", :key => [ obj_type, name ], :include_docs => true)
- if r["rows"].length == 0
- raise Chef::Exceptions::CouchDBNotFound, "Cannot find #{obj_type} #{name} in CouchDB!"
- end
- if with_id
- [ r["rows"][0]["doc"], r["rows"][0]["id"] ]
- else
- r["rows"][0]["doc"]
- end
- end
-
- def get_view(design, view, options={})
- view_string = view_uri(design, view)
- view_string << "?" if options.length != 0
- view_string << options.map { |k,v| "#{k}=#{URI.escape(v.to_json)}"}.join('&')
- @rest.get_rest(view_string)
- end
-
- def bulk_get(*to_fetch)
- response = @rest.post_rest("#{couchdb_database}/_all_docs?include_docs=true", { "keys" => to_fetch.flatten })
- response["rows"].collect { |r| r["doc"] }
- end
-
- def view_uri(design, view)
- "#{couchdb_database}/_design/#{design}/_view/#{view}"
- end
-
- def server_stats
- @rest.get_rest('/')
- end
-
- def db_stats
- @rest.get_rest("/#{@db}")
- end
-
- end
-end
diff --git a/chef/lib/chef/data_bag.rb b/chef/lib/chef/data_bag.rb
index 32188c0861..9ce6215b20 100644
--- a/chef/lib/chef/data_bag.rb
+++ b/chef/lib/chef/data_bag.rb
@@ -21,9 +21,7 @@
require 'chef/config'
require 'chef/mixin/params_validate'
require 'chef/mixin/from_file'
-require 'chef/couchdb'
require 'chef/data_bag_item'
-require 'chef/index_queue'
require 'chef/mash'
require 'chef/json_compat'
@@ -32,58 +30,18 @@ class Chef
include Chef::Mixin::FromFile
include Chef::Mixin::ParamsValidate
- include Chef::IndexQueue::Indexable
VALID_NAME = /^[\-[:alnum:]_]+$/
- DESIGN_DOCUMENT = {
- "version" => 2,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "data_bag") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "data_bag") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- },
- "entries" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "data_bag_item") {
- emit(doc.data_bag, doc.raw_data.id);
- }
- }
- EOJS
- }
- }
- }
-
def self.validate_name!(name)
unless name =~ VALID_NAME
raise Exceptions::InvalidDataBagName, "DataBags must have a name matching #{VALID_NAME.inspect}, you gave #{name.inspect}"
end
end
- attr_accessor :couchdb_rev, :couchdb_id, :couchdb
-
# Create a new Chef::DataBag
- def initialize(couchdb=nil)
+ def initialize
@name = ''
- @couchdb_rev = nil
- @couchdb_id = nil
- @couchdb = (couchdb || Chef::CouchDB.new)
end
def name(arg=nil)
@@ -100,7 +58,6 @@ class Chef
'json_class' => self.class.name,
"chef_type" => "data_bag",
}
- result["_rev"] = @couchdb_rev if @couchdb_rev
result
end
@@ -121,20 +78,9 @@ class Chef
def self.json_create(o)
bag = new
bag.name(o["name"])
- bag.couchdb_rev = o["_rev"] if o.has_key?("_rev")
- bag.couchdb_id = o["_id"] if o.has_key?("_id")
- bag.index_id = bag.couchdb_id
bag
end
- # List all the Chef::DataBag objects in the CouchDB. If inflate is set to true, you will get
- # the full list of all Roles, fully inflated.
- def self.cdb_list(inflate=false, couchdb=nil)
- rs = (couchdb || Chef::CouchDB.new).list("data_bags", inflate)
- lookup = (inflate ? "value" : "key")
- rs["rows"].collect { |r| r[lookup] }
- end
-
def self.list(inflate=false)
if inflate
# Can't search for all data bags like other objects, fall back to N+1 :(
@@ -147,11 +93,6 @@ class Chef
end
end
- # Load a Data Bag by name from CouchDB
- def self.cdb_load(name, couchdb=nil)
- (couchdb || Chef::CouchDB.new).load("data_bag", name)
- end
-
# Load a Data Bag by name via either the RESTful API or local data_bag_path if run in solo mode
def self.load(name)
if Chef::Config[:solo]
@@ -169,27 +110,10 @@ class Chef
end
end
- # Remove this Data Bag from CouchDB
- def cdb_destroy
- removed = @couchdb.delete("data_bag", @name, @couchdb_rev)
- rs = @couchdb.get_view("data_bags", "entries", :include_docs => true, :startkey => @name, :endkey => @name)
- rs["rows"].each do |row|
- row["doc"].couchdb = couchdb
- row["doc"].cdb_destroy
- end
- removed
- end
-
def destroy
chef_server_rest.delete_rest("data/#{@name}")
end
- # Save this Data Bag to the CouchDB
- def cdb_save
- results = @couchdb.store("data_bag", @name, self)
- @couchdb_rev = results["rev"]
- end
-
# Save the Data Bag via RESTful API
def save
begin
@@ -211,24 +135,6 @@ class Chef
self
end
- # List all the items in this Bag from CouchDB
- # The self.load method does this through the REST API
- def list(inflate=false)
- rs = nil
- if inflate
- rs = @couchdb.get_view("data_bags", "entries", :include_docs => true, :startkey => @name, :endkey => @name)
- rs["rows"].collect { |r| r["doc"] }
- else
- rs = @couchdb.get_view("data_bags", "entries", :startkey => @name, :endkey => @name)
- rs["rows"].collect { |r| r["value"] }
- end
- end
-
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("data_bags", DESIGN_DOCUMENT)
- end
-
# As a string
def to_s
"data_bag[#{@name}]"
diff --git a/chef/lib/chef/data_bag_item.rb b/chef/lib/chef/data_bag_item.rb
index 87bde509a5..3528ba724a 100644
--- a/chef/lib/chef/data_bag_item.rb
+++ b/chef/lib/chef/data_bag_item.rb
@@ -23,8 +23,6 @@ require 'forwardable'
require 'chef/config'
require 'chef/mixin/params_validate'
require 'chef/mixin/from_file'
-require 'chef/couchdb'
-require 'chef/index_queue'
require 'chef/data_bag'
require 'chef/mash'
require 'chef/json_compat'
@@ -36,35 +34,9 @@ class Chef
include Chef::Mixin::FromFile
include Chef::Mixin::ParamsValidate
- include Chef::IndexQueue::Indexable
VALID_ID = /^[\-[:alnum:]_]+$/
- DESIGN_DOCUMENT = {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "data_bag_item") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "data_bag_item") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- }
- }
- }
-
def self.validate_id!(id_str)
if id_str.nil? || ( id_str !~ VALID_ID )
raise Exceptions::InvalidDataBagItemID, "Data Bag items must have an id matching #{VALID_ID.inspect}, you gave: #{id_str.inspect}"
@@ -74,16 +46,12 @@ class Chef
# Define all Hash's instance methods as delegating to @raw_data
def_delegators(:@raw_data, *(Hash.instance_methods - Object.instance_methods))
- attr_accessor :couchdb_rev, :couchdb_id, :couchdb
attr_reader :raw_data
# Create a new Chef::DataBagItem
- def initialize(couchdb=nil)
- @couchdb_rev = nil
- @couchdb_id = nil
+ def initialize
@data_bag = nil
@raw_data = Mash.new
- @couchdb = couchdb || Chef::CouchDB.new
end
def chef_server_rest
@@ -138,7 +106,6 @@ class Chef
result = self.raw_data
result["chef_type"] = "data_bag_item"
result["data_bag"] = self.data_bag
- result["_rev"] = @couchdb_rev if @couchdb_rev
result
end
@@ -151,7 +118,6 @@ class Chef
"data_bag" => self.data_bag,
"raw_data" => self.raw_data
}
- result["_rev"] = @couchdb_rev if @couchdb_rev
result.to_json(*a)
end
@@ -169,24 +135,11 @@ class Chef
o.delete("chef_type")
o.delete("json_class")
o.delete("name")
- if o.has_key?("_rev")
- bag_item.couchdb_rev = o["_rev"]
- o.delete("_rev")
- end
- if o.has_key?("_id")
- bag_item.couchdb_id = o["_id"]
- bag_item.index_id = bag_item.couchdb_id
- o.delete("_id")
- end
+
bag_item.raw_data = Mash.new(o["raw_data"])
bag_item
end
- # Load a Data Bag Item by name from CouchDB
- def self.cdb_load(data_bag, name, couchdb=nil)
- (couchdb || Chef::CouchDB.new).load("data_bag_item", object_name(data_bag, name))
- end
-
# Load a Data Bag Item by name via either the RESTful API or local data_bag_path if run in solo mode
def self.load(data_bag, name)
if Chef::Config[:solo]
@@ -205,21 +158,10 @@ class Chef
end
end
- # Remove this Data Bag Item from CouchDB
- def cdb_destroy
- Chef::Log.debug "Destroying data bag item: #{self.inspect}"
- @couchdb.delete("data_bag_item", object_name, @couchdb_rev)
- end
-
def destroy(data_bag=data_bag, databag_item=name)
chef_server_rest.delete_rest("data/#{data_bag}/#{databag_item}")
end
- # Save this Data Bag Item to CouchDB
- def cdb_save
- @couchdb_rev = @couchdb.store("data_bag_item", object_name, self)["rev"]
- end
-
# Save this Data Bag Item via RESTful API
def save(item_id=@raw_data['id'])
r = chef_server_rest
@@ -242,11 +184,6 @@ class Chef
self
end
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("data_bag_items", DESIGN_DOCUMENT)
- end
-
def ==(other)
other.respond_to?(:to_hash) &&
other.respond_to?(:data_bag) &&
diff --git a/chef/lib/chef/environment.rb b/chef/lib/chef/environment.rb
index 1e2cea282b..00cc253083 100644
--- a/chef/lib/chef/environment.rb
+++ b/chef/lib/chef/environment.rb
@@ -22,8 +22,6 @@ require 'chef/config'
require 'chef/mash'
require 'chef/mixin/params_validate'
require 'chef/mixin/from_file'
-require 'chef/couchdb'
-require 'chef/index_queue'
require 'chef/version_constraint'
class Chef
@@ -33,52 +31,15 @@ class Chef
include Chef::Mixin::ParamsValidate
include Chef::Mixin::FromFile
- include Chef::IndexQueue::Indexable
COMBINED_COOKBOOK_CONSTRAINT = /(.+)(?:[\s]+)((?:#{Chef::VersionConstraint::OPS.join('|')})(?:[\s]+).+)$/.freeze
- attr_accessor :couchdb, :couchdb_rev
- attr_reader :couchdb_id
-
- DESIGN_DOCUMENT = {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "environment") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "environment") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- }
- }
- }
-
- def initialize(couchdb=nil)
+ def initialize
@name = ''
@description = ''
@default_attributes = Mash.new
@override_attributes = Mash.new
@cookbook_versions = Hash.new
- @couchdb_rev = nil
- @couchdb_id = nil
- @couchdb = couchdb || Chef::CouchDB.new
- end
-
- def couchdb_id=(value)
- @couchdb_id = value
- self.index_id = value
end
def chef_server_rest
@@ -163,7 +124,6 @@ class Chef
"default_attributes" => @default_attributes,
"override_attributes" => @override_attributes
}
- result["_rev"] = couchdb_rev if couchdb_rev
result
end
@@ -260,17 +220,9 @@ class Chef
environment.cookbook_versions(o["cookbook_versions"])
environment.default_attributes(o["default_attributes"])
environment.override_attributes(o["override_attributes"])
- environment.couchdb_rev = o["_rev"] if o.has_key?("_rev")
- environment.couchdb_id = o["_id"] if o.has_key?("_id")
environment
end
- def self.cdb_list(inflate=false, couchdb=nil)
- es = (couchdb || Chef::CouchDB.new).list("environments", inflate)
- lookup = (inflate ? "value" : "key")
- es["rows"].collect { |e| e[lookup] }
- end
-
def self.list(inflate=false)
if inflate
response = Hash.new
@@ -283,34 +235,14 @@ class Chef
end
end
- def self.cdb_load(name, couchdb=nil)
- (couchdb || Chef::CouchDB.new).load("environment", name)
- end
-
def self.load(name)
chef_server_rest.get_rest("environments/#{name}")
end
- def self.exists?(name, couchdb)
- begin
- self.cdb_load(name, couchdb)
- rescue Chef::Exceptions::CouchDBNotFound
- nil
- end
- end
-
- def cdb_destroy
- couchdb.delete("environment", @name, couchdb_rev)
- end
-
def destroy
chef_server_rest.delete_rest("environments/#{@name}")
end
- def cdb_save
- self.couchdb_rev = couchdb.store("environment", @name, self)["rev"]
- end
-
def save
begin
chef_server_rest.put_rest("environments/#{@name}", self)
@@ -326,106 +258,6 @@ class Chef
self
end
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("environments", DESIGN_DOCUMENT)
- end
-
- # Loads the set of Chef::CookbookVersion objects available to a given environment
- # === Returns
- # Hash
- # i.e.
- # {
- # "cookbook_name" => [ Chef::CookbookVersion ... ] ## the array of CookbookVersions is sorted highest to lowest
- # }
- #
- # There will be a key for every cookbook. If no CookbookVersions
- # are available for the specified environment the value will be an
- # empty list.
- #
- def self.cdb_load_filtered_cookbook_versions(name, couchdb=nil)
- version_constraints = cdb_load(name, couchdb).cookbook_versions.inject({}) {|res, (k,v)| res[k] = Chef::VersionConstraint.new(v); res}
-
- # inject all cookbooks into the hash while filtering out restricted versions, then sort the individual arrays
- cookbook_list = Chef::CookbookVersion.cdb_list(true, couchdb)
-
- filtered_list = cookbook_list.inject({}) do |res, cookbook|
- # FIXME: should cookbook.version return a Chef::Version?
- version = Chef::Version.new(cookbook.version)
- requirement_satisfied = version_constraints.has_key?(cookbook.name) ? version_constraints[cookbook.name].include?(version) : true
- # we want a key for every cookbook, even if no versions are available
- res[cookbook.name] ||= []
- res[cookbook.name] << cookbook if requirement_satisfied
- res
- end
-
- sorted_list = filtered_list.inject({}) do |res, (cookbook_name, versions)|
- res[cookbook_name] = versions.sort.reverse
- res
- end
-
- sorted_list
- end
-
- # Like +cdb_load_filtered_cookbook_versions+, loads the set of
- # cookbooks available in a given environment. The difference is that
- # this method will load Chef::MinimalCookbookVersion objects that
- # contain only the information necessary for solving a cookbook
- # collection for a given run list. The user of this method must call
- # Chef::MinimalCookbookVersion.load_full_versions_of() after solving
- # the cookbook collection to get the full objects.
- # === Returns
- # Hash
- # i.e.
- # {
- # "cookbook_name" => [ Chef::CookbookVersion ... ] ## the array of CookbookVersions is sorted highest to lowest
- # }
- #
- # There will be a key for every cookbook. If no CookbookVersions
- # are available for the specified environment the value will be an
- # empty list.
- def self.cdb_minimal_filtered_versions(name, couchdb=nil)
- version_constraints = cdb_load(name, couchdb).cookbook_versions.inject({}) {|res, (k,v)| res[k] = Chef::VersionConstraint.new(v); res}
-
- # inject all cookbooks into the hash while filtering out restricted versions, then sort the individual arrays
- cookbook_list = Chef::MinimalCookbookVersion.load_all(couchdb)
-
- filtered_list = cookbook_list.inject({}) do |res, cookbook|
- # FIXME: should cookbook.version return a Chef::Version?
- version = Chef::Version.new(cookbook.version)
- requirement_satisfied = version_constraints.has_key?(cookbook.name) ? version_constraints[cookbook.name].include?(version) : true
- # we want a key for every cookbook, even if no versions are available
- res[cookbook.name] ||= []
- res[cookbook.name] << cookbook if requirement_satisfied
- res
- end
-
- sorted_list = filtered_list.inject({}) do |res, (cookbook_name, versions)|
- res[cookbook_name] = versions.sort.reverse
- res
- end
-
- sorted_list
- end
-
- def self.cdb_load_filtered_recipe_list(name, couchdb=nil)
- cdb_load_filtered_cookbook_versions(name, couchdb).map do |cb_name, cb|
- if cb.empty? # no available versions
- [] # empty list elided with flatten
- else
- latest_version = cb.first
- latest_version.recipe_filenames_by_name.keys.map do |recipe|
- case recipe
- when DEFAULT
- cb_name
- else
- "#{cb_name}::#{recipe}"
- end
- end
- end
- end.flatten
- end
-
def self.load_filtered_recipe_list(environment)
chef_server_rest.get_rest("environments/#{environment}/recipes")
end
@@ -451,16 +283,5 @@ class Chef
end
end
- def self.create_default_environment(couchdb=nil)
- couchdb = couchdb || Chef::CouchDB.new
- begin
- Chef::Environment.cdb_load('_default', couchdb)
- rescue Chef::Exceptions::CouchDBNotFound
- env = Chef::Environment.new(couchdb)
- env.name '_default'
- env.description 'The default Chef environment'
- env.cdb_save
- end
- end
end
end
diff --git a/chef/lib/chef/exceptions.rb b/chef/lib/chef/exceptions.rb
index c5d213f8b3..87802639d3 100644
--- a/chef/lib/chef/exceptions.rb
+++ b/chef/lib/chef/exceptions.rb
@@ -54,7 +54,6 @@ class Chef
class Group < RuntimeError; end
class Link < RuntimeError; end
class Mount < RuntimeError; end
- class CouchDBNotFound < RuntimeError; end
class PrivateKeyMissing < RuntimeError; end
class CannotWritePrivateKey < RuntimeError; end
class RoleNotFound < RuntimeError; end
@@ -112,7 +111,7 @@ class Chef
# File operation attempted but no permissions to perform it
class InsufficientPermissions < RuntimeError; end
-
+
# Ifconfig failed
class Ifconfig < RuntimeError; end
diff --git a/chef/lib/chef/index_queue.rb b/chef/lib/chef/index_queue.rb
deleted file mode 100644
index b350949aae..0000000000
--- a/chef/lib/chef/index_queue.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require "singleton"
-require "bunny"
-
-require "chef/index_queue/amqp_client"
-require "chef/index_queue/indexable"
-require "chef/index_queue/consumer"
-
-class Chef
- module IndexQueue
- end
-end
diff --git a/chef/lib/chef/index_queue/amqp_client.rb b/chef/lib/chef/index_queue/amqp_client.rb
deleted file mode 100644
index a7d155f4d1..0000000000
--- a/chef/lib/chef/index_queue/amqp_client.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-class Chef
- module IndexQueue
- class AmqpClient
- VNODES = 1024
-
- include Singleton
-
- def initialize
- reset!
- end
-
- def reset!
- @amqp_client && amqp_client.connected? && amqp_client.stop
- @amqp_client = nil
- @exchange = nil
- end
-
- def stop
- @amqp_client && @amqp_client.stop
- end
-
- def amqp_client
- unless @amqp_client
- begin
- @amqp_client = Bunny.new(amqp_opts)
- Chef::Log.debug "Starting AMQP connection with client settings: #{@amqp_client.inspect}"
- @amqp_client.start
- @amqp_client.qos(:prefetch_count => 1)
- rescue Bunny::ServerDownError => e
- Chef::Log.fatal "Could not connect to rabbitmq. Is it running, reachable, and configured correctly?"
- raise e
- rescue Bunny::ProtocolError => e
- Chef::Log.fatal "Connection to rabbitmq refused. Check your rabbitmq configuration and chef's amqp* settings"
- raise e
- end
- end
- @amqp_client
- end
-
- def exchange
- @exchange ||= amqp_client.exchange("chef-indexer", :durable => true, :type => :fanout)
- end
-
- def disconnected!
- Chef::Log.error("Disconnected from the AMQP Broker (RabbitMQ)")
- @amqp_client = nil
- reset!
- end
-
- def queue_for_object(obj_id)
- retries = 0
- vnode_tag = obj_id_to_int(obj_id) % VNODES
- begin
- yield amqp_client.queue("vnode-#{vnode_tag}", :passive => false, :durable => true, :exclusive => false, :auto_delete => false)
- rescue Bunny::ServerDownError, Bunny::ConnectionError, Errno::ECONNRESET
- disconnected!
- if (retries += 1) < 2
- Chef::Log.info("Attempting to reconnect to the AMQP broker")
- retry
- else
- Chef::Log.fatal("Could not re-connect to the AMQP broker, giving up")
- raise
- end
- end
- end
-
- private
-
- # Sometimes object ids are "proper" UUIDs, like "64bc00eb-120b-b6a2-ec0e-34fc90d151be"
- # and sometimes they omit the dashes, like "64bc00eb120bb6a2ec0e34fc90d151be"
- # UUIDTools uses different methods to parse the different styles.
- def obj_id_to_int(obj_id)
- UUIDTools::UUID.parse(obj_id).to_i
- rescue ArgumentError
- UUIDTools::UUID.parse_hexdigest(obj_id).to_i
- end
-
- def durable_queue?
- !!Chef::Config[:amqp_consumer_id]
- end
-
- def consumer_id
- Chef::Config[:amqp_consumer_id] || UUIDTools::UUID.random_create.to_s
- end
-
- def amqp_opts
- { :spec => '08',
- :host => Chef::Config[:amqp_host],
- :port => Chef::Config[:amqp_port],
- :user => Chef::Config[:amqp_user],
- :pass => Chef::Config[:amqp_pass],
- :vhost => Chef::Config[:amqp_vhost]}
- end
-
- end
- end
-end
-
diff --git a/chef/lib/chef/index_queue/consumer.rb b/chef/lib/chef/index_queue/consumer.rb
deleted file mode 100644
index 8701cffa47..0000000000
--- a/chef/lib/chef/index_queue/consumer.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-class Chef
- module IndexQueue
- module Consumer
- module ClassMethods
- def expose(*methods)
- @exposed_methods = Array(@exposed_methods)
- @exposed_methods += methods
- end
-
- def exposed_methods
- @exposed_methods || []
- end
-
- def whitelisted?(method_name)
- exposed_methods.include?(method_name)
- end
- end
-
- def self.included(including_class)
- including_class.send(:extend, ClassMethods)
- end
-
- def run
- Chef::Log.debug("Starting Index Queue Consumer")
- AmqpClient.instance.queue # triggers connection setup
-
- begin
- AmqpClient.instance.queue.subscribe(:ack => true, :timeout => false) do |message|
- call_action_for_message(message)
- end
- rescue Bunny::ConnectionError, Errno::ECONNRESET, Bunny::ServerDownError
- AmqpClient.instance.disconnected!
- Chef::Log.warn "Connection to rabbitmq lost. attempting to reconnect"
- sleep 1
- retry
- end
- end
- alias :start :run
-
- def call_action_for_message(message)
- amqp_payload = Chef::JSONCompat.from_json(message[:payload], :create_additions => false, :max_nesting => false)
- action = amqp_payload["action"].to_sym
- app_payload = amqp_payload["payload"]
- assert_method_whitelisted(action)
- send(action, app_payload)
- end
-
- private
-
- def assert_method_whitelisted(method_name)
- unless self.class.whitelisted?(method_name)
- raise ArgumentError, "non-exposed method #{method_name} called via index queue"
- end
- end
-
- end
- end
-end
diff --git a/chef/lib/chef/index_queue/indexable.rb b/chef/lib/chef/index_queue/indexable.rb
deleted file mode 100644
index 73fd08bbb5..0000000000
--- a/chef/lib/chef/index_queue/indexable.rb
+++ /dev/null
@@ -1,109 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# Copyright:: Copyright (c) 2010 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-require 'chef/json_compat'
-
-class Chef
- module IndexQueue
- module Indexable
-
- module ClassMethods
-
- def index_object_type(explicit_type_name=nil)
- @index_object_type = explicit_type_name.to_s if explicit_type_name
- @index_object_type
- end
-
- # Resets all metadata used for indexing to nil. Used for testing
- def reset_index_metadata!
- @index_object_type = nil
- end
-
- end
-
- def self.included(including_class)
- including_class.send(:extend, ClassMethods)
- end
-
- attr_accessor :index_id
-
- def index_object_type
- self.class.index_object_type || Mixin::ConvertToClassName.snake_case_basename(self.class.name)
- end
-
- def with_indexer_metadata(indexer_metadata={})
- # changing input param symbol keys to strings, as the keys in hash that goes to solr are expected to be strings [cb]
- # Ruby 1.9 hates you, cb [dan]
- with_metadata = {}
- indexer_metadata.each_key do |key|
- with_metadata[key.to_s] = indexer_metadata[key]
- end
-
- with_metadata["type"] ||= self.index_object_type
- with_metadata["id"] ||= self.index_id
- with_metadata["database"] ||= Chef::Config[:couchdb_database]
- with_metadata["item"] ||= self.to_hash
- with_metadata["enqueued_at"] ||= Time.now.utc.to_i
-
- raise ArgumentError, "Type, Id, or Database missing in index operation: #{with_metadata.inspect}" if (with_metadata["id"].nil? or with_metadata["type"].nil?)
- with_metadata
- end
-
- def add_to_index(metadata={})
- Chef::Log.debug("Pushing item to index queue for addition: #{self.with_indexer_metadata(metadata)}")
- object_with_metadata = with_indexer_metadata(metadata)
- obj_id = object_with_metadata["id"]
- obj = {:action => :add, :payload => self.with_indexer_metadata(metadata)}
-
- publish_object(obj_id, obj)
- end
-
- def delete_from_index(metadata={})
- Chef::Log.debug("Pushing item to index queue for deletion: #{self.with_indexer_metadata(metadata)}")
- object_with_metadata = with_indexer_metadata(metadata)
- obj_id = object_with_metadata["id"]
- obj = {:action => :delete, :payload => self.with_indexer_metadata(metadata)}
-
- publish_object(obj_id, obj)
- end
-
- private
-
- # Uses the publisher to update the object's queue. If
- # Chef::Config[:persistent_queue] is true, the update is wrapped
- # in a transaction.
- def publish_object(object_id, object)
- publisher = AmqpClient.instance
- begin
- publisher.amqp_client.tx_select if Chef::Config[:persistent_queue]
- publisher.queue_for_object(object_id) do |queue|
- queue.publish(Chef::JSONCompat.to_json(object), :persistent => Chef::Config[:persistent_queue])
- end
- publisher.amqp_client.tx_commit if Chef::Config[:persistent_queue]
- rescue
- publisher.amqp_client.tx_rollback if Chef::Config[:persistent_queue]
- raise
- end
-
- true
- end
-
- end
- end
-end
diff --git a/chef/lib/chef/node.rb b/chef/lib/chef/node.rb
index 1229e0db28..92a2374bce 100644
--- a/chef/lib/chef/node.rb
+++ b/chef/lib/chef/node.rb
@@ -28,11 +28,9 @@ require 'chef/mixin/from_file'
require 'chef/mixin/deep_merge'
require 'chef/dsl/include_attribute'
require 'chef/environment'
-require 'chef/couchdb'
require 'chef/rest'
require 'chef/run_list'
require 'chef/node/attribute'
-require 'chef/index_queue'
require 'chef/mash'
require 'chef/json_compat'
require 'chef/search/query'
@@ -44,8 +42,7 @@ class Chef
def_delegators :attributes, :keys, :each_key, :each_value, :key?, :has_key?
- attr_accessor :recipe_list, :couchdb, :couchdb_rev, :run_state, :run_list
- attr_reader :couchdb_id
+ attr_accessor :recipe_list, :run_state, :run_list
attr_accessor :run_context
@@ -54,103 +51,9 @@ class Chef
include Chef::Mixin::CheckHelper
include Chef::Mixin::ParamsValidate
- include Chef::IndexQueue::Indexable
-
- DESIGN_DOCUMENT = {
- "version" => 11,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "node") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "node") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- },
- "status" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "node") {
- var to_emit = { "name": doc.name, "chef_environment": doc.chef_environment };
- if (doc["attributes"]["fqdn"]) {
- to_emit["fqdn"] = doc["attributes"]["fqdn"];
- } else {
- to_emit["fqdn"] = "Undefined";
- }
- if (doc["attributes"]["ipaddress"]) {
- to_emit["ipaddress"] = doc["attributes"]["ipaddress"];
- } else {
- to_emit["ipaddress"] = "Undefined";
- }
- if (doc["attributes"]["ohai_time"]) {
- to_emit["ohai_time"] = doc["attributes"]["ohai_time"];
- } else {
- to_emit["ohai_time"] = "Undefined";
- }
- if (doc["attributes"]["uptime"]) {
- to_emit["uptime"] = doc["attributes"]["uptime"];
- } else {
- to_emit["uptime"] = "Undefined";
- }
- if (doc["attributes"]["platform"]) {
- to_emit["platform"] = doc["attributes"]["platform"];
- } else {
- to_emit["platform"] = "Undefined";
- }
- if (doc["attributes"]["platform_version"]) {
- to_emit["platform_version"] = doc["attributes"]["platform_version"];
- } else {
- to_emit["platform_version"] = "Undefined";
- }
- if (doc["run_list"]) {
- to_emit["run_list"] = doc["run_list"];
- } else {
- to_emit["run_list"] = "Undefined";
- }
- emit(doc.name, to_emit);
- }
- }
- EOJS
- },
- "by_run_list" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "node") {
- if (doc['run_list']) {
- for (var i=0; i < doc.run_list.length; i++) {
- emit(doc['run_list'][i], doc.name);
- }
- }
- }
- }
- EOJS
- },
- "by_environment" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "node") {
- var env = (doc['chef_environment'] == null ? "_default" : doc['chef_environment']);
- emit(env, doc.name);
- }
- }
- EOJS
- }
- },
- }
# Create a new Chef::Node object.
- def initialize(couchdb=nil)
+ def initialize
@name = nil
@chef_environment = '_default'
@@ -158,18 +61,9 @@ class Chef
@attributes = Chef::Node::Attribute.new({}, {}, {}, {})
- @couchdb_rev = nil
- @couchdb_id = nil
- @couchdb = couchdb || Chef::CouchDB.new
-
@run_state = {}
end
- def couchdb_id=(value)
- @couchdb_id = value
- @index_id = value
- end
-
# Used by DSL
def node
self
@@ -470,7 +364,6 @@ class Chef
#Render correctly for run_list items so malformed json does not result
"run_list" => run_list.run_list.map { |item| item.to_s }
}
- result["_rev"] = couchdb_rev if couchdb_rev
result.to_json(*a)
end
@@ -502,17 +395,9 @@ class Chef
else
o["recipes"].each { |r| node.recipes << r }
end
- node.couchdb_rev = o["_rev"] if o.has_key?("_rev")
- node.couchdb_id = o["_id"] if o.has_key?("_id")
- node.index_id = node.couchdb_id
node
end
- def self.cdb_list_by_environment(environment, inflate=false, couchdb=nil)
- rs = (couchdb || Chef::CouchDB.new).get_view("nodes", "by_environment", :include_docs => inflate, :startkey => environment, :endkey => environment)
- inflate ? rs["rows"].collect {|r| r["doc"]} : rs["rows"].collect {|r| r["value"]}
- end
-
def self.list_by_environment(environment, inflate=false)
if inflate
response = Hash.new
@@ -523,14 +408,6 @@ class Chef
end
end
- # List all the Chef::Node objects in the CouchDB. If inflate is set to true, you will get
- # the full list of all Nodes, fully inflated.
- def self.cdb_list(inflate=false, couchdb=nil)
- rs =(couchdb || Chef::CouchDB.new).list("nodes", inflate)
- lookup = (inflate ? "value" : "key")
- rs["rows"].collect { |r| r[lookup] }
- end
-
def self.list(inflate=false)
if inflate
response = Hash.new
@@ -543,19 +420,6 @@ class Chef
end
end
- # Load a node by name from CouchDB
- def self.cdb_load(name, couchdb=nil)
- (couchdb || Chef::CouchDB.new).load("node", name)
- end
-
- def self.exists?(nodename, couchdb)
- begin
- self.cdb_load(nodename, couchdb)
- rescue Chef::Exceptions::CouchDBNotFound
- nil
- end
- end
-
def self.find_or_create(node_name)
load(node_name)
rescue Net::HTTPServerException => e
@@ -576,21 +440,11 @@ class Chef
Chef::REST.new(Chef::Config[:chef_server_url]).get_rest("nodes/#{name}")
end
- # Remove this node from the CouchDB
- def cdb_destroy
- couchdb.delete("node", name, couchdb_rev)
- end
-
# Remove this node via the REST API
def destroy
chef_server_rest.delete_rest("nodes/#{name}")
end
- # Save this node to the CouchDB
- def cdb_save
- @couchdb_rev = couchdb.store("node", name, self)["rev"]
- end
-
# Save this node via the REST API
def save
# Try PUT. If the node doesn't yet exist, PUT will return 404,
@@ -614,11 +468,6 @@ class Chef
self
end
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("nodes", DESIGN_DOCUMENT)
- end
-
def to_s
"node[#{name}]"
end
diff --git a/chef/lib/chef/openid_registration.rb b/chef/lib/chef/openid_registration.rb
deleted file mode 100644
index f7bb9595d9..0000000000
--- a/chef/lib/chef/openid_registration.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'chef/config'
-require 'chef/mixin/params_validate'
-require 'chef/couchdb'
-require 'chef/index_queue'
-require 'digest/sha1'
-require 'chef/json_compat'
-
-class Chef
- class OpenIDRegistration
-
- attr_accessor :name, :salt, :validated, :password, :couchdb_rev, :admin
-
- include Chef::Mixin::ParamsValidate
- include Chef::IndexQueue::Indexable
-
- DESIGN_DOCUMENT = {
- "version" => 3,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "openid_registration") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "openid_registration") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- },
- "validated" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "openid_registration") {
- if (doc.validated == true) {
- emit(doc.name, doc);
- }
- }
- }
- EOJS
- },
- "unvalidated" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "openid_registration") {
- if (doc.validated == false) {
- emit(doc.name, doc);
- }
- }
- }
- EOJS
- },
- },
- }
-
- # Create a new Chef::OpenIDRegistration object.
- def initialize()
- @name = nil
- @salt = nil
- @password = nil
- @validated = false
- @admin = false
- @couchdb_rev = nil
- @couchdb = Chef::CouchDB.new
- end
-
- def name=(n)
- @name = n.gsub(/\./, '_')
- end
-
- # Set the password for this object.
- def set_password(password)
- @salt = generate_salt
- @password = encrypt_password(@salt, password)
- 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,
- 'salt' => @salt,
- 'password' => @password,
- 'validated' => @validated,
- 'admin' => @admin,
- 'chef_type' => 'openid_registration',
- }
- result["_rev"] = @couchdb_rev if @couchdb_rev
- result.to_json(*a)
- end
-
- # Create a Chef::Node from JSON
- def self.json_create(o)
- me = new
- me.name = o["name"]
- me.salt = o["salt"]
- me.password = o["password"]
- me.validated = o["validated"]
- me.admin = o["admin"]
- me.couchdb_rev = o["_rev"] if o.has_key?("_rev")
- me
- end
-
- # List all the Chef::OpenIDRegistration objects in the CouchDB. If inflate is set to true, you will get
- # the full list of all registration objects. Otherwise, you'll just get the IDs
- def self.list(inflate=false)
- rs = Chef::CouchDB.new.list("registrations", inflate)
- if inflate
- rs["rows"].collect { |r| r["value"] }
- else
- rs["rows"].collect { |r| r["key"] }
- end
- end
-
- def self.cdb_list(*args)
- list(*args)
- end
-
- # Load an OpenIDRegistration by name from CouchDB
- def self.load(name)
- Chef::CouchDB.new.load("openid_registration", name)
- end
-
- # Whether or not there is an OpenID Registration with this key.
- def self.has_key?(name)
- Chef::CouchDB.new.has_key?("openid_registration", name)
- end
-
- # Remove this OpenIDRegistration from the CouchDB
- def destroy
- @couchdb.delete("openid_registration", @name, @couchdb_rev)
- end
-
- # Save this OpenIDRegistration to the CouchDB
- def save
- results = @couchdb.store("openid_registration", @name, self)
- @couchdb_rev = results["rev"]
- end
-
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- couchdb ||= Chef::CouchDB.new
- couchdb.create_design_document("registrations", DESIGN_DOCUMENT)
- end
-
- protected
-
- def generate_salt
- salt = Time.now.to_s
- chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
- 1.upto(30) { |i| salt << chars[rand(chars.size-1)] }
- salt
- end
-
- def encrypt_password(salt, password)
- Digest::SHA1.hexdigest("--#{salt}--#{password}--")
- end
-
- end
-end
diff --git a/chef/lib/chef/role.rb b/chef/lib/chef/role.rb
index c428472f1f..78bbfadb88 100644
--- a/chef/lib/chef/role.rb
+++ b/chef/lib/chef/role.rb
@@ -21,9 +21,7 @@
require 'chef/config'
require 'chef/mixin/params_validate'
require 'chef/mixin/from_file'
-require 'chef/couchdb'
require 'chef/run_list'
-require 'chef/index_queue'
require 'chef/mash'
require 'chef/json_compat'
require 'chef/search/query'
@@ -33,51 +31,14 @@ class Chef
include Chef::Mixin::FromFile
include Chef::Mixin::ParamsValidate
- include Chef::IndexQueue::Indexable
-
- DESIGN_DOCUMENT = {
- "version" => 6,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "role") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "role") {
- emit(doc.name, doc.name);
- }
- }
- EOJS
- }
- }
- }
-
- attr_accessor :couchdb_rev, :couchdb
- attr_reader :couchdb_id
# Create a new Chef::Role object.
- def initialize(couchdb=nil)
+ def initialize
@name = ''
@description = ''
@default_attributes = Mash.new
@override_attributes = Mash.new
@env_run_lists = {"_default" => Chef::RunList.new}
- @couchdb_rev = nil
- @couchdb_id = nil
- @couchdb = couchdb || Chef::CouchDB.new
- end
-
- def couchdb_id=(value)
- @couchdb_id = value
- self.index_id = value
end
def chef_server_rest
@@ -177,7 +138,6 @@ class Chef
accumulator
end
}
- result["_rev"] = couchdb_rev if couchdb_rev
result
end
@@ -214,20 +174,9 @@ class Chef
end
role.env_run_lists(env_run_list_hash)
- role.couchdb_rev = o["_rev"] if o.has_key?("_rev")
- role.index_id = role.couchdb_id
- role.couchdb_id = o["_id"] if o.has_key?("_id")
role
end
- # List all the Chef::Role objects in the CouchDB. If inflate is set to true, you will get
- # the full list of all Roles, fully inflated.
- def self.cdb_list(inflate=false, couchdb=nil)
- rs = (couchdb || Chef::CouchDB.new).list("roles", inflate)
- lookup = (inflate ? "value" : "key")
- rs["rows"].collect { |r| r[lookup] }
- end
-
# Get the list of all roles from the API.
def self.list(inflate=false)
if inflate
@@ -241,24 +190,11 @@ class Chef
end
end
- # Load a role by name from CouchDB
- def self.cdb_load(name, couchdb=nil)
- (couchdb || Chef::CouchDB.new).load("role", name)
- end
-
# Load a role by name from the API
def self.load(name)
chef_server_rest.get_rest("roles/#{name}")
end
- def self.exists?(rolename, couchdb)
- begin
- self.cdb_load(rolename, couchdb)
- rescue Chef::Exceptions::CouchDBNotFound
- nil
- end
- end
-
def environment(env_name)
chef_server_rest.get_rest("roles/#{@name}/environments/#{env_name}")
end
@@ -267,21 +203,11 @@ class Chef
chef_server_rest.get_rest("roles/#{@name}/environments")
end
- # Remove this role from the CouchDB
- def cdb_destroy
- couchdb.delete("role", @name, couchdb_rev)
- end
-
# Remove this role via the REST API
def destroy
chef_server_rest.delete_rest("roles/#{@name}")
end
- # Save this role to the CouchDB
- def cdb_save
- self.couchdb_rev = couchdb.store("role", @name, self)["rev"]
- end
-
# Save this role via the REST API
def save
begin
@@ -299,11 +225,6 @@ class Chef
self
end
- # Set up our CouchDB design document
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("roles", DESIGN_DOCUMENT)
- end
-
# As a string
def to_s
"role[#{@name}]"
@@ -328,22 +249,5 @@ class Chef
end
end
- # Sync all the json roles with couchdb from disk
- def self.sync_from_disk_to_couchdb
- Dir[File.join(Chef::Config[:role_path], "*.json")].each do |role_file|
- short_name = File.basename(role_file, ".json")
- Chef::Log.warn("Loading #{short_name}")
- r = Chef::Role.from_disk(short_name, "json")
- begin
- couch_role = Chef::Role.cdb_load(short_name)
- r.couchdb_rev = couch_role.couchdb_rev
- Chef::Log.debug("Replacing role #{short_name} with data from #{role_file}")
- rescue Chef::Exceptions::CouchDBNotFound
- Chef::Log.debug("Creating role #{short_name} with data from #{role_file}")
- end
- r.cdb_save
- end
- end
-
end
end
diff --git a/chef/lib/chef/run_list.rb b/chef/lib/chef/run_list.rb
index 1e4bdd255a..684c5e19fc 100644
--- a/chef/lib/chef/run_list.rb
+++ b/chef/lib/chef/run_list.rb
@@ -155,8 +155,6 @@ class Chef
RunListExpansionFromDisk.new(environment, @run_list_items)
when 'server'
RunListExpansionFromAPI.new(environment, @run_list_items, opts[:rest])
- when 'couchdb'
- RunListExpansionFromCouchDB.new(environment, @run_list_items, opts[:couchdb])
end
end
diff --git a/chef/lib/chef/run_list/run_list_expansion.rb b/chef/lib/chef/run_list/run_list_expansion.rb
index 690eb3392b..7b8108a2d4 100644
--- a/chef/lib/chef/run_list/run_list_expansion.rb
+++ b/chef/lib/chef/run_list/run_list_expansion.rb
@@ -21,7 +21,6 @@ require 'chef/mash'
require 'chef/mixin/deep_merge'
require 'chef/role'
-require 'chef/couchdb'
require 'chef/rest'
class Chef
@@ -188,19 +187,5 @@ class Chef
end
end
- # Expand a run list from couchdb. Used in chef-server-api
- class RunListExpansionFromCouchDB < RunListExpansion
-
- def couchdb
- source
- end
-
- def fetch_role(name, included_by)
- Chef::Role.cdb_load(name, couchdb)
- rescue Chef::Exceptions::CouchDBNotFound
- role_not_found(name, included_by)
- end
-
- end
end
end
diff --git a/chef/lib/chef/sandbox.rb b/chef/lib/chef/sandbox.rb
deleted file mode 100644
index 4d05a1db70..0000000000
--- a/chef/lib/chef/sandbox.rb
+++ /dev/null
@@ -1,153 +0,0 @@
-#
-# Author:: Tim Hinderliter (<tim@opscode.com>)
-# Copyright:: Copyright (c) 2010 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-require 'chef/log'
-require 'uuidtools'
-
-class Chef
- class Sandbox
- attr_accessor :is_completed, :create_time
- alias_method :is_completed?, :is_completed
- attr_reader :guid
-
- alias :name :guid
-
- attr_accessor :couchdb, :couchdb_id, :couchdb_rev
-
- # list of checksum ids
- attr_accessor :checksums
-
- DESIGN_DOCUMENT = {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "sandbox") {
- emit(doc.guid, doc);
- }
- }
- EOJS
- },
- "all_id" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "sandbox") {
- emit(doc.guid, doc.guid);
- }
- }
- EOJS
- },
- "all_incomplete" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "sandbox" && !doc.is_completed) {
- emit(doc.guid, doc.guid);
- }
- }
- EOJS
- },
- "all_completed" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "sandbox" && doc.is_completed) {
- emit(doc.guid, doc.guid);
- }
- }
- EOJS
- },
- }
- }
-
- # Creates a new Chef::Sandbox object.
- #
- # === Returns
- # object<Chef::Sandbox>:: Duh. :)
- def initialize(guid=nil, couchdb=nil)
- @guid = guid || UUIDTools::UUID.random_create.to_s.gsub(/\-/,'').downcase
- @is_completed = false
- @create_time = Time.now.iso8601
- @checksums = Array.new
- end
-
- def include?(checksum)
- @checksums.include?(checksum)
- end
-
- alias :member? :include?
-
- def to_json(*a)
- result = {
- :guid => guid,
- :name => name, # same as guid, used for id_map
- :checksums => checksums,
- :create_time => create_time,
- :is_completed => is_completed,
- :json_class => self.class.name,
- :chef_type => 'sandbox'
- }
- result["_rev"] = @couchdb_rev if @couchdb_rev
- result.to_json(*a)
- end
-
- def self.json_create(o)
- sandbox = new(o['guid'])
- sandbox.checksums = o['checksums']
- sandbox.create_time = o['create_time']
- sandbox.is_completed = o['is_completed']
- if o.has_key?('_rev')
- sandbox.couchdb_rev = o["_rev"]
- o.delete("_rev")
- end
- if o.has_key?("_id")
- sandbox.couchdb_id = o["_id"]
- #sandbox.index_id = sandbox.couchdb_id
- o.delete("_id")
- end
- sandbox
- end
-
- ##
- # Couchdb
- ##
-
- def self.create_design_document(couchdb=nil)
- (couchdb || Chef::CouchDB.new).create_design_document("sandboxes", DESIGN_DOCUMENT)
- end
-
- def self.cdb_list(inflate=false, couchdb=nil)
- rs = (couchdb || Chef::CouchDB.new).list("sandboxes", inflate)
- lookup = (inflate ? "value" : "key")
- rs["rows"].collect { |r| r[lookup] }
- end
-
- def self.cdb_load(guid, couchdb=nil)
- # Probably want to look for a view here at some point
- (couchdb || Chef::CouchDB.new).load("sandbox", guid)
- end
-
- def cdb_destroy
- (couchdb || Chef::CouchDB.new).delete("sandbox", guid, @couchdb_rev)
- end
-
- def cdb_save(couchdb=nil)
- @couchdb_rev = (couchdb || Chef::CouchDB.new).store("sandbox", guid, self)["rev"]
- end
-
- end
-end
diff --git a/chef/lib/chef/solr_query.rb b/chef/lib/chef/solr_query.rb
deleted file mode 100644
index 3360ecc24d..0000000000
--- a/chef/lib/chef/solr_query.rb
+++ /dev/null
@@ -1,187 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright (c) 2009-2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'chef/mixin/xml_escape'
-require 'chef/log'
-require 'chef/config'
-require 'chef/couchdb'
-require 'chef/solr_query/solr_http_request'
-require 'chef/solr_query/query_transform'
-
-class Chef
- class SolrQuery
-
- ID_KEY = "X_CHEF_id_CHEF_X"
- DEFAULT_PARAMS = Mash.new(:start => 0, :rows => 1000, :sort => "#{ID_KEY} asc", :wt => 'json', :indent => 'off').freeze
- FILTER_PARAM_MAP = {:database => 'X_CHEF_database_CHEF_X', :type => "X_CHEF_type_CHEF_X", :data_bag => 'data_bag'}
- VALID_PARAMS = [:start,:rows,:sort,:q,:type]
- BUILTIN_SEARCH_TYPES = ["role","node","client","environment"]
- DATA_BAG_ITEM = 'data_bag_item'
-
- include Chef::Mixin::XMLEscape
-
- attr_accessor :query
- attr_accessor :params
-
- # Create a new Query object - takes the solr_url and optional
- # Chef::CouchDB object to inflate objects into.
- def initialize(couchdb = nil)
- @filter_query = {}
- @params = {}
-
- if couchdb.nil?
- @database = Chef::Config[:couchdb_database]
- @couchdb = Chef::CouchDB.new(nil, Chef::Config[:couchdb_database])
- else
- unless couchdb.respond_to?(:couchdb_database)
- Chef::Log.warn("Passing the database name to Chef::Solr::Query initialization is deprecated. Please pass in the Chef::CouchDB object instead.")
- @database = couchdb
- @couchdb = Chef::CouchDB.new(nil, couchdb)
- else
- @database = couchdb.couchdb_database
- @couchdb = couchdb
- end
- end
- end
-
- def self.from_params(params, couchdb=nil)
- query = new(couchdb)
- query.params = VALID_PARAMS.inject({}) do |p, param_name|
- p[param_name] = params[param_name] if params.key?(param_name)
- p
- end
- query.update_filter_query_from_params
- query.update_query_from_params
- query
- end
-
- def filter_by(filter_query_params)
- filter_query_params.each do |key, value|
- @filter_query[FILTER_PARAM_MAP[key]] = value
- end
- end
-
- def filter_query
- @filter_query.map { |param, value| "+#{param}:#{value}" }.join(' ')
- end
-
- def filter_by_type(type)
- case type
- when *BUILTIN_SEARCH_TYPES
- filter_by(:type => type)
- else
- filter_by(:type => DATA_BAG_ITEM, :data_bag => type)
- end
- end
-
- def update_filter_query_from_params
- filter_by(:database => @database)
- filter_by_type(params.delete(:type))
- end
-
- def update_query_from_params
- original_query = URI.decode(params.delete(:q) || "*:*")
- @query = Chef::SolrQuery::QueryTransform.transform(original_query)
- end
-
- def objects
- if !object_ids.empty?
- @bulk_objects ||= @couchdb.bulk_get(object_ids)
- Chef::Log.debug { "Bulk get of objects: #{@bulk_objects.inspect}" }
- @bulk_objects
- else
- []
- end
- end
-
- def object_ids
- @object_ids ||= results["response"]["docs"].map { |d| d[ID_KEY] }
- end
-
- def results
- @results ||= SolrHTTPRequest.select(self.to_hash)
- end
-
- # Search Solr for objects of a given type, for a given query.
- def search
- { "rows" => objects, "start" => results["response"]["start"],
- "total" => results["response"]["numFound"] }
- end
-
- def to_hash
- options = DEFAULT_PARAMS.merge(params)
- options[:fq] = filter_query
- options[:q] = @query
- options
- end
-
- START_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".freeze
- START_DELETE_BY_QUERY = "<delete><query>".freeze
- END_DELETE_BY_QUERY = "</query></delete>\n".freeze
- COMMIT = "<commit/>\n".freeze
-
- def commit(opts={})
- SolrHTTPRequest.update("#{START_XML}#{COMMIT}")
- end
-
- def delete_database(db)
- query_data = xml_escape("X_CHEF_database_CHEF_X:#{db}")
- xml = "#{START_XML}#{START_DELETE_BY_QUERY}#{query_data}#{END_DELETE_BY_QUERY}"
- SolrHTTPRequest.update(xml)
- commit
- end
-
- def rebuild_index(db=Chef::Config[:couchdb_database])
- delete_database(db)
-
- results = {}
- [Chef::ApiClient, Chef::Node, Chef::Role, Chef::Environment].each do |klass|
- results[klass.name] = reindex_all(klass) ? "success" : "failed"
- end
- databags = Chef::DataBag.cdb_list(true)
- Chef::Log.info("Reloading #{databags.size.to_s} #{Chef::DataBag} objects into the indexer")
- databags.each { |i| i.add_to_index; i.list(true).each { |x| x.add_to_index } }
- results[Chef::DataBag.name] = "success"
- results
- end
-
- def reindex_all(klass, metadata={})
- begin
- items = klass.cdb_list(true)
- Chef::Log.info("Reloading #{items.size.to_s} #{klass.name} objects into the indexer")
- items.each { |i| i.add_to_index }
- rescue Net::HTTPServerException => e
- # 404s are okay, there might not be any of that kind of object...
- if e.message =~ /Not Found/
- Chef::Log.warn("Could not load #{klass.name} objects from couch for re-indexing (this is ok if you don't have any of these)")
- return false
- else
- raise e
- end
- rescue Exception => e
- Chef::Log.fatal("Chef encountered an error while attempting to load #{klass.name} objects back into the index")
- raise e
- end
- true
- end
-
-
- end
-end
diff --git a/chef/lib/chef/solr_query/lucene.treetop b/chef/lib/chef/solr_query/lucene.treetop
deleted file mode 100644
index 99d3e1f709..0000000000
--- a/chef/lib/chef/solr_query/lucene.treetop
+++ /dev/null
@@ -1,150 +0,0 @@
-#
-# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-grammar Lucene
-
- rule body
- (expression / space)* <Body>
- end
-
- rule expression
- operation / group / field / field_range / term / string
- end
-
- rule term
- keyword valid_letter+ <Term> / !keyword !"?" valid_letter <Term>
- end
-
- rule field
- field_name ":" (term/string/group) <Field>
- end
-
- rule field_range
- field_name ":" "[" range_value " TO " range_value "]" <InclFieldRange>
- /
- field_name ":" "{" range_value " TO " range_value "}" <ExclFieldRange>
- end
-
- rule field_name
- !keyword valid_letter+ <FieldName>
- end
-
- rule range_value
- valid_letter+ <RangeValue> / "*" <RangeValue>
- end
-
- rule group
- space? '(' body ')' space? <Group>
- end
-
- rule operation
- binary_op / unary_op / fuzzy_op / boost_op
- end
-
- rule unary_op
- not_op / required_op / prohibited_op
- end
-
- rule binary_op
- (group / field / field_range / term) space? boolean_operator space+ body <BinaryOp>
- end
-
- rule boolean_operator
- and_operator / or_operator
- end
-
- rule and_operator
- 'AND' <AndOperator> / '&&' <AndOperator>
- end
-
- rule or_operator
- 'OR' <OrOperator> / '||' <OrOperator>
- end
-
- rule not_op
- not_operator space (group / field / field_range / term / string) <UnaryOp>
- /
- bang_operator space? (group / field / field_range / term / string) <UnaryOp>
- end
-
- rule not_operator
- 'NOT' <NotOperator>
- end
-
- rule bang_operator
- '!' <NotOperator>
- end
-
- rule required_op
- !valid_letter required_operator (term/string) <UnaryOp>
- /
- required_operator (term/string) <UnaryOp>
- end
-
- rule required_operator
- '+' <RequiredOperator>
- end
-
- rule prohibited_op
- !valid_letter prohibited_operator (field/field_range/term/string) <UnaryOp>
- end
-
- rule prohibited_operator
- '-' <ProhibitedOperator>
- end
-
- rule boost_op
- (term/string) '^' fuzzy_param <BoostOp>
- end
-
- rule fuzzy_op
- (term/string) '~' fuzzy_param? (space / !valid_letter) <FuzzyOp>
- end
-
- rule fuzzy_param
- [0-9] '.'? [0-9] <FuzzyParam> / [0-9]+ <FuzzyParam>
- end
-
- rule string
- '"' term (space term)* '"' <Phrase>
- end
-
- rule keyword
- 'AND' / 'OR' / 'NOT'
- end
-
- rule valid_letter
- start_letter+ ([a-zA-Z0-9@*?_.-] / '\\' special_char)*
- end
-
- rule start_letter
- [a-zA-Z0-9@._*] / '\\' special_char
- end
-
- rule end_letter
- [a-zA-Z0-9*?_.] / '\\' special_char
- end
-
- rule special_char
- [-+&|!(){}\[\]^"~*?:\\]
- end
-
- rule space
- [\s]+
- end
-end
diff --git a/chef/lib/chef/solr_query/lucene_nodes.rb b/chef/lib/chef/solr_query/lucene_nodes.rb
deleted file mode 100644
index c2d7777365..0000000000
--- a/chef/lib/chef/solr_query/lucene_nodes.rb
+++ /dev/null
@@ -1,285 +0,0 @@
-#
-# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'treetop'
-
-module Lucene
- SEP = "__=__"
-
- class Term < Treetop::Runtime::SyntaxNode
- def to_array
- "T:#{self.text_value}"
- end
-
- def transform
- self.text_value
- end
- end
-
- class Field < Treetop::Runtime::SyntaxNode
- def to_array
- field = self.elements[0].text_value
- term = self.elements[1].to_array
- "(F:#{field} #{term})"
- end
-
- def transform
- field = self.elements[0].text_value
- term = self.elements[1]
- if term.is_a? Phrase
- str = term.transform
- # remove quotes
- str = str[1 ... (str.length - 1)]
- "content:\"#{field}#{SEP}#{str}\""
- else
- "content:#{field}#{SEP}#{term.transform}"
- end
- end
- end
-
- class FieldRange < Treetop::Runtime::SyntaxNode
-
- def to_array
- field = self.elements[0].text_value
- range_start = self.elements[1].to_array
- range_end = self.elements[2].to_array
- "(FR:#{field} #{left}#{range_start}#{right} #{left}#{range_end}#{right})"
- end
-
- def transform
- field = self.elements[0].text_value
- range_start = self.elements[1].transform
- range_end = self.elements[2].transform
- # FIXME: handle special cases for missing start/end
- if ("*" == range_start && "*" == range_end)
- "content:#{field}#{SEP}*"
- elsif "*" == range_end
- "content:#{left}#{field}#{SEP}#{range_start} TO #{field}#{SEP}\\ufff0#{right}"
- elsif "*" == range_start
- "content:#{left}#{field}#{SEP} TO #{field}#{SEP}#{range_end}#{right}"
- else
- "content:#{left}#{field}#{SEP}#{range_start} TO #{field}#{SEP}#{range_end}#{right}"
- end
- end
-
- end
-
- class InclFieldRange < FieldRange
- def left
- "["
- end
- def right
- "]"
- end
- end
-
- class ExclFieldRange < FieldRange
- def left
- "{"
- end
- def right
- "}"
- end
- end
-
- class RangeValue < Treetop::Runtime::SyntaxNode
- def to_array
- self.text_value
- end
-
- def transform
- to_array
- end
- end
-
- class FieldName < Treetop::Runtime::SyntaxNode
- def to_array
- self.text_value
- end
-
- def transform
- to_array
- end
- end
-
-
- class Body < Treetop::Runtime::SyntaxNode
- def to_array
- self.elements.map { |x| x.to_array }.join(" ")
- end
-
- def transform
- self.elements.map { |x| x.transform }.join(" ")
- end
- end
-
- class Group < Treetop::Runtime::SyntaxNode
- def to_array
- "(" + self.elements[0].to_array + ")"
- end
-
- def transform
- "(" + self.elements[0].transform + ")"
- end
- end
-
- class BinaryOp < Treetop::Runtime::SyntaxNode
- def to_array
- op = self.elements[1].to_array
- a = self.elements[0].to_array
- b = self.elements[2].to_array
- "(#{op} #{a} #{b})"
- end
-
- def transform
- op = self.elements[1].transform
- a = self.elements[0].transform
- b = self.elements[2].transform
- "#{a} #{op} #{b}"
- end
- end
-
- class AndOperator < Treetop::Runtime::SyntaxNode
- def to_array
- "OP:AND"
- end
-
- def transform
- "AND"
- end
- end
-
- class OrOperator < Treetop::Runtime::SyntaxNode
- def to_array
- "OP:OR"
- end
-
- def transform
- "OR"
- end
- end
-
- class FuzzyOp < Treetop::Runtime::SyntaxNode
- def to_array
- a = self.elements[0].to_array
- param = self.elements[1]
- if param
- "(OP:~ #{a} #{param.to_array})"
- else
- "(OP:~ #{a})"
- end
- end
-
- def transform
- a = self.elements[0].transform
- param = self.elements[1]
- if param
- "#{a}~#{param.transform}"
- else
- "#{a}~"
- end
- end
- end
-
- class BoostOp < Treetop::Runtime::SyntaxNode
- def to_array
- a = self.elements[0].to_array
- param = self.elements[1]
- "(OP:^ #{a} #{param.to_array})"
- end
-
- def transform
- a = self.elements[0].transform
- param = self.elements[1]
- "#{a}^#{param.transform}"
- end
- end
-
- class FuzzyParam < Treetop::Runtime::SyntaxNode
- def to_array
- self.text_value
- end
-
- def transform
- self.text_value
- end
- end
-
- class UnaryOp < Treetop::Runtime::SyntaxNode
- def to_array
- op = self.elements[0].to_array
- a = self.elements[1].to_array
- "(#{op} #{a})"
- end
-
- def transform
- op = self.elements[0].transform
- a = self.elements[1].transform
- spc = case op
- when "+", "-"
- ""
- else
- " "
- end
- "#{op}#{spc}#{a}"
- end
-
- end
-
- class NotOperator < Treetop::Runtime::SyntaxNode
- def to_array
- "OP:NOT"
- end
-
- def transform
- "NOT"
- end
-
- end
-
- class RequiredOperator < Treetop::Runtime::SyntaxNode
- def to_array
- "OP:+"
- end
-
- def transform
- "+"
- end
-
- end
-
- class ProhibitedOperator < Treetop::Runtime::SyntaxNode
- def to_array
- "OP:-"
- end
-
- def transform
- "-"
- end
- end
-
- class Phrase < Treetop::Runtime::SyntaxNode
- def to_array
- "STR:#{self.text_value}"
- end
-
- def transform
- "#{self.text_value}"
- end
- end
-end
diff --git a/chef/lib/chef/solr_query/query_transform.rb b/chef/lib/chef/solr_query/query_transform.rb
deleted file mode 100644
index 529f9de482..0000000000
--- a/chef/lib/chef/solr_query/query_transform.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-require 'treetop'
-require 'chef/solr_query/lucene_nodes'
-
-class Chef
- class Exceptions
- class QueryParseError < StandardError
- end
- end
-end
-
-class Chef
- class SolrQuery
- class QueryTransform
- @@base_path = File.expand_path(File.dirname(__FILE__))
- Treetop.load(File.join(@@base_path, 'lucene.treetop'))
- @@parser = LuceneParser.new
-
- def self.parse(data)
- tree = @@parser.parse(data)
- msg = "Parse error at offset: #{@@parser.index}\n"
- msg += "Reason: #{@@parser.failure_reason}"
- raise Chef::Exceptions::QueryParseError, msg if tree.nil?
- self.clean_tree(tree)
- tree.to_array
- end
-
- def self.transform(data)
- return "*:*" if data == "*:*"
- tree = @@parser.parse(data)
- msg = "Parse error at offset: #{@@parser.index}\n"
- msg += "Reason: #{@@parser.failure_reason}"
- raise Chef::Exceptions::QueryParseError, msg if tree.nil?
- self.clean_tree(tree)
- tree.transform
- end
-
- private
-
- def self.clean_tree(root_node)
- return if root_node.elements.nil?
- root_node.elements.delete_if do |node|
- node.class.name == "Treetop::Runtime::SyntaxNode"
- end
- root_node.elements.each { |node| self.clean_tree(node) }
- end
- end
- end
-end
diff --git a/chef/lib/chef/solr_query/solr_http_request.rb b/chef/lib/chef/solr_query/solr_http_request.rb
deleted file mode 100644
index e7ce1d5675..0000000000
--- a/chef/lib/chef/solr_query/solr_http_request.rb
+++ /dev/null
@@ -1,132 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Copyright:: Copyright (c) 2009-2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'net/http'
-require 'uri'
-require 'chef/json_compat'
-require 'chef/config'
-
-class Chef
- class SolrQuery
- class SolrHTTPRequest
- CLASS_FOR_METHOD = {:GET => Net::HTTP::Get, :POST => Net::HTTP::Post}
-
- TEXT_XML = {"Content-Type" => "text/xml"}
-
- def self.solr_url=(solr_url)
- @solr_url = solr_url
- @http_client = nil
- @url_prefix = nil
- end
-
- def self.solr_url
- @solr_url || Chef::Config[:solr_url]
- end
-
- def self.http_client
- @http_client ||= begin
- uri = URI.parse(solr_url)
- http_client = Net::HTTP.new(uri.host, uri.port)
- http_client.use_ssl = true if uri.port == 443
- http_client
- end
- end
-
- def self.url_prefix
- @url_prefix ||= begin
- uri = URI.parse(solr_url)
- if uri.path == ""
- "/solr"
- else
- uri.path.gsub(%r{/$}, '')
- end
- end
- end
-
- def self.select(params={})
- url = "#{url_prefix}/select?#{url_join(params)}"
- Chef::Log.debug("Sending #{url} to Solr")
- request = new(:GET, url)
- json_response = request.run("Search Query to Solr '#{solr_url}#{url}'")
- Chef::JSONCompat.from_json(json_response)
- end
-
- def self.update(doc)
- url = "#{url_prefix}/update"
- Chef::Log.debug("POSTing document to SOLR:\n#{doc}")
- request = new(:POST, url, TEXT_XML) { |req| req.body = doc.to_s }
- request.run("POST to Solr '#{solr_url}#{url}', data: #{doc}")
- end
-
- def self.url_join(params_hash={})
- params = params_hash.inject("") do |param_str, params|
- param_str << "#{params[0]}=#{escape(params[1])}&"
- end
- params.chop! # trailing &
- params
- end
-
- def self.escape(s)
- s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
- '%'+$1.unpack('H2'*$1.size).join('%').upcase
- }.tr(' ', '+')
- end
-
- def initialize(method, url, headers=nil)
- args = headers ? [url, headers] : url
- @request = CLASS_FOR_METHOD[method].new(*args)
- yield @request if block_given?
- end
-
- def http_client
- self.class.http_client
- end
-
- def solr_url
- self.class.solr_url
- end
-
- def run(description="HTTP Request to Solr")
- response = http_client.request(@request)
- request_failed!(response, description) unless response.kind_of?(Net::HTTPSuccess)
- response.body
- rescue NoMethodError => e
- # http://redmine.ruby-lang.org/issues/show/2708
- # http://redmine.ruby-lang.org/issues/show/2758
- if e.to_s =~ /#{Regexp.escape(%q|undefined method 'closed?' for nil:NilClass|)}/
- Chef::Log.fatal("#{description} failed. Chef::Exceptions::SolrConnectionError exception: Errno::ECONNREFUSED (net/http undefined method closed?) attempting to contact #{solr_url}")
- Chef::Log.debug("Rescued error in http connect, treating it as Errno::ECONNREFUSED to hide bug in net/http")
- Chef::Log.debug(e.backtrace.join("\n"))
- raise Chef::Exceptions::SolrConnectionError, "Errno::ECONNREFUSED: Connection refused attempting to contact #{solr_url}"
- else
- raise
- end
- end
-
- def request_failed!(response, description='HTTP call')
- Chef::Log.fatal("#{description} failed (#{response.class} #{response.code} #{response.message})")
- response.error!
- rescue Timeout::Error, Errno::EINVAL, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT => e
- Chef::Log.debug(e.backtrace.join("\n"))
- raise Chef::Exceptions::SolrConnectionError, "#{e.class.name}: #{e.to_s}"
- end
-
- end
- end
-end
diff --git a/chef/lib/chef/webui_user.rb b/chef/lib/chef/webui_user.rb
deleted file mode 100644
index e0dbde4a61..0000000000
--- a/chef/lib/chef/webui_user.rb
+++ /dev/null
@@ -1,156 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Author:: Nuo Yan (<nuo@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'chef/config'
-require 'chef/mixin/params_validate'
-require 'chef/index_queue'
-require 'digest/sha1'
-require 'chef/json_compat'
-
-
-class Chef
- class WebUIUser
-
- attr_accessor :name, :validated, :admin, :openid, :couchdb
- attr_reader :password, :salt, :couchdb_id, :couchdb_rev
-
- include Chef::Mixin::ParamsValidate
-
- # Create a new Chef::WebUIUser object.
- def initialize(opts={})
- @name, @salt, @password = opts['name'], opts['salt'], opts['password']
- @openid = opts['openid']
- @admin = false
- end
-
- def name=(n)
- @name = n.gsub(/\./, '_')
- end
-
- def admin?
- admin
- end
-
- # Set the password for this object.
- def set_password(password, confirm_password=password)
- raise ArgumentError, "Passwords do not match" unless password == confirm_password
- raise ArgumentError, "Password cannot be blank" if (password.nil? || password.length==0)
- raise ArgumentError, "Password must be a minimum of 6 characters" if password.length < 6
- generate_salt
- @password = encrypt_password(password)
- end
-
- def set_openid(given_openid)
- @openid = given_openid
- end
-
- def verify_password(given_password)
- encrypt_password(given_password) == @password
- 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,
- 'salt' => salt,
- 'password' => password,
- 'openid' => openid,
- 'admin' => admin,
- 'chef_type' => 'webui_user',
- }
- result["_id"] = @couchdb_id if @couchdb_id
- result["_rev"] = @couchdb_rev if @couchdb_rev
- result.to_json(*a)
- end
-
- # Create a Chef::WebUIUser from JSON
- def self.json_create(o)
- me = new(o)
- me.admin = o["admin"]
- me
- end
-
- def chef_server_rest
- Chef::REST.new(Chef::Config[:chef_server_url])
- end
-
- def self.chef_server_rest
- Chef::REST.new(Chef::Config[:chef_server_url])
- end
-
- def self.list(inflate=false)
- if inflate
- response = Hash.new
- Chef::Search::Query.new.search(:user) do |n|
- response[n.name] = n unless n.nil?
- end
- response
- else
- chef_server_rest.get_rest("users")
- end
- end
-
- # Load a User by name
- def self.load(name)
- chef_server_rest.get_rest("users/#{name}")
- end
-
- # Remove this WebUIUser via the REST API
- def destroy
- chef_server_rest.delete_rest("users/#{@name}")
- end
-
- # Save this WebUIUser via the REST API
- def save
- begin
- chef_server_rest.put_rest("users/#{@name}", self)
- rescue Net::HTTPServerException => e
- if e.response.code == "404"
- chef_server_rest.post_rest("users", self)
- else
- raise e
- end
- end
- self
- end
-
- # Create the WebUIUser via the REST API
- def create
- chef_server_rest.post_rest("users", self)
- self
- end
-
- protected
-
- def generate_salt
- @salt = Time.now.to_s
- chars = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
- 1.upto(30) { |i| @salt << chars[rand(chars.size-1)] }
- @salt
- end
-
- def encrypt_password(password)
- Digest::SHA1.hexdigest("--#{salt}--#{password}--")
- end
-
- end
-end
diff --git a/chef/spec/unit/api_client_spec.rb b/chef/spec/unit/api_client_spec.rb
index b9d9cecc01..e01243152e 100644
--- a/chef/spec/unit/api_client_spec.rb
+++ b/chef/spec/unit/api_client_spec.rb
@@ -6,9 +6,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -57,8 +57,8 @@ describe Chef::ApiClient do
end
it "should return the current admin value" do
- @client.admin true
- @client.admin.should == true
+ @client.admin true
+ @client.admin.should == true
end
it "should default to false" do
@@ -82,7 +82,7 @@ describe Chef::ApiClient do
it "should throw an ArgumentError if you feed it something lame" do
lambda { @client.public_key Hash.new }.should raise_error(ArgumentError)
- end
+ end
end
describe "private_key" do
@@ -97,27 +97,6 @@ describe Chef::ApiClient do
it "should throw an ArgumentError if you feed it something lame" do
lambda { @client.private_key Hash.new }.should raise_error(ArgumentError)
- end
- end
-
- describe "create_keys" do
- before(:each) do
- Chef::Certificate.stub!(:gen_keypair).and_return(["cert", "key"])
- end
-
- it "should create a certificate based on the client name" do
- Chef::Certificate.should_receive(:gen_keypair).with(@client.name)
- @client.create_keys
- end
-
- it "should set the private key" do
- @client.create_keys
- @client.private_key.should == "key"
- end
-
- it "should set the public key" do
- @client.create_keys
- @client.public_key.should == "cert"
end
end
@@ -136,7 +115,7 @@ describe Chef::ApiClient do
%w{
name
public_key
- }.each do |t|
+ }.each do |t|
it "should include '#{t}'" do
@serial.should =~ /"#{t}":"#{@client.send(t.to_sym)}"/
end
@@ -168,7 +147,7 @@ describe Chef::ApiClient do
name
public_key
admin
- }.each do |t|
+ }.each do |t|
it "should match '#{t}'" do
@deserial.send(t.to_sym).should == @client.send(t.to_sym)
end
diff --git a/chef/spec/unit/certificate_spec.rb b/chef/spec/unit/certificate_spec.rb
deleted file mode 100644
index 4f0b07519f..0000000000
--- a/chef/spec/unit/certificate_spec.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2009 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-
-require 'chef/certificate'
-require 'ostruct'
-require 'tempfile'
-
-class FakeFile
- attr_accessor :data
-
- def write(arg)
- @data = arg
- end
-end
-
-describe Chef::Certificate do
- describe "generate_signing_ca" do
- before(:each) do
- Chef::Config[:signing_ca_user] = nil
- Chef::Config[:signing_ca_group] = nil
- FileUtils.stub!(:mkdir_p).and_return(true)
- FileUtils.stub!(:chown).and_return(true)
- File.stub!(:open).and_return(true)
- File.stub!(:exists?).and_return(false)
- @ca_cert = FakeFile.new
- @ca_key = FakeFile.new
- end
-
- it "should generate a ca certificate" do
- File.should_receive(:open).with(Chef::Config[:signing_ca_cert], "w").and_yield(@ca_cert)
- Chef::Certificate.generate_signing_ca
- @ca_cert.data.should =~ /BEGIN CERTIFICATE/
- end
-
- it "should generate an RSA private key" do
- File.should_receive(:open).with(Chef::Config[:signing_ca_key], File::WRONLY|File::EXCL|File::CREAT, 0600).and_yield(@ca_key)
- FileUtils.should_not_receive(:chown)
- Chef::Certificate.generate_signing_ca
- @ca_key.data.should =~ /BEGIN RSA PRIVATE KEY/
- end
-
- it "should generate an RSA private key with user and group" do
- Chef::Config[:signing_ca_user] = "funky"
- Chef::Config[:signing_ca_group] = "fresh"
- File.should_receive(:open).with(Chef::Config[:signing_ca_key], File::WRONLY|File::EXCL|File::CREAT, 0600).and_yield(@ca_key)
- FileUtils.should_receive(:chown).with(Chef::Config[:signing_ca_user], Chef::Config[:signing_ca_group], Chef::Config[:signing_ca_key])
- Chef::Certificate.generate_signing_ca
- @ca_key.data.should =~ /BEGIN RSA PRIVATE KEY/
- end
- end
-
- describe "generate_keypair" do
- it "should return a client certificate" do
- public_key, private_key = Chef::Certificate.gen_keypair("oasis")
- public_key.to_s.should =~ /(BEGIN RSA PUBLIC KEY|BEGIN PUBLIC KEY)/
- private_key.to_s.should =~ /BEGIN RSA PRIVATE KEY/
- end
- end
-end
diff --git a/chef/spec/unit/checksum_spec.rb b/chef/spec/unit/checksum_spec.rb
deleted file mode 100644
index aad559cf3d..0000000000
--- a/chef/spec/unit/checksum_spec.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Copyright:: Copyright (c) 2010 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-require 'chef/checksum'
-
-describe Chef::Checksum do
-
- before do
- Chef::Log.logger = Logger.new(StringIO.new)
-
- @now = Time.now
-
- Time.stub!(:now).and_return(@now)
-
- @checksum_of_the_file = "3fafecfb15585ede6b840158cbc2f399"
- @checksum = Chef::Checksum.new(@checksum_of_the_file)
- end
-
- it "has no original committed file location" do
- @checksum.original_committed_file_location.should be_nil
- end
-
- it "has the MD5 checksum of the file it represents" do
- @checksum.checksum.should == @checksum_of_the_file
- end
-
- it "stores the time it was created" do
- @checksum.create_time.should == @now.iso8601
- end
-
- it "commits a sandbox file from a given location to the checksum repo location" do
- @checksum.storage.should_receive(:commit).with("/tmp/arbitrary_file_location")
- @checksum.should_receive(:cdb_save)
- @checksum.commit_sandbox_file("/tmp/arbitrary_file_location")
- @checksum.original_committed_file_location.should == "/tmp/arbitrary_file_location"
- end
-
- it "reverts committing a sandbox file" do
- @checksum.storage.should_receive(:commit).with("/tmp/arbitrary_file_location")
- @checksum.should_receive(:cdb_save)
- @checksum.commit_sandbox_file("/tmp/arbitrary_file_location")
- @checksum.original_committed_file_location.should == "/tmp/arbitrary_file_location"
-
- @checksum.storage.should_receive(:revert).with("/tmp/arbitrary_file_location")
- @checksum.should_receive(:cdb_destroy)
- @checksum.revert_sandbox_file_commit
- end
-
- it "raises an error when trying to revert a checksum that was not previously committed" do
- lambda {@checksum.revert_sandbox_file_commit}.should raise_error(Chef::Exceptions::IllegalChecksumRevert)
- end
-
- it "deletes the file and its document from couchdb" do
- @checksum.should_receive(:cdb_destroy)
- @checksum.storage.should_receive(:purge)
- @checksum.purge
- end
-
- describe "when converted to json" do
- before do
- @checksum_as_json = @checksum.to_json
- @checksum_as_hash_from_json = Chef::JSONCompat.from_json(@checksum_as_json, :create_additions => false)
- end
-
- it "contains the file's MD5 checksum" do
- @checksum_as_hash_from_json["checksum"].should == @checksum_of_the_file
- end
-
- it "contains the creation time" do
- @checksum_as_hash_from_json["create_time"].should == @now.iso8601
- end
-
- it "uses the file's MD5 checksum for its 'name' property" do
- @checksum_as_hash_from_json["name"].should == @checksum_of_the_file
- end
- end
-
-end
diff --git a/chef/spec/unit/client_spec.rb b/chef/spec/unit/client_spec.rb
index e8a75b7009..9d0c88dad1 100644
--- a/chef/spec/unit/client_spec.rb
+++ b/chef/spec/unit/client_spec.rb
@@ -41,7 +41,7 @@ shared_examples_for Chef::Client do
ohai_data.stub!(:data).and_return(ohai_data)
Ohai::System.stub!(:new).and_return(ohai_data)
- @node = Chef::Node.new(@hostname)
+ @node = Chef::Node.new
@node.name(@fqdn)
@node.chef_environment("_default")
@@ -90,7 +90,7 @@ shared_examples_for Chef::Client do
Chef::REST.should_receive(:new).with(Chef::Config[:client_url], Chef::Config[:validation_client_name], Chef::Config[:validation_key]).exactly(1).and_return(mock_chef_rest_for_client)
mock_chef_rest_for_client.should_receive(:register).with(@fqdn, Chef::Config[:client_key]).exactly(1).and_return(true)
# Client.register will then turn around create another
-
+
# Chef::REST object, this time with the client key it got from the
# previous step.
Chef::REST.should_receive(:new).with(Chef::Config[:chef_server_url], @fqdn, Chef::Config[:client_key]).exactly(1).and_return(mock_chef_rest_for_node)
@@ -139,7 +139,6 @@ shared_examples_for Chef::Client do
res.replace(string)
end
pipe_sim.should_receive(:gets).and_return(res)
- Chef::CouchDB.should_receive(:new).and_return(nil)
IO.should_receive(:pipe).and_return([pipe_sim, pipe_sim])
IO.should_receive(:select).and_return(true)
end
@@ -151,7 +150,7 @@ shared_examples_for Chef::Client do
block.call
end
end
-
+
# This is what we're testing.
@client.run
@@ -160,7 +159,7 @@ shared_examples_for Chef::Client do
@node.automatic_attrs[:platform_version].should == "example-platform-1.0"
end
end
-
+
describe "when notifying other objects of the status of the chef run" do
before do
Chef::Client.clear_notifications
@@ -235,7 +234,7 @@ shared_examples_for Chef::Client do
describe "when a run list override is provided" do
before do
- @node = Chef::Node.new(@hostname)
+ @node = Chef::Node.new
@node.name(@fqdn)
@node.chef_environment("_default")
@node.automatic_attrs[:platform] = "example-platform"
@@ -265,7 +264,7 @@ shared_examples_for Chef::Client do
@node.should_receive(:save).and_return(nil)
@client.build_node
-
+
@node[:roles].should_not be_nil
@node[:roles].should eql(['test_role'])
@node[:recipes].should eql(['cookbook1'])
diff --git a/chef/spec/unit/cookbook_version_spec.rb b/chef/spec/unit/cookbook_version_spec.rb
index 90f411d8b2..85e1db1fae 100644
--- a/chef/spec/unit/cookbook_version_spec.rb
+++ b/chef/spec/unit/cookbook_version_spec.rb
@@ -6,9 +6,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,56 +17,10 @@
require 'spec_helper'
-describe Chef::MinimalCookbookVersion do
- describe "when first created" do
- before do
- @params = { "id"=>"1a806f1c-b409-4d8e-abab-fa414ff5b96d",
- "key"=>"activemq",
- "value"=>{"version"=>"0.3.3", "deps"=>{"java"=>">= 0.0.0", "runit"=>">= 0.0.0"}}}
- @minimal_cookbook_version = Chef::MinimalCookbookVersion.new(@params)
- end
-
- it "has a name" do
- @minimal_cookbook_version.name.should == 'activemq'
- end
-
- it "has a version" do
- @minimal_cookbook_version.version.should == '0.3.3'
- end
-
- it "has a list of dependencies" do
- @minimal_cookbook_version.deps.should == {"java" => ">= 0.0.0", "runit" => ">= 0.0.0"}
- end
-
- it "has cookbook metadata" do
- metadata = @minimal_cookbook_version.metadata
-
- metadata.name.should == 'activemq'
- metadata.dependencies['java'].should == '>= 0.0.0'
- metadata.dependencies['runit'].should == '>= 0.0.0'
- end
- end
-
- describe "when created from cookbooks with old style version contraints" do
- before do
- @params = { "id"=>"1a806f1c-b409-4d8e-abab-fa414ff5b96d",
- "key"=>"activemq",
- "value"=>{"version"=>"0.3.3", "deps"=>{"apt" => ">> 1.0.0"}}}
- @minimal_cookbook_version = Chef::MinimalCookbookVersion.new(@params)
- end
-
- it "translates the version constraints" do
- metadata = @minimal_cookbook_version.metadata
- metadata.dependencies['apt'].should == '> 1.0.0'
- end
- end
-end
-
describe Chef::CookbookVersion do
describe "when first created" do
before do
- @couchdb_driver = Chef::CouchDB.new
- @cookbook_version = Chef::CookbookVersion.new("tatft", @couchdb_driver)
+ @cookbook_version = Chef::CookbookVersion.new("tatft")
end
it "has a name" do
@@ -114,14 +68,6 @@ describe Chef::CookbookVersion do
@cookbook_version.should be_frozen_version
end
- it "has no couchdb id" do
- @cookbook_version.couchdb_id.should be_nil
- end
-
- it "has the couchdb driver it was given on create" do
- @cookbook_version.couchdb.should equal(@couchdb_driver)
- end
-
it "is \"ready\"" do
# WTF is this? what are the valid states? and why aren't they set with encapsulating methods?
# [Dan 15-Jul-2010]
@@ -133,19 +79,19 @@ describe Chef::CookbookVersion do
end
it "creates a manifest hash of its contents" do
- expected = {"recipes"=>[],
- "definitions"=>[],
- "libraries"=>[],
- "attributes"=>[],
- "files"=>[],
- "templates"=>[],
- "resources"=>[],
- "providers"=>[],
- "root_files"=>[],
- "cookbook_name"=>"tatft",
+ expected = {"recipes"=>[],
+ "definitions"=>[],
+ "libraries"=>[],
+ "attributes"=>[],
+ "files"=>[],
+ "templates"=>[],
+ "resources"=>[],
+ "providers"=>[],
+ "root_files"=>[],
+ "cookbook_name"=>"tatft",
"metadata"=>Chef::Cookbook::Metadata.new,
- "version"=>"0.0.0",
- "name"=>"tatft-0.0.0"}
+ "version"=>"0.0.0",
+ "name"=>"tatft-0.0.0"}
@cookbook_version.manifest.should == expected
end
end
@@ -280,7 +226,7 @@ describe Chef::CookbookVersion do
useful_explanation = Regexp.new(Regexp.escape("Cookbook 'tatft' (0.0.0) does not contain"))
@attempt_to_load_file.should raise_error(Chef::Exceptions::FileNotFound, useful_explanation)
end
-
+
it "lists suggested places to look" do
useful_explanation = Regexp.new(Regexp.escape("files/default/no-such-thing.txt"))
@attempt_to_load_file.should raise_error(Chef::Exceptions::FileNotFound, useful_explanation)
@@ -325,7 +271,7 @@ describe Chef::CookbookVersion do
b.version = "1.2.0"
a.should == b
end
-
+
it "should not allow you to sort cookbooks with different names" do
apt = Chef::CookbookVersion.new "apt"
@@ -358,54 +304,4 @@ describe Chef::CookbookVersion do
end
- describe "when deleting in the database" do
- before do
- @couchdb_driver = Chef::CouchDB.new
- @cookbook_version = Chef::CookbookVersion.new("tatft", @couchdb_driver)
- @cookbook_version.version = "1.2.3"
- @couchdb_rev = "_123456789"
- @cookbook_version.couchdb_rev = @couchdb_rev
- end
-
- it "deletes its document from couchdb" do
- @couchdb_driver.should_receive(:delete).with("cookbook_version", "tatft-1.2.3", @couchdb_rev)
- @cookbook_version.cdb_destroy
- end
-
- it "deletes associated checksum objects when purged" do
- checksums = {"12345" => "/tmp/foo", "23456" => "/tmp/bar", "34567" => "/tmp/baz"}
- @cookbook_version.stub!(:checksums).and_return(checksums)
-
- chksum_docs = checksums.map do |md5, path|
- cksum_doc = mock("Chef::Checksum for #{md5} at #{path}")
- Chef::Checksum.should_receive(:cdb_load).with(md5, @couchdb_driver).and_return(cksum_doc)
- cksum_doc.should_receive(:purge)
- cksum_doc
- end
-
- @cookbook_version.should_receive(:cdb_destroy)
- @cookbook_version.purge
- end
-
- it "successfully purges when associated checksum objects are missing" do
- checksums = {"12345" => "/tmp/foo", "23456" => "/tmp/bar", "34567" => "/tmp/baz"}
-
- chksum_docs = checksums.map do |md5, path|
- cksum_doc = mock("Chef::Checksum for #{md5} at #{path}")
- Chef::Checksum.should_receive(:cdb_load).with(md5, @couchdb_driver).and_return(cksum_doc)
- cksum_doc.should_receive(:purge)
- cksum_doc
- end
-
- missing_checksum = {"99999" => "/tmp/qux"}
- Chef::Checksum.should_receive(:cdb_load).with("99999", @couchdb_driver).and_raise(Chef::Exceptions::CouchDBNotFound)
-
- @cookbook_version.stub!(:checksums).and_return(checksums.merge(missing_checksum))
-
- @cookbook_version.should_receive(:cdb_destroy)
- lambda {@cookbook_version.purge}.should_not raise_error
- end
-
- end
-
end
diff --git a/chef/spec/unit/couchdb_spec.rb b/chef/spec/unit/couchdb_spec.rb
deleted file mode 100644
index 480dd61980..0000000000
--- a/chef/spec/unit/couchdb_spec.rb
+++ /dev/null
@@ -1,274 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-
-describe Chef::CouchDB do
- before(:each) do
- Chef::Config[:couchdb_database] = "chef"
- @rest = mock("Chef::REST")
- @rest.stub!(:run_request).and_return({"couchdb" => "Welcome", "version" =>"0.9.0"})
- @rest.stub!(:url).and_return("http://localhost:5984")
- Chef::REST.stub!(:new).and_return(@rest)
- @couchdb = Chef::CouchDB.new
- end
-
- describe "new" do
- it "should create a new Chef::REST object from the default url" do
- old_url = Chef::Config[:couchdb_url]
- Chef::Config[:couchdb_url] = "http://monkey"
- Chef::REST.should_receive(:new).with("http://monkey", nil, nil)
- Chef::CouchDB.new
- Chef::Config[:couchdb_url] = old_url
- end
-
- it "should create a new Chef::REST object from a provided url" do
- Chef::REST.should_receive(:new).with("http://monkeypants", nil, nil)
- Chef::CouchDB.new("http://monkeypants")
- end
- end
-
- describe "create_db" do
- before(:each) do
- @couchdb.stub!(:create_design_document).and_return(true)
- end
-
- it "should get a list of current databases" do
- @rest.should_receive(:get_rest).and_return(["chef"])
- @couchdb.create_db
- end
-
- it "should create the chef database if it does not exist" do
- @rest.stub!(:get_rest).and_return([])
- @rest.should_receive(:put_rest).with("chef", {}).and_return(true)
- @couchdb.create_db
- end
-
- it "should not create the chef database if it does exist" do
- @rest.stub!(:get_rest).and_return(["chef"])
- @rest.should_not_receive(:put_rest)
- @couchdb.create_db
- end
-
- it "should return 'chef'" do
- @rest.should_receive(:get_rest).with("_all_dbs").and_return(%w{chef})
- @couchdb.create_db.should eql("chef")
- end
- end
-
- describe "create_design_document" do
- before(:each) do
- @mock_design = {
- "version" => 1,
- "_rev" => 1
- }
- @mock_data = {
- "version" => 1,
- "language" => "javascript",
- "views" => {
- "all" => {
- "map" => <<-EOJS
- function(doc) {
- if (doc.chef_type == "node") {
- emit(doc.name, doc);
- }
- }
- EOJS
- },
- }
- }
- @rest.stub!(:get_rest).and_return(@mock_design)
- @rest.stub!(:put_rest).and_return(true)
- @couchdb.stub!(:create_db).and_return(true)
- end
-
- def do_create_design_document
- @couchdb.create_design_document("bob", @mock_data)
- end
-
- it "should fetch the existing design document" do
- @rest.should_receive(:get_rest).with("chef/_design/bob")
- do_create_design_document
- end
-
- it "should populate the _rev in the new design if the versions dont match" do
- @mock_data["version"] = 2
- do_create_design_document
- @mock_data["_rev"].should eql(1)
- end
-
- it "should create the view if it requires updating" do
- @mock_data["version"] = 2
- @rest.should_receive(:put_rest).with("chef/_design%2Fbob", @mock_data)
- do_create_design_document
- end
-
- it "should not create the view if it does not require updating" do
- @mock_data["version"] = 1
- @rest.should_not_receive(:put_rest)
- do_create_design_document
- end
- end
-
- describe "store" do
- before(:each) do
- @mock_results = {
- "rows" => [
- "id" => 'a0934635-e111-45d9-8223-cb58e1c9434c'
- ]
- }
- @couchdb.stub!(:get_view).with("id_map", "name_to_id", :key => [ "node", "bob" ]).and_return(@mock_results)
- end
-
- it "should put the object into couchdb with a pre-existing GUID" do
- item_to_store = {}
- item_to_store.should_receive(:add_to_index)
- @rest.should_receive(:put_rest).with("chef/#{@mock_results["rows"][0]["id"]}", item_to_store).and_return(true)
- @couchdb.store("node", "bob", item_to_store)
- end
-
- it "should put the object into couchdb with a new GUID" do
- @mock_results = { "rows" => [] }
- item_to_store = {}
- item_to_store.should_receive(:add_to_index).with(:database => "chef", :id => "aaaaaaaa-xxxx-xxxx-xxxx-xxxxxxxxxxx", :type => "node")
- @couchdb.stub!(:get_view).with("id_map", "name_to_id", :key => [ "node", "bob" ]).and_return(@mock_results)
- UUIDTools::UUID.stub!(:random_create).and_return("aaaaaaaa-xxxx-xxxx-xxxx-xxxxxxxxxxx")
- @rest.should_receive(:put_rest).with("chef/aaaaaaaa-xxxx-xxxx-xxxx-xxxxxxxxxxx", item_to_store).and_return(true)
- @couchdb.store("node", "bob", item_to_store)
- end
-
- end
-
- describe "when fetching the database status" do
- it "gets couchdb's version string'" do
- @rest.should_receive(:get_rest).with('/').and_return({"couchdb" => "Welcome","version" => "1.0.1"})
- @couchdb.server_stats.should == {"couchdb" => "Welcome","version" => "1.0.1"}
- end
-
- it "gets database stats" do
- db_stats = {"db_name" => "opscode_account","doc_count" => 206,"doc_del_count" => 1,"update_seq" => 208,"purge_seq" => 0,
- "compact_running" => false,"disk_size" => 122969,"instance_start_time" => "1298070021394804","disk_format_version" => 5,"committed_update_seq" => 208}
- @rest.should_receive(:get_rest).with('/chef').and_return(db_stats)
- @couchdb.db_stats.should == db_stats
- end
-
- end
-
- describe "load" do
- before(:each) do
- @mock_node = Chef::Node.new()
- @mock_node.name("bob")
- @couchdb.stub!(:find_by_name).with("node", "bob").and_return(@mock_node)
- end
-
- it "should load the object from couchdb" do
- @couchdb.load("node", "bob").should eql(@mock_node)
- end
- end
-
- describe "delete" do
- before(:each) do
- @mock_current = {
- "version" => 1,
- "_rev" => 1
- }
- @rest.stub!(:get_rest).and_return(@mock_current)
- @rest.stub!(:delete_rest).and_return(true)
- @node = Chef::Node.new()
- @node.name("bob")
- @node.couchdb_rev = 15
- @couchdb.stub!(:find_by_name).with("node", "bob", true).and_return([ @node, "ax" ])
- end
-
- def do_delete(rev=nil)
- @couchdb.delete("node", "bob", rev)
- end
-
- it "should remove the object from couchdb with a specific revision" do
- @node.should_receive(:delete_from_index)
- @rest.should_receive(:delete_rest).with("chef/ax?rev=1")
- do_delete(1)
- end
-
- it "should remove the object from couchdb based on the couchdb_rev of the current obj" do
- @node.should_receive(:delete_from_index)
- @rest.should_receive(:delete_rest).with("chef/ax?rev=15")
- do_delete
- end
- end
-
- describe "list" do
- before(:each) do
- Chef::Config.stub!(:[]).with(:couchdb_database).and_return("chef")
- @mock_response = {"rows" => []}
- end
-
- describe "on couchdb 0.9+" do
- before do
- Chef::Config.stub!(:[]).with(:couchdb_version).and_return(0.9)
- end
-
- it "should get the view for all objects if inflate is true" do
- @rest.should_receive(:get_rest).with("chef/_design/node/_view/all").and_return(@mock_response)
- @couchdb.list("node", true)
- end
-
- it "should get the view for just the object id's if inflate is false" do
- @rest.should_receive(:get_rest).with("chef/_design/node/_view/all_id").and_return(@mock_response)
- @couchdb.list("node", false)
- end
- end
- end
-
- describe "has_key?" do
- it "should return true if the object exists" do
- @couchdb.stub!(:find_by_name).with("node", "bob").and_return(true)
- @couchdb.has_key?("node", "bob").should eql(true)
- end
-
- it "should return false if the object does not exist" do
- @couchdb.stub!(:find_by_name).and_raise(Chef::Exceptions::CouchDBNotFound)
- @couchdb.has_key?("node", "bob").should eql(false)
- end
- end
-
- describe "get_view" do
- it "should construct a call to the view for the proper design document" do
- @rest.should_receive(:get_rest).with("chef/_design/nodes/_view/mastodon")
- @couchdb.get_view("nodes", "mastodon")
- end
-
- it "should allow arguments to the view" do
- @rest.should_receive(:get_rest).with("chef/_design/nodes/_view/mastodon?startkey=%22dont%20stay%22")
- @couchdb.get_view("nodes", "mastodon", :startkey => "dont stay")
- end
-
- end
-
- describe "view_uri" do
- it "should output an appropriately formed view URI" do
- @couchdb.should_receive(:view_uri).with("nodes", "all").and_return("chef/_design/nodes/_view/all")
- @couchdb.view_uri("nodes", "all")
- end
- end
-
-end
-
-
-
-
diff --git a/chef/spec/unit/environment_spec.rb b/chef/spec/unit/environment_spec.rb
index 7b0a835e8c..97f0c3395e 100644
--- a/chef/spec/unit/environment_spec.rb
+++ b/chef/spec/unit/environment_spec.rb
@@ -235,107 +235,6 @@ describe Chef::Environment do
end
end
- describe "when listing the available cookbooks filtered by policy" do
- before(:each) do
- @environment.name "prod"
- @environment.cookbook_versions({
- "apt" => "= 1.0.0",
- "apache2" => "= 2.0.0"
- })
- Chef::Environment.stub!(:cdb_load).and_return @environment
-
- @all_cookbooks = []
- @all_cookbooks << begin
- cv = Chef::CookbookVersion.new("apt")
- cv.version = "1.0.0"
- cv.recipe_filenames = ["default.rb", "only-in-1-0.rb"]
- cv
- end
- @all_cookbooks << begin
- cv = Chef::CookbookVersion.new("apt")
- cv.version = "1.1.0"
- cv.recipe_filenames = ["default.rb", "only-in-1-1.rb"]
- cv
- end
- @all_cookbooks << begin
- cv = Chef::CookbookVersion.new("apache2")
- cv.version = "2.0.0"
- cv.recipe_filenames = ["default.rb", "mod_ssl.rb"]
- cv
- end
- @all_cookbooks << begin
- cv = Chef::CookbookVersion.new("god")
- cv.version = "4.2.0"
- cv.recipe_filenames = ["default.rb"]
- cv
- end
- Chef::CookbookVersion.stub!(:cdb_list).and_return @all_cookbooks
- end
-
- it "should load the environment" do
- Chef::Environment.should_receive(:cdb_load).with("prod", nil)
- Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
- end
-
- it "should handle cookbooks with no available version" do
- @environment.cookbook_versions({
- "apt" => "> 999.0.0",
- "apache2" => "= 2.0.0"
- })
- Chef::Environment.should_receive(:cdb_load).with("prod", nil)
- recipes = Chef::Environment.cdb_load_filtered_recipe_list("prod")
- # order doesn't matter
- recipes.should =~ ["god", "apache2", "apache2::mod_ssl"]
- end
-
-
- it "should load all the cookbook versions" do
- Chef::CookbookVersion.should_receive(:cdb_list)
- Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
- recipes = Chef::Environment.cdb_load_filtered_recipe_list("prod")
- recipes.should =~ ["apache2", "apache2::mod_ssl", "apt",
- "apt::only-in-1-0", "god"]
- end
-
- it "should load all the cookbook versions with no policy" do
- @environment.cookbook_versions({})
- Chef::CookbookVersion.should_receive(:cdb_list)
- Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
- recipes = Chef::Environment.cdb_load_filtered_recipe_list("prod")
- recipes.should =~ ["apache2", "apache2::mod_ssl", "apt",
- "apt::only-in-1-1", "god"]
- end
-
- it "should restrict the cookbook versions, as specified in the environment" do
- res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
- res["apt"].detect {|cb| cb.version == "1.0.0"}.should_not == nil
- res["apache2"].detect {|cb| cb.version == "2.0.0"}.should_not == nil
- res["god"].detect {|cb| cb.version == "4.2.0"}.should_not == nil
- end
-
- it "should produce correct results, regardless of the cookbook order in couch" do
- # a bug present before the environments feature defaulted to the last CookbookVersion
- # object for a cookbook as returned from couchdb when fetching cookbooks for a node
- # this is a regression test
- @all_cookbooks << begin
- cv = Chef::CookbookVersion.new("god")
- cv.version = "0.0.1"
- cv
- end
- res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
- res["apt"].detect {|cb| cb.version == "1.0.0"}.should_not == nil
- res["apache2"].detect {|cb| cb.version == "2.0.0"}.should_not == nil
- res["god"].detect {|cb| cb.version == "4.2.0"}.should_not == nil
- end
-
- it "should return all versions of a cookbook that meet the version requirement" do
- @environment.cookbook "apt", ">= 1.0.0"
- res = Chef::Environment.cdb_load_filtered_cookbook_versions("prod")
- res["apt"].detect {|cb| cb.version == "1.0.0"}.should_not == nil
- res["apt"].detect {|cb| cb.version == "1.1.0"}.should_not == nil
- end
- end
-
describe "self.validate_cookbook_versions" do
before(:each) do
@cookbook_versions = {
@@ -376,35 +275,6 @@ describe Chef::Environment do
end
end
- describe "self.create_default_environment" do
- it "should check if the '_default' environment exists" do
- @couchdb = Chef::CouchDB.new
- Chef::CouchDB.stub!(:new).and_return @couchdb
- Chef::Environment.should_receive(:cdb_load).with('_default', Chef::CouchDB.new)
- Chef::Environment.create_default_environment
- end
-
- it "should not re-create the environment if it exists" do
- @couchdb = Chef::CouchDB.new
- Chef::CouchDB.stub!(:new).and_return @couchdb
- Chef::Environment.should_receive(:cdb_load).with('_default', Chef::CouchDB.new).and_return true
- Chef::Environment.should_not_receive(:new)
- Chef::Environment.create_default_environment
- end
-
- it "should create the environment if it doesn't exist" do
- @env = Chef::Environment.new
- @env.stub!(:cdb_save).and_return true
- @couchdb = Chef::CouchDB.new
- Chef::Environment.stub!(:new).and_return @env
- Chef::CouchDB.stub!(:new).and_return @couchdb
-
- Chef::Environment.should_receive(:cdb_load).with('_default', Chef::CouchDB.new).and_raise(Chef::Exceptions::CouchDBNotFound)
- Chef::Environment.should_receive(:new)
- Chef::Environment.create_default_environment
- end
- end
-
describe "when updating from a parameter hash" do
before do
@environment = Chef::Environment.new
diff --git a/chef/spec/unit/exceptions_spec.rb b/chef/spec/unit/exceptions_spec.rb
index fe920fd817..a979d2f6b9 100644
--- a/chef/spec/unit/exceptions_spec.rb
+++ b/chef/spec/unit/exceptions_spec.rb
@@ -8,9 +8,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,7 +40,6 @@ describe Chef::Exceptions do
Chef::Exceptions::Group => RuntimeError,
Chef::Exceptions::Link => RuntimeError,
Chef::Exceptions::Mount => RuntimeError,
- Chef::Exceptions::CouchDBNotFound => RuntimeError,
Chef::Exceptions::PrivateKeyMissing => RuntimeError,
Chef::Exceptions::CannotWritePrivateKey => RuntimeError,
Chef::Exceptions::RoleNotFound => RuntimeError,
diff --git a/chef/spec/unit/index_queue_spec.rb b/chef/spec/unit/index_queue_spec.rb
deleted file mode 100644
index 3043585757..0000000000
--- a/chef/spec/unit/index_queue_spec.rb
+++ /dev/null
@@ -1,391 +0,0 @@
-#
-# Author:: Daniel DeLeo (<dan@kallistec.com>)
-# Copyright:: Copyright (c) 2009 Daniel DeLeo
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-
-class Chef
- class IndexableTestHarness
- include Chef::IndexQueue::Indexable
- attr_reader :couchdb_id
- def couchdb_id=(value)
- self.index_id = @couchdb_id = value
- end
- attr_reader :index_id
- def index_id=(value)
- @index_id = value
- end
-
- def to_hash
- {"ohai_world" => "I am IndexableTestHarness", "object_id" => object_id}
- end
-
- end
-end
-
-class IndexQueueSpecError < RuntimeError ; end
-
-class FauxQueue
-
- attr_reader :published_message, :publish_options
-
- # Note: If publish is not called, this published_message will cause
- # JSON parsing to die with "can't convert Symbol into String"
- def initialize
- @published_message = :epic_fail!
- @publish_options = :epic_fail!
- end
-
- def publish(message, options=nil)
- @published_message = message
- @publish_options = options
- end
-end
-
-class IndexConsumerTestHarness
- include Chef::IndexQueue::Consumer
-
- attr_reader :last_indexed_object, :unexposed_attr
-
- expose :index_this
-
- def index_this(object_to_index)
- @last_indexed_object = object_to_index
- end
-
- def not_exposed(arg)
- @unexposed_attr = arg
- end
-end
-
-describe Chef::IndexQueue::Indexable do
- def a_uuid
- /[0-9a-f]{8}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{4}\-[0-9a-f]{12}/
- end
-
- before do
- Chef::IndexableTestHarness.reset_index_metadata!
- @publisher = Chef::IndexQueue::AmqpClient.instance
- @indexable_obj = Chef::IndexableTestHarness.new
- @item_as_hash = {"ohai_world" => "I am IndexableTestHarness", "object_id" => @indexable_obj.object_id}
-
- @now = Time.now
- Time.stub!(:now).and_return(@now)
- end
-
- it "downcases the class name for the index_object_type when it's not explicitly set" do
- @indexable_obj.index_object_type.should == "indexable_test_harness"
- end
-
- it "uses an explicitly set index_object_type" do
- Chef::IndexableTestHarness.index_object_type :a_weird_name
- @indexable_obj.index_object_type.should == "a_weird_name"
- end
-
- it "adds 'database', 'type', and 'id' (UUID) keys to the published object" do
- with_metadata = @indexable_obj.with_indexer_metadata(:database => "foo", :id=>UUIDTools::UUID.random_create.to_s)
- with_metadata.should have(5).keys
- with_metadata.keys.should include("type", "id", "item", "database", "enqueued_at")
- with_metadata["type"].should == "indexable_test_harness"
- with_metadata["database"].should == "foo"
- with_metadata["item"].should == @item_as_hash
- with_metadata["id"].should match(a_uuid)
- with_metadata["enqueued_at"].should == @now.utc.to_i
- end
-
- it "uses the couchdb_id if available" do
- expected_uuid = "0000000-1111-2222-3333-444444444444"
- @indexable_obj.couchdb_id = expected_uuid
- metadata_id = @indexable_obj.with_indexer_metadata["id"]
- metadata_id.should == expected_uuid
- end
-
- describe "adds and removes items to and from the index and respects Chef::Config[:persistent_queue]" do
- before do
- @exchange = mock("Bunny::Exchange")
- @amqp_client = mock("Bunny::Client", :start => true, :exchange => @exchange)
- @publisher.stub!(:amqp_client).and_return(@amqp_client)
- @queue = FauxQueue.new
- @publisher.should_receive(:queue_for_object).with("0000000-1111-2222-3333-444444444444").and_yield(@queue)
- Chef::Config[:persistent_queue] = false
- end
-
- it "adds items to the index" do
- @amqp_client.should_not_receive(:tx_select)
- @amqp_client.should_not_receive(:tx_commit)
- @amqp_client.should_not_receive(:tx_rollback)
-
- @indexable_obj.add_to_index(:database => "couchdb@localhost,etc.", :id=>"0000000-1111-2222-3333-444444444444")
-
- published_message = Chef::JSONCompat.from_json(@queue.published_message)
- published_message.should == {"action" => "add", "payload" => {"item" => @item_as_hash,
- "type" => "indexable_test_harness",
- "database" => "couchdb@localhost,etc.",
- "id" => "0000000-1111-2222-3333-444444444444",
- "enqueued_at" => @now.utc.to_i}}
- @queue.publish_options[:persistent].should == false
- end
-
- it "adds items to the index transactionactionally when Chef::Config[:persistent_queue] == true" do
- @amqp_client.should_receive(:tx_select)
- @amqp_client.should_receive(:tx_commit)
- @amqp_client.should_not_receive(:tx_rollback)
-
- # set and restore Chef::Config[:persistent_queue] to true
- orig_value = Chef::Config[:persistent_queue]
- Chef::Config[:persistent_queue] = true
- begin
- @indexable_obj.add_to_index(:database => "couchdb@localhost,etc.", :id=>"0000000-1111-2222-3333-444444444444")
- ensure
- Chef::Config[:persistent_queue] = orig_value
- end
-
- published_message = Chef::JSONCompat.from_json(@queue.published_message)
- published_message.should == {"action" => "add", "payload" => {"item" => @item_as_hash,
- "type" => "indexable_test_harness",
- "database" => "couchdb@localhost,etc.",
- "id" => "0000000-1111-2222-3333-444444444444",
- "enqueued_at" => @now.utc.to_i}}
- @queue.publish_options[:persistent].should == true
- end
-
- it "adds items to the index transactionally when Chef::Config[:persistent_queue] == true and rolls it back when there is a failure" do
- @amqp_client.should_receive(:tx_select)
- @amqp_client.should_receive(:tx_rollback)
- @amqp_client.should_not_receive(:tx_commit)
-
- # cause the publish to fail, and make sure the failure is our own
- # by using a specific class
- @queue.should_receive(:publish).and_raise(IndexQueueSpecError)
-
- # set and restore Chef::Config[:persistent_queue] to true
- orig_value = Chef::Config[:persistent_queue]
- Chef::Config[:persistent_queue] = true
- begin
- lambda{
- @indexable_obj.add_to_index(:database => "couchdb@localhost,etc.", :id=>"0000000-1111-2222-3333-444444444444")
- }.should raise_error(IndexQueueSpecError)
- ensure
- Chef::Config[:persistent_queue] = orig_value
- end
- end
-
- it "removes items from the index" do
- @amqp_client.should_not_receive(:tx_select)
- @amqp_client.should_not_receive(:tx_commit)
- @amqp_client.should_not_receive(:tx_rollback)
-
- @indexable_obj.delete_from_index(:database => "couchdb2@localhost", :id=>"0000000-1111-2222-3333-444444444444")
- published_message = Chef::JSONCompat.from_json(@queue.published_message)
- published_message.should == {"action" => "delete", "payload" => { "item" => @item_as_hash,
- "type" => "indexable_test_harness",
- "database" => "couchdb2@localhost",
- "id" => "0000000-1111-2222-3333-444444444444",
- "enqueued_at" => @now.utc.to_i}}
- @queue.publish_options[:persistent].should == false
- end
-
- it "removes items from the index transactionactionally when Chef::Config[:persistent_queue] == true" do
- @amqp_client.should_receive(:tx_select)
- @amqp_client.should_receive(:tx_commit)
- @amqp_client.should_not_receive(:tx_rollback)
-
- # set and restore Chef::Config[:persistent_queue] to true
- orig_value = Chef::Config[:persistent_queue]
- Chef::Config[:persistent_queue] = true
- begin
- @indexable_obj.delete_from_index(:database => "couchdb2@localhost", :id=>"0000000-1111-2222-3333-444444444444")
- ensure
- Chef::Config[:persistent_queue] = orig_value
- end
-
- published_message = Chef::JSONCompat.from_json(@queue.published_message)
- published_message.should == {"action" => "delete", "payload" => { "item" => @item_as_hash,
- "type" => "indexable_test_harness",
- "database" => "couchdb2@localhost",
- "id" => "0000000-1111-2222-3333-444444444444",
- "enqueued_at" => @now.utc.to_i}}
- @queue.publish_options[:persistent].should == true
- end
-
- it "remove items from the index transactionally when Chef::Config[:persistent_queue] == true and rolls it back when there is a failure" do
- @amqp_client.should_receive(:tx_select)
- @amqp_client.should_receive(:tx_rollback)
- @amqp_client.should_not_receive(:tx_commit)
-
- # cause the publish to fail, and make sure the failure is our own
- # by using a specific class
- @queue.should_receive(:publish).and_raise(IndexQueueSpecError)
-
- # set and restore Chef::Config[:persistent_queue] to true
- orig_value = Chef::Config[:persistent_queue]
- Chef::Config[:persistent_queue] = true
- begin
- lambda{
- @indexable_obj.delete_from_index(:database => "couchdb2@localhost", :id=>"0000000-1111-2222-3333-444444444444") }.should raise_error(IndexQueueSpecError)
- ensure
- Chef::Config[:persistent_queue] = orig_value
- end
- end
- end
-
-end
-
-describe Chef::IndexQueue::Consumer do
- before do
- @amqp_client = Chef::IndexQueue::AmqpClient.instance
- @consumer = IndexConsumerTestHarness.new
- end
-
- it "keeps a whitelist of exposed methods" do
- IndexConsumerTestHarness.exposed_methods.should == [:index_this]
- IndexConsumerTestHarness.whitelisted?(:index_this).should be_true
- IndexConsumerTestHarness.whitelisted?(:not_exposed).should be_false
- end
-
- it "doesn't route non-whitelisted methods" do
- payload_json = {"payload" => {"a_placeholder" => "object"}, "action" => "not_exposed"}.to_json
- received_message = {:payload => payload_json}
- lambda {@consumer.call_action_for_message(received_message)}.should raise_error(ArgumentError)
- @consumer.unexposed_attr.should be_nil
- end
-
- it "routes message payloads to the correct method" do
- payload_json = {"payload" => {"a_placeholder" => "object"}, "action" => "index_this"}.to_json
- received_message = {:payload => payload_json}
- @consumer.call_action_for_message(received_message)
- @consumer.last_indexed_object.should == {"a_placeholder" => "object"}
-
- end
-
- it "subscribes to the queue for the indexer" do
- payload_json = {"payload" => {"a_placeholder" => "object"}, "action" => "index_this"}.to_json
- message = {:payload => payload_json}
- queue = mock("Bunny::Queue")
- @amqp_client.stub!(:queue).and_return(queue)
- queue.should_receive(:subscribe).with(:timeout => false, :ack => true).and_yield(message)
- @consumer.run
- @consumer.last_indexed_object.should == {"a_placeholder" => "object"}
- end
-
-end
-
-
-describe Chef::IndexQueue::AmqpClient do
- before do
- Chef::Config[:amqp_host] = '4.3.2.1'
- Chef::Config[:amqp_port] = '1337'
- Chef::Config[:amqp_user] = 'teh_rspecz'
- Chef::Config[:amqp_pass] = 'access_granted2rspec'
- Chef::Config[:amqp_vhost] = '/chef-specz'
- Chef::Config[:amqp_consumer_id] = nil
-
- @publisher = Chef::IndexQueue::AmqpClient.instance
- @exchange = mock("Bunny::Exchange")
-
- @amqp_client = mock("Bunny::Client", :start => true, :exchange => @exchange)
- def @amqp_client.connected?; false; end # stubbing predicate methods not working?
- Bunny.stub!(:new).and_return(@amqp_client)
-
- @publisher.reset!
- end
-
- after do
- @publisher.disconnected!
- end
-
- it "is a singleton" do
- lambda {Chef::IndexQueue::Indexable::AmqpClient.new}.should raise_error
- end
-
- it "creates an amqp client object on demand, starts a connection, and caches it" do
- @amqp_client.should_receive(:start).once
- @amqp_client.should_receive(:qos).with(:prefetch_count => 1)
- ::Bunny.should_receive(:new).once.and_return(@amqp_client)
- @publisher.amqp_client.should == @amqp_client
- @publisher.amqp_client
- end
-
- it "configures the amqp client with credentials from the config file" do
- @publisher.reset!
- Bunny.should_receive(:new).with(:spec => '08', :host => '4.3.2.1', :port => '1337', :user => "teh_rspecz",
- :pass => "access_granted2rspec", :vhost => '/chef-specz').and_return(@amqp_client)
- @amqp_client.should_receive(:qos).with(:prefetch_count => 1)
- @publisher.amqp_client.should == @amqp_client
- end
-
- it "creates an amqp exchange on demand and caches it" do
- @amqp_client.stub!(:qos)
- @publisher.exchange.should == @exchange
- @amqp_client.should_not_receive(:exchange)
- @publisher.exchange.should == @exchange
- end
-
- describe "publishing" do
-
- before do
- @queue_1 = FauxQueue.new
- @queue_2 = FauxQueue.new
-
- @amqp_client.stub!(:qos)
- #@amqp_client.stub!(:queue).and_return(@queue)
- @data = {"some_data" => "in_a_hash"}
- end
-
- it "resets the client upon a Bunny::ServerDownError when publishing" do
- Bunny.stub!(:new).and_return(@amqp_client)
- @amqp_client.should_receive(:queue).with("vnode-68", {:passive=>false, :durable=>true, :exclusive=>false, :auto_delete=>false}).twice.and_return(@queue_1, @queue_2)
-
- @queue_1.should_receive(:publish).with(@data).and_raise(Bunny::ServerDownError)
- @queue_2.should_receive(:publish).with(@data).and_raise(Bunny::ServerDownError)
-
- @publisher.should_receive(:disconnected!).at_least(3).times
- lambda {@publisher.queue_for_object("00000000-1111-2222-3333-444444444444") {|q| q.publish(@data)}}.should raise_error(Bunny::ServerDownError)
- end
-
- it "resets the client upon a Bunny::ConnectionError when publishing" do
- Bunny.stub!(:new).and_return(@amqp_client)
- @amqp_client.should_receive(:queue).with("vnode-68", {:passive=>false, :durable=>true, :exclusive=>false, :auto_delete=>false}).twice.and_return(@queue_1, @queue_2)
-
- @queue_1.should_receive(:publish).with(@data).and_raise(Bunny::ConnectionError)
- @queue_2.should_receive(:publish).with(@data).and_raise(Bunny::ConnectionError)
-
- @publisher.should_receive(:disconnected!).at_least(3).times
- lambda {@publisher.queue_for_object("00000000-1111-2222-3333-444444444444") {|q| q.publish(@data)}}.should raise_error(Bunny::ConnectionError)
- end
-
- it "resets the client upon a Errno::ECONNRESET when publishing" do
- Bunny.stub!(:new).and_return(@amqp_client)
- @amqp_client.should_receive(:queue).with("vnode-68", {:passive=>false, :durable=>true, :exclusive=>false, :auto_delete=>false}).twice.and_return(@queue_1, @queue_2)
-
- @queue_1.should_receive(:publish).with(@data).and_raise(Errno::ECONNRESET)
- @queue_2.should_receive(:publish).with(@data).and_raise(Errno::ECONNRESET)
-
- @publisher.should_receive(:disconnected!).at_least(3).times
- lambda {@publisher.queue_for_object("00000000-1111-2222-3333-444444444444") {|q| q.publish(@data)}}.should raise_error(Errno::ECONNRESET)
- end
-
- end
-
- it "stops bunny and clears subscriptions" do
- bunny_client = mock("Bunny::Client")
- @publisher.instance_variable_set(:@amqp_client, bunny_client)
- bunny_client.should_receive(:stop)
- @publisher.stop
- end
-
-end
diff --git a/chef/spec/unit/knife/ssh_spec.rb b/chef/spec/unit/knife/ssh_spec.rb
index a4853e11cc..6e90a87f01 100644
--- a/chef/spec/unit/knife/ssh_spec.rb
+++ b/chef/spec/unit/knife/ssh_spec.rb
@@ -36,10 +36,10 @@ describe Chef::Knife::Ssh do
@knife = Chef::Knife::Ssh.new
@knife.config.clear
@knife.config[:attribute] = "fqdn"
- @node_foo = Chef::Node.new('foo')
+ @node_foo = Chef::Node.new
@node_foo.automatic_attrs[:fqdn] = "foo.example.org"
@node_foo.automatic_attrs[:ipaddress] = "10.0.0.1"
- @node_bar = Chef::Node.new('bar')
+ @node_bar = Chef::Node.new
@node_bar.automatic_attrs[:fqdn] = "bar.example.org"
@node_bar.automatic_attrs[:ipaddress] = "10.0.0.2"
end
@@ -64,7 +64,7 @@ describe Chef::Knife::Ssh do
@knife.should_receive(:session_from_list).with(['10.0.0.1', '10.0.0.2'])
@knife.configure_session
end
-
+
it "returns an array of the attributes specified on the command line even when a config value is set" do
@knife.config[:attribute] = "config_file" # this value will be the config file
@knife.config[:override_attribute] = "ipaddress" # this is the value of the command line via #configure_attribute
diff --git a/chef/spec/unit/lwrp_spec.rb b/chef/spec/unit/lwrp_spec.rb
index 76834cf182..da2278e547 100644
--- a/chef/spec/unit/lwrp_spec.rb
+++ b/chef/spec/unit/lwrp_spec.rb
@@ -6,9 +6,9 @@
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -94,7 +94,7 @@ describe "LWRP" do
end
it "should have access to the run context and node during class definition" do
- node = Chef::Node.new(nil)
+ node = Chef::Node.new
node.normal[:penguin_name] = "jackass"
run_context = Chef::RunContext.new(node, Chef::CookbookCollection.new, @events)
diff --git a/chef/spec/unit/mixin/params_validate_spec.rb b/chef/spec/unit/mixin/params_validate_spec.rb
index dd0366c37c..b79156109b 100644
--- a/chef/spec/unit/mixin/params_validate_spec.rb
+++ b/chef/spec/unit/mixin/params_validate_spec.rb
@@ -330,10 +330,12 @@ describe Chef::Mixin::ParamsValidate do
it "asserts that a value returns false from a predicate method" do
lambda do
- @vo.validate({:not_blank => "should pass"}, {:not_blank => {:cannot_be => :blank}})
+ @vo.validate({:not_blank => "should pass"},
+ {:not_blank => {:cannot_be => :nil, :cannot_be => :empty}})
end.should_not raise_error
lambda do
- @vo.validate({:not_blank => ""}, {:not_blank => {:cannot_be => :blank}})
+ @vo.validate({:not_blank => ""},
+ {:not_blank => {:cannot_be => :nil, :cannot_be => :empty}})
end.should raise_error(Chef::Exceptions::ValidationFailed)
end
diff --git a/chef/spec/unit/node_spec.rb b/chef/spec/unit/node_spec.rb
index 4577d5098b..b6f63c9651 100644
--- a/chef/spec/unit/node_spec.rb
+++ b/chef/spec/unit/node_spec.rb
@@ -681,80 +681,4 @@ describe Chef::Node do
end
end
- describe "acting as a CouchDB-backed model" do
- before(:each) do
- @couchdb = Chef::CouchDB.new
- @mock_couch = mock('couch mock')
- end
-
- describe "list" do
- before(:each) do
- @mock_couch.stub!(:list).and_return(
- { "rows" => [ { "value" => "a", "key" => "avenue" } ] }
- )
- Chef::CouchDB.stub!(:new).and_return(@mock_couch)
- end
-
- it "should retrieve a list of nodes from CouchDB" do
- Chef::Node.cdb_list.should eql(["avenue"])
- end
-
- it "should return just the ids if inflate is false" do
- Chef::Node.cdb_list(false).should eql(["avenue"])
- end
-
- it "should return the full objects if inflate is true" do
- Chef::Node.cdb_list(true).should eql(["a"])
- end
- end
-
- describe "when loading a given node" do
- it "should load a node from couchdb by name" do
- @couchdb.should_receive(:load).with("node", "coffee").and_return(true)
- Chef::CouchDB.stub!(:new).and_return(@couchdb)
- Chef::Node.cdb_load("coffee")
- end
- end
-
- describe "when destroying a Node" do
- it "should delete this node from couchdb" do
- @couchdb.should_receive(:delete).with("node", "bob", 1).and_return(true)
- Chef::CouchDB.stub!(:new).and_return(@couchdb)
- node = Chef::Node.new
- node.name "bob"
- node.couchdb_rev = 1
- node.cdb_destroy
- end
- end
-
- describe "when saving a Node" do
- before(:each) do
- @couchdb.stub!(:store).and_return({ "rev" => 33 })
- Chef::CouchDB.stub!(:new).and_return(@couchdb)
- @node = Chef::Node.new
- @node.name "bob"
- @node.couchdb_rev = 1
- end
-
- it "should save the node to couchdb" do
- @couchdb.should_receive(:store).with("node", "bob", @node).and_return({ "rev" => 33 })
- @node.cdb_save
- end
-
- it "should store the new couchdb_rev" do
- @node.cdb_save
- @node.couchdb_rev.should eql(33)
- end
- end
-
- describe "create_design_document" do
- it "should create our design document" do
- @couchdb.should_receive(:create_design_document).with("nodes", Chef::Node::DESIGN_DOCUMENT)
- Chef::CouchDB.stub!(:new).and_return(@couchdb)
- Chef::Node.create_design_document
- end
- end
-
- end
-
end
diff --git a/chef/spec/unit/openid_registration_spec.rb b/chef/spec/unit/openid_registration_spec.rb
deleted file mode 100644
index 70d4964104..0000000000
--- a/chef/spec/unit/openid_registration_spec.rb
+++ /dev/null
@@ -1,153 +0,0 @@
-#
-# Author:: Adam Jacob (<adam@opscode.com>)
-# Copyright:: Copyright (c) 2008 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-
-describe Chef::OpenIDRegistration, "initialize" do
- it "should return a new Chef::OpenIDRegistration object" do
- Chef::OpenIDRegistration.new.should be_kind_of(Chef::OpenIDRegistration)
- end
-end
-
-describe Chef::OpenIDRegistration, "set_password" do
- it "should generate a salt for this object" do
- oreg = Chef::OpenIDRegistration.new
- oreg.salt.should eql(nil)
- oreg.set_password("foolio")
- oreg.salt.should_not eql(nil)
- end
-
- it "should encrypt the password with the salt and the plaintext password" do
- oreg = Chef::OpenIDRegistration.new
- oreg.set_password("foolio")
- oreg.password.should_not eql(nil)
- end
-end
-
-describe Chef::OpenIDRegistration, "to_json" do
- it "should serialize itself as json" do
- oreg = Chef::OpenIDRegistration.new
- oreg.set_password("monkey")
- json = oreg.to_json
- %w{json_class chef_type name salt password validated}.each do |verify|
- json.should =~ /#{verify}/
- end
- end
-end
-
-describe Chef::OpenIDRegistration, "from_json" do
- it "should serialize itself as json" do
- oreg = Chef::OpenIDRegistration.new()
- oreg.name = "foobar"
- oreg.set_password("monkey")
- oreg_json = oreg.to_json
- nreg = Chef::JSONCompat.from_json(oreg_json)
- nreg.should be_a_kind_of(Chef::OpenIDRegistration)
- %w{name salt password validated}.each do |verify|
- nreg.send(verify.to_sym).should eql(oreg.send(verify.to_sym))
- end
- end
-end
-
-describe Chef::OpenIDRegistration, "list" do
- before(:each) do
- @mock_couch = mock("Chef::CouchDB")
- @mock_couch.stub!(:list).and_return({
- "rows" => [
- {
- "value" => "a",
- "key" => "avenue"
- }
- ]
- })
- Chef::CouchDB.stub!(:new).and_return(@mock_couch)
- end
-
- it "should retrieve a list of nodes from CouchDB" do
- Chef::OpenIDRegistration.list.should eql(["avenue"])
- end
-
- it "should return just the ids if inflate is false" do
- Chef::OpenIDRegistration.list(false).should eql(["avenue"])
- end
-
- it "should return the full objects if inflate is true" do
- Chef::OpenIDRegistration.list(true).should eql(["a"])
- end
-end
-
-describe Chef::OpenIDRegistration, "load" do
- it "should load a registration from couchdb by name" do
- @mock_couch = mock("Chef::CouchDB")
- Chef::CouchDB.stub!(:new).and_return(@mock_couch)
- @mock_couch.should_receive(:load).with("openid_registration", "coffee").and_return(true)
- Chef::OpenIDRegistration.load("coffee")
- end
-end
-
-describe Chef::OpenIDRegistration, "destroy" do
- it "should delete this registration from couchdb" do
- @mock_couch = mock("Chef::CouchDB")
- @mock_couch.should_receive(:delete).with("openid_registration", "bob", 1).and_return(true)
- Chef::CouchDB.stub!(:new).and_return(@mock_couch)
- reg = Chef::OpenIDRegistration.new
- reg.name = "bob"
- reg.couchdb_rev = 1
- reg.destroy
- end
-end
-
-describe Chef::OpenIDRegistration, "save" do
- before(:each) do
- @mock_couch = mock("Chef::CouchDB")
- Chef::CouchDB.stub!(:new).and_return(@mock_couch)
- @reg = Chef::OpenIDRegistration.new
- @reg.name = "bob"
- @reg.couchdb_rev = 1
- end
-
- it "should save the registration to couchdb" do
- @mock_couch.should_receive(:store).with("openid_registration", "bob", @reg).and_return({ "rev" => 33 })
- @reg.save
- end
-
- it "should store the new couchdb_rev" do
- @mock_couch.stub!(:store).with("openid_registration", "bob", @reg).and_return({ "rev" => 33 })
- @reg.save
- @reg.couchdb_rev.should eql(33)
- end
-end
-
-describe Chef::OpenIDRegistration, "create_design_document" do
- it "should create our design document" do
- mock_couch = mock("Chef::CouchDB")
- mock_couch.should_receive(:create_design_document).with("registrations", Chef::OpenIDRegistration::DESIGN_DOCUMENT)
- Chef::CouchDB.stub!(:new).and_return(mock_couch)
- Chef::OpenIDRegistration.create_design_document
- end
-end
-
-describe Chef::OpenIDRegistration, "has_key?" do
- it "should check with CouchDB for a registration with this key" do
- @mock_couch = mock("Chef::CouchDB")
- @mock_couch.should_receive(:has_key?).with("openid_registration", "bob").and_return(true)
- Chef::CouchDB.stub!(:new).and_return(@mock_couch)
- Chef::OpenIDRegistration.has_key?("bob")
- end
-end
-
diff --git a/chef/spec/unit/provider/ohai_spec.rb b/chef/spec/unit/provider/ohai_spec.rb
index c86ad288eb..8402c92e97 100644
--- a/chef/spec/unit/provider/ohai_spec.rb
+++ b/chef/spec/unit/provider/ohai_spec.rb
@@ -34,7 +34,7 @@ describe Chef::Provider::Ohai do
:platform => @platform,
:platform_version => @platform_version,
:data => {
- :origdata => "somevalue"
+ :origdata => "somevalue"
},
:data2 => {
:origdata => "somevalue",
@@ -49,7 +49,7 @@ describe Chef::Provider::Ohai do
Chef::Platform.stub!(:find_platform_and_version).and_return({ "platform" => @platform,
"platform_version" => @platform_version})
# Fake node with a dummy save
- @node = Chef::Node.new(@hostname)
+ @node = Chef::Node.new
@node.name(@fqdn)
@node.stub!(:save).and_return(@node)
@events = Chef::EventDispatch::Dispatcher.new
diff --git a/chef/spec/unit/run_list_spec.rb b/chef/spec/unit/run_list_spec.rb
index cc261edbd8..f18f21a82b 100644
--- a/chef/spec/unit/run_list_spec.rb
+++ b/chef/spec/unit/run_list_spec.rb
@@ -23,13 +23,6 @@ require 'spec_helper'
require 'chef/version_class'
require 'chef/version_constraint'
-# dep_selector/gecode on many platforms is currenly a bowel of hurt
-begin
-require 'chef/cookbook_version_selector'
-rescue LoadError
- STDERR.puts "\n*** dep_selector not installed. marking all unit tests 'pending' that have a transitive dependency on dep_selector. ***\n\n"
-end
-
describe Chef::RunList do
before(:each) do
@run_list = Chef::RunList.new
@@ -255,13 +248,6 @@ describe Chef::RunList do
end
- describe "from couchdb" do
- it "should load the role from couchdb" do
- Chef::Role.should_receive(:cdb_load).and_return(@role)
- @run_list.expand("_default", "couchdb")
- end
- end
-
it "should return the list of expanded recipes" do
expansion = @run_list.expand("_default")
expansion.recipes[0].should == "one"
@@ -323,199 +309,4 @@ describe Chef::RunList do
end
- describe "constrain" do
-
- pending "=> can't find 'dep_selector' gem...skipping Chef::CookbookVersionSelector related tests" do
-
- @fake_db = Object.new
-
- def cookbook_maker(name, version, deps)
- book = Chef::CookbookVersion.new(name, @fake_db)
- book.version = version
- deps.each { |dep_name, vc| book.metadata.depends(dep_name, vc) }
- book
- end
-
- def vc_maker(cookbook_name, version_constraint)
- vc = Chef::VersionConstraint.new(version_constraint)
- { :name => cookbook_name, :version_constraint => vc }
- end
-
- def assert_failure_unsatisfiable_item(run_list, all_cookbooks, constraints, expected_message)
- begin
- Chef::CookbookVersionSelector.constrain(all_cookbooks, constraints)
- fail "Should have raised a Chef::Exceptions::CookbookVersionSelection::UnsatisfiableRunListItem exception"
- rescue Chef::Exceptions::CookbookVersionSelection::UnsatisfiableRunListItem => urli
- urli.message.should include(expected_message)
- end
- end
-
- def assert_failure_invalid_items(run_list, all_cookbooks, constraints, expected_message)
- begin
- Chef::CookbookVersionSelector.constrain(all_cookbooks, constraints)
- fail "Should have raised a Chef::Exceptions::CookbookVersionSelection::InvalidRunListItems exception"
- rescue Chef::Exceptions::CookbookVersionSelection::InvalidRunListItems => irli
- irli.message.should include(expected_message)
- end
- end
-
- before(:each) do
- a1 = cookbook_maker("a", "1.0", [["c", "< 4.0"]])
- b1 = cookbook_maker("b", "1.0", [["c", "< 3.0"]])
-
- c2 = cookbook_maker("c", "2.0", [["d", "> 1.0"], ["f", nil]])
- c3 = cookbook_maker("c", "3.0", [["d", "> 2.0"], ["e", nil]])
-
- d1_1 = cookbook_maker("d", "1.1", [])
- d2_1 = cookbook_maker("d", "2.1", [])
- e1 = cookbook_maker("e", "1.0", [])
- f1 = cookbook_maker("f", "1.0", [])
- g1 = cookbook_maker("g", "1.0", [["d", "> 5.0"]])
-
- n1_1 = cookbook_maker("n", "1.1", [])
- n1_2 = cookbook_maker("n", "1.2", [])
- n1_10 = cookbook_maker("n", "1.10", [])
-
- depends_on_nosuch = cookbook_maker("depends_on_nosuch", "1.0", [["nosuch", nil]])
-
- @all_cookbooks = {
- "a" => [a1],
- "b" => [b1],
- "c" => [c2, c3],
- "d" => [d1_1, d2_1],
- "e" => [e1],
- "f" => [f1],
- "g" => [g1],
- "n" => [n1_1, n1_2, n1_10],
- "depends_on_nosuch" => [depends_on_nosuch]
- }
-
- $stderr.reopen DEV_NULL
- end
-
- after do
- $stderr.reopen STDERR
- end
-
- it "pulls in transitive dependencies" do
- constraints = [vc_maker("a", "~> 1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- %w(a c d e).each { |k| cookbooks.should have_key k }
- cookbooks.size.should == 4
- cookbooks["c"].version.should == "3.0.0"
- cookbooks["d"].version.should == "2.1.0"
- end
-
- it "should satisfy recipe-specific dependencies" do
- depends_on_recipe = cookbook_maker("depends_on_recipe", "1.0", [["f::recipe", "1.0"]])
- @all_cookbooks["depends_on_recipe"] = [depends_on_recipe]
- constraints = [vc_maker("depends_on_recipe", "= 1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks["f"].version.should == "1.0.0"
- end
-
- it "properly sorts version triples, treating each term numerically" do
- constraints = [vc_maker("n", "> 1.2")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 1
- cookbooks["n"].version.should == "1.10.0"
- end
-
- it "should fail to find a solution when a run list item is constrained to a range that includes no cookbooks" do
- constraints = [vc_maker("d", "> 5.0")]
- assert_failure_invalid_items(@run_list, @all_cookbooks, constraints, "Run list contains invalid items: no versions match the constraints on cookbook d.")
- end
-
- it "should fail to find a solution when a run list item's dependency is constrained to a range that includes no cookbooks" do
- constraints = [vc_maker("g", nil)]
- assert_failure_unsatisfiable_item(@run_list, @all_cookbooks, constraints, "Unable to satisfy constraints on cookbook d due to run list item (g >= 0.0.0)")
- end
-
- it "selects 'd 2.1.0' given constraint 'd > 1.2.3'" do
- constraints = [vc_maker("d", "> 1.2.3")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 1
- cookbooks["d"].version.should == "2.1.0"
- end
-
- it "selects largest version when constraint allows multiple" do
- constraints = [vc_maker("d", "> 1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 1
- cookbooks["d"].version.should == "2.1.0"
- end
-
- it "selects 'd 1.1.0' given constraint 'd ~> 1.0'" do
- constraints = [vc_maker("d", "~> 1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 1
- cookbooks["d"].version.should == "1.1.0"
- end
-
- it "raises InvalidRunListItems for an unknown cookbook in the run list" do
- constraints = [vc_maker("nosuch", "1.0.0")]
- assert_failure_invalid_items(@run_list, @all_cookbooks, constraints, "Run list contains invalid items: no such cookbook nosuch.")
- end
-
- it "raises CookbookVersionConflict for an unknown cookbook in a cookbook's dependencies" do
- constraints = [vc_maker("depends_on_nosuch", "1.0.0")]
- assert_failure_unsatisfiable_item(@run_list, @all_cookbooks, constraints, "Unable to satisfy constraints on cookbook nosuch, which does not exist, due to run list item (depends_on_nosuch = 1.0.0). Run list items that may result in a constraint on nosuch: [(depends_on_nosuch = 1.0.0) -> (nosuch >= 0.0.0)]")
- end
-
- it "raises UnsatisfiableRunListItem for direct conflict" do
- constraints = [vc_maker("d", "= 1.1.0"), vc_maker("d", ">= 2.0")]
- assert_failure_unsatisfiable_item(@run_list, @all_cookbooks, constraints, "Unable to satisfy constraints on cookbook d due to run list item (d >= 2.0.0)")
- end
-
- describe "should solve regardless of constraint order" do
-
- it "raises CookbookVersionConflict a then b" do
- # Cookbooks a and b both have a dependency on c, but with
- # differing constraints.
- constraints = [vc_maker("a", "1.0"), vc_maker("b", "1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 5
- %w(a b c d f).each { |k| cookbooks.should have_key k }
- cookbooks["a"].version.should == "1.0.0"
- cookbooks["b"].version.should == "1.0.0"
- cookbooks["c"].version.should == "2.0.0"
- cookbooks["d"].version.should == "2.1.0"
- end
-
- it "resolves b then a" do
- # See above comment for a then b. When b is pulled in first,
- # we should get a version of c that satifies the constraints
- # on the c dependency for both b and a.
- constraints = [vc_maker("b", "1.0"), vc_maker("a", "1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 5
- %w(a b c d f).each { |k| cookbooks.should have_key k }
- cookbooks["a"].version.should == "1.0.0"
- cookbooks["b"].version.should == "1.0.0"
- cookbooks["c"].version.should == "2.0.0"
- cookbooks["d"].version.should == "2.1.0"
- end
-
- it "resolves a then d" do
- constraints = [vc_maker("a", "1.0"), vc_maker("d", "1.1")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 4
- %w(a c d f).each { |k| cookbooks.should have_key k }
- cookbooks["a"].version.should == "1.0.0"
- cookbooks["c"].version.should == "2.0.0"
- cookbooks["d"].version.should == "1.1.0"
- end
-
- it "resolves d then a" do
- constraints = [vc_maker("d", "1.1"), vc_maker("a", "1.0")]
- cookbooks = Chef::CookbookVersionSelector.constrain(@all_cookbooks, constraints)
- cookbooks.size.should == 4
- %w(a c d f).each { |k| cookbooks.should have_key k }
- cookbooks["a"].version.should == "1.0.0"
- cookbooks["c"].version.should == "2.0.0"
- cookbooks["d"].version.should == "1.1.0"
- end
- end
- end
- end
end
diff --git a/chef/spec/unit/solr_query/query_transform_spec.rb b/chef/spec/unit/solr_query/query_transform_spec.rb
deleted file mode 100644
index f3fc746746..0000000000
--- a/chef/spec/unit/solr_query/query_transform_spec.rb
+++ /dev/null
@@ -1,454 +0,0 @@
-#
-# Author:: Seth Falcon (<seth@opscode.com>)
-# Copyright:: Copyright (c) 2010-2011 Opscode, Inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-require 'chef/solr_query/query_transform'
-
-describe "Chef::SolrQuery::QueryTransform" do
- before(:each) do
- @parser = Chef::SolrQuery::QueryTransform
- @parseError = Chef::Exceptions::QueryParseError
- end
-
- describe "single term queries" do
- basic_terms = %w(a ab 123 a1 2b foo_bar baz-baz)
- basic_terms << " leading"
- basic_terms << "trailing "
- basic_terms += %w(XAND ANDX XOR ORX XNOT NOTX)
- basic_terms.each do |term|
- expect = "T:#{term.strip}"
- it "'#{term}' => #{expect}" do
- @parser.parse(term).should == expect
- end
- end
- describe "invalid" do
- %w(AND OR NOT :).each do |t|
- it "'#{t}' => ParseError" do
- lambda { @parser.parse(t) }.should raise_error(@parseError)
- end
- end
- end
-
- describe "wildcards in terms" do
- it "allows * as a wildcard" do
- @parser.parse("foo*bar").should == "T:foo*bar"
- end
-
- it "allows a single ? as a wildcard" do
- @parser.parse("foo?bar").should == "T:foo?bar"
- end
-
- it "allows multiple ? as fixed length wildcards" do
- @parser.parse("foo???bar").should == "T:foo???bar"
- end
-
- it "allows a leading wildcard with *" do
- # NOTE: This is not valid lucene query syntax. However, our
- # index format and query transformation can allow it because
- # the transformed query ends up with the '*' not in leading
- # position. We decided that allowing it makes sense because
- # queries like ec2:* are useful and many users expect this
- # behavior to work.
- @parser.parse("*foobar").should == "T:*foobar"
- end
-
- it "does not allow a leading wildcard with ?" do
- lambda { @parser.parse("?foobar") }.should raise_error(@parseError)
- end
-
- it "does not allow a leading wildcard with ?" do
- lambda { @parser.parse("afield:?foobar") }.should raise_error(@parseError)
- end
-
- end
-
- describe "escaped special characters in terms" do
- special_chars = ["!", "(", ")", "{", "}", "[", "]", "^", "\"",
- "~", "*", "?", ":", "\\", "&", "|", "+", "-"]
- example_fmts = ['foo%sbar', '%sb', 'a%s']
- special_chars.each do |char|
- example_fmts.each do |fmt|
- input = fmt % ("\\" + char)
- expect = "T:#{input}"
- it "'#{input}' => #{expect}" do
- @parser.parse(input).should == expect
- end
- end
- end
- end
-
- describe "special characters in terms are not allowed" do
- # NOTE: '*' is not a valid start letter for a lucene search
- # term, however, we can support it because of our index
- # structure and query transformation. We decided to keep this
- # flexibility because queries like ec2:* are common and useful.
- prefix_ok = ["!", "+", "-", "*"]
- suffix_ok = ["*", "?", "~", "-"]
- # FIXME: ideally, '!' would not be allowed in the middle of a
- # term. Currently we parse foo!bar the same as foo !bar.
- # Also '+' might be nice to disallow
- embed_ok = ["*", "?", ":", "-", "!", "+"]
- special_chars = ["!", "(", ")", "{", "}", "[", "]", "^", "\"",
- "~", "*", "?", ":", "\\", "&", "|", "+", "-"]
- example_fmts = {
- :prefix => '%sb',
- :middle => 'foo%sbar',
- :suffix => 'a%s'
- }
- special_chars.each do |char|
- example_fmts.keys.each do |key|
- fmt = example_fmts[key]
- if key == :prefix && prefix_ok.include?(char)
- :pass
- elsif key == :middle && embed_ok.include?(char)
- :pass
- elsif key == :suffix && suffix_ok.include?(char)
- :pass
- else
- input = fmt % char
- it "disallows: '#{input}'" do
- lambda { @parser.parse(input) }.should raise_error(@parseError)
- end
- end
- end
- end
- end
-
- end
-
- describe "multiple terms" do
- it "should allow multiple terms" do
- @parser.parse("a b cdefg").should == "T:a T:b T:cdefg"
- end
- end
-
- describe "boolean queries" do
- describe "two term basic and/or" do
- binary_operators = [['AND', 'AND'], ['&&', 'AND'], ['OR', 'OR'], ['||', 'OR']]
- binary_operators.each do |op, op_name|
- expect = "(OP:#{op_name} T:t1 T:t2)"
- it "should parse 't1 #{op} t2' => #{expect}" do
- @parser.parse("t1 #{op} t2").should == expect
- end
- end
- end
-
- it "should allow a string of terms with ands and ors" do
- expect = "(OP:AND T:t1 (OP:OR T:t2 (OP:AND T:t3 T:t4)))"
- @parser.parse("t1 AND t2 OR t3 AND t4").should == expect
- end
- end
-
- describe "grouping with parens" do
- it "should create a single group for (aterm)" do
- @parser.parse("(aterm)").should == "(T:aterm)"
- end
-
- describe "and booleans" do
-
- %w(AND &&).each do |op|
- expect = "((OP:AND T:a T:b))"
- input = "(a #{op} b)"
- it "parses #{input} => #{expect}" do
- @parser.parse(input).should == expect
- end
- end
-
- %w(OR ||).each do |op|
- expect = "((OP:OR T:a T:b))"
- input = "(a #{op} b)"
- it "parses #{input} => #{expect}" do
- @parser.parse(input).should == expect
- end
- end
-
- it "should handle a LHS group" do
- expect = "(OP:OR ((OP:AND T:a T:b)) T:c)"
- @parser.parse("(a && b) OR c").should == expect
- @parser.parse("(a && b) || c").should == expect
- end
-
- it "should handle a RHS group" do
- expect = "(OP:OR T:c ((OP:AND T:a T:b)))"
- @parser.parse("c OR (a && b)").should == expect
- @parser.parse("c OR (a AND b)").should == expect
- end
-
- it "should handle both sides as groups" do
- expect = "(OP:OR ((OP:AND T:c T:d)) ((OP:AND T:a T:b)))"
- @parser.parse("(c AND d) OR (a && b)").should == expect
- end
- end
- end
-
- describe "NOT queries" do
- # input, output
- [
- ["a NOT b", "T:a (OP:NOT T:b)"],
- ["a ! b", "T:a (OP:NOT T:b)"],
- ["a !b", "T:a (OP:NOT T:b)"],
- ["a NOT (b || c)", "T:a (OP:NOT ((OP:OR T:b T:c)))"],
- ["a ! (b || c)", "T:a (OP:NOT ((OP:OR T:b T:c)))"],
- ["a !(b || c)", "T:a (OP:NOT ((OP:OR T:b T:c)))"]
- ].each do |input, expected|
- it "should parse '#{input}' => #{expected.inspect}" do
- @parser.parse(input).should == expected
- end
- end
-
- ["NOT", "a NOT", "(NOT)"].each do |d|
- it "should raise a ParseError on '#{d}'" do
- lambda { @parser.parse(d) }.should raise_error(@parseError)
- end
- end
- end
-
- describe 'required and prohibited prefixes (+/-)' do
- ["+", "-"].each do |kind|
- [
- ["#{kind}foo", "(OP:#{kind} T:foo)"],
- ["bar #{kind}foo", "T:bar (OP:#{kind} T:foo)"],
- ["(#{kind}oneA twoA) b", "((OP:#{kind} T:oneA) T:twoA) T:b"]
- ].each do |input, expect|
- it "should parse '#{input} => #{expect.inspect}" do
- @parser.parse(input).should == expect
- end
- end
- end
-
- # it 'ignores + embedded in a term' do
- # @parser.parse("one+two").should == "T:one+two"
- # end
-
- it 'ignores - embedded in a term' do
- @parser.parse("one-two").should == "T:one-two"
- end
-
- it "allows a trailing dash" do
- @parser.parse("one-").should == "T:one-"
- end
-
- end
-
- describe "phrases (strings)" do
- phrases = [['"single"', 'STR:"single"'],
- ['"two term"', 'STR:"two term"'],
- ['"has \"escaped\" quote\"s"', 'STR:"has \"escaped\" quote\"s"']
- ]
- phrases.each do |phrase, expect|
- it "'#{phrase}' => #{expect}" do
- @parser.parse(phrase).should == expect
- end
- end
-
- describe "invalid" do
- bad = ['""', '":not:a:term"', '"a :bad:']
- bad.each do |t|
- it "'#{t}' => ParseError" do
- lambda { @parser.parse(t) }.should raise_error(@parseError)
- end
- end
- end
-
- it "allows phrases to be required with '+'" do
- @parser.parse('+"a b c"').should == '(OP:+ STR:"a b c")'
- end
-
- it "allows phrases to be prohibited with '-'" do
- @parser.parse('-"a b c"').should == '(OP:- STR:"a b c")'
- end
-
- it "allows phrases to be excluded with NOT" do
- @parser.parse('a NOT "b c"').should == 'T:a (OP:NOT STR:"b c")'
- end
-
- end
-
- describe "fields" do
- it "parses a term annotated with a field" do
- @parser.parse("afield:aterm").should == "(F:afield T:aterm)"
- end
-
- it "allows underscore in a field name" do
- @parser.parse("a_field:aterm").should == "(F:a_field T:aterm)"
- end
-
- it "parses a group annotated with a field" do
- @parser.parse("afield:(a b c)").should == "(F:afield (T:a T:b T:c))"
- end
-
- it "parses a phrase annotated with a field" do
- @parser.parse('afield:"a b c"').should == '(F:afield STR:"a b c")'
- end
-
- it "allows @ in a term" do
- @parser.parse('afield:foo@acme.org').should == '(F:afield T:foo@acme.org)'
- end
-
- describe "and binary operators" do
- examples = [
- ['term1 AND afield:term2', "(OP:AND T:term1 (F:afield T:term2))"],
- ['afield:term1 AND term2', "(OP:AND (F:afield T:term1) T:term2)"],
- ['afield:term1 AND bfield:term2',
- "(OP:AND (F:afield T:term1) (F:bfield T:term2))"]]
- examples.each do |input, want|
- it "'#{input}' => '#{want}'" do
- @parser.parse(input).should == want
- end
- end
- end
-
- describe "and unary operators" do
- examples = [
- ['term1 AND NOT afield:term2',
- "(OP:AND T:term1 (OP:NOT (F:afield T:term2)))"],
- ['term1 AND ! afield:term2',
- "(OP:AND T:term1 (OP:NOT (F:afield T:term2)))"],
- ['term1 AND !afield:term2',
- "(OP:AND T:term1 (OP:NOT (F:afield T:term2)))"],
- ['term1 AND -afield:term2',
- "(OP:AND T:term1 (OP:- (F:afield T:term2)))"],
- ['-afield:[* TO *]',
- "(OP:- (FR:afield [*] [*]))"]
- ]
- examples.each do |input, want|
- it "#{input} => #{want}" do
- @parser.parse(input).should == want
- end
- end
- end
- end
-
- describe "range queries" do
- before(:each) do
- @kinds = {
- "inclusive" => {:left => "[", :right => "]"},
- "exclusive" => {:left => "{", :right => "}"}
- }
- end
-
- def make_expect(kind, field, s, e)
- expect_fmt = "(FR:%s %s%s%s %s%s%s)"
- left = @kinds[kind][:left]
- right = @kinds[kind][:right]
- expect_fmt % [field, left, s, right, left, e, right]
- end
-
- def make_query(kind, field, s, e)
- query_fmt = "%s:%s%s TO %s%s"
- left = @kinds[kind][:left]
- right = @kinds[kind][:right]
- query_fmt % [field, left, s, e, right]
- end
-
- ["inclusive", "exclusive"].each do |kind|
- tests = [["afield", "start", "end"],
- ["afield", "start", "*"],
- ["afield", "*", "end"],
- ["afield", "*", "*"]
- ]
- tests.each do |field, s, e|
- it "parses an #{kind} range query #{s} TO #{e}" do
- expect = make_expect(kind, field, s, e)
- query = make_query(kind, field, s, e)
- @parser.parse(query).should == expect
- end
- end
- end
-
- describe "and binary operators" do
- [["afield:[start TO end] AND term",
- "(OP:AND (FR:afield [start] [end]) T:term)"],
- ["term OR afield:[start TO end]",
- "(OP:OR T:term (FR:afield [start] [end]))"],
- ["f1:[s1 TO e1] OR f2:[s2 TO e2]",
- "(OP:OR (FR:f1 [s1] [e1]) (FR:f2 [s2] [e2]))"]
- ].each do |q, want|
- it "parses '#{q}'" do
- @parser.parse(q).should == want
- end
- end
- end
-
- describe "and unary operators" do
- [["t1 NOT afield:[start TO end]",
- "T:t1 (OP:NOT (FR:afield [start] [end]))"]
- ].each do |input, want|
- it "#{input} => #{want}" do
- @parser.parse(input).should == want
- end
- end
- end
- end
-
- describe "proximity query" do
- [
- ['"one two"~10', '(OP:~ STR:"one two" 10)'],
- ['word~', '(OP:~ T:word)'],
- ['word~0.5', '(OP:~ T:word 0.5)']
- ].each do |input, expect|
- it "'#{input}' => #{expect}" do
- @parser.parse(input).should == expect
- end
- end
- end
-
- describe "term boosting" do
- [
- ['"one two"^10', '(OP:^ STR:"one two" 10)'],
- ['word^0.5', '(OP:^ T:word 0.5)']
- ].each do |input, expect|
- it "'#{input}' => #{expect}" do
- @parser.parse(input).should == expect
- end
- end
-
- it "should fail to parse if no boosting argument is given" do
- lambda { @parser.parse("foo^")}.should raise_error(@parseError)
- end
- end
-
- describe "examples" do
- examples = [['tags:apples*.for.eating.com', "(F:tags T:apples*.for.eating.com)"],
- ['ohai_time:[1234.567 TO *]', "(FR:ohai_time [1234.567] [*])"],
- ['ohai_time:[* TO 1234.567]', "(FR:ohai_time [*] [1234.567])"],
- ['ohai_time:[* TO *]', "(FR:ohai_time [*] [*])"]]
- # ['aterm AND afield:aterm', "((OP:AND T:aterm ((F:afield T:aterm))))"],
- # ['role:prod AND aterm', "blah"],
- # ['role:prod AND xy:true', "blah"]]
- examples.each do |input, want|
- it "'#{input}' => '#{want}'" do
- @parser.parse(input).should == want
- end
- end
- end
-
- describe "transform queries for solr schema" do
- testcase_file = "#{CHEF_SPEC_DATA}/search_queries_to_transform.txt"
- lines = File.readlines(testcase_file).map { |line| line.strip }
- lines = lines.select { |line| !line.empty? }
- testcases = Hash[*(lines)]
- testcases.keys.sort.each do |input|
- expected = testcases[input]
- it "from> #{input}\n to> #{expected}\n" do
- @parser.transform(input).should == expected
- end
- end
- end
-
-end
diff --git a/chef/spec/unit/solr_query/solr_http_request_spec.rb b/chef/spec/unit/solr_query/solr_http_request_spec.rb
deleted file mode 100644
index c70c347a14..0000000000
--- a/chef/spec/unit/solr_query/solr_http_request_spec.rb
+++ /dev/null
@@ -1,244 +0,0 @@
-# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Copyright:: Copyright (c) 2011 Opscode, inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-
-require 'chef/solr_query'
-require 'net/http'
-
-describe Chef::SolrQuery::SolrHTTPRequest do
- before do
- Chef::Config[:solr_url] = "http://example.com:8983"
- Chef::SolrQuery::SolrHTTPRequest.instance_variable_set(:@solr_url, nil)
- Chef::SolrQuery::SolrHTTPRequest.instance_variable_set(:@url_prefix, nil)
-
- @request = Chef::SolrQuery::SolrHTTPRequest.new(:GET, '/solr/select')
- end
-
- it "defaults to using the configured solr_url" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url.should == "http://example.com:8983"
- end
-
- it "supports solr_url with a path" do
- Chef::Config[:solr_url] = "http://example.com:8983/test"
- Chef::SolrQuery::SolrHTTPRequest.instance_variable_set(:@solr_url, nil)
-
- Chef::SolrQuery::SolrHTTPRequest.solr_url.should == "http://example.com:8983/test"
- end
-
- it "updates the Solr URL as you like" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234"
- Chef::SolrQuery::SolrHTTPRequest.solr_url.should == "http://chunkybacon.org:1234"
- end
-
- it "updates the URL prefix with a path" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234/something"
- Chef::SolrQuery::SolrHTTPRequest.url_prefix.should == "/something"
- end
-
- it "removes extra / at the end of solr_url" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234/extra/"
- Chef::SolrQuery::SolrHTTPRequest.url_prefix.should == "/extra"
- end
-
- it "creates a Net::HTTP client for the base Solr URL" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234"
- http_client = Chef::SolrQuery::SolrHTTPRequest.http_client
- http_client.address.should == "chunkybacon.org"
- http_client.port.should == 1234
- end
-
- it "creates a Net::HTTP client for the base Solr URL ignoring the path" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234/test"
- http_client = Chef::SolrQuery::SolrHTTPRequest.http_client
- http_client.address.should == "chunkybacon.org"
- http_client.port.should == 1234
- end
-
- it "defaults url_prefix to /solr if the configured solr_url has no path" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234"
- Chef::SolrQuery::SolrHTTPRequest.url_prefix.should == "/solr"
- end
-
- it "defaults url_prefix to the path from the configured solr_url" do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://chunkybacon.org:1234/test"
- Chef::SolrQuery::SolrHTTPRequest.url_prefix.should == "/test"
- end
-
- describe "when configured with the Solr URL" do
- before do
- @http_response = mock(
- "Net::HTTP::Response",
- :kind_of? => Net::HTTPSuccess,
- :body => "{ :some => :hash }"
- )
- @http_request = mock(
- "Net::HTTP::Request",
- :body= => true
- )
- @http = mock("Net::HTTP", :request => @http_response)
- Chef::SolrQuery::SolrHTTPRequest.stub!(:http_client).and_return(@http)
- end
-
- describe "when executing a select query" do
- before(:each) do
- @http_response = mock(
- "Net::HTTP::Response",
- :kind_of? => Net::HTTPSuccess,
- :body => '{"some": "hash" }'
- )
- @solr = Chef::SolrQuery.from_params(:type => 'node',
- :q => "hostname:latte")
- @params = @solr.to_hash
- @http = mock("Net::HTTP", :request => @http_response)
- Chef::SolrQuery::SolrHTTPRequest.stub!(:http_client).and_return(@http)
- end
-
- describe "when the HTTP call is successful" do
- it "should call get to /solr/select with the escaped query" do
- txfm_query = "q=content%3Ahostname__%3D__latte"
- Net::HTTP::Get.should_receive(:new).with(%r(/solr/select?.+#{txfm_query}))
- Chef::SolrQuery::SolrHTTPRequest.select(@params)
- end
-
- it "uses Solr's JSON response format" do
- Net::HTTP::Get.should_receive(:new).with(%r(wt=json))
- Chef::SolrQuery::SolrHTTPRequest.select(@params)
- end
-
- it "uses indent=off to get a compact response" do
- Net::HTTP::Get.should_receive(:new).with(%r(indent=off))
- Chef::SolrQuery::SolrHTTPRequest.select(@params)
- end
-
- it "uses the filter query to restrict the result set" do
- filter_query =@solr.filter_query.gsub('+', '%2B').gsub(':', "%3A").gsub(' ', '+')
- Net::HTTP::Get.should_receive(:new).with(/fq=#{Regexp.escape(filter_query)}/)
- Chef::SolrQuery::SolrHTTPRequest.select(@params)
- end
-
- it "returns the evaluated response body" do
- res = Chef::SolrQuery::SolrHTTPRequest.select(@params)
- res.should == {"some" => "hash" }
- end
- end
- end
-
- describe "when updating" do
- before do
- Net::HTTP::Post.stub!(:new).and_return(@http_request)
- end
-
- it "should post to /solr/update" do
- @doc = "<xml is the old tldr>"
- Net::HTTP::Post.should_receive(:new).with("/solr/update", "Content-Type" => "text/xml").and_return(@http_request)
- Chef::SolrQuery::SolrHTTPRequest.update(@doc)
- end
-
- it "should set the body of the request to the stringified doc" do
- @http_request.should_receive(:body=).with("foo")
- Chef::SolrQuery::SolrHTTPRequest.update(:foo)
- end
-
- it "should send the request to solr" do
- @http.should_receive(:request).with(@http_request).and_return(@http_response)
- Chef::SolrQuery::SolrHTTPRequest.update(:foo)
- end
-
- end
-
- describe "when the HTTP call is unsuccessful" do
- [Timeout::Error, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EINVAL].each do |exception|
- it "should rescue, log an error message, and raise a SolrConnectionError encountering exception #{exception}" do
- response = mock("Net:HTTPResponse test double", :code => 500, :message => "oops", :class => exception)
- @http.should_receive(:request).with(instance_of(Net::HTTP::Get)).and_return(response)
- response.should_receive(:error!).and_raise(exception)
- Chef::Log.should_receive(:fatal).with("Search Query to Solr failed (#{exception} 500 oops)")
-
- lambda {@request.run('Search Query to Solr')}.should raise_error(Chef::Exceptions::SolrConnectionError)
- end
- end
-
- it "should rescue, log an error message, and raise a SolrConnectionError when encountering exception NoMethodError and net/http closed? bug" do
- @no_method_error = NoMethodError.new("undefined method 'closed\?' for nil:NilClass")
- @http.should_receive(:request).with(instance_of(Net::HTTP::Get)).and_raise(@no_method_error)
- Chef::Log.should_receive(:fatal).with("HTTP Request to Solr failed. Chef::Exceptions::SolrConnectionError exception: Errno::ECONNREFUSED (net/http undefined method closed?) attempting to contact http://example.com:8983")
- lambda {
- @request.run
- }.should raise_error(Chef::Exceptions::SolrConnectionError)
- end
- end
-
- end
-
- describe "when configured with the Solr URL with a path" do
- before do
- Chef::Config[:solr_url] = "http://example.com:8983/test"
- Chef::SolrQuery::SolrHTTPRequest.instance_variable_set(:@solr_url, nil)
- Chef::SolrQuery::SolrHTTPRequest.instance_variable_set(:@url_prefix, nil)
-
- @request = Chef::SolrQuery::SolrHTTPRequest.new(:GET, '/solr/select')
-
- @http_response = mock(
- "Net::HTTP::Response",
- :kind_of? => Net::HTTPSuccess,
- :body => "{ :some => :hash }"
- )
- @http_request = mock(
- "Net::HTTP::Request",
- :body= => true
- )
- @http = mock("Net::HTTP", :request => @http_response)
- Chef::SolrQuery::SolrHTTPRequest.stub!(:http_client).and_return(@http)
- end
-
- describe "when executing a select query" do
- before(:each) do
- @http_response = mock(
- "Net::HTTP::Response",
- :kind_of? => Net::HTTPSuccess,
- :body => '{"some": "hash" }'
- )
- @solr = Chef::SolrQuery.from_params(:type => 'node',
- :q => "hostname:latte")
- @params = @solr.to_hash
- @http = mock("Net::HTTP", :request => @http_response)
- Chef::SolrQuery::SolrHTTPRequest.stub!(:http_client).and_return(@http)
- end
-
- describe "when the HTTP call is successful" do
- it "should call get to /test/select with the escaped query" do
- txfm_query = "q=content%3Ahostname__%3D__latte"
- Net::HTTP::Get.should_receive(:new).with(%r(/test/select?.+#{txfm_query}))
- Chef::SolrQuery::SolrHTTPRequest.select(@params)
- end
- end
- end
-
- describe "when updating" do
- before do
- Net::HTTP::Post.stub!(:new).and_return(@http_request)
- end
-
- it "should post to /test/update" do
- @doc = "<xml is the old tldr>"
- Net::HTTP::Post.should_receive(:new).with("/test/update", "Content-Type" => "text/xml").and_return(@http_request)
- Chef::SolrQuery::SolrHTTPRequest.update(@doc)
- end
- end
- end
-end
diff --git a/chef/spec/unit/solr_query_spec.rb b/chef/spec/unit/solr_query_spec.rb
deleted file mode 100644
index 8b48011713..0000000000
--- a/chef/spec/unit/solr_query_spec.rb
+++ /dev/null
@@ -1,203 +0,0 @@
-# Author:: Daniel DeLeo (<dan@opscode.com>)
-# Copyright:: Copyright (c) 2010, 2011 Opscode, inc.
-# License:: Apache License, Version 2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-require 'spec_helper'
-
-require 'chef/solr_query'
-require 'net/http'
-
-#require 'rspec/mocks'
-
-describe Chef::SolrQuery do
- before do
- Chef::SolrQuery::SolrHTTPRequest.solr_url = "http://example.com:8983"
-
- @http_response = mock(
- "Net::HTTP::Response",
- :kind_of? => Net::HTTPSuccess,
- :body => "{ :some => :hash }"
- )
- @http_request = mock(
- "Net::HTTP::Request",
- :body= => true
- )
- @http = mock("Net::HTTP", :request => @http_response)
- Chef::SolrQuery::SolrHTTPRequest.stub!(:http_client).and_return(@http)
- Net::HTTP::Post.stub!(:new).and_return(@http_request)
- Net::HTTP::Get.stub!(:new).and_return(@http_request)
- @doc = { "foo" => "bar" }
- end
-
- before(:each) do
- @solr = Chef::SolrQuery.new
- end
-
- it "sets filter query params" do
- @solr.filter_by(:database => 'chef')
- @solr.filter_query.should == "+X_CHEF_database_CHEF_X:chef"
- end
-
- it "filters by type when querying for a builtin type" do
- @solr.filter_by_type("node")
- @solr.filter_query.should == "+X_CHEF_type_CHEF_X:node"
- end
-
- it "filters by type for data bag items" do
- @solr.filter_by_type("users")
- @solr.filter_query.split(" ").sort.should == ['+X_CHEF_type_CHEF_X:data_bag_item', '+data_bag:users']
- end
-
- it "stores the main query" do
- @solr.query = "role:prod AND tags:chef-server"
- @solr.query.should == "role:prod AND tags:chef-server"
- end
-
- describe "when generating query params for select" do
- before(:each) do
- @solr = Chef::SolrQuery.from_params(:type => 'node', :q => "hostname:latte")
- @params = @solr.to_hash
- end
-
- it "includes the query as q" do
- @params[:q].should == "content:hostname__=__latte"
- end
-
- it "sets the response format to json" do
- @params[:wt].should == "json"
- end
-
- it "uses indent=off to get a compact response" do
- @params[:indent].should == "off"
- end
-
- it "includes the filter query to restrict the result set" do
- @params[:fq].should == @solr.filter_query
- end
-
- it "defaults to returning 1000 rows" do
- @params[:rows].should == 1000
- end
-
- it "returns the number of rows requested" do
- @solr.params[:rows] = 500
- @solr.to_hash[:rows].should == 500
- end
-
- it "offsets the row selection if requested" do
- @solr.params[:start] = 500
- @solr.to_hash[:start].should == 500
- end
-
- end
-
- describe "when querying solr" do
- before do
- @couchdb = mock("CouchDB Test Double", :couchdb_database => "chunky_bacon")
- @couchdb.stub!(:kind_of?).with(Chef::CouchDB).and_return(true) #ugh.
- @solr = Chef::SolrQuery.from_params({:type => 'node', :q => "hostname:latte", :start => 10, :rows => 5}, @couchdb)
- @docs = [1,2,3,4,5].map { |doc_id| {'X_CHEF_id_CHEF_X' => doc_id} }
- @solr_response = {"response" => {"docs" => @docs, "start" => 10, "results" => 123}}
- Chef::SolrQuery::SolrHTTPRequest.should_receive(:select).with(@solr.to_hash).and_return(@solr_response)
- end
-
- it "it collects the document ids from the response" do
- @solr.object_ids.should == [1,2,3,4,5]
- end
-
- it "does a bulk get of the objects from CouchDB" do
- @couchdb.should_receive(:bulk_get).with([1,2,3,4,5]).and_return(%w{obj1 obj2 obj3 obj4 obj5})
- @solr.objects.should == %w{obj1 obj2 obj3 obj4 obj5}
- end
-
- end
-
- describe "when forcing a Solr commit" do
- it "sends valid commit xml to solr" do
- Chef::SolrQuery::SolrHTTPRequest.should_receive(:update).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<commit/>\n")
- @solr.commit
- end
- end
-
- describe "when deleting a database from Solr" do
- it "sends a valid delete query to solr and forces a commit" do
- Chef::SolrQuery::SolrHTTPRequest.should_receive(:update).with("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<delete><query>X_CHEF_database_CHEF_X:chef</query></delete>\n")
- @solr.should_receive(:commit)
- @solr.delete_database("chef")
- end
- end
-
- describe "rebuilding the index" do
- before do
- Chef::Config[:couchdb_database] = "chunky_bacon"
- end
-
- it "deletes the index and commits" do
- @solr.should_receive(:delete_database).with("chunky_bacon")
- @solr.stub!(:reindex_all)
- Chef::DataBag.stub!(:cdb_list).and_return([])
- @solr.rebuild_index
- end
-
- it "reindexes Chef::ApiClient, Chef::Node, and Chef::Role objects, reporting the results as a hash" do
- @solr.should_receive(:delete_database).with("chunky_bacon")
- @solr.should_receive(:reindex_all).with(Chef::ApiClient).and_return(true)
- @solr.should_receive(:reindex_all).with(Chef::Environment).and_return(true)
- @solr.should_receive(:reindex_all).with(Chef::Node).and_return(true)
- @solr.should_receive(:reindex_all).with(Chef::Role).and_return(true)
- Chef::DataBag.stub!(:cdb_list).and_return([])
-
- result = @solr.rebuild_index
- result["Chef::ApiClient"].should == "success"
- result["Chef::Node"].should == "success"
- result["Chef::Role"].should == "success"
- end
-
- it "does not reindex Chef::OpenIDRegistration or Chef::WebUIUser objects" do
- # hi there. the reason we're specifying this behavior is because these objects
- # are not properly indexed in the first place and trying to reindex them
- # tickles a bug in our CamelCase to snake_case code. See CHEF-1009.
- @solr.should_receive(:delete_database).with("chunky_bacon")
- @solr.stub!(:reindex_all).with(Chef::ApiClient)
- @solr.stub!(:reindex_all).with(Chef::Node)
- @solr.stub!(:reindex_all).with(Chef::Role)
- @solr.should_not_receive(:reindex_all).with(Chef::OpenIDRegistration)
- @solr.should_not_receive(:reindex_all).with(Chef::WebUIUser)
- Chef::DataBag.stub!(:cdb_list).and_return([])
-
- @solr.rebuild_index
- end
-
- it "reindexes databags" do
- one_data_item = Chef::DataBagItem.new
- one_data_item.raw_data = {"maybe"=>"snakes actually are evil", "id" => "just_sayin"}
- two_data_item = Chef::DataBagItem.new
- two_data_item.raw_data = {"tone_depth"=>"rumble_fish", "id" => "eff_yes"}
- data_bag = Chef::DataBag.new
- data_bag.stub!(:list).and_return([one_data_item, two_data_item])
-
- @solr.should_receive(:delete_database).with("chunky_bacon")
- @solr.stub!(:reindex_all)
- Chef::DataBag.stub!(:cdb_list).and_return([data_bag])
-
- data_bag.should_receive(:add_to_index)
- one_data_item.should_receive(:add_to_index)
- two_data_item.should_receive(:add_to_index)
-
- @solr.rebuild_index["Chef::DataBag"].should == "success"
- end
- end
-end