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,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,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 @@
|
|
1
|
+
<p>Congratulations! That was all we needed, and we should be finishing up.</p>
|
@@ -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
|