kitchen-ansible 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,673 +1,694 @@
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_repo]
72
- case ansible_platform
73
- when "debian", "ubuntu"
74
- info("Installing ansible on #{ansible_platform}")
75
- cmd = install_debian_command
76
- when "redhat", "centos", "fedora"
77
- info("Installing ansible on #{ansible_platform}")
78
- cmd = install_redhat_command
79
- when "amazon"
80
- info("Installing ansible on #{ansible_platform}")
81
- cmd = install_amazon_linux_command
82
- else
83
- info("Installing ansible, will try to determine platform os")
84
- cmd = <<-INSTALL
85
- if [ ! $(which ansible) ]; then
86
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
87
- if ! [ grep -q 'Amazon Linux' /etc/system-release ]; then
88
- #{install_redhat_command}
89
- else
90
- #{install_amazon_linux_command}
91
- fi
92
- else
93
- #{install_debian_command}
94
- fi
95
- fi
96
- INSTALL
97
- end
98
- elsif config[:require_ansible_source]
99
- info("Installing ansible from source")
100
- cmd = install_ansible_from_source_command
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_modules
188
- prepare_roles
189
- prepare_ansible_cfg
190
- prepare_group_vars
191
- prepare_additional_copy_path
192
- prepare_host_vars
193
- prepare_hosts
194
- prepare_filter_plugins
195
- prepare_ansible_vault_password_file
196
- info('Finished Preparing files for transfer')
197
-
198
- end
199
-
200
- def cleanup_sandbox
201
- return if sandbox_path.nil?
202
- debug("Cleaning up local sandbox in #{sandbox_path}")
203
- FileUtils.rmtree(sandbox_path)
204
- end
205
-
206
- def prepare_command
207
- commands = []
208
-
209
- # Prevent failure when ansible package installation doesn't contain /etc/ansible
210
- commands << [
211
- sudo("bash -c '[ -d /etc/ansible ] || mkdir /etc/ansible'")
212
- ]
213
-
214
- commands << [
215
- sudo('cp'),File.join(config[:root_path], 'ansible.cfg'),'/etc/ansible',
216
- ].join(' ')
217
-
218
- commands << [
219
- sudo('cp -r'), File.join(config[:root_path],'group_vars'), '/etc/ansible/.',
220
- ].join(' ')
221
-
222
- commands << [
223
- sudo('cp -r'), File.join(config[:root_path],'host_vars'), '/etc/ansible/.',
224
- ].join(' ')
225
-
226
- if galaxy_requirements
227
- if config[:require_ansible_source]
228
- commands << setup_ansible_env_from_source
229
- end
230
- commands << [
231
- 'ansible-galaxy', 'install', '--force',
232
- '-p', File.join(config[:root_path], 'roles'),
233
- '-r', File.join(config[:root_path], galaxy_requirements),
234
- ].join(' ')
235
- end
236
-
237
- command = commands.join(' && ')
238
- debug(command)
239
- command
240
- end
241
-
242
- def run_command
243
- if config[:require_ansible_source]
244
- cmd = "#{setup_ansible_env_from_source} && ansible-playbook"
245
- else
246
- cmd = sudo("ansible-playbook")
247
- end
248
- [
249
- cmd,
250
- "-i #{File.join(config[:root_path], 'hosts')}",
251
- "-M #{File.join(config[:root_path], 'modules')}",
252
- ansible_verbose_flag,
253
- ansible_check_flag,
254
- ansible_diff_flag,
255
- ansible_vault_flag,
256
- extra_vars,
257
- tags,
258
- "#{File.join(config[:root_path], File.basename(config[:playbook]))}",
259
- ].join(" ")
260
- end
261
-
262
- protected
263
-
264
- def load_needed_dependencies!
265
- if File.exists?(ansiblefile)
266
- debug("Ansiblefile found at #{ansiblefile}, loading Librarian-Ansible")
267
- Ansible::Librarian.load!(logger)
268
- end
269
- end
270
-
271
- def install_ansible_from_source_command
272
- <<-INSTALL
273
- if [ ! -d #{config[:root_path]}/ansible ]; then
274
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
275
- #{update_packages_redhat_cmd}
276
- #{sudo('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev
277
- else
278
- #{update_packages_debian_cmd}
279
- #{sudo('apt-get')} -y install git python python-setuptools
280
- fi
281
-
282
- git clone git://github.com/ansible/ansible.git --recursive #{config[:root_path]}/ansible
283
- #{sudo('easy_install')} pip
284
- sudo -EH 'pip' install paramiko PyYAML Jinja2 httplib2
285
- fi
286
- INSTALL
287
- end
288
-
289
- def install_omnibus_command
290
- info("Installing ansible using ansible omnibus")
291
- version = if !config[:ansible_version].nil?
292
- "-v #{config[:ansible_version]}"
293
- else
294
- ""
295
- end
296
- <<-INSTALL
297
- #{Util.shell_helpers}
298
-
299
- if [ ! -d "#{config[:ansible_omnibus_remote_path]}" ]; then
300
- echo "-----> Installing Ansible Omnibus"
301
- do_download #{config[:ansible_omnibus_url]} /tmp/ansible_install.sh
302
- #{sudo('sh')} /tmp/ansible_install.sh #{version}
303
- fi
304
- INSTALL
305
- end
306
-
307
- def install_debian_command
308
- <<-INSTALL
309
- if [ ! $(which ansible) ]; then
310
- #{update_packages_debian_cmd}
311
-
312
- ## Install apt-utils to silence debconf warning: http://serverfault.com/q/358943/77156
313
- #{sudo('apt-get')} -y install apt-utils git
314
-
315
- ## Fix debconf tty warning messages
316
- export DEBIAN_FRONTEND=noninteractive
317
-
318
- ## 13.10, 14.04 include add-apt-repository in software-properties-common
319
- #{sudo('apt-get')} -y install software-properties-common
320
-
321
- ## 10.04, 12.04 include add-apt-repository in
322
- #{sudo('apt-get')} -y install python-software-properties
323
-
324
- ## 10.04 version of add-apt-repository doesn't accept --yes
325
- ## later versions require interaction from user, so we must specify --yes
326
- ## First try with -y flag, else if it fails, try without.
327
- ## "add-apt-repository: error: no such option: -y" is returned but is ok to ignore, we just retry
328
- #{sudo('add-apt-repository')} -y #{ansible_apt_repo} || #{sudo('add-apt-repository')} #{ansible_apt_repo}
329
- #{sudo('apt-get')} update
330
- #{sudo('apt-get')} -y install ansible
331
- fi
332
- INSTALL
333
- end
334
-
335
- def install_redhat_command
336
- <<-INSTALL
337
- if [ ! $(which ansible) ]; then
338
- #{sudo('rpm')} -ivh #{ansible_yum_repo}
339
- #{update_packages_redhat_cmd}
340
- #{sudo('yum')} -y install ansible#{ansible_redhat_version} libselinux-python git
341
- fi
342
- INSTALL
343
- end
344
-
345
- def install_amazon_linux_command
346
- <<-INSTALL
347
- if [ ! $(which ansible) ]; then
348
- #{sudo('yum-config-manager')} --enable epel/x86_64
349
- #{sudo('yum')} -y install ansible#{ansible_redhat_version} git
350
- #{sudo('alternatives')} --set python /usr/bin/python2.6
351
- #{sudo('yum')} clean all
352
- #{sudo('yum')} install yum-python26 -y
353
- fi
354
- INSTALL
355
- end
356
-
357
- def setup_ansible_env_from_source
358
- "cd #{config[:root_path]}/ansible && source hacking/env-setup && cd ../"
359
- end
360
-
361
- def tmp_modules_dir
362
- File.join(sandbox_path, 'modules')
363
- end
364
-
365
- def tmp_playbook_path
366
- File.join(sandbox_path, File.basename(playbook))
367
- end
368
-
369
- def tmp_host_vars_dir
370
- File.join(sandbox_path, 'host_vars')
371
- end
372
-
373
- def tmp_roles_dir
374
- File.join(sandbox_path, 'roles')
375
- end
376
-
377
- def tmp_filter_plugins_dir
378
- File.join(sandbox_path, 'filter_plugins')
379
- end
380
-
381
- def tmp_ansible_vault_password_file_path
382
- File.join(sandbox_path, File.basename(ansible_vault_password_file))
383
- end
384
-
385
- def ansiblefile
386
- config[:ansiblefile_path] || ''
387
- end
388
-
389
- def galaxy_requirements
390
- config[:requirements_path] || nil
391
- end
392
-
393
- def playbook
394
- config[:playbook]
395
- end
396
-
397
- def hosts
398
- config[:hosts]
399
- end
400
-
401
- def roles
402
- config[:roles_path]
403
- end
404
-
405
- def role_name
406
- File.basename(roles) == 'roles' ? '' : File.basename(roles)
407
- end
408
-
409
- def modules
410
- config[:modules_path]
411
- end
412
-
413
- def group_vars
414
- config[:group_vars_path].to_s
415
- end
416
-
417
- def additional_copy
418
- config[:additional_copy_path]
419
- end
420
-
421
- def host_vars
422
- config[:host_vars_path].to_s
423
- end
424
-
425
- def filter_plugins
426
- config[:filter_plugins_path].to_s
427
- end
428
-
429
- def ansible_vault_password_file
430
- config[:ansible_vault_password_file]
431
- end
432
-
433
- def ansible_debian_version
434
- config[:ansible_version] ? "=#{config[:ansible_version]}" : nil
435
- end
436
-
437
- def ansible_redhat_version
438
- config[:ansible_version] ? "-#{config[:ansible_version]}" : nil
439
- end
440
-
441
- def ansible_verbose_flag
442
- config[:ansible_verbose] ? '-' << ('v' * verbosity_level(config[:ansible_verbosity])) : nil
443
- end
444
-
445
- def ansible_check_flag
446
- config[:ansible_check] ? '--check' : nil
447
- end
448
-
449
- def ansible_diff_flag
450
- config[:ansible_diff] ? '--diff' : nil
451
- end
452
-
453
- def ansible_vault_flag
454
- debug(config[:ansible_vault_password_file])
455
- config[:ansible_vault_password_file] ? "--vault-password-file=#{File.join(config[:root_path], File.basename(config[:ansible_vault_password_file]))}" : nil
456
- end
457
-
458
- def ansible_platform
459
- config[:ansible_platform].to_s.downcase
460
- end
461
-
462
- def update_packages_debian_cmd
463
- config[:update_package_repos] ? "#{sudo('apt-get')} update" : nil
464
- end
465
-
466
- def update_packages_redhat_cmd
467
- config[:update_package_repos] ? "#{sudo('yum')} makecache" : nil
468
- end
469
-
470
- def extra_vars
471
- bash_vars = config[:extra_vars]
472
- if config.key?(:attributes) && config[:attributes].key?(:extra_vars) && config[:attributes][:extra_vars].is_a?(Hash)
473
- bash_vars = config[:attributes][:extra_vars]
474
- end
475
-
476
- return nil if bash_vars.none?
477
- bash_vars = JSON.dump(bash_vars)
478
- bash_vars = "-e '#{bash_vars}'"
479
- debug(bash_vars)
480
- bash_vars
481
- end
482
-
483
- def tags
484
- bash_tags = config.key?(:attributes) && config[:attributes].key?(:tags) && config[:attributes][:tags].is_a?(Array) ? config[:attributes][:tags] : config[:tags]
485
- return nil if bash_tags.empty?
486
-
487
- bash_tags = bash_tags.join(",")
488
- bash_tags = "-t '#{bash_tags}'"
489
- debug(bash_tags)
490
- bash_tags
491
- end
492
-
493
- def ansible_apt_repo
494
- config[:ansible_apt_repo]
495
- end
496
-
497
- def ansible_apt_repo_file
498
- config[:ansible_apt_repo].split('/').last
499
- end
500
-
501
- def ansible_yum_repo
502
- config[:ansible_yum_repo]
503
- end
504
-
505
- def chef_url
506
- config[:chef_bootstrap_url]
507
- end
508
-
509
- def require_ruby_for_busser
510
- config[:require_ruby_for_busser]
511
- end
512
-
513
- def require_chef_for_busser
514
- config[:require_chef_for_busser]
515
- end
516
-
517
- def prepare_roles
518
- info('Preparing roles')
519
- debug("Using roles from #{roles}")
520
-
521
- resolve_with_librarian if File.exists?(ansiblefile)
522
-
523
- if galaxy_requirements
524
- FileUtils.cp(galaxy_requirements, File.join(sandbox_path, galaxy_requirements))
525
- end
526
-
527
- # Detect whether we are running tests on a role
528
- # If so, make sure to copy into VM so dir structure is like: /tmp/kitchen/roles/role_name
529
-
530
- FileUtils.mkdir_p(File.join(tmp_roles_dir, role_name))
531
- FileUtils.cp_r(Dir.glob("#{roles}/*"), File.join(tmp_roles_dir, role_name))
532
- end
533
-
534
- # /etc/ansible/ansible.cfg should contain
535
- # roles_path = /tmp/kitchen/roles
536
- def prepare_ansible_cfg
537
- info('Preparing ansible.cfg file')
538
- ansible_config_file = "#{File.join(sandbox_path, 'ansible.cfg')}"
539
-
540
- roles_paths = []
541
- roles_paths << File.join(config[:root_path], 'roles') unless config[:roles_path].nil?
542
- additional_files.each do |additional_file|
543
- roles_paths << File.join(config[:root_path], File.basename(additional_file))
544
- end
545
-
546
- if roles_paths.empty?
547
- info('No roles have been set. empty ansible.cfg generated')
548
- File.open(ansible_config_file, "wb") do |file|
549
- file.write("#no roles path specified\n")
550
- end
551
- else
552
- debug("Setting roles_path inside VM to #{ roles_paths.join(':') }")
553
- File.open( ansible_config_file, "wb") do |file|
554
- file.write("[defaults]\nroles_path = #{ roles_paths.join(':') }\n")
555
- end
556
- end
557
- end
558
-
559
-
560
- # localhost ansible_connection=local
561
- # [example_servers]
562
- # localhost
563
- def prepare_hosts
564
- info('Preparing hosts file')
565
-
566
- if config[:hosts].nil?
567
- raise 'No hosts have been set. Please specify one in .kitchen.yml'
568
- else
569
- debug("Using host from #{hosts}")
570
- File.open(File.join(sandbox_path, "hosts"), "wb") do |file|
571
- file.write("localhost ansible_connection=local\n[#{hosts}]\nlocalhost\n")
572
- end
573
- end
574
- end
575
-
576
- def prepare_playbook
577
- info('Preparing playbook')
578
- debug("Copying playbook from #{playbook} to #{tmp_playbook_path}")
579
- FileUtils.cp_r(playbook, tmp_playbook_path)
580
- end
581
-
582
-
583
- def prepare_group_vars
584
- info('Preparing group_vars')
585
- tmp_group_vars_dir = File.join(sandbox_path, 'group_vars')
586
- FileUtils.mkdir_p(tmp_group_vars_dir)
587
-
588
- unless File.directory?(group_vars)
589
- info 'nothing to do for group_vars'
590
- return
591
- end
592
-
593
- debug("Using group_vars from #{group_vars}")
594
- FileUtils.cp_r(Dir.glob("#{group_vars}/*"), tmp_group_vars_dir)
595
- end
596
-
597
- def prepare_additional_copy_path
598
- info('Preparing additional_copy_path')
599
- additional_files.each do |file|
600
- destination = File.join(sandbox_path, File.basename(file))
601
- if File.directory?(file)
602
- info("Copy dir: #{file} #{destination}")
603
- FileUtils.cp_r(file, destination)
604
- else
605
- info("Copy file: #{file} #{destination}")
606
- FileUtils.cp file, destination
607
- end
608
- end
609
- end
610
-
611
- def additional_files
612
- additional_files = []
613
- if ( additional_copy )
614
- additional_files = additional_copy.kind_of?(Array) ? additional_copy : [additional_copy]
615
- end
616
- additional_files.map { |additional_dir | additional_dir.to_s }
617
- end
618
-
619
- def prepare_host_vars
620
- info('Preparing host_vars')
621
- FileUtils.mkdir_p(tmp_host_vars_dir)
622
-
623
- unless File.directory?(host_vars)
624
- info 'nothing to do for host_vars'
625
- return
626
- end
627
-
628
- debug("Using host_vars from #{host_vars}")
629
- FileUtils.cp_r(Dir.glob("#{host_vars}/*"), tmp_host_vars_dir)
630
- end
631
-
632
- def prepare_modules
633
- info('Preparing modules')
634
-
635
- FileUtils.mkdir_p(tmp_modules_dir)
636
-
637
- if modules && File.directory?(modules)
638
- debug("Using modules from #{modules}")
639
- FileUtils.cp_r(Dir.glob("#{modules}/*"), tmp_modules_dir, remove_destination: true)
640
- else
641
- info 'nothing to do for modules'
642
- end
643
- end
644
-
645
- def prepare_filter_plugins
646
- info('Preparing filter_plugins')
647
- FileUtils.mkdir_p(tmp_filter_plugins_dir)
648
-
649
- if filter_plugins && File.directory?(filter_plugins)
650
- debug("Using filter_plugins from #{filter_plugins}")
651
- FileUtils.cp_r(Dir.glob("#{filter_plugins}/*.py"), tmp_filter_plugins_dir, remove_destination: true)
652
- else
653
- info 'nothing to do for filter_plugins'
654
- end
655
- end
656
-
657
- def prepare_ansible_vault_password_file
658
- if ansible_vault_password_file
659
- info('Preparing ansible vault password')
660
- debug("Copying ansible vault password file from #{ansible_vault_password_file} to #{tmp_ansible_vault_password_file_path}")
661
-
662
- FileUtils.cp(ansible_vault_password_file, tmp_ansible_vault_password_file_path)
663
- end
664
- end
665
-
666
- def resolve_with_librarian
667
- Kitchen.mutex.synchronize do
668
- Ansible::Librarian.new(ansiblefile, tmp_roles_dir, logger).resolve
669
- end
670
- end
671
- end
672
- end
673
- 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
+ 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