devstructure 0.1.0 → 0.1.1

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.
@@ -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