test-kitchen 1.5.0 → 1.6.0

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.
@@ -6,12 +6,9 @@ This release process applies to all Test Kitchen projects, but each project may
6
6
  2. Check out the master branch of the project being prepared for release.
7
7
  3. Branch into a release-branch of the form `150_release_prep`.
8
8
  4. Modify the `version.rb` file to specify the version for releasing.
9
- 5. Update the changelog to include what is being released.
10
- 1. For these projects we use [PimpMyChangelog](https://github.com/pcreux/pimpmychangelog). All this does is make the CHANGELOG look pretty - for now we manually import the PRs / Issues and categorize them.
11
- 2. Start a [diff](https://github.com/test-kitchen/test-kitchen/compare/v1.4.2...master) in Github between master and the last release
12
- 3. Look for all the merged PRs and add them to the CHANGELOG.md under the appropriate category. They should have the form `* PR #999: PR Description (@author)`.
13
- 4. Install and run `pimpmychangelog`. This should change all the PR numbers and @ mentions into links.
9
+ 5. Run `rake changelog` to regenerate the changelog.
14
10
  6. `git commit` the `version.rb` and `CHANGELOG.md` changes to the branch and setup a PR for them. Allow the PR to run any automated tests and review the CHANGELOG for accuracy.
15
11
  7. Merge the PR to master after review.
16
- 8. Switch your local copy to the master branch and `git pull` to pull in the release preperation changes.
12
+ 8. Switch your local copy to the master branch and `git pull` to pull in the release preparation changes.
17
13
  9. Run `rake release` on the master branch.
14
+ 10. Modify the `version.rb` file and bump the patch or minor version, and commit/push.
data/Rakefile CHANGED
@@ -65,3 +65,12 @@ task :deploy_over_dk do
65
65
  end
66
66
 
67
67
  task :dk_install => [:deploy_over_dk, :install]
68
+
69
+ require "github_changelog_generator/task"
70
+
71
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
72
+ config.future_release = Kitchen::VERSION
73
+ config.enhancement_labels = "enhancement,Enhancement,New Feature,Feature".split(",")
74
+ config.bug_labels = "bug,Bug,Improvement".split(",")
75
+ config.exclude_labels = %w[Duplicate Question Discussion]
76
+ end
@@ -19,8 +19,12 @@
19
19
  require "kitchen/command"
20
20
 
21
21
  require "rubygems/spec_fetcher"
22
- require "chef-config/config"
23
- require "chef-config/workstation_config_loader"
22
+ begin
23
+ require "chef-config/config"
24
+ require "chef-config/workstation_config_loader"
25
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
26
+ # This space left intentionally blank.
27
+ end
24
28
 
25
29
  module Kitchen
26
30
 
@@ -36,8 +40,10 @@ module Kitchen
36
40
  # We are introducing the idea of using the Chef configuration as a
37
41
  # unified config for all the ChefDK tools. The first practical
38
42
  # implementation of this is 1 location to setup proxy configurations.
39
- ChefConfig::WorkstationConfigLoader.new(options[:chef_config_path]).load
40
- ChefConfig::Config.export_proxies
43
+ if defined?(ChefConfig::WorkstationConfigLoader)
44
+ ChefConfig::WorkstationConfigLoader.new(options[:chef_config_path]).load
45
+ end
46
+ ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
41
47
 
42
48
  specs = fetch_gem_specs.sort { |x, y| x[0] <=> y[0] }
43
49
  specs = specs[0, 49].push(["...", "..."]) if specs.size > 49
@@ -123,6 +123,10 @@ module Kitchen
123
123
  raise ClientError, "#{self.class}#destroy must be implemented"
124
124
  end
125
125
 
126
+ def legacy_state(state)
127
+ backcompat_merged_state(state)
128
+ end
129
+
126
130
  # (see Base#login_command)
127
131
  def login_command(state)
128
132
  instance.transport.connection(backcompat_merged_state(state)).
@@ -391,6 +391,20 @@ module Kitchen
391
391
  self
392
392
  end
393
393
 
394
+ # returns true, if the verifier is busser
395
+ def verifier_busser?(verifier)
396
+ !defined?(Kitchen::Verifier::Busser).nil? && verifier.is_a?(Kitchen::Verifier::Busser)
397
+ end
398
+
399
+ # returns true, if the verifier is dummy
400
+ def verifier_dummy?(verifier)
401
+ !defined?(Kitchen::Verifier::Dummy).nil? && verifier.is_a?(Kitchen::Verifier::Dummy)
402
+ end
403
+
404
+ def use_legacy_ssh_verifier?(verifier)
405
+ verifier_busser?(verifier) || verifier_dummy?(verifier)
406
+ end
407
+
394
408
  # Perform the verify action.
395
409
  #
396
410
  # @see Driver::Base#verify
@@ -399,8 +413,12 @@ module Kitchen
399
413
  def verify_action
400
414
  banner "Verifying #{to_str}..."
401
415
  elapsed = action(:verify) do |state|
402
- if legacy_ssh_base_driver?
416
+ # use special handling for legacy driver
417
+ if legacy_ssh_base_driver? && use_legacy_ssh_verifier?(verifier)
403
418
  legacy_ssh_base_verify(state)
419
+ elsif legacy_ssh_base_driver?
420
+ # read ssh options from legacy driver
421
+ verifier.call(driver.legacy_state(state))
404
422
  else
405
423
  verifier.call(state)
406
424
  end
@@ -44,13 +44,19 @@ module Kitchen
44
44
  raise ClientError, "Platform#new requires option :name"
45
45
  end
46
46
  @os_type = options.fetch(:os_type) do
47
- @name.downcase =~ /^win/ ? "windows" : "unix"
47
+ windows?(options) ? "windows" : "unix"
48
48
  end
49
49
  @shell_type = options.fetch(:shell_type) do
50
- @name.downcase =~ /^win/ ? "powershell" : "bourne"
50
+ windows?(options) ? "powershell" : "bourne"
51
51
  end
52
52
  end
53
53
 
54
+ def windows?(options)
55
+ @name.downcase =~ /^win/ || (
56
+ !options[:transport].nil? && options[:transport][:name] == "winrm"
57
+ )
58
+ end
59
+
54
60
  # Returns a Hash of configuration and other useful diagnostic information.
55
61
  #
56
62
  # @return [Hash] a diagnostic hash
@@ -205,10 +205,18 @@ module Kitchen
205
205
  # Conditionally prefixes a command with a sudo command.
206
206
  #
207
207
  # @param command [String] command to be prefixed
208
- # @return [String] the command, conditionaly prefixed with sudo
208
+ # @return [String] the command, conditionally prefixed with sudo
209
209
  # @api private
210
210
  def sudo(script)
211
- config[:sudo] ? "#{config[:sudo_command]} #{script}" : script
211
+ "#{sudo_command} #{script}".lstrip
212
+ end
213
+
214
+ # Returns the sudo command to use or empty string if sudo is not configured
215
+ #
216
+ # @return [String] the sudo command if sudo config is true
217
+ # @api private
218
+ def sudo_command
219
+ config[:sudo] ? config[:sudo_command].to_s : ""
212
220
  end
213
221
 
214
222
  # Conditionally prefixes a command with a command prefix.
@@ -0,0 +1,125 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: SAWANOBORI Yukihiko <sawanoboriyu@higanworks.com>)
4
+ #
5
+ # Copyright (C) 2015, HiganWorks LLC
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ # Usage:
20
+ #
21
+ # puts your recipes to` apply/` directory.
22
+ #
23
+ # An example of .kitchen.yml.
24
+ #
25
+ # ---
26
+ # driver:
27
+ # name: vagrant
28
+ #
29
+ # provisioner:
30
+ # name: chef_apply
31
+ #
32
+ # platforms:
33
+ # - name: ubuntu-12.04
34
+ # - name: centos-6.4
35
+ #
36
+ # suites:
37
+ # - name: default
38
+ # run_list:
39
+ # - recipe1
40
+ # - recipe2
41
+ #
42
+ #
43
+ # The chef-apply runs twice below.
44
+ #
45
+ # chef-apply apply/recipe1.rb
46
+ # chef-apply apply/recipe2.rb
47
+
48
+ require "kitchen/provisioner/chef_base"
49
+
50
+ module Kitchen
51
+
52
+ module Provisioner
53
+
54
+ # Chef Apply provisioner.
55
+ #
56
+ # @author SAWANOBORI Yukihiko <sawanoboriyu@higanworks.com>)
57
+ class ChefApply < ChefBase
58
+
59
+ kitchen_provisioner_api_version 2
60
+
61
+ plugin_version Kitchen::VERSION
62
+
63
+ default_config :chef_apply_path do |provisioner|
64
+ provisioner.
65
+ remote_path_join(%W[#{provisioner[:chef_omnibus_root]} bin chef-apply]).
66
+ tap { |path| path.concat(".bat") if provisioner.windows_os? }
67
+ end
68
+
69
+ default_config :apply_path do |provisioner|
70
+ provisioner.calculate_path("apply")
71
+ end
72
+ expand_path_for :apply_path
73
+
74
+ # (see ChefBase#create_sandbox)
75
+ def create_sandbox
76
+ @sandbox_path = Dir.mktmpdir("#{instance.name}-sandbox-")
77
+ File.chmod(0755, sandbox_path)
78
+ info("Preparing files for transfer")
79
+ debug("Creating local sandbox in #{sandbox_path}")
80
+
81
+ prepare_json
82
+ prepare(:apply)
83
+ end
84
+
85
+ # (see ChefBase#init_command)
86
+ def init_command
87
+ dirs = %w[
88
+ apply
89
+ ].sort.map { |dir| remote_path_join(config[:root_path], dir) }
90
+
91
+ vars = if powershell_shell?
92
+ init_command_vars_for_powershell(dirs)
93
+ else
94
+ init_command_vars_for_bourne(dirs)
95
+ end
96
+
97
+ prefix_command(shell_code_from_file(vars, "chef_base_init_command"))
98
+ end
99
+
100
+ # (see ChefSolo#run_command)
101
+ def run_command
102
+ level = config[:log_level] == :info ? :auto : config[:log_level]
103
+
104
+ lines = []
105
+ config[:run_list].map do |recipe|
106
+ cmd = sudo(config[:chef_apply_path]).dup.
107
+ tap { |str| str.insert(0, "& ") if powershell_shell? }
108
+ args = [
109
+ "apply/#{recipe}.rb",
110
+ "--log_level #{level}",
111
+ "--no-color"
112
+ ]
113
+ args << "--logfile #{config[:log_file]}" if config[:log_file]
114
+
115
+ lines << wrap_shell_code(
116
+ [cmd, *args].join(" ").
117
+ tap { |str| str.insert(0, reload_ps1_path) if windows_os? }
118
+ )
119
+ end
120
+
121
+ prefix_command(lines.join("\n"))
122
+ end
123
+ end
124
+ end
125
+ end
@@ -26,8 +26,12 @@ require "kitchen/provisioner/chef/common_sandbox"
26
26
  require "kitchen/provisioner/chef/librarian"
27
27
  require "kitchen/util"
28
28
  require "mixlib/install"
29
- require "chef-config/config"
30
- require "chef-config/workstation_config_loader"
29
+ begin
30
+ require "chef-config/config"
31
+ require "chef-config/workstation_config_loader"
32
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
33
+ # This space left intentionally blank.
34
+ end
31
35
 
32
36
  module Kitchen
33
37
 
@@ -96,10 +100,12 @@ module Kitchen
96
100
  def initialize(config = {})
97
101
  super(config)
98
102
 
99
- ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
103
+ if defined?(ChefConfig::WorkstationConfigLoader)
104
+ ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
105
+ end
100
106
  # This exports any proxy config present in the Chef config to
101
107
  # appropriate environment variables, which Test Kitchen respects
102
- ChefConfig::Config.export_proxies
108
+ ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
103
109
  end
104
110
 
105
111
  # (see Base#create_sandbox)
@@ -149,7 +155,8 @@ module Kitchen
149
155
  {
150
156
  :omnibus_url => config[:chef_omnibus_url],
151
157
  :project => project.nil? ? nil : project[1],
152
- :install_flags => config[:chef_omnibus_install_options]
158
+ :install_flags => config[:chef_omnibus_install_options],
159
+ :sudo_command => sudo_command
153
160
  }.tap do |opts|
154
161
  opts[:root] = config[:chef_omnibus_root] if config.key? :chef_omnibus_root
155
162
  opts[:http_proxy] = config[:http_proxy] if config.key? :http_proxy
@@ -46,7 +46,7 @@ module Kitchen
46
46
  default_config :connection_retries, 5
47
47
  default_config :connection_retry_sleep, 1
48
48
  default_config :max_wait_until_ready, 600
49
- default_config :winrm_transport, "plaintext"
49
+ default_config :winrm_transport, :negotiate
50
50
  default_config :port do |transport|
51
51
  transport[:winrm_transport] == :ssl ? 5986 : 5985
52
52
  end
@@ -58,18 +58,7 @@ module Kitchen
58
58
  def finalize_config!(instance)
59
59
  super
60
60
 
61
- transport = config[:winrm_transport].to_sym
62
- config[:winrm_transport] =
63
- case transport
64
- when :sspinegotiate
65
- if host_os_windows?
66
- transport
67
- else
68
- :plaintext
69
- end
70
- else
71
- transport
72
- end
61
+ config[:winrm_transport] = config[:winrm_transport].to_sym
73
62
 
74
63
  self
75
64
  end
@@ -96,10 +85,7 @@ module Kitchen
96
85
  def close
97
86
  return if @session.nil?
98
87
 
99
- shell_id = session.shell
100
- logger.debug("[WinRM] closing remote shell #{shell_id} on #{self}")
101
88
  session.close
102
- logger.debug("[WinRM] remote shell #{shell_id} closed")
103
89
  ensure
104
90
  @session = nil
105
91
  end
@@ -147,10 +133,8 @@ module Kitchen
147
133
  def wait_until_ready
148
134
  delay = 3
149
135
  session(
150
- :retries => max_wait_until_ready / delay,
151
- :delay => delay,
152
- :message => "Waiting for WinRM service on #{endpoint}, " \
153
- "retrying in #{delay} seconds"
136
+ :retry_limit => max_wait_until_ready / delay,
137
+ :retry_delay => delay
154
138
  )
155
139
  execute(PING_COMMAND.dup)
156
140
  end
@@ -164,16 +148,6 @@ module Kitchen
164
148
  # UTF-16 string which will double the string size.
165
149
  MAX_COMMAND_SIZE = 3000
166
150
 
167
- RESCUE_EXCEPTIONS_ON_ESTABLISH = lambda do
168
- [
169
- Errno::EACCES, Errno::EADDRINUSE, Errno::ECONNREFUSED, Errno::ETIMEDOUT,
170
- Errno::ECONNRESET, Errno::ENETUNREACH, Errno::EHOSTUNREACH,
171
- ::WinRM::WinRMHTTPTransportError, ::WinRM::WinRMAuthorizationError,
172
- HTTPClient::KeepAliveDisconnected,
173
- HTTPClient::ConnectTimeoutError
174
- ].freeze
175
- end
176
-
177
151
  # @return [Integer] how many times to retry when failing to execute
178
152
  # a command or transfer files
179
153
  # @api private
@@ -235,31 +209,6 @@ module Kitchen
235
209
  end
236
210
  end
237
211
 
238
- # Establish a remote shell session on the remote host.
239
- #
240
- # @param opts [Hash] retry options
241
- # @option opts [Integer] :retries the number of times to retry before
242
- # failing
243
- # @option opts [Float] :delay the number of seconds to wait until
244
- # attempting a retry
245
- # @option opts [String] :message an optional message to be logged on
246
- # debug (overriding the default) when a rescuable exception is raised
247
- # @return [Winrm::CommandExecutor] the command executor session
248
- # @api private
249
- def establish_shell(opts)
250
- service_args = [endpoint, winrm_transport, options]
251
- @service = ::WinRM::WinRMWebService.new(*service_args)
252
- closer = WinRM::Transport::ShellCloser.new("#{self}", logger.debug?, service_args)
253
-
254
- executor = WinRM::Transport::CommandExecutor.new(@service, logger, closer)
255
- retryable(opts) do
256
- logger.debug("[WinRM] opening remote shell on #{self}")
257
- shell_id = executor.open
258
- logger.debug("[WinRM] remote shell #{shell_id} is open on #{self}")
259
- end
260
- executor
261
- end
262
-
263
212
  # Execute a Powershell script over WinRM and return the command's
264
213
  # exit code and standard error.
265
214
  #
@@ -278,7 +227,7 @@ module Kitchen
278
227
  # @return [Winrm::FileTransporter] a file transporter
279
228
  # @api private
280
229
  def file_transporter
281
- @file_transporter ||= WinRM::Transport::FileTransporter.new(session, logger)
230
+ @file_transporter ||= WinRM::FS::Core::FileTransporter.new(session)
282
231
  end
283
232
 
284
233
  # (see Base#init_options)
@@ -353,38 +302,6 @@ module Kitchen
353
302
  File.join(kitchen_root, ".kitchen", "#{instance_name}.rdp")
354
303
  end
355
304
 
356
- # Yields to a block and reties the block if certain rescuable
357
- # exceptions are raised.
358
- #
359
- # @param opts [Hash] retry options
360
- # @option opts [Integer] :retries the number of times to retry before
361
- # failing
362
- # @option opts [Float] :delay the number of seconds to wait until
363
- # attempting a retry
364
- # @option opts [String] :message an optional message to be logged on
365
- # debug (overriding the default) when a rescuable exception is raised
366
- # @return [Winrm::CommandExecutor] the command executor session
367
- # @api private
368
- def retryable(opts)
369
- yield
370
- rescue *RESCUE_EXCEPTIONS_ON_ESTABLISH.call => e
371
- if (opts[:retries] -= 1) > 0
372
- message = if opts[:message]
373
- logger.debug("[WinRM] connection failed (#{e.inspect})")
374
- opts[:message]
375
- else
376
- "[WinRM] connection failed, " \
377
- "retrying in #{opts[:delay]} seconds (#{e.inspect})"
378
- end
379
- logger.info(message)
380
- sleep(opts[:delay])
381
- retry
382
- else
383
- logger.warn("[WinRM] connection failed, terminating (#{e.inspect})")
384
- raise
385
- end
386
- end
387
-
388
305
  # Establishes a remote shell session, or establishes one when invoked
389
306
  # the first time.
390
307
  #
@@ -392,10 +309,17 @@ module Kitchen
392
309
  # @return [Winrm::CommandExecutor] the command executor session
393
310
  # @api private
394
311
  def session(retry_options = {})
395
- @session ||= establish_shell({
396
- :retries => connection_retries.to_i,
397
- :delay => connection_retry_sleep.to_i
398
- }.merge(retry_options))
312
+ @session ||= begin
313
+ opts = {
314
+ :retry_limit => connection_retries.to_i,
315
+ :retry_delay => connection_retry_sleep.to_i
316
+ }.merge(retry_options)
317
+
318
+ service_args = [endpoint, winrm_transport, options.merge(opts)]
319
+ @service = ::WinRM::WinRMWebService.new(*service_args)
320
+ @service.logger = logger
321
+ @service.create_executor
322
+ end
399
323
  end
400
324
 
401
325
  # String representation of object, reporting its connection details and
@@ -425,7 +349,7 @@ module Kitchen
425
349
  target_path = File.join("$env:TEMP", "kitchen")
426
350
  upload(script_path, target_path)
427
351
 
428
- %{& "#{File.join(target_path, script_name)}"}
352
+ %{powershell -ExecutionPolicy Bypass -File "#{File.join(target_path, script_name)}"}
429
353
  ensure
430
354
  FileUtils.rmtree(temp_dir)
431
355
  end
@@ -434,7 +358,8 @@ module Kitchen
434
358
 
435
359
  private
436
360
 
437
- WINRM_TRANSPORT_SPEC_VERSION = ["~> 1.0", ">= 1.0.3"].freeze
361
+ WINRM_SPEC_VERSION = ["~> 1.6"].freeze
362
+ WINRM_FS_SPEC_VERSION = ["~> 0.3"].freeze
438
363
 
439
364
  # Builds the hash of options needed by the Connection object on
440
365
  # construction.
@@ -461,8 +386,8 @@ module Kitchen
461
386
  end
462
387
 
463
388
  def additional_transport_args(transport_type)
464
- case transport_type
465
- when :ssl, :sspinegotiate
389
+ case transport_type.to_sym
390
+ when :ssl, :negotiate
466
391
  {
467
392
  :no_ssl_peer_verification => true,
468
393
  :disable_sspi => false,
@@ -473,6 +398,8 @@ module Kitchen
473
398
  :disable_sspi => true,
474
399
  :basic_auth_only => true
475
400
  }
401
+ else
402
+ {}
476
403
  end
477
404
  end
478
405
 
@@ -495,66 +422,27 @@ module Kitchen
495
422
  # (see Base#load_needed_dependencies!)
496
423
  def load_needed_dependencies!
497
424
  super
498
- load_winrm_transport!
499
- load_winrm_s! if host_os_windows?
500
- end
501
-
502
- # Load WinRM::Transport code.
503
- #
504
- # @api private
505
- def load_winrm_transport!
506
- spec_version = WINRM_TRANSPORT_SPEC_VERSION.dup
507
- options = {
508
- :load_msg => "Winrm Transport requested," \
509
- " loading WinRM::Transport gem (#{spec_version})",
510
- :success_msg => "WinRM::Transport library loaded",
511
- :already_msg => "WinRM::Transport previously loaded",
512
- :name => "winrm-transport",
513
- :version => spec_version
514
- }
515
-
516
- load_with_rescue!(options) do
517
- gem "winrm-transport", WINRM_TRANSPORT_SPEC_VERSION.dup
518
- require "winrm/transport/version"
519
- end
520
-
521
- silence_warnings { require "winrm" }
522
- require "winrm/transport/shell_closer"
523
- require "winrm/transport/command_executor"
524
- require "winrm/transport/file_transporter"
525
- end
526
-
527
- def load_winrm_s!
528
- options = {
529
- :load_msg => "The winrm-s gem is being loaded" \
530
- " to enable sspiauthentication.",
531
- :success_msg => "winrm-s is loaded." \
532
- " sspinegotiate auth is now available.",
533
- :already_msg => "winrm-s was already loaded.",
534
- :name => "winrm-s"
535
- }
536
-
537
- load_with_rescue!(options) { require "winrm-s" }
425
+ load_with_rescue!("winrm", WINRM_SPEC_VERSION.dup)
426
+ load_with_rescue!("winrm-fs", WINRM_FS_SPEC_VERSION.dup)
538
427
  end
539
428
 
540
- def load_with_rescue!(options = {}, &block)
541
- logger.debug(options[:load_msg])
542
- attempt_load = execute_block(&block)
429
+ def load_with_rescue!(gem_name, spec_version)
430
+ logger.debug("#{gem_name} requested," \
431
+ " loading #{gem_name} gem (#{spec_version})")
432
+ attempt_load = false
433
+ gem gem_name, spec_version
434
+ silence_warnings { attempt_load = require gem_name }
543
435
  if attempt_load
544
- logger.debug(options[:success_msg])
436
+ logger.debug("#{gem_name} is loaded.")
545
437
  else
546
- logger.debug(options[:already_msg])
438
+ logger.debug("#{gem_name} was already loaded.")
547
439
  end
548
440
  rescue LoadError => e
549
- message = fail_to_load_gem_message(options[:name],
550
- options[:version])
441
+ message = fail_to_load_gem_message(gem_name,
442
+ spec_version)
551
443
  logger.fatal(message)
552
444
  raise UserError,
553
- "Could not load or activate #{options[:name]}. (#{e.message})"
554
- end
555
-
556
- def execute_block
557
- yield if block_given?
445
+ "Could not load or activate #{gem_name}. (#{e.message})"
558
446
  end
559
447
 
560
448
  def fail_to_load_gem_message(name, version = nil)