Class: Kitchen::Driver::Vagrant

Inherits:
Base
  • Object
show all
Includes:
HypervHelpers, ShellOut
Defined in:
lib/kitchen/driver/vagrant.rb

Overview

Vagrant driver for Kitchen. It communicates to Vagrant via the CLI.

Author:

Constant Summary collapse

LIVE_STATES =

Machine states Vagrant reports for a box that is up and reachable.

Returns:

  • (Array<String>)
%w{running}.freeze

Class Attribute Summary collapse

Instance Method Summary collapse

Methods included from HypervHelpers

#encode_command, #execute_command, #hyperv_default_switch_ps, #hyperv_switch, #is_32bit?, #is_64bit?, #os_architecture, #powershell_64_bit, #ruby_64bit?, #run_ps, #sanitize_stdout, #wrap_command

Class Attribute Details

.vagrant_versionString?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Memoises vagrant --version for the life of the process, so that every instance in a multi-instance run shells out at most once.

Returns:

  • (String, nil)

    the version of Vagrant installed on the workstation, or nil before anything has looked it up



318
319
320
# File 'lib/kitchen/driver/vagrant.rb', line 318

def vagrant_version
  @vagrant_version
end

Instance Method Details

#cache_directoryString, false

The guest-side directory that the host's omnibus package cache should be shared into, so repeated converges do not re-download packages.

Returns:

  • (String, false)

    the guest path, or false if caching does not apply to this box and provider combination



295
296
297
298
299
300
301
# File 'lib/kitchen/driver/vagrant.rb', line 295

def cache_directory
  if enable_cache?
    config[:cache_directory]
  else
    false
  end
end

#create(state) ⇒ void

This method returns an undefined value.

Creates a Vagrant VM instance.

Parameters:

  • state (Hash)

    mutable instance state

Raises:

  • (ActionFailed)

    if the action could not be completed



132
133
134
135
136
137
138
139
140
141
142
# File 'lib/kitchen/driver/vagrant.rb', line 132

def create(state)
  create_vagrantfile
  run_pre_create_command
  check_box_outdated
  run_box_auto_update
  run_box_auto_prune
  run_vagrant_up
  update_state(state)
  instance.transport.connection(state).wait_until_ready
  info("Vagrant instance #{instance.to_str} created.")
end

#default_boxString?

The box this Instance should use when the user has not named one.

Platforms the Bento project builds are mapped onto their bento/ box; anything else is assumed to name a box directly.

Returns:

  • (String, nil)

    the Vagrant box for this Instance



150
151
152
153
154
155
156
# File 'lib/kitchen/driver/vagrant.rb', line 150

def default_box
  if bento_box?(instance.platform.name)
    "bento/#{instance.platform.name}"
  else
    instance.platform.name
  end
end

#default_box_urlString?

The box URL this Instance should use when the user has not named one.

Always nil: modern Vagrant resolves boxes through Vagrant Cloud, so an explicit URL is only needed for privately hosted boxes.

Returns:

  • (String, nil)

    the Vagrant box URL for this Instance



164
165
166
# File 'lib/kitchen/driver/vagrant.rb', line 164

def default_box_url
  nil
end

#destroy(state) ⇒ void

This method returns an undefined value.

Destroys an instance.

Parameters:

  • state (Hash)

    mutable instance state

Raises:

  • (ActionFailed)

    if the action could not be completed



173
174
175
176
177
178
179
180
181
182
183
# File 'lib/kitchen/driver/vagrant.rb', line 173

def destroy(state)
  return if state[:hostname].nil?

  create_vagrantfile
  @vagrantfile_created = false
  instance.transport.connection(state).close
  run("#{config[:vagrant_binary]} destroy -f")
  FileUtils.rm_rf(vagrant_root)
  info("Vagrant instance #{instance.to_str} destroyed.")
  state.delete(:hostname)
end

#doctor(state) ⇒ Boolean

Checks the host-side things a Vagrant run needs, reporting rather than raising so kitchen doctor can list every problem at once.

