provisioners/ansible: honor galaxy_roles_path when running ansible-playbook

This commit include the following changes:
- systematically set ANSIBLE_ROLES_PATH environment variable when
  galaxy_roles_path is defined.
- slightly refactor to introduce the concept of "provisioning working
  directory" (possible usage in the future for resolving GH-7195)
- fix a bug in ansible-galaxy execution by the ansible_local provisioner
  if the paths contains blank characters.

Fix #7269
This commit is contained in:
Gilles Cornu 2016-06-11 07:28:05 +02:00
parent 2cecbfd2eb
commit a7dfc73b85
4 changed files with 39 additions and 10 deletions

View File

@ -37,7 +37,7 @@ module VagrantPlugins
def ansible_playbook_command_for_shell_execution def ansible_playbook_command_for_shell_execution
shell_command = [] shell_command = []
@environment_variables.each_pair do |k, v| @environment_variables.each_pair do |k, v|
if k == 'ANSIBLE_SSH_ARGS' if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH/
shell_command << "#{k}='#{v}'" shell_command << "#{k}='#{v}'"
else else
shell_command << "#{k}=#{v}" shell_command << "#{k}=#{v}"
@ -98,6 +98,10 @@ module VagrantPlugins
# Setting ANSIBLE_NOCOLOR is "unnecessary" at the moment, but this could change in the future # Setting ANSIBLE_NOCOLOR is "unnecessary" at the moment, but this could change in the future
# (e.g. local provisioner [GH-2103], possible change in vagrant/ansible integration, etc.) # (e.g. local provisioner [GH-2103], possible change in vagrant/ansible integration, etc.)
@environment_variables["ANSIBLE_NOCOLOR"] = "true" if !@machine.env.ui.color? @environment_variables["ANSIBLE_NOCOLOR"] = "true" if !@machine.env.ui.color?
# Use ANSIBLE_ROLES_PATH to tell ansible-playbook where to look for roles
# (there is no equivalent command line argument in ansible-playbook)
@environment_variables["ANSIBLE_ROLES_PATH"] = get_galaxy_roles_path if config.galaxy_roles_path
end end
# Auto-generate "safe" inventory file based on Vagrantfile, # Auto-generate "safe" inventory file based on Vagrantfile,
@ -221,11 +225,12 @@ module VagrantPlugins
end end
end end
def get_galaxy_role_file(base_dir) def get_galaxy_role_file
Helpers::expand_path_in_unix_style(config.galaxy_role_file, base_dir) Helpers::expand_path_in_unix_style(config.galaxy_role_file, get_provisioning_working_directory)
end end
def get_galaxy_roles_path(base_dir) def get_galaxy_roles_path
base_dir = get_provisioning_working_directory
if config.galaxy_roles_path if config.galaxy_roles_path
Helpers::expand_path_in_unix_style(config.galaxy_roles_path, base_dir) Helpers::expand_path_in_unix_style(config.galaxy_roles_path, base_dir)
else else

View File

@ -67,10 +67,14 @@ module VagrantPlugins
end end
end end
def get_provisioning_working_directory
config.provisioning_path
end
def execute_ansible_galaxy_on_guest def execute_ansible_galaxy_on_guest
command_values = { command_values = {
role_file: get_galaxy_role_file(config.provisioning_path), role_file: "'#{get_galaxy_role_file}'",
roles_path: get_galaxy_roles_path(config.provisioning_path) roles_path: "'#{get_galaxy_roles_path}'"
} }
remote_command = config.galaxy_command % command_values remote_command = config.galaxy_command % command_values

View File

@ -89,8 +89,8 @@ module VagrantPlugins
def execute_ansible_galaxy_from_host def execute_ansible_galaxy_from_host
command_values = { command_values = {
role_file: get_galaxy_role_file(machine.env.root_path), role_file: get_galaxy_role_file,
roles_path: get_galaxy_roles_path(machine.env.root_path) roles_path: get_galaxy_roles_path
} }
command_template = config.galaxy_command.gsub(' ', VAGRANT_ARG_SEPARATOR) command_template = config.galaxy_command.gsub(' ', VAGRANT_ARG_SEPARATOR)
str_command = command_template % command_values str_command = command_template % command_values
@ -102,6 +102,7 @@ module VagrantPlugins
workdir: @machine.env.root_path.to_s workdir: @machine.env.root_path.to_s
} }
# FIXME: role_file and roles_path arguments should be quoted in the console output
ui_running_ansible_command "galaxy", str_command.gsub(VAGRANT_ARG_SEPARATOR, ' ') ui_running_ansible_command "galaxy", str_command.gsub(VAGRANT_ARG_SEPARATOR, ' ')
execute_command_from_host command execute_command_from_host command
@ -188,6 +189,10 @@ module VagrantPlugins
return machines return machines
end end
def get_provisioning_working_directory
machine.env.root_path
end
def get_inventory_ssh_machine(machine, ssh_info) def get_inventory_ssh_machine(machine, ssh_info)
forced_remote_user = "" forced_remote_user = ""
if config.force_remote_user if config.force_remote_user

View File

@ -771,6 +771,20 @@ VF
end end
end end
context "with galaxy_roles_path option defined" do
before do
config.galaxy_roles_path = "my-roles"
end
it "sets ANSIBLE_ROLES_PATH with corresponding absolute path" do
expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args|
cmd_opts = args.last
expect(cmd_opts[:env]).to include("ANSIBLE_ROLES_PATH")
expect(cmd_opts[:env]['ANSIBLE_ROLES_PATH']).to eql(File.join(machine.env.root_path, "my-roles"))
}
end
end
context "with extra_vars option defined" do context "with extra_vars option defined" do
describe "with a hash value" do describe "with a hash value" do
before do before do
@ -798,6 +812,7 @@ VF
ssh_info[:private_key_path] = ['/my/key1', '/my/key2'] ssh_info[:private_key_path] = ['/my/key1', '/my/key2']
# command line arguments # command line arguments
config.galaxy_roles_path = "/up/to the stars"
config.extra_vars = { var1: %Q(string with 'apostrophes', \\, " and =), var2: { x: 42 } } config.extra_vars = { var1: %Q(string with 'apostrophes', \\, " and =), var2: { x: 42 } }
config.sudo = true config.sudo = true
config.sudo_user = 'deployer' config.sudo_user = 'deployer'
@ -816,7 +831,7 @@ VF
config.raw_ssh_args = ['-o ControlMaster=no'] config.raw_ssh_args = ['-o ControlMaster=no']
end end
it_should_set_arguments_and_environment_variables 21, 4, true it_should_set_arguments_and_environment_variables 21, 5, true
it_should_explicitly_enable_ansible_ssh_control_persist_defaults it_should_explicitly_enable_ansible_ssh_control_persist_defaults
it_should_set_optional_arguments({ "extra_vars" => "--extra-vars={\"var1\":\"string with 'apostrophes', \\\\, \\\" and =\",\"var2\":{\"x\":42}}", it_should_set_optional_arguments({ "extra_vars" => "--extra-vars={\"var1\":\"string with 'apostrophes', \\\\, \\\" and =\",\"var2\":{\"x\":42}}",
"sudo" => "--sudo", "sudo" => "--sudo",
@ -843,7 +858,7 @@ 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(%Q(PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -i '/my/key1' -i '/my/key2' -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --ask-sudo-pass --ask-vault-pass --limit="machine*:&vagrant:!that_one" --inventory-file=#{generated_inventory_dir} --extra-vars="{\\"var1\\":\\"string with 'apostrophes', \\\\\\\\, \\\\\\" and =\\",\\"var2\\":{\\"x\\":42}}" --sudo --sudo-user=deployer -vvv --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task="joe's awesome task" --why-not --su-user=foot --ask-su-pass --limit=all --private-key=./myself.key --extra-vars='{\"var3\":\"foo\"}' playbook.yml)) expect(full_command).to eq(%Q(PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_ROLES_PATH='/up/to the stars' ANSIBLE_HOST_KEY_CHECKING=true ANSIBLE_SSH_ARGS='-o IdentitiesOnly=yes -i '/my/key1' -i '/my/key2' -o ForwardAgent=yes -o ControlMaster=no -o ControlMaster=auto -o ControlPersist=60s' ansible-playbook --connection=ssh --timeout=30 --ask-sudo-pass --ask-vault-pass --limit="machine*:&vagrant:!that_one" --inventory-file=#{generated_inventory_dir} --extra-vars="{\\"var1\\":\\"string with 'apostrophes', \\\\\\\\, \\\\\\" and =\\",\\"var2\\":{\\"x\\":42}}" --sudo --sudo-user=deployer -vvv --vault-password-file=#{File.expand_path(__FILE__)} --tags=db,www --skip-tags=foo,bar --start-at-task="joe's awesome task" --why-not --su-user=foot --ask-su-pass --limit=all --private-key=./myself.key --extra-vars='{\"var3\":\"foo\"}' playbook.yml))
} }
end end
end end