devstructure 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,11 +9,11 @@ class DevStructure::Blueprint < Hash
9
9
  include DevStructure::Puppet
10
10
 
11
11
  def initialize(name, hash)
12
- @name = name
13
- self["name"] = name
14
12
  super nil
15
13
  clear
16
14
  hash.each { |k, v| self[k.to_s] = v }
15
+ @name = name
16
+ self["name"] = name
17
17
  end
18
18
 
19
19
  attr_accessor :name
@@ -44,7 +44,16 @@ class DevStructure::Blueprint < Hash
44
44
  other.walk(
45
45
  :package => lambda { |manager, command, package, version|
46
46
  return if b.packages[package]
47
- b.packages[manager]["_packages"].delete package
47
+ versions = [b.packages[manager]["_packages"][package]].flatten
48
+ [version].flatten.each { |v| versions.delete v }
49
+ case versions.length
50
+ when 0
51
+ b.packages[manager]["_packages"].delete package
52
+ when 1
53
+ b.packages[manager]["_packages"][package] = versions.to_s
54
+ else
55
+ b.packages[manager]["_packages"][package] = versions
56
+ end
48
57
  }
49
58
  )
50
59
 
@@ -152,69 +161,79 @@ EOF
152
161
 
153
162
  def puppet
154
163
  disclaimer
155
- puts "class #{@name} {"
156
- puts Exec.defaults(:path => ENV["PATH"].split(":"))
164
+ manifest = Manifest.new(@name)
165
+ manifest << Exec.defaults(:path => ENV["PATH"].split(":"))
166
+
167
+ # Map managers to their manager.
168
+ managers = {}
169
+ walk(:package => lambda { |manager, command, package, version|
170
+ managers[package] = manager if packages[package] && manager != package
171
+ })
157
172
 
158
173
  # Packages.