#verify_dependencies already raises on an old or absent Vagrant, but it only runs on the actions that need it. This repeats the version rule as a report and adds the file and folder checks that nothing validates today.

Parameters:

  • state (Hash)

    mutable instance and driver state

Returns:

  • (Boolean)

    true when a problem was reported



276
277
278
279
280
281
# File 'lib/kitchen/driver/vagrant.rb', line 276

def doctor(state) # rubocop:disable Lint/UnusedMethodArgument
  problems = vagrant_problems + template_problems + synced_folder_problems

  problems.each { |problem| warn(problem) }
  !problems.empty?
end

#finalize_config!(instance) ⇒ self

A lifecycle method that should be invoked when the object is about ready to be used. A reference to an Instance is required as configuration dependant data may be access through an Instance. This also acts as a hook point where the object may wish to perform other last minute checks, validations, or configuration expansions.

Parameters:

  • instance (Instance)

    an associated instance

Returns:

  • (self)

    itself, for use in chaining

Raises:

  • (ClientError)

    if instance parameter is nil



237
238
239
240
241
242
243
244
245
246
247
# File 'lib/kitchen/driver/vagrant.rb', line 237

def finalize_config!(instance)
  super
  finalize_vm_hostname!
  finalize_box_auto_update!
  finalize_box_auto_prune!
  finalize_pre_create_command!
  finalize_synced_folders!
  finalize_ca_cert!
  finalize_network!
  self
end

#package(state) ⇒ void

This method returns an undefined value.

Packages a created instance into a redistributable .box file in the current working directory, then destroys the instance.

Parameters:

  • state (Hash)

    mutable instance state

Raises:

  • (UserError)

    if the instance has not been created

  • (ActionFailed)

    if the action could not be completed



192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/kitchen/driver/vagrant.rb', line 192

def package(state)
  if state[:hostname].nil?
    raise UserError, "Vagrant instance not created!"
  end

  unless config[:ssh] && config[:ssh][:insert_key] == false
    m = "Disable vagrant ssh key replacement to preserve the default key!"
    warn(m)
  end
  instance.transport.connection(state).close
  box_name = File.join(Dir.pwd, instance.name + ".box")
  run("#{config[:vagrant_binary]} package --output #{box_name}")
  destroy(state)
end

#status(state) ⇒ Hash

Reports what Vagrant currently thinks of the machine.

Parameters:

  • state (Hash)

    instance state naming the machine

Returns:

  • (Hash)

    a Test Kitchen status hash, or the base implementation's answer when there is nothing to ask Vagrant about



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/kitchen/driver/vagrant.rb', line 212

def status(state)
  return super unless state[:hostname]

  machine_state = vagrant_machine_state
  return super unless machine_state

  {
    live: LIVE_STATES.include?(machine_state),
    state: machine_state,
    source: "driver",
    resource_id: instance.name,
    message: "Vagrant reports the machine as #{machine_state}",
    checked_at: Time.now.utc.iso8601,
  }
end

#verify_dependenciesvoid

This method returns an undefined value.

Performs whatever tests that may be required to ensure that this driver will be able to function in the current environment. This may involve checking for the presence of certain directories, software installed, etc.

Raises:

  • (UserError)

    if the driver will not be able to perform or if a documented dependency is missing from the system



257
258
259
260
261
262
263
264
# File 'lib/kitchen/driver/vagrant.rb', line 257

def verify_dependencies
  super
  if Gem::Version.new(vagrant_version) < Gem::Version.new(MIN_VER.dup)
    raise UserError, "Detected an old version of Vagrant " \
      "(#{vagrant_version})." \
      " Please upgrade to version #{MIN_VER} or higher from #{WEBSITE}."
  end
end

#winrm_transport?TrueClass, FalseClass

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns whether or not the transport's name implies a WinRM-based transport.

Returns:

  • (TrueClass, FalseClass)

    whether or not the transport's name implies a WinRM-based transport



286
287
288
# File 'lib/kitchen/driver/vagrant.rb', line 286

def winrm_transport?
  instance.transport.name.downcase =~ /win_?rm/
end