2013-03-20 14:41:21 +00:00
module VagrantPlugins
module Ansible
class Provisioner < Vagrant . plugin ( " 2 " , :provisioner )
def provision
2014-02-02 21:32:22 +00:00
@logger = Log4r :: Logger . new ( " vagrant::provisioners::ansible " )
2013-03-20 14:41:21 +00:00
ssh = @machine . ssh_info
2013-04-04 20:48:58 +00:00
2013-11-26 18:07:45 +00:00
# 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 ] } ]
2013-05-06 20:28:20 +00:00
# Joker! Not (yet) supported arguments can be passed this way.
2013-12-16 20:20:10 +00:00
options . concat ( self . as_array ( config . raw_arguments ) ) if config . raw_arguments
2013-05-06 20:28:20 +00:00
2014-02-01 21:04:20 +00:00
# By default we limit by the current machine. This can be
# overriden by the limit config option.
limit_option = if config . limit == nil
" --limit= #{ @machine . name } "
elsif not config . limit . empty?
" --limit= #{ as_list_argument ( config . limit ) } "
end
2013-10-02 02:28:55 +00:00
# Append Provisioner options (highest precedence):
2013-09-07 12:32:36 +00:00
options << " --inventory-file= #{ self . setup_inventory_file } "
2013-10-11 22:29:39 +00:00
options << " --extra-vars= #{ self . get_extra_vars_argument } " if config . extra_vars
2013-03-20 14:41:21 +00:00
options << " --sudo " if config . sudo
options << " --sudo-user= #{ config . sudo_user } " if config . sudo_user
2013-10-04 06:58:49 +00:00
options << " #{ self . get_verbosity_argument } " if config . verbose
2013-09-07 12:32:36 +00:00
options << " --ask-sudo-pass " if config . ask_sudo_pass
2013-09-02 22:30:49 +00:00
options << " --tags= #{ as_list_argument ( config . tags ) } " if config . tags
options << " --skip-tags= #{ as_list_argument ( config . skip_tags ) } " if config . skip_tags
2014-02-01 21:04:20 +00:00
options << limit_option if limit_option
2013-09-02 22:30:49 +00:00
options << " --start-at-task= #{ config . start_at_task } " if config . start_at_task
2013-04-04 07:07:59 +00:00
# Assemble the full ansible-playbook command
2013-03-20 14:41:21 +00:00
command = ( %w( ansible-playbook ) << options << config . playbook ) . flatten
2013-04-04 20:48:58 +00:00
2013-04-04 07:07:59 +00:00
# Write stdout and stderr data, since it's the regular Ansible output
2013-04-04 18:31:27 +00:00
command << {
2013-09-17 04:02:22 +00:00
:env = > {
" ANSIBLE_FORCE_COLOR " = > " true " ,
2013-09-26 09:13:44 +00:00
" 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
2013-09-17 04:02:22 +00:00
} ,
2013-08-29 18:55:58 +00:00
:notify = > [ :stdout , :stderr ] ,
:workdir = > @machine . env . root_path . to_s
2013-04-04 18:31:27 +00:00
}
2013-04-04 20:48:58 +00:00
2013-04-04 20:58:33 +00:00
begin
2013-07-30 12:25:15 +00:00
result = Vagrant :: Util :: Subprocess . execute ( * command ) do | type , data |
2013-04-04 20:58:33 +00:00
if type == :stdout || type == :stderr
2013-07-20 03:38:25 +00:00
@machine . env . ui . info ( data , :new_line = > false , :prefix = > false )
2013-04-04 20:58:33 +00:00
end
2013-04-04 20:48:58 +00:00
end
2013-07-20 04:07:09 +00:00
2013-07-30 12:25:15 +00:00
raise Vagrant :: Errors :: AnsibleFailed if result . exit_code != 0
2013-04-04 20:58:33 +00:00
rescue Vagrant :: Util :: Subprocess :: LaunchError
raise Vagrant :: Errors :: AnsiblePlaybookAppNotFound
2013-04-04 07:07:59 +00:00
end
2013-03-20 14:41:21 +00:00
end
2013-08-28 23:52:13 +00:00
2013-09-07 12:32:36 +00:00
protected
# Auto-generate "safe" inventory file based on Vagrantfile,
# unless inventory_path is explicitly provided
2013-08-28 23:52:13 +00:00
def setup_inventory_file
2013-09-01 04:48:41 +00:00
return config . inventory_path if config . inventory_path
2013-08-28 23:52:13 +00:00
2013-07-07 06:47:37 +00:00
ssh = @machine . ssh_info
2013-08-28 23:54:44 +00:00
2014-02-02 21:32:22 +00:00
# Managed machines
inventory_machines = [ ]
2013-08-28 23:54:44 +00:00
generated_inventory_file =
2014-02-01 21:04:20 +00:00
@machine . env . root_path . join ( " vagrant_ansible_inventory " )
2013-08-28 23:54:44 +00:00
generated_inventory_file . open ( 'w' ) do | file |
2013-07-07 06:47:37 +00:00
file . write ( " # Generated by Vagrant \n \n " )
2013-12-09 07:01:01 +00:00
2014-02-01 21:04:20 +00:00
@machine . env . active_machines . each do | am |
2014-02-02 21:32:22 +00:00
begin
m = @machine . env . machine ( * am )
if ! m . ssh_info . nil?
file . write ( " #{ m . name } ansible_ssh_host= #{ m . ssh_info [ :host ] } ansible_ssh_port= #{ m . ssh_info [ :port ] } \n " )
inventory_machines << m
else
@logger . error ( " Auto-generated inventory: Impossible to get SSH information for machine ' #{ m . name } ( #{ m . provider_name } )'. This machine should be recreated. " )
# Let a note about this missing machine
file . write ( " # MISSING: ' #{ m . name } ' machine was probably removed without using Vagrant. This machine should be recreated. \n " )
end
rescue Vagrant :: Errors :: MachineNotFound = > e
@logger . info ( " Auto-generated inventory: Skip machine ' #{ am [ 0 ] } ( #{ am [ 1 ] } )', which is not configured for this Vagrant environment. " )
end
2014-02-01 21:04:20 +00:00
end
# Write out groups information. Only includes groups and
# machines which have been defined, otherwise Ansible will
# complain.
2013-12-09 07:01:01 +00:00
groups_of_groups = { }
included_groups = [ ]
config . groups . each_pair do | gname , gmembers |
2014-02-02 22:14:07 +00:00
# Require that gmembers be an array
# (easier to be tolerant and avoid error management of few value)
gmembers = [ gmembers ] if ! gmembers . is_a? ( Array )
2013-12-09 07:01:01 +00:00
if gname . end_with? ( " :children " )
groups_of_groups [ gname ] = gmembers
2014-02-02 22:28:04 +00:00
elsif ! gname . include? ( ':' )
# skip group variables [:vars] and any other ":" suffixes
2013-12-09 07:01:01 +00:00
included_groups << gname
file . write ( " \n [ #{ gname } ] \n " )
2014-02-01 21:04:20 +00:00
gmembers . each do | gm |
2014-02-02 21:32:22 +00:00
file . write ( " #{ gm } \n " ) if inventory_machines . map { | m | m . name } . include? ( gm . to_sym )
2014-02-01 21:04:20 +00:00
end
2013-12-09 07:01:01 +00:00
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
2013-07-07 06:47:37 +00:00
end
2013-08-28 23:52:13 +00:00
2013-08-28 23:54:44 +00:00
return generated_inventory_file . to_s
2013-07-07 06:47:37 +00:00
end
2013-09-02 22:30:49 +00:00
2013-10-11 22:29:39 +00:00
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
2013-11-25 05:29:04 +00:00
# Expected to be a Hash after config validation. (extra_vars as
# JSON requires Ansible 1.2+, while YAML requires Ansible 1.3+)
2013-10-11 22:29:39 +00:00
return config . extra_vars . to_json
end
end
2013-09-07 13:17:43 +00:00
def get_verbosity_argument
if config . verbose . to_s =~ / ^v+$ /
2013-10-04 06:58:49 +00:00
# ansible-playbook accepts "silly" arguments like '-vvvvv' as '-vvvv' for now
2013-09-17 04:02:22 +00:00
return " - #{ config . verbose } "
2013-10-04 19:32:10 +00:00
else
# safe default, in case input strays
return '-v'
2013-09-07 13:17:43 +00:00
end
end
2013-05-06 19:17:45 +00:00
def as_list_argument ( v )
v . kind_of? ( Array ) ? v . join ( ',' ) : v
end
2013-12-16 20:20:10 +00:00
def as_array ( v )
v . kind_of? ( Array ) ? v : [ v ]
end
2013-03-20 14:41:21 +00:00
end
end
end