souffle 0.0.3 → 0.0.4
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/CHANGELOG.md +35 -22
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/lib/souffle/exceptions.rb +3 -0
- data/lib/souffle/http.rb +1 -2
- data/lib/souffle/node.rb +9 -2
- data/lib/souffle/provider.rb +42 -21
- data/lib/souffle/provider/aws.rb +36 -11
- data/lib/souffle/provisioner/node.rb +13 -1
- data/lib/souffle/provisioner/system.rb +16 -18
- data/lib/souffle/server.rb +24 -9
- data/lib/souffle/system.rb +7 -0
- data/lib/souffle/version.rb +1 -2
- data/spec/provider_spec.rb +10 -0
- metadata +4 -4
data/CHANGELOG.md
CHANGED
@@ -1,19 +1,30 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### v0.0.4
|
3
4
|
|
4
|
-
|
5
|
+
* Added chef-client support
|
6
|
+
* Added warning for cli one-off runs
|
7
|
+
* Added provider plugins support
|
8
|
+
* Added provider helper methods
|
9
|
+
* Updated documentation
|
10
|
+
* System timeout set to 10 minutes
|
11
|
+
* Updated handler for node provisioning
|
12
|
+
* Updated handler for system provisioning
|
13
|
+
* Node provisioning updates are now evented
|
14
|
+
* Updated eventmachine to 1.0.0
|
15
|
+
* Fixed timing issue with mdadm install
|
5
16
|
|
6
|
-
|
7
|
-
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
* Added
|
13
|
-
*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
*
|
17
|
+
### v0.0.3
|
18
|
+
|
19
|
+
* Multiple documentation updates
|
20
|
+
* AWS provider
|
21
|
+
* Tags now use `hex(4)` instead of `hex(6)`
|
22
|
+
* Deprecated default tag prefix
|
23
|
+
* Added chef roles support to providers
|
24
|
+
* Fixed /version url link
|
25
|
+
* Added `tag`, `domain`, and `fqdn` node helpers
|
26
|
+
* Bugfix for repo_path
|
27
|
+
* Hostname is now set at provisioning
|
17
28
|
|
18
29
|
### v0.0.2
|
19
30
|
|
@@ -29,14 +40,16 @@
|
|
29
40
|
* Optimized AWS polling mechanism
|
30
41
|
* Optimized AWS creation ordering
|
31
42
|
|
32
|
-
###
|
43
|
+
### v0.0.1
|
33
44
|
|
34
|
-
*
|
35
|
-
*
|
36
|
-
|
37
|
-
|
38
|
-
*
|
39
|
-
*
|
40
|
-
* Added
|
41
|
-
*
|
42
|
-
*
|
45
|
+
* Application framework laid out
|
46
|
+
* Initial node state machine
|
47
|
+
* Initial system state machine
|
48
|
+
* Added AWS provider
|
49
|
+
* Initial command line interface
|
50
|
+
* Added daemonization
|
51
|
+
* Added singleton configuration
|
52
|
+
* Initial runlist parser
|
53
|
+
* Initial dependency traversal
|
54
|
+
* System rebalancing (pre-provisioning)
|
55
|
+
* Added REST API
|
data/Gemfile
CHANGED
data/README.md
CHANGED
data/lib/souffle/exceptions.rb
CHANGED
data/lib/souffle/http.rb
CHANGED
@@ -35,9 +35,8 @@ class Souffle::Http < Sinatra::Base
|
|
35
35
|
Souffle::Log.debug msg
|
36
36
|
Souffle::Log.debug data.to_s
|
37
37
|
|
38
|
-
provider = Souffle::Provider::AWS.new
|
39
|
-
|
40
38
|
system = Souffle::System.from_hash(data)
|
39
|
+
provider = Souffle::Provider.plugin(system.try_opt(:provider)).new
|
41
40
|
system_tag = provider.create_system(system)
|
42
41
|
|
43
42
|
begin
|
data/lib/souffle/node.rb
CHANGED
@@ -99,15 +99,22 @@ class Souffle::Node
|
|
99
99
|
nil
|
100
100
|
end
|
101
101
|
|
102
|
+
# Returns the current system provider.
|
103
|
+
#
|
104
|
+
# @return [ Souffle::Provider::Base ] The current system provider.
|
105
|
+
def provider
|
106
|
+
system.provider
|
107
|
+
end
|
108
|
+
|
102
109
|
# The logging prefix for the given node.
|
103
|
-
#
|
110
|
+
#
|
104
111
|
# @return [ String ] The logging prefix for the given node.
|
105
112
|
def log_prefix
|
106
113
|
"[#{tag}: #{name}]"
|
107
114
|
end
|
108
115
|
|
109
116
|
# The tag for the given node.
|
110
|
-
#
|
117
|
+
#
|
111
118
|
# @return [ String ] The tag for the given node.
|
112
119
|
def tag
|
113
120
|
try_opt(:tag)
|
data/lib/souffle/provider.rb
CHANGED
@@ -3,12 +3,33 @@ require 'tmpdir'
|
|
3
3
|
|
4
4
|
# A metal provider module (Describes AWS, Softlayer, etc).
|
5
5
|
module Souffle::Provider
|
6
|
+
class << self
|
7
|
+
# Returns the list of available provider plugins.
|
8
|
+
#
|
9
|
+
# @return [ Array ] The list of available provider plugins.
|
10
|
+
def plugins
|
11
|
+
constants.map { |k| k.to_s.downcase }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the plugin with the given name.
|
15
|
+
#
|
16
|
+
# @param [ String ] name The name of the plugin to select.
|
17
|
+
#
|
18
|
+
# @return [ Souffle::Provider::Base ] The plugin with the given name.
|
19
|
+
def plugin(name)
|
20
|
+
plug = constants.select { |k| k.to_s.downcase == name.downcase }.first
|
21
|
+
Souffle::Provider.const_get(plug)
|
22
|
+
rescue Souffle::Exceptions::PluginDoesNotExist => e
|
23
|
+
Souffle::Log.error "#{e.message}:\n#{e.backtrace.join("\n")}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
6
27
|
# The souffle cloud provider class.
|
7
28
|
class Base
|
8
29
|
attr_accessor :system
|
9
30
|
|
10
31
|
# Initialize a new provider for a given system.
|
11
|
-
#
|
32
|
+
#
|
12
33
|
# @param [ Souffle::System ] system The system to provision.
|
13
34
|
def initialize(system=Souffle::System.new)
|
14
35
|
@system ||= system
|
@@ -16,7 +37,7 @@ module Souffle::Provider
|
|
16
37
|
end
|
17
38
|
|
18
39
|
# The name of the given provider.
|
19
|
-
#
|
40
|
+
#
|
20
41
|
# @return [ String ] The name of the given provider.
|
21
42
|
def name
|
22
43
|
self.class.name.split('::').last
|
@@ -30,7 +51,7 @@ module Souffle::Provider
|
|
30
51
|
#
|
31
52
|
# @raise [Souffle::Exceptions::Provider] This definition must be
|
32
53
|
# overrridden.
|
33
|
-
#
|
54
|
+
#
|
34
55
|
# @param [ Souffle::System ] system The system to instantiate.
|
35
56
|
# @param [ String ] tag The tag to use for the system.
|
36
57
|
def create_system(system, tag=nil)
|
@@ -39,7 +60,7 @@ module Souffle::Provider
|
|
39
60
|
end
|
40
61
|
|
41
62
|
# Takes a node definition and begins the provisioning process.
|
42
|
-
#
|
63
|
+
#
|
43
64
|
# @param [ Souffle::Node ] node The node to instantiate.
|
44
65
|
# @param [ String ] tag The tag to use for the node.
|
45
66
|
def create_node(node, tag=nil)
|
@@ -48,7 +69,7 @@ module Souffle::Provider
|
|
48
69
|
end
|
49
70
|
|
50
71
|
# Creates a raid array for a given provider. Intended to be overridden.
|
51
|
-
#
|
72
|
+
#
|
52
73
|
# @raise [Souffle::Exceptions::Provider] This definition must be
|
53
74
|
# overridden.
|
54
75
|
def create_raid
|
@@ -57,9 +78,9 @@ module Souffle::Provider
|
|
57
78
|
end
|
58
79
|
|
59
80
|
# Generates the json required for chef-solo to run on a node.
|
60
|
-
#
|
81
|
+
#
|
61
82
|
# @param [ Souffle::Node ] node The node to generate chef-solo json for.
|
62
|
-
#
|
83
|
+
#
|
63
84
|
# @return [ String ] The chef-solo json for the particular node.
|
64
85
|
def generate_chef_json(node)
|
65
86
|
json_info = Hash.new
|
@@ -71,7 +92,7 @@ module Souffle::Provider
|
|
71
92
|
|
72
93
|
# Waits for ssh to be accessible for a node for the initial connection and
|
73
94
|
# yields an ssh object to manage the commands naturally from there.
|
74
|
-
#
|
95
|
+
#
|
75
96
|
# @param [ String ] address The address of the machine to connect to.
|
76
97
|
# @param [ String ] user The user to connect as.
|
77
98
|
# @param [ String, NilClass ] pass By default publickey and password auth
|
@@ -83,7 +104,7 @@ module Souffle::Provider
|
|
83
104
|
# @option opts [ Hash ] :timeout (TIMEOUT) default timeout for all
|
84
105
|
# #wait_for and #send_wait calls.
|
85
106
|
# @option opts [ Boolean ] :reconnect When disconnected reconnect.
|
86
|
-
#
|
107
|
+
#
|
87
108
|
# @yield [ Eventmachine::Ssh:Session ] The ssh session.
|
88
109
|
def wait_for_boot(address, user="root", pass=nil, opts={},
|
89
110
|
timeout=200)
|
@@ -111,7 +132,7 @@ module Souffle::Provider
|
|
111
132
|
end
|
112
133
|
|
113
134
|
# Yields an ssh object to manage the commands naturally from there.
|
114
|
-
#
|
135
|
+
#
|
115
136
|
# @param [ String ] address The address of the machine to connect to.
|
116
137
|
# @param [ String ] user The user to connect as.
|
117
138
|
# @param [ String, NilClass ] pass By default publickey and password auth
|
@@ -122,7 +143,7 @@ module Souffle::Provider
|
|
122
143
|
# @option opts [ Hash ] :timeout (TIMEOUT) default timeout for all
|
123
144
|
# #wait_for and #send_wait calls.
|
124
145
|
# @option opts [ Boolean ] :reconnect When disconnected reconnect.
|
125
|
-
#
|
146
|
+
#
|
126
147
|
# @yield [ EventMachine::Ssh::Session ] The ssh session.
|
127
148
|
def ssh_block(address, user="root", pass=nil, opts={})
|
128
149
|
opts[:password] = pass unless pass.nil?
|
@@ -136,18 +157,18 @@ module Souffle::Provider
|
|
136
157
|
end
|
137
158
|
|
138
159
|
# The path to the ssh key with the given name.
|
139
|
-
#
|
160
|
+
#
|
140
161
|
# @param [ String ] key_name The name fo the ssh key to lookup.
|
141
|
-
#
|
162
|
+
#
|
142
163
|
# @return [ String ] The path to the ssh key with the given name.
|
143
164
|
def ssh_key(key_name)
|
144
165
|
"#{ssh_key_path}/#{key_name}"
|
145
166
|
end
|
146
167
|
|
147
168
|
# Grabs an ssh key for a given aws node.
|
148
|
-
#
|
169
|
+
#
|
149
170
|
# @param [ String ] key_name The name fo the ssh key to lookup.
|
150
|
-
#
|
171
|
+
#
|
151
172
|
# @return [ Boolean ] Whether or not the ssh_key exists
|
152
173
|
# for the node.
|
153
174
|
def ssh_key_exists?(key_name)
|
@@ -160,11 +181,11 @@ module Souffle::Provider
|
|
160
181
|
rescue
|
161
182
|
error_msg = "The ssh key directory does not have write permissions: "
|
162
183
|
error_msg << ssh_key_path
|
163
|
-
raise PermissionErrorSshKeys, error_msg
|
184
|
+
raise Souffle::Exceptions::PermissionErrorSshKeys, error_msg
|
164
185
|
end
|
165
186
|
|
166
187
|
# The path to the ssh keys for the provider.
|
167
|
-
#
|
188
|
+
#
|
168
189
|
# @return [ String ] The path to the ssh keys for the provider.
|
169
190
|
def ssh_key_path
|
170
191
|
File.join(File.dirname(
|
@@ -172,7 +193,7 @@ module Souffle::Provider
|
|
172
193
|
end
|
173
194
|
|
174
195
|
# Rsync's a file to a remote node.
|
175
|
-
#
|
196
|
+
#
|
176
197
|
# @param [ String ] ipaddress The ipaddress of the node to connect to.
|
177
198
|
# @param [ String ] file The file to rsync.
|
178
199
|
# @param [ String ] path The remote path to rsync.
|
@@ -189,7 +210,7 @@ module Souffle::Provider
|
|
189
210
|
end
|
190
211
|
|
191
212
|
# The list of cookbooks and their full paths.
|
192
|
-
#
|
213
|
+
#
|
193
214
|
# @return [ Array ] The list of cookbooks and their full paths.
|
194
215
|
def cookbook_paths
|
195
216
|
Array(Souffle::Config[:chef_cookbook_path]).inject([]) do |_paths, path|
|
@@ -201,7 +222,7 @@ module Souffle::Provider
|
|
201
222
|
end
|
202
223
|
|
203
224
|
# The list of roles and their full paths.
|
204
|
-
#
|
225
|
+
#
|
205
226
|
# @return [ Array ] The list of roles and their full paths.
|
206
227
|
def role_paths
|
207
228
|
Array(Souffle::Config[:chef_role_path]).inject([]) do |_paths, path|
|
@@ -213,7 +234,7 @@ module Souffle::Provider
|
|
213
234
|
end
|
214
235
|
|
215
236
|
# Creates a new cookbook tarball for the deployment.
|
216
|
-
#
|
237
|
+
#
|
217
238
|
# @return [ String ] The path to the created tarball.
|
218
239
|
def create_cookbooks_tarball
|
219
240
|
tarball_name = "cookbooks-latest.tar.gz"
|
data/lib/souffle/provider/aws.rb
CHANGED
@@ -210,7 +210,7 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
210
210
|
|
211
211
|
pre_event do
|
212
212
|
@partitions = 0
|
213
|
-
@provider = node.
|
213
|
+
@provider = node.provider
|
214
214
|
node.options[:volumes].each_with_index do |volume, index|
|
215
215
|
@provider.partition_device(
|
216
216
|
node, @provider.volume_id_to_device(index)) do |count|
|
@@ -284,10 +284,10 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
284
284
|
#
|
285
285
|
# @param [ Souffle::Node ] node The node to install mdadm on.
|
286
286
|
def setup_mdadm(node)
|
287
|
-
ssh_block(node) do |ssh|
|
287
|
+
n = node; ssh_block(node) do |ssh|
|
288
288
|
ssh.exec!("/usr/bin/yum install -y mdadm")
|
289
|
+
n.provisioner.mdadm_installed
|
289
290
|
end
|
290
|
-
node.provisioner.mdadm_installed
|
291
291
|
end
|
292
292
|
|
293
293
|
# Sets up software raid for the given node.
|
@@ -330,7 +330,7 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
330
330
|
|
331
331
|
pre_event do
|
332
332
|
Souffle::Log.info "#{node.log_prefix} Waiting for node running..."
|
333
|
-
@provider = node.
|
333
|
+
@provider = node.provider
|
334
334
|
@blk = blk
|
335
335
|
end
|
336
336
|
|
@@ -364,7 +364,7 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
364
364
|
|
365
365
|
pre_event do
|
366
366
|
Souffle::Log.info "#{node.log_prefix} Waiting for EBS to be ready..."
|
367
|
-
@provider = node.
|
367
|
+
@provider = node.provider
|
368
368
|
@volume_ids = node.options[:volumes].map { |v| v[:aws_id] }
|
369
369
|
end
|
370
370
|
|
@@ -479,12 +479,11 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
479
479
|
# @todo Setup the chef/chef-solo tar gzip and ssh connections.
|
480
480
|
def provision(node)
|
481
481
|
set_hostname(node)
|
482
|
-
if node.try_opt(:chef_provisioner) ==
|
482
|
+
if node.try_opt(:chef_provisioner).to_s.downcase == "solo"
|
483
483
|
provision_chef_solo(node, generate_chef_json(node))
|
484
484
|
else
|
485
485
|
provision_chef_client(node)
|
486
486
|
end
|
487
|
-
node.provisioner.provisioned
|
488
487
|
end
|
489
488
|
|
490
489
|
# Waits for ssh to be accessible for a node for the initial connection and
|
@@ -515,7 +514,7 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
515
514
|
|
516
515
|
pre_event do
|
517
516
|
Souffle::Log.info "#{node.log_prefix} Waiting for ssh..."
|
518
|
-
@provider = node.
|
517
|
+
@provider = node.provider
|
519
518
|
@blk = blk
|
520
519
|
end
|
521
520
|
|
@@ -572,7 +571,7 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
572
571
|
solo_config = "node_name \"#{node.fqdn}\"\n"
|
573
572
|
solo_config << "cookbook_path \"/tmp/cookbooks\"\n"
|
574
573
|
solo_config << 'role_path "/tmp/roles"'
|
575
|
-
ssh_block(node) do |ssh|
|
574
|
+
n = node; ssh_block(node) do |ssh|
|
576
575
|
ssh.exec!("sleep 2; tar -zxf /tmp/cookbooks-latest.tar.gz -C /tmp")
|
577
576
|
ssh.exec!("echo '#{solo_config}' >/tmp/solo.rb")
|
578
577
|
ssh.exec!("echo '#{solo_json}' >/tmp/solo.json")
|
@@ -580,6 +579,7 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
580
579
|
rm_files = %w{ /tmp/cookbooks /tmp/cookbooks-latest.tar.gz
|
581
580
|
/tmp/roles /tmp/solo.rb /tmp/solo.json /tmp/chef_bootstrap }
|
582
581
|
ssh.exec!("rm -rf #{rm_files}")
|
582
|
+
n.provisioner.provisioned
|
583
583
|
end
|
584
584
|
end
|
585
585
|
|
@@ -587,8 +587,14 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
587
587
|
#
|
588
588
|
# @todo Chef client provisioner needs to be completed.
|
589
589
|
def provision_chef_client(node)
|
590
|
-
|
591
|
-
|
590
|
+
client_cmds = "chef-client -N #{node.fqdn} "
|
591
|
+
client_cmds << "-j /tmp/client.json "
|
592
|
+
client_cmds << "-S #{node.try_opt(:chef_server)} "
|
593
|
+
n = node; ssh_block(node) do |ssh|
|
594
|
+
write_temp_chef_json(ssh, n)
|
595
|
+
ssh.exec!(client_cmds)
|
596
|
+
cleanup_temp_chef_files(ssh, n)
|
597
|
+
node.provisioner.provisioned
|
592
598
|
end
|
593
599
|
end
|
594
600
|
|
@@ -725,4 +731,23 @@ class Souffle::Provider::AWS < Souffle::Provider::Base
|
|
725
731
|
end
|
726
732
|
end
|
727
733
|
|
734
|
+
private
|
735
|
+
|
736
|
+
# Writes a temporary chef-client json file.
|
737
|
+
#
|
738
|
+
# @param [ EventMachine::Ssh::Connection ] ssh The em-ssh connection.
|
739
|
+
# @param [ Souffle::Node ] node The given node to work with.
|
740
|
+
def write_temp_chef_json(ssh, node)
|
741
|
+
ssh.exec!("echo '''#{generate_chef_json(node)}''' > /tmp/client.json")
|
742
|
+
end
|
743
|
+
|
744
|
+
# Removes the temporary chef-client files.
|
745
|
+
#
|
746
|
+
# @param [ EventMachine::Ssh::Connection ] ssh The em-ssh connection.
|
747
|
+
# @param [ Souffle::Node ] node The given node to work with.
|
748
|
+
def cleanup_temp_chef_files(ssh, node)
|
749
|
+
ssh.exec!("rm -f /tmp/client.json")
|
750
|
+
ssh.exec!("rm -f /etc/chef/validation.pem")
|
751
|
+
end
|
752
|
+
|
728
753
|
end
|
@@ -19,6 +19,7 @@ class Souffle::Provisioner::Node
|
|
19
19
|
after_transition :formatting_device => :ready_to_provision,
|
20
20
|
:do => :ready
|
21
21
|
after_transition any => :provisioning, :do => :provision
|
22
|
+
after_transition any => :complete, :do => :node_provisioned
|
22
23
|
|
23
24
|
event :reclaimed do
|
24
25
|
transition any => :creating
|
@@ -133,6 +134,12 @@ class Souffle::Provisioner::Node
|
|
133
134
|
provider.provision(@node)
|
134
135
|
end
|
135
136
|
|
137
|
+
# Notifies the system that the current node has completed provisioning.
|
138
|
+
def node_provisioned
|
139
|
+
Souffle::Log.info "#{@node.log_prefix} Node provisioned."
|
140
|
+
system_provisioner.node_provisioned
|
141
|
+
end
|
142
|
+
|
136
143
|
# Kills the node entirely.
|
137
144
|
def kill
|
138
145
|
Souffle::Log.info "#{@node.log_prefix} Killing node..."
|
@@ -152,6 +159,11 @@ class Souffle::Provisioner::Node
|
|
152
159
|
|
153
160
|
# Helper function for the node's system provider.
|
154
161
|
def provider
|
155
|
-
@node.
|
162
|
+
@node.provider
|
163
|
+
end
|
164
|
+
|
165
|
+
# Helper function for the system provisioner.
|
166
|
+
def system_provisioner
|
167
|
+
@node.system.provisioner
|
156
168
|
end
|
157
169
|
end
|
@@ -13,6 +13,7 @@ class Souffle::Provisioner::System
|
|
13
13
|
after_transition :initializing => :creating, :do => :create
|
14
14
|
after_transition :creating => :provisioning, :do => :provision
|
15
15
|
after_transition any => :initializing, :do => :create
|
16
|
+
after_transition :provisioning => :complete, :do => :system_provisioned
|
16
17
|
|
17
18
|
event :initialized do
|
18
19
|
transition :initializing => :creating
|
@@ -51,13 +52,14 @@ class Souffle::Provisioner::System
|
|
51
52
|
# @param [ Souffle::Provider::Base ] provider The provider to use.
|
52
53
|
# @param [ Fixnum ] max_failures the maximum number of failures.
|
53
54
|
# @param [ Fixnum ] timeout The maximum time to wait for node creation.
|
54
|
-
def initialize(system, provider, max_failures=3, timeout=
|
55
|
+
def initialize(system, provider, max_failures=3, timeout=600)
|
55
56
|
@failures = 0
|
56
57
|
@system = system
|
57
58
|
@provider = provider
|
58
59
|
@time_used = 0
|
59
60
|
@timeout = timeout
|
60
61
|
@max_failures = max_failures
|
62
|
+
@nodes_completed = 0
|
61
63
|
super() # NOTE: This is here to initialize state_machine.
|
62
64
|
end
|
63
65
|
|
@@ -113,12 +115,23 @@ class Souffle::Provisioner::System
|
|
113
115
|
end
|
114
116
|
end
|
115
117
|
|
118
|
+
# System has completed provisioning.
|
119
|
+
def system_provisioned
|
120
|
+
Souffle::Log.info "[#{system_tag}] System provisioned."
|
121
|
+
end
|
122
|
+
|
123
|
+
# Updates the number of nodes provisioned for the system provisioner.
|
124
|
+
def node_provisioned
|
125
|
+
@nodes_completed += 1
|
126
|
+
provisioned if @nodes_completed == @system.nodes.size
|
127
|
+
end
|
128
|
+
|
116
129
|
# Kills the system.
|
117
130
|
def kill_system
|
118
131
|
# @provider.kill(@system.nodes)
|
119
132
|
end
|
120
133
|
|
121
|
-
# Handles the error state and recreates the system
|
134
|
+
# Handles the error state and recreates the system.
|
122
135
|
def error_handler
|
123
136
|
@failures += 1
|
124
137
|
if @failures >= @max_failures
|
@@ -169,24 +182,9 @@ class Souffle::Provisioner::System
|
|
169
182
|
|
170
183
|
# Wait until all of the nodes are provisioned and then continue.
|
171
184
|
def wait_until_complete
|
172
|
-
total_nodes = @system.nodes.size
|
173
|
-
all_complete = false
|
174
|
-
timer = EM::PeriodicTimer.new(2) do
|
175
|
-
nodes_ready = @system.nodes.select do |n|
|
176
|
-
n.provisioner.state == "complete"
|
177
|
-
end.size
|
178
|
-
|
179
|
-
if nodes_ready == total_nodes
|
180
|
-
all_complete = true
|
181
|
-
timer.cancel
|
182
|
-
created
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
185
|
EM::Timer.new(@timeout) do
|
187
|
-
unless
|
186
|
+
unless @nodes_completed == @system.nodes.size
|
188
187
|
Souffle::Log.error "[#{system_tag}] System provision timeout reached."
|
189
|
-
timer.cancel
|
190
188
|
error_occurred
|
191
189
|
end
|
192
190
|
end
|
data/lib/souffle/server.rb
CHANGED
@@ -13,15 +13,9 @@ class Souffle::Server
|
|
13
13
|
# Runs the server.
|
14
14
|
def run
|
15
15
|
if Souffle::Config[:server]
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
use Rack::ShowExceptions
|
20
|
-
run Rack::Cascade.new([Souffle::Http])
|
21
|
-
end.to_app
|
22
|
-
|
23
|
-
Rack::Handler.get(:thin).run(@app, rack_options)
|
24
|
-
end
|
16
|
+
run_server
|
17
|
+
else
|
18
|
+
run_instance
|
25
19
|
end
|
26
20
|
end
|
27
21
|
|
@@ -44,5 +38,26 @@ class Souffle::Server
|
|
44
38
|
end
|
45
39
|
opts
|
46
40
|
end
|
41
|
+
|
42
|
+
# Starts a long-running webserver that continuously handles requests.
|
43
|
+
def run_server
|
44
|
+
EM.synchrony do
|
45
|
+
@app = Rack::Builder.new do
|
46
|
+
use Rack::Lint
|
47
|
+
use Rack::ShowExceptions
|
48
|
+
run Rack::Cascade.new([Souffle::Http])
|
49
|
+
end.to_app
|
50
|
+
|
51
|
+
Rack::Handler.get(:thin).run(@app, rack_options)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Starts a single instance of the provisioner.
|
56
|
+
def run_instance
|
57
|
+
Souffle::Log.info "Single instance runs are not currently implemented..."
|
58
|
+
# system = Souffle::System.from_hash(data)
|
59
|
+
# provider = Souffle::Provider.plugin(system.try_opt(:provider)).new
|
60
|
+
# system_tag = provider.create_system(system)
|
61
|
+
end
|
47
62
|
|
48
63
|
end
|
data/lib/souffle/system.rb
CHANGED
@@ -103,6 +103,13 @@ class Souffle::System
|
|
103
103
|
@nodes.select { |n| n.dependencies.any? }
|
104
104
|
end
|
105
105
|
|
106
|
+
# Returns the current system provider.
|
107
|
+
#
|
108
|
+
# @return [ Souffle::Provider::Base ] The current system provider.
|
109
|
+
def provider
|
110
|
+
@provisioner.provider
|
111
|
+
end
|
112
|
+
|
106
113
|
# Tries to fetch an option parameter otherwise it grabs it from config.
|
107
114
|
#
|
108
115
|
# @param [ Symbol ] opt The option to try and fetch.
|
data/lib/souffle/version.rb
CHANGED
data/spec/provider_spec.rb
CHANGED
@@ -53,4 +53,14 @@ describe "Souffle::Provider::Base" do
|
|
53
53
|
|
54
54
|
JSON.parse(@provider.generate_chef_json(node)).should eql(runlist)
|
55
55
|
end
|
56
|
+
|
57
|
+
it "should be able to generate a list of provider plugins" do
|
58
|
+
["base", "vagrant", "aws"].each do |plugin|
|
59
|
+
Souffle::Provider.plugins.include?(plugin).should eql(true)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be able to select a particular plugin" do
|
64
|
+
Souffle::Provider.plugin("aws").should eql(Souffle::Provider::AWS)
|
65
|
+
end
|
56
66
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: souffle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-09-
|
12
|
+
date: 2012-09-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: yajl-ruby
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 0.
|
37
|
+
version: 1.0.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 0.
|
45
|
+
version: 1.0.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: amqp
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|