Gilles Cornu e5f45e2b79 Ansible: Fix a bug in raw_arguments option
Without this change, it is not possible to pass more than one "raw"
argument, which was not the expected behavior. In addition to Array
format, String (for a single argument) is still accepted (for sake of
"backward compatibility" and ease of use).

Note: Due to low/expert usage of this option, I think that it is not
necessary to add more robust validation on this parameter (e.g. Array
of String type checking or argument syntax pattern matching). Use it at
your own risk ;-)
2013-12-16 21:20:10 +01:00

133 lines
4.8 KiB
Ruby

module VagrantPlugins
module Ansible
class Provisioner < Vagrant.plugin("2", :provisioner)
def provision
ssh = @machine.ssh_info
# Connect with Vagrant user (unless --user or --private-key are
# overidden by 'raw_arguments').
#
# TODO: multiple private key support
options = %W[--private-key=#{ssh[:private_key_path][0]} --user=#{ssh[:username]}]
# Joker! Not (yet) supported arguments can be passed this way.
options.concat(self.as_array(config.raw_arguments)) if config.raw_arguments
# Append Provisioner options (highest precedence):
options << "--inventory-file=#{self.setup_inventory_file}"
options << "--extra-vars=#{self.get_extra_vars_argument}" if config.extra_vars
options << "--sudo" if config.sudo
options << "--sudo-user=#{config.sudo_user}" if config.sudo_user
options << "#{self.get_verbosity_argument}" if config.verbose
options << "--ask-sudo-pass" if config.ask_sudo_pass
options << "--tags=#{as_list_argument(config.tags)}" if config.tags
options << "--skip-tags=#{as_list_argument(config.skip_tags)}" if config.skip_tags
options << "--limit=#{as_list_argument(config.limit)}" if config.limit
options << "--start-at-task=#{config.start_at_task}" if config.start_at_task
# Assemble the full ansible-playbook command
command = (%w(ansible-playbook) << options << config.playbook).flatten
# Write stdout and stderr data, since it's the regular Ansible output
command << {
:env => {
"ANSIBLE_FORCE_COLOR" => "true",
"ANSIBLE_HOST_KEY_CHECKING" => "#{config.host_key_checking}",
# Ensure Ansible output isn't buffered so that we receive ouput
# on a task-by-task basis.
"PYTHONUNBUFFERED" => 1
},
: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 Vagrant::Errors::AnsibleFailed if result.exit_code != 0
rescue Vagrant::Util::Subprocess::LaunchError
raise Vagrant::Errors::AnsiblePlaybookAppNotFound
end
end
protected
# Auto-generate "safe" inventory file based on Vagrantfile,
# unless inventory_path is explicitly provided
def setup_inventory_file
return config.inventory_path if config.inventory_path
ssh = @machine.ssh_info
generated_inventory_file =
@machine.env.root_path.join("vagrant_ansible_inventory_#{machine.name}")
generated_inventory_file.open('w') do |file|
file.write("# Generated by Vagrant\n\n")
file.write("#{machine.name} ansible_ssh_host=#{ssh[:host]} ansible_ssh_port=#{ssh[:port]}\n")
# Write out groups information. Only include current
# machine and its groups to avoid Ansible errors on
# provisioning.
groups_of_groups = {}
included_groups = []
config.groups.each_pair do |gname, gmembers|
if gname.end_with?(":children")
groups_of_groups[gname] = gmembers
elsif gmembers.include?("#{machine.name}")
included_groups << gname
file.write("\n[#{gname}]\n")
file.write("#{machine.name}\n")
end
end
groups_of_groups.each_pair do |gname, gmembers|
unless (included_groups & gmembers).empty?
file.write("\n[#{gname}]\n")
gmembers.each do |gm|
file.write("#{gm}\n") if included_groups.include?(gm)
end
end
end
end
return generated_inventory_file.to_s
end
def get_extra_vars_argument
if config.extra_vars.kind_of?(String) and config.extra_vars =~ /^@.+$/
# A JSON or YAML file is referenced (requires Ansible 1.3+)
return config.extra_vars
else
# Expected to be a Hash after config validation. (extra_vars as
# JSON requires Ansible 1.2+, while YAML requires Ansible 1.3+)
return config.extra_vars.to_json
end
end
def get_verbosity_argument
if config.verbose.to_s =~ /^v+$/
# ansible-playbook accepts "silly" arguments like '-vvvvv' as '-vvvv' for now
return "-#{config.verbose}"
else
# safe default, in case input strays
return '-v'
end
end
def as_list_argument(v)
v.kind_of?(Array) ? v.join(',') : v
end
def as_array(v)
v.kind_of?(Array) ? v : [v]
end
end
end
end