logical-construct 0.0.1.localtesting

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/lib/logical-construct/ground-control.rb +3 -0
  2. data/lib/logical-construct/ground-control/core.rb +33 -0
  3. data/lib/logical-construct/ground-control/provision.rb +70 -0
  4. data/lib/logical-construct/ground-control/run-on-target.rb +32 -0
  5. data/lib/logical-construct/ground-control/setup.rb +57 -0
  6. data/lib/logical-construct/ground-control/setup/build-files.rb +64 -0
  7. data/lib/logical-construct/ground-control/setup/bundle-setup.rb +36 -0
  8. data/lib/logical-construct/ground-control/setup/copy-files.rb +66 -0
  9. data/lib/logical-construct/ground-control/setup/create-construct-directory.rb +21 -0
  10. data/lib/logical-construct/ground-control/setup/ensure-env.rb +15 -0
  11. data/lib/logical-construct/resolving-task.rb +38 -0
  12. data/lib/logical-construct/satisfiable-task.rb +64 -0
  13. data/lib/logical-construct/target.rb +4 -0
  14. data/lib/logical-construct/target/chef-solo.rb +40 -0
  15. data/lib/logical-construct/target/platforms.rb +51 -0
  16. data/lib/logical-construct/target/platforms/aws.rb +8 -0
  17. data/lib/logical-construct/target/platforms/default/chef-config.rb +89 -0
  18. data/lib/logical-construct/target/platforms/default/resolve-configuration.rb +25 -0
  19. data/lib/logical-construct/target/platforms/default/volume.rb +11 -0
  20. data/lib/logical-construct/target/platforms/virtualbox.rb +8 -0
  21. data/lib/logical-construct/target/platforms/virtualbox/volume.rb +15 -0
  22. data/lib/logical-construct/target/provision.rb +26 -0
  23. data/lib/logical-construct/target/sinatra-resolver.rb +102 -0
  24. data/lib/logical-construct/target/unpack-cookbook.rb +40 -0
  25. data/lib/logical-construct/testing/resolve-configuration.rb +24 -0
  26. data/lib/logical-construct/testing/resolving-task.rb +15 -0
  27. data/lib/templates/Gemfile.erb +3 -0
  28. data/lib/templates/Rakefile.erb +14 -0
  29. data/lib/templates/chef.rb.erb +4 -0
  30. data/lib/templates/resolver/finished.html.erb +1 -0
  31. data/lib/templates/resolver/index.html.erb +8 -0
  32. data/lib/templates/resolver/task-form.html.erb +6 -0
  33. data/spec/target/chef-config.rb +64 -0
  34. data/spec/target/chef-solo.rb +47 -0
  35. data/spec/target/platforms.rb +36 -0
  36. data/spec_help/file-sandbox.rb +164 -0
  37. data/spec_help/gem_test_suite.rb +17 -0
  38. data/spec_help/mock-resolve.rb +21 -0
  39. data/spec_help/spec_helper.rb +13 -0
  40. data/spec_help/ungemmer.rb +36 -0
  41. metadata +131 -0
@@ -0,0 +1,3 @@
1
+ require 'logical-construct/ground-control/core'
2
+ require 'logical-construct/ground-control/setup'
3
+ require 'logical-construct/ground-control/provision'
@@ -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