kitchen-puppet 0.0.12 → 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
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