diff --git a/CHANGELOG.md b/CHANGELOG.md index f9f46eb3c..3ecd67de9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,79 @@ +## 1.7.3 (unreleased) + +BUG FIXES: + + - core: push configurations are validated with global configs [GH-5130] + - core: remove executable permissions on internal file [GH-5220] + - core: check name and version in `has_plugin?` [GH-5218] + - hosts/nfs: allow colons (`:`) in NFS IDs [GH-5222] + - guests/funtoo: fix incorrect path in configure networks [GH-4812] + - plugins/login: allow users to login with a token [GH-5145] + - providers/hyperv: allow users to configure memory, cpu count, and vmname [GH-5183] + - provisioners/ansible: fix SSH settings to support more than 5 ssh keys [GH-5017] + - provisioners/ansible: increase ansible connection timeout to 30 seconds [GH-5018] + - provisioners/docker: use docker.com instead of docker.io [GH-5216] + +## 1.7.2 (January 6, 2015) + +BREAKING CHANGES: + + - If you depended on the paths that Chef/Puppet provisioners use to + store cookbooks (ex. "/tmp/vagrant-chef-1"), these will no longer be + correct. Without this change, Chef/Puppet didn't work at all with + `vagrant provision`. We expect this to affect only a minor number of + people, since it's not something that was ever documented or recommended + by Vagrant, or even meant to be supported. + +FEATURES: + + - provisioners/salt: add support for grains [GH-4895] + +IMPROVEMENTS: + + - commands/reload,up: `--provision-with` implies `--provision` [GH-5085] + +BUG FIXES: + + - core: private boxes still referencing vagrantcloud.com will have + their vagrant login access token properly appended + - core: push plugin configuration is properly validated + - core: restore box packaging functionality + - commands/package: fix crash + - commands/push: push lookups are by user-defined name, not push + strategy name [GH-4975] + - commands/push: validate the configuration + - communicators/winrm: detect parse errors in PowerShell and error + - guests/arch: fix network configuration due to poor line breaks. [GH-4964] + - guests/solaris: Merge configurations properly so configs can be set + in default Vagrantfiles. [GH-5092] + - installer: SSL cert bundle contains 1024-bit keys, fixing SSL verification + for a lot of sites. + - installer: vagrant executable properly `cygpaths` the SSL bundle path + for Cygwin + - installer: Nokogiri (XML lib used by Vagrant and dependencies) linker + dependencies fixed, fixing load issues on some platforms + - providers/docker: Symlinks in shared folders work. [GH-5093] + - providers/hyperv: VM start errors turn into proper Vagrant errors. [GH-5101] + - provisioners/chef: fix missing shared folder error [GH-4988] + - provisioners/chef: remove Chef version check from solo.rb generation and + make `roles_path` populate correctly + - provisioners/chef: fix bad invocation of `with_clean_env` [GH-5021] + - pushes/atlas: support more verbose logging + - pushes/ftp: expand file paths relative to the Vagrantfile + - pushes/ftp: improved debugging output + - pushes/ftp: create parent directories if they do not exist on the remote + server + +## 1.7.1 (December 11, 2014) + +IMPROVEMENTS: + + - provisioners/ansible: Use Docker proxy if needed. [GH-4906] + +BUG FIXES: + + - providers/docker: Add support of SSH agent forwarding. [GH-4905] + ## 1.7.0 (December 9, 2014) BREAKING CHANGES: @@ -102,6 +178,7 @@ BUG FIXES: - provisioners/ansible: Force `ssh` (OpenSSH) connection by default [GH-3396] - provisioners/ansible: Don't use or modify `~/.ssh/known_hosts` file by default, similarly to native vagrant commands [GH-3900] + - provisioners/ansible: Use intermediate Docker host when needed. [GH-4071] - provisioners/docker: Get GPG key over SSL. [GH-4597] - provisioners/docker: Search for docker binary in multiple places. [GH-4580] - provisioners/salt: Highstate works properly with a master. [GH-4471] diff --git a/LICENSE b/LICENSE index 661398b6b..91ca85a81 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License -Copyright (c) 2010-2014 Mitchell Hashimoto +Copyright (c) 2010-2015 Mitchell Hashimoto Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 7e1325dbf..ee1026409 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ like so: bundle exec vagrant help -**NOTE:** By default running Vagrant in via `bundle` will disable plugins. +**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. diff --git a/Vagrantfile b/Vagrantfile index 075157ed9..e928b3c6b 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -6,13 +6,21 @@ Vagrant.configure("2") do |config| config.vm.box = "hashicorp/precise64" - ["virtualbox", "vmware_fusion", "vmware_workstation"].each do |provider| + ["vmware_fusion", "vmware_workstation", "virtualbox"].each do |provider| config.vm.provider provider do |v, override| v.memory = "1024" end end config.vm.provision "shell", inline: $shell + + config.push.define "www", strategy: "local-exec" do |push| + push.script = "scripts/website_push_www.sh" + end + + config.push.define "docs", strategy: "local-exec" do |push| + push.script = "scripts/website_push_docs.sh" + end end $shell = <<-CONTENTS diff --git a/contrib/bash/completion.sh b/contrib/bash/completion.sh index 636795744..e21dc8dcf 100644 --- a/contrib/bash/completion.sh +++ b/contrib/bash/completion.sh @@ -65,7 +65,7 @@ _vagrant() { then case "$prev" in "init") - local box_list=$(find $HOME/.vagrant.d/boxes -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + local box_list=$(find "${VAGRANT_HOME:-${HOME}/.vagrant.d}/boxes" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) COMPREPLY=($(compgen -W "${box_list}" -- ${cur})) return 0 ;; @@ -111,7 +111,7 @@ _vagrant() { then case "$prev" in "remove"|"repackage") - local box_list=$(find $HOME/.vagrant.d/boxes -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) + local box_list=$(find "${VAGRANT_HOME:-${HOME}/.vagrant.d}/boxes" -mindepth 1 -maxdepth 1 -type d -exec basename {} \;) COMPREPLY=($(compgen -W "${box_list}" -- ${cur})) return 0 ;; diff --git a/contrib/sudoers/linux-fedora b/contrib/sudoers/linux-fedora new file mode 100644 index 000000000..f2d64b66d --- /dev/null +++ b/contrib/sudoers/linux-fedora @@ -0,0 +1,6 @@ +Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports +Cmnd_Alias VAGRANT_NFSD_CHECK = /usr/bin/systemctl status nfs-server.service +Cmnd_Alias VAGRANT_NFSD_START = /usr/bin/systemctl start nfs-server.service +Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar +Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports +%vagrant ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE diff --git a/contrib/sudoers/linux b/contrib/sudoers/linux-ubuntu similarity index 100% rename from contrib/sudoers/linux rename to contrib/sudoers/linux-ubuntu diff --git a/lib/vagrant.rb b/lib/vagrant.rb index 4b5dc84ba..1fb9c49d6 100644 --- a/lib/vagrant.rb +++ b/lib/vagrant.rb @@ -156,7 +156,7 @@ module Vagrant Plugin::Manager.instance.installed_specs.any? do |s| match = s.name == name next match if !version - next version.satisfied_by?(s.version) + next match && version.satisfied_by?(s.version) end end diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index 13688bae5..deed8b9ef 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -369,7 +369,7 @@ module Vagrant # # @return [Hash] def downloader(url, env, **opts) - opts[:ui] = true if !opts.has_key?(:ui) + opts[:ui] = true if !opts.key?(:ui) temp_path = env[:tmp_path].join("box" + Digest::SHA1.hexdigest(url)) @logger.info("Downloading box: #{url} => #{temp_path}") @@ -409,7 +409,7 @@ module Vagrant end def download(url, env, **opts) - opts[:ui] = true if !opts.has_key?(:ui) + opts[:ui] = true if !opts.key?(:ui) d = downloader(url, env, **opts) diff --git a/lib/vagrant/action/builtin/config_validate.rb b/lib/vagrant/action/builtin/config_validate.rb index e4fd44cdd..3c4461a10 100644 --- a/lib/vagrant/action/builtin/config_validate.rb +++ b/lib/vagrant/action/builtin/config_validate.rb @@ -11,7 +11,7 @@ module Vagrant end def call(env) - if !env.has_key?(:config_validate) || env[:config_validate] + if !env.key?(:config_validate) || env[:config_validate] errors = env[:machine].config.validate(env[:machine]) if errors && !errors.empty? diff --git a/lib/vagrant/action/builtin/graceful_halt.rb b/lib/vagrant/action/builtin/graceful_halt.rb index 5ccd8389d..33f6cfb9b 100644 --- a/lib/vagrant/action/builtin/graceful_halt.rb +++ b/lib/vagrant/action/builtin/graceful_halt.rb @@ -24,7 +24,7 @@ module Vagrant def call(env) graceful = true - graceful = !env[:force_halt] if env.has_key?(:force_halt) + graceful = !env[:force_halt] if env.key?(:force_halt) # By default, we didn't succeed. env[:result] = false diff --git a/lib/vagrant/action/builtin/mixin_synced_folders.rb b/lib/vagrant/action/builtin/mixin_synced_folders.rb index da8437dee..5a44c5ac8 100644 --- a/lib/vagrant/action/builtin/mixin_synced_folders.rb +++ b/lib/vagrant/action/builtin/mixin_synced_folders.rb @@ -129,7 +129,7 @@ module Vagrant # If we have folders with the "default" key, then determine the # most appropriate implementation for this. - if folders.has_key?("") && !folders[""].empty? + if folders.key?("") && !folders[""].empty? default_impl = default_synced_folder_type(machine, plugins) if !default_impl types = plugins.to_hash.keys.map { |t| t.to_s }.sort.join(", ") diff --git a/lib/vagrant/action/builtin/provision.rb b/lib/vagrant/action/builtin/provision.rb index 2163a2c6a..02868c735 100644 --- a/lib/vagrant/action/builtin/provision.rb +++ b/lib/vagrant/action/builtin/provision.rb @@ -24,13 +24,13 @@ module Vagrant # Tracks whether we were configured to provision config_enabled = true - config_enabled = env[:provision_enabled] if env.has_key?(:provision_enabled) + config_enabled = env[:provision_enabled] if env.key?(:provision_enabled) # Check if we already provisioned, and if so, disable the rest provision_enabled = true ignore_sentinel = true - if env.has_key?(:provision_ignore_sentinel) + if env.key?(:provision_ignore_sentinel) ignore_sentinel = env[:provision_ignore_sentinel] end if ignore_sentinel @@ -69,7 +69,7 @@ module Vagrant end # Store the value so that other actions can use it - env[:provision_enabled] = provision_enabled if !env.has_key?(:provision_enabled) + env[:provision_enabled] = provision_enabled if !env.key?(:provision_enabled) # Ask the provisioners to modify the configuration if needed provisioner_instances(env).each do |p, _| diff --git a/lib/vagrant/action/runner.rb b/lib/vagrant/action/runner.rb index 6d4a2e409..bfb187709 100644 --- a/lib/vagrant/action/runner.rb +++ b/lib/vagrant/action/runner.rb @@ -49,7 +49,7 @@ module Vagrant # Run the action chain in a busy block, marking the environment as # interrupted if a SIGINT occurs, and exiting cleanly once the # chain has been run. - ui = environment[:ui] if environment.has_key?(:ui) + ui = environment[:ui] if environment.key?(:ui) int_callback = lambda do if environment[:interrupted] ui.error I18n.t("vagrant.actions.runner.exit_immediately") if ui diff --git a/lib/vagrant/capability_host.rb b/lib/vagrant/capability_host.rb index e3b579a49..47491deef 100644 --- a/lib/vagrant/capability_host.rb +++ b/lib/vagrant/capability_host.rb @@ -165,7 +165,7 @@ module Vagrant @cap_logger.debug("Checking in: #{host_name}") caps = @cap_caps[host_name] - if caps && caps.has_key?(cap_name) + if caps && caps.key?(cap_name) @cap_logger.debug("Found cap: #{cap_name} in #{host_name}") return caps[cap_name] end diff --git a/lib/vagrant/config/loader.rb b/lib/vagrant/config/loader.rb index f57b5d31e..35b0d0828 100644 --- a/lib/vagrant/config/loader.rb +++ b/lib/vagrant/config/loader.rb @@ -49,7 +49,7 @@ module Vagrant # Gather the procs for every source, since that is what we care about. procs = [] sources.each do |source| - if !@proc_cache.has_key?(source) + if !@proc_cache.key?(source) # Load the procs for this source and cache them. This caching # avoids the issue where a file may have side effects when loading # and loading it multiple times causes unexpected behavior. @@ -92,10 +92,10 @@ module Vagrant errors = [] order.each do |key| - next if !@sources.has_key?(key) + next if !@sources.key?(key) @sources[key].each do |version, proc| - if !@config_cache.has_key?(proc) + if !@config_cache.key?(proc) @logger.debug("Loading from: #{key} (evaluating)") # Get the proper version loader for this version and load diff --git a/lib/vagrant/config/v1/loader.rb b/lib/vagrant/config/v1/loader.rb index 910ae3dda..e26c88e44 100644 --- a/lib/vagrant/config/v1/loader.rb +++ b/lib/vagrant/config/v1/loader.rb @@ -60,7 +60,7 @@ module Vagrant new_keys = new_state["keys"] keys = {} old_keys.each do |key, old_value| - if new_keys.has_key?(key) + if new_keys.key?(key) # We need to do a merge, which we expect to be available # on the config class itself. keys[key] = old_value.merge(new_keys[key]) @@ -72,7 +72,7 @@ module Vagrant new_keys.each do |key, new_value| # Add in the keys that the new class has that we haven't merged. - if !keys.has_key?(key) + if !keys.key?(key) keys[key] = new_value.dup end end diff --git a/lib/vagrant/config/v1/root.rb b/lib/vagrant/config/v1/root.rb index 1f7db9763..975a9e4d3 100644 --- a/lib/vagrant/config/v1/root.rb +++ b/lib/vagrant/config/v1/root.rb @@ -20,7 +20,7 @@ module Vagrant # used for Vagrant and load the proper configuration classes for # each. def method_missing(name, *args) - return @keys[name] if @keys.has_key?(name) + return @keys[name] if @keys.key?(name) config_klass = @config_map[name.to_sym] if config_klass diff --git a/lib/vagrant/config/v2/loader.rb b/lib/vagrant/config/v2/loader.rb index 1c3bc0224..2f5b6cbac 100644 --- a/lib/vagrant/config/v2/loader.rb +++ b/lib/vagrant/config/v2/loader.rb @@ -70,7 +70,7 @@ module Vagrant new_keys = new_state["keys"] keys = {} old_keys.each do |key, old_value| - if new_keys.has_key?(key) + if new_keys.key?(key) # We need to do a merge, which we expect to be available # on the config class itself. keys[key] = old_value.merge(new_keys[key]) @@ -82,7 +82,7 @@ module Vagrant new_keys.each do |key, new_value| # Add in the keys that the new class has that we haven't merged. - if !keys.has_key?(key) + if !keys.key?(key) keys[key] = new_value.dup end end diff --git a/lib/vagrant/config/v2/root.rb b/lib/vagrant/config/v2/root.rb index f64129dad..f4a18c10b 100644 --- a/lib/vagrant/config/v2/root.rb +++ b/lib/vagrant/config/v2/root.rb @@ -22,7 +22,7 @@ module Vagrant # used for Vagrant and load the proper configuration classes for # each. def method_missing(name, *args) - return @keys[name] if @keys.has_key?(name) + return @keys[name] if @keys.key?(name) config_klass = @config_map[name.to_sym] if config_klass @@ -41,7 +41,7 @@ module Vagrant # mutate itself. def finalize! @config_map.each do |key, klass| - if !@keys.has_key?(key) + if !@keys.key?(key) @keys[key] = klass.new end end @@ -102,9 +102,9 @@ module Vagrant # This sets the internal state. This is used by the core to do some # merging logic and shouldn't be used by the general public. def __set_internal_state(state) - @config_map = state["config_map"] if state.has_key?("config_map") - @keys = state["keys"] if state.has_key?("keys") - @missing_key_calls = state["missing_key_calls"] if state.has_key?("missing_key_calls") + @config_map = state["config_map"] if state.key?("config_map") + @keys = state["keys"] if state.key?("keys") + @missing_key_calls = state["missing_key_calls"] if state.key?("missing_key_calls") end end end diff --git a/lib/vagrant/environment.rb b/lib/vagrant/environment.rb index acda0c178..b57092b03 100644 --- a/lib/vagrant/environment.rb +++ b/lib/vagrant/environment.rb @@ -80,7 +80,7 @@ module Vagrant }.merge(opts || {}) # Set the default working directory to look for the vagrantfile - opts[:cwd] ||= ENV["VAGRANT_CWD"] if ENV.has_key?("VAGRANT_CWD") + opts[:cwd] ||= ENV["VAGRANT_CWD"] if ENV.key?("VAGRANT_CWD") opts[:cwd] ||= Dir.pwd opts[:cwd] = Pathname.new(opts[:cwd]) if !opts[:cwd].directory? @@ -94,7 +94,7 @@ module Vagrant # Set the Vagrantfile name up. We append "Vagrantfile" and "vagrantfile" so that # those continue to work as well, but anything custom will take precedence. opts[:vagrantfile_name] ||= ENV["VAGRANT_VAGRANTFILE"] if \ - ENV.has_key?("VAGRANT_VAGRANTFILE") + ENV.key?("VAGRANT_VAGRANTFILE") opts[:vagrantfile_name] = [opts[:vagrantfile_name]] if \ opts[:vagrantfile_name] && !opts[:vagrantfile_name].is_a?(Array) @@ -307,7 +307,7 @@ module Vagrant # @return [Symbol] Name of the default provider. def default_provider(**opts) opts[:exclude] = Set.new(opts[:exclude]) if opts[:exclude] - opts[:force_default] = true if !opts.has_key?(:force_default) + opts[:force_default] = true if !opts.key?(:force_default) default = ENV["VAGRANT_DEFAULT_PROVIDER"] default = nil if default == "" @@ -351,15 +351,15 @@ module Vagrant # Skip providers that can't be defaulted, unless they're in our # config, in which case someone made our decision for us. - if !config.has_key?(key) - next if popts.has_key?(:defaultable) && !popts[:defaultable] + if !config.key?(key) + next if popts.key?(:defaultable) && !popts[:defaultable] end # The priority is higher if it is in our config. Otherwise, it is # the priority it set PLUS the length of the config to make sure it # is never higher than the configuration keys. priority = popts[:priority] - priority = config[key] + max_priority if config.has_key?(key) + priority = config[key] + max_priority if config.key?(key) ordered << [priority, key, impl, popts] end @@ -596,7 +596,7 @@ module Vagrant @machines.delete(cache_key) end - if @machines.has_key?(cache_key) + if @machines.key?(cache_key) @logger.info("Returning cached machine: #{name} (#{provider})") return @machines[cache_key] end diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index 07489e977..03ca19f07 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -150,12 +150,14 @@ module Vagrant # @param [Hash] extra_env This data will be passed into the action runner # as extra data set on the environment hash for the middleware # runner. - def action(name, **opts) + def action(name, opts=nil) @logger.info("Calling action: #{name} on provider #{@provider}") + opts ||= {} + # Determine whether we lock or not lock = true - lock = opts.delete(:lock) if opts.has_key?(:lock) + lock = opts.delete(:lock) if opts.key?(:lock) # Extra env keys are the remaining opts extra_env = opts.dup diff --git a/lib/vagrant/plugin/manager.rb b/lib/vagrant/plugin/manager.rb index 0cd71c8ba..dfaab2ecf 100644 --- a/lib/vagrant/plugin/manager.rb +++ b/lib/vagrant/plugin/manager.rb @@ -143,7 +143,7 @@ module Vagrant # If we already have a newer version in our list of installed, # then ignore it - next if installed_map.has_key?(spec.name) && + next if installed_map.key?(spec.name) && installed_map[spec.name].version >= spec.version installed_map[spec.name] = spec diff --git a/lib/vagrant/plugin/state_file.rb b/lib/vagrant/plugin/state_file.rb index 4a39a52bc..f41da1b86 100644 --- a/lib/vagrant/plugin/state_file.rb +++ b/lib/vagrant/plugin/state_file.rb @@ -61,7 +61,7 @@ module Vagrant # # @return [Boolean] def has_plugin?(name) - @data["installed"].has_key?(name) + @data["installed"].key?(name) end # Remove a plugin that is installed from the state file. diff --git a/lib/vagrant/plugin/v2/plugin.rb b/lib/vagrant/plugin/v2/plugin.rb index a39b3cf10..025032fd9 100644 --- a/lib/vagrant/plugin/v2/plugin.rb +++ b/lib/vagrant/plugin/v2/plugin.rb @@ -88,7 +88,7 @@ module Vagrant end # By default, the command is primary - opts[:primary] = true if !opts.has_key?(:primary) + opts[:primary] = true if !opts.key?(:primary) # Register the command components.commands.register(name.to_sym) do diff --git a/lib/vagrant/registry.rb b/lib/vagrant/registry.rb index f3c86edec..d84a745a5 100644 --- a/lib/vagrant/registry.rb +++ b/lib/vagrant/registry.rb @@ -22,8 +22,8 @@ module Vagrant # This will evaluate the block given to `register` and return the # resulting value. def get(key) - return nil if !@items.has_key?(key) - return @results_cache[key] if @results_cache.has_key?(key) + return nil if !@items.key?(key) + return @results_cache[key] if @results_cache.key?(key) @results_cache[key] = @items[key].call end alias :[] :get @@ -31,9 +31,10 @@ module Vagrant # Checks if the given key is registered with the registry. # # @return [Boolean] - def has_key?(key) - @items.has_key?(key) + def key?(key) + @items.key?(key) end + alias_method :has_key?, :key? # Returns an array populated with the keys of this object. # diff --git a/lib/vagrant/shared_helpers.rb b/lib/vagrant/shared_helpers.rb index b195c36df..12545ae4f 100644 --- a/lib/vagrant/shared_helpers.rb +++ b/lib/vagrant/shared_helpers.rb @@ -52,6 +52,13 @@ module Vagrant !!ENV["VAGRANT_I_KNOW_WHAT_IM_DOING_PLEASE_BE_QUIET"] end + # The current log level for Vagrant + # + # @return [String] + def self.log_level + ENV["VAGRANT_LOG"] + end + # Returns the URL prefix to the server. # # @return [String] diff --git a/lib/vagrant/ui.rb b/lib/vagrant/ui.rb index 4b47c3e1f..a84448a1c 100644 --- a/lib/vagrant/ui.rb +++ b/lib/vagrant/ui.rb @@ -136,9 +136,9 @@ module Vagrant # Setup the options so that the new line is suppressed opts ||= {} - opts[:echo] = true if !opts.has_key?(:echo) - opts[:new_line] = false if !opts.has_key?(:new_line) - opts[:prefix] = false if !opts.has_key?(:prefix) + opts[:echo] = true if !opts.key?(:echo) + opts[:new_line] = false if !opts.key?(:new_line) + opts[:prefix] = false if !opts.key?(:prefix) # Output the data say(:info, message, opts) @@ -249,7 +249,7 @@ module Vagrant class_eval <<-CODE def #{method}(message, *args, **opts) super(message) - if !@ui.opts.has_key?(:bold) && !opts.has_key?(:bold) + if !@ui.opts.key?(:bold) && !opts.key?(:bold) opts[:bold] = #{method.inspect} != :detail && \ #{method.inspect} != :ask end @@ -284,7 +284,7 @@ module Vagrant opts = self.opts.merge(opts) prefix = "" - if !opts.has_key?(:prefix) || opts[:prefix] + if !opts.key?(:prefix) || opts[:prefix] prefix = OUTPUT_PREFIX prefix = " " * OUTPUT_PREFIX.length if \ type == :detail || type == :ask || opts[:prefix_spaces] @@ -294,7 +294,7 @@ module Vagrant return message if prefix.empty? target = @prefix - target = opts[:target] if opts.has_key?(:target) + target = opts[:target] if opts.key?(:target) # Get the lines. The first default is because if the message # is an empty string, then we want to still use the empty string. diff --git a/lib/vagrant/util/env.rb b/lib/vagrant/util/env.rb index e7c23ccc6..3d3200f17 100644 --- a/lib/vagrant/util/env.rb +++ b/lib/vagrant/util/env.rb @@ -26,7 +26,7 @@ module Vagrant # @param [Proc] block # the block to execute with the cleaned environment # - def with_clean_env(&block) + def self.with_clean_env(&block) original = ENV.to_hash ENV.delete('_ORIGINAL_GEM_PATH') diff --git a/lib/vagrant/util/is_port_open.rb b/lib/vagrant/util/is_port_open.rb index e98dd4c24..63652ee28 100644 --- a/lib/vagrant/util/is_port_open.rb +++ b/lib/vagrant/util/is_port_open.rb @@ -29,7 +29,8 @@ module Vagrant # to connect. return true end - rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, Errno::ENETUNREACH + rescue Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTUNREACH, \ + Errno::ENETUNREACH, Errno::EACCES # Any of the above exceptions signal that the port is closed. return false end diff --git a/lib/vagrant/util/platform.rb b/lib/vagrant/util/platform.rb index d2b399616..c452eb295 100644 --- a/lib/vagrant/util/platform.rb +++ b/lib/vagrant/util/platform.rb @@ -148,7 +148,7 @@ module Vagrant # output. def terminal_supports_colors? if windows? - return true if ENV.has_key?("ANSICON") + return true if ENV.key?("ANSICON") return true if cygwin? return true if ENV["TERM"] == "cygwin" return false diff --git a/plugins/commands/destroy/command.rb b/plugins/commands/destroy/command.rb index e7a2f603f..141bfd38b 100644 --- a/plugins/commands/destroy/command.rb +++ b/plugins/commands/destroy/command.rb @@ -32,7 +32,7 @@ module VagrantPlugins :destroy, force_confirm_destroy: options[:force]) total += 1 - declined += 1 if action_env.has_key?(:force_confirm_destroy_result) && + declined += 1 if action_env.key?(:force_confirm_destroy_result) && action_env[:force_confirm_destroy_result] == false end diff --git a/plugins/commands/login/client.rb b/plugins/commands/login/client.rb index 1e8381fe4..63b01f335 100644 --- a/plugins/commands/login/client.rb +++ b/plugins/commands/login/client.rb @@ -7,11 +7,13 @@ module VagrantPlugins # # @param [Vagrant::Environment] env def initialize(env) - @env = env + @logger = Log4r::Logger.new("vagrant::login::client") + @env = env end # Removes the token, effectively logging the user out. def clear_token + @logger.info("Clearing token") token_path.delete if token_path.file? end @@ -38,6 +40,8 @@ module VagrantPlugins # @param [String] pass # @return [String] token The access token, or nil if auth failed. def login(user, pass) + @logger.info("Logging in '#{user}'") + with_error_handling do url = "#{Vagrant.server_url}/api/v1/authenticate" request = { "user" => { "login" => user, "password" => pass } } @@ -52,9 +56,12 @@ module VagrantPlugins # # @param [String] token def store_token(token) + @logger.info("Storing token in #{token_path}") + token_path.open("w") do |f| f.write(token) end + nil end @@ -65,13 +72,17 @@ module VagrantPlugins # @return [String] def token if ENV["ATLAS_TOKEN"] && !ENV["ATLAS_TOKEN"].empty? + @logger.debug("Using authentication token from environment variable") return ENV["ATLAS_TOKEN"] end if token_path.exist? + @logger.debug("Using authentication token from disk at #{token_path}") return token_path.read.strip end + @logger.debug("No authentication token in environment or #{token_path}") + nil end @@ -80,18 +91,21 @@ module VagrantPlugins def with_error_handling(&block) yield rescue RestClient::Unauthorized + @logger.debug("Unauthorized!") false rescue RestClient::NotAcceptable => e - begin - errors = JSON.parse(e.response)["errors"] - .map { |h| h["message"] } - .join("\n") + @logger.debug("Got unacceptable response:") + @logger.debug(e.message) + @logger.debug(e.backtrace.join("\n")) + begin + errors = JSON.parse(e.response)["errors"].join("\n") raise Errors::ServerError, errors: errors rescue JSON::ParserError; end raise "An unexpected error occurred: #{e.inspect}" rescue SocketError + @logger.info("Socket error") raise Errors::ServerUnreachable, url: Vagrant.server_url.to_s end diff --git a/plugins/commands/login/command.rb b/plugins/commands/login/command.rb index e16b1afaf..203b09009 100644 --- a/plugins/commands/login/command.rb +++ b/plugins/commands/login/command.rb @@ -18,6 +18,10 @@ module VagrantPlugins o.on("-k", "--logout", "Logs you out if you're logged in") do |k| options[:logout] = k end + + o.on("-t", "--token TOKEN", String, "Set the Atlas token") do |t| + options[:token] = t + end end # Parse the options @@ -31,6 +35,8 @@ module VagrantPlugins return execute_check elsif options[:logout] return execute_logout + elsif options[:token] + return execute_token(options[:token]) end # Let the user know what is going on. @@ -78,6 +84,19 @@ module VagrantPlugins @env.ui.success(I18n.t("login_command.logged_out")) return 0 end + + def execute_token(token) + @client.store_token(token) + @env.ui.success(I18n.t("login_command.token_saved")) + + if @client.logged_in? + @env.ui.success(I18n.t("login_command.check_logged_in")) + return 0 + else + @env.ui.error(I18n.t("login_command.invalid_token")) + return 1 + end + end end end end diff --git a/plugins/commands/login/locales/en.yml b/plugins/commands/login/locales/en.yml index 51020df1d..dba4d52d7 100644 --- a/plugins/commands/login/locales/en.yml +++ b/plugins/commands/login/locales/en.yml @@ -24,7 +24,11 @@ en: https://atlas.hashicorp.com. invalid_login: |- Invalid username or password. Please try again. + invalid_token: |- + Invalid token. Please try again. logged_in: |- You are now logged in. logged_out: |- You are logged out. + token_saved: |- + The token was successfully saved. diff --git a/plugins/commands/login/middleware/add_authentication.rb b/plugins/commands/login/middleware/add_authentication.rb index bfb7dd46b..faaa3cfe7 100644 --- a/plugins/commands/login/middleware/add_authentication.rb +++ b/plugins/commands/login/middleware/add_authentication.rb @@ -18,7 +18,17 @@ module VagrantPlugins env[:box_urls].map! do |url| u = URI.parse(url) - if u.host == server_uri.host + replace = u.host == server_uri.host + if !replace + # We need this in here for the transition we made from + # Vagrant Cloud to Atlas. This preserves access tokens + # appending to both without leaking access tokens to + # unsavory URLs. + replace = u.host == "vagrantcloud.com" && + server_uri.host == "atlas.hashicorp.com" + end + + if replace u.query ||= "" u.query += "&" if u.query != "" u.query += "access_token=#{token}" diff --git a/plugins/commands/plugin/action/plugin_exists_check.rb b/plugins/commands/plugin/action/plugin_exists_check.rb index 7a369976e..b7b7b9623 100644 --- a/plugins/commands/plugin/action/plugin_exists_check.rb +++ b/plugins/commands/plugin/action/plugin_exists_check.rb @@ -12,7 +12,7 @@ module VagrantPlugins def call(env) installed = Vagrant::Plugin::Manager.instance.installed_plugins - if !installed.has_key?(env[:plugin_name]) + if !installed.key?(env[:plugin_name]) raise Vagrant::Errors::PluginNotInstalled, name: env[:plugin_name] end diff --git a/plugins/commands/push/command.rb b/plugins/commands/push/command.rb index d04e296fb..902a0c946 100644 --- a/plugins/commands/push/command.rb +++ b/plugins/commands/push/command.rb @@ -19,6 +19,11 @@ module VagrantPlugins name = validate_pushes!(@env.pushes, argv[0]) + # Validate the configuration + @env.machine(@env.machine_names.first, @env.default_provider).action_raw( + :config_validate, + Vagrant::Action::Builtin::ConfigValidate) + @logger.debug("'push' environment with strategy: `#{name}'") @env.push(name) @@ -51,17 +56,19 @@ module VagrantPlugins if pushes.length == 1 return pushes.first.to_sym else - raise Vagrant::Errors::PushStrategyNotProvided, pushes: pushes + raise Vagrant::Errors::PushStrategyNotProvided, + pushes: pushes.map(&:to_s) end end + name = name.to_sym if !pushes.include?(name) raise Vagrant::Errors::PushStrategyNotDefined, - name: name, - pushes: pushes + name: name.to_s, + pushes: pushes.map(&:to_s) end - return name.to_sym + return name end end end diff --git a/plugins/commands/up/command.rb b/plugins/commands/up/command.rb index d7b3bd7dc..826bea0ae 100644 --- a/plugins/commands/up/command.rb +++ b/plugins/commands/up/command.rb @@ -60,8 +60,8 @@ module VagrantPlugins if names.empty? autostart = false @env.vagrantfile.machine_names_and_options.each do |n, o| - autostart = true if o.has_key?(:autostart) - o[:autostart] = true if !o.has_key?(:autostart) + autostart = true if o.key?(:autostart) + o[:autostart] = true if !o.key?(:autostart) names << n.to_s if o[:autostart] end diff --git a/plugins/commands/up/start_mixins.rb b/plugins/commands/up/start_mixins.rb index e0aeb6de2..548d889ca 100644 --- a/plugins/commands/up/start_mixins.rb +++ b/plugins/commands/up/start_mixins.rb @@ -19,6 +19,8 @@ module VagrantPlugins parser.on("--provision-with x,y,z", Array, "Enable only certain provisioners, by type.") do |list| options[:provision_types] = list.map { |type| type.to_sym } + options[:provision_enabled] = true + options[:provision_ignore_sentinel] = true end end diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index 35506e31e..64455042b 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -320,7 +320,7 @@ module VagrantPlugins raise Vagrant::Errors::SSHNotReady if ssh_info.nil? # Default some options - opts[:retries] = 5 if !opts.has_key?(:retries) + opts[:retries] = 5 if !opts.key?(:retries) # Build the options we'll use to initiate the connection via Net::SSH common_connect_opts = { diff --git a/plugins/communicators/winrm/command_filters/mkdir.rb b/plugins/communicators/winrm/command_filters/mkdir.rb old mode 100755 new mode 100644 diff --git a/plugins/communicators/winrm/communicator.rb b/plugins/communicators/winrm/communicator.rb index 4bd6e47d4..82587079d 100644 --- a/plugins/communicators/winrm/communicator.rb +++ b/plugins/communicators/winrm/communicator.rb @@ -79,12 +79,21 @@ module VagrantPlugins alias_method :sudo, :execute def test(command, opts=nil) - # If this is a *nix command with no Windows equivilant, assume failure + # If this is a *nix command (which we know about) with no Windows + # equivilant, assume failure command = @cmd_filter.filter(command) return false if command.empty? - opts = { error_check: false }.merge(opts || {}) - execute(command, opts) == 0 + opts = { + command: command, + elevated: false, + error_check: false, + }.merge(opts || {}) + + # If we're passed a *nix command which PS can't parse we get exit code + # 0, but output in stderr. We need to check both exit code and stderr. + output = shell.send(:powershell, command) + return output[:exitcode] == 0 && flatten_stderr(output).length == 0 end def upload(from, to) @@ -153,8 +162,8 @@ module VagrantPlugins def raise_execution_error(output, opts) # WinRM can return multiple stderr and stdout entries error_opts = opts.merge( - stdout: output[:data].collect { |e| e[:stdout] }.join, - stderr: output[:data].collect { |e| e[:stderr] }.join + stdout: flatten_stdout(output), + stderr: flatten_stderr(output) ) # Use a different error message key if the caller gave us one, @@ -164,6 +173,20 @@ module VagrantPlugins # Raise the error, use the type the caller gave us or the comm default raise opts[:error_class], error_opts end + + + # TODO: Replace with WinRM Output class when WinRM 1.3 is released + def flatten_stderr(output) + output[:data].map do | line | + line[:stderr] + end.compact.join + end + + def flatten_stdout(output) + output[:data].map do | line | + line[:flatten_stdout] + end.compact.join + end end #WinRM class end end diff --git a/plugins/communicators/winrm/shell.rb b/plugins/communicators/winrm/shell.rb index 1f9e6796c..0476465c7 100644 --- a/plugins/communicators/winrm/shell.rb +++ b/plugins/communicators/winrm/shell.rb @@ -91,7 +91,23 @@ module VagrantPlugins block.call(:stdout, out) if block_given? && out block.call(:stderr, err) if block_given? && err end + @logger.debug("Output: #{output.inspect}") + + # Verify that we didn't get a parser error, and if so we should + # set the exit code to 1. Parse errors return exit code 0 so we + # need to do this. + if output[:exitcode] == 0 + (output[:data] || []).each do |data| + next if !data[:stderr] + if data[:stderr].include?("ParserError") + @logger.warn("Detected ParserError, setting exit code to 1") + output[:exitcode] = 1 + break + end + end + end + return output end end diff --git a/plugins/guests/arch/cap/configure_networks.rb b/plugins/guests/arch/cap/configure_networks.rb index 3d69fee7c..fd06c24ea 100644 --- a/plugins/guests/arch/cap/configure_networks.rb +++ b/plugins/guests/arch/cap/configure_networks.rb @@ -11,20 +11,14 @@ module VagrantPlugins def self.configure_networks(machine, networks) interfaces = Array.new - machine.communicate.sudo("ip -o -0 addr | grep -v LOOPBACK | awk - '{print $2}' | sed 's/://'") do |_, result| + machine.communicate.sudo("ip -o -0 addr | grep -v LOOPBACK | awk '{print $2}' | sed 's/://'") do |_, result| interfaces = result.split("\n") end networks.each do |network| - # We use :device in the template instead of - # eth#{network[:interface]} in order to support Predictable - # Network Interfaces network[:device] = interfaces[network[:interface]] - entry = - TemplateRenderer.render("guests/arch/network_#{network[:type]}", - options: network) + entry = TemplateRenderer.render("guests/arch/network_#{network[:type]}", options: network) temp = Tempfile.new("vagrant") temp.binmode @@ -32,10 +26,8 @@ module VagrantPlugins temp.close machine.communicate.upload(temp.path, "/tmp/vagrant_network") - machine.communicate.sudo("mv /tmp/vagrant_network - /etc/netctl/#{network[:device]}") - machine.communicate.sudo("ip link set #{network[:device]} down && - netctl start #{network[:device]}") + machine.communicate.sudo("mv /tmp/vagrant_network /etc/netctl/#{network[:device]}") + machine.communicate.sudo("ip link set #{network[:device]} down && netctl start #{network[:device]}") end end end diff --git a/plugins/guests/darwin/cap/rsync.rb b/plugins/guests/darwin/cap/rsync.rb index e98d6e5ae..7e5d6d9a5 100644 --- a/plugins/guests/darwin/cap/rsync.rb +++ b/plugins/guests/darwin/cap/rsync.rb @@ -17,7 +17,7 @@ module VagrantPlugins end def self.rsync_post(machine, opts) - if opts.has_key?(:chown) && !opts[:chown] + if opts.key?(:chown) && !opts[:chown] return end diff --git a/plugins/guests/debian/cap/configure_networks.rb b/plugins/guests/debian/cap/configure_networks.rb index 49da980bf..3cb896b15 100644 --- a/plugins/guests/debian/cap/configure_networks.rb +++ b/plugins/guests/debian/cap/configure_networks.rb @@ -13,9 +13,8 @@ module VagrantPlugins machine.communicate.tap do |comm| # First, remove any previous network modifications # from the interface file. - comm.sudo("sed -e '/^#VAGRANT-BEGIN/,/^#VAGRANT-END/ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces") - comm.sudo("su -c 'cat /tmp/vagrant-network-interfaces > /etc/network/interfaces'") - comm.sudo("rm -f /tmp/vagrant-network-interfaces") + comm.sudo("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre") + comm.sudo("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tail -n +2 > /tmp/vagrant-network-interfaces.post") # Accumulate the configurations to add to the interfaces file as # well as what interfaces we're actually configuring since we use that @@ -47,8 +46,8 @@ module VagrantPlugins comm.sudo("/sbin/ip addr flush dev eth#{interface} 2> /dev/null") end - comm.sudo("cat /tmp/vagrant-network-entry >> /etc/network/interfaces") - comm.sudo("rm -f /tmp/vagrant-network-entry") + comm.sudo('cat /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post > /etc/network/interfaces') + comm.sudo('rm -f /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post') # Bring back up each network interface, reconfigured interfaces.each do |interface| diff --git a/plugins/guests/fedora/cap/configure_networks.rb b/plugins/guests/fedora/cap/configure_networks.rb index 549a99dff..2f67099cd 100644 --- a/plugins/guests/fedora/cap/configure_networks.rb +++ b/plugins/guests/fedora/cap/configure_networks.rb @@ -26,7 +26,7 @@ module VagrantPlugins end interface_names = networks.map do |network| - "eth#{network[:interface]}" + "#{interface_names[network[:interface]]}" end else machine.communicate.sudo("/usr/sbin/biosdevname -d | grep Kernel | cut -f2 -d: | sed -e 's/ //;'") do |_, result| diff --git a/plugins/guests/freebsd/cap/rsync.rb b/plugins/guests/freebsd/cap/rsync.rb index 2876b5943..c8fb36006 100644 --- a/plugins/guests/freebsd/cap/rsync.rb +++ b/plugins/guests/freebsd/cap/rsync.rb @@ -31,7 +31,7 @@ module VagrantPlugins end def self.rsync_post(machine, opts) - if opts.has_key?(:chown) && !opts[:chown] + if opts.key?(:chown) && !opts[:chown] return end diff --git a/plugins/guests/funtoo/cap/configure_networks.rb b/plugins/guests/funtoo/cap/configure_networks.rb index 466e3a57b..c52182b6f 100644 --- a/plugins/guests/funtoo/cap/configure_networks.rb +++ b/plugins/guests/funtoo/cap/configure_networks.rb @@ -28,7 +28,7 @@ module VagrantPlugins temp.binmode temp.write(entry) temp.close - comm.upload(temp.path, "/tmp/vagrant-network-entry-#{ifFile}") + comm.upload(temp.path, "/tmp/vagrant-#{ifFile}") comm.sudo("cp /tmp/vagrant-#{ifFile} /etc/conf.d/#{ifFile}") comm.sudo("chmod 0644 /etc/conf.d/#{ifFile}") comm.sudo("ln -fs /etc/init.d/netif.tmpl /etc/init.d/#{ifFile}") diff --git a/plugins/guests/linux/cap/rsync.rb b/plugins/guests/linux/cap/rsync.rb index 113b18dd0..424d20f46 100644 --- a/plugins/guests/linux/cap/rsync.rb +++ b/plugins/guests/linux/cap/rsync.rb @@ -17,7 +17,7 @@ module VagrantPlugins end def self.rsync_post(machine, opts) - if opts.has_key?(:chown) && !opts[:chown] + if opts.key?(:chown) && !opts[:chown] return end diff --git a/plugins/guests/solaris/cap/rsync.rb b/plugins/guests/solaris/cap/rsync.rb index d060a8020..0d0220f40 100644 --- a/plugins/guests/solaris/cap/rsync.rb +++ b/plugins/guests/solaris/cap/rsync.rb @@ -17,10 +17,10 @@ module VagrantPlugins end def self.rsync_post(machine, opts) - su_cmd = machine.config.solaris.su_cmd + suexec_cmd = machine.config.solaris.suexec_cmd machine.communicate.execute( - "#{su_cmd} find '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " + - "xargs -0 -r chown #{opts[:owner]}:#{opts[:group]}") + "#{suexec_cmd} find '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " + + "xargs -0 chown #{opts[:owner]}:#{opts[:group]}") end end end diff --git a/plugins/guests/solaris/config.rb b/plugins/guests/solaris/config.rb index e0a6a486b..5983b6837 100644 --- a/plugins/guests/solaris/config.rb +++ b/plugins/guests/solaris/config.rb @@ -3,24 +3,28 @@ module VagrantPlugins class Config < Vagrant.plugin("2", :config) attr_accessor :halt_timeout attr_accessor :halt_check_interval - # This sets the command to use to execute items as a superuser. sudo is default + attr_accessor :suexec_cmd attr_accessor :device def initialize @halt_timeout = UNSET_VALUE @halt_check_interval = UNSET_VALUE - @suexec_cmd = 'sudo' - @device = "e1000g" + @suexec_cmd = UNSET_VALUE + @device = UNSET_VALUE end def finalize! if @halt_timeout != UNSET_VALUE puts "solaris.halt_timeout is deprecated and will be removed in Vagrant 1.7" end + if @halt_check_interval != UNSET_VALUE puts "solaris.halt_check_interval is deprecated and will be removed in Vagrant 1.7" end + + @suexec_cmd = "sudo" if @suexec_cmd == UNSET_VALUE + @device = "e1000g" if @device == UNSET_VALUE end end end diff --git a/plugins/guests/solaris11/cap/rsync.rb b/plugins/guests/solaris11/cap/rsync.rb index 039602172..95df046c9 100644 --- a/plugins/guests/solaris11/cap/rsync.rb +++ b/plugins/guests/solaris11/cap/rsync.rb @@ -17,10 +17,10 @@ module VagrantPlugins end def self.rsync_post(machine, opts) - su_cmd = machine.config.solaris11.su_cmd + suexec_cmd = machine.config.solaris11.suexec_cmd machine.communicate.execute( - "#{su_cmd} '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " + - "xargs -0 -r chown #{opts[:owner]}:#{opts[:group]}") + "#{suexec_cmd} '#{opts[:guestpath]}' '(' ! -user #{opts[:owner]} -or ! -group #{opts[:group]} ')' -print0 | " + + "xargs -0 chown #{opts[:owner]}:#{opts[:group]}") end end end diff --git a/plugins/hosts/bsd/cap/nfs.rb b/plugins/hosts/bsd/cap/nfs.rb index 9fd1f7ef8..5d31c3cc1 100644 --- a/plugins/hosts/bsd/cap/nfs.rb +++ b/plugins/hosts/bsd/cap/nfs.rb @@ -137,7 +137,7 @@ module VagrantPlugins user = Process.uid File.read("/etc/exports").lines.each do |line| - if id = line[/^# VAGRANT-BEGIN:( #{user})? ([\.\/A-Za-z0-9\-_]+?)$/, 2] + if id = line[/^# VAGRANT-BEGIN:( #{user})? ([\.\/A-Za-z0-9\-_:]+?)$/, 2] if valid_ids.include?(id) logger.debug("Valid ID: #{id}") else diff --git a/plugins/hosts/linux/cap/nfs.rb b/plugins/hosts/linux/cap/nfs.rb index 189800db4..bf10aff9e 100644 --- a/plugins/hosts/linux/cap/nfs.rb +++ b/plugins/hosts/linux/cap/nfs.rb @@ -71,7 +71,7 @@ module VagrantPlugins user = Process.uid File.read("/etc/exports").lines.each do |line| - if id = line[/^# VAGRANT-BEGIN:( #{user})? ([\.\/A-Za-z0-9\-_]+?)$/, 2] + if id = line[/^# VAGRANT-BEGIN:( #{user})? ([\.\/A-Za-z0-9\-_:]+?)$/, 2] if valid_ids.include?(id) logger.debug("Valid ID: #{id}") else diff --git a/plugins/kernel_v2/config/push.rb b/plugins/kernel_v2/config/push.rb index e0137b29d..ccba3826d 100644 --- a/plugins/kernel_v2/config/push.rb +++ b/plugins/kernel_v2/config/push.rb @@ -21,18 +21,18 @@ module VagrantPlugins # Compile all the provider configurations @__defined_pushes.each do |name, tuples| - # Find the configuration class for this push - config_class = Vagrant.plugin("2").manager.push_configs[name] - config_class ||= Vagrant::Config::V2::DummyConfig - - # Load it up - config = config_class.new - # Capture the strategy so we can use it later. This will be used in # the block iteration for merging/overwriting strategy = name strategy = tuples[0][0] if tuples[0] + # Find the configuration class for this push + config_class = Vagrant.plugin("2").manager.push_configs[strategy] + config_class ||= Vagrant::Config::V2::DummyConfig + + # Load it up + config = config_class.new + begin tuples.each do |s, b| # Update the strategy if it has changed, reseting the current @@ -115,6 +115,22 @@ module VagrantPlugins end end + # Validate all pushes + def validate(machine) + errors = { "push" => _detected_errors } + + __compiled_pushes.each do |_, push| + config = push[1] + push_errors = config.validate(machine) + + if push_errors + errors = Vagrant::Config::V2::Util.merge_errors(errors, push_errors) + end + end + + errors + end + # This returns the list of compiled pushes as a hash by name. # # @return [Hash>] diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index fd08f436a..11947a30c 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -96,7 +96,7 @@ module VagrantPlugins end other_defined_vms.each do |key, subvm| - if !new_defined_vms.has_key?(key) + if !new_defined_vms.key?(key) new_defined_vms[key] = subvm.clone else new_defined_vms[key].config_procs.concat(subvm.config_procs) @@ -197,7 +197,7 @@ module VagrantPlugins options ||= {} options[:guestpath] = guestpath.to_s.gsub(/\/$/, '') options[:hostpath] = hostpath - options[:disabled] = false if !options.has_key?(:disabled) + options[:disabled] = false if !options.key?(:disabled) options = (@__synced_folders[options[:guestpath]] || {}). merge(options.dup) @@ -247,7 +247,7 @@ module VagrantPlugins id = "#{type}-#{id}" # Merge in the previous settings if we have them. - if @__networks.has_key?(id) + if @__networks.key?(id) options = @__networks[id][1].merge(options) end @@ -279,13 +279,13 @@ module VagrantPlugins def provision(name, **options, &block) type = name - if options.has_key?(:type) + if options.key?(:type) type = options.delete(:type) else name = nil end - if options.has_key?(:id) + if options.key?(:id) puts "Setting `id` on a provisioner is deprecated. Please use the" puts "new syntax of `config.vm.provision \"name\", type: \"type\"" puts "where \"name\" is the replacement for `id`. This will be" @@ -306,8 +306,8 @@ module VagrantPlugins end prov.preserve_order = !!options.delete(:preserve_order) if \ - options.has_key?(:preserve_order) - prov.run = options.delete(:run) if options.has_key?(:run) + options.key?(:preserve_order) + prov.run = options.delete(:run) if options.key?(:run) prov.add_config(options, &block) nil end diff --git a/plugins/providers/docker/action/host_machine_sync_folders.rb b/plugins/providers/docker/action/host_machine_sync_folders.rb index 2c10df337..9a6f03893 100644 --- a/plugins/providers/docker/action/host_machine_sync_folders.rb +++ b/plugins/providers/docker/action/host_machine_sync_folders.rb @@ -22,7 +22,7 @@ module VagrantPlugins def call(env) return @app.call(env) if !env[:machine].provider.host_vm? - if !env.has_key?(:host_machine_sync_folders) + if !env.key?(:host_machine_sync_folders) env[:host_machine_sync_folders] = true end @@ -115,7 +115,7 @@ module VagrantPlugins # Add this synced folder onto the new config if we haven't # already shared it before. - if !existing_ids.has_key?(id) + if !existing_ids.key?(id) # A bit of a hack for VirtualBox to mount our # folder as transient. This can be removed once # the VirtualBox synced folder mechanism is smarter. diff --git a/plugins/providers/docker/action/prepare_ssh.rb b/plugins/providers/docker/action/prepare_ssh.rb index 1a7298a66..450b139c6 100644 --- a/plugins/providers/docker/action/prepare_ssh.rb +++ b/plugins/providers/docker/action/prepare_ssh.rb @@ -19,14 +19,19 @@ module VagrantPlugins # Modify the SSH options for when we `vagrant ssh`... ssh_opts = env[:ssh_opts] || {} - # Build the command we'll execute within the host machine + # Build the command we'll execute within the Docker host machine: ssh_command = env[:machine].communicate.container_ssh_command if !Array(ssh_opts[:extra_args]).empty? ssh_command << " #{Array(ssh_opts[:extra_args]).join(" ")}" end + # Modify the SSH options for the original command: # Append "-t" to force a TTY allocation ssh_opts[:extra_args] = ["-t"] + # Enable Agent forwarding when requested for the target VM + if env[:machine].ssh_info[:forward_agent] + ssh_opts[:extra_args] << "-o ForwardAgent=yes" + end ssh_opts[:extra_args] << ssh_command # Set the opts diff --git a/plugins/providers/docker/communicator.rb b/plugins/providers/docker/communicator.rb index 657789575..fb6c9fe9e 100644 --- a/plugins/providers/docker/communicator.rb +++ b/plugins/providers/docker/communicator.rb @@ -137,18 +137,21 @@ module VagrantPlugins info[:port] ||= 22 # Make sure our private keys are synced over to the host VM - key_args = sync_private_keys(info).map do |path| + ssh_args = sync_private_keys(info).map do |path| "-i #{path}" - end.join(" ") + end + + # Use ad-hoc SSH options for the hop on the docker proxy + if info[:forward_agent] + ssh_args << "-o ForwardAgent=yes" + end + ssh_args.concat(["-o Compression=yes", + "-o ConnectTimeout=5", + "-o StrictHostKeyChecking=no", + "-o UserKnownHostsFile=/dev/null"]) # Build the SSH command - "ssh #{key_args} " + - "-o Compression=yes " + - "-o ConnectTimeout=5 " + - "-o StrictHostKeyChecking=no " + - "-o UserKnownHostsFile=/dev/null " + - "-p#{info[:port]} " + - "#{info[:username]}@#{info[:host]}" + "ssh #{info[:username]}@#{info[:host]} -p#{info[:port]} #{ssh_args.join(" ")}" end protected diff --git a/plugins/providers/docker/hostmachine/Vagrantfile b/plugins/providers/docker/hostmachine/Vagrantfile index 752ba888d..79cd59f8c 100644 --- a/plugins/providers/docker/hostmachine/Vagrantfile +++ b/plugins/providers/docker/hostmachine/Vagrantfile @@ -18,4 +18,9 @@ Vagrant.configure("2") do |config| # b2d doesn't support NFS config.nfs.functional = false + + # b2d doesn't persist filesystem between reboots + if config.ssh.respond_to?(:insert_key) + config.ssh.insert_key = false + end end diff --git a/plugins/providers/hyperv/action/import.rb b/plugins/providers/hyperv/action/import.rb index 0687503af..468a55c57 100644 --- a/plugins/providers/hyperv/action/import.rb +++ b/plugins/providers/hyperv/action/import.rb @@ -14,6 +14,15 @@ module VagrantPlugins def call(env) vm_dir = env[:machine].box.directory.join("Virtual Machines") hd_dir = env[:machine].box.directory.join("Virtual Hard Disks") + memory = env[:machine].provider_config.memory + maxmemory = env[:machine].provider_config.maxmemory + cpus = env[:machine].provider_config.cpus + vmname = env[:machine].provider_config.vmname + + env[:ui].output("Configured Dynamical memory allocation, maxmemory is #{maxmemory}") if maxmemory + env[:ui].output("Configured startup memory is #{memory}") if memory + env[:ui].output("Configured cpus number is #{cpus}") if cpus + env[:ui].output("Configured vmname is #{vmname}") if vmname if !vm_dir.directory? || !hd_dir.directory? raise Errors::BoxInvalid @@ -78,6 +87,10 @@ module VagrantPlugins image_path: image_path.to_s.gsub("/", "\\") } options[:switchname] = switch if switch + options[:memory] = memory if memory + options[:maxmemory] = maxmemory if maxmemory + options[:cpus] = cpus if cpus + options[:vmname] = vmname if vmname env[:ui].detail("Creating and registering the VM...") server = env[:machine].provider.driver.import(options) diff --git a/plugins/providers/hyperv/config.rb b/plugins/providers/hyperv/config.rb index ad69e3059..89b51c0a6 100644 --- a/plugins/providers/hyperv/config.rb +++ b/plugins/providers/hyperv/config.rb @@ -8,15 +8,27 @@ module VagrantPlugins # # @return [Integer] attr_accessor :ip_address_timeout + attr_accessor :memory + attr_accessor :maxmemory + attr_accessor :cpus + attr_accessor :vmname def initialize @ip_address_timeout = UNSET_VALUE + @memory = UNSET_VALUE + @maxmemory = UNSET_VALUE + @cpus = UNSET_VALUE + @vmname = UNSET_VALUE end def finalize! if @ip_address_timeout == UNSET_VALUE @ip_address_timeout = 120 end + @memory = nil if @memory == UNSET_VALUE + @maxmemory = nil if @maxmemory == UNSET_VALUE + @cpus = nil if @cpus == UNSET_VALUE + @vmname = nil if @vmname == UNSET_VALUE end def validate(machine) diff --git a/plugins/providers/hyperv/scripts/import_vm.ps1 b/plugins/providers/hyperv/scripts/import_vm.ps1 index 0b1d74a7e..5aea63875 100644 --- a/plugins/providers/hyperv/scripts/import_vm.ps1 +++ b/plugins/providers/hyperv/scripts/import_vm.ps1 @@ -4,7 +4,11 @@ Param( [Parameter(Mandatory=$true)] [string]$image_path, - [string]$switchname=$null + [string]$switchname=$null, + [string]$memory=$null, + [string]$maxmemory=$null, + [string]$cpus=$null, + [string]$vmname=$null ) # Include the following modules @@ -13,10 +17,22 @@ $Dir = Split-Path $script:MyInvocation.MyCommand.Path [xml]$vmconfig = Get-Content -Path $vm_xml_config -$vm_name = $vmconfig.configuration.properties.name.'#text' -$processors = $vmconfig.configuration.settings.processors.count.'#text' $generation = [int]($vmconfig.configuration.properties.subtype.'#text')+1 +if (!$vmname) { + # Get the name of the vm + $vm_name = $vmconfig.configuration.properties.name.'#text' +}else { + $vm_name = $vmname +} + +if (!$cpus) { + # Get the name of the vm + $processors = $vmconfig.configuration.settings.processors.count.'#text' +}else { + $processors = $cpus +} + function GetUniqueName($name) { Get-VM | ForEach-Object -Process { if ($name -eq $_.Name) { @@ -31,18 +47,34 @@ do { $vm_name = GetUniqueName $name } while ($vm_name -ne $name) -$memory = (Select-Xml -xml $vmconfig -XPath "//memory").node.Bank -if ($memory.dynamic_memory_enabled."#text" -eq "True") { - $dynamicmemory = $True +if (!$memory) { + $xmlmemory = (Select-Xml -xml $vmconfig -XPath "//memory").node.Bank + if ($xmlmemory.dynamic_memory_enabled."#text" -eq "True") { + $dynamicmemory = $True + } + else { + $dynamicmemory = $False + } + # Memory values need to be in bytes + $MemoryMaximumBytes = ($xmlmemory.limit."#text" -as [int]) * 1MB + $MemoryStartupBytes = ($xmlmemory.size."#text" -as [int]) * 1MB + $MemoryMinimumBytes = ($xmlmemory.reservation."#text" -as [int]) * 1MB } else { - $dynamicmemory = $False + 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 + } } -# Memory values need to be in bytes -$MemoryMaximumBytes = ($memory.limit."#text" -as [int]) * 1MB -$MemoryStartupBytes = ($memory.size."#text" -as [int]) * 1MB -$MemoryMinimumBytes = ($memory.reservation."#text" -as [int]) * 1MB if (!$switchname) { # Get the name of the virtual switch diff --git a/plugins/providers/hyperv/scripts/start_vm.ps1 b/plugins/providers/hyperv/scripts/start_vm.ps1 index 937ce75ed..54025c9a4 100644 --- a/plugins/providers/hyperv/scripts/start_vm.ps1 +++ b/plugins/providers/hyperv/scripts/start_vm.ps1 @@ -10,7 +10,7 @@ forEach ($module in $modules) { . $module } try { $vm = Get-VM -Id $VmId -ErrorAction "stop" - Start-VM $vm + Start-VM $vm -ErrorAction "stop" $state = $vm.state $status = $vm.status $name = $vm.name @@ -24,4 +24,4 @@ try { } catch { Write-Error-Message "Failed to start a VM $_" -} +} \ No newline at end of file diff --git a/plugins/providers/virtualbox/action/prepare_nfs_settings.rb b/plugins/providers/virtualbox/action/prepare_nfs_settings.rb index c5f95af1f..d3edf3e93 100644 --- a/plugins/providers/virtualbox/action/prepare_nfs_settings.rb +++ b/plugins/providers/virtualbox/action/prepare_nfs_settings.rb @@ -24,7 +24,7 @@ module VagrantPlugins } folders = synced_folders(env[:machine], **opts) - if folders.has_key?(:nfs) + if folders.key?(:nfs) @logger.info("Using NFS, preparing NFS settings by reading host IP and machine IP") add_ips_to_env!(env) end diff --git a/plugins/providers/virtualbox/action/set_name.rb b/plugins/providers/virtualbox/action/set_name.rb index 3cbcf131a..0e80f4591 100644 --- a/plugins/providers/virtualbox/action/set_name.rb +++ b/plugins/providers/virtualbox/action/set_name.rb @@ -32,9 +32,9 @@ module VagrantPlugins # Verify the name is not taken vms = env[:machine].provider.driver.read_vms raise Vagrant::Errors::VMNameExists, name: name if \ - vms.has_key?(name) && vms[name] != env[:machine].id + vms.key?(name) && vms[name] != env[:machine].id - if vms.has_key?(name) + if vms.key?(name) @logger.info("Not setting the name because our name is already set.") else env[:ui].info(I18n.t( diff --git a/plugins/providers/virtualbox/config.rb b/plugins/providers/virtualbox/config.rb index aed1c692c..5bb1e754b 100644 --- a/plugins/providers/virtualbox/config.rb +++ b/plugins/providers/virtualbox/config.rb @@ -143,7 +143,7 @@ module VagrantPlugins def validate(machine) errors = _detected_errors - valid_events = ["pre-import", "pre-boot", "post-boot"] + valid_events = ["pre-import", "pre-boot", "post-boot", "post-comm"] @customizations.each do |event, _| if !valid_events.include?(event) errors << I18n.t( diff --git a/plugins/providers/virtualbox/driver/base.rb b/plugins/providers/virtualbox/driver/base.rb index 3002418f7..da019eae8 100644 --- a/plugins/providers/virtualbox/driver/base.rb +++ b/plugins/providers/virtualbox/driver/base.rb @@ -30,8 +30,8 @@ module VagrantPlugins # On Windows, we use the VBOX_INSTALL_PATH environmental # variable to find VBoxManage. - if ENV.has_key?("VBOX_INSTALL_PATH") || - ENV.has_key?("VBOX_MSI_INSTALL_PATH") + if ENV.key?("VBOX_INSTALL_PATH") || + ENV.key?("VBOX_MSI_INSTALL_PATH") # Get the path. path = ENV["VBOX_INSTALL_PATH"] || ENV["VBOX_MSI_INSTALL_PATH"] @logger.debug("VBOX_INSTALL_PATH value: #{path}") diff --git a/plugins/providers/virtualbox/driver/version_4_0.rb b/plugins/providers/virtualbox/driver/version_4_0.rb index 04070b559..a29193842 100644 --- a/plugins/providers/virtualbox/driver/version_4_0.rb +++ b/plugins/providers/virtualbox/driver/version_4_0.rb @@ -445,7 +445,7 @@ module VagrantPlugins folder[:name], "--hostpath", folder[:hostpath]] - args << "--transient" if folder.has_key?(:transient) && folder[:transient] + args << "--transient" if folder.key?(:transient) && folder[:transient] execute("sharedfolder", "add", @uuid, *args) end end diff --git a/plugins/providers/virtualbox/driver/version_4_1.rb b/plugins/providers/virtualbox/driver/version_4_1.rb index b3fd44978..c22042b6b 100644 --- a/plugins/providers/virtualbox/driver/version_4_1.rb +++ b/plugins/providers/virtualbox/driver/version_4_1.rb @@ -450,13 +450,13 @@ module VagrantPlugins folder[:name], "--hostpath", folder[:hostpath]] - args << "--transient" if folder.has_key?(:transient) && folder[:transient] - - # Add the shared folder - execute("sharedfolder", "add", @uuid, *args) + args << "--transient" if folder.key?(:transient) && folder[:transient] # Enable symlinks on the shared folder execute("setextradata", @uuid, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{folder[:name]}", "1") + + # Add the shared folder + execute("sharedfolder", "add", @uuid, *args) end end diff --git a/plugins/providers/virtualbox/driver/version_4_2.rb b/plugins/providers/virtualbox/driver/version_4_2.rb index 765855e77..d976d973c 100644 --- a/plugins/providers/virtualbox/driver/version_4_2.rb +++ b/plugins/providers/virtualbox/driver/version_4_2.rb @@ -189,9 +189,9 @@ module VagrantPlugins # we use the block form of sub here to ensure that if the specified_name happens to end with a number (which is fairly likely) then # we won't end up having the character sequence of a \ followed by a number be interpreted as a back reference. For example, if # specified_name were "abc123", then "\\abc123\\".reverse would be "\\321cba\\", and the \3 would be treated as a back reference by the sub - disk_params << path.reverse.sub("\\#{suggested_name}\\".reverse) { "\\#{specified_name}\\".reverse }.reverse # Replace only last occurrence + disk_params << path.reverse.sub("\\#{suggested_name}\\".reverse) { "\\#{specified_name}\\".reverse }.reverse # Replace only last occurrence else - disk_params << path.reverse.sub("/#{suggested_name}/".reverse, "/#{specified_name}/".reverse).reverse # Replace only last occurrence + disk_params << path.reverse.sub("/#{suggested_name}/".reverse, "/#{specified_name}/".reverse).reverse # Replace only last occurrence end end @@ -481,13 +481,13 @@ module VagrantPlugins folder[:name], "--hostpath", folder[:hostpath]] - args << "--transient" if folder.has_key?(:transient) && folder[:transient] - - # Add the shared folder - execute("sharedfolder", "add", @uuid, *args) + args << "--transient" if folder.key?(:transient) && folder[:transient] # Enable symlinks on the shared folder execute("setextradata", @uuid, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{folder[:name]}", "1") + + # Add the shared folder + execute("sharedfolder", "add", @uuid, *args) end end diff --git a/plugins/providers/virtualbox/driver/version_4_3.rb b/plugins/providers/virtualbox/driver/version_4_3.rb index ad3cc4cd9..28e6539d4 100644 --- a/plugins/providers/virtualbox/driver/version_4_3.rb +++ b/plugins/providers/virtualbox/driver/version_4_3.rb @@ -498,13 +498,13 @@ module VagrantPlugins folder[:name], "--hostpath", folder[:hostpath]] - args << "--transient" if folder.has_key?(:transient) && folder[:transient] - - # Add the shared folder - execute("sharedfolder", "add", @uuid, *args) + args << "--transient" if folder.key?(:transient) && folder[:transient] # Enable symlinks on the shared folder execute("setextradata", @uuid, "VBoxInternal2/SharedFoldersEnableSymlinksCreate/#{folder[:name]}", "1") + + # Add the shared folder + execute("sharedfolder", "add", @uuid, *args) end end diff --git a/plugins/providers/virtualbox/model/forwarded_port.rb b/plugins/providers/virtualbox/model/forwarded_port.rb index 2229519f7..03107408e 100644 --- a/plugins/providers/virtualbox/model/forwarded_port.rb +++ b/plugins/providers/virtualbox/model/forwarded_port.rb @@ -51,7 +51,7 @@ module VagrantPlugins options ||= {} @auto_correct = false - @auto_correct = options[:auto_correct] if options.has_key?(:auto_correct) + @auto_correct = options[:auto_correct] if options.key?(:auto_correct) @adapter = (options[:adapter] || 1).to_i @guest_ip = options[:guest_ip] || nil @host_ip = options[:host_ip] || nil diff --git a/plugins/provisioners/ansible/provisioner.rb b/plugins/provisioners/ansible/provisioner.rb index 49015997b..9e2cb155b 100644 --- a/plugins/provisioners/ansible/provisioner.rb +++ b/plugins/provisioners/ansible/provisioner.rb @@ -1,3 +1,5 @@ +require "vagrant/util/platform" + module VagrantPlugins module Ansible class Provisioner < Vagrant.plugin("2", :provisioner) @@ -23,6 +25,12 @@ module VagrantPlugins # but can be enabled via raw_arguments option. options << "--connection=ssh" + # Increase the SSH connection timeout, as the Ansible default value (10 seconds) + # is a bit demanding for some overloaded developer boxes. This is particularly + # helpful when additional virtual networks are configured, as their availability + # is not controlled during vagrant boot process. + options << "--timeout=30" + # By default we limit by the current machine, but # this can be overridden by the `limit` option. if config.limit @@ -188,9 +196,33 @@ module VagrantPlugins def get_ansible_ssh_args ssh_options = [] + # Use an SSH ProxyCommand when using the Docker provider with the intermediate host + if @machine.provider_name == :docker && machine.provider.host_vm? + docker_host_ssh_info = machine.provider.host_vm.ssh_info + + proxy_cmd = "ssh #{docker_host_ssh_info[:username]}@#{docker_host_ssh_info[:host]}" + + " -p #{docker_host_ssh_info[:port]} -i #{docker_host_ssh_info[:private_key_path][0]}" + + # Use same options than plugins/providers/docker/communicator.rb + # Note: this could be improved (DRY'ed) by sharing these settings. + proxy_cmd += " -o Compression=yes -o ConnectTimeout=5 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + + proxy_cmd += " -o ForwardAgent=yes" if @ssh_info[:forward_agent] + + proxy_cmd += " exec nc %h %p 2>/dev/null" + + ssh_options << "-o ProxyCommand='#{ proxy_cmd }'" + end + # Don't access user's known_hosts file, except when host_key_checking is enabled. ssh_options << "-o UserKnownHostsFile=/dev/null" unless config.host_key_checking + # Set IdentitiesOnly=yes to avoid authentication errors when the host has more than 5 ssh keys. + # Notes: + # - Solaris/OpenSolaris/Illumos uses SunSSH which doesn't support the IdentitiesOnly option. + # - this could be improved by sharing logic with lib/vagrant/util/ssh.rb + ssh_options << "-o IdentitiesOnly=yes" unless Vagrant::Util::Platform.solaris? + # Multiple Private Keys @ssh_info[:private_key_path].drop(1).each do |key| ssh_options << "-o IdentityFile=#{key}" diff --git a/plugins/provisioners/chef/cap/debian/chef_install.rb b/plugins/provisioners/chef/cap/debian/chef_install.rb index 5bb5f6acb..3d9302d80 100644 --- a/plugins/provisioners/chef/cap/debian/chef_install.rb +++ b/plugins/provisioners/chef/cap/debian/chef_install.rb @@ -5,11 +5,11 @@ module VagrantPlugins module Cap module Debian module ChefInstall - def self.chef_install(machine, version, prerelease) + def self.chef_install(machine, version, prerelease, download_path) machine.communicate.sudo("apt-get update -y -qq") machine.communicate.sudo("apt-get install -y -qq curl") - command = Omnibus.build_command(version, prerelease) + command = Omnibus.build_command(version, prerelease, download_path) machine.communicate.sudo(command) end end diff --git a/plugins/provisioners/chef/cap/omnios/chef_install.rb b/plugins/provisioners/chef/cap/omnios/chef_install.rb new file mode 100644 index 000000000..b20332638 --- /dev/null +++ b/plugins/provisioners/chef/cap/omnios/chef_install.rb @@ -0,0 +1,20 @@ +require_relative "../../omnibus" + +module VagrantPlugins + module Chef + module Cap + module OmniOS + module ChefInstall + def self.chef_install(machine, version, prerelease, download_path) + su_cmd = machine.config.solaris.suexec_cmd + + machine.communicate.execute("#{su_cmd} pkg list --no-refresh web/curl > /dev/null 2>&1 || pkg install -q --accept web/curl") + + command = VagrantPlugins::Chef::Omnibus.build_command(version, prerelease, download_path) + machine.communicate.execute(su_cmd + ' ' + command) + end + end + end + end + end +end diff --git a/plugins/provisioners/chef/cap/omnios/chef_installed.rb b/plugins/provisioners/chef/cap/omnios/chef_installed.rb new file mode 100644 index 000000000..2345d3b6a --- /dev/null +++ b/plugins/provisioners/chef/cap/omnios/chef_installed.rb @@ -0,0 +1,23 @@ +module VagrantPlugins + module Chef + module Cap + module OmniOS + module ChefInstalled + # TODO: this is the same code as cap/linux/chef_installed, consider merging + # Check if Chef is installed at the given version. + # @return [true, false] + def self.chef_installed(machine, version) + knife = "/opt/chef/bin/knife" + command = "test -x #{knife}" + + if version != :latest + command << "&& #{knife} --version | grep 'Chef: #{version}'" + end + + machine.communicate.test(command, sudo: true) + end + end + end + end + end +end diff --git a/plugins/provisioners/chef/cap/redhat/chef_install.rb b/plugins/provisioners/chef/cap/redhat/chef_install.rb index 49db9bf9c..c6aff7bad 100644 --- a/plugins/provisioners/chef/cap/redhat/chef_install.rb +++ b/plugins/provisioners/chef/cap/redhat/chef_install.rb @@ -5,10 +5,10 @@ module VagrantPlugins module Cap module Redhat module ChefInstall - def self.chef_install(machine, version, prerelease) + def self.chef_install(machine, version, prerelease, download_path) machine.communicate.sudo("yum install -y -q curl") - command = Omnibus.build_command(version, prerelease) + command = Omnibus.build_command(version, prerelease, download_path) machine.communicate.sudo(command) end end diff --git a/plugins/provisioners/chef/config/base.rb b/plugins/provisioners/chef/config/base.rb index 37124ad3f..370736fd6 100644 --- a/plugins/provisioners/chef/config/base.rb +++ b/plugins/provisioners/chef/config/base.rb @@ -1,11 +1,7 @@ -require "vagrant/util/counter" - module VagrantPlugins module Chef module Config class Base < Vagrant.plugin("2", :config) - extend Vagrant::Util::Counter - # The path to Chef's bin/ directory. # @return [String] attr_accessor :binary_path @@ -48,6 +44,14 @@ module VagrantPlugins # @return [String] attr_accessor :version + # The path where the Chef installer will be downloaded to. Only valid if + # install is true or "force". It defaults to nil, which means that the + # omnibus installer will choose the destination and you have no control + # over it. + # + # @return [String] + attr_accessor :installer_download_path + def initialize super @@ -57,6 +61,7 @@ module VagrantPlugins @log_level = UNSET_VALUE @prerelease = UNSET_VALUE @version = UNSET_VALUE + @installer_download_path = UNSET_VALUE end def finalize! @@ -66,6 +71,7 @@ module VagrantPlugins @log_level = :info if @log_level == UNSET_VALUE @prerelease = false if @prerelease == UNSET_VALUE @version = :latest if @version == UNSET_VALUE + @installer_download_path = nil if @installer_download_path == UNSET_VALUE # Make sure the install is a symbol if it's not a boolean if @install.respond_to?(:to_sym) diff --git a/plugins/provisioners/chef/config/base_runner.rb b/plugins/provisioners/chef/config/base_runner.rb index 334c9b739..12ac0aabd 100644 --- a/plugins/provisioners/chef/config/base_runner.rb +++ b/plugins/provisioners/chef/config/base_runner.rb @@ -81,7 +81,7 @@ module VagrantPlugins @https_proxy_pass = nil if @https_proxy_pass == UNSET_VALUE @no_proxy = nil if @no_proxy == UNSET_VALUE @node_name = nil if @node_name == UNSET_VALUE - @provisioning_path = nil if @provisioning_path == UNSET_VALUE + @provisioning_path = "/tmp/vagrant-chef" if @provisioning_path == UNSET_VALUE @file_backup_path = "/var/chef/backup" if @file_backup_path == UNSET_VALUE @file_cache_path = "/var/chef/cache" if @file_cache_path == UNSET_VALUE @verbose_logging = false if @verbose_logging == UNSET_VALUE @@ -89,12 +89,6 @@ module VagrantPlugins if @encrypted_data_bag_secret_key_path == UNSET_VALUE @encrypted_data_bag_secret_key_path = nil end - - # Set the default provisioning path to be a unique path in /tmp - if !@provisioning_path - counter = self.class.get_and_update_counter(:chef_config) - @provisioning_path = "/tmp/vagrant-chef-#{counter}" - end end def merge(other) diff --git a/plugins/provisioners/chef/config/chef_apply.rb b/plugins/provisioners/chef/config/chef_apply.rb index 9f313b790..8f7081875 100644 --- a/plugins/provisioners/chef/config/chef_apply.rb +++ b/plugins/provisioners/chef/config/chef_apply.rb @@ -24,11 +24,7 @@ module VagrantPlugins super @recipe = nil if @recipe == UNSET_VALUE - - if @upload_path == UNSET_VALUE - counter = self.class.get_and_update_counter(:chef_apply) - @upload_path = "/tmp/vagrant-chef-apply-#{counter}" - end + @upload_path = "/tmp/vagrant-chef-apply" if @upload_path == UNSET_VALUE end def validate(machine) diff --git a/plugins/provisioners/chef/installer.rb b/plugins/provisioners/chef/installer.rb index e8b08f10d..16467111c 100644 --- a/plugins/provisioners/chef/installer.rb +++ b/plugins/provisioners/chef/installer.rb @@ -6,6 +6,7 @@ module VagrantPlugins @version = options.fetch(:version, :latest) @prerelease = options.fetch(:prerelease, :latest) @force = options.fetch(:force, false) + @download_path = options.fetch(:download_path, nil) end # This handles verifying the Chef installation, installing it if it was @@ -27,7 +28,7 @@ module VagrantPlugins @machine.ui.detail(I18n.t("vagrant.chef_installing", version: @version.to_s)) - @machine.guest.capability(:chef_install, @version, @prerelease) + @machine.guest.capability(:chef_install, @version, @prerelease, @download_path) if !@machine.guest.capability(:chef_installed, @version) raise Provisioner::Base::ChefError, :install_failed diff --git a/plugins/provisioners/chef/omnibus.rb b/plugins/provisioners/chef/omnibus.rb index db62b4fdc..5c2eef2fb 100644 --- a/plugins/provisioners/chef/omnibus.rb +++ b/plugins/provisioners/chef/omnibus.rb @@ -1,14 +1,14 @@ module VagrantPlugins module Chef module Omnibus - OMNITRUCK = "https://www.getchef.com/chef/install.sh".freeze + OMNITRUCK = "https://www.chef.io/chef/install.sh".freeze # Read more about the Omnibus installer here: # https://docs.getchef.com/install_omnibus.html - def build_command(version, prerelease = false) + def build_command(version, prerelease = false, download_path = nil) command = "curl -sL #{OMNITRUCK} | sudo bash" - if prerelease || version != :latest + if prerelease || version != :latest || download_path != nil command << " -s --" end @@ -20,6 +20,10 @@ module VagrantPlugins command << " -v \"#{version}\"" end + if download_path + command << " -d \"#{download_path}\"" + end + command end module_function :build_command diff --git a/plugins/provisioners/chef/plugin.rb b/plugins/provisioners/chef/plugin.rb index b2fb5cef5..5a1b2876f 100644 --- a/plugins/provisioners/chef/plugin.rb +++ b/plugins/provisioners/chef/plugin.rb @@ -10,7 +10,7 @@ module VagrantPlugins name "chef" description <<-DESC Provides support for provisioning your virtual machines with - Chef via `chef-solo`, `chef-client`, or `chef-apply`. + Chef via `chef-solo`, `chef-client`, `chef-zero` or `chef-apply`. DESC config(:chef_apply, :provisioner) do @@ -67,6 +67,17 @@ module VagrantPlugins require_relative "cap/redhat/chef_install" Cap::Redhat::ChefInstall end + + guest_capability(:omnios, :chef_installed) do + require_relative "cap/omnios/chef_installed" + Cap::OmniOS::ChefInstalled + end + + guest_capability(:omnios, :chef_install) do + require_relative "cap/omnios/chef_install" + Cap::OmniOS::ChefInstall + end + end end end diff --git a/plugins/provisioners/chef/provisioner/base.rb b/plugins/provisioners/chef/provisioner/base.rb index 81f8c6e48..f623bb498 100644 --- a/plugins/provisioners/chef/provisioner/base.rb +++ b/plugins/provisioners/chef/provisioner/base.rb @@ -29,6 +29,7 @@ module VagrantPlugins force: config.install == :force, version: config.version, prerelease: config.prerelease, + download_path: config.installer_download_path ) installer.ensure_installed end diff --git a/plugins/provisioners/chef/provisioner/chef_apply.rb b/plugins/provisioners/chef/provisioner/chef_apply.rb index ed857c3b3..1ff4790b6 100644 --- a/plugins/provisioners/chef/provisioner/chef_apply.rb +++ b/plugins/provisioners/chef/provisioner/chef_apply.rb @@ -1,3 +1,4 @@ +require "digest/md5" require "tempfile" require_relative "base" @@ -42,7 +43,8 @@ module VagrantPlugins # The destination (on the guest) where the recipe will live # @return [String] def target_recipe_path - File.join(config.upload_path, "recipe.rb") + key = Digest::MD5.hexdigest(config.recipe) + File.join(config.upload_path, "recipe-#{key}.rb") end # Write the raw recipe contents to a tempfile and upload that to the diff --git a/plugins/provisioners/chef/provisioner/chef_solo.rb b/plugins/provisioners/chef/provisioner/chef_solo.rb index d05794f18..18bdc9e1d 100644 --- a/plugins/provisioners/chef/provisioner/chef_solo.rb +++ b/plugins/provisioners/chef/provisioner/chef_solo.rb @@ -1,3 +1,7 @@ +require "digest/md5" +require "securerandom" +require "set" + require "log4r" require "vagrant/util/counter" @@ -11,6 +15,8 @@ module VagrantPlugins class ChefSolo < Base extend Vagrant::Util::Counter include Vagrant::Util::Counter + include Vagrant::Action::Builtin::MixinSyncedFolders + attr_reader :environments_folders attr_reader :cookbook_folders attr_reader :role_folders @@ -28,13 +34,14 @@ module VagrantPlugins @data_bags_folders = expanded_folders(@config.data_bags_path, "data_bags") @environments_folders = expanded_folders(@config.environments_path, "environments") - share_folders(root_config, "csc", @cookbook_folders) - share_folders(root_config, "csr", @role_folders) - share_folders(root_config, "csdb", @data_bags_folders) - share_folders(root_config, "cse", @environments_folders) + existing = synced_folders(@machine, cached: true) + share_folders(root_config, "csc", @cookbook_folders, existing) + share_folders(root_config, "csr", @role_folders, existing) + share_folders(root_config, "csdb", @data_bags_folders, existing) + share_folders(root_config, "cse", @environments_folders, existing) end - def provision + def provision(mode = :solo) install_chef # Verify that the proper shared folders exist. check = [] @@ -51,7 +58,7 @@ module VagrantPlugins upload_encrypted_data_bag_secret setup_json setup_solo_config - run_chef_solo + run_chef(mode) delete_encrypted_data_bag_secret end @@ -72,8 +79,10 @@ module VagrantPlugins local_path = File.expand_path(path, @machine.env.root_path) if File.exist?(local_path) - # Path exists on the host, setup the remote path - remote_path = "#{@config.provisioning_path}/chef-solo-#{get_and_update_counter(:cookbooks_path)}" + # Path exists on the host, setup the remote path. We use + # the MD5 of the local path so that it is predictable. + key = Digest::MD5.hexdigest(local_path) + remote_path = "#{@config.provisioning_path}/#{key}" else @machine.ui.warn(I18n.t("vagrant.provisioners.chef.cookbook_folder_not_found_warning", path: local_path.to_s)) @@ -103,16 +112,31 @@ module VagrantPlugins # Shares the given folders with the given prefix. The folders should # be of the structure resulting from the `expanded_folders` function. - def share_folders(root_config, prefix, folders) - folders.each do |type, local_path, remote_path| - if type == :host - opts = {} - opts[:id] = "v-#{prefix}-#{self.class.get_and_update_counter(:shared_folder)}" - opts[:type] = @config.synced_folder_type if @config.synced_folder_type - - root_config.vm.synced_folder(local_path, remote_path, opts) + def share_folders(root_config, prefix, folders, existing=nil) + existing_set = Set.new + (existing || []).each do |_, fs| + fs.each do |id, data| + existing_set.add(data[:guestpath]) end end + + folders.each do |type, local_path, remote_path| + next if type != :host + + # If this folder already exists, then we don't share it, it means + # it was already put down on disk. + if existing_set.include?(remote_path) + @logger.debug("Not sharing #{local_path}, exists as #{remote_path}") + next + end + + opts = {} + opts[:id] = "v-#{prefix}-#{self.class.get_and_update_counter(:shared_folder)}" + opts[:type] = @config.synced_folder_type if @config.synced_folder_type + + root_config.vm.synced_folder(local_path, remote_path, opts) + end + @shared_folders += folders end @@ -130,7 +154,7 @@ module VagrantPlugins } end - def run_chef_solo + def run_chef(mode) if @config.run_list && @config.run_list.empty? @machine.ui.warn(I18n.t("vagrant.chef_run_list_empty")) end @@ -143,9 +167,9 @@ module VagrantPlugins @config.attempts.times do |attempt| if attempt == 0 - @machine.ui.info I18n.t("vagrant.provisioners.chef.running_solo") + @machine.ui.info I18n.t("vagrant.provisioners.chef.running_#{mode}") else - @machine.ui.info I18n.t("vagrant.provisioners.chef.running_solo_again") + @machine.ui.info I18n.t("vagrant.provisioners.chef.running_#{mode}_again") end opts = { error_check: false, elevated: true } diff --git a/plugins/provisioners/chef/provisioner/chef_zero.rb b/plugins/provisioners/chef/provisioner/chef_zero.rb index 8ccae6130..f634bc9a7 100644 --- a/plugins/provisioners/chef/provisioner/chef_zero.rb +++ b/plugins/provisioners/chef/provisioner/chef_zero.rb @@ -22,6 +22,10 @@ module VagrantPlugins share_folders(root_config, "csn", @node_folders) end + def provision + super(:zero) + end + def solo_config super.merge( local_mode: true, diff --git a/plugins/provisioners/docker/cap/debian/docker_install.rb b/plugins/provisioners/docker/cap/debian/docker_install.rb index 5db0f12ba..4e4a2ae6e 100644 --- a/plugins/provisioners/docker/cap/debian/docker_install.rb +++ b/plugins/provisioners/docker/cap/debian/docker_install.rb @@ -14,8 +14,8 @@ module VagrantPlugins end comm.sudo("apt-get update -y") comm.sudo("apt-get install -y --force-yes -q curl") - comm.sudo("curl -sSL https://get.docker.io/gpg | apt-key add -") - comm.sudo("echo deb http://get.docker.io/ubuntu docker main > /etc/apt/sources.list.d/docker.list") + comm.sudo("curl -sSL https://get.docker.com/gpg | apt-key add -") + comm.sudo("echo deb http://get.docker.com/ubuntu docker main > /etc/apt/sources.list.d/docker.list") comm.sudo("apt-get update") comm.sudo("echo lxc lxc/directory string /var/lib/lxc | debconf-set-selections") comm.sudo("apt-get install -y --force-yes -q xz-utils #{package} -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'") diff --git a/plugins/provisioners/docker/config.rb b/plugins/provisioners/docker/config.rb index c96e97305..7e6c37787 100644 --- a/plugins/provisioners/docker/config.rb +++ b/plugins/provisioners/docker/config.rb @@ -70,8 +70,8 @@ module VagrantPlugins @__containers.each do |name, params| params[:image] ||= name - params[:auto_assign_name] = true if !params.has_key?(:auto_assign_name) - params[:daemonize] = true if !params.has_key?(:daemonize) + params[:auto_assign_name] = true if !params.key?(:auto_assign_name) + params[:daemonize] = true if !params.key?(:daemonize) end end end diff --git a/plugins/provisioners/puppet/config/puppet.rb b/plugins/provisioners/puppet/config/puppet.rb index 3117f9f6f..1810b989b 100644 --- a/plugins/provisioners/puppet/config/puppet.rb +++ b/plugins/provisioners/puppet/config/puppet.rb @@ -1,11 +1,7 @@ -require "vagrant/util/counter" - module VagrantPlugins module Puppet module Config class Puppet < Vagrant.plugin("2", :config) - extend Vagrant::Util::Counter - attr_accessor :facter attr_accessor :hiera_config_path attr_accessor :manifest_file @@ -65,15 +61,8 @@ module VagrantPlugins @manifest_file = "default.pp" if @manifest_file == UNSET_VALUE @module_path = nil if @module_path == UNSET_VALUE @synced_folder_type = nil if @synced_folder_type == UNSET_VALUE - @temp_dir = nil if @temp_dir == UNSET_VALUE + @temp_dir = "/tmp/vagrant-puppet" if @temp_dir == UNSET_VALUE @working_directory = nil if @working_directory == UNSET_VALUE - - # Set a default temp dir that has an increasing counter so - # that multiple Puppet definitions won't overwrite each other - if !@temp_dir - counter = self.class.get_and_update_counter(:puppet_config) - @temp_dir = "/tmp/vagrant-puppet-#{counter}" - end end # Returns the module paths as an array of paths expanded relative to the diff --git a/plugins/provisioners/puppet/provisioner/puppet.rb b/plugins/provisioners/puppet/provisioner/puppet.rb index 62c32efa2..c1e01c966 100644 --- a/plugins/provisioners/puppet/provisioner/puppet.rb +++ b/plugins/provisioners/puppet/provisioner/puppet.rb @@ -1,3 +1,5 @@ +require "digest/md5" + require "log4r" module VagrantPlugins @@ -22,8 +24,9 @@ module VagrantPlugins # Setup the module paths @module_paths = [] - @expanded_module_paths.each_with_index do |path, i| - @module_paths << [path, File.join(config.temp_dir, "modules-#{i}")] + @expanded_module_paths.each_with_index do |path, _| + key = Digest::MD5.hexdigest(path.to_s) + @module_paths << [path, File.join(config.temp_dir, "modules-#{key}")] end folder_opts = {} @@ -85,7 +88,8 @@ module VagrantPlugins def manifests_guest_path if config.manifests_path[0] == :host # The path is on the host, so point to where it is shared - File.join(config.temp_dir, "manifests") + key = Digest::MD5.hexdigest(config.manifests_path[1]) + File.join(config.temp_dir, "manifests-#{key}") else # The path is on the VM, so just point directly to it config.manifests_path[1] diff --git a/plugins/provisioners/salt/config.rb b/plugins/provisioners/salt/config.rb index 0a99d3fc8..4d97d942c 100644 --- a/plugins/provisioners/salt/config.rb +++ b/plugins/provisioners/salt/config.rb @@ -12,6 +12,7 @@ module VagrantPlugins attr_accessor :master_config attr_accessor :master_key attr_accessor :master_pub + attr_accessor :grains_config attr_accessor :run_highstate attr_accessor :run_overstate attr_accessor :always_install @@ -38,6 +39,7 @@ module VagrantPlugins @master_config = UNSET_VALUE @master_key = UNSET_VALUE @master_pub = UNSET_VALUE + @grains_config = UNSET_VALUE @run_highstate = UNSET_VALUE @run_overstate = UNSET_VALUE @always_install = UNSET_VALUE @@ -63,6 +65,7 @@ module VagrantPlugins @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 @run_highstate = nil if @run_highstate == UNSET_VALUE @run_overstate = nil if @run_overstate == UNSET_VALUE @always_install = nil if @always_install == UNSET_VALUE @@ -115,6 +118,13 @@ module VagrantPlugins end end + if @grains_config + expanded = Pathname.new(@grains_config).expand_path(machine.env.root_path) + if !expanded.file? + errors << I18n.t("vagrant.provisioners.salt.grains_config_nonexist") + end + end + if @install_master && !@no_minion && !@seed_master && @run_highstate errors << I18n.t("vagrant.provisioners.salt.must_accept_keys") end diff --git a/plugins/provisioners/salt/provisioner.rb b/plugins/provisioners/salt/provisioner.rb index a47bce2a6..87af7cc7d 100644 --- a/plugins/provisioners/salt/provisioner.rb +++ b/plugins/provisioners/salt/provisioner.rb @@ -75,7 +75,7 @@ module VagrantPlugins end def need_configure - @config.minion_config or @config.minion_key or @config.master_config or @config.master_key + @config.minion_config or @config.minion_key or @config.master_config or @config.master_key or @config.grains_config end def need_install @@ -181,6 +181,11 @@ module VagrantPlugins @machine.env.ui.info "Copying salt master config to vm." @machine.communicate.upload(expanded_path(@config.master_config).to_s, temp_config_dir + "/master") end + + if @config.grains_config + @machine.env.ui.info "Copying salt grains config to vm." + @machine.communicate.upload(expanded_path(@config.grains_config).to_s, temp_config_dir + "/grains") + end end # Copy master and minion keys to VM diff --git a/plugins/pushes/atlas/push.rb b/plugins/pushes/atlas/push.rb index 24a6d28b0..8a892fa2c 100644 --- a/plugins/pushes/atlas/push.rb +++ b/plugins/pushes/atlas/push.rb @@ -23,6 +23,7 @@ module VagrantPlugins # if we're on a system that doesn't support exec, so handle that properly. def execute(uploader) cmd = [] + cmd << "-debug" if !Vagrant.log_level.nil? cmd << "-vcs" if config.vcs cmd += config.includes.map { |v| ["-include", v] } cmd += config.excludes.map { |v| ["-exclude", v] } diff --git a/plugins/pushes/ftp/adapter.rb b/plugins/pushes/ftp/adapter.rb index f370d411f..8a9414376 100644 --- a/plugins/pushes/ftp/adapter.rb +++ b/plugins/pushes/ftp/adapter.rb @@ -1,3 +1,5 @@ +require "pathname" + module VagrantPlugins module FTPPush class Adapter @@ -50,7 +52,7 @@ module VagrantPlugins end def default_port - 20 + 21 end def connect(&block) @@ -67,16 +69,25 @@ module VagrantPlugins end def upload(local, remote) - parent = File.dirname(remote) + parent = File.dirname(remote) + fullpath = Pathname.new(File.expand_path(parent, pwd)) - # Create the parent directory if it does not exist - if !@server.list("/").any? { |f| f.start_with?(parent) } - @server.mkdir(parent) + # Create the parent directories if they does not exist (naive mkdir -p) + fullpath.descend do |path| + if @server.list(path.to_s).empty? + @server.mkdir(path.to_s) + end end # Upload the file @server.putbinaryfile(local, remote) end + + private + + def pwd + @pwd ||= @server.pwd + end end # diff --git a/plugins/pushes/ftp/push.rb b/plugins/pushes/ftp/push.rb index 3cf4169a0..7a69c4f02 100644 --- a/plugins/pushes/ftp/push.rb +++ b/plugins/pushes/ftp/push.rb @@ -7,6 +7,12 @@ module VagrantPlugins module FTPPush class Push < Vagrant.plugin("2", :push) IGNORED_FILES = %w(. ..).freeze + DEFAULT_EXCLUDES = %w(.git .hg .svn .vagrant).freeze + + def initialize(*) + super + @logger = Log4r::Logger.new("vagrant::pushes::ftp") + end def push # Grab files early so if there's an exception or issue, we don't have to @@ -14,11 +20,16 @@ module VagrantPlugins files = Hash[*all_files.flat_map do |file| relative_path = relative_path_for(file, config.dir) destination = File.expand_path(File.join(config.destination, relative_path)) + file = File.expand_path(file, env.root_path) [file, destination] end] + ftp = "#{config.username}@#{config.host}:#{config.destination}" + env.ui.info "Uploading #{env.root_path} to #{ftp}" + connect do |ftp| files.each do |local, remote| + @logger.info "Uploading #{local} => #{remote}" ftp.upload(local, remote) end end @@ -33,16 +44,6 @@ module VagrantPlugins ftp.connect(&block) end - # Parse the host into it's url and port parts. - # @return [Array] - def parse_host(host) - if host.include?(":") - host.split(":", 2) - else - [host, "22"] - end - end - # The list of all files that should be pushed by this push. This method # only returns **files**, not folders or symlinks! # @return [Array] @@ -72,7 +73,10 @@ module VagrantPlugins # @param [Array] excludes # the exclude patterns or files def filter_excludes!(list, excludes) - excludes = Array(excludes).flat_map { |e| [e, "#{e}/*"] } + excludes = Array(excludes) + excludes = excludes + DEFAULT_EXCLUDES + excludes = excludes.flat_map { |e| [e, "#{e}/*"] } + list.reject! do |file| basename = relative_path_for(file, config.dir) diff --git a/plugins/pushes/local-exec/plugin.rb b/plugins/pushes/local-exec/plugin.rb index 9f8be467b..e58fe4bed 100644 --- a/plugins/pushes/local-exec/plugin.rb +++ b/plugins/pushes/local-exec/plugin.rb @@ -8,13 +8,13 @@ module VagrantPlugins Run a local command or script to push DESC - config(:local_exec, :push) do + config(:"local-exec", :push) do require File.expand_path("../config", __FILE__) init! Config end - push(:local_exec) do + push(:"local-exec") do require File.expand_path("../push", __FILE__) init! Push diff --git a/plugins/pushes/local-exec/push.rb b/plugins/pushes/local-exec/push.rb index be74e68d5..bad308f3b 100644 --- a/plugins/pushes/local-exec/push.rb +++ b/plugins/pushes/local-exec/push.rb @@ -1,6 +1,6 @@ require "fileutils" require "tempfile" -require "vagrant/util/subprocess" +require "vagrant/util/safe_exec" require_relative "errors" @@ -38,16 +38,7 @@ module VagrantPlugins # Execute the script, raising an exception if it fails. def execute!(*cmd) - result = Vagrant::Util::Subprocess.execute(*cmd) - - if result.exit_code != 0 - raise Errors::CommandFailed, - cmd: cmd.join(" "), - stdout: result.stdout, - stderr: result.stderr - end - - result + Vagrant::Util::SafeExec.exec(cmd[0], *cmd[1..-1]) end end end diff --git a/plugins/synced_folders/nfs/synced_folder.rb b/plugins/synced_folders/nfs/synced_folder.rb index f2cdbd0dd..7cf51aabe 100644 --- a/plugins/synced_folders/nfs/synced_folder.rb +++ b/plugins/synced_folders/nfs/synced_folder.rb @@ -64,7 +64,7 @@ module VagrantPlugins export_folders = folders.dup export_folders.keys.each do |id| opts = export_folders[id] - if opts.has_key?(:nfs_export) && !opts[:nfs_export] + if opts.key?(:nfs_export) && !opts[:nfs_export] export_folders.delete(id) end end @@ -117,7 +117,7 @@ module VagrantPlugins def prepare_folder(machine, opts) opts[:map_uid] = prepare_permission(machine, :uid, opts) opts[:map_gid] = prepare_permission(machine, :gid, opts) - opts[:nfs_udp] = true if !opts.has_key?(:nfs_udp) + opts[:nfs_udp] = true if !opts.key?(:nfs_udp) opts[:nfs_version] ||= 3 # We use a CRC32 to generate a 32-bit checksum so that the @@ -128,11 +128,11 @@ module VagrantPlugins # Prepares the UID/GID settings for a single folder. def prepare_permission(machine, perm, opts) key = "map_#{perm}".to_sym - return nil if opts.has_key?(key) && opts[key].nil? + return nil if opts.key?(key) && opts[key].nil? # The options on the hash get priority, then the default # values - value = opts.has_key?(key) ? opts[key] : machine.config.nfs.send(key) + value = opts.key?(key) ? opts[key] : machine.config.nfs.send(key) return value if value != :auto # Get UID/GID from folder if we've made it this far diff --git a/plugins/synced_folders/rsync/command/rsync_auto.rb b/plugins/synced_folders/rsync/command/rsync_auto.rb index 802fb6e58..b2a4adc0b 100644 --- a/plugins/synced_folders/rsync/command/rsync_auto.rb +++ b/plugins/synced_folders/rsync/command/rsync_auto.rb @@ -83,7 +83,7 @@ module VagrantPlugins folders.each do |id, folder_opts| # If we marked this folder to not auto sync, then # don't do it. - next if folder_opts.has_key?(:auto) && !folder_opts[:auto] + next if folder_opts.key?(:auto) && !folder_opts[:auto] hostpath = folder_opts[:hostpath] hostpath = File.expand_path(hostpath, machine.env.root_path) diff --git a/scripts/website_push_docs.sh b/scripts/website_push_docs.sh index ec2d8a09f..fd3937fc4 100755 --- a/scripts/website_push_docs.sh +++ b/scripts/website_push_docs.sh @@ -8,5 +8,10 @@ DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" # Change into that directory cd $DIR +# Add the git remote if it doesn't exist +git remote | grep heroku-docs || { + git remote add heroku-docs git@heroku.com:vagrantup-docs.git +} + # Push the subtree (force) git push heroku-docs `git subtree split --prefix website/docs master`:master --force diff --git a/scripts/website_push_www.sh b/scripts/website_push_www.sh index 9e8bff265..1d5f180f9 100755 --- a/scripts/website_push_www.sh +++ b/scripts/website_push_www.sh @@ -8,5 +8,10 @@ DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" # Change into that directory cd $DIR +# Add the git remote if it doesn't exist +git remote | grep heroku-www || { + git remote add heroku-www git@heroku.com:vagrantup-www.git +} + # Push the subtree (force) git push heroku-www `git subtree split --prefix website/www master`:master --force diff --git a/templates/commands/init/Vagrantfile.erb b/templates/commands/init/Vagrantfile.erb index 710e61664..4cae3c990 100644 --- a/templates/commands/init/Vagrantfile.erb +++ b/templates/commands/init/Vagrantfile.erb @@ -8,9 +8,10 @@ Vagrant.configure(2) do |config| # The most common configuration options are documented and commented below. # For a complete reference, please see the online documentation at - # vagrantup.com + # https://docs.vagrantup.com. - # Every Vagrant virtual environment requires a box to build off of. + # Every Vagrant development environment requires a box. You can search for + # boxes at https://atlas.hashicorp.com/search. config.vm.box = "<%= box_name %>" <% if box_url -%> @@ -38,10 +39,6 @@ Vagrant.configure(2) do |config| # your network. # config.vm.network "public_network" - # If true, then any SSH connections made will enable agent forwarding. - # Default value: false - # config.ssh.forward_agent = true - # Share an additional folder to the guest VM. The first argument is # the path on the host to the actual folder. The second argument is # the path on the guest to mount the folder. And the optional third @@ -53,134 +50,28 @@ Vagrant.configure(2) do |config| # Example for VirtualBox: # # config.vm.provider "virtualbox" do |vb| - # # Don't boot with headless mode + # # Display the VirtualBox GUI when booting the machine # vb.gui = true # - # # Use VBoxManage to customize the VM. For example to change memory: - # vb.customize ["modifyvm", :id, "--memory", "1024"] + # # Customize the amount of memory on the VM: + # vb.memory = "1024" # end # - # View the documentation for the provider you're using for more + # View the documentation for the provider you are using for more # information on available options. - # Enable provisioning with CFEngine. CFEngine Community packages are - # automatically installed. For example, configure the host as a - # policy server and optionally a policy file to run: - # - # config.vm.provision "cfengine" do |cf| - # cf.am_policy_hub = true - # # cf.run_file = "motd.cf" - # end - # - # You can also configure and bootstrap a client to an existing - # policy server: - # - # config.vm.provision "cfengine" do |cf| - # cf.policy_server_address = "10.0.2.15" + # Define a Vagrant Push strategy for pushing to Atlas. Other push strategies + # such as FTP and Heroku are also available. See the documentation at + # https://docs.vagrantup.com/v2/push/atlas.html for more information. + # config.push.define "atlas" do |push| + # push.app = "YOUR_ATLAS_USERNAME/YOUR_APPLICATION_NAME" # end - # Enable provisioning with Puppet stand alone. Puppet manifests - # are contained in a directory path relative to this Vagrantfile. - # You will need to create the manifests directory and a manifest in - # the file default.pp in the manifests_path directory. - # - # config.vm.provision "puppet" do |puppet| - # puppet.manifests_path = "manifests" - # puppet.manifest_file = "default.pp" - # end - - # Enable provisioning with Chef Solo, specifying a cookbooks path, roles - # path, and data_bags path (all relative to this Vagrantfile), and adding - # some recipes and/or roles. - # - # config.vm.provision "chef_solo" do |chef| - # chef.cookbooks_path = "~/chef/cookbooks" - # chef.roles_path = "~/chef/roles" - # chef.data_bags_path = "~/chef/data_bags" - # - # chef.add_recipe "mysql" - # chef.add_role "web" - # - # chef.json = { mysql_password: "foo" } - # end - # - # Chef Solo will automatically install the latest version of Chef for you. - # This can be configured in the provisioner block: - # - # config.vm.provision "chef_solo" do |chef| - # chef.version = "11.16.4" - # end - # - # Alternative you can disable the installation of Chef entirely: - # - # config.vm.provision "chef_solo" do |chef| - # chef.install = false - # end - - # Enable provisioning with Chef Zero. The Chef Zero provisioner accepts the - # exact same parameter as the Chef Solo provisioner: - # - # config.vm.provision "chef_zero" do |chef| - # chef.cookbooks_path = "~/chef/cookbooks" - # chef.roles_path = "~/chef/roles" - # chef.data_bags_path = "~/chef/data_bags" - # - # chef.add_recipe "mysql" - # chef.add_role "web" - # - # # You may also specify custom JSON attributes: - # chef.json = { mysql_password: "foo" } - # end - - # Enable provisioning with Chef Server, specifying the chef server URL, - # and the path to the validation key (relative to this Vagrantfile). - # - # The Hosted Chef platform uses HTTPS. Substitute your organization for - # ORGNAME in the URL and validation key. - # - # If you have your own Chef Server, use the appropriate URL, which may be - # HTTP instead of HTTPS depending on your configuration. Also change the - # validation key to validation.pem. - # - # config.vm.provision "chef_client" do |chef| - # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME" - # chef.validation_key_path = "ORGNAME-validator.pem" - # end - # - # If you're using the Hosted Chef platform, your validator client is - # ORGNAME-validator, replacing ORGNAME with your organization name. - # - # If you have your own Chef Server, the default validation client name is - # chef-validator, unless you changed the configuration. - # - # chef.validation_client_name = "ORGNAME-validator" - # - # Chef Client will automatically install the latest version of Chef for you. - # This can be configured in the provisioner block: - # - # config.vm.provision "chef_client" do |chef| - # chef.version = "11.16.4" - # end - # - # Alternative you can disable the installation of Chef entirely: - # - # config.vm.provision "chef_client" do |chef| - # chef.install = false - # end - - # Enable provisioning with Chef Apply, specifying an inline recipe to execute - # on the target system. - # - # config.vm.provision "chef_apply" do |chef| - # chef.recipe = <<-RECIPE - # package "curl" - # RECIPE - # end - # - # Chef Apply will automatically install the latest version of Chef for you. - # This can be configured in the provisioner block: - # - # config.vm.provision "chef_apply" do |chef| - # chef.version = "11.16.4" - # end + # Enable provisioning with a shell script. Additional provisioners such as + # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the + # documentation for more information about their specific syntax and use. + # config.vm.provision "shell", inline: <<-SHELL + # sudo apt-get update + # sudo apt-get install -y apache2 + # SHELL end diff --git a/templates/commands/init/Vagrantfile.min.erb b/templates/commands/init/Vagrantfile.min.erb index 6120ce0e4..ac70f5e7c 100644 --- a/templates/commands/init/Vagrantfile.min.erb +++ b/templates/commands/init/Vagrantfile.min.erb @@ -1,6 +1,3 @@ -# -*- mode: ruby -*- -# vi: set ft=ruby : - Vagrant.configure(2) do |config| config.vm.box = "<%= box_name %>" <% if box_url -%> diff --git a/templates/locales/en.yml b/templates/locales/en.yml index e28106a20..155cd77dc 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -144,7 +144,7 @@ en: inserting_random_key: |- Inserting generated public key within guest... inserting_remove_key: |- - Removing insecure key from the guest if its present... + Removing insecure key from the guest if it's present... list_commands: |- Below is a listing of all available Vagrant commands and a brief description of what they do. @@ -243,7 +243,7 @@ en: Press ctrl-c now to exit if you want to remove some boxes or free up some disk space. - Press any other key to continue. + Press the Enter or Return key to continue. version_current: |- Installed Version: %{version} version_latest: |- @@ -1809,6 +1809,8 @@ en: running_apply: "Running chef-apply..." running_solo: "Running chef-solo..." running_solo_again: "Running chef-solo again (failed to converge)..." + running_zero: "Running chef-zero..." + running_zero_again: "Running chef-zero again (failed to converge)..." missing_shared_folders: |- Shared folders that Chef requires are missing on the virtual machine. This is usually due to configuration changing after already booting the @@ -1909,6 +1911,8 @@ en: The specified minion_config file could not be found. master_config_nonexist: |- The specified master_config file could not be found. + grains_config_nonexist: |- + The specified grains_config file could not be found. missing_key: |- You must include both public and private keys. must_accept_keys: |- diff --git a/templates/provisioners/chef_solo/solo.erb b/templates/provisioners/chef_solo/solo.erb index b7d08a65b..25d3346b7 100644 --- a/templates/provisioners/chef_solo/solo.erb +++ b/templates/provisioners/chef_solo/solo.erb @@ -5,11 +5,7 @@ file_cache_path "<%= file_cache_path %>" file_backup_path "<%= file_backup_path %>" cookbook_path <%= cookbooks_path.inspect %> <% if roles_path %> -if Chef::VERSION.to_f < 11.8 - role_path <%= roles_path.first.inspect %> -else - role_path <%= roles_path.inspect %> -end +role_path <%= roles_path.size == 1 ? roles_path.first.inspect : roles_path.inspect %> <% end %> log_level <%= log_level.inspect %> verbose_logging <%= verbose_logging.inspect %> diff --git a/test/unit/plugins/commands/login/client_test.rb b/test/unit/plugins/commands/login/client_test.rb index fcdf1b902..f57670eb0 100644 --- a/test/unit/plugins/commands/login/client_test.rb +++ b/test/unit/plugins/commands/login/client_test.rb @@ -5,19 +5,12 @@ require Vagrant.source_root.join("plugins/commands/login/command") describe VagrantPlugins::LoginCommand::Client do include_context "unit" - def stub_env(key, value = nil) - allow(ENV).to receive(:[]).and_call_original - allow(ENV).to receive(:[]) - .with(key) - .and_return(value) - end - let(:env) { isolated_environment.create_vagrant_env } subject { described_class.new(env) } before do - stub_env("ATLAS_TOKEN", nil) + stub_env("ATLAS_TOKEN" => nil) subject.clear_token end @@ -101,7 +94,7 @@ describe VagrantPlugins::LoginCommand::Client do describe "#token" do it "reads ATLAS_TOKEN" do - stub_env("ATLAS_TOKEN", "ABCD1234") + stub_env("ATLAS_TOKEN" => "ABCD1234") expect(subject.token).to eq("ABCD1234") end @@ -111,7 +104,7 @@ describe VagrantPlugins::LoginCommand::Client do end it "prefers the environment variable" do - stub_env("ATLAS_TOKEN", "ABCD1234") + stub_env("ATLAS_TOKEN" => "ABCD1234") subject.store_token("EFGH5678") expect(subject.token).to eq("ABCD1234") end diff --git a/test/unit/plugins/commands/login/command_test.rb b/test/unit/plugins/commands/login/command_test.rb new file mode 100644 index 000000000..c92c51174 --- /dev/null +++ b/test/unit/plugins/commands/login/command_test.rb @@ -0,0 +1,96 @@ +require File.expand_path("../../../../base", __FILE__) + +require Vagrant.source_root.join("plugins/commands/login/command") + +describe VagrantPlugins::LoginCommand::Command do + include_context "unit" + + let(:env) { isolated_environment.create_vagrant_env } + + let(:token_path) { env.data_dir.join("vagrant_login_token") } + + let(:stdout) { StringIO.new } + let(:stderr) { StringIO.new } + + subject { described_class.new(argv, env) } + + before do + stub_env("ATLAS_TOKEN" => "") + end + + describe "#execute" do + context "with no args" do + let(:argv) { [] } + end + + context "with --check" do + let(:argv) { ["--check"] } + + context "when there is a token" do + before do + stub_request(:get, %r{^#{Vagrant.server_url}/api/v1/authenticate}) + .to_return(status: 200) + end + + before do + File.open(token_path, "w+") { |f| f.write("abcd1234") } + end + + it "returns 0" do + expect(subject.execute).to eq(0) + end + end + + context "when there is no token" do + it "returns 1" do + expect(subject.execute).to eq(1) + end + end + end + + context "with --logout" do + let(:argv) { ["--logout"] } + + it "returns 0" do + expect(subject.execute).to eq(0) + end + + it "clears the token" do + subject.execute + expect(File.exist?(token_path)).to be(false) + end + end + + context "with --token" do + let(:argv) { ["--token", "efgh5678"] } + + context "when the token is valid" do + before do + stub_request(:get, %r{^#{Vagrant.server_url}/api/v1/authenticate}) + .to_return(status: 200) + end + + it "sets the token" do + subject.execute + token = File.read(token_path).strip + expect(token).to eq("efgh5678") + end + + it "returns 0" do + expect(subject.execute).to eq(0) + end + end + + context "when the token is invalid" do + before do + stub_request(:get, %r{^#{Vagrant.server_url}/api/v1/authenticate}) + .to_return(status: 401) + end + + it "returns 1" do + expect(subject.execute).to eq(1) + end + end + end + end +end diff --git a/test/unit/plugins/commands/login/middleware/add_authentication_test.rb b/test/unit/plugins/commands/login/middleware/add_authentication_test.rb index 826e5d46b..99c99a8af 100644 --- a/test/unit/plugins/commands/login/middleware/add_authentication_test.rb +++ b/test/unit/plugins/commands/login/middleware/add_authentication_test.rb @@ -17,6 +17,7 @@ describe VagrantPlugins::LoginCommand::AddAuthentication do before do allow(Vagrant).to receive(:server_url).and_return(server_url) + stub_env("ATLAS_TOKEN" => nil) end describe "#call" do @@ -60,5 +61,28 @@ describe VagrantPlugins::LoginCommand::AddAuthentication do expect(env[:box_urls]).to eq(expected) end + + it "appends the access token to vagrantcloud.com URLs if Atlas" do + server_url = "https://atlas.hashicorp.com" + allow(Vagrant).to receive(:server_url).and_return(server_url) + + token = "foobarbaz" + VagrantPlugins::LoginCommand::Client.new(iso_env).store_token(token) + + original = [ + "http://google.com/box.box", + "http://vagrantcloud.com/foo.box", + "http://vagrantcloud.com/bar.box?arg=true", + ] + + expected = original.dup + expected[1] = "#{original[1]}?access_token=#{token}" + expected[2] = "#{original[2]}&access_token=#{token}" + + env[:box_urls] = original.dup + subject.call(env) + + expect(env[:box_urls]).to eq(expected) + end end end diff --git a/test/unit/plugins/commands/push/command_test.rb b/test/unit/plugins/commands/push/command_test.rb index 06995d51d..a97f4caba 100644 --- a/test/unit/plugins/commands/push/command_test.rb +++ b/test/unit/plugins/commands/push/command_test.rb @@ -6,11 +6,14 @@ describe VagrantPlugins::CommandPush::Command do include_context "unit" include_context "command plugin helpers" + let(:iso_env) { isolated_environment } let(:env) do - isolated_environment.tap do |env| - env.vagrantfile("") - env.create_vagrant_env - end + iso_env.vagrantfile(<<-VF) + Vagrant.configure("2") do |config| + config.vm.box = "hashicorp/precise64" + end + VF + iso_env.create_vagrant_env end let(:argv) { [] } @@ -39,6 +42,26 @@ describe VagrantPlugins::CommandPush::Command do expect(env).to receive(:push).once subject.execute end + + it "validates the configuration" do + iso_env.vagrantfile <<-EOH + Vagrant.configure("2") do |config| + config.vm.box = "hashicorp/precise64" + + config.push.define "noop" do |push| + push.bad = "ham" + end + end + EOH + + subject = described_class.new(argv, iso_env.create_vagrant_env) + allow(subject).to receive(:validate_pushes!) + .and_return(:noop) + + expect { subject.execute }.to raise_error(Vagrant::Errors::ConfigInvalid) { |err| + expect(err.message).to include("The following settings shouldn't exist: bad") + } + end end describe "#validate_pushes!" do diff --git a/test/unit/plugins/communicators/winrm/communicator_test.rb b/test/unit/plugins/communicators/winrm/communicator_test.rb index c73106900..af92d365b 100644 --- a/test/unit/plugins/communicators/winrm/communicator_test.rb +++ b/test/unit/plugins/communicators/winrm/communicator_test.rb @@ -75,15 +75,23 @@ describe VagrantPlugins::CommunicatorWinRM::Communicator do describe ".test" do it "returns true when exit code is zero" do - expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ exitcode: 0 }) + output = { exitcode: 0, data:[{ stderr: '' }] } + expect(shell).to receive(:powershell).with(kind_of(String)).and_return(output) expect(subject.test("test -d c:/windows")).to be_true end it "returns false when exit code is non-zero" do - expect(shell).to receive(:powershell).with(kind_of(String)).and_return({ exitcode: 1 }) + output = { exitcode: 1, data:[{ stderr: '' }] } + expect(shell).to receive(:powershell).with(kind_of(String)).and_return(output) expect(subject.test("test -d /tmp/foobar")).to be_false end + it "returns false when stderr contains output" do + output = { exitcode: 0, data:[{ stderr: 'this is an error' }] } + expect(shell).to receive(:powershell).with(kind_of(String)).and_return(output) + expect(subject.test("[-x stuff] && foo")).to be_false + end + it "returns false when command is testing for linux OS" do expect(subject.test("uname -s | grep Debian")).to be_false end diff --git a/test/unit/plugins/kernel_v2/config/push_test.rb b/test/unit/plugins/kernel_v2/config/push_test.rb index 28430d171..e1c67996f 100644 --- a/test/unit/plugins/kernel_v2/config/push_test.rb +++ b/test/unit/plugins/kernel_v2/config/push_test.rb @@ -89,6 +89,7 @@ describe VagrantPlugins::Kernel_V2::PushConfig do let(:key) { pushes[:foo][0] } let(:config) { pushes[:foo][1] } let(:unset) { Vagrant.plugin("2", :config).const_get(:UNSET_VALUE) } + let(:dummy_klass) { Vagrant::Config::V2::DummyConfig } before do register_plugin("2") do |plugin| @@ -112,6 +113,62 @@ describe VagrantPlugins::Kernel_V2::PushConfig do end end + it "compiles the proper configuration with a single strategy" do + instance = described_class.new.tap do |i| + i.define "foo" + end + + instance.finalize! + + pushes = instance.__compiled_pushes + strategy, config = pushes[:foo] + expect(strategy).to eq(:foo) + expect(config.bar).to be(unset) + end + + it "compiles the proper configuration with a single strategy and block" do + instance = described_class.new.tap do |i| + i.define "foo" do |b| + b.bar = 42 + end + end + + instance.finalize! + + pushes = instance.__compiled_pushes + strategy, config = pushes[:foo] + expect(strategy).to eq(:foo) + expect(config.bar).to eq(42) + end + + it "compiles the proper config with a name and explicit strategy" do + instance = described_class.new.tap do |i| + i.define "bar", strategy: "foo" + end + + instance.finalize! + + pushes = instance.__compiled_pushes + strategy, config = pushes[:bar] + expect(strategy).to eq(:foo) + expect(config.bar).to be(unset) + end + + it "compiles the proper config with a name and explicit strategy with block" do + instance = described_class.new.tap do |i| + i.define "bar", strategy: "foo" do |b| + b.bar = 42 + end + end + + instance.finalize! + + pushes = instance.__compiled_pushes + strategy, config = pushes[:bar] + expect(strategy).to eq(:foo) + expect(config.bar).to eq(42) + end + context "with the same name but different strategy" do context "with no block" do let(:a) do @@ -128,8 +185,7 @@ describe VagrantPlugins::Kernel_V2::PushConfig do it "chooses the last config" do expect(key).to eq(:zip) - expect(config.bar).to be(unset) - expect(config.zip).to be(unset) + expect(config).to be_kind_of(dummy_klass) end end @@ -152,8 +208,7 @@ describe VagrantPlugins::Kernel_V2::PushConfig do it "chooses the last config" do expect(key).to eq(:zip) - expect(config.bar).to eq(unset) - expect(config.zip).to eq("b") + expect(config).to be_kind_of(dummy_klass) end end @@ -174,8 +229,7 @@ describe VagrantPlugins::Kernel_V2::PushConfig do it "chooses the last config" do expect(key).to eq(:zip) - expect(config.bar).to be(unset) - expect(config.zip).to be(unset) + expect(config).to be_kind_of(dummy_klass) end end @@ -196,8 +250,7 @@ describe VagrantPlugins::Kernel_V2::PushConfig do it "chooses the last config" do expect(key).to eq(:zip) - expect(config.bar).to eq("b") - expect(config.zip).to eq("b") + expect(config).to be_kind_of(dummy_klass) end end end @@ -286,8 +339,7 @@ describe VagrantPlugins::Kernel_V2::PushConfig do it "merges the configs" do expect(key).to eq(:zip) - expect(config.bar).to eq(unset) - expect(config.zip).to eq("b") + expect(config).to be_kind_of(dummy_klass) end end end diff --git a/test/unit/plugins/providers/hyperv/config_test.rb b/test/unit/plugins/providers/hyperv/config_test.rb index 5177dca59..a3c46c619 100644 --- a/test/unit/plugins/providers/hyperv/config_test.rb +++ b/test/unit/plugins/providers/hyperv/config_test.rb @@ -9,10 +9,37 @@ describe VagrantPlugins::HyperV::Config do subject.finalize! expect(subject.ip_address_timeout).to eq(180) end - it "defaults to a number" do subject.finalize! expect(subject.ip_address_timeout).to eq(120) end end + describe "#vmname" do + it "can be set" do + subject.vmname = "test" + subject.finalize! + expect(subject.vmname).to eq("test") + end + end + describe "#memory" do + it "can be set" do + subject.memory = 512 + subject.finalize! + expect(subject.memory).to eq(512) + end + end + describe "#maxmemory" do + it "can be set" do + subject.maxmemory = 1024 + subject.finalize! + expect(subject.maxmemory).to eq(1024) + end + end + describe "#cpus" do + it "can be set" do + subject.cpus = 2 + subject.finalize! + expect(subject.cpus).to eq(2) + end + end end diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index 756f95769..05fa8fae3 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -50,6 +50,7 @@ VF let(:generated_inventory_file) { File.join(generated_inventory_dir, 'vagrant_ansible_inventory') } before do + Vagrant::Util::Platform.stub(solaris?: false) subject.instance_variable_get(:@logger).stub(:debug?).and_return(false) machine.stub(ssh_info: ssh_info) @@ -63,7 +64,7 @@ VF # def self.it_should_set_arguments_and_environment_variables( - expected_args_count = 6, expected_vars_count = 4, expected_host_key_checking = false, expected_transport_mode = "ssh") + expected_args_count = 7, expected_vars_count = 4, expected_host_key_checking = false, expected_transport_mode = "ssh") it "sets implicit arguments in a specific order" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -72,6 +73,7 @@ VF expect(args[1]).to eq("--private-key=#{machine.ssh_info[:private_key_path][0]}") expect(args[2]).to eq("--user=#{machine.ssh_info[:username]}") expect(args[3]).to eq("--connection=ssh") + expect(args[4]).to eq("--timeout=30") inventory_count = args.count { |x| x =~ /^--inventory-file=.+$/ } expect(inventory_count).to be > 0 @@ -103,10 +105,11 @@ VF cmd_opts = args.last if expected_host_key_checking - expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to be_nil unless config.raw_arguments + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to_not include("-o UserKnownHostsFile=/dev/null") else expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o UserKnownHostsFile=/dev/null") end + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o IdentitiesOnly=yes") expect(cmd_opts[:env]['ANSIBLE_FORCE_COLOR']).to eql("true") expect(cmd_opts[:env]['ANSIBLE_HOST_KEY_CHECKING']).to eql(expected_host_key_checking.to_s) expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1) @@ -270,7 +273,7 @@ VF config.host_key_checking = true end - it_should_set_arguments_and_environment_variables 6, 3, true + it_should_set_arguments_and_environment_variables 7, 4, true end describe "with boolean (flag) options disabled" do @@ -282,7 +285,7 @@ VF config.sudo_user = 'root' end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it_should_set_optional_arguments({ "sudo_user" => "--sudo-user=root" }) it "it does not set boolean flag when corresponding option is set to false" do @@ -311,7 +314,7 @@ VF "--new-arg=yeah"] end - it_should_set_arguments_and_environment_variables 17, 4, false, "paramiko" + it_should_set_arguments_and_environment_variables 18, 4, false, "paramiko" it "sets all raw arguments" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -367,7 +370,7 @@ VF config.ask_vault_pass = true end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it "should ask the vault password" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -381,7 +384,7 @@ VF config.vault_password_file = existing_file end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it "uses the given vault password file" do expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| @@ -395,7 +398,7 @@ VF config.raw_ssh_args = ['-o ControlMaster=no', '-o ForwardAgent=no'] end - it_should_set_arguments_and_environment_variables 6, 4 + it_should_set_arguments_and_environment_variables 7, 4 it_should_explicitly_enable_ansible_ssh_control_persist_defaults it "passes custom SSH options via ANSIBLE_SSH_ARGS with the highest priority" do @@ -429,7 +432,7 @@ VF ssh_info[:private_key_path] = ['/path/to/my/key', '/an/other/identity', '/yet/an/other/key'] end - it_should_set_arguments_and_environment_variables 6, 4 + it_should_set_arguments_and_environment_variables 7, 4 it_should_explicitly_enable_ansible_ssh_control_persist_defaults it "passes additional Identity Files via ANSIBLE_SSH_ARGS" do @@ -446,7 +449,7 @@ VF ssh_info[:forward_agent] = true end - it_should_set_arguments_and_environment_variables 6, 4 + it_should_set_arguments_and_environment_variables 7, 4 it_should_explicitly_enable_ansible_ssh_control_persist_defaults it "enables SSH-Forwarding via ANSIBLE_SSH_ARGS" do @@ -465,7 +468,7 @@ VF it "shows the ansible-playbook command" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml") } end end @@ -475,12 +478,12 @@ VF config.verbose = 'v' end - it_should_set_arguments_and_environment_variables 7 + it_should_set_arguments_and_environment_variables 8 it_should_set_optional_arguments({ "verbose" => "-v" }) it "shows the ansible-playbook command" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=false ANSIBLE_SSH_ARGS='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/path/to/my/key --user=testuser --connection=ssh --timeout=30 --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml") } end end @@ -513,7 +516,7 @@ VF config.raw_ssh_args = ['-o ControlMaster=no'] end - it_should_set_arguments_and_environment_variables 20, 4, true + it_should_set_arguments_and_environment_variables 21, 4, true it_should_explicitly_enable_ansible_ssh_control_persist_defaults it_should_set_optional_arguments({ "extra_vars" => "--extra-vars=@#{File.expand_path(__FILE__)}", "sudo" => "--sudo", @@ -538,10 +541,84 @@ VF it "shows the ansible-playbook command, with additional quotes when required" do expect(machine.env.ui).to receive(:detail).with { |full_command| - expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' playbook.yml") + expect(full_command).to eq("PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -o IdentityFile=/my/key2 -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --private-key=/my/key1 --user=testuser --connection=ssh --timeout=30 --limit='machine*:&vagrant:!that_one' --inventory-file=#{generated_inventory_dir} --extra-vars=@#{File.expand_path(__FILE__)} --sudo --sudo-user=deployer -vvv --ask-sudo-pass --ask-vault-pass --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task='an awesome task' --why-not --su-user=foot --ask-su-pass --limit='all' playbook.yml") } end end + # + # Special cases related to the VM provider context + # + + context "with Docker provider on a non-Linux host" do + + let(:fake_host_ssh_info) {{ + private_key_path: ['/path/to/docker/host/key'], + username: 'boot9docker', + host: '127.0.0.1', + port: 2299 + }} + let(:fake_host_vm) { + double("host_vm").tap do |h| + h.stub(ssh_info: fake_host_ssh_info) + end + } + + before do + machine.stub(provider_name: :docker) + machine.provider.stub(host_vm?: true) + machine.provider.stub(host_vm: fake_host_vm) + end + + it "uses an SSH ProxyCommand to reach the VM" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + cmd_opts = args.last + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o ProxyCommand='ssh boot9docker@127.0.0.1 -p 2299 -i /path/to/docker/host/key -o Compression=yes -o ConnectTimeout=5 -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no exec nc %h %p 2>/dev/null'") + } + end + end + + # + # Special cases related to the Vagrant Host operating system in use + # + + context "with a Solaris-like host" do + before do + Vagrant::Util::Platform.stub(solaris?: true) + end + + it "does not set IdentitiesOnly=yes in ANSIBLE_SSH_ARGS" do + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + cmd_opts = args.last + expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to_not include("-o IdentitiesOnly=yes") + + # Note: + # The expectation below is a workaround to a possible misuse (or bug) in RSpec/Ruby stack. + # If 'args' variable is not required by in this block, the "Vagrant::Util::Subprocess).to receive" + # surprisingly expects to receive "no args". + # This problem can be "solved" by using args the "unnecessary" (but harmless) expectation below: + expect(true).to be_true + } + end + + describe "and with host_key_checking option enabled" do + it "does not set ANSIBLE_SSH_ARGS environment variable" do + config.host_key_checking = true + + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + cmd_opts = args.last + expect(cmd_opts[:env]).to_not include('ANSIBLE_SSH_ARGS') + + # Note: + # The expectation below is a workaround to a possible misuse (or bug) in RSpec/Ruby stack. + # If 'args' variable is not required by in this block, the "Vagrant::Util::Subprocess).to receive" + # surprisingly expects to receive "no args". + # This problem can be "solved" by using args the "unnecessary" (but harmless) expectation below: + expect(true).to be_true + } + end + end + + end end end diff --git a/test/unit/plugins/provisioners/chef/config/base_runner_test.rb b/test/unit/plugins/provisioners/chef/config/base_runner_test.rb index 591ec743e..330c31616 100644 --- a/test/unit/plugins/provisioners/chef/config/base_runner_test.rb +++ b/test/unit/plugins/provisioners/chef/config/base_runner_test.rb @@ -123,7 +123,7 @@ describe VagrantPlugins::Chef::Config::BaseRunner do describe "#provisioning_path" do it "defaults to a tmp_path" do subject.finalize! - expect(subject.provisioning_path).to match(%r{/tmp/vagrant-chef-\d+}) + expect(subject.provisioning_path).to eq("/tmp/vagrant-chef") end end diff --git a/test/unit/plugins/provisioners/chef/config/base_test.rb b/test/unit/plugins/provisioners/chef/config/base_test.rb index 2355f28cd..4b018f11b 100644 --- a/test/unit/plugins/provisioners/chef/config/base_test.rb +++ b/test/unit/plugins/provisioners/chef/config/base_test.rb @@ -68,4 +68,11 @@ describe VagrantPlugins::Chef::Config::Base do expect(subject.version).to eq(:latest) end end + + describe "#installer_download_path" do + it "defaults to nil" do + subject.finalize! + expect(subject.installer_download_path).to be(nil) + end + end end diff --git a/test/unit/plugins/provisioners/chef/config/chef_apply_test.rb b/test/unit/plugins/provisioners/chef/config/chef_apply_test.rb index 242eda7ad..135c04213 100644 --- a/test/unit/plugins/provisioners/chef/config/chef_apply_test.rb +++ b/test/unit/plugins/provisioners/chef/config/chef_apply_test.rb @@ -23,7 +23,7 @@ describe VagrantPlugins::Chef::Config::ChefApply do describe "#upload_path" do it "defaults to /tmp/vagrant-chef-apply.rb" do subject.finalize! - expect(subject.upload_path).to match(%r{/tmp/vagrant-chef-apply-\d+}) + expect(subject.upload_path).to eq("/tmp/vagrant-chef-apply") end end diff --git a/test/unit/plugins/provisioners/chef/omnibus_test.rb b/test/unit/plugins/provisioners/chef/omnibus_test.rb index 9c42df1cc..b053f94bc 100644 --- a/test/unit/plugins/provisioners/chef/omnibus_test.rb +++ b/test/unit/plugins/provisioners/chef/omnibus_test.rb @@ -2,13 +2,14 @@ require_relative "../../../base" require Vagrant.source_root.join("plugins/provisioners/chef/omnibus") -describe VagrantPlugins::Chef::Omnibus, :focus do +describe VagrantPlugins::Chef::Omnibus do let(:prefix) { "curl -sL #{described_class.const_get(:OMNITRUCK)}" } let(:version) { :latest } let(:prerelease) { false } + let(:download_path) { nil } - let(:build_command) { described_class.build_command(version, prerelease) } + let(:build_command) { described_class.build_command(version, prerelease, download_path) } context "when prerelease is given" do let(:prerelease) { true } @@ -18,6 +19,14 @@ describe VagrantPlugins::Chef::Omnibus, :focus do end end + context "when download_path is given" do + let(:download_path) { '/tmp/path/to/omnibuses' } + + it "returns the correct command" do + expect(build_command).to eq("#{prefix} | sudo bash -s -- -d \"/tmp/path/to/omnibuses\"") + end + end + context "when version is :latest" do let(:version) { :latest } @@ -34,12 +43,13 @@ describe VagrantPlugins::Chef::Omnibus, :focus do end end - context "when prerelease and version are given" do + context "when prerelease and version and download_path are given" do let(:version) { "1.2.3" } let(:prerelease) { true } + let(:download_path) { "/some/path" } it "returns the correct command" do - expect(build_command).to eq("#{prefix} | sudo bash -s -- -p -v \"1.2.3\"") + expect(build_command).to eq("#{prefix} | sudo bash -s -- -p -v \"1.2.3\" -d \"/some/path\"") end end end diff --git a/test/unit/plugins/provisioners/salt/config_test.rb b/test/unit/plugins/provisioners/salt/config_test.rb index c640a7497..24bf24796 100644 --- a/test/unit/plugins/provisioners/salt/config_test.rb +++ b/test/unit/plugins/provisioners/salt/config_test.rb @@ -60,5 +60,23 @@ describe VagrantPlugins::Salt::Config do expect(result[error_key]).to be_empty end end + + context "grains_config" do + it "fails if grains_config is set and missing" do + subject.grains_config = "/nope/still/not/here" + subject.finalize! + + result = subject.validate(machine) + expect(result[error_key]).to_not be_empty + end + + it "is valid if is set and not missing" do + subject.grains_config = File.expand_path(__FILE__) + subject.finalize! + + result = subject.validate(machine) + expect(result[error_key]).to be_empty + end + end end end diff --git a/test/unit/plugins/pushes/ftp/adapter_test.rb b/test/unit/plugins/pushes/ftp/adapter_test.rb index 54bacc1d1..e929078cd 100644 --- a/test/unit/plugins/pushes/ftp/adapter_test.rb +++ b/test/unit/plugins/pushes/ftp/adapter_test.rb @@ -54,8 +54,8 @@ describe VagrantPlugins::FTPPush::FTPAdapter do end describe "#default_port" do - it "is 20" do - expect(subject.default_port).to eq(20) + it "is 21" do + expect(subject.default_port).to eq(21) end end diff --git a/test/unit/plugins/pushes/ftp/push_test.rb b/test/unit/plugins/pushes/ftp/push_test.rb index ca8ee2752..1f6773e24 100644 --- a/test/unit/plugins/pushes/ftp/push_test.rb +++ b/test/unit/plugins/pushes/ftp/push_test.rb @@ -9,7 +9,7 @@ describe VagrantPlugins::FTPPush::Push do let(:env) { isolated_environment } let(:config) do double("config", - host: "127.0.0.1:21212", + host: "127.0.0.1:51234", username: "sethvargo", password: "bacon", passive: false, @@ -17,12 +17,24 @@ describe VagrantPlugins::FTPPush::Push do destination: "/var/www/site", ) end + let(:ui) do + double("ui", + info: nil, + ) + end subject { described_class.new(env, config) } + before do + allow(env).to receive(:root_path) + .and_return(File.expand_path("..", __FILE__)) + allow(env).to receive(:ui) + .and_return(ui) + end + describe "#push" do before(:all) do - @server = FakeFtp::Server.new(21212, 21213) + @server = FakeFtp::Server.new(51234, 21213) @server.start @dir = Dir.mktmpdir @@ -93,34 +105,6 @@ describe VagrantPlugins::FTPPush::Push do end end - describe "#parse_host" do - let(:result) { subject.parse_host(host) } - - context "when no port is given" do - let(:host) { "127.0.0.1" } - - it "returns the url and port 22" do - expect(result).to eq(["127.0.0.1", "22"]) - end - end - - context "when a port is given" do - let(:host) { "127.0.0.1:23456" } - - it "returns the url and port 23456" do - expect(result).to eq(["127.0.0.1", "23456"]) - end - end - - context "when more than more port is given" do - let(:host) { "127.0.0.1:22:33:44" } - - it "returns the url and everything after" do - expect(result).to eq(["127.0.0.1", "22:33:44"]) - end - end - end - describe "#all_files" do before(:all) do @dir = Dir.mktmpdir diff --git a/test/unit/plugins/pushes/local-exec/push_test.rb b/test/unit/plugins/pushes/local-exec/push_test.rb index 6896428d1..1efdfa3b1 100644 --- a/test/unit/plugins/pushes/local-exec/push_test.rb +++ b/test/unit/plugins/pushes/local-exec/push_test.rb @@ -93,47 +93,9 @@ describe VagrantPlugins::LocalExecPush::Push do end describe "#execute!" do - let(:exit_code) { 0 } - let(:stdout) { "This is the output" } - let(:stderr) { "This is the errput" } - - let(:process) do - double("process", - exit_code: exit_code, - stdout: stdout, - stderr: stderr, - ) - end - - before do - allow(Vagrant::Util::Subprocess).to receive(:execute) - .and_return(process) - end - - it "creates a subprocess" do - expect(Vagrant::Util::Subprocess).to receive(:execute) + it "safe execs" do + expect(Vagrant::Util::SafeExec).to receive(:exec) expect { subject.execute! }.to_not raise_error end - - it "returns the resulting process" do - expect(subject.execute!).to be(process) - end - - context "when the exit code is non-zero" do - let(:exit_code) { 1 } - - it "raises an exception" do - klass = VagrantPlugins::LocalExecPush::Errors::CommandFailed - cmd = ["foo", "bar"] - - expect { subject.execute!(*cmd) }.to raise_error(klass) { |error| - expect(error.message).to eq(I18n.t("local_exec_push.errors.command_failed", - cmd: cmd.join(" "), - stdout: stdout, - stderr: stderr, - )) - } - end - end end end diff --git a/test/unit/support/shared/base_context.rb b/test/unit/support/shared/base_context.rb index 35c26788a..0f823948d 100644 --- a/test/unit/support/shared/base_context.rb +++ b/test/unit/support/shared/base_context.rb @@ -83,6 +83,18 @@ shared_context "unit" do return Pathname.new(d) end + # Stub the given environment in ENV, without actually touching ENV. Keys and + # values are converted to strings because that's how the real ENV works. + def stub_env(hash) + allow(ENV).to receive(:[]).and_call_original + + hash.each do |key, value| + allow(ENV).to receive(:[]) + .with(key.to_s) + .and_return(value.to_s) + end + end + # This helper provides temporary environmental variable changes. def with_temp_env(environment) # Build up the new environment, preserving the old values so we diff --git a/test/unit/vagrant/action/warden_test.rb b/test/unit/vagrant/action/warden_test.rb index b9758be7a..9c668e371 100644 --- a/test/unit/vagrant/action/warden_test.rb +++ b/test/unit/vagrant/action/warden_test.rb @@ -87,6 +87,6 @@ describe Vagrant::Action::Warden do expect { instance.call(data) }.to raise_error(SystemExit) # The recover should not have been called - expect(data.has_key?(:recover)).not_to be + expect(data.key?(:recover)).not_to be end end diff --git a/test/unit/vagrant/environment_test.rb b/test/unit/vagrant/environment_test.rb index 02effd7db..c5cf8370d 100644 --- a/test/unit/vagrant/environment_test.rb +++ b/test/unit/vagrant/environment_test.rb @@ -991,7 +991,7 @@ VF end def push - !!self.class.class_variable_set(:@@pushed, true) + self.class.class_variable_set(:@@pushed, true) end end end diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index 128df3d6f..5da1be84f 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -263,6 +263,17 @@ describe Vagrant::Machine do expect(foo).to eq(:bar) end + it "should pass any extra options to the environment as strings" do + action_name = :up + foo = nil + callable = lambda { |env| foo = env["foo"] } + + allow(provider).to receive(:action).with(action_name).and_return(callable) + instance.action(:up, "foo" => :bar) + + expect(foo).to eq(:bar) + end + it "should return the environment as a result" do action_name = :up callable = lambda { |env| env[:result] = "FOO" } diff --git a/test/unit/vagrant/util/hash_with_indifferent_access_test.rb b/test/unit/vagrant/util/hash_with_indifferent_access_test.rb index 397773eed..fdebeb374 100644 --- a/test/unit/vagrant/util/hash_with_indifferent_access_test.rb +++ b/test/unit/vagrant/util/hash_with_indifferent_access_test.rb @@ -22,7 +22,7 @@ describe Vagrant::Util::HashWithIndifferentAccess do it "allows indifferent key lookup" do instance["foo"] = "bar" expect(instance.key?(:foo)).to be - expect(instance.has_key?(:foo)).to be + expect(instance.key?(:foo)).to be expect(instance.include?(:foo)).to be expect(instance.member?(:foo)).to be end diff --git a/test/unit/vagrant_test.rb b/test/unit/vagrant_test.rb index 613e3a98b..ec317a628 100644 --- a/test/unit/vagrant_test.rb +++ b/test/unit/vagrant_test.rb @@ -75,7 +75,7 @@ describe Vagrant do expect(described_class.has_plugin?("bar")).to be_false end - it "finds plugins by gem version" do + it "finds plugins by gem name and version" do specs = [Gem::Specification.new] specs[0].name = "foo" specs[0].version = "1.2.3" @@ -83,6 +83,7 @@ describe Vagrant do expect(described_class.has_plugin?("foo", "~> 1.2.0")).to be_true expect(described_class.has_plugin?("foo", "~> 1.0.0")).to be_false + expect(described_class.has_plugin?("bar", "~> 1.2.0")).to be_false end end diff --git a/vagrant.gemspec b/vagrant.gemspec index b032b8f73..40ca48c1f 100644 --- a/vagrant.gemspec +++ b/vagrant.gemspec @@ -19,7 +19,7 @@ Gem::Specification.new do |s| s.add_dependency "childprocess", "~> 0.5.0" s.add_dependency "erubis", "~> 2.7.0" s.add_dependency "i18n", "~> 0.6.0" - s.add_dependency "listen", "~> 2.7.11" + s.add_dependency "listen", "~> 2.8.0" s.add_dependency "hashicorp-checkpoint", "~> 0.1.1" s.add_dependency "log4r", "~> 1.1.9", "< 1.1.11" s.add_dependency "net-ssh", ">= 2.6.6", "< 2.10.0" diff --git a/version.txt b/version.txt index bd8bf882d..f8a696c8d 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.7.0 +1.7.2 diff --git a/website/docs/Gemfile.lock b/website/docs/Gemfile.lock index 7e3a024b4..cced2615a 100644 --- a/website/docs/Gemfile.lock +++ b/website/docs/Gemfile.lock @@ -23,7 +23,7 @@ GEM compass-import-once (1.0.5) sass (>= 3.2, < 3.5) daemons (1.1.9) - eventmachine (1.0.3) + eventmachine (1.0.4) execjs (1.4.1) multi_json (~> 1.0) ffi (1.9.6) diff --git a/website/docs/source/layouts/layout.erb b/website/docs/source/layouts/layout.erb index 8a1883920..310d7b0a8 100644 --- a/website/docs/source/layouts/layout.erb +++ b/website/docs/source/layouts/layout.erb @@ -173,6 +173,7 @@ >Ansible >CFEngine >Chef Solo + >Chef Zero >Chef Client >Chef Apply >Docker diff --git a/website/docs/source/stylesheets/_base.less b/website/docs/source/stylesheets/_base.less index d78333d04..68790ad40 100644 --- a/website/docs/source/stylesheets/_base.less +++ b/website/docs/source/stylesheets/_base.less @@ -1,11 +1,11 @@ html { - font-size: 100%; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; - text-rendering: optimizeLegibility; - -webkit-tap-highlight-color: transparent; -} + font-size: 100%; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + text-rendering: optimizeLegibility; + -webkit-tap-highlight-color: transparent; +} body { font-family: @sans-serif-stack; font-size: @base-font-size; @@ -14,17 +14,18 @@ body { background-color: @white; letter-spacing: 2px; .museo-sans-regular; -} +} .wrapper { -margin-top: 80px; -} + margin-top: 80px; +} .container { -z-index: 999; //keep content on top -position: relative; -} + z-index: 999; + //keep content on top + position: relative; +} h1, h2, h3, @@ -36,272 +37,298 @@ h6 { color: inherit; text-rendering: optimizelegibility; .museo-sans-bold; + } +h1 { + @font-size: 70px; + font-size: @font-size; + line-height: 80px; + letter-spacing: 3px; - h1 { - @font-size: 70px; - font-size: @font-size; - line-height: 80px; - letter-spacing: 3px; + span { + font-size: @headline-span-size; + display: block; - span { - font-size: @headline-span-size; - display: block; - } + } + &.all-caps { + text-transform: uppercase; + text-align: center; + font-size: 40px; + } - &.all-caps { - text-transform: uppercase; - text-align: center; - font-size: 40px; - } - } - - h2 { - @font-size: 30px; - font-size: @font-size; - line-height: 35px; - } - - h3 { - @font-size: 30px; - font-size: @font-size; - line-height: @font-size; - } - - h4 { - @font-size: 24px; - font-size: @font-size; - line-height: @font-size; - } - - h5 { - @font-size: 20px; - font-size: @font-size; - line-height: @font-size; - } - - h6 { - @font-size: 12px; - font-size: @font-size; - line-height: @font-size; - } - -p, td { - letter-spacing: normal; - line-height: 32px; - - a { - color: @docs-blue; - text-decoration: none; - border-bottom: 1px solid @docs-blue; - - &:hover { - text-decoration: none; - color: darken(@blue, 10%); - border-bottom: 1px solid darken(@blue, 10%); - } - } } +h2 { + @font-size: 30px; + font-size: @font-size; + line-height: 35px; +} +h3 { + @font-size: 30px; + font-size: @font-size; + line-height: @font-size; + +} +h4 { + @font-size: 24px; + font-size: @font-size; + line-height: @font-size; + +} +h5 { + @font-size: 20px; + font-size: @font-size; + line-height: @font-size; + +} +h6 { + @font-size: 12px; + font-size: @font-size; + line-height: @font-size; + +} +p, +td { + letter-spacing: normal; + line-height: 32px; + + a { + color: @docs-blue; + text-decoration: none; + border-bottom: 1px solid @docs-blue; + + &:hover { + text-decoration: none; + color: darken(@blue, 10%); + border-bottom: 1px solid darken(@blue, 10%); + } + } + +} a { - color: inherit; - text-decoration: none; + color: inherit; + text-decoration: none; + &:hover { + text-decoration: none; + color: @purple; + .animate-text-color; - &:hover { - text-decoration: none; - color: @purple; - .animate-text-color; - } + } + &:active { + color: @blue; - &:active { - color: @blue; - } + } + &:visited { - &:visited { + } - } } - ul { -} +} li { -line-height: @base-line-height; -} + line-height: @base-line-height; +} blockquote { - border: none; + border: none; margin: 60px; - p { // blockquote p - font-size: @base-font-size * 2; - line-height: @base-line-height * 2; - font-style: italic; + p { + // blockquote p + font-size: @base-font-size * 2; + line-height: @base-line-height * 2; + font-style: italic; } -} +} strong { -.museo-sans-bold; -} + .museo-sans-bold; +} em { -.museo-sans-regular-italic; -} + .museo-sans-regular-italic; +} br { -display:block; -line-height: (@baseline * 2); -} + display: block; + line-height: (@baseline * 2); +} pre, code { -font-family: @mono-stack; -} + font-family: @mono-stack; +} code { -font-size: inherit; -} + font-size: inherit; +} pre { -border: none; -font-size: @base-font-size; -background: @black; -color: @white; -padding: 20px; -line-height: @base-line-height; -margin-top: 20px; -margin-bottom: 20px; + border: none; + font-size: @base-font-size; + background: @black; + color: @white; + padding: 20px; + line-height: @base-line-height; + margin-top: 20px; + margin-bottom: 20px; + + span { + color: @code-highlight-text; + } - span { - color: @code-highlight-text; - } } - hr { -} +} .vr { -width: 2px; -height: 100%; -} + width: 2px; + height: 100%; +} form { -} +} input { -letter-spacing: 3px; + letter-spacing: 3px; - &:focus { - outline: none; - } + &:focus { + outline: none; + } } +::-webkit-input-placeholder { - ::-webkit-input-placeholder { - overflow: visible; - padding-top: 3px; - color: @light-gray-text; - } - - input:-moz-placeholder { - overflow: visible; - padding-top: 3px; - color: @light-gray-text; - } + overflow: visible; + padding-top: 3px; + color: @light-gray-text; +} +input:-moz-placeholder { + overflow: visible; + padding-top: 3px; + color: @light-gray-text; +} /* type and styles */ .meta, .legal, .date { -color: @medium-gray-text; -line-height: @base-line-height; -.museo-sans-regular; + color: @medium-gray-text; + line-height: @base-line-height; + .museo-sans-regular; + } +.date { + text-transform: uppercase; - .date { - text-transform: uppercase; - } - +} .button { -color: @white; -text-align: center; -background-color: @primary-button-color; -display: block; -padding: 15px 0; -margin-top: 20px !important; -text-transform: uppercase; -font-size: 25px; -letter-spacing: 5px; -.museo-sans-light; -.rounded; -.hover; + color: @white; + text-align: center; + background-color: @primary-button-color; + display: block; + padding: 15px 0; + margin-top: 20px !important; + text-transform: uppercase; + font-size: 25px; + letter-spacing: 5px; + .museo-sans-light; + .rounded; + .hover; - &.inline-button { - background-color: @vagrant-blue; - padding: 5px 20px; - color: @white !important; - font-size: 15px; - letter-spacing: 1px; - .rounded; + &.inline-button { + background-color: @vagrant-blue; + padding: 5px 20px; + color: @white !important; + font-size: 15px; + letter-spacing: 1px; + .rounded; + + a, + a:hover { + color: @white; + } + &.next-button, + &.prev-button { + max-width: 33%; + white-space: nowrap; + } + &.next-button { + float: right; + &:before { + content: "Next:"; + display: inline-block; + padding-right: 3px; + } + &:after { + content: "\00BB"; + display: inline-block; + padding-left: 3px; + } + + } + &.prev-button { + float: left; + &:before { + content: "\00AB\0020Previous: "; + display: inline-block; + padding-right: 3px; + } + } - a, - a:hover { - color: @white; } -} + &.white-button { + background: fade(@white, 20%); -&.white-button { - background: fade(@white, 20%); + &:hover { + background: fade(@white, 30%); + } + } + &.secondary-button { + background: @light-gray; + + &:hover { + background: @purple; + } + + } + &.with-carat span { + margin-right: -10px; + //recenter text if there's a carat after text + + } + span { + // button text styles can go here + + } &:hover { - background: fade(@white, 30%); + background-color: @purple; + .animate-background-color; + } -} + &:active { -&.secondary-button { - background: @light-gray; - &:hover { - background: @purple; } -} - -&.with-carat span { - margin-right: -10px; //recenter text if there's a carat after text + &.disabled { + background-color: @light-gray-background; + } } - -span { - // button text styles can go here -} - -&:hover { - background-color: @purple; - .animate-background-color; -} - -&:active { - -} - -&.disabled { - background-color: @light-gray-background; -} - -} - a.read-more { color: @blue; &:hover { color: darken(@blue, 10%); } -} +} // misc. styles .loading { text-align: center; @@ -310,8 +337,8 @@ a.read-more { letter-spacing: 5px; color: @medium-gray-text; padding: 30px 0 20px; -} -.pinned { - position:fixed; +} +.pinned { + position: fixed; } diff --git a/website/docs/source/v2/cli/login.html.md b/website/docs/source/v2/cli/login.html.md index c8f6ee7d9..1ff6e9c6d 100644 --- a/website/docs/source/v2/cli/login.html.md +++ b/website/docs/source/v2/cli/login.html.md @@ -19,6 +19,7 @@ boxes or [Vagrant Share](/v2/share/index.html) require a login. The reference of available command-line flags to this command is available below. + ## Options * `--check` - This will check if you're logged in. In addition to outputting @@ -28,3 +29,32 @@ is available below. * `--logout` - This will log you out if you're logged in. If you're already logged out, this command will do nothing. It is not an error to call this command if you're already logged out. + +* `--token` - This will set the Atlas login token manually to the provided + string. It is assumed this token is a valid Atlas access token. + + +## Examples + +Securely authenticate to Atlas using a username and password: + +```text +$ vagrant login +# ... +Atlas username: +Atlas password: +``` + +Check if the current user is authenticated: + +```text +$ vagrant login --check +You are already logged in. +``` + +Securely authenticate with Atlas using a token: + +```text +$ vagrant login --token ABCD1234 +The token was successfully saved. +``` diff --git a/website/docs/source/v2/docker/basics.html.md b/website/docs/source/v2/docker/basics.html.md index 6f2f41c48..9f4dd97a6 100644 --- a/website/docs/source/v2/docker/basics.html.md +++ b/website/docs/source/v2/docker/basics.html.md @@ -65,6 +65,8 @@ and networking options into Docker volumes and forwarded ports. You don't have to use the Docker-specific configurations to do this. This helps keep your Vagrantfile similar to how it has always looked. +Private and public networks are not currently supported. + ## Host VM On systems that can't run Linux containers natively, such as Mac OS X diff --git a/website/docs/source/v2/docker/configuration.html.md b/website/docs/source/v2/docker/configuration.html.md index a8dfed3c7..73bde2df3 100644 --- a/website/docs/source/v2/docker/configuration.html.md +++ b/website/docs/source/v2/docker/configuration.html.md @@ -36,7 +36,8 @@ General settings: but not to the host machine. Useful for links. * `link` (method, string argument) - Link this container to another - by name. Example: `docker.link("db:db")`. Note, if you're linking to + by name. The argument should be in the format of `(name:alias)`. + Example: `docker.link("db:db")`. Note, if you're linking to another container in the same Vagrantfile, make sure you call `vagrant up` with the `--no-parallel` flag. diff --git a/website/docs/source/v2/getting-started/boxes.html.md b/website/docs/source/v2/getting-started/boxes.html.md index 7ed1f83d7..9d165d2ad 100644 --- a/website/docs/source/v2/getting-started/boxes.html.md +++ b/website/docs/source/v2/getting-started/boxes.html.md @@ -72,3 +72,6 @@ feature to allow you to find the box you care about. In addition to finding free boxes, HashiCorp's Atlas lets you host your own boxes, as well as private boxes if you intend on creating boxes for your own organization. + +Project Setup +Up And SSH diff --git a/website/docs/source/v2/getting-started/index.html.md b/website/docs/source/v2/getting-started/index.html.md index 687294274..26cbae2cb 100644 --- a/website/docs/source/v2/getting-started/index.html.md +++ b/website/docs/source/v2/getting-started/index.html.md @@ -17,7 +17,7 @@ since it is free, available on every major platform, and built-in to Vagrant. After reading the guide though, don't forget that Vagrant can work with [many other providers](/v2/getting-started/providers.html). -Before diving into your first project, please [install Vagrant](/v2/installation/index.html). +Before diving into your first project, please [install the latest version of Vagrant](/v2/installation/index.html). And because we'll be using [VirtualBox](http://www.virtualbox.org) as our provider for the getting started guide, please install that as well. @@ -54,3 +54,5 @@ comfort of your own machine. The rest of this guide will walk you through setting up a more complete project, covering more features of Vagrant. + +Project Setup diff --git a/website/docs/source/v2/getting-started/networking.html.md b/website/docs/source/v2/getting-started/networking.html.md index 150b4cab1..69ac4c3fc 100644 --- a/website/docs/source/v2/getting-started/networking.html.md +++ b/website/docs/source/v2/getting-started/networking.html.md @@ -43,3 +43,6 @@ Vagrant also has other forms of networking, allowing you to assign a static IP address to the guest machine, or to bridge the guest machine onto an existing network. If you're interested in other options, read the [networking](/v2/networking/index.html) page. + +Provisioning +Share diff --git a/website/docs/source/v2/getting-started/project_setup.html.md b/website/docs/source/v2/getting-started/project_setup.html.md index e36fac01c..1a2029bd1 100644 --- a/website/docs/source/v2/getting-started/project_setup.html.md +++ b/website/docs/source/v2/getting-started/project_setup.html.md @@ -36,3 +36,6 @@ set up Vagrant for an existing project. The Vagrantfile is meant to be committed to version control with your project, if you use version control. This way, every person working with that project can benefit from Vagrant without any upfront work. + +Getting Started +Boxes diff --git a/website/docs/source/v2/getting-started/providers.html.md b/website/docs/source/v2/getting-started/providers.html.md index abda2deec..9dfd31d71 100644 --- a/website/docs/source/v2/getting-started/providers.html.md +++ b/website/docs/source/v2/getting-started/providers.html.md @@ -35,3 +35,5 @@ flags necessary. For more information on providers, read the full documentation on [providers](/v2/providers/index.html). + +Rebuild diff --git a/website/docs/source/v2/getting-started/provisioning.html.md b/website/docs/source/v2/getting-started/provisioning.html.md index ad2b24150..ceb79e82d 100644 --- a/website/docs/source/v2/getting-started/provisioning.html.md +++ b/website/docs/source/v2/getting-started/provisioning.html.md @@ -75,3 +75,6 @@ directory, which is the default synced folder setup by Vagrant. You can play around some more by creating some more files and viewing them from the terminal, but in the next step we'll cover networking options so that you can use your own browser to access the guest machine. + +Synced Folders +Networking diff --git a/website/docs/source/v2/getting-started/rebuild.html.md b/website/docs/source/v2/getting-started/rebuild.html.md index aa5a3bc40..1555ca6b5 100644 --- a/website/docs/source/v2/getting-started/rebuild.html.md +++ b/website/docs/source/v2/getting-started/rebuild.html.md @@ -15,3 +15,6 @@ $ vagrant up That's it! Since the Vagrant environment is already all configured via the Vagrantfile, you or any of your coworkers simply have to run a `vagrant up` at any time and Vagrant will recreate your work environment. + +Teardown +Providers diff --git a/website/docs/source/v2/getting-started/share.html.md b/website/docs/source/v2/getting-started/share.html.md index 694bd5d15..46cde9c70 100644 --- a/website/docs/source/v2/getting-started/share.html.md +++ b/website/docs/source/v2/getting-started/share.html.md @@ -54,3 +54,6 @@ the URL again to verify that your environment is no longer being shared. Vagrant Share is much more powerful than simply HTTP sharing. For more details, see the [complete Vagrant Share documentation](/v2/share/index.html). + +Networking +Teardown diff --git a/website/docs/source/v2/getting-started/synced_folders.html.md b/website/docs/source/v2/getting-started/synced_folders.html.md index 11612e84c..80c42c876 100644 --- a/website/docs/source/v2/getting-started/synced_folders.html.md +++ b/website/docs/source/v2/getting-started/synced_folders.html.md @@ -40,3 +40,6 @@ the folders in sync. With [synced folders](/v2/synced-folders/index.html), you can continue to use your own editor on your host machine and have the files sync into the guest machine. + +Up And SSH +Provisioning diff --git a/website/docs/source/v2/getting-started/teardown.html.md b/website/docs/source/v2/getting-started/teardown.html.md index 764de1969..04ce15f9f 100644 --- a/website/docs/source/v2/getting-started/teardown.html.md +++ b/website/docs/source/v2/getting-started/teardown.html.md @@ -23,19 +23,22 @@ work. The downside is that the virtual machine still eats up your disk space, and requires even more disk space to store all the state of the virtual machine RAM on disk. -**Halting** the virtual machine by calling `vagrant halt` will gracefully -shut down the guest operating system and power down the guest machine. -You can use `vagrant up` when you're ready to boot it again. The benefit of -this method is that it will cleanly shut down your machine, preserving the +**Halting** the virtual machine by calling `vagrant halt` will gracefully +shut down the guest operating system and power down the guest machine. +You can use `vagrant up` when you're ready to boot it again. The benefit of +this method is that it will cleanly shut down your machine, preserving the contents of disk, and allowing it to be cleanly started again. The downside is that it'll take some extra time to start from a cold boot, and the guest machine still consumes disk space. -**Destroying** the virtual machine by calling `vagrant destroy` will remove -all traces of the guest machine from your system. It'll stop the guest machine, -power it down, and remove all of the guest hard disks. Again, when you're ready to +**Destroying** the virtual machine by calling `vagrant destroy` will remove +all traces of the guest machine from your system. It'll stop the guest machine, +power it down, and remove all of the guest hard disks. Again, when you're ready to work again, just issue a `vagrant up`. The benefit of this is that _no cruft_ is left on your machine. The disk space and RAM consumed by the guest machine is reclaimed and your host machine is left clean. The downside is that `vagrant up` to get working again will take some extra time since it has to reimport the machine and reprovision it. + +Share +Rebuild diff --git a/website/docs/source/v2/getting-started/up.html.md b/website/docs/source/v2/getting-started/up.html.md index 3a9686afa..f1e59a6cf 100644 --- a/website/docs/source/v2/getting-started/up.html.md +++ b/website/docs/source/v2/getting-started/up.html.md @@ -33,3 +33,6 @@ virtual machine. Cool. When you're done fiddling around with the machine, run `vagrant destroy` back on your host machine, and Vagrant will remove all traces of the virtual machine. + +Boxes +Synced Folders diff --git a/website/docs/source/v2/hyperv/configuration.html.md b/website/docs/source/v2/hyperv/configuration.html.md index 2459c7c0d..18ed9e89c 100644 --- a/website/docs/source/v2/hyperv/configuration.html.md +++ b/website/docs/source/v2/hyperv/configuration.html.md @@ -8,6 +8,15 @@ sidebar_current: "hyperv-configuration" The Hyper-V provider has some provider-specific configuration options you may set. A complete reference is shown below: + * `vmname` (string) - Name of virtual mashine as shown in Hyper-V manager. + Defaults is taken from box image XML. + * `cpus` (integer) - Number of virtual CPU given to mashine. + Defaults is taken from box image XML. + * `memory` (integer) - Number of MegaBytes allocated to VM at startup. + Defaults is taken from box image XML. + * `maxmemory` (integer) - Number of MegaBytes maximal allowed to allocate for VM + This parameter is switch on Dynamic Allocation of memory. + Defaults is taken from box image XML. * `ip_address_timeout` (integer) - The time in seconds to wait for the virtual machine to report an IP address. This defaults to 120 seconds. This may have to be increased if your VM takes longer to boot. diff --git a/website/docs/source/v2/plugins/hosts.html.md b/website/docs/source/v2/plugins/hosts.html.md index aaf1d6bdf..aed652f84 100644 --- a/website/docs/source/v2/plugins/hosts.html.md +++ b/website/docs/source/v2/plugins/hosts.html.md @@ -47,7 +47,7 @@ Implementations of hosts subclass `Vagrant.plugin("2", "host")`. Within this implementation, only the `detect?` method needs to be implemented. The `detect?` method is called by Vagrant very early on in its initialization -process to determine if the OS that Vagrant is running on is this hsot. +process to determine if the OS that Vagrant is running on is this host. If you detect that it is your operating system, return `true` from `detect?`. Otherwise, return `false`. diff --git a/website/docs/source/v2/provisioning/ansible.html.md b/website/docs/source/v2/provisioning/ansible.html.md index 9301e0fb8..10fd1fc6d 100644 --- a/website/docs/source/v2/provisioning/ansible.html.md +++ b/website/docs/source/v2/provisioning/ansible.html.md @@ -33,30 +33,30 @@ a single page of documentation. ## Inventory File When using Ansible, it needs to know on which machines a given playbook should run. It does -this by way of an [inventory](http://docs.ansible.com/intro_inventory.html) file which lists those machines. In the context of Vagrant, -there are two ways to approach working with inventory files. +this by way of an [inventory](http://docs.ansible.com/intro_inventory.html) file which lists those machines. +In the context of Vagrant, there are two ways to approach working with inventory files. + +### Auto-Generated Inventory The first and simplest option is to not provide one to Vagrant at all. Vagrant will generate an inventory file encompassing all of the virtual machines it manages, and use it for provisioning machines. The generated inventory file is stored as part of your local Vagrant environment in `.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory`. -The `ansible.groups` option can be used to pass a hash of group -names and group members to be included in the generated inventory file. Group variables -are intentionally not supported, as this practice is not recommended. -For example: +**Groups of Hosts** + +The `ansible.groups` option can be used to pass a hash of group names and group members to be included in the generated inventory file. + +With this configuration example: ``` ansible.groups = { "group1" => ["machine1"], - "group2" => ["machine2", "machine3"], - "all_groups:children" => ["group1", "group2", "group3"] + "group2" => ["machine2"], + "all_groups:children" => ["group1", "group2"] } ``` -Note that unmanaged machines and undefined groups are not added to the inventory. -For example, `group3` in the above example would not be added to the inventory file. - -A generated inventory might look like: +Vagrant would generate an inventory file that might look like: ``` # Generated by Vagrant @@ -75,6 +75,24 @@ group1 group2 ``` +**Notes** + + * The generation of group variables blocks (e.g. `[group1:vars]`) are intentionally not supported, as it is [not recommended to store group variables in the main inventory file](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). A good practice is to store these group (or host) variables in `YAML` files stored in `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory. + * Unmanaged machines and undefined groups are not added to the inventory, to avoid useless Ansible errors (e.g. *unreachable host* or *undefined child group*) + +For example, `machine3`, `group3` and `group1:vars` in the example below would not be added to the generated inventory file: + +``` +ansible.groups = { + "group1" => ["machine1"], + "group2" => ["machine2", "machine3"], + "all_groups:children" => ["group1", "group2", "group3"], + "group1:vars" => { "variable1" => 9, "variable2" => "example" } +} +``` + +### Static Inventory + The second option is for situations where you'd like to have more control over the inventory management. With the `ansible.inventory_path` option, you can reference a specific inventory resource (e.g. a static inventory file, a [dynamic inventory script](http://docs.ansible.com/intro_dynamic_inventory.html) or even [multiple inventories stored in the same directory](http://docs.ansible.com/intro_dynamic_inventory.html#using-multiple-inventory-sources)). Vagrant will then use this inventory information instead of generating it. @@ -90,8 +108,10 @@ Where the above IP address is one set in your Vagrantfile: config.vm.network :private_network, ip: "192.168.111.222" ``` -Note that machine names in `Vagrantfile` and `ansible.inventory_path` file should correspond, -unless you use `ansible.limit` option to reference the correct machines. +**Notes:** + + * The machine names in `Vagrantfile` and `ansible.inventory_path` files should correspond, unless you use `ansible.limit` option to reference the correct machines. + * The SSH host addresses (and ports) must obviously be specified twice, in `Vagrantfile` and `ansible.inventory_path` files. ## Playbook @@ -207,6 +227,12 @@ by the sudo command. Vagrant is designed to provision [multi-machine environments](/v2/multi-machine) in sequence, but the following configuration pattern can be used to take advantage of Ansible parallelism: ``` + # By default, Vagrant 1.7+ automatically inserts a different + # insecure keypair for each new VM created. The easiest way + # to use the same keypair for all the machines is to disable + # this feature and rely on the legacy insecure key. + config.ssh.insert_key = false + config.vm.define 'machine2' do |machine| machine.vm.hostname = 'machine2' machine.vm.network "private_network", ip: "192.168.77.22" diff --git a/website/docs/source/v2/provisioning/basic_usage.html.md b/website/docs/source/v2/provisioning/basic_usage.html.md index f61cae325..d53439a05 100644 --- a/website/docs/source/v2/provisioning/basic_usage.html.md +++ b/website/docs/source/v2/provisioning/basic_usage.html.md @@ -45,7 +45,7 @@ it can greatly improve readability. Additionally, some provisioners, like the Chef provisioner, have special methods that can be called within that block to ease configuration that can't be done with the key/value approach. -Provisioners can also be named. These names are used cosmetically for output +Provisioners can also be named (since 1.7.0). These names are used cosmetically for output as well as overriding provisioner settings (covered further below). An example of naming provisioners is shown below: diff --git a/website/docs/source/v2/provisioning/chef_apply.html.md b/website/docs/source/v2/provisioning/chef_apply.html.md index 6aae0927a..268894cb2 100644 --- a/website/docs/source/v2/provisioning/chef_apply.html.md +++ b/website/docs/source/v2/provisioning/chef_apply.html.md @@ -29,9 +29,6 @@ This section lists the complete set of available options for the Chef Apply provisioner. More detailed examples of how to use the provisioner are available below this section. -Due to the unqiue nature of Chef Apply, the Chef Apply provisioner does not -inherit the [common options for other Chef provisioners](/v2/provisioning/chef_common.html). - * `recipe` (string) - The raw recipe contents to execute using Chef Apply on the guest. @@ -44,6 +41,9 @@ inherit the [common options for other Chef provisioners](/v2/provisioning/chef_c `/tmp/vagrant-chef-apply-#` where `#` is a unique counter generated by Vagrant to prevent collisions. +In addition to all the options listed above, the Chef Apply provisioner supports +the [common options for all Chef provisioners](/v2/provisioning/chef_common.html). + ## Specifying a Recipe The easiest way to get started with the Chef Apply provisioner is to just diff --git a/website/docs/source/v2/provisioning/chef_client.html.md b/website/docs/source/v2/provisioning/chef_client.html.md index a22ddcc47..d56359050 100644 --- a/website/docs/source/v2/provisioning/chef_client.html.md +++ b/website/docs/source/v2/provisioning/chef_client.html.md @@ -82,12 +82,15 @@ end There are a few more configuration options available. These generally don't need to be modified but are available if your Chef Server requires customization -of these variables: +of these variables. * `client_key_path` * `node_name` * `validation_client_name` +In addition to all the options listed above, the Chef Client provisioner supports +the [common options for all Chef provisioners](/v2/provisioning/chef_common.html). + ## Cleanup When you provision your Vagrant virtual machine with Chef Server, it creates a diff --git a/website/docs/source/v2/provisioning/chef_common.html.md b/website/docs/source/v2/provisioning/chef_common.html.md index ed776ad0c..d63a0d680 100644 --- a/website/docs/source/v2/provisioning/chef_common.html.md +++ b/website/docs/source/v2/provisioning/chef_common.html.md @@ -5,12 +5,55 @@ sidebar_current: "provisioning-chefcommon" # Shared Chef Options -This page documents the list of available options that are available in the -[Chef Solo](/v2/provisioning/chef_solo.html), -[Chef Zero](/v2/provisioning/chef_zero.html) -and -[Chef Client](/v2/provisioning/chef_client.html) -provisioners. +## All Chef Provisioners + +The following options are available to all Chef provisioners. Many of these +options are for advanced users only and should not be used unless you understand +their purpose. + +- `binary_path` (string) - The path to Chef's `bin/` directory on the guest + machine. + +- `binary_env` (string) - Arbitrary environment variables to set before running + the Chef provisioner command. This should be of the format `KEY=value` as a + string. + +- `install` (boolean, string) - Install Chef on the system if it does not exist. + The default value is "true", which will use the official Omnibus installer + from Chef. This is a trinary attribute (it can have three values): + + - `true` (boolean) - install Chef + - `false` (boolean) - do not install Chef + - `"force"` (string) - install Chef, even if it is already installed at the + proper version on the guest + +- `installer_download_path` (string) - The path where the Chef installer will be + downloaded to. This option is only honored if the `install` attribute is + `true` or `"force"`. The default value is to use the path provided by Chef's + Omnibus installer, which varies between releases. + +- `log_level` (string) - The Chef log level. See the Chef docs for acceptable + values. + +- `prerelease` (boolean) - Install a prerelease version of Chef. The default + value is false. + +- `version` (string) - The version of Chef to install on the guest. If Chef is + already installed on the system, the installed version is compared with the + requested version. If they match, no action is taken. If they do not match, + the value specified in this attribute will be installed in favor of the + existing version (a message will be displayed). + + You can also specify "latest" (default), which will install the latest + version of Chef on the system. In this case, Chef will use whatever + version is on the system. To force the newest version of Chef to be + installed on every provision, set the {#install} option to "force". + + +## Runner Chef Provisioners + +The following options are available to any of the Chef "runner" provisioners +which include [Chef Solo](/v2/provisioning/chef_solo.html), [Chef Zero](/v2/provisioning/chef_zero.html), and [Chef Client](/v2/provisioning/chef_client.html). * `arguments` (string) - A list of additional arguments to pass on the command-line to Chef. Since these are passed in a shell-like environment, @@ -21,9 +64,6 @@ provisioners. This defaults to 1. This can be increased to a higher number if your Chef runs take multiple runs to reach convergence. -* `binary_path` (string) - The path to the directory of the Chef executable - binaries. By default, Vagrant looks for the proper Chef binary on the PATH. - * `custom_config_path` (string) - A path to a custom Chef configuration local on your machine that will be used as the Chef configuration. This Chef configuration will be loaded _after_ the Chef configuration that Vagrant diff --git a/website/docs/source/v2/provisioning/chef_solo.html.md b/website/docs/source/v2/provisioning/chef_solo.html.md index d916f4fe2..129e17e17 100644 --- a/website/docs/source/v2/provisioning/chef_solo.html.md +++ b/website/docs/source/v2/provisioning/chef_solo.html.md @@ -32,10 +32,6 @@ This section lists the complete set of available options for the Chef Solo provisioner. More detailed examples of how to use the provisioner are available below this section. -Note that only the Chef-solo specific options are shown below. There is -also a large set of [common options](/v2/provisioning/chef_common.html) -that are available with all Chef provisioners. - * `cookbooks_path` (string or array) - A list of paths to where cookbooks are stored. By default this is "cookbooks", expecting a cookbooks folder relative to the Vagrantfile location. @@ -62,6 +58,9 @@ that are available with all Chef provisioners. this will use the default synced folder type. For example, you can set this to "nfs" to use NFS synced folders. +In addition to all the options listed above, the Chef Solo provisioner supports +the [common options for all Chef provisioners](/v2/provisioning/chef_common.html). + ## Specifying a Run List The easiest way to get started with the Chef Solo provisioner is to just diff --git a/website/docs/source/v2/provisioning/chef_zero.html.md b/website/docs/source/v2/provisioning/chef_zero.html.md index f716d3ff9..ec50dac0a 100644 --- a/website/docs/source/v2/provisioning/chef_zero.html.md +++ b/website/docs/source/v2/provisioning/chef_zero.html.md @@ -31,13 +31,12 @@ This section lists the complete set of available options for the Chef Zero provisioner. More detailed examples of how to use the provisioner are available below this section. -Note that only the Chef Zero specific options are shown below, but all [Chef -Solo options](/v2/provisioning/chef_solo.html), including the [common Chef -provisioner options](/v2/provisioning/chef_common.html), are also inherited. - * `nodes_path` (string) - A path where the Chef nodes are stored. Be default, no node path is set. +In addition to all the options listed above, the Chef Zero provisioner supports +the [common options for all Chef provisioners](/v2/provisioning/chef_common.html). + ## Usage The Chef Zero provisioner is configured basically the same way as the Chef Solo diff --git a/website/docs/source/v2/provisioning/salt.html.md b/website/docs/source/v2/provisioning/salt.html.md index f66ac7c60..ddc81fa90 100644 --- a/website/docs/source/v2/provisioning/salt.html.md +++ b/website/docs/source/v2/provisioning/salt.html.md @@ -56,7 +56,7 @@ on this machine. Not supported on Windows. `false`. Not supported on Windows. * `install_type` (stable | git | daily | testing) - Whether to install from a -distribution's stable package manager, git tree-ish, daily ppa, or testing repository. +distribution's stable package manager, git tree-ish, daily ppa, or testing repository. Not supported on Windows. * `install_args` (develop) - When performing a git install, @@ -77,6 +77,7 @@ a custom salt minion config file. * `minion_pub` (salt/key/minion.pub) - Path to your minion public key +* `grains_config` (string) - Path to a custom salt grains file. ## Master Options These only make sense when `install_master` is `true`. diff --git a/website/docs/source/v2/push/heroku.html.md b/website/docs/source/v2/push/heroku.html.md index dc730dc62..90aa20e82 100644 --- a/website/docs/source/v2/push/heroku.html.md +++ b/website/docs/source/v2/push/heroku.html.md @@ -10,7 +10,7 @@ description: |- ## Heroku Strategy -[Heroku][] is a public IAAS provider that makes it easy to deploy an +[Heroku][] is a public PAAS provider that makes it easy to deploy an application. The Vagrant Push Heroku strategy pushes your application's code to Heroku. diff --git a/website/docs/source/v2/share/connect.html.md b/website/docs/source/v2/share/connect.html.md index 37a3bf8e9..c7074d675 100644 --- a/website/docs/source/v2/share/connect.html.md +++ b/website/docs/source/v2/share/connect.html.md @@ -29,7 +29,7 @@ machines. `vagrant connect` creates a tiny virtual machine that takes up only around 20 MB in RAM, using VirtualBox or VMware (more provider support is coming soon). -Any traffic sent to this tiny virtual machine is then proxies through to +Any traffic sent to this tiny virtual machine is then proxied through to the shared Vagrant environment as if it were directed at it. ## Beware: Vagrant Insecure Key diff --git a/website/docs/source/v2/synced-folders/nfs.html.md b/website/docs/source/v2/synced-folders/nfs.html.md index 1e0959581..dbe565b48 100644 --- a/website/docs/source/v2/synced-folders/nfs.html.md +++ b/website/docs/source/v2/synced-folders/nfs.html.md @@ -90,7 +90,7 @@ Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/ d -ibak /etc/exports %admin ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE ``` -For Linux, sudoers should look like this: +For Ubuntu Linux , sudoers should look like this: ``` Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports @@ -101,3 +101,14 @@ Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports %sudo ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE ``` +For Fedora Linux, sudoers might look like this (given your user +belongs to the vagrant group): + +``` +Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports +Cmnd_Alias VAGRANT_NFSD_CHECK = /usr/bin/systemctl status nfs-server.service +Cmnd_Alias VAGRANT_NFSD_START = /usr/bin/systemctl start nfs-server.service +Cmnd_Alias VAGRANT_NFSD_APPLY = /usr/sbin/exportfs -ar +Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /bin/sed -r -e * d -ibak /etc/exports +%vagrant ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD_CHECK, VAGRANT_NFSD_START, VAGRANT_NFSD_APPLY, VAGRANT_EXPORTS_REMOVE +``` diff --git a/website/docs/source/v2/synced-folders/rsync.html.md b/website/docs/source/v2/synced-folders/rsync.html.md index 62e88d0dd..0d242676e 100644 --- a/website/docs/source/v2/synced-folders/rsync.html.md +++ b/website/docs/source/v2/synced-folders/rsync.html.md @@ -44,7 +44,7 @@ the destination folder. The rsync synced folder type accepts the following options: * `rsync__args` (array of strings) - A list of arguments to supply - to `rsync`. By default this is `["--verbose", "--archive", "--delete", "-z"]`. + to `rsync`. By default this is `["--verbose", "--archive", "--delete", "-z", "--copy-links"]`. * `rsync__auto` (boolean) - If false, then `rsync-auto` will not watch and automatically sync this folder. By default, this is true. @@ -81,7 +81,7 @@ permissions, use `"--rsync-path='sudo rsync'"` to run rsync with sudo on the gue
 Vagrant.configure("2") do |config|
   config.vm.synced_folder "bin", "/usr/local/bin", type: "rsync",
