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 ;-)
133 lines
4.8 KiB
Ruby
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
|