kitchen-ansible 0.44.2 → 0.44.3

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,1039 +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 '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
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