logical-construct 0.0.1.localtesting
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/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
|