knife 17.4.18 → 17.4.46
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/knife.gemspec +2 -3
- data/lib/chef/knife/client_create.rb +34 -16
- data/lib/chef/knife/cookbook_upload.rb +34 -13
- data/lib/chef/knife/version.rb +1 -1
- data/spec/integration/client_create_spec.rb +0 -1
- data/spec/unit/knife/client_create_spec.rb +64 -36
- data/spec/unit/knife/cookbook_upload_spec.rb +98 -36
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5bce1fdf8a026140f71d734c579f29ac19eeb68da7965ebc5426cdad7c00eb51
|
4
|
+
data.tar.gz: b10eafb114347dec04f3e1f0aaf0c1a9d9806ba2f76cfad8b57c1065e72bb0b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a5df15d3687dddd23e0469fb170fd2ea6325ee186378f98a334f7a1d42757195d2dc541ff9b370b624f949a0ab06de11d607b2029559788f0a1e406b0d8ac8d
|
7
|
+
data.tar.gz: 24414b3f673ae91d6c837c3b3c8740cf60746dc337c770b752fa1baf65f1773510ea9a8c72ee19e2979d70688ca1810a502afbe43092c321ae0cc1dceb8a8e69
|
data/Gemfile
CHANGED
@@ -17,10 +17,10 @@ group(:omnibus_package, :pry) do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
group(:chefstyle) do
|
20
|
-
gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "
|
20
|
+
gem "chefstyle", git: "https://github.com/chef/chefstyle.git", branch: "main"
|
21
21
|
end
|
22
22
|
|
23
|
-
gem "ohai", git: "https://github.com/chef/ohai.git", branch: "
|
23
|
+
gem "ohai", git: "https://github.com/chef/ohai.git", branch: "main"
|
24
24
|
gem "chef", path: ".."
|
25
25
|
gem "chef-utils", path: File.expand_path("../chef-utils", __dir__) if File.exist?(File.expand_path("../chef-utils", __dir__))
|
26
26
|
gem "chef-config", path: File.expand_path("../chef-config", __dir__) if File.exist?(File.expand_path("../chef-config", __dir__))
|
data/knife.gemspec
CHANGED
@@ -30,8 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.add_dependency "net-ssh-multi", "~> 1.2", ">= 1.2.1"
|
31
31
|
s.add_dependency "ed25519", "~> 1.2" # ed25519 ssh key support
|
32
32
|
s.add_dependency "bcrypt_pbkdf", "~> 1.1" # ed25519 ssh key support
|
33
|
-
|
34
|
-
# s.add_dependency "x25519" # ed25519 KEX module
|
33
|
+
s.add_dependency "x25519", ">= 1.0.9" # ed25519 KEX module. 1.0.9+ required to resolve sigill failures
|
35
34
|
s.add_dependency "highline", ">= 1.6.9", "< 3" # Used in UI to present a list, no other usage.
|
36
35
|
|
37
36
|
s.add_dependency "tty-prompt", "~> 0.21" # knife ui.ask prompt
|
@@ -52,7 +51,7 @@ Gem::Specification.new do |s|
|
|
52
51
|
|
53
52
|
s.metadata = {
|
54
53
|
"bug_tracker_uri" => "https://github.com/chef/chef/issues",
|
55
|
-
"changelog_uri" => "https://github.com/chef/chef/blob/
|
54
|
+
"changelog_uri" => "https://github.com/chef/chef/blob/main/CHANGELOG.md",
|
56
55
|
"documentation_uri" => "https://docs.chef.io/",
|
57
56
|
"homepage_uri" => "https://www.chef.io",
|
58
57
|
"mailing_list_uri" => "https://discourse.chef.io/",
|
@@ -54,6 +54,10 @@ class Chef
|
|
54
54
|
@client_field ||= Chef::ApiClientV1.new
|
55
55
|
end
|
56
56
|
|
57
|
+
def file
|
58
|
+
config[:file]
|
59
|
+
end
|
60
|
+
|
57
61
|
def create_client(client)
|
58
62
|
# should not be using save :( bad behavior
|
59
63
|
Chef::ApiClientV1.from_hash(client).save
|
@@ -81,13 +85,7 @@ class Chef
|
|
81
85
|
client.public_key File.read(File.expand_path(config[:public_key]))
|
82
86
|
end
|
83
87
|
|
84
|
-
|
85
|
-
if config[:file]
|
86
|
-
file = config[:file]
|
87
|
-
dir_name = File.dirname(file)
|
88
|
-
check_writable_or_exists(dir_name, "Directory")
|
89
|
-
check_writable_or_exists(file, "File")
|
90
|
-
end
|
88
|
+
file_is_writable!
|
91
89
|
|
92
90
|
output = edit_hash(client)
|
93
91
|
final_client = create_client(output)
|
@@ -105,15 +103,35 @@ class Chef
|
|
105
103
|
end
|
106
104
|
end
|
107
105
|
|
108
|
-
#
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
106
|
+
#
|
107
|
+
# This method is used to verify that the file and it's containing
|
108
|
+
# directory are writable. This ensures that you don't create the client
|
109
|
+
# and then lose the private key because you weren't able to write it to
|
110
|
+
# disk.
|
111
|
+
#
|
112
|
+
# @return [void]
|
113
|
+
#
|
114
|
+
def file_is_writable!
|
115
|
+
return unless file
|
116
|
+
|
117
|
+
dir = File.dirname(File.expand_path(file))
|
118
|
+
unless File.exist?(dir)
|
119
|
+
ui.fatal "Directory #{dir} does not exist. Please create and retry."
|
120
|
+
exit 1
|
121
|
+
end
|
122
|
+
|
123
|
+
unless File.directory?(dir)
|
124
|
+
ui.fatal "#{dir} exists, but is not a directory. Please update your file path (--file #{file}) or re-create #{dir} as a directory."
|
125
|
+
exit 1
|
126
|
+
end
|
127
|
+
|
128
|
+
unless File.writable?(dir)
|
129
|
+
ui.fatal "Directory #{dir} is not writable. Please check the permissions."
|
130
|
+
exit 1
|
131
|
+
end
|
132
|
+
|
133
|
+
if File.exist?(file) && !File.writable?(file)
|
134
|
+
ui.fatal "File #{file} is not writable. Please check the permissions."
|
117
135
|
exit 1
|
118
136
|
end
|
119
137
|
end
|
@@ -71,6 +71,11 @@ class Chef
|
|
71
71
|
long: "--include-dependencies",
|
72
72
|
description: "Also upload cookbook dependencies."
|
73
73
|
|
74
|
+
option :check_dependencies,
|
75
|
+
boolean: true, long: "--[no-]check-dependencies",
|
76
|
+
description: "Whether or not cookbook dependencies are verified before uploading cookbook(s) to #{ChefUtils::Dist::Server::PRODUCT}. You shouldn't disable this unless you really know what you're doing.",
|
77
|
+
default: true
|
78
|
+
|
74
79
|
def run
|
75
80
|
# Sanity check before we load anything from the server
|
76
81
|
if ! config[:all] && @name_args.empty?
|
@@ -86,11 +91,6 @@ class Chef
|
|
86
91
|
upload_failures = 0
|
87
92
|
upload_ok = 0
|
88
93
|
|
89
|
-
# Get a list of cookbooks and their versions from the server
|
90
|
-
# to check for the existence of a cookbook's dependencies.
|
91
|
-
@server_side_cookbooks = Chef::CookbookVersion.list_all_versions
|
92
|
-
justify_width = @server_side_cookbooks.map(&:size).max.to_i + 2
|
93
|
-
|
94
94
|
cookbooks = []
|
95
95
|
cookbooks_to_upload.each do |cookbook_name, cookbook|
|
96
96
|
raise Chef::Exceptions::MetadataNotFound.new(cookbook.root_paths[0], cookbook_name) unless cookbook.has_metadata_file?
|
@@ -120,7 +120,7 @@ class Chef
|
|
120
120
|
if config[:all]
|
121
121
|
if cookbooks_for_upload.any?
|
122
122
|
begin
|
123
|
-
upload(cookbooks_for_upload
|
123
|
+
upload(cookbooks_for_upload)
|
124
124
|
rescue Chef::Exceptions::CookbookFrozen
|
125
125
|
ui.warn("Not updating version constraints for some cookbooks in the environment as the cookbook is frozen.")
|
126
126
|
ui.error("Uploading of some of the cookbooks must be failed. Remove cookbook whose version is frozen from your cookbooks repo OR use --force option.")
|
@@ -133,7 +133,7 @@ class Chef
|
|
133
133
|
else
|
134
134
|
tmp_cl.each do |cookbook_name, cookbook|
|
135
135
|
|
136
|
-
upload([cookbook]
|
136
|
+
upload([cookbook])
|
137
137
|
upload_ok += 1
|
138
138
|
rescue Exceptions::CookbookNotFoundInRepo => e
|
139
139
|
upload_failures += 1
|
@@ -165,6 +165,27 @@ class Chef
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
+
def server_side_cookbooks
|
169
|
+
@server_side_cookbooks ||= Chef::CookbookVersion.list_all_versions
|
170
|
+
end
|
171
|
+
|
172
|
+
def justify_width
|
173
|
+
@justify_width ||= server_side_cookbooks.map(&:size).max.to_i + 2
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# @param cookbook [Chef::CookbookVersion]
|
178
|
+
#
|
179
|
+
def left_justify_name(cookbook)
|
180
|
+
# We only want to lookup justify width value if we're already loading
|
181
|
+
# cookbooks to check dependencies exist in Chef Infra Server.
|
182
|
+
if config[:check_dependencies] == true
|
183
|
+
cookbook.name.to_s.ljust(justify_width + 10)
|
184
|
+
else
|
185
|
+
cookbook.name.to_s.ljust(24)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
168
189
|
def cookbooks_to_upload
|
169
190
|
@cookbooks_to_upload ||=
|
170
191
|
if config[:all]
|
@@ -220,11 +241,11 @@ class Chef
|
|
220
241
|
end
|
221
242
|
end
|
222
243
|
|
223
|
-
def upload(cookbooks
|
244
|
+
def upload(cookbooks)
|
224
245
|
cookbooks.each do |cb|
|
225
|
-
ui.info("Uploading #{cb
|
246
|
+
ui.info("Uploading #{left_justify_name(cb)} [#{cb.version}]")
|
226
247
|
check_for_broken_links!(cb)
|
227
|
-
check_for_dependencies!(cb)
|
248
|
+
check_for_dependencies!(cb) if config[:check_dependencies] == true
|
228
249
|
end
|
229
250
|
Chef::CookbookUploader.new(cookbooks, force: config[:force], concurrency: config[:concurrency]).upload_cookbooks
|
230
251
|
rescue Chef::Exceptions::CookbookFrozen => e
|
@@ -265,12 +286,12 @@ class Chef
|
|
265
286
|
end
|
266
287
|
|
267
288
|
def check_server_side_cookbooks(cookbook_name, version)
|
268
|
-
if
|
289
|
+
if server_side_cookbooks[cookbook_name].nil?
|
269
290
|
false
|
270
291
|
else
|
271
|
-
versions =
|
292
|
+
versions = server_side_cookbooks[cookbook_name]["versions"].collect { |versions| versions["version"] }
|
272
293
|
Log.debug "Versions of cookbook '#{cookbook_name}' returned by the server: #{versions.join(", ")}"
|
273
|
-
|
294
|
+
server_side_cookbooks[cookbook_name]["versions"].each do |versions_hash|
|
274
295
|
if Chef::VersionConstraint.new(version).include?(versions_hash["version"])
|
275
296
|
Log.debug "Matched cookbook '#{cookbook_name}' with constraint '#{version}' to cookbook version '#{versions_hash["version"]}' on the server"
|
276
297
|
return true
|
data/lib/chef/knife/version.rb
CHANGED
@@ -50,7 +50,6 @@ describe "knife client create", :workstation do
|
|
50
50
|
|
51
51
|
it "saves the private key to a file" do
|
52
52
|
Dir.mktmpdir do |tgt|
|
53
|
-
File.open("#{tgt}/bah.pem", "w") { |pub| pub.write("test key") }
|
54
53
|
knife("client create -f #{tgt}/bah.pem bah").should_succeed stderr: out
|
55
54
|
expect(File).to exist("#{tgt}/bah.pem")
|
56
55
|
end
|
@@ -54,6 +54,19 @@ describe Chef::Knife::ClientCreate do
|
|
54
54
|
Chef::Config[:node_name] = "webmonkey.example.com"
|
55
55
|
end
|
56
56
|
|
57
|
+
let(:tmpdir) { Dir.mktmpdir }
|
58
|
+
let(:file_path) { File.join(tmpdir, "client.pem") }
|
59
|
+
let(:dir_path) { File.dirname(file_path) }
|
60
|
+
|
61
|
+
before do
|
62
|
+
allow(File).to receive(:exist?).and_call_original
|
63
|
+
allow(File).to receive(:exist?).with(file_path).and_return(false)
|
64
|
+
allow(File).to receive(:exist?).with(dir_path).and_return(true)
|
65
|
+
allow(File).to receive(:directory?).with(dir_path).and_return(true)
|
66
|
+
allow(File).to receive(:writable?).with(file_path).and_return(true)
|
67
|
+
allow(File).to receive(:writable?).with(dir_path).and_return(true)
|
68
|
+
end
|
69
|
+
|
57
70
|
describe "run" do
|
58
71
|
context "when nothing is passed" do
|
59
72
|
# from spec/support/shared/unit/knife_shared.rb
|
@@ -118,18 +131,66 @@ describe Chef::Knife::ClientCreate do
|
|
118
131
|
|
119
132
|
describe "with -f or --file" do
|
120
133
|
before do
|
134
|
+
knife.config[:file] = file_path
|
121
135
|
client.private_key "woot"
|
122
136
|
end
|
123
137
|
|
124
138
|
it "should write the private key to a file" do
|
125
|
-
file = Tempfile.new
|
126
|
-
file_path = file.path
|
127
|
-
knife.config[:file] = file_path
|
128
139
|
filehandle = double("Filehandle")
|
129
140
|
expect(filehandle).to receive(:print).with("woot")
|
130
141
|
expect(File).to receive(:open).with(file_path, "w").and_yield(filehandle)
|
131
142
|
knife.run
|
132
143
|
end
|
144
|
+
|
145
|
+
context "when the directory does not exist" do
|
146
|
+
before { allow(File).to receive(:exist?).with(dir_path).and_return(false) }
|
147
|
+
|
148
|
+
it "writes a fatal message and exits 1" do
|
149
|
+
expect(knife.ui).to receive(:fatal).with("Directory #{dir_path} does not exist. Please create and retry.")
|
150
|
+
expect { knife.run }.to raise_error(SystemExit)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when the directory is not writable" do
|
155
|
+
before { allow(File).to receive(:writable?).with(dir_path).and_return(false) }
|
156
|
+
|
157
|
+
it "writes a fatal message and exits 1" do
|
158
|
+
expect(knife.ui).to receive(:fatal).with("Directory #{dir_path} is not writable. Please check the permissions.")
|
159
|
+
expect { knife.run }.to raise_error(SystemExit)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "when the directory is a file" do
|
164
|
+
before { allow(File).to receive(:directory?).with(dir_path).and_return(false) }
|
165
|
+
|
166
|
+
it "writes a fatal message and exits 1" do
|
167
|
+
expect(knife.ui).to receive(:fatal).with("#{dir_path} exists, but is not a directory. Please update your file path (--file #{file_path}) or re-create #{dir_path} as a directory.")
|
168
|
+
expect { knife.run }.to raise_error(SystemExit)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context "when the file does not exist" do
|
173
|
+
before do
|
174
|
+
allow(File).to receive(:exist?).with(file_path).and_return(false)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "does not log a fatal message and does not raise exception" do
|
178
|
+
expect(knife.ui).not_to receive(:fatal)
|
179
|
+
expect { knife.run }.not_to raise_error
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
context "when the file exists and is not writable" do
|
184
|
+
before do
|
185
|
+
allow(File).to receive(:exist?).with(file_path).and_return(true)
|
186
|
+
allow(File).to receive(:writable?).with(file_path).and_return(false)
|
187
|
+
end
|
188
|
+
|
189
|
+
it "writes a fatal message and exits 1" do
|
190
|
+
expect(knife.ui).to receive(:fatal).with("File #{file_path} is not writable. Please check the permissions.")
|
191
|
+
expect { knife.run }.to raise_error(SystemExit)
|
192
|
+
end
|
193
|
+
end
|
133
194
|
end
|
134
195
|
|
135
196
|
describe "with -p or --public-key" do
|
@@ -166,39 +227,6 @@ describe Chef::Knife::ClientCreate do
|
|
166
227
|
expect(client.validator).to be_truthy
|
167
228
|
end
|
168
229
|
end
|
169
|
-
|
170
|
-
describe "with -f or --file when dir or file is not writable or does not exists" do
|
171
|
-
let(:dir_path) { File.expand_path(File.join(CHEF_SPEC_DATA, "knife", "temp_dir")) }
|
172
|
-
let(:file_path) { File.expand_path(File.join(dir_path, "tmp.pem")) }
|
173
|
-
|
174
|
-
it "when the directory does not exists" do
|
175
|
-
knife.config[:file] = "example/client1.pem"
|
176
|
-
expect(knife.ui).to receive(:fatal).with("Directory example does not exist.")
|
177
|
-
expect { knife.run }.to raise_error(SystemExit)
|
178
|
-
end
|
179
|
-
|
180
|
-
it "when the directory not writable" do
|
181
|
-
knife.config[:file] = file_path
|
182
|
-
File.chmod(777, dir_path)
|
183
|
-
expect(knife.ui).to receive(:fatal).with("Directory #{dir_path} is not writable. Check permissions.")
|
184
|
-
expect { knife.run }.to raise_error(SystemExit)
|
185
|
-
end
|
186
|
-
|
187
|
-
it "when the file does not exists" do
|
188
|
-
path = "#{dir_path}/client1.pem"
|
189
|
-
knife.config[:file] = path
|
190
|
-
File.chmod(0755, dir_path)
|
191
|
-
expect(knife.ui).to receive(:fatal).with("File #{path} does not exist.")
|
192
|
-
expect { knife.run }.to raise_error(SystemExit)
|
193
|
-
end
|
194
|
-
|
195
|
-
it "when the file is not writable" do
|
196
|
-
knife.config[:file] = file_path
|
197
|
-
File.chmod(777, file_path)
|
198
|
-
expect(knife.ui).to receive(:fatal).with("File #{file_path} is not writable. Check permissions.")
|
199
|
-
expect { knife.run }.to raise_error(SystemExit)
|
200
|
-
end
|
201
|
-
end
|
202
230
|
end
|
203
231
|
end
|
204
232
|
end
|
@@ -60,11 +60,12 @@ describe Chef::Knife::CookbookUpload do
|
|
60
60
|
before(:each) do
|
61
61
|
allow(Chef::CookbookLoader).to receive(:new).and_return(cookbook_loader)
|
62
62
|
allow(Chef::CookbookLoader).to receive(:copy_to_tmp_dir_from_array).and_yield(cookbook_loader)
|
63
|
+
allow(Chef::CookbookVersion).to receive(:list).and_return({})
|
64
|
+
allow(Chef::CookbookVersion).to receive(:list_all_versions).and_return({})
|
63
65
|
end
|
64
66
|
|
65
67
|
describe "with --concurrency" do
|
66
68
|
it "should upload cookbooks with predefined concurrency" do
|
67
|
-
allow(Chef::CookbookVersion).to receive(:list_all_versions).and_return({})
|
68
69
|
knife.config[:concurrency] = 3
|
69
70
|
test_cookbook = Chef::CookbookVersion.new("test_cookbook", "/tmp/blah")
|
70
71
|
allow(cookbook_loader).to receive(:each).and_yield("test_cookbook", test_cookbook)
|
@@ -79,7 +80,6 @@ describe Chef::Knife::CookbookUpload do
|
|
79
80
|
describe "run" do
|
80
81
|
before(:each) do
|
81
82
|
allow(Chef::CookbookUploader).to receive_messages(new: cookbook_uploader)
|
82
|
-
allow(Chef::CookbookVersion).to receive(:list_all_versions).and_return({})
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should print usage and exit when a cookbook name is not provided" do
|
@@ -214,48 +214,110 @@ describe Chef::Knife::CookbookUpload do
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
-
|
218
|
-
|
217
|
+
context "when chef_dependencies config is disabled" do
|
218
|
+
before do
|
219
|
+
knife.config[:check_dependencies] = false
|
220
|
+
end
|
219
221
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
222
|
+
describe "when specifying a cookbook name with missing dependencies" do
|
223
|
+
let(:cookbook_dependency) { Chef::CookbookVersion.new("dependency", "/tmp/blah") }
|
224
|
+
|
225
|
+
before(:each) do
|
226
|
+
cookbook.metadata.depends("dependency")
|
227
|
+
allow(cookbook_loader).to receive(:[]) do |ckbk|
|
228
|
+
{ "test_cookbook" => cookbook,
|
229
|
+
"dependency" => cookbook_dependency }[ckbk]
|
230
|
+
end
|
231
|
+
allow(knife).to receive(:cookbook_names).and_return(%w{cookbook_dependency test_cookbook})
|
232
|
+
@stdout, @stderr, @stdin = StringIO.new, StringIO.new, StringIO.new
|
233
|
+
knife.ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {})
|
225
234
|
end
|
226
|
-
allow(knife).to receive(:cookbook_names).and_return(%w{cookbook_dependency test_cookbook})
|
227
|
-
@stdout, @stderr, @stdin = StringIO.new, StringIO.new, StringIO.new
|
228
|
-
knife.ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {})
|
229
|
-
end
|
230
235
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
236
|
+
it "should not fetch all cookbooks from Chef Infra Server" do
|
237
|
+
expect(Chef::CookbookVersion).not_to receive(:list_all_versions)
|
238
|
+
knife.run
|
239
|
+
end
|
240
|
+
|
241
|
+
it "should upload the cookbook" do
|
242
|
+
expect(cookbook_loader).to receive(:[]).once.with("test_cookbook")
|
243
|
+
expect(cookbook_uploader).to receive(:upload_cookbooks)
|
244
|
+
knife.run
|
245
|
+
end
|
246
|
+
|
247
|
+
it "should not output a message for a single missing dependency" do
|
248
|
+
knife.run
|
249
|
+
expect(@stderr.string).not_to include("Cookbook test_cookbook depends on cookbooks which are not currently")
|
250
|
+
expect(@stderr.string).not_to include("being uploaded and cannot be found on the server.")
|
251
|
+
expect(@stderr.string).not_to include("The missing cookbook(s) are: 'dependency' version '>= 0.0.0'")
|
252
|
+
end
|
253
|
+
|
254
|
+
it "should not output a message for a multiple missing dependencies which are concatenated" do
|
255
|
+
cookbook_dependency2 = Chef::CookbookVersion.new("dependency2")
|
256
|
+
cookbook.metadata.depends("dependency2")
|
257
|
+
allow(cookbook_loader).to receive(:[]) do |ckbk|
|
258
|
+
{ "test_cookbook" => cookbook,
|
259
|
+
"dependency" => cookbook_dependency,
|
260
|
+
"dependency2" => cookbook_dependency2 }[ckbk]
|
261
|
+
end
|
262
|
+
allow(knife).to receive(:cookbook_names).and_return(%w{dependency dependency2 test_cookbook})
|
263
|
+
knife.run
|
264
|
+
expect(@stderr.string).not_to include("Cookbook test_cookbook depends on cookbooks which are not currently")
|
265
|
+
expect(@stderr.string).not_to include("being uploaded and cannot be found on the server.")
|
266
|
+
expect(@stderr.string).not_to include("The missing cookbook(s) are:")
|
267
|
+
expect(@stderr.string).not_to include("'dependency' version '>= 0.0.0'")
|
268
|
+
expect(@stderr.string).not_to include("'dependency2' version '>= 0.0.0'")
|
269
|
+
end
|
235
270
|
end
|
271
|
+
end
|
236
272
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
expect(@stderr.string).to include("being uploaded and cannot be found on the server.")
|
241
|
-
expect(@stderr.string).to include("The missing cookbook(s) are: 'dependency' version '>= 0.0.0'")
|
273
|
+
context "when chef_dependencies config is enabled" do
|
274
|
+
before do
|
275
|
+
knife.config[:check_dependencies] = true
|
242
276
|
end
|
243
277
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
"
|
278
|
+
describe "when specifying a cookbook name with missing dependencies" do
|
279
|
+
let(:cookbook_dependency) { Chef::CookbookVersion.new("dependency", "/tmp/blah") }
|
280
|
+
|
281
|
+
before(:each) do
|
282
|
+
cookbook.metadata.depends("dependency")
|
283
|
+
allow(cookbook_loader).to receive(:[]) do |ckbk|
|
284
|
+
{ "test_cookbook" => cookbook,
|
285
|
+
"dependency" => cookbook_dependency }[ckbk]
|
286
|
+
end
|
287
|
+
allow(knife).to receive(:cookbook_names).and_return(%w{cookbook_dependency test_cookbook})
|
288
|
+
@stdout, @stderr, @stdin = StringIO.new, StringIO.new, StringIO.new
|
289
|
+
knife.ui = Chef::Knife::UI.new(@stdout, @stderr, @stdin, {})
|
290
|
+
end
|
291
|
+
|
292
|
+
it "should exit and not upload the cookbook" do
|
293
|
+
expect(cookbook_loader).to receive(:[]).once.with("test_cookbook")
|
294
|
+
expect(cookbook_uploader).not_to receive(:upload_cookbooks)
|
295
|
+
expect { knife.run }.to raise_error(SystemExit)
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should output a message for a single missing dependency" do
|
299
|
+
expect { knife.run }.to raise_error(SystemExit)
|
300
|
+
expect(@stderr.string).to include("Cookbook test_cookbook depends on cookbooks which are not currently")
|
301
|
+
expect(@stderr.string).to include("being uploaded and cannot be found on the server.")
|
302
|
+
expect(@stderr.string).to include("The missing cookbook(s) are: 'dependency' version '>= 0.0.0'")
|
303
|
+
end
|
304
|
+
|
305
|
+
it "should output a message for a multiple missing dependencies which are concatenated" do
|
306
|
+
cookbook_dependency2 = Chef::CookbookVersion.new("dependency2")
|
307
|
+
cookbook.metadata.depends("dependency2")
|
308
|
+
allow(cookbook_loader).to receive(:[]) do |ckbk|
|
309
|
+
{ "test_cookbook" => cookbook,
|
310
|
+
"dependency" => cookbook_dependency,
|
311
|
+
"dependency2" => cookbook_dependency2 }[ckbk]
|
312
|
+
end
|
313
|
+
allow(knife).to receive(:cookbook_names).and_return(%w{dependency dependency2 test_cookbook})
|
314
|
+
expect { knife.run }.to raise_error(SystemExit)
|
315
|
+
expect(@stderr.string).to include("Cookbook test_cookbook depends on cookbooks which are not currently")
|
316
|
+
expect(@stderr.string).to include("being uploaded and cannot be found on the server.")
|
317
|
+
expect(@stderr.string).to include("The missing cookbook(s) are:")
|
318
|
+
expect(@stderr.string).to include("'dependency' version '>= 0.0.0'")
|
319
|
+
expect(@stderr.string).to include("'dependency2' version '>= 0.0.0'")
|
251
320
|
end
|
252
|
-
allow(knife).to receive(:cookbook_names).and_return(%w{dependency dependency2 test_cookbook})
|
253
|
-
expect { knife.run }.to raise_error(SystemExit)
|
254
|
-
expect(@stderr.string).to include("Cookbook test_cookbook depends on cookbooks which are not currently")
|
255
|
-
expect(@stderr.string).to include("being uploaded and cannot be found on the server.")
|
256
|
-
expect(@stderr.string).to include("The missing cookbook(s) are:")
|
257
|
-
expect(@stderr.string).to include("'dependency' version '>= 0.0.0'")
|
258
|
-
expect(@stderr.string).to include("'dependency2' version '>= 0.0.0'")
|
259
321
|
end
|
260
322
|
end
|
261
323
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: knife
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 17.4.
|
4
|
+
version: 17.4.46
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Jacob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-config
|
@@ -256,6 +256,20 @@ dependencies:
|
|
256
256
|
- - "~>"
|
257
257
|
- !ruby/object:Gem::Version
|
258
258
|
version: '1.1'
|
259
|
+
- !ruby/object:Gem::Dependency
|
260
|
+
name: x25519
|
261
|
+
requirement: !ruby/object:Gem::Requirement
|
262
|
+
requirements:
|
263
|
+
- - ">="
|
264
|
+
- !ruby/object:Gem::Version
|
265
|
+
version: 1.0.9
|
266
|
+
type: :runtime
|
267
|
+
prerelease: false
|
268
|
+
version_requirements: !ruby/object:Gem::Requirement
|
269
|
+
requirements:
|
270
|
+
- - ">="
|
271
|
+
- !ruby/object:Gem::Version
|
272
|
+
version: 1.0.9
|
259
273
|
- !ruby/object:Gem::Dependency
|
260
274
|
name: highline
|
261
275
|
requirement: !ruby/object:Gem::Requirement
|
@@ -1130,7 +1144,7 @@ licenses:
|
|
1130
1144
|
- Apache-2.0
|
1131
1145
|
metadata:
|
1132
1146
|
bug_tracker_uri: https://github.com/chef/chef/issues
|
1133
|
-
changelog_uri: https://github.com/chef/chef/blob/
|
1147
|
+
changelog_uri: https://github.com/chef/chef/blob/main/CHANGELOG.md
|
1134
1148
|
documentation_uri: https://docs.chef.io/
|
1135
1149
|
homepage_uri: https://www.chef.io
|
1136
1150
|
mailing_list_uri: https://discourse.chef.io/
|