elastic_beans 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +91 -16
- data/exe/beans +26 -20
- data/lib/elastic_beans/application.rb +33 -1
- data/lib/elastic_beans/application_version.rb +18 -3
- data/lib/elastic_beans/aws/cloudformation_stack.rb +2 -0
- data/lib/elastic_beans/command/configure.rb +12 -18
- data/lib/elastic_beans/command/create.rb +8 -4
- data/lib/elastic_beans/command/deploy.rb +3 -3
- data/lib/elastic_beans/command/exec.rb +4 -3
- data/lib/elastic_beans/command/scale.rb +2 -2
- data/lib/elastic_beans/command/set_env.rb +4 -3
- data/lib/elastic_beans/command/talk.rb +1 -0
- data/lib/elastic_beans/command/version.rb +1 -0
- data/lib/elastic_beans/command.rb +2 -0
- data/lib/elastic_beans/configuration_template/base.rb +12 -2
- data/lib/elastic_beans/configuration_template/exec.rb +6 -0
- data/lib/elastic_beans/configuration_template/scheduler.rb +4 -0
- data/lib/elastic_beans/configuration_template/webserver.rb +11 -4
- data/lib/elastic_beans/configuration_template/worker.rb +6 -0
- data/lib/elastic_beans/configuration_template.rb +32 -11
- data/lib/elastic_beans/dns_entry.rb +2 -0
- data/lib/elastic_beans/env_vars.rb +6 -0
- data/lib/elastic_beans/environment/exec.rb +13 -4
- data/lib/elastic_beans/environment/scheduler.rb +13 -4
- data/lib/elastic_beans/environment/webserver.rb +13 -4
- data/lib/elastic_beans/environment/worker.rb +15 -4
- data/lib/elastic_beans/environment.rb +74 -18
- data/lib/elastic_beans/error/environments_not_ready.rb +2 -0
- data/lib/elastic_beans/error.rb +1 -0
- data/lib/elastic_beans/exec/init.rb +2 -0
- data/lib/elastic_beans/exec/sqs_consumer.rb +2 -0
- data/lib/elastic_beans/network.rb +1 -0
- data/lib/elastic_beans/rack/exec.rb +5 -0
- data/lib/elastic_beans/ui.rb +2 -0
- data/lib/elastic_beans/version.rb +1 -1
- metadata +2 -2
@@ -3,14 +3,15 @@ require "elastic_beans/error/environments_not_ready"
|
|
3
3
|
|
4
4
|
module ElasticBeans
|
5
5
|
module Command
|
6
|
+
# :nodoc: all
|
6
7
|
class SetEnv
|
7
|
-
USAGE = "setenv
|
8
|
+
USAGE = "setenv KEY=[value] [KEY=[value]]..."
|
8
9
|
DESC = "Update environment variables in the Elastic Beanstalk application"
|
9
10
|
LONG_DESC = <<-LONG_DESC
|
10
11
|
Update environment variables in the Elastic Beanstalk application.
|
11
|
-
|
12
|
+
These are stored in S3 to avoid the 4096-byte limit on environment variables in Elastic Beanstalk.
|
13
|
+
Restarts all running environments so they load the updated environment.
|
12
14
|
|
13
|
-
Requires the application name.
|
14
15
|
Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
|
15
16
|
LONG_DESC
|
16
17
|
|
@@ -2,13 +2,19 @@ require "elastic_beans/error"
|
|
2
2
|
|
3
3
|
module ElasticBeans
|
4
4
|
class ConfigurationTemplate
|
5
|
+
# The "base" configuration template stored in the Elastic Beanstalk application.
|
6
|
+
# Common settings are stored here, such as networking settings and environment variables.
|
7
|
+
# Used as a "source configuration" when creating other configuration templates, so that new templates share the
|
8
|
+
# existing configuration.
|
5
9
|
class Base < ElasticBeans::ConfigurationTemplate
|
10
|
+
# The solution stack used for a new application. Should not be hardcoded, but here we are.
|
6
11
|
SOLUTION_STACK_NAME = "64bit Amazon Linux 2016.09 v2.2.0 running Ruby 2.3 (Puma)"
|
7
12
|
|
8
13
|
def initialize(**args)
|
9
14
|
super(name: "base", **args)
|
10
15
|
end
|
11
16
|
|
17
|
+
# Overrides ElasticBeans::ConfigurationTemplate#upsert to add the solution stack to the base configuration.
|
12
18
|
def upsert(**args)
|
13
19
|
@option_settings = build_option_settings(**args)
|
14
20
|
if configuration_settings_description
|
@@ -32,16 +38,18 @@ module ElasticBeans
|
|
32
38
|
|
33
39
|
protected
|
34
40
|
|
41
|
+
# Constructs the common configuration for all environments.
|
42
|
+
# +network+, +database_url+, +secret_key_base+, +keypair+, and +iam+ are all required on first run.
|
35
43
|
def build_option_settings(
|
36
44
|
network: nil,
|
37
45
|
database_url: nil,
|
38
46
|
secret_key_base: nil,
|
47
|
+
keypair: nil,
|
48
|
+
iam: nil,
|
39
49
|
image_id: nil,
|
40
50
|
instance_type: nil,
|
41
|
-
keypair: nil,
|
42
51
|
min_size: nil,
|
43
52
|
max_size: nil,
|
44
|
-
iam: nil,
|
45
53
|
**_
|
46
54
|
)
|
47
55
|
instance_profile_setting = template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "IamInstanceProfile", override: instance_profile(iam))
|
@@ -126,6 +134,8 @@ module ElasticBeans
|
|
126
134
|
network.vpc if network
|
127
135
|
end
|
128
136
|
|
137
|
+
# :nodoc: all
|
138
|
+
# @!visibility private
|
129
139
|
class MissingInstanceProfileError < ElasticBeans::Error
|
130
140
|
def message
|
131
141
|
"Could not find Elastic Beanstalk instance profile." \
|
@@ -3,6 +3,8 @@ require "elastic_beans/error"
|
|
3
3
|
|
4
4
|
module ElasticBeans
|
5
5
|
class ConfigurationTemplate
|
6
|
+
# The "exec" configuration template stored in the Elastic Beanstalk application.
|
7
|
+
# Settings for the exec environment are stored here, such as the exec queue URL and the logging endpoint.
|
6
8
|
class Exec < ElasticBeans::ConfigurationTemplate::Base
|
7
9
|
def initialize(**args)
|
8
10
|
super(name: "exec", **args)
|
@@ -10,6 +12,8 @@ module ElasticBeans
|
|
10
12
|
|
11
13
|
protected
|
12
14
|
|
15
|
+
# Constructs the configuration for the exec environment.
|
16
|
+
# +logging_endpoint+, if provided, must be a valid HTTPS URL.
|
13
17
|
def build_option_settings(logging_endpoint: nil, **_)
|
14
18
|
if logging_endpoint
|
15
19
|
begin
|
@@ -36,6 +40,8 @@ module ElasticBeans
|
|
36
40
|
super + settings
|
37
41
|
end
|
38
42
|
|
43
|
+
# :nodoc: all
|
44
|
+
# @!visibility private
|
39
45
|
class InvalidLoggingEndpointError < ElasticBeans::Error
|
40
46
|
def initialize(logging_endpoint:)
|
41
47
|
@logging_endpoint = logging_endpoint
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module ElasticBeans
|
2
2
|
class ConfigurationTemplate
|
3
|
+
# The "scheduler" configuration template stored in the Elastic Beanstalk application.
|
4
|
+
# Settings for the scheduler environment are stored here.
|
3
5
|
class Scheduler < ElasticBeans::ConfigurationTemplate::Base
|
4
6
|
def initialize(**args)
|
5
7
|
super(name: "scheduler", **args)
|
@@ -7,6 +9,8 @@ module ElasticBeans
|
|
7
9
|
|
8
10
|
protected
|
9
11
|
|
12
|
+
# Constructs the configuration for the scheduler environment.
|
13
|
+
# No special options here!
|
10
14
|
def build_option_settings(**_)
|
11
15
|
super + [
|
12
16
|
template_option_setting(namespace: "aws:elasticbeanstalk:application", option_name: "Application Healthcheck URL", default: "HTTP:80/"),
|
@@ -2,6 +2,8 @@ require "elastic_beans/error"
|
|
2
2
|
|
3
3
|
module ElasticBeans
|
4
4
|
class ConfigurationTemplate
|
5
|
+
# The "webserver" configuration template stored in the Elastic Beanstalk application.
|
6
|
+
# Settings for the webserver environment are stored here.
|
5
7
|
class Webserver < ElasticBeans::ConfigurationTemplate::Base
|
6
8
|
def initialize(**args)
|
7
9
|
super(name: "webserver", **args)
|
@@ -9,10 +11,12 @@ module ElasticBeans
|
|
9
11
|
|
10
12
|
protected
|
11
13
|
|
12
|
-
|
14
|
+
# Constructs the configuration for the webserver environment.
|
15
|
+
# All arguments are required on first run.
|
16
|
+
def build_option_settings(network: nil, public_key: nil, ssl_certificate_arn: nil, **_)
|
13
17
|
public_key_policy_names_setting = template_option_setting(namespace: "aws:elb:policies:backendencryption", option_name: "PublicKeyPolicyNames", default: "backendkey")
|
14
18
|
public_key_setting = template_option_setting(namespace: "aws:elb:policies:#{public_key_policy_names_setting[:value]}", option_name: "PublicKey", override: public_key)
|
15
|
-
ssl_certificate_setting = template_option_setting(namespace: "aws:elb:listener:443", option_name: "SSLCertificateId", override:
|
19
|
+
ssl_certificate_setting = template_option_setting(namespace: "aws:elb:listener:443", option_name: "SSLCertificateId", override: ssl_certificate_arn)
|
16
20
|
if public_key_setting[:value].nil? || ssl_certificate_setting[:value].nil?
|
17
21
|
raise NoEncryptionSettingsError
|
18
22
|
end
|
@@ -42,13 +46,16 @@ module ElasticBeans
|
|
42
46
|
network.elb_security_groups[0] if network
|
43
47
|
end
|
44
48
|
|
49
|
+
# :nodoc: all
|
50
|
+
# @!visibility private
|
45
51
|
class NoEncryptionSettingsError < ElasticBeans::Error
|
46
52
|
def message
|
47
53
|
require "elastic_beans/command/configure"
|
48
54
|
<<-MESSAGE
|
49
|
-
Missing required end-to-end encryption settings.
|
55
|
+
Missing required end-to-end encryption settings.
|
56
|
+
Please re-run `#{command_as_string "configure"}` and make sure to specify SSL certificate ARN and internal public key.
|
50
57
|
|
51
|
-
|
58
|
+
#{`#{$0} help configure`}
|
52
59
|
MESSAGE
|
53
60
|
end
|
54
61
|
end
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module ElasticBeans
|
2
2
|
class ConfigurationTemplate
|
3
|
+
# The worker configuration templates stored in the Elastic Beanstalk application.
|
4
|
+
# Settings for the worker environments are stored here.
|
5
|
+
# This class is used to construct multiple worker configuration templates, one per queue.
|
3
6
|
class Worker < ElasticBeans::ConfigurationTemplate::Base
|
4
7
|
attr_reader :queue
|
5
8
|
|
@@ -10,6 +13,9 @@ module ElasticBeans
|
|
10
13
|
|
11
14
|
protected
|
12
15
|
|
16
|
+
# Constructs the configuration for the worker environments.
|
17
|
+
# No special arguments, the +queue+ name is stored from the initializer and is used to look up the appropriate
|
18
|
+
# URL.
|
13
19
|
def build_option_settings(**_)
|
14
20
|
super + [
|
15
21
|
template_option_setting(namespace: "aws:elasticbeanstalk:application", option_name: "Application Healthcheck URL", default: "HTTP:80/"),
|
@@ -5,11 +5,20 @@ require "elastic_beans/configuration_template/webserver"
|
|
5
5
|
require "elastic_beans/configuration_template/worker"
|
6
6
|
|
7
7
|
module ElasticBeans
|
8
|
+
# An Elastic Beanstalk saved configuration (also known as a configuration template) which may or may not exist.
|
9
|
+
#
|
10
|
+
# This is an abstract class; use the provided factories in this class or use a subclass (contained within this
|
11
|
+
# namespace) directly.
|
8
12
|
class ConfigurationTemplate
|
13
|
+
# :category: Internal
|
9
14
|
WORKER_TEMPLATE_NAME_PATTERN = /\Aworker-(?<queue>\w+)\z/
|
10
15
|
|
11
16
|
attr_reader :name
|
12
17
|
|
18
|
+
# Create a new configuration template of a particular +type+.
|
19
|
+
# See the particular subclass being created for details on arguments.
|
20
|
+
#
|
21
|
+
# Raises an error if the +type+ is not recognized.
|
13
22
|
def self.new_by_type(type, **args)
|
14
23
|
case type
|
15
24
|
when "base"
|
@@ -27,6 +36,10 @@ module ElasticBeans
|
|
27
36
|
end
|
28
37
|
end
|
29
38
|
|
39
|
+
# Create a representation of an existing configuration template.
|
40
|
+
# Uses the +template_name+ to discover the appropriate type (and queue, in the case of a worker).
|
41
|
+
#
|
42
|
+
# Raises an error if the +template_name+ is not recognized.
|
30
43
|
def self.new_from_existing(template_name, **args)
|
31
44
|
case template_name
|
32
45
|
when "base"
|
@@ -45,6 +58,7 @@ module ElasticBeans
|
|
45
58
|
end
|
46
59
|
end
|
47
60
|
|
61
|
+
# :category: Internal
|
48
62
|
def initialize(
|
49
63
|
name:,
|
50
64
|
application:,
|
@@ -56,6 +70,7 @@ module ElasticBeans
|
|
56
70
|
@elastic_beanstalk = elastic_beanstalk
|
57
71
|
end
|
58
72
|
|
73
|
+
# :category: Internal
|
59
74
|
def option_settings
|
60
75
|
# do not fetch option settings from Elastic Beanstalk, because those cannot be naively used.
|
61
76
|
# the set built in #build_option_settings is what we care about.
|
@@ -63,6 +78,9 @@ module ElasticBeans
|
|
63
78
|
raise MissingConfigurationError
|
64
79
|
end
|
65
80
|
|
81
|
+
# Create or update the configuration template in Elastic Beanstalk.
|
82
|
+
# Arguments are passed to #build_option_settings.
|
83
|
+
# See the appropriate subclass for what the arguments should be.
|
66
84
|
def upsert(**args)
|
67
85
|
@option_settings = build_option_settings(**args)
|
68
86
|
if configuration_settings_description
|
@@ -86,7 +104,10 @@ module ElasticBeans
|
|
86
104
|
|
87
105
|
protected
|
88
106
|
|
89
|
-
|
107
|
+
# :category: Internal
|
108
|
+
attr_reader :application
|
109
|
+
# :category: Internal
|
110
|
+
attr_reader :elastic_beanstalk
|
90
111
|
|
91
112
|
def build_option_settings(**_)
|
92
113
|
[]
|
@@ -123,6 +144,8 @@ module ElasticBeans
|
|
123
144
|
option_setting.merge!(value: setting[:value])
|
124
145
|
end
|
125
146
|
|
147
|
+
# :nodoc: all
|
148
|
+
# @!visibility private
|
126
149
|
class InvalidConfigurationError < ElasticBeans::Error
|
127
150
|
include Nesty::NestedError
|
128
151
|
|
@@ -139,6 +162,8 @@ module ElasticBeans
|
|
139
162
|
end
|
140
163
|
end
|
141
164
|
|
165
|
+
# :nodoc: all
|
166
|
+
# @!visibility private
|
142
167
|
class MissingConfigurationError < ElasticBeans::Error
|
143
168
|
include Nesty::NestedError
|
144
169
|
|
@@ -149,23 +174,19 @@ module ElasticBeans
|
|
149
174
|
def message
|
150
175
|
require "elastic_beans/command/configure"
|
151
176
|
msg = <<-MESSAGE
|
152
|
-
Some configuration must be set before creating an environment
|
153
|
-
|
154
|
-
* keypair
|
155
|
-
* SSL configuration
|
156
|
-
* environment variables that Rails always requires
|
157
|
-
* DATABASE_URL
|
158
|
-
* SECRET_KEY_BASE
|
159
|
-
|
160
|
-
#{$0} #{ElasticBeans::Command::Configure::USAGE}
|
177
|
+
Some configuration is missing and must be set before creating or updating an environment.
|
161
178
|
MESSAGE
|
162
179
|
if nested
|
163
|
-
msg
|
180
|
+
msg << "The error from AWS was \"#{nested.message}\"\n#{msg}\n"
|
181
|
+
else
|
182
|
+
msg << "Please re-run `#{command_as_string "configure"}`.\n\n#{`#{$0} help configure`}"
|
164
183
|
end
|
165
184
|
msg
|
166
185
|
end
|
167
186
|
end
|
168
187
|
|
188
|
+
# :nodoc: all
|
189
|
+
# @!visibility private
|
169
190
|
class UnknownConfigurationType < ElasticBeans::Error
|
170
191
|
def initialize(type:)
|
171
192
|
@type = type
|
@@ -3,6 +3,9 @@ require "aws-sdk"
|
|
3
3
|
require "elastic_beans/error"
|
4
4
|
|
5
5
|
module ElasticBeans
|
6
|
+
# Interfaces with environment variable storage for the Elastic Beanstalk application.
|
7
|
+
# Environment variables are stored in JSON in S3 to avoid the 4096-byte limit on environment variables in Elastic
|
8
|
+
# Beanstalk. An ebextension is used to inject these into the environment variables on the running instance.
|
6
9
|
class EnvVars
|
7
10
|
def initialize(application:, s3:)
|
8
11
|
@application = application
|
@@ -13,6 +16,7 @@ module ElasticBeans
|
|
13
16
|
@s3_key ||= "#{application.name}/env_vars.json"
|
14
17
|
end
|
15
18
|
|
19
|
+
# Updates the environment variables stored in S3 by merging it with the given +env_hash+.
|
16
20
|
def update(env_hash)
|
17
21
|
body = env_script(existing_env_hash.merge(env_hash))
|
18
22
|
s3.put_object(bucket: application.bucket_name, key: s3_key, body: body)
|
@@ -37,6 +41,8 @@ module ElasticBeans
|
|
37
41
|
raise CannotAccessConfigError.new(bucket_name: application.bucket_name, key: s3_key)
|
38
42
|
end
|
39
43
|
|
44
|
+
# :nodoc: all
|
45
|
+
# @!visibility private
|
40
46
|
class CannotAccessConfigError < ElasticBeans::Error
|
41
47
|
def initialize(bucket_name:, key:)
|
42
48
|
@bucket_name = bucket_name
|
@@ -1,14 +1,23 @@
|
|
1
1
|
module ElasticBeans
|
2
2
|
class Environment
|
3
|
+
# The "exec" environment for executing one-off commands.
|
3
4
|
class Exec < ElasticBeans::Environment
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
# :category: Internal
|
6
|
+
TYPE = "exec"
|
7
|
+
# :category: Internal
|
7
8
|
TIER_NAME = "Worker"
|
9
|
+
# :category: Internal
|
8
10
|
TIER_TYPE = "SQS/HTTP"
|
9
11
|
|
12
|
+
# Returns "exec"
|
13
|
+
def type
|
14
|
+
TYPE
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
10
19
|
def template_name
|
11
|
-
|
20
|
+
type
|
12
21
|
end
|
13
22
|
|
14
23
|
def tier_name
|
@@ -1,14 +1,23 @@
|
|
1
1
|
module ElasticBeans
|
2
2
|
class Environment
|
3
|
+
# The "scheduler" environment for processing periodic tasks.
|
3
4
|
class Scheduler < ElasticBeans::Environment
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
# :category: Internal
|
6
|
+
TYPE = "scheduler"
|
7
|
+
# :category: Internal
|
7
8
|
TIER_NAME = "Worker"
|
9
|
+
# :category: Internal
|
8
10
|
TIER_TYPE = "SQS/HTTP"
|
9
11
|
|
12
|
+
# Returns "scheduler"
|
13
|
+
def type
|
14
|
+
TYPE
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
10
19
|
def template_name
|
11
|
-
|
20
|
+
type
|
12
21
|
end
|
13
22
|
|
14
23
|
def tier_name
|
@@ -1,14 +1,23 @@
|
|
1
1
|
module ElasticBeans
|
2
2
|
class Environment
|
3
|
+
# The "webserver" environment for responding to web requests.
|
3
4
|
class Webserver < ElasticBeans::Environment
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
# :category: Internal
|
6
|
+
TYPE = "webserver"
|
7
|
+
# :category: Internal
|
7
8
|
TIER_NAME = "Webserver"
|
9
|
+
# :category: Internal
|
8
10
|
TIER_TYPE = "Standard"
|
9
11
|
|
12
|
+
# Returns "webserver"
|
13
|
+
def type
|
14
|
+
TYPE
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
10
19
|
def template_name
|
11
|
-
|
20
|
+
type
|
12
21
|
end
|
13
22
|
|
14
23
|
def tier_name
|
@@ -1,6 +1,15 @@
|
|
1
1
|
module ElasticBeans
|
2
2
|
class Environment
|
3
|
+
# The worker environments for background job execution.
|
4
|
+
# This class is used to construct multiple worker environments, one per queue.
|
3
5
|
class Worker < ElasticBeans::Environment
|
6
|
+
# :category: Internal
|
7
|
+
TYPE = "worker"
|
8
|
+
# :category: Internal
|
9
|
+
TIER_NAME = "Worker"
|
10
|
+
# :category: Internal
|
11
|
+
TIER_TYPE = "SQS/HTTP"
|
12
|
+
|
4
13
|
attr_reader :queue
|
5
14
|
|
6
15
|
def initialize(name, queue:, **_)
|
@@ -8,13 +17,15 @@ module ElasticBeans
|
|
8
17
|
@queue = queue
|
9
18
|
end
|
10
19
|
|
11
|
-
|
20
|
+
# Returns "worker"
|
21
|
+
def type
|
22
|
+
TYPE
|
23
|
+
end
|
12
24
|
|
13
|
-
|
14
|
-
TIER_TYPE = "SQS/HTTP"
|
25
|
+
protected
|
15
26
|
|
16
27
|
def template_name
|
17
|
-
@template_name ||= "
|
28
|
+
@template_name ||= "#{type}-#{queue}"
|
18
29
|
end
|
19
30
|
|
20
31
|
def tier_name
|