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