kitchen-ansible 0.43.1 → 0.44.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,44 +1,44 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Michael Heap (<m@michaelheap.com>)
4
- #
5
- # Copyright (C) 2015 Michael Heap
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
-
20
- module Kitchen
21
- module Provisioner
22
- module Ansible
23
- class Os
24
- class Suse < Os
25
- def install_command
26
- <<-INSTALL
27
-
28
- if [ ! $(which ansible) ]; then
29
- #{sudo_env('zypper')} ar #{@config[:python_sles_repo]}
30
- #{sudo_env('zypper')} ar #{@config[:ansible_sles_repo]}
31
- #{update_packages_command}
32
- #{sudo_env('zypper')} --non-interactive install ansible
33
- fi
34
- INSTALL
35
- end
36
-
37
- def update_packages_command
38
- @config[:update_package_repos] ? "#{sudo_env('zypper')} --gpg-auto-import-keys ref" : nil
39
- end
40
- end
41
- end
42
- end
43
- end
44
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Michael Heap (<m@michaelheap.com>)
4
+ #
5
+ # Copyright (C) 2015 Michael Heap
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
+
20
+ module Kitchen
21
+ module Provisioner
22
+ module Ansible
23
+ class Os
24
+ class Suse < Os
25
+ def install_command
26
+ <<-INSTALL
27
+
28
+ if [ ! $(which ansible) ]; then
29
+ #{sudo_env('zypper')} ar #{@config[:python_sles_repo]}
30
+ #{sudo_env('zypper')} ar #{@config[:ansible_sles_repo]}
31
+ #{update_packages_command}
32
+ #{sudo_env('zypper')} --non-interactive install ansible
33
+ fi
34
+ INSTALL
35
+ end
36
+
37
+ def update_packages_command
38
+ @config[:update_package_repos] ? "#{sudo_env('zypper')} --gpg-auto-import-keys ref" : nil
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,1024 +1,1039 @@
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/os'
27
- require 'kitchen/provisioner/ansible/librarian'
28
-
29
- module Kitchen
30
- class Busser
31
- def non_suite_dirs
32
- %w(data)
33
- end
34
- end
35
-
36
- module Provisioner
37
- #
38
- # Ansible Playbook provisioner.
39
- #
40
- class AnsiblePlaybook < Base
41
- attr_accessor :tmp_dir
42
-
43
- def initialize(provisioner_config)
44
- config = Kitchen::Provisioner::Ansible::Config.new(provisioner_config)
45
- super(config)
46
-
47
- @os = Kitchen::Provisioner::Ansible::Os.make(ansible_platform, config)
48
- end
49
-
50
- def finalize_config!(instance)
51
- config.instance = instance
52
- super(instance)
53
- end
54
-
55
- def verbosity_level(level = 1)
56
- level = level.to_sym if level.is_a? String
57
- log_levels = { info: 1, warn: 2, debug: 3, trace: 4 }
58
- if level.is_a?(Symbol) && log_levels.include?(level)
59
- # puts "Log Level is: #{log_levels[level]}"
60
- log_levels[level]
61
- elsif level.is_a?(Integer) && level > 0
62
- # puts "Log Level is: #{level}"
63
- level
64
- else
65
- fail 'Invalid ansible_verbosity setting. Valid values are: 1, 2, 3, 4 OR :info, :warn, :debug, :trace'
66
- end
67
- end
68
-
69
- def install_command
70
- if config[:require_ansible_omnibus]
71
- cmd = install_omnibus_command
72
- elsif config[:require_ansible_source]
73
- info('Installing ansible from source')
74
- cmd = install_ansible_from_source_command
75
- elsif config[:require_pip]
76
- info('Installing ansible through pip')
77
- cmd = install_ansible_from_pip_command
78
- elsif config[:require_ansible_repo]
79
- if !@os.nil?
80
- info("Installing ansible on #{@os.name}")
81
- cmd = @os.install_command
82
- else
83
- info('Installing ansible, will try to determine platform os')
84
- cmd = <<-INSTALL
85
-
86
- if [ ! $(which ansible) ]; then
87
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
88
- if [ -z `grep -q 'Amazon Linux' /etc/system-release` ]; then
89
- #{Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).install_command}
90
- else
91
- #{Kitchen::Provisioner::Ansible::Os::Amazon.new('amazon', config).install_command}
92
- fi
93
- elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
94
- #{Kitchen::Provisioner::Ansible::Os::Suse.new('suse', config).install_command}
95
- else
96
- #{Kitchen::Provisioner::Ansible::Os::Debian.new('debian', config).install_command}
97
- fi
98
- fi
99
- INSTALL
100
- end
101
- else
102
- return
103
- end
104
- result = cmd + install_windows_support + install_busser_prereqs
105
- debug("Going to install ansible with: #{result}")
106
- result
107
- end
108
-
109
- def install_windows_support
110
- install = ''
111
- if require_windows_support
112
- install << <<-INSTALL
113
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
114
- #{sudo_env('yum')} -y install python-devel krb5-devel krb5-libs krb5-workstation gcc
115
- else
116
- if [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
117
- #{sudo_env('zypper')} ar #{python_sles_repo}
118
- #{sudo_env('zypper')} --non-interactive install python python-devel krb5-client pam_krb5
119
- else
120
- #{sudo_env('apt-get')} install python-dev libkrb5-dev build-essential
121
- fi
122
- fi
123
- #{export_http_proxy}
124
- #{sudo_env('easy_install')} pip
125
- #{sudo_env('pip')} install pywinrm kerberos
126
- INSTALL
127
- end
128
- install
129
- end
130
-
131
- def install_busser_prereqs
132
- install = ''
133
- install << <<-INSTALL
134
- #{Util.shell_helpers}
135
- # Fix for https://github.com/test-kitchen/busser/issues/12
136
- if [ -h /usr/bin/ruby ]; then
137
- L=$(readlink -f /usr/bin/ruby)
138
- #{sudo_env('rm')} /usr/bin/ruby
139
- #{sudo_env('ln')} -s $L /usr/bin/ruby
140
- fi
141
- INSTALL
142
-
143
- if require_ruby_for_busser
144
- install << <<-INSTALL
145
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
146
- if [ -z `grep -q 'Amazon Linux' /etc/system-release` ]; then
147
- rhelversion6=$(cat /etc/redhat-release | grep 'release 6')
148
- rhelversion7=$(cat /etc/redhat-release | grep 'release 7')
149
- # For CentOS6/CentOS7/RHEL6/RHEL7 install ruby from SCL
150
- if [ -n "$rhelversion6" ] || [ -n "$rhelversion7" ]; then
151
- if [ ! -d "/opt/rh/ruby200" ]; then
152
- echo "-----> Installing ruby200 SCL in CentOS6/CentOS7/RHEL6/RHEL7 to install busser to run tests"
153
- #{sudo_env('yum')} install -y centos-release-scl
154
- #{sudo_env('yum')} install -y ruby200
155
- #{sudo_env('yum')} install -y ruby200-ruby-devel
156
- echo "-----> Enabling ruby200"
157
- source /opt/rh/ruby200/enable
158
- echo "/opt/rh/ruby200/root/usr/lib64" | sudo tee -a /etc/ld.so.conf
159
- #{sudo_env('ldconfig')}
160
- #{sudo_env('ln')} -sf /opt/rh/ruby200/root/usr/bin/ruby /usr/bin/ruby
161
- #{sudo_env('ln')} -sf /opt/rh/ruby200/root/usr/bin/gem /usr/bin/gem
162
- fi
163
- else
164
- if [ ! $(which ruby) ]; then
165
- #{update_packages_redhat_cmd}
166
- #{sudo_env('yum')} -y install ruby ruby-devel
167
- fi
168
- fi
169
- else
170
- #{update_packages_redhat_cmd}
171
- #{sudo_env('yum')} -y install ruby ruby-devel gcc
172
- fi
173
- elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
174
- #{update_packages_suse_cmd}
175
- #{sudo_env('zypper')} --non-interactive install ruby ruby-devel ca-certificates ca-certificates-cacert ca-certificates-mozilla
176
- #{sudo_env('gem')} sources --add https://rubygems.org/
177
- else
178
- if [ ! $(which ruby) ]; then
179
- #{update_packages_debian_cmd}
180
- # default package selection for Debian/Ubuntu machines
181
- PACKAGES="ruby1.9.1 ruby1.9.1-dev"
182
- if [ "$(lsb_release -si)" = "Debian" ]; then
183
- debvers=$(sed 's/\\..*//' /etc/debian_version)
184
- if [ $debvers -ge 8 ]; then
185
- # this is jessie or better, where ruby1.9.1 is
186
- # no longer in the repositories
187
- PACKAGES="ruby ruby-dev ruby2.1 ruby2.1-dev"
188
- fi
189
- fi
190
- if [ "$(lsb_release -si)" = "Ubuntu" ]; then
191
- ubuntuvers=$(lsb_release -sr | tr -d .)
192
- if [ $ubuntuvers -ge 1410 ]; then
193
- # Default ruby is 2.x in utopic and newer
194
- PACKAGES="ruby ruby-dev"
195
- fi
196
- fi
197
- #{sudo_env('apt-get')} -y install $PACKAGES
198
- if [ $debvers -eq 6 ]; then
199
- # in squeeze we need to update alternatives
200
- # for enable ruby1.9.1
201
- ALTERNATIVES_STRING="--install /usr/bin/ruby ruby /usr/bin/ruby1.9.1 10 --slave /usr/share/man/man1/ruby.1.gz ruby.1.gz /usr/share/man/man1/ruby1.9.1.1.gz --slave /usr/bin/erb erb /usr/bin/erb1.9.1 --slave /usr/bin/gem gem /usr/bin/gem1.9.1 --slave /usr/bin/irb irb /usr/bin/irb1.9.1 --slave /usr/bin/rake rake /usr/bin/rake1.9.1 --slave /usr/bin/rdoc rdoc /usr/bin/rdoc1.9.1 --slave /usr/bin/testrb testrb /usr/bin/testrb1.9.1 --slave /usr/share/man/man1/erb.1.gz erb.1.gz /usr/share/man/man1/erb1.9.1.1.gz --slave /usr/share/man/man1/gem.1.gz gem.1.gz /usr/share/man/man1/gem1.9.1.1.gz --slave /usr/share/man/man1/irb.1.gz irb.1.gz /usr/share/man/man1/irb1.9.1.1.gz --slave /usr/share/man/man1/rake.1.gz rake.1.gz /usr/share/man/man1/rake1.9.1.1.gz --slave /usr/share/man/man1/rdoc.1.gz rdoc.1.gz /usr/share/man/man1/rdoc1.9.1.1.gz --slave /usr/share/man/man1/testrb.1.gz testrb.1.gz /usr/share/man/man1/testrb1.9.1.1.gz"
202
- #{sudo_env('update-alternatives')} $ALTERNATIVES_STRING
203
- # need to update gem tool because gem 1.3.7 from ruby 1.9.1 is broken
204
- #{sudo_env('gem')} install rubygems-update
205
- #{sudo_env('/var/lib/gems/1.9.1/bin/update_rubygems')}
206
- # clear local gem cache
207
- #{sudo_env('rm')} -r /home/vagrant/.gem
208
- fi
209
- fi
210
- fi
211
- INSTALL
212
-
213
- elsif require_chef_for_busser && chef_url
214
- install << <<-INSTALL
215
- # install chef omnibus so that busser works as this is needed to run tests :(
216
- if [ ! -d "/opt/chef" ]
217
- then
218
- echo "-----> Installing Chef Omnibus to install busser to run tests"
219
- #{export_http_proxy}
220
- do_download #{chef_url} /tmp/install.sh
221
- #{sudo_env('sh')} /tmp/install.sh
222
- fi
223
- INSTALL
224
- end
225
-
226
- install
227
- end
228
-
229
- def init_command
230
- dirs = %w(modules roles group_vars host_vars)
231
- .map { |dir| File.join(config[:root_path], dir) }.join(' ')
232
- cmd = "#{sudo_env('rm')} -rf #{dirs};"
233
- cmd += " mkdir -p #{config[:root_path]}"
234
- debug(cmd)
235
- cmd
236
- end
237
-
238
- def create_sandbox
239
- super
240
- debug("Creating local sandbox in #{sandbox_path}")
241
-
242
- yield if block_given?
243
-
244
- prepare_playbook
245
- prepare_inventory
246
- prepare_modules
247
- prepare_roles
248
- prepare_ansible_cfg
249
- prepare_group_vars
250
- prepare_additional_copy_path
251
- prepare_host_vars
252
- prepare_hosts
253
- prepare_spec
254
- prepare_library_plugins
255
- prepare_callback_plugins
256
- prepare_filter_plugins
257
- prepare_lookup_plugins
258
- prepare_ansible_vault_password_file
259
- prepare_kerberos_conf_file
260
- info('Finished Preparing files for transfer')
261
- end
262
-
263
- def cleanup_sandbox
264
- return if sandbox_path.nil?
265
- debug("Cleaning up local sandbox in #{sandbox_path}")
266
- FileUtils.rmtree(sandbox_path)
267
- end
268
-
269
- def prepare_command
270
- commands = []
271
-
272
- # Prevent failure when ansible package installation doesn't contain /etc/ansible
273
- commands << [
274
- sudo_env("bash -c '[ -d /etc/ansible ] || mkdir /etc/ansible'")
275
- ]
276
-
277
- commands << [
278
- sudo_env('cp'), File.join(config[:root_path], 'ansible.cfg'), '/etc/ansible'
279
- ].join(' ')
280
-
281
- commands << [
282
- sudo_env('cp -r'), File.join(config[:root_path], 'group_vars'), '/etc/ansible/.'
283
- ].join(' ')
284
-
285
- commands << [
286
- sudo_env('cp -r'), File.join(config[:root_path], 'host_vars'), '/etc/ansible/.'
287
- ].join(' ')
288
-
289
- if config[:ssh_known_hosts]
290
- config[:ssh_known_hosts].each do |host|
291
- info("Add #{host} to ~/.ssh/known_hosts")
292
- commands << "ssh-keyscan #{host} > ~/.ssh/known_hosts 2> /dev/null"
293
- end
294
- end
295
-
296
- if ansible_inventory
297
- if File.directory?(ansible_inventory)
298
- Dir.foreach(ansible_inventory) do |f|
299
- next if f == "." or f == ".."
300
- contents = File.open("#{ansible_inventory}/#{f}", 'rb') { |g| g.read }
301
- if contents.start_with?('#!')
302
- commands << [
303
- sudo_env('chmod +x'), File.join("#{config[:root_path]}/#{File.basename(ansible_inventory)}", File.basename(f))
304
- ].join(' ')
305
- end
306
- end
307
- else
308
- contents = File.open(ansible_inventory, 'rb') { |f| f.read }
309
- if contents.start_with?('#!')
310
- commands << [
311
- sudo_env('chmod +x'), File.join(config[:root_path], File.basename(ansible_inventory))
312
- ].join(' ')
313
- end
314
- end
315
- end
316
-
317
- if galaxy_requirements
318
- if config[:require_ansible_source]
319
- commands << setup_ansible_env_from_source
320
- end
321
- commands << ansible_galaxy_command
322
- end
323
-
324
- if kerberos_conf_file
325
- commands << [
326
- sudo_env('cp -f'), File.join(config[:root_path], 'krb5.conf'), '/etc'
327
- ].join(' ')
328
- end
329
-
330
- command = commands.join(' && ')
331
- debug(command)
332
- command
333
- end
334
-
335
- def run_command
336
- if !config[:ansible_playbook_command].nil?
337
- return config[:ansible_playbook_command]
338
- else
339
-
340
- if config[:require_ansible_source] && !config[:ansible_binary_path]
341
- # this is an ugly hack to get around the fact that extra vars uses ' and "
342
- cmd = ansible_command("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 ansible-playbook")
343
- elsif config[:ansible_binary_path]
344
- cmd = ansible_command("#{config[:ansible_binary_path]}/ansible-playbook")
345
- else
346
- cmd = ansible_command('ansible-playbook')
347
- end
348
-
349
- cmd = "HTTPS_PROXY=#{https_proxy} #{cmd}" if https_proxy
350
- cmd = "HTTP_PROXY=#{http_proxy} #{cmd}" if http_proxy
351
- cmd = "NO_PROXY=#{no_proxy} #{cmd}" if no_proxy
352
- cmd = "ANSIBLE_ROLES_PATH=#{ansible_roles_path} #{cmd}" if ansible_roles_path
353
- cmd = "ANSIBLE_HOST_KEY_CHECKING=false #{cmd}" if !ansible_host_key_checking
354
-
355
- cmd = "#{cd_ansible} #{cmd}" if !config[:ansible_sudo].nil? && !config[:ansible_sudo]
356
- cmd = "#{copy_private_key_cmd} #{cmd}" if config[:private_key]
357
-
358
- result = [
359
- cmd,
360
- ansible_inventory_flag,
361
- ansible_limit_flag,
362
- ansible_connection_flag,
363
- "-M #{File.join(config[:root_path], 'modules')}",
364
- ansible_verbose_flag,
365
- ansible_check_flag,
366
- ansible_diff_flag,
367
- ansible_vault_flag,
368
- private_key,
369
- extra_vars,
370
- tags,
371
- ansible_extra_flags,
372
- "#{File.join(config[:root_path], File.basename(config[:playbook]))}"
373
- ].join(' ')
374
- debug("Going to invoke ansible-playbook with: #{result}")
375
- if config[:idempotency_test]
376
- result = "#{result} && (echo 'Going to invoke ansible-playbook second time:'; #{result} | tee /tmp/idempotency_test.txt; grep -q 'changed=0.*failed=0' /tmp/idempotency_test.txt && (echo 'Idempotence test: PASS' && exit 0) || (echo 'Idempotence test: FAIL' && exit 1))"
377
- debug("Full cmd with idempotency test: #{result}")
378
- end
379
-
380
- result
381
- end
382
- end
383
-
384
- def ansible_command(script)
385
- if config[:ansible_sudo].nil? || config[:ansible_sudo] == true
386
- s = https_proxy ? "https_proxy=#{https_proxy}" : nil
387
- p = http_proxy ? "http_proxy=#{http_proxy}" : nil
388
- n = no_proxy ? "no_proxy=#{no_proxy}" : nil
389
- p || s || n ? " #{p} #{s} #{n} #{config[:sudo_command]} -s #{cd_ansible} #{script}" : "#{config[:sudo_command]} -s #{cd_ansible} #{script}"
390
- else
391
- return script
392
- end
393
- end
394
-
395
- def ansible_galaxy_command
396
- cmd = [
397
- 'ansible-galaxy', 'install', '--force',
398
- '-p', File.join(config[:root_path], 'roles'),
399
- '-r', File.join(config[:root_path], galaxy_requirements)
400
- ].join(' ')
401
- cmd = "https_proxy=#{https_proxy} #{cmd}" if https_proxy
402
- cmd = "http_proxy=#{http_proxy} #{cmd}" if http_proxy
403
- cmd = "no_proxy=#{no_proxy} #{cmd}" if no_proxy
404
- cmd
405
- end
406
-
407
- def cd_ansible
408
- # this is not working so just return nil for now
409
- # File.exist?('ansible.cfg') ? "cd #{config[:root_path]};" : nil
410
- nil
411
- end
412
-
413
- protected
414
-
415
- def load_needed_dependencies!
416
- return unless File.exist?(ansiblefile)
417
-
418
- debug("Ansiblefile found at #{ansiblefile}, loading Librarian-Ansible")
419
- Ansible::Librarian.load!(logger)
420
- end
421
-
422
- def install_ansible_from_source_command
423
- <<-INSTALL
424
- if [ ! -d #{config[:root_path]}/ansible ]; then
425
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
426
- #{Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).install_epel_repo}
427
- #{update_packages_redhat_cmd}
428
- #{sudo_env('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev libffi-devel libssl-devel
429
- else
430
- if [ -f /etc/SUSE-brand ] || [ -f /etc/SuSE-release ]; then
431
- #{sudo_env('zypper')} ar #{python_sles_repo}
432
- #{update_packages_suse_cmd}
433
- #{sudo_env('zypper')} --non-interactive install python python-devel git python-setuptools python-pip python-six libyaml-devel libffi-devel libopenssl-devel
434
- else
435
- #{update_packages_debian_cmd}
436
- #{sudo_env('apt-get')} -y install git python python-setuptools build-essential python-dev libffi-dev libssl-dev
437
- fi
438
- fi
439
-
440
- #{export_http_proxy}
441
- git clone git://github.com/ansible/ansible.git --recursive #{config[:root_path]}/ansible #{install_source_rev}
442
- #{sudo_env('easy_install')} pip
443
- #{sudo_env('pip')} install -U setuptools
444
- #{sudo_env('pip')} install six paramiko PyYAML Jinja2 httplib2
445
- fi
446
- INSTALL
447
- end
448
-
449
- def install_ansible_from_pip_command
450
- ansible_version = ''
451
- ansible_version = "==#{config[:ansible_version]}" unless config[:ansible_version] == 'latest'
452
-
453
- <<-INSTALL
454
- if [ ! -d #{config[:root_path]}/ansible ]; then
455
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
456
- #{Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).install_epel_repo}
457
- #{update_packages_redhat_cmd}
458
- #{sudo_env('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev libffi-devel libssl-devel
459
- else
460
- if [ -f /etc/SUSE-brand ] || [ -f /etc/SuSE-release ]; then
461
- #{sudo_env('zypper')} ar #{python_sles_repo}
462
- #{update_packages_suse_cmd}
463
- #{sudo_env('zypper')} --non-interactive install python python-devel git python-setuptools python-pip python-six libyaml-devel libffi-devel libopenssl-devel
464
- else
465
- #{update_packages_debian_cmd}
466
- #{sudo_env('apt-get')} -y install git python python-setuptools build-essential python-dev libffi-dev libssl-dev
467
- fi
468
- fi
469
-
470
- #{export_http_proxy}
471
- #{sudo_env('easy_install')} pip
472
- #{sudo_env('pip')} install -U setuptools
473
- #{sudo_env('pip')} install ansible#{ansible_version}
474
- fi
475
- INSTALL
476
- end
477
-
478
- def install_omnibus_command
479
- info('Installing ansible using ansible omnibus')
480
-
481
- version = ''
482
- version = "-v #{config[:ansible_version]}" unless config[:ansible_version].nil?
483
-
484
- <<-INSTALL
485
- #{Util.shell_helpers}
486
-
487
- if [ ! -d "#{config[:ansible_omnibus_remote_path]}" ]; then
488
- echo "-----> Installing Ansible Omnibus"
489
- #{export_http_proxy}
490
- do_download #{config[:ansible_omnibus_url]} /tmp/ansible_install.sh
491
- #{sudo_env('sh')} /tmp/ansible_install.sh #{version}
492
- fi
493
- INSTALL
494
- end
495
-
496
- def setup_ansible_env_from_source
497
- "cd #{config[:root_path]}/ansible && source hacking/env-setup && cd ../"
498
- end
499
-
500
- def tmp_modules_dir
501
- File.join(sandbox_path, 'modules')
502
- end
503
-
504
- def tmp_playbook_path
505
- File.join(sandbox_path, File.basename(playbook))
506
- end
507
-
508
- def tmp_host_vars_dir
509
- File.join(sandbox_path, 'host_vars')
510
- end
511
-
512
- def tmp_roles_dir
513
- File.join(sandbox_path, 'roles')
514
- end
515
-
516
- def tmp_spec_dir
517
- File.join(sandbox_path, 'spec')
518
- end
519
-
520
- def tmp_library_plugins_dir
521
- File.join(sandbox_path, 'library')
522
- end
523
-
524
- def tmp_callback_plugins_dir
525
- File.join(sandbox_path, 'callback_plugins')
526
- end
527
-
528
- def tmp_filter_plugins_dir
529
- File.join(sandbox_path, 'filter_plugins')
530
- end
531
-
532
- def tmp_lookup_plugins_dir
533
- File.join(sandbox_path, 'lookup_plugins')
534
- end
535
-
536
- def tmp_ansible_vault_password_file_path
537
- File.join(sandbox_path, File.basename(ansible_vault_password_file).reverse.chomp('.').reverse)
538
- end
539
-
540
- def tmp_kerberos_conf_file_path
541
- File.join(sandbox_path, 'krb5.conf')
542
- end
543
-
544
- def tmp_inventory_path
545
- File.join(sandbox_path, File.basename(ansible_inventory))
546
- end
547
-
548
- def ansiblefile
549
- config[:ansiblefile_path] || ''
550
- end
551
-
552
- def galaxy_requirements
553
- config[:requirements_path] || nil
554
- end
555
-
556
- def playbook
557
- config[:playbook]
558
- end
559
-
560
- def hosts
561
- config[:hosts]
562
- end
563
-
564
- def roles
565
- config[:roles_path]
566
- end
567
-
568
- def role_name
569
- if config[:role_name]
570
- config[:role_name]
571
- elsif File.basename(roles) == 'roles'
572
- ''
573
- else
574
- File.basename(roles)
575
- end
576
- end
577
-
578
- def modules
579
- config[:modules_path]
580
- end
581
-
582
- def spec
583
- 'spec'
584
- end
585
-
586
- def group_vars
587
- config[:group_vars_path].to_s
588
- end
589
-
590
- def additional_copy
591
- config[:additional_copy_path]
592
- end
593
-
594
- def host_vars
595
- config[:host_vars_path].to_s
596
- end
597
-
598
- def library_plugins
599
- config[:library_plugins_path].to_s
600
- end
601
-
602
- def callback_plugins
603
- config[:callback_plugins_path].to_s
604
- end
605
-
606
- def filter_plugins
607
- config[:filter_plugins_path].to_s
608
- end
609
-
610
- def lookup_plugins
611
- config[:lookup_plugins_path].to_s
612
- end
613
-
614
- def ansible_vault_password_file
615
- config[:ansible_vault_password_file]
616
- end
617
-
618
- def ansible_inventory
619
- return nil if config[:ansible_inventory] == 'none'
620
- config[:ansible_inventory] = config[:ansible_inventory_file] if config[:ansible_inventory].nil?
621
- info('ansible_inventory_file parameter deprecated use ansible_inventory') if config[:ansible_inventory_file]
622
- config[:ansible_inventory]
623
- end
624
-
625
- def ansible_debian_version
626
- if @config[:ansible_version] == 'latest' || @config[:ansible_version] == nil
627
- ''
628
- else
629
- "=#{@config[:ansible_version]}"
630
- end
631
- end
632
-
633
- def ansible_connection_flag
634
- "-c #{config[:ansible_connection]}" if config[:ansible_connection] != 'none'
635
- end
636
-
637
- def ansible_verbose_flag
638
- config[:ansible_verbose] ? '-' << ('v' * verbosity_level(config[:ansible_verbosity])) : nil
639
- end
640
-
641
- def ansible_check_flag
642
- config[:ansible_check] ? '--check' : nil
643
- end
644
-
645
- def ansible_diff_flag
646
- config[:ansible_diff] ? '--diff' : nil
647
- end
648
-
649
- def ansible_vault_flag
650
- debug(config[:ansible_vault_password_file])
651
- config[:ansible_vault_password_file] ? "--vault-password-file=#{File.join(config[:root_path], File.basename(config[:ansible_vault_password_file]).reverse.chomp('.').reverse)}" : nil
652
- end
653
-
654
- def ansible_inventory_flag
655
- return nil if config[:ansible_inventory] == 'none'
656
- ansible_inventory ? "-i #{File.join(config[:root_path], File.basename(ansible_inventory))}" : "-i #{File.join(config[:root_path], 'hosts')}"
657
- end
658
-
659
- def ansible_limit_flag
660
- config[:ansible_limit] ? "-l #{config[:ansible_limit]}" : ""
661
- end
662
-
663
- def ansible_extra_flags
664
- config[:ansible_extra_flags] || ''
665
- end
666
-
667
- def ansible_platform
668
- config[:ansible_platform].to_s.downcase
669
- end
670
-
671
- def ansible_host_key_checking
672
- config[:ansible_host_key_checking]
673
- end
674
-
675
- def private_key
676
- if config[:private_key]
677
- "--private-key #{private_key_file}"
678
- end
679
- end
680
-
681
- def copy_private_key_cmd
682
- if !config[:private_key].start_with?('/') && !config[:private_key].start_with?('~')
683
- ssh_private_key = File.join('~/.ssh', File.basename(config[:private_key]))
684
- tmp_private_key = File.join(config[:root_path], config[:private_key])
685
- "rm -rf #{ssh_private_key}; cp #{tmp_private_key} #{ssh_private_key}; chmod 400 #{ssh_private_key};"
686
- end
687
- end
688
-
689
- def private_key_file
690
- if config[:private_key].start_with?('/') || config[:private_key].start_with?('~')
691
- "#{config[:private_key]}"
692
- elsif config[:private_key]
693
- "#{File.join('~/.ssh', File.basename(config[:private_key]))}"
694
- end
695
- end
696
-
697
- def update_packages_debian_cmd
698
- Kitchen::Provisioner::Ansible::Os::Debian.new('debian', config).update_packages_command
699
- end
700
-
701
- def update_packages_suse_cmd
702
- Kitchen::Provisioner::Ansible::Os::Suse.new('suse', config).update_packages_command
703
- end
704
-
705
- def update_packages_redhat_cmd
706
- Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).update_packages_command
707
- end
708
-
709
- def python_sles_repo
710
- config[:python_sles_repo]
711
- end
712
-
713
- def extra_vars
714
- bash_vars = config[:extra_vars]
715
- if config.key?(:attributes) && config[:attributes].key?(:extra_vars) && config[:attributes][:extra_vars].is_a?(Hash)
716
- bash_vars = config[:attributes][:extra_vars]
717
- end
718
-
719
- return nil if bash_vars.none?
720
- bash_vars = JSON.dump(bash_vars)
721
- bash_vars = "-e '#{bash_vars}'"
722
- debug(bash_vars)
723
- bash_vars
724
- end
725
-
726
- def tags
727
- bash_tags = config.key?(:attributes) && config[:attributes].key?(:tags) && config[:attributes][:tags].is_a?(Array) ? config[:attributes][:tags] : config[:tags]
728
- return nil if bash_tags.empty?
729
-
730
- bash_tags = bash_tags.join(',')
731
- bash_tags = "-t '#{bash_tags}'"
732
- debug(bash_tags)
733
- bash_tags
734
- end
735
-
736
- def chef_url
737
- config[:chef_bootstrap_url]
738
- end
739
-
740
- def require_ruby_for_busser
741
- config[:require_ruby_for_busser]
742
- end
743
-
744
- def require_chef_for_busser
745
- config[:require_chef_for_busser]
746
- end
747
-
748
- def require_windows_support
749
- config[:require_windows_support]
750
- end
751
-
752
- def kerberos_conf_file
753
- config[:kerberos_conf_file]
754
- end
755
-
756
- def install_source_rev
757
- config[:ansible_source_rev] ? "--branch #{config[:ansible_source_rev]}" : nil
758
- end
759
-
760
- def http_proxy
761
- config[:http_proxy]
762
- end
763
-
764
- def https_proxy
765
- config[:https_proxy]
766
- end
767
-
768
- def no_proxy
769
- config[:no_proxy]
770
- end
771
-
772
- def sudo_env(pm,home=false)
773
- s = https_proxy ? "https_proxy=#{https_proxy}" : nil
774
- p = http_proxy ? "http_proxy=#{http_proxy}" : nil
775
- n = no_proxy ? "no_proxy=#{no_proxy}" : nil
776
- if home
777
- p || s || n ? "#{sudo_home('env')} #{p} #{s} #{n} #{pm}" : "#{sudo_home(pm)}"
778
- else
779
- p || s || n ? "#{sudo('env')} #{p} #{s} #{n} #{pm}" : "#{sudo(pm)}"
780
- end
781
- end
782
-
783
- def export_http_proxy
784
- cmd = ''
785
- cmd = " HTTP_PROXY=#{http_proxy}" if http_proxy
786
- cmd = "#{cmd} HTTPS_PROXY=#{https_proxy}" if https_proxy
787
- cmd = "#{cmd} NO_PROXY=#{no_proxy}" if no_proxy
788
- cmd = "export #{cmd}" if cmd != ''
789
- cmd
790
- end
791
-
792
- def ansible_roles_path
793
- roles_paths = []
794
- roles_paths << File.join(config[:root_path], 'roles') unless config[:roles_path].nil?
795
- additional_files.each do |additional_file|
796
- roles_paths << File.join(config[:root_path], File.basename(additional_file))
797
- end
798
- if roles_paths.empty?
799
- info('No roles have been set.')
800
- nil
801
- else
802
- debug("Setting roles_path inside VM to #{ roles_paths.join(':') }")
803
- roles_paths.join(':')
804
- end
805
- end
806
-
807
- def prepare_roles
808
- info('Preparing roles')
809
- debug("Using roles from #{roles}")
810
-
811
- resolve_with_librarian if File.exist?(ansiblefile)
812
-
813
- if galaxy_requirements
814
- dest = File.join(sandbox_path, galaxy_requirements)
815
- FileUtils.mkdir_p(File.dirname(dest))
816
- FileUtils.cp(galaxy_requirements, dest)
817
- end
818
-
819
- # Detect whether we are running tests on a role
820
- # If so, make sure to copy into VM so dir structure is like: /tmp/kitchen/roles/role_name
821
-
822
- FileUtils.mkdir_p(File.join(tmp_roles_dir, role_name))
823
- FileUtils.cp_r(Dir.glob("#{roles}/*"), File.join(tmp_roles_dir, role_name))
824
- end
825
-
826
- # copy ansible.cfg if found in root of repo
827
- def prepare_ansible_cfg
828
- info('Preparing ansible.cfg file')
829
- ansible_config_file = "#{File.join(sandbox_path, 'ansible.cfg')}"
830
- if File.exist?('ansible.cfg')
831
- info('Found existing ansible.cfg')
832
- FileUtils.cp_r('ansible.cfg', ansible_config_file)
833
- else
834
- info('Empty ansible.cfg generated')
835
- File.open(ansible_config_file, 'wb') do |file|
836
- file.write("#no config parameters\n")
837
- end
838
- end
839
- end
840
-
841
- def prepare_inventory
842
- info('Preparing inventory')
843
- return unless ansible_inventory
844
- if File.directory?(ansible_inventory)
845
- debug("Copying inventory directory from #{ansible_inventory} to #{tmp_inventory_path}")
846
- FileUtils.cp_r(ansible_inventory, sandbox_path)
847
- else
848
- debug("Copying inventory file from #{ansible_inventory} to #{tmp_inventory_path}")
849
- FileUtils.cp_r(ansible_inventory, tmp_inventory_path)
850
- end
851
- end
852
-
853
- # localhost ansible_connection=local
854
- # [example_servers]
855
- # localhost
856
- def prepare_hosts
857
- return if ansible_inventory
858
- info('Preparing hosts file')
859
-
860
- if config[:hosts].nil?
861
- fail 'No hosts have been set. Please specify one in .kitchen.yml'
862
- else
863
- debug("Using host from #{hosts}")
864
- File.open(File.join(sandbox_path, 'hosts'), 'wb') do |file|
865
- file.write("localhost ansible_connection=local\n[#{hosts}]\nlocalhost\n")
866
- end
867
- end
868
- end
869
-
870
- def prepare_playbook
871
- info('Preparing playbook')
872
- debug("Copying playbook from #{playbook} to #{tmp_playbook_path}")
873
- FileUtils.cp_r(playbook, tmp_playbook_path)
874
- end
875
-
876
- def prepare_group_vars
877
- info('Preparing group_vars')
878
- tmp_group_vars_dir = File.join(sandbox_path, 'group_vars')
879
- FileUtils.mkdir_p(tmp_group_vars_dir)
880
-
881
- unless File.directory?(group_vars)
882
- info('nothing to do for group_vars')
883
- return
884
- end
885
-
886
- debug("Using group_vars from #{group_vars}")
887
- FileUtils.cp_r(Dir.glob("#{group_vars}/*"), tmp_group_vars_dir)
888
- end
889
-
890
- def prepare_additional_copy_path
891
- info('Preparing additional_copy_path')
892
- additional_files.each do |file|
893
- destination = File.join(sandbox_path, File.basename(file))
894
- if File.directory?(file)
895
- info("Copy dir: #{file} #{destination}")
896
- FileUtils.cp_r(file, destination)
897
- else
898
- info("Copy file: #{file} #{destination}")
899
- FileUtils.cp file, destination
900
- end
901
- end
902
- end
903
-
904
- def additional_files
905
- additional_files = []
906
- if additional_copy
907
- additional_files = additional_copy.is_a?(Array) ? additional_copy : [additional_copy]
908
- end
909
- additional_files.map(&:to_s)
910
- end
911
-
912
- def prepare_host_vars
913
- info('Preparing host_vars')
914
- FileUtils.mkdir_p(tmp_host_vars_dir)
915
-
916
- unless File.directory?(host_vars)
917
- info 'nothing to do for host_vars'
918
- return
919
- end
920
-
921
- debug("Using host_vars from #{host_vars}")
922
- FileUtils.cp_r(Dir.glob("#{host_vars}/*"), tmp_host_vars_dir)
923
- end
924
-
925
- def prepare_modules
926
- info('Preparing modules')
927
-
928
- FileUtils.mkdir_p(tmp_modules_dir)
929
-
930
- if modules && File.directory?(modules)
931
- debug("Using modules from #{modules}")
932
- FileUtils.cp_r(Dir.glob("#{modules}/*"), tmp_modules_dir, remove_destination: true)
933
- else
934
- info 'nothing to do for modules'
935
- end
936
- end
937
-
938
- def prepare_spec
939
- info('Preparing spec')
940
-
941
- FileUtils.mkdir_p(tmp_spec_dir)
942
-
943
- if spec && File.directory?(spec)
944
- debug("Using spec from #{spec}")
945
- FileUtils.cp_r(Dir.glob("#{spec}/*"), tmp_spec_dir, remove_destination: true)
946
- else
947
- info 'nothing to do for spec'
948
- end
949
- end
950
-
951
- def prepare_library_plugins
952
- info('Preparing library plugins')
953
- FileUtils.mkdir_p(tmp_library_plugins_dir)
954
-
955
- if library_plugins && File.directory?(library_plugins)
956
- debug("Using library plugins from #{library_plugins}")
957
- FileUtils.cp_r(Dir.glob("#{library_plugins}/{*,!*.pyc}"), tmp_library_plugins_dir, remove_destination: true)
958
- else
959
- info 'nothing to do for library plugins'
960
- end
961
- end
962
-
963
- def prepare_callback_plugins
964
- info('Preparing callback plugins')
965
- FileUtils.mkdir_p(tmp_callback_plugins_dir)
966
-
967
- if callback_plugins && File.directory?(callback_plugins)
968
- debug("Using callback plugins from #{callback_plugins}")
969
- FileUtils.cp_r(Dir.glob("#{callback_plugins}/{*,!*.pyc}"), tmp_callback_plugins_dir, remove_destination: true)
970
- else
971
- info 'nothing to do for callback plugins'
972
- end
973
- end
974
-
975
- def prepare_filter_plugins
976
- info('Preparing filter_plugins')
977
- FileUtils.mkdir_p(tmp_filter_plugins_dir)
978
-
979
- if filter_plugins && File.directory?(filter_plugins)
980
- debug("Using filter_plugins from #{filter_plugins}")
981
- FileUtils.cp_r(Dir.glob("#{filter_plugins}/*.py"), tmp_filter_plugins_dir, remove_destination: true)
982
- else
983
- info 'nothing to do for filter_plugins'
984
- end
985
- end
986
-
987
- def prepare_lookup_plugins
988
- info('Preparing lookup_plugins')
989
- FileUtils.mkdir_p(tmp_lookup_plugins_dir)
990
-
991
- if lookup_plugins && File.directory?(lookup_plugins)
992
- debug("Using lookup_plugins from #{lookup_plugins}")
993
- FileUtils.cp_r(Dir.glob("#{lookup_plugins}/*.py"), tmp_lookup_plugins_dir, remove_destination: true)
994
- else
995
- info 'nothing to do for lookup_plugins'
996
- end
997
- end
998
-
999
- def prepare_ansible_vault_password_file
1000
- return unless ansible_vault_password_file
1001
-
1002
- info('Preparing ansible vault password')
1003
- debug("Copying ansible vault password file from #{ansible_vault_password_file} to #{tmp_ansible_vault_password_file_path}")
1004
-
1005
- FileUtils.cp(ansible_vault_password_file, tmp_ansible_vault_password_file_path)
1006
- end
1007
-
1008
- def prepare_kerberos_conf_file
1009
- return unless kerberos_conf_file
1010
-
1011
- info('Preparing kerberos configuration file')
1012
- debug("Copying kerberos configuration file from #{kerberos_conf_file} to #{tmp_kerberos_conf_file_path}")
1013
-
1014
- FileUtils.cp(kerberos_conf_file, tmp_kerberos_conf_file_path)
1015
- end
1016
-
1017
- def resolve_with_librarian
1018
- Kitchen.mutex.synchronize do
1019
- Ansible::Librarian.new(ansiblefile, tmp_roles_dir, logger).resolve
1020
- end
1021
- end
1022
- end
1023
- end
1024
- 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 'find'
25
+ require 'kitchen/provisioner/base'
26
+ require 'kitchen/provisioner/ansible/config'
27
+ require 'kitchen/provisioner/ansible/os'
28
+ require 'kitchen/provisioner/ansible/librarian'
29
+
30
+ module Kitchen
31
+ class Busser
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
+
48
+ @os = Kitchen::Provisioner::Ansible::Os.make(ansible_platform, config)
49
+ end
50
+
51
+ def finalize_config!(instance)
52
+ config.instance = instance
53
+ super(instance)
54
+ end
55
+
56
+ def verbosity_level(level = 1)
57
+ level = level.to_sym if level.is_a? String
58
+ log_levels = { info: 1, warn: 2, debug: 3, trace: 4 }
59
+ if level.is_a?(Symbol) && log_levels.include?(level)
60
+ # puts "Log Level is: #{log_levels[level]}"
61
+ log_levels[level]
62
+ elsif level.is_a?(Integer) && level > 0
63
+ # puts "Log Level is: #{level}"
64
+ level
65
+ else
66
+ fail 'Invalid ansible_verbosity setting. Valid values are: 1, 2, 3, 4 OR :info, :warn, :debug, :trace'
67
+ end
68
+ end
69
+
70
+ def install_command
71
+ if config[:require_ansible_omnibus]
72
+ cmd = install_omnibus_command
73
+ elsif config[:require_ansible_source]
74
+ info('Installing ansible from source')
75
+ cmd = install_ansible_from_source_command
76
+ elsif config[:require_pip]
77
+ info('Installing ansible through pip')
78
+ cmd = install_ansible_from_pip_command
79
+ elsif config[:require_ansible_repo]
80
+ if !@os.nil?
81
+ info("Installing ansible on #{@os.name}")
82
+ cmd = @os.install_command
83
+ else
84
+ info('Installing ansible, will try to determine platform os')
85
+ cmd = <<-INSTALL
86
+
87
+ if [ ! $(which ansible) ]; then
88
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
89
+ if [ -z `grep -q 'Amazon Linux' /etc/system-release` ]; then
90
+ #{Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).install_command}
91
+ else
92
+ #{Kitchen::Provisioner::Ansible::Os::Amazon.new('amazon', config).install_command}
93
+ fi
94
+ elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
95
+ #{Kitchen::Provisioner::Ansible::Os::Suse.new('suse', config).install_command}
96
+ else
97
+ #{Kitchen::Provisioner::Ansible::Os::Debian.new('debian', config).install_command}
98
+ fi
99
+ fi
100
+ INSTALL
101
+ end
102
+ else
103
+ return
104
+ end
105
+ result = cmd + install_windows_support + install_busser_prereqs
106
+ debug("Going to install ansible with: #{result}")
107
+ result
108
+ end
109
+
110
+ def install_windows_support
111
+ install = ''
112
+ if require_windows_support
113
+ install << <<-INSTALL
114
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
115
+ #{sudo_env('yum')} -y install python-devel krb5-devel krb5-libs krb5-workstation gcc
116
+ else
117
+ if [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
118
+ #{sudo_env('zypper')} ar #{python_sles_repo}
119
+ #{sudo_env('zypper')} --non-interactive install python python-devel krb5-client pam_krb5
120
+ else
121
+ #{sudo_env('apt-get')} install python-dev libkrb5-dev build-essential
122
+ fi
123
+ fi
124
+ #{export_http_proxy}
125
+ #{sudo_env('easy_install')} pip
126
+ #{sudo_env('pip')} install pywinrm kerberos
127
+ INSTALL
128
+ end
129
+ install
130
+ end
131
+
132
+ def install_busser_prereqs
133
+ install = ''
134
+ install << <<-INSTALL
135
+ #{Util.shell_helpers}
136
+ # Fix for https://github.com/test-kitchen/busser/issues/12
137
+ if [ -h /usr/bin/ruby ]; then
138
+ L=$(readlink -f /usr/bin/ruby)
139
+ #{sudo_env('rm')} /usr/bin/ruby
140
+ #{sudo_env('ln')} -s $L /usr/bin/ruby
141
+ fi
142
+ INSTALL
143
+
144
+ if require_ruby_for_busser
145
+ install << <<-INSTALL
146
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
147
+ if [ -z `grep -q 'Amazon Linux' /etc/system-release` ]; then
148
+ rhelversion6=$(cat /etc/redhat-release | grep 'release 6')
149
+ rhelversion7=$(cat /etc/redhat-release | grep 'release 7')
150
+ # For CentOS6/CentOS7/RHEL6/RHEL7 install ruby from SCL
151
+ if [ -n "$rhelversion6" ] || [ -n "$rhelversion7" ]; then
152
+ if [ ! -d "/opt/rh/ruby200" ]; then
153
+ echo "-----> Installing ruby200 SCL in CentOS6/CentOS7/RHEL6/RHEL7 to install busser to run tests"
154
+ #{sudo_env('yum')} install -y centos-release-scl
155
+ #{sudo_env('yum')} install -y ruby200
156
+ #{sudo_env('yum')} install -y ruby200-ruby-devel
157
+ echo "-----> Enabling ruby200"
158
+ source /opt/rh/ruby200/enable
159
+ echo "/opt/rh/ruby200/root/usr/lib64" | sudo tee -a /etc/ld.so.conf
160
+ #{sudo_env('ldconfig')}
161
+ #{sudo_env('ln')} -sf /opt/rh/ruby200/root/usr/bin/ruby /usr/bin/ruby
162
+ #{sudo_env('ln')} -sf /opt/rh/ruby200/root/usr/bin/gem /usr/bin/gem
163
+ fi
164
+ else
165
+ if [ ! $(which ruby) ]; then
166
+ #{update_packages_redhat_cmd}
167
+ #{sudo_env('yum')} -y install ruby ruby-devel
168
+ fi
169
+ fi
170
+ else
171
+ #{update_packages_redhat_cmd}
172
+ #{sudo_env('yum')} -y install ruby ruby-devel gcc
173
+ fi
174
+ elif [ -f /etc/SuSE-release ] || [ -f /etc/SUSE-brand ]; then
175
+ #{update_packages_suse_cmd}
176
+ #{sudo_env('zypper')} --non-interactive install ruby ruby-devel ca-certificates ca-certificates-cacert ca-certificates-mozilla
177
+ #{sudo_env('gem')} sources --add https://rubygems.org/
178
+ else
179
+ if [ ! $(which ruby) ]; then
180
+ #{update_packages_debian_cmd}
181
+ # default package selection for Debian/Ubuntu machines
182
+ PACKAGES="ruby1.9.1 ruby1.9.1-dev"
183
+ if [ "$(lsb_release -si)" = "Debian" ]; then
184
+ debvers=$(sed 's/\\..*//' /etc/debian_version)
185
+ if [ $debvers -ge 8 ]; then
186
+ # this is jessie or better, where ruby1.9.1 is
187
+ # no longer in the repositories
188
+ PACKAGES="ruby ruby-dev ruby2.1 ruby2.1-dev"
189
+ fi
190
+ fi
191
+ if [ "$(lsb_release -si)" = "Ubuntu" ]; then
192
+ ubuntuvers=$(lsb_release -sr | tr -d .)
193
+ if [ $ubuntuvers -ge 1410 ]; then
194
+ # Default ruby is 2.x in utopic and newer
195
+ PACKAGES="ruby ruby-dev"
196
+ fi
197
+ fi
198
+ #{sudo_env('apt-get')} -y install $PACKAGES
199
+ if [ $debvers -eq 6 ]; then
200
+ # in squeeze we need to update alternatives
201
+ # for enable ruby1.9.1
202
+ ALTERNATIVES_STRING="--install /usr/bin/ruby ruby /usr/bin/ruby1.9.1 10 --slave /usr/share/man/man1/ruby.1.gz ruby.1.gz /usr/share/man/man1/ruby1.9.1.1.gz --slave /usr/bin/erb erb /usr/bin/erb1.9.1 --slave /usr/bin/gem gem /usr/bin/gem1.9.1 --slave /usr/bin/irb irb /usr/bin/irb1.9.1 --slave /usr/bin/rake rake /usr/bin/rake1.9.1 --slave /usr/bin/rdoc rdoc /usr/bin/rdoc1.9.1 --slave /usr/bin/testrb testrb /usr/bin/testrb1.9.1 --slave /usr/share/man/man1/erb.1.gz erb.1.gz /usr/share/man/man1/erb1.9.1.1.gz --slave /usr/share/man/man1/gem.1.gz gem.1.gz /usr/share/man/man1/gem1.9.1.1.gz --slave /usr/share/man/man1/irb.1.gz irb.1.gz /usr/share/man/man1/irb1.9.1.1.gz --slave /usr/share/man/man1/rake.1.gz rake.1.gz /usr/share/man/man1/rake1.9.1.1.gz --slave /usr/share/man/man1/rdoc.1.gz rdoc.1.gz /usr/share/man/man1/rdoc1.9.1.1.gz --slave /usr/share/man/man1/testrb.1.gz testrb.1.gz /usr/share/man/man1/testrb1.9.1.1.gz"
203
+ #{sudo_env('update-alternatives')} $ALTERNATIVES_STRING
204
+ # need to update gem tool because gem 1.3.7 from ruby 1.9.1 is broken
205
+ #{sudo_env('gem')} install rubygems-update
206
+ #{sudo_env('/var/lib/gems/1.9.1/bin/update_rubygems')}
207
+ # clear local gem cache
208
+ #{sudo_env('rm')} -r /home/vagrant/.gem
209
+ fi
210
+ fi
211
+ fi
212
+ INSTALL
213
+
214
+ elsif require_chef_for_busser && chef_url
215
+ install << <<-INSTALL
216
+ # install chef omnibus so that busser works as this is needed to run tests :(
217
+ if [ ! -d "/opt/chef" ]
218
+ then
219
+ echo "-----> Installing Chef Omnibus to install busser to run tests"
220
+ #{export_http_proxy}
221
+ do_download #{chef_url} /tmp/install.sh
222
+ #{sudo_env('sh')} /tmp/install.sh
223
+ fi
224
+ INSTALL
225
+ end
226
+
227
+ install
228
+ end
229
+
230
+ def init_command
231
+ dirs = %w(modules roles group_vars host_vars)
232
+ .map { |dir| File.join(config[:root_path], dir) }.join(' ')
233
+ cmd = "#{sudo_env('rm')} -rf #{dirs};"
234
+ cmd += " mkdir -p #{config[:root_path]}"
235
+ debug(cmd)
236
+ cmd
237
+ end
238
+
239
+ def create_sandbox
240
+ super
241
+ debug("Creating local sandbox in #{sandbox_path}")
242
+
243
+ yield if block_given?
244
+
245
+ prepare_playbook
246
+ prepare_inventory
247
+ prepare_modules
248
+ prepare_roles
249
+ prepare_ansible_cfg
250
+ prepare_group_vars
251
+ prepare_additional_copy_path
252
+ prepare_host_vars
253
+ prepare_hosts
254
+ prepare_spec
255
+ prepare_library_plugins
256
+ prepare_callback_plugins
257
+ prepare_filter_plugins
258
+ prepare_lookup_plugins
259
+ prepare_ansible_vault_password_file
260
+ prepare_kerberos_conf_file
261
+ info('Finished Preparing files for transfer')
262
+ end
263
+
264
+ def cleanup_sandbox
265
+ return if sandbox_path.nil?
266
+ debug("Cleaning up local sandbox in #{sandbox_path}")
267
+ FileUtils.rmtree(sandbox_path)
268
+ end
269
+
270
+ def prepare_command
271
+ commands = []
272
+
273
+ # Prevent failure when ansible package installation doesn't contain /etc/ansible
274
+ commands << [
275
+ sudo_env("bash -c '[ -d /etc/ansible ] || mkdir /etc/ansible'")
276
+ ]
277
+
278
+ commands << [
279
+ sudo_env('cp'), File.join(config[:root_path], 'ansible.cfg'), '/etc/ansible'
280
+ ].join(' ')
281
+
282
+ commands << [
283
+ sudo_env('cp -r'), File.join(config[:root_path], 'group_vars'), '/etc/ansible/.'
284
+ ].join(' ')
285
+
286
+ commands << [
287
+ sudo_env('cp -r'), File.join(config[:root_path], 'host_vars'), '/etc/ansible/.'
288
+ ].join(' ')
289
+
290
+ if config[:ssh_known_hosts]
291
+ config[:ssh_known_hosts].each do |host|
292
+ info("Add #{host} to ~/.ssh/known_hosts")
293
+ commands << "ssh-keyscan #{host} > ~/.ssh/known_hosts 2> /dev/null"
294
+ end
295
+ end
296
+
297
+ if ansible_inventory
298
+ if File.directory?(ansible_inventory)
299
+ Dir.foreach(ansible_inventory) do |f|
300
+ next if f == "." or f == ".."
301
+ contents = File.open("#{ansible_inventory}/#{f}", 'rb') { |g| g.read }
302
+ if contents.start_with?('#!')
303
+ commands << [
304
+ sudo_env('chmod +x'), File.join("#{config[:root_path]}/#{File.basename(ansible_inventory)}", File.basename(f))
305
+ ].join(' ')
306
+ end
307
+ end
308
+ else
309
+ contents = File.open(ansible_inventory, 'rb') { |f| f.read }
310
+ if contents.start_with?('#!')
311
+ commands << [
312
+ sudo_env('chmod +x'), File.join(config[:root_path], File.basename(ansible_inventory))
313
+ ].join(' ')
314
+ end
315
+ end
316
+ end
317
+
318
+ if galaxy_requirements
319
+ if config[:require_ansible_source]
320
+ commands << setup_ansible_env_from_source
321
+ end
322
+ commands << ansible_galaxy_command
323
+ end
324
+
325
+ if kerberos_conf_file
326
+ commands << [
327
+ sudo_env('cp -f'), File.join(config[:root_path], 'krb5.conf'), '/etc'
328
+ ].join(' ')
329
+ end
330
+
331
+ command = commands.join(' && ')
332
+ debug(command)
333
+ command
334
+ end
335
+
336
+ def run_command
337
+ if !config[:ansible_playbook_command].nil?
338
+ return config[:ansible_playbook_command]
339
+ else
340
+
341
+ if config[:require_ansible_source] && !config[:ansible_binary_path]
342
+ # this is an ugly hack to get around the fact that extra vars uses ' and "
343
+ cmd = ansible_command("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 ansible-playbook")
344
+ elsif config[:ansible_binary_path]
345
+ cmd = ansible_command("#{config[:ansible_binary_path]}/ansible-playbook")
346
+ else
347
+ cmd = ansible_command('ansible-playbook')
348
+ end
349
+
350
+ cmd = "HTTPS_PROXY=#{https_proxy} #{cmd}" if https_proxy
351
+ cmd = "HTTP_PROXY=#{http_proxy} #{cmd}" if http_proxy
352
+ cmd = "NO_PROXY=#{no_proxy} #{cmd}" if no_proxy
353
+ cmd = "ANSIBLE_ROLES_PATH=#{ansible_roles_path} #{cmd}" if ansible_roles_path
354
+ cmd = "ANSIBLE_HOST_KEY_CHECKING=false #{cmd}" if !ansible_host_key_checking
355
+
356
+ cmd = "#{cd_ansible} #{cmd}" if !config[:ansible_sudo].nil? && !config[:ansible_sudo]
357
+ cmd = "#{copy_private_key_cmd} #{cmd}" if config[:private_key]
358
+
359
+ result = [
360
+ cmd,
361
+ ansible_inventory_flag,
362
+ ansible_limit_flag,
363
+ ansible_connection_flag,
364
+ "-M #{File.join(config[:root_path], 'modules')}",
365
+ ansible_verbose_flag,
366
+ ansible_check_flag,
367
+ ansible_diff_flag,
368
+ ansible_vault_flag,
369
+ private_key,
370
+ extra_vars,
371
+ tags,
372
+ ansible_extra_flags,
373
+ "#{File.join(config[:root_path], File.basename(config[:playbook]))}"
374
+ ].join(' ')
375
+ debug("Going to invoke ansible-playbook with: #{result}")
376
+ if config[:idempotency_test]
377
+ result = "#{result} && (echo 'Going to invoke ansible-playbook second time:'; #{result} | tee /tmp/idempotency_test.txt; grep -q 'changed=0.*failed=0' /tmp/idempotency_test.txt && (echo 'Idempotence test: PASS' && exit 0) || (echo 'Idempotence test: FAIL' && exit 1))"
378
+ debug("Full cmd with idempotency test: #{result}")
379
+ end
380
+
381
+ result
382
+ end
383
+ end
384
+
385
+ def ansible_command(script)
386
+ if config[:ansible_sudo].nil? || config[:ansible_sudo] == true
387
+ s = https_proxy ? "https_proxy=#{https_proxy}" : nil
388
+ p = http_proxy ? "http_proxy=#{http_proxy}" : nil
389
+ n = no_proxy ? "no_proxy=#{no_proxy}" : nil
390
+ p || s || n ? " #{p} #{s} #{n} #{config[:sudo_command]} -s #{cd_ansible} #{script}" : "#{config[:sudo_command]} -s #{cd_ansible} #{script}"
391
+ else
392
+ return script
393
+ end
394
+ end
395
+
396
+ def ansible_galaxy_command
397
+ cmd = [
398
+ 'ansible-galaxy', 'install', '--force',
399
+ '-p', File.join(config[:root_path], 'roles'),
400
+ '-r', File.join(config[:root_path], galaxy_requirements)
401
+ ].join(' ')
402
+ cmd = "https_proxy=#{https_proxy} #{cmd}" if https_proxy
403
+ cmd = "http_proxy=#{http_proxy} #{cmd}" if http_proxy
404
+ cmd = "no_proxy=#{no_proxy} #{cmd}" if no_proxy
405
+ cmd
406
+ end
407
+
408
+ def cd_ansible
409
+ # this is not working so just return nil for now
410
+ # File.exist?('ansible.cfg') ? "cd #{config[:root_path]};" : nil
411
+ nil
412
+ end
413
+
414
+ protected
415
+
416
+ def load_needed_dependencies!
417
+ return unless File.exist?(ansiblefile)
418
+
419
+ debug("Ansiblefile found at #{ansiblefile}, loading Librarian-Ansible")
420
+ Ansible::Librarian.load!(logger)
421
+ end
422
+
423
+ def install_ansible_from_source_command
424
+ <<-INSTALL
425
+ if [ ! -d #{config[:root_path]}/ansible ]; then
426
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
427
+ #{Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).install_epel_repo}
428
+ #{update_packages_redhat_cmd}
429
+ #{sudo_env('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev libffi-devel libssl-devel
430
+ else
431
+ if [ -f /etc/SUSE-brand ] || [ -f /etc/SuSE-release ]; then
432
+ #{sudo_env('zypper')} ar #{python_sles_repo}
433
+ #{update_packages_suse_cmd}
434
+ #{sudo_env('zypper')} --non-interactive install python python-devel git python-setuptools python-pip python-six libyaml-devel libffi-devel libopenssl-devel
435
+ else
436
+ #{update_packages_debian_cmd}
437
+ #{sudo_env('apt-get')} -y install git python python-setuptools build-essential python-dev libffi-dev libssl-dev
438
+ fi
439
+ fi
440
+
441
+ #{export_http_proxy}
442
+ git clone git://github.com/ansible/ansible.git --recursive #{config[:root_path]}/ansible #{install_source_rev}
443
+ #{sudo_env('easy_install')} pip
444
+ #{sudo_env('pip')} install -U setuptools
445
+ #{sudo_env('pip')} install six paramiko PyYAML Jinja2 httplib2
446
+ fi
447
+ INSTALL
448
+ end
449
+
450
+ def install_ansible_from_pip_command
451
+ ansible_version = ''
452
+ ansible_version = "==#{config[:ansible_version]}" unless config[:ansible_version] == 'latest'
453
+
454
+ <<-INSTALL
455
+ if [ ! -d #{config[:root_path]}/ansible ]; then
456
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
457
+ #{Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).install_epel_repo}
458
+ #{update_packages_redhat_cmd}
459
+ #{sudo_env('yum')} -y install libselinux-python python2-devel git python-setuptools python-setuptools-dev libffi-devel libssl-devel
460
+ else
461
+ if [ -f /etc/SUSE-brand ] || [ -f /etc/SuSE-release ]; then
462
+ #{sudo_env('zypper')} ar #{python_sles_repo}
463
+ #{update_packages_suse_cmd}
464
+ #{sudo_env('zypper')} --non-interactive install python python-devel git python-setuptools python-pip python-six libyaml-devel libffi-devel libopenssl-devel
465
+ else
466
+ #{update_packages_debian_cmd}
467
+ #{sudo_env('apt-get')} -y install git python python-setuptools build-essential python-dev libffi-dev libssl-dev
468
+ fi
469
+ fi
470
+
471
+ #{export_http_proxy}
472
+ #{sudo_env('easy_install')} pip
473
+ #{sudo_env('pip')} install -U setuptools
474
+ #{sudo_env('pip')} install ansible#{ansible_version}
475
+ fi
476
+ INSTALL
477
+ end
478
+
479
+ def install_omnibus_command
480
+ info('Installing ansible using ansible omnibus')
481
+
482
+ version = ''
483
+ version = "-v #{config[:ansible_version]}" unless config[:ansible_version].nil?
484
+
485
+ <<-INSTALL
486
+ #{Util.shell_helpers}
487
+
488
+ if [ ! -d "#{config[:ansible_omnibus_remote_path]}" ]; then
489
+ echo "-----> Installing Ansible Omnibus"
490
+ #{export_http_proxy}
491
+ do_download #{config[:ansible_omnibus_url]} /tmp/ansible_install.sh
492
+ #{sudo_env('sh')} /tmp/ansible_install.sh #{version}
493
+ fi
494
+ INSTALL
495
+ end
496
+
497
+ def setup_ansible_env_from_source
498
+ "cd #{config[:root_path]}/ansible && source hacking/env-setup && cd ../"
499
+ end
500
+
501
+ def tmp_modules_dir
502
+ File.join(sandbox_path, 'modules')
503
+ end
504
+
505
+ def tmp_playbook_path
506
+ File.join(sandbox_path, File.basename(playbook))
507
+ end
508
+
509
+ def tmp_host_vars_dir
510
+ File.join(sandbox_path, 'host_vars')
511
+ end
512
+
513
+ def tmp_roles_dir
514
+ File.join(sandbox_path, 'roles')
515
+ end
516
+
517
+ def tmp_spec_dir
518
+ File.join(sandbox_path, 'spec')
519
+ end
520
+
521
+ def tmp_library_plugins_dir
522
+ File.join(sandbox_path, 'library')
523
+ end
524
+
525
+ def tmp_callback_plugins_dir
526
+ File.join(sandbox_path, 'callback_plugins')
527
+ end
528
+
529
+ def tmp_filter_plugins_dir
530
+ File.join(sandbox_path, 'filter_plugins')
531
+ end
532
+
533
+ def tmp_lookup_plugins_dir
534
+ File.join(sandbox_path, 'lookup_plugins')
535
+ end
536
+
537
+ def tmp_ansible_vault_password_file_path
538
+ File.join(sandbox_path, File.basename(ansible_vault_password_file).reverse.chomp('.').reverse)
539
+ end
540
+
541
+ def tmp_kerberos_conf_file_path
542
+ File.join(sandbox_path, 'krb5.conf')
543
+ end
544
+
545
+ def tmp_inventory_path
546
+ File.join(sandbox_path, File.basename(ansible_inventory))
547
+ end
548
+
549
+ def ansiblefile
550
+ config[:ansiblefile_path] || ''
551
+ end
552
+
553
+ def galaxy_requirements
554
+ config[:requirements_path] || nil
555
+ end
556
+
557
+ def playbook
558
+ config[:playbook]
559
+ end
560
+
561
+ def hosts
562
+ config[:hosts]
563
+ end
564
+
565
+ def roles
566
+ config[:roles_path]
567
+ end
568
+
569
+ def role_name
570
+ if config[:role_name]
571
+ config[:role_name]
572
+ elsif File.basename(roles) == 'roles'
573
+ ''
574
+ else
575
+ File.basename(roles)
576
+ end
577
+ end
578
+
579
+ def modules
580
+ config[:modules_path]
581
+ end
582
+
583
+ def spec
584
+ 'spec'
585
+ end
586
+
587
+ def group_vars
588
+ config[:group_vars_path].to_s
589
+ end
590
+
591
+ def additional_copy
592
+ config[:additional_copy_path]
593
+ end
594
+
595
+ def host_vars
596
+ config[:host_vars_path].to_s
597
+ end
598
+
599
+ def library_plugins
600
+ config[:library_plugins_path].to_s
601
+ end
602
+
603
+ def callback_plugins
604
+ config[:callback_plugins_path].to_s
605
+ end
606
+
607
+ def filter_plugins
608
+ config[:filter_plugins_path].to_s
609
+ end
610
+
611
+ def lookup_plugins
612
+ config[:lookup_plugins_path].to_s
613
+ end
614
+
615
+ def ansible_vault_password_file
616
+ config[:ansible_vault_password_file]
617
+ end
618
+
619
+ def ansible_inventory
620
+ return nil if config[:ansible_inventory] == 'none'
621
+ config[:ansible_inventory] = config[:ansible_inventory_file] if config[:ansible_inventory].nil?
622
+ info('ansible_inventory_file parameter deprecated use ansible_inventory') if config[:ansible_inventory_file]
623
+ config[:ansible_inventory]
624
+ end
625
+
626
+ def ansible_debian_version
627
+ if @config[:ansible_version] == 'latest' || @config[:ansible_version] == nil
628
+ ''
629
+ else
630
+ "=#{@config[:ansible_version]}"
631
+ end
632
+ end
633
+
634
+ def ansible_connection_flag
635
+ "-c #{config[:ansible_connection]}" if config[:ansible_connection] != 'none'
636
+ end
637
+
638
+ def ansible_verbose_flag
639
+ config[:ansible_verbose] ? '-' << ('v' * verbosity_level(config[:ansible_verbosity])) : nil
640
+ end
641
+
642
+ def ansible_check_flag
643
+ config[:ansible_check] ? '--check' : nil
644
+ end
645
+
646
+ def ansible_diff_flag
647
+ config[:ansible_diff] ? '--diff' : nil
648
+ end
649
+
650
+ def ansible_vault_flag
651
+ debug(config[:ansible_vault_password_file])
652
+ config[:ansible_vault_password_file] ? "--vault-password-file=#{File.join(config[:root_path], File.basename(config[:ansible_vault_password_file]).reverse.chomp('.').reverse)}" : nil
653
+ end
654
+
655
+ def ansible_inventory_flag
656
+ return nil if config[:ansible_inventory] == 'none'
657
+ ansible_inventory ? "-i #{File.join(config[:root_path], File.basename(ansible_inventory))}" : "-i #{File.join(config[:root_path], 'hosts')}"
658
+ end
659
+
660
+ def ansible_limit_flag
661
+ config[:ansible_limit] ? "-l #{config[:ansible_limit]}" : ""
662
+ end
663
+
664
+ def ansible_extra_flags
665
+ config[:ansible_extra_flags] || ''
666
+ end
667
+
668
+ def ansible_platform
669
+ config[:ansible_platform].to_s.downcase
670
+ end
671
+
672
+ def ansible_host_key_checking
673
+ config[:ansible_host_key_checking]
674
+ end
675
+
676
+ def private_key
677
+ if config[:private_key]
678
+ "--private-key #{private_key_file}"
679
+ end
680
+ end
681
+
682
+ def copy_private_key_cmd
683
+ if !config[:private_key].start_with?('/') && !config[:private_key].start_with?('~')
684
+ ssh_private_key = File.join('~/.ssh', File.basename(config[:private_key]))
685
+ tmp_private_key = File.join(config[:root_path], config[:private_key])
686
+ "rm -rf #{ssh_private_key}; cp #{tmp_private_key} #{ssh_private_key}; chmod 400 #{ssh_private_key};"
687
+ end
688
+ end
689
+
690
+ def private_key_file
691
+ if config[:private_key].start_with?('/') || config[:private_key].start_with?('~')
692
+ "#{config[:private_key]}"
693
+ elsif config[:private_key]
694
+ "#{File.join('~/.ssh', File.basename(config[:private_key]))}"
695
+ end
696
+ end
697
+
698
+ def update_packages_debian_cmd
699
+ Kitchen::Provisioner::Ansible::Os::Debian.new('debian', config).update_packages_command
700
+ end
701
+
702
+ def update_packages_suse_cmd
703
+ Kitchen::Provisioner::Ansible::Os::Suse.new('suse', config).update_packages_command
704
+ end
705
+
706
+ def update_packages_redhat_cmd
707
+ Kitchen::Provisioner::Ansible::Os::Redhat.new('redhat', config).update_packages_command
708
+ end
709
+
710
+ def python_sles_repo
711
+ config[:python_sles_repo]
712
+ end
713
+
714
+ def extra_vars
715
+ bash_vars = config[:extra_vars]
716
+ if config.key?(:attributes) && config[:attributes].key?(:extra_vars) && config[:attributes][:extra_vars].is_a?(Hash)
717
+ bash_vars = config[:attributes][:extra_vars]
718
+ end
719
+
720
+ return nil if bash_vars.none?
721
+ bash_vars = JSON.dump(bash_vars)
722
+ bash_vars = "-e '#{bash_vars}'"
723
+ debug(bash_vars)
724
+ bash_vars
725
+ end
726
+
727
+ def tags
728
+ bash_tags = config.key?(:attributes) && config[:attributes].key?(:tags) && config[:attributes][:tags].is_a?(Array) ? config[:attributes][:tags] : config[:tags]
729
+ return nil if bash_tags.empty?
730
+
731
+ bash_tags = bash_tags.join(',')
732
+ bash_tags = "-t '#{bash_tags}'"
733
+ debug(bash_tags)
734
+ bash_tags
735
+ end
736
+
737
+ def chef_url
738
+ config[:chef_bootstrap_url]
739
+ end
740
+
741
+ def require_ruby_for_busser
742
+ config[:require_ruby_for_busser]
743
+ end
744
+
745
+ def require_chef_for_busser
746
+ config[:require_chef_for_busser]
747
+ end
748
+
749
+ def require_windows_support
750
+ config[:require_windows_support]
751
+ end
752
+
753
+ def kerberos_conf_file
754
+ config[:kerberos_conf_file]
755
+ end
756
+
757
+ def install_source_rev
758
+ config[:ansible_source_rev] ? "--branch #{config[:ansible_source_rev]}" : nil
759
+ end
760
+
761
+ def http_proxy
762
+ config[:http_proxy]
763
+ end
764
+
765
+ def https_proxy
766
+ config[:https_proxy]
767
+ end
768
+
769
+ def no_proxy
770
+ config[:no_proxy]
771
+ end
772
+
773
+ def sudo_env(pm,home=false)
774
+ s = https_proxy ? "https_proxy=#{https_proxy}" : nil
775
+ p = http_proxy ? "http_proxy=#{http_proxy}" : nil
776
+ n = no_proxy ? "no_proxy=#{no_proxy}" : nil
777
+ if home
778
+ p || s || n ? "#{sudo_home('env')} #{p} #{s} #{n} #{pm}" : "#{sudo_home(pm)}"
779
+ else
780
+ p || s || n ? "#{sudo('env')} #{p} #{s} #{n} #{pm}" : "#{sudo(pm)}"
781
+ end
782
+ end
783
+
784
+ def export_http_proxy
785
+ cmd = ''
786
+ cmd = " HTTP_PROXY=#{http_proxy}" if http_proxy
787
+ cmd = "#{cmd} HTTPS_PROXY=#{https_proxy}" if https_proxy
788
+ cmd = "#{cmd} NO_PROXY=#{no_proxy}" if no_proxy
789
+ cmd = "export #{cmd}" if cmd != ''
790
+ cmd
791
+ end
792
+
793
+ def ansible_roles_path
794
+ roles_paths = []
795
+ roles_paths << File.join(config[:root_path], 'roles') unless config[:roles_path].nil?
796
+ additional_files.each do |additional_file|
797
+ roles_paths << File.join(config[:root_path], File.basename(additional_file))
798
+ end
799
+ if roles_paths.empty?
800
+ info('No roles have been set.')
801
+ nil
802
+ else
803
+ debug("Setting roles_path inside VM to #{ roles_paths.join(':') }")
804
+ roles_paths.join(':')
805
+ end
806
+ end
807
+
808
+ def prepare_roles
809
+ info('Preparing roles')
810
+ debug("Using roles from #{roles}")
811
+
812
+ resolve_with_librarian if File.exist?(ansiblefile)
813
+
814
+ if galaxy_requirements
815
+ dest = File.join(sandbox_path, galaxy_requirements)
816
+ FileUtils.mkdir_p(File.dirname(dest))
817
+ FileUtils.cp(galaxy_requirements, dest)
818
+ end
819
+
820
+ FileUtils.mkdir_p(File.join(tmp_roles_dir, role_name))
821
+ Find.find(roles) do |source|
822
+ # Detect whether we are running tests on a role
823
+ # If so, make sure to copy into VM so dir structure is like: /tmp/kitchen/roles/role_name
824
+ role_path = source.sub(/#{roles}|\/roles/, '')
825
+ unless roles =~ /\/roles$/
826
+ role_path = "#{File.basename(roles)}/#{role_path}"
827
+ end
828
+
829
+ target = File.join(tmp_roles_dir, role_path)
830
+
831
+ Find.prune if config[:ignore_paths_from_root].include? File.basename(source)
832
+ if File.directory?(source)
833
+ FileUtils.mkdir_p(target)
834
+ else
835
+ FileUtils.cp(source, target)
836
+ end
837
+ end
838
+ end
839
+
840
+ # copy ansible.cfg if found in root of repo
841
+ def prepare_ansible_cfg
842
+ info('Preparing ansible.cfg file')
843
+ ansible_config_file = "#{File.join(sandbox_path, 'ansible.cfg')}"
844
+ if File.exist?('ansible.cfg')
845
+ info('Found existing ansible.cfg')
846
+ FileUtils.cp_r('ansible.cfg', ansible_config_file)
847
+ else
848
+ info('Empty ansible.cfg generated')
849
+ File.open(ansible_config_file, 'wb') do |file|
850
+ file.write("#no config parameters\n")
851
+ end
852
+ end
853
+ end
854
+
855
+ def prepare_inventory
856
+ info('Preparing inventory')
857
+ return unless ansible_inventory
858
+ if File.directory?(ansible_inventory)
859
+ debug("Copying inventory directory from #{ansible_inventory} to #{tmp_inventory_path}")
860
+ FileUtils.cp_r(ansible_inventory, sandbox_path)
861
+ else
862
+ debug("Copying inventory file from #{ansible_inventory} to #{tmp_inventory_path}")
863
+ FileUtils.cp_r(ansible_inventory, tmp_inventory_path)
864
+ end
865
+ end
866
+
867
+ # localhost ansible_connection=local
868
+ # [example_servers]
869
+ # localhost
870
+ def prepare_hosts
871
+ return if ansible_inventory
872
+ info('Preparing hosts file')
873
+
874
+ if config[:hosts].nil?
875
+ fail 'No hosts have been set. Please specify one in .kitchen.yml'
876
+ else
877
+ debug("Using host from #{hosts}")
878
+ File.open(File.join(sandbox_path, 'hosts'), 'wb') do |file|
879
+ file.write("localhost ansible_connection=local\n[#{hosts}]\nlocalhost\n")
880
+ end
881
+ end
882
+ end
883
+
884
+ def prepare_playbook
885
+ info('Preparing playbook')
886
+ debug("Copying playbook from #{playbook} to #{tmp_playbook_path}")
887
+ FileUtils.cp_r(playbook, tmp_playbook_path)
888
+ end
889
+
890
+ def prepare_group_vars
891
+ info('Preparing group_vars')
892
+ tmp_group_vars_dir = File.join(sandbox_path, 'group_vars')
893
+ FileUtils.mkdir_p(tmp_group_vars_dir)
894
+
895
+ unless File.directory?(group_vars)
896
+ info('nothing to do for group_vars')
897
+ return
898
+ end
899
+
900
+ debug("Using group_vars from #{group_vars}")
901
+ FileUtils.cp_r(Dir.glob("#{group_vars}/*"), tmp_group_vars_dir)
902
+ end
903
+
904
+ def prepare_additional_copy_path
905
+ info('Preparing additional_copy_path')
906
+ additional_files.each do |file|
907
+ destination = File.join(sandbox_path, File.basename(file))
908
+ if File.directory?(file)
909
+ info("Copy dir: #{file} #{destination}")
910
+ Find.prune if config[:ignore_paths_from_root].include? File.basename(file)
911
+ FileUtils.mkdir_p(destination)
912
+ else
913
+ info("Copy file: #{file} #{destination}")
914
+ FileUtils.cp(file, destination)
915
+ end
916
+ end
917
+ end
918
+
919
+ def additional_files
920
+ additional_files = []
921
+ if additional_copy
922
+ additional_files = additional_copy.is_a?(Array) ? additional_copy : [additional_copy]
923
+ end
924
+ additional_files.map(&:to_s)
925
+ end
926
+
927
+ def prepare_host_vars
928
+ info('Preparing host_vars')
929
+ FileUtils.mkdir_p(tmp_host_vars_dir)
930
+
931
+ unless File.directory?(host_vars)
932
+ info 'nothing to do for host_vars'
933
+ return
934
+ end
935
+
936
+ debug("Using host_vars from #{host_vars}")
937
+ FileUtils.cp_r(Dir.glob("#{host_vars}/*"), tmp_host_vars_dir)
938
+ end
939
+
940
+ def prepare_modules
941
+ info('Preparing modules')
942
+
943
+ FileUtils.mkdir_p(tmp_modules_dir)
944
+
945
+ if modules && File.directory?(modules)
946
+ debug("Using modules from #{modules}")
947
+ FileUtils.cp_r(Dir.glob("#{modules}/*"), tmp_modules_dir, remove_destination: true)
948
+ else
949
+ info 'nothing to do for modules'
950
+ end
951
+ end
952
+
953
+ def prepare_spec
954
+ info('Preparing spec')
955
+
956
+ FileUtils.mkdir_p(tmp_spec_dir)
957
+
958
+ if spec && File.directory?(spec)
959
+ debug("Using spec from #{spec}")
960
+ FileUtils.cp_r(Dir.glob("#{spec}/*"), tmp_spec_dir, remove_destination: true)
961
+ else
962
+ info 'nothing to do for spec'
963
+ end
964
+ end
965
+
966
+ def prepare_library_plugins
967
+ info('Preparing library plugins')
968
+ FileUtils.mkdir_p(tmp_library_plugins_dir)
969
+
970
+ if library_plugins && File.directory?(library_plugins)
971
+ debug("Using library plugins from #{library_plugins}")
972
+ FileUtils.cp_r(Dir.glob("#{library_plugins}/{*,!*.pyc}"), tmp_library_plugins_dir, remove_destination: true)
973
+ else
974
+ info 'nothing to do for library plugins'
975
+ end
976
+ end
977
+
978
+ def prepare_callback_plugins
979
+ info('Preparing callback plugins')
980
+ FileUtils.mkdir_p(tmp_callback_plugins_dir)
981
+
982
+ if callback_plugins && File.directory?(callback_plugins)
983
+ debug("Using callback plugins from #{callback_plugins}")
984
+ FileUtils.cp_r(Dir.glob("#{callback_plugins}/{*,!*.pyc}"), tmp_callback_plugins_dir, remove_destination: true)
985
+ else
986
+ info 'nothing to do for callback plugins'
987
+ end
988
+ end
989
+
990
+ def prepare_filter_plugins
991
+ info('Preparing filter_plugins')
992
+ FileUtils.mkdir_p(tmp_filter_plugins_dir)
993
+
994
+ if filter_plugins && File.directory?(filter_plugins)
995
+ debug("Using filter_plugins from #{filter_plugins}")
996
+ FileUtils.cp_r(Dir.glob("#{filter_plugins}/*.py"), tmp_filter_plugins_dir, remove_destination: true)
997
+ else
998
+ info 'nothing to do for filter_plugins'
999
+ end
1000
+ end
1001
+
1002
+ def prepare_lookup_plugins
1003
+ info('Preparing lookup_plugins')
1004
+ FileUtils.mkdir_p(tmp_lookup_plugins_dir)
1005
+
1006
+ if lookup_plugins && File.directory?(lookup_plugins)
1007
+ debug("Using lookup_plugins from #{lookup_plugins}")
1008
+ FileUtils.cp_r(Dir.glob("#{lookup_plugins}/*.py"), tmp_lookup_plugins_dir, remove_destination: true)
1009
+ else
1010
+ info 'nothing to do for lookup_plugins'
1011
+ end
1012
+ end
1013
+
1014
+ def prepare_ansible_vault_password_file
1015
+ return unless ansible_vault_password_file
1016
+
1017
+ info('Preparing ansible vault password')
1018
+ debug("Copying ansible vault password file from #{ansible_vault_password_file} to #{tmp_ansible_vault_password_file_path}")
1019
+
1020
+ FileUtils.cp(ansible_vault_password_file, tmp_ansible_vault_password_file_path)
1021
+ end
1022
+
1023
+ def prepare_kerberos_conf_file
1024
+ return unless kerberos_conf_file
1025
+
1026
+ info('Preparing kerberos configuration file')
1027
+ debug("Copying kerberos configuration file from #{kerberos_conf_file} to #{tmp_kerberos_conf_file_path}")
1028
+
1029
+ FileUtils.cp(kerberos_conf_file, tmp_kerberos_conf_file_path)
1030
+ end
1031
+
1032
+ def resolve_with_librarian
1033
+ Kitchen.mutex.synchronize do
1034
+ Ansible::Librarian.new(ansiblefile, tmp_roles_dir, logger).resolve
1035
+ end
1036
+ end
1037
+ end
1038
+ end
1039
+ end