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.
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