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,40 @@
1
+ module LogicalConstruct
2
+ class UnpackCookbook < Mattock::TaskLib
3
+ def default_namespace
4
+ :cookbook
5
+ end
6
+
7
+ def default_settings(provision)
8
+ settings(
9
+ :construct_dir => provision.construct_dir,
10
+ :cookbook_metadata => nil,
11
+ :cookbook_dir => nil,
12
+ :cookbook_name => "cookbook",
13
+ :cookbook_archive => nil
14
+ )
15
+ end
16
+
17
+ def resolve_settings
18
+ self.cookbook_archive ||= File::join(construct_dir, "cookbook.tbz")
19
+ self.cookbook_dir ||= File::join(construct_dir, cookbook_name)
20
+
21
+ self.cookbook_metadata ||= File::join(cookbook_dir, "metadata.rb")
22
+ end
23
+
24
+ def untar_command
25
+ Mattock::CommandLine.new("tar", "-xjf") do |cmd|
26
+ cmd.options << cookbook_archive
27
+ end
28
+ end
29
+
30
+ def define
31
+ in_namespace do
32
+ file cookbook_archive
33
+ file cookbook_metadata => cookbook_archive do
34
+ untar_command.run
35
+ end
36
+ task :unpack => cookbook_metadata
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+ require 'mattock/tasklib'
2
+ require 'logical-construct/testing/resolving-task'
3
+
4
+ module LogicalConstruct
5
+ module Testing
6
+ class ResolveConfiguration < Mattock::Tasklib
7
+ default_namespace 'configuration'
8
+
9
+ setting :resolutions, {}
10
+
11
+ def default_configuration(provision)
12
+ end
13
+
14
+ def define
15
+ in_namespace do
16
+ LogicalConstruct::Testing::ResolvingTask.new do |task|
17
+ task.task_name = "resolve"
18
+ copy_settings_to(task)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ require 'logical-construct/resolving-task'
2
+
3
+ module LogicalConstruct
4
+ module Testing
5
+ class ResolvingTask < ::LogicalConstruct::ResolvingTask
6
+ setting :resolutions, {}
7
+
8
+ def action
9
+ unsatisfied_prerequisites.each do |task|
10
+ task.fulfill(resolutions.fetch(task.name))
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org/"
2
+
3
+ gem "logical-construct"
@@ -0,0 +1,14 @@
1
+ require 'logical-construct/target'
2
+
3
+ include LogicalConstruct
4
+ include LogicalConstruct::Platform()
5
+
6
+ provision = Provision.new
7
+
8
+ provision.in_namespace do
9
+ resolution = ResolveConfiguration.new(provision)
10
+ chef_config = ChefConfig.new(provision, resolution)
11
+ chef_solo = ChefSolo.new(chef_config)
12
+ end
13
+
14
+ task :default => :provision
@@ -0,0 +1,4 @@
1
+ file_cache_path "<%= file_cache_path %>"
2
+ cookbook_path "<%= cookbook_path %>"
3
+ json_attribs "<%= json_attribs %>"
4
+ <% unless role_path.nil? %>role_path "<%= role_path %>"<% end %>
@@ -0,0 +1 @@
1
+ <p>Congratulations! That was all we needed, and we should be finishing up.</p>
@@ -0,0 +1,8 @@
1
+ <p>The following conditions must be satisfied in order to provision this machine:</p>
2
+ <ul>
3
+ <% unsatisfied_prerequisites.each do |task| %>
4
+ <li>
5
+ <a href="<%= web_path(task)%>"><%= task.name %></a>
6
+ </li>
7
+ <% end %>
8
+ </ul>
@@ -0,0 +1,6 @@
1
+ <form action="<%= task_path %>" method="post">
2
+ <textarea name="data"></textarea>
3
+ <button type="submit" class="button" value="" name="" >
4
+ Submit
5
+ </button>
6
+ </form>
@@ -0,0 +1,64 @@
1
+ require 'logical-construct/target/platforms'
2
+ require 'mattock/testing/rake-example-group'
3
+
4
+ describe LogicalConstruct::VirtualBox::ChefConfig do
5
+ include Mattock::RakeExampleGroup
6
+ include Mattock::CommandLineExampleGroup
7
+ include FileSandbox
8
+
9
+ before :each do
10
+ sandbox.new :directory => "construct-dir"
11
+ sandbox.new :directory => "chef-dir"
12
+ end
13
+
14
+ let :provision do
15
+ require 'logical-construct/target/provision'
16
+ LogicalConstruct::Provision.new do |prov|
17
+ prov.construct_dir = "construct-dir"
18
+ end
19
+ end
20
+
21
+ let :resolution do
22
+ require 'logical-construct/testing/resolve-configuration'
23
+ LogicalConstruct::Testing::ResolveConfiguration.new(provision) do |resolve|
24
+ resolve.resolutions = {
25
+ 'chef_config:cookbook_tarball' => "",
26
+ 'chef_config:json_attribs' => "",
27
+ }
28
+ end
29
+ end
30
+
31
+ let! :chef_config do
32
+ LogicalConstruct::VirtualBox::ChefConfig.new(provision, resolution) do |cc|
33
+ cc.file_cache_path = "chef-dir"
34
+ cc.solo_rb = "chef-solo.rb"
35
+ end
36
+ end
37
+
38
+ it "should make an absolute path for solo.rb" do
39
+ chef_config.solo_rb.should =~ /\A\//
40
+ end
41
+
42
+ describe "invoked" do
43
+ before :each do
44
+ expect_command /tar/, 0
45
+ rake[File::join(sandbox["chef-dir"].path, "chef-solo.rb")].invoke
46
+ end
47
+
48
+ it "should generate the chef-solo.rb file" do
49
+ sandbox["chef-dir/chef-solo.rb"].should be_exist
50
+ end
51
+
52
+ describe "resulting config file" do
53
+ subject do
54
+ sandbox["chef-dir/chef-solo.rb"].contents
55
+ end
56
+
57
+ it{ should =~ %r{file_cache_path\s*(["']).*\1} }
58
+ it{ should =~ %r{cookbook_path\s*(["']).*/cookbooks\1} }
59
+ it{ should =~ %r{json_attribs\s*(["']).*/node.json\1} }
60
+ it{ should_not =~ /role_path/ }
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,47 @@
1
+ require 'logical-construct/target/chef-solo'
2
+ require 'logical-construct/target/platforms'
3
+ require 'mattock/testing/rake-example-group'
4
+ require 'mattock/testing/mock-command-line'
5
+
6
+ describe LogicalConstruct::ChefSolo do
7
+ include Mattock::RakeExampleGroup
8
+ include FileSandbox
9
+
10
+ let :provision do
11
+ require 'logical-construct/target/provision'
12
+ LogicalConstruct::Provision.new
13
+ end
14
+
15
+ let :resolver do
16
+ require 'logical-construct/testing/resolve-configuration'
17
+ LogicalConstruct::Testing::ResolveConfiguration.new(provision) do |resolve|
18
+ resolve.resolutions = {
19
+ 'chef_config:cookbook_tarball' => '',
20
+ 'chef_config:json_attribs' => '',
21
+ }
22
+ end
23
+ end
24
+
25
+ let! :chef_config do
26
+ LogicalConstruct::VirtualBox::ChefConfig.new(provision, resolver) do |cc|
27
+ cc.file_cache_path = "chef-dir"
28
+ cc.solo_rb = "chef-solo.rb"
29
+ end
30
+ end
31
+
32
+ let! :chef_solo do
33
+ LogicalConstruct::ChefSolo.new(chef_config)
34
+ end
35
+
36
+ describe "invoked" do
37
+ include Mattock::CommandLineExampleGroup
38
+
39
+ it "should run chef-solo" do
40
+ Rake.verbose(true)
41
+ expect_command /tar/, 0
42
+ expect_command /chef-solo/, 0
43
+
44
+ rake["chef_solo:run"].invoke
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ require 'logical-construct/target/platforms'
2
+
3
+ describe LogicalConstruct do
4
+ after :each do
5
+ ENV['LOGCON_DEPLOYMENT_PLATFORM'] = nil
6
+ $DEPLOYMENT_PLATFORM = nil
7
+ end
8
+
9
+ describe "Platform()" do
10
+ it "should fail for unset plaform" do
11
+ expect do
12
+ LogicalConstruct::Platform()
13
+ end.to raise_error(KeyError)
14
+ end
15
+
16
+ it "should succeed for ENV VirtualBox" do
17
+ ENV['LOGCON_DEPLOYMENT_PLATFORM'] = 'VirtualBox'
18
+ LogicalConstruct::Platform().should == LogicalConstruct::VirtualBox
19
+ end
20
+
21
+ it "should succeed for global VirtualBox" do
22
+ $DEPLOYMENT_PLATFORM = 'VirtualBox'
23
+ LogicalConstruct::Platform().should == LogicalConstruct::VirtualBox
24
+ end
25
+ end
26
+
27
+ describe "including VirtualBox" do
28
+ before :each do
29
+ ENV['LOGCON_DEPLOYMENT_PLATFORM'] = 'VirtualBox'
30
+ end
31
+
32
+ it "should make ChefConfig available" do
33
+ LogicalConstruct::Platform()::ChefConfig.should == ::LogicalConstruct::VirtualBox::ChefConfig
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,164 @@
1
+ #require 'ftools'
2
+ require 'fileutils'
3
+
4
+ module FileSandbox
5
+ def self.included(spec)
6
+ return unless spec.respond_to? :before
7
+
8
+ spec.before do
9
+ setup_sandbox
10
+ end
11
+
12
+ spec.after do
13
+ teardown_sandbox
14
+ end
15
+ end
16
+
17
+ class HaveContents
18
+ def initialize(contents)
19
+ @contents = contents
20
+ end
21
+
22
+ def matches?(target)
23
+ case @contents
24
+ when Regexp
25
+ @contents =~ target.contents
26
+ when String
27
+ @contents == target.contents
28
+ end
29
+ end
30
+ end
31
+
32
+ def have_contents(expected)
33
+ HaveContents.new(expected)
34
+ end
35
+
36
+ attr_reader :sandbox
37
+
38
+ def in_sandbox(&block)
39
+ raise "I expected to create a sandbox as you passed in a block to me" if !block_given?
40
+
41
+ setup_sandbox
42
+ original_error = nil
43
+
44
+ begin
45
+ yield @sandbox
46
+ rescue => e
47
+ original_error = e
48
+ raise
49
+ ensure
50
+ begin
51
+ teardown_sandbox
52
+ rescue
53
+ if original_error
54
+ STDERR.puts "ALERT: a test raised an error and failed to release some lock(s) in the sandbox directory"
55
+ raise(original_error)
56
+ else
57
+ raise
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def setup_sandbox(path = '__sandbox')
64
+ unless @sandbox
65
+ @sandbox = Sandbox.new(path)
66
+ @__old_path_for_sandbox = Dir.pwd
67
+ Dir.chdir(@sandbox.root)
68
+ end
69
+ end
70
+
71
+ def teardown_sandbox
72
+ if @sandbox
73
+ Dir.chdir(@__old_path_for_sandbox)
74
+ @sandbox.clean_up
75
+ @sandbox = nil
76
+ end
77
+ end
78
+
79
+ class Sandbox
80
+ attr_reader :root
81
+
82
+ def initialize(path = '__sandbox')
83
+ @root = File.expand_path(path)
84
+ clean_up
85
+ FileUtils.mkdir_p @root
86
+ end
87
+
88
+ def [](name)
89
+ SandboxFile.new(File.join(@root, name), name)
90
+ end
91
+
92
+ # usage new :file=>'my file.rb', :with_contents=>'some stuff'
93
+ def new(options)
94
+ if options.has_key? :directory
95
+ dir = self[options.delete(:directory)]
96
+ FileUtils.mkdir_p dir.path
97
+ else
98
+ file = self[options.delete(:file)]
99
+ if (binary_content = options.delete(:with_binary_content) || options.delete(:with_binary_contents))
100
+ file.binary_content = binary_content
101
+ else
102
+ file.content = (options.delete(:with_content) || options.delete(:with_contents) || '')
103
+ end
104
+ end
105
+
106
+ raise "unexpected keys '#{options.keys.join(', ')}'" unless options.empty?
107
+
108
+ dir || file
109
+ end
110
+
111
+ def remove(options)
112
+ name = File.join(@root, options[:file])
113
+ FileUtils.remove_file name
114
+ end
115
+
116
+ def clean_up
117
+ FileUtils.rm_rf @root
118
+ if File.exists? @root
119
+ raise "Could not remove directory #{@root.inspect}, something is probably still holding a lock on it"
120
+ end
121
+ end
122
+ end
123
+
124
+
125
+ class SandboxFile
126
+ attr_reader :path
127
+
128
+ def initialize(path, sandbox_path)
129
+ @path = path
130
+ @sandbox_path = sandbox_path
131
+ end
132
+
133
+ def inspect
134
+ "SandboxFile: #@sandbox_path"
135
+ end
136
+
137
+ def exist?
138
+ File.exist? path
139
+ end
140
+
141
+ def content
142
+ File.read path
143
+ end
144
+
145
+ def content=(content)
146
+ FileUtils.mkdir_p File.dirname(@path)
147
+ File.open(@path, "w") {|f| f << content}
148
+ end
149
+
150
+ def binary_content=(content)
151
+ FileUtils.mkdir_p File.dirname(@path)
152
+ File.open(@path, "wb") {|f| f << content}
153
+ end
154
+
155
+ def create
156
+ self.content = ''
157
+ end
158
+
159
+ alias exists? exist?
160
+ alias contents content
161
+ alias contents= content=
162
+ alias binary_contents= binary_content=
163
+ end
164
+ end