knife 17.4.18 → 17.4.46
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/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/
|