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 CHANGED
@@ -1,19 +1,30 @@
1
1
  # Changelog
2
2
 
3
+ ### v0.0.4
3
4
 
4
- ### v0.0.1
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
- * Application framework laid out
7
- * Initial node state machine
8
- * Initial system state machine
9
- * Added AWS provider
10
- * Initial command line interface
11
- * Added daemonization
12
- * Added singleton configuration
13
- * Initial runlist parser
14
- * Initial dependency traversal
15
- * System rebalancing (pre-provisioning)
16
- * Added REST API
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
- ### v0.0.3
43
+ ### v0.0.1
33
44
 
34
- * Multiple documentation updates
35
- * AWS provider
36
- * Tags now use `hex(4)` instead of `hex(6)`
37
- * Deprecated default tag prefix
38
- * Added chef roles support to providers
39
- * Fixed /version url link
40
- * Added `tag`, `domain`, and `fqdn` node helpers
41
- * Bugfix for repo_path
42
- * Hostname is now set at provisioning
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
@@ -4,7 +4,7 @@ source "http://rubygems.org"
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
6
  gem "yajl-ruby", "~> 1.1.0"
7
- gem "eventmachine", "~> 0.12.10"
7
+ gem "eventmachine", "~> 1.0.0"
8
8
  gem "amqp", "~> 0.9.7"
9
9
  gem "state_machine", "~> 1.1.2"
10
10
  gem "em-ssh", "~> 0.4.0"
data/README.md CHANGED
@@ -48,9 +48,9 @@ As an example system we'll generate two nodes that both are provisioned with `so
48
48
 
49
49
  ```json
50
50
  {
51
- "provider": "aws",
52
51
  "user": "josh",
53
52
  "options": {
53
+ "provider": "aws",
54
54
  "domain": "mydomain.com",
55
55
  "type": "solo",
56
56
  "aws_ebs_size": 10,
@@ -30,4 +30,7 @@ class Souffle::Exceptions
30
30
 
31
31
  # The AWS Keys are invalid.
32
32
  class InvalidAwsKeys < RuntimeError; end
33
+
34
+ # Plugin does not exist.
35
+ class PluginDoesNotExist < RuntimeError; end
33
36
  end
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)
@@ -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"
@@ -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.provisioner.provider
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.provisioner.provider
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.provisioner.provider
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) == :solo
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.provisioner.provider
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
- ssh_block(node) do |ssh|
591
- ssh.exec!("chef-client")
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.system.provisioner.provider
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=500)
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 all_complete
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
@@ -13,15 +13,9 @@ class Souffle::Server
13
13
  # Runs the server.
14
14
  def run
15
15
  if Souffle::Config[:server]
16
- EM.synchrony do
17
- @app = Rack::Builder.new do
18
- use Rack::Lint
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
@@ -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.
@@ -1,6 +1,5 @@
1
1
  # An orchestrator for setting up isolated chef-managed systems.
2
2
  module Souffle
3
3
  # The current souffle version.
4
- VERSION = "0.0.3"
4
+ VERSION = "0.0.4"
5
5
  end
6
-
@@ -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.3
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-19 00:00:00.000000000 Z
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.12.10
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.12.10
45
+ version: 1.0.0
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: amqp
48
48
  requirement: !ruby/object:Gem::Requirement