kitchen-puppet 0.0.12 → 0.0.13

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.
data/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # kitchen-puppet
2
- A Test Kitchen Provisioner for Puppet
3
-
4
- The provider works by passing the puppet repository based on attributes in .kitchen.yml & calling puppet apply.
5
-
6
- This provider has been tested against the Ubuntu 1204 and Centos 6.5 boxes running in vagrant/virtualbox.
7
-
8
- ## Requirements
9
- You'll need a driver box without a chef installation so puppet can be installed. Puppet have one at http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box or http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box.
10
-
11
-
12
- ## Installation & Setup
13
- You'll need the test-kitchen & kitchen-puppet gem's installed in your system, along with kitchen-vagrant or some ther suitable driver for test-kitchen.
14
-
1
+ # kitchen-puppet
2
+ A Test Kitchen Provisioner for Puppet
3
+
4
+ The provider works by passing the puppet repository based on attributes in .kitchen.yml & calling puppet apply.
5
+
6
+ This provider has been tested against the Ubuntu 1204 and Centos 6.5 boxes running in vagrant/virtualbox.
7
+
8
+ ## Requirements
9
+ You'll need a driver box without a chef installation so puppet can be installed. Puppet have one at http://puppet-vagrant-boxes.puppetlabs.com/ubuntu-server-12042-x64-vbox4210-nocm.box or http://puppet-vagrant-boxes.puppetlabs.com/centos-65-x64-virtualbox-nocm.box.
10
+
11
+
12
+ ## Installation & Setup
13
+ You'll need the test-kitchen & kitchen-puppet gem's installed in your system, along with kitchen-vagrant or some ther suitable driver for test-kitchen.
14
+
15
15
  Please see the Provisioner Options (https://github.com/neillturner/kitchen-puppet/blob/master/provisioner_options.md).
@@ -1,29 +1,29 @@
1
- # encoding: utf-8
2
-
3
- $:.unshift File.expand_path('../lib', __FILE__)
4
- require 'kitchen-puppet/version'
5
-
6
- Gem::Specification.new do |s|
7
- s.name = "kitchen-puppet"
8
- s.version = Kitchen::Puppet::VERSION
9
- s.authors = ["Neill Turner"]
10
- s.email = ["neillwturner@gmail.com"]
11
- s.homepage = "https://github.com/neillturner/kitchen-puppet"
12
- s.summary = "puppet provisioner for test-kitchen"
13
- candidates = Dir.glob("{lib}/**/*") + ['README.md', 'provisioner_options.md', 'kitchen-puppet.gemspec']
14
- s.files = candidates.sort
15
- s.platform = Gem::Platform::RUBY
16
- s.require_paths = ['lib']
17
- s.rubyforge_project = '[none]'
18
- s.description = <<-EOF
19
- == DESCRIPTION:
20
-
21
- Puppet Provisioner for Test Kitchen
22
-
23
- == FEATURES:
24
-
25
- Supports puppet apply, hiera and custom facts
26
-
27
- EOF
28
-
29
- end
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+ require 'kitchen-puppet/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "kitchen-puppet"
8
+ s.version = Kitchen::Puppet::VERSION
9
+ s.authors = ["Neill Turner"]
10
+ s.email = ["neillwturner@gmail.com"]
11
+ s.homepage = "https://github.com/neillturner/kitchen-puppet"
12
+ s.summary = "puppet provisioner for test-kitchen"
13
+ candidates = Dir.glob("{lib}/**/*") + ['README.md', 'provisioner_options.md', 'kitchen-puppet.gemspec']
14
+ s.files = candidates.sort
15
+ s.platform = Gem::Platform::RUBY
16
+ s.require_paths = ['lib']
17
+ s.rubyforge_project = '[none]'
18
+ s.description = <<-EOF
19
+ == DESCRIPTION:
20
+
21
+ Puppet Provisioner for Test Kitchen
22
+
23
+ == FEATURES:
24
+
25
+ Supports puppet apply, hiera and custom facts
26
+
27
+ EOF
28
+
29
+ end
@@ -1,5 +1,5 @@
1
- module Kitchen
2
- module Puppet
3
- VERSION = "0.0.12"
4
- end
5
- end
1
+ module Kitchen
2
+ module Puppet
3
+ VERSION = "0.0.13"
4
+ end
5
+ end
@@ -1,83 +1,83 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
- # Author:: Fletcher Nichol (<fnichol@nichol.ca>) Neill Turner (<neillwturner@gmail.com>)
4
- #
5
- # Copyright (C) 2013, Fletcher Nichol, 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
- require 'kitchen/errors'
20
- require 'kitchen/logging'
21
-
22
- module Kitchen
23
-
24
- module Provisioner
25
-
26
- module Puppet
27
-
28
- # Puppet module resolver that uses Librarian-Puppet and a Puppetfile to
29
- # calculate # dependencies.
30
- #
31
- class Librarian
32
-
33
- include Logging
34
-
35
-
36
- def initialize(puppetfile, path, logger = Kitchen.logger)
37
- @puppetfile = puppetfile
38
- @path = path
39
- @logger = logger
40
- end
41
-
42
- def self.load!(logger = Kitchen.logger)
43
- load_librarian!(logger)
44
- end
45
-
46
- def resolve
47
- version = ::Librarian::Puppet::VERSION
48
- info("Resolving module dependencies with Librarian-Puppet #{version}...")
49
- debug("Using Puppetfile from #{puppetfile}")
50
-
51
- env = ::Librarian::Puppet::Environment.new(
52
- :project_path => File.dirname(puppetfile))
53
- env.config_db.local["path"] = path
54
- ::Librarian::Action::Resolve.new(env).run
55
- ::Librarian::Action::Install.new(env).run
56
- end
57
-
58
- attr_reader :puppetfile, :path, :logger
59
-
60
- def self.load_librarian!(logger)
61
- first_load = require 'librarian/puppet'
62
- require 'librarian/puppet/environment'
63
- require 'librarian/action/resolve'
64
- require 'librarian/action/install'
65
-
66
- version = ::Librarian::Puppet::VERSION
67
- if first_load
68
- logger.debug("Librarian-Puppet #{version} library loaded")
69
- else
70
- logger.debug("Librarian-Puppet #{version} previously loaded")
71
- end
72
- rescue LoadError => e
73
- logger.fatal("The `librarian-puppet' gem is missing and must be installed" +
74
- " or cannot be properly activated. Run" +
75
- " `gem install librarian-puppet` or add the following to your" +
76
- " Gemfile if you are using Bundler: `gem 'librarian-puppet'`.")
77
- raise UserError,
78
- "Could not load or activate Librarian-Puppet (#{e.message})"
79
- end
80
- end
81
- end
82
- end
83
- end
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>) Neill Turner (<neillwturner@gmail.com>)
4
+ #
5
+ # Copyright (C) 2013, Fletcher Nichol, 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
+ require 'kitchen/errors'
20
+ require 'kitchen/logging'
21
+
22
+ module Kitchen
23
+
24
+ module Provisioner
25
+
26
+ module Puppet
27
+
28
+ # Puppet module resolver that uses Librarian-Puppet and a Puppetfile to
29
+ # calculate # dependencies.
30
+ #
31
+ class Librarian
32
+
33
+ include Logging
34
+
35
+
36
+ def initialize(puppetfile, path, logger = Kitchen.logger)
37
+ @puppetfile = puppetfile
38
+ @path = path
39
+ @logger = logger
40
+ end
41
+
42
+ def self.load!(logger = Kitchen.logger)
43
+ load_librarian!(logger)
44
+ end
45
+
46
+ def resolve
47
+ version = ::Librarian::Puppet::VERSION
48
+ info("Resolving module dependencies with Librarian-Puppet #{version}...")
49
+ debug("Using Puppetfile from #{puppetfile}")
50
+
51
+ env = ::Librarian::Puppet::Environment.new(
52
+ :project_path => File.dirname(puppetfile))
53
+ env.config_db.local["path"] = path
54
+ ::Librarian::Action::Resolve.new(env).run
55
+ ::Librarian::Action::Install.new(env).run
56
+ end
57
+
58
+ attr_reader :puppetfile, :path, :logger
59
+
60
+ def self.load_librarian!(logger)
61
+ first_load = require 'librarian/puppet'
62
+ require 'librarian/puppet/environment'
63
+ require 'librarian/action/resolve'
64
+ require 'librarian/action/install'
65
+
66
+ version = ::Librarian::Puppet::VERSION
67
+ if first_load
68
+ logger.debug("Librarian-Puppet #{version} library loaded")
69
+ else
70
+ logger.debug("Librarian-Puppet #{version} previously loaded")
71
+ end
72
+ rescue LoadError => e
73
+ logger.fatal("The `librarian-puppet' gem is missing and must be installed" +
74
+ " or cannot be properly activated. Run" +
75
+ " `gem install librarian-puppet` or add the following to your" +
76
+ " Gemfile if you are using Bundler: `gem 'librarian-puppet'`.")
77
+ raise UserError,
78
+ "Could not load or activate Librarian-Puppet (#{e.message})"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,502 +1,542 @@
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 'json'
24
- require 'kitchen/provisioner/base'
25
- require 'kitchen/provisioner/puppet/librarian'
26
-
27
- module Kitchen
28
-
29
- class Busser
30
-
31
- def non_suite_dirs
32
- %w{data data_bags environments nodes roles puppet}
33
- end
34
- end
35
-
36
- module Provisioner
37
- #
38
- # Puppet Apply provisioner.
39
- #
40
- class PuppetApply < Base
41
- attr_accessor :tmp_dir
42
-
43
- default_config :require_puppet_omnibus, false
44
- # TODO use something like https://github.com/fnichol/omnibus-puppet
45
- default_config :puppet_omnibus_url, nil
46
- default_config :puppet_omnibus_remote_path, '/opt/puppet'
47
- default_config :puppet_version, nil
48
- default_config :require_puppet_repo, true
49
- default_config :puppet_apt_repo, "http://apt.puppetlabs.com/puppetlabs-release-precise.deb"
50
- default_config :puppet_yum_repo, "https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm"
51
- default_config :chef_bootstrap_url, "https://www.getchef.com/chef/install.sh"
52
-
53
- default_config :hiera_data_remote_path, '/var/lib/hiera'
54
- default_config :manifest, 'site.pp'
55
-
56
- default_config :manifests_path do |provisioner|
57
- provisioner.calculate_path('manifests') or
58
- raise 'No manifests_path detected. Please specify one in .kitchen.yml'
59
- end
60
-
61
- default_config :modules_path do |provisioner|
62
- modules_path = provisioner.calculate_path('modules')
63
- if modules_path.nil? && provisioner.calculate_path('Puppetfile', :file).nil?
64
- raise 'No modules_path detected. Please specify one in .kitchen.yml'
65
- end
66
- modules_path
67
- end
68
-
69
- default_config :files_path do |provisioner|
70
- provisioner.calculate_path('files') || 'files'
71
- end
72
-
73
- default_config :hiera_data_path do |provisioner|
74
- provisioner.calculate_path('hiera')
75
- end
76
-
77
- default_config :hiera_config_path do |provisioner|
78
- provisioner.calculate_path('hiera.yaml', :file)
79
- end
80
-
81
- default_config :fileserver_config_path do |provisioner|
82
- provisioner.calculate_path('fileserver.conf', :file)
83
- end
84
-
85
- default_config :puppetfile_path do |provisioner|
86
- provisioner.calculate_path('Puppetfile', :file)
87
- end
88
-
89
- default_config :modulefile_path do |provisioner|
90
- provisioner.calculate_path('Modulefile', :file)
91
- end
92
-
93
- default_config :metadata_json_path do |provisioner|
94
- provisioner.calculate_path('metadata.json', :file)
95
- end
96
-
97
- default_config :manifests_path do |provisioner|
98
- provisioner.calculate_path('manifests', :directory)
99
- end
100
-
101
-
102
- default_config :puppet_debug, false
103
- default_config :puppet_verbose, false
104
- default_config :puppet_noop, false
105
- default_config :puppet_platform, ''
106
- default_config :update_package_repos, true
107
- default_config :custom_facts, {}
108
-
109
- def calculate_path(path, type = :directory)
110
- base = config[:test_base_path]
111
- candidates = []
112
- candidates << File.join(base, instance.suite.name, 'puppet', path)
113
- candidates << File.join(base, instance.suite.name, path)
114
- candidates << File.join(base, path)
115
- candidates << File.join(Dir.pwd, path)
116
-
117
- candidates.find do |c|
118
- type == :directory ? File.directory?(c) : File.file?(c)
119
- end
120
- end
121
-
122
- def install_command
123
- return unless config[:require_puppet_omnibus] or config[:require_puppet_repo]
124
- if config[:require_puppet_omnibus]
125
- info("Installing puppet using puppet omnibus")
126
- version = if !config[:puppet_version].nil?
127
- "-v #{config[:puppet_version]}"
128
- else
129
- ""
130
- end
131
- <<-INSTALL
132
- #{Util.shell_helpers}
133
-
134
- if [ ! -d "#{config[:puppet_omnibus_remote_path]}" ]; then
135
- echo "-----> Installing Puppet Omnibus"
136
- do_download #{config[:puppet_omnibus_url]} /tmp/puppet_install.sh
137
- #{sudo('sh')} /tmp/puppet_install.sh #{version}
138
- fi
139
- #{install_busser}
140
- INSTALL
141
- else
142
- case puppet_platform
143
- when "debian", "ubuntu"
144
- info("Installing puppet on #{puppet_platform}")
145
- <<-INSTALL
146
- if [ ! $(which puppet) ]; then
147
- #{sudo('wget')} #{puppet_apt_repo}
148
- #{sudo('dpkg')} -i #{puppet_apt_repo_file}
149
- #{update_packages_debian_cmd}
150
- #{sudo('apt-get')} -y install puppet#{puppet_debian_version}
151
- fi
152
- #{install_busser}
153
- INSTALL
154
- when "redhat", "centos", "fedora"
155
- info("Installing puppet on #{puppet_platform}")
156
- <<-INSTALL
157
- if [ ! $(which puppet) ]; then
158
- #{sudo('rpm')} -ivh #{puppet_yum_repo}
159
- #{update_packages_redhat_cmd}
160
- #{sudo('yum')} -y install puppet#{puppet_redhat_version}
161
- fi
162
- #{install_busser}
163
- INSTALL
164
- else
165
- info("Installing puppet, will try to determine platform os")
166
- <<-INSTALL
167
- if [ ! $(which puppet) ]; then
168
- if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ]; then
169
- #{sudo('rpm')} -ivh #{puppet_yum_repo}
170
- #{update_packages_redhat_cmd}
171
- #{sudo('yum')} -y install puppet#{puppet_redhat_version}
172
- else
173
- #{sudo('wget')} #{puppet_apt_repo}
174
- #{sudo('dpkg')} -i #{puppet_apt_repo_file}
175
- #{update_packages_debian_cmd}
176
- #{sudo('apt-get')} -y install puppet#{puppet_debian_version}
177
- fi
178
- fi
179
- #{install_busser}
180
- INSTALL
181
- end
182
- end
183
- end
184
-
185
- def install_busser
186
- <<-INSTALL
187
- #{Util.shell_helpers}
188
- # install chef omnibus so that busser works as this is needed to run tests :(
189
- # TODO: work out how to install enough ruby
190
- # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
191
- # whole chef client
192
- if [ ! -d "/opt/chef" ]
193
- then
194
- echo "-----> Installing Chef Omnibus to install busser to run tests"
195
- do_download #{chef_url} /tmp/install.sh
196
- #{sudo('sh')} /tmp/install.sh
197
- fi
198
- INSTALL
199
- end
200
-
201
- def init_command
202
- dirs = %w{modules manifests files hiera hiera.yaml}.
203
- map { |dir| File.join(config[:root_path], dir) }.join(" ")
204
- cmd = "#{sudo('rm')} -rf #{dirs} #{hiera_data_remote_path} /etc/hiera.yaml /etc/puppet/hiera.yaml /etc/puppet/fileserver.conf;"
205
- cmd = cmd+" mkdir -p #{config[:root_path]}"
206
- debug(cmd)
207
- cmd
208
- end
209
-
210
- def create_sandbox
211
- super
212
- debug("Creating local sandbox in #{sandbox_path}")
213
-
214
- yield if block_given?
215
-
216
- prepare_modules
217
- prepare_manifests
218
- prepare_files
219
- prepare_hiera_config
220
- prepare_fileserver_config
221
- prepare_hiera_data
222
- info('Finished Preparing files for transfer')
223
-
224
- end
225
-
226
- def cleanup_sandbox
227
- return if sandbox_path.nil?
228
- debug("Cleaning up local sandbox in #{sandbox_path}")
229
- FileUtils.rmtree(sandbox_path)
230
- end
231
-
232
- def prepare_command
233
- commands = []
234
-
235
- if hiera_config
236
- commands << [
237
- sudo('cp'), File.join(config[:root_path],'hiera.yaml'), '/etc/',
238
- ].join(' ')
239
-
240
- commands << [
241
- sudo('cp'), File.join(config[:root_path],'hiera.yaml'), '/etc/puppet/',
242
- ].join(' ')
243
- end
244
-
245
- if fileserver_config
246
- commands << [
247
- sudo('cp'),
248
- File.join(config[:root_path], 'fileserver.conf'),
249
- '/etc/puppet',
250
- ].join(' ')
251
- end
252
-
253
- if hiera_data and hiera_data_remote_path == '/var/lib/hiera'
254
- commands << [
255
- sudo('cp -r'), File.join(config[:root_path], 'hiera'), '/var/lib/'
256
- ].join(' ')
257
- end
258
-
259
- if hiera_data and hiera_data_remote_path != '/var/lib/hiera'
260
- commands << [
261
- sudo('mkdir -p'), hiera_data_remote_path
262
- ].join(' ')
263
- commands << [
264
- sudo('cp -r'), File.join(config[:root_path], 'hiera/*'), hiera_data_remote_path
265
- ].join(' ')
266
- end
267
-
268
- command = commands.join(' && ')
269
- debug(command)
270
- command
271
- end
272
-
273
- def run_command
274
- [
275
- custom_facts,
276
- sudo('puppet'),
277
- 'apply',
278
- File.join(config[:root_path], 'manifests', manifest),
279
- "--modulepath=#{File.join(config[:root_path], 'modules')}",
280
- "--manifestdir=#{File.join(config[:root_path], 'manifests')}",
281
- "--fileserverconfig=#{File.join(config[:root_path], 'fileserver.conf')}",
282
- puppet_noop_flag,
283
- puppet_verbose_flag,
284
- puppet_debug_flag,
285
- ].join(" ")
286
- end
287
-
288
- protected
289
-
290
- def load_needed_dependencies!
291
- if File.exists?(puppetfile)
292
- debug("Puppetfile found at #{puppetfile}, loading Librarian-Puppet")
293
- Puppet::Librarian.load!(logger)
294
- end
295
- end
296
-
297
- def tmpmodules_dir
298
- File.join(sandbox_path, 'modules')
299
- end
300
-
301
- def puppetfile
302
- config[:puppetfile_path] or ''
303
- end
304
-
305
- def modulefile
306
- config[:modulefile_path] or ''
307
- end
308
-
309
- def metadata_json
310
- config[:metadata_json_path] or ''
311
- end
312
-
313
- def manifest
314
- config[:manifest]
315
- end
316
-
317
- def manifests
318
- config[:manifests_path]
319
- end
320
-
321
- def modules
322
- config[:modules_path]
323
- end
324
-
325
- def files
326
- config[:files_path] || 'files'
327
- end
328
-
329
- def hiera_config
330
- config[:hiera_config_path]
331
- end
332
-
333
- def fileserver_config
334
- config[:fileserver_config_path]
335
- end
336
-
337
- def hiera_data
338
- config[:hiera_data_path]
339
- end
340
-
341
- def hiera_data_remote_path
342
- config[:hiera_data_remote_path]
343
- end
344
-
345
- def puppet_debian_version
346
- config[:puppet_version] ? "=#{config[:puppet_version]}" : nil
347
- end
348
-
349
- def puppet_redhat_version
350
- config[:puppet_version] ? "-#{config[:puppet_version]}" : nil
351
- end
352
-
353
- def puppet_noop_flag
354
- config[:puppet_noop] ? '--noop' : nil
355
- end
356
-
357
- def puppet_debug_flag
358
- config[:puppet_debug] ? '-d' : nil
359
- end
360
-
361
- def puppet_verbose_flag
362
- config[:puppet_verbose] ? '-v' : nil
363
- end
364
-
365
- def puppet_platform
366
- config[:puppet_platform].to_s.downcase
367
- end
368
-
369
- def update_packages_debian_cmd
370
- config[:update_package_repos] ? "#{sudo('apt-get')} update" : nil
371
- end
372
-
373
- def update_packages_redhat_cmd
374
- config[:update_package_repos] ? "#{sudo('yum')} makecache" : nil
375
- end
376
-
377
- def custom_facts
378
- return nil if config[:custom_facts].none?
379
- bash_vars = config[:custom_facts].map { |k,v| "FACTER_#{k}=#{v}" }.join(" ")
380
- bash_vars = "export #{bash_vars};"
381
- debug(bash_vars)
382
- bash_vars
383
- end
384
-
385
- def puppet_apt_repo
386
- config[:puppet_apt_repo]
387
- end
388
-
389
- def puppet_apt_repo_file
390
- config[:puppet_apt_repo].split('/').last
391
- end
392
-
393
- def puppet_yum_repo
394
- config[:puppet_yum_repo]
395
- end
396
-
397
- def chef_url
398
- config[:chef_bootstrap_url]
399
- end
400
-
401
- def prepare_manifests
402
- info('Preparing manifests')
403
- debug("Using manifests from #{manifests}")
404
-
405
- tmp_manifests_dir = File.join(sandbox_path, 'manifests')
406
- FileUtils.mkdir_p(tmp_manifests_dir)
407
- FileUtils.cp_r(Dir.glob("#{manifests}/*"), tmp_manifests_dir)
408
- end
409
-
410
- def prepare_files
411
- info('Preparing files')
412
-
413
- unless File.directory?(files)
414
- info 'nothing to do for files'
415
- return
416
- end
417
-
418
- debug("Using files from #{files}")
419
-
420
- tmp_files_dir = File.join(sandbox_path, 'files')
421
- FileUtils.mkdir_p(tmp_files_dir)
422
- FileUtils.cp_r(Dir.glob("#{files}/*"), tmp_files_dir)
423
- end
424
-
425
- def prepare_modules
426
- info('Preparing modules')
427
-
428
- FileUtils.mkdir_p(tmpmodules_dir)
429
-
430
- if modules && File.directory?(modules)
431
- debug("Using modules from #{modules}")
432
- FileUtils.cp_r(Dir.glob("#{modules}/*"), tmpmodules_dir, remove_destination: true)
433
- else
434
- info 'nothing to do for modules'
435
- end
436
-
437
- resolve_with_librarian if File.exists?(puppetfile)
438
-
439
- copy_self_as_module
440
- end
441
-
442
- def copy_self_as_module
443
- if File.exists?(modulefile)
444
- warn('Modulefile found but this is depricated, ignoring it, see https://tickets.puppetlabs.com/browse/PUP-1188')
445
- end
446
-
447
- if File.exists?(metadata_json)
448
- module_name = nil
449
- begin
450
- module_name = JSON.parse(IO.read(metadata_json))['name'].split('/').last
451
- rescue
452
- error("not able to load or parse #{metadata_json_path} for the name of the module")
453
- end
454
-
455
- if module_name
456
- module_target_path = File.join(sandbox_path, 'modules', module_name)
457
- FileUtils.mkdir_p(module_target_path)
458
- FileUtils.cp_r(
459
- Dir.glob(File.join(config[:kitchen_root], '*')).reject { |entry| entry =~ /modules/ },
460
- module_target_path,
461
- remove_destination: true
462
- )
463
- end
464
- end
465
- end
466
-
467
- def prepare_hiera_config
468
- return unless hiera_config
469
-
470
- info('Preparing hiera')
471
- debug("Using hiera from #{hiera_config}")
472
-
473
- FileUtils.cp_r(hiera_config, File.join(sandbox_path, 'hiera.yaml'))
474
- end
475
-
476
- def prepare_fileserver_config
477
- return unless fileserver_config
478
-
479
- info('Preparing fileserver')
480
- debug("Using fileserver config from #{fileserver_config}")
481
-
482
- FileUtils.cp_r(fileserver_config, File.join(sandbox_path, 'fileserver.conf'))
483
- end
484
-
485
- def prepare_hiera_data
486
- return unless hiera_data
487
- info('Preparing hiera data')
488
- debug("Using hiera data from #{hiera_data}")
489
-
490
- tmp_hiera_dir = File.join(sandbox_path, 'hiera')
491
- FileUtils.mkdir_p(tmp_hiera_dir)
492
- FileUtils.cp_r(Dir.glob("#{hiera_data}/*"), tmp_hiera_dir)
493
- end
494
-
495
- def resolve_with_librarian
496
- Kitchen.mutex.synchronize do
497
- Puppet::Librarian.new(puppetfile, tmpmodules_dir, logger).resolve
498
- end
499
- end
500
- end
501
- end
502
- 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 'json'
24
+ require 'kitchen/provisioner/base'
25
+ require 'kitchen/provisioner/puppet/librarian'
26
+
27
+ module Kitchen
28
+
29
+ class Busser
30
+
31
+ def non_suite_dirs
32
+ %w{data data_bags environments nodes roles puppet}
33
+ end
34
+ end
35
+
36
+ module Provisioner
37
+ #
38
+ # Puppet Apply provisioner.
39
+ #
40
+ class PuppetApply < Base
41
+ attr_accessor :tmp_dir
42
+
43
+ default_config :require_puppet_omnibus, false
44
+ # TODO use something like https://github.com/fnichol/omnibus-puppet
45
+ default_config :puppet_omnibus_url, nil
46
+ default_config :puppet_omnibus_remote_path, '/opt/puppet'
47
+ default_config :puppet_version, nil
48
+ default_config :require_puppet_repo, true
49
+ default_config :require_chef_for_busser, true
50
+ default_config :resolve_with_librarian_puppet, true
51
+ default_config :puppet_apt_repo, "http://apt.puppetlabs.com/puppetlabs-release-precise.deb"
52
+ default_config :puppet_yum_repo, "https://yum.puppetlabs.com/puppetlabs-release-el-6.noarch.rpm"
53
+ default_config :chef_bootstrap_url, "https://www.getchef.com/chef/install.sh"
54
+
55
+ default_config :puppet_apply_command, nil
56
+
57
+ default_config :hiera_data_remote_path, '/var/lib/hiera'
58
+ default_config :manifest, 'site.pp'
59
+
60
+ default_config :manifests_path do |provisioner|
61
+ provisioner.calculate_path('manifests') or
62
+ raise 'No manifests_path detected. Please specify one in .kitchen.yml'
63
+ end
64
+
65
+ default_config :modules_path do |provisioner|
66
+ modules_path = provisioner.calculate_path('modules')
67
+ if modules_path.nil? && provisioner.calculate_path('Puppetfile', :file).nil?
68
+ raise 'No modules_path detected. Please specify one in .kitchen.yml'
69
+ end
70
+ modules_path
71
+ end
72
+
73
+ default_config :files_path do |provisioner|
74
+ provisioner.calculate_path('files') || 'files'
75
+ end
76
+
77
+ default_config :hiera_data_path do |provisioner|
78
+ provisioner.calculate_path('hiera')
79
+ end
80
+
81
+ default_config :puppet_config_path do |provisioner|
82
+ provisioner.calculate_path('puppet.conf', :file)
83
+ end
84
+
85
+ default_config :hiera_config_path do |provisioner|
86
+ provisioner.calculate_path('hiera.yaml', :file)
87
+ end
88
+
89
+ default_config :fileserver_config_path do |provisioner|
90
+ provisioner.calculate_path('fileserver.conf', :file)
91
+ end
92
+
93
+ default_config :puppetfile_path do |provisioner|
94
+ provisioner.calculate_path('Puppetfile', :file)
95
+ end
96
+
97
+ default_config :modulefile_path do |provisioner|
98
+ provisioner.calculate_path('Modulefile', :file)
99
+ end
100
+
101
+ default_config :metadata_json_path do |provisioner|
102
+ provisioner.calculate_path('metadata.json', :file)
103
+ end
104
+
105
+ default_config :manifests_path do |provisioner|
106
+ provisioner.calculate_path('manifests', :directory)
107
+ end
108
+
109
+
110
+ default_config :puppet_debug, false
111
+ default_config :puppet_verbose, false
112
+ default_config :puppet_noop, false
113
+ default_config :puppet_platform, ''
114
+ default_config :update_package_repos, true
115
+ default_config :custom_facts, {}
116
+
117
+ def calculate_path(path, type = :directory)
118
+ base = config[:test_base_path]
119
+ candidates = []
120
+ candidates << File.join(base, instance.suite.name, 'puppet', path)
121
+ candidates << File.join(base, instance.suite.name, path)
122
+ candidates << File.join(base, path)
123
+ candidates << File.join(Dir.pwd, path)
124
+
125
+ candidates.find do |c|
126
+ type == :directory ? File.directory?(c) : File.file?(c)
127
+ end
128
+ end
129
+
130
+ def install_command
131
+ return unless config[:require_puppet_omnibus] or config[:require_puppet_repo]
132
+ if config[:require_puppet_omnibus]
133
+ info("Installing puppet using puppet omnibus")
134
+ version = if !config[:puppet_version].nil?
135
+ "-v #{config[:puppet_version]}"
136
+ else
137
+ ""
138
+ end
139
+ <<-INSTALL
140
+ #{Util.shell_helpers}
141
+
142
+ if [ ! -d "#{config[:puppet_omnibus_remote_path]}" ]; then
143
+ echo "-----> Installing Puppet Omnibus"
144
+ do_download #{config[:puppet_omnibus_url]} /tmp/puppet_install.sh
145
+ #{sudo('sh')} /tmp/puppet_install.sh #{version}
146
+ fi
147
+ #{install_busser}
148
+ INSTALL
149
+ else
150
+ case puppet_platform
151
+ when "debian", "ubuntu"
152
+ info("Installing puppet on #{puppet_platform}")
153
+ <<-INSTALL
154
+ if [ ! $(which puppet) ]; then
155
+ #{sudo('wget')} #{puppet_apt_repo}
156
+ #{sudo('dpkg')} -i #{puppet_apt_repo_file}
157
+ #{update_packages_debian_cmd}
158
+ #{sudo('apt-get')} -y install puppet-common#{puppet_debian_version}
159
+ #{sudo('apt-get')} -y install puppet#{puppet_debian_version}
160
+ fi
161
+ #{install_busser}
162
+ INSTALL
163
+ when "redhat", "centos", "fedora"
164
+ info("Installing puppet on #{puppet_platform}")
165
+ <<-INSTALL
166
+ if [ ! $(which puppet) ]; then
167
+ #{sudo('rpm')} -ivh #{puppet_yum_repo}
168
+ #{update_packages_redhat_cmd}
169
+ #{sudo('yum')} -y install puppet#{puppet_redhat_version}
170
+ fi
171
+ #{install_busser}
172
+ INSTALL
173
+ else
174
+ info("Installing puppet, will try to determine platform os")
175
+ <<-INSTALL
176
+ if [ ! $(which puppet) ]; then
177
+ if [ -f /etc/centos-release ] || [ -f /etc/redhat-release ] || [ -f /etc/oracle-release ]; then
178
+ #{sudo('rpm')} -ivh #{puppet_yum_repo}
179
+ #{update_packages_redhat_cmd}
180
+ #{sudo('yum')} -y install puppet#{puppet_redhat_version}
181
+ else
182
+ #{sudo('wget')} #{puppet_apt_repo}
183
+ #{sudo('dpkg')} -i #{puppet_apt_repo_file}
184
+ #{update_packages_debian_cmd}
185
+ #{sudo('apt-get')} -y install puppet-common#{puppet_debian_version}
186
+ #{sudo('apt-get')} -y install puppet#{puppet_debian_version}
187
+ fi
188
+ fi
189
+ #{install_busser}
190
+ INSTALL
191
+ end
192
+ end
193
+ end
194
+
195
+ def install_busser
196
+ if config[:require_chef_for_busser]
197
+ <<-INSTALL
198
+ #{Util.shell_helpers}
199
+ # install chef omnibus so that busser works as this is needed to run tests :(
200
+ # TODO: work out how to install enough ruby
201
+ # and set busser: { :ruby_bindir => '/usr/bin/ruby' } so that we dont need the
202
+ # whole chef client
203
+ if [ ! -d "/opt/chef" ]
204
+ then
205
+ echo "-----> Installing Chef Omnibus to install busser to run tests"
206
+ do_download #{chef_url} /tmp/install.sh
207
+ #{sudo('sh')} /tmp/install.sh
208
+ fi
209
+ INSTALL
210
+ end
211
+ end
212
+
213
+
214
+
215
+ def init_command
216
+ dirs = %w{modules manifests files hiera hiera.yaml}.
217
+ map { |dir| File.join(config[:root_path], dir) }.join(" ")
218
+ cmd = "#{sudo('rm')} -rf #{dirs} #{hiera_data_remote_path} /etc/hiera.yaml /etc/puppet/hiera.yaml /etc/puppet/fileserver.conf;"
219
+ cmd = cmd+" mkdir -p #{config[:root_path]}"
220
+ debug(cmd)
221
+ cmd
222
+ end
223
+
224
+ def create_sandbox
225
+ super
226
+ debug("Creating local sandbox in #{sandbox_path}")
227
+
228
+ yield if block_given?
229
+
230
+ prepare_modules
231
+ prepare_manifests
232
+ prepare_files
233
+ prepare_puppet_config
234
+ prepare_hiera_config
235
+ prepare_fileserver_config
236
+ prepare_hiera_data
237
+ info('Finished Preparing files for transfer')
238
+
239
+ end
240
+
241
+ def cleanup_sandbox
242
+ return if sandbox_path.nil?
243
+ debug("Cleaning up local sandbox in #{sandbox_path}")
244
+ FileUtils.rmtree(sandbox_path)
245
+ end
246
+
247
+ def prepare_command
248
+ commands = []
249
+
250
+ if puppet_config
251
+ commands << [
252
+ sudo('cp'),
253
+ File.join(config[:root_path], 'puppet.conf'),
254
+ '/etc/puppet',
255
+ ].join(' ')
256
+ end
257
+
258
+ if hiera_config
259
+ commands << [
260
+ sudo('cp'), File.join(config[:root_path],'hiera.yaml'), '/etc/',
261
+ ].join(' ')
262
+
263
+ commands << [
264
+ sudo('cp'), File.join(config[:root_path],'hiera.yaml'), '/etc/puppet/',
265
+ ].join(' ')
266
+ end
267
+
268
+ if fileserver_config
269
+ commands << [
270
+ sudo('cp'),
271
+ File.join(config[:root_path], 'fileserver.conf'),
272
+ '/etc/puppet',
273
+ ].join(' ')
274
+ end
275
+
276
+ if hiera_data and hiera_data_remote_path == '/var/lib/hiera'
277
+ commands << [
278
+ sudo('cp -r'), File.join(config[:root_path], 'hiera'), '/var/lib/'
279
+ ].join(' ')
280
+ end
281
+
282
+ if hiera_data and hiera_data_remote_path != '/var/lib/hiera'
283
+ commands << [
284
+ sudo('mkdir -p'), hiera_data_remote_path
285
+ ].join(' ')
286
+ commands << [
287
+ sudo('cp -r'), File.join(config[:root_path], 'hiera/*'), hiera_data_remote_path
288
+ ].join(' ')
289
+ end
290
+
291
+ command = commands.join(' && ')
292
+ debug(command)
293
+ command
294
+ end
295
+
296
+ def run_command
297
+ if !config[:puppet_apply_command].nil?
298
+ return config[:puppet_apply_command]
299
+ else
300
+ [
301
+ custom_facts,
302
+ sudo('puppet'),
303
+ 'apply',
304
+ File.join(config[:root_path], 'manifests', manifest),
305
+ "--modulepath=#{File.join(config[:root_path], 'modules')}",
306
+ "--manifestdir=#{File.join(config[:root_path], 'manifests')}",
307
+ "--fileserverconfig=#{File.join(config[:root_path], 'fileserver.conf')}",
308
+ puppet_noop_flag,
309
+ puppet_verbose_flag,
310
+ puppet_debug_flag,
311
+ ].join(" ")
312
+ end
313
+ end
314
+
315
+ protected
316
+
317
+ def load_needed_dependencies!
318
+ if File.exists?(puppetfile) and config[:resolve_with_librarian_puppet]
319
+ debug("Puppetfile found at #{puppetfile}, loading Librarian-Puppet")
320
+ Puppet::Librarian.load!(logger)
321
+ end
322
+ end
323
+
324
+ def tmpmodules_dir
325
+ File.join(sandbox_path, 'modules')
326
+ end
327
+
328
+ def puppetfile
329
+ config[:puppetfile_path] or ''
330
+ end
331
+
332
+ def modulefile
333
+ config[:modulefile_path] or ''
334
+ end
335
+
336
+ def metadata_json
337
+ config[:metadata_json_path] or ''
338
+ end
339
+
340
+ def manifest
341
+ config[:manifest]
342
+ end
343
+
344
+ def manifests
345
+ config[:manifests_path]
346
+ end
347
+
348
+ def modules
349
+ config[:modules_path]
350
+ end
351
+
352
+ def files
353
+ config[:files_path] || 'files'
354
+ end
355
+
356
+ def puppet_config
357
+ config[:puppet_config_path]
358
+ end
359
+
360
+ def hiera_config
361
+ config[:hiera_config_path]
362
+ end
363
+
364
+ def fileserver_config
365
+ config[:fileserver_config_path]
366
+ end
367
+
368
+ def hiera_data
369
+ config[:hiera_data_path]
370
+ end
371
+
372
+ def hiera_data_remote_path
373
+ config[:hiera_data_remote_path]
374
+ end
375
+
376
+ def puppet_debian_version
377
+ config[:puppet_version] ? "=#{config[:puppet_version]}" : nil
378
+ end
379
+
380
+ def puppet_redhat_version
381
+ config[:puppet_version] ? "-#{config[:puppet_version]}" : nil
382
+ end
383
+
384
+ def puppet_noop_flag
385
+ config[:puppet_noop] ? '--noop' : nil
386
+ end
387
+
388
+ def puppet_debug_flag
389
+ config[:puppet_debug] ? '-d' : nil
390
+ end
391
+
392
+ def puppet_verbose_flag
393
+ config[:puppet_verbose] ? '-v' : nil
394
+ end
395
+
396
+ def puppet_platform
397
+ config[:puppet_platform].to_s.downcase
398
+ end
399
+
400
+ def update_packages_debian_cmd
401
+ config[:update_package_repos] ? "#{sudo('apt-get')} update" : nil
402
+ end
403
+
404
+ def update_packages_redhat_cmd
405
+ config[:update_package_repos] ? "#{sudo('yum')} makecache" : nil
406
+ end
407
+
408
+ def custom_facts
409
+ return nil if config[:custom_facts].none?
410
+ bash_vars = config[:custom_facts].map { |k,v| "FACTER_#{k}=#{v}" }.join(" ")
411
+ bash_vars = "export #{bash_vars};"
412
+ debug(bash_vars)
413
+ bash_vars
414
+ end
415
+
416
+ def puppet_apt_repo
417
+ config[:puppet_apt_repo]
418
+ end
419
+
420
+ def puppet_apt_repo_file
421
+ config[:puppet_apt_repo].split('/').last
422
+ end
423
+
424
+ def puppet_yum_repo
425
+ config[:puppet_yum_repo]
426
+ end
427
+
428
+ def chef_url
429
+ config[:chef_bootstrap_url]
430
+ end
431
+
432
+ def prepare_manifests
433
+ info('Preparing manifests')
434
+ debug("Using manifests from #{manifests}")
435
+
436
+ tmp_manifests_dir = File.join(sandbox_path, 'manifests')
437
+ FileUtils.mkdir_p(tmp_manifests_dir)
438
+ FileUtils.cp_r(Dir.glob("#{manifests}/*"), tmp_manifests_dir)
439
+ end
440
+
441
+ def prepare_files
442
+ info('Preparing files')
443
+
444
+ unless File.directory?(files)
445
+ info 'nothing to do for files'
446
+ return
447
+ end
448
+
449
+ debug("Using files from #{files}")
450
+
451
+ tmp_files_dir = File.join(sandbox_path, 'files')
452
+ FileUtils.mkdir_p(tmp_files_dir)
453
+ FileUtils.cp_r(Dir.glob("#{files}/*"), tmp_files_dir)
454
+ end
455
+
456
+ def prepare_modules
457
+ info('Preparing modules')
458
+
459
+ FileUtils.mkdir_p(tmpmodules_dir)
460
+
461
+ resolve_with_librarian if File.exists?(puppetfile) and config[:resolve_with_librarian_puppet]
462
+
463
+ if modules && File.directory?(modules)
464
+ debug("Copying modules from #{modules} to #{tmpmodules_dir}")
465
+ FileUtils.cp_r(Dir.glob("#{modules}/*"), tmpmodules_dir, remove_destination: true)
466
+ else
467
+ info 'nothing to do for modules'
468
+ end
469
+
470
+ copy_self_as_module
471
+ end
472
+
473
+ def copy_self_as_module
474
+ if File.exists?(modulefile)
475
+ warn('Modulefile found but this is depricated, ignoring it, see https://tickets.puppetlabs.com/browse/PUP-1188')
476
+ end
477
+
478
+ if File.exists?(metadata_json)
479
+ module_name = nil
480
+ begin
481
+ module_name = JSON.parse(IO.read(metadata_json))['name'].split('/').last
482
+ rescue
483
+ error("not able to load or parse #{metadata_json_path} for the name of the module")
484
+ end
485
+
486
+ if module_name
487
+ module_target_path = File.join(sandbox_path, 'modules', module_name)
488
+ FileUtils.mkdir_p(module_target_path)
489
+ FileUtils.cp_r(
490
+ Dir.glob(File.join(config[:kitchen_root], '*')).reject { |entry| entry =~ /modules/ },
491
+ module_target_path,
492
+ remove_destination: true
493
+ )
494
+ end
495
+ end
496
+ end
497
+
498
+ def prepare_puppet_config
499
+ return unless puppet_config
500
+
501
+ info('Preparing puppet.conf')
502
+ debug("Using puppet config from #{puppet_config}")
503
+
504
+ FileUtils.cp_r(puppet_config, File.join(sandbox_path, 'puppet.conf'))
505
+ end
506
+
507
+ def prepare_hiera_config
508
+ return unless hiera_config
509
+
510
+ info('Preparing hiera')
511
+ debug("Using hiera from #{hiera_config}")
512
+
513
+ FileUtils.cp_r(hiera_config, File.join(sandbox_path, 'hiera.yaml'))
514
+ end
515
+
516
+ def prepare_fileserver_config
517
+ return unless fileserver_config
518
+
519
+ info('Preparing fileserver')
520
+ debug("Using fileserver config from #{fileserver_config}")
521
+
522
+ FileUtils.cp_r(fileserver_config, File.join(sandbox_path, 'fileserver.conf'))
523
+ end
524
+
525
+ def prepare_hiera_data
526
+ return unless hiera_data
527
+ info('Preparing hiera data')
528
+
529
+ tmp_hiera_dir = File.join(sandbox_path, 'hiera')
530
+ debug("Copying hiera data from #{hiera_data} to #{tmp_hiera_dir}")
531
+ FileUtils.mkdir_p(tmp_hiera_dir)
532
+ FileUtils.cp_r(Dir.glob("#{hiera_data}/*"), tmp_hiera_dir)
533
+ end
534
+
535
+ def resolve_with_librarian
536
+ Kitchen.mutex.synchronize do
537
+ Puppet::Librarian.new(puppetfile, tmpmodules_dir, logger).resolve
538
+ end
539
+ end
540
+ end
541
+ end
542
+ end