diff --git a/CHANGELOG.md b/CHANGELOG.md index 3dad03c86..6c0e97281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,27 @@ FEATURES: IMPROVEMENTS: -- commands/snapshot: enforce unique snapshot names and introduce `--force` flag [GH-7810] + - commands/snapshot: Enforce unique snapshot names and introduce `--force` flag [GH-7810] + - commands/ssh: Introduce tty flag for `vagrant ssh -c` [GH-6827] + - core: Warn about vagrant CWD changes for a machine [GH-3921] + - core/box: Warn if user sets box as url [GH-7118] + - guests/kali: Add support for guest [GH-8553] + - guests/smartos: Update halt capability and add public key insert and remove capabilities [GH-8618] + - provisioners/ansible: Fix SSH keys only behavior to be consistent with Vagrant [GH-8467] + - snapshot/delete: Improve error message when given snapshot doesn't exist [GH-8653] + - snapshot/list: Raise exception if provider does not support snapshots [GH-8619] + - snapshot/restore: Improve error message when given snapshot doesn't exist [GH-8653] + - snapshot/save: Raise exception if provider does not support snapshots [GH-8619] BUG FIXES: + - communicators/ssh: Move `none` cipher to end of default cipher list in Net::SSH [GH-8661] + - core: Add unique identifier to provisioner objects [GH-8680] + - guests/windows: Fix directory creation when using rsync for synced folders [GH-8588] + - providers/docker: Fix check for docker-compose [GH-8659, GH-8660] + - provisioners/ansible_local: Catch pip_args in FreeBSD's and SUSE's ansible_install [GH-8676] + - snapshot/restore: Exit 1 if vm has not been created when command is invoked [GH-8653] + ## 1.9.5 (May 15, 2017) FEATURES: diff --git a/lib/vagrant/action/builtin/box_add.rb b/lib/vagrant/action/builtin/box_add.rb index 316420490..5f2aa907c 100644 --- a/lib/vagrant/action/builtin/box_add.rb +++ b/lib/vagrant/action/builtin/box_add.rb @@ -30,6 +30,12 @@ module Vagrant def call(env) @download_interrupted = false + unless env[:box_name].nil? + if URI.parse(env[:box_name]).kind_of?(URI::HTTP) + env[:ui].warn(I18n.t("vagrant.box_add_url_warn")) + end + end + url = Array(env[:box_url]).map do |u| u = u.gsub("\\", "/") if Util::Platform.windows? && u =~ /^[a-z]:/i diff --git a/lib/vagrant/action/builtin/ssh_run.rb b/lib/vagrant/action/builtin/ssh_run.rb index 9d6cb8ab7..9ea58ca50 100644 --- a/lib/vagrant/action/builtin/ssh_run.rb +++ b/lib/vagrant/action/builtin/ssh_run.rb @@ -44,7 +44,9 @@ module Vagrant # Allow the user to specify a tty or non-tty manually, but if they # don't then we default to a TTY - if !opts[:extra_args].include?("-t") && !opts[:extra_args].include?("-T") + if !opts[:extra_args].include?("-t") && + !opts[:extra_args].include?("-T") && + env[:tty] opts[:extra_args] << "-t" end diff --git a/lib/vagrant/errors.rb b/lib/vagrant/errors.rb index f1c2cb3e4..42b732c42 100644 --- a/lib/vagrant/errors.rb +++ b/lib/vagrant/errors.rb @@ -656,6 +656,14 @@ module Vagrant error_key(:snapshot_force) end + class SnapshotNotFound < VagrantError + error_key(:snapshot_not_found) + end + + class SnapshotNotSupported < VagrantError + error_key(:snapshot_not_supported) + end + class SSHAuthenticationFailed < VagrantError error_key(:ssh_authentication_failed) end diff --git a/lib/vagrant/machine.rb b/lib/vagrant/machine.rb index e7107fb62..c5e73b415 100644 --- a/lib/vagrant/machine.rb +++ b/lib/vagrant/machine.rb @@ -170,6 +170,8 @@ module Vagrant # Extra env keys are the remaining opts extra_env = opts.dup + check_cwd # Warns the UI if the machine was last used on a different dir + # Create a deterministic ID for this machine vf = nil vf = @env.vagrantfile_name[0] if @env.vagrantfile_name @@ -559,5 +561,26 @@ module Vagrant return nil if !@data_dir @data_dir.join("creator_uid") end + + # Checks the current directory for a given machine + # and displays a warning if that machine has moved + # from its previous location on disk. If the machine + # has moved, it prints a warning to the user. + def check_cwd + vagrant_cwd_filepath = @data_dir.join('vagrant_cwd') + vagrant_cwd = if File.exist?(vagrant_cwd_filepath) + File.read(vagrant_cwd_filepath).chomp + end + + if vagrant_cwd.nil? + File.write(vagrant_cwd_filepath, @env.cwd) + elsif vagrant_cwd != @env.cwd.to_s + ui.warn(I18n.t( + 'vagrant.moved_cwd', + old_wd: vagrant_cwd, + current_wd: @env.cwd.to_s)) + File.write(vagrant_cwd_filepath, @env.cwd) + end + end end end diff --git a/plugins/commands/snapshot/command/delete.rb b/plugins/commands/snapshot/command/delete.rb index 0d5118847..aa822b28d 100644 --- a/plugins/commands/snapshot/command/delete.rb +++ b/plugins/commands/snapshot/command/delete.rb @@ -23,7 +23,19 @@ module VagrantPlugins name = argv.pop with_target_vms(argv) do |vm| - vm.action(:snapshot_delete, snapshot_name: name) + if !vm.provider.capability?(:snapshot_list) + raise Vagrant::Errors::SnapshotNotSupported + end + + snapshot_list = vm.provider.capability(:snapshot_list) + + if snapshot_list.include? name + vm.action(:snapshot_delete, snapshot_name: name) + else + raise Vagrant::Errors::SnapshotNotFound, + snapshot_name: name, + machine: vm.name.to_s + end end # Success, exit status 0 diff --git a/plugins/commands/snapshot/command/list.rb b/plugins/commands/snapshot/command/list.rb index d0c433b94..1ee77aac4 100644 --- a/plugins/commands/snapshot/command/list.rb +++ b/plugins/commands/snapshot/command/list.rb @@ -22,8 +22,7 @@ module VagrantPlugins end if !vm.provider.capability?(:snapshot_list) - vm.ui.info(I18n.t("vagrant.commands.snapshot.not_supported")) - next + raise Vagrant::Errors::SnapshotNotSupported end snapshots = vm.provider.capability(:snapshot_list) diff --git a/plugins/commands/snapshot/command/restore.rb b/plugins/commands/snapshot/command/restore.rb index 18ca0fe04..1d8df2ca3 100644 --- a/plugins/commands/snapshot/command/restore.rb +++ b/plugins/commands/snapshot/command/restore.rb @@ -36,7 +36,19 @@ module VagrantPlugins options[:snapshot_name] = name with_target_vms(argv) do |vm| - vm.action(:snapshot_restore, options) + if !vm.provider.capability?(:snapshot_list) + raise Vagrant::Errors::SnapshotNotSupported + end + + snapshot_list = vm.provider.capability(:snapshot_list) + + if snapshot_list.include? name + vm.action(:snapshot_restore, options) + else + raise Vagrant::Errors::SnapshotNotFound, + snapshot_name: name, + machine: vm.name.to_s + end end # Success, exit status 0 diff --git a/plugins/commands/snapshot/command/save.rb b/plugins/commands/snapshot/command/save.rb index 28d9afe0c..e380c228e 100644 --- a/plugins/commands/snapshot/command/save.rb +++ b/plugins/commands/snapshot/command/save.rb @@ -34,8 +34,7 @@ module VagrantPlugins name = argv.pop with_target_vms(argv) do |vm| if !vm.provider.capability?(:snapshot_list) - vm.ui.info(I18n.t("vagrant.commands.snapshot.not_supported")) - next + raise Vagrant::Errors::SnapshotNotSupported end snapshot_list = vm.provider.capability(:snapshot_list) diff --git a/plugins/commands/ssh/command.rb b/plugins/commands/ssh/command.rb index d136d33a1..1e153d2be 100644 --- a/plugins/commands/ssh/command.rb +++ b/plugins/commands/ssh/command.rb @@ -9,6 +9,7 @@ module VagrantPlugins def execute options = {} + options[:tty] = true opts = OptionParser.new do |o| o.banner = "Usage: vagrant ssh [options] [name|id] [-- extra ssh args]" @@ -23,6 +24,10 @@ module VagrantPlugins o.on("-p", "--plain", "Plain mode, leaves authentication up to user") do |p| options[:plain_mode] = p end + + o.on("-t", "--[no-]tty", "Enables tty when executing an ssh command (defaults to true)") do |t| + options[:tty] = t + end end # Parse out the extra args to send to SSH, which is everything @@ -48,7 +53,8 @@ module VagrantPlugins @logger.debug("Executing single command on remote machine: #{options[:command]}") env = vm.action(:ssh_run, ssh_opts: ssh_opts, - ssh_run_command: options[:command],) + ssh_run_command: options[:command], + tty: options[:tty],) # Exit with the exit status of the command or a 0 if we didn't # get one. diff --git a/plugins/communicators/ssh/communicator.rb b/plugins/communicators/ssh/communicator.rb index be48252a8..831dcc779 100644 --- a/plugins/communicators/ssh/communicator.rb +++ b/plugins/communicators/ssh/communicator.rb @@ -348,6 +348,14 @@ module VagrantPlugins auth_methods << "publickey" if ssh_info[:private_key_path] auth_methods << "password" if ssh_info[:password] + # yanked directly from ruby's Net::SSH, but with `none` last + # TODO: Remove this once Vagrant has updated its dependency on Net:SSH + # to be > 4.1.0, which should include this fix. + cipher_array = Net::SSH::Transport::Algorithms::ALGORITHMS[:encryption].dup + if cipher_array.delete("none") + cipher_array.push("none") + end + # Build the options we'll use to initiate the connection via Net::SSH common_connect_opts = { auth_methods: auth_methods, @@ -361,6 +369,7 @@ module VagrantPlugins timeout: 15, user_known_hosts_file: [], verbose: :debug, + encryption: cipher_array, } # Connect to SSH, giving it a few tries diff --git a/plugins/guests/kali/guest.rb b/plugins/guests/kali/guest.rb new file mode 100755 index 000000000..fbc12ae3c --- /dev/null +++ b/plugins/guests/kali/guest.rb @@ -0,0 +1,10 @@ +require_relative '../linux/guest' + +module VagrantPlugins + module GuestKali + class Guest < VagrantPlugins::GuestLinux::Guest + # Name used for guest detection + GUEST_DETECTION_NAME = "kali".freeze + end + end +end diff --git a/plugins/guests/kali/plugin.rb b/plugins/guests/kali/plugin.rb new file mode 100755 index 000000000..44565f899 --- /dev/null +++ b/plugins/guests/kali/plugin.rb @@ -0,0 +1,15 @@ +require "vagrant" + +module VagrantPlugins + module GuestKali + class Plugin < Vagrant.plugin("2") + name "Kali guest" + description "Kali guest support." + + guest(:kali, :debian) do + require_relative "guest" + Guest + end + end + end +end diff --git a/plugins/guests/smartos/cap/halt.rb b/plugins/guests/smartos/cap/halt.rb index 7e10ee2cc..bb764b4c3 100644 --- a/plugins/guests/smartos/cap/halt.rb +++ b/plugins/guests/smartos/cap/halt.rb @@ -10,7 +10,7 @@ module VagrantPlugins # does not exist in /etc/user_attr. TODO begin machine.communicate.execute( - "#{machine.config.smartos.suexec_cmd} /usr/sbin/shutdown -y -i5 -g0") + "#{machine.config.smartos.suexec_cmd} /usr/sbin/poweroff") rescue IOError, Vagrant::Errors::SSHDisconnected # Ignore, this probably means connection closed because it # shut down. diff --git a/plugins/guests/smartos/cap/insert_public_key.rb b/plugins/guests/smartos/cap/insert_public_key.rb new file mode 100644 index 000000000..6c0c38dff --- /dev/null +++ b/plugins/guests/smartos/cap/insert_public_key.rb @@ -0,0 +1,28 @@ +require "vagrant/util/shell_quote" + +module VagrantPlugins + module GuestSmartos + module Cap + class InsertPublicKey + def self.insert_public_key(machine, contents) + contents = contents.chomp + contents = Vagrant::Util::ShellQuote.escape(contents, "'") + + machine.communicate.tap do |comm| + comm.execute <<-EOH.sub(/^ */, '') + if [ -d /usbkey ] && [ "$(zonename)" == "global" ] ; then + printf '#{contents}\\n' >> /usbkey/config.inc/authorized_keys + cp /usbkey/config.inc/authorized_keys ~/.ssh/authorized_keys + else + mkdir -p ~/.ssh + chmod 0700 ~/.ssh + printf '#{contents}\\n' >> ~/.ssh/authorized_keys + chmod 0600 ~/.ssh/authorized_keys + fi + EOH + end + end + end + end + end +end diff --git a/plugins/guests/smartos/cap/remove_public_key.rb b/plugins/guests/smartos/cap/remove_public_key.rb new file mode 100644 index 000000000..d01363dd0 --- /dev/null +++ b/plugins/guests/smartos/cap/remove_public_key.rb @@ -0,0 +1,25 @@ +require "vagrant/util/shell_quote" + +module VagrantPlugins + module GuestSmartos + module Cap + class RemovePublicKey + def self.remove_public_key(machine, contents) + contents = contents.chomp + contents = Vagrant::Util::ShellQuote.escape(contents, "'") + + machine.communicate.tap do |comm| + comm.execute <<-EOH.sub(/^ */, '') + if test -f /usbkey/config.inc/authorized_keys ; then + sed -i '' '/^.*#{contents}.*$/d' /usbkey/config.inc/authorized_keys + fi + if test -f ~/.ssh/authorized_keys ; then + sed -i '' '/^.*#{contents}.*$/d' ~/.ssh/authorized_keys + fi + EOH + end + end + end + end + end +end diff --git a/plugins/guests/smartos/plugin.rb b/plugins/guests/smartos/plugin.rb index 0ed34941f..6f5365af2 100644 --- a/plugins/guests/smartos/plugin.rb +++ b/plugins/guests/smartos/plugin.rb @@ -31,11 +31,21 @@ module VagrantPlugins Cap::Halt end + guest_capability(:smartos, :insert_public_key) do + require_relative "cap/insert_public_key" + Cap::InsertPublicKey + end + guest_capability(:smartos, :mount_nfs_folder) do require_relative "cap/mount_nfs" Cap::MountNFS end + guest_capability(:smartos, :remove_public_key) do + require_relative "cap/remove_public_key" + Cap::RemovePublicKey + end + guest_capability(:smartos, :rsync_installed) do require_relative "cap/rsync" Cap::RSync @@ -58,3 +68,4 @@ module VagrantPlugins end end end + diff --git a/plugins/guests/windows/cap/rsync.rb b/plugins/guests/windows/cap/rsync.rb index aa9f1bcdf..bf2456249 100644 --- a/plugins/guests/windows/cap/rsync.rb +++ b/plugins/guests/windows/cap/rsync.rb @@ -13,7 +13,7 @@ module VagrantPlugins machine.communicate.tap do |comm| # rsync does not construct any gaps in the path to the target directory # make sure that all subdirectories are created - comm.execute("mkdir '#{opts[:guestpath]}'") + comm.execute("mkdir -p '#{opts[:guestpath]}'") end end end diff --git a/plugins/kernel_v2/config/vm.rb b/plugins/kernel_v2/config/vm.rb index e8abe106c..794db57b2 100644 --- a/plugins/kernel_v2/config/vm.rb +++ b/plugins/kernel_v2/config/vm.rb @@ -145,18 +145,16 @@ module VagrantPlugins new_provs = [] other_provs = other.provisioners.dup @provisioners.each do |p| - if p.name - other_p = other_provs.find { |o| p.name == o.name } - if other_p - # There is an override. Take it. - other_p.config = p.config.merge(other_p.config) - other_p.run ||= p.run - next if !other_p.preserve_order + other_p = other_provs.find { |o| p.id == o.id } + if other_p + # There is an override. Take it. + other_p.config = p.config.merge(other_p.config) + other_p.run ||= p.run + next if !other_p.preserve_order - # We're preserving order, delete from other - p = other_p - other_provs.delete(other_p) - end + # We're preserving order, delete from other + p = other_p + other_provs.delete(other_p) end # There is an override, merge it into the diff --git a/plugins/kernel_v2/config/vm_provisioner.rb b/plugins/kernel_v2/config/vm_provisioner.rb index aedafe9fe..59833c850 100644 --- a/plugins/kernel_v2/config/vm_provisioner.rb +++ b/plugins/kernel_v2/config/vm_provisioner.rb @@ -9,6 +9,15 @@ module VagrantPlugins # @return [String] attr_reader :name + # Internal unique name for this provisioner + # Set to the given :name if exists, otherwise + # it's set as a UUID. + # + # Note: This is for internal use only. + # + # @return [String] + attr_reader :id + # The type of the provisioner that should be registered # as a plugin. # @@ -35,6 +44,7 @@ module VagrantPlugins @logger = Log4r::Logger.new("vagrant::config::vm::provisioner") @logger.debug("Provisioner defined: #{name}") + @id = name || SecureRandom.uuid @config = nil @invalid = false @name = name diff --git a/plugins/providers/docker/driver/compose.rb b/plugins/providers/docker/driver/compose.rb index 804cdad32..506188765 100644 --- a/plugins/providers/docker/driver/compose.rb +++ b/plugins/providers/docker/driver/compose.rb @@ -20,7 +20,7 @@ module VagrantPlugins # # @param [Vagrant::Machine] machine Machine instance for this driver def initialize(machine) - if !Vagrant::Util::Which.which("vagrant-compose") + if !Vagrant::Util::Which.which("docker-compose") raise Errors::DockerComposeNotInstalledError end super() diff --git a/plugins/providers/virtualbox/action.rb b/plugins/providers/virtualbox/action.rb index 1f0130791..39c4ac61b 100644 --- a/plugins/providers/virtualbox/action.rb +++ b/plugins/providers/virtualbox/action.rb @@ -245,14 +245,13 @@ module VagrantPlugins end end - # This is the action that is primarily responsible for saving a snapshot + # This is the action that is primarily responsible for restoring a snapshot def self.action_snapshot_restore Vagrant::Action::Builder.new.tap do |b| b.use CheckVirtualbox b.use Call, Created do |env, b2| if !env[:result] - b2.use MessageNotCreated - next + raise Vagrant::Errors::VMNotCreatedError end b2.use CheckAccessible diff --git a/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb b/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb index 3d01d4276..189a67e3a 100644 --- a/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb +++ b/plugins/provisioners/ansible/cap/guest/freebsd/ansible_install.rb @@ -7,7 +7,7 @@ module VagrantPlugins module FreeBSD module AnsibleInstall - def self.ansible_install(machine, install_mode, ansible_version) + def self.ansible_install(machine, install_mode, ansible_version, pip_args) if install_mode != :default raise Ansible::Errors::AnsiblePipInstallIsNotSupported else diff --git a/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb b/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb index 0aa66e00f..e2beb838f 100644 --- a/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb +++ b/plugins/provisioners/ansible/cap/guest/suse/ansible_install.rb @@ -6,7 +6,7 @@ module VagrantPlugins module SUSE module AnsibleInstall - def self.ansible_install(machine, install_mode, ansible_version) + def self.ansible_install(machine, install_mode, ansible_version, pip_args) if install_mode != :default raise Ansible::Errors::AnsiblePipInstallIsNotSupported else diff --git a/plugins/provisioners/ansible/provisioner/host.rb b/plugins/provisioners/ansible/provisioner/host.rb index e0fc70f0b..b86157208 100644 --- a/plugins/provisioners/ansible/provisioner/host.rb +++ b/plugins/provisioners/ansible/provisioner/host.rb @@ -249,11 +249,8 @@ module VagrantPlugins # 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? + # Compare to lib/vagrant/util/ssh.rb + ssh_options << "-o IdentitiesOnly=yes" if !Vagrant::Util::Platform.solaris? && @ssh_info[:keys_only] # Multiple Private Keys unless !config.inventory_path && @ssh_info[:private_key_path].size == 1 diff --git a/templates/locales/en.yml b/templates/locales/en.yml index f4e182a31..af3fad1a4 100644 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -22,6 +22,9 @@ en: Successfully added box '%{name}' (v%{version}) for '%{provider}'! box_adding_direct: |- Box file was not detected as metadata. Adding it directly... + box_add_url_warn: |- + It looks like you attempted to add a box with a URL for the name... + Instead, use box_url instead of box for box URLs. box_downloading: |- Downloading: %{url} box_download_error: |- @@ -162,6 +165,10 @@ en: description of what they do. %{list} + moved_cwd: |- + This machine used to live in %{old_wd} but it's now at %{current_wd}. + Please change the name of the machine if you want to run it as a different + machine. guest_deb_installing_smb: |- Installing SMB "mount.cifs"... global_status_footer: |- @@ -1158,6 +1165,15 @@ en: guest system. Please report a bug with your Vagrantfile and debug log. snapshot_force: |- You must include the `--force` option to replace an existing snapshot. + snapshot_not_supported: |- + This provider doesn't support snapshots. + + This may be intentional or this may be a bug. If this provider + should support snapshots, then please report this as a bug to the + maintainer of the provider. + snapshot_not_found: |- + The snapshot name `%{snapshot_name}` was not found for the + virtual machine `%{machine}`. ssh_authentication_failed: |- SSH authentication failed! This is typically caused by the public/private keypair for the SSH user not being properly set on the guest VM. Please @@ -1539,7 +1555,7 @@ en: unexpected errors. To learn more about this, and the options that are available, please refer to the Vagrant documentation: - https://www.vagrantup.com/docs/other/wsl + https://www.vagrantup.com/docs/other/wsl.html wsl_virtualbox_windows_access: |- Vagrant is unable to use the VirtualBox provider from the Windows Subsystem for Linux without access to the Windows environment. Enabling this access must be @@ -1547,7 +1563,7 @@ en: on enabing Windows access and using VirtualBox from the Windows Subsystem for Linux, please refer to the Vagrant documentation: - https://www.vagrantup.com/docs/other/wsl + https://www.vagrantup.com/docs/other/wsl.html #------------------------------------------------------------------------------- # Translations for config validation errors #------------------------------------------------------------------------------- diff --git a/test/unit/plugins/commands/snapshot/command/delete_test.rb b/test/unit/plugins/commands/snapshot/command/delete_test.rb new file mode 100644 index 000000000..438c9c05e --- /dev/null +++ b/test/unit/plugins/commands/snapshot/command/delete_test.rb @@ -0,0 +1,97 @@ +require File.expand_path("../../../../../base", __FILE__) + +require Vagrant.source_root.join("plugins/commands/snapshot/command/delete") + +describe VagrantPlugins::CommandSnapshot::Command::Delete do + include_context "unit" + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:guest) { double("guest") } + let(:host) { double("host") } + let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) } + + let(:argv) { [] } + + subject { described_class.new(argv, iso_env) } + + before do + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return([]) + + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(true) + + allow(subject).to receive(:with_target_vms) { |&block| block.call machine } + end + + describe "execute" do + context "with no arguments" do + it "shows help" do + expect { subject.execute }. + to raise_error(Vagrant::Errors::CLIInvalidUsage) + end + end + + context "with an unsupported provider" do + let(:argv) { ["test"] } + + before do + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(false) + end + + it "raises an exception" do + machine.id = "foo" + expect { subject.execute }. + to raise_error(Vagrant::Errors::SnapshotNotSupported) + end + end + + context "with a snapshot name given" do + let(:argv) { ["test"] } + it "calls snapshot_delete with a snapshot name" do + machine.id = "foo" + + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return(["test"]) + + expect(machine).to receive(:action) do |name, opts| + expect(name).to eq(:snapshot_delete) + expect(opts[:snapshot_name]).to eq("test") + end + + expect(subject.execute).to eq(0) + end + + it "doesn't delete a snapshot on a non-existent machine" do + machine.id = nil + + expect(subject).to receive(:with_target_vms){} + + expect(machine).to_not receive(:action) + expect(subject.execute).to eq(0) + end + end + + context "with a snapshot name that doesn't exist" do + let(:argv) { ["nopetest"] } + + it "fails to take a snapshot and prints a warning to the user" do + machine.id = "foo" + + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return(["test"]) + + expect(machine).to_not receive(:action) + expect { subject.execute }. + to raise_error(Vagrant::Errors::SnapshotNotFound) + end + end + end +end diff --git a/test/unit/plugins/commands/snapshot/command/list_test.rb b/test/unit/plugins/commands/snapshot/command/list_test.rb new file mode 100644 index 000000000..a812aa40f --- /dev/null +++ b/test/unit/plugins/commands/snapshot/command/list_test.rb @@ -0,0 +1,83 @@ +require File.expand_path("../../../../../base", __FILE__) + +require Vagrant.source_root.join("plugins/commands/snapshot/command/list") + +describe VagrantPlugins::CommandSnapshot::Command::List do + include_context "unit" + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:guest) { double("guest") } + let(:host) { double("host") } + let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) } + + let(:argv) { [] } + + subject { described_class.new(argv, iso_env) } + + before do + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(true) + + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return([]) + + allow(subject).to receive(:with_target_vms) { |&block| block.call machine } + end + + describe "execute" do + context "with an unsupported provider" do + let(:argv) { ["foo"] } + + before do + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(false) + end + + it "raises an exception" do + machine.id = "foo" + expect { subject.execute }. + to raise_error(Vagrant::Errors::SnapshotNotSupported) + end + end + + context "with a vm given" do + let(:argv) { ["foo"] } + + it "prints a message if the vm does not exist" do + machine.id = nil + + expect(iso_env.ui).to receive(:info).with { |message, _| + expect(message).to include("VM not created") + } + expect(machine).to_not receive(:action) + expect(subject.execute).to eq(0) + end + + it "prints a message if no snapshots have been taken" do + machine.id = "foo" + + expect(iso_env.ui).to receive(:output) + .with(/No snapshots have been taken yet!/, anything) + expect(subject.execute).to eq(0) + end + + it "prints a list of snapshots" do + machine.id = "foo" + + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return(["foo", "bar", "baz"]) + + expect(iso_env.ui).to receive(:output).with(/foo/, anything) + expect(iso_env.ui).to receive(:output).with(/bar/, anything) + expect(iso_env.ui).to receive(:output).with(/baz/, anything) + expect(subject.execute).to eq(0) + end + end + end +end diff --git a/test/unit/plugins/commands/snapshot/command/restore_test.rb b/test/unit/plugins/commands/snapshot/command/restore_test.rb new file mode 100644 index 000000000..8747998f1 --- /dev/null +++ b/test/unit/plugins/commands/snapshot/command/restore_test.rb @@ -0,0 +1,97 @@ +require File.expand_path("../../../../../base", __FILE__) + +require Vagrant.source_root.join("plugins/commands/snapshot/command/restore") + +describe VagrantPlugins::CommandSnapshot::Command::Restore do + include_context "unit" + + let(:iso_env) do + # We have to create a Vagrantfile so there is a root path + env = isolated_environment + env.vagrantfile("") + env.create_vagrant_env + end + + let(:guest) { double("guest") } + let(:host) { double("host") } + let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) } + + let(:argv) { [] } + + subject { described_class.new(argv, iso_env) } + + before do + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return([]) + + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(true) + + allow(subject).to receive(:with_target_vms) { |&block| block.call machine } + end + + describe "execute" do + context "with no arguments" do + it "shows help" do + expect { subject.execute }. + to raise_error(Vagrant::Errors::CLIInvalidUsage) + end + end + + context "with an unsupported provider" do + let(:argv) { ["test"] } + + before do + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(false) + end + + it "raises an exception" do + machine.id = "foo" + expect { subject.execute }. + to raise_error(Vagrant::Errors::SnapshotNotSupported) + end + end + + context "with a snapshot name given" do + let(:argv) { ["test"] } + it "calls snapshot_delete with a snapshot name" do + machine.id = "foo" + + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return(["test"]) + + expect(machine).to receive(:action) do |name, opts| + expect(name).to eq(:snapshot_restore) + expect(opts[:snapshot_name]).to eq("test") + end + + expect(subject.execute).to eq(0) + end + + it "doesn't delete a snapshot on a non-existent machine" do + machine.id = nil + + expect(subject).to receive(:with_target_vms){} + + expect(machine).to_not receive(:action) + expect(subject.execute).to eq(0) + end + end + + context "with a snapshot name that doesn't exist" do + let(:argv) { ["nopetest"] } + + it "fails to take a snapshot and prints a warning to the user" do + machine.id = "foo" + + allow(machine.provider).to receive(:capability).with(:snapshot_list). + and_return(["test"]) + + expect(machine).to_not receive(:action) + expect { subject.execute }. + to raise_error(Vagrant::Errors::SnapshotNotFound) + end + end + end +end diff --git a/test/unit/plugins/commands/snapshot/command/save_test.rb b/test/unit/plugins/commands/snapshot/command/save_test.rb index 2dbdf4145..3ed2f1ffb 100644 --- a/test/unit/plugins/commands/snapshot/command/save_test.rb +++ b/test/unit/plugins/commands/snapshot/command/save_test.rb @@ -38,6 +38,21 @@ describe VagrantPlugins::CommandSnapshot::Command::Save do end end + context "with an unsupported provider" do + let(:argv) { ["test"] } + + before do + allow(machine.provider).to receive(:capability?).with(:snapshot_list). + and_return(false) + end + + it "raises an exception" do + machine.id = "foo" + expect { subject.execute }. + to raise_error(Vagrant::Errors::SnapshotNotSupported) + end + end + context "with a snapshot name given" do let(:argv) { ["test"] } it "calls snapshot_save with a snapshot name" do diff --git a/test/unit/plugins/communicators/ssh/communicator_test.rb b/test/unit/plugins/communicators/ssh/communicator_test.rb index a0998c6dc..0a2f67195 100644 --- a/test/unit/plugins/communicators/ssh/communicator_test.rb +++ b/test/unit/plugins/communicators/ssh/communicator_test.rb @@ -396,6 +396,20 @@ describe VagrantPlugins::CommunicatorSSH::Communicator do ).and_return(true) communicator.send(:connect) end + + it "includes the default cipher array for encryption" do + cipher_array = %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc + aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se + idea-cbc arcfour128 arcfour256 arcfour + aes128-ctr aes192-ctr aes256-ctr + cast128-ctr blowfish-ctr 3des-ctr none) + expect(Net::SSH).to receive(:start).with( + nil, nil, hash_including( + encryption: cipher_array + ) + ).and_return(true) + communicator.send(:connect) + end end context "with keys_only disabled and paranoid enabled" do diff --git a/test/unit/plugins/guests/smartos/cap/halt_test.rb b/test/unit/plugins/guests/smartos/cap/halt_test.rb index 137749489..08b563c39 100644 --- a/test/unit/plugins/guests/smartos/cap/halt_test.rb +++ b/test/unit/plugins/guests/smartos/cap/halt_test.rb @@ -5,7 +5,7 @@ describe "VagrantPlugins::GuestSmartos::Cap::Halt" do let(:machine) { double("machine") } let(:config) { double("config", smartos: double("smartos", suexec_cmd: 'pfexec')) } let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) } - let(:shutdown_command){ "pfexec /usr/sbin/shutdown -y -i5 -g0" } + let(:shutdown_command){ "pfexec /usr/sbin/poweroff" } before do machine.stub(:communicate).and_return(communicator) diff --git a/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb b/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb new file mode 100644 index 000000000..917f0baa9 --- /dev/null +++ b/test/unit/plugins/guests/smartos/cap/insert_public_key_test.rb @@ -0,0 +1,38 @@ +require_relative "../../../../base" + +describe "VagrantPlugins::GuestSmartos::Cap::InsertPublicKey" do + let(:caps) do + VagrantPlugins::GuestSmartos::Plugin + .components + .guest_capabilities[:smartos] + end + + let(:machine) { double("machine") } + let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + + before do + allow(machine).to receive(:communicate).and_return(comm) + end + + after do + comm.verify_expectations! + end + + describe ".insert_public_key" do + let(:cap) { caps.get(:insert_public_key) } + + it "inserts the public key" do + cap.insert_public_key(machine, "ssh-rsa ...") + + expect(comm.received_commands[0]).to match(/if \[ -d \/usbkey \] && \[ "\$\(zonename\)" == "global" \] ; then/) + expect(comm.received_commands[0]).to match(/printf 'ssh-rsa ...\\n' >> \/usbkey\/config.inc\/authorized_keys/) + expect(comm.received_commands[0]).to match(/cp \/usbkey\/config.inc\/authorized_keys ~\/.ssh\/authorized_keys/) + expect(comm.received_commands[0]).to match(/else/) + expect(comm.received_commands[0]).to match(/mkdir -p ~\/.ssh/) + expect(comm.received_commands[0]).to match(/chmod 0700 ~\/.ssh/) + expect(comm.received_commands[0]).to match(/printf 'ssh-rsa ...\\n' >> ~\/.ssh\/authorized_keys/) + expect(comm.received_commands[0]).to match(/chmod 0600 ~\/.ssh\/authorized_keys/) + expect(comm.received_commands[0]).to match(/fi/) + end + end +end diff --git a/test/unit/plugins/guests/smartos/cap/remove_public_key_test.rb b/test/unit/plugins/guests/smartos/cap/remove_public_key_test.rb new file mode 100644 index 000000000..3984173bd --- /dev/null +++ b/test/unit/plugins/guests/smartos/cap/remove_public_key_test.rb @@ -0,0 +1,34 @@ +require_relative "../../../../base" + +describe "VagrantPlugins::GuestSmartos::Cap::RemovePublicKey" do + let(:caps) do + VagrantPlugins::GuestSmartos::Plugin + .components + .guest_capabilities[:smartos] + end + + let(:machine) { double("machine") } + let(:comm) { VagrantTests::DummyCommunicator::Communicator.new(machine) } + + before do + allow(machine).to receive(:communicate).and_return(comm) + end + + after do + comm.verify_expectations! + end + + describe ".remove_public_key" do + let(:cap) { caps.get(:remove_public_key) } + + it "removes the public key" do + cap.remove_public_key(machine, "ssh-rsa keyvalue comment") + expect(comm.received_commands[0]).to match(/if test -f \/usbkey\/config.inc\/authorized_keys ; then/) + expect(comm.received_commands[0]).to match(/sed -i '' '\/\^.*ssh-rsa keyvalue comment.*\$\/d' \/usbkey\/config.inc\/authorized_keys/) + expect(comm.received_commands[0]).to match(/fi/) + expect(comm.received_commands[0]).to match(/if test -f ~\/.ssh\/authorized_keys ; then/) + expect(comm.received_commands[0]).to match(/sed -i '' '\/\^.*ssh-rsa keyvalue comment.*\$\/d' ~\/.ssh\/authorized_keys/) + expect(comm.received_commands[0]).to match(/fi/) + end + end +end diff --git a/test/unit/plugins/guests/windows/cap/rsync_test.rb b/test/unit/plugins/guests/windows/cap/rsync_test.rb index d32568c40..e55006512 100644 --- a/test/unit/plugins/guests/windows/cap/rsync_test.rb +++ b/test/unit/plugins/guests/windows/cap/rsync_test.rb @@ -19,7 +19,7 @@ describe "VagrantPlugins::GuestWindows::Cap::RSync" do describe ".rsync_pre" do it 'makes the guestpath directory with mkdir' do - communicator.expect_command("mkdir '/sync_dir'") + communicator.expect_command("mkdir -p '/sync_dir'") described_class.rsync_pre(machine, guestpath: '/sync_dir') end end diff --git a/test/unit/plugins/kernel_v2/config/vm_test.rb b/test/unit/plugins/kernel_v2/config/vm_test.rb index 17d121ed7..ef3734898 100644 --- a/test/unit/plugins/kernel_v2/config/vm_test.rb +++ b/test/unit/plugins/kernel_v2/config/vm_test.rb @@ -424,6 +424,24 @@ describe VagrantPlugins::Kernel_V2::VMConfig do expect{ subject.finalize! }.to_not raise_error end + it "generates a uuid if no name was provided" do + allow(SecureRandom).to receive(:uuid).and_return("MY_CUSTOM_VALUE") + + subject.provision("shell", path: "foo") { |s| s.inline = "foo" } + subject.finalize! + + r = subject.provisioners + expect(r[0].id).to eq("MY_CUSTOM_VALUE") + end + + it "sets id as name if a name was provided" do + subject.provision("ghost", type: "shell", path: "motoko") { |s| s.inline = "motoko" } + subject.finalize! + + r = subject.provisioners + expect(r[0].id).to eq(:ghost) + end + describe "merging" do it "ignores non-overriding runs" do subject.provision("shell", inline: "foo", run: "once") @@ -439,6 +457,16 @@ describe VagrantPlugins::Kernel_V2::VMConfig do expect(merged_provs[1].run).to eq("always") end + it "does not merge duplicate provisioners" do + subject.provision("shell", inline: "foo") + subject.provision("shell", inline: "bar") + + merged = subject.merge(subject) + merged_provs = merged.provisioners + + expect(merged_provs.length).to eql(2) + end + it "copies the configs" do subject.provision("shell", inline: "foo") subject_provs = subject.provisioners diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index 2c8c27fb4..308307aab 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -40,6 +40,7 @@ VF let(:config) { VagrantPlugins::Ansible::Config::Host.new } let(:ssh_info) {{ private_key_path: ['/path/to/my/key'], + keys_only: true, username: 'testuser', host: '127.0.0.1', port: 2223 @@ -988,5 +989,20 @@ VF end end + + describe 'with config.ssh.keys_only = false' do + it 'does not set IdentitiesOnly=yes in ANSIBLE_SSH_ARGS' do + ssh_info[:keys_only] = false + + 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") + + # Ending this block with a negative expectation (to_not / not_to) + # would lead to a failure of the above expectation. + true + } + end + end end end diff --git a/test/unit/vagrant/action/builtin/box_add_test.rb b/test/unit/vagrant/action/builtin/box_add_test.rb index a1f966d4b..d7c6efa97 100644 --- a/test/unit/vagrant/action/builtin/box_add_test.rb +++ b/test/unit/vagrant/action/builtin/box_add_test.rb @@ -280,6 +280,31 @@ describe Vagrant::Action::Builtin::BoxAdd, :skip_windows do subject.call(env) end + context "with a box name accidentally set as a URL" do + it "displays a warning to the user" do + box_path = iso_env.box2_file(:virtualbox) + with_web_server(box_path) do |port| + + box_url_name = "http://127.0.0.1:#{port}/#{box_path.basename}" + env[:box_name] = box_url_name + + expect(box_collection).to receive(:add).with { |path, name, version, **opts| + expect(name).to eq(box_url_name) + expect(version).to eq("0") + expect(opts[:metadata_url]).to be_nil + true + }.and_return(box) + + expect(app).to receive(:call).with(env) + + expect(env[:ui]).to receive(:warn) + .with(/It looks like you attempted to add a box with a URL for the name/) + + subject.call(env) + end + end + end + context "with URL containing credentials" do let(:username){ "box-username" } let(:password){ "box-password" } diff --git a/test/unit/vagrant/action/builtin/ssh_run_test.rb b/test/unit/vagrant/action/builtin/ssh_run_test.rb new file mode 100644 index 000000000..56609607d --- /dev/null +++ b/test/unit/vagrant/action/builtin/ssh_run_test.rb @@ -0,0 +1,83 @@ +require File.expand_path("../../../../base", __FILE__) + +describe Vagrant::Action::Builtin::SSHRun do + let(:app) { lambda { |env| } } + let(:env) { { machine: machine, tty: true } } + + # SSH configuration information mock + let(:ssh) do + double("ssh", + timeout: 1, + host: nil, + port: 5986, + guest_port: 5986, + pty: false, + keep_alive: false, + insert_key: false, + shell: 'bash -l' + ) + end + + # Configuration mock + let(:config) { double("config", ssh: ssh) } + + let(:machine) do + double("machine", + config: config,) + end + + let(:machine_ssh_info) { {} } + let(:ssh_klass) { Vagrant::Util::SSH } + + before(:each) do + # Stub the methods so that even if we test incorrectly, no side + # effects actually happen. + allow(ssh_klass).to receive(:exec) + allow(machine).to receive(:ssh_info).and_return(machine_ssh_info) + end + + it "should raise an exception if SSH is not ready" do + not_ready_machine = double("machine") + allow(not_ready_machine).to receive(:ssh_info).and_return(nil) + + env[:machine] = not_ready_machine + expect { described_class.new(app, env).call(env) }. + to raise_error(Vagrant::Errors::SSHNotReady) + end + + it "should exec with the SSH info in the env if given" do + ssh_info = { foo: :bar } + opts = {:extra_args=>["-t", "bash -l -c 'echo test'"], :subprocess=>true} + + expect(ssh_klass).to receive(:exec). + with(ssh_info, opts) + + env[:ssh_info] = ssh_info + env[:ssh_run_command] = "echo test" + described_class.new(app, env).call(env) + end + + it "should exec with the SSH info in the env if given and disable tty" do + ssh_info = { foo: :bar } + opts = {:extra_args=>["bash -l -c 'echo test'"], :subprocess=>true} + env[:tty] = false + + expect(ssh_klass).to receive(:exec). + with(ssh_info, opts) + + env[:ssh_info] = ssh_info + env[:ssh_run_command] = "echo test" + described_class.new(app, env).call(env) + end + + it "should exec with the options given in `ssh_opts`" do + ssh_opts = { foo: :bar } + + expect(ssh_klass).to receive(:exec). + with(machine_ssh_info, ssh_opts) + + env[:ssh_opts] = ssh_opts + env[:ssh_run_command] = "echo test" + described_class.new(app, env).call(env) + end +end diff --git a/test/unit/vagrant/machine_test.rb b/test/unit/vagrant/machine_test.rb index c59d3b029..635255c77 100644 --- a/test/unit/vagrant/machine_test.rb +++ b/test/unit/vagrant/machine_test.rb @@ -307,6 +307,45 @@ describe Vagrant::Machine do expect { instance.action(action_name) }. to raise_error(Vagrant::Errors::UnimplementedProviderAction) end + + it 'should not warn if the machines cwd has not changed' do + initial_action_name = :up + second_action_name = :reload + callable = lambda { |_env| } + original_cwd = env.cwd.to_s + + allow(provider).to receive(:action).with(initial_action_name).and_return(callable) + allow(provider).to receive(:action).with(second_action_name).and_return(callable) + allow(subject.ui).to receive(:warn) + + instance.action(initial_action_name) + expect(subject.ui).to_not have_received(:warn) + + instance.action(second_action_name) + expect(subject.ui).to_not have_received(:warn) + end + + it 'should warn if the machine was last run under a different directory' do + action_name = :up + callable = lambda { |_env| } + original_cwd = env.cwd.to_s + + allow(provider).to receive(:action).with(action_name).and_return(callable) + allow(subject.ui).to receive(:warn) + + instance.action(action_name) + + expect(subject.ui).to_not have_received(:warn) + + # Whenever the machine is run on a different directory, the user is warned + allow(env).to receive(:cwd).and_return('/a/new/path') + instance.action(action_name) + + expect(subject.ui).to have_received(:warn) do |warn_msg| + expect(warn_msg).to include(original_cwd) + expect(warn_msg).to include('/a/new/path') + end + end end describe "#action_raw" do diff --git a/website/Gemfile b/website/Gemfile index 405a8c992..d1a2ed44a 100644 --- a/website/Gemfile +++ b/website/Gemfile @@ -1,3 +1,3 @@ source "https://rubygems.org" -gem "middleman-hashicorp", "0.3.22" +gem "middleman-hashicorp", "0.3.26" diff --git a/website/Gemfile.lock b/website/Gemfile.lock index 229218ac9..e429194fa 100644 --- a/website/Gemfile.lock +++ b/website/Gemfile.lock @@ -6,7 +6,7 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - autoprefixer-rails (6.7.7.1) + autoprefixer-rails (7.1.1) execjs bootstrap-sass (3.3.7) autoprefixer-rails (>= 5.2.1) @@ -42,14 +42,15 @@ GEM eventmachine (1.2.3) execjs (2.7.0) ffi (1.9.18) - haml (4.0.7) + haml (5.0.1) + temple (>= 0.8.0) tilt hike (1.2.3) hooks (0.4.1) uber (~> 0.0.14) http_parser.rb (0.6.0) i18n (0.7.0) - json (2.0.3) + json (2.1.0) kramdown (1.13.2) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) @@ -77,7 +78,7 @@ GEM rack (>= 1.4.5, < 2.0) thor (>= 0.15.2, < 2.0) tilt (~> 1.4.1, < 2.0) - middleman-hashicorp (0.3.22) + middleman-hashicorp (0.3.26) bootstrap-sass (~> 3.3) builder (~> 3.2) middleman (~> 3.4) @@ -100,18 +101,18 @@ GEM mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) - mini_portile2 (2.1.0) - minitest (5.10.1) + mini_portile2 (2.2.0) + minitest (5.10.2) multi_json (1.12.1) - nokogiri (1.7.1) - mini_portile2 (~> 2.1.0) + nokogiri (1.8.0) + mini_portile2 (~> 2.2.0) padrino-helpers (0.12.8.1) i18n (~> 0.6, >= 0.6.7) padrino-support (= 0.12.8.1) tilt (~> 1.4.1) padrino-support (0.12.8.1) activesupport (>= 3.1) - rack (1.6.5) + rack (1.6.8) rack-livereload (0.3.16) rack rack-test (0.6.3) @@ -121,7 +122,7 @@ GEM ffi (>= 0.5.0) redcarpet (3.4.0) rouge (2.0.7) - sass (3.4.23) + sass (3.4.24) sprockets (2.12.4) hike (~> 1.2) multi_json (~> 1.0) @@ -132,26 +133,27 @@ GEM sprockets-sass (1.3.1) sprockets (~> 2.0) tilt (~> 1.1) + temple (0.8.0) thor (0.19.4) thread_safe (0.3.6) tilt (1.4.1) turbolinks (5.0.1) turbolinks-source (~> 5) - turbolinks-source (5.0.0) + turbolinks-source (5.0.3) tzinfo (1.2.3) thread_safe (~> 0.1) uber (0.0.15) uglifier (2.7.2) execjs (>= 0.3.0) json (>= 1.8.0) - xpath (2.0.0) + xpath (2.1.0) nokogiri (~> 1.3) PLATFORMS ruby DEPENDENCIES - middleman-hashicorp (= 0.3.22) + middleman-hashicorp (= 0.3.26) BUNDLED WITH 1.14.6 diff --git a/website/Makefile b/website/Makefile index d7620d1c2..2388d5f68 100644 --- a/website/Makefile +++ b/website/Makefile @@ -1,4 +1,4 @@ -VERSION?="0.3.22" +VERSION?="0.3.26" build: @echo "==> Starting build in Docker..." diff --git a/website/packer.json b/website/packer.json index 35de63232..9e2274365 100644 --- a/website/packer.json +++ b/website/packer.json @@ -8,7 +8,7 @@ "builders": [ { "type": "docker", - "image": "hashicorp/middleman-hashicorp:0.3.22", + "image": "hashicorp/middleman-hashicorp:0.3.26", "discard": "true", "run_command": ["-d", "-i", "-t", "{{ .Image }}", "/bin/sh"] } diff --git a/website/source/docs/boxes.html.md b/website/source/docs/boxes.html.md index 0632dcb10..97eb188b4 100644 --- a/website/source/docs/boxes.html.md +++ b/website/source/docs/boxes.html.md @@ -69,8 +69,8 @@ $ vagrant init hashicorp/precise64 or you can update your `Vagrantfile` as follows: ```ruby -Vagrant.configure("2") do - config.box = "hashicorp/precise64" +Vagrant.configure("2") do |config| + config.vm.box = "hashicorp/precise64" end ``` diff --git a/website/source/docs/cli/box.html.md b/website/source/docs/cli/box.html.md index 8ecede044..68947cbf3 100644 --- a/website/source/docs/cli/box.html.md +++ b/website/source/docs/cli/box.html.md @@ -16,13 +16,13 @@ This is the command used to manage (add, remove, etc.) [boxes](/docs/boxes.html) The main functionality of this command is exposed via even more subcommands: -* `add` -* `list` -* `outdated` -* `prune` -* `remove` -* `repackage` -* `update` +* [`add`](#box-add) +* [`list`](#box-list) +* [`outdated`](#box-outdated) +* [`prune`](#box-prune) +* [`remove`](#box-remove) +* [`repackage`](#box-repackage) +* [`update`](#box-update) # Box Add diff --git a/website/source/docs/other/environmental-variables.html.md b/website/source/docs/other/environmental-variables.html.md index 16a308441..ece769bb3 100644 --- a/website/source/docs/other/environmental-variables.html.md +++ b/website/source/docs/other/environmental-variables.html.md @@ -165,7 +165,7 @@ jailbreak by setting `VAGRANT_SKIP_SUBPROCESS_JAILBREAK`. ## `VAGRANT_VAGRANTFILE` This specifies the filename of the Vagrantfile that Vagrant searches for. -By default, this is "Vagrantfile." Note that this is _not_ a file path, +By default, this is "Vagrantfile". Note that this is _not_ a file path, but just a filename. This environmental variable is commonly used in scripting environments diff --git a/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md b/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md index a87983025..dc685167b 100644 --- a/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md +++ b/website/source/docs/vagrant-cloud/vagrant-cloud-migration.html.md @@ -7,19 +7,116 @@ sidebar_current: "vagrant-cloud-migration" # Vagrant Cloud Migration Vagrant-related functionality will be moved from Terraform Enterprise into its own product, Vagrant Cloud. -This migration is currently planned for **June 27th, 2017**. +This migration is currently planned for **June 27th, 2017** at 6PM EDT/3PM PDT/10PM UTC. -All existing Vagrant boxes will be moved to the new system on that date. +All existing Vagrant boxes will be moved to the new system at that time. All users, organizations, and teams will be copied as well. +~> If you only use Vagrant to download and run public boxes, then nothing is changing. +~> All box names, versions, and URLs will stay the same (or redirect) with no changes to your workflow or Vagrantfiles. + +## Vagrant Boxes, Users, Organizations, and Teams + +All Vagrant boxes will be moved to the new Vagrant Cloud on June 27th. +Additionally, all users and organizations will be copied. +Any existing box collaborations or team ACLs will persist into the new system. + +All existing box names (hashicorp/precise64) and URLs will continue working as-is, or permanently redirect to the correct location. +If you’re only using public Vagrant boxes, no changes will be required to your Vagrantfiles or workflow. +Users of private Vagrant boxes will need to create a new authentication (see below), and activate their Vagrant Cloud account after the migration has completed. + +Vagrant Cloud users and organizations will be considered inactive in the future if they have not logged into Vagrant Cloud after the migration and do not have any published Vagrant boxes. +Inactive user accounts will be deleted on or after October 1st, 2017. + +## Vagrant Cloud Account Activation + +In order to begin using Vagrant Cloud with your Atlas account, you will first need to activate your Vagrant Cloud account. +This will require you to login to Atlas, as well as confirm your password (and 2FA credentials, if configured). +There will be links and instructions on the Vagrant Cloud login screen directing you to do this. + +During Vagrant Cloud account activation, you will create a new password for Vagrant Cloud and optionally configure 2FA. +Your pre-existing Atlas account, password, and 2FA configuration will remain unchanged within Atlas. + +~> New users of Vagrant Cloud can always create a new account for free, at any time. + ## Authentication Tokens -No existing Terraform Enterprise authentication tokens will be transferred. -To prevent a disruption of service for Vagrant-related operations, users must create a new authentication token and check "Migrate to Vagrant Cloud" and begin using these tokens for creating and modifying Vagrant boxes. -These tokens will be moved on the migration date. +If you are currently using an authentication token to interact with Atlas for Vagrant features, you will need to generate a new Vagrant Cloud token prior to June 27th. +You can see your existing tokens and generate new tokens on the Tokens page of your account settings. -Creating a token via `vagrant login` will also mark a token as "Migrate to Vagrant Cloud". +When creating this new token, select Migrate to Vagrant Cloud. -## More Information +You can see which authentication tokens which will be copied to Vagrant Cloud in the token list. -At least 1 month prior to the migration, we will be releasing more information on the specifics and impact of the migration. +Only these authentication tokens will be moved to Vagrant Cloud on June 27th. +They will also be removed from Terraform Enterprise at this time, and will no longer work for Terraform or Packer operations. +If you do not create a token in Atlas by June 27th, you will need to create a token within Vagrant Cloud after the migration. + +~> Creating a token in Atlas via `vagrant login` will also mark a token as "Migrate to Vagrant Cloud". + +## Packer and Terraform Enterprise + +Packer has two post-processors which can create Vagrant boxes in Terraform Enterprise (Atlas): `atlas` and `vagrant-cloud`. +The `atlas post-processor` will no longer create Vagrant boxes after June 27th. +If you are currently publishing Vagrant boxes with Packer, please ensure that you are using the vagrant-cloud post-processor. + +For example, if your Packer post-processor JSON looks like this: + +```json +{ + "variables": { + "atlas_token": "{{env `ATLAS_TOKEN`}}", + "version": "1.0.{{timestamp}}" + }, + "builders": [ + ], + "post-processors": [ + { + "type": "atlas", + "token": "{{user `atlas_token`}}", + "artifact": "hashicorp/example", + "artifact_type": "vagrant.box", + "metadata": { + "version": "{{user `version`}}" + } + } + ] +} +``` + +You must replace the `atlas` post-processor with the `vagrant` and `vagrant-cloud` post-processors (note the nested array, which tells Packer to run these steps serially). + +```json +{ + "variables": { + "vagrantcloud_token": "{{env `VAGRANTCLOUD_TOKEN`}}", + "version": "1.0.{{timestamp}}" + }, + "builders": [ + ], + "post-processors": [ + [ + { + "type": "vagrant", + "output": "output.box" + }, + { + "type": "vagrant-cloud", + "access_token": "{{user `vagrantcloud_token`}}", + "box_tag": "hashicorp/example", + "version": "{{user `version`}}" + } + ] + ] +} +``` + +## Vagrant Share + +Vagrant Share via Atlas has been deprecated, and instead Vagrant supports native integration with [ngrok](https://ngrok.com). +Users of Vagrant Share should switch to the [ngrok-powered Vagrant Share driver](https://www.vagrantup.com/docs/share/ngrok.html) prior to June 27th, which will become the default in the next version of Vagrant + +## Downtime + +There will be a brief outage of Vagrant services within Atlas/Terraform Enterprise on June 27th at 6PM EDT/3PM PDT until the migration is complete. +We estimate that this will take less than 30 minutes.