provisioners/ansible: add `IdentitiesOnly=yes`
This SSH option is always set, except when Vagrant is running from an
operating system fo the Solaris-family, as this parameter is not
supported by SunSSH. Logic taken from
bed1f8335f/lib/vagrant/util/ssh.rb (L116-L121)
Fix #5017
This commit is contained in:
parent
49d1a92bf6
commit
c3cae3d235
|
@ -5,6 +5,7 @@ BUG FIXES:
|
||||||
- core: push configurations are validated with global configs [GH-5130]
|
- core: push configurations are validated with global configs [GH-5130]
|
||||||
- guests/funtoo: fix incorrect path in configure networks [GH-4812]
|
- guests/funtoo: fix incorrect path in configure networks [GH-4812]
|
||||||
- plugins/login: allow users to login with a token [GH-5145]
|
- plugins/login: allow users to login with a token [GH-5145]
|
||||||
|
- provisioners/ansible: fix SSH settings to support more than 5 ssh keys [GH-5017]
|
||||||
|
|
||||||
## 1.7.2 (January 6, 2015)
|
## 1.7.2 (January 6, 2015)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
require "vagrant/util/platform"
|
||||||
|
|
||||||
module VagrantPlugins
|
module VagrantPlugins
|
||||||
module Ansible
|
module Ansible
|
||||||
class Provisioner < Vagrant.plugin("2", :provisioner)
|
class Provisioner < Vagrant.plugin("2", :provisioner)
|
||||||
|
@ -209,6 +211,12 @@ module VagrantPlugins
|
||||||
# Don't access user's known_hosts file, except when host_key_checking is enabled.
|
# 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
|
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
|
# Multiple Private Keys
|
||||||
@ssh_info[:private_key_path].drop(1).each do |key|
|
@ssh_info[:private_key_path].drop(1).each do |key|
|
||||||
ssh_options << "-o IdentityFile=#{key}"
|
ssh_options << "-o IdentityFile=#{key}"
|
||||||
|
|
|
@ -50,6 +50,7 @@ VF
|
||||||
let(:generated_inventory_file) { File.join(generated_inventory_dir, 'vagrant_ansible_inventory') }
|
let(:generated_inventory_file) { File.join(generated_inventory_dir, 'vagrant_ansible_inventory') }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
|
Vagrant::Util::Platform.stub(solaris?: false)
|
||||||
subject.instance_variable_get(:@logger).stub(:debug?).and_return(false)
|
subject.instance_variable_get(:@logger).stub(:debug?).and_return(false)
|
||||||
|
|
||||||
machine.stub(ssh_info: ssh_info)
|
machine.stub(ssh_info: ssh_info)
|
||||||
|
@ -103,10 +104,11 @@ VF
|
||||||
cmd_opts = args.last
|
cmd_opts = args.last
|
||||||
|
|
||||||
if expected_host_key_checking
|
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
|
else
|
||||||
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o UserKnownHostsFile=/dev/null")
|
expect(cmd_opts[:env]['ANSIBLE_SSH_ARGS']).to include("-o UserKnownHostsFile=/dev/null")
|
||||||
end
|
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_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]['ANSIBLE_HOST_KEY_CHECKING']).to eql(expected_host_key_checking.to_s)
|
||||||
expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1)
|
expect(cmd_opts[:env]['PYTHONUNBUFFERED']).to eql(1)
|
||||||
|
@ -270,7 +272,7 @@ VF
|
||||||
config.host_key_checking = true
|
config.host_key_checking = true
|
||||||
end
|
end
|
||||||
|
|
||||||
it_should_set_arguments_and_environment_variables 6, 3, true
|
it_should_set_arguments_and_environment_variables 6, 4, true
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with boolean (flag) options disabled" do
|
describe "with boolean (flag) options disabled" do
|
||||||
|
@ -465,7 +467,7 @@ VF
|
||||||
|
|
||||||
it "shows the ansible-playbook command" do
|
it "shows the ansible-playbook command" do
|
||||||
expect(machine.env.ui).to receive(:detail).with { |full_command|
|
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 --limit='machine1' --inventory-file=#{generated_inventory_dir} playbook.yml")
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -480,7 +482,7 @@ VF
|
||||||
|
|
||||||
it "shows the ansible-playbook command" do
|
it "shows the ansible-playbook command" do
|
||||||
expect(machine.env.ui).to receive(:detail).with { |full_command|
|
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 --limit='machine1' --inventory-file=#{generated_inventory_dir} -v playbook.yml")
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -538,10 +540,52 @@ VF
|
||||||
|
|
||||||
it "shows the ansible-playbook command, with additional quotes when required" do
|
it "shows the ansible-playbook command, with additional quotes when required" do
|
||||||
expect(machine.env.ui).to receive(:detail).with { |full_command|
|
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 --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 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
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue