kitchen-ansible 0.45.1 → 0.45.2

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