knife 18.6.13 → 18.8.13

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e494361153bfaa991e49f354d0c38aa08b7c34fe4168cd26684b04172f4fb8cf
4
- data.tar.gz: 6dedb2d0c6c50b3d0527eb240006b0daeafedcda9e1de2f036961555ae75ea22
3
+ metadata.gz: 947a92dbe3f969e49b8a064a00d3f48e9e2ea21668ac06a7ec30516ed152084c
4
+ data.tar.gz: 94ce940ff4591d74d0f4ac11a6d94d05f0865ae3173e1a1e88359395cddd534a
5
5
  SHA512:
6
- metadata.gz: 7ebbe1f402396739175969bf45e3c7008cb331f3baaa6baadf8086586a4890f73faf9a6a09a8edb4461f9e9ed381376fbef560789deaeadb7f67e2dcb187ef57
7
- data.tar.gz: ba70d328f4f95a93dc291946cab804e09c5507e04099c745a3f6e998a70ee5cd6b94cc141d57fa5d9821008af041a6023e7104bf0131fca15bf16dee96112790
6
+ metadata.gz: fedb26a1a3e59e4bd36a3aa48960f2aa3b1552e9b080bf8d55a4410afb1b6fb67f9232b98f2215099e338e3e63a11bc79e3b9d5ad03475b88b0b45590a436f93
7
+ data.tar.gz: 2fd51a2cec9d9b39bd86008a49b2bd52db896f177400661a4213f2c11778b33c481c8c52f4f8f70161cdcfa19619736e04e4e6e9673450de3f25bbcf229c814a
data/knife.gemspec CHANGED
@@ -15,12 +15,12 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.required_ruby_version = ">= 3.1.0"
17
17
 
18
- s.add_dependency "chef-config", "~> 18.6"
19
- s.add_dependency "chef-utils", "~> 18.6"
20
- s.add_dependency "chef", "~> 18.6"
21
- s.add_dependency "chef-bin", "~> 18.6"
18
+ s.add_dependency "chef-config", "~> 18.0"
19
+ s.add_dependency "chef-utils", "~> 18.0"
20
+ s.add_dependency "chef", "~> 18.0"
21
+ s.add_dependency "chef-bin", "~> 18.0"
22
22
  s.add_dependency "train-core", "~> 3.10" # 3.2.28 fixes sudo prompts. See https://github.com/chef/chef/pull/9635
23
- s.add_dependency "train-winrm", ">= 0.2.5"
23
+ s.add_dependency "train-winrm", "~> 0.2.17"
24
24
  s.add_dependency "license-acceptance", ">= 1.0.5", "< 3"
25
25
  s.add_dependency "mixlib-cli", ">= 2.1.1", "< 3.0"
26
26
  s.add_dependency "mixlib-archive", ">= 0.4", "< 2.0"
@@ -47,6 +47,8 @@ Gem::Specification.new do |s|
47
47
 
48
48
  s.add_dependency "chef-licensing", "~> 1.0"
49
49
 
50
+ s.add_dependency "chef-zero", "~> 15.0.21" # for knife zero
51
+
50
52
  s.bindir = "bin"
51
53
  s.executables = %w{ knife }
52
54
 
@@ -126,7 +126,7 @@ class Chef
126
126
  when nil
127
127
  []
128
128
  when String
129
- run_list.split(/\s*,\s*/)
129
+ run_list.split(",").map(&:strip)
130
130
  when Array
131
131
  run_list
132
132
  end
@@ -456,6 +456,10 @@ class Chef
456
456
  end
457
457
  end
458
458
 
459
+ # This method was renamed to check_eula_license to better reflect its purpose.
460
+ # Some of the knife plugins may still be using the old name, so we keep it for backward compatibility.
461
+ alias_method :check_license, :check_eula_license
462
+
459
463
  # The default bootstrap template to use to bootstrap a server.
460
464
  # This is a public API hook which knife plugins use or inherit and override.
461
465
  #
@@ -547,7 +551,7 @@ class Chef
547
551
  require "erubis" unless defined?(Erubis)
548
552
  @config[:first_boot_attributes] = first_boot_attributes
549
553
  template_file = find_template