159
174
  walk(
160
175
  :before => lambda { |manager, command|
161
176
  p = packages[manager]["_packages"]
162
177
  return if 0 == p.length || 1 == p.length && p[manager]
163
- puts "\n\t# Packages that depend on #{manager}."
164
- case manager
165
- when /rubygems|rip/
166
- puts "\tpackage {"
167
- when /ruby|python/
168
- puts "\texec {"
169
- else
170
- puts "\tpackage {"
171
- end
172
178
  },
173
179
  :package => lambda { |manager, command, package, version|
174
180
  command =~ /gem(\d+\.\d+) install/
181
+ ruby_version = $1
175
182
  case manager
176
183
  when "apt"
177
184
  unless manager == package
178
- puts Package.partial(package, :ensure => version)
185
+ manifest[manager] << Package.new(package, :ensure => version)
179
186
  end
180
187
  when "rubygems-update"
181
188
  unless manager == package
182
- puts Package.partial(package,
183
- :require => [Package["ruby#{$1}-dev"], Exec["update_rubygems"]],
189
+ manifest[manager] << Package.new(package,
190
+ :require => [
191
+ Puppet::Class[managers[manager]],
192
+ Package["ruby#{ruby_version}-dev"],
193
+ Exec["update_rubygems"],
194
+ ],
184
195
  :provider => :gem,
185
196
  :ensure => version
186
197
  )
187
198
  end
188
199
  when /rubygems|rip/
189
200
  options = {
190
- :require => Package["rubygems#{$1}", "ruby#{$1}-dev"],
201
+ :require => [
202
+ Puppet::Class[managers[manager]],
203
+ Package["rubygems#{ruby_version}", "ruby#{ruby_version}-dev"],
204
+ ],
191
205
  :provider => :gem,
192
206
  :ensure => version
193
207
  }
194
208
  options[:require] += [Package[manager]] unless manager == package
195
- puts Package.partial(package, options)
209
+ manifest[manager] << Package.new(package, options)
196
210
  when /python/
197
- puts Exec.partial(sprintf("#{command}\n", package),
198
- :require => Package[manager, "python-setuptools"]
211
+ manifest[manager] << Exec.new(sprintf("#{command}", package),
212
+ :require => [
213
+ Puppet::Class[managers[manager]],
214
+ Package[manager, "python-setuptools"],
215
+ ]
199
216
  )
200
217
 
201
218
  # TODO Expand Java, Erlang, etc.
202
219
 
203
220
  else
204
- puts Exec.partial(sprintf("#{command}\n", package, version),
205
- :require => Package[manager]
221
+ manifest[manager] << Exec.new(sprintf("#{command}", package,
222
+ version), :require => [
223
+ Puppet::Class[managers[manager]],
224
+ Package[manager],
225
+ ]
206
226
  )
207
227
  end
208
228
  },
209
229
  :after => lambda { |manager, command|
210
230
  p = packages[manager]["_packages"]
211
231
  return if 0 == p.length || 1 == p.length && manager == p.keys.first
212
- puts "\t}"
213
232
 
214
233
  # Update RubyGems if we're through with gems in Debian's location.
215
234
  return unless manager =~ /^rubygems\d+\.\d+$/
216
235
  return unless p["rubygems-update"]
217
- puts Exec.complete("update_rubygems",
236
+ manifest[manager] << Exec.new("update_rubygems",
218
237
  :subscribe => Package["rubygems-update"],
219
238
  :path => %w(/usr/bin /var/lib/gems/1.8/bin),
220
239
  :refreshonly => true
@@ -225,31 +244,29 @@ EOF
225
244
 
226
245
  # System files.
227
246
  if 0 < files.length
228
- puts "\n\t# System files depend on all packages."
229
- puts Package.defaults(
247
+ manifest << Package.defaults(
230
248
  :before => files.sort.map { |pathname, content|
231
249
  Puppet::File[pathname]
232
250
  }
233
251
  )
234
- puts "\tfile {"
235
252
  files.sort.each do |pathname, content|
236
253
  if Hash == content.class
237
254
  if content["_target"]
238
- puts Puppet::File.partial(pathname, :ensure => content["_target"])
255
+ manifest << Puppet::File.new(pathname,
256
+ :ensure => content["_target"])
239
257
  next
240
258
  elsif content["_base64"]
241
259
  content = Base64.decode64(content["_base64"])
242
260
  end
243
261
  end
244
- puts Puppet::File.partial(pathname,
262
+ manifest << Puppet::File.new(pathname,
245
263
  :content => content,
246
264
  :ensure => :present
247
265
  )
248
266
  end
249
- puts "\t}"
250
267
  end
251
268
 
252
- puts "\n}"
269
+ puts manifest
253
270
  end
254
271
 
255
272
  def chef
@@ -9,24 +9,58 @@ end
9
9
 
10
10
  module DevStructure::Puppet
11
11
 
12
- # A generic Puppet resource to be subclassed. The name of the class
13
- # dictates how the resource will be printed so do not instantiate this
14
- # class directly.
15
- class Resource
12
+ # A Puppet manifest that contains a tree of classes that each contain
13
+ # some resources.
14
+ class Manifest
16
15
 
17
- # A resource that will (by default) provide its complete representation.
18
- def self.complete(name, options={})
19
- self.new name, :complete, options
16
+ def initialize(name, parent=nil)
17
+ @name, @parent = name, parent
18
+ @manifests, @resources = {}, []
20
19
  end
21
20
 
22
- # A resource that will (by default) provide its partial representation.
23
- def self.partial(name, options={})
24
- self.new name, :partial, options
21
+ # Return a reference to a sub-manifest of the given name.
22
+ def [](name)
23
+ @manifests[name.to_s] ||= self.class.new(name.to_s, @name)
24
+ end
25
+ def method_missing(symbol, *args)
26
+ self[symbol]
25
27
  end
26
28
 
27
- # A resource that will provide defaults for its resource type.
28
- def self.defaults(options={})
29
- self.new "", :defaults, options
29
+ # Add a resource to this manifest.
30
+ def <<(resource)
31
+ @resources << resource
32
+ end
33
+
34
+ def to_s(tab="")
35
+ out = []
36
+ out << "#{tab}class #{@name.gsub(".", "--")} {"
37
+ @manifests.each_value do |manifest|
38
+ out << manifest.to_s("#{tab}\t")
39
+ end
40
+ @resources.each do |resource|
41
+ out << resource.to_s("#{tab}\t")
42
+ end
43
+ out << "#{tab}}"
44
+ out << "#{tab}include #{@name.gsub(".", "--")}" if @parent
45
+ out.join("\n")
46
+ end
47
+
48
+ end
49
+
50
+ # A generic Puppet resource to be subclassed. The name of the class
51
+ # dictates how the resource will be printed so do not instantiate this
52
+ # class directly.
53
+ class Resource < Hash
54
+ attr_accessor :type, :name, :style
55
+
56
+ # A resource.
57
+ def initialize(name, options={})
58
+ super nil
59
+ clear
60
+ options.each { |k, v| self[k.to_s] = v }
61
+ @type = self.class.to_s.downcase[/[^:]+$/]
62
+ @name = name.to_s.downcase
63
+ @style = :complete
30
64
  end
31
65
 
32
66
  # A resource with only a name, typically being listed as a dependency.
@@ -34,46 +68,52 @@ module DevStructure::Puppet
34
68
  # will be generated.
35
69
  def self.[](*args)
36
70
  if 1 == args.length
37
- self.new args[0], :complete
71
+ self.new args[0]
38
72
  else
39
73
  args.collect { |arg| self[arg] }
40
74
  end
41
75
  end
42
76
 
77
+ # A set of defaults for a resource type.
78
+ def self.defaults(options)
79
+ resource = self.new(nil, options)
80
+ resource.style = :defaults
81
+ resource
82
+ end
83
+
43
84
  # Return Puppet code for this resource. Whether a complete, partial,
44
85
  # or defaults representation is returned depends on which class method
45
86
  # instantiated this resource but can be overridden by passing a Symbol.
46
- def to_s(style=nil)
47
- style ||= @style
87
+ def to_s(tab="")
48
88
  out = []
49
89
 
50
90
  # Settle on the indentation level for the rest of the resource.
51
91
  # Raise an exception if the style is invalid.
52
- tab = case style
92
+ tab_params = case @style
53
93
  when :complete
54
- out << "\t#{@type} { \"#{@name}\":"
55
- "\t"
94
+ out << "#{tab}#{@type} { \"#{@name}\":"
95
+ "#{tab}"
56
96
  when :partial
57
- out << "\t\t\"#{@name}\":"
58
- "\t\t"
97
+ out << "#{tab}\t\"#{@name}\":"
98
+ "#{tab}\t"
59
99
  when :defaults
60
- out << "\t#{@type.capitalize} {"
61
- "\t"
100
+ out << "#{tab}#{@type.capitalize} {"
101
+ "#{tab}"
62
102
  else
63
103
  raise ArgumentError
64
104
  end
65
105
 
66
106
  # Handle the options Hash.
67
- if 0 < @options.length
107
+ if 0 < length
68
108
 
69
109
  # Note the longest option name so we can line up => operators as
70
110
  # per the Puppet coding standards.
71
- l = @options.collect { |k, v| k.to_s.length }.max
111
+ l = collect { |k, v| k.to_s.length }.max
72
112
 
73
113
  # Map options to Puppet code strings. Symbols become unquoted
74
114
  # strings, nils become undefs, and Arrays are flattened. Unless
75
115
  # the value is a Symbol, #inspect is called on the value.
76
- out += @options.sort.collect do |k, v|
116
+ out += sort.collect do |k, v|
77
117
  k = "#{k.to_s}#{" " * (l - k.to_s.length)}"
78
118
  v = if v.respond_to?(:flatten)
79
119
  if 1 == v.length
@@ -86,23 +126,23 @@ module DevStructure::Puppet
86
126
  end
87
127
  v = :undef if v.nil?
88
128
  v = v.inspect.gsub(/\$/, "\\$") unless Symbol == v.class
89
- "\t#{tab}#{k} => #{v},"
129
+ "\t#{tab_params}#{k} => #{v},"
90
130
  end
91
131
 
92
132
  # Close this resource.
93
- case style
133
+ case @style
94
134
  when :complete
95
- out << "\t}"
135
+ out << "#{tab}}"
96
136
  when :partial
97
137
  out << "#{out.pop.chop};"
98
138
  when :defaults
99
- out << "\t}"
139
+ out << "#{tab}}"
100
140
  end
101
141
 
102
142
  # Don't bother with an empty options Hash. Go ahead and close this
103
143
  # resource.
104
144
  else
105
- case style
145
+ case @style
106
146
  when :complete
107
147
  out << "#{out.pop} }"
108
148
  when :partial
@@ -120,15 +160,9 @@ module DevStructure::Puppet
120
160
  def inspect
121
161
  "#{@type.capitalize}[\"#{@name}\"]"
122
162
  end
123
-
124
- # A resource with a name and default representation.
125
- def initialize(name, style, options={})
126
- @type = self.class.to_s.downcase[/[^:]+$/]
127
- @name = name.to_s.downcase
128
- @style = style.to_sym
129
- @options = options
163
+ def pretty_print(pp)
164
+ pp.text inspect
130
165
  end
131
- private :initialize
132
166
 
133
167
  end
134
168
 
@@ -140,4 +174,11 @@ module DevStructure::Puppet
140
174
  class File < Resource
141
175
  end
142
176
 
177
+ # A class resource type for dependencies.
178
+ class Class < Resource
179
+ def inspect
180
+ "#{@type.capitalize}[\"#{@name.gsub(".", "--")}\"]"
181
+ end
182
+ end
183
+
143
184
  end
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: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Richard Crowley