Merge pull request #7918 from mitchellh/gildegoma/fix-7195
Add `config_file` option to both Ansible provisioners
This commit is contained in:
commit
8caed8ea16
|
@ -6,6 +6,7 @@ module VagrantPlugins
|
|||
GALAXY_COMMAND_DEFAULT = "ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force".freeze
|
||||
PLAYBOOK_COMMAND_DEFAULT = "ansible-playbook".freeze
|
||||
|
||||
attr_accessor :config_file
|
||||
attr_accessor :extra_vars
|
||||
attr_accessor :galaxy_role_file
|
||||
attr_accessor :galaxy_roles_path
|
||||
|
@ -26,6 +27,7 @@ module VagrantPlugins
|
|||
attr_accessor :verbose
|
||||
|
||||
def initialize
|
||||
@config_file = UNSET_VALUE
|
||||
@extra_vars = UNSET_VALUE
|
||||
@galaxy_role_file = UNSET_VALUE
|
||||
@galaxy_roles_path = UNSET_VALUE
|
||||
|
@ -47,6 +49,7 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def finalize!
|
||||
@config_file = nil if @config_file == UNSET_VALUE
|
||||
@extra_vars = nil if @extra_vars == UNSET_VALUE
|
||||
@galaxy_role_file = nil if @galaxy_role_file == UNSET_VALUE
|
||||
@galaxy_roles_path = nil if @galaxy_roles_path == UNSET_VALUE
|
||||
|
|
|
@ -29,20 +29,39 @@ module VagrantPlugins
|
|||
check_path_is_a_file(config.playbook, :playbook)
|
||||
|
||||
check_path_exists(config.inventory_path, :inventory_path) if config.inventory_path
|
||||
check_path_is_a_file(config.config_file, :config_file) if config.config_file
|
||||
check_path_is_a_file(config.extra_vars[1..-1], :extra_vars) if has_an_extra_vars_file_argument
|
||||
check_path_is_a_file(config.galaxy_role_file, :galaxy_role_file) if config.galaxy_role_file
|
||||
check_path_is_a_file(config.vault_password_file, :vault_password_file) if config.vault_password_file
|
||||
end
|
||||
|
||||
def ansible_playbook_command_for_shell_execution
|
||||
shell_command = []
|
||||
def get_environment_variables_for_shell_execution
|
||||
shell_env_vars = []
|
||||
@environment_variables.each_pair do |k, v|
|
||||
if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH/
|
||||
shell_command << "#{k}='#{v}'"
|
||||
if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH|ANSIBLE_CONFIG/
|
||||
shell_env_vars << "#{k}='#{v}'"
|
||||
else
|
||||
shell_command << "#{k}=#{v}"
|
||||
shell_env_vars << "#{k}=#{v}"
|
||||
end
|
||||
end
|
||||
shell_env_vars
|
||||
end
|
||||
|
||||
def ansible_galaxy_command_for_shell_execution
|
||||
command_values = {
|
||||
role_file: "'#{get_galaxy_role_file}'",
|
||||
roles_path: "'#{get_galaxy_roles_path}'"
|
||||
}
|
||||
|
||||
shell_command = get_environment_variables_for_shell_execution
|
||||
|
||||
shell_command << config.galaxy_command % command_values
|
||||
|
||||
shell_command.flatten.join(' ')
|
||||
end
|
||||
|
||||
def ansible_playbook_command_for_shell_execution
|
||||
shell_command = get_environment_variables_for_shell_execution
|
||||
|
||||
shell_command << config.playbook_command
|
||||
|
||||
|
@ -102,6 +121,12 @@ module VagrantPlugins
|
|||
# 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
|
||||
|
||||
prepare_ansible_config_environment_variable
|
||||
end
|
||||
|
||||
def prepare_ansible_config_environment_variable
|
||||
@environment_variables["ANSIBLE_CONFIG"] = config.config_file if config.config_file
|
||||
end
|
||||
|
||||
# Auto-generate "safe" inventory file based on Vagrantfile,
|
||||
|
|
|
@ -72,14 +72,9 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def execute_ansible_galaxy_on_guest
|
||||
command_values = {
|
||||
role_file: "'#{get_galaxy_role_file}'",
|
||||
roles_path: "'#{get_galaxy_roles_path}'"
|
||||
}
|
||||
prepare_ansible_config_environment_variable
|
||||
|
||||
remote_command = config.galaxy_command % command_values
|
||||
|
||||
execute_ansible_command_on_guest "galaxy", remote_command
|
||||
execute_ansible_command_on_guest "galaxy", ansible_galaxy_command_for_shell_execution
|
||||
end
|
||||
|
||||
def execute_ansible_playbook_on_guest
|
||||
|
|
|
@ -20,6 +20,7 @@ module VagrantPlugins
|
|||
|
||||
check_files_existence
|
||||
warn_for_unsupported_platform
|
||||
|
||||
execute_ansible_galaxy_from_host if config.galaxy_role_file
|
||||
execute_ansible_playbook_from_host
|
||||
end
|
||||
|
@ -88,6 +89,8 @@ module VagrantPlugins
|
|||
end
|
||||
|
||||
def execute_ansible_galaxy_from_host
|
||||
prepare_ansible_config_environment_variable
|
||||
|
||||
command_values = {
|
||||
role_file: get_galaxy_role_file,
|
||||
roles_path: get_galaxy_roles_path
|
||||
|
@ -97,20 +100,20 @@ module VagrantPlugins
|
|||
|
||||
command = str_command.split(VAGRANT_ARG_SEPARATOR)
|
||||
command << {
|
||||
env: @environment_variables,
|
||||
# Write stdout and stderr data, since it's the regular Ansible output
|
||||
notify: [:stdout, :stderr],
|
||||
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", ansible_galaxy_command_for_shell_execution
|
||||
|
||||
execute_command_from_host command
|
||||
end
|
||||
|
||||
def execute_ansible_playbook_from_host
|
||||
prepare_command_arguments
|
||||
prepare_environment_variables
|
||||
prepare_command_arguments
|
||||
|
||||
# Assemble the full ansible-playbook command
|
||||
command = [config.playbook_command] << @command_arguments
|
||||
|
@ -234,6 +237,7 @@ module VagrantPlugins
|
|||
proxy_cmd += " exec nc %h %p 2>/dev/null"
|
||||
|
||||
ssh_options << "-o ProxyCommand='#{ proxy_cmd }'"
|
||||
# TODO ssh_options << "-o ProxyCommand=\"#{ proxy_cmd }\""
|
||||
end
|
||||
|
||||
# Use an SSH ProxyCommand when corresponding Vagrant setting is defined
|
||||
|
|
|
@ -16,7 +16,8 @@ describe VagrantPlugins::Ansible::Config::Guest do
|
|||
let(:existing_file) { "this/path/is/a/stub" }
|
||||
|
||||
it "supports a list of options" do
|
||||
supported_options = %w( extra_vars
|
||||
supported_options = %w( config_file
|
||||
extra_vars
|
||||
galaxy_command
|
||||
galaxy_role_file
|
||||
galaxy_roles_path
|
||||
|
|
|
@ -15,6 +15,7 @@ describe VagrantPlugins::Ansible::Config::Host, :skip_windows => true do
|
|||
it "supports a list of options" do
|
||||
supported_options = %w( ask_sudo_pass
|
||||
ask_vault_pass
|
||||
config_file
|
||||
extra_vars
|
||||
force_remote_user
|
||||
galaxy_command
|
||||
|
|
|
@ -3,6 +3,7 @@ shared_examples_for 'options shared by both Ansible provisioners' do
|
|||
it "assigns default values to unset common options" do
|
||||
subject.finalize!
|
||||
|
||||
expect(subject.config_file).to be_nil
|
||||
expect(subject.extra_vars).to be_nil
|
||||
expect(subject.galaxy_command).to eql("ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force")
|
||||
expect(subject.galaxy_role_file).to be_nil
|
||||
|
|
|
@ -59,8 +59,6 @@ VF
|
|||
stubbed_ui.stub(detail: "")
|
||||
machine.env.stub(ui: stubbed_ui)
|
||||
|
||||
subject.stub(:check_path)
|
||||
|
||||
config.playbook = 'playbook.yml'
|
||||
end
|
||||
|
||||
|
@ -195,7 +193,9 @@ VF
|
|||
before do
|
||||
unless example.metadata[:skip_before]
|
||||
config.finalize!
|
||||
|
||||
Vagrant::Util::Subprocess.stub(execute: Vagrant::Util::Subprocess::Result.new(0, "", ""))
|
||||
subject.stub(:check_path)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -207,44 +207,46 @@ VF
|
|||
|
||||
describe 'checking existence of Ansible configuration files' do
|
||||
|
||||
describe 'when the playbook file does not exist' do
|
||||
it "raises an error", skip_before: true, skip_after: true do
|
||||
STUBBED_INVALID_PATH = "/test/239nfmd/invalid_path".freeze
|
||||
|
||||
subject.stub(:check_path).and_raise(VagrantPlugins::Ansible::Errors::AnsibleError,
|
||||
_key: :config_file_not_found,
|
||||
config_option: "playbook",
|
||||
path: "/home/wip/test/invalid_path.yml",
|
||||
system: "host")
|
||||
it 'raises an error when the `playbook` file does not exist', skip_before: true, skip_after: true do
|
||||
subject.stub(:check_path).and_raise(VagrantPlugins::Ansible::Errors::AnsibleError,
|
||||
_key: :config_file_not_found,
|
||||
config_option: "playbook",
|
||||
path: STUBBED_INVALID_PATH,
|
||||
system: "host")
|
||||
|
||||
config.playbook = "/home/wip/test/invalid_path.yml"
|
||||
config.finalize!
|
||||
config.playbook = STUBBED_INVALID_PATH
|
||||
config.finalize!
|
||||
|
||||
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleError,
|
||||
"`playbook` does not exist on the host: /home/wip/test/invalid_path.yml")
|
||||
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleError,
|
||||
"`playbook` does not exist on the host: #{STUBBED_INVALID_PATH}")
|
||||
end
|
||||
|
||||
%w(config_file extra_vars inventory_path galaxy_role_file vault_password_file).each do |option_name|
|
||||
it "raises an error when the '#{option_name}' does not exist", skip_before: true, skip_after: true do
|
||||
Vagrant::Util::Subprocess.stub(execute: Vagrant::Util::Subprocess::Result.new(0, "", ""))
|
||||
|
||||
config.playbook = existing_file
|
||||
config.send(option_name + '=', STUBBED_INVALID_PATH)
|
||||
if option_name == 'extra_vars'
|
||||
# little trick to auto-append the '@' prefix, which is a duty of the config validator...
|
||||
config.validate(machine)
|
||||
end
|
||||
config.finalize!
|
||||
|
||||
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleError,
|
||||
"`#{option_name}` does not exist on the host: #{STUBBED_INVALID_PATH}")
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when the inventory path does not exist' do
|
||||
it "raises an error"
|
||||
end
|
||||
|
||||
describe 'when the extra_vars file does not exist' do
|
||||
it "raises an error"
|
||||
end
|
||||
|
||||
describe 'when the galaxy_role_file does not exist' do
|
||||
it "raises an error"
|
||||
end
|
||||
|
||||
describe 'when the vault_password_file does not exist' do
|
||||
it "raises an error"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'when ansible-playbook fails' do
|
||||
it "raises an error", skip_before: true, skip_after: true do
|
||||
config.finalize!
|
||||
|
||||
subject.stub(:check_path)
|
||||
Vagrant::Util::Subprocess.stub(execute: Vagrant::Util::Subprocess::Result.new(1, "", ""))
|
||||
|
||||
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed)
|
||||
|
@ -582,6 +584,20 @@ VF
|
|||
end
|
||||
end
|
||||
|
||||
context "with config_file option defined" do
|
||||
before do
|
||||
config.config_file = existing_file
|
||||
end
|
||||
|
||||
it "sets ANSIBLE_CONFIG environment variable" do
|
||||
expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args|
|
||||
cmd_opts = args.last
|
||||
expect(cmd_opts[:env]).to include("ANSIBLE_CONFIG")
|
||||
expect(cmd_opts[:env]['ANSIBLE_CONFIG']).to eql(existing_file)
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
describe "with ask_vault_pass option" do
|
||||
before do
|
||||
config.ask_vault_pass = true
|
||||
|
@ -777,6 +793,8 @@ VF
|
|||
|
||||
it "raises an error when ansible-galaxy command fails", skip_before: true, skip_after: true do
|
||||
config.finalize!
|
||||
|
||||
subject.stub(:check_path)
|
||||
Vagrant::Util::Subprocess.stub(execute: Vagrant::Util::Subprocess::Result.new(1, "", ""))
|
||||
|
||||
expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed)
|
||||
|
@ -852,11 +870,12 @@ VF
|
|||
config.raw_arguments = ["--why-not", "--su-user=foot", "--ask-su-pass", "--limit=all", "--private-key=./myself.key", "--extra-vars='{\"var3\":\"foo\"}'"]
|
||||
|
||||
# environment variables
|
||||
config.config_file = existing_file
|
||||
config.host_key_checking = true
|
||||
config.raw_ssh_args = ['-o ControlMaster=no']
|
||||
end
|
||||
|
||||
it_should_set_arguments_and_environment_variables 21, 5, true
|
||||
it_should_set_arguments_and_environment_variables 21, 6, true
|
||||
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}}",
|
||||
"sudo" => "--sudo",
|
||||
|
@ -883,7 +902,7 @@ 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(%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))
|
||||
expect(full_command).to eq(%Q(PYTHONUNBUFFERED=1 ANSIBLE_FORCE_COLOR=true ANSIBLE_ROLES_PATH='/up/to the stars' ANSIBLE_CONFIG='#{existing_file}' 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=#{existing_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
|
||||
|
|
|
@ -17,6 +17,10 @@ These options get passed to the `ansible-playbook` command that ships with Ansib
|
|||
|
||||
Some of these options are for advanced usage only and should not be used unless you understand their purpose.
|
||||
|
||||
- `config_file` (string) - The path to an [Ansible Configuration file](https://docs.ansible.com/intro_configuration.html).
|
||||
|
||||
By default, this option is not set, and Ansible will [search for a possible configuration file in some default locations](/docs/provisioning/ansible_intro.html#ANSIBLE_CONFIG).
|
||||
|
||||
- `extra_vars` (string or hash) - Pass additional variables (with highest priority) to the playbook.
|
||||
|
||||
This parameter can be a path to a JSON or YAML file, or a hash.
|
||||
|
|
|
@ -246,12 +246,11 @@ Certain settings in Ansible are (only) adjustable via a [configuration file](htt
|
|||
|
||||
When shipping an Ansible configuration file it is good to know that:
|
||||
|
||||
- it is possible to reference an Ansible configuration file via `ANSIBLE_CONFIG` environment variable, if you want to be flexible about the location of this file.
|
||||
- as of Ansible 1.5, the lookup order is the following:
|
||||
|
||||
- `ANSIBLE_CONFIG` an environment variable
|
||||
- `ansible.cfg` in the runtime working directory
|
||||
- `.ansible.cfg` in the user home directory
|
||||
- `/etc/ansible/ansible.cfg`
|
||||
|
||||
- `ansible-playbook` doesn't look for a configuration file relative to the playbook file location (e.g. in the same directory)
|
||||
- as of Ansible 1.5, the lookup order is the following:
|
||||
- any path set as `ANSIBLE_CONFIG` environment variable
|
||||
- `ansible.cfg` in the runtime working directory
|
||||
- `.ansible.cfg` in the user home directory
|
||||
- `/etc/ansible/ansible.cfg`
|
||||
- Ansible commands don't look for a configuration file relative to the playbook file location (e.g. in the same directory)
|
||||
- an `ansible.cfg` file located in the same directory as your `Vagrantfile` will be used by default.
|
||||
- it is also possible to reference any other location with the [config_file](/docs/provisioning/ansible_common.html#config_file) provisioner option. In this case, Vagrant will set the `ANSIBLE_CONFIG` environment variable accordingly.
|
||||
|
|
Loading…
Reference in New Issue