kitchen-ansible 0.48.8 → 0.51.0

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