kitchen-ansible 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,694 +1,695 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Neill Turner (<neillwturner@gmail.com>)
4
- #
5
- # Copyright (C) 2013,2014 Neill Turner
6
- #
7
- # Licensed under the Apache License, Version 2.0 (the "License");
8
- # you may not use this file except in compliance with the License.
9
- # You may obtain a copy of the License at
10
- #
11
- # http://www.apache.org/licenses/LICENSE-2.0
12
- #
13
- # Unless required by applicable law or agreed to in writing, software
14
- # distributed under the License is distributed on an "AS IS" BASIS,
15
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- # See the License for the specific language governing permissions and
17
- # limitations under the License.
18
- #
19
- # See https://github.com/neillturner/kitchen-ansible/blob/master/provisioner_options.md
20
- # for documentation configuration parameters with ansible_playbook provisioner.
21
- #
22
-
23
- require 'json'
24
- require 'kitchen/provisioner/base'
25
- require 'kitchen/provisioner/ansible/config'
26
- require 'kitchen/provisioner/ansible/librarian'
27
-
28
- module Kitchen
29
-
30
- class Busser
31
-
32
- def non_suite_dirs
33
- %w{data}
34
- end
35
- end
36
-
37
- module Provisioner
38
- #
39
- # Ansible Playbook provisioner.
40
- #
41
- class AnsiblePlaybook < Base
42
- attr_accessor :tmp_dir
43
-
44
- def initialize(provisioner_config)
45
- config = Kitchen::Provisioner::Ansible::Config.new(provisioner_config)
46
- super(config)
47
- end
48
-
49
- def finalize_config!(instance)
50
- config.set_instance(instance)
51
- super(instance)
52
- end
53
-
54
- def verbosity_level(level = 1)
55
- level = level.to_sym if level.is_a? String
56
- log_levels = { :info => 1, :warn => 2, :debug => 3, :trace => 4 }
57
- if level.is_a? Symbol and log_levels.include? level
58
- # puts "Log Level is: #{log_levels[level]}"
59
- log_levels[level]
60
- elsif level.is_a? Integer and level > 0
61
- # puts "Log Level is: #{level}"
62
- level
63
- else
64
- raise 'Invalid ansible_verbosity setting. Valid values are: 1, 2, 3, 4 OR :info, :warn, :debug, :trace'
65
- end
66
- end
67
-
68
- def install_command
69
- if config[:require_ansible_omnibus]
70
- cmd = install_omnibus_command
71
- elsif config[:require_ansible_source]
72
- info("Installing ansible from source")
73
- cmd = install_ansible_from_source_command
74
- elsif config[:require_ansible_repo]
75
- case ansible_platform
76
- when "debian", "ubuntu"
77
- info("Installing ansible on #{ansible_platform}")
78
- cmd = install_debian_command
79
- when "redhat", "centos", "fedora"
80
- info("Installing ansible on #{ansible_platform}")
81
- cmd = install_redhat_command
82
- when "amazon"
83
- info("Installing ansible on #{ansible_platform}")
84
- cmd = install_amazon_linux_command
85
- else
86
- info("Installing ansible, will try to determine platform os")
87
- cmd = <<-INSTALL
88
- if [ ! $(which ansible) ]; then
89
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
90
- if ! [ grep -q 'Amazon Linux' /etc/system-release ]; then
91
- #{install_redhat_command}
92
- else
93
- #{install_amazon_linux_command}
94
- fi
95
- else
96
- #{install_debian_command}
97
- fi
98
- fi
99
- INSTALL
100
- end
101
- else
102
- return
103
- end
104
- cmd + install_busser_prereqs
105
- end
106
-
107
- def install_busser_prereqs
108
- install = ''
109
- install << <<-INSTALL
110
- #{Util.shell_helpers}
111
- # Fix for https://github.com/test-kitchen/busser/issues/12
112
- if [ -h /usr/bin/ruby ]; then
113
- L=$(readlink -f /usr/bin/ruby)
114
- #{sudo('rm')} /usr/bin/ruby
115
- #{sudo('ln')} -s $L /usr/bin/ruby
116
- fi
117
- INSTALL
118
-
119
- if require_ruby_for_busser
120
- install << <<-INSTALL
121
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
122
- if ! [ grep -q 'Amazon Linux' /etc/system-release ]; then
123
- rhelversion=$(cat /etc/redhat-release | grep 'release 6')
124
- # For CentOS6/RHEL6 install ruby from SCL
125
- if [ -n "$rhelversion" ]; then
126
- if [ ! -d "/opt/rh/ruby193" ]; then
127
- echo "-----> Installing ruby SCL in CentOS6/RHEL6 to install busser to run tests"
128
- #{sudo('yum')} install -y centos-release-SCL
129
- #{sudo('yum')} install -y ruby193
130
- #{sudo('yum')} install -y ruby193-ruby-devel
131
- echo "-----> Enabling ruby193"
132
- source /opt/rh/ruby193/enable
133
- echo "/opt/rh/ruby193/root/usr/lib64" | sudo tee -a /etc/ld.so.conf
134
- sudo ldconfig
135
- sudo ln -s /opt/rh/ruby193/root/usr/bin/ruby /usr/bin/ruby
136
- sudo ln -s /opt/rh/ruby193/root/usr/bin/gem /usr/bin/gem
137
- fi
138
- else
139
- if [ ! $(which ruby) ]; then
140
- #{update_packages_redhat_cmd}
141
- #{sudo('yum')} -y install ruby ruby-devel
142
- fi
143
- fi
144
- else
145
- #{update_packages_redhat_cmd}
146
- #{sudo('yum')} -y install ruby ruby-devel gcc
147
- fi
148
- else
149
- if [ ! $(which ruby) ]; then
150
- #{update_packages_debian_cmd}
151
- #{sudo('apt-get')} -y install ruby1.9.1 ruby1.9.1-dev
152
- fi
153
- fi
154
- INSTALL
155
-
156
- elsif require_chef_for_busser && chef_url then
157
- install << <<-INSTALL
158
- # install chef omnibus so that busser works as this is needed to run tests :(
159
- if [ ! -d "/opt/chef" ]
160
- then
161
- echo "-----> Installing Chef Omnibus to install busser to run tests"
162
- do_download #{chef_url} /tmp/install.sh
163
- #{sudo('sh')} /tmp/install.sh
164
- fi
165
- INSTALL
166
- end
167
-
168
- install
169
- end
170
-
171
- def init_command
172
- dirs = %w{modules roles group_vars host_vars}.
173
- map { |dir| File.join(config[:root_path], dir) }.join(" ")
174
- cmd = "#{sudo('rm')} -rf #{dirs};"
175
- cmd = cmd+" mkdir -p #{config[:root_path]}"
176
- debug(cmd)
177
- cmd
178
- end
179
-
180
- def create_sandbox
181
- super
182
- debug("Creating local sandbox in #{sandbox_path}")
183
-
184
- yield if block_given?
185
-
186
- prepare_playbook
187
- prepare_inventory_file
188
- prepare_modules
189
- prepare_roles
190
- prepare_ansible_cfg
191
- prepare_group_vars
192
- prepare_additional_copy_path
193
- prepare_host_vars
194
- prepare_hosts
195
- prepare_filter_plugins
196
- prepare_ansible_vault_password_file
197
- info('Finished Preparing files for transfer')
198
-
199
- end
200
-
201
- def cleanup_sandbox
202
- return if sandbox_path.nil?
203
- debug("Cleaning up local sandbox in #{sandbox_path}")
204
- FileUtils.rmtree(sandbox_path)
205
- end
206
-
207
- def prepare_command
208
- commands = []
209
-
210
- # Prevent failure when ansible package installation doesn't contain /etc/ansible
211
- commands << [
212
- sudo("bash -c '[ -d /etc/ansible ] || mkdir /etc/ansible'")
213
- ]
214
-
215
- commands << [
216
- sudo('cp'),File.join(config[:root_path], 'ansible.cfg'),'/etc/ansible',
217
- ].join(' ')
218
-
219
- commands << [
220
- sudo('cp -r'), File.join(config[:root_path],'group_vars'), '/etc/ansible/.',
221
- ].join(' ')
222
-
223
- commands << [
224
- sudo('cp -r'), File.join(config[:root_path],'host_vars'), '/etc/ansible/.',
225
- ].join(' ')
226
-
227
- if galaxy_requirements
228
- if config[:require_ansible_source]
229
- commands << setup_ansible_env_from_source
230
- end
231
- commands << [
232
- 'ansible-galaxy', 'install', '--force',
233
- '-p', File.join(config[:root_path], 'roles'),
234
- '-r', File.join(config[:root_path], galaxy_requirements),
235
- ].join(' ')
236
- end
237
-
238
- command = commands.join(' && ')
239
- debug(command)
240
- command
241
- end
242
-
243
- def run_command
244
- if config[:require_ansible_source]
245
- cmd = "#{setup_ansible_env_from_source} && ansible-playbook"
246
- else
247
- cmd = sudo("ansible-playbook")
248
- end
249
- [
250
- cmd,
251
- ansible_inventory_flag,
252
- "-c #{config[:ansible_connection]}",
253
- "-M #{File.join(config[:root_path], 'modules')}",
254
- ansible_verbose_flag,
255
- ansible_check_flag,
256
- ansible_diff_flag,
257
- ansible_vault_flag,
258
- extra_vars,
259
- tags,
260
- "#{File.join(config[:root_path], File.basename(config[:playbook]))}",
261
- ].join(" ")
262
- end
263
-
264
- protected
265
-
266
- def load_needed_dependencies!
267
- if File.exists?(ansiblefile)
268
- debug("Ansiblefile found at #{ansiblefile}, loading Librarian-Ansible")
269
- Ansible::Librarian.load!(logger)
270
- end
271
- end
272
-
273
- def install_ansible_from_source_command
274
- <<-INSTALL
275
- if [ ! -d #{config[:root_path]}/ansible ]; then
276
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
277
- #{update_packages_redhat_cmd}
278
- #{sudo('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev
279
- else
280
- #{update_packages_debian_cmd}
281
- #{sudo('apt-get')} -y install git python python-setuptools build-essential python-dev
282
- fi
283
-
284
- git clone git://github.com/ansible/ansible.git --recursive #{config[:root_path]}/ansible
285
- #{sudo('easy_install')} pip
286
- #{setup_ansible_env_from_source} && pip install paramiko PyYAML Jinja2 httplib2
287
- fi
288
- INSTALL
289
- end
290
-
291
- def install_omnibus_command
292
- info("Installing ansible using ansible omnibus")
293
- version = if !config[:ansible_version].nil?
294
- "-v #{config[:ansible_version]}"
295
- else
296
- ""
297
- end
298
- <<-INSTALL
299
- #{Util.shell_helpers}
300
-
301
- if [ ! -d "#{config[:ansible_omnibus_remote_path]}" ]; then
302
- echo "-----> Installing Ansible Omnibus"
303
- do_download #{config[:ansible_omnibus_url]} /tmp/ansible_install.sh
304
- #{sudo('sh')} /tmp/ansible_install.sh #{version}
305
- fi
306
- INSTALL
307
- end
308
-
309
- def install_debian_command
310
- <<-INSTALL
311
- if [ ! $(which ansible) ]; then
312
- #{update_packages_debian_cmd}
313
-
314
- ## Install apt-utils to silence debconf warning: http://serverfault.com/q/358943/77156
315
- #{sudo('apt-get')} -y install apt-utils git
316
-
317
- ## Fix debconf tty warning messages
318
- export DEBIAN_FRONTEND=noninteractive
319
-
320
- ## 13.10, 14.04 include add-apt-repository in software-properties-common
321
- #{sudo('apt-get')} -y install software-properties-common
322
-
323
- ## 10.04, 12.04 include add-apt-repository in
324
- #{sudo('apt-get')} -y install python-software-properties
325
-
326
- ## 10.04 version of add-apt-repository doesn't accept --yes
327
- ## later versions require interaction from user, so we must specify --yes
328
- ## First try with -y flag, else if it fails, try without.
329
- ## "add-apt-repository: error: no such option: -y" is returned but is ok to ignore, we just retry
330
- #{sudo('add-apt-repository')} -y #{ansible_apt_repo} || #{sudo('add-apt-repository')} #{ansible_apt_repo}
331
- #{sudo('apt-get')} update
332
- #{sudo('apt-get')} -y install ansible
333
- fi
334
- INSTALL
335
- end
336
-
337
- def install_redhat_command
338
- <<-INSTALL
339
- if [ ! $(which ansible) ]; then
340
- #{sudo('rpm')} -ivh #{ansible_yum_repo}
341
- #{update_packages_redhat_cmd}
342
- #{sudo('yum')} -y install ansible#{ansible_redhat_version} libselinux-python git
343
- fi
344
- INSTALL
345
- end
346
-
347
- def install_amazon_linux_command
348
- <<-INSTALL
349
- if [ ! $(which ansible) ]; then
350
- #{sudo('yum-config-manager')} --enable epel/x86_64
351
- #{sudo('yum')} -y install ansible#{ansible_redhat_version} git
352
- #{sudo('alternatives')} --set python /usr/bin/python2.6
353
- #{sudo('yum')} clean all
354
- #{sudo('yum')} install yum-python26 -y
355
- fi
356
- INSTALL
357
- end
358
-
359
- def setup_ansible_env_from_source
360
- "cd #{config[:root_path]}/ansible && source hacking/env-setup && cd ../"
361
- end
362
-
363
- def tmp_modules_dir
364
- File.join(sandbox_path, 'modules')
365
- end
366
-
367
- def tmp_playbook_path
368
- File.join(sandbox_path, File.basename(playbook))
369
- end
370
-
371
- def tmp_host_vars_dir
372
- File.join(sandbox_path, 'host_vars')
373
- end
374
-
375
- def tmp_roles_dir
376
- File.join(sandbox_path, 'roles')
377
- end
378
-
379
- def tmp_filter_plugins_dir
380
- File.join(sandbox_path, 'filter_plugins')
381
- end
382
-
383
- def tmp_ansible_vault_password_file_path
384
- File.join(sandbox_path, File.basename(ansible_vault_password_file))
385
- end
386
-
387
- def tmp_inventory_file_path
388
- File.join(sandbox_path, File.basename(ansible_inventory_file))
389
- end
390
-
391
- def ansiblefile
392
- config[:ansiblefile_path] || ''
393
- end
394
-
395
- def galaxy_requirements
396
- config[:requirements_path] || nil
397
- end
398
-
399
- def playbook
400
- config[:playbook]
401
- end
402
-
403
- def hosts
404
- config[:hosts]
405
- end
406
-
407
- def roles
408
- config[:roles_path]
409
- end
410
-
411
- def role_name
412
- File.basename(roles) == 'roles' ? '' : File.basename(roles)
413
- end
414
-
415
- def modules
416
- config[:modules_path]
417
- end
418
-
419
- def group_vars
420
- config[:group_vars_path].to_s
421
- end
422
-
423
- def additional_copy
424
- config[:additional_copy_path]
425
- end
426
-
427
- def host_vars
428
- config[:host_vars_path].to_s
429
- end
430
-
431
- def filter_plugins
432
- config[:filter_plugins_path].to_s
433
- end
434
-
435
- def ansible_vault_password_file
436
- config[:ansible_vault_password_file]
437
- end
438
-
439
- def ansible_inventory_file
440
- config[:ansible_inventory_file]
441
- end
442
-
443
- def ansible_debian_version
444
- config[:ansible_version] ? "=#{config[:ansible_version]}" : nil
445
- end
446
-
447
- def ansible_redhat_version
448
- config[:ansible_version] ? "-#{config[:ansible_version]}" : nil
449
- end
450
-
451
- def ansible_verbose_flag
452
- config[:ansible_verbose] ? '-' << ('v' * verbosity_level(config[:ansible_verbosity])) : nil
453
- end
454
-
455
- def ansible_check_flag
456
- config[:ansible_check] ? '--check' : nil
457
- end
458
-
459
- def ansible_diff_flag
460
- config[:ansible_diff] ? '--diff' : nil
461
- end
462
-
463
- def ansible_vault_flag
464
- debug(config[:ansible_vault_password_file])
465
- config[:ansible_vault_password_file] ? "--vault-password-file=#{File.join(config[:root_path], File.basename(config[:ansible_vault_password_file]))}" : nil
466
- end
467
-
468
- def ansible_inventory_flag
469
- config[:ansible_inventory_file] ? "--inventory-file=#{File.join(config[:root_path], File.basename(config[:ansible_inventory_file]))}" : "--inventory-file=#{File.join(config[:root_path], 'hosts')}"
470
- end
471
-
472
- def ansible_platform
473
- config[:ansible_platform].to_s.downcase
474
- end
475
-
476
- def update_packages_debian_cmd
477
- config[:update_package_repos] ? "#{sudo('apt-get')} update" : nil
478
- end
479
-
480
- def update_packages_redhat_cmd
481
- config[:update_package_repos] ? "#{sudo('yum')} makecache" : nil
482
- end
483
-
484
- def extra_vars
485
- bash_vars = config[:extra_vars]
486
- if config.key?(:attributes) && config[:attributes].key?(:extra_vars) && config[:attributes][:extra_vars].is_a?(Hash)
487
- bash_vars = config[:attributes][:extra_vars]
488
- end
489
-
490
- return nil if bash_vars.none?
491
- bash_vars = JSON.dump(bash_vars)
492
- bash_vars = "-e '#{bash_vars}'"
493
- debug(bash_vars)
494
- bash_vars
495
- end
496
-
497
- def tags
498
- bash_tags = config.key?(:attributes) && config[:attributes].key?(:tags) && config[:attributes][:tags].is_a?(Array) ? config[:attributes][:tags] : config[:tags]
499
- return nil if bash_tags.empty?
500
-
501
- bash_tags = bash_tags.join(",")
502
- bash_tags = "-t '#{bash_tags}'"
503
- debug(bash_tags)
504
- bash_tags
505
- end
506
-
507
- def ansible_apt_repo
508
- config[:ansible_apt_repo]
509
- end
510
-
511
- def ansible_apt_repo_file
512
- config[:ansible_apt_repo].split('/').last
513
- end
514
-
515
- def ansible_yum_repo
516
- config[:ansible_yum_repo]
517
- end
518
-
519
- def chef_url
520
- config[:chef_bootstrap_url]
521
- end
522
-
523
- def require_ruby_for_busser
524
- config[:require_ruby_for_busser]
525
- end
526
-
527
- def require_chef_for_busser
528
- config[:require_chef_for_busser]
529
- end
530
-
531
- def prepare_roles
532
- info('Preparing roles')
533
- debug("Using roles from #{roles}")
534
-
535
- resolve_with_librarian if File.exists?(ansiblefile)
536
-
537
- if galaxy_requirements
538
- FileUtils.cp(galaxy_requirements, File.join(sandbox_path, galaxy_requirements))
539
- end
540
-
541
- # Detect whether we are running tests on a role
542
- # If so, make sure to copy into VM so dir structure is like: /tmp/kitchen/roles/role_name
543
-
544
- FileUtils.mkdir_p(File.join(tmp_roles_dir, role_name))
545
- FileUtils.cp_r(Dir.glob("#{roles}/*"), File.join(tmp_roles_dir, role_name))
546
- end
547
-
548
- # /etc/ansible/ansible.cfg should contain
549
- # roles_path = /tmp/kitchen/roles
550
- def prepare_ansible_cfg
551
- info('Preparing ansible.cfg file')
552
- ansible_config_file = "#{File.join(sandbox_path, 'ansible.cfg')}"
553
-
554
- roles_paths = []
555
- roles_paths << File.join(config[:root_path], 'roles') unless config[:roles_path].nil?
556
- additional_files.each do |additional_file|
557
- roles_paths << File.join(config[:root_path], File.basename(additional_file))
558
- end
559
-
560
- if roles_paths.empty?
561
- info('No roles have been set. empty ansible.cfg generated')
562
- File.open(ansible_config_file, "wb") do |file|
563
- file.write("#no roles path specified\n")
564
- end
565
- else
566
- debug("Setting roles_path inside VM to #{ roles_paths.join(':') }")
567
- File.open( ansible_config_file, "wb") do |file|
568
- file.write("[defaults]\nroles_path = #{ roles_paths.join(':') }\n")
569
- end
570
- end
571
- end
572
-
573
- def prepare_inventory_file
574
- info('Preparing inventory file')
575
-
576
- if ansible_inventory_file
577
- debug("Copying inventory file from #{ansible_inventory_file} to #{tmp_inventory_file_path}")
578
- FileUtils.cp_r(ansible_inventory_file, tmp_inventory_file_path)
579
- end
580
- end
581
-
582
- # localhost ansible_connection=local
583
- # [example_servers]
584
- # localhost
585
- def prepare_hosts
586
- info('Preparing hosts file')
587
-
588
- if config[:hosts].nil?
589
- raise 'No hosts have been set. Please specify one in .kitchen.yml'
590
- else
591
- debug("Using host from #{hosts}")
592
- File.open(File.join(sandbox_path, "hosts"), "wb") do |file|
593
- file.write("localhost ansible_connection=local\n[#{hosts}]\nlocalhost\n")
594
- end
595
- end
596
- end
597
-
598
- def prepare_playbook
599
- info('Preparing playbook')
600
- debug("Copying playbook from #{playbook} to #{tmp_playbook_path}")
601
- FileUtils.cp_r(playbook, tmp_playbook_path)
602
- end
603
-
604
- def prepare_group_vars
605
- info('Preparing group_vars')
606
- tmp_group_vars_dir = File.join(sandbox_path, 'group_vars')
607
- FileUtils.mkdir_p(tmp_group_vars_dir)
608
-
609
- unless File.directory?(group_vars)
610
- info 'nothing to do for group_vars'
611
- return
612
- end
613
-
614
- debug("Using group_vars from #{group_vars}")
615
- FileUtils.cp_r(Dir.glob("#{group_vars}/*"), tmp_group_vars_dir)
616
- end
617
-
618
- def prepare_additional_copy_path
619
- info('Preparing additional_copy_path')
620
- additional_files.each do |file|
621
- destination = File.join(sandbox_path, File.basename(file))
622
- if File.directory?(file)
623
- info("Copy dir: #{file} #{destination}")
624
- FileUtils.cp_r(file, destination)
625
- else
626
- info("Copy file: #{file} #{destination}")
627
- FileUtils.cp file, destination
628
- end
629
- end
630
- end
631
-
632
- def additional_files
633
- additional_files = []
634
- if ( additional_copy )
635
- additional_files = additional_copy.kind_of?(Array) ? additional_copy : [additional_copy]
636
- end
637
- additional_files.map { |additional_dir | additional_dir.to_s }
638
- end
639
-
640
- def prepare_host_vars
641
- info('Preparing host_vars')
642
- FileUtils.mkdir_p(tmp_host_vars_dir)
643
-
644
- unless File.directory?(host_vars)
645
- info 'nothing to do for host_vars'
646
- return
647
- end
648
-
649
- debug("Using host_vars from #{host_vars}")
650
- FileUtils.cp_r(Dir.glob("#{host_vars}/*"), tmp_host_vars_dir)
651
- end
652
-
653
- def prepare_modules
654
- info('Preparing modules')
655
-
656
- FileUtils.mkdir_p(tmp_modules_dir)
657
-
658
- if modules && File.directory?(modules)
659
- debug("Using modules from #{modules}")
660
- FileUtils.cp_r(Dir.glob("#{modules}/*"), tmp_modules_dir, remove_destination: true)
661
- else
662
- info 'nothing to do for modules'
663
- end
664
- end
665
-
666
- def prepare_filter_plugins
667
- info('Preparing filter_plugins')
668
- FileUtils.mkdir_p(tmp_filter_plugins_dir)
669
-
670
- if filter_plugins && File.directory?(filter_plugins)
671
- debug("Using filter_plugins from #{filter_plugins}")
672
- FileUtils.cp_r(Dir.glob("#{filter_plugins}/*.py"), tmp_filter_plugins_dir, remove_destination: true)
673
- else
674
- info 'nothing to do for filter_plugins'
675
- end
676
- end
677
-
678
- def prepare_ansible_vault_password_file
679
- if ansible_vault_password_file
680
- info('Preparing ansible vault password')
681
- debug("Copying ansible vault password file from #{ansible_vault_password_file} to #{tmp_ansible_vault_password_file_path}")
682
-
683
- FileUtils.cp(ansible_vault_password_file, tmp_ansible_vault_password_file_path)
684
- end
685
- end
686
-
687
- def resolve_with_librarian
688
- Kitchen.mutex.synchronize do
689
- Ansible::Librarian.new(ansiblefile, tmp_roles_dir, logger).resolve
690
- end
691
- end
692
- end
693
- end
694
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Neill Turner (<neillwturner@gmail.com>)
4
+ #
5
+ # Copyright (C) 2013,2014 Neill Turner
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ # See https://github.com/neillturner/kitchen-ansible/blob/master/provisioner_options.md
20
+ # for documentation configuration parameters with ansible_playbook provisioner.
21
+ #
22
+
23
+ require 'json'
24
+ require 'kitchen/provisioner/base'
25
+ require 'kitchen/provisioner/ansible/config'
26
+ require 'kitchen/provisioner/ansible/librarian'
27
+
28
+ module Kitchen
29
+
30
+ class Busser
31
+
32
+ def non_suite_dirs
33
+ %w{data}
34
+ end
35
+ end
36
+
37
+ module Provisioner
38
+ #
39
+ # Ansible Playbook provisioner.
40
+ #
41
+ class AnsiblePlaybook < Base
42
+ attr_accessor :tmp_dir
43
+
44
+ def initialize(provisioner_config)
45
+ config = Kitchen::Provisioner::Ansible::Config.new(provisioner_config)
46
+ super(config)
47
+ end
48
+
49
+ def finalize_config!(instance)
50
+ config.set_instance(instance)
51
+ super(instance)
52
+ end
53
+
54
+ def verbosity_level(level = 1)
55
+ level = level.to_sym if level.is_a? String
56
+ log_levels = { :info => 1, :warn => 2, :debug => 3, :trace => 4 }
57
+ if level.is_a? Symbol and log_levels.include? level
58
+ # puts "Log Level is: #{log_levels[level]}"
59
+ log_levels[level]
60
+ elsif level.is_a? Integer and level > 0
61
+ # puts "Log Level is: #{level}"
62
+ level
63
+ else
64
+ raise 'Invalid ansible_verbosity setting. Valid values are: 1, 2, 3, 4 OR :info, :warn, :debug, :trace'
65
+ end
66
+ end
67
+
68
+ def install_command
69
+ if config[:require_ansible_omnibus]
70
+ cmd = install_omnibus_command
71
+ elsif config[:require_ansible_source]
72
+ info("Installing ansible from source")
73
+ cmd = install_ansible_from_source_command
74
+ elsif config[:require_ansible_repo]
75
+ case ansible_platform
76
+ when "debian", "ubuntu"
77
+ info("Installing ansible on #{ansible_platform}")
78
+ cmd = install_debian_command
79
+ when "redhat", "centos", "fedora"
80
+ info("Installing ansible on #{ansible_platform}")
81
+ cmd = install_redhat_command
82
+ when "amazon"
83
+ info("Installing ansible on #{ansible_platform}")
84
+ cmd = install_amazon_linux_command
85
+ else
86
+ info("Installing ansible, will try to determine platform os")
87
+ cmd = <<-INSTALL
88
+ if [ ! $(which ansible) ]; then
89
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
90
+ if ! [ grep -q 'Amazon Linux' /etc/system-release ]; then
91
+ #{install_redhat_command}
92
+ else
93
+ #{install_amazon_linux_command}
94
+ fi
95
+ else
96
+ #{install_debian_command}
97
+ fi
98
+ fi
99
+ INSTALL
100
+ end
101
+ else
102
+ return
103
+ end
104
+ cmd + install_busser_prereqs
105
+ end
106
+
107
+ def install_busser_prereqs
108
+ install = ''
109
+ install << <<-INSTALL
110
+ #{Util.shell_helpers}
111
+ # Fix for https://github.com/test-kitchen/busser/issues/12
112
+ if [ -h /usr/bin/ruby ]; then
113
+ L=$(readlink -f /usr/bin/ruby)
114
+ #{sudo('rm')} /usr/bin/ruby
115
+ #{sudo('ln')} -s $L /usr/bin/ruby
116
+ fi
117
+ INSTALL
118
+
119
+ if require_ruby_for_busser
120
+ install << <<-INSTALL
121
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
122
+ if ! [ grep -q 'Amazon Linux' /etc/system-release ]; then
123
+ rhelversion=$(cat /etc/redhat-release | grep 'release 6')
124
+ # For CentOS6/RHEL6 install ruby from SCL
125
+ if [ -n "$rhelversion" ]; then
126
+ if [ ! -d "/opt/rh/ruby193" ]; then
127
+ echo "-----> Installing ruby SCL in CentOS6/RHEL6 to install busser to run tests"
128
+ #{sudo('yum')} install -y centos-release-SCL
129
+ #{sudo('yum')} install -y ruby193
130
+ #{sudo('yum')} install -y ruby193-ruby-devel
131
+ echo "-----> Enabling ruby193"
132
+ source /opt/rh/ruby193/enable
133
+ echo "/opt/rh/ruby193/root/usr/lib64" | sudo tee -a /etc/ld.so.conf
134
+ #{sudo('ldconfig')}
135
+ #{sudo('ln')} -s /opt/rh/ruby193/root/usr/bin/ruby /usr/bin/ruby
136
+ #{sudo('ln')} -s /opt/rh/ruby193/root/usr/bin/gem /usr/bin/gem
137
+ fi
138
+ else
139
+ if [ ! $(which ruby) ]; then
140
+ #{update_packages_redhat_cmd}
141
+ #{sudo('yum')} -y install ruby ruby-devel
142
+ fi
143
+ fi
144
+ else
145
+ #{update_packages_redhat_cmd}
146
+ #{sudo('yum')} -y install ruby ruby-devel gcc
147
+ fi
148
+ else
149
+ if [ ! $(which ruby) ]; then
150
+ #{update_packages_debian_cmd}
151
+ #{sudo('apt-get')} -y install ruby1.9.1 ruby1.9.1-dev
152
+ fi
153
+ fi
154
+ INSTALL
155
+
156
+ elsif require_chef_for_busser && chef_url then
157
+ install << <<-INSTALL
158
+ # install chef omnibus so that busser works as this is needed to run tests :(
159
+ if [ ! -d "/opt/chef" ]
160
+ then
161
+ echo "-----> Installing Chef Omnibus to install busser to run tests"
162
+ do_download #{chef_url} /tmp/install.sh
163
+ #{sudo('sh')} /tmp/install.sh
164
+ fi
165
+ INSTALL
166
+ end
167
+
168
+ install
169
+ end
170
+
171
+ def init_command
172
+ dirs = %w{modules roles group_vars host_vars}.
173
+ map { |dir| File.join(config[:root_path], dir) }.join(" ")
174
+ cmd = "#{sudo('rm')} -rf #{dirs};"
175
+ cmd = cmd+" mkdir -p #{config[:root_path]}"
176
+ debug(cmd)
177
+ cmd
178
+ end
179
+
180
+ def create_sandbox
181
+ super
182
+ debug("Creating local sandbox in #{sandbox_path}")
183
+
184
+ yield if block_given?
185
+
186
+ prepare_playbook
187
+ prepare_inventory_file
188
+ prepare_modules
189
+ prepare_roles
190
+ prepare_ansible_cfg
191
+ prepare_group_vars
192
+ prepare_additional_copy_path
193
+ prepare_host_vars
194
+ prepare_hosts
195
+ prepare_filter_plugins
196
+ prepare_ansible_vault_password_file
197
+ info('Finished Preparing files for transfer')
198
+
199
+ end
200
+
201
+ def cleanup_sandbox
202
+ return if sandbox_path.nil?
203
+ debug("Cleaning up local sandbox in #{sandbox_path}")
204
+ FileUtils.rmtree(sandbox_path)
205
+ end
206
+
207
+ def prepare_command
208
+ commands = []
209
+
210
+ # Prevent failure when ansible package installation doesn't contain /etc/ansible
211
+ commands << [
212
+ sudo("bash -c '[ -d /etc/ansible ] || mkdir /etc/ansible'")
213
+ ]
214
+
215
+ commands << [
216
+ sudo('cp'),File.join(config[:root_path], 'ansible.cfg'),'/etc/ansible',
217
+ ].join(' ')
218
+
219
+ commands << [
220
+ sudo('cp -r'), File.join(config[:root_path],'group_vars'), '/etc/ansible/.',
221
+ ].join(' ')
222
+
223
+ commands << [
224
+ sudo('cp -r'), File.join(config[:root_path],'host_vars'), '/etc/ansible/.',
225
+ ].join(' ')
226
+
227
+ if galaxy_requirements
228
+ if config[:require_ansible_source]
229
+ commands << setup_ansible_env_from_source
230
+ end
231
+ commands << [
232
+ 'ansible-galaxy', 'install', '--force',
233
+ '-p', File.join(config[:root_path], 'roles'),
234
+ '-r', File.join(config[:root_path], galaxy_requirements),
235
+ ].join(' ')
236
+ end
237
+
238
+ command = commands.join(' && ')
239
+ debug(command)
240
+ command
241
+ end
242
+
243
+ def run_command
244
+ if config[:require_ansible_source]
245
+ # this is an ugly hack to get around the fact that extra vars uses ' and "
246
+ cmd = sudo("PATH=#{config[:root_path]}/ansible/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games PYTHONPATH=#{config[:root_path]}/ansible/lib MANPATH=#{config[:root_path]}/ansible/docs/man #{config[:root_path]}/ansible/bin/ansible-playbook")
247
+ else
248
+ cmd = sudo("ansible-playbook")
249
+ end
250
+ [
251
+ cmd,
252
+ ansible_inventory_flag,
253
+ "-c #{config[:ansible_connection]}",
254
+ "-M #{File.join(config[:root_path], 'modules')}",
255
+ ansible_verbose_flag,
256
+ ansible_check_flag,
257
+ ansible_diff_flag,
258
+ ansible_vault_flag,
259
+ extra_vars,
260
+ tags,
261
+ "#{File.join(config[:root_path], File.basename(config[:playbook]))}",
262
+ ].join(" ")
263
+ end
264
+
265
+ protected
266
+
267
+ def load_needed_dependencies!
268
+ if File.exists?(ansiblefile)
269
+ debug("Ansiblefile found at #{ansiblefile}, loading Librarian-Ansible")
270
+ Ansible::Librarian.load!(logger)
271
+ end
272
+ end
273
+
274
+ def install_ansible_from_source_command
275
+ <<-INSTALL
276
+ if [ ! -d #{config[:root_path]}/ansible ]; then
277
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
278
+ #{update_packages_redhat_cmd}
279
+ #{sudo('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev
280
+ else
281
+ #{update_packages_debian_cmd}
282
+ #{sudo('apt-get')} -y install git python python-setuptools build-essential python-dev
283
+ fi
284
+
285
+ git clone git://github.com/ansible/ansible.git --recursive #{config[:root_path]}/ansible
286
+ #{sudo('easy_install')} pip
287
+ #{sudo('pip')} install paramiko PyYAML Jinja2 httplib2
288
+ fi
289
+ INSTALL
290
+ end
291
+
292
+ def install_omnibus_command
293
+ info("Installing ansible using ansible omnibus")
294
+ version = if !config[:ansible_version].nil?
295
+ "-v #{config[:ansible_version]}"
296
+ else
297
+ ""
298
+ end
299
+ <<-INSTALL
300
+ #{Util.shell_helpers}
301
+
302
+ if [ ! -d "#{config[:ansible_omnibus_remote_path]}" ]; then
303
+ echo "-----> Installing Ansible Omnibus"
304
+ do_download #{config[:ansible_omnibus_url]} /tmp/ansible_install.sh
305
+ #{sudo('sh')} /tmp/ansible_install.sh #{version}
306
+ fi
307
+ INSTALL
308
+ end
309
+
310
+ def install_debian_command
311
+ <<-INSTALL
312
+ if [ ! $(which ansible) ]; then
313
+ #{update_packages_debian_cmd}
314
+
315
+ ## Install apt-utils to silence debconf warning: http://serverfault.com/q/358943/77156
316
+ #{sudo('apt-get')} -y install apt-utils git
317
+
318
+ ## Fix debconf tty warning messages
319
+ export DEBIAN_FRONTEND=noninteractive
320
+
321
+ ## 13.10, 14.04 include add-apt-repository in software-properties-common
322
+ #{sudo('apt-get')} -y install software-properties-common
323
+
324
+ ## 10.04, 12.04 include add-apt-repository in
325
+ #{sudo('apt-get')} -y install python-software-properties
326
+
327
+ ## 10.04 version of add-apt-repository doesn't accept --yes
328
+ ## later versions require interaction from user, so we must specify --yes
329
+ ## First try with -y flag, else if it fails, try without.
330
+ ## "add-apt-repository: error: no such option: -y" is returned but is ok to ignore, we just retry
331
+ #{sudo('add-apt-repository')} -y #{ansible_apt_repo} || #{sudo('add-apt-repository')} #{ansible_apt_repo}
332
+ #{sudo('apt-get')} update
333
+ #{sudo('apt-get')} -y install ansible
334
+ fi
335
+ INSTALL
336
+ end
337
+
338
+ def install_redhat_command
339
+ <<-INSTALL
340
+ if [ ! $(which ansible) ]; then
341
+ #{sudo('rpm')} -ivh #{ansible_yum_repo}
342
+ #{update_packages_redhat_cmd}
343
+ #{sudo('yum')} -y install ansible#{ansible_redhat_version} libselinux-python git
344
+ fi
345
+ INSTALL
346
+ end
347
+
348
+ def install_amazon_linux_command
349
+ <<-INSTALL
350
+ if [ ! $(which ansible) ]; then
351
+ #{sudo('yum-config-manager')} --enable epel/x86_64
352
+ #{sudo('yum')} -y install ansible#{ansible_redhat_version} git
353
+ #{sudo('alternatives')} --set python /usr/bin/python2.6
354
+ #{sudo('yum')} clean all
355
+ #{sudo('yum')} install yum-python26 -y
356
+ fi
357
+ INSTALL
358
+ end
359
+
360
+ def setup_ansible_env_from_source
361
+ "cd #{config[:root_path]}/ansible && source hacking/env-setup && cd ../"
362
+ end
363
+
364
+ def tmp_modules_dir
365
+ File.join(sandbox_path, 'modules')
366
+ end
367
+
368
+ def tmp_playbook_path
369
+ File.join(sandbox_path, File.basename(playbook))
370
+ end
371
+
372
+ def tmp_host_vars_dir
373
+ File.join(sandbox_path, 'host_vars')
374
+ end
375
+
376
+ def tmp_roles_dir
377
+ File.join(sandbox_path, 'roles')
378
+ end
379
+
380
+ def tmp_filter_plugins_dir
381
+ File.join(sandbox_path, 'filter_plugins')
382
+ end
383
+
384
+ def tmp_ansible_vault_password_file_path
385
+ File.join(sandbox_path, File.basename(ansible_vault_password_file))
386
+ end
387
+
388
+ def tmp_inventory_file_path
389
+ File.join(sandbox_path, File.basename(ansible_inventory_file))
390
+ end
391
+
392
+ def ansiblefile
393
+ config[:ansiblefile_path] || ''
394
+ end
395
+
396
+ def galaxy_requirements
397
+ config[:requirements_path] || nil
398
+ end
399
+
400
+ def playbook
401
+ config[:playbook]
402
+ end
403
+
404
+ def hosts
405
+ config[:hosts]
406
+ end
407
+
408
+ def roles
409
+ config[:roles_path]
410
+ end
411
+
412
+ def role_name
413
+ File.basename(roles) == 'roles' ? '' : File.basename(roles)
414
+ end
415
+
416
+ def modules
417
+ config[:modules_path]
418
+ end
419
+
420
+ def group_vars
421
+ config[:group_vars_path].to_s
422
+ end
423
+
424
+ def additional_copy
425
+ config[:additional_copy_path]
426
+ end
427
+
428
+ def host_vars
429
+ config[:host_vars_path].to_s
430
+ end
431
+
432
+ def filter_plugins
433
+ config[:filter_plugins_path].to_s
434
+ end
435
+
436
+ def ansible_vault_password_file
437
+ config[:ansible_vault_password_file]
438
+ end
439
+
440
+ def ansible_inventory_file
441
+ config[:ansible_inventory_file]
442
+ end
443
+
444
+ def ansible_debian_version
445
+ config[:ansible_version] ? "=#{config[:ansible_version]}" : nil
446
+ end
447
+
448
+ def ansible_redhat_version
449
+ config[:ansible_version] ? "-#{config[:ansible_version]}" : nil
450
+ end
451
+
452
+ def ansible_verbose_flag
453
+ config[:ansible_verbose] ? '-' << ('v' * verbosity_level(config[:ansible_verbosity])) : nil
454
+ end
455
+
456
+ def ansible_check_flag
457
+ config[:ansible_check] ? '--check' : nil
458
+ end
459
+
460
+ def ansible_diff_flag
461
+ config[:ansible_diff] ? '--diff' : nil
462
+ end
463
+
464
+ def ansible_vault_flag
465
+ debug(config[:ansible_vault_password_file])
466
+ config[:ansible_vault_password_file] ? "--vault-password-file=#{File.join(config[:root_path], File.basename(config[:ansible_vault_password_file]))}" : nil
467
+ end
468
+
469
+ def ansible_inventory_flag
470
+ config[:ansible_inventory_file] ? "--inventory-file=#{File.join(config[:root_path], File.basename(config[:ansible_inventory_file]))}" : "--inventory-file=#{File.join(config[:root_path], 'hosts')}"
471
+ end
472
+
473
+ def ansible_platform
474
+ config[:ansible_platform].to_s.downcase
475
+ end
476
+
477
+ def update_packages_debian_cmd
478
+ config[:update_package_repos] ? "#{sudo('apt-get')} update" : nil
479
+ end
480
+
481
+ def update_packages_redhat_cmd
482
+ config[:update_package_repos] ? "#{sudo('yum')} makecache" : nil
483
+ end
484
+
485
+ def extra_vars
486
+ bash_vars = config[:extra_vars]
487
+ if config.key?(:attributes) && config[:attributes].key?(:extra_vars) && config[:attributes][:extra_vars].is_a?(Hash)
488
+ bash_vars = config[:attributes][:extra_vars]
489
+ end
490
+
491
+ return nil if bash_vars.none?
492
+ bash_vars = JSON.dump(bash_vars)
493
+ bash_vars = "-e '#{bash_vars}'"
494
+ debug(bash_vars)
495
+ bash_vars
496
+ end
497
+
498
+ def tags
499
+ bash_tags = config.key?(:attributes) && config[:attributes].key?(:tags) && config[:attributes][:tags].is_a?(Array) ? config[:attributes][:tags] : config[:tags]
500
+ return nil if bash_tags.empty?
501
+
502
+ bash_tags = bash_tags.join(",")
503
+ bash_tags = "-t '#{bash_tags}'"
504
+ debug(bash_tags)
505
+ bash_tags
506
+ end
507
+
508
+ def ansible_apt_repo
509
+ config[:ansible_apt_repo]
510
+ end
511
+
512
+ def ansible_apt_repo_file
513
+ config[:ansible_apt_repo].split('/').last
514
+ end
515
+
516
+ def ansible_yum_repo
517
+ config[:ansible_yum_repo]
518
+ end
519
+
520
+ def chef_url
521
+ config[:chef_bootstrap_url]
522
+ end
523
+
524
+ def require_ruby_for_busser
525
+ config[:require_ruby_for_busser]
526
+ end
527
+
528
+ def require_chef_for_busser
529
+ config[:require_chef_for_busser]
530
+ end
531
+
532
+ def prepare_roles
533
+ info('Preparing roles')
534
+ debug("Using roles from #{roles}")
535
+
536
+ resolve_with_librarian if File.exists?(ansiblefile)
537
+
538
+ if galaxy_requirements
539
+ FileUtils.cp(galaxy_requirements, File.join(sandbox_path, galaxy_requirements))
540
+ end
541
+
542
+ # Detect whether we are running tests on a role
543
+ # If so, make sure to copy into VM so dir structure is like: /tmp/kitchen/roles/role_name
544
+
545
+ FileUtils.mkdir_p(File.join(tmp_roles_dir, role_name))
546
+ FileUtils.cp_r(Dir.glob("#{roles}/*"), File.join(tmp_roles_dir, role_name))
547
+ end
548
+
549
+ # /etc/ansible/ansible.cfg should contain
550
+ # roles_path = /tmp/kitchen/roles
551
+ def prepare_ansible_cfg
552
+ info('Preparing ansible.cfg file')
553
+ ansible_config_file = "#{File.join(sandbox_path, 'ansible.cfg')}"
554
+
555
+ roles_paths = []
556
+ roles_paths << File.join(config[:root_path], 'roles') unless config[:roles_path].nil?
557
+ additional_files.each do |additional_file|
558
+ roles_paths << File.join(config[:root_path], File.basename(additional_file))
559
+ end
560
+
561
+ if roles_paths.empty?
562
+ info('No roles have been set. empty ansible.cfg generated')
563
+ File.open(ansible_config_file, "wb") do |file|
564
+ file.write("#no roles path specified\n")
565
+ end
566
+ else
567
+ debug("Setting roles_path inside VM to #{ roles_paths.join(':') }")
568
+ File.open( ansible_config_file, "wb") do |file|
569
+ file.write("[defaults]\nroles_path = #{ roles_paths.join(':') }\n")
570
+ end
571
+ end
572
+ end
573
+
574
+ def prepare_inventory_file
575
+ info('Preparing inventory file')
576
+
577
+ if ansible_inventory_file
578
+ debug("Copying inventory file from #{ansible_inventory_file} to #{tmp_inventory_file_path}")
579
+ FileUtils.cp_r(ansible_inventory_file, tmp_inventory_file_path)
580
+ end
581
+ end
582
+
583
+ # localhost ansible_connection=local
584
+ # [example_servers]
585
+ # localhost
586
+ def prepare_hosts
587
+ info('Preparing hosts file')
588
+
589
+ if config[:hosts].nil?
590
+ raise 'No hosts have been set. Please specify one in .kitchen.yml'
591
+ else
592
+ debug("Using host from #{hosts}")
593
+ File.open(File.join(sandbox_path, "hosts"), "wb") do |file|
594
+ file.write("localhost ansible_connection=local\n[#{hosts}]\nlocalhost\n")
595
+ end
596
+ end
597
+ end
598
+
599
+ def prepare_playbook
600
+ info('Preparing playbook')
601
+ debug("Copying playbook from #{playbook} to #{tmp_playbook_path}")
602
+ FileUtils.cp_r(playbook, tmp_playbook_path)
603
+ end
604
+
605
+ def prepare_group_vars
606
+ info('Preparing group_vars')
607
+ tmp_group_vars_dir = File.join(sandbox_path, 'group_vars')
608
+ FileUtils.mkdir_p(tmp_group_vars_dir)
609
+
610
+ unless File.directory?(group_vars)
611
+ info 'nothing to do for group_vars'
612
+ return
613
+ end
614
+
615
+ debug("Using group_vars from #{group_vars}")
616
+ FileUtils.cp_r(Dir.glob("#{group_vars}/*"), tmp_group_vars_dir)
617
+ end
618
+
619
+ def prepare_additional_copy_path
620
+ info('Preparing additional_copy_path')
621
+ additional_files.each do |file|
622
+ destination = File.join(sandbox_path, File.basename(file))
623
+ if File.directory?(file)
624
+ info("Copy dir: #{file} #{destination}")
625
+ FileUtils.cp_r(file, destination)
626
+ else
627
+ info("Copy file: #{file} #{destination}")
628
+ FileUtils.cp file, destination
629
+ end
630
+ end
631
+ end
632
+
633
+ def additional_files
634
+ additional_files = []
635
+ if ( additional_copy )
636
+ additional_files = additional_copy.kind_of?(Array) ? additional_copy : [additional_copy]
637
+ end
638
+ additional_files.map { |additional_dir | additional_dir.to_s }
639
+ end
640
+
641
+ def prepare_host_vars
642
+ info('Preparing host_vars')
643
+ FileUtils.mkdir_p(tmp_host_vars_dir)
644
+
645
+ unless File.directory?(host_vars)
646
+ info 'nothing to do for host_vars'
647
+ return
648
+ end
649
+
650
+ debug("Using host_vars from #{host_vars}")
651
+ FileUtils.cp_r(Dir.glob("#{host_vars}/*"), tmp_host_vars_dir)
652
+ end
653
+
654
+ def prepare_modules
655
+ info('Preparing modules')
656
+
657
+ FileUtils.mkdir_p(tmp_modules_dir)
658
+
659
+ if modules && File.directory?(modules)
660
+ debug("Using modules from #{modules}")
661
+ FileUtils.cp_r(Dir.glob("#{modules}/*"), tmp_modules_dir, remove_destination: true)
662
+ else
663
+ info 'nothing to do for modules'
664
+ end
665
+ end
666
+
667
+ def prepare_filter_plugins
668
+ info('Preparing filter_plugins')
669
+ FileUtils.mkdir_p(tmp_filter_plugins_dir)
670
+
671
+ if filter_plugins && File.directory?(filter_plugins)
672
+ debug("Using filter_plugins from #{filter_plugins}")
673
+ FileUtils.cp_r(Dir.glob("#{filter_plugins}/*.py"), tmp_filter_plugins_dir, remove_destination: true)
674
+ else
675
+ info 'nothing to do for filter_plugins'
676
+ end
677
+ end
678
+
679
+ def prepare_ansible_vault_password_file
680
+ if ansible_vault_password_file
681
+ info('Preparing ansible vault password')
682
+ debug("Copying ansible vault password file from #{ansible_vault_password_file} to #{tmp_ansible_vault_password_file_path}")
683
+
684
+ FileUtils.cp(ansible_vault_password_file, tmp_ansible_vault_password_file_path)
685
+ end
686
+ end
687
+
688
+ def resolve_with_librarian
689
+ Kitchen.mutex.synchronize do
690
+ Ansible::Librarian.new(ansiblefile, tmp_roles_dir, logger).resolve
691
+ end
692
+ end
693
+ end
694
+ end
695
+ end