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
@@ -1,93 +0,0 @@
|
|
1
|
-
require 'mattock'
|
2
|
-
require 'mattock/bundle-command-task'
|
3
|
-
|
4
|
-
module LogicalConstruct
|
5
|
-
class ConfigBuilder < Mattock::TaskLib
|
6
|
-
include Mattock::TemplateHost
|
7
|
-
include Mattock::DeferredDefinition
|
8
|
-
Mattock::DeferredDefinition.add_settings(self)
|
9
|
-
|
10
|
-
setting(:source_path, nil)
|
11
|
-
setting(:target_path, nil)
|
12
|
-
|
13
|
-
setting(:valise)
|
14
|
-
setting(:target_dir)
|
15
|
-
|
16
|
-
setting(:base_name)
|
17
|
-
setting(:extra, {})
|
18
|
-
|
19
|
-
def default_configuration(host)
|
20
|
-
super
|
21
|
-
host.copy_settings_to(self)
|
22
|
-
end
|
23
|
-
|
24
|
-
def resolve_configuration
|
25
|
-
self.target_path ||= fail_unless_set(:target_dir) && File::join(target_dir, base_name)
|
26
|
-
self.source_path ||= fail_unless_set(:base_name) && "#{base_name}.erb"
|
27
|
-
super
|
28
|
-
end
|
29
|
-
|
30
|
-
def define
|
31
|
-
task base_name => [target_dir, valise.find("templates/" + source_path).full_path, Rake.application.rakefile] do
|
32
|
-
finalize_configuration
|
33
|
-
File::open(target_path, "w") do |file|
|
34
|
-
file.write render(source_path)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
task base_name => target_dir
|
38
|
-
task :local_setup => target_path
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
class BuildFiles < Mattock::TaskLib
|
43
|
-
include Mattock::CommandLineDSL
|
44
|
-
|
45
|
-
default_namespace :build_files
|
46
|
-
|
47
|
-
setting(:target_dir, "target_configs")
|
48
|
-
required_fields :valise, :construct_dir, :platform
|
49
|
-
|
50
|
-
def default_configuration(parent)
|
51
|
-
super
|
52
|
-
self.valise = parent.valise
|
53
|
-
self.construct_dir = parent.construct_dir
|
54
|
-
self.platform = parent.proxy_value.platform
|
55
|
-
end
|
56
|
-
|
57
|
-
def define
|
58
|
-
rakefile = nil
|
59
|
-
initd = nil
|
60
|
-
in_namespace do
|
61
|
-
directory target_dir
|
62
|
-
|
63
|
-
gemfile = ConfigBuilder.new(self) do |task|
|
64
|
-
task.base_name = "Gemfile"
|
65
|
-
end
|
66
|
-
|
67
|
-
Mattock::BundleCommandTask.new(:standalone => gemfile.target_path) do |bundle_build|
|
68
|
-
bundle_build.command = (
|
69
|
-
cmd("cd", target_dir) &
|
70
|
-
cmd("bundle", "install"){|bundler|
|
71
|
-
bundler.options << "--standalone"
|
72
|
-
bundler.options << "--binstubs=bin"
|
73
|
-
})
|
74
|
-
end
|
75
|
-
|
76
|
-
rakefile = ConfigBuilder.new(self) do |task|
|
77
|
-
task.base_name = "Rakefile"
|
78
|
-
end
|
79
|
-
|
80
|
-
initd = ConfigBuilder.new(self) do |task|
|
81
|
-
task.base_name = "construct.init.d"
|
82
|
-
task.extra[:construct_dir] = construct_dir
|
83
|
-
task.runtime_definition do
|
84
|
-
task.extra[:platform] = platform
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
task root_task => [rakefile.target_path] + in_namespace(:standalone)
|
89
|
-
task root_task => [initd.target_path] + in_namespace(:standalone)
|
90
|
-
task :local_setup => root_task
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'logical-construct/ground-control/run-on-target'
|
2
|
-
|
3
|
-
module LogicalConstruct
|
4
|
-
class CreateConstructDirectory < RunOnTarget
|
5
|
-
default_namespace :construct_directory
|
6
|
-
|
7
|
-
setting(:construct_dir)
|
8
|
-
|
9
|
-
def default_configuration(setup)
|
10
|
-
self.construct_dir = setup.construct_dir
|
11
|
-
self.remote_server = setup.proxy_value.remote_server
|
12
|
-
super
|
13
|
-
end
|
14
|
-
|
15
|
-
def define
|
16
|
-
remote_task(:create) do |task|
|
17
|
-
task.command = cmd "mkdir", "-p", construct_dir
|
18
|
-
end
|
19
|
-
task :remote_groundwork => self[:create]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'mattock'
|
2
|
-
require 'logical-construct/ground-control/run-on-target'
|
3
|
-
|
4
|
-
module LogicalConstruct
|
5
|
-
module GroundControl
|
6
|
-
class InstallInit < RunOnTarget
|
7
|
-
required_fields :source_path, :target_path
|
8
|
-
setting :construct_dir
|
9
|
-
setting :service_name, "logical-construct"
|
10
|
-
setting :initd_path, "/etc/init.d"
|
11
|
-
|
12
|
-
def default_configuration(setup)
|
13
|
-
super
|
14
|
-
setup.copy_settings_to(self)
|
15
|
-
end
|
16
|
-
|
17
|
-
def resolve_configuration
|
18
|
-
super
|
19
|
-
self.source_path ||= File::join(construct_dir, "construct.init.d")
|
20
|
-
self.target_path ||= File::join(initd_path, service_name)
|
21
|
-
end
|
22
|
-
|
23
|
-
def define
|
24
|
-
remote_task(:install_init) do |task|
|
25
|
-
task.command = cmd("install", "-T", source_path, target_path) &
|
26
|
-
["rc-update", "add", service_name, "default"]
|
27
|
-
end
|
28
|
-
bracket_task(:remote_config, :install_init, :remote_setup)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,141 +0,0 @@
|
|
1
|
-
require 'rake/task'
|
2
|
-
require 'mattock/task'
|
3
|
-
require 'logical-construct/satisfiable-task'
|
4
|
-
|
5
|
-
module LogicalConstruct
|
6
|
-
#Ensures that all it's deps are satisfied before proceeding - the action for
|
7
|
-
#ResolvingTasks is all about satisfying deps.
|
8
|
-
#
|
9
|
-
#Key is how Rake invokes tasks:
|
10
|
-
#Task runner calls Task#invoke
|
11
|
-
#Which is "setup args" and #invoke_with_call_chain
|
12
|
-
#which is
|
13
|
-
# return if @already_invoked
|
14
|
-
# and #invoke_prerequisites
|
15
|
-
# which is prereqs.each{|pr| pr.invoke_with_call_chain }
|
16
|
-
# and #execute if needed
|
17
|
-
#
|
18
|
-
#So, of note: you'll only get invoked once, ever
|
19
|
-
#You'll only be executed if #needed?
|
20
|
-
#Deps will get invoked (ish) even if not #needed?
|
21
|
-
module SatisfiableManager
|
22
|
-
def default_configuration(*configurables)
|
23
|
-
super
|
24
|
-
self.satisfiables = configurables.find_all do |conf|
|
25
|
-
conf.is_a? SatisfiableTask
|
26
|
-
end.map{|sat| sat.rake_task}
|
27
|
-
end
|
28
|
-
|
29
|
-
def define
|
30
|
-
super
|
31
|
-
satisfiables.each do |sat|
|
32
|
-
sat.enhance([rake_task.name])
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def add_satisfiable(task)
|
37
|
-
task = task.rake_task if task.respond_to? :rake_task
|
38
|
-
satisfiables << task
|
39
|
-
task.enhance([rake_task.name])
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
require 'yaml'
|
44
|
-
require 'digest'
|
45
|
-
module ResolutionProtocol
|
46
|
-
def digest
|
47
|
-
@digest ||= Digest::SHA2.new
|
48
|
-
end
|
49
|
-
|
50
|
-
def file_checksum(path)
|
51
|
-
generate_checksum(File::read(path))
|
52
|
-
end
|
53
|
-
|
54
|
-
def generate_checksum(data)
|
55
|
-
digest.reset
|
56
|
-
digest << data
|
57
|
-
digest.hexdigest
|
58
|
-
end
|
59
|
-
|
60
|
-
def web_path(task_name)
|
61
|
-
"/" + task_name.gsub(":", "/")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class ResolvingTask < Rake::Task
|
66
|
-
include Mattock::TaskMixin
|
67
|
-
include SatisfiableManager
|
68
|
-
setting :satisfiables, []
|
69
|
-
|
70
|
-
def needed?
|
71
|
-
!unsatisfied.empty?
|
72
|
-
end
|
73
|
-
|
74
|
-
def unsatisfied
|
75
|
-
satisfiables.find_all{|task| task.needed?}
|
76
|
-
end
|
77
|
-
|
78
|
-
def execute(args=nil)
|
79
|
-
super
|
80
|
-
if needed?
|
81
|
-
raise "Task #{name} failed to satisfy: #{unsatisfied.inspect}"
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class Manifest < SatisfiableTask
|
87
|
-
include SatisfiableManager
|
88
|
-
include ResolutionProtocol
|
89
|
-
|
90
|
-
setting :satisfiables, []
|
91
|
-
nil_field :manifest
|
92
|
-
|
93
|
-
default_taskname "Manifest"
|
94
|
-
|
95
|
-
def invalid_checksum(checksum, path)
|
96
|
-
return false unless File::exists?(path)
|
97
|
-
return true if checksum.nil? or checksum.empty?
|
98
|
-
return checksum != file_checksum(path)
|
99
|
-
end
|
100
|
-
|
101
|
-
def needed?
|
102
|
-
manifest.nil?
|
103
|
-
end
|
104
|
-
|
105
|
-
def fulfill(data)
|
106
|
-
self.manifest = YAML::load(data)
|
107
|
-
satisfiables.each do |sat|
|
108
|
-
path = sat.target_path
|
109
|
-
checksum = manifest[sat.name]
|
110
|
-
if invalid_checksum(checksum, path)
|
111
|
-
File::rename(path, path + ".invalid")
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
class GenerateManifest < Mattock::Task
|
118
|
-
include ResolutionProtocol
|
119
|
-
setting :hash, {}
|
120
|
-
setting :resolutions
|
121
|
-
setting :receiving_name
|
122
|
-
|
123
|
-
def default_configuration(resolution_host)
|
124
|
-
super
|
125
|
-
self.resolutions = resolution_host.resolutions
|
126
|
-
end
|
127
|
-
|
128
|
-
def data_checksum(path, data)
|
129
|
-
hash[path] = generate_checksum(data)
|
130
|
-
end
|
131
|
-
|
132
|
-
def action
|
133
|
-
resolutions.each_pair do |destination, data|
|
134
|
-
data = data.call if data.respond_to? :call
|
135
|
-
data = data.read if data.respond_to? :read
|
136
|
-
hash[destination] = generate_checksum(data)
|
137
|
-
end
|
138
|
-
resolutions[receiving_name] = YAML::dump(hash)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require 'mattock/task'
|
2
|
-
|
3
|
-
module LogicalConstruct
|
4
|
-
#This task won't kill the run if it fails - the assumption is that there's a
|
5
|
-
#ResolvingTask that depends on this task to make it work.
|
6
|
-
#
|
7
|
-
#Based on my reasoning about Rake (c.f. ResolvingTask):
|
8
|
-
# Each ST should have a configured #needed? that checks it's responsibility
|
9
|
-
# Execute needs to catch errors
|
10
|
-
class SatisfiableTask < Rake::Task
|
11
|
-
include Mattock::TaskMixin
|
12
|
-
|
13
|
-
def execute(args=nil)
|
14
|
-
super
|
15
|
-
if application.options.trace and needed?
|
16
|
-
$stderr.puts "** Unsatisfied: #{name}"
|
17
|
-
end
|
18
|
-
rescue Object => ex
|
19
|
-
warn "#{ex.class}: #{ex.message} while performing #{name}"
|
20
|
-
#Swallowed
|
21
|
-
end
|
22
|
-
|
23
|
-
def prefer_file?
|
24
|
-
false
|
25
|
-
end
|
26
|
-
|
27
|
-
def receive(data)
|
28
|
-
return unless needed?
|
29
|
-
fulfill(data)
|
30
|
-
if data.respond_to? :path
|
31
|
-
fulfill_file(data)
|
32
|
-
elsif data.respond_to? :read
|
33
|
-
fulfill(data.read)
|
34
|
-
else
|
35
|
-
fulfill(data.to_s)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def receive_file(file)
|
40
|
-
fulfill(file.read)
|
41
|
-
end
|
42
|
-
|
43
|
-
def fulfill(string)
|
44
|
-
end
|
45
|
-
|
46
|
-
def needed?
|
47
|
-
return !criteria(self)
|
48
|
-
end
|
49
|
-
|
50
|
-
def criteria(me)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
class SatisfiableFileTask < SatisfiableTask
|
55
|
-
setting :target_path
|
56
|
-
|
57
|
-
def prefer_file?
|
58
|
-
true
|
59
|
-
end
|
60
|
-
|
61
|
-
def criteria(task)
|
62
|
-
File::exists?(target_path)
|
63
|
-
end
|
64
|
-
|
65
|
-
def fulfill_file(file)
|
66
|
-
FileUtils::move(file.path, target_path)
|
67
|
-
end
|
68
|
-
|
69
|
-
def fulfill(data)
|
70
|
-
File::open(target_path, "w") do |file|
|
71
|
-
file.write(data)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class SatisfiableEnvTask < SatisfiableTask
|
77
|
-
setting :target_name
|
78
|
-
|
79
|
-
def criteria(task)
|
80
|
-
ENV.has_key?(target_name)
|
81
|
-
end
|
82
|
-
|
83
|
-
def fulfill(string)
|
84
|
-
ENV[target_name] = string
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'mattock/tasklib'
|
2
|
-
|
3
|
-
module LogicalConstruct
|
4
|
-
class ChefSolo < Mattock::TaskLib
|
5
|
-
default_namespace :chef_solo
|
6
|
-
|
7
|
-
settings(
|
8
|
-
:chef_solo_bin => "chef-solo",
|
9
|
-
:daemonize => nil,
|
10
|
-
:user => nil,
|
11
|
-
:group => nil,
|
12
|
-
:node_name => nil
|
13
|
-
)
|
14
|
-
|
15
|
-
setting :config_file
|
16
|
-
|
17
|
-
def default_configuration(chef_config)
|
18
|
-
super
|
19
|
-
self.config_file = chef_config.solo_rb
|
20
|
-
end
|
21
|
-
|
22
|
-
def define
|
23
|
-
in_namespace do
|
24
|
-
Mattock::CommandTask.new(:run) do |task|
|
25
|
-
task.command = Mattock::CommandLine.new(chef_solo_bin) do |cmd|
|
26
|
-
cmd.options << "--config #{config_file}" unless config_file.nil?
|
27
|
-
cmd.options << "--daemonize" if daemonize
|
28
|
-
cmd.options << "--user #{user}" if user
|
29
|
-
cmd.options << "--group #{group}" if group
|
30
|
-
cmd.options << "--node_name #{node_name}" if node_name
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
bracket_task(:build_configs, :run, :provision)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
module LogicalConstruct
|
2
|
-
def self.platforms
|
3
|
-
@platforms ||= {}
|
4
|
-
end
|
5
|
-
|
6
|
-
def self.register_platform(mod)
|
7
|
-
name = mod.name.split('::').last
|
8
|
-
platforms[name] = mod
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.require_platform_files(platform, mod = nil)
|
12
|
-
[
|
13
|
-
['volume', :Volume],
|
14
|
-
['chef-config', :ChefConfig],
|
15
|
-
['resolve-configuration', :ResolveConfiguration],
|
16
|
-
].each do |file, classname|
|
17
|
-
begin
|
18
|
-
require File::join('logical-construct', 'target', 'platforms', platform, file)
|
19
|
-
rescue LoadError
|
20
|
-
raise if mod.nil?
|
21
|
-
klass = Class.new(LogicalConstruct::Default.const_get(classname))
|
22
|
-
mod.const_set(classname, klass)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.Platform(explicit = nil)
|
28
|
-
name = explicit || $DEPLOYMENT_PLATFORM || ENV['LOGCON_DEPLOYMENT_PLATFORM']
|
29
|
-
return platforms.fetch(name)
|
30
|
-
rescue KeyError
|
31
|
-
puts "Cannot find platform specified:"
|
32
|
-
puts " explicit argument: #{explicit.inspect}"
|
33
|
-
puts " $DEPLOYMENT_PLATFORM: #{$DEPLOYMENT_PLATFORM.inspect}"
|
34
|
-
puts " ENV['LOGCON_DEPLOYMENT_PLATFORM']: #{ENV['LOGCON_DEPLOYMENT_PLATFORM'].inspect}"
|
35
|
-
puts " available: #{platforms.keys.inspect}"
|
36
|
-
puts
|
37
|
-
raise
|
38
|
-
end
|
39
|
-
|
40
|
-
module PlatformSpecific
|
41
|
-
def register_platform(name)
|
42
|
-
LogicalConstruct.register_platform(self)
|
43
|
-
LogicalConstruct.require_platform_files(name, self)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
require_platform_files('default')
|
48
|
-
end
|
49
|
-
|
50
|
-
require 'logical-construct/target/platforms/virtualbox'
|
51
|
-
require 'logical-construct/target/platforms/aws'
|