devstructure 0.4.0 → 0.5.0
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/lib/devstructure/blueprint.rb +13 -11
- data/lib/devstructure/chef.rb +5 -5
- data/lib/devstructure/puppet.rb +83 -7
- metadata +4 -4
@@ -235,8 +235,7 @@ EOF
|
|
235
235
|
|
236
236
|
# This is the Puppet code generator.
|
237
237
|
def puppet(io=StringIO.new)
|
238
|
-
|
239
|
-
manifest = Puppet::Manifest.new(@name)
|
238
|
+
manifest = Puppet::Manifest.new(@name, nil, disclaimer)
|
240
239
|
|
241
240
|
# Right out of the gate, we set a default `PATH` because Puppet does not.
|
242
241
|
manifest << Puppet::Exec.defaults(:path => ENV["PATH"].split(":"))
|
@@ -264,7 +263,7 @@ EOF
|
|
264
263
|
if 0 < classes.length
|
265
264
|
manifest << Puppet::File.defaults(:before => classes)
|
266
265
|
end
|
267
|
-
files.
|
266
|
+
files.each do |pathname, content|
|
268
267
|
|
269
268
|
# Resources for all parent directories are created ahead of
|
270
269
|
# any file. Puppet's autorequire mechanism will ensure that a
|
@@ -272,7 +271,7 @@ EOF
|
|
272
271
|
dirnames = File.dirname(pathname).split("/")
|
273
272
|
dirnames.shift
|
274
273
|
(0..(dirnames.length - 1)).each do |i|
|
275
|
-
manifest << Puppet::File.new("/#{dirnames[0..i].join("/")}",
|
274
|
+
manifest << Puppet::File.new("/#{dirnames[0..i].join("/")}", nil,
|
276
275
|
:ensure => :directory)
|
277
276
|
end
|
278
277
|
|
@@ -284,10 +283,12 @@ EOF
|
|
284
283
|
options[:group] = content["_group"] if content["_group"]
|
285
284
|
if content["_target"]
|
286
285
|
options[:ensure] = content["_target"]
|
286
|
+
content = nil
|
287
287
|
else
|
288
288
|
options[:mode] = content["_mode"] if content["_mode"]
|
289
289
|
options[:ensure] = :file
|
290
|
-
options[:content] =
|
290
|
+
options[:content] = :"template(\"#{manifest.name}#{pathname}\")"
|
291
|
+
content = if content["_base64"]
|
291
292
|
Base64.decode64(content["_base64"])
|
292
293
|
else
|
293
294
|
content["_content"]
|
@@ -299,12 +300,12 @@ EOF
|
|
299
300
|
# be set according to the `umask`.
|
300
301
|
else
|
301
302
|
options = {
|
302
|
-
:content =>
|
303
|
+
:content => :"template(\"#{manifest.name}#{pathname}\")",
|
303
304
|
:ensure => :file,
|
304
305
|
}
|
305
306
|
end
|
306
307
|
|
307
|
-
manifest << Puppet::File.new(pathname, options)
|
308
|
+
manifest << Puppet::File.new(pathname, content, options)
|
308
309
|
end
|
309
310
|
end
|
310
311
|
|
@@ -426,7 +427,7 @@ EOF
|
|
426
427
|
# such as this in a shell invocation. This is a pretty direct Puppet
|
427
428
|
# equivalent to the shell version above.
|
428
429
|
if sources && 0 < sources.length
|
429
|
-
sources.
|
430
|
+
sources.each do |dirname, filename|
|
430
431
|
manifest << Puppet::Exec.new(filename,
|
431
432
|
:command => "/bin/sh -c 'wget http://s3.amazonaws.com/blueprint-sources/#{filename}; tar xf #{filename}; rm #{filename}'",
|
432
433
|
:cwd => dirname
|
@@ -434,9 +435,10 @@ EOF
|
|
434
435
|
end
|
435
436
|
end
|
436
437
|
|
437
|
-
|
438
|
-
|
439
|
-
io
|
438
|
+
# Generate a module tarball containing the manifest and any templates
|
439
|
+
# needed to compile a catalog that includes this module.
|
440
|
+
manifest.to_gz(io)
|
441
|
+
|
440
442
|
end
|
441
443
|
|
442
444
|
# This is the Chef code generator. It is the first of its kind in
|
data/lib/devstructure/chef.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# The Chef code generator is structured much like the shell code generator
|
2
2
|
# because Chef doesn't include any sort of dependency management like
|
3
|
-
# Puppet. As expected, we'll start with
|
3
|
+
# Puppet. As expected, we'll start with files, follow them with packages,
|
4
4
|
# and finish with source tarballs.
|
5
5
|
#
|
6
6
|
# The monkeywrench is that the ultimate output is a tarball of a Chef
|
@@ -94,20 +94,20 @@ module Chef
|
|
94
94
|
:mtime => mtime
|
95
95
|
}) { |w| w.write resources }
|
96
96
|
|
97
|
-
#
|
97
|
+
# Include any files referenced by `cookbook_file` resources. They
|
98
98
|
# all appear in `files/default/` as if that is the root of the
|
99
99
|
# filesystem.
|
100
100
|
if 0 < @files.length
|
101
101
|
tar.mkdir "#{@name}/files", :mode => 0755, :mtime => mtime
|
102
102
|
tar.mkdir "#{@name}/files/default", :mode => 0755, :mtime => mtime
|
103
|
-
@files.each do |
|
104
|
-
dirnames = File.dirname(
|
103
|
+
@files.each do |pathname, content|
|
104
|
+
dirnames = File.dirname(pathname).split("/")
|
105
105
|
dirnames.shift
|
106
106
|
(0..(dirnames.length - 1)).each do |i|
|
107
107
|
tar.mkdir "#{@name}/files/default/#{dirnames[0..i].join("/")}",
|
108
108
|
:mode => 0755, :mtime => mtime
|
109
109
|
end
|
110
|
-
tar.add_file_simple("#{@name}/files/default#{
|
110
|
+
tar.add_file_simple("#{@name}/files/default#{pathname}", {
|
111
111
|
:mode => 0644,
|
112
112
|
:size => content.length,
|
113
113
|
:mtime => mtime
|
data/lib/devstructure/puppet.rb
CHANGED
@@ -14,6 +14,13 @@
|
|
14
14
|
# [sandbox-blueprint]: http://devstructure.github.com/contractor/sandbox-blueprint.1.html
|
15
15
|
require 'devstructure'
|
16
16
|
|
17
|
+
# Unfortunately, RubyGems rears its ugly head. The call to `gem` here is
|
18
|
+
# just because the gem's name is different than the path being `require`d.
|
19
|
+
gem 'archive-tar-minitar', :require => 'archive/tar/minitar'
|
20
|
+
require 'archive/tar/minitar'
|
21
|
+
|
22
|
+
require 'zlib'
|
23
|
+
|
17
24
|
# Make `Symbol`s and `nil`s `Comparable` so we can sort each list of resource
|
18
25
|
# attributes before converting to a string.
|
19
26
|
class Symbol
|
@@ -37,11 +44,13 @@ module DevStructure::Puppet
|
|
37
44
|
|
38
45
|
# Each class must have a name and might have a parent. If a manifest
|
39
46
|
# has a parent, this signals it to `include` itself in the parent.
|
40
|
-
def initialize(name, parent=nil)
|
41
|
-
@name, @parent = name, parent
|
47
|
+
def initialize(name, parent=nil, comment=nil)
|
48
|
+
@name, @parent, @comment = name.gsub(".", "--"), parent, comment
|
42
49
|
@manifests, @resources = {}, {}
|
43
50
|
end
|
44
51
|
|
52
|
+
attr_reader :name
|
53
|
+
|
45
54
|
# Manifests behave a bit like hashes in that their children can be
|
46
55
|
# traversed. Note the children can't be assigned directly because
|
47
56
|
# we must maintain parent-child relationships.
|
@@ -68,6 +77,18 @@ module DevStructure::Puppet
|
|
68
77
|
end
|
69
78
|
end
|
70
79
|
|
80
|
+
# Return a hash of `pathname`s to `content`s for all the templates
|
81
|
+
# referenced in this manifest. `file` resources which define the
|
82
|
+
# `content` attribute must have a template containing the file itself.
|
83
|
+
def templates
|
84
|
+
out = {}
|
85
|
+
(@resources["file"] || {}).select do |name, resource|
|
86
|
+
next unless resource[:content] && resource.content
|
87
|
+
out[name] = resource.content
|
88
|
+
end
|
89
|
+
out
|
90
|
+
end
|
91
|
+
|
71
92
|
# Turn this manifest into a Puppet class. We start with a base level
|
72
93
|
# of indentation that we carry through our resources and manifests.
|
73
94
|
# Order is again not important so we don't make much effort. The
|
@@ -80,7 +101,8 @@ module DevStructure::Puppet
|
|
80
101
|
# ourselves in the parent.
|
81
102
|
def to_s(tab="")
|
82
103
|
out = []
|
83
|
-
out <<
|
104
|
+
out << @comment if @comment
|
105
|
+
out << "#{tab}class #{@name} {"
|
84
106
|
@manifests.each_value do |manifest|
|
85
107
|
out << manifest.to_s("#{tab}\t")
|
86
108
|
end
|
@@ -100,10 +122,54 @@ module DevStructure::Puppet
|
|
100
122
|
end
|
101
123
|
end
|
102
124
|
out << "#{tab}}"
|
103
|
-
out << "#{tab}include #{@name
|
125
|
+
out << "#{tab}include #{@name}" if @parent
|
104
126
|
out.join("\n")
|
105
127
|
end
|
106
128
|
|
129
|
+
# Create a Puppet module containing a manifest and the files being
|
130
|
+
# distributed as templates.
|
131
|
+
def to_gz(io)
|
132
|
+
mtime = Time.now
|
133
|
+
gz = Zlib::GzipWriter.new(io)
|
134
|
+
tar = Archive::Tar::Minitar::Writer.new(gz)
|
135
|
+
tar.mkdir @name, :mode => 0755, :mtime => mtime
|
136
|
+
|
137
|
+
# Store the manifest in the tarball.
|
138
|
+
manifest = to_s
|
139
|
+
tar.mkdir "#{@name}/manifests", :mode => 0755, :mtime => mtime
|
140
|
+
tar.add_file_simple("#{@name}/manifests/init.pp", {
|
141
|
+
:mode => 0644,
|
142
|
+
:size => manifest.length,
|
143
|
+
:mtime => mtime
|
144
|
+
}) { |w| w.write manifest }
|
145
|
+
|
146
|
+
# Include as templates the content of any files in the module.
|
147
|
+
templates = self.templates
|
148
|
+
@manifests.each_value { |manifest| templates.merge! manifest.templates }
|
149
|
+
if 0 < templates.length
|
150
|
+
tar.mkdir "#{@name}/templates", :mode => 0755, :mtime => mtime
|
151
|
+
templates.each do |pathname, content|
|
152
|
+
dirnames = ::File.dirname(pathname).split("/")
|
153
|
+
dirnames.shift
|
154
|
+
(0..(dirnames.length - 1)).each do |i|
|
155
|
+
tar.mkdir "#{@name}/templates/#{dirnames[0..i].join("/")}",
|
156
|
+
:mode => 0755, :mtime => mtime
|
157
|
+
end
|
158
|
+
tar.add_file_simple("#{@name}/templates#{pathname}", {
|
159
|
+
:mode => 0644,
|
160
|
+
:size => content.length,
|
161
|
+
:mtime => mtime
|
162
|
+
}) { |w| w.write content }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# Return the finalized tarball.
|
167
|
+
tar.close
|
168
|
+
gz.close
|
169
|
+
io
|
170
|
+
|
171
|
+
end
|
172
|
+
|
107
173
|
end
|
108
174
|
|
109
175
|
# A Puppet resource is basically a named hash. The name is unique
|
@@ -113,12 +179,13 @@ module DevStructure::Puppet
|
|
113
179
|
# name to determine the type, so do not instantiate `Resource`
|
114
180
|
# directly.
|
115
181
|
class Resource < Hash
|
116
|
-
|
182
|
+
attr_reader :type
|
183
|
+
attr_accessor :name, :style
|
117
184
|
|
118
185
|
def initialize(name, options={})
|
119
186
|
super nil
|
120
187
|
clear
|
121
|
-
options.each { |k, v| self[k.
|
188
|
+
options.each { |k, v| self[k.to_sym] = v }
|
122
189
|
@type = self.class.to_s.downcase[/[^:]+$/]
|
123
190
|
@name = name && name.to_s
|
124
191
|
@style = :complete
|
@@ -237,7 +304,16 @@ module DevStructure::Puppet
|
|
237
304
|
# type. The most common types are `Package`, `Exec`, and `File`.
|
238
305
|
class Package < Resource; end
|
239
306
|
class Exec < Resource; end
|
240
|
-
|
307
|
+
|
308
|
+
# `File` resources are a special because they need their content stored
|
309
|
+
# in a template.
|
310
|
+
class File < Resource
|
311
|
+
def initialize(name, content, options={})
|
312
|
+
super name, options
|
313
|
+
@content = content
|
314
|
+
end
|
315
|
+
attr_reader :content
|
316
|
+
end
|
241
317
|
|
242
318
|
# `Class` is also a useful resource type but needs a little more help
|
243
319
|
# because of the stricter rules governing class names in the Puppet
|
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:
|
4
|
+
hash: 11
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 5
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.5.0
|
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-
|
18
|
+
date: 2010-10-05 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|