vagrant/plugins/provisioners/ansible/provisioner/base.rb

389 lines
15 KiB
Ruby
Raw Normal View History

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"
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)
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",
}
}
protected
def initialize(machine, config)
super
@control_machine = nil
@command_arguments = []
@environment_variables = {}
@inventory_machines = {}
@inventory_path = nil
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
@gathered_version_stdout = nil
@gathered_version_major = nil
@gathered_version = nil
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
end
def set_and_check_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
begin
set_gathered_ansible_version(gather_ansible_version)
rescue Exception => e
# Nothing to do here, as the fallback on safe compatibility_mode is done below
@logger.error("Error while gathering the ansible version: #{e.to_s}")
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
if @gathered_version_major
if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
detect_compatibility_mode
elsif @gathered_version_major.to_i < 2 && config.compatibility_mode == Ansible::COMPATIBILITY_MODE_V2_0
# A better version comparator will be needed
# when more compatibility modes come... but so far let's keep it simple!
raise Ansible::Errors::AnsibleCompatibilityModeConflict,
ansible_version: @gathered_version,
system: @control_machine,
compatibility_mode: 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
end
end
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: @gathered_version_stdout) +
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
"\n")
end
unless Ansible::COMPATIBILITY_MODES.slice(1..-1).include?(config.compatibility_mode)
raise "Programming Error: compatibility_mode must correctly set at this stage!"
end
@lexicon = ANSIBLE_PARAMETER_NAMES[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
end
def check_files_existence
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 get_environment_variables_for_shell_execution
shell_env_vars = []
@environment_variables.each_pair do |k, v|
if k =~ /ANSIBLE_SSH_ARGS|ANSIBLE_ROLES_PATH|ANSIBLE_CONFIG/
shell_env_vars << "#{k}='#{v}'"
else
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
shell_args = []
@command_arguments.each do |arg|
if arg =~ /(--start-at-task|--limit)=(.+)/
shell_args << %Q(#{$1}="#{$2}")
elsif arg =~ /(--extra-vars)=(.+)/
shell_args << %Q(%s=%s) % [$1, $2.shellescape]
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
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
@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?
# 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,
# 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)
# 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
def generate_inventory
inventory = "# Generated by Vagrant\n\n"
# This "abstract" step must fill the @inventory_machines list
# and return the list of supported host(s)
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 = []
group_vars = {}
inventory_groups = ""
# Verify if host range patterns exist and warn
if config.groups.any? { |gm| gm.to_s[RANGE_PATTERN] }
@machine.ui.warn(I18n.t("vagrant.provisioners.ansible.ansible_host_pattern_detected"))
end
config.groups.each_pair do |gname, gmembers|
if gname.is_a?(Symbol)
gname = gname.to_s
end
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
if gname.end_with?(":children")
groups_of_groups[gname] = gmembers
defined_groups << gname.sub(/:children$/, '')
elsif gname.end_with?(":vars")
group_vars[gname] = gmembers
else
defined_groups << gname
inventory_groups += "\n[#{gname}]\n"
gmembers.each do |gm|
# TODO : Expand and validate host range patterns
# against @inventory_machines list before adding them
# otherwise abort with an error message
if gm[RANGE_PATTERN]
inventory_groups += "#{gm}\n"
end
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
group_vars.each_pair do |gname, gmembers|
if defined_groups.include?(gname.sub(/:vars$/, "")) || gname == "all:vars"
inventory_groups += "\n[#{gname}]\n" + gmembers.join("\n") + "\n"
end
end
return inventory_groups
end
def has_an_extra_vars_file_argument
config.extra_vars && config.extra_vars.kind_of?(String) && config.extra_vars =~ /^@.+$/
end
def extra_vars_argument
if has_an_extra_vars_file_argument
# 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
def get_galaxy_role_file
Helpers::expand_path_in_unix_style(config.galaxy_role_file, get_provisioning_working_directory)
end
def get_galaxy_roles_path
base_dir = get_provisioning_working_directory
if config.galaxy_roles_path
Helpers::expand_path_in_unix_style(config.galaxy_roles_path, base_dir)
else
playbook_path = Helpers::expand_path_in_unix_style(config.playbook, base_dir)
File.join(Pathname.new(playbook_path).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
def verbosity_argument
if config.verbose.to_s =~ /^-?(v+)$/
"-#{$+}"
else
# safe default, in case input strays
'-v'
end
end
private
def detect_compatibility_mode
if !@gathered_version_major || config.compatibility_mode != Ansible::COMPATIBILITY_MODE_AUTO
raise "Programming Error: detect_compatibility_mode() shouldn't have been called."
end
if @gathered_version_major.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: @gathered_version) +
"\n")
end
def set_gathered_ansible_version(stdout_output)
@gathered_version_stdout = stdout_output
if !@gathered_version_stdout.empty?
first_line = @gathered_version_stdout.lines[0]
ansible_version_pattern = first_line.match(/(^ansible\s+)(.+)$/)
if ansible_version_pattern
_, @gathered_version, _ = ansible_version_pattern.captures
if @gathered_version
@gathered_version_major = @gathered_version.match(/^(\d)\..+$/).captures[0].to_i
end
end
end
end
end
end
end
end