logical-construct 0.0.1.localtesting
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/logical-construct/ground-control.rb +3 -0
- data/lib/logical-construct/ground-control/core.rb +33 -0
- data/lib/logical-construct/ground-control/provision.rb +70 -0
- data/lib/logical-construct/ground-control/run-on-target.rb +32 -0
- data/lib/logical-construct/ground-control/setup.rb +57 -0
- data/lib/logical-construct/ground-control/setup/build-files.rb +64 -0
- data/lib/logical-construct/ground-control/setup/bundle-setup.rb +36 -0
- data/lib/logical-construct/ground-control/setup/copy-files.rb +66 -0
- data/lib/logical-construct/ground-control/setup/create-construct-directory.rb +21 -0
- data/lib/logical-construct/ground-control/setup/ensure-env.rb +15 -0
- data/lib/logical-construct/resolving-task.rb +38 -0
- data/lib/logical-construct/satisfiable-task.rb +64 -0
- data/lib/logical-construct/target.rb +4 -0
- data/lib/logical-construct/target/chef-solo.rb +40 -0
- data/lib/logical-construct/target/platforms.rb +51 -0
- data/lib/logical-construct/target/platforms/aws.rb +8 -0
- data/lib/logical-construct/target/platforms/default/chef-config.rb +89 -0
- data/lib/logical-construct/target/platforms/default/resolve-configuration.rb +25 -0
- data/lib/logical-construct/target/platforms/default/volume.rb +11 -0
- data/lib/logical-construct/target/platforms/virtualbox.rb +8 -0
- data/lib/logical-construct/target/platforms/virtualbox/volume.rb +15 -0
- data/lib/logical-construct/target/provision.rb +26 -0
- data/lib/logical-construct/target/sinatra-resolver.rb +102 -0
- data/lib/logical-construct/target/unpack-cookbook.rb +40 -0
- data/lib/logical-construct/testing/resolve-configuration.rb +24 -0
- data/lib/logical-construct/testing/resolving-task.rb +15 -0
- data/lib/templates/Gemfile.erb +3 -0
- data/lib/templates/Rakefile.erb +14 -0
- data/lib/templates/chef.rb.erb +4 -0
- data/lib/templates/resolver/finished.html.erb +1 -0
- data/lib/templates/resolver/index.html.erb +8 -0
- data/lib/templates/resolver/task-form.html.erb +6 -0
- data/spec/target/chef-config.rb +64 -0
- data/spec/target/chef-solo.rb +47 -0
- data/spec/target/platforms.rb +36 -0
- data/spec_help/file-sandbox.rb +164 -0
- data/spec_help/gem_test_suite.rb +17 -0
- data/spec_help/mock-resolve.rb +21 -0
- data/spec_help/spec_helper.rb +13 -0
- data/spec_help/ungemmer.rb +36 -0
- metadata +131 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
p :loading => __FILE__
|
2
|
+
require 'mattock'
|
3
|
+
|
4
|
+
module LogicalConstruct
|
5
|
+
module GroundControl
|
6
|
+
class Core < Mattock::TaskLib
|
7
|
+
include Mattock::ValiseManager
|
8
|
+
extend Mattock::ValiseManager
|
9
|
+
|
10
|
+
default_namespace :core
|
11
|
+
setting(:search_paths, [rel_dir(__FILE__)])
|
12
|
+
setting(:valise)
|
13
|
+
|
14
|
+
def default_configuration
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def resolve_configuration
|
19
|
+
self.valise = default_valise(*search_paths)
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
23
|
+
def define
|
24
|
+
in_namespace do
|
25
|
+
desc "List the search paths for files used by ground control"
|
26
|
+
task :search_paths do
|
27
|
+
p valise
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'mattock'
|
2
|
+
require 'rake/packagetask'
|
3
|
+
|
4
|
+
module LogicalConstruct
|
5
|
+
module GroundControl
|
6
|
+
class Provision < Mattock::Tasklib
|
7
|
+
class WebConfigure < Mattock::Task
|
8
|
+
setting :target_ipaddr, nil
|
9
|
+
setting :web_port, 51076
|
10
|
+
setting :resolutions, {}
|
11
|
+
|
12
|
+
def action
|
13
|
+
connection = Excon.new(target_address)
|
14
|
+
index = connection.get
|
15
|
+
body = Nokogiri::HTML(index.body)
|
16
|
+
resolution_needed = body.xpath('//a[@href]')
|
17
|
+
resolution_needed.each do |link|
|
18
|
+
href = link['href']
|
19
|
+
connection.post(href, {"data" => resolve(href)})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def resolve(path)
|
24
|
+
resolved = resolutions.fetch(path)
|
25
|
+
if resolved.respond_to? :call
|
26
|
+
resolved = resolved.call
|
27
|
+
end
|
28
|
+
return resolved
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
default_namespace :provision
|
33
|
+
|
34
|
+
setting :valise
|
35
|
+
setting :web_port, 51076
|
36
|
+
setting :target_ipaddr, nil
|
37
|
+
setting :resolutions, {}
|
38
|
+
setting :marshalling_path
|
39
|
+
setting :cookbooks_path
|
40
|
+
|
41
|
+
def default_configuration(core)
|
42
|
+
core.copy_settings_to(self)
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def define
|
47
|
+
in_namespace do
|
48
|
+
task :collect, [:ipaddr] do |task, args|
|
49
|
+
self.target_ipaddr = args[:ipaddr]
|
50
|
+
end
|
51
|
+
|
52
|
+
WebConfigure.new(:web_configure => :collect) do |task|
|
53
|
+
self.copy_settings_to(task)
|
54
|
+
end
|
55
|
+
|
56
|
+
namespace :cookbook do
|
57
|
+
Rake::PackageTask.new("cookbook", :noversion) do |task|
|
58
|
+
task.need_tar_gz = true
|
59
|
+
task.package_dir = marshalling_path
|
60
|
+
task.package_files.include(cookbooks_path + "/**/*")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
task root_task, [:ipaddr] => :web_configure
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'logical-construct/ground-control'
|
2
|
+
require 'mattock/remote-command-task'
|
3
|
+
|
4
|
+
module LogicalConstruct
|
5
|
+
class RunOnTarget < Mattock::TaskLib
|
6
|
+
include Mattock::CommandLineDSL
|
7
|
+
|
8
|
+
runtime_setting(:remote_server)
|
9
|
+
|
10
|
+
def default_configuration(setup)
|
11
|
+
super
|
12
|
+
self.remote_server = setup.proxy_value.remote_server
|
13
|
+
end
|
14
|
+
|
15
|
+
def remote_task(name, comment = nil)
|
16
|
+
in_namespace do
|
17
|
+
desc comment unless comment.nil?
|
18
|
+
Mattock::RemoteCommandTask.new(name) do |task|
|
19
|
+
task.ssh_options << "ControlMaster=auto"
|
20
|
+
task.ssh_options << "ControlPersist=3600"
|
21
|
+
task.ssh_options << "StrictHostKeyChecking=no"
|
22
|
+
task.ssh_options << "UserKnownHostsFile=/dev/null"
|
23
|
+
|
24
|
+
task.runtime_definition do |task|
|
25
|
+
copy_settings_to(task)
|
26
|
+
yield(task)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module LogicalConstruct
|
2
|
+
module GroundControl
|
3
|
+
class Setup < Mattock::TaskLib
|
4
|
+
|
5
|
+
default_namespace :setup
|
6
|
+
|
7
|
+
settings(
|
8
|
+
:remote_server => nested( :address => nil, :user => "root"),
|
9
|
+
:construct_dir => "/var/logical-construct"
|
10
|
+
)
|
11
|
+
|
12
|
+
nil_fields :valise
|
13
|
+
|
14
|
+
def default_configuration(core)
|
15
|
+
core.copy_settings_to(self)
|
16
|
+
end
|
17
|
+
|
18
|
+
def define
|
19
|
+
in_namespace do
|
20
|
+
task :collect, [:address] do |t, args|
|
21
|
+
remote_server.address = args[:address]
|
22
|
+
p :collect => remote_server
|
23
|
+
end
|
24
|
+
|
25
|
+
task :local_setup => [:collect]
|
26
|
+
|
27
|
+
task :remote_groundwork => [:local_setup]
|
28
|
+
|
29
|
+
task :remote_config => [:remote_groundwork]
|
30
|
+
|
31
|
+
task :remote_setup => [:remote_config]
|
32
|
+
|
33
|
+
task :complete => [:local_setup, :remote_setup]
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Set up a remote server to act as a Construct foundation"
|
37
|
+
task root_task,[:address] => self[:complete]
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_subtasks
|
41
|
+
in_namespace do
|
42
|
+
CreateConstructDirectory.new(self)
|
43
|
+
EnsureEnv.new(self)
|
44
|
+
BundleSetup.new(self)
|
45
|
+
build_files = BuildFiles.new(self)
|
46
|
+
CopyFiles.new(self, build_files)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
require 'logical-construct/ground-control/setup/bundle-setup'
|
54
|
+
require 'logical-construct/ground-control/setup/create-construct-directory'
|
55
|
+
require 'logical-construct/ground-control/setup/ensure-env'
|
56
|
+
require 'logical-construct/ground-control/setup/copy-files'
|
57
|
+
require 'logical-construct/ground-control/setup/build-files'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module LogicalConstruct
|
2
|
+
class ConfigBuilder < Mattock::TaskLib
|
3
|
+
include Mattock::TemplateHost
|
4
|
+
|
5
|
+
setting(:source_path, nil)
|
6
|
+
setting(:target_path, nil)
|
7
|
+
|
8
|
+
setting(:valise)
|
9
|
+
setting(:target_dir)
|
10
|
+
|
11
|
+
setting(:base_name)
|
12
|
+
setting(:extra, {})
|
13
|
+
|
14
|
+
def default_configuration(host)
|
15
|
+
super
|
16
|
+
host.copy_settings_to(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def resolve_configuration
|
20
|
+
self.target_path ||= fail_unless_set(:target_dir) && File::join(target_dir, base_name)
|
21
|
+
self.source_path ||= fail_unless_set(:base_name) && "#{base_name}.erb"
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
def define
|
26
|
+
file target_path => [target_dir, valise.find("templates/" + source_path).full_path, Rake.application.rakefile] do
|
27
|
+
File::open(target_path, "w") do |file|
|
28
|
+
file.write render(source_path)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
task :local_setup => target_path
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class BuildFiles < Mattock::TaskLib
|
36
|
+
default_namespace :build_files
|
37
|
+
|
38
|
+
setting(:target_dir, "target_configs")
|
39
|
+
setting(:valise)
|
40
|
+
|
41
|
+
def default_configuration(parent)
|
42
|
+
super
|
43
|
+
self.valise = parent.valise
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_reader :built_files
|
47
|
+
|
48
|
+
def define
|
49
|
+
file_tasks = []
|
50
|
+
in_namespace do
|
51
|
+
directory target_dir
|
52
|
+
|
53
|
+
file_tasks = ["Rakefile", "Gemfile"].map do |path|
|
54
|
+
ConfigBuilder.new(self) do |task|
|
55
|
+
task.base_name = path
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
desc "Template files to be created on the remote server"
|
60
|
+
task root_task => file_tasks.map{|t| t.target_path}
|
61
|
+
task :local_setup => root_task
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'logical-construct/ground-control/run-on-target'
|
2
|
+
|
3
|
+
module LogicalConstruct
|
4
|
+
class BundleSetup < RunOnTarget
|
5
|
+
default_namespace :bundle_setup
|
6
|
+
|
7
|
+
setting :construct_dir
|
8
|
+
nil_fields :bundle_path, :bin_path
|
9
|
+
|
10
|
+
def default_configuration(setup)
|
11
|
+
setup.copy_settings_to(self)
|
12
|
+
super
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve_configuration
|
16
|
+
self.bundle_path ||= File.join(construct_dir, "lib")
|
17
|
+
self.bin_path ||= File.join(construct_dir, "bin")
|
18
|
+
end
|
19
|
+
|
20
|
+
def remote_command
|
21
|
+
Mattock::PrereqChain.new do |cmd|
|
22
|
+
cmd.add Mattock::CommandLine.new("cd", construct_dir)
|
23
|
+
cmd.add Mattock::CommandLine.new("bundle") do |cmd|
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def define
|
29
|
+
remote_task(:run, "Set up bundle on the remote server") do |task|
|
30
|
+
task.command = (cmd("cd", construct_dir) &
|
31
|
+
["bundle", "--path #{bundle_path}", "--binstubs #{bin_path}"]).tap{|cl| p cl}
|
32
|
+
end
|
33
|
+
bracket_task(:remote_config, :run, :remote_setup)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'mattock/command-task'
|
2
|
+
|
3
|
+
module LogicalConstruct
|
4
|
+
class SecureCopyFile < Mattock::CommandTask
|
5
|
+
nil_fields :destination_address
|
6
|
+
nil_fields :source_dir, :destination_dir, :basename
|
7
|
+
required_fields :source_path, :destination_path
|
8
|
+
runtime_required_field :remote_server
|
9
|
+
runtime_required_field :command
|
10
|
+
|
11
|
+
def default_configuration(copy)
|
12
|
+
self.remote_server = copy.proxy_value.remote_server
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve_configuration
|
16
|
+
super
|
17
|
+
self.source_path ||= File::join(source_dir, basename)
|
18
|
+
self.destination_path ||= File::join(destination_dir, basename)
|
19
|
+
end
|
20
|
+
|
21
|
+
def resolve_runtime_configuration
|
22
|
+
self.destination_address ||= [remote_server.address, destination_path].join(":")
|
23
|
+
if remote_server.user
|
24
|
+
self.destination_address = "#{remote_server.user}@#{destination_address}"
|
25
|
+
end
|
26
|
+
self.command = cmd("scp",
|
27
|
+
"-o ControlMaster=auto",
|
28
|
+
source_path, destination_address)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class CopyFiles < Mattock::TaskLib
|
33
|
+
default_namespace :copy_files
|
34
|
+
|
35
|
+
required_fields :files_dir, :remote_server, :construct_dir
|
36
|
+
|
37
|
+
setting :files, ["Rakefile", "Gemfile"]
|
38
|
+
|
39
|
+
def default_configuration(setup, build_files)
|
40
|
+
super()
|
41
|
+
self.files_dir = build_files.target_dir
|
42
|
+
self.remote_server = setup.proxy_value.remote_server
|
43
|
+
self.construct_dir = setup.construct_dir
|
44
|
+
end
|
45
|
+
|
46
|
+
def define
|
47
|
+
files.each do |file|
|
48
|
+
in_namespace do
|
49
|
+
SecureCopyFile.new(self, file) do |task|
|
50
|
+
task.runtime_definition do
|
51
|
+
task.remote_server = remote_server
|
52
|
+
end
|
53
|
+
task.source_dir = files_dir
|
54
|
+
task.destination_dir = construct_dir
|
55
|
+
task.basename = file
|
56
|
+
end
|
57
|
+
end
|
58
|
+
bracket_task(:local_setup, file, :remote_config)
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Copy locally generated files to the remote server"
|
62
|
+
task root_task => in_namespace(*files)
|
63
|
+
task :remote_config => root_task
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,21 @@
|
|
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
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def define
|
15
|
+
remote_task(:create, "Create #{construct_dir} on the remote server") do |task|
|
16
|
+
task.command = cmd "mkdir", "-p", construct_dir
|
17
|
+
end
|
18
|
+
task :remote_groundwork => self[:create]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'logical-construct/ground-control/run-on-target'
|
2
|
+
|
3
|
+
module LogicalConstruct
|
4
|
+
class EnsureEnv < RunOnTarget
|
5
|
+
default_namespace :ensure_env
|
6
|
+
|
7
|
+
def define
|
8
|
+
remote_task(:bundler, "Ensure that bundler is installed on the remote server") do |task|
|
9
|
+
task.verify_command = cmd "bundle", "--version"
|
10
|
+
task.command = cmd("sudo") - %w{gem install bundler}
|
11
|
+
end
|
12
|
+
bracket_task(:local_setup, :bundler, :remote_setup)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rake/task'
|
2
|
+
require 'mattock/task'
|
3
|
+
|
4
|
+
module LogicalConstruct
|
5
|
+
#Ensures that all it's deps are satisfied before proceeding - the action for
|
6
|
+
#ResolvingTasks is all about satisfying deps.
|
7
|
+
#
|
8
|
+
#Key is how Rake invokes tasks:
|
9
|
+
#Task runner calls Task#invoke
|
10
|
+
#Which is "setup args" and #invoke_with_call_chain
|
11
|
+
#which is
|
12
|
+
# return if @already_invoked
|
13
|
+
# and #invoke_prerequisites
|
14
|
+
# which is prereqs.each{|pr| pr.invoke_with_call_chain }
|
15
|
+
# and #execute if needed
|
16
|
+
#
|
17
|
+
#So, of note: you'll only get invoked once, ever
|
18
|
+
#You'll only be executed if #needed?
|
19
|
+
#Deps will get invoked (ish) even if not #needed?
|
20
|
+
#
|
21
|
+
class ResolvingTask < Rake::Task
|
22
|
+
include Mattock::TaskMixin
|
23
|
+
def needed?
|
24
|
+
prerequisite_tasks.any?{|task| task.needed?}
|
25
|
+
end
|
26
|
+
|
27
|
+
def unsatisfied_prerequisites
|
28
|
+
prerequisite_tasks.find_all{|task| task.needed?}
|
29
|
+
end
|
30
|
+
|
31
|
+
def execute(args=nil)
|
32
|
+
super
|
33
|
+
if needed?
|
34
|
+
raise "Task #{name} failed to satisfy: #{unsatisfied_prerequisites.inspect}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|