summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorSerdar Sutay <serdar@opscode.com>2014-08-22 11:34:34 -0700
committerSerdar Sutay <serdar@opscode.com>2014-08-26 15:42:27 -0700
commitc79ceca006bb18b59489ac077879710711bdfd99 (patch)
treeec6e99faa9acea4993af70dee4813aa74a9230f2 /spec
parentb03b2aa547e6c9766d9ed39e29351540209c7b06 (diff)
downloadchef-c79ceca006bb18b59489ac077879710711bdfd99.tar.gz
Specs for bootstrap cleanup.
Diffstat (limited to 'spec')
-rw-r--r--spec/unit/knife/bootstrap_spec.rb445
1 files changed, 277 insertions, 168 deletions
diff --git a/spec/unit/knife/bootstrap_spec.rb b/spec/unit/knife/bootstrap_spec.rb
index 434878ed93..5aae5bdddf 100644
--- a/spec/unit/knife/bootstrap_spec.rb
+++ b/spec/unit/knife/bootstrap_spec.rb
@@ -22,110 +22,194 @@ Chef::Knife::Bootstrap.load_deps
require 'net/ssh'
describe Chef::Knife::Bootstrap do
- before(:each) do
+ let(:knife) do
Chef::Log.logger = Logger.new(StringIO.new)
- @knife = Chef::Knife::Bootstrap.new
- # Merge default settings in.
- @knife.merge_configs
- @knife.config[:template_file] = File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb"))
- @stdout = StringIO.new
- @knife.ui.stub(:stdout).and_return(@stdout)
- @stderr = StringIO.new
- @knife.ui.stub(:stderr).and_return(@stderr)
- end
+ Chef::Config[:knife][:bootstrap_template] = bootstrap_template unless bootstrap_template.nil?
- it "should return a name of default bootstrap template" do
- @knife.find_template.should be_a_kind_of(String)
- end
+ k = Chef::Knife::Bootstrap.new
+ k.merge_configs
- it "should error if template can not be found" do
- Chef::Config[:knife][:bootstrap_template] = 'penultimate'
- lambda { @knife.find_template }.should raise_error
+ k.ui.stub(:stderr).and_return(stderr)
+ k
end
- it "should look for templates early in the run" do
- File.stub(:exists?).and_return(true)
- @knife.name_args = ['shatner']
- @knife.stub(:read_template).and_return("")
- @knife.stub(:knife_ssh).and_return(true)
- @knife_ssh = @knife.knife_ssh
- @knife.should_receive(:find_template).ordered
- @knife.should_receive(:knife_ssh).ordered
- @knife_ssh.should_receive(:run) # rspec appears to keep order per object
- @knife.run
- end
+ let(:stderr) { StringIO.new }
- it "should load the specified template" do
- @knife.config[:template] = 'fedora13-gems'
- lambda { @knife.find_template }.should_not raise_error
- end
+ let(:bootstrap_template) { nil }
- it "should load the specified template from a Ruby gem" do
- @knife.config[:template_file] = false
- Gem.stub(:find_files).and_return(["/Users/schisamo/.rvm/gems/ruby-1.9.2-p180@chef-0.10/gems/knife-windows-0.5.4/lib/chef/knife/bootstrap/fake-bootstrap-template.erb"])
- File.stub(:exists?).and_return(true)
- IO.stub(:read).and_return('random content')
- @knife.config[:template] = 'fake-bootstrap-template'
- lambda { @knife.find_template }.should_not raise_error
+ it "should use chef-full as default template" do
+ knife.find_template.should be_a_kind_of(String)
+ File.basename(knife.find_template).should eq("chef-full.erb")
end
- it "should return an empty run_list" do
- @knife.instance_variable_set("@template_file", @knife.config[:template_file])
- template_string = @knife.read_template
- @knife.render_template(template_string).should == '{"run_list":[]}'
- end
+ context "when finding templates" do
+ context "when :bootstrap_template config is set to a file" do
+ context "that doesn't exist" do
+ let(:bootstrap_template) { "/opt/blah/not/exists/template.erb" }
- it "should have role[base] in the run_list" do
- @knife.instance_variable_set("@template_file", @knife.config[:template_file])
- template_string = @knife.read_template
- @knife.parse_options(["-r","role[base]"])
- @knife.render_template(template_string).should == '{"run_list":["role[base]"]}'
- end
+ it "raises an error" do
+ lambda { knife.find_template }.should raise_error
+ end
+ end
- it "should have role[base] and recipe[cupcakes] in the run_list" do
- @knife.instance_variable_set("@template_file", @knife.config[:template_file])
- template_string = @knife.read_template
- @knife.parse_options(["-r", "role[base],recipe[cupcakes]"])
- @knife.render_template(template_string).should == '{"run_list":["role[base]","recipe[cupcakes]"]}'
- end
+ context "that exists" do
+ let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")) }
+
+ it "loads the given file as the template" do
+ Chef::Log.should_receive(:debug)
+ knife.find_template.should eq(File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")))
+ end
+ end
+ end
+
+ context "when :bootstrap_template config is set to a template name" do
+ let(:bootstrap_template) { "example" }
- it "should have foo => {bar => baz} in the first_boot" do
- @knife.instance_variable_set("@template_file", @knife.config[:template_file])
- template_string = @knife.read_template
- @knife.parse_options(["-j", '{"foo":{"bar":"baz"}}'])
- expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}')
- actual_hash = FFI_Yajl::Parser.new.parse(@knife.render_template(template_string))
- actual_hash.should == expected_hash
+ let(:builtin_template_path) { File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/chef/knife/bootstrap', "example.erb"))}
+
+ let(:chef_config_dir_template_path) { "/knife/chef/config/bootstrap/example.erb" }
+
+ let(:env_home_template_path) { "/env/home/.chef/bootstrap/example.erb" }
+
+ let(:gem_files_template_path) { "/Users/schisamo/.rvm/gems/ruby-1.9.2-p180@chef-0.10/gems/knife-windows-0.5.4/lib/chef/knife/bootstrap/fake-bootstrap-template.erb" }
+
+ def configure_chef_config_dir
+ Chef::Knife.stub(:chef_config_dir).and_return("/knife/chef/config")
+ end
+
+ def configure_env_home
+ ENV['HOME'] = "/env/home"
+ end
+
+ def configure_gem_files
+ Gem.stub(:find_files).and_return([ gem_files_template_path ])
+ end
+
+ before(:each) do
+ @original_home = ENV['HOME']
+ ENV['HOME'] = nil
+ File.should_receive(:exists?).with(bootstrap_template).and_return(false)
+ end
+
+ after(:each) do
+ ENV['HOME'] = @original_home
+ end
+
+ context "when file is available everywhere" do
+ before do
+ configure_chef_config_dir
+ configure_env_home
+ configure_gem_files
+
+ File.should_receive(:exists?).with(builtin_template_path).and_return(true)
+ end
+
+ it "should load the template from built-in templates" do
+ knife.find_template.should eq(builtin_template_path)
+ end
+ end
+
+ context "when file is available in chef_config_dir" do
+ before do
+ configure_chef_config_dir
+ configure_env_home
+ configure_gem_files
+
+ File.should_receive(:exists?).with(builtin_template_path).and_return(false)
+ File.should_receive(:exists?).with(chef_config_dir_template_path).and_return(true)
+
+ it "should load the template from chef_config_dir" do
+ knife.find_template.should eq(chef_config_dir_template_path)
+ end
+ end
+ end
+
+ context "when file is available in ENV['HOME']" do
+ before do
+ configure_chef_config_dir
+ configure_env_home
+ configure_gem_files
+
+ File.should_receive(:exists?).with(builtin_template_path).and_return(false)
+ File.should_receive(:exists?).with(chef_config_dir_template_path).and_return(false)
+ File.should_receive(:exists?).with(env_home_template_path).and_return(true)
+ end
+
+ it "should load the template from chef_config_dir" do
+ knife.find_template.should eq(env_home_template_path)
+ end
+ end
+
+ context "when file is available in Gem files" do
+ before do
+ configure_chef_config_dir
+ configure_gem_files
+
+ File.should_receive(:exists?).with(builtin_template_path).and_return(false)
+ File.should_receive(:exists?).with(chef_config_dir_template_path).and_return(false)
+ File.should_receive(:exists?).with(gem_files_template_path).and_return(true)
+ end
+
+ it "should load the template from Gem files" do
+ knife.find_template.should eq(gem_files_template_path)
+ end
+ end
+ end
end
- it "should create a hint file when told to" do
- @knife.config[:template_file] = File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test-hints.erb"))
- @knife.instance_variable_set("@template_file", @knife.config[:template_file])
- template_string = @knife.read_template
- @knife.parse_options(["--hint", "openstack"])
- @knife.render_template(template_string).should match /\/etc\/chef\/ohai\/hints\/openstack.json/
+ ["-d", "--distro", "-t", "--template", "--template-file"].each do |t|
+ context "when #{t} option is given in the command line" do
+ it "sets the knife :bootstrap_template config" do
+ knife.parse_options([t,"blahblah"])
+ Chef::Config[:knife][:bootstrap_template].should eq("blahblah")
+ end
+ end
end
- it "should populate a hint file with JSON when given a file to read" do
- @knife.stub(:find_template).and_return(true)
- @knife.config[:template_file] = File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test-hints.erb"))
- ::File.stub(:read).and_return('{ "foo" : "bar" }')
- @knife.instance_variable_set("@template_file", @knife.config[:template_file])
- template_string = @knife.read_template
- @knife.stub(:read_template).and_return('{ "foo" : "bar" }')
- @knife.parse_options(["--hint", "openstack=hints/openstack.json"])
- @knife.render_template(template_string).should match /\{\"foo\":\"bar\"\}/
+ context "with run_list template" do
+ let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")) }
+
+ it "should return an empty run_list" do
+ knife.render_template.should == '{"run_list":[]}'
+ end
+
+ it "should have role[base] in the run_list" do
+ knife.parse_options(["-r","role[base]"])
+ knife.render_template.should == '{"run_list":["role[base]"]}'
+ end
+
+ it "should have role[base] and recipe[cupcakes] in the run_list" do
+ knife.parse_options(["-r", "role[base],recipe[cupcakes]"])
+ knife.render_template.should == '{"run_list":["role[base]","recipe[cupcakes]"]}'
+ end
+
+ it "should have foo => {bar => baz} in the first_boot" do
+ knife.parse_options(["-j", '{"foo":{"bar":"baz"}}'])
+ expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}')
+ actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template)
+ actual_hash.should == expected_hash
+ end
end
- it "should take the node name from ARGV" do
- @knife.name_args = ['barf']
- @knife.name_args.first.should == "barf"
+ context "with hints template" do
+ let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test-hints.erb")) }
+
+ it "should create a hint file when told to" do
+ knife.parse_options(["--hint", "openstack"])
+ knife.render_template.should match /\/etc\/chef\/ohai\/hints\/openstack.json/
+ end
+
+ it "should populate a hint file with JSON when given a file to read" do
+ ::File.stub(:read).and_return('{ "foo" : "bar" }')
+ knife.parse_options(["--hint", "openstack=hints/openstack.json"])
+ knife.render_template.should match /\{\"foo\":\"bar\"\}/
+ end
end
describe "specifying no_proxy with various entries" do
subject(:knife) do
k = described_class.new
- k.instance_variable_set("@template_file", template_file)
+ Chef::Config[:knife][:bootstrap_template] = template_file
k.parse_options(options)
k.merge_configs
k
@@ -138,8 +222,7 @@ describe Chef::Knife::Bootstrap do
let(:options){ ["--bootstrap-no-proxy", setting, "-s", "foo"] }
let(:template_file) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "no_proxy.erb")) }
let(:rendered_template) do
- template_string = knife.read_template
- knife.render_template(template_string)
+ knife.render_template
end
context "via --bootstrap-no-proxy" do
@@ -160,16 +243,13 @@ describe Chef::Knife::Bootstrap do
end
describe "specifying the encrypted data bag secret key" do
- subject(:knife) { described_class.new }
let(:secret) { "supersekret" }
let(:secret_file) { File.join(CHEF_SPEC_DATA, 'bootstrap', 'encrypted_data_bag_secret') }
let(:options) { [] }
- let(:template_file) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "secret.erb")) }
+ let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "secret.erb")) }
let(:rendered_template) do
- knife.instance_variable_set("@template_file", template_file)
knife.parse_options(options)
- template_string = knife.read_template
- knife.render_template(template_string)
+ knife.render_template
end
context "via --secret" do
@@ -197,175 +277,204 @@ describe Chef::Knife::Bootstrap do
end
end
+ context "secret via config" do
+ before do
+ Chef::Config[:knife][:secret] = secret
+ end
+
+ it "creates a secret file" do
+ rendered_template.should match(%r{#{secret}})
+ end
+
+ it "renders the client.rb with an encrypted_data_bag_secret entry" do
+ rendered_template.should match(%r{encrypted_data_bag_secret\s*"/etc/chef/encrypted_data_bag_secret"})
+ end
+ end
+
+ context "secret-file via config" do
+ let(:secret) { IO.read(secret_file) }
+
+ before do
+ Chef::Config[:knife][:secret_file] = secret_file
+ end
+
+ it "creates a secret file" do
+ rendered_template.should match(%r{#{secret}})
+ end
+
+ it "renders the client.rb with an encrypted_data_bag_secret entry" do
+ rendered_template.should match(%r{encrypted_data_bag_secret\s*"/etc/chef/encrypted_data_bag_secret"})
+ end
+ end
end
describe "when configuring the underlying knife ssh command" do
context "from the command line" do
- before do
- @knife.name_args = ["foo.example.com"]
- @knife.config[:ssh_user] = "rooty"
- @knife.config[:ssh_port] = "4001"
- @knife.config[:ssh_password] = "open_sesame"
+ let(:knife_ssh) do
+ knife.name_args = ["foo.example.com"]
+ knife.config[:ssh_user] = "rooty"
+ knife.config[:ssh_port] = "4001"
+ knife.config[:ssh_password] = "open_sesame"
Chef::Config[:knife][:ssh_user] = nil
Chef::Config[:knife][:ssh_port] = nil
- @knife.config[:forward_agent] = true
- @knife.config[:identity_file] = "~/.ssh/me.rsa"
- @knife.stub(:read_template).and_return("")
- @knife_ssh = @knife.knife_ssh
+ knife.config[:forward_agent] = true
+ knife.config[:identity_file] = "~/.ssh/me.rsa"
+ knife.stub(:render_template).and_return("")
+ knife.knife_ssh
end
it "configures the hostname" do
- @knife_ssh.name_args.first.should == "foo.example.com"
+ knife_ssh.name_args.first.should == "foo.example.com"
end
it "configures the ssh user" do
- @knife_ssh.config[:ssh_user].should == 'rooty'
+ knife_ssh.config[:ssh_user].should == 'rooty'
end
it "configures the ssh password" do
- @knife_ssh.config[:ssh_password].should == 'open_sesame'
+ knife_ssh.config[:ssh_password].should == 'open_sesame'
end
it "configures the ssh port" do
- @knife_ssh.config[:ssh_port].should == '4001'
+ knife_ssh.config[:ssh_port].should == '4001'
end
it "configures the ssh agent forwarding" do
- @knife_ssh.config[:forward_agent].should == true
+ knife_ssh.config[:forward_agent].should == true
end
it "configures the ssh identity file" do
- @knife_ssh.config[:identity_file].should == '~/.ssh/me.rsa'
+ knife_ssh.config[:identity_file].should == '~/.ssh/me.rsa'
end
end
+
context "validating use_sudo_password" do
before do
- @knife.config[:ssh_password] = "password"
- @knife.stub(:read_template).and_return("This is the template contents.")
+ knife.config[:ssh_password] = "password"
+ knife.stub(:render_template).and_return("")
end
it "use_sudo_password contains description and long params for help" do
- @knife.options.should have_key(:use_sudo_password) \
- and @knife.options[:use_sudo_password][:description].to_s.should_not == ''\
- and @knife.options[:use_sudo_password][:long].to_s.should_not == ''
+ knife.options.should have_key(:use_sudo_password) \
+ and knife.options[:use_sudo_password][:description].to_s.should_not == ''\
+ and knife.options[:use_sudo_password][:long].to_s.should_not == ''
end
it "uses the password from --ssh-password for sudo when --use-sudo-password is set" do
- @knife.config[:use_sudo] = true
- @knife.config[:use_sudo_password] = true
- @knife.ssh_command.should include("echo \'#{@knife.config[:ssh_password]}\' | sudo -S")
+ knife.config[:use_sudo] = true
+ knife.config[:use_sudo_password] = true
+ knife.ssh_command.should include("echo \'#{knife.config[:ssh_password]}\' | sudo -S")
end
it "should not honor --use-sudo-password when --use-sudo is not set" do
- @knife.config[:use_sudo] = false
- @knife.config[:use_sudo_password] = true
- @knife.ssh_command.should_not include("echo #{@knife.config[:ssh_password]} | sudo -S")
+ knife.config[:use_sudo] = false
+ knife.config[:use_sudo_password] = true
+ knife.ssh_command.should_not include("echo #{knife.config[:ssh_password]} | sudo -S")
end
end
+
context "from the knife config file" do
- before do
- @knife.name_args = ["config.example.com"]
- @knife.config[:ssh_user] = nil
- @knife.config[:ssh_port] = nil
- @knife.config[:ssh_gateway] = nil
- @knife.config[:forward_agent] = nil
- @knife.config[:identity_file] = nil
- @knife.config[:host_key_verify] = nil
+ let(:knife_ssh) do
+ knife.name_args = ["config.example.com"]
+ knife.config[:ssh_user] = nil
+ knife.config[:ssh_port] = nil
+ knife.config[:ssh_gateway] = nil
+ knife.config[:forward_agent] = nil
+ knife.config[:identity_file] = nil
+ knife.config[:host_key_verify] = nil
Chef::Config[:knife][:ssh_user] = "curiosity"
Chef::Config[:knife][:ssh_port] = "2430"
Chef::Config[:knife][:forward_agent] = true
Chef::Config[:knife][:identity_file] = "~/.ssh/you.rsa"
Chef::Config[:knife][:ssh_gateway] = "towel.blinkenlights.nl"
Chef::Config[:knife][:host_key_verify] = true
- @knife.stub(:read_template).and_return("")
- @knife_ssh = @knife.knife_ssh
+ knife.stub(:render_template).and_return("")
+ knife.knife_ssh
end
it "configures the ssh user" do
- @knife_ssh.config[:ssh_user].should == 'curiosity'
+ knife_ssh.config[:ssh_user].should == 'curiosity'
end
it "configures the ssh port" do
- @knife_ssh.config[:ssh_port].should == '2430'
+ knife_ssh.config[:ssh_port].should == '2430'
end
it "configures the ssh agent forwarding" do
- @knife_ssh.config[:forward_agent].should == true
+ knife_ssh.config[:forward_agent].should == true
end
it "configures the ssh identity file" do
- @knife_ssh.config[:identity_file].should == '~/.ssh/you.rsa'
+ knife_ssh.config[:identity_file].should == '~/.ssh/you.rsa'
end
it "configures the ssh gateway" do
- @knife_ssh.config[:ssh_gateway].should == 'towel.blinkenlights.nl'
+ knife_ssh.config[:ssh_gateway].should == 'towel.blinkenlights.nl'
end
it "configures the host key verify mode" do
- @knife_ssh.config[:host_key_verify].should == true
+ knife_ssh.config[:host_key_verify].should == true
end
end
describe "when falling back to password auth when host key auth fails" do
- before do
- @knife.name_args = ["foo.example.com"]
- @knife.config[:ssh_user] = "rooty"
- @knife.config[:identity_file] = "~/.ssh/me.rsa"
- @knife.stub(:read_template).and_return("")
- @knife_ssh = @knife.knife_ssh
+ let(:knife_ssh_with_password_auth) do
+ knife.name_args = ["foo.example.com"]
+ knife.config[:ssh_user] = "rooty"
+ knife.config[:identity_file] = "~/.ssh/me.rsa"
+ knife.stub(:render_template).and_return("")
+ k = knife.knife_ssh
+ k.stub(:get_password).and_return('typed_in_password')
+ knife.stub(:knife_ssh).and_return(k)
+ knife.knife_ssh_with_password_auth
end
it "prompts the user for a password " do
- @knife.stub(:knife_ssh).and_return(@knife_ssh)
- @knife_ssh.stub(:get_password).and_return('typed_in_password')
- alternate_knife_ssh = @knife.knife_ssh_with_password_auth
- alternate_knife_ssh.config[:ssh_password].should == 'typed_in_password'
+ knife_ssh_with_password_auth.config[:ssh_password].should == 'typed_in_password'
end
it "configures knife not to use the identity file that didn't work previously" do
- @knife.stub(:knife_ssh).and_return(@knife_ssh)
- @knife_ssh.stub(:get_password).and_return('typed_in_password')
- alternate_knife_ssh = @knife.knife_ssh_with_password_auth
- alternate_knife_ssh.config[:identity_file].should be_nil
+ knife_ssh_with_password_auth.config[:identity_file].should be_nil
end
end
end
- describe "when running the bootstrap" do
- before do
- @knife.name_args = ["foo.example.com"]
- @knife.config[:ssh_user] = "rooty"
- @knife.config[:identity_file] = "~/.ssh/me.rsa"
- @knife.stub(:read_template).and_return("")
- @knife_ssh = @knife.knife_ssh
- @knife.stub(:knife_ssh).and_return(@knife_ssh)
- end
+ it "verifies that a server to bootstrap was given as a command line arg" do
+ knife.name_args = nil
+ lambda { knife.run }.should raise_error(SystemExit)
+ stderr.string.should match /ERROR:.+FQDN or ip/
+ end
- it "verifies that a server to bootstrap was given as a command line arg" do
- @knife.name_args = nil
- lambda { @knife.run }.should raise_error(SystemExit)
- @stderr.string.should match /ERROR:.+FQDN or ip/
+ describe "when running the bootstrap" do
+ let(:knife_ssh) do
+ knife.name_args = ["foo.example.com"]
+ knife.config[:ssh_user] = "rooty"
+ knife.config[:identity_file] = "~/.ssh/me.rsa"
+ knife.stub(:render_template).and_return("")
+ knife_ssh = knife.knife_ssh
+ knife.stub(:knife_ssh).and_return(knife_ssh)
+ knife_ssh
end
it "configures the underlying ssh command and then runs it" do
- @knife_ssh.should_receive(:run)
- @knife.run
+ knife_ssh.should_receive(:run)
+ knife.run
end
it "falls back to password based auth when auth fails the first time" do
- @knife.stub(:puts)
+ knife.stub(:puts)
- @fallback_knife_ssh = @knife_ssh.dup
- @knife_ssh.should_receive(:run).and_raise(Net::SSH::AuthenticationFailed.new("no ssh for you"))
- @knife.stub(:knife_ssh_with_password_auth).and_return(@fallback_knife_ssh)
- @fallback_knife_ssh.should_receive(:run)
- @knife.run
+ fallback_knife_ssh = knife_ssh.dup
+ knife_ssh.should_receive(:run).and_raise(Net::SSH::AuthenticationFailed.new("no ssh for you"))
+ knife.stub(:knife_ssh_with_password_auth).and_return(fallback_knife_ssh)
+ fallback_knife_ssh.should_receive(:run)
+ knife.run
end
it "raises the exception if config[:ssh_password] is set and an authentication exception is raised" do
- @knife.config[:ssh_password] = "password"
- @knife_ssh.should_receive(:run).and_raise(Net::SSH::AuthenticationFailed)
- lambda { @knife.run }.should raise_error(Net::SSH::AuthenticationFailed)
+ knife.config[:ssh_password] = "password"
+ knife_ssh.should_receive(:run).and_raise(Net::SSH::AuthenticationFailed)
+ lambda { knife.run }.should raise_error(Net::SSH::AuthenticationFailed)
end
end