diff --git a/plugins/provisioners/ansible/config/base.rb b/plugins/provisioners/ansible/config/base.rb index e0b610a27..2cefe4a89 100644 --- a/plugins/provisioners/ansible/config/base.rb +++ b/plugins/provisioners/ansible/config/base.rb @@ -3,7 +3,12 @@ module VagrantPlugins module Config class Base < Vagrant.plugin("2", :config) + GALAXY_COMMAND_DEFAULT = "ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force".freeze + attr_accessor :extra_vars + attr_accessor :galaxy_role_file + attr_accessor :galaxy_roles_path + attr_accessor :galaxy_command attr_accessor :groups attr_accessor :inventory_path attr_accessor :limit @@ -19,6 +24,9 @@ module VagrantPlugins def initialize @extra_vars = UNSET_VALUE + @galaxy_role_file = UNSET_VALUE + @galaxy_roles_path = UNSET_VALUE + @galaxy_command = UNSET_VALUE @groups = UNSET_VALUE @inventory_path = UNSET_VALUE @limit = UNSET_VALUE @@ -34,19 +42,22 @@ module VagrantPlugins end def finalize! - @extra_vars = nil if @extra_vars == UNSET_VALUE - @groups = {} if @groups == UNSET_VALUE - @inventory_path = nil if @inventory_path == UNSET_VALUE - @limit = nil if @limit == UNSET_VALUE - @playbook = nil if @playbook == UNSET_VALUE - @raw_arguments = nil if @raw_arguments == UNSET_VALUE - @skip_tags = nil if @skip_tags == UNSET_VALUE - @start_at_task = nil if @start_at_task == UNSET_VALUE - @sudo = false if @sudo != true - @sudo_user = nil if @sudo_user == UNSET_VALUE - @tags = nil if @tags == UNSET_VALUE - @vault_password_file = nil if @vault_password_file == UNSET_VALUE - @verbose = false if @verbose == 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 + @galaxy_command = GALAXY_COMMAND_DEFAULT if @galaxy_command == UNSET_VALUE + @groups = {} if @groups == UNSET_VALUE + @inventory_path = nil if @inventory_path == UNSET_VALUE + @limit = nil if @limit == UNSET_VALUE + @playbook = nil if @playbook == UNSET_VALUE + @raw_arguments = nil if @raw_arguments == UNSET_VALUE + @skip_tags = nil if @skip_tags == UNSET_VALUE + @start_at_task = nil if @start_at_task == UNSET_VALUE + @sudo = false if @sudo != true + @sudo_user = nil if @sudo_user == UNSET_VALUE + @tags = nil if @tags == UNSET_VALUE + @vault_password_file = nil if @vault_password_file == UNSET_VALUE + @verbose = false if @verbose == UNSET_VALUE end # Just like the normal configuration "validate" method except that @@ -57,26 +68,26 @@ module VagrantPlugins # Validate that a playbook path was provided if !playbook - @errors << I18n.t("vagrant.provisioners.ansible.no_playbook") + @errors << I18n.t("vagrant.provisioners.ansible.errors.no_playbook") end - # Validate the existence of the playbook if playbook - check_path_is_a_file(machine, playbook, "vagrant.provisioners.ansible.playbook_path_invalid") + check_path_is_a_file(machine, playbook, "vagrant.provisioners.ansible.errors.playbook_path_invalid") end - # Validate the existence of the inventory_path, if specified if inventory_path - check_path_exists(machine, inventory_path, "vagrant.provisioners.ansible.inventory_path_invalid") + check_path_exists(machine, inventory_path, "vagrant.provisioners.ansible.errors.inventory_path_invalid") + end + + if galaxy_role_file + check_path_is_a_file(machine, galaxy_role_file, "vagrant.provisioners.ansible.errors.galaxy_role_file_invalid") end - # Validate the existence of the vault_password_file, if specified if vault_password_file - check_path_is_a_file(machine, vault_password_file, "vagrant.provisioners.ansible.vault_password_file_invalid") + check_path_is_a_file(machine, vault_password_file, "vagrant.provisioners.ansible.errors.vault_password_file_invalid") end - # Validate that extra_vars is either a hash, or a path to an - # existing file + # Validate that extra_vars is either a hash, or a path to an existing file if extra_vars extra_vars_is_valid = extra_vars.kind_of?(Hash) || extra_vars.kind_of?(String) if extra_vars.kind_of?(String) @@ -92,7 +103,7 @@ module VagrantPlugins if !extra_vars_is_valid @errors << I18n.t( - "vagrant.provisioners.ansible.extra_vars_invalid", + "vagrant.provisioners.ansible.errors.extra_vars_invalid", type: extra_vars.class.to_s, value: extra_vars.to_s) end diff --git a/plugins/provisioners/ansible/errors.rb b/plugins/provisioners/ansible/errors.rb index 2a6f8dbbd..06a1063cf 100644 --- a/plugins/provisioners/ansible/errors.rb +++ b/plugins/provisioners/ansible/errors.rb @@ -7,16 +7,16 @@ module VagrantPlugins error_namespace("vagrant.provisioners.ansible.errors") end - class AnsiblePlaybookAppFailed < AnsibleError - error_key(:ansible_playbook_app_failed) + class AnsibleCommandFailed < AnsibleError + error_key(:ansible_command_failed) end - class AnsiblePlaybookAppNotFoundOnHost < AnsibleError - error_key(:ansible_playbook_app_not_found_on_host) + class AnsibleNotFoundOnHost < AnsibleError + error_key(:ansible_not_found_on_host) end - class AnsiblePlaybookAppNotFoundOnGuest < AnsibleError - error_key(:ansible_playbook_app_not_found_on_guest) + class AnsibleNotFoundOnGuest < AnsibleError + error_key(:ansible_not_found_on_guest) end class AnsibleVersionNotFoundOnGuest < AnsibleError diff --git a/plugins/provisioners/ansible/provisioner/base.rb b/plugins/provisioners/ansible/provisioner/base.rb index 051473271..7a455b2bf 100644 --- a/plugins/provisioners/ansible/provisioner/base.rb +++ b/plugins/provisioners/ansible/provisioner/base.rb @@ -132,6 +132,26 @@ module VagrantPlugins end end + def get_galaxy_role_file(basedir) + File.expand_path(config.galaxy_role_file, basedir) + end + + def get_galaxy_roles_path(basedir) + if config.galaxy_roles_path + File.expand_path(config.galaxy_roles_path, basedir) + else + File.join(Pathname.new(config.playbook).expand_path(basedir).parent, 'roles') + end + end + + def ui_running_ansible_command(name, command) + @machine.ui.detail I18n.t("vagrant.provisioners.ansible.running_#{name}") + if verbosity_is_enabled? + # Show the ansible command in use + @machine.env.ui.detail command + end + end + def verbosity_is_enabled? config.verbose && !config.verbose.to_s.empty? end diff --git a/plugins/provisioners/ansible/provisioner/guest.rb b/plugins/provisioners/ansible/provisioner/guest.rb index 285df8ac1..a82bf7562 100644 --- a/plugins/provisioners/ansible/provisioner/guest.rb +++ b/plugins/provisioners/ansible/provisioner/guest.rb @@ -14,8 +14,7 @@ module VagrantPlugins def provision check_and_install_ansible - prepare_common_command_arguments - prepare_common_environment_variables + execute_ansible_galaxy_on_guest if config.galaxy_role_file execute_ansible_playbook_on_guest end @@ -47,15 +46,15 @@ module VagrantPlugins if config.install && (config.version.to_s.to_sym == :latest || !@machine.guest.capability(:ansible_installed, config.version)) - @machine.ui.detail(I18n.t("vagrant.provisioners.ansible.installing")) + @machine.ui.detail I18n.t("vagrant.provisioners.ansible.installing") @machine.guest.capability(:ansible_install) end - # Check for the existence of ansible-playbook binary on the guest, + # Check that ansible binaries are well installed on the guest, @machine.communicate.execute( - "ansible-playbook --help", - :error_class => Ansible::Errors::AnsibleError, - :error_key => :ansible_playbook_app_not_found_on_guest) + "ansible-galaxy --help && ansible-playbook --help", + :error_class => Ansible::Errors::AnsibleNotFoundOnGuest, + :error_key => :ansible_not_found_on_guest) # Check if requested ansible version is available if (!config.version.empty? && @@ -65,18 +64,31 @@ module VagrantPlugins end end + def execute_ansible_galaxy_on_guest + command_values = { + :role_file => get_galaxy_role_file(config.provisioning_path), + :roles_path => get_galaxy_roles_path(config.provisioning_path) + } + remote_command = config.galaxy_command % command_values + + execute_ansible_command_on_guest "galaxy", remote_command + end + def execute_ansible_playbook_on_guest + prepare_common_command_arguments + prepare_common_environment_variables + command = (%w(ansible-playbook) << @command_arguments << config.playbook).flatten remote_command = "cd #{config.provisioning_path} && #{Helpers::stringify_ansible_playbook_command(@environment_variables, command)}" - # TODO: generic HOOK ??? - # Show the ansible command in use - if verbosity_is_enabled? - @machine.env.ui.detail(remote_command) - end + execute_ansible_command_on_guest "playbook", remote_command + end - result = execute_on_guest(remote_command) - raise Ansible::Errors::AnsiblePlaybookAppFailed if result != 0 + def execute_ansible_command_on_guest(name, command) + ui_running_ansible_command name, command + + result = execute_on_guest(command) + raise Ansible::Errors::AnsibleCommandFailed if result != 0 end def execute_on_guest(command) diff --git a/plugins/provisioners/ansible/provisioner/host.rb b/plugins/provisioners/ansible/provisioner/host.rb index d25c88567..23d59f7d2 100644 --- a/plugins/provisioners/ansible/provisioner/host.rb +++ b/plugins/provisioners/ansible/provisioner/host.rb @@ -19,13 +19,14 @@ module VagrantPlugins @ssh_info = @machine.ssh_info warn_for_unsupported_platform - prepare_command_arguments - prepare_environment_variables + execute_ansible_galaxy_from_host if config.galaxy_role_file execute_ansible_playbook_from_host end protected + VAGRANT_ARG_SEPARATOR = 'VAGRANT_ARG_SEP' + def warn_for_unsupported_platform if Vagrant::Util::Platform.windows? @machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.windows_not_supported_for_control_machine")) @@ -72,33 +73,56 @@ module VagrantPlugins @environment_variables["ANSIBLE_SSH_ARGS"] = ansible_ssh_args unless ansible_ssh_args.empty? end - def execute_ansible_playbook_from_host - # Assemble the full ansible-playbook command - command = (%w(ansible-playbook) << @command_arguments << config.playbook).flatten - - # TODO: generic HOOK ??? - # Show the ansible command in use - if verbosity_is_enabled? - @machine.env.ui.detail(Helpers::stringify_ansible_playbook_command(@environment_variables, command)) + def execute_command_from_host(command) + begin + result = Vagrant::Util::Subprocess.execute(*command) do |type, data| + if type == :stdout || type == :stderr + @machine.env.ui.detail(data, new_line: false, prefix: false) + end + end + raise Ansible::Errors::AnsibleCommandFailed if result.exit_code != 0 + rescue Vagrant::Errors::CommandUnavailable + raise Ansible::Errors::AnsibleNotFoundOnHost end + end - # Write stdout and stderr data, since it's the regular Ansible output + def execute_ansible_galaxy_from_host + command_values = { + :role_file => get_galaxy_role_file(machine.env.root_path), + :roles_path => get_galaxy_roles_path(machine.env.root_path) + } + command_template = config.galaxy_command.gsub(' ', VAGRANT_ARG_SEPARATOR) + str_command = command_template % command_values + + ui_running_ansible_command "galaxy", str_command.gsub(VAGRANT_ARG_SEPARATOR, ' ') + + 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 } - begin - result = Vagrant::Util::Subprocess.execute(*command) do |type, data| - if type == :stdout || type == :stderr - @machine.env.ui.info(data, new_line: false, prefix: false) - end - end - raise Ansible::Errors::AnsiblePlaybookAppFailed if result.exit_code != 0 - rescue Vagrant::Errors::CommandUnavailable - raise Ansible::Errors::AnsiblePlaybookAppNotFoundOnHost - end + execute_command_from_host command + end + + def execute_ansible_playbook_from_host + prepare_command_arguments + prepare_environment_variables + + # Assemble the full ansible-playbook command + command = (%w(ansible-playbook) << @command_arguments << config.playbook).flatten + + ui_running_ansible_command "playbook", Helpers::stringify_ansible_playbook_command(@environment_variables, command) + + 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 + } + + execute_command_from_host command end def ship_generated_inventory(inventory_content) diff --git a/templates/locales/en.yml b/templates/locales/en.yml index 3367c500a..f4bde55d3 100755 --- a/templates/locales/en.yml +++ b/templates/locales/en.yml @@ -2054,52 +2054,61 @@ en: interactive_not_elevated: "To be interactive, it must also be privileged." ansible: + cannot_detect: |- + Vagrant does not support detecting whether Ansible is installed + for the guest OS running in the machine. Vagrant will assume it is + installed and attempt to continue. + + If you'd like this provisioner to be improved, please + take a look at the Vagrant source code linked below and try + to contribute back support. Thank you! + + https://github.com/mitchellh/vagrant errors: - ansible_playbook_app_failed: |- + ansible_command_failed: |- Ansible failed to complete successfully. Any error output should be visible above. Please fix these errors and try again. - ansible_playbook_app_not_found_on_guest: |- - The "ansible-playbook" program could not be found! Please verify + ansible_not_found_on_guest: |- + The Ansible software could not be found! Please verify that Ansible is correctly installed on your guest system. If you haven't installed Ansible yet, please install Ansible on your Vagrant basebox, or enable the automated setup with the `install` option of this provisioner. Please check - http://docs.vagrantup.com/v2/provisioning/ansible_local.html + https://docs.vagrantup.com/v2/provisioning/ansible_local.html for more information. - ansible_version_not_found_on_guest: |- - The requested Ansible version (%{required_version}) was not found on the guest. - Please check the ansible installation on your guest system, - or adapt the `version` option of this provisioner in your Vagrantfile. - See http://docs.vagrantup.com/v2/provisioning/ansible_local.html - for more information. - ansible_playbook_app_not_found_on_host: |- - The "ansible-playbook" program could not be found! Please verify + ansible_not_found_on_host: |- + The Ansible software could not be found! Please verify that Ansible is correctly installed on your host system. If you haven't installed Ansible yet, please install Ansible on your host system. Vagrant can't do this for you in a safe and automated way. - Please check http://docs.ansible.com for more information. - extra_vars_invalid: |- - `extra_vars` for the Ansible provisioner must be a hash or a path to an existing file. Received: %{value} (as %{type}) - inventory_path_invalid: |- - `inventory_path` for the Ansible provisioner does not exist on the %{system}: %{path} - no_playbook: |- - `playbook` must be set for the Ansible provisioner. - playbook_path_invalid: |- - `playbook` for the Ansible provisioner does not exist on the %{system}: %{path} - vault_password_file_invalid: |- - `vault_password_file` for the Ansible provisioner does not exist on the %{system}: %{path} - cannot_detect: |- - Vagrant does not support detecting whether Ansible is installed - for the guest OS running in the machine. Vagrant will assume it is - installed and attempt to continue. - installing: |- - Installing Ansible... + Please check https://docs.ansible.com for more information. + ansible_version_not_found_on_guest: |- + The requested Ansible version (%{required_version}) was not found on the guest. + Please check the ansible installation on your guest system, + or adapt the `version` option of this provisioner in your Vagrantfile. + See https://docs.vagrantup.com/v2/provisioning/ansible_local.html + for more information. + extra_vars_invalid: |- + `extra_vars` must be a hash or a path to an existing file. Received: %{value} (as %{type}) + galaxy_role_file_invalid: |- + `galaxy_role_file` does not exist on the %{system}: %{path} + inventory_path_invalid: |- + `inventory_path` does not exist on the %{system}: %{path} + no_playbook: |- + `playbook` file path must be set. + playbook_path_invalid: |- + `playbook` does not exist on the %{system}: %{path} + vault_password_file_invalid: |- + `vault_password_file` does not exist on the %{system}: %{path} + installing: "Installing Ansible..." + running_galaxy: "Running ansible-galaxy..." + running_playbook: "Running ansible-playbook..." windows_not_supported_for_control_machine: |- Windows is not officially supported for the Ansible Control Machine. - Please check http://docs.ansible.com/intro_installation.html#control-machine-requirements + Please check https://docs.ansible.com/intro_installation.html#control-machine-requirements docker: not_running: "Docker is not running on the guest VM." diff --git a/test/unit/plugins/provisioners/ansible/config_test.rb b/test/unit/plugins/provisioners/ansible/config_test.rb index 5babba6f5..78e352914 100644 --- a/test/unit/plugins/provisioners/ansible/config_test.rb +++ b/test/unit/plugins/provisioners/ansible/config_test.rb @@ -25,6 +25,9 @@ describe VagrantPlugins::Ansible::Config::Host do ask_vault_pass extra_vars force_remote_user + galaxy_command + galaxy_role_file + galaxy_roles_path groups host_key_checking inventory_path @@ -99,7 +102,7 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to eql([ - I18n.t("vagrant.provisioners.ansible.no_playbook") + I18n.t("vagrant.provisioners.ansible.errors.no_playbook") ]) end @@ -109,7 +112,7 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to eql([ - I18n.t("vagrant.provisioners.ansible.playbook_path_invalid", + I18n.t("vagrant.provisioners.ansible.errors.playbook_path_invalid", path: non_existing_file, system: "host") ]) end @@ -136,7 +139,7 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to eql([ - I18n.t("vagrant.provisioners.ansible.extra_vars_invalid", + I18n.t("vagrant.provisioners.ansible.errors.extra_vars_invalid", type: subject.extra_vars.class.to_s, value: subject.extra_vars.to_s) ]) @@ -148,7 +151,7 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to eql([ - I18n.t("vagrant.provisioners.ansible.extra_vars_invalid", + I18n.t("vagrant.provisioners.ansible.errors.extra_vars_invalid", type: subject.extra_vars.class.to_s, value: subject.extra_vars.to_s) ]) @@ -168,7 +171,7 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to eql([ - I18n.t("vagrant.provisioners.ansible.inventory_path_invalid", + I18n.t("vagrant.provisioners.ansible.errors.inventory_path_invalid", path: non_existing_file, system: "host") ]) end @@ -179,7 +182,18 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to eql([ - I18n.t("vagrant.provisioners.ansible.vault_password_file_invalid", + I18n.t("vagrant.provisioners.ansible.errors.vault_password_file_invalid", + path: non_existing_file, system: "host") + ]) + end + + it "returns an error if galaxy_role_file is specified, but does not exist" do + subject.galaxy_role_file = non_existing_file + subject.finalize! + + result = subject.validate(machine) + expect(result["ansible remote provisioner"]).to eql([ + I18n.t("vagrant.provisioners.ansible.errors.galaxy_role_file_invalid", path: non_existing_file, system: "host") ]) end @@ -192,14 +206,14 @@ describe VagrantPlugins::Ansible::Config::Host do result = subject.validate(machine) expect(result["ansible remote provisioner"]).to include( - I18n.t("vagrant.provisioners.ansible.playbook_path_invalid", + I18n.t("vagrant.provisioners.ansible.errors.playbook_path_invalid", path: non_existing_file, system: "host")) expect(result["ansible remote provisioner"]).to include( - I18n.t("vagrant.provisioners.ansible.extra_vars_invalid", + I18n.t("vagrant.provisioners.ansible.errors.extra_vars_invalid", type: subject.extra_vars.class.to_s, value: subject.extra_vars.to_s)) expect(result["ansible remote provisioner"]).to include( - I18n.t("vagrant.provisioners.ansible.inventory_path_invalid", + I18n.t("vagrant.provisioners.ansible.errors.inventory_path_invalid", path: non_existing_file, system: "host")) end diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index dbcfe7d4f..94626389a 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -208,7 +208,7 @@ VF config.finalize! Vagrant::Util::Subprocess.stub(execute: Vagrant::Util::Subprocess::Result.new(1, "", "")) - expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsiblePlaybookAppFailed) + expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed) end end @@ -583,6 +583,33 @@ VF end end + describe "with galaxy support" do + + before do + config.galaxy_role_file = existing_file + end + + it "raises an error when ansible-galaxy command fails", skip_before: true, skip_after: true do + config.finalize! + Vagrant::Util::Subprocess.stub(execute: Vagrant::Util::Subprocess::Result.new(1, "", "")) + + expect {subject.provision}.to raise_error(VagrantPlugins::Ansible::Errors::AnsibleCommandFailed) + end + + it "execute ansible-galaxy and ansible-playbook" do + # TODO: to be improved, but I'm currenty facing some issues, maybe only present in RSpec 2.14... + expect(Vagrant::Util::Subprocess).to receive(:execute).twice + end + + describe "with verbose option enabled" do + before do + config.verbose = true + end + + xit "shows the ansible-galaxy command in use" + end + end + # The Vagrant Ansible provisioner does not validate the coherency of # argument combinations, and let ansible-playbook complain. describe "with a maximum of options" do @@ -678,7 +705,20 @@ VF # Special cases related to the Vagrant Host operating system in use # - context "with a Solaris-like host" do + context "on a Windows host" do + before do + Vagrant::Util::Platform.stub(windows?: true) + machine.ui.stub(:warn) + end + + it "warns that Windows is not officially supported for the Ansible control machine" do + expect(machine.env.ui).to receive(:warn).with { |warning| + expect(warning).to eq(I18n.t("vagrant.provisioners.ansible.windows_not_supported_for_control_machine")) + } + end + end + + context "on a Solaris-like host" do before do Vagrant::Util::Platform.stub(solaris?: true) end diff --git a/website/docs/source/v2/provisioning/ansible_common.html.md b/website/docs/source/v2/provisioning/ansible_common.html.md index 3b6d7fbc1..cb8daf55e 100644 --- a/website/docs/source/v2/provisioning/ansible_common.html.md +++ b/website/docs/source/v2/provisioning/ansible_common.html.md @@ -51,6 +51,28 @@ Some of these options are for advanced usage only and should not be used unless By default, this option is disabled and Vagrant generates an inventory based on the `Vagrantfile` information. +- `galaxy_command` (template string) - The command pattern used to install Galaxy roles when `galaxy_role_file` is set. + + The following (optional) placeholders can be used in this command pattern: + - `%{role_file}` is replaced by the absolute path to the `galaxy_role_file` option + - `%{roles_path}` is + - replaced by the absolute path to the `galaxy_roles_path` option when such option is defined, or + - replaced by the absolute path to a `roles` subdirectory sitting in the `playbook` parent directory. + + By default, this option is set to + + `ansible-galaxy install --role-file=%{role_file} --roles-path=%{roles_path} --force` + +- `galaxy_role_file` (string) - The path to the Ansible Galaxy role file. + + By default, this option is set to `nil` and Galaxy support is then disabled. + + Note: if an absolute path is given, the `ansible_local` provisioner will assume that it corresponds to the exact location on the guest system. + +- `galaxy_roles_path` (string) - The path to the directory where Ansible Galaxy roles must be installed + + By default, this option is set to `nil`, which means that the Galaxy roles will be installed in a `roles` subdirectory located in the parent directory of the `playbook` file. + - `limit` (string or array of strings) - Set of machines or groups from the inventory file to further control which hosts [are affected](http://docs.ansible.com/glossary.html#limit-groups). The default value is set to the machine name (taken from `Vagrantfile`) to ensure that `vagrant provision` command only affect the expected machine.