elastic_beans 0.2.0 → 0.3.0

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +91 -16
  3. data/exe/beans +26 -20
  4. data/lib/elastic_beans/application.rb +33 -1
  5. data/lib/elastic_beans/application_version.rb +18 -3
  6. data/lib/elastic_beans/aws/cloudformation_stack.rb +2 -0
  7. data/lib/elastic_beans/command/configure.rb +12 -18
  8. data/lib/elastic_beans/command/create.rb +8 -4
  9. data/lib/elastic_beans/command/deploy.rb +3 -3
  10. data/lib/elastic_beans/command/exec.rb +4 -3
  11. data/lib/elastic_beans/command/scale.rb +2 -2
  12. data/lib/elastic_beans/command/set_env.rb +4 -3
  13. data/lib/elastic_beans/command/talk.rb +1 -0
  14. data/lib/elastic_beans/command/version.rb +1 -0
  15. data/lib/elastic_beans/command.rb +2 -0
  16. data/lib/elastic_beans/configuration_template/base.rb +12 -2
  17. data/lib/elastic_beans/configuration_template/exec.rb +6 -0
  18. data/lib/elastic_beans/configuration_template/scheduler.rb +4 -0
  19. data/lib/elastic_beans/configuration_template/webserver.rb +11 -4
  20. data/lib/elastic_beans/configuration_template/worker.rb +6 -0
  21. data/lib/elastic_beans/configuration_template.rb +32 -11
  22. data/lib/elastic_beans/dns_entry.rb +2 -0
  23. data/lib/elastic_beans/env_vars.rb +6 -0
  24. data/lib/elastic_beans/environment/exec.rb +13 -4
  25. data/lib/elastic_beans/environment/scheduler.rb +13 -4
  26. data/lib/elastic_beans/environment/webserver.rb +13 -4
  27. data/lib/elastic_beans/environment/worker.rb +15 -4
  28. data/lib/elastic_beans/environment.rb +74 -18
  29. data/lib/elastic_beans/error/environments_not_ready.rb +2 -0
  30. data/lib/elastic_beans/error.rb +1 -0
  31. data/lib/elastic_beans/exec/init.rb +2 -0
  32. data/lib/elastic_beans/exec/sqs_consumer.rb +2 -0
  33. data/lib/elastic_beans/network.rb +1 -0
  34. data/lib/elastic_beans/rack/exec.rb +5 -0
  35. data/lib/elastic_beans/ui.rb +2 -0
  36. data/lib/elastic_beans/version.rb +1 -1
  37. metadata +2 -2
@@ -8,14 +8,28 @@ require "elastic_beans/environment/worker"
8
8
  require "elastic_beans/error"
9
9
 
10
10
  module ElasticBeans
11
+ # An Elastic Beanstalk environment which may or may not exist.
12
+ #
13
+ # This is an abstract class; use the provided factories in this class or use a subclass (contained within this
14
+ # namespace) directly.
11
15
  class Environment
16
+ # :category: Internal
12
17
  TEMPLATE_NAME = "base"
18
+ # :category: Internal
13
19
  TIER_NAME = "Webserver"
20
+ # :category: Internal
14
21
  TIER_TYPE = "Standard"
22
+ # :category: Internal
15
23
  WORKER_TEMPLATE_NAME_PATTERN = /worker-(?<queue>\w+)/
16
24
 
17
25
  attr_reader :name
18
26
 
27
+ # Create a new environment of a particular +type+.
28
+ # See the particular subclass being created for details on arguments.
29
+ # The name of the environment will be the application name, joined with the +type+ (and the queue in the case of a
30
+ # worker).
31
+ #
32
+ # Raises an error if the +type+ is not recognized.
19
33
  def self.new_by_type(type, application:, **args)
20
34
  name = "#{application.name}-#{type}"
21
35
  case type
@@ -33,6 +47,12 @@ module ElasticBeans
33
47
  end
34
48
  end
35
49
 
50
+ # Create a representation of an existing environment.
51
+ # Uses the +environment+ to discover the appropriate type (and queue, in the case of a worker).
52
+ # If the +environment+ type is not recognized, the tier will be inspected. If the tier is worker, then the
53
+ # "default" queue will be assumed.
54
+ #
55
+ # Raises an error if the +environment+ type or tier is not recognized.
36
56
  def self.new_from_existing(environment, application:, **args)
37
57
  app_name_pattern = /#{Regexp.escape(application.name)}/
38
58
  case environment.environment_name
@@ -73,6 +93,11 @@ module ElasticBeans
73
93
  @elastic_beanstalk = elastic_beanstalk
74
94
  end
75
95
 
96
+ # Creates the environment in Elastic Beanstalk.
97
+ # Blocks until the environment is Ready.
98
+ #
99
+ # Raises an error if the configuration template for this environment does not exist.
100
+ # Raises an error if the environment is not healthy.
76
101
  def create(version:, tags: {})
