knife 18.8.68 → 19.0.102

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.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +30 -9
  3. data/LICENSE +201 -201
  4. data/Rakefile +23 -0
  5. data/knife.gemspec +9 -15
  6. data/lib/chef/application/knife.rb +3 -5
  7. data/lib/chef/chef_fs/knife.rb +1 -1
  8. data/lib/chef/knife/acl_base.rb +1 -1
  9. data/lib/chef/knife/acl_bulk_add.rb +0 -1
  10. data/lib/chef/knife/acl_bulk_remove.rb +0 -1
  11. data/lib/chef/knife/bootstrap/templates/chef-full.erb +24 -5
  12. data/lib/chef/knife/bootstrap/templates/windows-chef-client-msi.erb +121 -4
  13. data/lib/chef/knife/bootstrap.rb +25 -29
  14. data/lib/chef/knife/config_get.rb +1 -1
  15. data/lib/chef/knife/config_get_profile.rb +1 -1
  16. data/lib/chef/knife/config_list_profiles.rb +1 -1
  17. data/lib/chef/knife/config_show.rb +1 -1
  18. data/lib/chef/knife/config_use_profile.rb +3 -3
  19. data/lib/chef/knife/configure_client.rb +1 -1
  20. data/lib/chef/knife/cookbook_bulk_delete.rb +1 -1
  21. data/lib/chef/knife/cookbook_delete.rb +1 -1
  22. data/lib/chef/knife/cookbook_download.rb +1 -1
  23. data/lib/chef/knife/cookbook_upload.rb +1 -1
  24. data/lib/chef/knife/core/bootstrap_context.rb +36 -6
  25. data/lib/chef/knife/core/cookbook_scm_repo.rb +2 -2
  26. data/lib/chef/knife/core/cookbook_site_streaming_uploader.rb +1 -6
  27. data/lib/chef/knife/core/gem_glob_loader.rb +4 -4
  28. data/lib/chef/knife/core/object_loader.rb +1 -1
  29. data/lib/chef/knife/core/status_presenter.rb +1 -1
  30. data/lib/chef/knife/core/subcommand_loader.rb +1 -1
  31. data/lib/chef/knife/core/text_formatter.rb +0 -1
  32. data/lib/chef/knife/core/windows_bootstrap_context.rb +103 -37
  33. data/lib/chef/knife/data_bag_secret_options.rb +1 -1
  34. data/lib/chef/knife/download.rb +1 -1
  35. data/lib/chef/knife/environment_compare.rb +2 -3
  36. data/lib/chef/knife/key_create.rb +1 -5
  37. data/lib/chef/knife/key_edit.rb +1 -5
  38. data/lib/chef/knife/license.rb +6 -2
  39. data/lib/chef/knife/list.rb +1 -1
  40. data/lib/chef/knife/node_edit.rb +1 -1
  41. data/lib/chef/knife/raw.rb +1 -2
  42. data/lib/chef/knife/recipe_list.rb +1 -1
  43. data/lib/chef/knife/search.rb +2 -2
  44. data/lib/chef/knife/ssh.rb +5 -5
  45. data/lib/chef/knife/ssl_fetch.rb +1 -1
  46. data/lib/chef/knife/supermarket_share.rb +3 -2
  47. data/lib/chef/knife/upload.rb +1 -1
  48. data/lib/chef/knife/user_create.rb +11 -21
  49. data/lib/chef/knife/user_list.rb +3 -3
  50. data/lib/chef/knife/version.rb +1 -3
  51. data/lib/chef/knife/xargs.rb +0 -1
  52. data/lib/chef/knife.rb +4 -1
  53. data/lib/chef/utils/licensing_config.rb +0 -1
  54. data/lib/chef/utils/licensing_handler.rb +18 -28
  55. data/spec/data/apt/chef-integration-test-1.0/debian/rules +0 -0
  56. data/spec/data/apt/chef-integration-test-1.1/debian/rules +0 -0
  57. data/spec/data/apt/chef-integration-test2-1.0/debian/rules +0 -0
  58. data/spec/data/cookbooks/openldap/templates/default/all_windows_line_endings.erb +4 -4
  59. data/spec/data/cookbooks/openldap/templates/default/some_windows_line_endings.erb +2 -2
  60. data/spec/functional/cookbook_delete_spec.rb +4 -4
  61. data/spec/functional/version_spec.rb +2 -3
  62. data/spec/integration/config_use_spec.rb +8 -8
  63. data/spec/integration/cookbook_api_ipv6_spec.rb +2 -2
  64. data/spec/integration/node_environment_set_spec.rb +1 -1
  65. data/spec/integration/node_run_list_set_spec.rb +1 -1
  66. data/spec/knife_spec_helper.rb +0 -5
  67. data/spec/support/platforms/prof/gc.rb +1 -1
  68. data/spec/support/shared/integration/integration_helper.rb +1 -1
  69. data/spec/tiny_server.rb +2 -2
  70. data/spec/unit/knife/bootstrap/templates/windows_presigned_url_spec.rb +183 -0
  71. data/spec/unit/knife/bootstrap_chef19_spec.rb +122 -0
  72. data/spec/unit/knife/bootstrap_spec.rb +121 -7
  73. data/spec/unit/knife/configure_spec.rb +3 -3
  74. data/spec/unit/knife/cookbook_list_spec.rb +1 -1
  75. data/spec/unit/knife/core/bootstrap_context_spec.rb +137 -0
  76. data/spec/unit/knife/core/windows_bootstrap_context_chef19_spec.rb +82 -0
  77. data/spec/unit/knife/core/windows_bootstrap_context_spec.rb +51 -64
  78. data/spec/unit/knife/license_spec.rb +1 -1
  79. data/spec/unit/knife/search_spec.rb +3 -3
  80. data/spec/unit/knife/supermarket_install_spec.rb +4 -5
  81. data/spec/unit/knife/utils/licensing_handler_chef19_spec.rb +144 -0
  82. metadata +61 -100
  83. data/spec/data/gems/chef-integration-test-0.1.0.gem +0 -0
  84. data/spec/data/nodes/default.rb +0 -15
  85. data/spec/data/nodes/test.example.com.rb +0 -17
  86. data/spec/data/nodes/test.rb +0 -15
  87. data/spec/unit/utils/licensing_handler_spec.rb +0 -140
@@ -172,11 +172,9 @@ do_download() {
172
172
  <%= @config[:bootstrap_install_command] %>
173
173
  <% else %>
174
174
  <% if @config[:bootstrap_url] %>
175
- install_sh="<%= @config[:bootstrap_url] %>"
176
- <% elsif license_available? %>
177
- install_sh="<%= config[:license_url] %>"
175
+ install_sh="<%= @config[:bootstrap_url] %>"
178
176
  <% else %>
179
- install_sh="https://omnitruck.chef.io/chef/install.sh"
177
+ install_sh="<%= config[:license_url] %>"
180
178
  <% end %>
181
179
 
182
180
  if test -f /usr/bin/<%= ChefUtils::Dist::Infra::CLIENT %>; then
@@ -184,7 +182,28 @@ do_download() {
184
182
  else
185
183
  echo "-----> Installing Chef Omnibus (<%= @config[:channel] %>/<%= version_to_install %>)"
186
184
  do_download ${install_sh} $tmp_dir/install.sh
187
- sh $tmp_dir/install.sh -P <%= @config[:bootstrap_product] %> -c <%= @config[:channel] %> -v <%= version_to_install %>
185
+
186
+ # Extract license key/ID and modify install script if license is required
187
+ <% if chef_ice? %>
188
+ <% if config[:license_key] %>
189
+ license_key="<%= config[:license_key] %>"
190
+ <% elsif config[:license_id] %>
191
+ license_key="<%= config[:license_id] %>"
192
+ <% elsif config[:license_url] && config[:license_url].include?('license_id=') %>
193
+ # Extract license_id from the URL
194
+ license_id=$(echo "<%= config[:license_url] %>" | grep -o 'license_id=[^&]*' | cut -d'=' -f2)
195
+ license_key="${license_id}"
196
+ <% else %>
197
+ license_key=""
198
+ <% end %>
199
+
200
+ # If we have a license key/ID, set environment variable for the package manager
201
+ if [ ! -z "$license_key" ]; then
202
+ export CHEF_LICENSE_KEY="$license_key"
203
+ fi
204
+ <% end %>
205
+
206
+ sh $tmp_dir/install.sh -P <%= product_to_install %> -c <%= @config[:channel] %> -v <%= version_to_install %>
188
207
  fi
189
208
  <% end %>
190
209
 
@@ -123,10 +123,10 @@ If !ERRORLEVEL!==0 (
123
123
  @rem If user has provided the custom installation command, execute it
124
124
  <% if @config[:bootstrap_install_command] %>
125
125
  <%= @config[:bootstrap_install_command] %>
126
- <% else %>
126
+ <% elsif msi_url %>
127
127
  @rem Install Chef using the MSI installer
128
128
 
129
- @set "LOCAL_DESTINATION_MSI_PATH=<%= local_download_path %>"
129
+ @set "LOCAL_DESTINATION_MSI_PATH=%TEMP%\chef-client.msi"
130
130
  @set "CHEF_CLIENT_MSI_LOG_PATH=%TEMP%\<%= ChefUtils::Dist::Infra::CLIENT %>-msi%RANDOM%.log"
131
131
 
132
132
  @rem Clear any pre-existing downloads
@@ -145,7 +145,7 @@ If !ERRORLEVEL!==0 (
145
145
  @if EXIST "%CHEF_CLIENT_MSI_LOG_PATH%" del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
146
146
 
147
147
  @echo Attempting to download client package using PowerShell if available...
148
- @set "REMOTE_SOURCE_MSI_URL=<%= msi_url('%MACHINE_OS%', '%MACHINE_ARCH%', 'PowerShell') %>"
148
+ @set "REMOTE_SOURCE_MSI_URL=<%= msi_url %>"
149
149
  @set powershell_download=powershell.exe -ExecutionPolicy Unrestricted -InputFormat None -NoProfile -NonInteractive -File <%= bootstrap_directory %>\wget.ps1 "%REMOTE_SOURCE_MSI_URL%" "%LOCAL_DESTINATION_MSI_PATH%"
150
150
  @echo !powershell_download!
151
151
  @call !powershell_download!
@@ -172,7 +172,7 @@ If !ERRORLEVEL!==0 (
172
172
 
173
173
  @if EXIST "%LOCAL_DESTINATION_MSI_PATH%" del /f /q "%LOCAL_DESTINATION_MSI_PATH%"
174
174
 
175
- @set "REMOTE_SOURCE_MSI_URL=<%= msi_url('%MACHINE_OS%', '%MACHINE_ARCH%') %>"
175
+ @set "REMOTE_SOURCE_MSI_URL=<%= msi_url %>"
176
176
  cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_MSI_URL%" /path:"%LOCAL_DESTINATION_MSI_PATH%"
177
177
 
178
178
  @if NOT ERRORLEVEL 1 (
@@ -204,6 +204,123 @@ If !ERRORLEVEL!==0 (
204
204
  del /f /q "%CHEF_CLIENT_MSI_LOG_PATH%"
205
205
  )
206
206
 
207
+ <% else %>
208
+ @rem Install Chef using the PowerShell install script
209
+
210
+ @set "LOCAL_DESTINATION_SCRIPT_PATH=%TEMP%\install.ps1"
211
+
212
+ @rem Clear any pre-existing downloads
213
+ @echo Checking for existing downloaded script at "%LOCAL_DESTINATION_SCRIPT_PATH%"
214
+ @if EXIST "%LOCAL_DESTINATION_SCRIPT_PATH%" (
215
+ @echo Found existing downloaded script, deleting.
216
+ @del /f /q "%LOCAL_DESTINATION_SCRIPT_PATH%"
217
+ @if ERRORLEVEL 1 (
218
+ echo Warning: Failed to delete pre-existing script with status code !ERRORLEVEL! > "&2"
219
+ )
220
+ ) else (
221
+ echo No existing downloaded scripts to delete.
222
+ )
223
+
224
+ @echo Attempting to download install script using PowerShell...
225
+ <% if @config[:bootstrap_url] %>
226
+ @rem Using direct PowerShell call to avoid batch variable expansion issues with special characters in URLs
227
+ @rem Pass URL via environment variable to avoid percent sign interpretation
228
+ @set "BOOTSTRAP_DOWNLOAD_URL=<%= @config[:bootstrap_url].gsub('%', '%%') %>"
229
+ powershell.exe -ExecutionPolicy Unrestricted -InputFormat None -NoProfile -NonInteractive -Command "& '<%= bootstrap_directory.gsub("'", "''") %>\wget.ps1' -remoteUrl $env:BOOTSTRAP_DOWNLOAD_URL -localPath '%LOCAL_DESTINATION_SCRIPT_PATH%'"
230
+ <% else %>
231
+ @set "REMOTE_SOURCE_SCRIPT_URL=<%= install_ps1_url %>"
232
+ powershell.exe -ExecutionPolicy Unrestricted -InputFormat None -NoProfile -NonInteractive -File <%= bootstrap_directory %>\wget.ps1 "%REMOTE_SOURCE_SCRIPT_URL%" "%LOCAL_DESTINATION_SCRIPT_PATH%"
233
+ <% end %>
234
+
235
+ @set DOWNLOAD_ERROR_STATUS=!ERRORLEVEL!
236
+
237
+ @if ERRORLEVEL 1 (
238
+ @echo Failed PowerShell download with status code !DOWNLOAD_ERROR_STATUS! > "&2"
239
+ @if !DOWNLOAD_ERROR_STATUS!==0 set DOWNLOAD_ERROR_STATUS=2
240
+ ) else (
241
+ @rem Sometimes the error level is not set even when the download failed,
242
+ @rem so check for the file to be sure it is there -- if it is not, we will retry
243
+ @if NOT EXIST "%LOCAL_DESTINATION_SCRIPT_PATH%" (
244
+ echo Failed download: download completed, but downloaded file not found > "&2"
245
+ set DOWNLOAD_ERROR_STATUS=2
246
+ ) else (
247
+ echo Download via PowerShell succeeded.
248
+ )
249
+ )
250
+
251
+ @if NOT %DOWNLOAD_ERROR_STATUS%==0 (
252
+ <% if @config[:bootstrap_url] %>
253
+ @echo Warning: Failed to download install script via PowerShell
254
+ @echo Warning: Retrying download with cscript ...
255
+
256
+ @if EXIST "%LOCAL_DESTINATION_SCRIPT_PATH%" del /f /q "%LOCAL_DESTINATION_SCRIPT_PATH%"
257
+
258
+ @rem For custom bootstrap URLs, use environment variable to pass URL to cscript
259
+ cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"!BOOTSTRAP_DOWNLOAD_URL!" /path:"%LOCAL_DESTINATION_SCRIPT_PATH%"
260
+ <% else %>
261
+ @echo Warning: Failed to download "%REMOTE_SOURCE_SCRIPT_URL%" to "%LOCAL_DESTINATION_SCRIPT_PATH%"
262
+ @echo Warning: Retrying download with cscript ...
263
+
264
+ @if EXIST "%LOCAL_DESTINATION_SCRIPT_PATH%" del /f /q "%LOCAL_DESTINATION_SCRIPT_PATH%"
265
+
266
+ cscript /nologo <%= bootstrap_directory %>\wget.vbs /url:"%REMOTE_SOURCE_SCRIPT_URL%" /path:"%LOCAL_DESTINATION_SCRIPT_PATH%"
267
+ <% end %>
268
+
269
+ @if NOT ERRORLEVEL 1 (
270
+ @rem Sometimes the error level is not set even when the download failed,
271
+ @rem so check for the file to be sure it is there.
272
+ @if NOT EXIST "%LOCAL_DESTINATION_SCRIPT_PATH%" (
273
+ echo Failed download: download completed, but downloaded file not found > "&2"
274
+ echo Exiting without bootstrapping due to download failure. > "&2"
275
+ exit /b 1
276
+ ) else (
277
+ echo Download via cscript succeeded.
278
+ )
279
+ ) else (
280
+ <% if @config[:bootstrap_url] %>
281
+ echo Failed to download install script with status code !ERRORLEVEL!. > "&2"
282
+ <% else %>
283
+ echo Failed to download "%REMOTE_SOURCE_SCRIPT_URL%" with status code !ERRORLEVEL!. > "&2"
284
+ <% end %>
285
+ echo Exiting without bootstrapping due to download failure. > "&2"
286
+ exit /b 1
287
+ )
288
+ )
289
+
290
+ @echo Installing <%= ChefUtils::Dist::Infra::PRODUCT %> using PowerShell install script...
291
+
292
+ @rem Set license environment variable if license is required
293
+ <% if chef_ice? %>
294
+ <% if config[:license_key] %>
295
+ @set CHEF_LICENSE_KEY=<%= config[:license_key] %>
296
+ <% elsif config[:license_id] %>
297
+ @set CHEF_LICENSE_KEY=<%= config[:license_id] %>
298
+ <% elsif config[:license_url] && config[:license_url].include?('license_id=') %>
299
+ @rem Extract license_id from the URL
300
+ @for /f "tokens=2 delims==" %%i in ("<%= config[:license_url] %>") do @set CHEF_LICENSE_KEY=%%i
301
+ <% end %>
302
+ <% end %>
303
+
304
+ @rem Execute the PowerShell install script with appropriate parameters
305
+ <% if @config[:bootstrap_url] %>
306
+ @rem Custom bootstrap URL - execute as-is without additional parameters
307
+ powershell.exe -ExecutionPolicy Unrestricted -File "%LOCAL_DESTINATION_SCRIPT_PATH%"
308
+ <% else %>
309
+ @rem Default Chef install script - invoke the install function with parameters
310
+ @echo Attempting installation with PowerShell parameters...
311
+ powershell.exe -ExecutionPolicy Unrestricted -Command "& { . '%LOCAL_DESTINATION_SCRIPT_PATH%'; install -Channel '<%= @config[:channel] %>' -Project '<%= product_to_install %>' -Version '<%= version_to_install %>' }"
312
+ <% end %>
313
+
314
+ @set INSTALL_ERROR_STATUS=!ERRORLEVEL!
315
+ @if !INSTALL_ERROR_STATUS! NEQ 0 (
316
+ echo <%= ChefUtils::Dist::Infra::CLIENT %> install script failed with status code !INSTALL_ERROR_STATUS!. > "&2"
317
+ echo See PowerShell output above for additional detail. > "&2"
318
+ exit /b !INSTALL_ERROR_STATUS!
319
+ )
320
+
321
+ @rem Clean up the downloaded script
322
+ @if EXIST "%LOCAL_DESTINATION_SCRIPT_PATH%" del /f /q "%LOCAL_DESTINATION_SCRIPT_PATH%"
323
+
207
324
  <% end %>
208
325
 
209
326
  @rem This line is required to separate the key_create label from the "block boundary"
@@ -23,7 +23,6 @@ require "license_acceptance/cli_flags/mixlib_cli"
23
23
  require "chef/json_compat" unless defined?(Chef::JSONCompat) # can't be lazy loaded since it's used in options
24
24
  require "chef/utils/licensing_config"
25
25
  require "chef/utils/licensing_handler"
26
-
27
26
  module LicenseAcceptance
28
27
  autoload :Acceptor, "license_acceptance/acceptor"
29
28
  end
@@ -300,8 +299,7 @@ class Chef
300
299
 
301
300
  option :bootstrap_product,
302
301
  long: "--bootstrap-product PRODUCT",
303
- description: "Product to install.",
304
- default: "chef"
302
+ description: "Product to install."
305
303
 
306
304
  option :msi_url, # Windows target only
307
305
  short: "-m URL",
@@ -350,6 +348,18 @@ class Chef
350
348
  accumulator[vault].push(item)
351
349
  accumulator
352
350
  }
351
+ option :disable_license_activation,
352
+ long: "--disable-license-activation",
353
+ description: "By default knife copies the local license key to the node and activates it. This options can be used to disable that.",
354
+ boolean: true
355
+
356
+ option :chef_license_key,
357
+ long: "--chef-license-key KEY",
358
+ description: "The Chef License key to be used for license activation. You can run `knife license` command to retrieve it."
359
+
360
+ option :chef_license_server,
361
+ long: "--chef-license-server URL",
362
+ description: "The Chef License server URL to be used for license activation. You can run `knife license` command to retrieve it."
353
363
 
354
364
  # Deprecated options. These must be declared after
355
365
  # regular options because they refer to the replacement
@@ -579,7 +589,6 @@ class Chef
579
589
  bootstrap_path = upload_bootstrap(content)
580
590
  perform_bootstrap(bootstrap_path)
581
591
  plugin_finalize
582
- warn_license_usage
583
592
  ensure
584
593
  connection.del_file!(bootstrap_path) if connection && bootstrap_path
585
594
  end
@@ -1199,33 +1208,20 @@ class Chef
1199
1208
 
1200
1209
  # Fetch the workstation license stored in the system
1201
1210
  def fetch_license
1202
- license = Chef::Utils::LicensingHandler.validate!
1203
- config[:license_url] = license.install_sh_url
1204
- config[:license_id] = license.license_key
1205
- config[:license_type] = license.license_type
1206
- config[:omnitruck_url] = license.omnitruck_url
1211
+ # The license is not needed if we are using a custom bootstrap URL, MSI URL, or template
1212
+ return if config[:bootstrap_url] || config[:bootstrap_template] || (config[:msi_url] && !config[:msi_url].empty?)
1213
+
1214
+ # This block will mandate license acceptance
1215
+ # require_license_for checks if distribution is official (skip licensing) or unofficial (enforce licensing)
1216
+ ChefLicensing::Config.require_license_for do
1217
+ license = Chef::Utils::LicensingHandler.validate!
1218
+ config[:license_url] = license.install_sh_url
1219
+ config[:license_id] = license.license_key
1220
+ config[:omnitruck_url] = license.omnitruck_url
1221
+ config[:license_type] = license.license_type
1222
+ end
1207
1223
  end
1208
1224
 
1209
- def warn_license_usage
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?)
1213
-
1214
- ui.warn(<<~MSG
1215
-
1216
- +---------------------------------------------------------------------------------------------------------------------+
1217
- To ensure uninterrupted downloads of Infra Client, Knife Bootstrap will soon require a license key.
1218
-
1219
- Here's what you need to know:
1220
- * Adding a License: Use the < knife license > command to easily add a license key.
1221
- * For Commercial Customers: Obtain your license key from the customer portal.
1222
- * For Free/Trial Users: Non-commercial users can generate a license key from https://www.chef.io/license-generation-free-trial
1223
-
1224
- No action is require at this time, but please prepare for this change.
1225
- +---------------------------------------------------------------------------------------------------------------------+
1226
- MSG
1227
- )
1228
- end
1229
1225
  end
1230
1226
  end
1231
1227
  end
@@ -18,7 +18,7 @@
18
18
  #
19
19
 
20
20
  require_relative "../knife"
21
- require_relative "./config_show"
21
+ require_relative "config_show"
22
22
 
23
23
  class Chef
24
24
  class Knife
@@ -16,7 +16,7 @@
16
16
  #
17
17
 
18
18
  require_relative "../knife"
19
- require_relative "./config_use"
19
+ require_relative "config_use"
20
20
 
21
21
  class Chef
22
22
  class Knife
@@ -16,7 +16,7 @@
16
16
  #
17
17
 
18
18
  require_relative "../knife"
19
- require_relative "./config_list"
19
+ require_relative "config_list"
20
20
 
21
21
  class Chef
22
22
  class Knife
@@ -75,7 +75,7 @@ class Chef
75
75
  # It's a regex.
76
76
  filter_re = Regexp.new($1, $2 ? Regexp::IGNORECASE : 0)
77
77
  config_data.each do |key, value|
78
- output_data[key] = value if key.to_s&.match?(filter_re)
78
+ output_data[key] = value if key.to_s.match?(filter_re)
79
79
  end
80
80
  else
81
81
  # It's a dotted path string.
@@ -16,7 +16,7 @@
16
16
  #
17
17
 
18
18
  require_relative "../knife"
19
- require_relative "./config_use"
19
+ require_relative "config_use"
20
20
 
21
21
  class Chef
22
22
  class Knife
@@ -31,8 +31,8 @@ class Chef
31
31
  def run
32
32
  Chef::Log.warn("knife config use-profile has been deprecated in favor of knife config use. This will be removed in the major release version!")
33
33
 
34
- credentials_data = self.class.config_loader.parse_credentials_file
35
- context_file = ChefConfig::PathHelper.home(".chef", "context").freeze
34
+ self.class.config_loader.parse_credentials_file
35
+ ChefConfig::PathHelper.home(".chef", "context").freeze
36
36
  profile = @name_args[0]&.strip
37
37
  if profile.nil? || profile.empty?
38
38
  show_usage
@@ -24,7 +24,7 @@ class Chef
24
24
  banner "knife configure client DIRECTORY"
25
25
 
26
26
  def run
27
- unless @config_dir = @name_args[0]
27
+ unless (@config_dir = @name_args[0])
28
28
  ui.fatal "You must provide the directory to put the files in"
29
29
  show_usage
30
30
  exit(1)
@@ -33,7 +33,7 @@ class Chef
33
33
  banner "knife cookbook bulk delete REGEX (options)"
34
34
 
35
35
  def run
36
- unless regex_str = @name_args.first
36
+ unless (regex_str = @name_args.first)
37
37
  ui.fatal("You must supply a regular expression to match the results against")
38
38
  exit 42
39
39
  end
@@ -113,7 +113,7 @@ class Chef
113
113
  exit(1)
114
114
  end
115
115
  versions = responses.map do |response|
116
- if version = valid_responses[response]
116
+ if (version = valid_responses[response])
117
117
  version
118
118
  else
119
119
  ui.error("#{response} is not a valid choice, skipping it")
@@ -130,7 +130,7 @@ class Chef
130
130
  question += "\n"
131
131
  response = ask_question(question).strip
132
132
 
133
- unless @version = valid_responses[response]
133
+ unless (@version = valid_responses[response])
134
134
  ui.error("'#{response}' is not a valid value.")
135
135
  exit(1)
136
136
  end
@@ -58,7 +58,7 @@ class Chef
58
58
  long: "--concurrency NUMBER_OF_THREADS",
59
59
  description: "How many concurrent threads will be used.",
60
60
  default: 10,
61
- proc: lambda { |o| o.to_i }
61
+ proc: lambda(&:to_i)
62
62
 
63
63
  option :environment,
64
64
  short: "-E",
@@ -192,7 +192,16 @@ class Chef
192
192
  s << " -l debug"
193
193
  end
194
194
  s << " -E #{bootstrap_environment}" unless bootstrap_environment.nil?
195
- s << " --no-color" unless config[:color]
195
+ s << " --no-color" if config.key?(:color) && !config[:color]
196
+
197
+ # Add license environment variable if required
198
+ unless config[:disable_license_activation]
199
+ if chef_ice?
200
+ license_key = config[:license_key] || config[:license_id]
201
+ s = "CHEF_LICENSE_KEY=\"#{license_key}\" " + s if license_key
202
+ end
203
+ end
204
+
196
205
  s
197
206
  end
198
207
 
@@ -204,7 +213,7 @@ class Chef
204
213
  return config[:bootstrap_version] if config[:bootstrap_version]
205
214
 
206
215
  if config[:license_url]
207
- if config[:channel] == "stable" && config[:license_type] == "commercial"
216
+ if config[:channel] == "stable" && config[:license_type] == "commercial" && (config[:bootstrap_product] == "chef-ice" || config[:bootstrap_product].nil?)
208
217
  Chef::VERSION.split(".").first
209
218
  else
210
219
  "latest"
@@ -216,6 +225,31 @@ class Chef
216
225
  end
217
226
  end
218
227
 
228
+ def product_to_install
229
+ # If explicitly specified, use it
230
+ return config[:bootstrap_product] if config[:bootstrap_product]
231
+
232
+ # Determine product based on version
233
+ version = version_to_install
234
+ if version == "latest"
235
+ "chef-ice"
236
+ elsif version.to_s.start_with?("19")
237
+ "chef-ice"
238
+ else
239
+ "chef"
240
+ end
241
+ end
242
+
243
+ def chef_ice?
244
+ product_to_install == "chef-ice"
245
+ end
246
+
247
+ def detect_package_manager
248
+ # This method would be called from the bootstrap template to detect package manager
249
+ # For now, return empty string as detection happens in the install script
250
+ ""
251
+ end
252
+
219
253
  def first_boot
220
254
  (config[:first_boot_attributes] = Mash.new(config[:first_boot_attributes]) || Mash.new).tap do |attributes|
221
255
  if config[:policy_name] && config[:policy_group]
@@ -229,10 +263,6 @@ class Chef
229
263
  end
230
264
  end
231
265
 
232
- def license_available?
233
- config[:license_id] && config[:license_type]
234
- end
235
-
236
266
  private
237
267
 
238
268
  # Returns a string for copying the trusted certificates on the workstation to the system being bootstrapped
@@ -22,7 +22,7 @@ class Chef
22
22
  class Knife
23
23
  class CookbookSCMRepo
24
24
 
25
- DIRTY_REPO = /^\s+M/.freeze
25
+ DIRTY_REPO = /^\s+M/
26
26
 
27
27
  include Chef::Mixin::ShellOut
28
28
 
@@ -86,7 +86,7 @@ class Chef
86
86
  end
87
87
 
88
88
  def finalize_updates_to(cookbook_name, version)
89
- if update_count = updated?(cookbook_name)
89
+ if (update_count = updated?(cookbook_name))
90
90
  ui.info "#{update_count} files updated, committing changes"
91
91
  git("add #{cookbook_name}")
92
92
  git("commit -m \"Import #{cookbook_name} version #{version}\" -- #{cookbook_name}")
@@ -218,11 +218,7 @@ class Chef
218
218
 
219
219
  how_much_current_part = @parts[@part_no].size - @part_offset
220
220
 
221
- how_much_current_part = if how_much_current_part > how_much
222
- how_much
223
- else
224
- how_much_current_part
225
- end
221
+ how_much_current_part = [how_much_current_part, how_much].min
226
222
 
227
223
  how_much_next_part = how_much - how_much_current_part
228
224
 
@@ -246,4 +242,3 @@ class Chef
246
242
  end
247
243
  end
248
244
  end
249
-
@@ -22,8 +22,8 @@ class Chef
22
22
  class Knife
23
23
  class SubcommandLoader
24
24
  class GemGlobLoader < Chef::Knife::SubcommandLoader
25
- MATCHES_CHEF_GEM ||= %r{/chef-\d+\.\d+\.\d+}.freeze
26
- MATCHES_THIS_CHEF_GEM ||= %r{/chef-#{Chef::VERSION}(-\w+)?(-\w+)?/}.freeze
25
+ MATCHES_CHEF_GEM ||= %r{/chef-\d+\.\d+\.\d+}
26
+ MATCHES_THIS_CHEF_GEM ||= %r{/chef-#{Chef::VERSION}(-\w+)?(-\w+)?/}
27
27
 
28
28
  def subcommand_files
29
29
  @subcommand_files ||= (gem_and_builtin_subcommands.values + site_subcommands).flatten.uniq
@@ -47,11 +47,11 @@ class Chef
47
47
 
48
48
  def find_subcommands_via_rubygems
49
49
  files = find_files_latest_gems "chef/knife/*.rb"
50
- version_file_match = /#{Regexp.escape(File.join('chef', 'knife', 'version'))}$/
50
+ version_file_match = /#{Regexp.escape(File.join("chef", "knife", "version"))}$/
51
51
  subcommand_files = {}
52
52
  files.each do |file|
53
53
 
54
- rel_path = file[/(.*)(#{Regexp.escape File.join('chef', 'knife', '')}.*)\.rb/, 2]
54
+ rel_path = file[/(.*)(#{Regexp.escape File.join("chef", "knife", "")}.*)\.rb/, 2]
55
55
 
56
56
  # When not installed as a gem (ChefDK/appbundler in particular), AND
57
57
  # a different version of Chef is installed via gems, `files` will
@@ -39,7 +39,7 @@ class Chef
39
39
  end
40
40
 
41
41
  def load_from(repo_location, *components)
42
- unless object_file = find_file(repo_location, *components)
42
+ unless (object_file = find_file(repo_location, *components))
43
43
  ui.error "Could not find or open file '#{components.last}' in current directory or in '#{repo_location}/#{components.join("/")}'"
44
44
  exit 1
45
45
  end
@@ -135,7 +135,7 @@ class Chef
135
135
  now = Time.now.to_i
136
136
  difference = now - unix_time.to_i
137
137
  hours = (difference / 3600).to_i
138
- difference = difference % 3600
138
+ difference %= 3600
139
139
  minutes = (difference / 60).to_i
140
140
  seconds = (difference % 60)
141
141
  [hours, minutes, seconds]
@@ -145,7 +145,7 @@ class Chef
145
145
  def find_subcommands_via_dirglob
146
146
  # The "require paths" of the core knife subcommands bundled with chef
147
147
  files = Dir[File.join(ChefConfig::PathHelper.escape_glob_dir(File.expand_path("../../knife", __dir__)), "*.rb")]
148
- version_file_match = /#{Regexp.escape(File.join('chef', 'knife', 'version.rb'))}/
148
+ version_file_match = /#{Regexp.escape(File.join("chef", "knife", "version.rb"))}/
149
149
  subcommand_files = {}
150
150
  files.each do |knife_file|
151
151
  rel_path = knife_file[/#{KNIFE_ROOT}#{Regexp.escape(File::SEPARATOR)}(.*)\.rb/, 1]
@@ -64,7 +64,6 @@ class Chef
64
64
  end
65
65
  elsif data.is_a?(Array)
66
66
  data.each_index do |index|
67
- item = data[index]
68
67
  buffer << text_format(data[index])
69
68
  # Separate items with newlines if it's an array of hashes or an
70
69
  # array of arrays