kitchen-vagrant 2.3.0 → 2.4.1
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.
- checksums.yaml +4 -4
- data/lib/kitchen/driver/helpers.rb +1 -1
- data/lib/kitchen/driver/vagrant.rb +178 -11
- data/lib/kitchen/driver/vagrant_version.rb +1 -1
- data/templates/Vagrantfile.erb +5 -1
- metadata +4 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6ded9303b651d9e3d46c4d56a805da70902c941946e6f034635e3ccedef10e37
|
|
4
|
+
data.tar.gz: 721a9bdf7801068039a3e4a446f92866e90601fc86f35cf4e4d6a284b62fb95b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67975ca9f88c44ab626a92acdd66ea6fe077da509ac856c76c1b40f0f36391a33d3d9b55332bd8ad84ccce722ad550460f7072338ef7ae27d240cccc3d920827
|
|
7
|
+
data.tar.gz: 856a7d25b3a15cb4792f07f69b1b20b4c957bf5eaa062f1cfa05a9fe32bd810522072eb46ee88915ebbe4149851b387e8e2b8708df9b66c796daaa7b7c00479c
|
|
@@ -127,7 +127,7 @@ module Kitchen
|
|
|
127
127
|
# @param cmd [String] command to run locally
|
|
128
128
|
# @param options [Hash] options hash
|
|
129
129
|
# @return [Hash,nil] the parsed JSON the script emitted, if any
|
|
130
|
-
# @see Kitchen::ShellOut
|
|
130
|
+
# @see Kitchen::ShellOut#run_command
|
|
131
131
|
# @api private
|
|
132
132
|
def run_ps(cmd, options = {})
|
|
133
133
|
cmd = "echo #{cmd}" if config[:dry_run]
|
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
require "erb" unless defined?(Erb)
|
|
19
19
|
require "fileutils" unless defined?(FileUtils)
|
|
20
20
|
require "rubygems/version"
|
|
21
|
+
# Chefstyle's Chef/Ruby/UnlessDefinedRequire wants this guard, even though the
|
|
22
|
+
# guard's other branch is unreachable: kitchen has already loaded "time" by here.
|
|
23
|
+
require "time" unless defined?(Time.now.iso8601)
|
|
21
24
|
|
|
22
25
|
require "kitchen"
|
|
23
26
|
require_relative "vagrant_version"
|
|
@@ -31,6 +34,10 @@ module Kitchen
|
|
|
31
34
|
#
|
|
32
35
|
# @author Fletcher Nichol <fnichol@nichol.ca>
|
|
33
36
|
class Vagrant < Kitchen::Driver::Base
|
|
37
|
+
# Machine states Vagrant reports for a box that is up and reachable.
|
|
38
|
+
#
|
|
39
|
+
# @return [Array<String>]
|
|
40
|
+
LIVE_STATES = %w{running}.freeze
|
|
34
41
|
|
|
35
42
|
include ShellOut
|
|
36
43
|
include Kitchen::Driver::HypervHelpers
|
|
@@ -101,11 +108,17 @@ module Kitchen
|
|
|
101
108
|
driver.windows_os? ? "/omnibus/cache" : "/tmp/omnibus/cache"
|
|
102
109
|
end
|
|
103
110
|
|
|
104
|
-
#
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
111
|
+
# Resolved per instance rather than when this file is loaded, so that
|
|
112
|
+
# `VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH` is read at the moment the
|
|
113
|
+
# driver needs it -- the same way `:provider` reads
|
|
114
|
+
# `VAGRANT_DEFAULT_PROVIDER`. Reading it eagerly froze one value into the
|
|
115
|
+
# class for the life of the process, which is wrong for anything that
|
|
116
|
+
# sets the variable after the driver has been required, and made the
|
|
117
|
+
# setting impossible to exercise.
|
|
118
|
+
default_config(:kitchen_cache_directory) do |_|
|
|
119
|
+
user_home = ENV["VAGRANT_WSL_WINDOWS_ACCESS_USER_HOME_PATH"] || "~"
|
|
108
120
|
File.expand_path("#{user_home}/.kitchen/cache")
|
|
121
|
+
end
|
|
109
122
|
|
|
110
123
|
default_config :cachier, nil
|
|
111
124
|
|
|
@@ -114,6 +127,7 @@ module Kitchen
|
|
|
114
127
|
# Creates a Vagrant VM instance.
|
|
115
128
|
#
|
|
116
129
|
# @param state [Hash] mutable instance state
|
|
130
|
+
# @return [void]
|
|
117
131
|
# @raise [ActionFailed] if the action could not be completed
|
|
118
132
|
def create(state)
|
|
119
133
|
create_vagrantfile
|
|
@@ -154,6 +168,7 @@ module Kitchen
|
|
|
154
168
|
# Destroys an instance.
|
|
155
169
|
#
|
|
156
170
|
# @param state [Hash] mutable instance state
|
|
171
|
+
# @return [void]
|
|
157
172
|
# @raise [ActionFailed] if the action could not be completed
|
|
158
173
|
def destroy(state)
|
|
159
174
|
return if state[:hostname].nil?
|
|
@@ -171,6 +186,7 @@ module Kitchen
|
|
|
171
186
|
# current working directory, then destroys the instance.
|
|
172
187
|
#
|
|
173
188
|
# @param state [Hash] mutable instance state
|
|
189
|
+
# @return [void]
|
|
174
190
|
# @raise [UserError] if the instance has not been created
|
|
175
191
|
# @raise [ActionFailed] if the action could not be completed
|
|
176
192
|
def package(state)
|
|
@@ -188,6 +204,27 @@ module Kitchen
|
|
|
188
204
|
destroy(state)
|
|
189
205
|
end
|
|
190
206
|
|
|
207
|
+
# Reports what Vagrant currently thinks of the machine.
|
|
208
|
+
#
|
|
209
|
+
# @param state [Hash] instance state naming the machine
|
|
210
|
+
# @return [Hash] a Test Kitchen status hash, or the base implementation's
|
|
211
|
+
# answer when there is nothing to ask Vagrant about
|
|
212
|
+
def status(state)
|
|
213
|
+
return super unless state[:hostname]
|
|
214
|
+
|
|
215
|
+
machine_state = vagrant_machine_state
|
|
216
|
+
return super unless machine_state
|
|
217
|
+
|
|
218
|
+
{
|
|
219
|
+
live: LIVE_STATES.include?(machine_state),
|
|
220
|
+
state: machine_state,
|
|
221
|
+
source: "driver",
|
|
222
|
+
resource_id: instance.name,
|
|
223
|
+
message: "Vagrant reports the machine as #{machine_state}",
|
|
224
|
+
checked_at: Time.now.utc.iso8601,
|
|
225
|
+
}
|
|
226
|
+
end
|
|
227
|
+
|
|
191
228
|
# A lifecycle method that should be invoked when the object is about
|
|
192
229
|
# ready to be used. A reference to an Instance is required as
|
|
193
230
|
# configuration dependant data may be access through an Instance. This
|
|
@@ -214,6 +251,7 @@ module Kitchen
|
|
|
214
251
|
# checking for the presence of certain directories, software installed,
|
|
215
252
|
# etc.
|
|
216
253
|
#
|
|
254
|
+
# @return [void]
|
|
217
255
|
# @raise [UserError] if the driver will not be able to perform or if a
|
|
218
256
|
# documented dependency is missing from the system
|
|
219
257
|
def verify_dependencies
|
|
@@ -225,6 +263,23 @@ module Kitchen
|
|
|
225
263
|
end
|
|
226
264
|
end
|
|
227
265
|
|
|
266
|
+
# Checks the host-side things a Vagrant run needs, reporting rather than
|
|
267
|
+
# raising so `kitchen doctor` can list every problem at once.
|
|
268
|
+
#
|
|
269
|
+
# {#verify_dependencies} already raises on an old or absent Vagrant, but
|
|
270
|
+
# it only runs on the actions that need it. This repeats the version rule
|
|
271
|
+
# as a report and adds the file and folder checks that nothing validates
|
|
272
|
+
# today.
|
|
273
|
+
#
|
|
274
|
+
# @param state [Hash] mutable instance and driver state
|
|
275
|
+
# @return [Boolean] true when a problem was reported
|
|
276
|
+
def doctor(state) # rubocop:disable Lint/UnusedMethodArgument
|
|
277
|
+
problems = vagrant_problems + template_problems + synced_folder_problems
|
|
278
|
+
|
|
279
|
+
problems.each { |problem| warn(problem) }
|
|
280
|
+
!problems.empty?
|
|
281
|
+
end
|
|
282
|
+
|
|
228
283
|
# @return [TrueClass,FalseClass] whether or not the transport's name
|
|
229
284
|
# implies a WinRM-based transport
|
|
230
285
|
# @api private
|
|
@@ -254,9 +309,20 @@ module Kitchen
|
|
|
254
309
|
MIN_VER = "2.4.0".freeze
|
|
255
310
|
|
|
256
311
|
class << self
|
|
257
|
-
#
|
|
312
|
+
# Memoises `vagrant --version` for the life of the process, so that
|
|
313
|
+
# every instance in a multi-instance run shells out at most once.
|
|
314
|
+
#
|
|
315
|
+
# @return [String,nil] the version of Vagrant installed on the
|
|
316
|
+
# workstation, or nil before anything has looked it up
|
|
258
317
|
# @api private
|
|
259
318
|
attr_accessor :vagrant_version
|
|
319
|
+
|
|
320
|
+
# @!method self.vagrant_version=(value)
|
|
321
|
+
# Records the version of Vagrant found on the workstation.
|
|
322
|
+
#
|
|
323
|
+
# @param value [String] the version string to memoise
|
|
324
|
+
# @return [String] the version string just stored
|
|
325
|
+
# @api private
|
|
260
326
|
end
|
|
261
327
|
|
|
262
328
|
# Returns whether or not a platform name could have a corresponding Bento
|
|
@@ -376,6 +442,7 @@ module Kitchen
|
|
|
376
442
|
|
|
377
443
|
# Replaces any `{{vagrant_root}}` tokens in the pre create command.
|
|
378
444
|
#
|
|
445
|
+
# @return [void]
|
|
379
446
|
# @api private
|
|
380
447
|
def finalize_pre_create_command!
|
|
381
448
|
return if config[:pre_create_command].nil?
|
|
@@ -503,11 +570,98 @@ module Kitchen
|
|
|
503
570
|
end
|
|
504
571
|
end
|
|
505
572
|
|
|
506
|
-
#
|
|
573
|
+
# Asks Vagrant for the machine state.
|
|
574
|
+
#
|
|
575
|
+
# `--machine-readable` is parsed rather than the human output because the
|
|
576
|
+
# human wording is localised and reworded between Vagrant releases, while
|
|
577
|
+
# the machine format is a stable comma-separated
|
|
578
|
+
# `timestamp,target,type,data` and the `state` row carries the raw value
|
|
579
|
+
# (`running`, `poweroff`, `not_created`, ...).
|
|
580
|
+
#
|
|
581
|
+
# @return [String, nil] the machine state, or nil when there is no
|
|
582
|
+
# Vagrantfile to ask about, the command fails, or no state row is found
|
|
583
|
+
# @api private
|
|
584
|
+
def vagrant_machine_state
|
|
585
|
+
return nil unless File.exist?(File.join(vagrant_root, "Vagrantfile"))
|
|
586
|
+
|
|
587
|
+
output = run("#{config[:vagrant_binary]} status --machine-readable")
|
|
588
|
+
parse_machine_state(output)
|
|
589
|
+
rescue ::StandardError => e
|
|
590
|
+
debug("Could not read the Vagrant machine state: #{e.message}")
|
|
591
|
+
nil
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
# Pulls the `state` row out of Vagrant's machine-readable output.
|
|
595
|
+
#
|
|
596
|
+
# @param output [String] the raw `--machine-readable` output
|
|
597
|
+
# @return [String, nil] the state value, or nil when no state row is present
|
|
598
|
+
# @api private
|
|
599
|
+
def parse_machine_state(output)
|
|
600
|
+
output.to_s.each_line do |line|
|
|
601
|
+
fields = line.strip.split(",")
|
|
602
|
+
return fields[3] if fields[2] == "state" && fields[3]
|
|
603
|
+
end
|
|
604
|
+
nil
|
|
605
|
+
end
|
|
606
|
+
|
|
607
|
+
# Vagrant itself: present, and new enough.
|
|
608
|
+
#
|
|
609
|
+
# @return [Array<String>] a problem, or an empty array
|
|
610
|
+
def vagrant_problems
|
|
611
|
+
found = vagrant_version
|
|
612
|
+
if Gem::Version.new(found) < Gem::Version.new(MIN_VER.dup)
|
|
613
|
+
return ["Vagrant #{found} is older than the #{MIN_VER} this driver " \
|
|
614
|
+
"needs. Upgrade from #{WEBSITE}."]
|
|
615
|
+
end
|
|
616
|
+
|
|
617
|
+
info("vagrant #{found} found at #{config[:vagrant_binary]}")
|
|
618
|
+
[]
|
|
619
|
+
rescue UserError => e
|
|
620
|
+
[e.message]
|
|
621
|
+
rescue ::StandardError => e
|
|
622
|
+
["Could not run #{config[:vagrant_binary]} --version: #{e.message}"]
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
# The Vagrantfile template, and any extra Vagrantfiles spliced into it.
|
|
626
|
+
# Both are `expand_path_for` settings, so a wrong relative path becomes
|
|
627
|
+
# an absolute path that simply is not there.
|
|
628
|
+
#
|
|
629
|
+
# @return [Array<String>] one problem per missing file
|
|
630
|
+
def template_problems
|
|
631
|
+
problems = []
|
|
632
|
+
|
|
633
|
+
unless File.exist?(config[:vagrantfile_erb].to_s)
|
|
634
|
+
problems << "vagrantfile_erb #{config[:vagrantfile_erb]} does not exist."
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
Array(config[:vagrantfiles]).each do |path|
|
|
638
|
+
problems << "vagrantfiles entry #{path} does not exist." unless File.exist?(path.to_s)
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
problems
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
# Host paths in `synced_folders`. Vagrant creates a missing host path
|
|
645
|
+
# silently for some providers and fails for others, so an absent source
|
|
646
|
+
# is worth naming either way.
|
|
647
|
+
#
|
|
648
|
+
# @return [Array<String>] one problem per missing host path
|
|
649
|
+
def synced_folder_problems
|
|
650
|
+
Array(config[:synced_folders]).filter_map do |source, destination, _options|
|
|
651
|
+
next if source.nil? || File.exist?(source.to_s)
|
|
652
|
+
|
|
653
|
+
"synced_folders source #{source} (mounted at #{destination}) does not exist."
|
|
654
|
+
end
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
# Convenience method to run a command locally, from {#vagrant_root}.
|
|
507
658
|
#
|
|
508
659
|
# @param cmd [String] command to run locally
|
|
509
660
|
# @param options [Hash] options hash
|
|
510
|
-
# @
|
|
661
|
+
# @return [String] the standard output of the command
|
|
662
|
+
# @raise [Kitchen::ShellOut::ShellCommandFailed] if the command exits
|
|
663
|
+
# non-zero
|
|
664
|
+
# @see Kitchen::ShellOut#run_command
|
|
511
665
|
# @api private
|
|
512
666
|
def run(cmd, options = {})
|
|
513
667
|
cmd = "echo #{cmd}" if config[:dry_run]
|
|
@@ -529,6 +683,8 @@ module Kitchen
|
|
|
529
683
|
# @param cmd [String] command to run locally
|
|
530
684
|
# @param options [Hash] options hash
|
|
531
685
|
# @return [String] the standard output of the command
|
|
686
|
+
# @raise [Kitchen::ShellOut::ShellCommandFailed] if the command exits
|
|
687
|
+
# non-zero
|
|
532
688
|
# @see Kitchen::ShellOut#run_command
|
|
533
689
|
# rubocop:disable Metrics/CyclomaticComplexity
|
|
534
690
|
def run_command(cmd, options = {})
|
|
@@ -752,7 +908,12 @@ module Kitchen
|
|
|
752
908
|
state[:rdp_port] = hash["RDPPort"] if hash["RDPPort"]
|
|
753
909
|
end
|
|
754
910
|
|
|
755
|
-
#
|
|
911
|
+
# The *host* side of the omnibus package cache: the directory that
|
|
912
|
+
# {#add_extra_synced_folders!} shares into the guest, where it is
|
|
913
|
+
# mounted at {#cache_directory}.
|
|
914
|
+
#
|
|
915
|
+
# @return [String] full absolute path, on the host, to the kitchen
|
|
916
|
+
# cache directory
|
|
756
917
|
# @api private
|
|
757
918
|
def local_kitchen_cache
|
|
758
919
|
@local_kitchen_cache ||= config[:kitchen_cache_directory]
|
|
@@ -789,9 +950,15 @@ module Kitchen
|
|
|
789
950
|
false
|
|
790
951
|
end
|
|
791
952
|
|
|
792
|
-
# Converts a Windows path to a WSL path
|
|
793
|
-
#
|
|
794
|
-
#
|
|
953
|
+
# Converts a Windows path to a WSL path.
|
|
954
|
+
#
|
|
955
|
+
# Anything that does not look like a drive-lettered Windows path is
|
|
956
|
+
# returned untouched. Note that the conversion downcases the whole
|
|
957
|
+
# path, not just the drive letter, so a path whose remainder is
|
|
958
|
+
# case-sensitive does not survive it.
|
|
959
|
+
#
|
|
960
|
+
# @param path [String] Windows path (e.g., `"C:/Users/..."`)
|
|
961
|
+
# @return [String] WSL path (e.g., `"/mnt/c/users/..."`)
|
|
795
962
|
# @api private
|
|
796
963
|
def windows_to_wsl_path(path)
|
|
797
964
|
# Only convert if it looks like a Windows path
|
data/templates/Vagrantfile.erb
CHANGED
|
@@ -99,6 +99,8 @@ Vagrant.configure("2") do |c|
|
|
|
99
99
|
p.name = "kitchen-<%= File.basename(config[:kitchen_root]) %>-<%= instance.name %>-<%= SecureRandom.uuid %>"
|
|
100
100
|
<% when "tart" %>
|
|
101
101
|
p.name = "kitchen-<%= File.basename(config[:kitchen_root]) %>-<%= instance.name %>"
|
|
102
|
+
<% when "libvirt" %>
|
|
103
|
+
p.default_prefix = "<%="kitchen-#{File.basename(config[:kitchen_root])}-#{instance.name}-#{SecureRandom.uuid}"[0..99].chomp("-") %>"
|
|
102
104
|
<% end %>
|
|
103
105
|
|
|
104
106
|
<% case config[:provider]
|
|
@@ -257,7 +259,9 @@ Vagrant.configure("2") do |c|
|
|
|
257
259
|
end
|
|
258
260
|
|
|
259
261
|
<% if config[:env] && !config[:env].empty? %>
|
|
260
|
-
#
|
|
262
|
+
# Environment variables for the *guest*, not for the host's Vagrant
|
|
263
|
+
# process: each entry becomes an export line in /etc/profile.d/kitchen.sh,
|
|
264
|
+
# so it applies to logins on Linux guests only.
|
|
261
265
|
<% config[:env].each do |env_var| %>
|
|
262
266
|
c.vm.provision "shell", inline: <<-SHELL
|
|
263
267
|
echo 'export <%= env_var.gsub("'", "'\\\\''") %>' >> /etc/profile.d/kitchen.sh
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kitchen-vagrant
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Fletcher Nichol
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -30,7 +30,7 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
33
|
+
version: '3.0'
|
|
34
34
|
- - "<"
|
|
35
35
|
- !ruby/object:Gem::Version
|
|
36
36
|
version: '5'
|
|
@@ -40,7 +40,7 @@ dependencies:
|
|
|
40
40
|
requirements:
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: '
|
|
43
|
+
version: '3.0'
|
|
44
44
|
- - "<"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
46
|
version: '5'
|