provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
require_relative "../constants"
|
2015-02-10 14:28:00 +00:00
|
|
|
require_relative "../errors"
|
|
|
|
require_relative "../helpers"
|
|
|
|
|
|
|
|
module VagrantPlugins
|
|
|
|
module Ansible
|
|
|
|
module Provisioner
|
|
|
|
|
|
|
|
# This class is a base class where the common functionality shared between
|
|
|
|
# both Ansible provisioners are stored.
|
|
|
|
# This is **not an actual provisioner**.
|
|
|
|
# Instead, {Host} (ansible) or {Guest} (ansible_local) should be used.
|
|
|
|
|
|
|
|
class Base < Vagrant.plugin("2", :provisioner)
|
|
|
|
|
2015-12-04 09:05:07 +00:00
|
|
|
RANGE_PATTERN = %r{(?:\[[a-z]:[a-z]\]|\[[0-9]+?:[0-9]+?\])}.freeze
|
|
|
|
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
ANSIBLE_PARAMETER_NAMES = {
|
|
|
|
Ansible::COMPATIBILITY_MODE_V1_8 => {
|
|
|
|
ansible_host: "ansible_ssh_host",
|
|
|
|
ansible_password: "ansible_ssh_pass",
|
|
|
|
ansible_port: "ansible_ssh_port",
|
|
|
|
ansible_user: "ansible_ssh_user",
|
|
|
|
ask_become_pass: "ask-sudo-pass",
|
|
|
|
become: "sudo",
|
|
|
|
become_user: "sudo-user",
|
|
|
|
},
|
|
|
|
Ansible::COMPATIBILITY_MODE_V2_0 => {
|
|
|
|
ansible_host: "ansible_host",
|
|
|
|
ansible_password: "ansible_password",
|
|
|
|
ansible_port: "ansible_port",
|
|
|
|
ansible_user: "ansible_user",
|
|
|
|
ask_become_pass: "ask-become-pass",
|
|
|
|
become: "become",
|
|
|
|
become_user: "become-user",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
protected
|
|
|
|
|
|
|
|
def initialize(machine, config)
|
|
|
|
super
|
2017-08-30 09:51:55 +00:00
|
|
|
@control_machine = nil
|
2015-02-10 14:28:00 +00:00
|
|
|
|
|
|
|
@command_arguments = []
|
|
|
|
@environment_variables = {}
|
|
|
|
@inventory_machines = {}
|
|
|
|
@inventory_path = nil
|
|
|
|
end
|
|
|
|
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
def set_compatibility_mode
|
2017-08-26 06:47:35 +00:00
|
|
|
if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
detect_compatibility_mode(gather_ansible_version)
|
|
|
|
end
|
|
|
|
|
2017-08-26 06:47:35 +00:00
|
|
|
unless Ansible::COMPATIBILITY_MODES.slice(1..-1).include?(config.compatibility_mode)
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
raise "Programming Error: compatibility_mode must correctly set at this stage!"
|
|
|
|
end
|
|
|
|
|
|
|
|
@lexicon = ANSIBLE_PARAMETER_NAMES[config.compatibility_mode]
|
|
|
|
end
|
|
|
|
|
|
|
|
def detect_compatibility_mode(ansible_version_stdoutput)
|
2017-08-26 06:47:35 +00:00
|
|
|
if config.compatibility_mode != Ansible::COMPATIBILITY_MODE_AUTO
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
raise "Programming Error: detect_compatibility_mode() shouldn't have been called."
|
|
|
|
end
|
|
|
|
|
|
|
|
begin
|
|
|
|
first_line = ansible_version_stdoutput.lines[0]
|
|
|
|
full_version = first_line.match(/ansible (\d)(\.\d+){1,}/)
|
|
|
|
|
|
|
|
if full_version
|
|
|
|
major_version, _ = full_version.captures
|
|
|
|
|
|
|
|
if major_version.to_i <= 1
|
|
|
|
config.compatibility_mode = Ansible::COMPATIBILITY_MODE_V1_8
|
|
|
|
else
|
|
|
|
config.compatibility_mode = Ansible::COMPATIBILITY_MODE_V2_0
|
|
|
|
end
|
|
|
|
|
|
|
|
@machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.compatibility_mode_warning",
|
|
|
|
compatibility_mode: config.compatibility_mode,
|
|
|
|
ansible_version: full_version) +
|
|
|
|
"\n")
|
|
|
|
end
|
|
|
|
rescue
|
|
|
|
# Nothing to do here, the fallback to default compatibility_mode is done below
|
|
|
|
end
|
|
|
|
|
2017-08-26 06:47:35 +00:00
|
|
|
if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
|
|
|
|
config.compatibility_mode = Ansible::SAFE_COMPATIBILITY_MODE
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
|
|
|
|
@machine.env.ui.warn(I18n.t("vagrant.provisioners.ansible.compatibility_mode_not_detected",
|
|
|
|
compatibility_mode: config.compatibility_mode,
|
|
|
|
gathered_version: ansible_version_stdoutput) +
|
|
|
|
"\n")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
provisioners/ansible(both): fix ansible config files presence checks
With this change, the presence of Ansible configuration files (like
playbook file, inventory path, galaxy role file, etc.) is no longer
performed by the `config` classes, but by the `provisioner` classes
(at the beginning of the provision command).
This change fixes several issues:
- Resolve #6984 as `provision` method are only executed when remote
(ssh) communication with the guest machine is possible.
- Resolve #6763 in a better way than 4e451c6 initially did.
- Improve the general provisioner speed since the `config` checks are
actually triggered by many vagrant actions (e.g. `destroy`,...), and
can also be triggered multiple times during a vagrant run (e.g. on
callback request made by the machine provider).
Unlike the former `config`-based checks, the provision action won't
collect all the invalid options, but only report the first invalid
option found and abort the execution.
Some unit tests were not implemented yet to save my scarce "open source
contribution time" for other important issues, but they should be done
at last via GH-6633.
2016-05-31 22:30:07 +00:00
|
|
|
def check_files_existence
|
2016-06-17 16:14:29 +00:00
|
|
|
check_path_is_a_file(config.playbook, :playbook)
|
provisioners/ansible(both): fix ansible config files presence checks
With this change, the presence of Ansible configuration files (like
playbook file, inventory path, galaxy role file, etc.) is no longer
performed by the `config` classes, but by the `provisioner` classes
(at the beginning of the provision command).
This change fixes several issues:
- Resolve #6984 as `provision` method are only executed when remote
(ssh) communication with the guest machine is possible.
- Resolve #6763 in a better way than 4e451c6 initially did.
- Improve the general provisioner speed since the `config` checks are
actually triggered by many vagrant actions (e.g. `destroy`,...), and
can also be triggered multiple times during a vagrant run (e.g. on
callback request made by the machine provider).
Unlike the former `config`-based checks, the provision action won't
collect all the invalid options, but only report the first invalid
option found and abort the execution.
Some unit tests were not implemented yet to save my scarce "open source
contribution time" for other important issues, but they should be done
at last via GH-6633.
2016-05-31 22:30:07 +00:00
|
|
|
|
2016-06-17 16:14:29 +00:00
|
|
|
check_path_exists(config.inventory_path, :inventory_path) if config.inventory_path
|
2016-09-20 20:58:41 +00:00
|
|
|
check_path_is_a_file(config.config_file, :config_file) if config.config_file
|
2016-06-17 16:14:29 +00:00
|
|
|
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
|
provisioners/ansible(both): fix ansible config files presence checks
With this change, the presence of Ansible configuration files (like
playbook file, inventory path, galaxy role file, etc.) is no longer
performed by the `config` classes, but by the `provisioner` classes
(at the beginning of the provision command).
This change fixes several issues:
- Resolve #6984 as `provision` method are only executed when remote
(ssh) communication with the guest machine is possible.
- Resolve #6763 in a better way than 4e451c6 initially did.
- Improve the general provisioner speed since the `config` checks are
actually triggered by many vagrant actions (e.g. `destroy`,...), and
can also be triggered multiple times during a vagrant run (e.g. on
callback request made by the machine provider).
Unlike the former `config`-based checks, the provision action won't
collect all the invalid options, but only report the first invalid
option found and abort the execution.
Some unit tests were not implemented yet to save my scarce "open source
contribution time" for other important issues, but they should be done
at last via GH-6633.
2016-05-31 22:30:07 +00:00
|
|
|
end
|
|
|
|
|
2016-09-20 20:58:41 +00:00
|
|
|
def get_environment_variables_for_shell_execution
|
|
|
|
shell_env_vars = []
|
2016-04-20 16:05:28 +00:00
|
|
|
@environment_variables.each_pair do |k, v|
|
2016-09-20 20:58:41 +00:00
|
|
|
if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH|ANSIBLE_CONFIG/
|
|
|
|
shell_env_vars << "#{k}='#{v}'"
|
2016-04-20 16:05:28 +00:00
|
|
|
else
|
2016-09-20 20:58:41 +00:00
|
|
|
shell_env_vars << "#{k}=#{v}"
|
2016-04-20 16:05:28 +00:00
|
|
|
end
|
|
|
|
end
|
2016-09-20 20:58:41 +00:00
|
|
|
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
|
2016-04-20 16:05:28 +00:00
|
|
|
|
2016-10-09 18:48:50 +00:00
|
|
|
shell_command << config.playbook_command
|
2016-04-20 16:05:28 +00:00
|
|
|
|
|
|
|
shell_args = []
|
|
|
|
@command_arguments.each do |arg|
|
|
|
|
if arg =~ /(--start-at-task|--limit)=(.+)/
|
|
|
|
shell_args << %Q(#{$1}="#{$2}")
|
|
|
|
elsif arg =~ /(--extra-vars)=(.+)/
|
2017-09-06 14:25:05 +00:00
|
|
|
shell_args << %Q(%s=%s) % [$1, $2.shellescape]
|
2016-04-20 16:05:28 +00:00
|
|
|
else
|
|
|
|
shell_args << arg
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
shell_command << shell_args
|
|
|
|
|
|
|
|
# Add the raw arguments at the end, to give them the highest precedence
|
|
|
|
shell_command << config.raw_arguments if config.raw_arguments
|
|
|
|
|
|
|
|
shell_command << config.playbook
|
|
|
|
|
|
|
|
shell_command.flatten.join(' ')
|
|
|
|
end
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
def prepare_common_command_arguments
|
|
|
|
# By default we limit by the current machine,
|
|
|
|
# but this can be overridden by the `limit` option.
|
|
|
|
if config.limit
|
|
|
|
@command_arguments << "--limit=#{Helpers::as_list_argument(config.limit)}"
|
|
|
|
else
|
|
|
|
@command_arguments << "--limit=#{@machine.name}"
|
|
|
|
end
|
|
|
|
|
|
|
|
@command_arguments << "--inventory-file=#{inventory_path}"
|
|
|
|
@command_arguments << "--extra-vars=#{extra_vars_argument}" if config.extra_vars
|
provisioners/ansible(both): Add compatibility mode
With this change, it is now possible to get rid of many deprecation
messages successively introduced in Ansible 1.9, and 2.0. More
interesting, the generated inventory will contain the recommended
variable names (e.g. `ansible_host` instead of `ansible_ssh_host`)
when the compatibility mode is set to '2.0'.
Details:
- Add `compatibility_mode` option to control the Ansible parameters
format to be used. The value corresponds to the minimal version
supported. For the moment, possible values are '1.8' (corresponding to
Vagrant's former behaviour) or '2.0'.
Note that a dynamic inventory generated in compatibility mode '2.0'
is not supported by Ansible 1.x. On the other hand, Ansible 2.x so far
supports inventory format generated by the compatibility mode '1.8'.
- Add compatibility mode auto-detection, based on the available Ansible
version. This is the default behaviour in order to bring a maximum of
user friendliness. The drawback of this approach is to let potential
compatibility breaking risks, for `ansible` provisioner setups that
already integrate Ansible 2.x **AND** rely on the existence of
the generated `_ssh` variable names. Thanks to the vagrant warnings
(and its release notes), I argue that it is worth to offer
auto-detection by default, which offers a sweet transition to most
users.
- Add `become`, `become_user` and `ask_become_pass` options and their
backwards compatible aliases. The legacy options are now deprecated.
Note that we intentionally didn't provide a '1.9' compatibility mode,
as it would add extra-complexity for practically no added-value.
To my knowledge, the Ansible 2.x series haven't introduced yet any major
changes or deprecations that would motivate to introduce a higher
version compatibility mode (to be confirmed/verified).
Resolve GH-6570
Still Pending:
- Optimization: Reduce the number of `ansible` command executions.
Currently two exec calls will be performed when the compatibility
mode auto-detection is enabled (i.e. by default). We could make the
provisioner a little bit smarter to only execute `ansible` only once
in any situation (by combining "presence" and "version" checks).
- User-friendliness: Add better validator on `compatibility_mode`
option, and shows a warning or an error instead of the silent
fallback on the auto-detection modus.
- Test coverage: All the added behaviours are not fully covered yet.
2016-11-13 19:58:26 +00:00
|
|
|
@command_arguments << "--#{@lexicon[:become]}" if config.become
|
|
|
|
@command_arguments << "--#{@lexicon[:become_user]}=#{config.become_user}" if config.become_user
|
2015-02-10 14:28:00 +00:00
|
|
|
@command_arguments << "#{verbosity_argument}" if verbosity_is_enabled?
|
|
|
|
@command_arguments << "--vault-password-file=#{config.vault_password_file}" if config.vault_password_file
|
|
|
|
@command_arguments << "--tags=#{Helpers::as_list_argument(config.tags)}" if config.tags
|
|
|
|
@command_arguments << "--skip-tags=#{Helpers::as_list_argument(config.skip_tags)}" if config.skip_tags
|
|
|
|
@command_arguments << "--start-at-task=#{config.start_at_task}" if config.start_at_task
|
|
|
|
end
|
|
|
|
|
|
|
|
def prepare_common_environment_variables
|
|
|
|
# Ensure Ansible output isn't buffered so that we receive output
|
|
|
|
# on a task-by-task basis.
|
|
|
|
@environment_variables["PYTHONUNBUFFERED"] = 1
|
|
|
|
|
|
|
|
# When Ansible output is piped in Vagrant integration, its default colorization is
|
|
|
|
# automatically disabled and the only way to re-enable colors is to use ANSIBLE_FORCE_COLOR.
|
|
|
|
@environment_variables["ANSIBLE_FORCE_COLOR"] = "true" if @machine.env.ui.color?
|
|
|
|
# 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.)
|
|
|
|
@environment_variables["ANSIBLE_NOCOLOR"] = "true" if !@machine.env.ui.color?
|
2016-06-11 05:28:05 +00:00
|
|
|
|
|
|
|
# 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
|
2016-09-20 20:58:41 +00:00
|
|
|
|
|
|
|
prepare_ansible_config_environment_variable
|
|
|
|
end
|
|
|
|
|
|
|
|
def prepare_ansible_config_environment_variable
|
|
|
|
@environment_variables["ANSIBLE_CONFIG"] = config.config_file if config.config_file
|
2015-02-10 14:28:00 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Auto-generate "safe" inventory file based on Vagrantfile,
|
|
|
|
# unless inventory_path is explicitly provided
|
|
|
|
def inventory_path
|
|
|
|
if config.inventory_path
|
|
|
|
config.inventory_path
|
|
|
|
else
|
|
|
|
@inventory_path ||= generate_inventory
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-12-01 17:15:40 +00:00
|
|
|
def get_inventory_host_vars_string(machine_name)
|
2015-12-02 07:37:41 +00:00
|
|
|
# In Ruby, Symbol and String values are different, but
|
|
|
|
# Vagrant has to unify them for better user experience.
|
|
|
|
vars = config.host_vars[machine_name.to_sym]
|
|
|
|
if !vars
|
|
|
|
vars = config.host_vars[machine_name.to_s]
|
|
|
|
end
|
2015-12-01 17:15:40 +00:00
|
|
|
s = nil
|
|
|
|
if vars.is_a?(Hash)
|
|
|
|
s = vars.each.collect{ |k, v| "#{k}=#{v}" }.join(" ")
|
|
|
|
elsif vars.is_a?(Array)
|
|
|
|
s = vars.join(" ")
|
|
|
|
elsif vars.is_a?(String)
|
|
|
|
s = vars
|
|
|
|
end
|
|
|
|
if s and !s.empty? then s else nil end
|
|
|
|
end
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
def generate_inventory
|
|
|
|
inventory = "# Generated by Vagrant\n\n"
|
|
|
|
|
2015-12-03 08:36:57 +00:00
|
|
|
# This "abstract" step must fill the @inventory_machines list
|
|
|
|
# and return the list of supported host(s)
|
2015-02-10 14:28:00 +00:00
|
|
|
inventory += generate_inventory_machines
|
|
|
|
|
|
|
|
inventory += generate_inventory_groups
|
|
|
|
|
|
|
|
# This "abstract" step must create the inventory file and
|
|
|
|
# return its location path
|
|
|
|
# TODO: explain possible race conditions, etc.
|
|
|
|
@inventory_path = ship_generated_inventory(inventory)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Write out groups information.
|
|
|
|
# All defined groups will be included, but only supported
|
|
|
|
# machines and defined child groups will be included.
|
|
|
|
def generate_inventory_groups
|
|
|
|
groups_of_groups = {}
|
|
|
|
defined_groups = []
|
2015-12-01 13:28:24 +00:00
|
|
|
group_vars = {}
|
2015-02-10 14:28:00 +00:00
|
|
|
inventory_groups = ""
|
|
|
|
|
2015-12-03 19:22:05 +00:00
|
|
|
# Verify if host range patterns exist and warn
|
2015-12-04 09:05:07 +00:00
|
|
|
if config.groups.any? { |gm| gm.to_s[RANGE_PATTERN] }
|
2015-12-03 19:22:05 +00:00
|
|
|
@machine.ui.warn(I18n.t("vagrant.provisioners.ansible.ansible_host_pattern_detected"))
|
|
|
|
end
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
config.groups.each_pair do |gname, gmembers|
|
2015-12-03 08:34:53 +00:00
|
|
|
if gname.is_a?(Symbol)
|
|
|
|
gname = gname.to_s
|
|
|
|
end
|
|
|
|
|
2015-12-01 13:28:24 +00:00
|
|
|
if gmembers.is_a?(String)
|
|
|
|
gmembers = gmembers.split(/\s+/)
|
|
|
|
elsif gmembers.is_a?(Hash)
|
|
|
|
gmembers = gmembers.each.collect{ |k, v| "#{k}=#{v}" }
|
|
|
|
elsif !gmembers.is_a?(Array)
|
|
|
|
gmembers = []
|
|
|
|
end
|
2015-02-10 14:28:00 +00:00
|
|
|
|
|
|
|
if gname.end_with?(":children")
|
|
|
|
groups_of_groups[gname] = gmembers
|
|
|
|
defined_groups << gname.sub(/:children$/, '')
|
2015-12-01 13:28:24 +00:00
|
|
|
elsif gname.end_with?(":vars")
|
|
|
|
group_vars[gname] = gmembers
|
|
|
|
else
|
2015-02-10 14:28:00 +00:00
|
|
|
defined_groups << gname
|
|
|
|
inventory_groups += "\n[#{gname}]\n"
|
|
|
|
gmembers.each do |gm|
|
2015-12-04 09:05:07 +00:00
|
|
|
# TODO : Expand and validate host range patterns
|
|
|
|
# against @inventory_machines list before adding them
|
|
|
|
# otherwise abort with an error message
|
|
|
|
if gm[RANGE_PATTERN]
|
2015-12-03 19:22:05 +00:00
|
|
|
inventory_groups += "#{gm}\n"
|
|
|
|
end
|
2015-02-10 14:28:00 +00:00
|
|
|
inventory_groups += "#{gm}\n" if @inventory_machines.include?(gm.to_sym)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
defined_groups.uniq!
|
|
|
|
groups_of_groups.each_pair do |gname, gmembers|
|
|
|
|
inventory_groups += "\n[#{gname}]\n"
|
|
|
|
gmembers.each do |gm|
|
|
|
|
inventory_groups += "#{gm}\n" if defined_groups.include?(gm)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-12-01 13:28:24 +00:00
|
|
|
group_vars.each_pair do |gname, gmembers|
|
2017-09-03 15:09:16 +00:00
|
|
|
if defined_groups.include?(gname.sub(/:vars$/, "")) || gname == "all:vars"
|
2015-12-01 13:28:24 +00:00
|
|
|
inventory_groups += "\n[#{gname}]\n" + gmembers.join("\n") + "\n"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
return inventory_groups
|
|
|
|
end
|
|
|
|
|
provisioners/ansible(both): fix ansible config files presence checks
With this change, the presence of Ansible configuration files (like
playbook file, inventory path, galaxy role file, etc.) is no longer
performed by the `config` classes, but by the `provisioner` classes
(at the beginning of the provision command).
This change fixes several issues:
- Resolve #6984 as `provision` method are only executed when remote
(ssh) communication with the guest machine is possible.
- Resolve #6763 in a better way than 4e451c6 initially did.
- Improve the general provisioner speed since the `config` checks are
actually triggered by many vagrant actions (e.g. `destroy`,...), and
can also be triggered multiple times during a vagrant run (e.g. on
callback request made by the machine provider).
Unlike the former `config`-based checks, the provision action won't
collect all the invalid options, but only report the first invalid
option found and abort the execution.
Some unit tests were not implemented yet to save my scarce "open source
contribution time" for other important issues, but they should be done
at last via GH-6633.
2016-05-31 22:30:07 +00:00
|
|
|
def has_an_extra_vars_file_argument
|
|
|
|
config.extra_vars && config.extra_vars.kind_of?(String) && config.extra_vars =~ /^@.+$/
|
|
|
|
end
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
def extra_vars_argument
|
provisioners/ansible(both): fix ansible config files presence checks
With this change, the presence of Ansible configuration files (like
playbook file, inventory path, galaxy role file, etc.) is no longer
performed by the `config` classes, but by the `provisioner` classes
(at the beginning of the provision command).
This change fixes several issues:
- Resolve #6984 as `provision` method are only executed when remote
(ssh) communication with the guest machine is possible.
- Resolve #6763 in a better way than 4e451c6 initially did.
- Improve the general provisioner speed since the `config` checks are
actually triggered by many vagrant actions (e.g. `destroy`,...), and
can also be triggered multiple times during a vagrant run (e.g. on
callback request made by the machine provider).
Unlike the former `config`-based checks, the provision action won't
collect all the invalid options, but only report the first invalid
option found and abort the execution.
Some unit tests were not implemented yet to save my scarce "open source
contribution time" for other important issues, but they should be done
at last via GH-6633.
2016-05-31 22:30:07 +00:00
|
|
|
if has_an_extra_vars_file_argument
|
2015-02-10 14:28:00 +00:00
|
|
|
# A JSON or YAML file is referenced.
|
|
|
|
config.extra_vars
|
|
|
|
else
|
|
|
|
# Expected to be a Hash after config validation.
|
|
|
|
config.extra_vars.to_json
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2016-06-11 05:28:05 +00:00
|
|
|
def get_galaxy_role_file
|
|
|
|
Helpers::expand_path_in_unix_style(config.galaxy_role_file, get_provisioning_working_directory)
|
2015-11-17 21:06:06 +00:00
|
|
|
end
|
|
|
|
|
2016-06-11 05:28:05 +00:00
|
|
|
def get_galaxy_roles_path
|
|
|
|
base_dir = get_provisioning_working_directory
|
2015-11-17 21:06:06 +00:00
|
|
|
if config.galaxy_roles_path
|
2016-01-05 07:22:10 +00:00
|
|
|
Helpers::expand_path_in_unix_style(config.galaxy_roles_path, base_dir)
|
2015-11-17 21:06:06 +00:00
|
|
|
else
|
2016-01-05 07:22:10 +00:00
|
|
|
playbook_path = Helpers::expand_path_in_unix_style(config.playbook, base_dir)
|
|
|
|
File.join(Pathname.new(playbook_path).parent, 'roles')
|
2015-11-17 21:06:06 +00:00
|
|
|
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
|
2015-11-18 08:37:27 +00:00
|
|
|
@machine.env.ui.detail command
|
2015-11-17 21:06:06 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-02-10 14:28:00 +00:00
|
|
|
def verbosity_is_enabled?
|
|
|
|
config.verbose && !config.verbose.to_s.empty?
|
|
|
|
end
|
|
|
|
|
|
|
|
def verbosity_argument
|
|
|
|
if config.verbose.to_s =~ /^-?(v+)$/
|
|
|
|
"-#{$+}"
|
|
|
|
else
|
|
|
|
# safe default, in case input strays
|
|
|
|
'-v'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|