souffle 0.0.1 → 0.0.2
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/Gemfile +9 -3
- data/README.md +6 -0
- data/bin/{souffle-server → souffle} +0 -0
- data/lib/souffle.rb +8 -8
- data/lib/souffle/application.rb +15 -10
- data/lib/souffle/application/souffle-server.rb +90 -5
- data/lib/souffle/config.rb +88 -59
- data/lib/souffle/daemon.rb +156 -0
- data/lib/souffle/exceptions.rb +29 -17
- data/lib/souffle/http.rb +43 -0
- data/lib/souffle/log.rb +11 -14
- data/lib/souffle/node.rb +91 -53
- data/lib/souffle/node/runlist.rb +16 -18
- data/lib/souffle/node/runlist_item.rb +43 -36
- data/lib/souffle/node/runlist_parser.rb +60 -62
- data/lib/souffle/polling_event.rb +110 -0
- data/lib/souffle/provider.rb +231 -23
- data/lib/souffle/provider/aws.rb +654 -7
- data/lib/souffle/provider/vagrant.rb +42 -5
- data/lib/souffle/provisioner.rb +55 -0
- data/lib/souffle/provisioner/node.rb +157 -0
- data/lib/souffle/provisioner/system.rb +195 -0
- data/lib/souffle/redis_client.rb +8 -0
- data/lib/souffle/redis_mixin.rb +40 -0
- data/lib/souffle/server.rb +42 -8
- data/lib/souffle/ssh_monkey.rb +8 -0
- data/lib/souffle/state.rb +16 -0
- data/lib/souffle/system.rb +139 -37
- data/lib/souffle/template.rb +30 -0
- data/lib/souffle/templates/Vagrantfile.erb +41 -0
- data/lib/souffle/version.rb +6 -0
- data/spec/config_spec.rb +20 -0
- data/spec/log_spec.rb +24 -0
- data/spec/{runlist_parser_spec.rb → node/runlist_parser_spec.rb} +1 -1
- data/spec/{runlist_spec.rb → node/runlist_spec.rb} +1 -1
- data/spec/node_spec.rb +43 -8
- data/spec/provider_spec.rb +56 -0
- data/spec/providers/aws_provider_spec.rb +114 -0
- data/spec/providers/vagrant_provider_spec.rb +22 -0
- data/spec/provisioner_spec.rb +47 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/system_spec.rb +242 -13
- data/spec/template_spec.rb +20 -0
- data/spec/templates/example_template.erb +1 -0
- metadata +125 -30
- data/bin/souffle-worker +0 -7
- data/lib/souffle/application/souffle-worker.rb +0 -46
- data/lib/souffle/providers.rb +0 -2
- data/lib/souffle/worker.rb +0 -14
data/spec/node_spec.rb
CHANGED
@@ -32,21 +32,28 @@ describe "Souffle::Node" do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should be able to describe a single node" do
|
35
|
-
|
36
|
-
|
35
|
+
rlist = [
|
36
|
+
"recipe[chef_server::rubygems_install]",
|
37
|
+
"role[dns_server]" ]
|
38
|
+
rlist.each { |rl| @node.run_list << rl }
|
39
|
+
@node.run_list.each do |rl_item|
|
40
|
+
rlist.include?(rl_item.to_s).should eql(true)
|
41
|
+
end
|
37
42
|
end
|
38
43
|
|
39
44
|
it "should be able to test whether or not a node depends on another" do
|
40
45
|
@node.run_list << "role[dns_server]"
|
41
46
|
node2 = Souffle::Node.new
|
42
47
|
node2.dependencies << "role[dns_server]"
|
43
|
-
node2.depends_on?(@node).should eql(
|
48
|
+
node2.depends_on?(@node).should eql(
|
49
|
+
[ true, [Souffle::Node::RunListItem.new("role[dns_server]")] ]
|
50
|
+
)
|
44
51
|
end
|
45
52
|
|
46
53
|
it "should not depend on another node when there are no dependencies" do
|
47
54
|
@node.run_list << "role[dns_server]"
|
48
55
|
node2 = Souffle::Node.new
|
49
|
-
node2.depends_on?(@node).should eql(false)
|
56
|
+
node2.depends_on?(@node).should eql([ false, [] ])
|
50
57
|
end
|
51
58
|
|
52
59
|
it "should be able to add child nodes" do
|
@@ -55,9 +62,15 @@ describe "Souffle::Node" do
|
|
55
62
|
@node.children.should eql([child])
|
56
63
|
end
|
57
64
|
|
65
|
+
it "should not duplicate a child node that's added" do
|
66
|
+
child = Souffle::Node.new
|
67
|
+
@node.add_child(child)
|
68
|
+
@node.add_child(child)
|
69
|
+
@node.children.should eql([child])
|
70
|
+
end
|
71
|
+
|
58
72
|
it "should raise and error on adding an invalid child" do
|
59
|
-
|
60
|
-
lambda { node.add_child(child) }.should raise_error
|
73
|
+
lambda { node.add_child([]) }.should raise_error
|
61
74
|
end
|
62
75
|
|
63
76
|
it "should be able to iterate across children" do
|
@@ -81,7 +94,29 @@ describe "Souffle::Node" do
|
|
81
94
|
@node.should eql(node2)
|
82
95
|
end
|
83
96
|
|
84
|
-
it "should have
|
85
|
-
@node.
|
97
|
+
it "should have a depency weight of 1 with no parents" do
|
98
|
+
@node.weight.should eql(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should have a dependency weight of at least 2 with a parent" do
|
102
|
+
parent = Souffle::Node.new
|
103
|
+
parent.add_child(@node)
|
104
|
+
(@node.weight >= 2).should eql(true)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should have a name and be able to set it" do
|
108
|
+
@node.name = "AwesomeName"
|
109
|
+
@node.name.should eql("AwesomeName")
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should be able to get node options with try_opt" do
|
113
|
+
@node.options[:example_opt] = "sporkmejohhny"
|
114
|
+
@node.try_opt(:example_opt).should eql("sporkmejohhny")
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should pass-thru to config options when they do not exist" do
|
118
|
+
Souffle::Config[:example_passthru] = "blehk"
|
119
|
+
@node.try_opt(:example_passthru).should eql("blehk")
|
120
|
+
Souffle::Config.configuration.delete(:example_passthru)
|
86
121
|
end
|
87
122
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Souffle::Provider::Base" do
|
4
|
+
before(:each) do
|
5
|
+
@provider = Souffle::Provider::Base.new
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:each) do
|
9
|
+
@provider = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have Base as a default name" do
|
13
|
+
@provider.name.should eql("Base")
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should raise errors on non-overridden create_system" do
|
17
|
+
n = Souffle::Node.new
|
18
|
+
lambda { @provider.create_system(n) }.should raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should raise errors on non-overridden create_node" do
|
22
|
+
n = Souffle::Node.new
|
23
|
+
lambda { @provider.create_node(n) }.should raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should raise errors on non-overridden create_raid" do
|
27
|
+
lambda { @provider.create_raid }.should raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should have an ssh_key_path that matches the provider name" do
|
31
|
+
@provider.send(:ssh_key_path).should eql(
|
32
|
+
"/etc/souffle/ssh/#{@provider.name.downcase}")
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should have a relative ssh key helpers" do
|
36
|
+
base_path = "/etc/souffle/ssh/base"
|
37
|
+
@provider.send(:ssh_key, "mykey").should eql("#{base_path}/mykey")
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should be able to generate chef-solo json for a node." do
|
41
|
+
node = Souffle::Node.new
|
42
|
+
node.name = "TheBestOne"
|
43
|
+
rlist = [ "recipe[chef_server::rubygems_install]", "role[dns_server]" ]
|
44
|
+
rlist.each { |rl| node.run_list << rl }
|
45
|
+
|
46
|
+
runlist = {
|
47
|
+
"domain" => "souffle",
|
48
|
+
"run_list" => [
|
49
|
+
"recipe[chef_server::rubygems_install]",
|
50
|
+
"role[dns_server]"
|
51
|
+
]
|
52
|
+
}
|
53
|
+
|
54
|
+
JSON.parse(@provider.generate_chef_json(node)).should eql(runlist)
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Souffle::Provider::AWS" do
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
get_config
|
8
|
+
@provider = Souffle::Provider::AWS.new
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
@provider = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Note:
|
16
|
+
# All of the AWS routines will only run if you are provided a
|
17
|
+
# valid aws_access_key and aws_access_secret.
|
18
|
+
|
19
|
+
it "should be able to see whether the configuration has vpc setup" do
|
20
|
+
aws_vpc_id = "vpc-124ae13"
|
21
|
+
aws_subnet_id = "subnet-24f6a87f"
|
22
|
+
node = Souffle::Node.new
|
23
|
+
|
24
|
+
Souffle::Config[:aws_vpc_id] = aws_vpc_id
|
25
|
+
Souffle::Config[:aws_subnet_id] = aws_subnet_id
|
26
|
+
|
27
|
+
@provider.using_vpc?(node).should eql(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should not use vpc when the keys are missing" do
|
31
|
+
aws_vpc_id = "vpc-124ae13"
|
32
|
+
aws_subnet_id = "subnet-24f6a87f"
|
33
|
+
node = Souffle::Node.new
|
34
|
+
|
35
|
+
Souffle::Config[:aws_vpc_id] = aws_vpc_id
|
36
|
+
Souffle::Config[:aws_subnet_id] = nil
|
37
|
+
@provider.using_vpc?(node).should eql(false)
|
38
|
+
|
39
|
+
Souffle::Config[:aws_vpc_id] = nil
|
40
|
+
Souffle::Config[:aws_subnet_id] = aws_subnet_id
|
41
|
+
@provider.using_vpc?(node).should eql(false)
|
42
|
+
|
43
|
+
Souffle::Config[:aws_vpc_id] = nil
|
44
|
+
Souffle::Config[:aws_subnet_id] = nil
|
45
|
+
@provider.using_vpc?(node).should eql(false)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should be able to generate a unique tag" do
|
49
|
+
tag1 = @provider.generate_tag
|
50
|
+
tag2 = @provider.generate_tag
|
51
|
+
tag1.should_not eql(tag2)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should be able to generate a unique tag with a prefix" do
|
55
|
+
@provider.generate_tag("example").include?("example").should eql(true)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return a list of instance ids for a list of nodes" do
|
59
|
+
node1 = Souffle::Node.new
|
60
|
+
node2 = Souffle::Node.new
|
61
|
+
node3 = Souffle::Node.new
|
62
|
+
|
63
|
+
node1.options[:aws_instance_id] = "1a"
|
64
|
+
node2.options[:aws_instance_id] = "2b"
|
65
|
+
node3.options[:aws_instance_id] = "3c"
|
66
|
+
|
67
|
+
nodelist = [node1, node2, node3]
|
68
|
+
@provider.instance_id_list(nodelist).should eql(["1a", "2b", "3c"])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "Souffle::Provider::AWS (live)", :live => true do
|
73
|
+
include Helpers
|
74
|
+
|
75
|
+
before(:each) do
|
76
|
+
get_config
|
77
|
+
@provider = Souffle::Provider::AWS.new
|
78
|
+
end
|
79
|
+
|
80
|
+
after(:each) do
|
81
|
+
@provider = nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should be able to launch and provision an entire system" do
|
85
|
+
EM.run do
|
86
|
+
system = Souffle::System.new
|
87
|
+
|
88
|
+
masternode = Souffle::Node.new
|
89
|
+
masternode.name = "MasterNode"
|
90
|
+
masternode.run_list << "recipe[git]"
|
91
|
+
masternode.options[:aws_ebs_size] = 1
|
92
|
+
masternode.options[:volume_count] = 2
|
93
|
+
|
94
|
+
child_node1 = Souffle::Node.new
|
95
|
+
child_node1.name = "child node 1"
|
96
|
+
child_node1.options[:aws_ebs_size] = 2
|
97
|
+
child_node1.options[:volume_count] = 2
|
98
|
+
|
99
|
+
child_node2 = Souffle::Node.new
|
100
|
+
child_node2.name = "child node 2"
|
101
|
+
child_node2.options[:aws_ebs_size] = 3
|
102
|
+
child_node2.options[:volume_count] = 2
|
103
|
+
|
104
|
+
system.add(masternode)
|
105
|
+
system.add(child_node1)
|
106
|
+
system.add(child_node2)
|
107
|
+
@provider.create_system(system)
|
108
|
+
|
109
|
+
EM::Timer.new(300) do
|
110
|
+
EM.stop
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Souffle::Provider::Vagrant" do
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
get_config
|
8
|
+
@provider = Souffle::Provider::Vagrant.new
|
9
|
+
end
|
10
|
+
|
11
|
+
after(:each) do
|
12
|
+
@provider = nil
|
13
|
+
Souffle::Config[:vagrant_dir] = "/#{ENV['HOME']}/vagrant/vms"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have setup initialize the access key and secret" do
|
17
|
+
example_vagrant_dir = "/path/to/vagrant/vms"
|
18
|
+
Souffle::Config[:vagrant_dir] = "/path/to/vagrant/vms"
|
19
|
+
@provider = Souffle::Provider::Vagrant.new
|
20
|
+
@provider.vagrant_dir.should eql(example_vagrant_dir)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe "Souffle::Provisioner" do
|
4
|
+
include Helpers
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
get_config
|
8
|
+
Souffle::Config[:provider] = "Vagrant"
|
9
|
+
@provisioner = Souffle::Provisioner.new
|
10
|
+
end
|
11
|
+
|
12
|
+
after(:each) do
|
13
|
+
@provisioner = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be able to initialize a Vagrant provider" do
|
17
|
+
@provisioner.provider.name.should eql("Vagrant")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be raise an error on an invalid provider" do
|
21
|
+
Souffle::Config[:provider] = "CompletelyInvalidProvider"
|
22
|
+
d = lambda { Souffle::Provisioner.new }
|
23
|
+
d.should raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be able to initialize an AWS provider" do
|
27
|
+
Souffle::Config[:provider] = "AWS"
|
28
|
+
@provisioner = Souffle::Provisioner.new
|
29
|
+
@provisioner.provider.name.should eql("AWS")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should be able to setup an Vagrant provider" do
|
33
|
+
Souffle::Config[:provider] = "Vagrant"
|
34
|
+
@provisioner = Souffle::Provisioner.new
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should be able to setup an AWS provider" do
|
38
|
+
Souffle::Config[:provider] = "AWS"
|
39
|
+
@provisioner = Souffle::Provisioner.new
|
40
|
+
end
|
41
|
+
|
42
|
+
it "raises an InvalidProvider error when the provider doesn't exist" do
|
43
|
+
Souffle::Config[:provider] = "UnholyProviderOfBadness"
|
44
|
+
d = lambda { Souffle::Provisioner.new }
|
45
|
+
d.should raise_error
|
46
|
+
end
|
47
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -28,5 +28,13 @@ require 'souffle'
|
|
28
28
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
29
29
|
|
30
30
|
RSpec.configure do |config|
|
31
|
+
if ENV['AWS_LIVE'].to_s != "true"
|
32
|
+
config.filter_run_excluding :live => true
|
33
|
+
end
|
34
|
+
end
|
31
35
|
|
36
|
+
module Helpers
|
37
|
+
def get_config
|
38
|
+
Souffle::Config.from_file("/etc/souffle/souffle.rb")
|
39
|
+
end
|
32
40
|
end
|
data/spec/system_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'set'
|
2
3
|
|
3
4
|
describe "Souffle::System" do
|
4
5
|
before(:each) do
|
@@ -9,27 +10,255 @@ describe "Souffle::System" do
|
|
9
10
|
@system = nil
|
10
11
|
end
|
11
12
|
|
12
|
-
it "should be able to
|
13
|
-
|
13
|
+
it "should be able to find all of the nodes with no parents" do
|
14
|
+
node1 = Souffle::Node.new
|
15
|
+
node2 = Souffle::Node.new
|
16
|
+
node3 = Souffle::Node.new
|
17
|
+
node4 = Souffle::Node.new
|
18
|
+
|
19
|
+
node1.dependencies << "role[awesomeone]"
|
20
|
+
node2.dependencies << "recipe[bleh]"
|
21
|
+
|
22
|
+
@system.add(node1)
|
23
|
+
@system.add(node2)
|
24
|
+
@system.add(node3)
|
25
|
+
@system.add(node4)
|
26
|
+
|
27
|
+
@system.roots.to_set.should eql(Set.new([node3, node4]))
|
14
28
|
end
|
15
29
|
|
16
|
-
it "should be able to
|
17
|
-
|
18
|
-
@system.
|
30
|
+
it "should be able to add a root node" do
|
31
|
+
node = Souffle::Node.new
|
32
|
+
@system.add(node)
|
33
|
+
@system.roots.should eql([node])
|
19
34
|
end
|
20
35
|
|
21
|
-
it "should
|
22
|
-
|
23
|
-
|
36
|
+
it "should be able to determine dependant nodes" do
|
37
|
+
node1 = Souffle::Node.new
|
38
|
+
node2 = Souffle::Node.new
|
39
|
+
|
40
|
+
node1.run_list << "role[some_silly_role]"
|
41
|
+
node2.dependencies << "role[some_silly_role]"
|
42
|
+
|
43
|
+
@system.add(node1)
|
44
|
+
@system.add(node2)
|
45
|
+
|
46
|
+
@system.rebalance_nodes
|
47
|
+
@system.dependent_nodes.should eql([node2])
|
24
48
|
end
|
25
49
|
|
26
|
-
it "should be able to
|
50
|
+
it "should be able to clear all nodes parent and child heirarchy" do
|
51
|
+
node1 = Souffle::Node.new
|
52
|
+
node2 = Souffle::Node.new
|
53
|
+
|
54
|
+
node1.run_list << "role[some_silly_role]"
|
55
|
+
node2.dependencies << "role[some_silly_role]"
|
56
|
+
|
57
|
+
@system.add(node1)
|
58
|
+
@system.add(node2)
|
59
|
+
@system.rebalance_nodes
|
60
|
+
|
61
|
+
node1.children.include?(node2).should eql(true)
|
62
|
+
node2.parents.include?(node1).should eql(true)
|
63
|
+
|
64
|
+
@system.clear_node_heirarchy
|
65
|
+
node1.children.should eql([])
|
66
|
+
node2.parents.should eql([])
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should be able to get the node dependencies on a system" do
|
70
|
+
node1 = Souffle::Node.new
|
71
|
+
node2 = Souffle::Node.new
|
72
|
+
node3 = Souffle::Node.new
|
73
|
+
|
74
|
+
node1.dependencies << "role[example_role]"
|
75
|
+
node1.dependencies << "recipe[the_best_one]"
|
76
|
+
|
77
|
+
node2.run_list << "role[example_role]"
|
78
|
+
node3.run_list << "recipe[the_best_one]"
|
79
|
+
|
80
|
+
@system.add(node1)
|
81
|
+
@system.add(node2)
|
82
|
+
@system.add(node3)
|
83
|
+
|
84
|
+
@system.dependencies_on_system(node1).should eql(
|
85
|
+
[ [node2, [Souffle::Node::RunListItem.new("role[example_role]")] ],
|
86
|
+
[node3, [Souffle::Node::RunListItem.new("recipe[the_best_one]")] ]
|
87
|
+
] )
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should be able to optimize a rebalanced system of nodes" do
|
91
|
+
target = Souffle::Node.new
|
92
|
+
heavy1 = Souffle::Node.new
|
93
|
+
heavy2 = Souffle::Node.new
|
94
|
+
root_node = Souffle::Node.new
|
95
|
+
light_node = Souffle::Node.new
|
96
|
+
|
97
|
+
target.dependencies << "role[example_role]"
|
98
|
+
target.dependencies << "recipe[the_best_one]"
|
99
|
+
|
100
|
+
heavy1.run_list << "role[example_role]"
|
101
|
+
heavy2.run_list << "recipe[the_best_one]"
|
102
|
+
heavy1.dependencies << "recipe[heavy]"
|
103
|
+
heavy2.dependencies << "recipe[heavy]"
|
104
|
+
|
105
|
+
root_node.run_list << "recipe[heavy]"
|
106
|
+
|
107
|
+
light_node.run_list << "role[example_role]"
|
108
|
+
light_node.run_list << "recipe[the_best_one]"
|
109
|
+
|
110
|
+
@system.add(target)
|
111
|
+
@system.add(heavy1)
|
112
|
+
@system.add(heavy2)
|
113
|
+
@system.add(root_node)
|
114
|
+
@system.add(light_node)
|
115
|
+
|
116
|
+
@system.rebalance_nodes
|
117
|
+
@system.optimized_node_dependencies(target).should eql([light_node])
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should have children nodes that can identify the system" do
|
121
|
+
target = Souffle::Node.new
|
122
|
+
heavy1 = Souffle::Node.new
|
123
|
+
heavy2 = Souffle::Node.new
|
124
|
+
root_node = Souffle::Node.new
|
125
|
+
light_node = Souffle::Node.new
|
126
|
+
|
127
|
+
target.dependencies << "role[example_role]"
|
128
|
+
target.dependencies << "recipe[the_best_one]"
|
129
|
+
|
130
|
+
heavy1.run_list << "role[example_role]"
|
131
|
+
heavy2.run_list << "recipe[the_best_one]"
|
132
|
+
heavy1.dependencies << "recipe[heavy]"
|
133
|
+
heavy2.dependencies << "recipe[heavy]"
|
134
|
+
|
135
|
+
root_node.run_list << "recipe[heavy]"
|
136
|
+
|
137
|
+
light_node.run_list << "role[example_role]"
|
138
|
+
light_node.run_list << "recipe[the_best_one]"
|
139
|
+
|
140
|
+
@system.add(target)
|
141
|
+
@system.add(heavy1)
|
142
|
+
@system.add(heavy2)
|
143
|
+
@system.add(root_node)
|
144
|
+
@system.add(light_node)
|
145
|
+
|
146
|
+
@system.rebalance_nodes
|
147
|
+
@system.nodes.each { |n| n.system.should eql(@system) }
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should raise an exception on an incorrect system hash" do
|
151
|
+
sys = {}
|
152
|
+
lambda { Souffle::System.from_hash(sys) }.should raise_error
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should be able to get system options with try_opt" do
|
156
|
+
@system.options[:example_opt] = "sporkmejohhny"
|
157
|
+
@system.try_opt(:example_opt).should eql("sporkmejohhny")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should pass-thru to config options when they do not exist" do
|
161
|
+
Souffle::Config[:example_passthru] = "blehk"
|
162
|
+
@system.try_opt(:example_passthru).should eql("blehk")
|
163
|
+
Souffle::Config.configuration.delete(:example_passthru)
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should let child nodes get system opts with pass-thru" do
|
27
167
|
node = Souffle::Node.new
|
28
|
-
@system.
|
29
|
-
@system.
|
168
|
+
@system.add(node)
|
169
|
+
@system.options[:example_opt] = "sporkmejohhny"
|
170
|
+
@system.nodes.first.try_opt(:example_opt).should eql("sporkmejohhny")
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should pass-thru to config options when they do not exist" do
|
174
|
+
Souffle::Config[:example_passthru] = "blehk"
|
175
|
+
@system.try_opt(:example_passthru).should eql("blehk")
|
176
|
+
Souffle::Config.configuration.delete(:example_passthru)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should be able to generate a system from a hash" do
|
180
|
+
sys = {
|
181
|
+
:nodes => [
|
182
|
+
{ :name => "parent_node",
|
183
|
+
:run_list => ["role[somerole]"],
|
184
|
+
:dependencies => [] },
|
185
|
+
{ :name => "lone_node",
|
186
|
+
:run_list => ["role[bestone]"],
|
187
|
+
:dependencies => [] },
|
188
|
+
{ :name => "child_node",
|
189
|
+
:run_list => ["recipe[base]"],
|
190
|
+
:dependencies => ["role[somerole]"] }
|
191
|
+
]
|
192
|
+
}
|
193
|
+
|
194
|
+
new_sys = Souffle::System.from_hash(sys)
|
195
|
+
new_sys.rebalance_nodes
|
196
|
+
|
197
|
+
parent = new_sys.nodes.select { |n| n.name == "parent_node" }.first
|
198
|
+
parent.children.first.name.should eql("child_node")
|
199
|
+
new_sys.roots.size.should eql(2)
|
200
|
+
new_sys.dependent_nodes.size.should eql(1)
|
30
201
|
end
|
31
202
|
|
32
|
-
it "should
|
33
|
-
|
203
|
+
it "should be able to generate system options and merge from a hash" do
|
204
|
+
sys = {
|
205
|
+
:options => { :type => "chef" },
|
206
|
+
:nodes => [
|
207
|
+
{ :name => "parent_node",
|
208
|
+
:options => { :type => "chef-solo" },
|
209
|
+
:run_list => ["role[somerole]"],
|
210
|
+
:dependencies => [] },
|
211
|
+
{ :name => "lone_node",
|
212
|
+
:run_list => ["role[bestone]"],
|
213
|
+
:dependencies => [] },
|
214
|
+
{ :name => "child_node",
|
215
|
+
:run_list => ["recipe[base]"],
|
216
|
+
:dependencies => ["role[somerole]"] }
|
217
|
+
]
|
218
|
+
}
|
219
|
+
|
220
|
+
new_sys = Souffle::System.from_hash(sys)
|
221
|
+
new_sys.rebalance_nodes
|
222
|
+
|
223
|
+
parent = new_sys.nodes.select { |n| n.name == "parent_node" }.first
|
224
|
+
parent.children.first.name.should eql("child_node")
|
225
|
+
parent.options.should eql({ :attributes => {}, :type => "chef-solo" })
|
226
|
+
parent.children.first.options.should eql({
|
227
|
+
:attributes => {}, :type => "chef" })
|
228
|
+
|
229
|
+
new_sys.roots.size.should eql(2)
|
230
|
+
new_sys.dependent_nodes.size.should eql(1)
|
231
|
+
end
|
232
|
+
|
233
|
+
it "should have the same system in a hash format as it does in dsl" do
|
234
|
+
sys = {
|
235
|
+
:nodes => [
|
236
|
+
{ :name => "MasterNode",
|
237
|
+
:run_list => [ "recipe[gem]",
|
238
|
+
"recipe[git]" ],
|
239
|
+
:options => {
|
240
|
+
:gem => { :source => "http://gem.test.com" },
|
241
|
+
:aws_ebs_size => 10,
|
242
|
+
:volume_count => 2
|
243
|
+
}
|
244
|
+
}
|
245
|
+
]
|
246
|
+
}
|
247
|
+
|
248
|
+
sys2 = Souffle::System.new
|
249
|
+
masternode = Souffle::Node.new
|
250
|
+
masternode.name = "MasterNode"
|
251
|
+
masternode.run_list << "recipe[gem]"
|
252
|
+
masternode.run_list << "recipe[git]"
|
253
|
+
masternode.options[:gem] = { :source => "http://gem.test.com" }
|
254
|
+
masternode.options[:aws_ebs_size] = 10
|
255
|
+
masternode.options[:volume_count] = 2
|
256
|
+
sys2.add(masternode)
|
257
|
+
|
258
|
+
new_sys = Souffle::System.from_hash(sys)
|
259
|
+
|
260
|
+
parent = new_sys.nodes.select { |n| n.name == "MasterNode" }.first
|
261
|
+
parent.run_list.should eql(masternode.run_list)
|
262
|
+
parent.options.should eql(masternode.options)
|
34
263
|
end
|
35
264
|
end
|