logical-construct 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/flight-deck +3 -0
- data/doc/DESIGN +48 -0
- data/doc/EC2-baking-notes +70 -0
- data/doc/ExampleStartupRakefile +152 -0
- data/doc/ExampleTargetRakefile +4 -0
- data/doc/TODO +148 -0
- data/doc/Vb-EC2-translation-notes +96 -0
- data/doc/hating-chef +32 -0
- data/lib/logical-construct/archive-tasks.rb +307 -0
- data/lib/logical-construct/ground-control.rb +4 -1
- data/lib/logical-construct/ground-control/build-plan.rb +95 -0
- data/lib/logical-construct/ground-control/core.rb +1 -1
- data/lib/logical-construct/ground-control/generate-manifest.rb +67 -0
- data/lib/logical-construct/ground-control/provision.rb +73 -168
- data/lib/logical-construct/ground-control/run-on-target.rb +1 -1
- data/lib/logical-construct/ground-control/setup.rb +1 -4
- data/lib/logical-construct/ground-control/setup/copy-files.rb +2 -2
- data/lib/logical-construct/ground-control/tools.rb +66 -0
- data/lib/logical-construct/node-client.rb +112 -0
- data/lib/logical-construct/plan.rb +2 -0
- data/lib/logical-construct/plan/core.rb +45 -0
- data/lib/logical-construct/plan/standalone-bundle.rb +80 -0
- data/lib/logical-construct/port-open-check.rb +41 -0
- data/lib/logical-construct/protocol.rb +2 -0
- data/lib/logical-construct/protocol/plan-validation.rb +46 -0
- data/lib/logical-construct/protocol/ssh-tunnel.rb +127 -0
- data/lib/logical-construct/protocol/vocabulary.rb +8 -0
- data/lib/logical-construct/target/Implement.rake +8 -0
- data/lib/logical-construct/target/command-line.rb +90 -0
- data/lib/logical-construct/target/flight-deck.rb +341 -0
- data/lib/logical-construct/target/implementation.rb +33 -0
- data/lib/logical-construct/target/plan-records.rb +317 -0
- data/lib/logical-construct/target/resolution-server.rb +153 -0
- data/lib/logical-construct/target/{unpack-cookbook.rb → unpack-plan.rb} +8 -4
- data/lib/logical-construct/template-file.rb +41 -0
- data/lib/templates/Rakefile.erb +8 -0
- data/spec/ground-control/smoke-test.rb +8 -7
- data/spec/node_resolution.rb +62 -0
- data/spec/target/plan-records.rb +142 -0
- data/spec/target/provisioning.rb +21 -0
- data/spec_help/file-sandbox.rb +12 -6
- data/spec_help/fixtures/Manifest +1 -0
- data/spec_help/fixtures/source/one.tbz +1 -0
- data/spec_help/fixtures/source/three.tbz +1 -0
- data/spec_help/fixtures/source/two.tbz +1 -0
- data/spec_help/spec_helper.rb +5 -7
- metadata +165 -72
- data/lib/logical-construct/ground-control/setup/build-files.rb +0 -93
- data/lib/logical-construct/ground-control/setup/create-construct-directory.rb +0 -22
- data/lib/logical-construct/ground-control/setup/install-init.rb +0 -32
- data/lib/logical-construct/resolving-task.rb +0 -141
- data/lib/logical-construct/satisfiable-task.rb +0 -87
- data/lib/logical-construct/target.rb +0 -4
- data/lib/logical-construct/target/chef-solo.rb +0 -37
- data/lib/logical-construct/target/platforms.rb +0 -51
- data/lib/logical-construct/target/platforms/aws.rb +0 -8
- data/lib/logical-construct/target/platforms/default/chef-config.rb +0 -134
- data/lib/logical-construct/target/platforms/default/resolve-configuration.rb +0 -44
- data/lib/logical-construct/target/platforms/default/volume.rb +0 -11
- data/lib/logical-construct/target/platforms/virtualbox.rb +0 -8
- data/lib/logical-construct/target/platforms/virtualbox/volume.rb +0 -15
- data/lib/logical-construct/target/provision.rb +0 -36
- data/lib/logical-construct/target/sinatra-resolver.rb +0 -99
- data/lib/logical-construct/testing/resolve-configuration.rb +0 -32
- data/lib/logical-construct/testing/resolving-task.rb +0 -15
- data/lib/templates/chef.rb.erb +0 -9
- data/lib/templates/construct.init.d.erb +0 -18
- data/lib/templates/resolver/finished.html.erb +0 -1
- data/lib/templates/resolver/index.html.erb +0 -17
- data/lib/templates/resolver/task-file-form.html.erb +0 -6
- data/lib/templates/resolver/task-form.html.erb +0 -6
- data/spec/resolution.rb +0 -147
- data/spec/target/chef-config.rb +0 -67
- data/spec/target/chef-solo.rb +0 -55
- data/spec/target/platforms.rb +0 -36
- data/spec/target/smoke-test.rb +0 -45
- data/spec_help/ungemmer.rb +0 -36
data/doc/hating-chef
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Notes about tasks that Chef performs:
|
2
|
+
|
3
|
+
Install software (i.e. emerge <thing>)
|
4
|
+
Template configs (w/o regard to changes)
|
5
|
+
Edit files (not using patch)
|
6
|
+
Create files (a la GNU install), directories
|
7
|
+
|
8
|
+
Doesn't: manage archives (tarballs)
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
So, tasks that would be nice:
|
13
|
+
emerge (or apt-get or ...)
|
14
|
+
template files
|
15
|
+
apply patches
|
16
|
+
edit files? (still seems dicey)
|
17
|
+
create files/directories like GNU install does
|
18
|
+
unpack tarballs
|
19
|
+
manage symlinks
|
20
|
+
VCS checkouts
|
21
|
+
|
22
|
+
restart/start/enable services
|
23
|
+
|
24
|
+
run arbitrary shell commands (as little as possible)
|
25
|
+
(Maybe just: template a file, run bash (file))
|
26
|
+
|
27
|
+
|
28
|
+
One thing Chef does that's useful is "notifies ... :delayed" - basically tasks that are only needed if this one is, but happen later
|
29
|
+
So: a Task type (mixin) that is #needed? based on a boolean - by default, not, but other tasks can say something like arm that:other:task ->
|
30
|
+
Rake::application[that:other:task].needed = true. Order of execution determined by dependency.
|
31
|
+
|
32
|
+
For package installs, consider /etc/portage/sets
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require 'mattock'
|
2
|
+
module LogicalConstruct
|
3
|
+
class TarballTask < ::Mattock::Rake::FileCommandTask
|
4
|
+
setting :compression, :auto
|
5
|
+
setting :compression_flag, nil
|
6
|
+
setting :exclude_vcs, true
|
7
|
+
|
8
|
+
dir(:unpacked_parent, dir(:unpacked_dir))
|
9
|
+
dir(:archive_parent, path(:archive))
|
10
|
+
|
11
|
+
setting :basename, nil
|
12
|
+
setting :extension, "tbz"
|
13
|
+
|
14
|
+
def default_configuration
|
15
|
+
super
|
16
|
+
self.compression_flag ||=
|
17
|
+
case compression
|
18
|
+
when :auto
|
19
|
+
"--auto-compress"
|
20
|
+
when :gzip
|
21
|
+
"--gzip"
|
22
|
+
when :bzip, :bzip2
|
23
|
+
"--bzip2"
|
24
|
+
when :xz
|
25
|
+
"--xz"
|
26
|
+
when :lzip
|
27
|
+
"--lzip"
|
28
|
+
when :lzma
|
29
|
+
"--lzma"
|
30
|
+
when :lzop
|
31
|
+
"--lzop"
|
32
|
+
when :compress
|
33
|
+
"--compress"
|
34
|
+
else
|
35
|
+
""
|
36
|
+
end
|
37
|
+
|
38
|
+
self.basename = name
|
39
|
+
end
|
40
|
+
|
41
|
+
def resolve_configuration
|
42
|
+
extension.sub(/[.]$/,'')
|
43
|
+
|
44
|
+
unpacked_parent.absolute_path ||= absolute_path
|
45
|
+
archive_parent.absolute_path ||= absolute_path
|
46
|
+
|
47
|
+
unless basename.nil?
|
48
|
+
unpacked_dir.relative_path ||= basename
|
49
|
+
archive.relative_path ||= [basename, extension].join(".")
|
50
|
+
end
|
51
|
+
|
52
|
+
resolve_paths
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
def action_flag(string)
|
57
|
+
case string
|
58
|
+
when "c", /create/
|
59
|
+
"--create"
|
60
|
+
when "x", /extract/
|
61
|
+
"--extract"
|
62
|
+
when "d", /compare/
|
63
|
+
"--compare"
|
64
|
+
else
|
65
|
+
string
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_options(tar)
|
70
|
+
tar.options << "--files-from=" + listfile
|
71
|
+
end
|
72
|
+
|
73
|
+
def tar_command(action, verbose = true, &block)
|
74
|
+
tar_command_without_directory(action, verbose) do |tar|
|
75
|
+
tar.options << "--directory="+unpacked_dir.absolute_path
|
76
|
+
yield tar if block_given?
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def tar_command_without_directory(action, verbose = true)
|
81
|
+
command = cmd("tar") do |tar|
|
82
|
+
tar.options << action
|
83
|
+
tar.options << "--verbose" if verbose
|
84
|
+
tar.options << compression_flag
|
85
|
+
tar.options << "--file="+archive.absolute_path
|
86
|
+
tar.options << "--exclude-vcs" if exclude_vcs
|
87
|
+
yield(tar) if block_given?
|
88
|
+
end
|
89
|
+
return command
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class PackTarballTask < TarballTask
|
94
|
+
default_taskname :pack_tarball
|
95
|
+
path :listfile
|
96
|
+
|
97
|
+
def command
|
98
|
+
tar_command("--create") do |tar|
|
99
|
+
tar.options << "--files-from="+listfile.absolute_path
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def needed?
|
104
|
+
return true if super
|
105
|
+
if File::exists?(target_path)
|
106
|
+
return !(tar_command("--compare"){|tar| tar.options << "--files-from=" + listfile.absolute_path } & tar_command("--compare")).succeeds?
|
107
|
+
end
|
108
|
+
return true
|
109
|
+
end
|
110
|
+
|
111
|
+
def define
|
112
|
+
super
|
113
|
+
if prerequisite_tasks.empty?
|
114
|
+
enhance(source_files)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class UnpackTarballTask < TarballTask
|
120
|
+
default_taskname :unpack_tarball
|
121
|
+
|
122
|
+
def command
|
123
|
+
(cmd("mkdir", "-p", unpacked_dir.absolute_path) & tar_command("--extract")) #ok
|
124
|
+
end
|
125
|
+
|
126
|
+
def target_files
|
127
|
+
FileList[tar_command_without_directory("--list", false).run.stdout.split.map do |path|
|
128
|
+
unpacked_dir.pathname.join(path).to_s
|
129
|
+
end]
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_target_dependencies
|
133
|
+
target_files.each do |path|
|
134
|
+
::Rake::FileTask.define_task(path => name)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def needed?
|
139
|
+
return true if super
|
140
|
+
if File::exists?(archive_path.absolute_path)
|
141
|
+
return !(tar_command("--compare")).succeeds?
|
142
|
+
end
|
143
|
+
return true
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class PackTarball < ::Mattock::Tasklib
|
148
|
+
default_namespace :pack
|
149
|
+
|
150
|
+
dir(:unpacked_dir)
|
151
|
+
|
152
|
+
dir(:marshalling,
|
153
|
+
path(:listfile),
|
154
|
+
path(:archive))
|
155
|
+
|
156
|
+
setting :basename, nil
|
157
|
+
setting :extension, "tbz"
|
158
|
+
setting :source_files
|
159
|
+
setting :source_pattern, "**/*"
|
160
|
+
setting :exclude_patterns, ['**/*.sw[p-z]'] #ok
|
161
|
+
|
162
|
+
def resolve_configuration
|
163
|
+
listfile.relative_path ||= "#{basename}.list"
|
164
|
+
unless basename.nil?
|
165
|
+
self.unpacked_dir.relative_path ||= basename
|
166
|
+
self.archive.relative_path ||= [basename, extension].join(".")
|
167
|
+
end
|
168
|
+
|
169
|
+
resolve_paths
|
170
|
+
|
171
|
+
self.source_files ||=
|
172
|
+
begin
|
173
|
+
pattern = File::join(unpacked_dir.absolute_path, source_pattern)
|
174
|
+
list = FileList[pattern]
|
175
|
+
exclude_patterns.each do |pattern|
|
176
|
+
list.exclude(pattern)
|
177
|
+
end
|
178
|
+
list
|
179
|
+
end
|
180
|
+
|
181
|
+
super
|
182
|
+
end
|
183
|
+
|
184
|
+
def define
|
185
|
+
super
|
186
|
+
in_namespace do
|
187
|
+
file listfile.absolute_path => [Rake.application.rakefile, marshalling.absolute_path] + source_files do |task|
|
188
|
+
require 'pathname'
|
189
|
+
source_pathname = Pathname.new(unpacked_dir.absolute_path)
|
190
|
+
files = source_files.map do |path|
|
191
|
+
Pathname.new(path)
|
192
|
+
end.find_all do |pathname|
|
193
|
+
not (pathname.directory? and not pathname.children.empty?)
|
194
|
+
end.map do |pathname|
|
195
|
+
pathname.relative_path_from source_pathname
|
196
|
+
end
|
197
|
+
|
198
|
+
File::open(listfile.absolute_path, "w") do |list|
|
199
|
+
list.write(files.join("\n"))
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
PackTarballTask.define_task(archive.absolute_path => [marshalling.absolute_path] + source_files + [listfile.absolute_path]) do |task|
|
204
|
+
copy_settings_to(task)
|
205
|
+
end
|
206
|
+
task archive.absolute_path => Rake.application.rakefile unless Rake.application.rakefile.nil?
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
class UnpackTarballs < Mattock::Tasklib
|
212
|
+
class RemoveFilesNotInArchives < TarballTask
|
213
|
+
dir :unpacked_dir
|
214
|
+
|
215
|
+
setting :archive_paths
|
216
|
+
setting :file_list
|
217
|
+
|
218
|
+
attr_accessor :stray_files
|
219
|
+
|
220
|
+
def resolve_configuration
|
221
|
+
resolve_paths
|
222
|
+
|
223
|
+
super
|
224
|
+
end
|
225
|
+
|
226
|
+
def stray_files
|
227
|
+
@stray_files ||=
|
228
|
+
begin
|
229
|
+
archive_paths.each do |archive_path|
|
230
|
+
list_process = tar_command("--list")
|
231
|
+
if list_process.succeeds?
|
232
|
+
self.archive_files += list_process.stdout.lines.to_a.map{|line| line.chomp}
|
233
|
+
end
|
234
|
+
end
|
235
|
+
archive_files.map!{|path| File::expand_path(path, target_dir)}
|
236
|
+
|
237
|
+
self.stray_files = file_list - archive_files
|
238
|
+
stray_files.delete_if{|path| File::directory?(path)}
|
239
|
+
unsafe_cleanup = stray_files.find_all do |path|
|
240
|
+
%r{\A/} =~ path and not %r{\A#{File::expand_path(target_dir)}} =~ path
|
241
|
+
end
|
242
|
+
raise "Unsafe stray cleanup: #{unsafe_cleanup.inspect}" unless unsafe_cleanup.empty?
|
243
|
+
stray_files
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def needed?
|
248
|
+
stray_files.any? do |path|
|
249
|
+
File.exists?(path)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def command
|
254
|
+
cmd("rm", "-f", *stray_files)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
default_namespace :unpack
|
259
|
+
|
260
|
+
setting :archive_paths, []
|
261
|
+
setting :archive_path, nil
|
262
|
+
|
263
|
+
dir :unpacked_dir
|
264
|
+
setting :target_pattern, "**/*"
|
265
|
+
setting :file_list
|
266
|
+
|
267
|
+
def resolve_configuration
|
268
|
+
unless archive_path.nil?
|
269
|
+
archive_paths << archive_path
|
270
|
+
end
|
271
|
+
|
272
|
+
resolve_paths
|
273
|
+
|
274
|
+
self.file_list ||= FileList[File::join(File::expand_path(target_dir),target_pattern)]
|
275
|
+
|
276
|
+
super
|
277
|
+
end
|
278
|
+
|
279
|
+
def define
|
280
|
+
in_namespace do
|
281
|
+
archive_paths.each do |archive|
|
282
|
+
UnpackTarballTask.define_task(archive) do |unpack|
|
283
|
+
copy_settings_to(unpack)
|
284
|
+
unpack.archive_path.absolute_path = archive
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
if file_list.empty?
|
289
|
+
task :unpack => archive_paths
|
290
|
+
else
|
291
|
+
RemoveFilesNotInArchives.define_task(:remove_strays => archive_paths) do |remove_strays|
|
292
|
+
copy_settings_to(remove_strays)
|
293
|
+
end
|
294
|
+
|
295
|
+
task :unpack => file_list
|
296
|
+
file_list.each do |path|
|
297
|
+
file path => :remove_strays
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
task namespace_name => self[:unpack]
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
UnpackTarball = UnpackTarballs
|
307
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'mattock'
|
1
2
|
require 'logical-construct/ground-control/core'
|
2
|
-
require 'logical-construct/ground-control/setup'
|
3
|
+
#require 'logical-construct/ground-control/setup'
|
3
4
|
require 'logical-construct/ground-control/provision'
|
5
|
+
require 'logical-construct/ground-control/tools'
|
6
|
+
require 'logical-construct/ground-control/generate-manifest'
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'logical-construct/ground-control'
|
2
|
+
require 'mattock/tasklib'
|
3
|
+
require 'logical-construct/archive-tasks'
|
4
|
+
|
5
|
+
module LogicalConstruct::GroundControl
|
6
|
+
class BuildPlan < Mattock::Tasklib
|
7
|
+
include Mattock::CommandLineDSL
|
8
|
+
|
9
|
+
default_namespace :build_plan
|
10
|
+
|
11
|
+
setting :manifest_task
|
12
|
+
|
13
|
+
dir(:plan_source, "source",
|
14
|
+
dir(:plan, path(:plan_rakefile, "plan.rake")))
|
15
|
+
dir(:marshalling, "marshall",
|
16
|
+
dir(:plan_temp,
|
17
|
+
dir(:synced, "sync")))
|
18
|
+
|
19
|
+
setting :source_pattern, "**/*"
|
20
|
+
setting :exclude_patterns, ["**/*.sw[p-z]"] #ok
|
21
|
+
setting :basename
|
22
|
+
|
23
|
+
setting :synced_files
|
24
|
+
|
25
|
+
def default_configuration(provisioning)
|
26
|
+
super
|
27
|
+
provisioning.copy_settings_to(self)
|
28
|
+
|
29
|
+
self.manifest_task = provisioning[:manifest]
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolve_configuration
|
33
|
+
fail_unless_set(:basename)
|
34
|
+
plan.relative_path ||= basename
|
35
|
+
plan_temp.relative_path ||= basename
|
36
|
+
|
37
|
+
resolve_paths
|
38
|
+
|
39
|
+
self.synced_files =
|
40
|
+
begin
|
41
|
+
pattern = File::join(plan.absolute_path, source_pattern)
|
42
|
+
list = FileList[pattern]
|
43
|
+
exclude_patterns.each do |pattern|
|
44
|
+
list.exclude(pattern)
|
45
|
+
end
|
46
|
+
list.map do |path|
|
47
|
+
synced.pathname.join(Pathname.new(path).relative_path_from(plan.pathname)).to_s
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def archive_path
|
55
|
+
@pack.archive.absolute_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def define
|
59
|
+
super
|
60
|
+
|
61
|
+
in_namespace do
|
62
|
+
task :compile do
|
63
|
+
(cmd("cd", plan.absolute_path) & cmd("rake", "--rakefile", plan_rakefile.absolute_path, "construct:compile")).must_succeed!
|
64
|
+
end
|
65
|
+
|
66
|
+
file_create synced.absolute_path do |dir|
|
67
|
+
cmd("mkdir", "-p", dir.name).must_succeed! #ok
|
68
|
+
end
|
69
|
+
|
70
|
+
#This looks absurd, but otherwise we need to make sure that no compile
|
71
|
+
#task creates a new file it doesn't need. `bundle standalone` already
|
72
|
+
#does, so...
|
73
|
+
task :rsync_artifacts => [synced.absolute_path, :compile] do
|
74
|
+
from_dir = plan.absolute_path
|
75
|
+
from_dir += "/" unless from_dir =~ %r"/$"
|
76
|
+
|
77
|
+
to_dir = synced.absolute_path
|
78
|
+
to_dir += "/" unless to_dir =~ %r"/$"
|
79
|
+
|
80
|
+
cmd("rsync", "-v", "-rlpgo", "--checksum", from_dir, to_dir).must_succeed!
|
81
|
+
end
|
82
|
+
|
83
|
+
synced_files.each do |path|
|
84
|
+
file path => :rsync_artifacts
|
85
|
+
end
|
86
|
+
|
87
|
+
@pack = ::LogicalConstruct::PackTarball.new do |pack|
|
88
|
+
copy_settings_to(pack)
|
89
|
+
pack.source_files = synced_files
|
90
|
+
pack.unpacked_dir.absolute_path = synced.absolute_path
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|