kitchen-puppet 1.44.1 → 1.44.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1207 +1,1207 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Chris Lundquist (<chris.lundquist@github.com>) Neill Turner (<neillwturner@gmail.com>)
4
- #
5
- # Copyright (C) 2013,2014 Chris Lundquist, 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-puppet/blob/master/provisioner_options.md
20
- # for documentation configuration parameters with puppet_apply provisioner.
21
- #
22
-
23
- require 'uri'
24
- require 'json'
25
- require 'kitchen'
26
- require 'kitchen/provisioner/puppet/librarian'
27
-
28
- module Kitchen
29
- class Busser
30
- def non_suite_dirs
31
- %w(data data_bags environments nodes roles puppet)
32
- end
33
- end
34
-
35
- module Configurable
36
- def platform_name
37
- instance.platform.name
38
- end
39
- end
40
-
41
- module Provisioner
42
- #
43
- # Puppet Apply provisioner.
44
- #
45
- class PuppetApply < Base
46
- attr_accessor :tmp_dir
47
-
48
- default_config :require_puppet_collections, false
49
- default_config :puppet_yum_collections_repo, 'http://yum.puppetlabs.com/puppetlabs-release-pc1-el-6.noarch.rpm'
50
- default_config :puppet_apt_collections_repo, 'http://apt.puppetlabs.com/puppetlabs-release-pc1-wheezy.deb'
51
- default_config :puppet_coll_remote_path, '/opt/puppetlabs'
52
- default_config :puppet_version, nil
53
- default_config :facter_version, nil
54
- default_config :hiera_version, nil
55
- default_config :install_hiera, false
56
- default_config :hiera_package, 'hiera-puppet'
57
- default_config :require_puppet_repo, true
58
- default_config :require_chef_for_busser, true
59
- default_config :resolve_with_librarian_puppet, true
60
- default_config :puppet_environment, nil
61
- default_config :puppet_apt_repo, 'http://apt.puppetlabs.com/puppetlabs-release-precise.deb'
62
- default_config :puppet_yum_repo, 'https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm'
63
- default_config :chef_bootstrap_url, 'https://www.getchef.com/chef/install.sh'
64
- default_config :puppet_logdest, nil
65
- default_config :custom_install_command, nil
66
- default_config :custom_pre_install_command, nil
67
- default_config :custom_pre_apply_command, nil
68
- default_config :puppet_whitelist_exit_code, nil
69
- default_config :require_puppet_omnibus, false
70
- default_config :puppet_omnibus_url, 'https://raw.githubusercontent.com/petems/puppet-install-shell/master/install_puppet.sh'
71
- default_config :puppet_enc, nil
72
- default_config :ignore_spec_fixtures, false
73
-
74
- default_config :puppet_apply_command, nil
75
-
76
- default_config :puppet_git_init, nil
77
- default_config :puppet_git_pr, nil
78
-
79
- default_config :http_proxy, nil
80
- default_config :https_proxy, nil
81
-
82
- default_config :ignored_paths_from_root, []
83
- default_config :hiera_data_remote_path, '/var/lib/hiera'
84
- default_config :manifest, 'site.pp'
85
-
86
- default_config :manifests_path do |provisioner|
87
- provisioner.calculate_path('manifests') ||
88
- raise('No manifests_path detected. Please specify one in .kitchen.yml')
89
- end
90
-
91
- default_config :modules_path do |provisioner|
92
- modules_path = provisioner.calculate_path('modules')
93
- if modules_path.nil? && provisioner.calculate_path('Puppetfile', :file).nil?
94
- raise('No modules_path detected. Please specify one in .kitchen.yml')
95
- end
96
- modules_path
97
- end
98
-
99
- default_config :files_path do |provisioner|
100
- provisioner.calculate_path('files') || 'files'
101
- end
102
-
103
- default_config :hiera_data_path do |provisioner|
104
- provisioner.calculate_path('hiera')
105
- end
106
-
107
- default_config :puppet_config_path do |provisioner|
108
- provisioner.calculate_path('puppet.conf', :file)
109
- end
110
-
111
- default_config :hiera_config_path do |provisioner|
112
- provisioner.calculate_path('hiera.yaml', :file)
113
- end
114
-
115
- default_config :fileserver_config_path do |provisioner|
116
- provisioner.calculate_path('fileserver.conf', :file)
117
- end
118
- default_config :puppetfile_path do |provisioner|
119
- provisioner.calculate_path('Puppetfile', :file)
120
- end
121
-
122
- default_config :modulefile_path do |provisioner|
123
- provisioner.calculate_path('Modulefile', :file)
124
- end
125
-
126
- default_config :metadata_json_path do |provisioner|
127
- provisioner.calculate_path('metadata.json', :file)
128
- end
129
-
130
- default_config :manifests_path do |provisioner|
131
- provisioner.calculate_path('manifests', :directory)
132
- end
133
-
134
- default_config :spec_files_path do |provisioner|
135
- provisioner.calculate_path('spec', :directory)
136
- end
137
-
138
- default_config :spec_files_remote_path, '/etc/puppet/spec'
139
-
140
- default_config :puppet_debug, false
141
- default_config :puppet_verbose, false
142
- default_config :puppet_noop, false
143
- default_config :platform, &:platform_name
144
- default_config :update_package_repos, true
145
- default_config :remove_puppet_repo, false
146
- default_config :install_custom_facts, false
147
- default_config :custom_facts, {}
148
- default_config :facterlib, nil
149
- default_config :puppet_detailed_exitcodes, nil
150
- default_config :facter_file, nil
151
- default_config :librarian_puppet_ssl_file, nil
152
-
153
- default_config :hiera_eyaml, false
154
- default_config :hiera_eyaml_key_remote_path, '/etc/puppet/secure/keys'
155
-
156
- default_config :hiera_eyaml_key_path do |provisioner|
157
- provisioner.calculate_path('hiera_keys')
158
- end
159
-
160
- default_config :hiera_deep_merge, false
161
- default_config :puppet_no_sudo, false
162
-
163
- def calculate_path(path, type = :directory)
164
- base = config[:test_base_path]
165
- candidates = []
166
- candidates << File.join(base, instance.suite.name, 'puppet', path)
167
- candidates << File.join(base, instance.suite.name, path)
168
- candidates << File.join(base, path)
169
- candidates << File.join(Dir.pwd, path)
170
-
171
- candidates.find do |c|
172
- type == :directory ? File.directory?(c) : File.file?(c)
173
- end
174
- end
175
-
176
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
177
- def install_command
178
- return unless config[:require_puppet_collections] || config[:require_puppet_repo] || config[:require_puppet_omnibus]
179
- if config[:require_puppet_omnibus]
180
- install_omnibus_command
181
- elsif config[:require_puppet_collections]
182
- install_command_collections
183
- else
184
- case puppet_platform
185
- when 'debian', 'ubuntu'
186
- info("Installing puppet on #{config[:platform]}")
187
- # need to add a CR to avoid trouble with proxy settings concatenation
188
- <<-INSTALL
189
-
190
- #{custom_pre_install_command}
191
- if [ ! $(which puppet) ]; then
192
- #{sudo('apt-get')} -y install wget
193
- #{sudo('wget')} #{wget_proxy_parm} #{puppet_apt_repo}
194
- #{sudo('dpkg')} -i #{puppet_apt_repo_file}
195
- #{update_packages_debian_cmd}
196
- #{sudo_env('apt-get')} -y install facter#{facter_debian_version}
197
- #{sudo_env('apt-get')} -y install puppet-common#{puppet_debian_version}
198
- #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
199
- #{install_hiera}
200
- fi
201
- #{install_eyaml}
202
- #{install_deep_merge}
203
- #{install_busser}
204
- #{custom_install_command}
205
- INSTALL
206
- when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
207
- info("Installing puppet from yum on #{puppet_platform}")
208
- # need to add a CR to avoid trouble with proxy settings concatenation
209
- <<-INSTALL
210
-
211
- #{custom_pre_install_command}
212
- if [ ! $(which puppet) ]; then
213
- #{install_puppet_yum_repo}
214
- fi
215
- #{install_eyaml}
216
- #{install_deep_merge}
217
- #{install_busser}
218
- #{custom_install_command}
219
- INSTALL
220
- when /^windows.*/
221
- info("Installing puppet on #{puppet_platform}")
222
- <<-INSTALL
223
- if(Get-Command puppet -ErrorAction 0) { return; }
224
- if( [Environment]::Is64BitOperatingSystem ) {
225
- $MsiUrl = "https://downloads.puppetlabs.com/windows/puppet-#{puppet_windows_version}-x64.msi"
226
- } else {
227
- $MsiUrl = "https://downloads.puppetlabs.com/windows/puppet-#{puppet_windows_version}.msi"
228
- }
229
- $process = Start-Process -FilePath msiexec.exe -Wait -PassThru -ArgumentList '/qn', '/norestart', '/i', $MsiUrl
230
- if ($process.ExitCode -ne 0) {
231
- Write-Host "Installer failed."
232
- Exit 1
233
- }
234
-
235
- #{install_busser}
236
- INSTALL
237
- else
238
- info('Installing puppet, will try to determine platform os')
239
- # need to add a CR to avoid trouble with proxy settings concatenation
240
- <<-INSTALL
241
-
242
- #{custom_pre_install_command}
243
- if [ ! $(which puppet) ]; then
244
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
245
- #{install_puppet_yum_repo}
246
- else
247
- if [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
248
- #{install_puppet_yum_repo}
249
- else
250
- #{sudo('apt-get')} -y install wget
251
- #{sudo('wget')} #{wget_proxy_parm} #{puppet_apt_repo}
252
- #{sudo('dpkg')} -i #{puppet_apt_repo_file}
253
- #{update_packages_debian_cmd}
254
- #{sudo_env('apt-get')} -y install facter#{facter_debian_version}
255
- #{sudo_env('apt-get')} -y install puppet-common#{puppet_debian_version}
256
- #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
257
- #{install_hiera}
258
- fi
259
- fi
260
- fi
261
- #{install_eyaml}
262
- #{install_deep_merge}
263
- #{install_busser}
264
- #{custom_install_command}
265
- INSTALL
266
- end
267
- end
268
- end
269
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
270
-
271
- def install_command_collections
272
- case puppet_platform
273
- when 'debian', 'ubuntu'
274
- info("Installing Puppet Collections on #{puppet_platform}")
275
- <<-INSTALL
276
-
277
- #{Util.shell_helpers}
278
- #{custom_pre_install_command}
279
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
280
- if [ ! -f "#{config[:puppet_apt_collections_repo]}" ]; then
281
- #{sudo('apt-get')} -y install wget
282
- #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
283
- fi
284
- #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
285
- #{sudo('apt-get')} update
286
- #{sudo_env('apt-get')} -y install puppet-agent#{puppet_debian_version}
287
- fi
288
- #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
289
- #{install_deep_merge}
290
- #{install_busser}
291
- #{custom_install_command}
292
- INSTALL
293
- when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
294
- info("Installing Puppet Collections on #{puppet_platform}")
295
- <<-INSTALL
296
-
297
- #{Util.shell_helpers}
298
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
299
- echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
300
- #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
301
- #{sudo_env('yum')} -y install puppet-agent#{puppet_redhat_version}
302
- fi
303
- #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
304
- #{install_deep_merge}
305
- #{install_busser}
306
- #{custom_install_command}
307
- INSTALL
308
- else
309
- info('Installing Puppet Collections, will try to determine platform os')
310
- <<-INSTALL
311
-
312
- #{Util.shell_helpers}
313
- #{custom_pre_install_command}
314
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
315
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ] || \
316
- [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
317
- echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
318
- #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
319
- #{sudo_env('yum')} -y install puppet-agent#{puppet_redhat_version}
320
- else
321
- #{sudo('apt-get')} -y install wget
322
- #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
323
- #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
324
- #{sudo('apt-get')} update
325
- #{sudo_env('apt-get')} -y install puppet-agent#{puppet_debian_version}
326
- fi
327
- fi
328
- #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
329
- #{install_deep_merge}
330
- #{install_busser}
331
- #{custom_install_command}
332
- INSTALL
333
- end
334
- end
335
-
336
- def install_deep_merge
337
- return unless config[:hiera_deep_merge]
338
- <<-INSTALL
339
- # Support for hash merge lookups to recursively merge hash keys
340
- if [[ $(#{sudo('gem')} list deep_merge -i) == 'false' ]]; then
341
- echo '-----> Installing deep_merge to provide deep_merge of hiera hashes'
342
- #{sudo('gem')} install #{gem_proxy_parm} --no-ri --no-rdoc deep_merge
343
- fi
344
- INSTALL
345
- end
346
-
347
- def install_eyaml(gem_cmd = 'gem')
348
- return unless config[:hiera_eyaml]
349
- <<-INSTALL
350
- # A backend for Hiera that provides per-value asymmetric encryption of sensitive data
351
- if [[ $(#{sudo(gem_cmd)} list hiera-eyaml -i) == 'false' ]]; then
352
- echo '-----> Installing hiera-eyaml to provide encryption of hiera data'
353
- #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc highline -v 1.6.21
354
- #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc hiera-eyaml
355
- fi
356
- INSTALL
357
- end
358
-
359
- def install_busser
360
- return unless config[:require_chef_for_busser]
361
- info("Install busser on #{puppet_platform}")
362
- case puppet_platform
363
- when /^windows.*/
364
- # https://raw.githubusercontent.com/opscode/knife-windows/master/lib/chef/knife/bootstrap/windows-chef-client-msi.erb
365
- <<-INSTALL
366
- $webclient = New-Object System.Net.WebClient; $webclient.DownloadFile('https://opscode-omnibus-packages.s3.amazonaws.com/windows/2008r2/x86_64/chef-windows-11.12.8-1.windows.msi','chef-windows-11.12.8-1.windows.msi')
367
- msiexec /qn /i chef-windows-11.12.8-1.windows.msi
368
-
369
- cmd.exe /C "SET PATH=%PATH%;`"C:\\opscode\\chef\\embedded\\bin`";`"C:\\tmp\\busser\\gems\\bin`""
370
-
371
- INSTALL
372
- else
373
- <<-INSTALL
374
- #{Util.shell_helpers}
375
- # install chef omnibus so that busser works as this is needed to run tests :(
376
- # TODO: work out how to install enough ruby
377
- # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
378
- # whole chef client
379
- if [ ! -d "/opt/chef" ]
380
- then
381
- echo '-----> Installing Chef Omnibus to install busser to run tests'
382
- #{export_http_proxy_parm}
383
- #{export_https_proxy_parm}
384
- do_download #{chef_url} /tmp/install.sh
385
- #{sudo('sh')} /tmp/install.sh
386
- fi
387
- INSTALL
388
- end
389
- end
390
-
391
- def install_omnibus_command
392
- info('Installing puppet using puppet omnibus')
393
-
394
- version = ''
395
- version = "-v #{config[:puppet_version]}" unless config[:puppet_version].nil?
396
-
397
- <<-INSTALL
398
- #{Util.shell_helpers}
399
- if [ ! $(which puppet) ]; then
400
- echo "-----> Installing Puppet Omnibus"
401
- #{export_http_proxy_parm}
402
- #{export_https_proxy_parm}
403
- do_download #{config[:puppet_omnibus_url]} /tmp/install_puppet.sh
404
- #{sudo_env('sh')} /tmp/install_puppet.sh #{version}
405
- fi
406
- INSTALL
407
- end
408
-
409
- def install_hiera
410
- return unless config[:install_hiera]
411
- <<-INSTALL
412
- #{sudo_env('apt-get')} -y install #{hiera_package}
413
- INSTALL
414
- end
415
-
416
- def hiera_package
417
- "#{config[:hiera_package]}#{puppet_hiera_debian_version}"
418
- end
419
-
420
- # /bin/wget -P /etc/pki/rpm-gpg/ http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
421
- # changed to curl
422
-
423
- def install_puppet_yum_repo
424
- <<-INSTALL
425
- rhelversion=$(cat /etc/redhat-release | grep 'release 7')
426
- # For CentOS7/RHEL7 the rdo release contains puppetlabs repo, creating conflict. Create temp-repo
427
- #{sudo_env('curl')} -o /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
428
- if [ -n "$rhelversion" ]; then
429
- echo '[puppettemp-products]
430
- name=Puppet Labs Products - \$basearch
431
- baseurl=http://yum.puppetlabs.com/el/7/products/\$basearch
432
- gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
433
- enabled=0
434
- gpgcheck=1
435
- [puppettemp-deps]
436
- name=Puppet Labs Dependencies - \$basearch
437
- baseurl=http://yum.puppetlabs.com/el/7/dependencies/\$basearch
438
- gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
439
- enabled=0
440
- gpgcheck=1' | sudo tee /etc/yum.repos.d/puppettemp.repo > /dev/null
441
- sudo sed -i 's/^[ \t]*//' /etc/yum.repos.d/puppettemp.repo
442
- #{update_packages_redhat_cmd}
443
- #{sudo_env('yum')} -y --enablerepo=puppettemp-products --enablerepo=puppettemp-deps install puppet#{puppet_redhat_version}
444
- # Clean up temporary puppet repo
445
- sudo rm -rf /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
446
- sudo rm -rf /etc/yum.repos.d/puppettemp.repo
447
- else
448
- #{sudo('rpm')} -ivh #{proxy_parm} #{puppet_yum_repo}
449
- #{update_packages_redhat_cmd}
450
- #{sudo_env('yum')} -y install puppet#{puppet_redhat_version}
451
- fi
452
- INSTALL
453
- end
454
-
455
- def custom_pre_install_command
456
- <<-INSTALL
457
- #{config[:custom_pre_install_command]}
458
- INSTALL
459
- end
460
-
461
- def custom_install_command
462
- <<-INSTALL
463
- #{config[:custom_install_command]}
464
- INSTALL
465
- end
466
-
467
- def init_command
468
- todelete = %w(modules manifests files hiera hiera.yaml facter spec enc)
469
- .map { |dir| File.join(config[:root_path], dir) }
470
- todelete += [hiera_data_remote_path,
471
- '/etc/hiera.yaml',
472
- "#{puppet_dir}/hiera.yaml",
473
- spec_files_remote_path.to_s,
474
- "#{puppet_dir}/fileserver.conf"]
475
- todelete += File.join(puppet_dir, config[:puppet_environment]) if config[:puppet_environment]
476
- cmd = "#{sudo(rm_command_paths(todelete))};"
477
- cmd += " #{mkdir_command} #{config[:root_path]};"
478
- cmd += " #{sudo(mkdir_command)} #{puppet_dir}"
479
- debug(cmd)
480
- cmd
481
- end
482
-
483
- def create_sandbox
484
- super
485
- debug("Creating local sandbox in #{sandbox_path}")
486
- yield if block_given?
487
- prepare_modules
488
- prepare_manifests
489
- prepare_files
490
- prepare_facter_file
491
- prepare_facts
492
- prepare_puppet_config
493
- prepare_hiera_config
494
- prepare_fileserver_config
495
- prepare_hiera_data
496
- prepare_enc
497
- prepare_spec_files
498
- info('Finished Preparing files for transfer')
499
- end
500
-
501
- def cleanup_sandbox
502
- return if sandbox_path.nil?
503
- debug("Cleaning up local sandbox in #{sandbox_path}")
504
- FileUtils.rmtree(sandbox_path)
505
- return if remove_repo.nil?
506
- debug("Cleaning up remote sandbox: #{remove_repo}")
507
- instance.remote_exec remove_repo
508
- end
509
-
510
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
511
- def prepare_command
512
- commands = []
513
- if puppet_git_init
514
- commands << [
515
- sudo('rm -rf'), '/etc/puppet'
516
- ].join(' ')
517
-
518
- commands << [
519
- sudo('git clone'), puppet_git_init, '/etc/puppet'
520
- ].join(' ')
521
- end
522
-
523
- if puppet_git_pr
524
- commands << [
525
- sudo('git'),
526
- '--git-dir=/etc/puppet/.git/',
527
- 'fetch -f',
528
- 'origin',
529
- "pull/#{puppet_git_pr}/head:pr_#{puppet_git_pr}"
530
- ].join(' ')
531
-
532
- commands << [
533
- sudo('git'),
534
- '--git-dir=/etc/puppet/.git/',
535
- '--work-tree=/etc/puppet/',
536
- 'checkout',
537
- "pr_#{puppet_git_pr}"
538
- ].join(' ')
539
- end
540
-
541
- if puppet_config
542
- commands << [
543
- sudo(cp_command),
544
- File.join(config[:root_path], 'puppet.conf'),
545
- puppet_dir
546
- ].join(' ')
547
- end
548
-
549
- if hiera_config
550
- commands << [
551
- sudo(cp_command), File.join(config[:root_path], 'hiera.yaml'), '/etc/'
552
- ].join(' ')
553
-
554
- commands << [
555
- sudo(cp_command), File.join(config[:root_path], 'hiera.yaml'), hiera_config_dir
556
- ].join(' ')
557
- end
558
-
559
- if fileserver_config
560
- commands << [
561
- sudo(cp_command),
562
- File.join(config[:root_path], 'fileserver.conf'),
563
- puppet_dir
564
- ].join(' ')
565
- end
566
-
567
- if hiera_data && hiera_data_remote_path == '/var/lib/hiera'
568
- commands << [
569
- sudo("#{cp_command} -r"), File.join(config[:root_path], 'hiera'), '/var/lib/'
570
- ].join(' ')
571
- end
572
-
573
- if hiera_data && hiera_data_remote_path != '/var/lib/hiera'
574
- commands << [
575
- sudo(mkdir_command), hiera_data_remote_path
576
- ].join(' ')
577
- commands << [
578
- sudo("#{cp_command} -r"), File.join(config[:root_path], 'hiera/*'), hiera_data_remote_path
579
- ].join(' ')
580
- end
581
-
582
- if hiera_eyaml
583
- commands << [
584
- sudo(mkdir_command), hiera_eyaml_key_remote_path
585
- ].join(' ')
586
- commands << [
587
- sudo("#{cp_command} -r"), File.join(config[:root_path], 'hiera_keys/*'), hiera_eyaml_key_remote_path
588
- ].join(' ')
589
- end
590
-
591
- if puppet_environment
592
- commands << [
593
- sudo('ln -s '), config[:root_path], File.join(puppet_dir, config[:puppet_environment])
594
- ].join(' ')
595
- end
596
-
597
- if spec_files_path && spec_files_remote_path
598
- commands << [
599
- sudo(mkdir_command), spec_files_remote_path
600
- ].join(' ')
601
- commands << [
602
- sudo("#{cp_command} -r"), File.join(config[:root_path], 'spec/*'), spec_files_remote_path
603
- ].join(' ')
604
- end
605
-
606
- if config[:puppet_enc]
607
- commands << [
608
- sudo('chmod 755'), File.join("#{config[:root_path]}/enc", File.basename(config[:puppet_enc]))
609
- ].join(' ')
610
- end
611
-
612
- command = powershell_shell? ? commands.join('; ') : commands.join(' && ')
613
- debug(command)
614
- command
615
- end
616
-
617
- def run_command
618
- if !config[:puppet_apply_command].nil?
619
- return config[:puppet_apply_command]
620
- else
621
- result = [
622
- facterlib,
623
- custom_facts,
624
- puppet_manifestdir,
625
- puppet_cmd,
626
- 'apply',
627
- File.join(config[:root_path], 'manifests', manifest),
628
- "--modulepath=#{File.join(config[:root_path], 'modules')}",
629
- "--fileserverconfig=#{File.join(config[:root_path], 'fileserver.conf')}",
630
- custom_options,
631
- puppet_environment_flag,
632
- puppet_noop_flag,
633
- puppet_enc_flag,
634
- puppet_detailed_exitcodes_flag,
635
- puppet_verbose_flag,
636
- puppet_debug_flag,
637
- puppet_logdest_flag,
638
- puppet_whitelist_exit_code
639
- ].join(' ')
640
- if config[:custom_post_apply_command]
641
- custom_post_apply_trap = <<-TRAP
642
- function custom_post_apply_command {
643
- #{config[:custom_post_apply_command]}
644
- }
645
- trap custom_post_apply_command EXIT
646
- TRAP
647
- end
648
- result = <<-RUN
649
- #{config[:custom_pre_apply_command]}
650
- #{custom_post_apply_trap}
651
- #{result}
652
- RUN
653
- info("Going to invoke puppet apply with: #{result}")
654
- result
655
- end
656
- end
657
-
658
- protected
659
-
660
- def load_needed_dependencies!
661
- return unless File.exist?(puppetfile)
662
- return unless config[:resolve_with_librarian_puppet]
663
- debug("Puppetfile found at #{puppetfile}, loading Librarian-Puppet")
664
- Puppet::Librarian.load!(logger)
665
- end
666
-
667
- def tmpmodules_dir
668
- File.join(sandbox_path, 'modules')
669
- end
670
-
671
- def puppetfile
672
- config[:puppetfile_path] || ''
673
- end
674
-
675
- def modulefile
676
- config[:modulefile_path] || ''
677
- end
678
-
679
- def metadata_json
680
- config[:metadata_json_path] || ''
681
- end
682
-
683
- def manifest
684
- config[:manifest]
685
- end
686
-
687
- def manifests
688
- config[:manifests_path]
689
- end
690
-
691
- def modules
692
- config[:modules_path]
693
- end
694
-
695
- def files
696
- config[:files_path] || 'files'
697
- end
698
-
699
- def puppet_config
700
- config[:puppet_config_path]
701
- end
702
-
703
- def puppet_environment
704
- config[:puppet_environment]
705
- end
706
-
707
- def puppet_git_init
708
- config[:puppet_git_init]
709
- end
710
-
711
- def puppet_git_pr
712
- config[:puppet_git_pr]
713
- end
714
-
715
- def hiera_config
716
- config[:hiera_config_path]
717
- end
718
-
719
- def fileserver_config
720
- config[:fileserver_config_path]
721
- end
722
-
723
- def hiera_data
724
- config[:hiera_data_path]
725
- end
726
-
727
- def hiera_data_remote_path
728
- config[:hiera_data_remote_path]
729
- end
730
-
731
- def hiera_eyaml
732
- config[:hiera_eyaml]
733
- end
734
-
735
- def hiera_eyaml_key_path
736
- config[:hiera_eyaml_key_path]
737
- end
738
-
739
- def hiera_eyaml_key_remote_path
740
- config[:hiera_eyaml_key_remote_path]
741
- end
742
-
743
- def hiera_deep_merge
744
- config[:hiera_deep_merge]
745
- end
746
-
747
- def librarian_puppet_ssl_file
748
- config[:librarian_puppet_ssl_file]
749
- end
750
-
751
- def puppet_cmd
752
- puppet_bin = powershell_shell? ? '& "C:\Program Files\Puppet Labs\Puppet\bin\puppet"' : 'puppet'
753
- if config[:require_puppet_collections]
754
- puppet_bin = "#{config[:puppet_coll_remote_path]}/bin/puppet"
755
- end
756
-
757
- if config[:puppet_no_sudo]
758
- puppet_bin
759
- else
760
- sudo_env(puppet_bin)
761
- end
762
- end
763
-
764
- def puppet_dir
765
- return '/etc/puppetlabs/puppet' if config[:require_puppet_collections]
766
- return '/etc/puppet' unless powershell_shell?
767
- 'C:/ProgramData/PuppetLabs/puppet/etc'
768
- end
769
-
770
- def hiera_config_dir
771
- return '/etc/puppetlabs/code' if config[:require_puppet_collections]
772
- return '/etc/puppet' unless powershell_shell?
773
- 'C:/ProgramData/PuppetLabs/puppet/etc'
774
- end
775
-
776
- def puppet_debian_version
777
- config[:puppet_version] ? "=#{config[:puppet_version]}" : nil
778
- end
779
-
780
- def facter_debian_version
781
- config[:facter_version] ? "=#{config[:facter_version]}" : nil
782
- end
783
-
784
- def puppet_hiera_debian_version
785
- config[:hiera_version] ? "=#{config[:hiera_version]}" : nil
786
- end
787
-
788
- def puppet_redhat_version
789
- if puppet_platform == 'amazon'
790
- config[:puppet_version]
791
- else
792
- config[:puppet_version] ? "-#{config[:puppet_version]}" : nil
793
- end
794
- end
795
-
796
- def puppet_windows_version
797
- config[:puppet_version] ? config[:puppet_version].to_s : '3.8.6'
798
- end
799
-
800
- def puppet_environment_flag
801
- if config[:puppet_version] =~ /^2/
802
- config[:puppet_environment] ? "--environment=#{config[:puppet_environment]}" : nil
803
- else
804
- config[:puppet_environment] ? "--environment=#{config[:puppet_environment]} --environmentpath=#{puppet_dir}" : nil
805
- end
806
- end
807
-
808
- def puppet_manifestdir
809
- return nil if config[:require_puppet_collections]
810
- return nil if config[:puppet_environment]
811
- return nil if powershell_shell?
812
- bash_vars = "export MANIFESTDIR='#{File.join(config[:root_path], 'manifests')}';"
813
- debug(bash_vars)
814
- bash_vars
815
- end
816
-
817
- def custom_options
818
- config[:custom_options] || ''
819
- end
820
-
821
- def puppet_noop_flag
822
- config[:puppet_noop] ? '--noop' : nil
823
- end
824
-
825
- def puppet_debug_flag
826
- config[:puppet_debug] ? '-d' : nil
827
- end
828
-
829
- def puppet_verbose_flag
830
- config[:puppet_verbose] ? '-v' : nil
831
- end
832
-
833
- def puppet_logdest_flag
834
- return nil unless config[:puppet_logdest]
835
- destinations = ''
836
- config[:puppet_logdest].each do |dest|
837
- destinations << "--logdest #{dest} "
838
- end
839
- destinations
840
- end
841
-
842
- def puppet_platform
843
- config[:platform].gsub(/-.*/, '')
844
- end
845
-
846
- def update_packages_debian_cmd
847
- config[:update_package_repos] ? "#{sudo_env('apt-get')} update" : nil
848
- end
849
-
850
- def update_packages_redhat_cmd
851
- # #{sudo('yum')}
852
- config[:update_package_repos] ? "#{sudo_env('yum')} makecache" : nil
853
- end
854
-
855
- def sudo_env(pm)
856
- s = https_proxy ? "https_proxy=#{https_proxy}" : nil
857
- p = http_proxy ? "http_proxy=#{http_proxy}" : nil
858
- p || s ? "#{sudo('env')} #{p} #{s} #{pm}" : sudo(pm).to_s
859
- end
860
-
861
- def remove_puppet_repo
862
- config[:remove_puppet_repo]
863
- end
864
-
865
- def spec_files_path
866
- config[:spec_files_path]
867
- end
868
-
869
- def spec_files_remote_path
870
- config[:spec_files_remote_path]
871
- end
872
-
873
- def facterlib
874
- factpath = nil
875
- factpath = File.join(config[:root_path], 'facter').to_s if config[:install_custom_facts] && !config[:custom_facts].none?
876
- factpath = File.join(config[:root_path], 'facter').to_s if config[:facter_file]
877
- factpath = "#{factpath}:" if config[:facterlib] && !factpath.nil?
878
- factpath = "#{factpath}#{config[:facterlib]}" if config[:facterlib]
879
- return nil if factpath.nil?
880
- bash_vars = "export FACTERLIB='#{factpath}';"
881
- debug(bash_vars)
882
- bash_vars
883
- end
884
-
885
- def custom_facts
886
- return nil if config[:custom_facts].none?
887
- return nil if config[:install_custom_facts]
888
- if powershell_shell?
889
- environment_vars = config[:custom_facts].map { |k, v| "$env:FACTER_#{k}='#{v}'" }.join('; ')
890
- environment_vars = "#{environment_vars};"
891
- else
892
- environment_vars = config[:custom_facts].map { |k, v| "FACTER_#{k}=#{v}" }.join(' ')
893
- environment_vars = "export #{environment_vars};"
894
- end
895
- debug(environment_vars)
896
- environment_vars
897
- end
898
-
899
- def puppet_enc_flag
900
- config[:puppet_enc] ? "--node_terminus=exec --external_nodes=#{config[:root_path]}/enc/#{File.basename(config[:puppet_enc])}" : nil
901
- end
902
-
903
- def puppet_detailed_exitcodes_flag
904
- config[:puppet_detailed_exitcodes] ? '--detailed-exitcodes' : nil
905
- end
906
-
907
- def remove_repo
908
- remove_puppet_repo ? "#{sudo('rm')} -rf /tmp/kitchen #{hiera_data_remote_path} #{hiera_eyaml_key_remote_path} #{puppet_dir}/* " : nil
909
- end
910
-
911
- def puppet_whitelist_exit_code
912
- if config[:puppet_whitelist_exit_code].nil?
913
- return powershell_shell? ? '; exit $LASTEXITCODE' : nil
914
- elsif powershell_shell?
915
- return "; if(@(#{[config[:puppet_whitelist_exit_code]].join(', ')}) -contains $LASTEXITCODE) {exit 0} else {exit $LASTEXITCODE}"
916
- else
917
- return "; [ $? -eq #{config[:puppet_whitelist_exit_code]} ] && exit 0"
918
- end
919
- end
920
-
921
- def puppet_apt_repo
922
- platform_version = config[:platform].partition('-')[2]
923
- case puppet_platform
924
- when 'ubuntu'
925
- case platform_version
926
- when '14.10'
927
- # Utopic Repo
928
- 'https://apt.puppetlabs.com/puppetlabs-release-utopic.deb'
929
- when '14.04'
930
- # Trusty Repo
931
- 'https://apt.puppetlabs.com/puppetlabs-release-trusty.deb'
932
- when '12.04'
933
- # Precise Repo
934
- 'https://apt.puppetlabs.com/puppetlabs-release-precise.deb'
935
- else
936
- # Configured Repo
937
- config[:puppet_apt_repo]
938
- end
939
- when 'debian'
940
- case platform_version.gsub(/\..*/, '')
941
- when '8'
942
- # Debian Jessie
943
- 'https://apt.puppetlabs.com/puppetlabs-release-jessie.deb'
944
- when '7'
945
- # Debian Wheezy
946
- 'https://apt.puppetlabs.com/puppetlabs-release-wheezy.deb'
947
- when '6'
948
- # Debian Squeeze
949
- 'https://apt.puppetlabs.com/puppetlabs-release-squeeze.deb'
950
- else
951
- # Configured Repo
952
- config[:puppet_apt_repo]
953
- end
954
- else
955
- debug("Apt repo detection failed with platform - #{config[:platform]}")
956
- false
957
- end
958
- end
959
-
960
- def puppet_apt_repo_file
961
- puppet_apt_repo.split('/').last if puppet_apt_repo
962
- end
963
-
964
- def puppet_apt_coll_repo_file
965
- config[:puppet_apt_collections_repo].split('/').last
966
- end
967
-
968
- def puppet_yum_repo
969
- config[:puppet_yum_repo]
970
- end
971
-
972
- def proxy_parm
973
- http_proxy ? "--httpproxy #{URI.parse(http_proxy).host.downcase} --httpport #{URI.parse(http_proxy).port} " : nil
974
- end
975
-
976
- def gem_proxy_parm
977
- http_proxy ? "--http-proxy #{http_proxy}" : nil
978
- end
979
-
980
- def wget_proxy_parm
981
- p = http_proxy ? "-e http_proxy=#{http_proxy}" : nil
982
- s = https_proxy ? "-e https_proxy=#{https_proxy}" : nil
983
- p || s ? "-e use_proxy=yes #{p} #{s}" : nil
984
- end
985
-
986
- def export_http_proxy_parm
987
- http_proxy ? "export http_proxy=#{http_proxy}" : nil
988
- end
989
-
990
- def export_https_proxy_parm
991
- https_proxy ? "export https_proxy=#{https_proxy}" : nil
992
- end
993
-
994
- def http_proxy
995
- config[:http_proxy]
996
- end
997
-
998
- def https_proxy
999
- config[:https_proxy]
1000
- end
1001
-
1002
- def chef_url
1003
- config[:chef_bootstrap_url]
1004
- end
1005
-
1006
- def prepare_manifests
1007
- info('Preparing manifests')
1008
- debug("Using manifests from #{manifests}")
1009
-
1010
- tmp_manifests_dir = File.join(sandbox_path, 'manifests')
1011
- FileUtils.mkdir_p(tmp_manifests_dir)
1012
- FileUtils.cp_r(Dir.glob("#{manifests}/*"), tmp_manifests_dir)
1013
- end
1014
-
1015
- def prepare_files
1016
- info('Preparing files')
1017
- unless File.directory?(files)
1018
- info 'nothing to do for files'
1019
- return
1020
- end
1021
-
1022
- debug("Using files from #{files}")
1023
-
1024
- tmp_files_dir = File.join(sandbox_path, 'files')
1025
- FileUtils.mkdir_p(tmp_files_dir)
1026
- FileUtils.cp_r(Dir.glob("#{files}/*"), tmp_files_dir)
1027
- end
1028
-
1029
- def prepare_facter_file
1030
- return unless config[:facter_file]
1031
- info 'Copying facter file'
1032
- facter_dir = File.join(sandbox_path, 'facter')
1033
- FileUtils.mkdir_p(facter_dir)
1034
- FileUtils.cp_r(config[:facter_file], facter_dir)
1035
- end
1036
-
1037
- def prepare_facts
1038
- return unless config[:install_custom_facts]
1039
- return unless config[:custom_facts]
1040
- info 'Installing custom facts'
1041
- facter_dir = File.join(sandbox_path, 'facter')
1042
- FileUtils.mkdir_p(facter_dir)
1043
- tmp_facter_file = File.join(facter_dir, 'kitchen.rb')
1044
- facter_facts = Hash[config[:custom_facts].map { |k, v| [k.to_s, v.to_s] }]
1045
- File.open(tmp_facter_file, 'a') do |out|
1046
- facter_facts.each do |k, v|
1047
- out.write "\nFacter.add(:#{k}) do\n"
1048
- out.write " setcode do\n"
1049
- out.write " \"#{v}\"\n"
1050
- out.write " end\n"
1051
- out.write "end\n"
1052
- end
1053
- end
1054
- end
1055
-
1056
- def prepare_modules
1057
- info('Preparing modules')
1058
-
1059
- FileUtils.mkdir_p(tmpmodules_dir)
1060
- resolve_with_librarian if File.exist?(puppetfile) && config[:resolve_with_librarian_puppet]
1061
-
1062
- if modules && modules.include?(':')
1063
- debug('Found multiple directories in module path merging.....')
1064
- modules_array = modules.split(':')
1065
- modules_array.each do |m|
1066
- copy_modules(m, tmpmodules_dir)
1067
- end
1068
- elsif modules
1069
- copy_modules(modules, tmpmodules_dir)
1070
- else
1071
- info 'nothing to do for modules'
1072
- end
1073
-
1074
- copy_self_as_module
1075
- end
1076
-
1077
- def copy_modules(source, destination)
1078
- return unless File.directory?(source)
1079
-
1080
- debug("Copying modules from #{source} to #{destination}")
1081
-
1082
- excluded_paths = %w(modules spec pkg) + config[:ignored_paths_from_root]
1083
-
1084
- Dir.glob("#{source}/*").each do |f|
1085
- module_name = File.basename(f)
1086
- target = "#{destination}/#{module_name}"
1087
- FileUtils.mkdir_p(target) unless File.exist? target
1088
- FileUtils.cp_r(Dir.glob("#{source}/#{module_name}/*").reject { |entry| entry =~ /#{excluded_paths.join('$|')}$/ }, target, remove_destination: true)
1089
- end
1090
- end
1091
-
1092
- def copy_self_as_module
1093
- if File.exist?(modulefile)
1094
- warn('Modulefile found but this is depricated, ignoring it, see https://tickets.puppetlabs.com/browse/PUP-1188')
1095
- end
1096
-
1097
- return unless File.exist?(metadata_json)
1098
- module_name = nil
1099
- begin
1100
- module_name = JSON.parse(IO.read(metadata_json))['name'].split('-').last
1101
- rescue
1102
- error("not able to load or parse #{metadata_json_path} for the name of the module")
1103
- end
1104
-
1105
- return unless module_name
1106
- module_target_path = File.join(sandbox_path, 'modules', module_name)
1107
- FileUtils.mkdir_p(module_target_path)
1108
-
1109
- excluded_paths = %w(modules spec pkg) + config[:ignored_paths_from_root]
1110
-
1111
- FileUtils.cp_r(
1112
- Dir.glob(File.join(config[:kitchen_root], '*')).reject { |entry| entry =~ /#{excluded_paths.join('$|')}$/ },
1113
- module_target_path,
1114
- remove_destination: true
1115
- )
1116
- end
1117
-
1118
- def prepare_puppet_config
1119
- return unless puppet_config
1120
-
1121
- info('Preparing puppet.conf')
1122
- debug("Using puppet config from #{puppet_config}")
1123
-
1124
- FileUtils.cp_r(puppet_config, File.join(sandbox_path, 'puppet.conf'))
1125
- end
1126
-
1127
- def prepare_enc
1128
- return unless config[:puppet_enc]
1129
- info 'Copying enc file'
1130
- enc_dir = File.join(sandbox_path, 'enc')
1131
- FileUtils.mkdir_p(enc_dir)
1132
- FileUtils.cp_r(config[:puppet_enc], File.join(enc_dir, '/'))
1133
- end
1134
-
1135
- def prepare_hiera_config
1136
- return unless hiera_config
1137
-
1138
- info('Preparing hiera')
1139
- debug("Using hiera from #{hiera_config}")
1140
-
1141
- FileUtils.cp_r(hiera_config, File.join(sandbox_path, 'hiera.yaml'))
1142
- end
1143
-
1144
- def prepare_fileserver_config
1145
- return unless fileserver_config
1146
-
1147
- info('Preparing fileserver')
1148
- debug("Using fileserver config from #{fileserver_config}")
1149
-
1150
- FileUtils.cp_r(fileserver_config, File.join(sandbox_path, 'fileserver.conf'))
1151
- end
1152
-
1153
- def prepare_hiera_data
1154
- return unless hiera_data
1155
- info('Preparing hiera data')
1156
- tmp_hiera_dir = File.join(sandbox_path, 'hiera')
1157
- debug("Copying hiera data from #{hiera_data} to #{tmp_hiera_dir}")
1158
- FileUtils.mkdir_p(tmp_hiera_dir)
1159
- FileUtils.cp_r(Dir.glob("#{hiera_data}/*"), tmp_hiera_dir)
1160
- return unless hiera_eyaml_key_path
1161
- tmp_hiera_key_dir = File.join(sandbox_path, 'hiera_keys')
1162
- debug("Copying hiera eyaml keys from #{hiera_eyaml_key_path} to #{tmp_hiera_key_dir}")
1163
- FileUtils.mkdir_p(tmp_hiera_key_dir)
1164
- FileUtils.cp_r(Dir.glob("#{hiera_eyaml_key_path}/*"), tmp_hiera_key_dir)
1165
- end
1166
-
1167
- def prepare_spec_files
1168
- return unless spec_files_path
1169
- info('Preparing spec files')
1170
- tmp_spec_dir = File.join(sandbox_path, 'spec')
1171
- debug("Copying specs from #{spec_files_path} to #{tmp_spec_dir}")
1172
- FileUtils.mkdir_p(tmp_spec_dir)
1173
- FileUtils.cp_r(Dir.glob(File.join(spec_files_path, '*')).reject { |entry| entry =~ /fixtures$/ }, tmp_spec_dir) if config[:ignore_spec_fixtures]
1174
- FileUtils.cp_r(Dir.glob("#{spec_files_path}/*"), tmp_spec_dir) unless config[:ignore_spec_fixtures]
1175
- end
1176
-
1177
- def resolve_with_librarian
1178
- Kitchen.mutex.synchronize do
1179
- ENV['SSL_CERT_FILE'] = librarian_puppet_ssl_file if librarian_puppet_ssl_file
1180
- Puppet::Librarian.new(puppetfile, tmpmodules_dir, logger).resolve
1181
- ENV['SSL_CERT_FILE'] = '' if librarian_puppet_ssl_file
1182
- end
1183
- end
1184
-
1185
- def cp_command
1186
- return 'cp -force' if powershell_shell?
1187
- 'cp'
1188
- end
1189
-
1190
- def rm_command
1191
- return 'rm -force -recurse' if powershell_shell?
1192
- 'rm -rf'
1193
- end
1194
-
1195
- def mkdir_command
1196
- return 'mkdir -force -path' if powershell_shell?
1197
- 'mkdir -p'
1198
- end
1199
-
1200
- def rm_command_paths(paths)
1201
- return :nil if paths.length.zero?
1202
- return "#{rm_command} \"#{paths.join('", "')}\"" if powershell_shell?
1203
- "#{rm_command} #{paths.join(' ')}"
1204
- end
1205
- end
1206
- end
1207
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Chris Lundquist (<chris.lundquist@github.com>) Neill Turner (<neillwturner@gmail.com>)
4
+ #
5
+ # Copyright (C) 2013,2014 Chris Lundquist, 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-puppet/blob/master/provisioner_options.md
20
+ # for documentation configuration parameters with puppet_apply provisioner.
21
+ #
22
+
23
+ require 'uri'
24
+ require 'json'
25
+ require 'kitchen'
26
+ require 'kitchen/provisioner/puppet/librarian'
27
+
28
+ module Kitchen
29
+ class Busser
30
+ def non_suite_dirs
31
+ %w(data data_bags environments nodes roles puppet)
32
+ end
33
+ end
34
+
35
+ module Configurable
36
+ def platform_name
37
+ instance.platform.name
38
+ end
39
+ end
40
+
41
+ module Provisioner
42
+ #
43
+ # Puppet Apply provisioner.
44
+ #
45
+ class PuppetApply < Base
46
+ attr_accessor :tmp_dir
47
+
48
+ default_config :require_puppet_collections, false
49
+ default_config :puppet_yum_collections_repo, 'http://yum.puppetlabs.com/puppetlabs-release-pc1-el-6.noarch.rpm'
50
+ default_config :puppet_apt_collections_repo, 'http://apt.puppetlabs.com/puppetlabs-release-pc1-wheezy.deb'
51
+ default_config :puppet_coll_remote_path, '/opt/puppetlabs'
52
+ default_config :puppet_version, nil
53
+ default_config :facter_version, nil
54
+ default_config :hiera_version, nil
55
+ default_config :install_hiera, false
56
+ default_config :hiera_package, 'hiera-puppet'
57
+ default_config :require_puppet_repo, true
58
+ default_config :require_chef_for_busser, true
59
+ default_config :resolve_with_librarian_puppet, true
60
+ default_config :puppet_environment, nil
61
+ default_config :puppet_apt_repo, 'http://apt.puppetlabs.com/puppetlabs-release-precise.deb'
62
+ default_config :puppet_yum_repo, 'https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm'
63
+ default_config :chef_bootstrap_url, 'https://www.getchef.com/chef/install.sh'
64
+ default_config :puppet_logdest, nil
65
+ default_config :custom_install_command, nil
66
+ default_config :custom_pre_install_command, nil
67
+ default_config :custom_pre_apply_command, nil
68
+ default_config :puppet_whitelist_exit_code, nil
69
+ default_config :require_puppet_omnibus, false
70
+ default_config :puppet_omnibus_url, 'https://raw.githubusercontent.com/petems/puppet-install-shell/master/install_puppet.sh'
71
+ default_config :puppet_enc, nil
72
+ default_config :ignore_spec_fixtures, false
73
+
74
+ default_config :puppet_apply_command, nil
75
+
76
+ default_config :puppet_git_init, nil
77
+ default_config :puppet_git_pr, nil
78
+
79
+ default_config :http_proxy, nil
80
+ default_config :https_proxy, nil
81
+
82
+ default_config :ignored_paths_from_root, []
83
+ default_config :hiera_data_remote_path, '/var/lib/hiera'
84
+ default_config :manifest, 'site.pp'
85
+
86
+ default_config :manifests_path do |provisioner|
87
+ provisioner.calculate_path('manifests') ||
88
+ raise('No manifests_path detected. Please specify one in .kitchen.yml')
89
+ end
90
+
91
+ default_config :modules_path do |provisioner|
92
+ modules_path = provisioner.calculate_path('modules')
93
+ if modules_path.nil? && provisioner.calculate_path('Puppetfile', :file).nil?
94
+ raise('No modules_path detected. Please specify one in .kitchen.yml')
95
+ end
96
+ modules_path
97
+ end
98
+
99
+ default_config :files_path do |provisioner|
100
+ provisioner.calculate_path('files') || 'files'
101
+ end
102
+
103
+ default_config :hiera_data_path do |provisioner|
104
+ provisioner.calculate_path('hiera')
105
+ end
106
+
107
+ default_config :puppet_config_path do |provisioner|
108
+ provisioner.calculate_path('puppet.conf', :file)
109
+ end
110
+
111
+ default_config :hiera_config_path do |provisioner|
112
+ provisioner.calculate_path('hiera.yaml', :file)
113
+ end
114
+
115
+ default_config :fileserver_config_path do |provisioner|
116
+ provisioner.calculate_path('fileserver.conf', :file)
117
+ end
118
+ default_config :puppetfile_path do |provisioner|
119
+ provisioner.calculate_path('Puppetfile', :file)
120
+ end
121
+
122
+ default_config :modulefile_path do |provisioner|
123
+ provisioner.calculate_path('Modulefile', :file)
124
+ end
125
+
126
+ default_config :metadata_json_path do |provisioner|
127
+ provisioner.calculate_path('metadata.json', :file)
128
+ end
129
+
130
+ default_config :manifests_path do |provisioner|
131
+ provisioner.calculate_path('manifests', :directory)
132
+ end
133
+
134
+ default_config :spec_files_path do |provisioner|
135
+ provisioner.calculate_path('spec', :directory)
136
+ end
137
+
138
+ default_config :spec_files_remote_path, '/etc/puppet/spec'
139
+
140
+ default_config :puppet_debug, false
141
+ default_config :puppet_verbose, false
142
+ default_config :puppet_noop, false
143
+ default_config :platform, &:platform_name
144
+ default_config :update_package_repos, true
145
+ default_config :remove_puppet_repo, false
146
+ default_config :install_custom_facts, false
147
+ default_config :custom_facts, {}
148
+ default_config :facterlib, nil
149
+ default_config :puppet_detailed_exitcodes, nil
150
+ default_config :facter_file, nil
151
+ default_config :librarian_puppet_ssl_file, nil
152
+
153
+ default_config :hiera_eyaml, false
154
+ default_config :hiera_eyaml_key_remote_path, '/etc/puppet/secure/keys'
155
+
156
+ default_config :hiera_eyaml_key_path do |provisioner|
157
+ provisioner.calculate_path('hiera_keys')
158
+ end
159
+
160
+ default_config :hiera_deep_merge, false
161
+ default_config :puppet_no_sudo, false
162
+
163
+ def calculate_path(path, type = :directory)
164
+ base = config[:test_base_path]
165
+ candidates = []
166
+ candidates << File.join(base, instance.suite.name, 'puppet', path)
167
+ candidates << File.join(base, instance.suite.name, path)
168
+ candidates << File.join(base, path)
169
+ candidates << File.join(Dir.pwd, path)
170
+
171
+ candidates.find do |c|
172
+ type == :directory ? File.directory?(c) : File.file?(c)
173
+ end
174
+ end
175
+
176
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
177
+ def install_command
178
+ return unless config[:require_puppet_collections] || config[:require_puppet_repo] || config[:require_puppet_omnibus]
179
+ if config[:require_puppet_omnibus]
180
+ install_omnibus_command
181
+ elsif config[:require_puppet_collections]
182
+ install_command_collections
183
+ else
184
+ case puppet_platform
185
+ when 'debian', 'ubuntu'
186
+ info("Installing puppet on #{config[:platform]}")
187
+ # need to add a CR to avoid trouble with proxy settings concatenation
188
+ <<-INSTALL
189
+
190
+ #{custom_pre_install_command}
191
+ if [ ! $(which puppet) ]; then
192
+ #{sudo('apt-get')} -y install wget
193
+ #{sudo('wget')} #{wget_proxy_parm} #{puppet_apt_repo}
194
+ #{sudo('dpkg')} -i #{puppet_apt_repo_file}
195
+ #{update_packages_debian_cmd}
196
+ #{sudo_env('apt-get')} -y install facter#{facter_debian_version}
197
+ #{sudo_env('apt-get')} -y install puppet-common#{puppet_debian_version}
198
+ #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
199
+ #{install_hiera}
200
+ fi
201
+ #{install_eyaml}
202
+ #{install_deep_merge}
203
+ #{install_busser}
204
+ #{custom_install_command}
205
+ INSTALL
206
+ when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
207
+ info("Installing puppet from yum on #{puppet_platform}")
208
+ # need to add a CR to avoid trouble with proxy settings concatenation
209
+ <<-INSTALL
210
+
211
+ #{custom_pre_install_command}
212
+ if [ ! $(which puppet) ]; then
213
+ #{install_puppet_yum_repo}
214
+ fi
215
+ #{install_eyaml}
216
+ #{install_deep_merge}
217
+ #{install_busser}
218
+ #{custom_install_command}
219
+ INSTALL
220
+ when /^windows.*/
221
+ info("Installing puppet on #{puppet_platform}")
222
+ <<-INSTALL
223
+ if(Get-Command puppet -ErrorAction 0) { return; }
224
+ if( [Environment]::Is64BitOperatingSystem ) {
225
+ $MsiUrl = "https://downloads.puppetlabs.com/windows/puppet-#{puppet_windows_version}-x64.msi"
226
+ } else {
227
+ $MsiUrl = "https://downloads.puppetlabs.com/windows/puppet-#{puppet_windows_version}.msi"
228
+ }
229
+ $process = Start-Process -FilePath msiexec.exe -Wait -PassThru -ArgumentList '/qn', '/norestart', '/i', $MsiUrl
230
+ if ($process.ExitCode -ne 0) {
231
+ Write-Host "Installer failed."
232
+ Exit 1
233
+ }
234
+
235
+ #{install_busser}
236
+ INSTALL
237
+ else
238
+ info('Installing puppet, will try to determine platform os')
239
+ # need to add a CR to avoid trouble with proxy settings concatenation
240
+ <<-INSTALL
241
+
242
+ #{custom_pre_install_command}
243
+ if [ ! $(which puppet) ]; then
244
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
245
+ #{install_puppet_yum_repo}
246
+ else
247
+ if [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
248
+ #{install_puppet_yum_repo}
249
+ else
250
+ #{sudo('apt-get')} -y install wget
251
+ #{sudo('wget')} #{wget_proxy_parm} #{puppet_apt_repo}
252
+ #{sudo('dpkg')} -i #{puppet_apt_repo_file}
253
+ #{update_packages_debian_cmd}
254
+ #{sudo_env('apt-get')} -y install facter#{facter_debian_version}
255
+ #{sudo_env('apt-get')} -y install puppet-common#{puppet_debian_version}
256
+ #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
257
+ #{install_hiera}
258
+ fi
259
+ fi
260
+ fi
261
+ #{install_eyaml}
262
+ #{install_deep_merge}
263
+ #{install_busser}
264
+ #{custom_install_command}
265
+ INSTALL
266
+ end
267
+ end
268
+ end
269
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
270
+
271
+ def install_command_collections
272
+ case puppet_platform
273
+ when 'debian', 'ubuntu'
274
+ info("Installing Puppet Collections on #{puppet_platform}")
275
+ <<-INSTALL
276
+
277
+ #{Util.shell_helpers}
278
+ #{custom_pre_install_command}
279
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
280
+ if [ ! -f "#{config[:puppet_apt_collections_repo]}" ]; then
281
+ #{sudo('apt-get')} -y install wget
282
+ #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
283
+ fi
284
+ #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
285
+ #{sudo('apt-get')} update
286
+ #{sudo_env('apt-get')} -y install puppet-agent#{puppet_debian_version}
287
+ fi
288
+ #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
289
+ #{install_deep_merge}
290
+ #{install_busser}
291
+ #{custom_install_command}
292
+ INSTALL
293
+ when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
294
+ info("Installing Puppet Collections on #{puppet_platform}")
295
+ <<-INSTALL
296
+
297
+ #{Util.shell_helpers}
298
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
299
+ echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
300
+ #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
301
+ #{sudo_env('yum')} -y install puppet-agent#{puppet_redhat_version}
302
+ fi
303
+ #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
304
+ #{install_deep_merge}
305
+ #{install_busser}
306
+ #{custom_install_command}
307
+ INSTALL
308
+ else
309
+ info('Installing Puppet Collections, will try to determine platform os')
310
+ <<-INSTALL
311
+
312
+ #{Util.shell_helpers}
313
+ #{custom_pre_install_command}
314
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
315
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ] || \
316
+ [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
317
+ echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
318
+ #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
319
+ #{sudo_env('yum')} -y install puppet-agent#{puppet_redhat_version}
320
+ else
321
+ #{sudo('apt-get')} -y install wget
322
+ #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
323
+ #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
324
+ #{sudo('apt-get')} update
325
+ #{sudo_env('apt-get')} -y install puppet-agent#{puppet_debian_version}
326
+ fi
327
+ fi
328
+ #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
329
+ #{install_deep_merge}
330
+ #{install_busser}
331
+ #{custom_install_command}
332
+ INSTALL
333
+ end
334
+ end
335
+
336
+ def install_deep_merge
337
+ return unless config[:hiera_deep_merge]
338
+ <<-INSTALL
339
+ # Support for hash merge lookups to recursively merge hash keys
340
+ if [[ $(#{sudo('gem')} list deep_merge -i) == 'false' ]]; then
341
+ echo '-----> Installing deep_merge to provide deep_merge of hiera hashes'
342
+ #{sudo('gem')} install #{gem_proxy_parm} --no-ri --no-rdoc deep_merge
343
+ fi
344
+ INSTALL
345
+ end
346
+
347
+ def install_eyaml(gem_cmd = 'gem')
348
+ return unless config[:hiera_eyaml]
349
+ <<-INSTALL
350
+ # A backend for Hiera that provides per-value asymmetric encryption of sensitive data
351
+ if [[ $(#{sudo(gem_cmd)} list hiera-eyaml -i) == 'false' ]]; then
352
+ echo '-----> Installing hiera-eyaml to provide encryption of hiera data'
353
+ #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc highline -v 1.6.21
354
+ #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc hiera-eyaml
355
+ fi
356
+ INSTALL
357
+ end
358
+
359
+ def install_busser
360
+ return unless config[:require_chef_for_busser]
361
+ info("Install busser on #{puppet_platform}")
362
+ case puppet_platform
363
+ when /^windows.*/
364
+ # https://raw.githubusercontent.com/opscode/knife-windows/master/lib/chef/knife/bootstrap/windows-chef-client-msi.erb
365
+ <<-INSTALL
366
+ $webclient = New-Object System.Net.WebClient; $webclient.DownloadFile('https://opscode-omnibus-packages.s3.amazonaws.com/windows/2008r2/x86_64/chef-windows-11.12.8-1.windows.msi','chef-windows-11.12.8-1.windows.msi')
367
+ msiexec /qn /i chef-windows-11.12.8-1.windows.msi
368
+
369
+ cmd.exe /C "SET PATH=%PATH%;`"C:\\opscode\\chef\\embedded\\bin`";`"C:\\tmp\\busser\\gems\\bin`""
370
+
371
+ INSTALL
372
+ else
373
+ <<-INSTALL
374
+ #{Util.shell_helpers}
375
+ # install chef omnibus so that busser works as this is needed to run tests :(
376
+ # TODO: work out how to install enough ruby
377
+ # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
378
+ # whole chef client
379
+ if [ ! -d "/opt/chef" ]
380
+ then
381
+ echo '-----> Installing Chef Omnibus to install busser to run tests'
382
+ #{export_http_proxy_parm}
383
+ #{export_https_proxy_parm}
384
+ do_download #{chef_url} /tmp/install.sh
385
+ #{sudo('sh')} /tmp/install.sh
386
+ fi
387
+ INSTALL
388
+ end
389
+ end
390
+
391
+ def install_omnibus_command
392
+ info('Installing puppet using puppet omnibus')
393
+
394
+ version = ''
395
+ version = "-v #{config[:puppet_version]}" unless config[:puppet_version].nil?
396
+
397
+ <<-INSTALL
398
+ #{Util.shell_helpers}
399
+ if [ ! $(which puppet) ]; then
400
+ echo "-----> Installing Puppet Omnibus"
401
+ #{export_http_proxy_parm}
402
+ #{export_https_proxy_parm}
403
+ do_download #{config[:puppet_omnibus_url]} /tmp/install_puppet.sh
404
+ #{sudo_env('sh')} /tmp/install_puppet.sh #{version}
405
+ fi
406
+ INSTALL
407
+ end
408
+
409
+ def install_hiera
410
+ return unless config[:install_hiera]
411
+ <<-INSTALL
412
+ #{sudo_env('apt-get')} -y install #{hiera_package}
413
+ INSTALL
414
+ end
415
+
416
+ def hiera_package
417
+ "#{config[:hiera_package]}#{puppet_hiera_debian_version}"
418
+ end
419
+
420
+ # /bin/wget -P /etc/pki/rpm-gpg/ http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
421
+ # changed to curl
422
+
423
+ def install_puppet_yum_repo
424
+ <<-INSTALL
425
+ rhelversion=$(cat /etc/redhat-release | grep 'release 7')
426
+ # For CentOS7/RHEL7 the rdo release contains puppetlabs repo, creating conflict. Create temp-repo
427
+ #{sudo_env('curl')} -o /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
428
+ if [ -n "$rhelversion" ]; then
429
+ echo '[puppettemp-products]
430
+ name=Puppet Labs Products - \$basearch
431
+ baseurl=http://yum.puppetlabs.com/el/7/products/\$basearch
432
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
433
+ enabled=0
434
+ gpgcheck=1
435
+ [puppettemp-deps]
436
+ name=Puppet Labs Dependencies - \$basearch
437
+ baseurl=http://yum.puppetlabs.com/el/7/dependencies/\$basearch
438
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
439
+ enabled=0
440
+ gpgcheck=1' | sudo tee /etc/yum.repos.d/puppettemp.repo > /dev/null
441
+ sudo sed -i 's/^[ \t]*//' /etc/yum.repos.d/puppettemp.repo
442
+ #{update_packages_redhat_cmd}
443
+ #{sudo_env('yum')} -y --enablerepo=puppettemp-products --enablerepo=puppettemp-deps install puppet#{puppet_redhat_version}
444
+ # Clean up temporary puppet repo
445
+ sudo rm -rf /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
446
+ sudo rm -rf /etc/yum.repos.d/puppettemp.repo
447
+ else
448
+ #{sudo('rpm')} -ivh #{proxy_parm} #{puppet_yum_repo}
449
+ #{update_packages_redhat_cmd}
450
+ #{sudo_env('yum')} -y install puppet#{puppet_redhat_version}
451
+ fi
452
+ INSTALL
453
+ end
454
+
455
+ def custom_pre_install_command
456
+ <<-INSTALL
457
+ #{config[:custom_pre_install_command]}
458
+ INSTALL
459
+ end
460
+
461
+ def custom_install_command
462
+ <<-INSTALL
463
+ #{config[:custom_install_command]}
464
+ INSTALL
465
+ end
466
+
467
+ def init_command
468
+ todelete = %w(modules manifests files hiera hiera.yaml facter spec enc)
469
+ .map { |dir| File.join(config[:root_path], dir) }
470
+ todelete += [hiera_data_remote_path,
471
+ '/etc/hiera.yaml',
472
+ "#{puppet_dir}/hiera.yaml",
473
+ spec_files_remote_path.to_s,
474
+ "#{puppet_dir}/fileserver.conf"]
475
+ todelete << File.join(puppet_dir, config[:puppet_environment]) if config[:puppet_environment]
476
+ cmd = "#{sudo(rm_command_paths(todelete))};"
477
+ cmd += " #{mkdir_command} #{config[:root_path]};"
478
+ cmd += " #{sudo(mkdir_command)} #{puppet_dir}"
479
+ debug(cmd)
480
+ cmd
481
+ end
482
+
483
+ def create_sandbox
484
+ super
485
+ debug("Creating local sandbox in #{sandbox_path}")
486
+ yield if block_given?
487
+ prepare_modules
488
+ prepare_manifests
489
+ prepare_files
490
+ prepare_facter_file
491
+ prepare_facts
492
+ prepare_puppet_config
493
+ prepare_hiera_config
494
+ prepare_fileserver_config
495
+ prepare_hiera_data
496
+ prepare_enc
497
+ prepare_spec_files
498
+ info('Finished Preparing files for transfer')
499
+ end
500
+
501
+ def cleanup_sandbox
502
+ return if sandbox_path.nil?
503
+ debug("Cleaning up local sandbox in #{sandbox_path}")
504
+ FileUtils.rmtree(sandbox_path)
505
+ return if remove_repo.nil?
506
+ debug("Cleaning up remote sandbox: #{remove_repo}")
507
+ instance.remote_exec remove_repo
508
+ end
509
+
510
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
511
+ def prepare_command
512
+ commands = []
513
+ if puppet_git_init
514
+ commands << [
515
+ sudo('rm -rf'), '/etc/puppet'
516
+ ].join(' ')
517
+
518
+ commands << [
519
+ sudo('git clone'), puppet_git_init, '/etc/puppet'
520
+ ].join(' ')
521
+ end
522
+
523
+ if puppet_git_pr
524
+ commands << [
525
+ sudo('git'),
526
+ '--git-dir=/etc/puppet/.git/',
527
+ 'fetch -f',
528
+ 'origin',
529
+ "pull/#{puppet_git_pr}/head:pr_#{puppet_git_pr}"
530
+ ].join(' ')
531
+
532
+ commands << [
533
+ sudo('git'),
534
+ '--git-dir=/etc/puppet/.git/',
535
+ '--work-tree=/etc/puppet/',
536
+ 'checkout',
537
+ "pr_#{puppet_git_pr}"
538
+ ].join(' ')
539
+ end
540
+
541
+ if puppet_config
542
+ commands << [
543
+ sudo(cp_command),
544
+ File.join(config[:root_path], 'puppet.conf'),
545
+ puppet_dir
546
+ ].join(' ')
547
+ end
548
+
549
+ if hiera_config
550
+ commands << [
551
+ sudo(cp_command), File.join(config[:root_path], 'hiera.yaml'), '/etc/'
552
+ ].join(' ')
553
+
554
+ commands << [
555
+ sudo(cp_command), File.join(config[:root_path], 'hiera.yaml'), hiera_config_dir
556
+ ].join(' ')
557
+ end
558
+
559
+ if fileserver_config
560
+ commands << [
561
+ sudo(cp_command),
562
+ File.join(config[:root_path], 'fileserver.conf'),
563
+ puppet_dir
564
+ ].join(' ')
565
+ end
566
+
567
+ if hiera_data && hiera_data_remote_path == '/var/lib/hiera'
568
+ commands << [
569
+ sudo("#{cp_command} -r"), File.join(config[:root_path], 'hiera'), '/var/lib/'
570
+ ].join(' ')
571
+ end
572
+
573
+ if hiera_data && hiera_data_remote_path != '/var/lib/hiera'
574
+ commands << [
575
+ sudo(mkdir_command), hiera_data_remote_path
576
+ ].join(' ')
577
+ commands << [
578
+ sudo("#{cp_command} -r"), File.join(config[:root_path], 'hiera/*'), hiera_data_remote_path
579
+ ].join(' ')
580
+ end
581
+
582
+ if hiera_eyaml
583
+ commands << [
584
+ sudo(mkdir_command), hiera_eyaml_key_remote_path
585
+ ].join(' ')
586
+ commands << [
587
+ sudo("#{cp_command} -r"), File.join(config[:root_path], 'hiera_keys/*'), hiera_eyaml_key_remote_path
588
+ ].join(' ')
589
+ end
590
+
591
+ if puppet_environment
592
+ commands << [
593
+ sudo('ln -s '), config[:root_path], File.join(puppet_dir, config[:puppet_environment])
594
+ ].join(' ')
595
+ end
596
+
597
+ if spec_files_path && spec_files_remote_path
598
+ commands << [
599
+ sudo(mkdir_command), spec_files_remote_path
600
+ ].join(' ')
601
+ commands << [
602
+ sudo("#{cp_command} -r"), File.join(config[:root_path], 'spec/*'), spec_files_remote_path
603
+ ].join(' ')
604
+ end
605
+
606
+ if config[:puppet_enc]
607
+ commands << [
608
+ sudo('chmod 755'), File.join("#{config[:root_path]}/enc", File.basename(config[:puppet_enc]))
609
+ ].join(' ')
610
+ end
611
+
612
+ command = powershell_shell? ? commands.join('; ') : commands.join(' && ')
613
+ debug(command)
614
+ command
615
+ end
616
+
617
+ def run_command
618
+ if !config[:puppet_apply_command].nil?
619
+ return config[:puppet_apply_command]
620
+ else
621
+ result = [
622
+ facterlib,
623
+ custom_facts,
624
+ puppet_manifestdir,
625
+ puppet_cmd,
626
+ 'apply',
627
+ File.join(config[:root_path], 'manifests', manifest),
628
+ "--modulepath=#{File.join(config[:root_path], 'modules')}",
629
+ "--fileserverconfig=#{File.join(config[:root_path], 'fileserver.conf')}",
630
+ custom_options,
631
+ puppet_environment_flag,
632
+ puppet_noop_flag,
633
+ puppet_enc_flag,
634
+ puppet_detailed_exitcodes_flag,
635
+ puppet_verbose_flag,
636
+ puppet_debug_flag,
637
+ puppet_logdest_flag,
638
+ puppet_whitelist_exit_code
639
+ ].join(' ')
640
+ if config[:custom_post_apply_command]
641
+ custom_post_apply_trap = <<-TRAP
642
+ function custom_post_apply_command {
643
+ #{config[:custom_post_apply_command]}
644
+ }
645
+ trap custom_post_apply_command EXIT
646
+ TRAP
647
+ end
648
+ result = <<-RUN
649
+ #{config[:custom_pre_apply_command]}
650
+ #{custom_post_apply_trap}
651
+ #{result}
652
+ RUN
653
+ info("Going to invoke puppet apply with: #{result}")
654
+ result
655
+ end
656
+ end
657
+
658
+ protected
659
+
660
+ def load_needed_dependencies!
661
+ return unless File.exist?(puppetfile)
662
+ return unless config[:resolve_with_librarian_puppet]
663
+ debug("Puppetfile found at #{puppetfile}, loading Librarian-Puppet")
664
+ Puppet::Librarian.load!(logger)
665
+ end
666
+
667
+ def tmpmodules_dir
668
+ File.join(sandbox_path, 'modules')
669
+ end
670
+
671
+ def puppetfile
672
+ config[:puppetfile_path] || ''
673
+ end
674
+
675
+ def modulefile
676
+ config[:modulefile_path] || ''
677
+ end
678
+
679
+ def metadata_json
680
+ config[:metadata_json_path] || ''
681
+ end
682
+
683
+ def manifest
684
+ config[:manifest]
685
+ end
686
+
687
+ def manifests
688
+ config[:manifests_path]
689
+ end
690
+
691
+ def modules
692
+ config[:modules_path]
693
+ end
694
+
695
+ def files
696
+ config[:files_path] || 'files'
697
+ end
698
+
699
+ def puppet_config
700
+ config[:puppet_config_path]
701
+ end
702
+
703
+ def puppet_environment
704
+ config[:puppet_environment]
705
+ end
706
+
707
+ def puppet_git_init
708
+ config[:puppet_git_init]
709
+ end
710
+
711
+ def puppet_git_pr
712
+ config[:puppet_git_pr]
713
+ end
714
+
715
+ def hiera_config
716
+ config[:hiera_config_path]
717
+ end
718
+
719
+ def fileserver_config
720
+ config[:fileserver_config_path]
721
+ end
722
+
723
+ def hiera_data
724
+ config[:hiera_data_path]
725
+ end
726
+
727
+ def hiera_data_remote_path
728
+ config[:hiera_data_remote_path]
729
+ end
730
+
731
+ def hiera_eyaml
732
+ config[:hiera_eyaml]
733
+ end
734
+
735
+ def hiera_eyaml_key_path
736
+ config[:hiera_eyaml_key_path]
737
+ end
738
+
739
+ def hiera_eyaml_key_remote_path
740
+ config[:hiera_eyaml_key_remote_path]
741
+ end
742
+
743
+ def hiera_deep_merge
744
+ config[:hiera_deep_merge]
745
+ end
746
+
747
+ def librarian_puppet_ssl_file
748
+ config[:librarian_puppet_ssl_file]
749
+ end
750
+
751
+ def puppet_cmd
752
+ puppet_bin = powershell_shell? ? '& "C:\Program Files\Puppet Labs\Puppet\bin\puppet"' : 'puppet'
753
+ if config[:require_puppet_collections]
754
+ puppet_bin = "#{config[:puppet_coll_remote_path]}/bin/puppet"
755
+ end
756
+
757
+ if config[:puppet_no_sudo]
758
+ puppet_bin
759
+ else
760
+ sudo_env(puppet_bin)
761
+ end
762
+ end
763
+
764
+ def puppet_dir
765
+ return '/etc/puppetlabs/puppet' if config[:require_puppet_collections]
766
+ return '/etc/puppet' unless powershell_shell?
767
+ 'C:/ProgramData/PuppetLabs/puppet/etc'
768
+ end
769
+
770
+ def hiera_config_dir
771
+ return '/etc/puppetlabs/code' if config[:require_puppet_collections]
772
+ return '/etc/puppet' unless powershell_shell?
773
+ 'C:/ProgramData/PuppetLabs/puppet/etc'
774
+ end
775
+
776
+ def puppet_debian_version
777
+ config[:puppet_version] ? "=#{config[:puppet_version]}" : nil
778
+ end
779
+
780
+ def facter_debian_version
781
+ config[:facter_version] ? "=#{config[:facter_version]}" : nil
782
+ end
783
+
784
+ def puppet_hiera_debian_version
785
+ config[:hiera_version] ? "=#{config[:hiera_version]}" : nil
786
+ end
787
+
788
+ def puppet_redhat_version
789
+ if puppet_platform == 'amazon'
790
+ config[:puppet_version]
791
+ else
792
+ config[:puppet_version] ? "-#{config[:puppet_version]}" : nil
793
+ end
794
+ end
795
+
796
+ def puppet_windows_version
797
+ config[:puppet_version] ? config[:puppet_version].to_s : '3.8.6'
798
+ end
799
+
800
+ def puppet_environment_flag
801
+ if config[:puppet_version] =~ /^2/
802
+ config[:puppet_environment] ? "--environment=#{config[:puppet_environment]}" : nil
803
+ else
804
+ config[:puppet_environment] ? "--environment=#{config[:puppet_environment]} --environmentpath=#{puppet_dir}" : nil
805
+ end
806
+ end
807
+
808
+ def puppet_manifestdir
809
+ return nil if config[:require_puppet_collections]
810
+ return nil if config[:puppet_environment]
811
+ return nil if powershell_shell?
812
+ bash_vars = "export MANIFESTDIR='#{File.join(config[:root_path], 'manifests')}';"
813
+ debug(bash_vars)
814
+ bash_vars
815
+ end
816
+
817
+ def custom_options
818
+ config[:custom_options] || ''
819
+ end
820
+
821
+ def puppet_noop_flag
822
+ config[:puppet_noop] ? '--noop' : nil
823
+ end
824
+
825
+ def puppet_debug_flag
826
+ config[:puppet_debug] ? '-d' : nil
827
+ end
828
+
829
+ def puppet_verbose_flag
830
+ config[:puppet_verbose] ? '-v' : nil
831
+ end
832
+
833
+ def puppet_logdest_flag
834
+ return nil unless config[:puppet_logdest]
835
+ destinations = ''
836
+ config[:puppet_logdest].each do |dest|
837
+ destinations << "--logdest #{dest} "
838
+ end
839
+ destinations
840
+ end
841
+
842
+ def puppet_platform
843
+ config[:platform].gsub(/-.*/, '')
844
+ end
845
+
846
+ def update_packages_debian_cmd
847
+ config[:update_package_repos] ? "#{sudo_env('apt-get')} update" : nil
848
+ end
849
+
850
+ def update_packages_redhat_cmd
851
+ # #{sudo('yum')}
852
+ config[:update_package_repos] ? "#{sudo_env('yum')} makecache" : nil
853
+ end
854
+
855
+ def sudo_env(pm)
856
+ s = https_proxy ? "https_proxy=#{https_proxy}" : nil
857
+ p = http_proxy ? "http_proxy=#{http_proxy}" : nil
858
+ p || s ? "#{sudo('env')} #{p} #{s} #{pm}" : sudo(pm).to_s
859
+ end
860
+
861
+ def remove_puppet_repo
862
+ config[:remove_puppet_repo]
863
+ end
864
+
865
+ def spec_files_path
866
+ config[:spec_files_path]
867
+ end
868
+
869
+ def spec_files_remote_path
870
+ config[:spec_files_remote_path]
871
+ end
872
+
873
+ def facterlib
874
+ factpath = nil
875
+ factpath = File.join(config[:root_path], 'facter').to_s if config[:install_custom_facts] && !config[:custom_facts].none?
876
+ factpath = File.join(config[:root_path], 'facter').to_s if config[:facter_file]
877
+ factpath = "#{factpath}:" if config[:facterlib] && !factpath.nil?
878
+ factpath = "#{factpath}#{config[:facterlib]}" if config[:facterlib]
879
+ return nil if factpath.nil?
880
+ bash_vars = "export FACTERLIB='#{factpath}';"
881
+ debug(bash_vars)
882
+ bash_vars
883
+ end
884
+
885
+ def custom_facts
886
+ return nil if config[:custom_facts].none?
887
+ return nil if config[:install_custom_facts]
888
+ if powershell_shell?
889
+ environment_vars = config[:custom_facts].map { |k, v| "$env:FACTER_#{k}='#{v}'" }.join('; ')
890
+ environment_vars = "#{environment_vars};"
891
+ else
892
+ environment_vars = config[:custom_facts].map { |k, v| "FACTER_#{k}=#{v}" }.join(' ')
893
+ environment_vars = "export #{environment_vars};"
894
+ end
895
+ debug(environment_vars)
896
+ environment_vars
897
+ end
898
+
899
+ def puppet_enc_flag
900
+ config[:puppet_enc] ? "--node_terminus=exec --external_nodes=#{config[:root_path]}/enc/#{File.basename(config[:puppet_enc])}" : nil
901
+ end
902
+
903
+ def puppet_detailed_exitcodes_flag
904
+ config[:puppet_detailed_exitcodes] ? '--detailed-exitcodes' : nil
905
+ end
906
+
907
+ def remove_repo
908
+ remove_puppet_repo ? "#{sudo('rm')} -rf /tmp/kitchen #{hiera_data_remote_path} #{hiera_eyaml_key_remote_path} #{puppet_dir}/* " : nil
909
+ end
910
+
911
+ def puppet_whitelist_exit_code
912
+ if config[:puppet_whitelist_exit_code].nil?
913
+ return powershell_shell? ? '; exit $LASTEXITCODE' : nil
914
+ elsif powershell_shell?
915
+ return "; if(@(#{[config[:puppet_whitelist_exit_code]].join(', ')}) -contains $LASTEXITCODE) {exit 0} else {exit $LASTEXITCODE}"
916
+ else
917
+ return "; [ $? -eq #{config[:puppet_whitelist_exit_code]} ] && exit 0"
918
+ end
919
+ end
920
+
921
+ def puppet_apt_repo
922
+ platform_version = config[:platform].partition('-')[2]
923
+ case puppet_platform
924
+ when 'ubuntu'
925
+ case platform_version
926
+ when '14.10'
927
+ # Utopic Repo
928
+ 'https://apt.puppetlabs.com/puppetlabs-release-utopic.deb'
929
+ when '14.04'
930
+ # Trusty Repo
931
+ 'https://apt.puppetlabs.com/puppetlabs-release-trusty.deb'
932
+ when '12.04'
933
+ # Precise Repo
934
+ 'https://apt.puppetlabs.com/puppetlabs-release-precise.deb'
935
+ else
936
+ # Configured Repo
937
+ config[:puppet_apt_repo]
938
+ end
939
+ when 'debian'
940
+ case platform_version.gsub(/\..*/, '')
941
+ when '8'
942
+ # Debian Jessie
943
+ 'https://apt.puppetlabs.com/puppetlabs-release-jessie.deb'
944
+ when '7'
945
+ # Debian Wheezy
946
+ 'https://apt.puppetlabs.com/puppetlabs-release-wheezy.deb'
947
+ when '6'
948
+ # Debian Squeeze
949
+ 'https://apt.puppetlabs.com/puppetlabs-release-squeeze.deb'
950
+ else
951
+ # Configured Repo
952
+ config[:puppet_apt_repo]
953
+ end
954
+ else
955
+ debug("Apt repo detection failed with platform - #{config[:platform]}")
956
+ false
957
+ end
958
+ end
959
+
960
+ def puppet_apt_repo_file
961
+ puppet_apt_repo.split('/').last if puppet_apt_repo
962
+ end
963
+
964
+ def puppet_apt_coll_repo_file
965
+ config[:puppet_apt_collections_repo].split('/').last
966
+ end
967
+
968
+ def puppet_yum_repo
969
+ config[:puppet_yum_repo]
970
+ end
971
+
972
+ def proxy_parm
973
+ http_proxy ? "--httpproxy #{URI.parse(http_proxy).host.downcase} --httpport #{URI.parse(http_proxy).port} " : nil
974
+ end
975
+
976
+ def gem_proxy_parm
977
+ http_proxy ? "--http-proxy #{http_proxy}" : nil
978
+ end
979
+
980
+ def wget_proxy_parm
981
+ p = http_proxy ? "-e http_proxy=#{http_proxy}" : nil
982
+ s = https_proxy ? "-e https_proxy=#{https_proxy}" : nil
983
+ p || s ? "-e use_proxy=yes #{p} #{s}" : nil
984
+ end
985
+
986
+ def export_http_proxy_parm
987
+ http_proxy ? "export http_proxy=#{http_proxy}" : nil
988
+ end
989
+
990
+ def export_https_proxy_parm
991
+ https_proxy ? "export https_proxy=#{https_proxy}" : nil
992
+ end
993
+
994
+ def http_proxy
995
+ config[:http_proxy]
996
+ end
997
+
998
+ def https_proxy
999
+ config[:https_proxy]
1000
+ end
1001
+
1002
+ def chef_url
1003
+ config[:chef_bootstrap_url]
1004
+ end
1005
+
1006
+ def prepare_manifests
1007
+ info('Preparing manifests')
1008
+ debug("Using manifests from #{manifests}")
1009
+
1010
+ tmp_manifests_dir = File.join(sandbox_path, 'manifests')
1011
+ FileUtils.mkdir_p(tmp_manifests_dir)
1012
+ FileUtils.cp_r(Dir.glob("#{manifests}/*"), tmp_manifests_dir)
1013
+ end
1014
+
1015
+ def prepare_files
1016
+ info('Preparing files')
1017
+ unless File.directory?(files)
1018
+ info 'nothing to do for files'
1019
+ return
1020
+ end
1021
+
1022
+ debug("Using files from #{files}")
1023
+
1024
+ tmp_files_dir = File.join(sandbox_path, 'files')
1025
+ FileUtils.mkdir_p(tmp_files_dir)
1026
+ FileUtils.cp_r(Dir.glob("#{files}/*"), tmp_files_dir)
1027
+ end
1028
+
1029
+ def prepare_facter_file
1030
+ return unless config[:facter_file]
1031
+ info 'Copying facter file'
1032
+ facter_dir = File.join(sandbox_path, 'facter')
1033
+ FileUtils.mkdir_p(facter_dir)
1034
+ FileUtils.cp_r(config[:facter_file], facter_dir)
1035
+ end
1036
+
1037
+ def prepare_facts
1038
+ return unless config[:install_custom_facts]
1039
+ return unless config[:custom_facts]
1040
+ info 'Installing custom facts'
1041
+ facter_dir = File.join(sandbox_path, 'facter')
1042
+ FileUtils.mkdir_p(facter_dir)
1043
+ tmp_facter_file = File.join(facter_dir, 'kitchen.rb')
1044
+ facter_facts = Hash[config[:custom_facts].map { |k, v| [k.to_s, v.to_s] }]
1045
+ File.open(tmp_facter_file, 'a') do |out|
1046
+ facter_facts.each do |k, v|
1047
+ out.write "\nFacter.add(:#{k}) do\n"
1048
+ out.write " setcode do\n"
1049
+ out.write " \"#{v}\"\n"
1050
+ out.write " end\n"
1051
+ out.write "end\n"
1052
+ end
1053
+ end
1054
+ end
1055
+
1056
+ def prepare_modules
1057
+ info('Preparing modules')
1058
+
1059
+ FileUtils.mkdir_p(tmpmodules_dir)
1060
+ resolve_with_librarian if File.exist?(puppetfile) && config[:resolve_with_librarian_puppet]
1061
+
1062
+ if modules && modules.include?(':')
1063
+ debug('Found multiple directories in module path merging.....')
1064
+ modules_array = modules.split(':')
1065
+ modules_array.each do |m|
1066
+ copy_modules(m, tmpmodules_dir)
1067
+ end
1068
+ elsif modules
1069
+ copy_modules(modules, tmpmodules_dir)
1070
+ else
1071
+ info 'nothing to do for modules'
1072
+ end
1073
+
1074
+ copy_self_as_module
1075
+ end
1076
+
1077
+ def copy_modules(source, destination)
1078
+ return unless File.directory?(source)
1079
+
1080
+ debug("Copying modules from #{source} to #{destination}")
1081
+
1082
+ excluded_paths = %w(modules spec pkg) + config[:ignored_paths_from_root]
1083
+
1084
+ Dir.glob("#{source}/*").each do |f|
1085
+ module_name = File.basename(f)
1086
+ target = "#{destination}/#{module_name}"
1087
+ FileUtils.mkdir_p(target) unless File.exist? target
1088
+ FileUtils.cp_r(Dir.glob("#{source}/#{module_name}/*").reject { |entry| entry =~ /#{excluded_paths.join('$|')}$/ }, target, remove_destination: true)
1089
+ end
1090
+ end
1091
+
1092
+ def copy_self_as_module
1093
+ if File.exist?(modulefile)
1094
+ warn('Modulefile found but this is depricated, ignoring it, see https://tickets.puppetlabs.com/browse/PUP-1188')
1095
+ end
1096
+
1097
+ return unless File.exist?(metadata_json)
1098
+ module_name = nil
1099
+ begin
1100
+ module_name = JSON.parse(IO.read(metadata_json))['name'].split('-').last
1101
+ rescue
1102
+ error("not able to load or parse #{metadata_json_path} for the name of the module")
1103
+ end
1104
+
1105
+ return unless module_name
1106
+ module_target_path = File.join(sandbox_path, 'modules', module_name)
1107
+ FileUtils.mkdir_p(module_target_path)
1108
+
1109
+ excluded_paths = %w(modules spec pkg) + config[:ignored_paths_from_root]
1110
+
1111
+ FileUtils.cp_r(
1112
+ Dir.glob(File.join(config[:kitchen_root], '*')).reject { |entry| entry =~ /#{excluded_paths.join('$|')}$/ },
1113
+ module_target_path,
1114
+ remove_destination: true
1115
+ )
1116
+ end
1117
+
1118
+ def prepare_puppet_config
1119
+ return unless puppet_config
1120
+
1121
+ info('Preparing puppet.conf')
1122
+ debug("Using puppet config from #{puppet_config}")
1123
+
1124
+ FileUtils.cp_r(puppet_config, File.join(sandbox_path, 'puppet.conf'))
1125
+ end
1126
+
1127
+ def prepare_enc
1128
+ return unless config[:puppet_enc]
1129
+ info 'Copying enc file'
1130
+ enc_dir = File.join(sandbox_path, 'enc')
1131
+ FileUtils.mkdir_p(enc_dir)
1132
+ FileUtils.cp_r(config[:puppet_enc], File.join(enc_dir, '/'))
1133
+ end
1134
+
1135
+ def prepare_hiera_config
1136
+ return unless hiera_config
1137
+
1138
+ info('Preparing hiera')
1139
+ debug("Using hiera from #{hiera_config}")
1140
+
1141
+ FileUtils.cp_r(hiera_config, File.join(sandbox_path, 'hiera.yaml'))
1142
+ end
1143
+
1144
+ def prepare_fileserver_config
1145
+ return unless fileserver_config
1146
+
1147
+ info('Preparing fileserver')
1148
+ debug("Using fileserver config from #{fileserver_config}")
1149
+
1150
+ FileUtils.cp_r(fileserver_config, File.join(sandbox_path, 'fileserver.conf'))
1151
+ end
1152
+
1153
+ def prepare_hiera_data
1154
+ return unless hiera_data
1155
+ info('Preparing hiera data')
1156
+ tmp_hiera_dir = File.join(sandbox_path, 'hiera')
1157
+ debug("Copying hiera data from #{hiera_data} to #{tmp_hiera_dir}")
1158
+ FileUtils.mkdir_p(tmp_hiera_dir)
1159
+ FileUtils.cp_r(Dir.glob("#{hiera_data}/*"), tmp_hiera_dir)
1160
+ return unless hiera_eyaml_key_path
1161
+ tmp_hiera_key_dir = File.join(sandbox_path, 'hiera_keys')
1162
+ debug("Copying hiera eyaml keys from #{hiera_eyaml_key_path} to #{tmp_hiera_key_dir}")
1163
+ FileUtils.mkdir_p(tmp_hiera_key_dir)
1164
+ FileUtils.cp_r(Dir.glob("#{hiera_eyaml_key_path}/*"), tmp_hiera_key_dir)
1165
+ end
1166
+
1167
+ def prepare_spec_files
1168
+ return unless spec_files_path
1169
+ info('Preparing spec files')
1170
+ tmp_spec_dir = File.join(sandbox_path, 'spec')
1171
+ debug("Copying specs from #{spec_files_path} to #{tmp_spec_dir}")
1172
+ FileUtils.mkdir_p(tmp_spec_dir)
1173
+ FileUtils.cp_r(Dir.glob(File.join(spec_files_path, '*')).reject { |entry| entry =~ /fixtures$/ }, tmp_spec_dir) if config[:ignore_spec_fixtures]
1174
+ FileUtils.cp_r(Dir.glob("#{spec_files_path}/*"), tmp_spec_dir) unless config[:ignore_spec_fixtures]
1175
+ end
1176
+
1177
+ def resolve_with_librarian
1178
+ Kitchen.mutex.synchronize do
1179
+ ENV['SSL_CERT_FILE'] = librarian_puppet_ssl_file if librarian_puppet_ssl_file
1180
+ Puppet::Librarian.new(puppetfile, tmpmodules_dir, logger).resolve
1181
+ ENV['SSL_CERT_FILE'] = '' if librarian_puppet_ssl_file
1182
+ end
1183
+ end
1184
+
1185
+ def cp_command
1186
+ return 'cp -force' if powershell_shell?
1187
+ 'cp'
1188
+ end
1189
+
1190
+ def rm_command
1191
+ return 'rm -force -recurse' if powershell_shell?
1192
+ 'rm -rf'
1193
+ end
1194
+
1195
+ def mkdir_command
1196
+ return 'mkdir -force -path' if powershell_shell?
1197
+ 'mkdir -p'
1198
+ end
1199
+
1200
+ def rm_command_paths(paths)
1201
+ return :nil if paths.length.zero?
1202
+ return "#{rm_command} \"#{paths.join('", "')}\"" if powershell_shell?
1203
+ "#{rm_command} #{paths.join(' ')}"
1204
+ end
1205
+ end
1206
+ end
1207
+ end