Merge tag 'tags/v1.9.1' into patch-guest-esxi
This commit is contained in:
commit
e3e7484e16
|
@ -4,18 +4,14 @@ sudo: false
|
||||||
|
|
||||||
cache: bundler
|
cache: bundler
|
||||||
|
|
||||||
before_install:
|
|
||||||
- gem uninstall bundler -aIxq --force
|
|
||||||
- gem uninstall -Ixq --force -i /home/travis/.rvm/gems/ruby-2.2.3@global bundler
|
|
||||||
- gem install bundler -v '1.12.5'
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
- bsdtar
|
- bsdtar
|
||||||
|
|
||||||
rvm:
|
rvm:
|
||||||
- 2.2.3
|
- 2.2.5
|
||||||
|
- 2.3.3
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
|
|
76
CHANGELOG.md
76
CHANGELOG.md
|
@ -1,7 +1,81 @@
|
||||||
## Next Version (Unreleased)
|
## 1.9.1 (December 7, 2016)
|
||||||
|
|
||||||
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
- core: Disable Vagrantfile loading when running plugin commands [GH-8066]
|
||||||
|
- guests/redhat: Detect and restart NetworkManager service if in use [GH-8052, GH-7994]
|
||||||
|
|
||||||
|
BUG FIXES:
|
||||||
|
|
||||||
|
- core: Detect load failures within install solution sets and retry [GH-8068]
|
||||||
|
- core: Prevent interactive shell on plugin uninstall [GH-8086, GH-8087]
|
||||||
|
- core: Remove bundler usage from Util::Env [GH-8090, GH-8094]
|
||||||
|
- guests/linux: Prevent stderr output on init version check for synced folders [GH-8051]
|
||||||
|
|
||||||
|
## 1.9.0 (November 28, 2016)
|
||||||
|
|
||||||
FEATURES:
|
FEATURES:
|
||||||
|
|
||||||
|
- commands/box: Add `prune` subcommand for removing outdated boxes [GH-7978]
|
||||||
|
- core: Remove Bundler integration for handling internal plugins [GH-7793, GH-8000, GH-8011, GH-8031]
|
||||||
|
- providers/hyperv: Add support for Hyper-V binary configuration format
|
||||||
|
[GH-7854, GH-7706, GH-6102]
|
||||||
|
- provisioners/shell: Support MD5/SHA1 checksum validation of remote scripts [GH-7985, GH-6323]
|
||||||
|
|
||||||
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
- commands/plugin: Retain name sorted output when listing plugins [GH-8028]
|
||||||
|
- communicator/ssh: Support custom environment variable export template
|
||||||
|
[GH-7976, GH-6747]
|
||||||
|
- provisioners/ansible(both): Add `config_file` option to point the location of an
|
||||||
|
`ansible.cfg` file via ANSIBLE_CONFIG environment variable [GH-7195, GH-7918]
|
||||||
|
- synced_folders: Support custom naming and disable auto-mount [GH-7980, GH-6836]
|
||||||
|
|
||||||
|
BUG FIXES:
|
||||||
|
|
||||||
|
- guests/linux: Do not match interfaces with special characters when sorting [GH-7989, GH-7988]
|
||||||
|
- provisioner/salt: Fix Hash construction for constant [GH-7986, GH-7981]
|
||||||
|
|
||||||
|
## 1.8.7 (November 4, 2016)
|
||||||
|
|
||||||
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
- guests/linux: Place ethernet devices at start of network devices list [GH-7848]
|
||||||
|
- guests/linux: Provide more consistent guest detection [GH-7887, GH-7827]
|
||||||
|
- guests/openbsd: Validate guest rsync installation success [GH-7929, GH-7898]
|
||||||
|
- guests/redhat: Include Virtuozzo Linux 7 within flavor identification [GH-7818]
|
||||||
|
- guests/windows: Allow vagrant to start Windows Nano without provisioning [GH-7831]
|
||||||
|
- provisioners/ansible_local: Change the Ansible binary detection mechanism [GH-7536]
|
||||||
|
- provisioners/ansible(both): Add the `playbook_command` option [GH-7881]
|
||||||
|
- provisioners/puppet: Support custom environment variables [GH-7931, GH-7252, GH-2270]
|
||||||
|
- util/safe_exec: Use subprocess for safe_exec on Windows [GH-7802]
|
||||||
|
- util/subprocess: Allow closing STDIN [GH-7778]
|
||||||
|
|
||||||
|
BUG FIXES:
|
||||||
|
|
||||||
|
- communicators/winrm: Prevent connection leakage [GH-7712]
|
||||||
|
- core: Prevent duplicate provider priorities [GH-7756]
|
||||||
|
- core: Allow Numeric type for box version [GH-7874, GH-6960]
|
||||||
|
- core: Provide friendly error when user environment is too large [GH-7889, GH-7857]
|
||||||
|
- guests: Remove `set -e` usage for better shell compatibility [GH-7921, GH-7739]
|
||||||
|
- guests/linux: Fix incorrectly configured private network [GH-7844, GH-7848]
|
||||||
|
- guests/linux: Properly order network interfaces
|
||||||
|
[GH-7866, GH-7876, GH-7858, GH-7876]
|
||||||
|
- guests/linux: Only emit upstart event if initctl is available [GH-7813]
|
||||||
|
- guests/netbsd: Fix rsync installation [GH-7922, GH-7901]
|
||||||
|
- guests/photon: Fix networking setup [GH-7808, GH-7873]
|
||||||
|
- guests/redhat: Properly configure network and restart service [GH-7751]
|
||||||
|
- guests/redhat: Prevent NetworkManager from managing devices on initial start [GH-7926]
|
||||||
|
- hosts/linux: Fix race condition in writing /etc/exports file for NFS configuration
|
||||||
|
[GH-7947, GH-7938] - Thanks to Aron Griffis (@agriffis) for identifying this issue
|
||||||
|
- plugins/rsync: Escape exclude paths [GH-7928, GH-7910]
|
||||||
|
- providers/docker: Remove --interactive flag when pty is true [GH-7688]
|
||||||
|
- provisioners/ansible_local: Use enquoted path for file/directory existence checks
|
||||||
|
- provisioners/salt: Synchronize configuration defaults with documentation [GH-7907, GH-6624]
|
||||||
|
- pushes/atlas: Fix atlas push on Windows platform [GH-6938, GH-7802]
|
||||||
|
|
||||||
|
## 1.8.6 (September 27, 2016)
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
- Add detection for DragonFly BSD [GH-7701]
|
- Add detection for DragonFly BSD [GH-7701]
|
||||||
|
|
13
README.md
13
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
* Website: [https://www.vagrantup.com/](https://www.vagrantup.com/)
|
* Website: [https://www.vagrantup.com/](https://www.vagrantup.com/)
|
||||||
* Source: [https://github.com/mitchellh/vagrant](https://github.com/mitchellh/vagrant)
|
* Source: [https://github.com/mitchellh/vagrant](https://github.com/mitchellh/vagrant)
|
||||||
* IRC: `#vagrant` on Freenode
|
* [![Gitter chat](https://badges.gitter.im/mitchellh/vagrant.png)](https://gitter.im/mitchellh/vagrant)
|
||||||
* Mailing list: [Google Groups](https://groups.google.com/group/vagrant-up)
|
* Mailing list: [Google Groups](https://groups.google.com/group/vagrant-up)
|
||||||
|
|
||||||
Vagrant is a tool for building and distributing development environments.
|
Vagrant is a tool for building and distributing development environments.
|
||||||
|
@ -45,11 +45,7 @@ To learn how to build a fully functional development environment, follow the
|
||||||
## Installing the Gem from Git
|
## Installing the Gem from Git
|
||||||
|
|
||||||
If you want the bleeding edge version of Vagrant, we try to keep master pretty stable
|
If you want the bleeding edge version of Vagrant, we try to keep master pretty stable
|
||||||
and you're welcome to give it a shot. The following is an example showing how to do this:
|
and you're welcome to give it a shot. Please review the installation page [here](https://www.vagrantup.com/docs/installation/source.html).
|
||||||
|
|
||||||
rake install
|
|
||||||
|
|
||||||
Ruby 2.0 is needed.
|
|
||||||
|
|
||||||
## Contributing to Vagrant
|
## Contributing to Vagrant
|
||||||
|
|
||||||
|
@ -66,11 +62,6 @@ like so:
|
||||||
|
|
||||||
bundle exec vagrant help
|
bundle exec vagrant help
|
||||||
|
|
||||||
**NOTE:** By default running Vagrant via `bundle` will disable plugins.
|
|
||||||
This is necessary because Vagrant creates its own private Bundler context
|
|
||||||
(it does not respect your Gemfile), because it uses Bundler to manage plugin
|
|
||||||
dependencies.
|
|
||||||
|
|
||||||
### Acceptance Tests
|
### Acceptance Tests
|
||||||
|
|
||||||
Vagrant also comes with an acceptance test suite that does black-box
|
Vagrant also comes with an acceptance test suite that does black-box
|
||||||
|
|
73
bin/vagrant
73
bin/vagrant
|
@ -8,6 +8,11 @@ Signal.trap("INT") { abort }
|
||||||
# Split arguments by "--" if its there, we'll recombine them later
|
# Split arguments by "--" if its there, we'll recombine them later
|
||||||
argv = ARGV.dup
|
argv = ARGV.dup
|
||||||
argv_extra = []
|
argv_extra = []
|
||||||
|
|
||||||
|
# These will be the options that are passed to initialze the Vagrant
|
||||||
|
# environment.
|
||||||
|
opts = {}
|
||||||
|
|
||||||
if idx = argv.index("--")
|
if idx = argv.index("--")
|
||||||
argv_extra = argv.slice(idx+1, argv.length-2)
|
argv_extra = argv.slice(idx+1, argv.length-2)
|
||||||
argv = argv.slice(0, idx)
|
argv = argv.slice(0, idx)
|
||||||
|
@ -20,43 +25,26 @@ if argv.include?("-v") || argv.include?("--version")
|
||||||
exit 0
|
exit 0
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is kind of hacky, and I'd love to find a better way to do this, but
|
# Disable plugin loading for commands where plugins are not required. This will
|
||||||
# if we're accessing the plugin interface, we want to NOT load plugins
|
# also disable loading of the Vagrantfile if it available as the environment
|
||||||
# for this run, because they can actually interfere with the function
|
# is not required for these commands
|
||||||
# of the plugin interface.
|
|
||||||
argv.each_index do |i|
|
argv.each_index do |i|
|
||||||
arg = argv[i]
|
arg = argv[i]
|
||||||
|
|
||||||
if !arg.start_with?("-")
|
if !arg.start_with?("-")
|
||||||
if arg == "plugin"
|
if ["plugin", "help"].include?(arg) || (arg == "box" && argv[i+1] == "list")
|
||||||
ENV["VAGRANT_NO_PLUGINS"] = "1"
|
opts[:vagrantfile_name] = ""
|
||||||
ENV["VAGRANT_VAGRANTFILE"] = "plugin_command_#{Time.now.to_i}"
|
ENV['VAGRANT_NO_PLUGINS'] = "1"
|
||||||
end
|
end
|
||||||
|
|
||||||
if arg == "help"
|
if arg == "plugin" && argv[i+1] != "list"
|
||||||
ENV["VAGRANT_VAGRANTFILE"] = "plugin_command_#{Time.now.to_i}"
|
ENV['VAGRANT_DISABLE_PLUGIN_INIT'] = "1"
|
||||||
end
|
|
||||||
|
|
||||||
if arg == "box" && argv[i+1] == "list"
|
|
||||||
ENV["VAGRANT_VAGRANTFILE"] = "plugin_command_#{Time.now.to_i}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# First, make sure that we're executing using the proper Bundler context
|
|
||||||
# with our plugins. If we're not, then load that and reload Vagrant.
|
|
||||||
if !ENV["VAGRANT_INTERNAL_BUNDLERIZED"]
|
|
||||||
require "rbconfig"
|
|
||||||
ruby_path = File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"])
|
|
||||||
Kernel.exec(
|
|
||||||
ruby_path,
|
|
||||||
File.expand_path("../../lib/vagrant/pre-rubygems.rb", __FILE__),
|
|
||||||
*ARGV)
|
|
||||||
raise "Fatal error: this line should never be reached"
|
|
||||||
end
|
|
||||||
|
|
||||||
# Set logging level to `debug`. This is done before loading 'vagrant', as it
|
# Set logging level to `debug`. This is done before loading 'vagrant', as it
|
||||||
# sets up the logging system.
|
# sets up the logging system.
|
||||||
if argv.include?("--debug")
|
if argv.include?("--debug")
|
||||||
|
@ -64,37 +52,6 @@ if argv.include?("--debug")
|
||||||
ENV["VAGRANT_LOG"] = "debug"
|
ENV["VAGRANT_LOG"] = "debug"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Setup our dependencies by initializing Bundler. If we're using plugins,
|
|
||||||
# then also initialize the paths to the plugins.
|
|
||||||
require "bundler"
|
|
||||||
begin
|
|
||||||
$vagrant_bundler_runtime = Bundler.setup(:default, :plugins)
|
|
||||||
rescue Bundler::GemNotFound
|
|
||||||
$stderr.puts "Bundler, the underlying system used to manage Vagrant plugins,"
|
|
||||||
$stderr.puts "is reporting that a plugin or its dependency can't be found."
|
|
||||||
$stderr.puts "This is usually caused by manual tampering with the 'plugins.json'"
|
|
||||||
$stderr.puts "file in the Vagrant home directory. To fix this error, please"
|
|
||||||
$stderr.puts "remove that file and reinstall all your plugins using `vagrant"
|
|
||||||
$stderr.puts "plugin install`."
|
|
||||||
rescue Bundler::VersionConflict => e
|
|
||||||
$stderr.puts "Vagrant experienced a version conflict with some installed plugins!"
|
|
||||||
$stderr.puts "This usually happens if you recently upgraded Vagrant. As part of the"
|
|
||||||
$stderr.puts "upgrade process, some existing plugins are no longer compatible with"
|
|
||||||
$stderr.puts "this version of Vagrant. The recommended way to fix this is to remove"
|
|
||||||
$stderr.puts "your existing plugins and reinstall them one-by-one. To remove all"
|
|
||||||
$stderr.puts "plugins:"
|
|
||||||
$stderr.puts ""
|
|
||||||
$stderr.puts " rm -r ~/.vagrant.d/plugins.json ~/.vagrant.d/gems"
|
|
||||||
$stderr.puts ""
|
|
||||||
$stderr.puts "Note if you have an alternate VAGRANT_HOME environmental variable"
|
|
||||||
$stderr.puts "set, the folders above will be in that directory rather than your"
|
|
||||||
$stderr.puts "user's home directory."
|
|
||||||
$stderr.puts ""
|
|
||||||
$stderr.puts "The error message is shown below:\n\n"
|
|
||||||
$stderr.puts e.message
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
|
|
||||||
# Stdout/stderr should not buffer output
|
# Stdout/stderr should not buffer output
|
||||||
$stdout.sync = true
|
$stdout.sync = true
|
||||||
$stderr.sync = true
|
$stderr.sync = true
|
||||||
|
@ -114,10 +71,6 @@ begin
|
||||||
logger = Log4r::Logger.new("vagrant::bin::vagrant")
|
logger = Log4r::Logger.new("vagrant::bin::vagrant")
|
||||||
logger.info("`vagrant` invoked: #{ARGV.inspect}")
|
logger.info("`vagrant` invoked: #{ARGV.inspect}")
|
||||||
|
|
||||||
# These will be the options that are passed to initialze the Vagrant
|
|
||||||
# environment.
|
|
||||||
opts = {}
|
|
||||||
|
|
||||||
# Disable color in a few cases:
|
# Disable color in a few cases:
|
||||||
#
|
#
|
||||||
# * --no-color is anywhere in our arguments
|
# * --no-color is anywhere in our arguments
|
||||||
|
|
|
@ -1,12 +1,5 @@
|
||||||
require "vagrant/shared_helpers"
|
require "vagrant/shared_helpers"
|
||||||
|
|
||||||
if Vagrant.plugins_enabled? && !defined?(Bundler)
|
|
||||||
puts "It appears that Vagrant was not properly loaded. Specifically,"
|
|
||||||
puts "the bundler context Vagrant requires was not setup. Please execute"
|
|
||||||
puts "vagrant using only the `vagrant` executable."
|
|
||||||
abort
|
|
||||||
end
|
|
||||||
|
|
||||||
require 'rubygems'
|
require 'rubygems'
|
||||||
require 'log4r'
|
require 'log4r'
|
||||||
|
|
||||||
|
@ -72,11 +65,6 @@ global_logger.info("RubyGems version: #{Gem::VERSION}")
|
||||||
ENV.each do |k, v|
|
ENV.each do |k, v|
|
||||||
global_logger.info("#{k}=#{v.inspect}") if k =~ /^VAGRANT_/
|
global_logger.info("#{k}=#{v.inspect}") if k =~ /^VAGRANT_/
|
||||||
end
|
end
|
||||||
global_logger.info("Plugins:")
|
|
||||||
Bundler.definition.specs_for([:plugins]).each do |spec|
|
|
||||||
global_logger.info(" - #{spec.name} = #{spec.version}")
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
# We need these components always so instead of an autoload we
|
# We need these components always so instead of an autoload we
|
||||||
# just require them explicitly here.
|
# just require them explicitly here.
|
||||||
|
@ -254,6 +242,35 @@ if I18n.config.respond_to?(:enforce_available_locales=)
|
||||||
I18n.config.enforce_available_locales = true
|
I18n.config.enforce_available_locales = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Setup the plugin manager and load any defined plugins
|
||||||
|
require_relative "vagrant/plugin/manager"
|
||||||
|
plugins = Vagrant::Plugin::Manager.instance.installed_plugins
|
||||||
|
|
||||||
|
global_logger.info("Plugins:")
|
||||||
|
plugins.each do |plugin_name, plugin_info|
|
||||||
|
installed_version = plugin_info["installed_gem_version"]
|
||||||
|
version_constraint = plugin_info["gem_version"]
|
||||||
|
installed_version = 'undefined' if installed_version.to_s.empty?
|
||||||
|
version_constraint = '> 0' if version_constraint.to_s.empty?
|
||||||
|
global_logger.info(
|
||||||
|
" - #{plugin_name} = [installed: " \
|
||||||
|
"#{installed_version} constraint: " \
|
||||||
|
"#{version_constraint}]"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
if Vagrant.plugins_init?
|
||||||
|
begin
|
||||||
|
Vagrant::Bundler.instance.init!(plugins)
|
||||||
|
rescue Exception => e
|
||||||
|
global_logger.error("Plugin initialization error - #{e.class}: #{e}")
|
||||||
|
e.backtrace.each do |backtrace_line|
|
||||||
|
global_logger.debug(backtrace_line)
|
||||||
|
end
|
||||||
|
raise Vagrant::Errors::PluginInitError, message: e.to_s
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# A lambda that knows how to load plugins from a single directory.
|
# A lambda that knows how to load plugins from a single directory.
|
||||||
plugin_load_proc = lambda do |directory|
|
plugin_load_proc = lambda do |directory|
|
||||||
# We only care about directories
|
# We only care about directories
|
||||||
|
@ -288,8 +305,40 @@ end
|
||||||
if Vagrant.plugins_enabled?
|
if Vagrant.plugins_enabled?
|
||||||
begin
|
begin
|
||||||
global_logger.info("Loading plugins!")
|
global_logger.info("Loading plugins!")
|
||||||
$vagrant_bundler_runtime.require(:plugins)
|
plugins.each do |plugin_name, plugin_info|
|
||||||
|
if plugin_info["require"].to_s.empty?
|
||||||
|
begin
|
||||||
|
global_logger.debug("Loading plugin `#{plugin_name}` with default require: `#{plugin_name}`")
|
||||||
|
require plugin_name
|
||||||
|
rescue LoadError, Gem::LoadError => load_error
|
||||||
|
if plugin_name.include?("-")
|
||||||
|
begin
|
||||||
|
plugin_slash = plugin_name.gsub("-", "/")
|
||||||
|
global_logger.debug("Failed to load plugin `#{plugin_name}` with default require.")
|
||||||
|
global_logger.debug("Loading plugin `#{plugin_name}` with slash require: `#{plugin_slash}`")
|
||||||
|
require plugin_slash
|
||||||
|
rescue LoadError, Gem::LoadError
|
||||||
|
raise load_error
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
global_logger.debug("Loading plugin `#{plugin_name}` with custom require: `#{plugin_info["require"]}`")
|
||||||
|
require plugin_info["require"]
|
||||||
|
end
|
||||||
|
global_logger.debug("Successfully loaded plugin `#{plugin_name}`.")
|
||||||
|
end
|
||||||
|
if defined?(::Bundler)
|
||||||
|
global_logger.debug("Bundler detected in use. Loading `:plugins` group.")
|
||||||
|
::Bundler.require(:plugins)
|
||||||
|
end
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
|
global_logger.error("Plugin loading error: #{e.class} - #{e}")
|
||||||
|
e.backtrace.each do |backtrace_line|
|
||||||
|
global_logger.debug(backtrace_line)
|
||||||
|
end
|
||||||
raise Vagrant::Errors::PluginLoadError, message: e.to_s
|
raise Vagrant::Errors::PluginLoadError, message: e.to_s
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
global_logger.debug("Plugin loading is currently disabled.")
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,9 @@ require "set"
|
||||||
require "tempfile"
|
require "tempfile"
|
||||||
require "fileutils"
|
require "fileutils"
|
||||||
|
|
||||||
require "bundler"
|
require "rubygems/package"
|
||||||
|
require "rubygems/uninstaller"
|
||||||
|
require "rubygems/name_tuple"
|
||||||
|
|
||||||
require_relative "shared_helpers"
|
require_relative "shared_helpers"
|
||||||
require_relative "version"
|
require_relative "version"
|
||||||
|
@ -15,83 +17,77 @@ module Vagrant
|
||||||
# Bundler as a way to properly resolve all dependencies of Vagrant and
|
# Bundler as a way to properly resolve all dependencies of Vagrant and
|
||||||
# all Vagrant-installed plugins.
|
# all Vagrant-installed plugins.
|
||||||
class Bundler
|
class Bundler
|
||||||
|
|
||||||
|
HASHICORP_GEMSTORE = 'https://gems.hashicorp.com'.freeze
|
||||||
|
|
||||||
def self.instance
|
def self.instance
|
||||||
@bundler ||= self.new
|
@bundler ||= self.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
attr_reader :plugin_gem_path
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@enabled = true if ENV["VAGRANT_INSTALLER_ENV"] ||
|
@plugin_gem_path = Vagrant.user_data_path.join("gems", RUBY_VERSION).freeze
|
||||||
ENV["VAGRANT_FORCE_BUNDLER"]
|
@logger = Log4r::Logger.new("vagrant::bundler")
|
||||||
@enabled = !::Bundler::SharedHelpers.in_bundle? if !@enabled
|
|
||||||
@monitor = Monitor.new
|
|
||||||
|
|
||||||
@gem_home = ENV["GEM_HOME"]
|
|
||||||
@gem_path = ENV["GEM_PATH"]
|
|
||||||
|
|
||||||
# Set the Bundler UI to be a silent UI. We have to add the
|
|
||||||
# `silence` method to it because Bundler UI doesn't have it.
|
|
||||||
::Bundler.ui =
|
|
||||||
if ::Bundler::UI.const_defined? :Silent
|
|
||||||
# bundler >= 1.6.0, we use our custom UI
|
|
||||||
BundlerUI.new
|
|
||||||
else
|
|
||||||
# bundler < 1.6.0
|
|
||||||
::Bundler::UI.new
|
|
||||||
end
|
|
||||||
if !::Bundler.ui.respond_to?(:silence)
|
|
||||||
ui = ::Bundler.ui
|
|
||||||
def ui.silence(*args)
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Initializes Bundler and the various gem paths so that we can begin
|
# Initializes Bundler and the various gem paths so that we can begin
|
||||||
# loading gems. This must only be called once.
|
# loading gems. This must only be called once.
|
||||||
def init!(plugins)
|
def init!(plugins, repair=false)
|
||||||
# If we're not enabled, then we don't do anything.
|
# Add HashiCorp RubyGems source
|
||||||
return if !@enabled
|
Gem.sources << HASHICORP_GEMSTORE
|
||||||
|
|
||||||
bundle_path = Vagrant.user_data_path.join("gems")
|
# Generate dependencies for all registered plugins
|
||||||
|
plugin_deps = plugins.map do |name, info|
|
||||||
# Setup the "local" Bundler configuration. We need to set BUNDLE_PATH
|
Gem::Dependency.new(name, info['gem_version'].to_s.empty? ? '> 0' : info['gem_version'])
|
||||||
# because the existence of this actually suppresses `sudo`.
|
|
||||||
@appconfigpath = Dir.mktmpdir("vagrant-bundle-app-config")
|
|
||||||
File.open(File.join(@appconfigpath, "config"), "w+") do |f|
|
|
||||||
f.write("BUNDLE_PATH: \"#{bundle_path}\"")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Setup the Bundler configuration
|
@logger.debug("Current generated plugin dependency list: #{plugin_deps}")
|
||||||
@configfile = tempfile("vagrant-configfile")
|
|
||||||
@configfile.close
|
|
||||||
|
|
||||||
# Build up the Gemfile for our Bundler context. We make sure to
|
# Load dependencies into a request set for resolution
|
||||||
# lock Vagrant to our current Vagrant version. In addition to that,
|
request_set = Gem::RequestSet.new(*plugin_deps)
|
||||||
# we add all our plugin dependencies.
|
# Never allow dependencies to be remotely satisfied during init
|
||||||
@gemfile = build_gemfile(plugins)
|
request_set.remote = false
|
||||||
|
|
||||||
Util::SafeEnv.change_env do |env|
|
repair_result = nil
|
||||||
# Set the environmental variables for Bundler
|
begin
|
||||||
env["BUNDLE_APP_CONFIG"] = @appconfigpath
|
# Compose set for resolution
|
||||||
env["BUNDLE_CONFIG"] = @configfile.path
|
composed_set = generate_vagrant_set
|
||||||
env["BUNDLE_GEMFILE"] = @gemfile.path
|
# Resolve the request set to ensure proper activation order
|
||||||
env["BUNDLE_RETRY"] = "3"
|
solution = request_set.resolve(composed_set)
|
||||||
env["GEM_PATH"] =
|
rescue Gem::UnsatisfiableDependencyError => failure
|
||||||
"#{bundle_path}#{::File::PATH_SEPARATOR}#{@gem_path}"
|
if repair
|
||||||
|
raise failure if @init_retried
|
||||||
|
@logger.debug("Resolution failed but attempting to repair. Failure: #{failure}")
|
||||||
|
install(plugins)
|
||||||
|
@init_retried = true
|
||||||
|
retry
|
||||||
|
else
|
||||||
|
raise
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Gem.clear_paths
|
# Activate the gems
|
||||||
|
activate_solution(solution)
|
||||||
|
|
||||||
|
full_vagrant_spec_list = Gem::Specification.find_all{true} +
|
||||||
|
solution.map(&:full_spec)
|
||||||
|
|
||||||
|
if(defined?(::Bundler))
|
||||||
|
@logger.debug("Updating Bundler with full specification list")
|
||||||
|
::Bundler.rubygems.replace_entrypoints(full_vagrant_spec_list)
|
||||||
|
end
|
||||||
|
|
||||||
|
Gem.post_reset do
|
||||||
|
Gem::Specification.all = full_vagrant_spec_list
|
||||||
|
end
|
||||||
|
|
||||||
|
Gem::Specification.reset
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes any temporary files created by init
|
# Removes any temporary files created by init
|
||||||
def deinit
|
def deinit
|
||||||
# If we weren't enabled, then we don't do anything.
|
# no-op
|
||||||
return if !@enabled
|
|
||||||
|
|
||||||
FileUtils.rm_rf(ENV["BUNDLE_APP_CONFIG"]) rescue nil
|
|
||||||
FileUtils.rm_f(ENV["BUNDLE_CONFIG"]) rescue nil
|
|
||||||
FileUtils.rm_f(ENV["BUNDLE_GEMFILE"]) rescue nil
|
|
||||||
FileUtils.rm_f(ENV["BUNDLE_GEMFILE"]+".lock") rescue nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Installs the list of plugins.
|
# Installs the list of plugins.
|
||||||
|
@ -106,35 +102,17 @@ module Vagrant
|
||||||
#
|
#
|
||||||
# @param [String] path Path to a local gem file.
|
# @param [String] path Path to a local gem file.
|
||||||
# @return [Gem::Specification]
|
# @return [Gem::Specification]
|
||||||
def install_local(path)
|
def install_local(path, opts={})
|
||||||
# We have to do this load here because this file can be loaded
|
plugin_source = Gem::Source::SpecificFile.new(path)
|
||||||
# before RubyGems is actually loaded.
|
plugin_info = {
|
||||||
require "rubygems/dependency_installer"
|
plugin_source.spec.name => {
|
||||||
begin
|
"local_source" => plugin_source,
|
||||||
require "rubygems/format"
|
"sources" => opts.fetch(:sources, Gem.sources.map(&:to_s))
|
||||||
rescue LoadError
|
}
|
||||||
# rubygems 2.x
|
}
|
||||||
end
|
@logger.debug("Installing local plugin - #{plugin_info}")
|
||||||
|
internal_install(plugin_info, {})
|
||||||
# If we're installing from a gem file, determine the name
|
plugin_source.spec
|
||||||
# based on the spec in the file.
|
|
||||||
pkg = if defined?(Gem::Format)
|
|
||||||
# RubyGems 1.x
|
|
||||||
Gem::Format.from_file_by_path(path)
|
|
||||||
else
|
|
||||||
# RubyGems 2.x
|
|
||||||
Gem::Package.new(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Install the gem manually. If the gem exists locally, then
|
|
||||||
# Bundler shouldn't attempt to get it remotely.
|
|
||||||
with_isolated_gem do
|
|
||||||
installer = Gem::DependencyInstaller.new(
|
|
||||||
document: [], prerelease: false)
|
|
||||||
installer.install(path, "= #{pkg.spec.version}")
|
|
||||||
end
|
|
||||||
|
|
||||||
pkg.spec
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Update updates the given plugins, or every plugin if none is given.
|
# Update updates the given plugins, or every plugin if none is given.
|
||||||
|
@ -144,277 +122,319 @@ module Vagrant
|
||||||
# empty or nil, all plugins will be updated.
|
# empty or nil, all plugins will be updated.
|
||||||
def update(plugins, specific)
|
def update(plugins, specific)
|
||||||
specific ||= []
|
specific ||= []
|
||||||
update = true
|
update = {gems: specific.empty? ? true : specific}
|
||||||
update = { gems: specific } if !specific.empty?
|
|
||||||
internal_install(plugins, update)
|
internal_install(plugins, update)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Clean removes any unused gems.
|
# Clean removes any unused gems.
|
||||||
def clean(plugins)
|
def clean(plugins)
|
||||||
gemfile = build_gemfile(plugins)
|
@logger.debug("Cleaning Vagrant plugins of stale gems.")
|
||||||
lockfile = "#{gemfile.path}.lock"
|
# Generate dependencies for all registered plugins
|
||||||
definition = ::Bundler::Definition.build(gemfile, lockfile, nil)
|
plugin_deps = plugins.map do |name, info|
|
||||||
root = File.dirname(gemfile.path)
|
gem_version = info['installed_gem_version']
|
||||||
|
gem_version = info['gem_version'] if gem_version.to_s.empty?
|
||||||
|
gem_version = "> 0" if gem_version.to_s.empty?
|
||||||
|
Gem::Dependency.new(name, gem_version)
|
||||||
|
end
|
||||||
|
|
||||||
with_isolated_gem do
|
@logger.debug("Current plugin dependency list: #{plugin_deps}")
|
||||||
runtime = ::Bundler::Runtime.new(root, definition)
|
|
||||||
runtime.clean
|
# Load dependencies into a request set for resolution
|
||||||
|
request_set = Gem::RequestSet.new(*plugin_deps)
|
||||||
|
# Never allow dependencies to be remotely satisfied during cleaning
|
||||||
|
request_set.remote = false
|
||||||
|
|
||||||
|
# Sets that we can resolve our dependencies from. Note that we only
|
||||||
|
# resolve from the current set as all required deps are activated during
|
||||||
|
# init.
|
||||||
|
current_set = generate_vagrant_set
|
||||||
|
|
||||||
|
# Collect all plugin specifications
|
||||||
|
plugin_specs = Dir.glob(plugin_gem_path.join('specifications/*.gemspec').to_s).map do |spec_path|
|
||||||
|
Gem::Specification.load(spec_path)
|
||||||
|
end
|
||||||
|
|
||||||
|
@logger.debug("Generating current plugin state solution set.")
|
||||||
|
|
||||||
|
# Resolve the request set to ensure proper activation order
|
||||||
|
solution = request_set.resolve(current_set)
|
||||||
|
solution_specs = solution.map(&:full_spec)
|
||||||
|
solution_full_names = solution_specs.map(&:full_name)
|
||||||
|
|
||||||
|
# Find all specs installed to plugins directory that are not
|
||||||
|
# found within the solution set
|
||||||
|
plugin_specs.delete_if do |spec|
|
||||||
|
solution_full_names.include?(spec.full_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
@logger.debug("Specifications to be removed - #{plugin_specs.map(&:full_name)}")
|
||||||
|
|
||||||
|
# Now delete all unused specs
|
||||||
|
plugin_specs.each do |spec|
|
||||||
|
@logger.debug("Uninstalling gem - #{spec.full_name}")
|
||||||
|
Gem::Uninstaller.new(spec.name,
|
||||||
|
version: spec.version,
|
||||||
|
install_dir: plugin_gem_path,
|
||||||
|
all: true,
|
||||||
|
executables: true,
|
||||||
|
force: true,
|
||||||
|
ignore: true,
|
||||||
|
).uninstall_gem(spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
solution.find_all do |spec|
|
||||||
|
plugins.keys.include?(spec.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# During the duration of the yielded block, Bundler loud output
|
# During the duration of the yielded block, Bundler loud output
|
||||||
# is enabled.
|
# is enabled.
|
||||||
def verbose
|
def verbose
|
||||||
@monitor.synchronize do
|
if block_given?
|
||||||
begin
|
initial_state = @verbose
|
||||||
old_ui = ::Bundler.ui
|
@verbose = true
|
||||||
require 'bundler/vendored_thor'
|
yield
|
||||||
::Bundler.ui = ::Bundler::UI::Shell.new
|
@verbose = initial_state
|
||||||
yield
|
else
|
||||||
ensure
|
@verbose = true
|
||||||
::Bundler.ui = old_ui
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
# Builds a valid Gemfile for use with Bundler given the list of
|
def internal_install(plugins, update, **extra)
|
||||||
# plugins.
|
# Only allow defined Gem sources
|
||||||
#
|
Gem.sources.clear
|
||||||
# @return [Tempfile]
|
|
||||||
def build_gemfile(plugins)
|
|
||||||
sources = plugins.values.map { |p| p["sources"] }.flatten.compact.uniq
|
|
||||||
|
|
||||||
f = tempfile("vagrant-gemfile")
|
update = {} if !update.is_a?(Hash)
|
||||||
f.tap do |gemfile|
|
skips = []
|
||||||
sources.each do |source|
|
installer_set = Gem::Resolver::InstallerSet.new(:both)
|
||||||
next if source == ""
|
|
||||||
gemfile.puts(%Q[source "#{source}"])
|
# Generate all required plugin deps
|
||||||
|
plugin_deps = plugins.map do |name, info|
|
||||||
|
if update[:gems] == true || (update[:gems].respond_to?(:include?) && update[:gems].include?(name))
|
||||||
|
gem_version = '> 0'
|
||||||
|
skips << name
|
||||||
|
else
|
||||||
|
gem_version = info['gem_version'].to_s.empty? ? '> 0' : info['gem_version']
|
||||||
end
|
end
|
||||||
|
if plugin_source = info.delete("local_source")
|
||||||
|
installer_set.add_local(plugin_source.spec.name, plugin_source.spec, plugin_source)
|
||||||
|
end
|
||||||
|
Array(info["sources"]).each do |source|
|
||||||
|
if !Gem.sources.include?(source)
|
||||||
|
@logger.debug("Adding RubyGems source for plugin install: #{source}")
|
||||||
|
Gem.sources << source
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Gem::Dependency.new(name, gem_version)
|
||||||
|
end
|
||||||
|
|
||||||
gemfile.puts(%Q[gem "vagrant", "= #{VERSION}"])
|
@logger.debug("Dependency list for installation: #{plugin_deps}")
|
||||||
|
|
||||||
gemfile.puts("group :plugins do")
|
# Create the request set for the new plugins
|
||||||
plugins.each do |name, plugin|
|
request_set = Gem::RequestSet.new(*plugin_deps)
|
||||||
version = plugin["gem_version"]
|
|
||||||
version = nil if version == ""
|
|
||||||
|
|
||||||
opts = {}
|
installer_set = Gem::Resolver.compose_sets(
|
||||||
if plugin["require"] && plugin["require"] != ""
|
installer_set,
|
||||||
opts[:require] = plugin["require"]
|
generate_builtin_set,
|
||||||
|
generate_plugin_set(skips)
|
||||||
|
)
|
||||||
|
|
||||||
|
@logger.debug("Generating solution set for installation.")
|
||||||
|
|
||||||
|
# Generate the required solution set for new plugins
|
||||||
|
solution = request_set.resolve(installer_set)
|
||||||
|
activate_solution(solution)
|
||||||
|
|
||||||
|
@logger.debug("Installing required gems.")
|
||||||
|
|
||||||
|
# Install all remote gems into plugin path. Set the installer to ignore dependencies
|
||||||
|
# as we know the dependencies are satisfied and it will attempt to validate a gem's
|
||||||
|
# dependencies are satisified by gems in the install directory (which will likely not
|
||||||
|
# be true)
|
||||||
|
result = request_set.install_into(plugin_gem_path.to_s, true, ignore_dependencies: true)
|
||||||
|
result = result.map(&:full_spec)
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the composite resolver set totally all of vagrant (builtin + plugin set)
|
||||||
|
def generate_vagrant_set
|
||||||
|
Gem::Resolver.compose_sets(generate_builtin_set, generate_plugin_set)
|
||||||
|
end
|
||||||
|
|
||||||
|
# @return [Array<[Gem::Specification, String]>] spec and directory pairs
|
||||||
|
def vagrant_internal_specs
|
||||||
|
list = {}
|
||||||
|
directories = [Gem::Specification.default_specifications_dir]
|
||||||
|
Gem::Specification.find_all{true}.each do |spec|
|
||||||
|
list[spec.full_name] = spec
|
||||||
|
end
|
||||||
|
if(!defined?(::Bundler))
|
||||||
|
directories += Gem::Specification.dirs.find_all do |path|
|
||||||
|
!path.start_with?(Gem.user_dir)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Gem::Specification.each_spec(directories) do |spec|
|
||||||
|
if !list[spec.full_name]
|
||||||
|
list[spec.full_name] = spec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
list.values
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the builtin resolver set
|
||||||
|
def generate_builtin_set
|
||||||
|
builtin_set = BuiltinSet.new
|
||||||
|
@logger.debug("Generating new builtin set instance.")
|
||||||
|
vagrant_internal_specs.each do |spec|
|
||||||
|
builtin_set.add_builtin_spec(spec)
|
||||||
|
end
|
||||||
|
builtin_set
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate the plugin resolver set. Optionally provide specification names (short or
|
||||||
|
# full) that should be ignored
|
||||||
|
def generate_plugin_set(skip=[])
|
||||||
|
plugin_set = PluginSet.new
|
||||||
|
@logger.debug("Generating new plugin set instance. Skip gems - #{skip}")
|
||||||
|
Dir.glob(plugin_gem_path.join('specifications/*.gemspec').to_s).each do |spec_path|
|
||||||
|
spec = Gem::Specification.load(spec_path)
|
||||||
|
desired_spec_path = File.join(spec.gem_dir, "#{spec.name}.gemspec")
|
||||||
|
# Vendor set requires the spec to be within the gem directory. Some gems will package their
|
||||||
|
# spec file, and that's not what we want to load.
|
||||||
|
if !File.exist?(desired_spec_path) || !FileUtils.cmp(spec.spec_file, desired_spec_path)
|
||||||
|
File.write(desired_spec_path, spec.to_ruby)
|
||||||
|
end
|
||||||
|
next if skip.include?(spec.name) || skip.include?(spec.full_name)
|
||||||
|
plugin_set.add_vendor_gem(spec.name, spec.gem_dir)
|
||||||
|
end
|
||||||
|
plugin_set
|
||||||
|
end
|
||||||
|
|
||||||
|
# Activate a given solution
|
||||||
|
def activate_solution(solution)
|
||||||
|
retried = false
|
||||||
|
begin
|
||||||
|
@logger.debug("Activating solution set: #{solution.map(&:full_name)}")
|
||||||
|
solution.each do |activation_request|
|
||||||
|
unless activation_request.full_spec.activated?
|
||||||
|
@logger.debug("Activating gem #{activation_request.full_spec.full_name}")
|
||||||
|
activation_request.full_spec.activate
|
||||||
|
if(defined?(::Bundler))
|
||||||
|
@logger.debug("Marking gem #{activation_request.full_spec.full_name} loaded within Bundler.")
|
||||||
|
::Bundler.rubygems.mark_loaded activation_request.full_spec
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue Gem::LoadError => e
|
||||||
|
# Depending on the version of Ruby, the ordering of the solution set
|
||||||
|
# will be either 0..n (molinillo) or n..0 (pre-molinillo). Instead of
|
||||||
|
# attempting to determine what's in use, or if it has some how changed
|
||||||
|
# again, just reverse order on failure and attempt again.
|
||||||
|
if retried
|
||||||
|
@logger.error("Failed to load solution set - #{e.class}: #{e}")
|
||||||
|
matcher = e.message.match(/Could not find '(?<gem_name>[^']+)'/)
|
||||||
|
if matcher && !matcher["gem_name"].empty?
|
||||||
|
desired_activation_request = solution.detect do |request|
|
||||||
|
request.name == matcher["gem_name"]
|
||||||
|
end
|
||||||
|
if desired_activation_request && !desired_activation_request.full_spec.activated?
|
||||||
|
activation_request = desired_activation_request
|
||||||
|
@logger.warn("Found misordered activation request for #{desired_activation_request.full_name}. Moving to solution HEAD.")
|
||||||
|
solution.delete(desired_activation_request)
|
||||||
|
solution.unshift(desired_activation_request)
|
||||||
|
retry
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
gemfile.puts(%Q[gem "#{name}", #{version.inspect}, #{opts.inspect}])
|
raise
|
||||||
|
else
|
||||||
|
@logger.debug("Failed to load solution set. Retrying with reverse order.")
|
||||||
|
retried = true
|
||||||
|
solution.reverse!
|
||||||
|
retry
|
||||||
end
|
end
|
||||||
gemfile.puts("end")
|
|
||||||
gemfile.close
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This installs a set of plugins and optionally updates those gems.
|
# This is a custom Gem::Resolver::Set for use with vagrant "system" gems. It
|
||||||
#
|
# allows the installed set of gems to be used for providing a solution while
|
||||||
# @param [Hash] plugins
|
# enforcing strict constraints. This ensures that plugins cannot "upgrade"
|
||||||
# @param [Hash, Boolean] update If true, updates all plugins, otherwise
|
# gems that are builtin to vagrant itself.
|
||||||
# can be a hash of options. See Bundler.definition.
|
class BuiltinSet < Gem::Resolver::Set
|
||||||
# @return [Array<Gem::Specification>]
|
|
||||||
def internal_install(plugins, update, **extra)
|
|
||||||
gemfile = build_gemfile(plugins)
|
|
||||||
lockfile = "#{gemfile.path}.lock"
|
|
||||||
definition = ::Bundler::Definition.build(gemfile, lockfile, update)
|
|
||||||
root = File.dirname(gemfile.path)
|
|
||||||
opts = {}
|
|
||||||
opts["local"] = true if extra[:local]
|
|
||||||
|
|
||||||
with_isolated_gem do
|
|
||||||
::Bundler::Installer.install(root, definition, opts)
|
|
||||||
end
|
|
||||||
|
|
||||||
# TODO(mitchellh): clean gems here... for some reason when I put
|
|
||||||
# it in on install, we get a GemNotFound exception. Gotta investigate.
|
|
||||||
|
|
||||||
definition.specs
|
|
||||||
rescue ::Bundler::VersionConflict => e
|
|
||||||
raise Errors::PluginInstallVersionConflict,
|
|
||||||
conflicts: e.to_s.gsub("Bundler", "Vagrant")
|
|
||||||
rescue ::Bundler::BundlerError => e
|
|
||||||
if !::Bundler.ui.is_a?(BundlerUI)
|
|
||||||
raise
|
|
||||||
end
|
|
||||||
|
|
||||||
# Add the warn/error level output from Bundler if we have any
|
|
||||||
message = "#{e.message}"
|
|
||||||
if ::Bundler.ui.output != ""
|
|
||||||
message += "\n\n#{::Bundler.ui.output}"
|
|
||||||
end
|
|
||||||
|
|
||||||
raise ::Bundler::BundlerError, message
|
|
||||||
end
|
|
||||||
|
|
||||||
def with_isolated_gem
|
|
||||||
raise Errors::BundlerDisabled if !@enabled
|
|
||||||
|
|
||||||
tmp_gemfile = tempfile("vagrant-gemfile")
|
|
||||||
tmp_gemfile.close
|
|
||||||
|
|
||||||
# Remove bundler settings so that Bundler isn't loaded when building
|
|
||||||
# native extensions because it causes all sorts of problems.
|
|
||||||
old_rubyopt = ENV["RUBYOPT"]
|
|
||||||
old_gemfile = ENV["BUNDLE_GEMFILE"]
|
|
||||||
ENV["BUNDLE_GEMFILE"] = tmp_gemfile.path
|
|
||||||
ENV["RUBYOPT"] = (ENV["RUBYOPT"] || "").gsub(/-rbundler\/setup\s*/, "")
|
|
||||||
|
|
||||||
# Set the GEM_HOME so gems are installed only to our local gem dir
|
|
||||||
ENV["GEM_HOME"] = Vagrant.user_data_path.join("gems").to_s
|
|
||||||
|
|
||||||
# Clear paths so that it reads the new GEM_HOME setting
|
|
||||||
Gem.paths = ENV
|
|
||||||
|
|
||||||
# Reset the all specs override that Bundler does
|
|
||||||
old_all = Gem::Specification._all
|
|
||||||
|
|
||||||
# WARNING: Seriously don't touch this without reading the comment attached
|
|
||||||
# to the monkey-patch at the bottom of this file.
|
|
||||||
Gem::Specification.vagrant_reset!
|
|
||||||
|
|
||||||
# /etc/gemrc and so on.
|
|
||||||
old_config = nil
|
|
||||||
begin
|
|
||||||
old_config = Gem.configuration
|
|
||||||
rescue Psych::SyntaxError
|
|
||||||
# Just ignore this. This means that the ".gemrc" file has
|
|
||||||
# an invalid syntax and can't be loaded. We don't care, because
|
|
||||||
# when we set Gem.configuration to nil later, it'll force a reload
|
|
||||||
# if it is needed.
|
|
||||||
end
|
|
||||||
Gem.configuration = NilGemConfig.new
|
|
||||||
|
|
||||||
# Use a silent UI so that we have no output
|
|
||||||
Gem::DefaultUserInteraction.use_ui(Gem::SilentUI.new) do
|
|
||||||
return yield
|
|
||||||
end
|
|
||||||
ensure
|
|
||||||
tmp_gemfile.unlink rescue nil
|
|
||||||
|
|
||||||
ENV["BUNDLE_GEMFILE"] = old_gemfile
|
|
||||||
ENV["GEM_HOME"] = @gem_home
|
|
||||||
ENV["RUBYOPT"] = old_rubyopt
|
|
||||||
|
|
||||||
Gem.configuration = old_config
|
|
||||||
Gem.paths = ENV
|
|
||||||
Gem::Specification.all = old_all
|
|
||||||
end
|
|
||||||
|
|
||||||
# This method returns a proper "tempfile" on disk. Ruby's Tempfile class
|
|
||||||
# would work really great for this, except GC can come along and remove
|
|
||||||
# the file before we are done with it. This is because we "close" the file,
|
|
||||||
# but we might be shelling out to a subprocess.
|
|
||||||
#
|
|
||||||
# @return [File]
|
|
||||||
def tempfile(name)
|
|
||||||
path = Dir::Tmpname.create(name) {}
|
|
||||||
return File.open(path, "w+")
|
|
||||||
end
|
|
||||||
|
|
||||||
# This is pretty hacky but it is a custom implementation of
|
|
||||||
# Gem::ConfigFile so that we don't load any gemrc files.
|
|
||||||
class NilGemConfig < Gem::ConfigFile
|
|
||||||
def initialize
|
def initialize
|
||||||
# We _can not_ `super` here because that can really mess up
|
super
|
||||||
# some other configuration state. We need to just set everything
|
@remote = false
|
||||||
# directly.
|
@specs = []
|
||||||
|
end
|
||||||
|
|
||||||
@api_keys = {}
|
def add_builtin_spec(spec)
|
||||||
@args = []
|
@specs.push(spec).uniq!
|
||||||
@backtrace = false
|
end
|
||||||
@bulk_threshold = 1000
|
|
||||||
@hash = {}
|
def find_all(req)
|
||||||
@update_sources = true
|
@specs.select do |spec|
|
||||||
@verbose = true
|
req.match?(spec)
|
||||||
|
end.map do |spec|
|
||||||
|
Gem::Resolver::InstalledSpecification.new(self, spec)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This monkey patches Gem::Specification from RubyGems to add a new method,
|
# This is a custom Gem::Resolver::Set for use with Vagrant plugins. It is
|
||||||
# `vagrant_reset!`. For some background, Vagrant needs to set the value
|
# a modified Gem::Resolver::VendorSet that supports multiple versions of
|
||||||
# of these variables to nil to force new specs to be loaded. Previously,
|
# a specific gem
|
||||||
# this was accomplished by setting Gem::Specification.specs = nil. However,
|
class PluginSet < Gem::Resolver::VendorSet
|
||||||
# newer versions of Rubygems try to map across that nil using a group_by
|
##
|
||||||
# clause, breaking things.
|
# Adds a specification to the set with the given +name+ which has been
|
||||||
#
|
# unpacked into the given +directory+.
|
||||||
# This generally never affected Vagrant users who were using the official
|
def add_vendor_gem(name, directory)
|
||||||
# Vagrant installers because we lock to an older version of Rubygems that
|
gemspec = File.join(directory, "#{name}.gemspec")
|
||||||
# does not have this issue. The users of the official debian packages,
|
spec = Gem::Specification.load(gemspec)
|
||||||
# however, experienced this issue because they float on Rubygems.
|
if !spec
|
||||||
#
|
raise Gem::GemNotFoundException,
|
||||||
# In GH-7073, a number of Debian users reported this issue, but it was not
|
"unable to find #{gemspec} for gem #{name}"
|
||||||
# reproducible in the official installer for reasons described above. Commit
|
end
|
||||||
# ba77d4b switched to using Gem::Specification.reset, but this actually
|
|
||||||
# broke the ability to install gems locally (GH-7493) because it resets
|
spec.full_gem_path = File.expand_path(directory)
|
||||||
# the complete local cache, which is already built.
|
|
||||||
#
|
@specs[spec.name] ||= []
|
||||||
# The only solution that works with both new and old versions of Rubygems
|
@specs[spec.name] << spec
|
||||||
# is to provide our own function for JUST resetting all the stubs. Both
|
@directories[spec] = directory
|
||||||
# @@all and @@stubs must be set to a falsey value, so some of the
|
|
||||||
# originally-suggested solutions of using an empty array do not work. Only
|
spec
|
||||||
# setting these values to nil (without clearing the cache), allows Vagrant
|
|
||||||
# to install and manage plugins.
|
|
||||||
class Gem::Specification < Gem::BasicSpecification
|
|
||||||
def self.vagrant_reset!
|
|
||||||
@@all = @@stubs = nil
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if ::Bundler::UI.const_defined? :Silent
|
##
|
||||||
class BundlerUI < ::Bundler::UI::Silent
|
# Returns an Array of VendorSpecification objects matching the
|
||||||
attr_reader :output
|
# DependencyRequest +req+.
|
||||||
|
def find_all(req)
|
||||||
def initialize
|
@specs.values.flatten.select do |spec|
|
||||||
@output = ""
|
req.match?(spec)
|
||||||
|
end.map do |spec|
|
||||||
|
source = Gem::Source::Vendor.new(@directories[spec])
|
||||||
|
Gem::Resolver::VendorSpecification.new(self, spec, source)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def info(message, newline = nil)
|
##
|
||||||
end
|
# Loads a spec with the given +name+. +version+, +platform+ and +source+ are
|
||||||
|
# ignored.
|
||||||
def confirm(message, newline = nil)
|
def load_spec (name, version, platform, source)
|
||||||
end
|
version = Gem::Version.new(version) if !version.is_a?(Gem::Version)
|
||||||
|
@specs.fetch(name, []).detect{|s| s.name == name && s.version = version}
|
||||||
def warn(message, newline = nil)
|
end
|
||||||
@output += message
|
end
|
||||||
@output += "\n" if newline
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def error(message, newline = nil)
|
# Patch for Ruby 2.2 and Bundler to behave properly when uninstalling plugins
|
||||||
@output += message
|
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
|
||||||
@output += "\n" if newline
|
if defined?(::Bundler) && !::Bundler::SpecSet.instance_methods.include?(:delete)
|
||||||
end
|
class Gem::Specification
|
||||||
|
def self.remove_spec(spec)
|
||||||
def debug(message, newline = nil)
|
Gem::Specification.reset
|
||||||
end
|
|
||||||
|
|
||||||
def debug?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def quiet?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def ask(message)
|
|
||||||
end
|
|
||||||
|
|
||||||
def level=(name)
|
|
||||||
end
|
|
||||||
|
|
||||||
def level(name = nil)
|
|
||||||
"info"
|
|
||||||
end
|
|
||||||
|
|
||||||
def trace(message, newline = nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
def silence
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -338,7 +338,7 @@ module Vagrant
|
||||||
# a priority to each in the order they exist so that we try these first.
|
# a priority to each in the order they exist so that we try these first.
|
||||||
config = {}
|
config = {}
|
||||||
root_config.vm.__providers.reverse.each_with_index do |key, idx|
|
root_config.vm.__providers.reverse.each_with_index do |key, idx|
|
||||||
config[key] = idx
|
config[key] = idx + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determine the max priority so that we can add the config priority
|
# Determine the max priority so that we can add the config priority
|
||||||
|
|
|
@ -340,6 +340,10 @@ module Vagrant
|
||||||
error_key(:downloader_interrupted)
|
error_key(:downloader_interrupted)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class DownloaderChecksumError < VagrantError
|
||||||
|
error_key(:downloader_checksum_error)
|
||||||
|
end
|
||||||
|
|
||||||
class EnvInval < VagrantError
|
class EnvInval < VagrantError
|
||||||
error_key(:env_inval)
|
error_key(:env_inval)
|
||||||
end
|
end
|
||||||
|
@ -456,6 +460,10 @@ module Vagrant
|
||||||
error_key(:nfs_bad_exports)
|
error_key(:nfs_bad_exports)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class NFSExportsFailed < VagrantError
|
||||||
|
error_key(:nfs_exports_failed)
|
||||||
|
end
|
||||||
|
|
||||||
class NFSCantReadExports < VagrantError
|
class NFSCantReadExports < VagrantError
|
||||||
error_key(:nfs_cant_read_exports)
|
error_key(:nfs_cant_read_exports)
|
||||||
end
|
end
|
||||||
|
@ -580,6 +588,10 @@ module Vagrant
|
||||||
error_key(:plugin_uninstall_system)
|
error_key(:plugin_uninstall_system)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class PluginInitError < VagrantError
|
||||||
|
error_key(:plugin_init_error)
|
||||||
|
end
|
||||||
|
|
||||||
class PushesNotDefined < VagrantError
|
class PushesNotDefined < VagrantError
|
||||||
error_key(:pushes_not_defined)
|
error_key(:pushes_not_defined)
|
||||||
end
|
end
|
||||||
|
@ -608,6 +620,10 @@ module Vagrant
|
||||||
error_key(:rsync_not_installed_in_guest)
|
error_key(:rsync_not_installed_in_guest)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
class RSyncGuestInstallError < VagrantError
|
||||||
|
error_key(:rsync_guest_install_error)
|
||||||
|
end
|
||||||
|
|
||||||
class SCPPermissionDenied < VagrantError
|
class SCPPermissionDenied < VagrantError
|
||||||
error_key(:scp_permission_denied)
|
error_key(:scp_permission_denied)
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,10 +44,9 @@ module Vagrant
|
||||||
local = false
|
local = false
|
||||||
if name =~ /\.gem$/
|
if name =~ /\.gem$/
|
||||||
# If this is a gem file, then we install that gem locally.
|
# If this is a gem file, then we install that gem locally.
|
||||||
local_spec = Vagrant::Bundler.instance.install_local(name)
|
local_spec = Vagrant::Bundler.instance.install_local(name, opts)
|
||||||
name = local_spec.name
|
name = local_spec.name
|
||||||
opts[:version] = local_spec.version.to_s
|
opts[:version] = local_spec.version.to_s
|
||||||
local = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
plugins = installed_plugins
|
plugins = installed_plugins
|
||||||
|
@ -57,33 +56,41 @@ module Vagrant
|
||||||
"sources" => opts[:sources],
|
"sources" => opts[:sources],
|
||||||
}
|
}
|
||||||
|
|
||||||
result = nil
|
if local_spec.nil?
|
||||||
install_lambda = lambda do
|
result = nil
|
||||||
Vagrant::Bundler.instance.install(plugins, local).each do |spec|
|
install_lambda = lambda do
|
||||||
next if spec.name != name
|
Vagrant::Bundler.instance.install(plugins, local).each do |spec|
|
||||||
next if result && result.version >= spec.version
|
next if spec.name != name
|
||||||
result = spec
|
next if result && result.version >= spec.version
|
||||||
|
result = spec
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if opts[:verbose]
|
if opts[:verbose]
|
||||||
Vagrant::Bundler.instance.verbose(&install_lambda)
|
Vagrant::Bundler.instance.verbose(&install_lambda)
|
||||||
|
else
|
||||||
|
install_lambda.call
|
||||||
|
end
|
||||||
else
|
else
|
||||||
install_lambda.call
|
result = local_spec
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add the plugin to the state file
|
# Add the plugin to the state file
|
||||||
@user_file.add_plugin(
|
@user_file.add_plugin(
|
||||||
result.name,
|
result.name,
|
||||||
version: opts[:version],
|
version: opts[:version],
|
||||||
require: opts[:require],
|
require: opts[:require],
|
||||||
sources: opts[:sources],
|
sources: opts[:sources],
|
||||||
|
installed_gem_version: result.version.to_s
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# After install clean plugin gems to remove any cruft. This is useful
|
||||||
|
# for removing outdated dependencies or other versions of an installed
|
||||||
|
# plugin if the plugin is upgraded/downgraded
|
||||||
|
Vagrant::Bundler.instance.clean(installed_plugins)
|
||||||
result
|
result
|
||||||
rescue ::Bundler::GemNotFound
|
rescue Gem::GemNotFoundException
|
||||||
raise Errors::PluginGemNotFound, name: name
|
raise Errors::PluginGemNotFound, name: name
|
||||||
rescue ::Bundler::BundlerError => e
|
rescue Gem::Exception => e
|
||||||
raise Errors::BundlerError, message: e.to_s
|
raise Errors::BundlerError, message: e.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -102,14 +109,30 @@ module Vagrant
|
||||||
|
|
||||||
# Clean the environment, removing any old plugins
|
# Clean the environment, removing any old plugins
|
||||||
Vagrant::Bundler.instance.clean(installed_plugins)
|
Vagrant::Bundler.instance.clean(installed_plugins)
|
||||||
rescue ::Bundler::BundlerError => e
|
rescue Gem::Exception => e
|
||||||
raise Errors::BundlerError, message: e.to_s
|
raise Errors::BundlerError, message: e.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# Updates all or a specific set of plugins.
|
# Updates all or a specific set of plugins.
|
||||||
def update_plugins(specific)
|
def update_plugins(specific)
|
||||||
Vagrant::Bundler.instance.update(installed_plugins, specific)
|
result = Vagrant::Bundler.instance.update(installed_plugins, specific)
|
||||||
rescue ::Bundler::BundlerError => e
|
installed_plugins.each do |name, info|
|
||||||
|
matching_spec = result.detect{|s| s.name == name}
|
||||||
|
info = Hash[
|
||||||
|
info.map do |key, value|
|
||||||
|
[key.to_sym, value]
|
||||||
|
end
|
||||||
|
]
|
||||||
|
if matching_spec
|
||||||
|
@user_file.add_plugin(name, **info.merge(
|
||||||
|
version: "> 0",
|
||||||
|
installed_gem_version: matching_spec.version.to_s
|
||||||
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Vagrant::Bundler.instance.clean(installed_plugins)
|
||||||
|
result
|
||||||
|
rescue Gem::Exception => e
|
||||||
raise Errors::BundlerError, message: e.to_s
|
raise Errors::BundlerError, message: e.to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,8 +146,14 @@ module Vagrant
|
||||||
system[k] = v.merge("system" => true)
|
system[k] = v.merge("system" => true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
plugin_list = system.merge(@user_file.installed_plugins)
|
||||||
|
|
||||||
system.merge(@user_file.installed_plugins)
|
# Sort plugins by name
|
||||||
|
Hash[
|
||||||
|
plugin_list.map{|plugin_name, plugin_info|
|
||||||
|
[plugin_name, plugin_info]
|
||||||
|
}.sort_by(&:first)
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
# This returns the list of plugins that are installed as
|
# This returns the list of plugins that are installed as
|
||||||
|
|
|
@ -31,11 +31,12 @@ module Vagrant
|
||||||
# @param [String] name The name of the plugin
|
# @param [String] name The name of the plugin
|
||||||
def add_plugin(name, **opts)
|
def add_plugin(name, **opts)
|
||||||
@data["installed"][name] = {
|
@data["installed"][name] = {
|
||||||
"ruby_version" => RUBY_VERSION,
|
"ruby_version" => RUBY_VERSION,
|
||||||
"vagrant_version" => Vagrant::VERSION,
|
"vagrant_version" => Vagrant::VERSION,
|
||||||
"gem_version" => opts[:version] || "",
|
"gem_version" => opts[:version] || "",
|
||||||
"require" => opts[:require] || "",
|
"require" => opts[:require] || "",
|
||||||
"sources" => opts[:sources] || [],
|
"sources" => opts[:sources] || [],
|
||||||
|
"installed_gem_version" => opts[:installed_gem_version]
|
||||||
}
|
}
|
||||||
|
|
||||||
save!
|
save!
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
# This file is to be loaded _before_ any RubyGems are loaded. This file
|
|
||||||
# initializes the Bundler context so that Vagrant and its associated plugins
|
|
||||||
# can load properly, and then execs out into Vagrant again.
|
|
||||||
|
|
||||||
require_relative "shared_helpers"
|
|
||||||
|
|
||||||
if defined?(Bundler)
|
|
||||||
require "bundler/shared_helpers"
|
|
||||||
if Bundler::SharedHelpers.in_bundle? && !Vagrant.very_quiet?
|
|
||||||
puts "Vagrant appears to be running in a Bundler environment. Your "
|
|
||||||
puts "existing Gemfile will be used. Vagrant will not auto-load any plugins"
|
|
||||||
puts "installed with `vagrant plugin`. Vagrant will autoload any plugins in"
|
|
||||||
puts "the 'plugins' group in your Gemfile. You can force Vagrant to take over"
|
|
||||||
puts "with VAGRANT_FORCE_BUNDLER."
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
require_relative "bundler"
|
|
||||||
require_relative "plugin/manager"
|
|
||||||
|
|
||||||
plugins = Vagrant::Plugin::Manager.instance.installed_plugins
|
|
||||||
Vagrant::Bundler.instance.init!(plugins)
|
|
||||||
|
|
||||||
ENV["VAGRANT_INTERNAL_BUNDLERIZED"] = "1"
|
|
||||||
|
|
||||||
# If the VAGRANT_EXECUTABLE env is set, then we use that to point to a
|
|
||||||
# Ruby file to directly execute. Otherwise, we just depend on PATH lookup.
|
|
||||||
# This minor optimization can save hundreds of milliseconds on Windows.
|
|
||||||
if ENV["VAGRANT_EXECUTABLE"]
|
|
||||||
Kernel.exec("ruby", ENV["VAGRANT_EXECUTABLE"], *ARGV)
|
|
||||||
else
|
|
||||||
Kernel.exec("vagrant", *ARGV)
|
|
||||||
end
|
|
|
@ -38,11 +38,18 @@ module Vagrant
|
||||||
ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"]
|
ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Should the plugin system be initialized
|
||||||
|
#
|
||||||
|
# @return [Boolean]
|
||||||
|
def self.plugins_init?
|
||||||
|
!ENV['VAGRANT_DISABLE_PLUGIN_INIT']
|
||||||
|
end
|
||||||
|
|
||||||
# This returns whether or not 3rd party plugins should and can be loaded.
|
# This returns whether or not 3rd party plugins should and can be loaded.
|
||||||
#
|
#
|
||||||
# @return [Boolean]
|
# @return [Boolean]
|
||||||
def self.plugins_enabled?
|
def self.plugins_enabled?
|
||||||
!ENV["VAGRANT_NO_PLUGINS"] && $vagrant_bundler_runtime
|
!ENV["VAGRANT_NO_PLUGINS"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether or not super quiet mode is enabled. This is ill-advised.
|
# Whether or not super quiet mode is enabled. This is ill-advised.
|
||||||
|
|
|
@ -9,6 +9,7 @@ module Vagrant
|
||||||
autoload :SafeExec, 'vagrant/util/safe_exec'
|
autoload :SafeExec, 'vagrant/util/safe_exec'
|
||||||
autoload :StackedProcRunner, 'vagrant/util/stacked_proc_runner'
|
autoload :StackedProcRunner, 'vagrant/util/stacked_proc_runner'
|
||||||
autoload :TemplateRenderer, 'vagrant/util/template_renderer'
|
autoload :TemplateRenderer, 'vagrant/util/template_renderer'
|
||||||
|
autoload :StringBlockEditor, 'vagrant/util/string_block_editor'
|
||||||
autoload :Subprocess, 'vagrant/util/subprocess'
|
autoload :Subprocess, 'vagrant/util/subprocess'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
require "uri"
|
require "uri"
|
||||||
|
|
||||||
require "log4r"
|
require "log4r"
|
||||||
|
require "digest/md5"
|
||||||
|
require "digest/sha1"
|
||||||
require "vagrant/util/busy"
|
require "vagrant/util/busy"
|
||||||
require "vagrant/util/platform"
|
require "vagrant/util/platform"
|
||||||
require "vagrant/util/subprocess"
|
require "vagrant/util/subprocess"
|
||||||
|
@ -18,6 +19,12 @@ module Vagrant
|
||||||
# Vagrant/1.7.4 (+https://www.vagrantup.com; ruby2.1.0)
|
# Vagrant/1.7.4 (+https://www.vagrantup.com; ruby2.1.0)
|
||||||
USER_AGENT = "Vagrant/#{VERSION} (+https://www.vagrantup.com; #{RUBY_ENGINE}#{RUBY_VERSION})".freeze
|
USER_AGENT = "Vagrant/#{VERSION} (+https://www.vagrantup.com; #{RUBY_ENGINE}#{RUBY_VERSION})".freeze
|
||||||
|
|
||||||
|
# Supported file checksum
|
||||||
|
CHECKSUM_MAP = {
|
||||||
|
:md5 => Digest::MD5,
|
||||||
|
:sha1 => Digest::SHA1
|
||||||
|
}.freeze
|
||||||
|
|
||||||
attr_reader :source
|
attr_reader :source
|
||||||
attr_reader :destination
|
attr_reader :destination
|
||||||
|
|
||||||
|
@ -52,6 +59,10 @@ module Vagrant
|
||||||
@ui = options[:ui]
|
@ui = options[:ui]
|
||||||
@client_cert = options[:client_cert]
|
@client_cert = options[:client_cert]
|
||||||
@location_trusted = options[:location_trusted]
|
@location_trusted = options[:location_trusted]
|
||||||
|
@checksums = {
|
||||||
|
:md5 => options[:md5],
|
||||||
|
:sha1 => options[:sha1]
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
# This executes the actual download, downloading the source file
|
# This executes the actual download, downloading the source file
|
||||||
|
@ -161,6 +172,8 @@ module Vagrant
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
validate_download!(@source, @destination, @checksums)
|
||||||
|
|
||||||
# Everything succeeded
|
# Everything succeeded
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
@ -178,6 +191,46 @@ module Vagrant
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
# Apply any checksum validations based on provided
|
||||||
|
# options content
|
||||||
|
#
|
||||||
|
# @param source [String] Source of file
|
||||||
|
# @param path [String, Pathname] local file path
|
||||||
|
# @param checksums [Hash] User provided options
|
||||||
|
# @option checksums [String] :md5 Compare MD5 checksum
|
||||||
|
# @option checksums [String] :sha1 Compare SHA1 checksum
|
||||||
|
# @return [Boolean]
|
||||||
|
def validate_download!(source, path, checksums)
|
||||||
|
CHECKSUM_MAP.each do |type, klass|
|
||||||
|
if checksums[type]
|
||||||
|
result = checksum_file(klass, path)
|
||||||
|
@logger.debug("Validating checksum (#{type}) for #{source}. " \
|
||||||
|
"expected: #{checksums[type]} actual: #{result}")
|
||||||
|
if checksums[type] != result
|
||||||
|
raise Errors::DownloaderChecksumError.new(
|
||||||
|
source: source,
|
||||||
|
path: path,
|
||||||
|
type: type,
|
||||||
|
expected_checksum: checksums[type],
|
||||||
|
actual_checksum: result
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
true
|
||||||
|
end
|
||||||
|
|
||||||
|
# Generate checksum on given file
|
||||||
|
#
|
||||||
|
# @param digest_class [Class] Digest class to use for generating checksum
|
||||||
|
# @param path [String, Pathname] Path to file
|
||||||
|
# @return [String] hexdigest result
|
||||||
|
def checksum_file(digest_class, path)
|
||||||
|
digester = digest_class.new
|
||||||
|
digester.file(path)
|
||||||
|
digester.hexdigest
|
||||||
|
end
|
||||||
|
|
||||||
def execute_curl(options, subprocess_options, &data_proc)
|
def execute_curl(options, subprocess_options, &data_proc)
|
||||||
options = options.dup
|
options = options.dup
|
||||||
options << subprocess_options
|
options << subprocess_options
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
require "bundler"
|
|
||||||
|
|
||||||
module Vagrant
|
module Vagrant
|
||||||
module Util
|
module Util
|
||||||
class Env
|
class Env
|
||||||
def self.with_original_env
|
def self.with_original_env
|
||||||
original_env = ENV.to_hash
|
original_env = ENV.to_hash
|
||||||
ENV.replace(::Bundler::ORIGINAL_ENV) if defined?(::Bundler::ORIGINAL_ENV)
|
if defined?(::Bundler) && defined?(::Bundler::ORIGINAL_ENV)
|
||||||
|
ENV.replace(::Bundler::ORIGINAL_ENV)
|
||||||
|
end
|
||||||
ENV.update(Vagrant.original_env)
|
ENV.update(Vagrant.original_env)
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
|
@ -37,7 +37,9 @@ module Vagrant
|
||||||
# the block to execute with the cleaned environment
|
# the block to execute with the cleaned environment
|
||||||
def self.with_clean_env
|
def self.with_clean_env
|
||||||
with_original_env do
|
with_original_env do
|
||||||
ENV["MANPATH"] = ENV["BUNDLE_ORIG_MANPATH"]
|
if ENV["BUNDLE_ORIG_MANPATH"]
|
||||||
|
ENV["MANPATH"] = ENV["BUNDLE_ORIG_MANPATH"]
|
||||||
|
end
|
||||||
ENV.delete_if { |k,_| k[0,7] == "BUNDLE_" }
|
ENV.delete_if { |k,_| k[0,7] == "BUNDLE_" }
|
||||||
if ENV.has_key? "RUBYOPT"
|
if ENV.has_key? "RUBYOPT"
|
||||||
ENV["RUBYOPT"] = ENV["RUBYOPT"].sub("-rbundler/setup", "")
|
ENV["RUBYOPT"] = ENV["RUBYOPT"].sub("-rbundler/setup", "")
|
||||||
|
|
|
@ -7,6 +7,9 @@ module Vagrant
|
||||||
# thread. In that case, `safe_exec` automatically falls back to
|
# thread. In that case, `safe_exec` automatically falls back to
|
||||||
# forking.
|
# forking.
|
||||||
class SafeExec
|
class SafeExec
|
||||||
|
|
||||||
|
@@logger = Log4r::Logger.new("vagrant::util::safe_exec")
|
||||||
|
|
||||||
def self.exec(command, *args)
|
def self.exec(command, *args)
|
||||||
# Create a list of things to rescue from. Since this is OS
|
# Create a list of things to rescue from. Since this is OS
|
||||||
# specific, we need to do some defined? checks here to make
|
# specific, we need to do some defined? checks here to make
|
||||||
|
@ -18,10 +21,27 @@ module Vagrant
|
||||||
|
|
||||||
fork_instead = false
|
fork_instead = false
|
||||||
begin
|
begin
|
||||||
pid = nil
|
if fork_instead
|
||||||
pid = fork if fork_instead
|
if Vagrant::Util::Platform.windows?
|
||||||
Kernel.exec(command, *args) if pid.nil?
|
@@logger.debug("Using subprocess because windows platform")
|
||||||
Process.wait(pid) if pid
|
args = args.dup << {notify: [:stdout, :stderr]}
|
||||||
|
result = Vagrant::Util::Subprocess.execute(command, *args) do |type, data|
|
||||||
|
case type
|
||||||
|
when :stdout
|
||||||
|
@@logger.info(data, new_line: false)
|
||||||
|
when :stderr
|
||||||
|
@@logger.info(data, new_line: false)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Kernel.exit(result.exit_code)
|
||||||
|
else
|
||||||
|
pid = fork
|
||||||
|
Kernel.exec(command, *args)
|
||||||
|
Process.wait(pid)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Kernel.exec(command, *args)
|
||||||
|
end
|
||||||
rescue *rescue_from
|
rescue *rescue_from
|
||||||
# We retried already, raise the issue and be done
|
# We retried already, raise the issue and be done
|
||||||
raise if fork_instead
|
raise if fork_instead
|
||||||
|
|
|
@ -144,10 +144,11 @@ module Vagrant
|
||||||
# Record the start time for timeout purposes
|
# Record the start time for timeout purposes
|
||||||
start_time = Time.now.to_i
|
start_time = Time.now.to_i
|
||||||
|
|
||||||
|
open_readers = [stdout, stderr]
|
||||||
|
open_writers = notify_stdin ? [process.io.stdin] : []
|
||||||
@logger.debug("Selecting on IO")
|
@logger.debug("Selecting on IO")
|
||||||
while true
|
while true
|
||||||
writers = notify_stdin ? [process.io.stdin] : []
|
results = ::IO.select(open_readers, open_writers, nil, 0.1)
|
||||||
results = ::IO.select([stdout, stderr], writers, nil, 0.1)
|
|
||||||
results ||= []
|
results ||= []
|
||||||
readers = results[0]
|
readers = results[0]
|
||||||
writers = results[1]
|
writers = results[1]
|
||||||
|
@ -178,8 +179,14 @@ module Vagrant
|
||||||
break if process.exited?
|
break if process.exited?
|
||||||
|
|
||||||
# Check the writers to see if they're ready, and notify any listeners
|
# Check the writers to see if they're ready, and notify any listeners
|
||||||
if writers && !writers.empty?
|
if writers && !writers.empty? && block_given?
|
||||||
yield :stdin, process.io.stdin if block_given?
|
yield :stdin, process.io.stdin
|
||||||
|
|
||||||
|
# if the callback closed stdin, we should remove it, because
|
||||||
|
# IO.select() will throw if called with a closed io.
|
||||||
|
if process.io.stdin.closed?
|
||||||
|
open_writers = []
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -290,7 +297,9 @@ module Vagrant
|
||||||
def jailbreak(env = {})
|
def jailbreak(env = {})
|
||||||
return if ENV.key?("VAGRANT_SKIP_SUBPROCESS_JAILBREAK")
|
return if ENV.key?("VAGRANT_SKIP_SUBPROCESS_JAILBREAK")
|
||||||
|
|
||||||
env.replace(::Bundler::ORIGINAL_ENV) if defined?(::Bundler::ORIGINAL_ENV)
|
if defined?(::Bundler) && defined?(::Bundler::ORIGINAL_ENV)
|
||||||
|
env.replace(::Bundler::ORIGINAL_ENV)
|
||||||
|
end
|
||||||
env.merge!(Vagrant.original_env)
|
env.merge!(Vagrant.original_env)
|
||||||
|
|
||||||
# Bundler does this, so I guess we should as well, since I think it
|
# Bundler does this, so I guess we should as well, since I think it
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module CommandBox
|
||||||
|
module Command
|
||||||
|
class Prune < Vagrant.plugin("2", :command)
|
||||||
|
def execute
|
||||||
|
options = {}
|
||||||
|
options[:force] = false
|
||||||
|
options[:dry_run] = false
|
||||||
|
|
||||||
|
opts = OptionParser.new do |o|
|
||||||
|
o.banner = "Usage: vagrant box prune [options]"
|
||||||
|
o.separator ""
|
||||||
|
o.separator "Options:"
|
||||||
|
o.separator ""
|
||||||
|
|
||||||
|
o.on("-p PROVIDER", "--provider PROVIDER", String, "The specific provider type for the boxes to destroy.") do |p|
|
||||||
|
options[:provider] = p
|
||||||
|
end
|
||||||
|
|
||||||
|
o.on("-n", "--dry-run", "Only print the boxes that would be removed.") do |f|
|
||||||
|
options[:dry_run] = f
|
||||||
|
end
|
||||||
|
|
||||||
|
o.on("--name NAME", String, "The specific box name to check for outdated versions.") do |name|
|
||||||
|
options[:name] = name
|
||||||
|
end
|
||||||
|
|
||||||
|
o.on("-f", "--force", "Destroy without confirmation even when box is in use.") do |f|
|
||||||
|
options[:force] = f
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse the options
|
||||||
|
argv = parse_options(opts)
|
||||||
|
return if !argv
|
||||||
|
|
||||||
|
boxes = @env.boxes.all.sort
|
||||||
|
if boxes.empty?
|
||||||
|
return @env.ui.warn(I18n.t("vagrant.commands.box.no_installed_boxes"), prefix: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
delete_oldest_boxes(boxes, options[:provider], options[:force], options[:name], options[:dry_run])
|
||||||
|
|
||||||
|
# Success, exit status 0
|
||||||
|
0
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def delete_oldest_boxes(boxes, only_provider, skip_confirm, only_name, dry_run)
|
||||||
|
# Find the longest box name
|
||||||
|
longest_box = boxes.max_by { |x| x[0].length }
|
||||||
|
longest_box_length = longest_box[0].length
|
||||||
|
|
||||||
|
# Hash map to keep track of newest versions
|
||||||
|
newest_boxes = Hash.new
|
||||||
|
|
||||||
|
# First find the newest version for every installed box
|
||||||
|
boxes.each do |name, version, provider|
|
||||||
|
next if only_provider and only_provider != provider.to_s
|
||||||
|
next if only_name and only_name != name
|
||||||
|
|
||||||
|
# Nested to make sure it works for boxes with different providers
|
||||||
|
if newest_boxes.has_key?(name)
|
||||||
|
if newest_boxes[name].has_key?(provider)
|
||||||
|
saved = Gem::Version.new(newest_boxes[name][provider])
|
||||||
|
current = Gem::Version.new(version)
|
||||||
|
if current > saved
|
||||||
|
newest_boxes[name][provider] = version
|
||||||
|
end
|
||||||
|
else
|
||||||
|
newest_boxes[name][provider] = version
|
||||||
|
end
|
||||||
|
else
|
||||||
|
newest_boxes[name] = Hash.new
|
||||||
|
newest_boxes[name][provider] = version
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@env.ui.info("The following boxes will be kept...");
|
||||||
|
newest_boxes.each do |name, providers|
|
||||||
|
providers.each do |provider, version|
|
||||||
|
@env.ui.info("#{name.ljust(longest_box_length)} (#{provider}, #{version})")
|
||||||
|
|
||||||
|
@env.ui.machine("box-name", name)
|
||||||
|
@env.ui.machine("box-provider", provider)
|
||||||
|
@env.ui.machine("box-version", version)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@env.ui.info("", prefix: false)
|
||||||
|
@env.ui.info("Checking for older boxes...");
|
||||||
|
|
||||||
|
# Track if we removed anything so the user can be informed
|
||||||
|
removed_any_box = false
|
||||||
|
boxes.each do |name, version, provider|
|
||||||
|
next if !newest_boxes.has_key?(name) or !newest_boxes[name].has_key?(provider)
|
||||||
|
|
||||||
|
current = Gem::Version.new(version)
|
||||||
|
saved = Gem::Version.new(newest_boxes[name][provider])
|
||||||
|
if current < saved
|
||||||
|
removed_any_box = true
|
||||||
|
|
||||||
|
# Use the remove box action
|
||||||
|
if dry_run
|
||||||
|
@env.ui.info("Would remove #{name} #{provider} #{version}")
|
||||||
|
else
|
||||||
|
@env.action_runner.run(Vagrant::Action.action_box_remove, {
|
||||||
|
box_name: name,
|
||||||
|
box_provider: provider,
|
||||||
|
box_version: version,
|
||||||
|
force_confirm_box_remove: skip_confirm,
|
||||||
|
box_remove_all_versions: false,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !removed_any_box
|
||||||
|
@env.ui.info("No old versions of boxes to remove...");
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -34,6 +34,11 @@ module VagrantPlugins
|
||||||
Remove
|
Remove
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@subcommands.register(:prune) do
|
||||||
|
require_relative "prune"
|
||||||
|
Prune
|
||||||
|
end
|
||||||
|
|
||||||
@subcommands.register(:repackage) do
|
@subcommands.register(:repackage) do
|
||||||
require File.expand_path("../repackage", __FILE__)
|
require File.expand_path("../repackage", __FILE__)
|
||||||
Repackage
|
Repackage
|
||||||
|
|
|
@ -6,6 +6,12 @@ module VagrantPlugins
|
||||||
module CommandPlugin
|
module CommandPlugin
|
||||||
module Action
|
module Action
|
||||||
# This middleware sequence will install a plugin.
|
# This middleware sequence will install a plugin.
|
||||||
|
def self.action_expunge
|
||||||
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
|
b.use ExpungePlugins
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.action_install
|
def self.action_install
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
b.use InstallGem
|
b.use InstallGem
|
||||||
|
@ -27,6 +33,13 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This middleware sequence will repair installed plugins.
|
||||||
|
def self.action_repair
|
||||||
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
|
b.use RepairPlugins
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# This middleware sequence will uninstall a plugin.
|
# This middleware sequence will uninstall a plugin.
|
||||||
def self.action_uninstall
|
def self.action_uninstall
|
||||||
Vagrant::Action::Builder.new.tap do |b|
|
Vagrant::Action::Builder.new.tap do |b|
|
||||||
|
@ -44,10 +57,12 @@ module VagrantPlugins
|
||||||
|
|
||||||
# The autoload farm
|
# The autoload farm
|
||||||
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
action_root = Pathname.new(File.expand_path("../action", __FILE__))
|
||||||
|
autoload :ExpungePlugins, action_root.join("expunge_plugins")
|
||||||
autoload :InstallGem, action_root.join("install_gem")
|
autoload :InstallGem, action_root.join("install_gem")
|
||||||
autoload :LicensePlugin, action_root.join("license_plugin")
|
autoload :LicensePlugin, action_root.join("license_plugin")
|
||||||
autoload :ListPlugins, action_root.join("list_plugins")
|
autoload :ListPlugins, action_root.join("list_plugins")
|
||||||
autoload :PluginExistsCheck, action_root.join("plugin_exists_check")
|
autoload :PluginExistsCheck, action_root.join("plugin_exists_check")
|
||||||
|
autoload :RepairPlugins, action_root.join("repair_plugins")
|
||||||
autoload :UninstallPlugin, action_root.join("uninstall_plugin")
|
autoload :UninstallPlugin, action_root.join("uninstall_plugin")
|
||||||
autoload :UpdateGems, action_root.join("update_gems")
|
autoload :UpdateGems, action_root.join("update_gems")
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
require "vagrant/plugin/manager"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module CommandPlugin
|
||||||
|
module Action
|
||||||
|
# This middleware removes user installed plugins by
|
||||||
|
# removing:
|
||||||
|
# * ~/.vagrant.d/plugins.json
|
||||||
|
# * ~/.vagrant.d/gems
|
||||||
|
# Usage should be restricted to when a repair is
|
||||||
|
# unsuccessful and the only reasonable option remaining
|
||||||
|
# is to re-install all plugins
|
||||||
|
class ExpungePlugins
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
if !env[:force]
|
||||||
|
result = env[:ui].ask(
|
||||||
|
I18n.t("vagrant.commands.plugin.expunge_confirm") +
|
||||||
|
" [Y/N]:"
|
||||||
|
)
|
||||||
|
if result.to_s.downcase.strip != 'y'
|
||||||
|
abort_action = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if !abort_action
|
||||||
|
plugins_json = File.join(env[:home_path], "plugins.json")
|
||||||
|
plugins_gems = env[:gems_path]
|
||||||
|
|
||||||
|
if File.exist?(plugins_json)
|
||||||
|
FileUtils.rm(plugins_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
if File.directory?(plugins_gems)
|
||||||
|
FileUtils.rm_rf(plugins_gems)
|
||||||
|
end
|
||||||
|
|
||||||
|
env[:ui].info(I18n.t("vagrant.commands.plugin.expunge_complete"))
|
||||||
|
|
||||||
|
@app.call(env)
|
||||||
|
else
|
||||||
|
env[:ui].info(I18n.t("vagrant.commands.plugin.expunge_aborted"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,7 +18,11 @@ module VagrantPlugins
|
||||||
def call(env)
|
def call(env)
|
||||||
manager = Vagrant::Plugin::Manager.instance
|
manager = Vagrant::Plugin::Manager.instance
|
||||||
plugins = manager.installed_plugins
|
plugins = manager.installed_plugins
|
||||||
specs = manager.installed_specs
|
specs = Hash[
|
||||||
|
manager.installed_specs.map do |spec|
|
||||||
|
[spec.name, spec]
|
||||||
|
end
|
||||||
|
]
|
||||||
|
|
||||||
# Output!
|
# Output!
|
||||||
if specs.empty?
|
if specs.empty?
|
||||||
|
@ -26,9 +30,10 @@ module VagrantPlugins
|
||||||
return @app.call(env)
|
return @app.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
specs.each do |spec|
|
plugins.each do |plugin_name, plugin|
|
||||||
# Grab the plugin.
|
|
||||||
plugin = plugins[spec.name]
|
spec = specs[plugin_name]
|
||||||
|
next if spec.nil?
|
||||||
|
|
||||||
system = ""
|
system = ""
|
||||||
system = ", system" if plugin && plugin["system"]
|
system = ", system" if plugin && plugin["system"]
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
require "vagrant/plugin/manager"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module CommandPlugin
|
||||||
|
module Action
|
||||||
|
# This middleware attempts to repair installed plugins.
|
||||||
|
#
|
||||||
|
# In general, if plugins are failing to properly load the
|
||||||
|
# core issue will likely be one of two issues:
|
||||||
|
# 1. manual modifications within ~/.vagrant.d/
|
||||||
|
# 2. vagrant upgrade
|
||||||
|
# Running an install on configured plugin set will most
|
||||||
|
# likely fix these issues, which is all this action does.
|
||||||
|
class RepairPlugins
|
||||||
|
def initialize(app, env)
|
||||||
|
@app = app
|
||||||
|
@logger = Log4r::Logger.new("vagrant::plugins::plugincommand::repair")
|
||||||
|
end
|
||||||
|
|
||||||
|
def call(env)
|
||||||
|
env[:ui].info(I18n.t("vagrant.commands.plugin.repairing"))
|
||||||
|
plugins = Vagrant::Plugin::Manager.instance.installed_plugins
|
||||||
|
begin
|
||||||
|
Vagrant::Bundler.instance.init!(plugins, :repair)
|
||||||
|
env[:ui].info(I18n.t("vagrant.commands.plugin.repair_complete"))
|
||||||
|
rescue Exception => e
|
||||||
|
@logger.error("Failed to repair user installed plugins: #{e.class} - #{e}")
|
||||||
|
e.backtrace.each do |backtrace_line|
|
||||||
|
@logger.debug(backtrace_line)
|
||||||
|
end
|
||||||
|
env[:ui].error(I18n.t("vagrant.commands.plugin.repair_failed", message: e.message))
|
||||||
|
end
|
||||||
|
# Continue
|
||||||
|
@app.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -19,17 +19,15 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
manager = Vagrant::Plugin::Manager.instance
|
manager = Vagrant::Plugin::Manager.instance
|
||||||
installed_specs = manager.installed_specs
|
installed_plugins = manager.installed_plugins
|
||||||
new_specs = manager.update_plugins(names)
|
new_specs = manager.update_plugins(names)
|
||||||
|
updated_plugins = manager.installed_plugins
|
||||||
|
|
||||||
updated = {}
|
updated = {}
|
||||||
installed_specs.each do |ispec|
|
installed_plugins.each do |name, info|
|
||||||
new_specs.each do |uspec|
|
update = updated_plugins[name]
|
||||||
next if uspec.name != ispec.name
|
if update && update["installed_gem_version"] != info["installed_gem_version"]
|
||||||
next if ispec.version >= uspec.version
|
updated[name] = update["installed_gem_version"]
|
||||||
next if updated[uspec.name] && updated[uspec.name].version >= uspec.version
|
|
||||||
|
|
||||||
updated[uspec.name] = uspec
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,9 +35,9 @@ module VagrantPlugins
|
||||||
env[:ui].success(I18n.t("vagrant.commands.plugin.up_to_date"))
|
env[:ui].success(I18n.t("vagrant.commands.plugin.up_to_date"))
|
||||||
end
|
end
|
||||||
|
|
||||||
updated.values.each do |spec|
|
updated.each do |name, version|
|
||||||
env[:ui].success(I18n.t("vagrant.commands.plugin.updated",
|
env[:ui].success(I18n.t("vagrant.commands.plugin.updated",
|
||||||
name: spec.name, version: spec.version.to_s))
|
name: name, version: version.to_s))
|
||||||
end
|
end
|
||||||
|
|
||||||
# Continue
|
# Continue
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
require_relative "base"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module CommandPlugin
|
||||||
|
module Command
|
||||||
|
class Expunge < Base
|
||||||
|
def execute
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
opts = OptionParser.new do |o|
|
||||||
|
o.banner = "Usage: vagrant plugin expunge [-h]"
|
||||||
|
|
||||||
|
o.on("--force", "Do not prompt for confirmation") do |force|
|
||||||
|
options[:force] = force
|
||||||
|
end
|
||||||
|
|
||||||
|
o.on("--reinstall", "Reinstall current plugins after expunge") do |reinstall|
|
||||||
|
options[:reinstall] = reinstall
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse the options
|
||||||
|
argv = parse_options(opts)
|
||||||
|
return if !argv
|
||||||
|
raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp if argv.length > 0
|
||||||
|
|
||||||
|
plugins = Vagrant::Plugin::Manager.instance.installed_plugins
|
||||||
|
|
||||||
|
if !options[:reinstall] && !options[:force] && !plugins.empty?
|
||||||
|
result = @env.ui.ask(
|
||||||
|
I18n.t("vagrant.commands.plugin.expunge_request_reinstall") +
|
||||||
|
" [Y/N]:"
|
||||||
|
)
|
||||||
|
options[:reinstall] = result.to_s.downcase.strip == "y"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove all installed user plugins
|
||||||
|
action(Action.action_expunge, options)
|
||||||
|
|
||||||
|
if options[:reinstall]
|
||||||
|
@env.ui.info(I18n.t("vagrant.commands.plugin.expunge_reinstall"))
|
||||||
|
plugins.each do |plugin_name, plugin_info|
|
||||||
|
next if plugin_info["system"] # system plugins do not require re-install
|
||||||
|
# Rebuild information hash to use symbols
|
||||||
|
plugin_info = Hash[
|
||||||
|
plugin_info.map do |key, value|
|
||||||
|
["plugin_#{key}".to_sym, value]
|
||||||
|
end
|
||||||
|
]
|
||||||
|
action(
|
||||||
|
Action.action_install,
|
||||||
|
plugin_info.merge(
|
||||||
|
plugin_name: plugin_name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Success, exit status 0
|
||||||
|
0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -13,15 +13,6 @@ module VagrantPlugins
|
||||||
options[:entry_point] = entry_point
|
options[:entry_point] = entry_point
|
||||||
end
|
end
|
||||||
|
|
||||||
# @deprecated
|
|
||||||
o.on("--plugin-prerelease",
|
|
||||||
"Allow prerelease versions of this plugin.") do |plugin_prerelease|
|
|
||||||
puts "--plugin-prelease is deprecated and will be removed in the next"
|
|
||||||
puts "version of Vagrant. It has no effect now. Use the '--plugin-version'"
|
|
||||||
puts "flag to get a specific pre-release version."
|
|
||||||
puts
|
|
||||||
end
|
|
||||||
|
|
||||||
o.on("--plugin-clean-sources",
|
o.on("--plugin-clean-sources",
|
||||||
"Remove all plugin sources defined so far (including defaults)") do |clean|
|
"Remove all plugin sources defined so far (including defaults)") do |clean|
|
||||||
options[:plugin_sources] = [] if clean
|
options[:plugin_sources] = [] if clean
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
require 'optparse'
|
||||||
|
|
||||||
|
require_relative "base"
|
||||||
|
|
||||||
|
module VagrantPlugins
|
||||||
|
module CommandPlugin
|
||||||
|
module Command
|
||||||
|
class Repair < Base
|
||||||
|
def execute
|
||||||
|
opts = OptionParser.new do |o|
|
||||||
|
o.banner = "Usage: vagrant plugin repair [-h]"
|
||||||
|
end
|
||||||
|
|
||||||
|
# Parse the options
|
||||||
|
argv = parse_options(opts)
|
||||||
|
return if !argv
|
||||||
|
raise Vagrant::Errors::CLIInvalidUsage, help: opts.help.chomp if argv.length > 0
|
||||||
|
|
||||||
|
# Attempt to repair installed plugins
|
||||||
|
action(Action.action_repair)
|
||||||
|
|
||||||
|
# Success, exit status 0
|
||||||
|
0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -14,6 +14,11 @@ module VagrantPlugins
|
||||||
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
@main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
|
||||||
|
|
||||||
@subcommands = Vagrant::Registry.new
|
@subcommands = Vagrant::Registry.new
|
||||||
|
@subcommands.register(:expunge) do
|
||||||
|
require_relative "expunge"
|
||||||
|
Expunge
|
||||||
|
end
|
||||||
|
|
||||||
@subcommands.register(:install) do
|
@subcommands.register(:install) do
|
||||||
require_relative "install"
|
require_relative "install"
|
||||||
Install
|
Install
|
||||||
|
@ -29,6 +34,11 @@ module VagrantPlugins
|
||||||
List
|
List
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@subcommands.register(:repair) do
|
||||||
|
require_relative "repair"
|
||||||
|
Repair
|
||||||
|
end
|
||||||
|
|
||||||
@subcommands.register(:update) do
|
@subcommands.register(:update) do
|
||||||
require_relative "update"
|
require_relative "update"
|
||||||
Update
|
Update
|
||||||
|
|
|
@ -540,7 +540,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
# Set the terminal
|
# Set the terminal
|
||||||
ch2.send_data "export TERM=vt100\n"
|
ch2.send_data generate_environment_export("TERM", "vt100")
|
||||||
|
|
||||||
# Set SSH_AUTH_SOCK if we are in sudo and forwarding agent.
|
# Set SSH_AUTH_SOCK if we are in sudo and forwarding agent.
|
||||||
# This is to work around often misconfigured boxes where
|
# This is to work around often misconfigured boxes where
|
||||||
|
@ -563,7 +563,7 @@ module VagrantPlugins
|
||||||
@logger.warn("No SSH_AUTH_SOCK found despite forward_agent being set.")
|
@logger.warn("No SSH_AUTH_SOCK found despite forward_agent being set.")
|
||||||
else
|
else
|
||||||
@logger.info("Setting SSH_AUTH_SOCK remotely: #{auth_socket}")
|
@logger.info("Setting SSH_AUTH_SOCK remotely: #{auth_socket}")
|
||||||
ch2.send_data "export SSH_AUTH_SOCK=#{auth_socket}\n"
|
ch2.send_data generate_environment_export("SSH_AUTH_SOCK", auth_socket)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -572,9 +572,9 @@ module VagrantPlugins
|
||||||
# without the cruft added from pty mode.
|
# without the cruft added from pty mode.
|
||||||
if pty
|
if pty
|
||||||
data = "stty raw -echo\n"
|
data = "stty raw -echo\n"
|
||||||
data += "export PS1=\n"
|
data += generate_environment_export("PS1", "")
|
||||||
data += "export PS2=\n"
|
data += generate_environment_export("PS2", "")
|
||||||
data += "export PROMPT_COMMAND=\n"
|
data += generate_environment_export("PROMPT_COMMAND", "")
|
||||||
data += "printf #{PTY_DELIM_START}\n"
|
data += "printf #{PTY_DELIM_START}\n"
|
||||||
data += "#{command}\n"
|
data += "#{command}\n"
|
||||||
data += "exitcode=$?\n"
|
data += "exitcode=$?\n"
|
||||||
|
@ -670,6 +670,11 @@ module VagrantPlugins
|
||||||
source_path = Vagrant.source_root.join("keys", "vagrant")
|
source_path = Vagrant.source_root.join("keys", "vagrant")
|
||||||
return File.read(path).chomp == source_path.read.chomp
|
return File.read(path).chomp == source_path.read.chomp
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generate_environment_export(env_key, env_value)
|
||||||
|
template = @machine.config.ssh.export_command_template
|
||||||
|
template.sub("%ENV_KEY%", env_key).sub("%ENV_VALUE%", env_value) + "\n"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -104,7 +104,7 @@ module VagrantPlugins
|
||||||
@logger.info("Checking whether WinRM is ready...")
|
@logger.info("Checking whether WinRM is ready...")
|
||||||
|
|
||||||
result = Timeout.timeout(@machine.config.winrm.timeout) do
|
result = Timeout.timeout(@machine.config.winrm.timeout) do
|
||||||
shell(true).powershell("hostname")
|
shell(true).cmd("hostname")
|
||||||
end
|
end
|
||||||
|
|
||||||
@logger.info("WinRM is ready!")
|
@logger.info("WinRM is ready!")
|
||||||
|
|
|
@ -56,11 +56,15 @@ module VagrantPlugins
|
||||||
def powershell(command, &block)
|
def powershell(command, &block)
|
||||||
# Ensure an exit code
|
# Ensure an exit code
|
||||||
command += "\r\nif ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
|
command += "\r\nif ($?) { exit 0 } else { if($LASTEXITCODE) { exit $LASTEXITCODE } else { exit 1 } }"
|
||||||
execute_with_rescue(executor.method("run_powershell_script"), command, &block)
|
session.create_executor do |executor|
|
||||||
|
execute_with_rescue(executor.method("run_powershell_script"), command, &block)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def cmd(command, &block)
|
def cmd(command, &block)
|
||||||
execute_with_rescue(executor.method("run_cmd"), command, &block)
|
session.create_executor do |executor|
|
||||||
|
execute_with_rescue(executor.method("run_cmd"), command, &block)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def wql(query, &block)
|
def wql(query, &block)
|
||||||
|
@ -172,10 +176,6 @@ module VagrantPlugins
|
||||||
@session ||= new_session
|
@session ||= new_session
|
||||||
end
|
end
|
||||||
|
|
||||||
def executor
|
|
||||||
@executor ||= session.create_executor
|
|
||||||
end
|
|
||||||
|
|
||||||
def endpoint
|
def endpoint
|
||||||
case @config.transport.to_sym
|
case @config.transport.to_sym
|
||||||
when :ssl
|
when :ssl
|
||||||
|
|
|
@ -8,18 +8,16 @@ module VagrantPlugins
|
||||||
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
||||||
basename = name.split(".", 2)[0]
|
basename = name.split(".", 2)[0]
|
||||||
comm.sudo <<-EOH.gsub(/^ {14}/, "")
|
comm.sudo <<-EOH.gsub(/^ {14}/, "")
|
||||||
set -e
|
# Remove comments and blank lines from /etc/hosts
|
||||||
|
sed -i'' -e 's/#.*$//' -e '/^$/d' /etc/hosts
|
||||||
|
|
||||||
# Set hostname
|
# Set hostname
|
||||||
hostnamectl set-hostname '#{basename}'
|
hostnamectl set-hostname '#{basename}'
|
||||||
|
|
||||||
# Remove comments and blank lines from /etc/hosts
|
|
||||||
sed -i'' -e 's/#.*$//' -e '/^$/d' /etc/hosts
|
|
||||||
|
|
||||||
# Prepend ourselves to /etc/hosts
|
# Prepend ourselves to /etc/hosts
|
||||||
grep -w '#{name}' /etc/hosts || {
|
test $? -eq 0 && (grep -w '#{name}' /etc/hosts || {
|
||||||
sed -i'' '1i 127.0.0.1\\t#{name}\\t#{basename}' /etc/hosts
|
sed -i'' '1i 127.0.0.1\\t#{name}\\t#{basename}' /etc/hosts
|
||||||
}
|
})
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,10 +12,9 @@ module VagrantPlugins
|
||||||
|
|
||||||
def self.configure_networks(machine, networks)
|
def self.configure_networks(machine, networks)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
|
commands = []
|
||||||
|
|
||||||
commands = ["set -e"]
|
|
||||||
interfaces = machine.guest.capability(:network_interfaces)
|
interfaces = machine.guest.capability(:network_interfaces)
|
||||||
|
|
||||||
networks.each.with_index do |network, i|
|
networks.each.with_index do |network, i|
|
||||||
network[:device] = interfaces[network[:interface]]
|
network[:device] = interfaces[network[:interface]]
|
||||||
|
|
||||||
|
@ -42,15 +41,15 @@ module VagrantPlugins
|
||||||
|
|
||||||
commands << <<-EOH.gsub(/^ {14}/, '')
|
commands << <<-EOH.gsub(/^ {14}/, '')
|
||||||
# Configure #{network[:device]}
|
# Configure #{network[:device]}
|
||||||
mv '#{remote_path}' '/etc/netctl/#{network[:device]}'
|
mv '#{remote_path}' '/etc/netctl/#{network[:device]}' &&
|
||||||
ip link set '#{network[:device]}' down
|
ip link set '#{network[:device]}' down &&
|
||||||
netctl restart '#{network[:device]}'
|
netctl restart '#{network[:device]}' &&
|
||||||
netctl enable '#{network[:device]}'
|
netctl enable '#{network[:device]}'
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
||||||
# Run all the network modification commands in one communicator call.
|
# Run all the network modification commands in one communicator call.
|
||||||
comm.sudo(commands.join("\n"))
|
comm.sudo(commands.join(" && \n"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,8 +15,7 @@ module VagrantPlugins
|
||||||
# https://bbs.archlinux.org/viewtopic.php?id=193410
|
# https://bbs.archlinux.org/viewtopic.php?id=193410
|
||||||
#
|
#
|
||||||
comm.sudo <<-EOH.gsub(/^ {12}/, "")
|
comm.sudo <<-EOH.gsub(/^ {12}/, "")
|
||||||
set -e
|
systemctl enable rpcbind &&
|
||||||
systemctl enable rpcbind
|
|
||||||
systemctl start rpcbind
|
systemctl start rpcbind
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
@ -24,8 +23,7 @@ module VagrantPlugins
|
||||||
def self.nfs_client_install(machine)
|
def self.nfs_client_install(machine)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
comm.sudo <<-EOH.gsub(/^ {12}/, "")
|
comm.sudo <<-EOH.gsub(/^ {12}/, "")
|
||||||
set -e
|
pacman --noconfirm -Syy &&
|
||||||
pacman --noconfirm -Syy
|
|
||||||
pacman --noconfirm -S nfs-utils ntp
|
pacman --noconfirm -S nfs-utils ntp
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,9 +5,9 @@ module VagrantPlugins
|
||||||
def self.rsync_install(machine)
|
def self.rsync_install(machine)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
comm.sudo <<-EOH.gsub(/^ {12}/, '')
|
comm.sudo <<-EOH.gsub(/^ {12}/, '')
|
||||||
set -e
|
|
||||||
pacman -Sy --noconfirm
|
pacman -Sy --noconfirm
|
||||||
pacman -S --noconfirm rsync
|
pacman -S --noconfirm rsync
|
||||||
|
exit $?
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,18 +8,16 @@ module VagrantPlugins
|
||||||
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
||||||
basename = name.split(".", 2)[0]
|
basename = name.split(".", 2)[0]
|
||||||
comm.sudo <<-EOH.gsub(/^ {14}/, "")
|
comm.sudo <<-EOH.gsub(/^ {14}/, "")
|
||||||
set -e
|
# Remove comments and blank lines from /etc/hosts
|
||||||
|
sed -i'' -e 's/#.*$//' -e '/^$/d' /etc/hosts
|
||||||
|
|
||||||
# Set hostname
|
# Set hostname
|
||||||
hostnamectl set-hostname '#{basename}'
|
hostnamectl set-hostname '#{basename}'
|
||||||
|
|
||||||
# Remove comments and blank lines from /etc/hosts
|
|
||||||
sed -i'' -e 's/#.*$//' -e '/^$/d' /etc/hosts
|
|
||||||
|
|
||||||
# Prepend ourselves to /etc/hosts
|
# Prepend ourselves to /etc/hosts
|
||||||
grep -w '#{name}' /etc/hosts || {
|
test $? -eq 0 && (grep -w '#{name}' /etc/hosts || {
|
||||||
sed -i'' '1i 127.0.0.1\\t#{name}\\t#{basename}' /etc/hosts
|
sed -i'' '1i 127.0.0.1\\t#{name}\\t#{basename}' /etc/hosts
|
||||||
}
|
})
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,10 +11,8 @@ module VagrantPlugins
|
||||||
def self.mount_nfs_folder(machine, ip, folders)
|
def self.mount_nfs_folder(machine, ip, folders)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
|
|
||||||
|
# Mount each folder separately so we can retry.
|
||||||
folders.each do |name, opts|
|
folders.each do |name, opts|
|
||||||
# Mount each folder separately so we can retry.
|
|
||||||
commands = ["set -e"]
|
|
||||||
|
|
||||||
# Shellescape the paths in case they do not have special characters.
|
# Shellescape the paths in case they do not have special characters.
|
||||||
guest_path = Shellwords.escape(opts[:guestpath])
|
guest_path = Shellwords.escape(opts[:guestpath])
|
||||||
host_path = Shellwords.escape(opts[:hostpath])
|
host_path = Shellwords.escape(opts[:hostpath])
|
||||||
|
@ -29,14 +27,14 @@ module VagrantPlugins
|
||||||
mount_opts = mount_opts.join(",")
|
mount_opts = mount_opts.join(",")
|
||||||
|
|
||||||
# Make the directory on the guest.
|
# Make the directory on the guest.
|
||||||
commands << "mkdir -p #{guest_path}"
|
machine.communicate.sudo("mkdir -p #{guest_path}")
|
||||||
|
|
||||||
# Perform the mount operation.
|
# Perform the mount operation.
|
||||||
commands << "/sbin/mount -t nfs -o '#{mount_opts}' #{ip}:#{host_path} #{guest_path}"
|
command = "/sbin/mount -t nfs -o '#{mount_opts}' #{ip}:#{host_path} #{guest_path}"
|
||||||
|
|
||||||
# Run the command, raising a specific error.
|
# Run the command, raising a specific error.
|
||||||
retryable(on: Vagrant::Errors::NFSMountFailed, tries: 3, sleep: 5) do
|
retryable(on: Vagrant::Errors::NFSMountFailed, tries: 3, sleep: 5) do
|
||||||
machine.communicate.sudo(commands.join("\n"),
|
machine.communicate.sudo(command,
|
||||||
error_class: Vagrant::Errors::NFSMountFailed,
|
error_class: Vagrant::Errors::NFSMountFailed,
|
||||||
shell: "sh",
|
shell: "sh",
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,14 +22,13 @@ module VagrantPlugins
|
||||||
# Use execute (not sudo) because we want to execute this as the SSH
|
# Use execute (not sudo) because we want to execute this as the SSH
|
||||||
# user (which is "vagrant" by default).
|
# user (which is "vagrant" by default).
|
||||||
comm.execute <<-EOH.gsub(/^ {12}/, "")
|
comm.execute <<-EOH.gsub(/^ {12}/, "")
|
||||||
set -e
|
|
||||||
|
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
chmod 0700 ~/.ssh
|
chmod 0700 ~/.ssh &&
|
||||||
cat '#{remote_path}' >> ~/.ssh/authorized_keys
|
cat '#{remote_path}' >> ~/.ssh/authorized_keys &&
|
||||||
chmod 0600 ~/.ssh/authorized_keys
|
chmod 0600 ~/.ssh/authorized_keys
|
||||||
|
result=$?
|
||||||
rm -f '#{remote_path}'
|
rm -f '#{remote_path}'
|
||||||
|
exit $result
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -49,15 +48,16 @@ module VagrantPlugins
|
||||||
# Use execute (not sudo) because we want to execute this as the SSH
|
# Use execute (not sudo) because we want to execute this as the SSH
|
||||||
# user (which is "vagrant" by default).
|
# user (which is "vagrant" by default).
|
||||||
comm.execute <<-EOH.sub(/^ {12}/, "")
|
comm.execute <<-EOH.sub(/^ {12}/, "")
|
||||||
set -e
|
result=0
|
||||||
|
|
||||||
if test -f ~/.ssh/authorized_keys; then
|
if test -f ~/.ssh/authorized_keys; then
|
||||||
grep -v -x -f '#{remote_path}' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
|
grep -v -x -f '#{remote_path}' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp &&
|
||||||
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys
|
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys &&
|
||||||
chmod 0600 ~/.ssh/authorized_keys
|
chmod 0600 ~/.ssh/authorized_keys
|
||||||
|
result=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f '#{remote_path}'
|
rm -f '#{remote_path}'
|
||||||
|
exit $result
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,16 +8,17 @@ module VagrantPlugins
|
||||||
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
||||||
basename = name.split(".", 2)[0]
|
basename = name.split(".", 2)[0]
|
||||||
|
|
||||||
comm.sudo <<-EOH.gsub(/^ {14}/, '')
|
# LocalHostName should not contain dots - it is used by Bonjour and
|
||||||
set -e
|
# visible through file sharing services.
|
||||||
|
comm.sudo <<-EOH.gsub(/^ */, '')
|
||||||
# Set hostname
|
# Set hostname
|
||||||
scutil --set ComputerName '#{name}'
|
scutil --set ComputerName '#{name}' &&
|
||||||
scutil --set HostName '#{name}'
|
scutil --set HostName '#{name}' &&
|
||||||
|
scutil --set LocalHostName '#{basename}'
|
||||||
# LocalHostName should not contain dots - it is used by Bonjour and
|
result=$?
|
||||||
# visible through file sharing services.
|
if [ $result -ne 0 ]; then
|
||||||
scutil --set LocalHostName '#{basename}'
|
exit $result
|
||||||
|
fi
|
||||||
|
|
||||||
hostname '#{name}'
|
hostname '#{name}'
|
||||||
|
|
||||||
|
@ -27,8 +28,8 @@ module VagrantPlugins
|
||||||
|
|
||||||
# Prepend ourselves to /etc/hosts - sed on bsd is sad
|
# Prepend ourselves to /etc/hosts - sed on bsd is sad
|
||||||
grep -w '#{name}' /etc/hosts || {
|
grep -w '#{name}' /etc/hosts || {
|
||||||
echo -e '127.0.0.1\\t#{name}\\t#{basename}' | cat - /etc/hosts > /tmp/tmp-hosts
|
echo -e '127.0.0.1\\t#{name}\\t#{basename}' | cat - /etc/hosts > /tmp/tmp-hosts &&
|
||||||
mv /tmp/tmp-hosts /etc/hosts
|
mv /tmp/tmp-hosts /etc/hosts
|
||||||
}
|
}
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,9 +8,6 @@ module VagrantPlugins
|
||||||
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
||||||
basename = name.split(".", 2)[0]
|
basename = name.split(".", 2)[0]
|
||||||
comm.sudo <<-EOH.gsub(/^ {14}/, '')
|
comm.sudo <<-EOH.gsub(/^ {14}/, '')
|
||||||
# Ensure exit on command error
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Set the hostname
|
# Set the hostname
|
||||||
echo '#{basename}' > /etc/hostname
|
echo '#{basename}' > /etc/hostname
|
||||||
hostname -F /etc/hostname
|
hostname -F /etc/hostname
|
||||||
|
|
|
@ -11,7 +11,7 @@ module VagrantPlugins
|
||||||
def self.configure_networks(machine, networks)
|
def self.configure_networks(machine, networks)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
|
|
||||||
commands = ["set -e"]
|
commands = []
|
||||||
entries = []
|
entries = []
|
||||||
interfaces = machine.guest.capability(:network_interfaces)
|
interfaces = machine.guest.capability(:network_interfaces)
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ module VagrantPlugins
|
||||||
def self.nfs_client_install(machine)
|
def self.nfs_client_install(machine)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
comm.sudo <<-EOH.gsub(/^ {12}/, '')
|
comm.sudo <<-EOH.gsub(/^ {12}/, '')
|
||||||
set -e
|
|
||||||
apt-get -yqq update
|
apt-get -yqq update
|
||||||
apt-get -yqq install nfs-common portmap
|
apt-get -yqq install nfs-common portmap
|
||||||
|
exit $?
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,6 @@ module VagrantPlugins
|
||||||
def self.rsync_install(machine)
|
def self.rsync_install(machine)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
comm.sudo <<-EOH.gsub(/^ {14}/, '')
|
comm.sudo <<-EOH.gsub(/^ {14}/, '')
|
||||||
set -e
|
|
||||||
apt-get -yqq update
|
apt-get -yqq update
|
||||||
apt-get -yqq install rsync
|
apt-get -yqq install rsync
|
||||||
EOH
|
EOH
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
require "vagrant"
|
require_relative '../linux/guest'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module GuestDebian
|
module GuestDebian
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < VagrantPlugins::GuestLinux::Guest
|
||||||
def detect?(machine)
|
# Name used for guest detection
|
||||||
machine.communicate.test("cat /etc/issue | grep 'Debian'")
|
GUEST_DETECTION_NAME = "debian".freeze
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,6 @@ module VagrantPlugins
|
||||||
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
if !comm.test("hostname -f | grep '^#{name}$'", sudo: false)
|
||||||
basename = name.split(".", 2)[0]
|
basename = name.split(".", 2)[0]
|
||||||
comm.sudo <<-EOH.gsub(/^ {14}/, "")
|
comm.sudo <<-EOH.gsub(/^ {14}/, "")
|
||||||
set -e
|
|
||||||
|
|
||||||
# Set the hostname
|
# Set the hostname
|
||||||
hostname '#{basename}'
|
hostname '#{basename}'
|
||||||
echo "hostname=#{basename}" > /etc/conf.d/hostname
|
echo "hostname=#{basename}" > /etc/conf.d/hostname
|
||||||
|
@ -20,8 +18,8 @@ module VagrantPlugins
|
||||||
|
|
||||||
# Prepend ourselves to /etc/hosts
|
# Prepend ourselves to /etc/hosts
|
||||||
grep -w '#{name}' /etc/hosts || {
|
grep -w '#{name}' /etc/hosts || {
|
||||||
echo -e '127.0.0.1\\t#{name}\\t#{basename}' | cat - /etc/hosts > /tmp/tmp-hosts
|
echo -e '127.0.0.1\\t#{name}\\t#{basename}' | cat - /etc/hosts > /tmp/tmp-hosts &&
|
||||||
mv /tmp/tmp-hosts /etc/hosts
|
mv /tmp/tmp-hosts /etc/hosts
|
||||||
}
|
}
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
|
@ -94,7 +94,7 @@ SCRIPT
|
||||||
|
|
||||||
# Emit an upstart event if we can
|
# Emit an upstart event if we can
|
||||||
machine.communicate.sudo <<-SCRIPT
|
machine.communicate.sudo <<-SCRIPT
|
||||||
if command -v /sbin/init && /sbin/init --version | grep upstart; then
|
if command -v /sbin/init && /sbin/init 2>/dev/null --version | grep upstart; then
|
||||||
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT='#{expanded_guest_path}'
|
||||||
fi
|
fi
|
||||||
SCRIPT
|
SCRIPT
|
||||||
|
|
|
@ -89,7 +89,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
# Emit an upstart event if we can
|
# Emit an upstart event if we can
|
||||||
machine.communicate.sudo <<-EOH.gsub(/^ {12}/, "")
|
machine.communicate.sudo <<-EOH.gsub(/^ {12}/, "")
|
||||||
if command -v /sbin/init && /sbin/init --version | grep upstart; then
|
if command -v /sbin/init && /sbin/init 2>/dev/null --version | grep upstart; then
|
||||||
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}
|
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}
|
||||||
fi
|
fi
|
||||||
EOH
|
EOH
|
||||||
|
|
|
@ -2,6 +2,11 @@ module VagrantPlugins
|
||||||
module GuestLinux
|
module GuestLinux
|
||||||
module Cap
|
module Cap
|
||||||
class NetworkInterfaces
|
class NetworkInterfaces
|
||||||
|
# Valid ethernet device prefix values.
|
||||||
|
# eth - classic prefix
|
||||||
|
# en - predictable interface names prefix
|
||||||
|
POSSIBLE_ETHERNET_PREFIXES = ["eth".freeze, "en".freeze].freeze
|
||||||
|
|
||||||
@@logger = Log4r::Logger.new("vagrant::guest::linux::network_interfaces")
|
@@logger = Log4r::Logger.new("vagrant::guest::linux::network_interfaces")
|
||||||
|
|
||||||
# Get network interfaces as a list. The result will be something like:
|
# Get network interfaces as a list. The result will be something like:
|
||||||
|
@ -18,6 +23,9 @@ module VagrantPlugins
|
||||||
@@logger.debug("Unsorted list: #{ifaces.inspect}")
|
@@logger.debug("Unsorted list: #{ifaces.inspect}")
|
||||||
# Break out integers from strings and sort the arrays to provide
|
# Break out integers from strings and sort the arrays to provide
|
||||||
# a natural sort for the interface names
|
# a natural sort for the interface names
|
||||||
|
# NOTE: Devices named with a hex value suffix will _not_ be sorted
|
||||||
|
# as expected. This is generally seen with veth* devices, and proper ordering
|
||||||
|
# is currently not required
|
||||||
ifaces = ifaces.map do |iface|
|
ifaces = ifaces.map do |iface|
|
||||||
iface.scan(/(.+?)(\d+)/).flatten.map do |iface_part|
|
iface.scan(/(.+?)(\d+)/).flatten.map do |iface_part|
|
||||||
if iface_part.to_i.to_s == iface_part
|
if iface_part.to_i.to_s == iface_part
|
||||||
|
@ -26,8 +34,32 @@ module VagrantPlugins
|
||||||
iface_part
|
iface_part
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end.sort.map(&:join)
|
end
|
||||||
|
ifaces = ifaces.sort do |lhs, rhs|
|
||||||
|
result = 0
|
||||||
|
slice_length = [rhs.size, lhs.size].min
|
||||||
|
slice_length.times do |idx|
|
||||||
|
if(lhs[idx].is_a?(rhs[idx].class))
|
||||||
|
result = lhs[idx] <=> rhs[idx]
|
||||||
|
elsif(lhs[idx].is_a?(String))
|
||||||
|
result = 1
|
||||||
|
else
|
||||||
|
result = -1
|
||||||
|
end
|
||||||
|
break if result != 0
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end.map(&:join)
|
||||||
@@logger.debug("Sorted list: #{ifaces.inspect}")
|
@@logger.debug("Sorted list: #{ifaces.inspect}")
|
||||||
|
# Extract ethernet devices and place at start of list
|
||||||
|
resorted_ifaces = []
|
||||||
|
resorted_ifaces += ifaces.find_all do |iface|
|
||||||
|
POSSIBLE_ETHERNET_PREFIXES.any?{|prefix| iface.start_with?(prefix)} &&
|
||||||
|
iface.match(/^[a-zA-Z0-9]+$/)
|
||||||
|
end
|
||||||
|
resorted_ifaces += ifaces - resorted_ifaces
|
||||||
|
ifaces = resorted_ifaces
|
||||||
|
@@logger.debug("Ethernet preferred sorted list: #{ifaces.inspect}")
|
||||||
ifaces
|
ifaces
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,10 +13,8 @@ module VagrantPlugins
|
||||||
def self.mount_nfs_folder(machine, ip, folders)
|
def self.mount_nfs_folder(machine, ip, folders)
|
||||||
comm = machine.communicate
|
comm = machine.communicate
|
||||||
|
|
||||||
|
# Mount each folder separately so we can retry.
|
||||||
folders.each do |name, opts|
|
folders.each do |name, opts|
|
||||||
# Mount each folder separately so we can retry.
|
|
||||||
commands = ["set -e"]
|
|
||||||
|
|
||||||
# Shellescape the paths in case they do not have special characters.
|
# Shellescape the paths in case they do not have special characters.
|
||||||
guest_path = Shellwords.escape(opts[:guestpath])
|
guest_path = Shellwords.escape(opts[:guestpath])
|
||||||
host_path = Shellwords.escape(opts[:hostpath])
|
host_path = Shellwords.escape(opts[:hostpath])
|
||||||
|
@ -30,22 +28,24 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
mount_opts = mount_opts.join(",")
|
mount_opts = mount_opts.join(",")
|
||||||
|
|
||||||
# Make the directory on the guest.
|
machine.communicate.sudo("mkdir -p #{guest_path}")
|
||||||
commands << "mkdir -p #{guest_path}"
|
|
||||||
|
|
||||||
# Perform the mount operation.
|
# Perform the mount operation and emit mount event if applicable
|
||||||
commands << "mount -o #{mount_opts} #{ip}:#{host_path} #{guest_path}"
|
command = <<-EOH.gsub(/^ */, '')
|
||||||
|
mount -o #{mount_opts} #{ip}:#{host_path} #{guest_path}
|
||||||
# Emit a mount event
|
result=$?
|
||||||
commands << <<-EOH.gsub(/^ {14}/, '')
|
if test $result -eq 0; then
|
||||||
if command -v /sbin/init && /sbin/init --version | grep upstart; then
|
if test -x /sbin/initctl && command -v /sbin/init && /sbin/init 2>/dev/null --version | grep upstart; then
|
||||||
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}
|
/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guest_path}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit $result
|
||||||
fi
|
fi
|
||||||
EOH
|
EOH
|
||||||
|
|
||||||
# Run the command, raising a specific error.
|
# Run the command, raising a specific error.
|
||||||
retryable(on: Vagrant::Errors::NFSMountFailed, tries: 3, sleep: 5) do
|
retryable(on: Vagrant::Errors::NFSMountFailed, tries: 3, sleep: 5) do
|
||||||
machine.communicate.sudo(commands.join("\n"),
|
machine.communicate.sudo(command,
|
||||||
error_class: Vagrant::Errors::NFSMountFailed,
|
error_class: Vagrant::Errors::NFSMountFailed,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,15 +21,13 @@ module VagrantPlugins
|
||||||
|
|
||||||
# Use execute (not sudo) because we want to execute this as the SSH
|
# Use execute (not sudo) because we want to execute this as the SSH
|
||||||
# user (which is "vagrant" by default).
|
# user (which is "vagrant" by default).
|
||||||
comm.execute <<-EOH.gsub(/^ {12}/, "")
|
comm.execute <<-EOH.gsub(/^ */, "")
|
||||||
set -e
|
|
||||||
|
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
chmod 0700 ~/.ssh
|
chmod 0700 ~/.ssh
|
||||||
cat '#{remote_path}' >> ~/.ssh/authorized_keys
|
cat '#{remote_path}' >> ~/.ssh/authorized_keys && chmod 0600 ~/.ssh/authorized_keys
|
||||||
chmod 0600 ~/.ssh/authorized_keys
|
result=$?
|
||||||
|
|
||||||
rm -f '#{remote_path}'
|
rm -f '#{remote_path}'
|
||||||
|
exit $result
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -48,16 +46,14 @@ module VagrantPlugins
|
||||||
|
|
||||||
# Use execute (not sudo) because we want to execute this as the SSH
|
# Use execute (not sudo) because we want to execute this as the SSH
|
||||||
# user (which is "vagrant" by default).
|
# user (which is "vagrant" by default).
|
||||||
comm.execute <<-EOH.sub(/^ {12}/, "")
|
comm.execute <<-EOH.sub(/^ */, "")
|
||||||
set -e
|
|
||||||
|
|
||||||
if test -f ~/.ssh/authorized_keys; then
|
if test -f ~/.ssh/authorized_keys; then
|
||||||
grep -v -x -f '#{remote_path}' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
|
grep -v -x -f '#{remote_path}' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
|
||||||
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys
|
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys && chmod 0600 ~/.ssh/authorized_keys
|
||||||
chmod 0600 ~/.ssh/authorized_keys
|
result=$?
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f '#{remote_path}'
|
rm -f '#{remote_path}'
|
||||||
|
exit $result
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,8 +1,22 @@
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module GuestLinux
|
module GuestLinux
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < Vagrant.plugin("2", :guest)
|
||||||
|
# Name used for guest detection
|
||||||
|
GUEST_DETECTION_NAME = "linux".freeze
|
||||||
|
|
||||||
def detect?(machine)
|
def detect?(machine)
|
||||||
machine.communicate.test("uname -s | grep 'Linux'")
|
machine.communicate.test <<-EOH.gsub(/^ */, '')
|
||||||
|
if test -r /etc/os-release; then
|
||||||
|
source /etc/os-release && test x#{self.class.const_get(:GUEST_DETECTION_NAME)} = x$ID && exit
|
||||||
|
fi
|
||||||
|
if test -x /usr/bin/lsb_release; then
|
||||||
|
/usr/bin/lsb_release -i 2>/dev/null | grep -qi #{self.class.const_get(:GUEST_DETECTION_NAME)} && exit
|
||||||
|
fi
|
||||||
|
if test -r /etc/issue; then
|
||||||
|
cat /etc/issue | grep -qi #{self.class.const_get(:GUEST_DETECTION_NAME)} && exit
|
||||||
|
fi
|
||||||
|
exit 1
|
||||||
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
require_relative '../linux/guest'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module GuestMint
|
module GuestMint
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < VagrantPlugins::GuestLinux::Guest
|
||||||
def detect?(machine)
|
# Name used for guest detection
|
||||||
machine.communicate.test("cat /etc/issue | grep 'Linux Mint'")
|
GUEST_DETECTION_NAME = "Linux Mint".freeze
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,9 +5,8 @@ module VagrantPlugins
|
||||||
def self.change_host_name(machine, name)
|
def self.change_host_name(machine, name)
|
||||||
if !machine.communicate.test("hostname -s | grep '^#{name}$'")
|
if !machine.communicate.test("hostname -s | grep '^#{name}$'")
|
||||||
machine.communicate.sudo(<<CMDS, {shell: "sh"})
|
machine.communicate.sudo(<<CMDS, {shell: "sh"})
|
||||||
set -e
|
sed -e 's/^hostname=.*$/hostname=#{name}/' /etc/rc.conf > /tmp/rc.conf.vagrant_changehostname_#{name} &&
|
||||||
sed -e 's/^hostname=.*$/hostname=#{name}/' /etc/rc.conf > /tmp/rc.conf.vagrant_changehostname_#{name}
|
mv /tmp/rc.conf.vagrant_changehostname_#{name} /etc/rc.conf &&
|
||||||
mv /tmp/rc.conf.vagrant_changehostname_#{name} /etc/rc.conf
|
|
||||||
hostname #{name}
|
hostname #{name}
|
||||||
CMDS
|
CMDS
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,9 +8,11 @@ module VagrantPlugins
|
||||||
|
|
||||||
def self.rsync_install(machine)
|
def self.rsync_install(machine)
|
||||||
machine.communicate.sudo(
|
machine.communicate.sudo(
|
||||||
'PKG_PATH="http://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/' \
|
'PATH=$PATH:/usr/sbin '\
|
||||||
'`uname -m`/`uname -r | cut -d. -f1-2`/All" ' \
|
'PKG_PATH="http://ftp.NetBSD.org/pub/pkgsrc/packages/NetBSD/' \
|
||||||
'pkg_add rsync')
|
'`uname -m`/`uname -r | cut -d. -f1-2`/All" ' \
|
||||||
|
'pkg_add rsync'
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,10 +7,21 @@ module VagrantPlugins
|
||||||
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
|
extend VagrantPlugins::SyncedFolderRSync::DefaultUnixCap
|
||||||
|
|
||||||
def self.rsync_install(machine)
|
def self.rsync_install(machine)
|
||||||
machine.communicate.sudo(
|
install_output = {:stderr => '', :stdout => ''}
|
||||||
'PKG_PATH="http://ftp.openbsd.org/pub/OpenBSD/' \
|
command = 'PKG_PATH="http://ftp.openbsd.org/pub/OpenBSD/' \
|
||||||
'`uname -r`/packages/`arch -s`/" ' \
|
'`uname -r`/packages/`arch -s`/" ' \
|
||||||
'pkg_add -I rsync--')
|
'pkg_add -I rsync--'
|
||||||
|
machine.communicate.sudo(command) do |type, data|
|
||||||
|
install_output[type] << data if install_output.key?(type)
|
||||||
|
end
|
||||||
|
# pkg_add returns 0 even if package was not found, so
|
||||||
|
# validate package is actually installed
|
||||||
|
machine.communicate.sudo('pkg_info -cA | grep inst:rsync-[[:digit:]]',
|
||||||
|
error_class: Vagrant::Errors::RSyncNotInstalledInGuest,
|
||||||
|
command: command,
|
||||||
|
stderr: install_output[:stderr],
|
||||||
|
stdout: install_output[:stdout]
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,7 +18,7 @@ module VagrantPlugins
|
||||||
device = interfaces[network[:interface]]
|
device = interfaces[network[:interface]]
|
||||||
command = "ifconfig #{device}"
|
command = "ifconfig #{device}"
|
||||||
command << " #{network[:ip]}" if network[:ip]
|
command << " #{network[:ip]}" if network[:ip]
|
||||||
command << " netmast #{network[:netmask]}" if network[:netmask]
|
command << " netmask #{network[:netmask]}" if network[:netmask]
|
||||||
commands << command
|
commands << command
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -31,8 +31,12 @@ module VagrantPlugins
|
||||||
sed -i'' '1i 127.0.0.1\\t#{name}\\t#{basename}' /etc/hosts
|
sed -i'' '1i 127.0.0.1\\t#{name}\\t#{basename}' /etc/hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
# Restart network
|
# Restart network (through NetworkManager if running)
|
||||||
service network restart
|
if service NetworkManager status 2>&1 | grep -q running; then
|
||||||
|
service NetworkManager restart
|
||||||
|
else
|
||||||
|
service network restart
|
||||||
|
fi
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -40,16 +40,23 @@ module VagrantPlugins
|
||||||
# Down the interface before munging the config file. This might
|
# Down the interface before munging the config file. This might
|
||||||
# fail if the interface is not actually set up yet so ignore
|
# fail if the interface is not actually set up yet so ignore
|
||||||
# errors.
|
# errors.
|
||||||
/sbin/ifdown '#{network[:device]}' || true
|
/sbin/ifdown '#{network[:device]}'
|
||||||
|
|
||||||
# Move new config into place
|
# Move new config into place
|
||||||
mv '#{remote_path}' '#{final_path}'
|
mv -f '#{remote_path}' '#{final_path}'
|
||||||
|
# attempt to force network manager to reload configurations
|
||||||
# Bring the interface up
|
nmcli c reload || true
|
||||||
ARPCHECK=no /sbin/ifup '#{network[:device]}'
|
|
||||||
EOH
|
EOH
|
||||||
end
|
end
|
||||||
|
|
||||||
|
commands << <<-EOH.gsub(/^ {12}/, '')
|
||||||
|
# Restart network (through NetworkManager if running)
|
||||||
|
if service NetworkManager status 2>&1 | grep -q running; then
|
||||||
|
service NetworkManager restart
|
||||||
|
else
|
||||||
|
service network restart
|
||||||
|
fi
|
||||||
|
EOH
|
||||||
|
|
||||||
comm.sudo(commands.join("\n"))
|
comm.sudo(commands.join("\n"))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,7 +10,7 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
# Detect various flavors we care about
|
# Detect various flavors we care about
|
||||||
if output =~ /(CentOS|Red Hat Enterprise|Scientific|Cloud)\s*Linux( .+)? release 7/i
|
if output =~ /(CentOS|Red Hat Enterprise|Scientific|Cloud|Virtuozzo)\s*Linux( .+)? release 7/i
|
||||||
return :rhel_7
|
return :rhel_7
|
||||||
else
|
else
|
||||||
return :rhel
|
return :rhel
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
require "vagrant"
|
require_relative '../linux/guest'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module GuestTinyCore
|
module GuestTinyCore
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < VagrantPlugins::GuestLinux::Guest
|
||||||
def detect?(machine)
|
# Name used for guest detection
|
||||||
machine.communicate.test("cat /etc/issue | grep 'Core Linux'")
|
GUEST_DETECTION_NAME = "Core Linux".freeze
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,24 +1,10 @@
|
||||||
|
require_relative '../linux/guest'
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module GuestUbuntu
|
module GuestUbuntu
|
||||||
class Guest < Vagrant.plugin("2", :guest)
|
class Guest < VagrantPlugins::GuestLinux::Guest
|
||||||
def detect?(machine)
|
# Name used for guest detection
|
||||||
# This command detects if we are running on Ubuntu. /etc/os-release is
|
GUEST_DETECTION_NAME = "ubuntu".freeze
|
||||||
# available on modern Ubuntu versions, but does not exist on 14.04 and
|
|
||||||
# previous versions, so we fall back to lsb_release.
|
|
||||||
#
|
|
||||||
# GH-7524
|
|
||||||
# GH-7625
|
|
||||||
#
|
|
||||||
machine.communicate.test <<-EOH.gsub(/^ {10}/, "")
|
|
||||||
if test -r /etc/os-release; then
|
|
||||||
source /etc/os-release && test xubuntu = x$ID
|
|
||||||
elif test -x /usr/bin/lsb_release; then
|
|
||||||
/usr/bin/lsb_release -i 2>/dev/null | grep -q Ubuntu
|
|
||||||
else
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
EOH
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,8 @@ module VagrantPlugins
|
||||||
module HostLinux
|
module HostLinux
|
||||||
module Cap
|
module Cap
|
||||||
class NFS
|
class NFS
|
||||||
|
|
||||||
|
NFS_EXPORTS_PATH = "/etc/exports".freeze
|
||||||
extend Vagrant::Util::Retryable
|
extend Vagrant::Util::Retryable
|
||||||
|
|
||||||
def self.nfs_apply_command(env)
|
def self.nfs_apply_command(env)
|
||||||
|
@ -36,16 +38,9 @@ module VagrantPlugins
|
||||||
ui.info I18n.t("vagrant.hosts.linux.nfs_export")
|
ui.info I18n.t("vagrant.hosts.linux.nfs_export")
|
||||||
sleep 0.5
|
sleep 0.5
|
||||||
|
|
||||||
nfs_cleanup(id)
|
nfs_cleanup("#{Process.uid} #{id}")
|
||||||
|
output = "#{nfs_exports_content}\n#{output}"
|
||||||
# Only use "sudo" if we can't write to /etc/exports directly
|
nfs_write_exports(output)
|
||||||
sudo_command = ""
|
|
||||||
sudo_command = "sudo " if !File.writable?("/etc/exports")
|
|
||||||
|
|
||||||
output.split("\n").each do |line|
|
|
||||||
line = Vagrant::Util::ShellQuote.escape(line, "'")
|
|
||||||
system(%Q[echo '#{line}' | #{sudo_command}tee -a /etc/exports >/dev/null])
|
|
||||||
end
|
|
||||||
|
|
||||||
if nfs_running?(nfs_check_command)
|
if nfs_running?(nfs_check_command)
|
||||||
system("sudo #{nfs_apply_command}")
|
system("sudo #{nfs_apply_command}")
|
||||||
|
@ -62,48 +57,111 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.nfs_prune(environment, ui, valid_ids)
|
def self.nfs_prune(environment, ui, valid_ids)
|
||||||
return if !File.exist?("/etc/exports")
|
return if !File.exist?(NFS_EXPORTS_PATH)
|
||||||
|
|
||||||
logger = Log4r::Logger.new("vagrant::hosts::linux")
|
logger = Log4r::Logger.new("vagrant::hosts::linux")
|
||||||
logger.info("Pruning invalid NFS entries...")
|
logger.info("Pruning invalid NFS entries...")
|
||||||
|
|
||||||
output = false
|
|
||||||
user = Process.uid
|
user = Process.uid
|
||||||
|
|
||||||
File.read("/etc/exports").lines.each do |line|
|
# Create editor instance for removing invalid IDs
|
||||||
if id = line[/^# VAGRANT-BEGIN:( #{user})? ([\.\/A-Za-z0-9\-_:]+?)$/, 2]
|
editor = Vagrant::Util::StringBlockEditor.new(nfs_exports_content)
|
||||||
if valid_ids.include?(id)
|
|
||||||
logger.debug("Valid ID: #{id}")
|
|
||||||
else
|
|
||||||
if !output
|
|
||||||
# We want to warn the user but we only want to output once
|
|
||||||
ui.info I18n.t("vagrant.hosts.linux.nfs_prune")
|
|
||||||
output = true
|
|
||||||
end
|
|
||||||
|
|
||||||
logger.info("Invalid ID, pruning: #{id}")
|
# Build composite IDs with UID information and discover invalid entries
|
||||||
nfs_cleanup(id)
|
composite_ids = valid_ids.map do |v_id|
|
||||||
end
|
"#{user} #{v_id}"
|
||||||
end
|
end
|
||||||
|
remove_ids = editor.keys - composite_ids
|
||||||
|
|
||||||
|
logger.debug("Known valid NFS export IDs: #{valid_ids}")
|
||||||
|
logger.debug("Composite valid NFS export IDs with user: #{composite_ids}")
|
||||||
|
logger.debug("NFS export IDs to be removed: #{remove_ids}")
|
||||||
|
if !remove_ids.empty?
|
||||||
|
ui.info I18n.t("vagrant.hosts.linux.nfs_prune")
|
||||||
|
nfs_cleanup(remove_ids)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def self.nfs_cleanup(id)
|
def self.nfs_cleanup(remove_ids)
|
||||||
return if !File.exist?("/etc/exports")
|
return if !File.exist?(NFS_EXPORTS_PATH)
|
||||||
|
|
||||||
user = Regexp.escape(Process.uid.to_s)
|
editor = Vagrant::Util::StringBlockEditor.new(nfs_exports_content)
|
||||||
id = Regexp.escape(id.to_s)
|
remove_ids = Array(remove_ids)
|
||||||
|
|
||||||
# Only use "sudo" if we can't write to /etc/exports directly
|
# Remove all invalid ID entries
|
||||||
sudo_command = ""
|
remove_ids.each do |r_id|
|
||||||
sudo_command = "sudo " if !File.writable?("/etc/exports")
|
editor.delete(r_id)
|
||||||
|
end
|
||||||
|
nfs_write_exports(editor.value)
|
||||||
|
end
|
||||||
|
|
||||||
# Use sed to just strip out the block of code which was inserted
|
def self.nfs_write_exports(new_exports_content)
|
||||||
# by Vagrant
|
if(nfs_exports_content != new_exports_content.strip)
|
||||||
tmp = ENV["TMPDIR"] || ENV["TMP"] || "/tmp"
|
begin
|
||||||
system("cp /etc/exports '#{tmp}' && #{sudo_command}sed -r -e '\\\x01^# VAGRANT-BEGIN:( #{user})? #{id}\x01,\\\x01^# VAGRANT-END:( #{user})? #{id}\x01 d' -ibak '#{tmp}/exports' ; #{sudo_command}cp '#{tmp}/exports' /etc/exports")
|
# Write contents out to temporary file
|
||||||
|
new_exports_file = Tempfile.create('vagrant')
|
||||||
|
new_exports_file.puts(new_exports_content)
|
||||||
|
new_exports_file.close
|
||||||
|
new_exports_path = new_exports_file.path
|
||||||
|
|
||||||
|
# Only use "sudo" if we can't write to /etc/exports directly
|
||||||
|
sudo_command = ""
|
||||||
|
sudo_command = "sudo " if !File.writable?(NFS_EXPORTS_PATH)
|
||||||
|
|
||||||
|
# Ensure new file mode and uid/gid match existing file to replace
|
||||||
|
existing_stat = File.stat(NFS_EXPORTS_PATH)
|
||||||
|
new_stat = File.stat(new_exports_path)
|
||||||
|
if existing_stat.mode != new_stat.mode
|
||||||
|
File.chmod(existing_stat.mode, new_exports_path)
|
||||||
|
end
|
||||||
|
if existing_stat.uid != new_stat.uid || existing_stat.gid != new_stat.gid
|
||||||
|
chown_cmd = "#{sudo_command}chown #{existing_stat.uid}:#{existing_stat.gid} #{new_exports_path}"
|
||||||
|
result = Vagrant::Util::Subprocess.execute(*Shellwords.split(chown_cmd))
|
||||||
|
if result.exit_code != 0
|
||||||
|
raise Vagrant::Errors::NFSExportsFailed,
|
||||||
|
command: chown_cmd,
|
||||||
|
stderr: result.stderr,
|
||||||
|
stdout: result.stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# Always force move the file to prevent overwrite prompting
|
||||||
|
mv_cmd = "#{sudo_command}mv -f #{new_exports_path} #{NFS_EXPORTS_PATH}"
|
||||||
|
result = Vagrant::Util::Subprocess.execute(*Shellwords.split(mv_cmd))
|
||||||
|
if result.exit_code != 0
|
||||||
|
raise Vagrant::Errors::NFSExportsFailed,
|
||||||
|
command: mv_cmd,
|
||||||
|
stderr: result.stderr,
|
||||||
|
stdout: result.stdout
|
||||||
|
end
|
||||||
|
ensure
|
||||||
|
if File.exist?(new_exports_path)
|
||||||
|
File.unlink(new_exports_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.nfs_exports_content
|
||||||
|
if(File.exist?(NFS_EXPORTS_PATH))
|
||||||
|
if(File.readable?(NFS_EXPORTS_PATH))
|
||||||
|
File.read(NFS_EXPORTS_PATH)
|
||||||
|
else
|
||||||
|
cmd = "sudo cat #{NFS_EXPORTS_PATH}"
|
||||||
|
result = Vagrant::Util::Subprocess.execute(*Shellwords.split(cmd))
|
||||||
|
if result.exit_code != 0
|
||||||
|
raise Vagrant::Errors::NFSExportsFailed,
|
||||||
|
command: cmd,
|
||||||
|
stderr: result.stderr,
|
||||||
|
stdout: result.stdout
|
||||||
|
else
|
||||||
|
result.stdout
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
""
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.nfs_opts_setup(folders)
|
def self.nfs_opts_setup(folders)
|
||||||
|
|
|
@ -15,24 +15,25 @@ module VagrantPlugins
|
||||||
attr_accessor :ssh_command
|
attr_accessor :ssh_command
|
||||||
attr_accessor :pty
|
attr_accessor :pty
|
||||||
attr_accessor :sudo_command
|
attr_accessor :sudo_command
|
||||||
|
attr_accessor :export_command_template
|
||||||
|
|
||||||
attr_reader :default
|
attr_reader :default
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
|
||||||
@forward_agent = UNSET_VALUE
|
@forward_agent = UNSET_VALUE
|
||||||
@forward_x11 = UNSET_VALUE
|
@forward_x11 = UNSET_VALUE
|
||||||
@forward_env = UNSET_VALUE
|
@forward_env = UNSET_VALUE
|
||||||
@guest_port = UNSET_VALUE
|
@guest_port = UNSET_VALUE
|
||||||
@keep_alive = UNSET_VALUE
|
@keep_alive = UNSET_VALUE
|
||||||
@proxy_command = UNSET_VALUE
|
@proxy_command = UNSET_VALUE
|
||||||
@ssh_command = UNSET_VALUE
|
@ssh_command = UNSET_VALUE
|
||||||
@pty = UNSET_VALUE
|
@pty = UNSET_VALUE
|
||||||
@shell = UNSET_VALUE
|
@shell = UNSET_VALUE
|
||||||
@sudo_command = UNSET_VALUE
|
@sudo_command = UNSET_VALUE
|
||||||
|
@export_command_template = UNSET_VALUE
|
||||||
@default = SSHConnectConfig.new
|
@default = SSHConnectConfig.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge(other)
|
def merge(other)
|
||||||
|
@ -55,6 +56,10 @@ module VagrantPlugins
|
||||||
@pty = false if @pty == UNSET_VALUE
|
@pty = false if @pty == UNSET_VALUE
|
||||||
@shell = "bash -l" if @shell == UNSET_VALUE
|
@shell = "bash -l" if @shell == UNSET_VALUE
|
||||||
|
|
||||||
|
if @export_command_template == UNSET_VALUE
|
||||||
|
@export_command_template = 'export %ENV_KEY%="%ENV_VALUE%"'
|
||||||
|
end
|
||||||
|
|
||||||
if @sudo_command == UNSET_VALUE
|
if @sudo_command == UNSET_VALUE
|
||||||
@sudo_command = "sudo -E -H %c"
|
@sudo_command = "sudo -E -H %c"
|
||||||
end
|
end
|
||||||
|
|
|
@ -207,7 +207,19 @@ module VagrantPlugins
|
||||||
hostpath = hostpath.to_s.gsub("\\", "/")
|
hostpath = hostpath.to_s.gsub("\\", "/")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if guestpath.is_a?(Hash)
|
||||||
|
options = guestpath
|
||||||
|
guestpath = nil
|
||||||
|
end
|
||||||
|
|
||||||
options ||= {}
|
options ||= {}
|
||||||
|
|
||||||
|
if options.has_key?(:name)
|
||||||
|
synced_folder_name = options.delete(:name)
|
||||||
|
else
|
||||||
|
synced_folder_name = guestpath
|
||||||
|
end
|
||||||
|
|
||||||
options[:guestpath] = guestpath.to_s.gsub(/\/$/, '')
|
options[:guestpath] = guestpath.to_s.gsub(/\/$/, '')
|
||||||
options[:hostpath] = hostpath
|
options[:hostpath] = hostpath
|
||||||
options[:disabled] = false if !options.key?(:disabled)
|
options[:disabled] = false if !options.key?(:disabled)
|
||||||
|
@ -217,7 +229,7 @@ module VagrantPlugins
|
||||||
# Make sure the type is a symbol
|
# Make sure the type is a symbol
|
||||||
options[:type] = options[:type].to_sym if options[:type]
|
options[:type] = options[:type].to_sym if options[:type]
|
||||||
|
|
||||||
@__synced_folders[options[:guestpath]] = options
|
@__synced_folders[synced_folder_name] = options
|
||||||
end
|
end
|
||||||
|
|
||||||
# Define a way to access the machine via a network. This exposes a
|
# Define a way to access the machine via a network. This exposes a
|
||||||
|
@ -581,7 +593,7 @@ module VagrantPlugins
|
||||||
@hostname && @hostname !~ /^[a-z0-9][-.a-z0-9]*$/i
|
@hostname && @hostname !~ /^[a-z0-9][-.a-z0-9]*$/i
|
||||||
|
|
||||||
if @box_version
|
if @box_version
|
||||||
@box_version.split(",").each do |v|
|
@box_version.to_s.split(",").each do |v|
|
||||||
begin
|
begin
|
||||||
Gem::Requirement.new(v.strip)
|
Gem::Requirement.new(v.strip)
|
||||||
rescue Gem::Requirement::BadRequirementError
|
rescue Gem::Requirement::BadRequirementError
|
||||||
|
@ -626,7 +638,7 @@ module VagrantPlugins
|
||||||
# If the shared folder is disabled then don't worry about validating it
|
# If the shared folder is disabled then don't worry about validating it
|
||||||
next if options[:disabled]
|
next if options[:disabled]
|
||||||
|
|
||||||
guestpath = Pathname.new(options[:guestpath])
|
guestpath = Pathname.new(options[:guestpath]) if options[:guestpath]
|
||||||
hostpath = Pathname.new(options[:hostpath]).expand_path(machine.env.root_path)
|
hostpath = Pathname.new(options[:hostpath]).expand_path(machine.env.root_path)
|
||||||
|
|
||||||
if guestpath.to_s != ""
|
if guestpath.to_s != ""
|
||||||
|
|
|
@ -48,7 +48,7 @@ module VagrantPlugins
|
||||||
run_cmd += volumes.map { |v| ['-v', v.to_s] }
|
run_cmd += volumes.map { |v| ['-v', v.to_s] }
|
||||||
run_cmd += %W(--privileged) if params[:privileged]
|
run_cmd += %W(--privileged) if params[:privileged]
|
||||||
run_cmd += %W(-h #{params[:hostname]}) if params[:hostname]
|
run_cmd += %W(-h #{params[:hostname]}) if params[:hostname]
|
||||||
run_cmd << "-i" << "-t" if params[:pty]
|
run_cmd << "-t" if params[:pty]
|
||||||
run_cmd << "--rm=true" if params[:rm]
|
run_cmd << "--rm=true" if params[:rm]
|
||||||
run_cmd += params[:extra_args] if params[:extra_args]
|
run_cmd += params[:extra_args] if params[:extra_args]
|
||||||
run_cmd += [image, cmd]
|
run_cmd += [image, cmd]
|
||||||
|
|
|
@ -7,7 +7,7 @@ module VagrantPlugins
|
||||||
module Action
|
module Action
|
||||||
class Import
|
class Import
|
||||||
def initialize(app, env)
|
def initialize(app, env)
|
||||||
@app = app
|
@app = app
|
||||||
@logger = Log4r::Logger.new("vagrant::hyperv::import")
|
@logger = Log4r::Logger.new("vagrant::hyperv::import")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -35,13 +35,28 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
config_path = nil
|
config_path = nil
|
||||||
|
config_type = nil
|
||||||
vm_dir.each_child do |f|
|
vm_dir.each_child do |f|
|
||||||
if f.extname.downcase == ".xml"
|
if f.extname.downcase == '.xml'
|
||||||
config_path = f
|
config_path = f
|
||||||
|
config_type = 'xml'
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Only check for .vmcx if there is no XML found to not
|
||||||
|
# risk breaking older vagrant boxes that added an XML
|
||||||
|
# file manually
|
||||||
|
if config_type == nil
|
||||||
|
vm_dir.each_child do |f|
|
||||||
|
if f.extname.downcase == '.vmcx'
|
||||||
|
config_path = f
|
||||||
|
config_type = 'vmcx'
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
image_path = nil
|
image_path = nil
|
||||||
image_ext = nil
|
image_ext = nil
|
||||||
image_filename = nil
|
image_filename = nil
|
||||||
|
@ -49,7 +64,7 @@ module VagrantPlugins
|
||||||
if %w{.vhd .vhdx}.include?(f.extname.downcase)
|
if %w{.vhd .vhdx}.include?(f.extname.downcase)
|
||||||
image_path = f
|
image_path = f
|
||||||
image_ext = f.extname.downcase
|
image_ext = f.extname.downcase
|
||||||
image_filename = File.basename(f,image_ext)
|
image_filename = File.basename(f, image_ext)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -100,19 +115,27 @@ module VagrantPlugins
|
||||||
|
|
||||||
env[:ui].detail("Cloning virtual hard drive...")
|
env[:ui].detail("Cloning virtual hard drive...")
|
||||||
source_path = image_path.to_s
|
source_path = image_path.to_s
|
||||||
dest_path = env[:machine].data_dir.join("#{image_filename}#{image_ext}").to_s
|
dest_path = env[:machine].data_dir.join("Virtual Hard Disks").join("#{image_filename}#{image_ext}").to_s
|
||||||
if differencing_disk
|
|
||||||
env[:machine].provider.driver.execute("clone_vhd.ps1", {Source: source_path, Destination: dest_path})
|
# Still hard copy the disk of old XML configurations
|
||||||
else
|
if config_type == 'xml'
|
||||||
FileUtils.cp(source_path, dest_path)
|
if differencing_disk
|
||||||
|
env[:machine].provider.driver.execute("clone_vhd.ps1", {Source: source_path, Destination: dest_path})
|
||||||
|
else
|
||||||
|
FileUtils.mkdir_p(env[:machine].data_dir.join("Virtual Hard Disks"))
|
||||||
|
FileUtils.cp(source_path, dest_path)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
image_path = dest_path
|
image_path = dest_path
|
||||||
|
|
||||||
# We have to normalize the paths to be Windows paths since
|
# We have to normalize the paths to be Windows paths since
|
||||||
# we're executing PowerShell.
|
# we're executing PowerShell.
|
||||||
options = {
|
options = {
|
||||||
vm_xml_config: config_path.to_s.gsub("/", "\\"),
|
vm_config_file: config_path.to_s.gsub("/", "\\"),
|
||||||
image_path: image_path.to_s.gsub("/", "\\")
|
vm_config_type: config_type,
|
||||||
|
source_path: source_path.to_s,
|
||||||
|
dest_path: dest_path,
|
||||||
|
data_path: env[:machine].data_dir.to_s.gsub("/", "\\")
|
||||||
}
|
}
|
||||||
options[:switchname] = switch if switch
|
options[:switchname] = switch if switch
|
||||||
options[:memory] = memory if memory
|
options[:memory] = memory if memory
|
||||||
|
@ -121,6 +144,7 @@ module VagrantPlugins
|
||||||
options[:vmname] = vmname if vmname
|
options[:vmname] = vmname if vmname
|
||||||
options[:auto_start_action] = auto_start_action if auto_start_action
|
options[:auto_start_action] = auto_start_action if auto_start_action
|
||||||
options[:auto_stop_action] = auto_stop_action if auto_stop_action
|
options[:auto_stop_action] = auto_stop_action if auto_stop_action
|
||||||
|
options[:differencing_disk] = differencing_disk if differencing_disk
|
||||||
|
|
||||||
env[:ui].detail("Creating and registering the VM...")
|
env[:ui].detail("Creating and registering the VM...")
|
||||||
server = env[:machine].provider.driver.import(options)
|
server = env[:machine].provider.driver.import(options)
|
||||||
|
|
|
@ -74,7 +74,15 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def import(options)
|
def import(options)
|
||||||
execute('import_vm.ps1', options)
|
config_type = options.delete(:vm_config_type)
|
||||||
|
if config_type === "vmcx"
|
||||||
|
execute('import_vm_vmcx.ps1', options)
|
||||||
|
else
|
||||||
|
options.delete(:data_path)
|
||||||
|
options.delete(:source_path)
|
||||||
|
options.delete(:differencing_disk)
|
||||||
|
execute('import_vm_xml.ps1', options)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def net_set_vlan(vlan_id)
|
def net_set_vlan(vlan_id)
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
Param(
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$vm_config_file,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$source_path,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$dest_path,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string]$data_path,
|
||||||
|
|
||||||
|
[string]$switchname=$null,
|
||||||
|
[string]$memory=$null,
|
||||||
|
[string]$maxmemory=$null,
|
||||||
|
[string]$cpus=$null,
|
||||||
|
[string]$vmname=$null,
|
||||||
|
[string]$auto_start_action=$null,
|
||||||
|
[string]$auto_stop_action=$null,
|
||||||
|
[string]$differencing_disk=$null
|
||||||
|
)
|
||||||
|
|
||||||
|
# Include the following modules
|
||||||
|
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
||||||
|
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
||||||
|
|
||||||
|
$VmProperties = @{
|
||||||
|
Path = $vm_config_file
|
||||||
|
SnapshotFilePath = Join-Path $data_path 'Snapshots'
|
||||||
|
VhdDestinationPath = Join-Path $data_path 'Virtual Hard Disks'
|
||||||
|
VirtualMachinePath = $data_path
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmConfig = (Compare-VM -Copy -GenerateNewID @VmProperties)
|
||||||
|
|
||||||
|
$generation = $vmConfig.VM.Generation
|
||||||
|
|
||||||
|
if (!$vmname) {
|
||||||
|
# Get the name of the vm
|
||||||
|
$vm_name = $vmconfig.VM.VMName
|
||||||
|
} else {
|
||||||
|
$vm_name = $vmname
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$cpus) {
|
||||||
|
# Get the processorcount of the VM
|
||||||
|
$processors = (Get-VMProcessor -VM $vmConfig.VM).Count
|
||||||
|
}else {
|
||||||
|
$processors = $cpus
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetUniqueName($name) {
|
||||||
|
Get-VM | ForEach-Object -Process {
|
||||||
|
if ($name -eq $_.Name) {
|
||||||
|
$name = $name + "_1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $name
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
$name = $vm_name
|
||||||
|
$vm_name = GetUniqueName $name
|
||||||
|
} while ($vm_name -ne $name)
|
||||||
|
|
||||||
|
if (!$memory) {
|
||||||
|
$configMemory = Get-VMMemory -VM $vmConfig.VM
|
||||||
|
$dynamicmemory = $configMemory.DynamicMemoryEnabled
|
||||||
|
|
||||||
|
$MemoryMaximumBytes = ($configMemory.Maximum)
|
||||||
|
$MemoryStartupBytes = ($configMemory.Startup)
|
||||||
|
$MemoryMinimumBytes = ($configMemory.Minimum)
|
||||||
|
} else {
|
||||||
|
if (!$maxmemory){
|
||||||
|
$dynamicmemory = $False
|
||||||
|
$MemoryMaximumBytes = ($memory -as [int]) * 1MB
|
||||||
|
$MemoryStartupBytes = ($memory -as [int]) * 1MB
|
||||||
|
$MemoryMinimumBytes = ($memory -as [int]) * 1MB
|
||||||
|
} else {
|
||||||
|
$dynamicmemory = $True
|
||||||
|
$MemoryMaximumBytes = ($maxmemory -as [int]) * 1MB
|
||||||
|
$MemoryStartupBytes = ($memory -as [int]) * 1MB
|
||||||
|
$MemoryMinimumBytes = ($memory -as [int]) * 1MB
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$switchname) {
|
||||||
|
$switchname = (Get-VMNetworkAdapter -VM $vmConfig.VM).SwitchName
|
||||||
|
}
|
||||||
|
|
||||||
|
$vmNetworkAdapter = Get-VMNetworkAdapter -VM $vmConfig.VM
|
||||||
|
Connect-VMNetworkAdapter -VMNetworkAdapter $vmNetworkAdapter -SwitchName $switchname
|
||||||
|
Set-VM -VM $vmConfig.VM -NewVMName $vm_name
|
||||||
|
Set-VM -VM $vmConfig.VM -ErrorAction "Stop"
|
||||||
|
Set-VM -VM $vmConfig.VM -ProcessorCount $processors
|
||||||
|
|
||||||
|
if ($dynamicmemory) {
|
||||||
|
Set-VM -VM $vmConfig.VM -DynamicMemory
|
||||||
|
Set-VM -VM $vmConfig.VM -MemoryMinimumBytes $MemoryMinimumBytes -MemoryMaximumBytes $MemoryMaximumBytes -MemoryStartupBytes $MemoryStartupBytes
|
||||||
|
} else {
|
||||||
|
Set-VM -VM $vmConfig.VM -StaticMemory
|
||||||
|
Set-VM -VM $vmConfig.VM -MemoryStartupBytes $MemoryStartupBytes
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($notes) {
|
||||||
|
Set-VM -VM $vmConfig.VM -Notes $notes
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($auto_start_action) {
|
||||||
|
Set-VM -VM $vmConfig.VM -AutomaticStartAction $auto_start_action
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($auto_stop_action) {
|
||||||
|
Set-VM -VM $vmConfig.VM -AutomaticStartAction $auto_stop_action
|
||||||
|
}
|
||||||
|
|
||||||
|
# Only set EFI secure boot for Gen 2 machines, not gen 1
|
||||||
|
if ($generation -ne 1) {
|
||||||
|
Set-VMFirmware -VM $vmConfig.VM -EnableSecureBoot (Get-VMFirmware -VM $vmConfig.VM).SecureBoot
|
||||||
|
}
|
||||||
|
|
||||||
|
$report = Compare-VM -CompatibilityReport $vmConfig
|
||||||
|
|
||||||
|
# Stop if there are incompatibilities
|
||||||
|
if($report.Incompatibilities.Length -gt 0){
|
||||||
|
Write-Error-Message $(ConvertTo-Json $($report.Incompatibilities | Select -ExpandProperty Message))
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if($differencing_disk){
|
||||||
|
# Get all controller on the VM, first scsi, then IDE if it is a Gen 1 device
|
||||||
|
$controllers = Get-VMScsiController -VM $vmConfig.VM
|
||||||
|
if($generation -eq 1){
|
||||||
|
$controllers = @($controllers) + @(Get-VMIdeController -VM $vmConfig.VM)
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($controller in $controllers){
|
||||||
|
foreach($drive in $controller.Drives){
|
||||||
|
if([System.IO.Path]::GetFileName($drive.Path) -eq [System.IO.Path]::GetFileName($source_path)){
|
||||||
|
# Remove the old disk and replace it with a differencing version
|
||||||
|
$path = $drive.Path
|
||||||
|
Remove-VMHardDiskDrive $drive
|
||||||
|
New-VHD -Path $dest_path -ParentPath $source_path -ErrorAction Stop
|
||||||
|
Add-VMHardDiskDrive -VM $vmConfig.VM -Path $dest_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Import-VM -CompatibilityReport $vmConfig
|
||||||
|
|
||||||
|
$vm_id = (Get-VM $vm_name).id.guid
|
||||||
|
$resultHash = @{
|
||||||
|
name = $vm_name
|
||||||
|
id = $vm_id
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = ConvertTo-Json $resultHash
|
||||||
|
Write-Output-Message $result
|
|
@ -1,8 +1,8 @@
|
||||||
Param(
|
Param(
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$vm_xml_config,
|
[string]$vm_config_file,
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
[string]$image_path,
|
[string]$dest_path,
|
||||||
|
|
||||||
[string]$switchname=$null,
|
[string]$switchname=$null,
|
||||||
[string]$memory=$null,
|
[string]$memory=$null,
|
||||||
|
@ -17,7 +17,7 @@ Param(
|
||||||
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
$Dir = Split-Path $script:MyInvocation.MyCommand.Path
|
||||||
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
. ([System.IO.Path]::Combine($Dir, "utils\write_messages.ps1"))
|
||||||
|
|
||||||
[xml]$vmconfig = Get-Content -Path $vm_xml_config
|
[xml]$vmconfig = Get-Content -Path $vm_config_file
|
||||||
|
|
||||||
$generation = [int]($vmconfig.configuration.properties.subtype.'#text')+1
|
$generation = [int]($vmconfig.configuration.properties.subtype.'#text')+1
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ foreach ($controller in $controllers) {
|
||||||
|
|
||||||
$addDriveParam = @{
|
$addDriveParam = @{
|
||||||
ControllerNumber = $rx.Match($controller.node.name).value
|
ControllerNumber = $rx.Match($controller.node.name).value
|
||||||
Path = $image_path
|
Path = $dest_path
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($drive.pool_id."#text") {
|
if ($drive.pool_id."#text") {
|
|
@ -4,16 +4,19 @@ module VagrantPlugins
|
||||||
class Base < Vagrant.plugin("2", :config)
|
class Base < Vagrant.plugin("2", :config)
|
||||||
|
|
||||||
GALAXY_COMMAND_DEFAULT = "ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force".freeze
|
GALAXY_COMMAND_DEFAULT = "ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force".freeze
|
||||||
|
PLAYBOOK_COMMAND_DEFAULT = "ansible-playbook".freeze
|
||||||
|
|
||||||
|
attr_accessor :config_file
|
||||||
attr_accessor :extra_vars
|
attr_accessor :extra_vars
|
||||||
attr_accessor :galaxy_role_file
|
attr_accessor :galaxy_role_file
|
||||||
attr_accessor :galaxy_roles_path
|
attr_accessor :galaxy_roles_path
|
||||||
attr_accessor :galaxy_command
|
attr_accessor :galaxy_command
|
||||||
attr_accessor :host_vars
|
|
||||||
attr_accessor :groups
|
attr_accessor :groups
|
||||||
|
attr_accessor :host_vars
|
||||||
attr_accessor :inventory_path
|
attr_accessor :inventory_path
|
||||||
attr_accessor :limit
|
attr_accessor :limit
|
||||||
attr_accessor :playbook
|
attr_accessor :playbook
|
||||||
|
attr_accessor :playbook_command
|
||||||
attr_accessor :raw_arguments
|
attr_accessor :raw_arguments
|
||||||
attr_accessor :skip_tags
|
attr_accessor :skip_tags
|
||||||
attr_accessor :start_at_task
|
attr_accessor :start_at_task
|
||||||
|
@ -24,15 +27,17 @@ module VagrantPlugins
|
||||||
attr_accessor :verbose
|
attr_accessor :verbose
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
@config_file = UNSET_VALUE
|
||||||
@extra_vars = UNSET_VALUE
|
@extra_vars = UNSET_VALUE
|
||||||
@galaxy_role_file = UNSET_VALUE
|
@galaxy_role_file = UNSET_VALUE
|
||||||
@galaxy_roles_path = UNSET_VALUE
|
@galaxy_roles_path = UNSET_VALUE
|
||||||
@galaxy_command = UNSET_VALUE
|
@galaxy_command = UNSET_VALUE
|
||||||
@host_vars = UNSET_VALUE
|
|
||||||
@groups = UNSET_VALUE
|
@groups = UNSET_VALUE
|
||||||
|
@host_vars = UNSET_VALUE
|
||||||
@inventory_path = UNSET_VALUE
|
@inventory_path = UNSET_VALUE
|
||||||
@limit = UNSET_VALUE
|
@limit = UNSET_VALUE
|
||||||
@playbook = UNSET_VALUE
|
@playbook = UNSET_VALUE
|
||||||
|
@playbook_command = UNSET_VALUE
|
||||||
@raw_arguments = UNSET_VALUE
|
@raw_arguments = UNSET_VALUE
|
||||||
@skip_tags = UNSET_VALUE
|
@skip_tags = UNSET_VALUE
|
||||||
@start_at_task = UNSET_VALUE
|
@start_at_task = UNSET_VALUE
|
||||||
|
@ -44,23 +49,25 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
@extra_vars = nil if @extra_vars == UNSET_VALUE
|
@config_file = nil if @config_file == UNSET_VALUE
|
||||||
@galaxy_role_file = nil if @galaxy_role_file == UNSET_VALUE
|
@extra_vars = nil if @extra_vars == UNSET_VALUE
|
||||||
@galaxy_roles_path = nil if @galaxy_roles_path == UNSET_VALUE
|
@galaxy_role_file = nil if @galaxy_role_file == UNSET_VALUE
|
||||||
@galaxy_command = GALAXY_COMMAND_DEFAULT if @galaxy_command == UNSET_VALUE
|
@galaxy_roles_path = nil if @galaxy_roles_path == UNSET_VALUE
|
||||||
@host_vars = {} if @host_vars == UNSET_VALUE
|
@galaxy_command = GALAXY_COMMAND_DEFAULT if @galaxy_command == UNSET_VALUE
|
||||||
@groups = {} if @groups == UNSET_VALUE
|
@groups = {} if @groups == UNSET_VALUE
|
||||||
@inventory_path = nil if @inventory_path == UNSET_VALUE
|
@host_vars = {} if @host_vars == UNSET_VALUE
|
||||||
@limit = nil if @limit == UNSET_VALUE
|
@inventory_path = nil if @inventory_path == UNSET_VALUE
|
||||||
@playbook = nil if @playbook == UNSET_VALUE
|
@limit = nil if @limit == UNSET_VALUE
|
||||||
@raw_arguments = nil if @raw_arguments == UNSET_VALUE
|
@playbook = nil if @playbook == UNSET_VALUE
|
||||||
@skip_tags = nil if @skip_tags == UNSET_VALUE
|
@playbook_command = PLAYBOOK_COMMAND_DEFAULT if @playbook_command == UNSET_VALUE
|
||||||
@start_at_task = nil if @start_at_task == UNSET_VALUE
|
@raw_arguments = nil if @raw_arguments == UNSET_VALUE
|
||||||
@sudo = false if @sudo != true
|
@skip_tags = nil if @skip_tags == UNSET_VALUE
|
||||||
@sudo_user = nil if @sudo_user == UNSET_VALUE
|
@start_at_task = nil if @start_at_task == UNSET_VALUE
|
||||||
@tags = nil if @tags == UNSET_VALUE
|
@sudo = false if @sudo != true
|
||||||
@vault_password_file = nil if @vault_password_file == UNSET_VALUE
|
@sudo_user = nil if @sudo_user == UNSET_VALUE
|
||||||
@verbose = false if @verbose == UNSET_VALUE
|
@tags = nil if @tags == UNSET_VALUE
|
||||||
|
@vault_password_file = nil if @vault_password_file == UNSET_VALUE
|
||||||
|
@verbose = false if @verbose == UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
# Just like the normal configuration "validate" method except that
|
# Just like the normal configuration "validate" method except that
|
||||||
|
|
|
@ -26,25 +26,44 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_files_existence
|
def check_files_existence
|
||||||
check_path_is_a_file config.playbook, :playbook
|
check_path_is_a_file(config.playbook, :playbook)
|
||||||
|
|
||||||
check_path_exists config.inventory_path, :inventory_path if config.inventory_path
|
check_path_exists(config.inventory_path, :inventory_path) if config.inventory_path
|
||||||
check_path_is_a_file config.extra_vars[1..-1], :extra_vars if has_an_extra_vars_file_argument
|
check_path_is_a_file(config.config_file, :config_file) if config.config_file
|
||||||
check_path_is_a_file config.galaxy_role_file, :galaxy_role_file if config.galaxy_role_file
|
check_path_is_a_file(config.extra_vars[1..-1], :extra_vars) if has_an_extra_vars_file_argument
|
||||||
check_path_is_a_file config.vault_password_file, :vault_password if config.vault_password_file
|
check_path_is_a_file(config.galaxy_role_file, :galaxy_role_file) if config.galaxy_role_file
|
||||||
|
check_path_is_a_file(config.vault_password_file, :vault_password_file) if config.vault_password_file
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_environment_variables_for_shell_execution
|
||||||
|
shell_env_vars = []
|
||||||
|
@environment_variables.each_pair do |k, v|
|
||||||
|
if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH|ANSIBLE_CONFIG/
|
||||||
|
shell_env_vars << "#{k}='#{v}'"
|
||||||
|
else
|
||||||
|
shell_env_vars << "#{k}=#{v}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
shell_env_vars
|
||||||
|
end
|
||||||
|
|
||||||
|
def ansible_galaxy_command_for_shell_execution
|
||||||
|
command_values = {
|
||||||
|
role_file: "'#{get_galaxy_role_file}'",
|
||||||
|
roles_path: "'#{get_galaxy_roles_path}'"
|
||||||
|
}
|
||||||
|
|
||||||
|
shell_command = get_environment_variables_for_shell_execution
|
||||||
|
|
||||||
|
shell_command << config.galaxy_command % command_values
|
||||||
|
|
||||||
|
shell_command.flatten.join(' ')
|
||||||
end
|
end
|
||||||
|
|
||||||
def ansible_playbook_command_for_shell_execution
|
def ansible_playbook_command_for_shell_execution
|
||||||
shell_command = []
|
shell_command = get_environment_variables_for_shell_execution
|
||||||
@environment_variables.each_pair do |k, v|
|
|
||||||
if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH/
|
|
||||||
shell_command << "#{k}='#{v}'"
|
|
||||||
else
|
|
||||||
shell_command << "#{k}=#{v}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
shell_command << "ansible-playbook"
|
shell_command << config.playbook_command
|
||||||
|
|
||||||
shell_args = []
|
shell_args = []
|
||||||
@command_arguments.each do |arg|
|
@command_arguments.each do |arg|
|
||||||
|
@ -102,6 +121,12 @@ module VagrantPlugins
|
||||||
# Use ANSIBLE_ROLES_PATH to tell ansible-playbook where to look for roles
|
# Use ANSIBLE_ROLES_PATH to tell ansible-playbook where to look for roles
|
||||||
# (there is no equivalent command line argument in ansible-playbook)
|
# (there is no equivalent command line argument in ansible-playbook)
|
||||||
@environment_variables["ANSIBLE_ROLES_PATH"] = get_galaxy_roles_path if config.galaxy_roles_path
|
@environment_variables["ANSIBLE_ROLES_PATH"] = get_galaxy_roles_path if config.galaxy_roles_path
|
||||||
|
|
||||||
|
prepare_ansible_config_environment_variable
|
||||||
|
end
|
||||||
|
|
||||||
|
def prepare_ansible_config_environment_variable
|
||||||
|
@environment_variables["ANSIBLE_CONFIG"] = config.config_file if config.config_file
|
||||||
end
|
end
|
||||||
|
|
||||||
# Auto-generate "safe" inventory file based on Vagrantfile,
|
# Auto-generate "safe" inventory file based on Vagrantfile,
|
||||||
|
|
|
@ -52,9 +52,9 @@ module VagrantPlugins
|
||||||
@machine.guest.capability(:ansible_install, config.install_mode, config.version)
|
@machine.guest.capability(:ansible_install, config.install_mode, config.version)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check that ansible binaries are well installed on the guest,
|
# Check that Ansible Playbook command is available on the guest
|
||||||
@machine.communicate.execute(
|
@machine.communicate.execute(
|
||||||
"ansible-galaxy info --help && ansible-playbook --help",
|
"test -x \"$(command -v #{config.playbook_command})\"",
|
||||||
error_class: Ansible::Errors::AnsibleNotFoundOnGuest,
|
error_class: Ansible::Errors::AnsibleNotFoundOnGuest,
|
||||||
error_key: :ansible_not_found_on_guest
|
error_key: :ansible_not_found_on_guest
|
||||||
)
|
)
|
||||||
|
@ -72,14 +72,9 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_ansible_galaxy_on_guest
|
def execute_ansible_galaxy_on_guest
|
||||||
command_values = {
|
prepare_ansible_config_environment_variable
|
||||||
role_file: "'#{get_galaxy_role_file}'",
|
|
||||||
roles_path: "'#{get_galaxy_roles_path}'"
|
|
||||||
}
|
|
||||||
|
|
||||||
remote_command = config.galaxy_command % command_values
|
execute_ansible_command_on_guest "galaxy", ansible_galaxy_command_for_shell_execution
|
||||||
|
|
||||||
execute_ansible_command_on_guest "galaxy", remote_command
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_ansible_playbook_on_guest
|
def execute_ansible_playbook_on_guest
|
||||||
|
@ -156,7 +151,7 @@ module VagrantPlugins
|
||||||
# and error if it doesn't exist.
|
# and error if it doesn't exist.
|
||||||
|
|
||||||
remote_path = Helpers::expand_path_in_unix_style(path, config.provisioning_path)
|
remote_path = Helpers::expand_path_in_unix_style(path, config.provisioning_path)
|
||||||
command = "test #{test_args} #{remote_path}"
|
command = "test #{test_args} '#{remote_path}'"
|
||||||
|
|
||||||
@machine.communicate.execute(
|
@machine.communicate.execute(
|
||||||
command,
|
command,
|
||||||
|
|
|
@ -20,6 +20,7 @@ module VagrantPlugins
|
||||||
|
|
||||||
check_files_existence
|
check_files_existence
|
||||||
warn_for_unsupported_platform
|
warn_for_unsupported_platform
|
||||||
|
|
||||||
execute_ansible_galaxy_from_host if config.galaxy_role_file
|
execute_ansible_galaxy_from_host if config.galaxy_role_file
|
||||||
execute_ansible_playbook_from_host
|
execute_ansible_playbook_from_host
|
||||||
end
|
end
|
||||||
|
@ -88,6 +89,8 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_ansible_galaxy_from_host
|
def execute_ansible_galaxy_from_host
|
||||||
|
prepare_ansible_config_environment_variable
|
||||||
|
|
||||||
command_values = {
|
command_values = {
|
||||||
role_file: get_galaxy_role_file,
|
role_file: get_galaxy_role_file,
|
||||||
roles_path: get_galaxy_roles_path
|
roles_path: get_galaxy_roles_path
|
||||||
|
@ -97,23 +100,23 @@ module VagrantPlugins
|
||||||
|
|
||||||
command = str_command.split(VAGRANT_ARG_SEPARATOR)
|
command = str_command.split(VAGRANT_ARG_SEPARATOR)
|
||||||
command << {
|
command << {
|
||||||
|
env: @environment_variables,
|
||||||
# Write stdout and stderr data, since it's the regular Ansible output
|
# Write stdout and stderr data, since it's the regular Ansible output
|
||||||
notify: [:stdout, :stderr],
|
notify: [:stdout, :stderr],
|
||||||
workdir: @machine.env.root_path.to_s
|
workdir: @machine.env.root_path.to_s
|
||||||
}
|
}
|
||||||
|
|
||||||
# FIXME: role_file and roles_path arguments should be quoted in the console output
|
ui_running_ansible_command "galaxy", ansible_galaxy_command_for_shell_execution
|
||||||
ui_running_ansible_command "galaxy", str_command.gsub(VAGRANT_ARG_SEPARATOR, ' ')
|
|
||||||
|
|
||||||
execute_command_from_host command
|
execute_command_from_host command
|
||||||
end
|
end
|
||||||
|
|
||||||
def execute_ansible_playbook_from_host
|
def execute_ansible_playbook_from_host
|
||||||
prepare_command_arguments
|
|
||||||
prepare_environment_variables
|
prepare_environment_variables
|
||||||
|
prepare_command_arguments
|
||||||
|
|
||||||
# Assemble the full ansible-playbook command
|
# Assemble the full ansible-playbook command
|
||||||
command = %w(ansible-playbook) << @command_arguments
|
command = [config.playbook_command] << @command_arguments
|
||||||
|
|
||||||
# Add the raw arguments at the end, to give them the highest precedence
|
# Add the raw arguments at the end, to give them the highest precedence
|
||||||
command << config.raw_arguments if config.raw_arguments
|
command << config.raw_arguments if config.raw_arguments
|
||||||
|
@ -234,6 +237,7 @@ module VagrantPlugins
|
||||||
proxy_cmd += " exec nc %h %p 2>/dev/null"
|
proxy_cmd += " exec nc %h %p 2>/dev/null"
|
||||||
|
|
||||||
ssh_options << "-o ProxyCommand='#{ proxy_cmd }'"
|
ssh_options << "-o ProxyCommand='#{ proxy_cmd }'"
|
||||||
|
# TODO ssh_options << "-o ProxyCommand=\"#{ proxy_cmd }\""
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use an SSH ProxyCommand when corresponding Vagrant setting is defined
|
# Use an SSH ProxyCommand when corresponding Vagrant setting is defined
|
||||||
|
|
|
@ -64,16 +64,6 @@ module VagrantPlugins
|
||||||
# @return [String]
|
# @return [String]
|
||||||
attr_accessor :installer_download_path
|
attr_accessor :installer_download_path
|
||||||
|
|
||||||
# @deprecated
|
|
||||||
def prerelease=(value)
|
|
||||||
STDOUT.puts <<-EOH
|
|
||||||
[DEPRECATED] The configuration `chef.prerelease' has been deprecated. Please use
|
|
||||||
`chef.channel' instead. The default value for channel is "stable", which
|
|
||||||
includes the latest published versions of the Chef Client. You can choose to use
|
|
||||||
prerelease versions by setting the channel to "current".
|
|
||||||
EOH
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,6 @@ module VagrantPlugins
|
||||||
class Config < Vagrant.plugin("2", :config)
|
class Config < Vagrant.plugin("2", :config)
|
||||||
attr_reader :images
|
attr_reader :images
|
||||||
|
|
||||||
def version=(value)
|
|
||||||
STDOUT.puts <<-EOH
|
|
||||||
[DEPRECATED] The configuration `docker.version' has been deprecated. Docker no
|
|
||||||
longer allows you to specify the version of Docker you want installed and will
|
|
||||||
automatically choose the best version for your guest. Please remove this option
|
|
||||||
from your Vagrantfile.
|
|
||||||
EOH
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@images = Set.new
|
@images = Set.new
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ module VagrantPlugins
|
||||||
attr_accessor :manifests_path
|
attr_accessor :manifests_path
|
||||||
attr_accessor :environment
|
attr_accessor :environment
|
||||||
attr_accessor :environment_path
|
attr_accessor :environment_path
|
||||||
|
attr_accessor :environment_variables
|
||||||
attr_accessor :module_path
|
attr_accessor :module_path
|
||||||
attr_accessor :options
|
attr_accessor :options
|
||||||
attr_accessor :synced_folder_type
|
attr_accessor :synced_folder_type
|
||||||
|
@ -23,18 +24,19 @@ module VagrantPlugins
|
||||||
def initialize
|
def initialize
|
||||||
super
|
super
|
||||||
|
|
||||||
@binary_path = UNSET_VALUE
|
@binary_path = UNSET_VALUE
|
||||||
@hiera_config_path = UNSET_VALUE
|
@hiera_config_path = UNSET_VALUE
|
||||||
@manifest_file = UNSET_VALUE
|
@manifest_file = UNSET_VALUE
|
||||||
@manifests_path = UNSET_VALUE
|
@manifests_path = UNSET_VALUE
|
||||||
@environment = UNSET_VALUE
|
@environment = UNSET_VALUE
|
||||||
@environment_path = UNSET_VALUE
|
@environment_path = UNSET_VALUE
|
||||||
@module_path = UNSET_VALUE
|
@environment_variables = UNSET_VALUE
|
||||||
@options = []
|
@module_path = UNSET_VALUE
|
||||||
@facter = {}
|
@options = []
|
||||||
@synced_folder_type = UNSET_VALUE
|
@facter = {}
|
||||||
@temp_dir = UNSET_VALUE
|
@synced_folder_type = UNSET_VALUE
|
||||||
@working_directory = UNSET_VALUE
|
@temp_dir = UNSET_VALUE
|
||||||
|
@working_directory = UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def nfs=(value)
|
def nfs=(value)
|
||||||
|
@ -87,6 +89,10 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @environment_variables == UNSET_VALUE
|
||||||
|
@environment_variables = {}
|
||||||
|
end
|
||||||
|
|
||||||
@binary_path = nil if @binary_path == UNSET_VALUE
|
@binary_path = nil if @binary_path == UNSET_VALUE
|
||||||
@module_path = nil if @module_path == UNSET_VALUE
|
@module_path = nil if @module_path == UNSET_VALUE
|
||||||
@synced_folder_type = nil if @synced_folder_type == UNSET_VALUE
|
@synced_folder_type = nil if @synced_folder_type == UNSET_VALUE
|
||||||
|
|
|
@ -207,7 +207,7 @@ module VagrantPlugins
|
||||||
options = options.join(" ")
|
options = options.join(" ")
|
||||||
|
|
||||||
# Build up the custom facts if we have any
|
# Build up the custom facts if we have any
|
||||||
facter = ""
|
facter = nil
|
||||||
if !config.facter.empty?
|
if !config.facter.empty?
|
||||||
facts = []
|
facts = []
|
||||||
config.facter.each do |key, value|
|
config.facter.each do |key, value|
|
||||||
|
@ -219,7 +219,7 @@ module VagrantPlugins
|
||||||
facts.map! { |v| "$env:#{v};" }
|
facts.map! { |v| "$env:#{v};" }
|
||||||
end
|
end
|
||||||
|
|
||||||
facter = "#{facts.join(" ")} "
|
facter = facts.join(" ")
|
||||||
end
|
end
|
||||||
|
|
||||||
puppet_bin = "puppet"
|
puppet_bin = "puppet"
|
||||||
|
@ -227,7 +227,28 @@ module VagrantPlugins
|
||||||
puppet_bin = File.join(@config.binary_path, puppet_bin)
|
puppet_bin = File.join(@config.binary_path, puppet_bin)
|
||||||
end
|
end
|
||||||
|
|
||||||
command = "#{facter} #{puppet_bin} apply #{options}"
|
env_vars = nil
|
||||||
|
if !config.environment_variables.nil? && !config.environment_variables.empty?
|
||||||
|
env_vars = config.environment_variables.map do |env_key, env_value|
|
||||||
|
"#{env_key}=\"#{env_value}\""
|
||||||
|
end
|
||||||
|
|
||||||
|
if windows?
|
||||||
|
env_vars.map! do |env_var_string|
|
||||||
|
"$env:#{env_var_string}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
env_vars = env_vars.join(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
command = [
|
||||||
|
env_vars,
|
||||||
|
facter,
|
||||||
|
puppet_bin,
|
||||||
|
"apply",
|
||||||
|
options
|
||||||
|
].compact.map(&:to_s).join(" ")
|
||||||
if config.working_directory
|
if config.working_directory
|
||||||
if windows?
|
if windows?
|
||||||
command = "cd #{config.working_directory}; if ($?) \{ #{command} \}"
|
command = "cd #{config.working_directory}; if ($?) \{ #{command} \}"
|
||||||
|
|
|
@ -4,11 +4,6 @@ require "vagrant/util/deep_merge"
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Salt
|
module Salt
|
||||||
class Config < Vagrant.plugin("2", :config)
|
class Config < Vagrant.plugin("2", :config)
|
||||||
## @deprecated
|
|
||||||
def config_dir=(value)
|
|
||||||
puts "salt config_dir is deprecated and will be removed in Vagrant 1.9"
|
|
||||||
end
|
|
||||||
|
|
||||||
## salty-vagrant options
|
## salty-vagrant options
|
||||||
attr_accessor :minion_config
|
attr_accessor :minion_config
|
||||||
attr_accessor :minion_key
|
attr_accessor :minion_key
|
||||||
|
@ -74,12 +69,6 @@ module VagrantPlugins
|
||||||
end
|
end
|
||||||
|
|
||||||
def finalize!
|
def finalize!
|
||||||
@minion_config = nil if @minion_config == UNSET_VALUE
|
|
||||||
@minion_key = nil if @minion_key == UNSET_VALUE
|
|
||||||
@minion_pub = nil if @minion_pub == UNSET_VALUE
|
|
||||||
@master_config = nil if @master_config == UNSET_VALUE
|
|
||||||
@master_key = nil if @master_key == UNSET_VALUE
|
|
||||||
@master_pub = nil if @master_pub == UNSET_VALUE
|
|
||||||
@grains_config = nil if @grains_config == UNSET_VALUE
|
@grains_config = nil if @grains_config == UNSET_VALUE
|
||||||
@run_highstate = nil if @run_highstate == UNSET_VALUE
|
@run_highstate = nil if @run_highstate == UNSET_VALUE
|
||||||
@run_overstate = nil if @run_overstate == UNSET_VALUE
|
@run_overstate = nil if @run_overstate == UNSET_VALUE
|
||||||
|
@ -102,6 +91,15 @@ module VagrantPlugins
|
||||||
@version = nil if @version == UNSET_VALUE
|
@version = nil if @version == UNSET_VALUE
|
||||||
@run_service = nil if @run_service == UNSET_VALUE
|
@run_service = nil if @run_service == UNSET_VALUE
|
||||||
@master_id = nil if @master_id == UNSET_VALUE
|
@master_id = nil if @master_id == UNSET_VALUE
|
||||||
|
|
||||||
|
# NOTE: Optimistic defaults are set in the provisioner. UNSET_VALUEs
|
||||||
|
# are converted there to allow proper detection of unset values.
|
||||||
|
# @minion_config = nil if @minion_config == UNSET_VALUE
|
||||||
|
# @minion_key = nil if @minion_key == UNSET_VALUE
|
||||||
|
# @minion_pub = nil if @minion_pub == UNSET_VALUE
|
||||||
|
# @master_config = nil if @master_config == UNSET_VALUE
|
||||||
|
# @master_key = nil if @master_key == UNSET_VALUE
|
||||||
|
# @master_pub = nil if @master_pub == UNSET_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def pillar(data)
|
def pillar(data)
|
||||||
|
@ -111,14 +109,14 @@ module VagrantPlugins
|
||||||
|
|
||||||
def validate(machine)
|
def validate(machine)
|
||||||
errors = _detected_errors
|
errors = _detected_errors
|
||||||
if @minion_config
|
if @minion_config && @minion_config != UNSET_VALUE
|
||||||
expanded = Pathname.new(@minion_config).expand_path(machine.env.root_path)
|
expanded = Pathname.new(@minion_config).expand_path(machine.env.root_path)
|
||||||
if !expanded.file?
|
if !expanded.file?
|
||||||
errors << I18n.t("vagrant.provisioners.salt.minion_config_nonexist", missing_config_file: expanded)
|
errors << I18n.t("vagrant.provisioners.salt.minion_config_nonexist", missing_config_file: expanded)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if @master_config
|
if @master_config && @master_config != UNSET_VALUE
|
||||||
expanded = Pathname.new(@master_config).expand_path(machine.env.root_path)
|
expanded = Pathname.new(@master_config).expand_path(machine.env.root_path)
|
||||||
if !expanded.file?
|
if !expanded.file?
|
||||||
errors << I18n.t("vagrant.provisioners.salt.master_config_nonexist", missing_config_file: expanded)
|
errors << I18n.t("vagrant.provisioners.salt.master_config_nonexist", missing_config_file: expanded)
|
||||||
|
|
|
@ -3,7 +3,20 @@ require 'json'
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Salt
|
module Salt
|
||||||
class Provisioner < Vagrant.plugin("2", :provisioner)
|
class Provisioner < Vagrant.plugin("2", :provisioner)
|
||||||
|
|
||||||
|
# Default path values to set within configuration only
|
||||||
|
# if configuration value is unset and local path exists
|
||||||
|
OPTIMISTIC_PATH_DEFAULTS = Hash[*[
|
||||||
|
"minion_config", "salt/minion",
|
||||||
|
"minion_key", "salt/key/minion.key",
|
||||||
|
"minion_pub", "salt/key/minion.pub",
|
||||||
|
"master_config", "salt/master",
|
||||||
|
"master_key", "salt/key/master.key",
|
||||||
|
"master_pub", "salt/key/master.pub"
|
||||||
|
].map(&:freeze)].freeze
|
||||||
|
|
||||||
def provision
|
def provision
|
||||||
|
set_default_configs
|
||||||
upload_configs
|
upload_configs
|
||||||
upload_keys
|
upload_keys
|
||||||
run_bootstrap_script
|
run_bootstrap_script
|
||||||
|
@ -238,19 +251,19 @@ module VagrantPlugins
|
||||||
bootstrap_path = get_bootstrap
|
bootstrap_path = get_bootstrap
|
||||||
if @machine.config.vm.communicator == :winrm
|
if @machine.config.vm.communicator == :winrm
|
||||||
if @config.version
|
if @config.version
|
||||||
options += " -version %s" % @config.version
|
options += " -version %s" % @config.version
|
||||||
end
|
end
|
||||||
if @config.run_service
|
if @config.run_service
|
||||||
@machine.env.ui.info "Salt minion will be stopped after installing."
|
@machine.env.ui.info "Salt minion will be stopped after installing."
|
||||||
options += " -runservice %s" % @config.run_service
|
options += " -runservice %s" % @config.run_service
|
||||||
end
|
end
|
||||||
if @config.minion_id
|
if @config.minion_id
|
||||||
@machine.env.ui.info "Setting minion to @config.minion_id."
|
@machine.env.ui.info "Setting minion to @config.minion_id."
|
||||||
options += " -minion %s" % @config.minion_id
|
options += " -minion %s" % @config.minion_id
|
||||||
end
|
end
|
||||||
if @config.master_id
|
if @config.master_id
|
||||||
@machine.env.ui.info "Setting master to @config.master_id."
|
@machine.env.ui.info "Setting master to @config.master_id."
|
||||||
options += " -master %s" % @config.master_id
|
options += " -master %s" % @config.master_id
|
||||||
end
|
end
|
||||||
bootstrap_destination = File.join(config_dir, "bootstrap_salt.ps1")
|
bootstrap_destination = File.join(config_dir, "bootstrap_salt.ps1")
|
||||||
else
|
else
|
||||||
|
@ -390,6 +403,16 @@ module VagrantPlugins
|
||||||
@machine.communicate.sudo(cmd, &log_output)
|
@machine.communicate.sudo(cmd, &log_output)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Sets optimistic default values into config
|
||||||
|
def set_default_configs
|
||||||
|
OPTIMISTIC_PATH_DEFAULTS.each do |config_key, config_default|
|
||||||
|
if config.send(config_key) == Config::UNSET_VALUE
|
||||||
|
config_value = File.exist?(expanded_path(config_default)) ? config_default : nil
|
||||||
|
config.send("#{config_key}=", config_value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,8 @@ module VagrantPlugins
|
||||||
class Config < Vagrant.plugin("2", :config)
|
class Config < Vagrant.plugin("2", :config)
|
||||||
attr_accessor :inline
|
attr_accessor :inline
|
||||||
attr_accessor :path
|
attr_accessor :path
|
||||||
|
attr_accessor :md5
|
||||||
|
attr_accessor :sha1
|
||||||
attr_accessor :env
|
attr_accessor :env
|
||||||
attr_accessor :upload_path
|
attr_accessor :upload_path
|
||||||
attr_accessor :args
|
attr_accessor :args
|
||||||
|
@ -19,6 +21,8 @@ module VagrantPlugins
|
||||||
@args = UNSET_VALUE
|
@args = UNSET_VALUE
|
||||||
@inline = UNSET_VALUE
|
@inline = UNSET_VALUE
|
||||||
@path = UNSET_VALUE
|
@path = UNSET_VALUE
|
||||||
|
@md5 = UNSET_VALUE
|
||||||
|
@sha1 = UNSET_VALUE
|
||||||
@env = UNSET_VALUE
|
@env = UNSET_VALUE
|
||||||
@upload_path = UNSET_VALUE
|
@upload_path = UNSET_VALUE
|
||||||
@privileged = UNSET_VALUE
|
@privileged = UNSET_VALUE
|
||||||
|
@ -33,6 +37,8 @@ module VagrantPlugins
|
||||||
@args = nil if @args == UNSET_VALUE
|
@args = nil if @args == UNSET_VALUE
|
||||||
@inline = nil if @inline == UNSET_VALUE
|
@inline = nil if @inline == UNSET_VALUE
|
||||||
@path = nil if @path == UNSET_VALUE
|
@path = nil if @path == UNSET_VALUE
|
||||||
|
@md5 = nil if @md5 == UNSET_VALUE
|
||||||
|
@sha1 = nil if @sha1 == UNSET_VALUE
|
||||||
@env = {} if @env == UNSET_VALUE
|
@env = {} if @env == UNSET_VALUE
|
||||||
@upload_path = "/tmp/vagrant-shell" if @upload_path == UNSET_VALUE
|
@upload_path = "/tmp/vagrant-shell" if @upload_path == UNSET_VALUE
|
||||||
@privileged = true if @privileged == UNSET_VALUE
|
@privileged = true if @privileged == UNSET_VALUE
|
||||||
|
|
|
@ -177,7 +177,12 @@ module VagrantPlugins
|
||||||
download_path.delete if download_path.file?
|
download_path.delete if download_path.file?
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Vagrant::Util::Downloader.new(config.path, download_path).download!
|
Vagrant::Util::Downloader.new(
|
||||||
|
config.path,
|
||||||
|
download_path,
|
||||||
|
md5: config.md5,
|
||||||
|
sha1: config.sha1
|
||||||
|
).download!
|
||||||
ext = File.extname(config.path)
|
ext = File.extname(config.path)
|
||||||
script = download_path.read
|
script = download_path.read
|
||||||
ensure
|
ensure
|
||||||
|
|
|
@ -32,7 +32,7 @@ module VagrantPlugins
|
||||||
exclude_base = Pathname.new(opts[:guestpath])
|
exclude_base = Pathname.new(opts[:guestpath])
|
||||||
exclusions = Array(opts[:exclude]).map do |ex_path|
|
exclusions = Array(opts[:exclude]).map do |ex_path|
|
||||||
ex_path = ex_path.slice(1, ex_path.size) if ex_path.start_with?(File::SEPARATOR)
|
ex_path = ex_path.slice(1, ex_path.size) if ex_path.start_with?(File::SEPARATOR)
|
||||||
"-path #{exclude_base.join(ex_path)} -prune"
|
"-path #{Shellwords.escape(exclude_base.join(ex_path))} -prune"
|
||||||
end.join(" -o ") + " -o "
|
end.join(" -o ") + " -o "
|
||||||
end
|
end
|
||||||
"find #{guest_path} #{exclusions}" \
|
"find #{guest_path} #{exclusions}" \
|
||||||
|
|
|
@ -734,6 +734,14 @@ en:
|
||||||
downloader_interrupted: |-
|
downloader_interrupted: |-
|
||||||
The download was interrupted by an external signal. It did not
|
The download was interrupted by an external signal. It did not
|
||||||
complete.
|
complete.
|
||||||
|
downloader_checksum_error: |-
|
||||||
|
The calculated checksum of the requested file does not match the expected
|
||||||
|
checksum!
|
||||||
|
|
||||||
|
File source: %{source}
|
||||||
|
Checsum type: %{type}
|
||||||
|
Expected checksum: %{expected_checksum}
|
||||||
|
Calculated checksum: %{actual_checksum}
|
||||||
env_inval: |-
|
env_inval: |-
|
||||||
Vagrant received an "EINVAL" error while attempting to set some
|
Vagrant received an "EINVAL" error while attempting to set some
|
||||||
environment variables. This is usually caused by the total size of your
|
environment variables. This is usually caused by the total size of your
|
||||||
|
@ -877,6 +885,14 @@ en:
|
||||||
the issues below and execute "vagrant reload":
|
the issues below and execute "vagrant reload":
|
||||||
|
|
||||||
%{output}
|
%{output}
|
||||||
|
nfs_exports_failed: |-
|
||||||
|
Vagrant failed to install an updated NFS exports file. This may be
|
||||||
|
due to overly restrictive permissions on your NFS exports file. Please
|
||||||
|
validate them and try again.
|
||||||
|
|
||||||
|
command: %{command}
|
||||||
|
stdout: %{stdout}
|
||||||
|
stderr: %{stderr}
|
||||||
nfs_cant_read_exports: |-
|
nfs_cant_read_exports: |-
|
||||||
Vagrant can't read your current NFS exports! The exports file should be
|
Vagrant can't read your current NFS exports! The exports file should be
|
||||||
readable by any user. This is usually caused by invalid permissions
|
readable by any user. This is usually caused by invalid permissions
|
||||||
|
@ -966,6 +982,20 @@ en:
|
||||||
by contacting a plugin author to see if they can address the conflict.
|
by contacting a plugin author to see if they can address the conflict.
|
||||||
|
|
||||||
%{conflicts}
|
%{conflicts}
|
||||||
|
plugin_init_error: |-
|
||||||
|
The plugins failed to initialize correctly. This may be due to manual
|
||||||
|
modifications made within the Vagrant home directory. Vagrant can
|
||||||
|
attempt to automatically correct this issue by running:
|
||||||
|
|
||||||
|
vagrant plugin repair
|
||||||
|
|
||||||
|
If Vagrant was recently updated, this error may be due to incompatible
|
||||||
|
versions of dependencies. To fix this problem please remove and re-install
|
||||||
|
all plugins. Vagrant can attempt to do this automatically by running:
|
||||||
|
|
||||||
|
vagrant plugin expunge --reinstall
|
||||||
|
|
||||||
|
Error message given during initialization: %{message}
|
||||||
plugin_load_error: |-
|
plugin_load_error: |-
|
||||||
The plugins failed to load properly. The error message given is
|
The plugins failed to load properly. The error message given is
|
||||||
shown below.
|
shown below.
|
||||||
|
@ -1065,6 +1095,15 @@ en:
|
||||||
Guest path: %{guestpath}
|
Guest path: %{guestpath}
|
||||||
Command: %{command}
|
Command: %{command}
|
||||||
Error: %{stderr}
|
Error: %{stderr}
|
||||||
|
rsync_guest_install_error: |-
|
||||||
|
Installation of rsync into the guest has failed! The stdout
|
||||||
|
and stderr are shown below. Please read the error output, resolve
|
||||||
|
it and try again. If the problem persists, please install rsync
|
||||||
|
manually within the guest.
|
||||||
|
|
||||||
|
Command: %{command}
|
||||||
|
Stdout: %{stdout}
|
||||||
|
Stderr: %{stderr}
|
||||||
rsync_not_found: |-
|
rsync_not_found: |-
|
||||||
"rsync" could not be found on your PATH. Make sure that rsync
|
"rsync" could not be found on your PATH. Make sure that rsync
|
||||||
is properly installed on your system and available on the PATH.
|
is properly installed on your system and available on the PATH.
|
||||||
|
@ -1559,6 +1598,24 @@ en:
|
||||||
the comments in the Vagrantfile as well as documentation on
|
the comments in the Vagrantfile as well as documentation on
|
||||||
`vagrantup.com` for more information on using Vagrant.
|
`vagrantup.com` for more information on using Vagrant.
|
||||||
plugin:
|
plugin:
|
||||||
|
expunge_confirm: |-
|
||||||
|
|
||||||
|
This command permanently deletes all currently installed user plugins. It
|
||||||
|
should only be used when a repair command is unable to properly fix the
|
||||||
|
system.
|
||||||
|
|
||||||
|
Continue?
|
||||||
|
expunge_request_reinstall: |-
|
||||||
|
Would you like Vagrant to attempt to reinstall current plugins?
|
||||||
|
expunge_complete: |-
|
||||||
|
|
||||||
|
All user installed plugins have been removed from this Vagrant environment!
|
||||||
|
expunge_reinstall: |-
|
||||||
|
|
||||||
|
Vagrant will now attempt to reinstall user plugins that were removed.
|
||||||
|
expunge_aborted: |-
|
||||||
|
|
||||||
|
Vagrant expunge has been declined. Skipping removal of plugins.
|
||||||
installed_license: |-
|
installed_license: |-
|
||||||
The license for '%{name}' was successfully installed!
|
The license for '%{name}' was successfully installed!
|
||||||
installing_license: |-
|
installing_license: |-
|
||||||
|
@ -1584,6 +1641,20 @@ en:
|
||||||
post_install: |-
|
post_install: |-
|
||||||
Post install message from the '%{name}' plugin:
|
Post install message from the '%{name}' plugin:
|
||||||
|
|
||||||
|
%{message}
|
||||||
|
repairing: |-
|
||||||
|
Repairing currently installed plugins. This may take a few minutes...
|
||||||
|
repair_complete: |-
|
||||||
|
Installed plugins successfully repaired!
|
||||||
|
repair_failed: |-
|
||||||
|
Failed to automatically repair installed Vagrant plugins. To fix this
|
||||||
|
problem remove all user installed plugins and reinstall. Vagrant can
|
||||||
|
do this for you automatically by running the following command:
|
||||||
|
|
||||||
|
vagrant plugin expunge --reinstall
|
||||||
|
|
||||||
|
Failure message received during repair:
|
||||||
|
|
||||||
%{message}
|
%{message}
|
||||||
snapshot:
|
snapshot:
|
||||||
not_supported: |-
|
not_supported: |-
|
||||||
|
|
|
@ -0,0 +1,194 @@
|
||||||
|
require File.expand_path("../../../../../base", __FILE__)
|
||||||
|
|
||||||
|
require Vagrant.source_root.join("plugins/commands/box/command/prune")
|
||||||
|
|
||||||
|
describe VagrantPlugins::CommandBox::Command::Prune do
|
||||||
|
include_context "unit"
|
||||||
|
include_context "command plugin helpers"
|
||||||
|
|
||||||
|
let(:entry_klass) { Vagrant::MachineIndex::Entry }
|
||||||
|
|
||||||
|
let(:iso_env) do
|
||||||
|
# We have to create a Vagrantfile so there is a root path
|
||||||
|
isolated_environment.tap do |env|
|
||||||
|
env.vagrantfile("")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:iso_vagrant_env) { iso_env.create_vagrant_env }
|
||||||
|
|
||||||
|
let(:argv) { [] }
|
||||||
|
|
||||||
|
# Seems this way of providing a box version triggers box in use.
|
||||||
|
def new_entry(name, box_name, box_provider, version)
|
||||||
|
entry_klass.new.tap do |e|
|
||||||
|
e.name = name
|
||||||
|
e.vagrantfile_path = "/bar"
|
||||||
|
e.extra_data["box"] = {
|
||||||
|
"name" => box_name,
|
||||||
|
"provider" => box_provider,
|
||||||
|
"version" => version,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { described_class.new(argv, iso_vagrant_env) }
|
||||||
|
|
||||||
|
describe "execute" do
|
||||||
|
context "with no args" do
|
||||||
|
it "removes the old version and keeps the current one" do
|
||||||
|
|
||||||
|
# Let's put some things in the index
|
||||||
|
iso_env.box3("foobox", "1.0", :virtualbox);
|
||||||
|
iso_env.box3("foobox", "1.1", :virtualbox);
|
||||||
|
iso_env.box3("barbox", "1.0", :vmware);
|
||||||
|
iso_env.box3("barbox", "1.1", :vmware);
|
||||||
|
|
||||||
|
iso_vagrant_env.machine_index.set(new_entry("foo", "foobox", "virtualbox", 1))
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
allow(iso_vagrant_env.ui).to receive(:info) do |data|
|
||||||
|
output << data
|
||||||
|
end
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(4)
|
||||||
|
expect(subject.execute).to eq(0)
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(2)
|
||||||
|
|
||||||
|
expect(output).to include("barbox (vmware, 1.1)")
|
||||||
|
expect(output).to include("Removing box 'barbox' (v1.0) with provider 'vmware'...")
|
||||||
|
expect(output).to include("foobox (virtualbox, 1.1)")
|
||||||
|
expect(output).to include("Removing box 'foobox' (v1.0) with provider 'virtualbox'...")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "removes nothing" do
|
||||||
|
# Let's put some things in the index
|
||||||
|
iso_env.box3("foobox", "1.0", :virtualbox);
|
||||||
|
iso_env.box3("barbox", "1.0", :vmware);
|
||||||
|
|
||||||
|
iso_vagrant_env.machine_index.set(new_entry("foo", "foobox", "virtualbox", 1))
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
allow(iso_vagrant_env.ui).to receive(:info) do |data|
|
||||||
|
output << data
|
||||||
|
end
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(2)
|
||||||
|
expect(subject.execute).to eq(0)
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(2)
|
||||||
|
|
||||||
|
expect(output).to include("No old versions of boxes to remove...")
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with --provider" do
|
||||||
|
let(:argv) { ["--provider", "virtualbox"] }
|
||||||
|
|
||||||
|
it "removes the old versions of the specified provider" do
|
||||||
|
|
||||||
|
# Let's put some things in the index
|
||||||
|
iso_env.box3("foobox", "1.0", :virtualbox);
|
||||||
|
iso_env.box3("foobox", "1.1", :virtualbox);
|
||||||
|
iso_env.box3("barbox", "1.0", :vmware);
|
||||||
|
iso_env.box3("barbox", "1.1", :vmware);
|
||||||
|
|
||||||
|
iso_vagrant_env.machine_index.set(new_entry("foo", "foobox", "virtualbox", 1))
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
allow(iso_vagrant_env.ui).to receive(:info) do |data|
|
||||||
|
output << "\n" + data
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(4)
|
||||||
|
expect(subject.execute).to eq(0)
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(3)
|
||||||
|
|
||||||
|
expect(output).to include("foobox (virtualbox, 1.1)")
|
||||||
|
expect(output).to include("Removing box 'foobox' (v1.0) with provider 'virtualbox'...")
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with --dry-run" do
|
||||||
|
let(:argv) { ["--dry-run"] }
|
||||||
|
|
||||||
|
it "removes the old versions of the specified provider" do
|
||||||
|
|
||||||
|
# Let's put some things in the index
|
||||||
|
iso_env.box3("foobox", "1.0", :virtualbox);
|
||||||
|
iso_env.box3("foobox", "1.1", :virtualbox);
|
||||||
|
|
||||||
|
iso_vagrant_env.machine_index.set(new_entry("foo", "foobox", "virtualbox", 1))
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
allow(iso_vagrant_env.ui).to receive(:info) do |data|
|
||||||
|
output << "\n" + data
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(2)
|
||||||
|
expect(subject.execute).to eq(0)
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(2)
|
||||||
|
|
||||||
|
|
||||||
|
expect(output).to include("foobox (virtualbox, 1.1)")
|
||||||
|
expect(output).to include("Would remove foobox virtualbox 1.0")
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with --name" do
|
||||||
|
let(:argv) { ["--name", "barbox"] }
|
||||||
|
|
||||||
|
it "removes the old versions of the specified provider" do
|
||||||
|
|
||||||
|
# Let's put some things in the index
|
||||||
|
iso_env.box3("foobox", "1.0", :virtualbox);
|
||||||
|
iso_env.box3("foobox", "1.1", :virtualbox);
|
||||||
|
iso_env.box3("barbox", "1.0", :vmware);
|
||||||
|
iso_env.box3("barbox", "1.1", :vmware);
|
||||||
|
|
||||||
|
iso_vagrant_env.machine_index.set(new_entry("foo", "foobox", "virtualbox", 1))
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
allow(iso_vagrant_env.ui).to receive(:info) do |data|
|
||||||
|
output << "\n" + data
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(4)
|
||||||
|
expect(subject.execute).to eq(0)
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(3)
|
||||||
|
|
||||||
|
expect(output).to include("barbox (vmware, 1.1)")
|
||||||
|
expect(output).to include("Removing box 'barbox' (v1.0) with provider 'vmware'...")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
context "with --name and --provider" do
|
||||||
|
let(:argv) { ["--name", "foobox", "--provider", "virtualbox"] }
|
||||||
|
|
||||||
|
it "removed the old versions of that name and provider only" do
|
||||||
|
# Let's put some things in the index
|
||||||
|
iso_env.box3("foobox", "1.0", :virtualbox);
|
||||||
|
iso_env.box3("foobox", "1.1", :virtualbox);
|
||||||
|
iso_env.box3("foobox", "1.0", :vmware);
|
||||||
|
iso_env.box3("foobox", "1.1", :vmware);
|
||||||
|
iso_env.box3("barbox", "1.0", :vmware);
|
||||||
|
iso_env.box3("barbox", "1.1", :vmware);
|
||||||
|
|
||||||
|
iso_vagrant_env.machine_index.set(new_entry("foo", "foobox", "virtualbox", 1))
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
allow(iso_vagrant_env.ui).to receive(:info) do |data|
|
||||||
|
output << "\n" + data
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(6)
|
||||||
|
expect(subject.execute).to eq(0)
|
||||||
|
expect(iso_vagrant_env.boxes.all.count).to eq(5)
|
||||||
|
|
||||||
|
expect(output).to include("Removing box 'foobox' (v1.0) with provider 'virtualbox'...")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,64 @@
|
||||||
|
require File.expand_path("../../../../../base", __FILE__)
|
||||||
|
|
||||||
|
describe VagrantPlugins::CommandPlugin::Action::ExpungePlugins do
|
||||||
|
let(:app) { lambda { |env| } }
|
||||||
|
let(:home_path){ '/fake/file/path/.vagrant.d' }
|
||||||
|
let(:gems_path){ "#{home_path}/gems" }
|
||||||
|
let(:force){ true }
|
||||||
|
let(:env) {{
|
||||||
|
ui: Vagrant::UI::Silent.new,
|
||||||
|
home_path: home_path,
|
||||||
|
gems_path: gems_path,
|
||||||
|
force: force
|
||||||
|
}}
|
||||||
|
|
||||||
|
let(:manager) { double("manager") }
|
||||||
|
|
||||||
|
let(:expect_to_receive) do
|
||||||
|
lambda do
|
||||||
|
allow(File).to receive(:exist?).with(File.join(home_path, 'plugins.json')).and_return(true)
|
||||||
|
allow(File).to receive(:directory?).with(gems_path).and_return(true)
|
||||||
|
expect(FileUtils).to receive(:rm).with(File.join(home_path, 'plugins.json'))
|
||||||
|
expect(FileUtils).to receive(:rm_rf).with(gems_path)
|
||||||
|
expect(app).to receive(:call).with(env).once
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { described_class.new(app, env) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
Vagrant::Plugin::Manager.stub(instance: manager)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#call" do
|
||||||
|
before do
|
||||||
|
instance_exec(&expect_to_receive)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should delete all plugins" do
|
||||||
|
subject.call(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when force is false" do
|
||||||
|
let(:force){ false }
|
||||||
|
|
||||||
|
it "should prompt user before deleting all plugins" do
|
||||||
|
expect(env[:ui]).to receive(:ask).and_return("Y\n")
|
||||||
|
subject.call(env)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "when user declines prompt" do
|
||||||
|
let(:expect_to_receive) do
|
||||||
|
lambda do
|
||||||
|
expect(app).not_to receive(:call)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not delete all plugins" do
|
||||||
|
expect(env[:ui]).to receive(:ask).and_return("N\n")
|
||||||
|
subject.call(env)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,12 +18,14 @@ describe VagrantPlugins::CommandPlugin::Action::UpdateGems do
|
||||||
describe "#call" do
|
describe "#call" do
|
||||||
it "should update all plugins if none are specified" do
|
it "should update all plugins if none are specified" do
|
||||||
expect(manager).to receive(:update_plugins).with([]).once.and_return([])
|
expect(manager).to receive(:update_plugins).with([]).once.and_return([])
|
||||||
|
expect(manager).to receive(:installed_plugins).twice.and_return({})
|
||||||
expect(app).to receive(:call).with(env).once
|
expect(app).to receive(:call).with(env).once
|
||||||
subject.call(env)
|
subject.call(env)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should update specified plugins" do
|
it "should update specified plugins" do
|
||||||
expect(manager).to receive(:update_plugins).with(["foo"]).once.and_return([])
|
expect(manager).to receive(:update_plugins).with(["foo"]).once.and_return([])
|
||||||
|
expect(manager).to receive(:installed_plugins).twice.and_return({})
|
||||||
expect(app).to receive(:call).with(env).once
|
expect(app).to receive(:call).with(env).once
|
||||||
|
|
||||||
env[:plugin_name] = ["foo"]
|
env[:plugin_name] = ["foo"]
|
||||||
|
|
|
@ -5,6 +5,8 @@ require Vagrant.source_root.join("plugins/communicators/ssh/communicator")
|
||||||
describe VagrantPlugins::CommunicatorSSH::Communicator do
|
describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||||
include_context "unit"
|
include_context "unit"
|
||||||
|
|
||||||
|
let(:export_command_template){ 'export %ENV_KEY%="%ENV_VALUE%"' }
|
||||||
|
|
||||||
# SSH configuration information mock
|
# SSH configuration information mock
|
||||||
let(:ssh) do
|
let(:ssh) do
|
||||||
double("ssh",
|
double("ssh",
|
||||||
|
@ -15,6 +17,7 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||||
pty: false,
|
pty: false,
|
||||||
keep_alive: false,
|
keep_alive: false,
|
||||||
insert_key: false,
|
insert_key: false,
|
||||||
|
export_command_template: export_command_template,
|
||||||
shell: 'bash -l'
|
shell: 'bash -l'
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -509,4 +512,18 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe ".generate_environment_export" do
|
||||||
|
it "should generate bourne shell compatible export" do
|
||||||
|
communicator.send(:generate_environment_export, "TEST", "value").should eq("export TEST=\"value\"\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with custom template defined" do
|
||||||
|
let(:export_command_template){ "setenv %ENV_KEY% %ENV_VALUE%" }
|
||||||
|
|
||||||
|
it "should generate custom export based on template" do
|
||||||
|
communicator.send(:generate_environment_export, "TEST", "value").should eq("setenv TEST value\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -45,7 +45,7 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do
|
||||||
port: '22',
|
port: '22',
|
||||||
})
|
})
|
||||||
# Makes ready? return true
|
# Makes ready? return true
|
||||||
allow(shell).to receive(:powershell).with("hostname").and_return({ exitcode: 0 })
|
allow(shell).to receive(:cmd).with("hostname").and_return({ exitcode: 0 })
|
||||||
end
|
end
|
||||||
|
|
||||||
it "retries ssh_info until ready" do
|
it "retries ssh_info until ready" do
|
||||||
|
@ -57,22 +57,22 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do
|
||||||
|
|
||||||
describe ".ready?" do
|
describe ".ready?" do
|
||||||
it "returns true if hostname command executes without error" do
|
it "returns true if hostname command executes without error" do
|
||||||
expect(shell).to receive(:powershell).with("hostname").and_return({ exitcode: 0 })
|
expect(shell).to receive(:cmd).with("hostname").and_return({ exitcode: 0 })
|
||||||
expect(subject.ready?).to be_true
|
expect(subject.ready?).to be_true
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns false if hostname command fails with a transient error" do
|
it "returns false if hostname command fails with a transient error" do
|
||||||
expect(shell).to receive(:powershell).with("hostname").and_raise(VagrantPlugins::CommunicatorWinRM::Errors::TransientError)
|
expect(shell).to receive(:cmd).with("hostname").and_raise(VagrantPlugins::CommunicatorWinRM::Errors::TransientError)
|
||||||
expect(subject.ready?).to be_false
|
expect(subject.ready?).to be_false
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an error if hostname command fails with an unknown error" do
|
it "raises an error if hostname command fails with an unknown error" do
|
||||||
expect(shell).to receive(:powershell).with("hostname").and_raise(Vagrant::Errors::VagrantError)
|
expect(shell).to receive(:cmd).with("hostname").and_raise(Vagrant::Errors::VagrantError)
|
||||||
expect { subject.ready? }.to raise_error(Vagrant::Errors::VagrantError)
|
expect { subject.ready? }.to raise_error(Vagrant::Errors::VagrantError)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises timeout error when hostname command takes longer then winrm timeout" do
|
it "raises timeout error when hostname command takes longer then winrm timeout" do
|
||||||
expect(shell).to receive(:powershell).with("hostname") do
|
expect(shell).to receive(:cmd).with("hostname") do
|
||||||
sleep 2 # winrm.timeout = 1
|
sleep 2 # winrm.timeout = 1
|
||||||
end
|
end
|
||||||
expect { subject.ready? }.to raise_error(Timeout::Error)
|
expect { subject.ready? }.to raise_error(Timeout::Error)
|
||||||
|
|
|
@ -6,7 +6,7 @@ require Vagrant.source_root.join("plugins/communicators/winrm/config")
|
||||||
describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
|
describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
|
||||||
include_context "unit"
|
include_context "unit"
|
||||||
|
|
||||||
let(:session) { double("winrm_session", create_executor: executor) }
|
let(:session) { double("winrm_session") }
|
||||||
let(:executor) { double("command_executor") }
|
let(:executor) { double("command_executor") }
|
||||||
let(:port) { config.transport == :ssl ? 5986 : 5985 }
|
let(:port) { config.transport == :ssl ? 5986 : 5985 }
|
||||||
let(:config) {
|
let(:config) {
|
||||||
|
@ -22,6 +22,8 @@ describe VagrantPlugins::CommunicatorWinRM::WinRMShell do
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
before { allow(session).to receive(:create_executor).and_yield(executor) }
|
||||||
|
|
||||||
subject do
|
subject do
|
||||||
described_class.new('localhost', port, config).tap do |comm|
|
described_class.new('localhost', port, config).tap do |comm|
|
||||||
allow(comm).to receive(:new_session).and_return(session)
|
allow(comm).to receive(:new_session).and_return(session)
|
||||||
|
|
|
@ -31,10 +31,9 @@ describe "VagrantPlugins::GuestBSD::Cap::NFS" do
|
||||||
}
|
}
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to match(/set -e/)
|
|
||||||
expect(comm.received_commands[0]).to match(/mkdir -p \/guest/)
|
expect(comm.received_commands[0]).to match(/mkdir -p \/guest/)
|
||||||
expect(comm.received_commands[0]).to match(/mount -t nfs/)
|
expect(comm.received_commands[1]).to match(/mount -t nfs/)
|
||||||
expect(comm.received_commands[0]).to match(/1.2.3.4:\/host \/guest/)
|
expect(comm.received_commands[1]).to match(/1.2.3.4:\/host \/guest/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "mounts with options" do
|
it "mounts with options" do
|
||||||
|
@ -49,7 +48,7 @@ describe "VagrantPlugins::GuestBSD::Cap::NFS" do
|
||||||
}
|
}
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to match(/mount -t nfs -o 'nfsv2,mntudp,banana'/)
|
expect(comm.received_commands[1]).to match(/mount -t nfs -o 'nfsv2,mntudp,banana'/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "escapes host and guest paths" do
|
it "escapes host and guest paths" do
|
||||||
|
@ -61,8 +60,8 @@ describe "VagrantPlugins::GuestBSD::Cap::NFS" do
|
||||||
}
|
}
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to match(/host\\\'s/)
|
expect(comm.received_commands[1]).to match(/host\\\'s/)
|
||||||
expect(comm.received_commands[0]).to match(/guest\\\ with\\\ spaces/)
|
expect(comm.received_commands[1]).to match(/guest\\\ with\\\ spaces/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -43,7 +43,7 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to match(/mkdir -p #{guestpath}/)
|
expect(comm.received_commands[0]).to match(/mkdir -p #{guestpath}/)
|
||||||
expect(comm.received_commands[0]).to match(/1.2.3.4:#{hostpath} #{guestpath}/)
|
expect(comm.received_commands[1]).to match(/1.2.3.4:#{hostpath} #{guestpath}/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "mounts with options" do
|
it "mounts with options" do
|
||||||
|
@ -58,7 +58,7 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
|
||||||
}
|
}
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to match(/mount -o vers=2,udp/)
|
expect(comm.received_commands[1]).to match(/mount -o vers=2,udp/)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "emits an event" do
|
it "emits an event" do
|
||||||
|
@ -71,7 +71,7 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
|
||||||
}
|
}
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to include(
|
expect(comm.received_commands[1]).to include(
|
||||||
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guestpath}")
|
"/sbin/initctl emit --no-wait vagrant-mounted MOUNTPOINT=#{guestpath}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -84,8 +84,8 @@ describe "VagrantPlugins::GuestLinux::Cap::MountNFS" do
|
||||||
}
|
}
|
||||||
cap.mount_nfs_folder(machine, ip, folders)
|
cap.mount_nfs_folder(machine, ip, folders)
|
||||||
|
|
||||||
expect(comm.received_commands[0]).to match(/host\\\'s/)
|
expect(comm.received_commands[1]).to match(/host\\\'s/)
|
||||||
expect(comm.received_commands[0]).to match(/guest\\\ with\\\ spaces/)
|
expect(comm.received_commands[1]).to match(/guest\\\ with\\\ spaces/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,5 +44,41 @@ describe "VagrantPlugins::GuestLinux::Cap::NetworkInterfaces" do
|
||||||
result = cap.network_interfaces(machine)
|
result = cap.network_interfaces(machine)
|
||||||
expect(result).to eq(["enp0s3", "enp0s5", "enp0s8", "enp0s10", "enp1s3"])
|
expect(result).to eq(["enp0s3", "enp0s5", "enp0s8", "enp0s10", "enp1s3"])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "sorts ethernet devices discovered with classic naming first in list" do
|
||||||
|
expect(comm).to receive(:sudo).and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0")
|
||||||
|
result = cap.network_interfaces(machine)
|
||||||
|
expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sorts ethernet devices discovered with predictable network interfaces naming first in list" do
|
||||||
|
expect(comm).to receive(:sudo).and_yield(:stdout, "enp0s8\ndocker0\nenp0s3\nbridge0\nenp0s5")
|
||||||
|
result = cap.network_interfaces(machine)
|
||||||
|
expect(result).to eq(["enp0s3", "enp0s5", "enp0s8", "bridge0", "docker0"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sorts ethernet devices discovered with predictable network interfaces naming first in list with less" do
|
||||||
|
expect(comm).to receive(:sudo).and_yield(:stdout, "enp0s3\nenp0s8\ndocker0")
|
||||||
|
result = cap.network_interfaces(machine)
|
||||||
|
expect(result).to eq(["enp0s3", "enp0s8", "docker0"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not include ethernet devices aliases within prefix device listing" do
|
||||||
|
expect(comm).to receive(:sudo).and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0\ndocker1\neth0:0")
|
||||||
|
result = cap.network_interfaces(machine)
|
||||||
|
expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0", "docker1", "eth0:0"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "does not include ethernet devices aliases within prefix device listing with dot separators" do
|
||||||
|
expect(comm).to receive(:sudo).and_yield(:stdout, "eth1\neth2\ndocker0\nbridge0\neth0\ndocker1\neth0.1@eth0")
|
||||||
|
result = cap.network_interfaces(machine)
|
||||||
|
expect(result).to eq(["eth0", "eth1", "eth2", "bridge0", "docker0", "docker1", "eth0.1@eth0"])
|
||||||
|
end
|
||||||
|
|
||||||
|
it "properly sorts non-consistent device name formats" do
|
||||||
|
expect(comm).to receive(:sudo).and_yield(:stdout, "eth0\neth1\ndocker0\nveth437f7f9\nveth06b3e44\nveth8bb7081")
|
||||||
|
result = cap.network_interfaces(machine)
|
||||||
|
expect(result).to eq(["eth0", "eth1", "docker0", "veth8bb7081", "veth437f7f9", "veth06b3e44"])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -70,15 +70,27 @@ describe "VagrantPlugins::GuestLinux::Cap::Rsync" do
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with excludes provided" do
|
context "with excludes provided" do
|
||||||
let(:excludes){ ["tmp", "state/*"] }
|
let(:excludes){ ["tmp", "state/*", "path/with a/space"] }
|
||||||
|
|
||||||
it "ignores files that are excluded" do
|
it "ignores files that are excluded" do
|
||||||
comm.expect_command(
|
# comm.expect_command(
|
||||||
"find #{guest_directory} -path #{File.join(guest_directory, excludes.first)} -prune -o " \
|
# "find #{guest_directory} -path #{Shellwords.escape(File.join(guest_directory, excludes.first))} -prune -o " \
|
||||||
"-path #{File.join(guest_directory, excludes.last)} -prune -o '!' -type l -a '(' ! -user " \
|
# "-path #{Shellwords.escape(File.join(guest_directory, excludes.last))} -prune -o '!' " \
|
||||||
"#{owner} -or ! -group #{group} ')' -exec chown #{owner}:#{group} '{}' +"
|
# "-path -type l -a '(' ! -user " \
|
||||||
)
|
# "#{owner} -or ! -group #{group} ')' -exec chown #{owner}:#{group} '{}' +"
|
||||||
|
# )
|
||||||
cap.rsync_post(machine, options)
|
cap.rsync_post(machine, options)
|
||||||
|
excludes.each do |ex_path|
|
||||||
|
expect(comm.received_commands.first).to include("-path #{Shellwords.escape(File.join(guest_directory, ex_path))} -prune")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "properly escapes excluded directories" do
|
||||||
|
cap.rsync_post(machine, options)
|
||||||
|
exclude_with_space = excludes.detect{|ex| ex.include?(' ')}
|
||||||
|
escaped_exclude_with_space = Shellwords.escape(exclude_with_space)
|
||||||
|
expect(comm.received_commands.first).not_to include(exclude_with_space)
|
||||||
|
expect(comm.received_commands.first).to include(escaped_exclude_with_space)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
require_relative "../../../../base"
|
||||||
|
|
||||||
|
describe "VagrantPlugins::GuestOpenBSD::Cap::RSync" do
|
||||||
|
let(:caps) do
|
||||||
|
VagrantPlugins::GuestOpenBSD::Plugin
|
||||||
|
.components
|
||||||
|
.guest_capabilities[:openbsd]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:machine) { double("machine") }
|
||||||
|
let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(machine).to receive(:communicate).and_return(comm)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
comm.verify_expectations!
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".rsync_install" do
|
||||||
|
let(:cap) { caps.get(:rsync_install) }
|
||||||
|
|
||||||
|
describe "successful installation" do
|
||||||
|
it "installs rsync" do
|
||||||
|
cap.rsync_install(machine)
|
||||||
|
expect(comm.received_commands[0]).to match(/pkg_add -I rsync/)
|
||||||
|
expect(comm.received_commands[1]).to match(/pkg_info/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "failure installation" do
|
||||||
|
before do
|
||||||
|
expect(comm).to receive(:execute).and_raise(Vagrant::Errors::RSyncNotInstalledInGuest, {command: '', output: ''})
|
||||||
|
end
|
||||||
|
|
||||||
|
it "raises custom exception" do
|
||||||
|
expect{ cap.rsync_install(machine) }.to raise_error(Vagrant::Errors::RSyncNotInstalledInGuest)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".rsync_installed" do
|
||||||
|
let(:cap) { caps.get(:rsync_installed) }
|
||||||
|
|
||||||
|
it "checks if rsync is installed" do
|
||||||
|
comm.expect_command("which rsync")
|
||||||
|
cap.rsync_installed(machine)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".rsync_command" do
|
||||||
|
let(:cap) { caps.get(:rsync_command) }
|
||||||
|
|
||||||
|
it "defaults to 'sudo rsync'" do
|
||||||
|
expect(cap.rsync_command(machine)).to eq("sudo rsync")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -45,7 +45,7 @@ describe "VagrantPlugins::GuestPhoton::Cap:ConfigureNetworks" do
|
||||||
it "creates and starts the networks" do
|
it "creates and starts the networks" do
|
||||||
cap.configure_networks(machine, [network_1, network_2])
|
cap.configure_networks(machine, [network_1, network_2])
|
||||||
expect(comm.received_commands[1]).to match(/ifconfig eth1/)
|
expect(comm.received_commands[1]).to match(/ifconfig eth1/)
|
||||||
expect(comm.received_commands[1]).to match(/ifconfig eth2 33.33.33.10 netmast 255.255.0.0/)
|
expect(comm.received_commands[1]).to match(/ifconfig eth2 33.33.33.10 netmask 255.255.0.0/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -56,9 +56,10 @@ describe "VagrantPlugins::GuestRedHat::Cap::ConfigureNetworks" do
|
||||||
|
|
||||||
cap.configure_networks(machine, [network_1, network_2])
|
cap.configure_networks(machine, [network_1, network_2])
|
||||||
expect(comm.received_commands[0]).to match(/\/sbin\/ifdown 'eth1'/)
|
expect(comm.received_commands[0]).to match(/\/sbin\/ifdown 'eth1'/)
|
||||||
expect(comm.received_commands[0]).to match(/\/sbin\/ifup 'eth1'/)
|
expect(comm.received_commands[0]).to match(/ifcfg-eth1/)
|
||||||
expect(comm.received_commands[0]).to match(/\/sbin\/ifdown 'eth2'/)
|
expect(comm.received_commands[0]).to match(/\/sbin\/ifdown 'eth2'/)
|
||||||
expect(comm.received_commands[0]).to match(/\/sbin\/ifup 'eth2'/)
|
expect(comm.received_commands[0]).to match(/ifcfg-eth2/)
|
||||||
|
expect(comm.received_commands[0]).to match(/nmcli c reload/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
require_relative "../../../../base"
|
||||||
|
require_relative "../../../../../../plugins/hosts/linux/cap/nfs"
|
||||||
|
require_relative "../../../../../../lib/vagrant/util"
|
||||||
|
|
||||||
|
describe VagrantPlugins::HostLinux::Cap::NFS do
|
||||||
|
|
||||||
|
include_context "unit"
|
||||||
|
|
||||||
|
let(:caps) do
|
||||||
|
VagrantPlugins::HostLinux::Plugin
|
||||||
|
.components
|
||||||
|
.host_capabilities[:linux]
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:tmp_exports_path) do
|
||||||
|
@tmp_exports ||= temporary_file
|
||||||
|
end
|
||||||
|
let(:exports_path){ VagrantPlugins::HostLinux::Cap::NFS::NFS_EXPORTS_PATH }
|
||||||
|
let(:env){ double(:env) }
|
||||||
|
let(:ui){ double(:ui) }
|
||||||
|
let(:host){ double(:host) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
@original_exports_path = VagrantPlugins::HostLinux::Cap::NFS::NFS_EXPORTS_PATH
|
||||||
|
VagrantPlugins::HostLinux::Cap::NFS.send(:remove_const, :NFS_EXPORTS_PATH)
|
||||||
|
VagrantPlugins::HostLinux::Cap::NFS.const_set(:NFS_EXPORTS_PATH, tmp_exports_path.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
VagrantPlugins::HostLinux::Cap::NFS.send(:remove_const, :NFS_EXPORTS_PATH)
|
||||||
|
VagrantPlugins::HostLinux::Cap::NFS.const_set(:NFS_EXPORTS_PATH, @original_exports_path)
|
||||||
|
File.unlink(tmp_exports_path.to_s) if File.exist?(tmp_exports_path.to_s)
|
||||||
|
@tmp_exports = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".nfs_export" do
|
||||||
|
|
||||||
|
let(:cap){ caps.get(:nfs_export) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(env).to receive(:host).and_return(host)
|
||||||
|
allow(host).to receive(:capability).with(:nfs_apply_command).and_return("/bin/true")
|
||||||
|
allow(host).to receive(:capability).with(:nfs_check_command).and_return("/bin/true")
|
||||||
|
allow(host).to receive(:capability).with(:nfs_start_command).and_return("/bin/true")
|
||||||
|
allow(ui).to receive(:info)
|
||||||
|
allow(cap).to receive(:system).with("sudo /bin/true").and_return(true)
|
||||||
|
allow(cap).to receive(:system).with("/bin/true").and_return(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should export new entries" do
|
||||||
|
cap.nfs_export(env, ui, SecureRandom.uuid, ["127.0.0.1"], "tmp" => {:hostpath => "/tmp"})
|
||||||
|
exports_content = File.read(exports_path)
|
||||||
|
expect(exports_content).to match(/\/tmp.*127\.0\.0\.1/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should not remove existing entries" do
|
||||||
|
File.write(exports_path, "/custom/directory hostname1(rw,sync,no_subtree_check)")
|
||||||
|
cap.nfs_export(env, ui, SecureRandom.uuid, ["127.0.0.1"], "tmp" => {:hostpath => "/tmp"})
|
||||||
|
exports_content = File.read(exports_path)
|
||||||
|
expect(exports_content).to match(/\/tmp.*127\.0\.0\.1/)
|
||||||
|
expect(exports_content).to match(/\/custom\/directory.*hostname1/)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should remove entries no longer valid" do
|
||||||
|
valid_id = SecureRandom.uuid
|
||||||
|
other_id = SecureRandom.uuid
|
||||||
|
content =<<-EOH
|
||||||
|
# VAGRANT-BEGIN: #{Process.uid} #{other_id}
|
||||||
|
"/tmp" 127.0.0.1(rw,no_subtree_check,all_squash,anonuid=,anongid=,fsid=)
|
||||||
|
# VAGRANT-END: #{Process.uid} #{other_id}
|
||||||
|
# VAGRANT-BEGIN: #{Process.uid} #{valid_id}
|
||||||
|
"/var" 127.0.0.1(rw,no_subtree_check,all_squash,anonuid=,anongid=,fsid=)
|
||||||
|
# VAGRANT-END: #{Process.uid} #{valid_id}
|
||||||
|
EOH
|
||||||
|
File.write(exports_path, content)
|
||||||
|
cap.nfs_export(env, ui, valid_id, ["127.0.0.1"], "home" => {:hostpath => "/home"})
|
||||||
|
exports_content = File.read(exports_path)
|
||||||
|
expect(exports_content).to include("/home")
|
||||||
|
expect(exports_content).to include("/tmp")
|
||||||
|
expect(exports_content).not_to include("/var")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".nfs_prune" do
|
||||||
|
|
||||||
|
let(:cap){ caps.get(:nfs_prune) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(ui).to receive(:info)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should remove entries no longer valid" do
|
||||||
|
invalid_id = SecureRandom.uuid
|
||||||
|
valid_id = SecureRandom.uuid
|
||||||
|
content =<<-EOH
|
||||||
|
# VAGRANT-BEGIN: #{Process.uid} #{invalid_id}
|
||||||
|
"/tmp" 127.0.0.1(rw,no_subtree_check,all_squash,anonuid=,anongid=,fsid=)
|
||||||
|
# VAGRANT-END: #{Process.uid} #{invalid_id}
|
||||||
|
# VAGRANT-BEGIN: #{Process.uid} #{valid_id}
|
||||||
|
"/var" 127.0.0.1(rw,no_subtree_check,all_squash,anonuid=,anongid=,fsid=)
|
||||||
|
# VAGRANT-END: #{Process.uid} #{valid_id}
|
||||||
|
EOH
|
||||||
|
File.write(exports_path, content)
|
||||||
|
cap.nfs_prune(env, ui, [valid_id])
|
||||||
|
exports_content = File.read(exports_path)
|
||||||
|
expect(exports_content).to include(valid_id)
|
||||||
|
expect(exports_content).not_to include(invalid_id)
|
||||||
|
expect(exports_content).to include("/var")
|
||||||
|
expect(exports_content).not_to include("/tmp")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe ".nfs_write_exports" do
|
||||||
|
|
||||||
|
before do
|
||||||
|
File.write(tmp_exports_path, "original content")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should write updated contents to file" do
|
||||||
|
described_class.nfs_write_exports("new content")
|
||||||
|
exports_content = File.read(exports_path)
|
||||||
|
expect(exports_content).to include("new content")
|
||||||
|
expect(exports_content).not_to include("original content")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should only update contents if different" do
|
||||||
|
original_stat = File.stat(exports_path)
|
||||||
|
described_class.nfs_write_exports("original content")
|
||||||
|
updated_stat = File.stat(exports_path)
|
||||||
|
expect(original_stat).to eq(updated_stat)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should retain existing file permissions" do
|
||||||
|
File.chmod(0600, exports_path)
|
||||||
|
original_stat = File.stat(exports_path)
|
||||||
|
described_class.nfs_write_exports("original content")
|
||||||
|
updated_stat = File.stat(exports_path)
|
||||||
|
expect(original_stat.mode).to eq(updated_stat.mode)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should raise exception when failing to move new exports file" do
|
||||||
|
expect(Vagrant::Util::Subprocess).to receive(:execute).and_return(
|
||||||
|
Vagrant::Util::Subprocess::Result.new(1, "Failed to move file", "")
|
||||||
|
)
|
||||||
|
expect{ described_class.nfs_write_exports("new content") }.to raise_error(Vagrant::Errors::NFSExportsFailed)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should retain existing file owner and group IDs" do
|
||||||
|
pending("investigate using a simulated FS to test")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "should raise custom exception when chown fails" do
|
||||||
|
pending("investigate using a simulated FS to test")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -133,6 +133,14 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
|
||||||
|
|
||||||
assert_valid
|
assert_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
["1", 1, "1.0", 1.0].each do |valid|
|
||||||
|
it "is valid: #{valid}" do
|
||||||
|
subject.box_version = valid
|
||||||
|
subject.finalize!
|
||||||
|
assert_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#communicator" do
|
describe "#communicator" do
|
||||||
|
@ -526,6 +534,21 @@ describe VagrantPlugins::Kernel_V2::VMConfig do
|
||||||
subject.finalize!
|
subject.finalize!
|
||||||
assert_valid
|
assert_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "allows providing custom name via options" do
|
||||||
|
subject.synced_folder(".", "/vagrant", name: "my-vagrant-folder")
|
||||||
|
sf = subject.synced_folders
|
||||||
|
expect(sf).to have_key("my-vagrant-folder")
|
||||||
|
expect(sf["my-vagrant-folder"][:guestpath]).to eq("/vagrant")
|
||||||
|
expect(sf["my-vagrant-folder"][:hostpath]).to eq(".")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "allows providing custom name without guest path" do
|
||||||
|
subject.synced_folder(".", name: "my-vagrant-folder")
|
||||||
|
sf = subject.synced_folders
|
||||||
|
expect(sf).to have_key("my-vagrant-folder")
|
||||||
|
expect(sf["my-vagrant-folder"][:hostpath]).to eq(".")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#usable_port_range" do
|
describe "#usable_port_range" do
|
||||||
|
|
|
@ -16,7 +16,8 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
||||||
let(:existing_file) { "this/path/is/a/stub" }
|
let(:existing_file) { "this/path/is/a/stub" }
|
||||||
|
|
||||||
it "supports a list of options" do
|
it "supports a list of options" do
|
||||||
supported_options = %w( extra_vars
|
supported_options = %w( config_file
|
||||||
|
extra_vars
|
||||||
galaxy_command
|
galaxy_command
|
||||||
galaxy_role_file
|
galaxy_role_file
|
||||||
galaxy_roles_path
|
galaxy_roles_path
|
||||||
|
@ -27,6 +28,7 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
||||||
inventory_path
|
inventory_path
|
||||||
limit
|
limit
|
||||||
playbook
|
playbook
|
||||||
|
playbook_command
|
||||||
provisioning_path
|
provisioning_path
|
||||||
raw_arguments
|
raw_arguments
|
||||||
skip_tags
|
skip_tags
|
||||||
|
|
|
@ -15,6 +15,7 @@ describe VagrantPlugins::Ansible::Config::Host, :skip_windows => true do
|
||||||
it "supports a list of options" do
|
it "supports a list of options" do
|
||||||
supported_options = %w( ask_sudo_pass
|
supported_options = %w( ask_sudo_pass
|
||||||
ask_vault_pass
|
ask_vault_pass
|
||||||
|
config_file
|
||||||
extra_vars
|
extra_vars
|
||||||
force_remote_user
|
force_remote_user
|
||||||
galaxy_command
|
galaxy_command
|
||||||
|
@ -26,6 +27,7 @@ describe VagrantPlugins::Ansible::Config::Host, :skip_windows => true do
|
||||||
inventory_path
|
inventory_path
|
||||||
limit
|
limit
|
||||||
playbook
|
playbook
|
||||||
|
playbook_command
|
||||||
raw_arguments
|
raw_arguments
|
||||||
raw_ssh_args
|
raw_ssh_args
|
||||||
skip_tags
|
skip_tags
|
||||||
|
@ -63,7 +65,7 @@ describe VagrantPlugins::Ansible::Config::Host, :skip_windows => true do
|
||||||
it_behaves_like "any VagrantConfigProvisioner strict boolean attribute", :ask_sudo_pass, false
|
it_behaves_like "any VagrantConfigProvisioner strict boolean attribute", :ask_sudo_pass, false
|
||||||
end
|
end
|
||||||
describe "ask_vault_pass option" do
|
describe "ask_vault_pass option" do
|
||||||
it_behaves_like "any VagrantConfigProvisioner strict boolean attribute", :ask_sudo_pass, false
|
it_behaves_like "any VagrantConfigProvisioner strict boolean attribute", :ask_vault_pass, false
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "#validate" do
|
describe "#validate" do
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue