devstructure 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -176,7 +176,7 @@ EOF
176
176
  return if manager == package
177
177
  io.printf "#{command}\n", package, version
178
178
  if "apt" == manager && package =~ /^rubygems(\d+\.\d+(?:\.\d+)?)$/
179
- io.puts "/usr/bin/gem#{$1} install rubygems-update"
179
+ io.puts "/usr/bin/gem#{$1} install --no-rdoc --no-ri rubygems-update"
180
180
  io.puts "/usr/bin/ruby#{$1} $(PATH=\"$PATH:/var/lib/gems/#{
181
181
  $1}/bin\" which update_rubygems)"
182
182
  end
@@ -187,25 +187,35 @@ EOF
187
187
  # and heredoc syntax. Binary files are written using `base64`(1) and
188
188
  # symbolic links are placed using `ln`(1). Shocking stuff.
189
189
  files.sort.each do |pathname, content|
190
- if Hash == content.class
190
+ io.puts "mkdir -p #{File.dirname(pathname)}"
191
+ owner = group = mode = nil
192
+ command = "cat"
193
+ if Hash === content
194
+ owner = content["_owner"]
195
+ group = content["_group"]
191
196
  if content["_target"]
192
197
  io.puts "ln -s #{content["_target"]} #{pathname}"
193
198
  next
194
- elsif content["_base64"]
195
- content = content["_base64"]
196
- command = "base64 --decode"
199
+ else
200
+ mode = content["_mode"]
201
+ if content["_base64"]
202
+ content = content["_base64"]
203
+ command = "base64 --decode"
204
+ else
205
+ content = content["_content"]
206
+ end
197
207
  end
198
- else
199
- content.gsub!(/\\/, "\\\\\\\\")
200
- content.gsub!(/\$/, "\\$")
201
- command = "cat"
202
208
  end
209
+ content.gsub!(/\\/, "\\\\\\\\")
210
+ content.gsub!(/\$/, "\\$")
203
211
  eof = "EOF"
204
212
  eof << "EOF" while content =~ /^#{eof}$/
205
- io.puts "mkdir -p #{File.dirname(pathname)}"
206
213
  io.puts "#{command} >#{pathname} <<#{eof}"
207
214
  io.puts content
208
215
  io.puts eof
216
+ io.puts "chown #{owner} #{pathname}" if owner
217
+ io.puts "chgrp #{group} #{pathname}" if group
218
+ io.puts "chmod #{mode} #{pathname}" if mode
209
219
  end if files
210
220
 
211
221
  # Source tarballs are downloaded, extracted, and removed. Generally,
@@ -231,7 +241,7 @@ EOF
231
241
 
232
242
  # We need a pre-built map of each manager to its own manager so we can
233
243
  # easily declare dependencies within the Puppet manifest tree.
234
- managers = {}
244
+ managers = {"apt" => nil}
235
245
  walk(:package => lambda { |manager, command, package, version|
236
246
  managers[package] = manager if packages[package] && manager != package
237
247
  })
@@ -277,7 +287,7 @@ EOF
277
287
  :provider => :gem,
278
288
  :ensure => :latest
279
289
  )
280
- Puppet::Package["rubygems1.8"]
290
+ Puppet::Package["rubygems-update"]
281
291
  else
282
292
  manifest[manager] << Puppet::Exec.new(
283
293
  "/usr/bin/gem#{v} install --no-rdoc --no-ri rubygems-update",
@@ -287,8 +297,8 @@ EOF
287
297
  Puppet::Exec["rubygems-update-#{v}"]
288
298
  end
289
299
  manifest[manager] << Puppet::Exec.new(
290
- "/usr/bin/ruby#{v} /usr/bin/update_rubygems",
291
- :path => %W(/usr/bin /var/lib/gems/#{v}/bin),
300
+ "/bin/sh -c '/usr/bin/ruby#{v} $(PATH=$PATH:/var/lib/gems/#{
301
+ v}/bin which update_rubygems)'",
292
302
  :require => prereq
293
303
  )
294
304
  end
@@ -354,35 +364,55 @@ EOF
354
364
  #
355
365
  # File content is handled much like the shell version except base 64
356
366
  # decoding takes place here in Ruby rather than in the `base64`(1)
357
- # tool. Resources for all parent directories are created ahead of
358
- # any file. Puppet's autorequire mechanism will ensure that a file's
359
- # parent directories are realized before the file itself.
367
+ # tool.
360
368
  if files && 0 < files.length
361
- manifest << Puppet::Package.defaults(
362
- :before => files.sort.map { |pathname, content|
363
- Puppet::File[pathname]
364
- }
365
- )
369
+ classes = managers.keys.
370
+ reject { |manager| 0 == packages[manager]["_packages"].length }.
371
+ map { |manager| Puppet::Class[manager] }
372
+ if 0 < classes.length
373
+ manifest << Puppet::File.defaults(:require => classes)
374
+ end
366
375
  files.sort.each do |pathname, content|
376
+
377
+ # Resources for all parent directories are created ahead of
378
+ # any file. Puppet's autorequire mechanism will ensure that a
379
+ # file's parent directories are realized before the file itself.
367
380
  dirnames = File.dirname(pathname).split("/")
368
381
  dirnames.shift
369
382
  (0..(dirnames.length - 1)).each do |i|
370
383
  manifest << Puppet::File.new("/#{dirnames[0..i].join("/")}",
371
384
  :ensure => :directory)
372
385
  end
373
- if Hash == content.class
386
+
387
+ # Convert the blueprint file attributes to those that Puppet
388
+ # understands. Everything's optional.
389
+ options = {}
390
+ if Hash === content
391
+ options[:owner] = content["_owner"] if content["_owner"]
392
+ options[:group] = content["_group"] if content["_group"]
374
393
  if content["_target"]
375
- manifest << Puppet::File.new(pathname,
376
- :ensure => content["_target"])
377
- next
378
- elsif content["_base64"]
379
- content = Base64.decode64(content["_base64"])
394
+ options[:ensure] = content["_target"]
395
+ else
396
+ options[:mode] = content["_mode"] if content["_mode"]
397
+ options[:ensure] = :file
398
+ options[:content] = if content["_base64"]
399
+ Base64.decode64(content["_base64"])
400
+ else
401
+ content["_content"]
402
+ end
380
403
  end
404
+
405
+ # The easiest way to specify a file is to include just the
406
+ # content. The owner and group will be `root` and the mode will
407
+ # be set according to the `umask`.
408
+ else
409
+ options = {
410
+ :content => content,
411
+ :ensure => :file,
412
+ }
381
413
  end
382
- manifest << Puppet::File.new(pathname,
383
- :content => content,
384
- :ensure => :file
385
- )
414
+
415
+ manifest << Puppet::File.new(pathname, options)
386
416
  end
387
417
  end
388
418
 
@@ -391,11 +421,6 @@ EOF
391
421
  # such as this in a shell invocation. This is a pretty direct Puppet
392
422
  # equivalent to the shell version above.
393
423
  if sources && 0 < sources.length
394
- manifest << Puppet::Package.defaults(
395
- :before => sources.sort.map { |dirname, filename|
396
- Puppet::Exec[pathname]
397
- }
398
- )
399
424
  sources.sort.each do |dirname, filename|
400
425
  manifest << Puppet::Exec.new(filename,
401
426
  :command => "/bin/sh -c 'wget http://s3.amazonaws.com/blueprint-sources/#{filename}; tar xf #{filename}; rm #{filename}'",
@@ -473,22 +498,30 @@ EOF
473
498
  :mode => "755",
474
499
  :owner => "root",
475
500
  :recursive => true
476
- if Hash == content.class
501
+ owner = group = mode = nil
502
+ if Hash === content
503
+ owner = content["_owner"]
504
+ group = content["_group"]
477
505
  if content["_target"]
478
506
  cookbook.link pathname,
479
- :group => "root",
480
- :owner => "root",
507
+ :group => group || "root",
508
+ :owner => owner || "root",
481
509
  :to => content["_target"]
482
510
  next
483
- elsif content["_base64"]
484
- content = content["_base64"]
511
+ else
512
+ mode = content["_mode"]
513
+ if content["_base64"]
514
+ content = content["_base64"]
515
+ else
516
+ content = content["_content"]
517
+ end
485
518
  end
486
519
  end
487
520
  cookbook.cookbook_file pathname, content,
488
521
  :backup => false,
489
- :group => "root",
490
- :mode => "644",
491
- :owner => "root",
522
+ :group => group || "root",
523
+ :mode => mode || "644",
524
+ :owner => owner || "root",
492
525
  :source => pathname[1..-1]
493
526
  end if files
494
527
 
@@ -14,13 +14,18 @@
14
14
  # [sandbox-blueprint]: http://devstructure.github.com/contractor/sandbox-blueprint.1.html
15
15
  require 'devstructure'
16
16
 
17
- # Make `Symbol`s `Comparable` so we can sort each list of resource
17
+ # Make `Symbol`s and `nil`s `Comparable` so we can sort each list of resource
18
18
  # attributes before converting to a string.
19
19
  class Symbol
20
20
  def <=>(other)
21
21
  to_s <=> other.to_s
22
22
  end
23
23
  end
24
+ class NilClass
25
+ def <=>(other)
26
+ other.nil? ? 0 : 1
27
+ end
28
+ end
24
29
 
25
30
  module DevStructure::Puppet
26
31
 
@@ -48,19 +53,31 @@ module DevStructure::Puppet
48
53
  end
49
54
 
50
55
  # Add a resource to this manifest. Order is never important in Puppet
51
- # since all dependencies must be declared.
56
+ # since all dependencies must be declared. Normal resources that have
57
+ # names are just added to the tree. Resources that are declaring
58
+ # defaults for an entire type have `nil` names so they behave more
59
+ # cumulatively.
52
60
  def <<(resource)
53
61
  @resources[resource.type] ||= {}
54
- @resources[resource.type][resource.name] = resource
62
+ if resource.name
63
+ @resources[resource.type][resource.name] = resource
64
+ elsif @resources[resource.type][resource.name]
65
+ @resources[resource.type][resource.name].merge!(resource)
66
+ else
67
+ @resources[resource.type][resource.name] = resource
68
+ end
55
69
  end
56
70
 
57
71
  # Turn this manifest into a Puppet class. We start with a base level
58
72
  # of indentation that we carry through our resources and manifests.
59
73
  # Order is again not important so we don't make much effort. The
60
74
  # Puppet grammar prohibits dots in class names so we replace `.` with
61
- # `--`. Resources are grouped by type to reduce the total number of
62
- # lines required. If this manifest has a parent, the last thing we
63
- # do is include ourselves in the parent.
75
+ # `--`.
76
+ #
77
+ # Defaults for the entire type are handled first. Normal resources
78
+ # are grouped by type to reduce the total number of lines required.
79
+ # If this manifest has a parent, the last thing we do is include
80
+ # ourselves in the parent.
64
81
  def to_s(tab="")
65
82
  out = []
66
83
  out << "#{tab}class #{@name.gsub(".", "--")} {"
@@ -68,6 +85,9 @@ module DevStructure::Puppet
68
85
  out << manifest.to_s("#{tab}\t")
69
86
  end
70
87
  @resources.sort.each do |type, resources|
88
+ if resource = resources.delete(nil)
89
+ out << resource.to_s("#{tab}\t")
90
+ end
71
91
  if 1 < resources.length
72
92
  out << "#{tab}\t#{type} {"
73
93
  resources.sort.each do |name, resource|
@@ -75,7 +95,7 @@ module DevStructure::Puppet
75
95
  out << resource.to_s("#{tab}\t")
76
96
  end
77
97
  out << "#{tab}\t}"
78
- else
98
+ elsif 1 == resources.length
79
99
  out << resources.values.first.to_s("#{tab}\t")
80
100
  end
81
101
  end
@@ -100,7 +120,7 @@ module DevStructure::Puppet
100
120
  clear
101
121
  options.each { |k, v| self[k.to_s] = v }
102
122
  @type = self.class.to_s.downcase[/[^:]+$/]
103
- @name = name.to_s.downcase
123
+ @name = name && name.to_s
104
124
  @style = :complete
105
125
  end
106
126
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devstructure
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 0
10
- version: 0.3.0
9
+ - 1
10
+ version: 0.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Richard Crowley
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-09-01 00:00:00 +00:00
18
+ date: 2010-09-02 00:00:00 +00:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency