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
@@ -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'
|