Class: Kitchen::Provisioner::Base

Inherits:
Kitchen::Plugin::Base show all
Includes:
Configurable, Logging
Defined in:
lib/kitchen/provisioner/base.rb

Overview

Base class for a provisioner.

Author:

Direct Known Subclasses

ChefBase, Dummy, Shell

Instance Attribute Summary

Attributes included from Configurable

#instance

Class Method Summary collapse

Instance Method Summary collapse

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 = {}) ⇒ Base

Constructs a new provisioner by providing a configuration hash.



62
63
64
# File 'lib/kitchen/provisioner/base.rb', line 62

def initialize(config = {})
  init_config(config)
end

Class Method Details

.kitchen_provisioner_api_version(version) ⇒ Object

Sets the API version for this provisioner. If the provisioner does not set this value, then ‘nil` will be used and reported.

Sets the API version for this provisioner

Examples:

setting an API version


module Kitchen
  module Provisioner
    class NewProvisioner < Kitchen::Provisioner::Base

      kitchen_provisioner_api_version 2

    end
  end
end


240
241
242
# File 'lib/kitchen/provisioner/base.rb', line 240

def self.kitchen_provisioner_api_version(version)
  @api_version = version
end

Instance Method Details

#call(state) ⇒ Object

Runs the provisioner on the instance.

rubocop:disable Metrics/AbcSize

Raises:



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/kitchen/provisioner/base.rb', line 71

def call(state)
  create_sandbox
  prepare_install_script

  instance.transport.connection(state) do |conn|
    config[:uploads].to_h.each do |locals, remote|
      debug("Uploading #{Array(locals).join(", ")} to #{remote}")
      conn.upload(locals.to_s, remote)
    end

    # Run the init command to create the kitchen tmp directory
    conn.execute(encode_for_powershell(init_command))

    # Upload the install script instead of directly executing the command
    if install_command
      script_filename = windows_os? ? "install_script.ps1" : "install_script"
      remote_script_path = remote_path_join(resolve_remote_path(config[:root_path]), script_filename)
      if install_script_path
        debug("Uploading install script to #{remote_script_path}")
        conn.upload(install_script_path, remote_script_path)
        # Make script executable on remote host
        conn.execute(make_executable_command(remote_script_path))
        # Execute the uploaded script
        conn.execute(run_script_command(remote_script_path))
      end
    end

    # The install script will remove the kitchen tmp directory, hence creating it again.
    conn.execute(init_command)
    info("Transferring files to #{instance.to_str}")
    conn.upload(sandbox_dirs, resolve_remote_path(config[:root_path]))
    debug("Transfer complete")
    conn.execute(prepare_command)
    conn.execute_with_retry(
      encode_for_powershell(run_command),
      config[:retry_on_exit_code],
      config[:max_retries],
      config[:wait_for_retry]
    )
    info("Downloading files from #{instance.to_str}")
    config[:downloads].to_h.each do |remotes, local|
      debug("Downloading #{Array(remotes).join(", ")} to #{local}")
      conn.download(remotes, local)
    end
    debug("Download complete")
  end
rescue Kitchen::Transport::TransportFailed => ex
  raise ActionFailed, ex.message
ensure
  cleanup_sandbox
end

#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.



134
# File 'lib/kitchen/provisioner/base.rb', line 134

def check_license; end

#cleanup_sandboxObject

Deletes the sandbox path. Without calling this method, the sandbox path will persist after the process terminates. In other words, cleanup is explicit. This method is safe to call multiple times.



213
214
215
216
217
218
219
# File 'lib/kitchen/provisioner/base.rb', line 213

def cleanup_sandbox
  return if sandbox_path.nil?

  debug("Cleaning up local sandbox in #{sandbox_path}")
  @install_script_path = nil
  FileUtils.rmtree(sandbox_path)
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


184
185
186
187
188
189
# File 'lib/kitchen/provisioner/base.rb', line 184

def create_sandbox
  @sandbox_path = Dir.mktmpdir("#{instance.name}-sandbox-")
  File.chmod(0755, sandbox_path)
  info("Preparing files for transfer")
  debug("Creating local sandbox in #{sandbox_path}")
end

#doctor(state) ⇒ Object

Check system and configuration for common errors.



127
128
129
# File 'lib/kitchen/provisioner/base.rb', line 127

def doctor(state)
  false
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.



149
# File 'lib/kitchen/provisioner/base.rb', line 149

def 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.



141
# File 'lib/kitchen/provisioner/base.rb', line 141

def install_command; end

#prepare_commandString

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



157
# File 'lib/kitchen/provisioner/base.rb', line 157

def prepare_command; end

#run_commandString

Generates a command string which will invoke the main provisioner command on the prepared instance. If no work is required, then ‘nil` will be returned.



164
# File 'lib/kitchen/provisioner/base.rb', line 164

def run_command; end

#sandbox_dirsString

Returns the list of items in the sandbox directory



206
207
208
# File 'lib/kitchen/provisioner/base.rb', line 206

def sandbox_dirs
  Util.list_directory(sandbox_path)
end

#sandbox_pathString

Returns the absolute path to the sandbox directory or raises an exception if ‘#create_sandbox` has not yet been called.

Raises:

  • (ClientError)

    if the sandbox directory has no yet been created by calling ‘#create_sandbox`



197
198
199
200
201
# File 'lib/kitchen/provisioner/base.rb', line 197

def sandbox_path
  @sandbox_path ||= raise ClientError, "Sandbox directory has not yet " \
    "been created. Please run #{self.class}#create_sandox before " \
    "trying to access the path."
end