kitchen-puppet 0.0.27 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,846 +1,847 @@
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/provisioner/base'
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 Provisioner
36
- #
37
- # Puppet Apply provisioner.
38
- #
39
- class PuppetApply < Base
40
- attr_accessor :tmp_dir
41
-
42
- default_config :require_puppet_collections, false
43
- default_config :puppet_yum_collections_repo, 'http://yum.puppetlabs.com/puppetlabs-release-pc1-el-6.noarch.rpm'
44
- default_config :puppet_apt_collections_repo, 'http://apt.puppetlabs.com/puppetlabs-release-pc1-wheezy.deb'
45
- default_config :puppet_coll_remote_path, '/opt/puppetlabs'
46
- default_config :puppet_version, nil
47
- default_config :require_puppet_repo, true
48
- default_config :require_chef_for_busser, true
49
- default_config :resolve_with_librarian_puppet, true
50
- default_config :puppet_environment, nil
51
- default_config :install_custom_facts, false
52
- default_config :puppet_apt_repo, 'http://apt.puppetlabs.com/puppetlabs-release-precise.deb'
53
- default_config :puppet_yum_repo, 'https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm'
54
- default_config :chef_bootstrap_url, 'https://www.getchef.com/chef/install.sh'
55
- default_config :puppet_logdest, nil
56
-
57
- default_config :puppet_apply_command, nil
58
-
59
- default_config :puppet_git_init, nil
60
- default_config :puppet_git_pr, nil
61
-
62
- default_config :http_proxy, nil
63
- default_config :https_proxy, nil
64
-
65
- default_config :hiera_data_remote_path, '/var/lib/hiera'
66
- default_config :manifest, 'site.pp'
67
-
68
- default_config :manifests_path do |provisioner|
69
- provisioner.calculate_path('manifests') ||
70
- fail('No manifests_path detected. Please specify one in .kitchen.yml')
71
- end
72
-
73
- default_config :modules_path do |provisioner|
74
- modules_path = provisioner.calculate_path('modules')
75
- if modules_path.nil? && provisioner.calculate_path('Puppetfile', :file).nil?
76
- fail 'No modules_path detected. Please specify one in .kitchen.yml'
77
- end
78
- modules_path
79
- end
80
-
81
- default_config :files_path do |provisioner|
82
- provisioner.calculate_path('files') || 'files'
83
- end
84
-
85
- default_config :hiera_data_path do |provisioner|
86
- provisioner.calculate_path('hiera')
87
- end
88
-
89
- default_config :puppet_config_path do |provisioner|
90
- provisioner.calculate_path('puppet.conf', :file)
91
- end
92
-
93
- default_config :hiera_config_path do |provisioner|
94
- provisioner.calculate_path('hiera.yaml', :file)
95
- end
96
-
97
- default_config :fileserver_config_path do |provisioner|
98
- provisioner.calculate_path('fileserver.conf', :file)
99
- end
100
- default_config :puppetfile_path do |provisioner|
101
- provisioner.calculate_path('Puppetfile', :file)
102
- end
103
-
104
- default_config :modulefile_path do |provisioner|
105
- provisioner.calculate_path('Modulefile', :file)
106
- end
107
-
108
- default_config :metadata_json_path do |provisioner|
109
- provisioner.calculate_path('metadata.json', :file)
110
- end
111
-
112
- default_config :manifests_path do |provisioner|
113
- provisioner.calculate_path('manifests', :directory)
114
- end
115
-
116
- default_config :puppet_debug, false
117
- default_config :puppet_verbose, false
118
- default_config :puppet_noop, false
119
- default_config :puppet_platform, ''
120
- default_config :update_package_repos, true
121
- default_config :remove_puppet_repo, false
122
- default_config :custom_facts, {}
123
- default_config :puppet_detailed_exitcodes, nil
124
- default_config :facter_file, nil
125
- default_config :librarian_puppet_ssl_file, nil
126
-
127
- default_config :hiera_eyaml, false
128
- default_config :hiera_eyaml_key_remote_path, '/etc/puppet/secure/keys'
129
-
130
- default_config :hiera_eyaml_key_path do |provisioner|
131
- provisioner.calculate_path('hiera_keys')
132
- end
133
-
134
- default_config :hiera_deep_merge, false
135
-
136
- def calculate_path(path, type = :directory)
137
- base = config[:test_base_path]
138
- candidates = []
139
- candidates << File.join(base, instance.suite.name, 'puppet', path)
140
- candidates << File.join(base, instance.suite.name, path)
141
- candidates << File.join(base, path)
142
- candidates << File.join(Dir.pwd, path)
143
-
144
- candidates.find do |c|
145
- type == :directory ? File.directory?(c) : File.file?(c)
146
- end
147
- end
148
-
149
- # TODO: refactor for smaller cyclomatic complexity and perceived complexity
150
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
151
- def install_command
152
- return unless config[:require_puppet_collections] || config[:require_puppet_repo]
153
- if config[:require_puppet_collections]
154
- install_command_collections
155
- else
156
- case puppet_platform
157
- when 'debian', 'ubuntu'
158
- info("Installing puppet on #{puppet_platform}")
159
- <<-INSTALL
160
- if [ ! $(which puppet) ]; then
161
- #{sudo('apt-get')} -y install wget
162
- #{sudo('wget')} #{wget_proxy_parm} #{puppet_apt_repo}
163
- #{sudo('dpkg')} -i #{puppet_apt_repo_file}
164
- #{update_packages_debian_cmd}
165
- #{sudo_env('apt-get')} -y install puppet-common#{puppet_debian_version}
166
- #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
167
- fi
168
- #{install_eyaml}
169
- #{install_deep_merge}
170
- #{install_busser}
171
- INSTALL
172
- when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
173
- info("Installing puppet from yum on #{puppet_platform}")
174
- <<-INSTALL
175
- if [ ! $(which puppet) ]; then
176
- #{install_puppet_yum_repo}
177
- fi
178
- #{install_eyaml}
179
- #{install_deep_merge}
180
- #{install_busser}
181
- INSTALL
182
- else
183
- info('Installing puppet, will try to determine platform os')
184
- <<-INSTALL
185
- if [ ! $(which puppet) ]; then
186
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
187
- #{install_puppet_yum_repo}
188
- else
189
- if [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
190
- #{install_puppet_yum_repo}
191
- else
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 puppet-common#{puppet_debian_version}
197
- #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
198
- fi
199
- fi
200
- fi
201
- #{install_eyaml}
202
- #{install_deep_merge}
203
- #{install_busser}
204
- INSTALL
205
- end
206
- end
207
- end
208
-
209
- def install_command_collections
210
- case puppet_platform
211
- when 'debian', 'ubuntu'
212
- info("Installing Puppet Collections on #{puppet_platform}")
213
- <<-INSTALL
214
- #{sudo('apt-get')} -y install wget
215
- #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
216
- #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
217
- INSTALL
218
- when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
219
- info("Installing Puppet Collections on #{puppet_platform}")
220
- <<-INSTALL
221
- #{Util.shell_helpers}
222
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
223
- echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
224
- #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
225
- #{sudo_env('yum')} -y install puppet
226
- fi
227
- #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
228
- #{install_deep_merge}
229
- #{install_busser}
230
- INSTALL
231
- else
232
- info('Installing Puppet Collections, will try to determine platform os')
233
- <<-INSTALL
234
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
235
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
236
- #{Util.shell_helpers}
237
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
238
- echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
239
- #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
240
- #{sudo_env('yum')} -y install puppet
241
- fi
242
- else
243
- if [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
244
- #{Util.shell_helpers}
245
- if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
246
- echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
247
- #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
248
- #{sudo_env('yum')} -y install puppet
249
- fi
250
- else
251
- #{sudo('apt-get')} -y install wget
252
- #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
253
- #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
254
- fi
255
- fi
256
- fi
257
- #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
258
- #{install_deep_merge}
259
- #{install_busser}
260
- INSTALL
261
- end
262
- end
263
-
264
- def install_deep_merge
265
- return unless config[:hiera_deep_merge]
266
- <<-INSTALL
267
- # Support for hash merge lookups to recursively merge hash keys
268
- if [[ $(#{sudo('gem')} list deep_merge -i) == 'false' ]]; then
269
- echo '-----> Installing deep_merge to provide deep_merge of hiera hashes'
270
- #{sudo('gem')} install #{gem_proxy_parm} --no-ri --no-rdoc deep_merge
271
- fi
272
- INSTALL
273
- end
274
-
275
- def install_eyaml(gem_cmd = 'gem')
276
- return unless config[:hiera_eyaml]
277
- <<-INSTALL
278
- # A backend for Hiera that provides per-value asymmetric encryption of sensitive data
279
- if [[ $(#{sudo(gem_cmd)} list hiera-eyaml -i) == 'false' ]]; then
280
- echo '-----> Installing hiera-eyaml to provide encryption of hiera data'
281
- #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc highline -v 1.6.21
282
- #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc hiera-eyaml
283
- fi
284
- INSTALL
285
- end
286
-
287
- def install_busser
288
- return unless config[:require_chef_for_busser]
289
- <<-INSTALL
290
- #{Util.shell_helpers}
291
- # install chef omnibus so that busser works as this is needed to run tests :(
292
- # TODO: work out how to install enough ruby
293
- # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
294
- # whole chef client
295
- if [ ! -d "/opt/chef" ]
296
- then
297
- echo '-----> Installing Chef Omnibus to install busser to run tests'
298
- do_download #{chef_url} /tmp/install.sh
299
- #{sudo('sh')} /tmp/install.sh
300
- fi
301
- INSTALL
302
- end
303
-
304
- # /bin/wget -P /etc/pki/rpm-gpg/ http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
305
- # changed to curl
306
-
307
- def install_puppet_yum_repo
308
- <<-INSTALL
309
- rhelversion=$(cat /etc/redhat-release | grep release\ 7)
310
- # For CentOS7/RHEL7 the rdo release contains puppetlabs repo, creating conflict. Create temp-repo
311
- #{sudo_env('curl')} -o /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
312
- if [ -n "$rhelversion" ]; then
313
- echo '[puppettemp-products]
314
- name=Puppet Labs Products - \$basearch
315
- baseurl=http://yum.puppetlabs.com/el/7/products/\$basearch
316
- gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
317
- enabled=0
318
- gpgcheck=1
319
- [puppettemp-deps]
320
- name=Puppet Labs Dependencies - \$basearch
321
- baseurl=http://yum.puppetlabs.com/el/7/dependencies/\$basearch
322
- gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
323
- enabled=0
324
- gpgcheck=1' >> /etc/yum.repos.d/puppettemp.repo
325
- #{update_packages_redhat_cmd}
326
- #{sudo_env('yum')} -y --enablerepo=puppettemp-products --enablerepo=puppettemp-deps install puppet#{puppet_redhat_version}
327
- # Clean up temporary puppet repo
328
- rm -rf /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
329
- rm -rf /etc/yum.repos.d/puppettemp.repo
330
- else
331
- #{sudo('rpm')} -ivh #{proxy_parm} #{puppet_yum_repo}
332
- #{update_packages_redhat_cmd}
333
- #{sudo_env('yum')} -y install puppet#{puppet_redhat_version}
334
- fi
335
- INSTALL
336
- end
337
-
338
- def init_command
339
- dirs = %w(modules manifests files hiera hiera.yaml)
340
- .map { |dir| File.join(config[:root_path], dir) }.join(' ')
341
- cmd = "#{sudo('rm')} -rf #{dirs} #{hiera_data_remote_path} /etc/hiera.yaml #{puppet_dir}/hiera.yaml #{puppet_dir}/fileserver.conf;"
342
- cmd += config[:puppet_environment] ? "#{sudo('rm')} -f #{File.join(puppet_dir, config[:puppet_environment])};" : ''
343
- cmd += " mkdir -p #{config[:root_path]} #{puppet_dir}"
344
- debug(cmd)
345
- cmd
346
- end
347
-
348
- def create_sandbox
349
- super
350
- debug("Creating local sandbox in #{sandbox_path}")
351
- yield if block_given?
352
- prepare_modules
353
- prepare_manifests
354
- prepare_files
355
- prepare_facts
356
- prepare_puppet_config
357
- prepare_hiera_config
358
- prepare_fileserver_config
359
- prepare_hiera_data
360
- info('Finished Preparing files for transfer')
361
- end
362
-
363
- def cleanup_sandbox
364
- return if sandbox_path.nil?
365
- debug("Cleaning up local sandbox in #{sandbox_path}")
366
- FileUtils.rmtree(sandbox_path)
367
- end
368
-
369
- # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
370
- def prepare_command
371
- commands = []
372
- if puppet_git_init
373
- commands << [
374
- sudo('rm -rf'), '/etc/puppet'
375
- ].join(' ')
376
-
377
- commands << [
378
- sudo('git clone'), puppet_git_init, '/etc/puppet'
379
- ].join(' ')
380
- end
381
-
382
- if puppet_git_pr
383
- commands << [sudo('git'),
384
- '--git-dir=/etc/puppet/.git/',
385
- 'fetch -f',
386
- 'origin',
387
- "pull/#{puppet_git_pr}/head:pr_#{puppet_git_pr}"
388
- ].join(' ')
389
-
390
- commands << [sudo('git'), '--git-dir=/etc/puppet/.git/',
391
- '--work-tree=/etc/puppet/',
392
- 'checkout',
393
- "pr_#{puppet_git_pr}"
394
- ].join(' ')
395
- end
396
-
397
- if puppet_config
398
- commands << [
399
- sudo('cp'),
400
- File.join(config[:root_path], 'puppet.conf'),
401
- puppet_dir
402
- ].join(' ')
403
- end
404
-
405
- if hiera_config
406
- commands << [
407
- sudo('cp'), File.join(config[:root_path], 'hiera.yaml'), '/etc/'
408
- ].join(' ')
409
-
410
- commands << [
411
- sudo('cp'), File.join(config[:root_path], 'hiera.yaml'), puppet_dir
412
- ].join(' ')
413
- end
414
-
415
- if fileserver_config
416
- commands << [
417
- sudo('cp'),
418
- File.join(config[:root_path], 'fileserver.conf'),
419
- puppet_dir
420
- ].join(' ')
421
- end
422
-
423
- if hiera_data && hiera_data_remote_path == '/var/lib/hiera'
424
- commands << [
425
- sudo('cp -r'), File.join(config[:root_path], 'hiera'), '/var/lib/'
426
- ].join(' ')
427
- end
428
-
429
- if hiera_data && hiera_data_remote_path != '/var/lib/hiera'
430
- commands << [
431
- sudo('mkdir -p'), hiera_data_remote_path
432
- ].join(' ')
433
- commands << [
434
- sudo('cp -r'), File.join(config[:root_path], 'hiera/*'), hiera_data_remote_path
435
- ].join(' ')
436
- end
437
-
438
- if hiera_eyaml
439
- commands << [
440
- sudo('mkdir -p'), hiera_eyaml_key_remote_path
441
- ].join(' ')
442
- commands << [
443
- sudo('cp -r'), File.join(config[:root_path], 'hiera_keys/*'), hiera_eyaml_key_remote_path
444
- ].join(' ')
445
- end
446
-
447
- if puppet_environment
448
- commands << [
449
- sudo('ln -s '), config[:root_path], File.join(puppet_dir, config[:puppet_environment])
450
- ].join(' ')
451
- end
452
-
453
- command = commands.join(' && ')
454
- debug(command)
455
- command
456
- end
457
- # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
458
-
459
- def run_command
460
- if !config[:puppet_apply_command].nil?
461
- return config[:puppet_apply_command]
462
- else
463
- [
464
- custom_facts,
465
- facter_facts,
466
- puppet_cmd,
467
- 'apply',
468
- File.join(config[:root_path], 'manifests', manifest),
469
- "--modulepath=#{File.join(config[:root_path], 'modules')}",
470
- puppet_manifestdir,
471
- "--fileserverconfig=#{File.join(config[:root_path], 'fileserver.conf')}",
472
- puppet_environment_flag,
473
- puppet_noop_flag,
474
- puppet_detailed_exitcodes_flag,
475
- puppet_verbose_flag,
476
- puppet_debug_flag,
477
- puppet_logdest_flag,
478
- remove_repo
479
- ].join(' ')
480
- end
481
- end
482
-
483
- protected
484
-
485
- def load_needed_dependencies!
486
- return unless File.exist?(puppetfile)
487
- return unless config[:resolve_with_librarian_puppet]
488
- debug("Puppetfile found at #{puppetfile}, loading Librarian-Puppet")
489
- Puppet::Librarian.load!(logger)
490
- end
491
-
492
- def tmpmodules_dir
493
- File.join(sandbox_path, 'modules')
494
- end
495
-
496
- def puppetfile
497
- config[:puppetfile_path] || ''
498
- end
499
-
500
- def modulefile
501
- config[:modulefile_path] || ''
502
- end
503
-
504
- def metadata_json
505
- config[:metadata_json_path] || ''
506
- end
507
-
508
- def manifest
509
- config[:manifest]
510
- end
511
-
512
- def manifests
513
- config[:manifests_path]
514
- end
515
-
516
- def modules
517
- config[:modules_path]
518
- end
519
-
520
- def files
521
- config[:files_path] || 'files'
522
- end
523
-
524
- def puppet_config
525
- config[:puppet_config_path]
526
- end
527
-
528
- def puppet_environment
529
- config[:puppet_environment]
530
- end
531
-
532
- def puppet_git_init
533
- config[:puppet_git_init]
534
- end
535
-
536
- def puppet_git_pr
537
- config[:puppet_git_pr]
538
- end
539
-
540
- def hiera_config
541
- config[:hiera_config_path]
542
- end
543
-
544
- def fileserver_config
545
- config[:fileserver_config_path]
546
- end
547
-
548
- def hiera_data
549
- config[:hiera_data_path]
550
- end
551
-
552
- def hiera_data_remote_path
553
- config[:hiera_data_remote_path]
554
- end
555
-
556
- def hiera_eyaml
557
- config[:hiera_eyaml]
558
- end
559
-
560
- def hiera_eyaml_key_path
561
- config[:hiera_eyaml_key_path]
562
- end
563
-
564
- def hiera_eyaml_key_remote_path
565
- config[:hiera_eyaml_key_remote_path]
566
- end
567
-
568
- def hiera_deep_merge
569
- config[:hiera_deep_merge]
570
- end
571
-
572
- def librarian_puppet_ssl_file
573
- config[:librarian_puppet_ssl_file]
574
- end
575
-
576
- def puppet_cmd
577
- if config[:require_puppet_collections]
578
- sudo_env("#{config[:puppet_coll_remote_path]}/bin/puppet")
579
- else
580
- sudo_env('puppet')
581
- end
582
- end
583
-
584
- def puppet_dir
585
- if config[:require_puppet_collections]
586
- '/etc/puppetlabs/puppet'
587
- else
588
- '/etc/puppet'
589
- end
590
- end
591
-
592
- def puppet_debian_version
593
- config[:puppet_version] ? "=#{config[:puppet_version]}" : nil
594
- end
595
-
596
- def puppet_redhat_version
597
- config[:puppet_version] ? "-#{config[:puppet_version]}" : nil
598
- end
599
-
600
- def puppet_environment_flag
601
- config[:puppet_environment] ? "--environment=#{config[:puppet_environment]} --environmentpath=#{puppet_dir}" : nil
602
- end
603
-
604
- def puppet_manifestdir
605
- config[:puppet_environment] ? nil : "--manifestdir=#{File.join(config[:root_path], 'manifests')}"
606
- end
607
-
608
- def puppet_noop_flag
609
- config[:puppet_noop] ? '--noop' : nil
610
- end
611
-
612
- def puppet_debug_flag
613
- config[:puppet_debug] ? '-d' : nil
614
- end
615
-
616
- def puppet_verbose_flag
617
- config[:puppet_verbose] ? '-v' : nil
618
- end
619
-
620
- def puppet_logdest_flag
621
- return nil unless config[:puppet_logdest]
622
- destinations = ''
623
- config[:puppet_logdest].each do |dest|
624
- destinations << "--logdest #{dest} "
625
- end
626
- destinations
627
- end
628
-
629
- def puppet_platform
630
- config[:puppet_platform].to_s.downcase
631
- end
632
-
633
- def facter_facts
634
- return nil unless config[:facter_file]
635
- fact_vars = 'export '
636
- fact_hash = YAML.load_file(config[:facter_file])
637
- fact_hash.each do |key, value|
638
- fact_vars << "FACTER_#{key}=#{value} "
639
- end
640
- fact_vars << ';'
641
- fact_vars
642
- end
643
-
644
- def update_packages_debian_cmd
645
- config[:update_package_repos] ? "#{sudo_env('apt-get')} update" : nil
646
- end
647
-
648
- def update_packages_redhat_cmd
649
- # #{sudo('yum')}
650
- config[:update_package_repos] ? "#{sudo_env('yum')} makecache" : nil
651
- end
652
-
653
- def sudo_env(pm)
654
- s = https_proxy ? "https_proxy=#{https_proxy}" : nil
655
- p = http_proxy ? "http_proxy=#{http_proxy}" : nil
656
- p || s ? "#{sudo('env')} #{p} #{s} #{pm}" : "#{sudo(pm)}"
657
- end
658
-
659
- def remove_puppet_repo
660
- config[:remove_puppet_repo]
661
- end
662
-
663
- def custom_facts
664
- return nil if config[:custom_facts].none?
665
- bash_vars = config[:custom_facts].map { |k, v| "FACTER_#{k}=#{v}" }.join(' ')
666
- bash_vars = "export #{bash_vars};"
667
- debug(bash_vars)
668
- bash_vars
669
- end
670
-
671
- def puppet_detailed_exitcodes_flag
672
- config[:puppet_detailed_exitcodes] ? '--detailed-exitcodes' : nil
673
- end
674
-
675
- def remove_repo
676
- remove_puppet_repo ? "; #{sudo('rm')} -rf /tmp/kitchen #{hiera_data_remote_path} #{hiera_eyaml_key_remote_path} #{puppet_dir}/* " : nil
677
- end
678
-
679
- def puppet_apt_repo
680
- config[:puppet_apt_repo]
681
- end
682
-
683
- def puppet_apt_repo_file
684
- config[:puppet_apt_repo].split('/').last
685
- end
686
-
687
- def puppet_apt_coll_repo_file
688
- config[:puppet_apt_collections_repo].split('/').last
689
- end
690
-
691
- def puppet_yum_repo
692
- config[:puppet_yum_repo]
693
- end
694
-
695
- def proxy_parm
696
- http_proxy ? "--httpproxy #{URI.parse(http_proxy).host.downcase} --httpport #{URI.parse(http_proxy).port} " : nil
697
- end
698
-
699
- def gem_proxy_parm
700
- http_proxy ? "--http-proxy #{http_proxy}" : nil
701
- end
702
-
703
- def wget_proxy_parm
704
- p = http_proxy ? "-e http_proxy=#{http_proxy}" : nil
705
- s = https_proxy ? "-e http_proxy=#{http_proxy}" : nil
706
- p || s ? "-e use_proxy=yes #{p} #{s}" : nil
707
- end
708
-
709
- def http_proxy
710
- config[:http_proxy]
711
- end
712
-
713
- def https_proxy
714
- config[:https_proxy]
715
- end
716
-
717
- def chef_url
718
- config[:chef_bootstrap_url]
719
- end
720
-
721
- def prepare_manifests
722
- info('Preparing manifests')
723
- debug("Using manifests from #{manifests}")
724
-
725
- tmp_manifests_dir = File.join(sandbox_path, 'manifests')
726
- FileUtils.mkdir_p(tmp_manifests_dir)
727
- FileUtils.cp_r(Dir.glob("#{manifests}/*"), tmp_manifests_dir)
728
- end
729
-
730
- def prepare_files
731
- info('Preparing files')
732
- unless File.directory?(files)
733
- info 'nothing to do for files'
734
- return
735
- end
736
-
737
- debug("Using files from #{files}")
738
-
739
- tmp_files_dir = File.join(sandbox_path, 'files')
740
- FileUtils.mkdir_p(tmp_files_dir)
741
- FileUtils.cp_r(Dir.glob("#{files}/*"), tmp_files_dir)
742
- end
743
-
744
- def prepare_facts
745
- return unless config[:install_custom_facts]
746
- return unless config[:custom_facts]
747
- info 'Installing custom facts'
748
- facter_dir = File.join(sandbox_path, 'facter')
749
- FileUtils.mkdir_p(facter_dir)
750
- tmp_facter_file = File.join(facter_dir, 'kitchen.yaml')
751
- facter_facts = Hash[config[:custom_facts].map { |k, v| [k.to_s, v.to_s] }]
752
- File.open(tmp_facter_file, 'w') do |out|
753
- YAML.dump(facter_facts, out)
754
- end
755
- end
756
-
757
- def prepare_modules
758
- info('Preparing modules')
759
-
760
- FileUtils.mkdir_p(tmpmodules_dir)
761
- resolve_with_librarian if File.exist?(puppetfile) && config[:resolve_with_librarian_puppet]
762
-
763
- if modules && File.directory?(modules)
764
- debug("Copying modules from #{modules} to #{tmpmodules_dir}")
765
- FileUtils.cp_r(Dir.glob("#{modules}/*"), tmpmodules_dir, remove_destination: true)
766
- else
767
- info 'nothing to do for modules'
768
- end
769
-
770
- copy_self_as_module
771
- end
772
-
773
- def copy_self_as_module
774
- if File.exist?(modulefile)
775
- warn('Modulefile found but this is depricated, ignoring it, see https://tickets.puppetlabs.com/browse/PUP-1188')
776
- end
777
-
778
- return unless File.exist?(metadata_json)
779
- module_name = nil
780
- begin
781
- module_name = JSON.parse(IO.read(metadata_json))['name'].split('-').last
782
- rescue
783
- error("not able to load or parse #{metadata_json_path} for the name of the module")
784
- end
785
-
786
- return unless module_name
787
- module_target_path = File.join(sandbox_path, 'modules', module_name)
788
- FileUtils.mkdir_p(module_target_path)
789
- FileUtils.cp_r(
790
- Dir.glob(File.join(config[:kitchen_root], '*')).reject { |entry| entry =~ /modules$/ },
791
- module_target_path,
792
- remove_destination: true
793
- )
794
- end
795
-
796
- def prepare_puppet_config
797
- return unless puppet_config
798
-
799
- info('Preparing puppet.conf')
800
- debug("Using puppet config from #{puppet_config}")
801
-
802
- FileUtils.cp_r(puppet_config, File.join(sandbox_path, 'puppet.conf'))
803
- end
804
-
805
- def prepare_hiera_config
806
- return unless hiera_config
807
-
808
- info('Preparing hiera')
809
- debug("Using hiera from #{hiera_config}")
810
-
811
- FileUtils.cp_r(hiera_config, File.join(sandbox_path, 'hiera.yaml'))
812
- end
813
-
814
- def prepare_fileserver_config
815
- return unless fileserver_config
816
-
817
- info('Preparing fileserver')
818
- debug("Using fileserver config from #{fileserver_config}")
819
-
820
- FileUtils.cp_r(fileserver_config, File.join(sandbox_path, 'fileserver.conf'))
821
- end
822
-
823
- def prepare_hiera_data
824
- return unless hiera_data
825
- info('Preparing hiera data')
826
- tmp_hiera_dir = File.join(sandbox_path, 'hiera')
827
- debug("Copying hiera data from #{hiera_data} to #{tmp_hiera_dir}")
828
- FileUtils.mkdir_p(tmp_hiera_dir)
829
- FileUtils.cp_r(Dir.glob("#{hiera_data}/*"), tmp_hiera_dir)
830
- return unless hiera_eyaml_key_path
831
- tmp_hiera_key_dir = File.join(sandbox_path, 'hiera_keys')
832
- debug("Copying hiera eyaml keys from #{hiera_eyaml_key_path} to #{tmp_hiera_key_dir}")
833
- FileUtils.mkdir_p(tmp_hiera_key_dir)
834
- FileUtils.cp_r(Dir.glob("#{hiera_eyaml_key_path}/*"), tmp_hiera_key_dir)
835
- end
836
-
837
- def resolve_with_librarian
838
- Kitchen.mutex.synchronize do
839
- ENV['SSL_CERT_FILE'] = librarian_puppet_ssl_file if librarian_puppet_ssl_file
840
- Puppet::Librarian.new(puppetfile, tmpmodules_dir, logger).resolve
841
- ENV['SSL_CERT_FILE'] = '' if librarian_puppet_ssl_file
842
- end
843
- end
844
- end
845
- end
846
- 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/provisioner/base'
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 Provisioner
36
+ #
37
+ # Puppet Apply provisioner.
38
+ #
39
+ class PuppetApply < Base
40
+ attr_accessor :tmp_dir
41
+
42
+ default_config :require_puppet_collections, false
43
+ default_config :puppet_yum_collections_repo, 'http://yum.puppetlabs.com/puppetlabs-release-pc1-el-6.noarch.rpm'
44
+ default_config :puppet_apt_collections_repo, 'http://apt.puppetlabs.com/puppetlabs-release-pc1-wheezy.deb'
45
+ default_config :puppet_coll_remote_path, '/opt/puppetlabs'
46
+ default_config :puppet_version, nil
47
+ default_config :require_puppet_repo, true
48
+ default_config :require_chef_for_busser, true
49
+ default_config :resolve_with_librarian_puppet, true
50
+ default_config :puppet_environment, nil
51
+ default_config :install_custom_facts, false
52
+ default_config :puppet_apt_repo, 'http://apt.puppetlabs.com/puppetlabs-release-precise.deb'
53
+ default_config :puppet_yum_repo, 'https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm'
54
+ default_config :chef_bootstrap_url, 'https://www.getchef.com/chef/install.sh'
55
+ default_config :puppet_logdest, nil
56
+
57
+ default_config :puppet_apply_command, nil
58
+
59
+ default_config :puppet_git_init, nil
60
+ default_config :puppet_git_pr, nil
61
+
62
+ default_config :http_proxy, nil
63
+ default_config :https_proxy, nil
64
+
65
+ default_config :hiera_data_remote_path, '/var/lib/hiera'
66
+ default_config :manifest, 'site.pp'
67
+
68
+ default_config :manifests_path do |provisioner|
69
+ provisioner.calculate_path('manifests') ||
70
+ fail('No manifests_path detected. Please specify one in .kitchen.yml')
71
+ end
72
+
73
+ default_config :modules_path do |provisioner|
74
+ modules_path = provisioner.calculate_path('modules')
75
+ if modules_path.nil? && provisioner.calculate_path('Puppetfile', :file).nil?
76
+ fail 'No modules_path detected. Please specify one in .kitchen.yml'
77
+ end
78
+ modules_path
79
+ end
80
+
81
+ default_config :files_path do |provisioner|
82
+ provisioner.calculate_path('files') || 'files'
83
+ end
84
+
85
+ default_config :hiera_data_path do |provisioner|
86
+ provisioner.calculate_path('hiera')
87
+ end
88
+
89
+ default_config :puppet_config_path do |provisioner|
90
+ provisioner.calculate_path('puppet.conf', :file)
91
+ end
92
+
93
+ default_config :hiera_config_path do |provisioner|
94
+ provisioner.calculate_path('hiera.yaml', :file)
95
+ end
96
+
97
+ default_config :fileserver_config_path do |provisioner|
98
+ provisioner.calculate_path('fileserver.conf', :file)
99
+ end
100
+ default_config :puppetfile_path do |provisioner|
101
+ provisioner.calculate_path('Puppetfile', :file)
102
+ end
103
+
104
+ default_config :modulefile_path do |provisioner|
105
+ provisioner.calculate_path('Modulefile', :file)
106
+ end
107
+
108
+ default_config :metadata_json_path do |provisioner|
109
+ provisioner.calculate_path('metadata.json', :file)
110
+ end
111
+
112
+ default_config :manifests_path do |provisioner|
113
+ provisioner.calculate_path('manifests', :directory)
114
+ end
115
+
116
+ default_config :puppet_debug, false
117
+ default_config :puppet_verbose, false
118
+ default_config :puppet_noop, false
119
+ default_config :puppet_platform, ''
120
+ default_config :update_package_repos, true
121
+ default_config :remove_puppet_repo, false
122
+ default_config :custom_facts, {}
123
+ default_config :puppet_detailed_exitcodes, nil
124
+ default_config :facter_file, nil
125
+ default_config :librarian_puppet_ssl_file, nil
126
+
127
+ default_config :hiera_eyaml, false
128
+ default_config :hiera_eyaml_key_remote_path, '/etc/puppet/secure/keys'
129
+
130
+ default_config :hiera_eyaml_key_path do |provisioner|
131
+ provisioner.calculate_path('hiera_keys')
132
+ end
133
+
134
+ default_config :hiera_deep_merge, false
135
+
136
+ def calculate_path(path, type = :directory)
137
+ base = config[:test_base_path]
138
+ candidates = []
139
+ candidates << File.join(base, instance.suite.name, 'puppet', path)
140
+ candidates << File.join(base, instance.suite.name, path)
141
+ candidates << File.join(base, path)
142
+ candidates << File.join(Dir.pwd, path)
143
+
144
+ candidates.find do |c|
145
+ type == :directory ? File.directory?(c) : File.file?(c)
146
+ end
147
+ end
148
+
149
+ # TODO: refactor for smaller cyclomatic complexity and perceived complexity
150
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
151
+ def install_command
152
+ return unless config[:require_puppet_collections] || config[:require_puppet_repo]
153
+ if config[:require_puppet_collections]
154
+ install_command_collections
155
+ else
156
+ case puppet_platform
157
+ when 'debian', 'ubuntu'
158
+ info("Installing puppet on #{puppet_platform}")
159
+ <<-INSTALL
160
+ if [ ! $(which puppet) ]; then
161
+ #{sudo('apt-get')} -y install wget
162
+ #{sudo('wget')} #{wget_proxy_parm} #{puppet_apt_repo}
163
+ #{sudo('dpkg')} -i #{puppet_apt_repo_file}
164
+ #{update_packages_debian_cmd}
165
+ #{sudo_env('apt-get')} -y install puppet-common#{puppet_debian_version}
166
+ #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
167
+ fi
168
+ #{install_eyaml}
169
+ #{install_deep_merge}
170
+ #{install_busser}
171
+ INSTALL
172
+ when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
173
+ info("Installing puppet from yum on #{puppet_platform}")
174
+ <<-INSTALL
175
+ if [ ! $(which puppet) ]; then
176
+ #{install_puppet_yum_repo}
177
+ fi
178
+ #{install_eyaml}
179
+ #{install_deep_merge}
180
+ #{install_busser}
181
+ INSTALL
182
+ else
183
+ info('Installing puppet, will try to determine platform os')
184
+ <<-INSTALL
185
+ if [ ! $(which puppet) ]; then
186
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
187
+ #{install_puppet_yum_repo}
188
+ else
189
+ if [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
190
+ #{install_puppet_yum_repo}
191
+ else
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 puppet-common#{puppet_debian_version}
197
+ #{sudo_env('apt-get')} -y install puppet#{puppet_debian_version}
198
+ fi
199
+ fi
200
+ fi
201
+ #{install_eyaml}
202
+ #{install_deep_merge}
203
+ #{install_busser}
204
+ INSTALL
205
+ end
206
+ end
207
+ end
208
+
209
+ def install_command_collections
210
+ case puppet_platform
211
+ when 'debian', 'ubuntu'
212
+ info("Installing Puppet Collections on #{puppet_platform}")
213
+ <<-INSTALL
214
+ #{sudo('apt-get')} -y install wget
215
+ #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
216
+ #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
217
+ INSTALL
218
+ when 'redhat', 'centos', 'fedora', 'oracle', 'amazon'
219
+ info("Installing Puppet Collections on #{puppet_platform}")
220
+ <<-INSTALL
221
+ #{Util.shell_helpers}
222
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
223
+ echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
224
+ #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
225
+ #{sudo_env('yum')} -y install puppet
226
+ fi
227
+ #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
228
+ #{install_deep_merge}
229
+ #{install_busser}
230
+ INSTALL
231
+ else
232
+ info('Installing Puppet Collections, will try to determine platform os')
233
+ <<-INSTALL
234
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
235
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
236
+ #{Util.shell_helpers}
237
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
238
+ echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
239
+ #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
240
+ #{sudo_env('yum')} -y install puppet
241
+ fi
242
+ else
243
+ if [ -f /etc/system-release ] || [ grep -q 'Amazon Linux' /etc/system-release ]; then
244
+ #{Util.shell_helpers}
245
+ if [ ! -d "#{config[:puppet_coll_remote_path]}" ]; then
246
+ echo "-----> #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}"
247
+ #{sudo_env('yum')} -y localinstall #{config[:puppet_yum_collections_repo]}
248
+ #{sudo_env('yum')} -y install puppet
249
+ fi
250
+ else
251
+ #{sudo('apt-get')} -y install wget
252
+ #{sudo('wget')} #{wget_proxy_parm} #{config[:puppet_apt_collections_repo]}
253
+ #{sudo('dpkg')} -i #{puppet_apt_coll_repo_file}
254
+ fi
255
+ fi
256
+ fi
257
+ #{install_eyaml("#{config[:puppet_coll_remote_path]}/puppet/bin/gem")}
258
+ #{install_deep_merge}
259
+ #{install_busser}
260
+ INSTALL
261
+ end
262
+ end
263
+
264
+ def install_deep_merge
265
+ return unless config[:hiera_deep_merge]
266
+ <<-INSTALL
267
+ # Support for hash merge lookups to recursively merge hash keys
268
+ if [[ $(#{sudo('gem')} list deep_merge -i) == 'false' ]]; then
269
+ echo '-----> Installing deep_merge to provide deep_merge of hiera hashes'
270
+ #{sudo('gem')} install #{gem_proxy_parm} --no-ri --no-rdoc deep_merge
271
+ fi
272
+ INSTALL
273
+ end
274
+
275
+ def install_eyaml(gem_cmd = 'gem')
276
+ return unless config[:hiera_eyaml]
277
+ <<-INSTALL
278
+ # A backend for Hiera that provides per-value asymmetric encryption of sensitive data
279
+ if [[ $(#{sudo(gem_cmd)} list hiera-eyaml -i) == 'false' ]]; then
280
+ echo '-----> Installing hiera-eyaml to provide encryption of hiera data'
281
+ #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc highline -v 1.6.21
282
+ #{sudo(gem_cmd)} install #{gem_proxy_parm} --no-ri --no-rdoc hiera-eyaml
283
+ fi
284
+ INSTALL
285
+ end
286
+
287
+ def install_busser
288
+ return unless config[:require_chef_for_busser]
289
+ <<-INSTALL
290
+ #{Util.shell_helpers}
291
+ # install chef omnibus so that busser works as this is needed to run tests :(
292
+ # TODO: work out how to install enough ruby
293
+ # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
294
+ # whole chef client
295
+ if [ ! -d "/opt/chef" ]
296
+ then
297
+ echo '-----> Installing Chef Omnibus to install busser to run tests'
298
+ do_download #{chef_url} /tmp/install.sh
299
+ #{sudo('sh')} /tmp/install.sh
300
+ fi
301
+ INSTALL
302
+ end
303
+
304
+ # /bin/wget -P /etc/pki/rpm-gpg/ http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
305
+ # changed to curl
306
+
307
+ def install_puppet_yum_repo
308
+ <<-INSTALL
309
+ rhelversion=$(cat /etc/redhat-release | grep 'release 7')
310
+ # For CentOS7/RHEL7 the rdo release contains puppetlabs repo, creating conflict. Create temp-repo
311
+ #{sudo_env('curl')} -o /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs http://yum.puppetlabs.com/RPM-GPG-KEY-puppetlabs
312
+ if [ -n "$rhelversion" ]; then
313
+ echo '[puppettemp-products]
314
+ name=Puppet Labs Products - \$basearch
315
+ baseurl=http://yum.puppetlabs.com/el/7/products/\$basearch
316
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
317
+ enabled=0
318
+ gpgcheck=1
319
+ [puppettemp-deps]
320
+ name=Puppet Labs Dependencies - \$basearch
321
+ baseurl=http://yum.puppetlabs.com/el/7/dependencies/\$basearch
322
+ gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
323
+ enabled=0
324
+ gpgcheck=1' | sudo tee /etc/yum.repos.d/puppettemp.repo > /dev/null
325
+ sudo sed -i 's/^[ \t]*//' /etc/yum.repos.d/puppettemp.repo
326
+ #{update_packages_redhat_cmd}
327
+ #{sudo_env('yum')} -y --enablerepo=puppettemp-products --enablerepo=puppettemp-deps install puppet#{puppet_redhat_version}
328
+ # Clean up temporary puppet repo
329
+ sudo rm -rf /etc/pki/rpm-gpg/RPM-GPG-KEY-puppetlabs
330
+ sudo rm -rf /etc/yum.repos.d/puppettemp.repo
331
+ else
332
+ #{sudo('rpm')} -ivh #{proxy_parm} #{puppet_yum_repo}
333
+ #{update_packages_redhat_cmd}
334
+ #{sudo_env('yum')} -y install puppet#{puppet_redhat_version}
335
+ fi
336
+ INSTALL
337
+ end
338
+
339
+ def init_command
340
+ dirs = %w(modules manifests files hiera hiera.yaml)
341
+ .map { |dir| File.join(config[:root_path], dir) }.join(' ')
342
+ cmd = "#{sudo('rm')} -rf #{dirs} #{hiera_data_remote_path} /etc/hiera.yaml #{puppet_dir}/hiera.yaml #{puppet_dir}/fileserver.conf;"
343
+ cmd += config[:puppet_environment] ? "#{sudo('rm')} -f #{File.join(puppet_dir, config[:puppet_environment])};" : ''
344
+ cmd += " mkdir -p #{config[:root_path]} #{puppet_dir}"
345
+ debug(cmd)
346
+ cmd
347
+ end
348
+
349
+ def create_sandbox
350
+ super
351
+ debug("Creating local sandbox in #{sandbox_path}")
352
+ yield if block_given?
353
+ prepare_modules
354
+ prepare_manifests
355
+ prepare_files
356
+ prepare_facts
357
+ prepare_puppet_config
358
+ prepare_hiera_config
359
+ prepare_fileserver_config
360
+ prepare_hiera_data
361
+ info('Finished Preparing files for transfer')
362
+ end
363
+
364
+ def cleanup_sandbox
365
+ return if sandbox_path.nil?
366
+ debug("Cleaning up local sandbox in #{sandbox_path}")
367
+ FileUtils.rmtree(sandbox_path)
368
+ end
369
+
370
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
371
+ def prepare_command
372
+ commands = []
373
+ if puppet_git_init
374
+ commands << [
375
+ sudo('rm -rf'), '/etc/puppet'
376
+ ].join(' ')
377
+
378
+ commands << [
379
+ sudo('git clone'), puppet_git_init, '/etc/puppet'
380
+ ].join(' ')
381
+ end
382
+
383
+ if puppet_git_pr
384
+ commands << [sudo('git'),
385
+ '--git-dir=/etc/puppet/.git/',
386
+ 'fetch -f',
387
+ 'origin',
388
+ "pull/#{puppet_git_pr}/head:pr_#{puppet_git_pr}"
389
+ ].join(' ')
390
+
391
+ commands << [sudo('git'), '--git-dir=/etc/puppet/.git/',
392
+ '--work-tree=/etc/puppet/',
393
+ 'checkout',
394
+ "pr_#{puppet_git_pr}"
395
+ ].join(' ')
396
+ end
397
+
398
+ if puppet_config
399
+ commands << [
400
+ sudo('cp'),
401
+ File.join(config[:root_path], 'puppet.conf'),
402
+ puppet_dir
403
+ ].join(' ')
404
+ end
405
+
406
+ if hiera_config
407
+ commands << [
408
+ sudo('cp'), File.join(config[:root_path], 'hiera.yaml'), '/etc/'
409
+ ].join(' ')
410
+
411
+ commands << [
412
+ sudo('cp'), File.join(config[:root_path], 'hiera.yaml'), puppet_dir
413
+ ].join(' ')
414
+ end
415
+
416
+ if fileserver_config
417
+ commands << [
418
+ sudo('cp'),
419
+ File.join(config[:root_path], 'fileserver.conf'),
420
+ puppet_dir
421
+ ].join(' ')
422
+ end
423
+
424
+ if hiera_data && hiera_data_remote_path == '/var/lib/hiera'
425
+ commands << [
426
+ sudo('cp -r'), File.join(config[:root_path], 'hiera'), '/var/lib/'
427
+ ].join(' ')
428
+ end
429
+
430
+ if hiera_data && hiera_data_remote_path != '/var/lib/hiera'
431
+ commands << [
432
+ sudo('mkdir -p'), hiera_data_remote_path
433
+ ].join(' ')
434
+ commands << [
435
+ sudo('cp -r'), File.join(config[:root_path], 'hiera/*'), hiera_data_remote_path
436
+ ].join(' ')
437
+ end
438
+
439
+ if hiera_eyaml
440
+ commands << [
441
+ sudo('mkdir -p'), hiera_eyaml_key_remote_path
442
+ ].join(' ')
443
+ commands << [
444
+ sudo('cp -r'), File.join(config[:root_path], 'hiera_keys/*'), hiera_eyaml_key_remote_path
445
+ ].join(' ')
446
+ end
447
+
448
+ if puppet_environment
449
+ commands << [
450
+ sudo('ln -s '), config[:root_path], File.join(puppet_dir, config[:puppet_environment])
451
+ ].join(' ')
452
+ end
453
+
454
+ command = commands.join(' && ')
455
+ debug(command)
456
+ command
457
+ end
458
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
459
+
460
+ def run_command
461
+ if !config[:puppet_apply_command].nil?
462
+ return config[:puppet_apply_command]
463
+ else
464
+ [
465
+ custom_facts,
466
+ facter_facts,
467
+ puppet_cmd,
468
+ 'apply',
469
+ File.join(config[:root_path], 'manifests', manifest),
470
+ "--modulepath=#{File.join(config[:root_path], 'modules')}",
471
+ puppet_manifestdir,
472
+ "--fileserverconfig=#{File.join(config[:root_path], 'fileserver.conf')}",
473
+ puppet_environment_flag,
474
+ puppet_noop_flag,
475
+ puppet_detailed_exitcodes_flag,
476
+ puppet_verbose_flag,
477
+ puppet_debug_flag,
478
+ puppet_logdest_flag,
479
+ remove_repo
480
+ ].join(' ')
481
+ end
482
+ end
483
+
484
+ protected
485
+
486
+ def load_needed_dependencies!
487
+ return unless File.exist?(puppetfile)
488
+ return unless config[:resolve_with_librarian_puppet]
489
+ debug("Puppetfile found at #{puppetfile}, loading Librarian-Puppet")
490
+ Puppet::Librarian.load!(logger)
491
+ end
492
+
493
+ def tmpmodules_dir
494
+ File.join(sandbox_path, 'modules')
495
+ end
496
+
497
+ def puppetfile
498
+ config[:puppetfile_path] || ''
499
+ end
500
+
501
+ def modulefile
502
+ config[:modulefile_path] || ''
503
+ end
504
+
505
+ def metadata_json
506
+ config[:metadata_json_path] || ''
507
+ end
508
+
509
+ def manifest
510
+ config[:manifest]
511
+ end
512
+
513
+ def manifests
514
+ config[:manifests_path]
515
+ end
516
+
517
+ def modules
518
+ config[:modules_path]
519
+ end
520
+
521
+ def files
522
+ config[:files_path] || 'files'
523
+ end
524
+
525
+ def puppet_config
526
+ config[:puppet_config_path]
527
+ end
528
+
529
+ def puppet_environment
530
+ config[:puppet_environment]
531
+ end
532
+
533
+ def puppet_git_init
534
+ config[:puppet_git_init]
535
+ end
536
+
537
+ def puppet_git_pr
538
+ config[:puppet_git_pr]
539
+ end
540
+
541
+ def hiera_config
542
+ config[:hiera_config_path]
543
+ end
544
+
545
+ def fileserver_config
546
+ config[:fileserver_config_path]
547
+ end
548
+
549
+ def hiera_data
550
+ config[:hiera_data_path]
551
+ end
552
+
553
+ def hiera_data_remote_path
554
+ config[:hiera_data_remote_path]
555
+ end
556
+
557
+ def hiera_eyaml
558
+ config[:hiera_eyaml]
559
+ end
560
+
561
+ def hiera_eyaml_key_path
562
+ config[:hiera_eyaml_key_path]
563
+ end
564
+
565
+ def hiera_eyaml_key_remote_path
566
+ config[:hiera_eyaml_key_remote_path]
567
+ end
568
+
569
+ def hiera_deep_merge
570
+ config[:hiera_deep_merge]
571
+ end
572
+
573
+ def librarian_puppet_ssl_file
574
+ config[:librarian_puppet_ssl_file]
575
+ end
576
+
577
+ def puppet_cmd
578
+ if config[:require_puppet_collections]
579
+ sudo_env("#{config[:puppet_coll_remote_path]}/bin/puppet")
580
+ else
581
+ sudo_env('puppet')
582
+ end
583
+ end
584
+
585
+ def puppet_dir
586
+ if config[:require_puppet_collections]
587
+ '/etc/puppetlabs/puppet'
588
+ else
589
+ '/etc/puppet'
590
+ end
591
+ end
592
+
593
+ def puppet_debian_version
594
+ config[:puppet_version] ? "=#{config[:puppet_version]}" : nil
595
+ end
596
+
597
+ def puppet_redhat_version
598
+ config[:puppet_version] ? "-#{config[:puppet_version]}" : nil
599
+ end
600
+
601
+ def puppet_environment_flag
602
+ config[:puppet_environment] ? "--environment=#{config[:puppet_environment]} --environmentpath=#{puppet_dir}" : nil
603
+ end
604
+
605
+ def puppet_manifestdir
606
+ config[:puppet_environment] ? nil : "--manifestdir=#{File.join(config[:root_path], 'manifests')}"
607
+ end
608
+
609
+ def puppet_noop_flag
610
+ config[:puppet_noop] ? '--noop' : nil
611
+ end
612
+
613
+ def puppet_debug_flag
614
+ config[:puppet_debug] ? '-d' : nil
615
+ end
616
+
617
+ def puppet_verbose_flag
618
+ config[:puppet_verbose] ? '-v' : nil
619
+ end
620
+
621
+ def puppet_logdest_flag
622
+ return nil unless config[:puppet_logdest]
623
+ destinations = ''
624
+ config[:puppet_logdest].each do |dest|
625
+ destinations << "--logdest #{dest} "
626
+ end
627
+ destinations
628
+ end
629
+
630
+ def puppet_platform
631
+ config[:puppet_platform].to_s.downcase
632
+ end
633
+
634
+ def facter_facts
635
+ return nil unless config[:facter_file]
636
+ fact_vars = 'export '
637
+ fact_hash = YAML.load_file(config[:facter_file])
638
+ fact_hash.each do |key, value|
639
+ fact_vars << "FACTER_#{key}=#{value} "
640
+ end
641
+ fact_vars << ';'
642
+ fact_vars
643
+ end
644
+
645
+ def update_packages_debian_cmd
646
+ config[:update_package_repos] ? "#{sudo_env('apt-get')} update" : nil
647
+ end
648
+
649
+ def update_packages_redhat_cmd
650
+ # #{sudo('yum')}
651
+ config[:update_package_repos] ? "#{sudo_env('yum')} makecache" : nil
652
+ end
653
+
654
+ def sudo_env(pm)
655
+ s = https_proxy ? "https_proxy=#{https_proxy}" : nil
656
+ p = http_proxy ? "http_proxy=#{http_proxy}" : nil
657
+ p || s ? "#{sudo('env')} #{p} #{s} #{pm}" : "#{sudo(pm)}"
658
+ end
659
+
660
+ def remove_puppet_repo
661
+ config[:remove_puppet_repo]
662
+ end
663
+
664
+ def custom_facts
665
+ return nil if config[:custom_facts].none?
666
+ bash_vars = config[:custom_facts].map { |k, v| "FACTER_#{k}=#{v}" }.join(' ')
667
+ bash_vars = "export #{bash_vars};"
668
+ debug(bash_vars)
669
+ bash_vars
670
+ end
671
+
672
+ def puppet_detailed_exitcodes_flag
673
+ config[:puppet_detailed_exitcodes] ? '--detailed-exitcodes' : nil
674
+ end
675
+
676
+ def remove_repo
677
+ remove_puppet_repo ? "; #{sudo('rm')} -rf /tmp/kitchen #{hiera_data_remote_path} #{hiera_eyaml_key_remote_path} #{puppet_dir}/* " : nil
678
+ end
679
+
680
+ def puppet_apt_repo
681
+ config[:puppet_apt_repo]
682
+ end
683
+
684
+ def puppet_apt_repo_file
685
+ config[:puppet_apt_repo].split('/').last
686
+ end
687
+
688
+ def puppet_apt_coll_repo_file
689
+ config[:puppet_apt_collections_repo].split('/').last
690
+ end
691
+
692
+ def puppet_yum_repo
693
+ config[:puppet_yum_repo]
694
+ end
695
+
696
+ def proxy_parm
697
+ http_proxy ? "--httpproxy #{URI.parse(http_proxy).host.downcase} --httpport #{URI.parse(http_proxy).port} " : nil
698
+ end
699
+
700
+ def gem_proxy_parm
701
+ http_proxy ? "--http-proxy #{http_proxy}" : nil
702
+ end
703
+
704
+ def wget_proxy_parm
705
+ p = http_proxy ? "-e http_proxy=#{http_proxy}" : nil
706
+ s = https_proxy ? "-e http_proxy=#{http_proxy}" : nil
707
+ p || s ? "-e use_proxy=yes #{p} #{s}" : nil
708
+ end
709
+
710
+ def http_proxy
711
+ config[:http_proxy]
712
+ end
713
+
714
+ def https_proxy
715
+ config[:https_proxy]
716
+ end
717
+
718
+ def chef_url
719
+ config[:chef_bootstrap_url]
720
+ end
721
+
722
+ def prepare_manifests
723
+ info('Preparing manifests')
724
+ debug("Using manifests from #{manifests}")
725
+
726
+ tmp_manifests_dir = File.join(sandbox_path, 'manifests')
727
+ FileUtils.mkdir_p(tmp_manifests_dir)
728
+ FileUtils.cp_r(Dir.glob("#{manifests}/*"), tmp_manifests_dir)
729
+ end
730
+
731
+ def prepare_files
732
+ info('Preparing files')
733
+ unless File.directory?(files)
734
+ info 'nothing to do for files'
735
+ return
736
+ end
737
+
738
+ debug("Using files from #{files}")
739
+
740
+ tmp_files_dir = File.join(sandbox_path, 'files')
741
+ FileUtils.mkdir_p(tmp_files_dir)
742
+ FileUtils.cp_r(Dir.glob("#{files}/*"), tmp_files_dir)
743
+ end
744
+
745
+ def prepare_facts
746
+ return unless config[:install_custom_facts]
747
+ return unless config[:custom_facts]
748
+ info 'Installing custom facts'
749
+ facter_dir = File.join(sandbox_path, 'facter')
750
+ FileUtils.mkdir_p(facter_dir)
751
+ tmp_facter_file = File.join(facter_dir, 'kitchen.yaml')
752
+ facter_facts = Hash[config[:custom_facts].map { |k, v| [k.to_s, v.to_s] }]
753
+ File.open(tmp_facter_file, 'w') do |out|
754
+ YAML.dump(facter_facts, out)
755
+ end
756
+ end
757
+
758
+ def prepare_modules
759
+ info('Preparing modules')
760
+
761
+ FileUtils.mkdir_p(tmpmodules_dir)
762
+ resolve_with_librarian if File.exist?(puppetfile) && config[:resolve_with_librarian_puppet]
763
+
764
+ if modules && File.directory?(modules)
765
+ debug("Copying modules from #{modules} to #{tmpmodules_dir}")
766
+ FileUtils.cp_r(Dir.glob("#{modules}/*"), tmpmodules_dir, remove_destination: true)
767
+ else
768
+ info 'nothing to do for modules'
769
+ end
770
+
771
+ copy_self_as_module
772
+ end
773
+
774
+ def copy_self_as_module
775
+ if File.exist?(modulefile)
776
+ warn('Modulefile found but this is depricated, ignoring it, see https://tickets.puppetlabs.com/browse/PUP-1188')
777
+ end
778
+
779
+ return unless File.exist?(metadata_json)
780
+ module_name = nil
781
+ begin
782
+ module_name = JSON.parse(IO.read(metadata_json))['name'].split('-').last
783
+ rescue
784
+ error("not able to load or parse #{metadata_json_path} for the name of the module")
785
+ end
786
+
787
+ return unless module_name
788
+ module_target_path = File.join(sandbox_path, 'modules', module_name)
789
+ FileUtils.mkdir_p(module_target_path)
790
+ FileUtils.cp_r(
791
+ Dir.glob(File.join(config[:kitchen_root], '*')).reject { |entry| entry =~ /modules$/ },
792
+ module_target_path,
793
+ remove_destination: true
794
+ )
795
+ end
796
+
797
+ def prepare_puppet_config
798
+ return unless puppet_config
799
+
800
+ info('Preparing puppet.conf')
801
+ debug("Using puppet config from #{puppet_config}")
802
+
803
+ FileUtils.cp_r(puppet_config, File.join(sandbox_path, 'puppet.conf'))
804
+ end
805
+
806
+ def prepare_hiera_config
807
+ return unless hiera_config
808
+
809
+ info('Preparing hiera')
810
+ debug("Using hiera from #{hiera_config}")
811
+
812
+ FileUtils.cp_r(hiera_config, File.join(sandbox_path, 'hiera.yaml'))
813
+ end
814
+
815
+ def prepare_fileserver_config
816
+ return unless fileserver_config
817
+
818
+ info('Preparing fileserver')
819
+ debug("Using fileserver config from #{fileserver_config}")
820
+
821
+ FileUtils.cp_r(fileserver_config, File.join(sandbox_path, 'fileserver.conf'))
822
+ end
823
+
824
+ def prepare_hiera_data
825
+ return unless hiera_data
826
+ info('Preparing hiera data')
827
+ tmp_hiera_dir = File.join(sandbox_path, 'hiera')
828
+ debug("Copying hiera data from #{hiera_data} to #{tmp_hiera_dir}")
829
+ FileUtils.mkdir_p(tmp_hiera_dir)
830
+ FileUtils.cp_r(Dir.glob("#{hiera_data}/*"), tmp_hiera_dir)
831
+ return unless hiera_eyaml_key_path
832
+ tmp_hiera_key_dir = File.join(sandbox_path, 'hiera_keys')
833
+ debug("Copying hiera eyaml keys from #{hiera_eyaml_key_path} to #{tmp_hiera_key_dir}")
834
+ FileUtils.mkdir_p(tmp_hiera_key_dir)
835
+ FileUtils.cp_r(Dir.glob("#{hiera_eyaml_key_path}/*"), tmp_hiera_key_dir)
836
+ end
837
+
838
+ def resolve_with_librarian
839
+ Kitchen.mutex.synchronize do
840
+ ENV['SSL_CERT_FILE'] = librarian_puppet_ssl_file if librarian_puppet_ssl_file
841
+ Puppet::Librarian.new(puppetfile, tmpmodules_dir, logger).resolve
842
+ ENV['SSL_CERT_FILE'] = '' if librarian_puppet_ssl_file
843
+ end
844
+ end
845
+ end
846
+ end
847
+ end