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