550
- template = IO.read(template_file).chomp
554
+ template = File.read(template_file).chomp
551
555
  Erubis::Eruby.new(template).evaluate(bootstrap_context)
552
556
  end
553
557
 
@@ -1199,10 +1203,13 @@ class Chef
1199
1203
  config[:license_url] = license.install_sh_url
1200
1204
  config[:license_id] = license.license_key
1201
1205
  config[:license_type] = license.license_type
1206
+ config[:omnitruck_url] = license.omnitruck_url
1202
1207
  end
1203
1208
 
1204
1209
  def warn_license_usage
1205
- return if config[:license_type].present?
1210
+ # remove the dependency on .present? from activesupport since this is the one usage
1211
+ license_type = config[:license_type]
1212
+ return unless license_type.nil? || (license_type.respond_to?(:empty?) && license_type.empty?)
1206
1213
 
1207
1214
  ui.warn(<<~MSG
1208
1215
 
@@ -51,7 +51,7 @@ class Chef
51
51
  else
52
52
  # Ensure the .chef/ folder exists.
53
53
  FileUtils.mkdir_p(File.dirname(context_file))
54
- IO.write(context_file, "#{profile}\n")
54
+ File.write(context_file, "#{profile}\n")
55
55
  ui.msg("Set default profile to #{profile}")
56
56
  end
57
57
  end
@@ -39,7 +39,7 @@ class Chef
39
39
  end
40
40
  ui.info("Writing validation.pem")
41
41
  File.open(File.join(@config_dir, "validation.pem"), "w") do |validation|
42
- validation.puts(IO.read(Chef::Config[:validation_key]))
42
+ validation.puts(File.read(Chef::Config[:validation_key]))
43
43
  end
44
44
  end
45
45
 
@@ -50,7 +50,7 @@ class Chef
50
50
  def validation_key
51
51
  if chef_config[:validation_key] &&
52
52
  File.exist?(File.expand_path(chef_config[:validation_key]))
53
- IO.read(File.expand_path(chef_config[:validation_key]))
53
+ File.read(File.expand_path(chef_config[:validation_key]))
54
54
  else
55
55
  false
56
56
  end
@@ -242,7 +242,7 @@ class Chef
242
242
  if chef_config[:trusted_certs_dir]
243
243
  Dir.glob(File.join(ChefConfig::PathHelper.escape_glob_dir(chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
244
244
  content << "cat > /etc/chef/trusted_certs/#{File.basename(cert)} <<'EOP'\n" +
245
- IO.read(File.expand_path(cert)) + "\nEOP\n"
245
+ File.read(File.expand_path(cert)) + "\nEOP\n"
246
246
  end
247
247
  end
248
248
  content
@@ -102,7 +102,7 @@ class Chef
102
102
  def merge_updates_from(cookbook_name, version)
103
103
  branch = "chef-vendor-#{cookbook_name}"
104
104
  Dir.chdir(repo_path) do
105
- if system("git merge #{branch}")
105
+ if system("git", "merge", branch)
106
106
  ui.info("Cookbook #{cookbook_name} version #{version} successfully installed")
107
107
  else
108
108
  ui.error("You have merge conflicts - please resolve manually")
@@ -87,7 +87,7 @@ class Chef
87
87
  def object_from_file(filename)
88
88
  case filename
89
89
  when /\.(js|json)$/
90
- r = FFI_Yajl::Parser.parse(IO.read(filename))
90
+ r = FFI_Yajl::Parser.parse(File.read(filename))
91
91
 
92
92
  # Chef::DataBagItem doesn't work well with the json_create method
93
93
  if @klass == Chef::DataBagItem
@@ -236,7 +236,7 @@ class Chef
236
236
  tf.close
237
237
  raise "Please set EDITOR environment variable. See https://docs.chef.io/workstation/knife_setup/#setting-your-text-editor for details." unless system("#{config[:editor]} #{tf.path}")
238
238
 
239
- output = IO.read(tf.path)
239
+ output = File.read(tf.path)
240
240
  end
241
241
  end
242
242
 
@@ -44,7 +44,7 @@ class Chef
44
44
 
45
45
  def validation_key
46
46
  if File.exist?(File.expand_path(chef_config[:validation_key]))
47
- IO.read(File.expand_path(chef_config[:validation_key]))
47
+ File.read(File.expand_path(chef_config[:validation_key]))
48
48
  else
49
49
  false
50
50
  end
@@ -330,16 +330,14 @@ class Chef
330
330
  # Build a URL that will redirect to the correct Chef Infra msi download.
331
331
  def msi_url(machine_os = nil, machine_arch = nil, download_context = nil)
332
332
  if config[:msi_url].nil? || config[:msi_url].empty?
333
- url = if config[:license_url]
334
- format(config[:license_url], config[:channel]) + "/chef/download?p=windows"
333
+ url = if config[:license_id] && !config[:omnitruck_url].empty?
334
+ format(config[:omnitruck_url], config[:channel] + "/chef/download") + "&p=windows"
335
335
  else
336
- "https://omnitruck.chef.io/chef/download?p=windows"
336
+ "https://omnitruck.chef.io/chef/download?p=windows&channel=#{config[:channel]}"
337
337
  end
338
338
  url += "&pv=#{machine_os}" unless machine_os.nil?
339
339
  url += "&m=#{machine_arch}" unless machine_arch.nil?
340
340
  url += "&DownloadContext=#{download_context}" unless download_context.nil?
341
- url += "&channel=#{config[:channel]}" if config[:license_url].blank?
342
- url += "&license_id=#{config[:license_id]}" unless config[:license_id].blank?
343
341
  url += "&v=#{version_to_install}"
344
342
  else
345
343
  config[:msi_url]
@@ -370,7 +368,7 @@ class Chef
370
368
  if chef_config[:trusted_certs_dir]
371
369
  Dir.glob(File.join(ChefConfig::PathHelper.escape_glob_dir(chef_config[:trusted_certs_dir]), "*.{crt,pem}")).each do |cert|
372
370
  content << "> #{bootstrap_directory}/trusted_certs/#{File.basename(cert)} (\n" +
373
- escape_and_echo(IO.read(File.expand_path(cert))) + "\n)\n"
371
+ escape_and_echo(File.read(File.expand_path(cert))) + "\n)\n"
374
372
  end
375
373
  end
376
374
  content
@@ -388,7 +386,7 @@ class Chef
388
386
  content << "mkdir #{file_on_node}\n"
389
387
  else
390
388
  content << "> #{file_on_node} (\n" +
391
- escape_and_echo(IO.read(File.expand_path(f))) + "\n)\n"
389
+ escape_and_echo(File.read(File.expand_path(f))) + "\n)\n"
392
390
  end
393
391
  end
394
392
  end
@@ -77,7 +77,7 @@ class Chef
77
77
  raise "Please set EDITOR environment variable. See https://docs.chef.io/workstation/knife_setup/#setting-your-text-editor for details."
78
78
  end
79
79
 
80
- result_text = IO.read(file.path)
80
+ result_text = File.read(file.path)
81
81
 
82
82
  return result_text if result_text != text
83
83
  end
@@ -57,7 +57,7 @@ class Chef::Knife::Exec < Chef::Knife
57
57
  elsif !scripts.empty?
58
58
  scripts.each do |script|
59
59
  file = find_script(script)
60
- context.instance_eval(IO.read(file), file, 0)
60
+ context.instance_eval(File.read(file), file, 0)
61
61
  end
62
62
  else
63
63
  puts "An interactive shell is opened"
@@ -86,7 +86,7 @@ class Chef
86
86
  path = name_args[0]
87
87
  data = false
88
88
  if config[:input]
89
- data = IO.read(config[:input])
89
+ data = File.read(config[:input])
90
90
  end
91
91
  begin
92
92
  method = config[:method].to_sym
@@ -267,7 +267,7 @@ class Chef
267
267
 
268
268
  def check_X509_certificate(cert_file)
269
269
  store = OpenSSL::X509::Store.new
270
- cert = OpenSSL::X509::Certificate.new(IO.read(File.expand_path(cert_file)))
270
+ cert = OpenSSL::X509::Certificate.new(File.read(File.expand_path(cert_file)))
271
271
  begin
272
272
  store.add_cert(cert)
273
273
  # test if the store can verify the cert we just added
@@ -69,7 +69,7 @@ class Chef
69
69
  # return updated user
70
70
  def get_updated_user(original_user)
71
71
  if config[:input]
72
- edited_user = JSON.parse(IO.read(config[:input]))
72
+ edited_user = JSON.parse(File.read(config[:input]))
73
73
  elsif config[:filename]
74
74
  file = config[:filename]
75
75
  unless File.exist?(file) ? File.writable?(file) : File.writable?(File.dirname(file))
@@ -83,7 +83,7 @@ class Chef
83
83
  f.close
84
84
  raise "Please set EDITOR environment variable. See https://docs.chef.io/workstation/knife_setup/#setting-your-text-editor for details." unless system("#{config[:editor]} #{f.path}")
85
85
 
86
- edited_user = JSON.parse(IO.read(f.path))
86
+ edited_user = JSON.parse(File.read(f.path))
87
87
  end
88
88
  end
89
89
  else
@@ -17,7 +17,7 @@
17
17
  class Chef
18
18
  class Knife
19
19
  KNIFE_ROOT = File.expand_path("../..", __dir__)
20
- VERSION = "18.6.13".freeze
20
+ VERSION = "18.8.13".freeze
21
21
  end
22
22
  end
23
23
 
@@ -238,7 +238,7 @@ class Chef
238
238
  # Check if the output is different
239
239
  tempfiles.each_pair do |tempfile, file|
240
240
  # Read the new output
241
- new_value = IO.binread(tempfile.path)
241
+ new_value = File.binread(tempfile.path)
242
242
 
243
243
  # Upload the output if different
244
244
  if config[:force] || new_value != file[:value]
@@ -48,7 +48,7 @@ class Chef::Knife::YamlConvert < Chef::Knife
48
48
  ui.fatal!("Output Ruby file '#{ruby_file}' already exists")
49
49
  end
50
50
 
51
- yaml_contents = IO.read(yaml_file)
51
+ yaml_contents = File.read(yaml_file)
52
52
 
53
53
  # YAML can contain multiple documents (--- is the separator), let's not support that.
54
54
  if ::YAML.load_stream(yaml_contents).length > 1
@@ -1,3 +1,20 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
1
18
  require_relative "licensing_config"
2
19
 
3
20
  class Chef
@@ -19,9 +36,11 @@ class Chef
19
36
  end
20
37
 
21
38
  def omnitruck_url
22
- url = OMNITRUCK_URLS[license_type] || LEGACY_OMNITRUCK_URL
39
+ url = OMNITRUCK_URLS[license_type]
40
+ is_legacy = url.nil?
41
+ url ||= LEGACY_OMNITRUCK_URL
23
42
 
24
- "#{url}/%s#{license_key ? "?license_id=#{license_key}" : ""}"
43
+ "#{url}/%s#{is_legacy ? "" : "?license_id=#{license_key}"}"
25
44
  end
26
45
 
27
46
  def install_sh_url
@@ -52,6 +52,7 @@ describe Chef::Knife::CookbookDelete do
52
52
 
53
53
  it "logs an error and exits" do
54
54
  expect { knife.run }.to raise_error(SystemExit)
55
+
55
56
  expect(knife_stderr.string).to match(/Cannot find a cookbook named no-such-cookbook to delete/)
56
57
  end
57
58
 
data/spec/tiny_server.rb CHANGED
@@ -19,6 +19,7 @@
19
19
  require "webrick"
20
20
  require "webrick/https"
21
21
  require "rack"
22
+ require "rackup"
22
23
  require "singleton"
23
24
  require "open-uri"
24
25
  require "chef/config"
@@ -91,7 +92,7 @@ module TinyServer
91
92
 
92
93
  def create_server(**extra_options)
93
94
  server = WEBrick::HTTPServer.new(**options, **extra_options)
94
- server.mount("/", Rack::Handler::WEBrick, API.instance)
95
+ server.mount("/", Rackup::Handler::WEBrick, API.instance)
95
96
  server
96
97
  end
97
98
  end
@@ -172,7 +173,9 @@ module TinyServer
172
173
 
173
174
  def initialize(response_code = 200, data = nil, headers = nil, &block)
174
175
  @response_code, @data = response_code, data
175
- @response_headers = headers ? HEADERS.merge(headers) : HEADERS
176
+ # .merge creates a new hash, headers is sometimes passed as nil, @response_headers gets mutated somewhere
177
+ # in processing
178
+ @response_headers = HEADERS.merge(headers || {})
176
179
  @block = block_given? ? block : nil
177
180
  end
178
181
 
@@ -75,6 +75,29 @@ describe Chef::Knife::Bootstrap do
75
75
  expect(Chef::Config[:chef_license]).to eq("accept-no-persist")
76
76
  end
77
77
  end
78
+
79
+ describe "alias" do
80
+ before do
81
+ expect(acceptor).to receive(:license_required?).and_return(false)
82
+ end
83
+
84
+ it "should be aliased to check_license" do
85
+ expect(knife).to respond_to(:check_license)
86
+ expect(knife).to respond_to(:check_eula_license)
87
+
88
+ knife.check_license
89
+ end
90
+
91
+ it "should logs check_eula_license using check_license" do
92
+ expect(Chef::Log).to receive(:debug).with("Checking if we need to accept Chef license to bootstrap node")
93
+ knife.check_license
94
+ end
95
+
96
+ it "should logs the same with check_eula_license" do
97
+ expect(Chef::Log).to receive(:debug).with("Checking if we need to accept Chef license to bootstrap node")
98
+ knife.check_eula_license
99
+ end
100
+ end
78
101
  end
79
102
 
80
103
  context "#bootstrap_template" do
@@ -368,7 +391,7 @@ describe Chef::Knife::Bootstrap do
368
391
  allow(::File).to receive(:read).and_return('{ "foo" : "bar" }')
369
392
  knife.parse_options(["--hint", "openstack=hints/openstack.json"])
370
393
  knife.merge_configs
371
- expect(knife.render_template).to match(/\{\"foo\":\"bar\"\}/)
394
+ expect(knife.render_template).to match(/\{ \"foo\" : \"bar\"\ }/)
372
395
  end
373
396
  end
374
397
 
@@ -209,7 +209,7 @@ describe Chef::Knife::Core::WindowsBootstrapContext do
209
209
  end
210
210
 
211
211
  it "returns a chef.io msi url with provided url parameters substituted" do
212
- reference_url = "https://omnitruck.chef.io/chef/download?p=windows&pv=machine&m=arch&DownloadContext=ctx&channel=stable&v=something"
212
+ reference_url = "https://omnitruck.chef.io/chef/download?p=windows&channel=stable&pv=machine&m=arch&DownloadContext=ctx&v=something"
213
213
  expect(bootstrap_context.msi_url("machine", "arch", "ctx")).to eq(reference_url)
214
214
  end
215
215
 
@@ -234,5 +234,49 @@ describe Chef::Knife::Core::WindowsBootstrapContext do
234
234
  expect(bootstrap_context.msi_url("machine", "arch", "ctx")).to eq(custom_url)
235
235
  end
236
236
  end
237
+
238
+ context "with licensing changes" do
239
+ let(:config) { { channel: "stable", bootstrap_version: "latest" } }
240
+
241
+ it "should return the old omnitruck api in case license not present" do
242
+ nil_license_obj = Chef::Utils::LicensingHandler.new(nil, nil)
243
+ expect(Chef::Utils::LicensingHandler).to receive(:validate!).and_return(nil_license_obj)
244
+ b = Chef::Knife::Bootstrap.new([])
245
+ b.send(:fetch_license)
246
+ config.merge!(b.config)
247
+
248
+ expect(bootstrap_context.msi_url).to eq("https://omnitruck.chef.io/chef/download?p=windows&channel=stable&v=latest")
249
+ end
250
+
251
+ it "should return the correct msi_url for trial license" do
252
+ license_obj_trial = Chef::Utils::LicensingHandler.new("key-trial-123", "trial")
253
+ expect(Chef::Utils::LicensingHandler).to receive(:validate!).and_return(license_obj_trial)
254
+
255
+ b = Chef::Knife::Bootstrap.new([])
256
+ b.send(:fetch_license)
257
+ config.merge!(b.config)
258
+ expect(bootstrap_context.msi_url).to eq("https://chefdownload-trial.chef.io/stable/chef/download?license_id=key-trial-123&p=windows&v=latest")
259
+ end
260
+
261
+ it "should return the correct msi_url for commercial license" do
262
+ license_obj_commercial = Chef::Utils::LicensingHandler.new("key-commercial-123", "commercial")
263
+ expect(Chef::Utils::LicensingHandler).to receive(:validate!).and_return(license_obj_commercial)
264
+
265
+ b = Chef::Knife::Bootstrap.new([])
266
+ b.send(:fetch_license)
267
+ config.merge!(b.config)
268
+ expect(bootstrap_context.msi_url).to eq("https://chefdownload-commerical.chef.io/stable/chef/download?license_id=key-commercial-123&p=windows&v=latest")
269
+ end
270
+
271
+ it "should return the omnitruck url in case of airgapped env" do
272
+ # In case of connection issues with the licensing service, the library will raise this exception
273
+ expect(ChefLicensing::LicenseKeyFetcher).to receive(:fetch).and_raise(ChefLicensing::RestfulClientConnectionError)
274
+
275
+ b = Chef::Knife::Bootstrap.new([])
276
+ b.send(:fetch_license)
277
+ config.merge!(b.config)
278
+ expect(bootstrap_context.msi_url).to eq("https://omnitruck.chef.io/chef/download?p=windows&channel=stable&v=latest")
279
+ end
280
+ end
237
281
  end
238
282
  end
@@ -50,6 +50,11 @@ describe Chef::Knife::License do
50
50
  c.output = STDOUT
51
51
  end
52
52
 
53
+ # Stubbing the fetch_and_persist method to simulate a failure
54
+ expect(ChefLicensing).to receive(:fetch_and_persist).and_raise(
55
+ ChefLicensing::LicenseKeyFetcher::LicenseKeyNotFetchedError.new("Unable to obtain a License Key.")
56
+ )
57
+
53
58
  expect { knife.run }.to raise_error(ChefLicensing::LicenseKeyFetcher::LicenseKeyNotFetchedError, "Unable to obtain a License Key.")
54
59
  end
55
60
  end
@@ -0,0 +1,140 @@
1
+ #
2
+ # Copyright:: Copyright (c) Chef Software Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ require "knife_spec_helper"
19
+ require "chef/utils/licensing_handler"
20
+
21
+ describe Chef::Utils::LicensingHandler do
22
+ let(:license_key) { "abc123" }
23
+ let(:license_type) { "commercial" }
24
+ let(:handler) { described_class.new(license_key, license_type) }
25
+
26
+ describe "#initialize" do
27
+ it "sets the license key and type" do
28
+ expect(handler.license_key).to eq(license_key)
29
+ expect(handler.license_type).to eq(license_type)
30
+ end
31
+ end
32
+
33
+ describe "#omnitruck_url" do
34
+ context "with a commercial license" do
35
+ it "returns the commercial URL with the license key" do
36
+ expected_url = "https://chefdownload-commerical.chef.io/%s?license_id=abc123"
37
+ expect(handler.omnitruck_url).to eq(expected_url)
38
+ end
39
+ end
40
+
41
+ context "with a trial license" do
42
+ let(:license_type) { "trial" }
43
+
44
+ it "returns the trial URL with the license key" do
45
+ expected_url = "https://chefdownload-trial.chef.io/%s?license_id=abc123"
46
+ expect(handler.omnitruck_url).to eq(expected_url)
47
+ end
48
+ end
49
+
50
+ context "with a free license" do
51
+ let(:license_type) { "free" }
52
+
53
+ it "returns the free (trial) URL with the license key" do
54
+ expected_url = "https://chefdownload-trial.chef.io/%s?license_id=abc123"
55
+ expect(handler.omnitruck_url).to eq(expected_url)
56
+ end
57
+ end
58
+
59
+ context "with an unknown license type" do
60
+ let(:license_type) { "unknown" }
61
+
62
+ it "returns the legacy URL without the license key" do
63
+ expected_url = "https://omnitruck.chef.io/%s"
64
+ expect(handler.omnitruck_url).to eq(expected_url)
65
+ end
66
+ end
67
+
68
+ context "with no license key" do
69
+ let(:license_key) { nil }
70
+ let(:license_type) { nil }
71
+
72
+ it "returns the legacy URL without a license ID parameter" do
73
+ expected_url = "https://omnitruck.chef.io/%s"
74
+ expect(handler.omnitruck_url).to eq(expected_url)
75
+ end
76
+ end
77
+ end
78
+
79
+ describe "#install_sh_url" do
80
+ it "formats the omnitruck URL with install.sh" do
81
+ expect(handler).to receive(:omnitruck_url).and_return("https://example.com/%s?license_id=abc123")
82
+ expect(handler.install_sh_url).to eq("https://example.com/install.sh?license_id=abc123")
83
+ end
84
+ end
85
+
86
+ describe ".validate!" do
87
+ let(:license_keys) { ["abc123"] }
88
+ let(:license_metadata) do
89
+ double("license_metadata", id: license_key, license_type: license_type)
90
+ end
91
+ let(:licenses_metadata) { [license_metadata] }
92
+
93
+ before do
94
+ allow(ChefLicensing::LicenseKeyFetcher).to receive(:fetch).and_return(license_keys)
95
+ allow(ChefLicensing::Api::Describe).to receive(:list).and_return(licenses_metadata)
96
+ end
97
+
98
+ context "when license keys are available" do
99
+ it "returns a new handler with the license key and type" do
100
+ handler = described_class.validate!
101
+ expect(handler.license_key).to eq(license_key)
102
+ expect(handler.license_type).to eq(license_type)
103
+ end
104
+
105
+ it "fetches license keys using ChefLicensing::LicenseKeyFetcher" do
106
+ expect(ChefLicensing::LicenseKeyFetcher).to receive(:fetch).and_return(license_keys)
107
+ described_class.validate!
108
+ end
109
+
110
+ it "gets license metadata using ChefLicensing::Api::Describe" do
111
+ expect(ChefLicensing::Api::Describe).to receive(:list).with({
112
+ license_keys: license_keys,
113
+ }).and_return(licenses_metadata)
114
+ described_class.validate!
115
+ end
116
+ end
117
+
118
+ context "when no license keys are available" do
119
+ let(:license_keys) { [] }
120
+
121
+ it "returns a new handler with nil license key and type" do
122
+ handler = described_class.validate!
123
+ expect(handler.license_key).to be_nil
124
+ expect(handler.license_type).to be_nil
125
+ end
126
+ end
127
+
128
+ context "when ChefLicensing::RestfulClientConnectionError is raised" do
129
+ before do
130
+ allow(ChefLicensing::LicenseKeyFetcher).to receive(:fetch).and_raise(ChefLicensing::RestfulClientConnectionError)
131
+ end
132
+
133
+ it "returns a new handler with nil license key and type" do
134
+ handler = described_class.validate!
135
+ expect(handler.license_key).to be_nil
136
+ expect(handler.license_type).to be_nil
137
+ end
138
+ end
139
+ end
140
+ end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife
3
3
  version: !ruby/object:Gem::Version
4
- version: 18.6.13
4
+ version: 18.8.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Jacob
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 2025-01-29 00:00:00.000000000 Z
11
+ date: 2025-08-18 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: chef-config
@@ -15,56 +16,56 @@ dependencies:
15
16
  requirements:
16
17
  - - "~>"
17
18
  - !ruby/object:Gem::Version
18
- version: '18.6'
19
+ version: '18.0'
19
20
  type: :runtime
20
21
  prerelease: false
21
22
  version_requirements: !ruby/object:Gem::Requirement
22
23
  requirements:
23
24
  - - "~>"
24
25
  - !ruby/object:Gem::Version
25
- version: '18.6'
26
+ version: '18.0'
26
27
  - !ruby/object:Gem::Dependency
27
28
  name: chef-utils
28
29
  requirement: !ruby/object:Gem::Requirement
29
30
  requirements:
30
31
  - - "~>"
31
32
  - !ruby/object:Gem::Version
32
- version: '18.6'
33
+ version: '18.0'
33
34
  type: :runtime
34
35
  prerelease: false
35
36
  version_requirements: !ruby/object:Gem::Requirement
36
37
  requirements:
37
38
  - - "~>"
38
39
  - !ruby/object:Gem::Version
39
- version: '18.6'
40
+ version: '18.0'
40
41
  - !ruby/object:Gem::Dependency
41
42
  name: chef
42
43
  requirement: !ruby/object:Gem::Requirement
43
44
  requirements:
44
45
  - - "~>"
45
46
  - !ruby/object:Gem::Version
46
- version: '18.6'
47
+ version: '18.0'
47
48
  type: :runtime
48
49
  prerelease: false
49
50
  version_requirements: !ruby/object:Gem::Requirement
50
51
  requirements:
51
52
  - - "~>"
52
53
  - !ruby/object:Gem::Version
53
- version: '18.6'
54
+ version: '18.0'
54
55
  - !ruby/object:Gem::Dependency
55
56
  name: chef-bin
56
57
  requirement: !ruby/object:Gem::Requirement
57
58
  requirements:
58
59
  - - "~>"
59
60
  - !ruby/object:Gem::Version
60
- version: '18.6'
61
+ version: '18.0'
61
62
  type: :runtime
62
63
  prerelease: false
63
64
  version_requirements: !ruby/object:Gem::Requirement
64
65
  requirements:
65
66
  - - "~>"
66
67
  - !ruby/object:Gem::Version
67
- version: '18.6'
68
+ version: '18.0'
68
69
  - !ruby/object:Gem::Dependency
69
70
  name: train-core
70
71
  requirement: !ruby/object:Gem::Requirement
@@ -83,16 +84,16 @@ dependencies:
83
84
  name: train-winrm
84
85
  requirement: !ruby/object:Gem::Requirement
85
86
  requirements:
86
- - - ">="
87
+ - - "~>"
87
88
  - !ruby/object:Gem::Version
88
- version: 0.2.5
89
+ version: 0.2.17
89
90
  type: :runtime
90
91
  prerelease: false
91
92
  version_requirements: !ruby/object:Gem::Requirement
92
93
  requirements:
93
- - - ">="
94
+ - - "~>"
94
95
  - !ruby/object:Gem::Version
95
- version: 0.2.5
96
+ version: 0.2.17
96
97
  - !ruby/object:Gem::Dependency
97
98
  name: license-acceptance
98
99
  requirement: !ruby/object:Gem::Requirement
@@ -395,6 +396,20 @@ dependencies:
395
396
  - - "~>"
396
397
  - !ruby/object:Gem::Version
397
398
  version: '1.0'
399
+ - !ruby/object:Gem::Dependency
400
+ name: chef-zero
401
+ requirement: !ruby/object:Gem::Requirement
402
+ requirements:
403
+ - - "~>"
404
+ - !ruby/object:Gem::Version
405
+ version: 15.0.21
406
+ type: :runtime
407
+ prerelease: false
408
+ version_requirements: !ruby/object:Gem::Requirement
409
+ requirements:
410
+ - - "~>"
411
+ - !ruby/object:Gem::Version
412
+ version: 15.0.21
398
413
  description: The knife CLI for Chef Infra.
399
414
  email: adam@chef.io
400
415
  executables:
@@ -1151,6 +1166,7 @@ files:
1151
1166
  - spec/unit/knife/user_reregister_spec.rb
1152
1167
  - spec/unit/knife/user_show_spec.rb
1153
1168
  - spec/unit/knife_spec.rb
1169
+ - spec/unit/utils/licensing_handler_spec.rb
1154
1170
  homepage: https://www.chef.io
1155
1171
  licenses:
1156
1172
  - Apache-2.0
@@ -1161,6 +1177,7 @@ metadata:
1161
1177
  homepage_uri: https://www.chef.io
1162
1178
  mailing_list_uri: https://discourse.chef.io/
1163
1179
  source_code_uri: https://github.com/chef/chef/
1180
+ post_install_message:
1164
1181
  rdoc_options: []
1165
1182
  require_paths:
1166
1183
  - lib
@@ -1175,7 +1192,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1175
1192
  - !ruby/object:Gem::Version
1176
1193
  version: '0'
1177
1194
  requirements: []
1178
- rubygems_version: 3.6.3
1195
+ rubygems_version: 3.3.7
1196
+ signing_key:
1179
1197
  specification_version: 4
1180
1198
  summary: The knife CLI for Chef Infra.
1181
1199
  test_files: []