elastic_beans 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +3 -0
- data/Gemfile +9 -0
- data/LICENSE.md +21 -0
- data/README.md +184 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/circle.yml +20 -0
- data/elastic_beans.gemspec +31 -0
- data/exe/beans +198 -0
- data/lib/elastic_beans/application.rb +127 -0
- data/lib/elastic_beans/application_version.rb +202 -0
- data/lib/elastic_beans/aws/cloudformation_stack.rb +66 -0
- data/lib/elastic_beans/command/configure.rb +184 -0
- data/lib/elastic_beans/command/create.rb +150 -0
- data/lib/elastic_beans/command/deploy.rb +77 -0
- data/lib/elastic_beans/command/exec.rb +37 -0
- data/lib/elastic_beans/command/set_env.rb +77 -0
- data/lib/elastic_beans/command/talk.rb +74 -0
- data/lib/elastic_beans/command/version.rb +17 -0
- data/lib/elastic_beans/command.rb +12 -0
- data/lib/elastic_beans/configuration_template/base.rb +114 -0
- data/lib/elastic_beans/configuration_template/exec.rb +50 -0
- data/lib/elastic_beans/configuration_template/scheduler.rb +20 -0
- data/lib/elastic_beans/configuration_template/webserver.rb +49 -0
- data/lib/elastic_beans/configuration_template/worker.rb +27 -0
- data/lib/elastic_beans/configuration_template.rb +197 -0
- data/lib/elastic_beans/dns_entry.rb +127 -0
- data/lib/elastic_beans/environment/exec.rb +23 -0
- data/lib/elastic_beans/environment/scheduler.rb +23 -0
- data/lib/elastic_beans/environment/webserver.rb +23 -0
- data/lib/elastic_beans/environment/worker.rb +29 -0
- data/lib/elastic_beans/environment.rb +300 -0
- data/lib/elastic_beans/error/environments_not_ready.rb +15 -0
- data/lib/elastic_beans/error.rb +15 -0
- data/lib/elastic_beans/exec/ebextension.yml +10 -0
- data/lib/elastic_beans/exec/elastic_beans_exec.conf +15 -0
- data/lib/elastic_beans/exec/init.rb +50 -0
- data/lib/elastic_beans/exec/run_command.sh +13 -0
- data/lib/elastic_beans/exec/sqs_consumer.rb +75 -0
- data/lib/elastic_beans/network.rb +44 -0
- data/lib/elastic_beans/rack/exec.rb +63 -0
- data/lib/elastic_beans/scheduler/ebextension.yml +4 -0
- data/lib/elastic_beans/ui.rb +31 -0
- data/lib/elastic_beans/version.rb +3 -0
- data/lib/elastic_beans.rb +9 -0
- metadata +218 -0
@@ -0,0 +1,114 @@
|
|
1
|
+
require "elastic_beans/error"
|
2
|
+
|
3
|
+
module ElasticBeans
|
4
|
+
class ConfigurationTemplate
|
5
|
+
class Base < ElasticBeans::ConfigurationTemplate
|
6
|
+
SOLUTION_STACK_NAME = "64bit Amazon Linux 2016.09 v2.2.0 running Ruby 2.3 (Puma)"
|
7
|
+
|
8
|
+
def initialize(**args)
|
9
|
+
super(name: "base", **args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def upsert(**args)
|
13
|
+
@option_settings = build_option_settings(**args)
|
14
|
+
if configuration_settings_description
|
15
|
+
elastic_beanstalk.update_configuration_template(
|
16
|
+
application_name: application.name,
|
17
|
+
template_name: name,
|
18
|
+
option_settings: option_settings,
|
19
|
+
)
|
20
|
+
else
|
21
|
+
elastic_beanstalk.create_configuration_template(
|
22
|
+
application_name: application.name,
|
23
|
+
template_name: name,
|
24
|
+
solution_stack_name: SOLUTION_STACK_NAME,
|
25
|
+
option_settings: option_settings,
|
26
|
+
)
|
27
|
+
end
|
28
|
+
rescue ::Aws::ElasticBeanstalk::Errors::Throttling
|
29
|
+
sleep 5
|
30
|
+
retry
|
31
|
+
end
|
32
|
+
|
33
|
+
protected
|
34
|
+
|
35
|
+
def build_option_settings(
|
36
|
+
network:,
|
37
|
+
database_url: nil,
|
38
|
+
secret_key_base: nil,
|
39
|
+
image_id: nil,
|
40
|
+
instance_type: nil,
|
41
|
+
keypair: nil,
|
42
|
+
iam:,
|
43
|
+
**_
|
44
|
+
)
|
45
|
+
instance_profile_setting = template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "IamInstanceProfile", override: instance_profile(iam))
|
46
|
+
if instance_profile_setting[:value].nil?
|
47
|
+
raise MissingInstanceProfileError
|
48
|
+
end
|
49
|
+
|
50
|
+
keypair_setting = template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "EC2KeyName", override: keypair)
|
51
|
+
database_url_setting = template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "DATABASE_URL", override: database_url)
|
52
|
+
secret_key_base_setting = template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "SECRET_KEY_BASE", override: secret_key_base)
|
53
|
+
if database_url_setting[:value].nil? || secret_key_base_setting[:value].nil? || keypair_setting[:value].nil?
|
54
|
+
raise MissingConfigurationError
|
55
|
+
end
|
56
|
+
|
57
|
+
security_groups = [network.ssh_security_group] + network.application_security_groups
|
58
|
+
settings = [
|
59
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:command", option_name: "BatchSize", default: "1"),
|
60
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:command", option_name: "BatchSizeType", default: "Fixed"),
|
61
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:command", option_name: "DeploymentPolicy", default: "Rolling"),
|
62
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "DISABLE_SQS_CONSUMER", default: "true"),
|
63
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:environment", option_name: "ServiceRole", default: "aws-elasticbeanstalk-service-role"),
|
64
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:healthreporting:system", option_name: "SystemType", default: "enhanced"),
|
65
|
+
template_option_setting(namespace: "aws:ec2:vpc", option_name: "AssociatePublicIpAddress", default: "false"),
|
66
|
+
template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "InstanceType", default: "c4.large", override: instance_type),
|
67
|
+
template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "SSHSourceRestriction", default: "tcp, 22, 22, 0.0.0.0/32"),
|
68
|
+
template_option_setting(namespace: "aws:autoscaling:updatepolicy:rollingupdate", option_name: "RollingUpdateType", default: "Health"),
|
69
|
+
template_option_setting(namespace: "aws:autoscaling:updatepolicy:rollingupdate", option_name: "RollingUpdateEnabled", default: "true"),
|
70
|
+
template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "SecurityGroups", override: security_groups.join(",")),
|
71
|
+
template_option_setting(namespace: "aws:ec2:vpc", option_name: "ELBSubnets", override: network.elb_subnets.join(",")),
|
72
|
+
template_option_setting(namespace: "aws:ec2:vpc", option_name: "Subnets", override: network.application_subnets.join(",")),
|
73
|
+
template_option_setting(namespace: "aws:ec2:vpc", option_name: "VPCId", override: network.vpc),
|
74
|
+
instance_profile_setting,
|
75
|
+
keypair_setting,
|
76
|
+
database_url_setting,
|
77
|
+
secret_key_base_setting,
|
78
|
+
]
|
79
|
+
if image_id
|
80
|
+
settings << template_option_setting(namespace: "aws:autoscaling:launchconfiguration", option_name: "ImageId", override: image_id)
|
81
|
+
end
|
82
|
+
settings
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def instance_profile(iam)
|
88
|
+
return @instance_profile if @instance_profile
|
89
|
+
marker = nil
|
90
|
+
loop do
|
91
|
+
response = iam.list_instance_profiles(marker: marker)
|
92
|
+
profile = response.instance_profiles.find { |profile|
|
93
|
+
profile.instance_profile_name == "aws-elasticbeanstalk-ec2-role"
|
94
|
+
}
|
95
|
+
if profile
|
96
|
+
@instance_profile = profile.arn
|
97
|
+
return @instance_profile
|
98
|
+
end
|
99
|
+
break unless response.is_truncated
|
100
|
+
marker = response.marker
|
101
|
+
end
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
105
|
+
class MissingInstanceProfileError < ElasticBeans::Error
|
106
|
+
def message
|
107
|
+
"Could not find Elastic Beanstalk instance profile." \
|
108
|
+
" Please create the default instance profile named \"aws-elasticbeanstalk-ec2-role\":" \
|
109
|
+
" http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.iam.html"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "uri"
|
2
|
+
require "elastic_beans/error"
|
3
|
+
|
4
|
+
module ElasticBeans
|
5
|
+
class ConfigurationTemplate
|
6
|
+
class Exec < ElasticBeans::ConfigurationTemplate::Base
|
7
|
+
def initialize(**args)
|
8
|
+
super(name: "exec", **args)
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def build_option_settings(logging_endpoint: nil, **_)
|
14
|
+
if logging_endpoint
|
15
|
+
begin
|
16
|
+
if URI(logging_endpoint).scheme != "https"
|
17
|
+
raise InvalidLoggingEndpointError.new(logging_endpoint: logging_endpoint)
|
18
|
+
end
|
19
|
+
rescue URI::InvalidURIError
|
20
|
+
raise InvalidLoggingEndpointError.new(logging_endpoint: logging_endpoint)
|
21
|
+
end
|
22
|
+
|
23
|
+
logging_endpoint_setting = template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "ELASTIC_BEANS_EXEC_LOGGING_ENDPOINT", override: logging_endpoint)
|
24
|
+
end
|
25
|
+
|
26
|
+
settings = [
|
27
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application", option_name: "Application Healthcheck URL", default: "HTTP:80/"),
|
28
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "DISABLE_SQS_CONSUMER", override: "false"),
|
29
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "ELASTIC_BEANS_EXEC_QUEUE_URL", override: application.exec_queue_url),
|
30
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_ASSET_COMPILATION", default: "true"),
|
31
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_MIGRATIONS", default: "true"),
|
32
|
+
]
|
33
|
+
if logging_endpoint
|
34
|
+
settings << logging_endpoint_setting
|
35
|
+
end
|
36
|
+
super + settings
|
37
|
+
end
|
38
|
+
|
39
|
+
class InvalidLoggingEndpointError < ElasticBeans::Error
|
40
|
+
def initialize(logging_endpoint:)
|
41
|
+
@logging_endpoint = logging_endpoint
|
42
|
+
end
|
43
|
+
|
44
|
+
def message
|
45
|
+
"Logging endpoint `#{@logging_endpoint}' must be a valid HTTPS URL."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module ElasticBeans
|
2
|
+
class ConfigurationTemplate
|
3
|
+
class Scheduler < ElasticBeans::ConfigurationTemplate::Base
|
4
|
+
def initialize(**args)
|
5
|
+
super(name: "scheduler", **args)
|
6
|
+
end
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def build_option_settings(**_)
|
11
|
+
super + [
|
12
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application", option_name: "Application Healthcheck URL", default: "HTTP:80/"),
|
13
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "DISABLE_SQS_CONSUMER", override: "false"),
|
14
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_ASSET_COMPILATION", default: "true"),
|
15
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_MIGRATIONS", default: "true"),
|
16
|
+
]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "elastic_beans/error"
|
2
|
+
|
3
|
+
module ElasticBeans
|
4
|
+
class ConfigurationTemplate
|
5
|
+
class Webserver < ElasticBeans::ConfigurationTemplate::Base
|
6
|
+
def initialize(**args)
|
7
|
+
super(name: "webserver", **args)
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def build_option_settings(network:, public_key:, ssl_certificate_id:, **_)
|
13
|
+
public_key_policy_names_setting = template_option_setting(namespace: "aws:elb:policies:backendencryption", option_name: "PublicKeyPolicyNames", default: "backendkey")
|
14
|
+
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: ssl_certificate_id)
|
16
|
+
if public_key_setting[:value].nil? || ssl_certificate_setting[:value].nil?
|
17
|
+
raise NoEncryptionSettingsError
|
18
|
+
end
|
19
|
+
|
20
|
+
super + [
|
21
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application", option_name: "Application Healthcheck URL", default: "HTTPS:443/"),
|
22
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_ASSET_COMPILATION", default: "false"),
|
23
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_MIGRATIONS", default: "false"),
|
24
|
+
template_option_setting(namespace: "aws:elb:listener:443", option_name: "InstancePort", default: "443"),
|
25
|
+
template_option_setting(namespace: "aws:elb:listener:443", option_name: "InstanceProtocol", default: "HTTPS"),
|
26
|
+
template_option_setting(namespace: "aws:elb:listener:443", option_name: "ListenerProtocol", default: "HTTPS"),
|
27
|
+
template_option_setting(namespace: "aws:elb:loadbalancer", option_name: "ManagedSecurityGroup", override: network.elb_security_groups[0]),
|
28
|
+
template_option_setting(namespace: "aws:elb:loadbalancer", option_name: "SecurityGroups", override: network.elb_security_groups.join(",")),
|
29
|
+
template_option_setting(namespace: "aws:elb:policies", option_name: "ConnectionDrainingEnabled", default: "true"),
|
30
|
+
template_option_setting(namespace: "aws:elb:policies:backendencryption", option_name: "InstancePorts", default: "443"),
|
31
|
+
public_key_policy_names_setting,
|
32
|
+
public_key_setting,
|
33
|
+
ssl_certificate_setting,
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
class NoEncryptionSettingsError < ElasticBeans::Error
|
38
|
+
def message
|
39
|
+
require "elastic_beans/command/configure"
|
40
|
+
<<-MESSAGE
|
41
|
+
Missing required end-to-end encryption settings. Make sure to specify SSL certificate ID and public key.
|
42
|
+
|
43
|
+
#{$0} #{ElasticBeans::Command::Configure::USAGE}
|
44
|
+
MESSAGE
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ElasticBeans
|
2
|
+
class ConfigurationTemplate
|
3
|
+
class Worker < ElasticBeans::ConfigurationTemplate::Base
|
4
|
+
attr_reader :queue
|
5
|
+
|
6
|
+
def initialize(queue:, **args)
|
7
|
+
@queue = queue
|
8
|
+
super(name: "worker-#{queue}", **args)
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def build_option_settings(**_)
|
14
|
+
super + [
|
15
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application", option_name: "Application Healthcheck URL", default: "HTTP:80/"),
|
16
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "DISABLE_SQS_CONSUMER", override: "false"),
|
17
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_ASSET_COMPILATION", default: "true"),
|
18
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "RAILS_SKIP_MIGRATIONS", default: "true"),
|
19
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:sqsd", option_name: "InactivityTimeout", default: "1800"),
|
20
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:sqsd", option_name: "MaxRetries", default: "10"),
|
21
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:sqsd", option_name: "VisibilityTimeout", default: "1800"),
|
22
|
+
template_option_setting(namespace: "aws:elasticbeanstalk:sqsd", option_name: "WorkerQueueURL", override: application.worker_queue_url(queue)),
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
require "elastic_beans/configuration_template/base"
|
2
|
+
require "elastic_beans/configuration_template/exec"
|
3
|
+
require "elastic_beans/configuration_template/scheduler"
|
4
|
+
require "elastic_beans/configuration_template/webserver"
|
5
|
+
require "elastic_beans/configuration_template/worker"
|
6
|
+
|
7
|
+
module ElasticBeans
|
8
|
+
class ConfigurationTemplate
|
9
|
+
WORKER_TEMPLATE_NAME_PATTERN = /\Aworker-(?<queue>\w+)\z/
|
10
|
+
|
11
|
+
attr_reader :name
|
12
|
+
|
13
|
+
def self.new_by_type(type, **args)
|
14
|
+
case type
|
15
|
+
when "base"
|
16
|
+
ElasticBeans::ConfigurationTemplate::Base.new(**args)
|
17
|
+
when "exec"
|
18
|
+
ElasticBeans::ConfigurationTemplate::Exec.new(**args)
|
19
|
+
when "scheduler"
|
20
|
+
ElasticBeans::ConfigurationTemplate::Scheduler.new(**args)
|
21
|
+
when "webserver"
|
22
|
+
ElasticBeans::ConfigurationTemplate::Webserver.new(**args)
|
23
|
+
when "worker"
|
24
|
+
ElasticBeans::ConfigurationTemplate::Worker.new(**args)
|
25
|
+
else
|
26
|
+
raise UnknownConfigurationType.new(type: type)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.new_from_existing(template_name, **args)
|
31
|
+
case template_name
|
32
|
+
when "base"
|
33
|
+
ElasticBeans::ConfigurationTemplate::Base.new(**args)
|
34
|
+
when "exec"
|
35
|
+
ElasticBeans::ConfigurationTemplate::Exec.new(**args)
|
36
|
+
when "scheduler"
|
37
|
+
ElasticBeans::ConfigurationTemplate::Scheduler.new(**args)
|
38
|
+
when "webserver"
|
39
|
+
ElasticBeans::ConfigurationTemplate::Webserver.new(**args)
|
40
|
+
when WORKER_TEMPLATE_NAME_PATTERN
|
41
|
+
match = WORKER_TEMPLATE_NAME_PATTERN.match(template_name)
|
42
|
+
ElasticBeans::ConfigurationTemplate::Worker.new(queue: match[:queue], **args)
|
43
|
+
else
|
44
|
+
raise UnknownConfigurationType.new(type: template_name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(
|
49
|
+
name:,
|
50
|
+
application:,
|
51
|
+
elastic_beanstalk:,
|
52
|
+
**_
|
53
|
+
)
|
54
|
+
@name = name
|
55
|
+
@application = application
|
56
|
+
@elastic_beanstalk = elastic_beanstalk
|
57
|
+
end
|
58
|
+
|
59
|
+
def option_settings
|
60
|
+
# do not fetch option settings from Elastic Beanstalk, because those cannot be naively used.
|
61
|
+
# the set built in #build_option_settings is what we care about.
|
62
|
+
return @option_settings if @option_settings
|
63
|
+
raise MissingConfigurationError
|
64
|
+
end
|
65
|
+
|
66
|
+
def update_environment(env_vars)
|
67
|
+
new_env_settings = env_vars.map { |k, v|
|
68
|
+
{namespace: "aws:elasticbeanstalk:application:environment", option_name: k, value: v}
|
69
|
+
}
|
70
|
+
elastic_beanstalk.update_configuration_template(
|
71
|
+
application_name: application.name,
|
72
|
+
template_name: name,
|
73
|
+
option_settings: new_env_settings,
|
74
|
+
)
|
75
|
+
rescue ::Aws::ElasticBeanstalk::Errors::ConfigurationValidationException => e
|
76
|
+
raise InvalidConfigurationError.new(cause: e)
|
77
|
+
rescue ::Aws::ElasticBeanstalk::Errors::InvalidParameterValue => e
|
78
|
+
raise MissingConfigurationError.new(cause: e)
|
79
|
+
rescue ::Aws::ElasticBeanstalk::Errors::Throttling
|
80
|
+
sleep 5
|
81
|
+
retry
|
82
|
+
end
|
83
|
+
|
84
|
+
def upsert(**args)
|
85
|
+
@option_settings = build_option_settings(**args)
|
86
|
+
if configuration_settings_description
|
87
|
+
elastic_beanstalk.update_configuration_template(
|
88
|
+
application_name: application.name,
|
89
|
+
template_name: name,
|
90
|
+
option_settings: option_settings,
|
91
|
+
)
|
92
|
+
else
|
93
|
+
elastic_beanstalk.create_configuration_template(
|
94
|
+
application_name: application.name,
|
95
|
+
template_name: name,
|
96
|
+
source_configuration: {application_name: application.name, template_name: "base"},
|
97
|
+
option_settings: option_settings,
|
98
|
+
)
|
99
|
+
end
|
100
|
+
rescue ::Aws::ElasticBeanstalk::Errors::Throttling
|
101
|
+
sleep 5
|
102
|
+
retry
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
|
107
|
+
attr_reader :application, :elastic_beanstalk
|
108
|
+
|
109
|
+
def build_option_settings(**_)
|
110
|
+
[]
|
111
|
+
end
|
112
|
+
|
113
|
+
def configuration_settings_description
|
114
|
+
@configuration_template ||= elastic_beanstalk.describe_configuration_settings(
|
115
|
+
application_name: application.name,
|
116
|
+
template_name: name,
|
117
|
+
).configuration_settings[0]
|
118
|
+
rescue ::Aws::ElasticBeanstalk::Errors::InvalidParameterValue => e
|
119
|
+
if e.message =~ /\bconfiguration template\b/i
|
120
|
+
return nil
|
121
|
+
end
|
122
|
+
raise MissingConfigurationError.new(cause: e)
|
123
|
+
end
|
124
|
+
|
125
|
+
def template_option_setting(template: configuration_settings_description, namespace:, option_name:, default: nil, override: nil)
|
126
|
+
option_setting = {namespace: namespace, option_name: option_name, value: default}
|
127
|
+
if override
|
128
|
+
return option_setting.merge!(value: override)
|
129
|
+
end
|
130
|
+
|
131
|
+
if template.nil?
|
132
|
+
return option_setting
|
133
|
+
end
|
134
|
+
setting = template.to_h[:option_settings].find { |setting|
|
135
|
+
setting[:namespace] == namespace && setting[:option_name] == option_name
|
136
|
+
}
|
137
|
+
if setting.nil?
|
138
|
+
return option_setting
|
139
|
+
end
|
140
|
+
|
141
|
+
option_setting.merge!(value: setting[:value])
|
142
|
+
end
|
143
|
+
|
144
|
+
class InvalidConfigurationError < ElasticBeans::Error
|
145
|
+
include Nesty::NestedError
|
146
|
+
|
147
|
+
def initialize(cause: nil)
|
148
|
+
@nested = cause
|
149
|
+
end
|
150
|
+
|
151
|
+
def message
|
152
|
+
msg = "Configuration was rejected by Elastic Beanstalk. Check for too much configuration or the use of reserved words."
|
153
|
+
if nested
|
154
|
+
msg << "The error from AWS was \"#{nested.message}\""
|
155
|
+
end
|
156
|
+
msg
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class MissingConfigurationError < ElasticBeans::Error
|
161
|
+
include Nesty::NestedError
|
162
|
+
|
163
|
+
def initialize(cause: nil)
|
164
|
+
@nested = cause
|
165
|
+
end
|
166
|
+
|
167
|
+
def message
|
168
|
+
require "elastic_beans/command/configure"
|
169
|
+
msg = <<-MESSAGE
|
170
|
+
Some configuration must be set before creating an environment:
|
171
|
+
|
172
|
+
* keypair
|
173
|
+
* SSL configuration
|
174
|
+
* environment variables that Rails always requires
|
175
|
+
* DATABASE_URL
|
176
|
+
* SECRET_KEY_BASE
|
177
|
+
|
178
|
+
#{$0} #{ElasticBeans::Command::Configure::USAGE}
|
179
|
+
MESSAGE
|
180
|
+
if nested
|
181
|
+
msg = "The error from AWS was \"#{nested.message}\"\n#{msg}"
|
182
|
+
end
|
183
|
+
msg
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
class UnknownConfigurationType < ElasticBeans::Error
|
188
|
+
def initialize(type:)
|
189
|
+
@type = type
|
190
|
+
end
|
191
|
+
|
192
|
+
def message
|
193
|
+
"Unknown configuration type `#{@type}'"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|