chef 15.3.14-universal-mingw32 → 15.4.45-universal-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/chef.gemspec +2 -2
- data/lib/chef/application/solo.rb +1 -1
- data/lib/chef/event_dispatch/dispatcher.rb +9 -2
- data/lib/chef/formatters/doc.rb +3 -3
- data/lib/chef/knife.rb +13 -3
- data/lib/chef/knife/bootstrap.rb +28 -4
- data/lib/chef/knife/bootstrap/templates/chef-full.erb +7 -8
- data/lib/chef/knife/data_bag_secret_options.rb +11 -4
- data/lib/chef/knife/download.rb +2 -2
- data/lib/chef/knife/exec.rb +9 -1
- data/lib/chef/knife/ssh.rb +1 -1
- data/lib/chef/knife/ssl_check.rb +1 -1
- data/lib/chef/knife/supermarket_list.rb +19 -7
- data/lib/chef/knife/supermarket_search.rb +3 -2
- data/lib/chef/node/attribute.rb +2 -0
- data/lib/chef/node/attribute_collections.rb +8 -0
- data/lib/chef/node/immutable_collections.rb +12 -0
- data/lib/chef/node/mixin/immutablize_array.rb +1 -0
- data/lib/chef/node/mixin/immutablize_hash.rb +1 -0
- data/lib/chef/provider.rb +14 -8
- data/lib/chef/provider/package/chocolatey.rb +11 -3
- data/lib/chef/provider/package/dnf/python_helper.rb +8 -3
- data/lib/chef/provider/package/windows/exe.rb +2 -2
- data/lib/chef/provider/package/windows/msi.rb +3 -3
- data/lib/chef/provider/package/yum/python_helper.rb +8 -3
- data/lib/chef/provider/service/windows.rb +1 -1
- data/lib/chef/resource/apt_repository.rb +19 -13
- data/lib/chef/resource/apt_update.rb +15 -1
- data/lib/chef/resource/archive_file.rb +10 -1
- data/lib/chef/resource/build_essential.rb +14 -1
- data/lib/chef/resource/chocolatey_config.rb +17 -1
- data/lib/chef/resource/chocolatey_feature.rb +15 -0
- data/lib/chef/resource/chocolatey_package.rb +31 -1
- data/lib/chef/resource/chocolatey_source.rb +17 -1
- data/lib/chef/resource/cookbook_file.rb +1 -1
- data/lib/chef/resource/cron_access.rb +22 -1
- data/lib/chef/resource/cron_d.rb +46 -1
- data/lib/chef/resource/dmg_package.rb +28 -0
- data/lib/chef/resource/kernel_module.rb +61 -0
- data/lib/chef/resource/sudo.rb +2 -2
- data/lib/chef/resource/windows_ad_join.rb +72 -3
- data/lib/chef/resource/windows_service.rb +1 -1
- data/lib/chef/resource/windows_share.rb +2 -1
- data/lib/chef/shell.rb +4 -4
- data/lib/chef/shell/ext.rb +2 -2
- data/lib/chef/train_transport.rb +1 -1
- data/lib/chef/version.rb +1 -1
- data/spec/functional/resource/ifconfig_spec.rb +0 -2
- data/spec/functional/resource/mount_spec.rb +0 -4
- data/spec/functional/util/powershell/cmdlet_spec.rb +2 -2
- data/spec/integration/knife/chef_repo_path_spec.rb +4 -2
- data/spec/integration/recipes/resource_converge_if_changed_spec.rb +19 -19
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/formatters/doc_spec.rb +18 -0
- data/spec/unit/knife/bootstrap_spec.rb +46 -10
- data/spec/unit/knife/supermarket_list_spec.rb +70 -0
- data/spec/unit/knife/supermarket_search_spec.rb +85 -0
- data/spec/unit/node/attribute_spec.rb +22 -0
- data/spec/unit/node/immutable_collections_spec.rb +72 -144
- data/spec/unit/provider/package/chocolatey_spec.rb +50 -35
- data/spec/unit/provider/package/windows/exe_spec.rb +1 -1
- data/spec/unit/provider/service/windows_spec.rb +23 -3
- data/spec/unit/resource/chocolatey_package_spec.rb +17 -2
- data/spec/unit/resource/windows_ad_join_spec.rb +4 -0
- data/spec/unit/resource/windows_service_spec.rb +5 -0
- data/spec/unit/resource/windows_share_spec.rb +7 -0
- data/tasks/docs.rb +4 -1
- metadata +10 -8
@@ -79,7 +79,8 @@ describe "chef_repo_path tests", :workstation do
|
|
79
79
|
EOM
|
80
80
|
end
|
81
81
|
|
82
|
-
|
82
|
+
# "Skipping for BK... As Windows 2019 has 8dot3name disabled by default"
|
83
|
+
it "knife list --local -Rfp --chef-repo-path chef_r~1 / grabs chef_repo2 stuff", :windows_only, :skip_buildkite do
|
83
84
|
Chef::Config.delete(:chef_repo_path)
|
84
85
|
knife("list --local -Rfp --chef-repo-path #{path_to("chef_r~1")} /").should_succeed <<~EOM
|
85
86
|
/clients/
|
@@ -101,7 +102,8 @@ describe "chef_repo_path tests", :workstation do
|
|
101
102
|
EOM
|
102
103
|
end
|
103
104
|
|
104
|
-
|
105
|
+
# "Skipping for BK... As Windows 2019 has 8dot3name disabled by default"
|
106
|
+
it "knife list --local -Rfp --chef-repo-path chef_r~1 / grabs chef_repo2 stuff", :windows_only, :skip_buildkite do
|
105
107
|
Chef::Config.delete(:chef_repo_path)
|
106
108
|
knife("list -z -Rfp --chef-repo-path #{path_to("chef_r~1")} /").should_succeed <<~EOM
|
107
109
|
/acls/
|
@@ -53,9 +53,9 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
53
53
|
context "and current_resource with state1=current, state2=current" do
|
54
54
|
before :each do
|
55
55
|
resource_class.load_current_value do
|
56
|
-
state1 "
|
57
|
-
state2 "
|
58
|
-
sensitive1 "
|
56
|
+
state1 "default_state1"
|
57
|
+
state2 "default_state2"
|
58
|
+
sensitive1 "default_dontprintme"
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
@@ -86,7 +86,7 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
86
86
|
expect(converged_recipe.stdout).to eq <<~EOM
|
87
87
|
* #{resource_name}[blah] action create
|
88
88
|
- update default_identity1
|
89
|
-
- set state1 to "new_state1" (was "
|
89
|
+
- set state1 to "new_state1" (was "default_state1")
|
90
90
|
EOM
|
91
91
|
end
|
92
92
|
end
|
@@ -107,8 +107,8 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
107
107
|
expect(converged_recipe.stdout).to eq <<~EOM
|
108
108
|
* #{resource_name}[blah] action create
|
109
109
|
- update default_identity1
|
110
|
-
- set state1 to "new_state1" (was "
|
111
|
-
- set state2 to "new_state2" (was "
|
110
|
+
- set state1 to "new_state1" (was "default_state1")
|
111
|
+
- set state2 to "new_state2" (was "default_state2")
|
112
112
|
EOM
|
113
113
|
end
|
114
114
|
end
|
@@ -160,7 +160,7 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
160
160
|
let(:converge_recipe) do
|
161
161
|
<<-EOM
|
162
162
|
#{resource_name} 'blah' do
|
163
|
-
state1 '
|
163
|
+
state1 'default_state1'
|
164
164
|
state2 'new_state2'
|
165
165
|
end
|
166
166
|
EOM
|
@@ -172,7 +172,7 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
172
172
|
expect(converged_recipe.stdout).to eq <<~EOM
|
173
173
|
* #{resource_name}[blah] action create
|
174
174
|
- update default_identity1
|
175
|
-
- set state2 to "new_state2" (was "
|
175
|
+
- set state2 to "new_state2" (was "default_state2")
|
176
176
|
EOM
|
177
177
|
end
|
178
178
|
end
|
@@ -181,8 +181,8 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
181
181
|
let(:converge_recipe) do
|
182
182
|
<<-EOM
|
183
183
|
#{resource_name} 'blah' do
|
184
|
-
state1 '
|
185
|
-
state2 '
|
184
|
+
state1 'default_state1'
|
185
|
+
state2 'default_state2'
|
186
186
|
end
|
187
187
|
EOM
|
188
188
|
end
|
@@ -344,8 +344,8 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
344
344
|
context "and current_resource with state1=current, state2=current" do
|
345
345
|
before :each do
|
346
346
|
resource_class.load_current_value do
|
347
|
-
state1 "
|
348
|
-
state2 "
|
347
|
+
state1 "default_state1"
|
348
|
+
state2 "default_state2"
|
349
349
|
end
|
350
350
|
end
|
351
351
|
|
@@ -377,7 +377,7 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
377
377
|
expect(converged_recipe.stdout).to eq <<~EOM
|
378
378
|
* #{resource_name}[blah] action create
|
379
379
|
- update default_identity1
|
380
|
-
- set state1 to "new_state1" (was "
|
380
|
+
- set state1 to "new_state1" (was "default_state1")
|
381
381
|
EOM
|
382
382
|
end
|
383
383
|
end
|
@@ -398,9 +398,9 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
398
398
|
expect(converged_recipe.stdout).to eq <<~EOM
|
399
399
|
* #{resource_name}[blah] action create
|
400
400
|
- update default_identity1
|
401
|
-
- set state1 to "new_state1" (was "
|
401
|
+
- set state1 to "new_state1" (was "default_state1")
|
402
402
|
- update default_identity1
|
403
|
-
- set state2 to "new_state2" (was "
|
403
|
+
- set state2 to "new_state2" (was "default_state2")
|
404
404
|
EOM
|
405
405
|
end
|
406
406
|
end
|
@@ -409,7 +409,7 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
409
409
|
let(:converge_recipe) do
|
410
410
|
<<-EOM
|
411
411
|
#{resource_name} 'blah' do
|
412
|
-
state1 '
|
412
|
+
state1 'default_state1'
|
413
413
|
state2 'new_state2'
|
414
414
|
end
|
415
415
|
EOM
|
@@ -421,7 +421,7 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
421
421
|
expect(converged_recipe.stdout).to eq <<~EOM
|
422
422
|
* #{resource_name}[blah] action create
|
423
423
|
- update default_identity1
|
424
|
-
- set state2 to "new_state2" (was "
|
424
|
+
- set state2 to "new_state2" (was "default_state2")
|
425
425
|
EOM
|
426
426
|
end
|
427
427
|
end
|
@@ -430,8 +430,8 @@ describe "Resource::ActionClass#converge_if_changed" do
|
|
430
430
|
let(:converge_recipe) do
|
431
431
|
<<-EOM
|
432
432
|
#{resource_name} 'blah' do
|
433
|
-
state1 '
|
434
|
-
state2 '
|
433
|
+
state1 'default_state1'
|
434
|
+
state2 'default_state2'
|
435
435
|
end
|
436
436
|
EOM
|
437
437
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -141,6 +141,8 @@ RSpec.configure do |config|
|
|
141
141
|
config.filter_run_excluding skip_appveyor: true if ENV["APPVEYOR"]
|
142
142
|
config.filter_run_excluding appveyor_only: true unless ENV["APPVEYOR"]
|
143
143
|
|
144
|
+
config.filter_run_excluding skip_buildkite: true if ENV["BUILDKITE"]
|
145
|
+
|
144
146
|
config.filter_run_excluding windows_only: true unless windows?
|
145
147
|
config.filter_run_excluding not_supported_on_windows: true if windows?
|
146
148
|
config.filter_run_excluding not_supported_on_macos: true if mac_osx?
|
@@ -76,6 +76,24 @@ describe Chef::Formatters::Base do
|
|
76
76
|
expect(formatter.pretty_elapsed_time).to include("10 hours 10 minutes 10 seconds")
|
77
77
|
end
|
78
78
|
|
79
|
+
it "shows nothing if total is nil" do
|
80
|
+
res = Chef::Resource::RemoteFile.new("canteloupe")
|
81
|
+
formatter.resource_update_progress(res, 35, nil, 10)
|
82
|
+
expect(out.string).to eq("")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "shows nothing if total is 0" do
|
86
|
+
res = Chef::Resource::RemoteFile.new("canteloupe")
|
87
|
+
formatter.resource_update_progress(res, 35, 0, 10)
|
88
|
+
expect(out.string).to eq("")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "shows nothing if current and total are 0" do
|
92
|
+
res = Chef::Resource::RemoteFile.new("canteloupe")
|
93
|
+
formatter.resource_update_progress(res, 0, 0, 10)
|
94
|
+
expect(out.string).to eq("")
|
95
|
+
end
|
96
|
+
|
79
97
|
it "shows the percentage completion of an action" do
|
80
98
|
res = Chef::Resource::RemoteFile.new("canteloupe")
|
81
99
|
formatter.resource_update_progress(res, 35, 50, 10)
|
@@ -1839,6 +1839,20 @@ describe Chef::Knife::Bootstrap do
|
|
1839
1839
|
e
|
1840
1840
|
end
|
1841
1841
|
|
1842
|
+
let(:expected_error_password_prompt) do
|
1843
|
+
e = Train::ClientError.new
|
1844
|
+
reason = :no_ssh_password_or_key_available
|
1845
|
+
allow(e).to receive(:reason).and_return(reason)
|
1846
|
+
e
|
1847
|
+
end
|
1848
|
+
|
1849
|
+
let(:expected_error_password_prompt_winrm) do
|
1850
|
+
e = RuntimeError.new
|
1851
|
+
message = "password is a required option"
|
1852
|
+
allow(e).to receive(:message).and_return(message)
|
1853
|
+
e
|
1854
|
+
end
|
1855
|
+
|
1842
1856
|
context "and password auth was used" do
|
1843
1857
|
before do
|
1844
1858
|
allow(connection).to receive(:password_auth?).and_return true
|
@@ -1854,19 +1868,41 @@ describe Chef::Knife::Bootstrap do
|
|
1854
1868
|
before do
|
1855
1869
|
allow(connection).to receive(:password_auth?).and_return false
|
1856
1870
|
allow(connection).to receive(:user).and_return "testuser"
|
1871
|
+
allow(knife).to receive(:connection_protocol).and_return connection_protocol
|
1857
1872
|
end
|
1858
1873
|
|
1859
|
-
|
1860
|
-
|
1861
|
-
|
1862
|
-
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1874
|
+
context "when using ssh" do
|
1875
|
+
let(:connection_protocol) { "ssh" }
|
1876
|
+
|
1877
|
+
it "warns, prompts for password, then reconnects with a password-enabled configuration using the new password" do
|
1878
|
+
question_mock = double("question")
|
1879
|
+
expect(knife).to receive(:do_connect).and_raise(expected_error_password_prompt)
|
1880
|
+
expect(knife.ui).to receive(:warn).with(/Failed to auth.*/)
|
1881
|
+
expect(knife.ui).to receive(:ask).and_yield(question_mock).and_return("newpassword")
|
1882
|
+
# Ensure that we set echo off to prevent showing password on the screen
|
1883
|
+
expect(question_mock).to receive(:echo=).with false
|
1884
|
+
expect(knife).to receive(:do_connect) do |opts|
|
1885
|
+
expect(opts[:password]).to eq "newpassword"
|
1886
|
+
end
|
1887
|
+
knife.connect!
|
1888
|
+
end
|
1889
|
+
end
|
1890
|
+
|
1891
|
+
context "when using winrm" do
|
1892
|
+
let(:connection_protocol) { "winrm" }
|
1893
|
+
|
1894
|
+
it "warns, prompts for password, then reconnects with a password-enabled configuration using the new password for" do
|
1895
|
+
question_mock = double("question")
|
1896
|
+
expect(knife).to receive(:do_connect).and_raise(expected_error_password_prompt_winrm)
|
1897
|
+
expect(knife.ui).to receive(:warn).with(/Failed to auth.*/)
|
1898
|
+
expect(knife.ui).to receive(:ask).and_yield(question_mock).and_return("newpassword")
|
1899
|
+
# Ensure that we set echo off to prevent showing password on the screen
|
1900
|
+
expect(question_mock).to receive(:echo=).with false
|
1901
|
+
expect(knife).to receive(:do_connect) do |opts|
|
1902
|
+
expect(opts[:password]).to eq "newpassword"
|
1903
|
+
end
|
1904
|
+
knife.connect!
|
1868
1905
|
end
|
1869
|
-
knife.connect!
|
1870
1906
|
end
|
1871
1907
|
end
|
1872
1908
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Vivek Singh (<vivek.singh@msystechnologies.com>)
|
3
|
+
# Copyright:: Copyright 2018-2019, Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef/knife/supermarket_list"
|
20
|
+
require "spec_helper"
|
21
|
+
|
22
|
+
describe Chef::Knife::SupermarketList do
|
23
|
+
let(:knife) { described_class.new }
|
24
|
+
let(:noauth_rest) { double("no auth rest") }
|
25
|
+
let(:stdout) { StringIO.new }
|
26
|
+
let(:cookbooks_data) {
|
27
|
+
[
|
28
|
+
{ "cookbook_name" => "1password", "cookbook_maintainer" => "jtimberman", "cookbook_description" => "Installs 1password", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/1password" },
|
29
|
+
{ "cookbook_name" => "301", "cookbook_maintainer" => "markhuge", "cookbook_description" => "Installs/Configures 301", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/301" },
|
30
|
+
{ "cookbook_name" => "3cx", "cookbook_maintainer" => "obay", "cookbook_description" => "Installs/Configures 3cx", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/3cx" },
|
31
|
+
{ "cookbook_name" => "7dtd", "cookbook_maintainer" => "gregf", "cookbook_description" => "Installs/Configures the 7 Days To Die server", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/7dtd" },
|
32
|
+
{ "cookbook_name" => "7-zip", "cookbook_maintainer" => "sneal", "cookbook_description" => "Installs/Configures the 7-zip file archiver", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/7-zip" },
|
33
|
+
]
|
34
|
+
}
|
35
|
+
|
36
|
+
let(:response_text) {
|
37
|
+
{
|
38
|
+
"start" => 0,
|
39
|
+
"total" => 5,
|
40
|
+
"items" => cookbooks_data,
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
describe "run" do
|
45
|
+
before do
|
46
|
+
allow(knife.ui).to receive(:stdout).and_return(stdout)
|
47
|
+
allow(knife).to receive(:noauth_rest).and_return(noauth_rest)
|
48
|
+
expect(noauth_rest).to receive(:get).and_return(response_text)
|
49
|
+
knife.configure_chef
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should display all supermarket cookbooks" do
|
53
|
+
knife.run
|
54
|
+
cookbooks_data.each do |item|
|
55
|
+
expect(stdout.string).to match /#{item["cookbook_name"]}\s/
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "with -w or --with-uri" do
|
60
|
+
it "should display the cookbook uris" do
|
61
|
+
knife.config[:with_uri] = true
|
62
|
+
knife.run
|
63
|
+
cookbooks_data.each do |item|
|
64
|
+
expect(stdout.string).to match /#{item["cookbook_name"]}\s/
|
65
|
+
expect(stdout.string).to match /#{item["cookbook"]}\s/
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Vivek Singh (<vivek.singh@msystechnologies.com>)
|
3
|
+
# Copyright:: Copyright 2018-2019, Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef/knife/supermarket_search"
|
20
|
+
require "spec_helper"
|
21
|
+
|
22
|
+
describe Chef::Knife::SupermarketSearch do
|
23
|
+
let(:knife) { described_class.new }
|
24
|
+
let(:noauth_rest) { double("no auth rest") }
|
25
|
+
let(:stdout) { StringIO.new }
|
26
|
+
let(:cookbooks_data) {
|
27
|
+
[
|
28
|
+
{ "cookbook_name" => "mysql", "cookbook_maintainer" => "sous-chefs", "cookbook_description" => "Provides mysql_service, mysql_config, and mysql_client resources", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mysql" },
|
29
|
+
{ "cookbook_name" => "mw_mysql", "cookbook_maintainer" => "car", "cookbook_description" => "Installs/Configures mw_mysql", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mw_mysql" },
|
30
|
+
{ "cookbook_name" => "L7-mysql", "cookbook_maintainer" => "szelcsanyi", "cookbook_description" => "Installs/Configures MySQL server", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/l7-mysql" },
|
31
|
+
{ "cookbook_name" => "mysql-sys", "cookbook_maintainer" => "ovaistariq", "cookbook_description" => "Installs the mysql-sys tool. Description of the tool is available here https://github.com/MarkLeith/mysql-sys", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/mysql-sys" },
|
32
|
+
{ "cookbook_name" => "cg_mysql", "cookbook_maintainer" => "phai", "cookbook_description" => "Installs/Configures mysql with master and slave", "cookbook" => "https://supermarket.chef.io/api/v1/cookbooks/cg_mysql" },
|
33
|
+
]
|
34
|
+
}
|
35
|
+
|
36
|
+
let(:response_text) {
|
37
|
+
{
|
38
|
+
"start" => 0,
|
39
|
+
"total" => 5,
|
40
|
+
"items" => cookbooks_data,
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
let(:empty_response_text) {
|
45
|
+
{
|
46
|
+
"start" => 0,
|
47
|
+
"total" => 0,
|
48
|
+
"items" => [],
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
describe "run" do
|
53
|
+
before do
|
54
|
+
allow(knife.ui).to receive(:stdout).and_return(stdout)
|
55
|
+
allow(knife).to receive(:noauth_rest).and_return(noauth_rest)
|
56
|
+
knife.configure_chef
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when name_args is present" do
|
60
|
+
before do
|
61
|
+
expect(noauth_rest).to receive(:get).and_return(response_text)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should display cookbooks with given name value" do
|
65
|
+
knife.name_args = ["mysql"]
|
66
|
+
knife.run
|
67
|
+
cookbooks_data.each do |item|
|
68
|
+
expect(stdout.string).to match /#{item["cookbook_name"]}\s/
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when name_args is empty string" do
|
74
|
+
before do
|
75
|
+
expect(noauth_rest).to receive(:get).and_return(empty_response_text)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "display nothing with name arg empty string" do
|
79
|
+
knife.name_args = [""]
|
80
|
+
knife.run
|
81
|
+
expect(stdout.string).to eq("\n")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -1297,4 +1297,26 @@ describe Chef::Node::Attribute do
|
|
1297
1297
|
expect(@attributes["foo"]).to be nil
|
1298
1298
|
end
|
1299
1299
|
end
|
1300
|
+
|
1301
|
+
describe "to_json" do
|
1302
|
+
it "should convert to a valid json string" do
|
1303
|
+
json = @attributes["hot"].to_json
|
1304
|
+
expect { JSON.parse(json) }.not_to raise_error
|
1305
|
+
end
|
1306
|
+
|
1307
|
+
it "should convert to a json based on current state" do
|
1308
|
+
expect(@attributes["hot"].to_json).to eq("{\"day\":\"sunday\"}")
|
1309
|
+
end
|
1310
|
+
end
|
1311
|
+
|
1312
|
+
describe "to_yaml" do
|
1313
|
+
it "should convert to a valid yaml format" do
|
1314
|
+
json = @attributes["hot"].to_yaml
|
1315
|
+
expect { YAML.parse(json) }.not_to raise_error
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
it "should convert to a yaml based on current state" do
|
1319
|
+
expect(@attributes["hot"].to_yaml).to eq("---\nday: sunday\n")
|
1320
|
+
end
|
1321
|
+
end
|
1300
1322
|
end
|
@@ -19,6 +19,64 @@
|
|
19
19
|
require "spec_helper"
|
20
20
|
require "chef/node/immutable_collections"
|
21
21
|
|
22
|
+
shared_examples_for "ImmutableMash module" do |param|
|
23
|
+
let(:copy) { @immutable_mash.send(param) }
|
24
|
+
|
25
|
+
it "converts an immutable mash to a new mutable hash" do
|
26
|
+
expect(copy).to be_is_a(Hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "converts an immutable nested mash to a new mutable hash" do
|
30
|
+
expect(copy["top_level_4"]["level2"]).to be_is_a(Hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "converts an immutable nested array to a new mutable array" do
|
34
|
+
expect(copy["top_level_2"]).to be_instance_of(Array)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should create a mash with the same content" do
|
38
|
+
expect(copy).to eq(@immutable_mash)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should allow mutation" do
|
42
|
+
expect { copy["m"] = "m" }.not_to raise_error
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
shared_examples_for "ImmutableArray module" do |param|
|
47
|
+
let(:copy) { @immutable_nested_array.send(param) }
|
48
|
+
|
49
|
+
it "converts an immutable array to a new mutable array" do
|
50
|
+
expect(copy).to be_instance_of(Array)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "converts an immutable nested array to a new mutable array" do
|
54
|
+
expect(copy[1]).to be_instance_of(Array)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "converts an immutable nested mash to a new mutable hash" do
|
58
|
+
expect(copy[2]).to be_is_a(Hash)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should create an array with the same content" do
|
62
|
+
expect(copy).to eq(@immutable_nested_array)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should allow mutation" do
|
66
|
+
expect { copy << "m" }.not_to raise_error
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
shared_examples_for "Immutable#to_yaml" do
|
71
|
+
it "converts an immutable array to a new valid YAML mutable string" do
|
72
|
+
expect { YAML.parse(copy) }.not_to raise_error
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should create a YAML string with content" do
|
76
|
+
expect(copy).to eq(parsed_yaml)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
22
80
|
describe Chef::Node::ImmutableMash do
|
23
81
|
before do
|
24
82
|
@data_in = { "top" => { "second_level" => "some value" },
|
@@ -67,82 +125,17 @@ describe Chef::Node::ImmutableMash do
|
|
67
125
|
expect(@mash["test2"]).to eql("bar")
|
68
126
|
end
|
69
127
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
it "converts an immutable mash to a new mutable hash" do
|
76
|
-
expect(@copy).to be_instance_of(Hash)
|
77
|
-
end
|
78
|
-
|
79
|
-
it "converts an immutable nested mash to a new mutable hash" do
|
80
|
-
expect(@copy["top_level_4"]["level2"]).to be_instance_of(Hash)
|
81
|
-
end
|
82
|
-
|
83
|
-
it "converts an immutable nested array to a new mutable array" do
|
84
|
-
expect(@copy["top_level_2"]).to be_instance_of(Array)
|
85
|
-
end
|
86
|
-
|
87
|
-
it "should create a mash with the same content" do
|
88
|
-
expect(@copy).to eq(@immutable_mash)
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should allow mutation" do
|
92
|
-
expect { @copy["m"] = "m" }.not_to raise_error
|
128
|
+
%w{to_h to_hash dup}.each do |immutable_meth|
|
129
|
+
describe "#{immutable_meth}" do
|
130
|
+
include_examples "ImmutableMash module", description
|
93
131
|
end
|
94
132
|
end
|
95
133
|
|
96
|
-
describe "
|
97
|
-
|
98
|
-
|
99
|
-
end
|
100
|
-
|
101
|
-
it "converts an immutable mash to a new mutable hash" do
|
102
|
-
expect(@copy).to be_instance_of(Mash)
|
103
|
-
end
|
104
|
-
|
105
|
-
it "converts an immutable nested mash to a new mutable hash" do
|
106
|
-
expect(@copy["top_level_4"]["level2"]).to be_instance_of(Mash)
|
107
|
-
end
|
108
|
-
|
109
|
-
it "converts an immutable nested array to a new mutable array" do
|
110
|
-
expect(@copy["top_level_2"]).to be_instance_of(Array)
|
111
|
-
end
|
112
|
-
|
113
|
-
it "should create a mash with the same content" do
|
114
|
-
expect(@copy).to eq(@immutable_mash)
|
115
|
-
end
|
134
|
+
describe "to_yaml" do
|
135
|
+
let(:copy) { @immutable_mash.to_yaml }
|
136
|
+
let(:parsed_yaml) { "---\ntop:\n second_level: some value\ntop_level_2:\n- array\n- of\n- values\ntop_level_3:\n- hash_array: 1\n hash_array_b: 2\ntop_level_4:\n level2:\n key: value\n" }
|
116
137
|
|
117
|
-
|
118
|
-
expect { @copy["m"] = "m" }.not_to raise_error
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
describe "to_h" do
|
123
|
-
before do
|
124
|
-
@copy = @immutable_mash.to_h
|
125
|
-
end
|
126
|
-
|
127
|
-
it "converts an immutable mash to a new mutable hash" do
|
128
|
-
expect(@copy).to be_instance_of(Hash)
|
129
|
-
end
|
130
|
-
|
131
|
-
it "converts an immutable nested mash to a new mutable hash" do
|
132
|
-
expect(@copy["top_level_4"]["level2"]).to be_instance_of(Hash)
|
133
|
-
end
|
134
|
-
|
135
|
-
it "converts an immutable nested array to a new mutable array" do
|
136
|
-
expect(@copy["top_level_2"]).to be_instance_of(Array)
|
137
|
-
end
|
138
|
-
|
139
|
-
it "should create a mash with the same content" do
|
140
|
-
expect(@copy).to eq(@immutable_mash)
|
141
|
-
end
|
142
|
-
|
143
|
-
it "should allow mutation" do
|
144
|
-
expect { @copy["m"] = "m" }.not_to raise_error
|
145
|
-
end
|
138
|
+
include_examples "Immutable#to_yaml"
|
146
139
|
end
|
147
140
|
|
148
141
|
%i{
|
@@ -240,82 +233,17 @@ describe Chef::Node::ImmutableArray do
|
|
240
233
|
expect(mutable[0]).to eq(:value)
|
241
234
|
end
|
242
235
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
end
|
247
|
-
|
248
|
-
it "converts an immutable array to a new mutable array" do
|
249
|
-
expect(@copy).to be_instance_of(Array)
|
250
|
-
end
|
251
|
-
|
252
|
-
it "converts an immutable nested array to a new mutable array" do
|
253
|
-
expect(@copy[1]).to be_instance_of(Array)
|
254
|
-
end
|
255
|
-
|
256
|
-
it "converts an immutable nested mash to a new mutable hash" do
|
257
|
-
expect(@copy[2]).to be_instance_of(Hash)
|
258
|
-
end
|
259
|
-
|
260
|
-
it "should create an array with the same content" do
|
261
|
-
expect(@copy).to eq(@immutable_nested_array)
|
262
|
-
end
|
263
|
-
|
264
|
-
it "should allow mutation" do
|
265
|
-
expect { @copy << "m" }.not_to raise_error
|
236
|
+
%w{to_a to_array dup}.each do |immutable_meth|
|
237
|
+
describe "#{immutable_meth}" do
|
238
|
+
include_examples "ImmutableArray module", description
|
266
239
|
end
|
267
240
|
end
|
268
241
|
|
269
|
-
describe "
|
270
|
-
|
271
|
-
|
272
|
-
end
|
273
|
-
|
274
|
-
it "converts an immutable array to a new mutable array" do
|
275
|
-
expect(@copy).to be_instance_of(Array)
|
276
|
-
end
|
277
|
-
|
278
|
-
it "converts an immutable nested array to a new mutable array" do
|
279
|
-
expect(@copy[1]).to be_instance_of(Array)
|
280
|
-
end
|
281
|
-
|
282
|
-
it "converts an immutable nested mash to a new mutable hash" do
|
283
|
-
expect(@copy[2]).to be_instance_of(Mash)
|
284
|
-
end
|
285
|
-
|
286
|
-
it "should create an array with the same content" do
|
287
|
-
expect(@copy).to eq(@immutable_nested_array)
|
288
|
-
end
|
289
|
-
|
290
|
-
it "should allow mutation" do
|
291
|
-
expect { @copy << "m" }.not_to raise_error
|
292
|
-
end
|
293
|
-
end
|
242
|
+
describe "to_yaml" do
|
243
|
+
let(:copy) { @immutable_nested_array.to_yaml }
|
244
|
+
let(:parsed_yaml) { "---\n- level1\n- - foo\n - bar\n - baz\n - 1\n - 2\n - 3\n - \n - true\n - false\n - - el\n - 0\n - \n- m: m\n" }
|
294
245
|
|
295
|
-
|
296
|
-
before do
|
297
|
-
@copy = @immutable_nested_array.to_array
|
298
|
-
end
|
299
|
-
|
300
|
-
it "converts an immutable array to a new mutable array" do
|
301
|
-
expect(@copy).to be_instance_of(Array)
|
302
|
-
end
|
303
|
-
|
304
|
-
it "converts an immutable nested array to a new mutable array" do
|
305
|
-
expect(@copy[1]).to be_instance_of(Array)
|
306
|
-
end
|
307
|
-
|
308
|
-
it "converts an immutable nested mash to a new mutable hash" do
|
309
|
-
expect(@copy[2]).to be_instance_of(Hash)
|
310
|
-
end
|
311
|
-
|
312
|
-
it "should create an array with the same content" do
|
313
|
-
expect(@copy).to eq(@immutable_nested_array)
|
314
|
-
end
|
315
|
-
|
316
|
-
it "should allow mutation" do
|
317
|
-
expect { @copy << "m" }.not_to raise_error
|
318
|
-
end
|
246
|
+
include_examples "Immutable#to_yaml"
|
319
247
|
end
|
320
248
|
|
321
249
|
describe "#[]" do
|