logical-construct 0.0.5 → 0.1.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/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
|