chef 12.0.0.alpha.1 → 12.0.0.alpha.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/chef/application.rb +8 -1
- data/lib/chef/application/apply.rb +4 -0
- data/lib/chef/application/client.rb +7 -7
- data/lib/chef/application/solo.rb +21 -13
- data/lib/chef/chef_fs/chef_fs_data_store.rb +60 -6
- data/lib/chef/chef_fs/config.rb +78 -4
- data/lib/chef/chef_fs/data_handler/acl_data_handler.rb +2 -2
- data/lib/chef/chef_fs/data_handler/client_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/container_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/cookbook_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/data_bag_item_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/data_handler_base.rb +76 -2
- data/lib/chef/chef_fs/data_handler/environment_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/group_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/node_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/organization_data_handler.rb +30 -0
- data/lib/chef/chef_fs/data_handler/organization_invites_data_handler.rb +17 -0
- data/lib/chef/chef_fs/data_handler/organization_members_data_handler.rb +17 -0
- data/lib/chef/chef_fs/data_handler/role_data_handler.rb +1 -1
- data/lib/chef/chef_fs/data_handler/user_data_handler.rb +2 -1
- data/lib/chef/chef_fs/file_system.rb +0 -1
- data/lib/chef/chef_fs/file_system/acl_entry.rb +1 -1
- data/lib/chef/chef_fs/file_system/chef_repository_file_system_cookbook_dir.rb +1 -1
- data/lib/chef/chef_fs/file_system/chef_repository_file_system_entry.rb +5 -1
- data/lib/chef/chef_fs/file_system/chef_repository_file_system_root_dir.rb +73 -13
- data/lib/chef/chef_fs/file_system/chef_server_root_dir.rb +44 -5
- data/lib/chef/chef_fs/file_system/cookbook_dir.rb +1 -1
- data/lib/chef/chef_fs/file_system/cookbooks_dir.rb +3 -3
- data/lib/chef/chef_fs/file_system/org_entry.rb +34 -0
- data/lib/chef/chef_fs/file_system/organization_invites_entry.rb +58 -0
- data/lib/chef/chef_fs/file_system/organization_members_entry.rb +57 -0
- data/lib/chef/chef_fs/file_system/rest_list_entry.rb +13 -4
- data/lib/chef/chef_fs/knife.rb +1 -1
- data/lib/chef/client.rb +8 -2
- data/lib/chef/config.rb +75 -57
- data/lib/chef/config_fetcher.rb +6 -21
- data/lib/chef/dsl/data_query.rb +48 -3
- data/lib/chef/dsl/platform_introspection.rb +42 -0
- data/lib/chef/dsl/reboot_pending.rb +6 -3
- data/lib/chef/encrypted_data_bag_item.rb +1 -1
- data/lib/chef/encrypted_data_bag_item/encryptor.rb +12 -0
- data/lib/chef/exceptions.rb +2 -0
- data/lib/chef/http/basic_client.rb +14 -0
- data/lib/chef/http/json_output.rb +7 -2
- data/lib/chef/knife.rb +36 -121
- data/lib/chef/knife/bootstrap.rb +68 -54
- data/lib/chef/knife/bootstrap/archlinux-gems.erb +6 -1
- data/lib/chef/knife/bootstrap/chef-aix.erb +5 -0
- data/lib/chef/knife/bootstrap/chef-full.erb +5 -1
- data/lib/chef/knife/core/bootstrap_context.rb +70 -29
- data/lib/chef/knife/search.rb +56 -12
- data/lib/chef/knife/serve.rb +1 -1
- data/lib/chef/local_mode.rb +10 -4
- data/lib/chef/mixin/deep_merge.rb +6 -3
- data/lib/chef/mixin/shell_out.rb +33 -17
- data/lib/chef/null_logger.rb +72 -0
- data/lib/chef/platform.rb +2 -1
- data/lib/chef/platform/provider_mapping.rb +1 -1
- data/lib/chef/platform/rebooter.rb +54 -0
- data/lib/chef/provider/ifconfig.rb +15 -16
- data/lib/chef/provider/link.rb +1 -1
- data/lib/chef/provider/mount/mount.rb +1 -1
- data/lib/chef/provider/mount/solaris.rb +102 -64
- data/lib/chef/provider/package/aix.rb +4 -12
- data/lib/chef/provider/package/ips.rb +8 -12
- data/lib/chef/provider/package/macports.rb +4 -12
- data/lib/chef/provider/package/pacman.rb +2 -6
- data/lib/chef/provider/package/portage.rb +2 -6
- data/lib/chef/provider/package/rpm.rb +4 -12
- data/lib/chef/provider/package/solaris.rb +4 -12
- data/lib/chef/provider/reboot.rb +69 -0
- data/lib/chef/provider/service/debian.rb +10 -10
- data/lib/chef/provider/service/freebsd.rb +89 -73
- data/lib/chef/provider/service/gentoo.rb +2 -2
- data/lib/chef/provider/service/init.rb +6 -4
- data/lib/chef/provider/service/insserv.rb +3 -3
- data/lib/chef/provider/service/macosx.rb +2 -2
- data/lib/chef/provider/service/simple.rb +6 -4
- data/lib/chef/provider/service/solaris.rb +1 -1
- data/lib/chef/provider/service/systemd.rb +9 -9
- data/lib/chef/provider/service/upstart.rb +6 -6
- data/lib/chef/provider/subversion.rb +6 -6
- data/lib/chef/provider/user/dscl.rb +32 -28
- data/lib/chef/provider/user/windows.rb +6 -6
- data/lib/chef/provider/whyrun_safe_ruby_block.rb +1 -1
- data/lib/chef/providers.rb +1 -0
- data/lib/chef/recipe.rb +0 -1
- data/lib/chef/resource.rb +3 -5
- data/lib/chef/resource/mount.rb +9 -0
- data/lib/chef/resource/reboot.rb +48 -0
- data/lib/chef/resources.rb +1 -0
- data/lib/chef/run_context.rb +25 -0
- data/lib/chef/search/query.rb +122 -14
- data/lib/chef/util/path_helper.rb +54 -6
- data/lib/chef/util/windows/net_user.rb +4 -1
- data/lib/chef/version.rb +1 -1
- data/lib/chef/win32/api/file.rb +1 -5
- data/lib/chef/win32/api/net.rb +1 -0
- data/lib/chef/workstation_config_loader.rb +177 -0
- data/spec/functional/http/simple_spec.rb +57 -1
- data/spec/functional/mixin/shell_out_spec.rb +2 -2
- data/spec/functional/provider/whyrun_safe_ruby_block_spec.rb +51 -0
- data/spec/functional/rebooter_spec.rb +105 -0
- data/spec/functional/resource/deploy_revision_spec.rb +0 -4
- data/spec/functional/resource/file_spec.rb +26 -3
- data/spec/functional/resource/group_spec.rb +5 -3
- data/spec/functional/resource/link_spec.rb +16 -16
- data/spec/functional/resource/reboot_spec.rb +103 -0
- data/spec/integration/client/client_spec.rb +4 -8
- data/spec/integration/client/ipv6_spec.rb +1 -1
- data/spec/integration/knife/cookbook_api_ipv6_spec.rb +3 -2
- data/spec/integration/knife/delete_spec.rb +39 -0
- data/spec/integration/knife/deps_spec.rb +30 -20
- data/spec/integration/knife/download_spec.rb +77 -1
- data/spec/integration/knife/list_spec.rb +221 -0
- data/spec/integration/knife/raw_spec.rb +1 -1
- data/spec/integration/knife/show_spec.rb +2 -2
- data/spec/integration/knife/upload_spec.rb +154 -1
- data/spec/support/pedant/run_pedant.rb +0 -1
- data/spec/support/shared/functional/http.rb +8 -1
- data/spec/support/shared/integration/integration_helper.rb +11 -19
- data/spec/support/shared/unit/platform_introspector.rb +22 -0
- data/spec/unit/application/apply.rb +11 -1
- data/spec/unit/application/solo_spec.rb +19 -3
- data/spec/unit/chef_fs/config_spec.rb +58 -0
- data/spec/unit/config_fetcher_spec.rb +1 -3
- data/spec/unit/config_spec.rb +247 -220
- data/spec/unit/dsl/data_query_spec.rb +165 -23
- data/spec/unit/dsl/reboot_pending_spec.rb +1 -7
- data/spec/unit/encrypted_data_bag_item_spec.rb +1 -1
- data/spec/unit/knife/bootstrap_spec.rb +354 -182
- data/spec/unit/knife/core/bootstrap_context_spec.rb +67 -30
- data/spec/unit/knife_spec.rb +3 -30
- data/spec/unit/mixin/deep_merge_spec.rb +14 -0
- data/spec/unit/mixin/shell_out_spec.rb +134 -64
- data/spec/unit/provider/ifconfig/debian_spec.rb +19 -9
- data/spec/unit/provider/ifconfig/redhat_spec.rb +16 -14
- data/spec/unit/provider/ifconfig_spec.rb +3 -3
- data/spec/unit/provider/link_spec.rb +5 -5
- data/spec/unit/provider/mount/mount_spec.rb +10 -1
- data/spec/unit/provider/mount/solaris_spec.rb +185 -11
- data/spec/unit/provider/package/aix_spec.rb +5 -17
- data/spec/unit/provider/package/ips_spec.rb +8 -21
- data/spec/unit/provider/package/macports_spec.rb +12 -12
- data/spec/unit/provider/package/pacman_spec.rb +4 -12
- data/spec/unit/provider/package/portage_spec.rb +5 -15
- data/spec/unit/provider/package/rpm_spec.rb +7 -22
- data/spec/unit/provider/package/solaris_spec.rb +5 -16
- data/spec/unit/provider/service/arch_service_spec.rb +8 -14
- data/spec/unit/provider/service/debian_service_spec.rb +1 -1
- data/spec/unit/provider/service/freebsd_service_spec.rb +457 -225
- data/spec/unit/provider/service/gentoo_service_spec.rb +2 -2
- data/spec/unit/provider/service/init_service_spec.rb +10 -10
- data/spec/unit/provider/service/insserv_service_spec.rb +3 -4
- data/spec/unit/provider/service/invokercd_service_spec.rb +8 -9
- data/spec/unit/provider/service/macosx_spec.rb +5 -5
- data/spec/unit/provider/service/simple_service_spec.rb +4 -6
- data/spec/unit/provider/service/solaris_smf_service_spec.rb +1 -3
- data/spec/unit/provider/service/systemd_service_spec.rb +20 -20
- data/spec/unit/provider/service/upstart_service_spec.rb +15 -17
- data/spec/unit/provider/subversion_spec.rb +5 -6
- data/spec/unit/provider/user/dscl_spec.rb +2 -1
- data/spec/unit/provider/user/windows_spec.rb +7 -0
- data/spec/unit/provider/whyrun_safe_ruby_block_spec.rb +2 -2
- data/spec/unit/resource/mount_spec.rb +9 -0
- data/spec/unit/resource_spec.rb +0 -4
- data/spec/unit/rest_spec.rb +1 -1
- data/spec/unit/run_context_spec.rb +15 -0
- data/spec/unit/search/query_spec.rb +196 -40
- data/spec/unit/util/path_helper_spec.rb +111 -28
- data/spec/unit/workstation_config_loader_spec.rb +283 -0
- metadata +36 -20
- data/lib/chef/knife/bootstrap/centos5-gems.erb +0 -62
- data/lib/chef/knife/bootstrap/fedora13-gems.erb +0 -44
- data/lib/chef/knife/bootstrap/ubuntu10.04-apt.erb +0 -53
- data/lib/chef/knife/bootstrap/ubuntu10.04-gems.erb +0 -48
- data/lib/chef/knife/bootstrap/ubuntu12.04-gems.erb +0 -46
- data/spec/support/shared/integration/chef_zero_support.rb +0 -130
- data/spec/unit/knife/config_file_selection_spec.rb +0 -135
@@ -24,43 +24,185 @@ class DataQueryDSLTester
|
|
24
24
|
end
|
25
25
|
|
26
26
|
describe Chef::DSL::DataQuery do
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
let(:node) { Hash.new }
|
28
|
+
|
29
|
+
let(:language) do
|
30
|
+
language = DataQueryDSLTester.new
|
31
|
+
language.stub(:node).and_return(@node)
|
32
|
+
language
|
31
33
|
end
|
32
34
|
|
33
|
-
describe "
|
35
|
+
describe "::data_bag" do
|
34
36
|
it "lists the items in a data bag" do
|
35
|
-
Chef::DataBag.
|
36
|
-
|
37
|
+
allow(Chef::DataBag).to receive(:load)
|
38
|
+
.with("bag_name")
|
39
|
+
.and_return("item_1" => "http://url_for/item_1", "item_2" => "http://url_for/item_2")
|
40
|
+
expect( language.data_bag("bag_name").sort ).to eql %w(item_1 item_2)
|
37
41
|
end
|
42
|
+
end
|
38
43
|
|
39
|
-
|
40
|
-
|
44
|
+
shared_examples_for "a data bag item" do
|
45
|
+
it "validates the name of the data bag you're trying to load an item from" do
|
46
|
+
expect{ language.send(method_name, " %%^& ", "item_name") }.to raise_error(Chef::Exceptions::InvalidDataBagName)
|
41
47
|
end
|
42
48
|
|
43
|
-
it "
|
44
|
-
|
45
|
-
@item.data_bag("bag_name")
|
46
|
-
@item.raw_data = {"id" => "item_name", "FUU" => "FUU"}
|
47
|
-
Chef::DataBagItem.should_receive(:load).with("bag_name", "item_name").and_return(@item)
|
48
|
-
@language.data_bag_item("bag_name", "item_name").should == @item
|
49
|
+
it "validates the id of the data bag item you're trying to load" do
|
50
|
+
expect{ language.send(method_name, "bag_name", " 987 (*&()") }.to raise_error(Chef::Exceptions::InvalidDataBagItemID)
|
49
51
|
end
|
50
52
|
|
51
|
-
it "validates the
|
52
|
-
|
53
|
+
it "validates that the id of the data bag item is not nil" do
|
54
|
+
expect{ language.send(method_name, "bag_name", nil) }.to raise_error(Chef::Exceptions::InvalidDataBagItemID)
|
53
55
|
end
|
56
|
+
end
|
54
57
|
|
55
|
-
|
56
|
-
|
58
|
+
describe "::data_bag_item" do
|
59
|
+
let(:bag_name) { "bag_name" }
|
60
|
+
|
61
|
+
let(:item_name) { "item_name" }
|
62
|
+
|
63
|
+
let(:raw_data) {{
|
64
|
+
"id" => item_name,
|
65
|
+
"greeting" => "hello",
|
66
|
+
"nested" => {
|
67
|
+
"a1" => [1, 2, 3],
|
68
|
+
"a2" => { "b1" => true }
|
69
|
+
}
|
70
|
+
}}
|
71
|
+
|
72
|
+
let(:item) do
|
73
|
+
item = Chef::DataBagItem.new
|
74
|
+
item.data_bag(bag_name)
|
75
|
+
item.raw_data = raw_data
|
76
|
+
item
|
57
77
|
end
|
58
78
|
|
59
|
-
it "
|
60
|
-
|
79
|
+
it "fetches a data bag item" do
|
80
|
+
allow( Chef::DataBagItem ).to receive(:load).with(bag_name, item_name).and_return(item)
|
81
|
+
expect( language.data_bag_item(bag_name, item_name) ).to eql item
|
61
82
|
end
|
62
83
|
|
63
|
-
|
84
|
+
include_examples "a data bag item" do
|
85
|
+
let(:method_name) { :data_bag_item }
|
86
|
+
end
|
64
87
|
|
65
|
-
|
88
|
+
context "when the item is encrypted" do
|
89
|
+
let(:default_secret) { "abc123SECRET" }
|
90
|
+
|
91
|
+
let(:encoded_data) { Chef::EncryptedDataBagItem.encrypt_data_bag_item(raw_data, default_secret) }
|
92
|
+
|
93
|
+
let(:item) do
|
94
|
+
item = Chef::DataBagItem.new
|
95
|
+
item.data_bag(bag_name)
|
96
|
+
item.raw_data = encoded_data
|
97
|
+
item
|
98
|
+
end
|
99
|
+
|
100
|
+
before do
|
101
|
+
allow( Chef::DataBagItem ).to receive(:load).with(bag_name, item_name).and_return(item)
|
102
|
+
end
|
66
103
|
|
104
|
+
shared_examples_for "encryption detected" do
|
105
|
+
let(:encoded_data) do
|
106
|
+
Chef::Config[:data_bag_encrypt_version] = version
|
107
|
+
Chef::EncryptedDataBagItem.encrypt_data_bag_item(raw_data, default_secret)
|
108
|
+
end
|
109
|
+
|
110
|
+
before do
|
111
|
+
allow( Chef::EncryptedDataBagItem ).to receive(:load_secret).and_return(default_secret)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "detects encrypted data bag" do
|
115
|
+
expect( encryptor ).to receive(:encryptor_keys).at_least(:once).and_call_original
|
116
|
+
expect( Chef::Log ).to receive(:debug).with(/Data bag item looks encrypted/)
|
117
|
+
language.data_bag_item(bag_name, item_name)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "when encryption version is 1" do
|
122
|
+
include_examples "encryption detected" do
|
123
|
+
let(:version) { 1 }
|
124
|
+
let(:encryptor) { Chef::EncryptedDataBagItem::Encryptor::Version1Encryptor }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "when encryption version is 2" do
|
129
|
+
include_examples "encryption detected" do
|
130
|
+
let(:version) { 2 }
|
131
|
+
let(:encryptor) { Chef::EncryptedDataBagItem::Encryptor::Version2Encryptor }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "when encryption version is 3", :ruby_20_only do
|
136
|
+
include_examples "encryption detected" do
|
137
|
+
let(:version) { 3 }
|
138
|
+
let(:encryptor) { Chef::EncryptedDataBagItem::Encryptor::Version3Encryptor }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
shared_examples_for "an encrypted data bag item" do
|
143
|
+
it "returns an encrypted data bag item" do
|
144
|
+
expect( language.data_bag_item(bag_name, item_name, secret) ).to be_a_kind_of(Chef::EncryptedDataBagItem)
|
145
|
+
end
|
146
|
+
|
147
|
+
it "decrypts the contents of the data bag item" do
|
148
|
+
expect( language.data_bag_item(bag_name, item_name, secret).to_hash ).to eql raw_data
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "when a secret is supplied" do
|
153
|
+
include_examples "an encrypted data bag item" do
|
154
|
+
let(:secret) { default_secret }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when a secret is not supplied" do
|
159
|
+
before do
|
160
|
+
allow( Chef::Config ).to receive(:[]).and_call_original
|
161
|
+
expect( Chef::Config ).to receive(:[]).with(:encrypted_data_bag_secret).and_return(path)
|
162
|
+
expect( Chef::EncryptedDataBagItem ).to receive(:load_secret).and_call_original
|
163
|
+
end
|
164
|
+
|
165
|
+
context "when a secret is located at Chef::Config[:encrypted_data_bag_secret]" do
|
166
|
+
let(:path) { "/tmp/my_secret" }
|
167
|
+
|
168
|
+
before do
|
169
|
+
expect( File ).to receive(:exist?).with(path).and_return(true)
|
170
|
+
expect( IO ).to receive(:read).with(path).and_return(default_secret)
|
171
|
+
end
|
172
|
+
|
173
|
+
include_examples "an encrypted data bag item" do
|
174
|
+
let(:secret) { nil }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
shared_examples_for "no secret file" do
|
179
|
+
it "should fail to load the data bag item" do
|
180
|
+
expect( Chef::Log ).to receive(:error).with(/Failed to load secret for encrypted data bag item/)
|
181
|
+
expect( Chef::Log ).to receive(:error).with(/Failed to load data bag item/)
|
182
|
+
expect{ language.data_bag_item(bag_name, item_name) }.to raise_error(error_type, error_message)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
context "when Chef::Config[:encrypted_data_bag_secret] is not configured" do
|
187
|
+
include_examples "no secret file" do
|
188
|
+
let(:path) { nil }
|
189
|
+
let(:error_type) { ArgumentError }
|
190
|
+
let(:error_message) { /No secret specified and no secret found/ }
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "when Chef::Config[:encrypted_data_bag_secret] does not exist" do
|
195
|
+
include_examples "no secret file" do
|
196
|
+
before do
|
197
|
+
expect( File ).to receive(:exist?).with(path).and_return(false)
|
198
|
+
end
|
199
|
+
|
200
|
+
let(:path) { "/tmp/my_secret" }
|
201
|
+
let(:error_type) { Errno::ENOENT }
|
202
|
+
let(:error_message) { /file not found/ }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -21,7 +21,7 @@ require "spec_helper"
|
|
21
21
|
|
22
22
|
describe Chef::DSL::RebootPending do
|
23
23
|
describe "reboot_pending?" do
|
24
|
-
describe "in
|
24
|
+
describe "in isolation" do
|
25
25
|
let(:recipe) { Object.new.extend(Chef::DSL::RebootPending) }
|
26
26
|
|
27
27
|
before do
|
@@ -74,12 +74,6 @@ describe Chef::DSL::RebootPending do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
context "platform is not supported" do
|
78
|
-
it 'should raise an exception' do
|
79
|
-
recipe.stub_chain(:node, :[]).with(:platform).and_return('msdos')
|
80
|
-
expect { recipe.reboot_pending? }.to raise_error(Chef::Exceptions::UnsupportedPlatform)
|
81
|
-
end
|
82
|
-
end
|
83
77
|
end # describe in isolation
|
84
78
|
|
85
79
|
describe "in a recipe" do
|
@@ -451,7 +451,7 @@ describe Chef::EncryptedDataBagItem do
|
|
451
451
|
end
|
452
452
|
|
453
453
|
it "load_secret(nil) emits a reasonable error message" do
|
454
|
-
lambda { Chef::EncryptedDataBagItem.load_secret(nil) }.should raise_error(ArgumentError,
|
454
|
+
lambda { Chef::EncryptedDataBagItem.load_secret(nil) }.should raise_error(ArgumentError, /No secret specified and no secret found at #{Chef::Config[:encrypted_data_bag_secret]}/)
|
455
455
|
end
|
456
456
|
end
|
457
457
|
|
@@ -22,111 +22,200 @@ Chef::Knife::Bootstrap.load_deps
|
|
22
22
|
require 'net/ssh'
|
23
23
|
|
24
24
|
describe Chef::Knife::Bootstrap do
|
25
|
-
|
25
|
+
let(:knife) do
|
26
26
|
Chef::Log.logger = Logger.new(StringIO.new)
|
27
|
-
|
28
|
-
# Merge default settings in.
|
29
|
-
@knife.merge_configs
|
30
|
-
@knife.config[:template_file] = File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb"))
|
31
|
-
@stdout = StringIO.new
|
32
|
-
@knife.ui.stub(:stdout).and_return(@stdout)
|
33
|
-
@stderr = StringIO.new
|
34
|
-
@knife.ui.stub(:stderr).and_return(@stderr)
|
35
|
-
end
|
27
|
+
Chef::Config[:knife][:bootstrap_template] = bootstrap_template unless bootstrap_template.nil?
|
36
28
|
|
37
|
-
|
38
|
-
|
39
|
-
end
|
29
|
+
k = Chef::Knife::Bootstrap.new
|
30
|
+
k.merge_configs
|
40
31
|
|
41
|
-
|
42
|
-
|
43
|
-
@knife.config[:distro] = 'penultimate'
|
44
|
-
lambda { @knife.find_template }.should raise_error
|
32
|
+
k.ui.stub(:stderr).and_return(stderr)
|
33
|
+
k
|
45
34
|
end
|
46
35
|
|
47
|
-
|
48
|
-
File.stub(:exists?).and_return(true)
|
49
|
-
@knife.name_args = ['shatner']
|
50
|
-
@knife.stub(:read_template).and_return("")
|
51
|
-
@knife.stub(:knife_ssh).and_return(true)
|
52
|
-
@knife_ssh = @knife.knife_ssh
|
53
|
-
@knife.should_receive(:find_template).ordered
|
54
|
-
@knife.should_receive(:knife_ssh).ordered
|
55
|
-
@knife_ssh.should_receive(:run) # rspec appears to keep order per object
|
56
|
-
@knife.run
|
57
|
-
end
|
36
|
+
let(:stderr) { StringIO.new }
|
58
37
|
|
59
|
-
|
60
|
-
@knife.config[:distro] = 'fedora13-gems'
|
61
|
-
lambda { @knife.find_template }.should_not raise_error
|
62
|
-
end
|
38
|
+
let(:bootstrap_template) { nil }
|
63
39
|
|
64
|
-
it "should
|
65
|
-
|
66
|
-
|
67
|
-
File.stub(:exists?).and_return(true)
|
68
|
-
IO.stub(:read).and_return('random content')
|
69
|
-
@knife.config[:distro] = 'fake-bootstrap-template'
|
70
|
-
lambda { @knife.find_template }.should_not raise_error
|
40
|
+
it "should use chef-full as default template" do
|
41
|
+
knife.bootstrap_template.should be_a_kind_of(String)
|
42
|
+
File.basename(knife.bootstrap_template).should eq("chef-full")
|
71
43
|
end
|
72
44
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
45
|
+
context "when finding templates" do
|
46
|
+
context "when :bootstrap_template config is set to a file" do
|
47
|
+
context "that doesn't exist" do
|
48
|
+
let(:bootstrap_template) { "/opt/blah/not/exists/template.erb" }
|
78
49
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
@knife.render_template(template_string).should == '{"run_list":["role[base]"]}'
|
84
|
-
end
|
50
|
+
it "raises an error" do
|
51
|
+
lambda { knife.find_template }.should raise_error
|
52
|
+
end
|
53
|
+
end
|
85
54
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
55
|
+
context "that exists" do
|
56
|
+
let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")) }
|
57
|
+
|
58
|
+
it "loads the given file as the template" do
|
59
|
+
Chef::Log.should_receive(:debug)
|
60
|
+
knife.find_template.should eq(File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "when :bootstrap_template config is set to a template name" do
|
66
|
+
let(:bootstrap_template) { "example" }
|
67
|
+
|
68
|
+
let(:builtin_template_path) { File.expand_path(File.join(File.dirname(__FILE__), '../../../lib/chef/knife/bootstrap', "example.erb"))}
|
69
|
+
|
70
|
+
let(:chef_config_dir_template_path) { "/knife/chef/config/bootstrap/example.erb" }
|
71
|
+
|
72
|
+
let(:env_home_template_path) { "/env/home/.chef/bootstrap/example.erb" }
|
73
|
+
|
74
|
+
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" }
|
75
|
+
|
76
|
+
def configure_chef_config_dir
|
77
|
+
Chef::Knife.stub(:chef_config_dir).and_return("/knife/chef/config")
|
78
|
+
end
|
79
|
+
|
80
|
+
def configure_env_home
|
81
|
+
ENV['HOME'] = "/env/home"
|
82
|
+
end
|
83
|
+
|
84
|
+
def configure_gem_files
|
85
|
+
Gem.stub(:find_files).and_return([ gem_files_template_path ])
|
86
|
+
end
|
87
|
+
|
88
|
+
before(:each) do
|
89
|
+
@original_home = ENV['HOME']
|
90
|
+
ENV['HOME'] = nil
|
91
|
+
File.should_receive(:exists?).with(bootstrap_template).and_return(false)
|
92
|
+
end
|
93
|
+
|
94
|
+
after(:each) do
|
95
|
+
ENV['HOME'] = @original_home
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when file is available everywhere" do
|
99
|
+
before do
|
100
|
+
configure_chef_config_dir
|
101
|
+
configure_env_home
|
102
|
+
configure_gem_files
|
103
|
+
|
104
|
+
File.should_receive(:exists?).with(builtin_template_path).and_return(true)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should load the template from built-in templates" do
|
108
|
+
knife.find_template.should eq(builtin_template_path)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when file is available in chef_config_dir" do
|
113
|
+
before do
|
114
|
+
configure_chef_config_dir
|
115
|
+
configure_env_home
|
116
|
+
configure_gem_files
|
92
117
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
118
|
+
File.should_receive(:exists?).with(builtin_template_path).and_return(false)
|
119
|
+
File.should_receive(:exists?).with(chef_config_dir_template_path).and_return(true)
|
120
|
+
|
121
|
+
it "should load the template from chef_config_dir" do
|
122
|
+
knife.find_template.should eq(chef_config_dir_template_path)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context "when file is available in ENV['HOME']" do
|
128
|
+
before do
|
129
|
+
configure_chef_config_dir
|
130
|
+
configure_env_home
|
131
|
+
configure_gem_files
|
132
|
+
|
133
|
+
File.should_receive(:exists?).with(builtin_template_path).and_return(false)
|
134
|
+
File.should_receive(:exists?).with(chef_config_dir_template_path).and_return(false)
|
135
|
+
File.should_receive(:exists?).with(env_home_template_path).and_return(true)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should load the template from chef_config_dir" do
|
139
|
+
knife.find_template.should eq(env_home_template_path)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "when file is available in Gem files" do
|
144
|
+
before do
|
145
|
+
configure_chef_config_dir
|
146
|
+
configure_gem_files
|
147
|
+
|
148
|
+
File.should_receive(:exists?).with(builtin_template_path).and_return(false)
|
149
|
+
File.should_receive(:exists?).with(chef_config_dir_template_path).and_return(false)
|
150
|
+
File.should_receive(:exists?).with(gem_files_template_path).and_return(true)
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should load the template from Gem files" do
|
154
|
+
knife.find_template.should eq(gem_files_template_path)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
100
158
|
end
|
101
159
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
160
|
+
["-d", "--distro", "-t", "--bootstrap-template", "--template-file"].each do |t|
|
161
|
+
context "when #{t} option is given in the command line" do
|
162
|
+
it "sets the knife :bootstrap_template config" do
|
163
|
+
knife.parse_options([t,"blahblah"])
|
164
|
+
knife.merge_configs
|
165
|
+
knife.bootstrap_template.should eq("blahblah")
|
166
|
+
end
|
167
|
+
end
|
108
168
|
end
|
109
169
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
170
|
+
context "with run_list template" do
|
171
|
+
let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test.erb")) }
|
172
|
+
|
173
|
+
it "should return an empty run_list" do
|
174
|
+
knife.render_template.should == '{"run_list":[]}'
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should have role[base] in the run_list" do
|
178
|
+
knife.parse_options(["-r","role[base]"])
|
179
|
+
knife.merge_configs
|
180
|
+
knife.render_template.should == '{"run_list":["role[base]"]}'
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should have role[base] and recipe[cupcakes] in the run_list" do
|
184
|
+
knife.parse_options(["-r", "role[base],recipe[cupcakes]"])
|
185
|
+
knife.merge_configs
|
186
|
+
knife.render_template.should == '{"run_list":["role[base]","recipe[cupcakes]"]}'
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should have foo => {bar => baz} in the first_boot" do
|
190
|
+
knife.parse_options(["-j", '{"foo":{"bar":"baz"}}'])
|
191
|
+
knife.merge_configs
|
192
|
+
expected_hash = FFI_Yajl::Parser.new.parse('{"foo":{"bar":"baz"},"run_list":[]}')
|
193
|
+
actual_hash = FFI_Yajl::Parser.new.parse(knife.render_template)
|
194
|
+
actual_hash.should == expected_hash
|
195
|
+
end
|
119
196
|
end
|
120
197
|
|
121
|
-
|
122
|
-
|
123
|
-
|
198
|
+
context "with hints template" do
|
199
|
+
let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "test-hints.erb")) }
|
200
|
+
|
201
|
+
it "should create a hint file when told to" do
|
202
|
+
knife.parse_options(["--hint", "openstack"])
|
203
|
+
knife.merge_configs
|
204
|
+
knife.render_template.should match /\/etc\/chef\/ohai\/hints\/openstack.json/
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should populate a hint file with JSON when given a file to read" do
|
208
|
+
::File.stub(:read).and_return('{ "foo" : "bar" }')
|
209
|
+
knife.parse_options(["--hint", "openstack=hints/openstack.json"])
|
210
|
+
knife.merge_configs
|
211
|
+
knife.render_template.should match /\{\"foo\":\"bar\"\}/
|
212
|
+
end
|
124
213
|
end
|
125
214
|
|
126
215
|
describe "specifying no_proxy with various entries" do
|
127
216
|
subject(:knife) do
|
128
217
|
k = described_class.new
|
129
|
-
|
218
|
+
Chef::Config[:knife][:bootstrap_template] = template_file
|
130
219
|
k.parse_options(options)
|
131
220
|
k.merge_configs
|
132
221
|
k
|
@@ -139,8 +228,7 @@ describe Chef::Knife::Bootstrap do
|
|
139
228
|
let(:options){ ["--bootstrap-no-proxy", setting, "-s", "foo"] }
|
140
229
|
let(:template_file) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "no_proxy.erb")) }
|
141
230
|
let(:rendered_template) do
|
142
|
-
|
143
|
-
knife.render_template(template_string)
|
231
|
+
knife.render_template
|
144
232
|
end
|
145
233
|
|
146
234
|
context "via --bootstrap-no-proxy" do
|
@@ -158,19 +246,57 @@ describe Chef::Knife::Bootstrap do
|
|
158
246
|
rendered_template.should match(%r{.*no_proxy\s*"api.opscode.com,172.16.10.\*".*})
|
159
247
|
end
|
160
248
|
end
|
249
|
+
|
250
|
+
context "via --ssl-verify-mode none" do
|
251
|
+
let(:options) { ["--node-ssl-verify-mode", "none"] }
|
252
|
+
|
253
|
+
it "renders the client.rb with ssl_verify_mode set to :verify_none" do
|
254
|
+
rendered_template.should match(/ssl_verify_mode :verify_none/)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "via --node-ssl-verify-mode peer" do
|
259
|
+
let(:options) { ["--node-ssl-verify-mode", "peer"] }
|
260
|
+
|
261
|
+
it "renders the client.rb with ssl_verify_mode set to :verify_peer" do
|
262
|
+
rendered_template.should match(/ssl_verify_mode :verify_peer/)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "via --node-ssl-verify-mode all" do
|
267
|
+
let(:options) { ["--node-ssl-verify-mode", "all"] }
|
268
|
+
|
269
|
+
it "raises error" do
|
270
|
+
lambda{ rendered_template }.should raise_error
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context "via --node-verify-api-cert" do
|
275
|
+
let(:options) { ["--node-verify-api-cert"] }
|
276
|
+
|
277
|
+
it "renders the client.rb with verify_api_cert set to true" do
|
278
|
+
rendered_template.should match(/verify_api_cert true/)
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
context "via --no-node-verify-api-cert" do
|
283
|
+
let(:options) { ["--no-node-verify-api-cert"] }
|
284
|
+
|
285
|
+
it "renders the client.rb with verify_api_cert set to false" do
|
286
|
+
rendered_template.should match(/verify_api_cert false/)
|
287
|
+
end
|
288
|
+
end
|
161
289
|
end
|
162
290
|
|
163
291
|
describe "specifying the encrypted data bag secret key" do
|
164
|
-
subject(:knife) { described_class.new }
|
165
292
|
let(:secret) { "supersekret" }
|
166
293
|
let(:secret_file) { File.join(CHEF_SPEC_DATA, 'bootstrap', 'encrypted_data_bag_secret') }
|
167
294
|
let(:options) { [] }
|
168
|
-
let(:
|
295
|
+
let(:bootstrap_template) { File.expand_path(File.join(CHEF_SPEC_DATA, "bootstrap", "secret.erb")) }
|
169
296
|
let(:rendered_template) do
|
170
|
-
knife.instance_variable_set("@template_file", template_file)
|
171
297
|
knife.parse_options(options)
|
172
|
-
|
173
|
-
knife.render_template
|
298
|
+
knife.merge_configs
|
299
|
+
knife.render_template
|
174
300
|
end
|
175
301
|
|
176
302
|
context "via --secret" do
|
@@ -198,10 +324,27 @@ describe Chef::Knife::Bootstrap do
|
|
198
324
|
end
|
199
325
|
end
|
200
326
|
|
201
|
-
context "via
|
202
|
-
before
|
327
|
+
context "secret via config" do
|
328
|
+
before do
|
329
|
+
Chef::Config[:knife][:secret] = secret
|
330
|
+
end
|
331
|
+
|
332
|
+
it "creates a secret file" do
|
333
|
+
rendered_template.should match(%r{#{secret}})
|
334
|
+
end
|
335
|
+
|
336
|
+
it "renders the client.rb with an encrypted_data_bag_secret entry" do
|
337
|
+
rendered_template.should match(%r{encrypted_data_bag_secret\s*"/etc/chef/encrypted_data_bag_secret"})
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
context "secret-file via config" do
|
203
342
|
let(:secret) { IO.read(secret_file) }
|
204
343
|
|
344
|
+
before do
|
345
|
+
Chef::Config[:knife][:secret_file] = secret_file
|
346
|
+
end
|
347
|
+
|
205
348
|
it "creates a secret file" do
|
206
349
|
rendered_template.should match(%r{#{secret}})
|
207
350
|
end
|
@@ -212,186 +355,215 @@ describe Chef::Knife::Bootstrap do
|
|
212
355
|
end
|
213
356
|
end
|
214
357
|
|
358
|
+
describe "when transferring trusted certificates" do
|
359
|
+
let(:trusted_certs_dir) { File.join(CHEF_SPEC_DATA, 'trusted_certs') }
|
360
|
+
|
361
|
+
let(:rendered_template) do
|
362
|
+
knife.merge_configs
|
363
|
+
knife.render_template
|
364
|
+
end
|
365
|
+
|
366
|
+
before do
|
367
|
+
Chef::Config[:trusted_certs_dir] = trusted_certs_dir
|
368
|
+
IO.stub(:read).and_call_original
|
369
|
+
IO.stub(:read).with("/etc/chef/validation.pem").and_return("")
|
370
|
+
end
|
371
|
+
|
372
|
+
def certificates
|
373
|
+
Dir[File.join(trusted_certs_dir, "*.{crt,pem}")]
|
374
|
+
end
|
375
|
+
|
376
|
+
it "creates /etc/chef/trusted_certs" do
|
377
|
+
rendered_template.should match(%r{mkdir -p /etc/chef/trusted_certs})
|
378
|
+
end
|
379
|
+
|
380
|
+
it "copies the certificates in the directory" do
|
381
|
+
certificates.each do |cert|
|
382
|
+
IO.should_receive(:read).with(File.expand_path(cert))
|
383
|
+
end
|
384
|
+
|
385
|
+
certificates.each do |cert|
|
386
|
+
rendered_template.should match(%r{cat > /etc/chef/trusted_certs/#{File.basename(cert)} <<'EOP'})
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
it "doesn't create /etc/chef/trusted_certs if :trusted_certs_dir is empty" do
|
391
|
+
Dir.should_receive(:glob).with(File.join(trusted_certs_dir, "*.{crt,pem}")).and_return([])
|
392
|
+
rendered_template.should_not match(%r{mkdir -p /etc/chef/trusted_certs})
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
215
396
|
describe "when configuring the underlying knife ssh command" do
|
216
397
|
context "from the command line" do
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
398
|
+
let(:knife_ssh) do
|
399
|
+
knife.name_args = ["foo.example.com"]
|
400
|
+
knife.config[:ssh_user] = "rooty"
|
401
|
+
knife.config[:ssh_port] = "4001"
|
402
|
+
knife.config[:ssh_password] = "open_sesame"
|
222
403
|
Chef::Config[:knife][:ssh_user] = nil
|
223
404
|
Chef::Config[:knife][:ssh_port] = nil
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
405
|
+
knife.config[:forward_agent] = true
|
406
|
+
knife.config[:identity_file] = "~/.ssh/me.rsa"
|
407
|
+
knife.stub(:render_template).and_return("")
|
408
|
+
knife.knife_ssh
|
228
409
|
end
|
229
410
|
|
230
411
|
it "configures the hostname" do
|
231
|
-
|
412
|
+
knife_ssh.name_args.first.should == "foo.example.com"
|
232
413
|
end
|
233
414
|
|
234
415
|
it "configures the ssh user" do
|
235
|
-
|
416
|
+
knife_ssh.config[:ssh_user].should == 'rooty'
|
236
417
|
end
|
237
418
|
|
238
419
|
it "configures the ssh password" do
|
239
|
-
|
420
|
+
knife_ssh.config[:ssh_password].should == 'open_sesame'
|
240
421
|
end
|
241
422
|
|
242
423
|
it "configures the ssh port" do
|
243
|
-
|
424
|
+
knife_ssh.config[:ssh_port].should == '4001'
|
244
425
|
end
|
245
426
|
|
246
427
|
it "configures the ssh agent forwarding" do
|
247
|
-
|
428
|
+
knife_ssh.config[:forward_agent].should == true
|
248
429
|
end
|
249
430
|
|
250
431
|
it "configures the ssh identity file" do
|
251
|
-
|
432
|
+
knife_ssh.config[:identity_file].should == '~/.ssh/me.rsa'
|
252
433
|
end
|
253
434
|
end
|
435
|
+
|
254
436
|
context "validating use_sudo_password" do
|
255
437
|
before do
|
256
|
-
|
257
|
-
|
258
|
-
@knife.stub(:read_template).and_return(IO.read(@knife.find_template).chomp)
|
438
|
+
knife.config[:ssh_password] = "password"
|
439
|
+
knife.stub(:render_template).and_return("")
|
259
440
|
end
|
260
441
|
|
261
442
|
it "use_sudo_password contains description and long params for help" do
|
262
|
-
|
263
|
-
and
|
264
|
-
and
|
443
|
+
knife.options.should have_key(:use_sudo_password) \
|
444
|
+
and knife.options[:use_sudo_password][:description].to_s.should_not == ''\
|
445
|
+
and knife.options[:use_sudo_password][:long].to_s.should_not == ''
|
265
446
|
end
|
266
447
|
|
267
448
|
it "uses the password from --ssh-password for sudo when --use-sudo-password is set" do
|
268
|
-
|
269
|
-
|
270
|
-
|
449
|
+
knife.config[:use_sudo] = true
|
450
|
+
knife.config[:use_sudo_password] = true
|
451
|
+
knife.ssh_command.should include("echo \'#{knife.config[:ssh_password]}\' | sudo -S")
|
271
452
|
end
|
272
453
|
|
273
454
|
it "should not honor --use-sudo-password when --use-sudo is not set" do
|
274
|
-
|
275
|
-
|
276
|
-
|
455
|
+
knife.config[:use_sudo] = false
|
456
|
+
knife.config[:use_sudo_password] = true
|
457
|
+
knife.ssh_command.should_not include("echo #{knife.config[:ssh_password]} | sudo -S")
|
277
458
|
end
|
278
459
|
end
|
460
|
+
|
279
461
|
context "from the knife config file" do
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
462
|
+
let(:knife_ssh) do
|
463
|
+
knife.name_args = ["config.example.com"]
|
464
|
+
knife.config[:ssh_user] = nil
|
465
|
+
knife.config[:ssh_port] = nil
|
466
|
+
knife.config[:ssh_gateway] = nil
|
467
|
+
knife.config[:forward_agent] = nil
|
468
|
+
knife.config[:identity_file] = nil
|
469
|
+
knife.config[:host_key_verify] = nil
|
288
470
|
Chef::Config[:knife][:ssh_user] = "curiosity"
|
289
471
|
Chef::Config[:knife][:ssh_port] = "2430"
|
290
472
|
Chef::Config[:knife][:forward_agent] = true
|
291
473
|
Chef::Config[:knife][:identity_file] = "~/.ssh/you.rsa"
|
292
474
|
Chef::Config[:knife][:ssh_gateway] = "towel.blinkenlights.nl"
|
293
475
|
Chef::Config[:knife][:host_key_verify] = true
|
294
|
-
|
295
|
-
|
476
|
+
knife.stub(:render_template).and_return("")
|
477
|
+
knife.knife_ssh
|
296
478
|
end
|
297
479
|
|
298
480
|
it "configures the ssh user" do
|
299
|
-
|
481
|
+
knife_ssh.config[:ssh_user].should == 'curiosity'
|
300
482
|
end
|
301
483
|
|
302
484
|
it "configures the ssh port" do
|
303
|
-
|
485
|
+
knife_ssh.config[:ssh_port].should == '2430'
|
304
486
|
end
|
305
487
|
|
306
488
|
it "configures the ssh agent forwarding" do
|
307
|
-
|
489
|
+
knife_ssh.config[:forward_agent].should == true
|
308
490
|
end
|
309
491
|
|
310
492
|
it "configures the ssh identity file" do
|
311
|
-
|
493
|
+
knife_ssh.config[:identity_file].should == '~/.ssh/you.rsa'
|
312
494
|
end
|
313
495
|
|
314
496
|
it "configures the ssh gateway" do
|
315
|
-
|
497
|
+
knife_ssh.config[:ssh_gateway].should == 'towel.blinkenlights.nl'
|
316
498
|
end
|
317
499
|
|
318
500
|
it "configures the host key verify mode" do
|
319
|
-
|
501
|
+
knife_ssh.config[:host_key_verify].should == true
|
320
502
|
end
|
321
503
|
end
|
322
504
|
|
323
505
|
describe "when falling back to password auth when host key auth fails" do
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
506
|
+
let(:knife_ssh_with_password_auth) do
|
507
|
+
knife.name_args = ["foo.example.com"]
|
508
|
+
knife.config[:ssh_user] = "rooty"
|
509
|
+
knife.config[:identity_file] = "~/.ssh/me.rsa"
|
510
|
+
knife.stub(:render_template).and_return("")
|
511
|
+
k = knife.knife_ssh
|
512
|
+
k.stub(:get_password).and_return('typed_in_password')
|
513
|
+
knife.stub(:knife_ssh).and_return(k)
|
514
|
+
knife.knife_ssh_with_password_auth
|
330
515
|
end
|
331
516
|
|
332
517
|
it "prompts the user for a password " do
|
333
|
-
|
334
|
-
@knife_ssh.stub(:get_password).and_return('typed_in_password')
|
335
|
-
alternate_knife_ssh = @knife.knife_ssh_with_password_auth
|
336
|
-
alternate_knife_ssh.config[:ssh_password].should == 'typed_in_password'
|
518
|
+
knife_ssh_with_password_auth.config[:ssh_password].should == 'typed_in_password'
|
337
519
|
end
|
338
520
|
|
339
521
|
it "configures knife not to use the identity file that didn't work previously" do
|
340
|
-
|
341
|
-
@knife_ssh.stub(:get_password).and_return('typed_in_password')
|
342
|
-
alternate_knife_ssh = @knife.knife_ssh_with_password_auth
|
343
|
-
alternate_knife_ssh.config[:identity_file].should be_nil
|
522
|
+
knife_ssh_with_password_auth.config[:identity_file].should be_nil
|
344
523
|
end
|
345
524
|
end
|
346
525
|
end
|
347
526
|
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
@knife.stub(:read_template).and_return("")
|
354
|
-
@knife_ssh = @knife.knife_ssh
|
355
|
-
@knife.stub(:knife_ssh).and_return(@knife_ssh)
|
356
|
-
end
|
527
|
+
it "verifies that a server to bootstrap was given as a command line arg" do
|
528
|
+
knife.name_args = nil
|
529
|
+
lambda { knife.run }.should raise_error(SystemExit)
|
530
|
+
stderr.string.should match /ERROR:.+FQDN or ip/
|
531
|
+
end
|
357
532
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
533
|
+
describe "when running the bootstrap" do
|
534
|
+
let(:knife_ssh) do
|
535
|
+
knife.name_args = ["foo.example.com"]
|
536
|
+
knife.config[:ssh_user] = "rooty"
|
537
|
+
knife.config[:identity_file] = "~/.ssh/me.rsa"
|
538
|
+
knife.stub(:render_template).and_return("")
|
539
|
+
knife_ssh = knife.knife_ssh
|
540
|
+
knife.stub(:knife_ssh).and_return(knife_ssh)
|
541
|
+
knife_ssh
|
362
542
|
end
|
363
543
|
|
364
544
|
it "configures the underlying ssh command and then runs it" do
|
365
|
-
|
366
|
-
|
545
|
+
knife_ssh.should_receive(:run)
|
546
|
+
knife.run
|
367
547
|
end
|
368
548
|
|
369
549
|
it "falls back to password based auth when auth fails the first time" do
|
370
|
-
|
550
|
+
knife.stub(:puts)
|
371
551
|
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
552
|
+
fallback_knife_ssh = knife_ssh.dup
|
553
|
+
knife_ssh.should_receive(:run).and_raise(Net::SSH::AuthenticationFailed.new("no ssh for you"))
|
554
|
+
knife.stub(:knife_ssh_with_password_auth).and_return(fallback_knife_ssh)
|
555
|
+
fallback_knife_ssh.should_receive(:run)
|
556
|
+
knife.run
|
377
557
|
end
|
378
558
|
|
379
559
|
it "raises the exception if config[:ssh_password] is set and an authentication exception is raised" do
|
380
|
-
|
381
|
-
|
382
|
-
lambda {
|
560
|
+
knife.config[:ssh_password] = "password"
|
561
|
+
knife_ssh.should_receive(:run).and_raise(Net::SSH::AuthenticationFailed)
|
562
|
+
lambda { knife.run }.should raise_error(Net::SSH::AuthenticationFailed)
|
383
563
|
end
|
564
|
+
end
|
384
565
|
|
385
|
-
|
386
|
-
let(:secret_file) { File.join(CHEF_SPEC_DATA, 'bootstrap', 'encrypted_data_bag_secret') }
|
387
|
-
before { Chef::Config[:encrypted_data_bag_secret] = secret_file }
|
388
|
-
|
389
|
-
it "warns the configuration option is deprecated" do
|
390
|
-
@knife_ssh.should_receive(:run)
|
391
|
-
@knife.ui.should_receive(:warn).at_least(3).times
|
392
|
-
@knife.run
|
393
|
-
end
|
394
|
-
end
|
566
|
+
describe "specifying ssl verification" do
|
395
567
|
|
396
568
|
end
|
397
569
|
|