summaryrefslogtreecommitdiff
path: root/chef
diff options
context:
space:
mode:
authorChristopher Brown <cb@opscode.com>2009-02-25 08:13:20 -0800
committerChristopher Brown <cb@opscode.com>2009-02-25 08:13:20 -0800
commitf79a7385964f6b60220ef1817120d331ae9d8d80 (patch)
tree62d702e134c1acaa9d0bc3b223705488ebaad29e /chef
parent6f5042c1947415db20edd4453f3c40252eca6cdc (diff)
parent409ffd22488aea6afc75ad18b32e64cc8fffcc78 (diff)
downloadchef-f79a7385964f6b60220ef1817120d331ae9d8d80.tar.gz
merged master 0.5.5
Diffstat (limited to 'chef')
-rw-r--r--chef/Rakefile2
-rwxr-xr-xchef/bin/chef-client7
-rw-r--r--chef/chef.gemspec2
-rw-r--r--chef/lib/chef.rb2
-rw-r--r--chef/lib/chef/config.rb2
-rw-r--r--chef/lib/chef/mixin/generate_url.rb2
-rw-r--r--chef/lib/chef/mixin/template.rb49
-rw-r--r--chef/lib/chef/provider/package.rb3
-rw-r--r--chef/lib/chef/provider/package/dpkg.rb110
-rw-r--r--chef/lib/chef/provider/remote_directory.rb4
-rw-r--r--chef/lib/chef/provider/remote_file.rb2
-rw-r--r--chef/lib/chef/resource/remote_directory.rb9
-rw-r--r--chef/lib/chef/rest.rb4
-rw-r--r--chef/spec/unit/mixin/template_spec.rb86
-rw-r--r--chef/spec/unit/provider/package/dpkg_spec.rb177
-rw-r--r--chef/spec/unit/provider/package_spec.rb9
-rw-r--r--chef/spec/unit/rest_spec.rb49
17 files changed, 481 insertions, 38 deletions
diff --git a/chef/Rakefile b/chef/Rakefile
index 9a52dec46a..faa66847a4 100644
--- a/chef/Rakefile
+++ b/chef/Rakefile
@@ -4,7 +4,7 @@ require 'rake/rdoctask'
require './tasks/rspec.rb'
GEM = "chef"
-CHEF_VERSION = "0.5.3"
+CHEF_VERSION = "0.5.5"
AUTHOR = "Adam Jacob"
EMAIL = "adam@opscode.com"
HOMEPAGE = "http://wiki.opscode.com/display/chef"
diff --git a/chef/bin/chef-client b/chef/bin/chef-client
index e217d11a5b..32a3c45fe0 100755
--- a/chef/bin/chef-client
+++ b/chef/bin/chef-client
@@ -57,6 +57,13 @@ opts = OptionParser.new do |opts|
end
opts.parse!(ARGV)
+trap("INT") { Chef.fatal!("SIGINT received, stopping", 2) }
+trap("HUP") {
+ Chef::Log.info("SIGHUP received, reloading configuration")
+ Chef::Config.from_file(config[:config_file])
+ Chef::Config.configure { |c| c.merge!(config) }
+}
+
unless File.exists?(config[:config_file]) and File.readable?(config[:config_file])
Chef.fatal!("I cannot find or read the config file: #{config[:config_file]}", 1)
end
diff --git a/chef/chef.gemspec b/chef/chef.gemspec
index 430123a498..5273922e20 100644
--- a/chef/chef.gemspec
+++ b/chef/chef.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |s|
s.name = %q{chef}
- s.version = "0.5.3"
+ s.version = "0.5.5"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Adam Jacob"]
diff --git a/chef/lib/chef.rb b/chef/lib/chef.rb
index 934fdc87aa..1123a0ea4a 100644
--- a/chef/lib/chef.rb
+++ b/chef/lib/chef.rb
@@ -27,7 +27,7 @@ require 'chef/config'
Dir[File.join(File.dirname(__FILE__), 'chef/mixin/**/*.rb')].sort.each { |lib| require lib }
class Chef
- VERSION = '0.5.3'
+ VERSION = '0.5.5'
class << self
def fatal!(msg, err = -1)
diff --git a/chef/lib/chef/config.rb b/chef/lib/chef/config.rb
index b416012044..325156b421 100644
--- a/chef/lib/chef/config.rb
+++ b/chef/lib/chef/config.rb
@@ -53,6 +53,8 @@ class Chef
:log_location => STDOUT,
:openid_providers => nil,
:ssl_verify_mode => :verify_none,
+ :ssl_client_cert => "",
+ :ssl_client_key => "",
:rest_timeout => 60,
:couchdb_url => "http://localhost:5984",
:registration_url => "http://localhost:4000",
diff --git a/chef/lib/chef/mixin/generate_url.rb b/chef/lib/chef/mixin/generate_url.rb
index abb28d6df0..9ebe22b832 100644
--- a/chef/lib/chef/mixin/generate_url.rb
+++ b/chef/lib/chef/mixin/generate_url.rb
@@ -24,7 +24,7 @@ class Chef
def generate_cookbook_url(url, cookbook, type, node, args=nil)
new_url = nil
- if url =~ /^http/
+ if url =~ /^(http|https):\/\//
new_url = url
else
new_url = "cookbooks/#{cookbook}/#{type}?"
diff --git a/chef/lib/chef/mixin/template.rb b/chef/lib/chef/mixin/template.rb
index 11329dbaa7..73a6ffbd95 100644
--- a/chef/lib/chef/mixin/template.rb
+++ b/chef/lib/chef/mixin/template.rb
@@ -26,14 +26,59 @@ class Chef
# Render a template with Erubis. Takes a template as a string, and a
# context hash.
def render_template(template, context)
- eruby = Erubis::Eruby.new(template)
- output = eruby.evaluate(context)
+ begin
+ eruby = Erubis::Eruby.new(template)
+ output = eruby.evaluate(context)
+ rescue Object => e
+ raise TemplateError.new(e, template, context)
+ end
final_tempfile = Tempfile.new("chef-rendered-template")
final_tempfile.print(output)
final_tempfile.close
final_tempfile
end
+ class TemplateError < RuntimeError
+ attr_reader :original_exception, :context
+ SOURCE_CONTEXT_WINDOW = 2 unless defined? SOURCE_CONTEXT_WINDOW
+
+ def initialize(original_exception, template, context)
+ @original_exception, @template, @context = original_exception, template, context
+ end
+
+ def message
+ @original_exception.message
+ end
+
+ def line_number
+ @line_number ||= $1.to_i if original_exception.backtrace.find {|line| line =~ /\(erubis\):(\d+)/ }
+ end
+
+ def source_location
+ "on line ##{line_number}"
+ end
+
+ def source_listing
+ @source_listing ||= begin
+ line_index = line_number - 1
+ beginning_line = line_index <= SOURCE_CONTEXT_WINDOW ? 0 : line_index - SOURCE_CONTEXT_WINDOW
+ source_size = SOURCE_CONTEXT_WINDOW * 2 + 1
+ lines = @template.split(/\n/)
+ contextual_lines = lines[beginning_line, source_size]
+ output = []
+ contextual_lines.each_with_index do |line, index|
+ line_number = (index+beginning_line+1).to_s.rjust(3)
+ output << "#{line_number}: #{line}"
+ end
+ output.join("\n")
+ end
+ end
+
+ def to_s
+ "\n\n#{self.class} (#{message}) #{source_location}:\n\n" +
+ "#{source_listing}\n\n #{original_exception.backtrace.join("\n ")}\n\n"
+ end
+ end
end
end
end
diff --git a/chef/lib/chef/provider/package.rb b/chef/lib/chef/provider/package.rb
index 5b323f2bdd..badc7aaacd 100644
--- a/chef/lib/chef/provider/package.rb
+++ b/chef/lib/chef/provider/package.rb
@@ -71,7 +71,8 @@ class Chef
def action_upgrade
if @current_resource.version != @candidate_version
- Chef::Log.info("Upgrading #{@new_resource} version from #{@current_resource.version} to #{@candidate_version}")
+ orig_version = @current_resource.version || "uninstalled"
+ Chef::Log.info("Upgrading #{@new_resource} version from #{orig_version} to #{@candidate_version}")
status = upgrade_package(@new_resource.package_name, @candidate_version)
if status
@new_resource.updated = true
diff --git a/chef/lib/chef/provider/package/dpkg.rb b/chef/lib/chef/provider/package/dpkg.rb
new file mode 100644
index 0000000000..0cad2d00e8
--- /dev/null
+++ b/chef/lib/chef/provider/package/dpkg.rb
@@ -0,0 +1,110 @@
+#
+# Author:: Bryan McLellan (btm@loftninjas.org)
+# Copyright:: Copyright (c) 2009 Bryan McLellan
+# 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/provider/package'
+require 'chef/mixin/command'
+require 'chef/resource/package'
+
+class Chef
+ class Provider
+ class Package
+ class Dpkg < Chef::Provider::Package::Apt
+
+ def load_current_resource
+ @current_resource = Chef::Resource::Package.new(@new_resource.name)
+ @current_resource.package_name(@new_resource.package_name)
+ @new_resource.version(nil)
+
+ # We only -need- source for action install
+ if @new_resource.source
+ unless ::File.exists?(@new_resource.source)
+ raise Chef::Exception::Package, "Package #{@new_resource.name} not found: #{@new_resource.source}"
+ end
+
+ # Get information from the package if supplied
+ Chef::Log.debug("Checking dpkg status for #{@new_resource.package_name}")
+ status = popen4("dpkg-deb -W #{@new_resource.source}") do |pid, stdin, stdout, stderr|
+ stdout.each do |line|
+ case line
+ when /([\w\d]+)\t([\w\d.-]+)/
+ @current_resource.package_name($1)
+ @new_resource.version($2)
+ end
+ end
+ end
+ else
+ # if the source was not set, and we're installing, fail
+ if @new_resource.action.include?(:install)
+ raise Chef::Exception::Package, "Source for package #{@new_resource.name} required for action install"
+ end
+ end
+
+ # Check to see if it is installed
+ package_installed = nil
+ Chef::Log.debug("Checking install state for #{@current_resource.package_name}")
+ status = popen4("dpkg -s #{@current_resource.package_name}") do |pid, stdin, stdout, stderr|
+ stdout.each do |line|
+ case line
+ when /^Status: install ok installed/
+ package_installed = true
+ when /^Version: (.+)$/
+ if package_installed
+ Chef::Log.debug("Current version is #{$1}")
+ @current_resource.version($1)
+ end
+ end
+ end
+ end
+
+ unless status.exitstatus == 0 || status.exitstatus == 1
+ raise Chef::Exception::Package, "dpkg failed - #{status.inspect}!"
+ end
+
+ @current_resource
+ end
+
+ def install_package(name, version)
+ run_command(
+ :command => "dpkg -i #{@new_resource.source}",
+ :environment => {
+ "DEBIAN_FRONTEND" => "noninteractive"
+ }
+ )
+ end
+
+ def remove_package(name, version)
+ run_command(
+ :command => "dpkg -r #{@new_resource.package_name}",
+ :environment => {
+ "DEBIAN_FRONTEND" => "noninteractive"
+ }
+ )
+ end
+
+ def purge_package(name, version)
+ run_command(
+ :command => "dpkg -P #{@new_resource.package_name}",
+ :environment => {
+ "DEBIAN_FRONTEND" => "noninteractive"
+ }
+ )
+ end
+ end
+ end
+ end
+end
diff --git a/chef/lib/chef/provider/remote_directory.rb b/chef/lib/chef/provider/remote_directory.rb
index fb490bbb1d..010e0b29cd 100644
--- a/chef/lib/chef/provider/remote_directory.rb
+++ b/chef/lib/chef/provider/remote_directory.rb
@@ -53,7 +53,7 @@ class Chef
full_dir = ::File.dirname(full_path)
unless ::File.directory?(full_dir)
new_dir = Chef::Resource::Directory.new(full_dir, nil, @node)
- new_dir.cookbook_name = @new_resource.cookbook_name
+ new_dir.cookbook_name = @new_resource.cookbook || @new_resource.cookbook_name
new_dir.mode(@new_resource.mode)
new_dir.group(@new_resource.group)
new_dir.owner(@new_resource.owner)
@@ -67,7 +67,7 @@ class Chef
end
remote_file = Chef::Resource::RemoteFile.new(full_path, nil, @node)
- remote_file.cookbook_name = @new_resource.cookbook_name
+ remote_file.cookbook_name = @new_resource.cookbook || @new_resource.cookbook_name
remote_file.source(::File.join(@new_resource.source, remote_file_source))
remote_file.mode(@new_resource.files_mode) if @new_resource.files_mode
remote_file.group(@new_resource.files_group) if @new_resource.files_group
diff --git a/chef/lib/chef/provider/remote_file.rb b/chef/lib/chef/provider/remote_file.rb
index 8ceed5f74d..8fd5eb0104 100644
--- a/chef/lib/chef/provider/remote_file.rb
+++ b/chef/lib/chef/provider/remote_file.rb
@@ -91,6 +91,7 @@ class Chef
uri = URI.parse(source)
if uri.absolute
r = Chef::REST.new(source)
+ Chef::Log.debug("Downloading from absolute URI: #{source}")
r.get_rest(source, true).open
end
rescue URI::InvalidURIError
@@ -101,6 +102,7 @@ class Chef
unless Chef::Config[:solo]
r = Chef::REST.new(Chef::Config[:remotefile_url])
url = generate_url(source, "files", :checksum => current_checksum)
+ Chef::Log.debug("Downloading from server: #{url}")
r.get_rest(url, true).open
end
end
diff --git a/chef/lib/chef/resource/remote_directory.rb b/chef/lib/chef/resource/remote_directory.rb
index 478cdc6528..1628af3a33 100644
--- a/chef/lib/chef/resource/remote_directory.rb
+++ b/chef/lib/chef/resource/remote_directory.rb
@@ -34,6 +34,7 @@ class Chef
@files_group = nil
@files_mode = 0644
@allowed_actions.push(:create, :delete)
+ @cookbook = nil
end
def source(args=nil)
@@ -76,6 +77,14 @@ class Chef
)
end
+ def cookbook(args=nil)
+ set_or_return(
+ :cookbook,
+ args,
+ :kind_of => String
+ )
+ end
+
end
end
end \ No newline at end of file
diff --git a/chef/lib/chef/rest.rb b/chef/lib/chef/rest.rb
index 3224262589..bac6788e52 100644
--- a/chef/lib/chef/rest.rb
+++ b/chef/lib/chef/rest.rb
@@ -123,6 +123,10 @@ class Chef
if Chef::Config[:ssl_verify_mode] == :verify_none
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
+ if File.exists?(Chef::Config[:ssl_client_cert])
+ http.cert = OpenSSL::X509::Certificate.new(File.read(Chef::Config[:ssl_client_cert]))
+ http.key = OpenSSL::PKey::RSA.new(File.read(Chef::Config[:ssl_client_key]))
+ end
end
http.read_timeout = Chef::Config[:rest_timeout]
headers = Hash.new
diff --git a/chef/spec/unit/mixin/template_spec.rb b/chef/spec/unit/mixin/template_spec.rb
index 443ca28e1d..86e0b59232 100644
--- a/chef/spec/unit/mixin/template_spec.rb
+++ b/chef/spec/unit/mixin/template_spec.rb
@@ -19,42 +19,72 @@
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
class TinyTemplateClass; include Chef::Mixin::Template; end
-
+require 'cgi'
describe Chef::Mixin::Template, "render_template" do
- before(:each) do
- @template = "abcnews"
- @context = { :fine => "dear" }
- @eruby = mock(:erubis, { :evaluate => "elvis costello" })
- Erubis::Eruby.stub!(:new).and_return(@eruby)
- @tempfile = mock(:tempfile, { :print => true, :close => true })
- Tempfile.stub!(:new).and_return(@tempfile)
- @tiny_template = TinyTemplateClass.new
- end
-
- it "should create a new Erubis object from the template" do
- Erubis::Eruby.should_receive(:new).with("abcnews").and_return(@eruby)
- @tiny_template.render_template(@template, @context)
+ before :each do
+ @template = TinyTemplateClass.new
end
-
- it "should evaluate the template with the provided context" do
- @eruby.should_receive(:evaluate).with(@context).and_return(true)
- @tiny_template.render_template(@template, @context)
+
+ it "should render the template evaluated in the given context" do
+ @template.render_template("<%= @foo %>", { :foo => "bar" }).open.read.should == "bar"
end
- it "should create a tempfile for the resulting file" do
- Tempfile.should_receive(:new).and_return(@tempfile)
- @tiny_template.render_template(@template, @context)
+ it "should return a file" do
+ @template.render_template("abcdef", {}).should be_kind_of(File)
end
- it "should print the contents of the resulting template to the tempfile" do
- @tempfile.should_receive(:print).with("elvis costello").and_return(true)
- @tiny_template.render_template(@template, @context)
- end
+ describe "when an exception is raised in the template" do
+ def do_raise
+ @context = {:chef => "cool"}
+ @template.render_template("foo\nbar\nbaz\n<%= this_is_not_defined %>\nquin\nqunx\ndunno", @context)
+ end
- it "should close the tempfile" do
- @tempfile.should_receive(:close).and_return(true)
- @tiny_template.render_template(@template, @context)
+ it "should catch and re-raise the exception as a TemplateError" do
+ lambda { do_raise }.should raise_error(Chef::Mixin::Template::TemplateError)
+ end
+
+ describe "the raised TemplateError" do
+ before :each do
+ begin
+ do_raise
+ rescue Chef::Mixin::Template::TemplateError => e
+ @exception = e
+ end
+ end
+
+ it "should have the original exception" do
+ @exception.original_exception.should be
+ @exception.original_exception.message.should =~ /undefined local variable or method `this_is_not_defined'/
+ end
+
+ it "should determine the line number of the exception" do
+ @exception.line_number.should == 4
+ end
+
+ it "should provide a source listing of the template around the exception" do
+ @exception.source_listing.should == " 2: bar\n 3: baz\n 4: <%= this_is_not_defined %>\n 5: quin\n 6: qunx"
+ end
+
+ it "should provide the evaluation context of the template" do
+ @exception.context.should == @context
+ end
+
+ it "should defer the message to the original exception" do
+ @exception.message.should =~ /undefined local variable or method `this_is_not_defined'/
+ end
+
+ it "should provide a nice source location" do
+ @exception.source_location.should == "on line #4"
+ end
+
+ it "should create a pretty output for the terminal" do
+ @exception.to_s.should =~ /Chef::Mixin::Template::TemplateError/
+ @exception.to_s.should =~ /undefined local variable or method `this_is_not_defined'/
+ @exception.to_s.should include(" 2: bar\n 3: baz\n 4: <%= this_is_not_defined %>\n 5: quin\n 6: qunx")
+ @exception.to_s.should include(@exception.original_exception.backtrace.first)
+ end
+ end
end
end
diff --git a/chef/spec/unit/provider/package/dpkg_spec.rb b/chef/spec/unit/provider/package/dpkg_spec.rb
new file mode 100644
index 0000000000..390609aca9
--- /dev/null
+++ b/chef/spec/unit/provider/package/dpkg_spec.rb
@@ -0,0 +1,177 @@
+#
+# Author:: Bryan McLellan (btm@loftninjas.org)
+# Copyright:: Copyright (c) 2009 Bryan McLellan
+# 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 File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "spec_helper"))
+
+describe Chef::Provider::Package::Dpkg, "load_current_resource" do
+ before(:each) do
+ @node = mock("Chef::Node", :null_object => true)
+ @new_resource = mock("Chef::Resource::Package",
+ :null_object => true,
+ :name => "wget",
+ :version => nil,
+ :package_name => "wget",
+ :updated => nil,
+ :source => "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
+ )
+ @current_resource = mock("Chef::Resource::Package",
+ :null_object => true,
+ :name => "wget",
+ :version => nil,
+ :package_name => nil,
+ :updated => nil
+ )
+
+ @provider = Chef::Provider::Package::Dpkg.new(@node, @new_resource)
+ Chef::Resource::Package.stub!(:new).and_return(@current_resource)
+
+ @stdin = mock("STDIN", :null_object => true)
+ @stdout = mock("STDOUT", :null_object => true)
+ @status = mock("Status", :exitstatus => 0)
+ @stderr = mock("STDERR", :null_object => true)
+ @pid = mock("PID", :null_object => true)
+ @provider.stub!(:popen4).and_return(@status)
+
+ ::File.stub!(:exists?).and_return(true)
+ end
+
+ it "should create a current resource with the name of the new_resource" do
+ Chef::Resource::Package.should_receive(:new).and_return(@current_resource)
+ @provider.load_current_resource
+ end
+
+ it "should set the current resources package name to the new resources package name" do
+ @current_resource.should_receive(:package_name).with(@new_resource.package_name)
+ @provider.load_current_resource
+ end
+
+ it "should raise an exception if a source is supplied but not found" do
+ ::File.stub!(:exists?).and_return(false)
+ lambda { @provider.load_current_resource }.should raise_error(Chef::Exception::Package)
+ end
+
+ it "should get the source package version from dpkg-deb if provided" do
+ @stdout.stub!(:each).and_yield("wget\t1.11.4-1ubuntu1")
+ @provider.stub!(:popen4).with("dpkg-deb -W #{@new_resource.source}").and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @current_resource.should_receive(:package_name).with("wget")
+ @new_resource.should_receive(:version).with("1.11.4-1ubuntu1")
+ @provider.load_current_resource
+ end
+
+ it "should raise an exception if the source is not set but we are installing" do
+ @new_resource = mock("Chef::Resource::Package",
+ :null_object => true,
+ :name => "wget",
+ :version => nil,
+ :package_name => "wget",
+ :updated => nil,
+ :source => nil
+ )
+ @provider = Chef::Provider::Package::Dpkg.new(@node, @new_resource)
+ lambda { @provider.load_current_resource }.should raise_error(Chef::Exception::Package)
+
+ end
+
+ it "should return the current version installed if found by dpkg" do
+ @stdout.stub!(:each).and_yield("Package: wget").
+ and_yield("Status: install ok installed").
+ and_yield("Priority: important").
+ and_yield("Section: web").
+ and_yield("Installed-Size: 1944").
+ and_yield("Maintainer: Ubuntu Core developers <ubuntu-devel-discuss@lists.ubuntu.com>").
+ and_yield("Architecture: amd64").
+ and_yield("Version: 1.11.4-1ubuntu1").
+ and_yield("Config-Version: 1.11.4-1ubuntu1").
+ and_yield("Depends: libc6 (>= 2.8~20080505), libssl0.9.8 (>= 0.9.8f-5)").
+ and_yield("Conflicts: wget-ssl")
+ @provider.stub!(:popen4).with("dpkg -s #{@current_resource.package_name}").and_yield(@pid, @stdin, @stdout, @stderr).and_return(@status)
+ @current_resource.should_receive(:version).with("1.11.4-1ubuntu1")
+ @provider.load_current_resource
+ end
+
+ it "should raise an exception if dpkg fails to run" do
+ @status = mock("Status", :exitstatus => -1)
+ @provider.stub!(:popen4).and_return(@status)
+ lambda { @provider.load_current_resource }.should raise_error(Chef::Exception::Package)
+ end
+end
+
+describe Chef::Provider::Package::Dpkg, "install and upgrade" do
+ before(:each) do
+ @node = mock("Chef::Node", :null_object => true)
+ @new_resource = mock("Chef::Resource::Package",
+ :null_object => true,
+ :name => "wget",
+ :version => nil,
+ :package_name => "wget",
+ :updated => nil,
+ :source => "/tmp/wget_1.11.4-1ubuntu1_amd64.deb"
+ )
+ @provider = Chef::Provider::Package::Dpkg.new(@node, @new_resource)
+ end
+
+ it "should run dpkg -i with the package source" do
+ @provider.should_receive(:run_command).with({
+ :command => "dpkg -i /tmp/wget_1.11.4-1ubuntu1_amd64.deb",
+ :environment => {
+ "DEBIAN_FRONTEND" => "noninteractive"
+ }
+ })
+ @provider.install_package("wget", "1.11.4-1ubuntu1")
+ end
+
+ it "should upgrade by running install_package" do
+ @provider.should_receive(:install_package).with("wget", "1.11.4-1ubuntu1")
+ @provider.upgrade_package("wget", "1.11.4-1ubuntu1")
+ end
+end
+
+describe Chef::Provider::Package::Dpkg, "remove and purge" do
+ before(:each) do
+ @node = mock("Chef::Node", :null_object => true)
+ @new_resource = mock("Chef::Resource::Package",
+ :null_object => true,
+ :name => "wget",
+ :version => nil,
+ :package_name => "wget",
+ :updated => nil
+ )
+ @provider = Chef::Provider::Package::Dpkg.new(@node, @new_resource)
+ end
+
+ it "should run dpkg -r to remove the package" do
+ @provider.should_receive(:run_command).with({
+ :command => "dpkg -r wget",
+ :environment => {
+ "DEBIAN_FRONTEND" => "noninteractive"
+ }
+ })
+ @provider.remove_package("wget", "1.11.4-1ubuntu1")
+ end
+
+ it "should run dpkg -P to purge the package" do
+ @provider.should_receive(:run_command).with({
+ :command => "dpkg -P wget",
+ :environment => {
+ "DEBIAN_FRONTEND" => "noninteractive"
+ }
+ })
+ @provider.purge_package("wget", "1.11.4-1ubuntu1")
+ end
+end
+
diff --git a/chef/spec/unit/provider/package_spec.rb b/chef/spec/unit/provider/package_spec.rb
index fbfc8b5bf2..925360e1dd 100644
--- a/chef/spec/unit/provider/package_spec.rb
+++ b/chef/spec/unit/provider/package_spec.rb
@@ -126,7 +126,8 @@ describe Chef::Provider::Package, "action_upgrade" do
:null_object => true,
:name => "emacs",
:version => nil,
- :package_name => "emacs"
+ :package_name => "emacs",
+ :to_s => 'package[emacs]'
)
@current_resource = mock("Chef::Resource::Package",
:null_object => true,
@@ -158,6 +159,12 @@ describe Chef::Provider::Package, "action_upgrade" do
@provider.should_not_receive(:upgrade_package)
@provider.action_upgrade
end
+
+ it "should print the word 'uninstalled' if there was no original version" do
+ @current_resource.stub!(:version).and_return(nil)
+ Chef::Log.should_receive(:info).with("Upgrading #{@new_resource} version from uninstalled to 1.0")
+ @provider.action_upgrade
+ end
end
# Oh ruby, you are so nice.
diff --git a/chef/spec/unit/rest_spec.rb b/chef/spec/unit/rest_spec.rb
index ba892944fc..525d17e148 100644
--- a/chef/spec/unit/rest_spec.rb
+++ b/chef/spec/unit/rest_spec.rb
@@ -140,6 +140,55 @@ describe Chef::REST, "run_request method" do
do_run_request
end
+ describe "with a client SSL cert" do
+ before(:each) do
+ Chef::Config[:ssl_client_cert] = "/etc/chef/client-cert.pem"
+ Chef::Config[:ssl_client_key] = "/etc/chef/client-cert.key"
+ File.stub!(:exists?).with("/etc/chef/client-cert.pem").and_return(true)
+ File.stub!(:exists?).with("/etc/chef/client-cert.key").and_return(true)
+ File.stub!(:read).with("/etc/chef/client-cert.pem").and_return("monkey magic client")
+ File.stub!(:read).with("/etc/chef/client-cert.key").and_return("monkey magic key")
+ OpenSSL::X509::Certificate.stub!(:new).and_return("monkey magic client data")
+ OpenSSL::PKey::RSA.stub!(:new).and_return("monkey magic key data")
+ end
+
+ it "should check that the client cert file exists" do
+ File.should_receive(:exists?).with("/etc/chef/client-cert.pem").and_return(true)
+ do_run_request
+ end
+
+ it "should read the cert file" do
+ File.should_receive(:read).with("/etc/chef/client-cert.pem").and_return("monkey magic client")
+ do_run_request
+ end
+
+ it "should read the cert into OpenSSL" do
+ OpenSSL::X509::Certificate.should_receive(:new).and_return("monkey magic client data")
+ do_run_request
+ end
+
+ it "should set the cert" do
+ @http_mock.should_receive(:cert=).and_return(true)
+ do_run_request
+ end
+
+ it "should read the key file" do
+ File.should_receive(:read).with("/etc/chef/client-cert.key").and_return("monkey magic key")
+ do_run_request
+ end
+
+ it "should read the key into OpenSSL" do
+ OpenSSL::PKey::RSA.should_receive(:new).and_return("monkey magic key data")
+ do_run_request
+ end
+
+ it "should set the key" do
+ @http_mock.should_receive(:key=).and_return(true)
+ do_run_request
+ end
+
+ end
+
it "should set a read timeout based on the rest_timeout config option" do
Chef::Config[:rest_timeout] = 10
@http_mock.should_receive(:read_timeout=).with(10).and_return(true)