77
102
  begin
78
103
  elastic_beanstalk.describe_configuration_settings(
@@ -104,6 +129,10 @@ module ElasticBeans
104
129
  )
105
130
  end
106
131
 
132
+ # Deploys the specified version label to the environment.
133
+ # Blocks until the environment is Ready.
134
+ #
135
+ # Raises an error if the environment is not healthy.
107
136
  def deploy_version(version_label)
108
137
  elastic_beanstalk.update_environment(
109
138
  environment_name: name,
@@ -118,6 +147,10 @@ module ElasticBeans
118
147
  raise UnhealthyEnvironmentError.new(environment_name: name, cause: e)
119
148
  end
120
149
 
150
+ # Restarts the environment application servers.
151
+ # Blocks until the environment is Ready.
152
+ #
153
+ # Raises an error if the environment is not healthy.
121
154
  def restart
122
155
  elastic_beanstalk.restart_app_server(environment_name: name)
123
156
  wait_environment(wait_status: "Updating", wait_health_status: "Info")
@@ -126,6 +159,10 @@ module ElasticBeans
126
159
  retry
127
160
  end
128
161
 
162
+ # Updates the environment configuration to change the minimum and maximum size of the autoscaling group.
163
+ # Blocks until the environment is Ready.
164
+ #
165
+ # Raises an error if the environment is not healthy.
129
166
  def scale(min_size:, max_size:)
130
167
  option_settings = [
131
168
  {namespace: "aws:autoscaling:asg", option_name: "MinSize", value: min_size},
@@ -137,12 +174,17 @@ module ElasticBeans
137
174
  )
138
175
  wait_environment(wait_status: "Updating", wait_health_status: "Info")
139
176
  rescue ::Aws::ElasticBeanstalk::Errors::InvalidParameterValue
140
- raise MissingEnvironmentError.new(environment_name: name)
177
+ raise MissingEnvironmentError.new(environment: self, application: application)
141
178
  rescue ::Aws::ElasticBeanstalk::Errors::Throttling
142
179
  sleep 5
143
180
  retry
144
181
  end
145
182
 
183
+ # Updates the environment configuration with its configuration template.
184
+ # Handy when the configuration template has been updated and you want those changes to take effect immediately.
185
+ # Blocks until the environment is Ready.
186
+ #
187
+ # Raises an error if the environment is not healthy.
146
188
  def update_configuration
147
189
  elastic_beanstalk.update_environment(
148
190
  environment_name: name,
@@ -151,31 +193,42 @@ module ElasticBeans
151
193
  )
152
194
  wait_environment(wait_status: "Updating", wait_health_status: "Info")
153
195
  rescue ::Aws::ElasticBeanstalk::Errors::InvalidParameterValue
154
- raise MissingEnvironmentError.new(environment_name: name)
196
+ raise MissingEnvironmentError.new(environment: self, application: application)
155
197
  rescue ::Aws::ElasticBeanstalk::Errors::Throttling
156
198
  sleep 5
157
199
  retry
158
200
  end
159
201
 
202
+ # Returns the Elastic Beanstalk CNAME, set for a webserver environment.
203
+ #
204
+ # Raises an error if the environment does not exist.
160
205
  def cname
161
206
  environment = environment_description
162
207
  unless environment
163
- raise MissingEnvironmentError.new(environment_name: name)
208
+ raise MissingEnvironmentError.new(environment: self, application: application)
164
209
  end
165
210
  environment.cname
166
211
  end
167
212
 
213
+ # Returns the status of the environment in Elastic Beanstalk.
214
+ #
215
+ # Raises an error if the environment does not exist.
168
216
  def status
169
217
  environment = environment_description
170
218
  unless environment
171
- raise MissingEnvironmentError.new(environment_name: name)
219
+ raise MissingEnvironmentError.new(environment: self, application: application)
172
220
  end
173
221
  environment.status
174
222
  end
175
223
 
176
224
  protected
177
225
 
178
- attr_reader :application, :version, :elastic_beanstalk
226
+ # :category: Internal
227
+ attr_reader :application
228
+ # :category: Internal
229
+ attr_reader :version
230
+ # :category: Internal
231
+ attr_reader :elastic_beanstalk
179
232
 
180
233
  def environment_description
181
234
  elastic_beanstalk.describe_environments(
@@ -245,38 +298,39 @@ module ElasticBeans
245
298
  )
246
299
  end
247
300
 
301
+ # :nodoc: all
302
+ # @!visibility private
248
303
  class MissingConfigurationError < ElasticBeans::Error
249
304
  def message
250
305
  require "elastic_beans/command/configure"
251
306
  <<-MESSAGE
252
- Some configuration must be set before creating an environment:
307
+ Some configuration is missing and must be set before creating an environment.
308
+ Please re-run `#{command_as_string "configure"}`.
253
309
 
254
- * keypair
255
- * SSL configuration
256
- * environment variables that Rails always requires
257
- * DATABASE_URL
258
- * SECRET_KEY_BASE
259
-
260
- #{$0} #{ElasticBeans::Command::Configure::USAGE}
310
+ #{`#{$0} help configure`}
261
311
  MESSAGE
262
312
  end
263
313
  end
264
314
 
315
+ # :nodoc: all
316
+ # @!visibility private
265
317
  class MissingEnvironmentError < ElasticBeans::Error
266
- def initialize(environment_name:)
267
- @environment_name = environment_name
318
+ def initialize(environment:, application:)
319
+ @environment = environment
320
+ @application = application
268
321
  end
269
322
 
270
323
  def message
271
324
  require "elastic_beans/command/create"
272
325
  <<-MESSAGE
273
- Environment `#{@environment_name}' does not exist. Try creating it!
274
-
275
- #{$0} #{ElasticBeans::Command::Create::USAGE}
326
+ Environment `#{@environment.name}' does not exist.
327
+ Please run `#{command_as_string "create #{@environment.type} -a #{@application.name}"}`.
276
328
  MESSAGE
277
329
  end
278
330
  end
279
331
 
332
+ # :nodoc: all
333
+ # @!visibility private
280
334
  class UnhealthyEnvironmentError < ElasticBeans::Error
281
335
  include Nesty::NestedError
282
336
 
@@ -296,6 +350,8 @@ Environment `#{@environment_name}' does not exist. Try creating it!
296
350
  end
297
351
  end
298
352
 
353
+ # :nodoc: all
354
+ # @!visibility private
299
355
  class UnknownEnvironmentType < ElasticBeans::Error
300
356
  def initialize(environment_type:)
301
357
  @environment_type = environment_type
@@ -1,5 +1,7 @@
1
1
  require "elastic_beans/error"
2
2
 
3
+ # :nodoc: all
4
+ # @!visibility private
3
5
  class EnvironmentsNotReady < ElasticBeans::Error
4
6
  def initialize(environments:)
5
7
  @environments = environments
@@ -1,6 +1,7 @@
1
1
  require "shellwords"
2
2
 
3
3
  module ElasticBeans
4
+ # The superclass for errors raised within ElasticBeans.
4
5
  class Error < StandardError
5
6
  protected
6
7
 
@@ -3,6 +3,8 @@ require "fileutils"
3
3
  require "net/http"
4
4
  require "uri"
5
5
 
6
+ # :nodoc: all
7
+ # @!visibility private
6
8
  class Init
7
9
  LOGFILE = "/var/log/elastic_beans_exec.log"
8
10
  PIDFILE = "/var/run/elastic_beans_exec.pid"
@@ -2,6 +2,8 @@ require "json"
2
2
  require "net/http"
3
3
  require "uri"
4
4
 
5
+ # :nodoc: all
6
+ # @!visibility private
5
7
  class SQSConsumer
6
8
  def initialize(logfile:, queue_url:, sqs:, logging_endpoint: nil)
7
9
  @logfile = logfile
@@ -1,6 +1,7 @@
1
1
  require "elastic_beans/aws/cloudformation_stack"
2
2
 
3
3
  module ElasticBeans
4
+ # The networking CloudFormation stack provided to configure.
4
5
  class Network
5
6
  APPLICATION_SECURITY_GROUP_KEY = "ApplicationSecurityGroup"
6
7
  APPLICATION_SUBNET_KEY = "ApplicationSubnet"
@@ -4,6 +4,11 @@ require "action_dispatch"
4
4
 
5
5
  module ElasticBeans
6
6
  module Rack
7
+ # A middleware that can convert specially-crafted paths into commands and enqueue them for execution using
8
+ # ElasticBeans::Application#enqueue_command.
9
+ # Load it in your Rails application so the "scheduler" environment enqueues commands for execution.
10
+ #
11
+ # Only accepts localhost requests from `aws-sqsd`.
7
12
  class Exec
8
13
  FAILURE = ['500', {'Content-type' => 'text/plain'}, [""]]
9
14
  SUCCESS = ['200', {'Content-type' => 'text/plain'}, [""]]
@@ -1,4 +1,6 @@
1
1
  module ElasticBeans
2
+ # :nodoc: all
3
+ # @!visibility private
2
4
  class UI
3
5
  attr_reader :stdout, :stderr
4
6
 
@@ -1,3 +1,3 @@
1
1
  module ElasticBeans
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic_beans
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Stegman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-12 00:00:00.000000000 Z
11
+ date: 2016-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk