Class: Kitchen::Provisioner::ChefBase

Inherits:
Base show all
Defined in:
lib/kitchen/provisioner/chef_base.rb

Overview

Common implementation details for Chef-related provisioners.

Author:

Direct Known Subclasses

ChefApply, ChefInfra, ChefSolo

Instance Attribute Summary

Attributes included from Configurable

#instance

Instance Method Summary collapse

Methods inherited from Base

#call, #cleanup_sandbox, kitchen_provisioner_api_version, #prepare_command, #run_command, #sandbox_dirs, #sandbox_path

Methods included from Logging

#banner, #debug, #error, #fatal, #info, #warn

Methods included from Configurable

#[], #bourne_shell?, #calculate_path, #config_keys, #diagnose, #diagnose_plugin, #finalize_config!, included, #name, #powershell_shell?, #remote_path_join, #unix_os?, #verify_dependencies, #windows_os?

Methods inherited from Kitchen::Plugin::Base

no_parallel_for

Constructor Details

#initialize(config = {}) ⇒ ChefBase

Reads the local Chef::Config object (if present). We do this because we want to start bring Chef config and Chef Workstation config closer together. For example, we want to configure proxy settings in 1 location instead of 3 configuration files.

Parameters:

  • config (Hash) (defaults to: {})

    initial provided configuration



235
236
237
238
239
240
241
242
243
244
# File 'lib/kitchen/provisioner/chef_base.rb', line 235

def initialize(config = {})
  super(config)

  if defined?(ChefConfig::WorkstationConfigLoader)
    ChefConfig::WorkstationConfigLoader.new(config[:config_path]).load
  end
  # This exports any proxy config present in the Chef config to
  # appropriate environment variables, which Test Kitchen respects
  ChefConfig::Config.export_proxies if defined?(ChefConfig::Config.export_proxies)
end

Instance Method Details

#check_licenseObject

Certain products that Test Kitchen uses to provision require accepting a license to use. Overwrite this method in the specific provisioner to implement this check.



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/kitchen/provisioner/chef_base.rb', line 286

def check_license
  name = license_acceptance_id
  version = product_version
  debug("Checking if we need to prompt for license acceptance on product: #{name} version: #{version}.")

  acceptor = LicenseAcceptance::Acceptor.new(logger: Kitchen.logger, provided: config[:chef_license])
  if acceptor.license_required?(name, version)
    debug("License acceptance required for #{name} version: #{version}. Prompting")
    license_id = acceptor.id_from_mixlib(name)
    begin
      acceptor.check_and_persist(license_id, version.to_s)
    rescue LicenseAcceptance::LicenseNotAcceptedError => e
      error("Cannot converge without accepting the #{e.product.pretty_name} License. Set it in your kitchen.yml or using the CHEF_LICENSE environment variable")
      raise
    end
    config[:chef_license] ||= acceptor.acceptance_value
  end
end

#create_sandboxObject

Creates a temporary directory on the local workstation into which provisioner related files and directories can be copied or created. The contents of this directory will be copied over to the instance before invoking the provisioner’s run command. After this method completes, it is expected that the contents of the sandbox is complete and ready for copy to the remote instance.

Note: any subclasses would be well advised to call super first when overriding this method, for example:

Examples:

overriding ‘#create_sandbox`


class MyProvisioner < Kitchen::Provisioner::Base
  def create_sandbox
    super
    # any further file copies, preparations, etc.
  end
end


306
307
308
309
310
# File 'lib/kitchen/provisioner/chef_base.rb', line 306

def create_sandbox
  super
  sanity_check_sandbox_options!
  Chef::CommonSandbox.new(config, sandbox_path, instance).populate
end

#doctor(state) ⇒ Object



246
247
248
249
250
251
# File 'lib/kitchen/provisioner/chef_base.rb', line 246

def doctor(state)
  deprecated_config = instance.driver.instance_variable_get(:@deprecated_config)
  deprecated_config.each do |attr, msg|
    info("**** #{attr} deprecated\n#{msg}")
  end
end

#init_commandString

Generates a command string which will perform any data initialization or configuration required after the provisioner software is installed but before the sandbox has been transferred to the instance. If no work is required, then ‘nil` will be returned.

Returns:

  • (String)

    a command string



313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/kitchen/provisioner/chef_base.rb', line 313

def init_command
  dirs = %w{
    cookbooks data data_bags environments roles clients
    encrypted_data_bag_secret
  }.sort.map { |dir| remote_path_join(config[:root_path], dir) }

  vars = if powershell_shell?
           init_command_vars_for_powershell(dirs)
         else
           init_command_vars_for_bourne(dirs)
         end

  prefix_command(shell_code_from_file(vars, "chef_base_init_command"))
end

#install_commandString

Generates a command string which will install and configure the provisioner software on an instance. If no work is required, then ‘nil` will be returned.

Returns:

  • (String)

    a command string



329
330
331
332
333
334
# File 'lib/kitchen/provisioner/chef_base.rb', line 329

def install_command
  return unless config[:require_chef_omnibus] || config[:product_name]
  return if config[:product_name] && config[:install_strategy] == "skip"

  prefix_command(install_script_contents)
end

#license_acceptance_idString

If the user has policyfiles we shell out to the ‘chef` executable, so need to ensure they have accepted the Chef Workstation license. Otherwise they just need the Chef Infra license.

Returns:

  • (String)

    license id to prompt for acceptance



274
275
276
277
278
279
280
281
282
283
# File 'lib/kitchen/provisioner/chef_base.rb', line 274

def license_acceptance_id
  case
    when File.exist?(policyfile)
      "chef-workstation"
    when config[:product_name]
      config[:product_name]
    else
      "chef"
  end
end

#product_versionString, ...

gives us the product version from either require_chef_omnibus or product_version If the non-default (true) value of require_chef_omnibus is present use that otherwise use config which defaults to :latest and is the actual default for chef provisioners

Returns:

  • (String, Symbol, NilClass)

    version or nil if not applicable



259
260
261
262
263
264
265
266
267
268
# File 'lib/kitchen/provisioner/chef_base.rb', line 259

def product_version
  case config[:require_chef_omnibus]
  when FalseClass
    nil
  when TrueClass
    config[:product_version]
  else
    config[:require_chef_omnibus]
  end
end