-    rsync__exclude: ".git/"
+    rsync__exclude: ".git/",
     rsync__args: ["--verbose", "--rsync-path='sudo rsync'", "--archive", "--delete", "-z"]
 end
 
diff --git a/website/docs/source/v2/vagrantfile/machine_settings.html.md b/website/docs/source/v2/vagrantfile/machine_settings.html.md index 8ea060de5..26565200e 100644 --- a/website/docs/source/v2/vagrantfile/machine_settings.html.md +++ b/website/docs/source/v2/vagrantfile/machine_settings.html.md @@ -64,7 +64,7 @@ bundle. `config.vm.box_download_ca_path` - Path to a directory containing CA certificates for downloading a box directly. By default, Vagrant will -use the Mozilla CA cert bundle.. +use the Mozilla CA cert bundle.
`config.vm.box_download_insecure` - If true, then SSL certificates diff --git a/website/docs/source/v2/vagrantfile/winrm_settings.html.md b/website/docs/source/v2/vagrantfile/winrm_settings.html.md index 462ccf56e..add316a40 100644 --- a/website/docs/source/v2/vagrantfile/winrm_settings.html.md +++ b/website/docs/source/v2/vagrantfile/winrm_settings.html.md @@ -44,3 +44,17 @@ example, if this is set to 5985 (the default), and Vagrant detects a forwarded port to port 5985 on the guest from port 4567 on the host, Vagrant will attempt to use port 4567 to talk to the guest if there is no other option. +
+ +Warning: In order for Vagrant to communicate with a Windows +guest, you must allow unencrypted WinRM connections on the guest machine +itself. Some public boxes already have this configured, but if you are +attempting to `vagrant up` a Windows box and the command hangs at +`Waiting for WinRM to become available...`, then you will need to run the +commands below on the guest machine itself, at the box setup stage, +after provisioning, or through a start up script. + +
+Set-Item WSMan:\localhost\Service\AllowUnencrypted -Value True
+Set-Item WSMan:\localhost\Service\Auth\Basic -Value True
+
\ No newline at end of file diff --git a/website/docs/source/v2/vmware/installation.html.md b/website/docs/source/v2/vmware/installation.html.md index c9a7ca561..972e2266e 100644 --- a/website/docs/source/v2/vmware/installation.html.md +++ b/website/docs/source/v2/vmware/installation.html.md @@ -5,36 +5,149 @@ sidebar_current: "vmware-installation" # Installation -The VMware provider is installed using -[standard plugin installation procedures](/v2/plugins/usage.html). -In addition to installing the plugin, a license must be provided so that -it can be loaded properly. +The Vagrant VMware provider can be installed using the standard plugin +installation procedure. VMware Fusion users should run: -To purchase a license, visit the [Vagrant VMware provider](http://www.vagrantup.com/vmware) -page. After purchasing a license, a link to download it will be emailed -to you. Download this file. - -Installing the plugin and license is easy using the `vagrant plugin` -interface. Both steps are shown below. Note that the plugin name is different -depending on the provider you're using. If you're using the Fusion provider, -it is `vagrant-vmware-fusion`. If you're using the Workstation provider, -it is `vagrant-vmware-workstation`. - -``` +```text $ vagrant plugin install vagrant-vmware-fusion -... -$ vagrant plugin license vagrant-vmware-fusion license.lic -... ``` -For licensing, the first parameter is the name of the plugin, which is -`vagrant-vmware-fusion` for the VMware Fusion provider, or `vagrant-vmware-workstation` -for the VMware Workstation provider. The second parameter is the path to the license itself. +VMware Workstation users should run: -You can verify the license is properly installed by running any -Vagrant command, such as `vagrant plugin list`. The VMware -provider will show an error message if you are missing a license or using an -invalid license. +```text +$ vagrant plugin install vagrant-vmware-workstation +``` -If there are problems installing the plugin, please contact -[support](http://www.vagrantup.com/support.html). +For more information on plugin installation, please see the +[Vagrant plugin usage documentation](/v2/plugins/usage.html). + +The Vagrant VMware plugins are commercial products provided by +[HashiCorp](https://www.hashicorp.com) and **require the purchase of a license** +to operate. To purchase a license, please visit the +[Vagrant VMware provider](http://www.vagrantup.com/vmware#buy-now) page. Upon +purchasing a license, you will receive a license file in your inbox. Download +this file and save it to a temporary location on your computer. + +
+ Warning! You cannot use your VMware product license as a + Vagrant VMware plugin license. They are separate commercial products, each + requiring their own license. +
+ +After installing the correct Vagrant VMware product plugin for your system, you +will need to install the license. For VMware Fusion users: + +```text +$ vagrant plugin license vagrant-vmware-fusion ~/license.lic +``` + +For VMware Workstation users: + +```text +$ vagrant plugin license vagrant-vmware-workstation ~/license.lic +``` + +The first parameter is the name of the plugin, and the second parameter is the +path to the license file on disk. Please be sure to replace `~/license.lic` +with the path where you temporarily saved the downloaded license file to disk. +After you have installed the plugin license, you may remove the temporary file. + +To verify the license installation, run: + +```text +$ vagrant plugin list +``` + +If the license is not installed correctly, you will see an error message. + + +## Frequently Asked Questions + +**Q: I purchased a Vagrant VMware plugin license, but I did not receive an email?**
+First, please check your JUNK or SPAM folders. Since the license comes from an +automated system, it might have been flagged as spam by your email provider. If +you do not see the email there, please [contact support](mailto:support@hashicorp.com?subject=License Not Received) +and include the original order number. + +**Q: Do you offer trial periods for the Vagrant VMware plugins?**
+We do not offer a trial mechanism at this time, but we do offer a 30-day, no +questions asked, 100% money-back guarantee. If you are not satisfied with the +product, contact us within 30 days and you will receive a full refund. + +**Q: Do you offer educational discounts on the Vagrant VMware plugins?**
+A select number of educational discounts are available for students, staff, and +faculty. Please [contact support](mailto:support@hashicorp.com?subject=Educational Discounts&body=Hello support! I would like to learn more about educational discounts on the Vagrant VMware plugins. Thanks!) for more +information. You will be asked to verify your status as an employee of active +student. + +**Q: Do I need to keep the Vagrant VMware plugin license file on disk?**
+After you have installed the Vagrant VMware plugin license, it is safe to remove +your copy from disk. Vagrant copies the license into its structure for reference +on boot. + +**Q: I lost my original email, where can I download my Vagrant VMware plugin license again?**
+Please [contact support](mailto:support@hashicorp.com?subject=Lost My License&body=Hello support! I seem to have misplaced my Vagrant VMware license. Could you please send it to me? Thanks!). **Note:** +please contact support using the email address with which you made the +original purchase. If you use an alternate email, you will be asked to verify +that you are the owner of the requested license. + +**Q: Where can I find the EULA for the Vagrant VMware plugins?**
+The [EULA for the Vagrant VMware plugins](http://www.vagrantup.com/vmware/eula) +is available on the Vagrant website. + +**Q: Do you offer bulk/volume discounts for the Vagrant VMware plugins?**
+We certainly do! [Email support](mailto:support@hashicorp.com?subject=Bulk Discounts) +with the number of licenses you need and we can give you bulk pricing +information. Please note that bulk pricing requires the purchase of at least 150 +seats. + +**Q: I upgraded my VMware product and now my license is invalid?**
+The Vagrant VMware plugin licenses are valid for specific VMware product +versions at the time of purchase. When new versions of VMware products are +released, significant changes to the plugin code are often required to support +this new version. For this reason, you may need to upgrade your current license +to work with the new version of the VMware product. Customers can check their +license upgrade eligibility by visiting the [License Upgrade Center](http://license.hashicorp.com/upgrade/vmware2014) +and entering the email address with which they made the original purchase. + +Your existing license will continue to work with all previous versions of the +VMware products. If you do not wish to update at this time, you can rollback +your VMware installation to an older version. + +**Q: Why is the Vagrant VMware plugin not working with my trial version of VMware Fusion/Workstation?**
+The Vagrant VMware Fusion and Vagrant VMware Workstation plugins are not +compatible with trial versions of the VMware products. We apologize for the +inconvenience. + +**Q: I accidentally bought the wrong Vagrant VMware plugin, can I switch?**
+Sure! Even though the Vagrant VMware Fusion plugin and the Vagrant VMware +Workstation plugin are different products, they are the same price and fall +under the same EULA. As such, we can transfer the license for you. Please +[contact support](mailto:support@hashicorp.com?subject=Transfer License). + +**Q: Since each license comes with two "seats", can I use one seat for the Vagrant VMware Fusion plugin and one seat for the Vagrant VMware Workstation plugin?**
+Unfortunately this is not permitted. The Vagrant VMware Fusion plugin and the +Vagrant VMware Workstation plugin are separate products and cannot be shared in +this manner. We apologize for the inconvenience. + +**Q: How do I upgrade my currently installed Vagrant VMware plugin?**
+You can update the Vagrant VMware plugin to the latest version by re-running the +install command. For VMware Fusion: + +```text +$ vagrant plugin install vagrant-vmware-fusion +``` + +For VMWare Workstation: + +```text +$ vagrant plugin install vagrant-vmware-workstation +``` + + +## Support +If you have any issues purchasing, installing, or using the Vagrant VMware +plugins, please [contact support](http://www.vagrantup.com/support.html). To +expedite the support process, please include the +[Vagrant debug output](/v2/other/debugging.html) as a Gist or pastebin if +applicable. This will help us more quickly diagnose your issue. diff --git a/website/www/Vagrantfile b/website/www/Vagrantfile index 7ce24fe70..2d8d8c9b4 100644 --- a/website/www/Vagrantfile +++ b/website/www/Vagrantfile @@ -4,13 +4,11 @@ $script = <