elastic_beans 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +1 -2
- data/exe/beans +1 -224
- data/lib/elastic_beans/cli.rb +226 -0
- data/lib/elastic_beans/cli/string_shell.rb +14 -0
- data/lib/elastic_beans/command/configure.rb +22 -17
- data/lib/elastic_beans/command/create.rb +1 -1
- data/lib/elastic_beans/command/deploy.rb +4 -3
- data/lib/elastic_beans/command/set_env.rb +1 -1
- data/lib/elastic_beans/configuration_template.rb +7 -2
- data/lib/elastic_beans/configuration_template/base.rb +37 -1
- data/lib/elastic_beans/configuration_template/webserver.rb +3 -2
- data/lib/elastic_beans/environment.rb +4 -3
- data/lib/elastic_beans/error.rb +9 -0
- data/lib/elastic_beans/exec/init.rb +1 -1
- data/lib/elastic_beans/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 661efbe2cb8fd10a68a49a3ebc7899ec3b30b61a
|
4
|
+
data.tar.gz: 6dee6beefb1f0dcd55f5cf7c8f7f73898c9e1432
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63dc0a28f1482b67a2d96fa6edefd65f768acbbe377357acec498bc7b34dafe9242f7ef4c365c82c15d24c80ea6e81a5d6c41cc92e85d3c39002cc969e2f04fc
|
7
|
+
data.tar.gz: ca7b8ffd98f6218a0bb935aea9bfce0cf3d3e804467a709e20d9d0adf83f313ba606ff9057aebffdb2e7dbf80d42e360f2689f0bdc6cc07f8ac5f0ddc6e2de84
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -67,8 +67,7 @@ AWS SDK clients must be passed into Elastic Beans constructors.
|
|
67
67
|
### Periodic tasks
|
68
68
|
|
69
69
|
Elastic Beanstalk [supports periodic tasks][periodic] by sending a POST request to an endpoint of your application.
|
70
|
-
Elastic Beans includes a middleware that can convert specially-crafted paths into commands and enqueue them for execution.
|
71
|
-
The middleware only accepts localhost requests from `aws-sqsd`.
|
70
|
+
Elastic Beans includes a middleware that can convert specially-crafted paths into commands and enqueue them for execution. "Specially-crafted" meaning with /exec at the front, as the cron.yaml section below explains. The middleware only accepts localhost requests from `aws-sqsd`.
|
72
71
|
|
73
72
|
[periodic]: http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html#worker-periodictasks
|
74
73
|
|
data/exe/beans
CHANGED
@@ -1,228 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require "
|
4
|
-
require "thor"
|
5
|
-
require "elastic_beans"
|
6
|
-
require "elastic_beans/error"
|
7
|
-
require "elastic_beans/command"
|
8
|
-
require "elastic_beans/ui"
|
9
|
-
|
10
|
-
class ElasticBeans::CLI < Thor
|
11
|
-
APPLICATION_DESC = "The name of the Elastic Beanstalk application and CloudFormation stack that contains application settings"
|
12
|
-
|
13
|
-
class_option :verbose, type: :boolean, aliases: %w(-v)
|
14
|
-
|
15
|
-
desc ElasticBeans::Command::Configure::USAGE, ElasticBeans::Command::Configure::DESC
|
16
|
-
long_desc ElasticBeans::Command::Configure::LONG_DESC
|
17
|
-
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
18
|
-
option :network, aliases: %w(-n), required: true, desc: "The name of the CloudFormation stack that contains networking settings"
|
19
|
-
option :database_url, aliases: %w(-d), desc: "The DATABASE_URL for the Rails application"
|
20
|
-
option :image_id, aliases: %w(-i), desc: "A custom AMI to use instead of the default Ruby Elastic Beanstalk AMI"
|
21
|
-
option :instance_type, aliases: %w(-t), desc: "A default instance type to use for all environments instead of c4.large"
|
22
|
-
option :keypair, aliases: %w(-k), desc: "Required on first run. The EC2 keypair to use for Elastic Beanstalk instances"
|
23
|
-
option :logging_endpoint, aliases: %w(-l), desc: "An HTTP endpoint that can receive logs from one-off commands"
|
24
|
-
option :public_key, aliases: %w(-p), desc: "For end-to-end encryption. The public key of the SSL certificate the ELB will verify to communicate with your Rails app"
|
25
|
-
option :secret_key_base, aliases: %w(-b), desc: "The SECRET_KEY_BASE for the Rails application"
|
26
|
-
option :ssl_certificate_arn, aliases: %w(-s), desc: "The ARN of the SSL server certificate stored in IAM to attach to the ELB"
|
27
|
-
def configure
|
28
|
-
@verbose = options[:verbose]
|
29
|
-
ElasticBeans::Command::Configure.new(
|
30
|
-
database_url: options[:database_url],
|
31
|
-
image_id: options[:image_id],
|
32
|
-
instance_type: options[:instance_type],
|
33
|
-
keypair: options[:keypair],
|
34
|
-
logging_endpoint: options[:logging_endpoint],
|
35
|
-
public_key: options[:public_key],
|
36
|
-
secret_key_base: options[:secret_key_base],
|
37
|
-
ssl_certificate_arn: options[:ssl_certificate_arn],
|
38
|
-
application: application(name: options[:application]),
|
39
|
-
network: network(stack_name: options[:network]),
|
40
|
-
elastic_beanstalk: elastic_beanstalk_client,
|
41
|
-
iam: iam_client,
|
42
|
-
ui: ui,
|
43
|
-
).run
|
44
|
-
rescue StandardError => e
|
45
|
-
error(e)
|
46
|
-
end
|
47
|
-
|
48
|
-
desc ElasticBeans::Command::Create::USAGE, ElasticBeans::Command::Create::DESC
|
49
|
-
long_desc ElasticBeans::Command::Create::LONG_DESC
|
50
|
-
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
51
|
-
option :dns, aliases: %w(-d), desc: "A Route53 DNS entry to create or update for a new webserver environment"
|
52
|
-
option :queue, aliases: %w(-q), desc: "The name of the queue a new worker environment should listen to, e.g. `default`"
|
53
|
-
option :tags, type: :hash, default: {}, desc: "EC2 tags to apply to the new environment as a Hash, e.g. `--tags=Environment:development Team:mine`"
|
54
|
-
def create(environment_type)
|
55
|
-
@verbose = options[:verbose]
|
56
|
-
ElasticBeans::Command::Create.new(
|
57
|
-
environment_type: environment_type,
|
58
|
-
dns: options[:dns],
|
59
|
-
queue: options[:queue],
|
60
|
-
tags: options[:tags],
|
61
|
-
application: application(name: options[:application]),
|
62
|
-
elastic_beanstalk: elastic_beanstalk_client,
|
63
|
-
route53: route53_client,
|
64
|
-
s3: s3_client,
|
65
|
-
ui: ui,
|
66
|
-
).run
|
67
|
-
rescue StandardError => e
|
68
|
-
error(e)
|
69
|
-
end
|
70
|
-
|
71
|
-
desc ElasticBeans::Command::Deploy::USAGE, ElasticBeans::Command::Deploy::DESC
|
72
|
-
long_desc ElasticBeans::Command::Deploy::LONG_DESC
|
73
|
-
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
74
|
-
def deploy
|
75
|
-
@verbose = options[:verbose]
|
76
|
-
ElasticBeans::Command::Deploy.new(
|
77
|
-
application: application(
|
78
|
-
name: options[:application],
|
79
|
-
),
|
80
|
-
elastic_beanstalk: elastic_beanstalk_client,
|
81
|
-
s3: s3_client,
|
82
|
-
ui: ui,
|
83
|
-
).run
|
84
|
-
rescue StandardError => e
|
85
|
-
error(e)
|
86
|
-
end
|
87
|
-
|
88
|
-
desc ElasticBeans::Command::Exec::USAGE, ElasticBeans::Command::Exec::DESC
|
89
|
-
long_desc ElasticBeans::Command::Exec::LONG_DESC
|
90
|
-
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
91
|
-
def exec(*command_parts)
|
92
|
-
@verbose = options[:verbose]
|
93
|
-
ElasticBeans::Command::Exec.new(
|
94
|
-
application: application(
|
95
|
-
name: options[:application],
|
96
|
-
),
|
97
|
-
sqs: sqs_client,
|
98
|
-
ui: ui,
|
99
|
-
).run(*command_parts)
|
100
|
-
rescue StandardError => e
|
101
|
-
error(e)
|
102
|
-
end
|
103
|
-
|
104
|
-
desc ElasticBeans::Command::Scale::USAGE, ElasticBeans::Command::Scale::DESC
|
105
|
-
long_desc ElasticBeans::Command::Scale::LONG_DESC
|
106
|
-
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
107
|
-
option :minimum, aliases: %w(-i --min), required: true, desc: "The minimum number of healthy instances to keep"
|
108
|
-
option :maximum, aliases: %w(-m --max), required: true, desc: "The maximum number of healthy instances to keep"
|
109
|
-
option :queue, aliases: %w(-q), desc: "The name of the queue to identify the worker environment to scale, e.g. `default`"
|
110
|
-
def scale(environment_type)
|
111
|
-
@verbose = options[:verbose]
|
112
|
-
ElasticBeans::Command::Scale.new(
|
113
|
-
application: application(
|
114
|
-
name: options[:application],
|
115
|
-
),
|
116
|
-
minimum: options[:minimum],
|
117
|
-
maximum: options[:maximum],
|
118
|
-
queue: options[:queue],
|
119
|
-
elastic_beanstalk: elastic_beanstalk_client,
|
120
|
-
ui: ui,
|
121
|
-
).run(environment_type)
|
122
|
-
rescue StandardError => e
|
123
|
-
error(e)
|
124
|
-
end
|
125
|
-
|
126
|
-
desc ElasticBeans::Command::SetEnv::USAGE, ElasticBeans::Command::SetEnv::DESC
|
127
|
-
long_desc ElasticBeans::Command::SetEnv::LONG_DESC
|
128
|
-
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
129
|
-
def setenv(*env_pairs)
|
130
|
-
@verbose = options[:verbose]
|
131
|
-
ElasticBeans::Command::SetEnv.new(
|
132
|
-
application: application(
|
133
|
-
name: options[:application],
|
134
|
-
),
|
135
|
-
ui: ui,
|
136
|
-
).run(*env_pairs)
|
137
|
-
rescue StandardError => e
|
138
|
-
error(e)
|
139
|
-
end
|
140
|
-
|
141
|
-
desc "talk", ""
|
142
|
-
def talk
|
143
|
-
ElasticBeans::Command::Talk.new(ui: ui).run
|
144
|
-
end
|
145
|
-
|
146
|
-
map %w[--version] => :__print_version
|
147
|
-
desc "--version", "Print the version and exit"
|
148
|
-
def __print_version
|
149
|
-
ElasticBeans::Command::Version.new(ui: ui).run
|
150
|
-
end
|
151
|
-
|
152
|
-
private
|
153
|
-
|
154
|
-
def application(
|
155
|
-
name:,
|
156
|
-
cloudformation: cloudformation_client,
|
157
|
-
elastic_beanstalk: elastic_beanstalk_client,
|
158
|
-
s3: s3_client
|
159
|
-
)
|
160
|
-
@application ||= ElasticBeans::Application.new(
|
161
|
-
name: name,
|
162
|
-
cloudformation: cloudformation,
|
163
|
-
elastic_beanstalk: elastic_beanstalk,
|
164
|
-
s3: s3,
|
165
|
-
)
|
166
|
-
end
|
167
|
-
|
168
|
-
def cloudformation_client
|
169
|
-
::Aws::CloudFormation::Client.new
|
170
|
-
end
|
171
|
-
|
172
|
-
def elastic_beanstalk_client
|
173
|
-
::Aws::ElasticBeanstalk::Client.new
|
174
|
-
end
|
175
|
-
|
176
|
-
def error(e)
|
177
|
-
ui.debug { e.inspect }
|
178
|
-
ui.debug { e.backtrace }
|
179
|
-
|
180
|
-
case e
|
181
|
-
when ElasticBeans::Error
|
182
|
-
ui.error(e.message)
|
183
|
-
when ::Aws::Errors::MissingCredentialsError
|
184
|
-
ui.error("Missing AWS credentials, please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and try again.")
|
185
|
-
else
|
186
|
-
raise e
|
187
|
-
end
|
188
|
-
|
189
|
-
exit 1
|
190
|
-
end
|
191
|
-
|
192
|
-
def iam_client
|
193
|
-
::Aws::IAM::Client.new
|
194
|
-
end
|
195
|
-
|
196
|
-
def network(stack_name:, cloudformation: cloudformation_client)
|
197
|
-
@network ||= ElasticBeans::Network.new(
|
198
|
-
stack_name: stack_name,
|
199
|
-
cloudformation: cloudformation,
|
200
|
-
)
|
201
|
-
end
|
202
|
-
|
203
|
-
def route53_client
|
204
|
-
::Aws::Route53::Client.new
|
205
|
-
end
|
206
|
-
|
207
|
-
def s3_client
|
208
|
-
::Aws::S3::Client.new
|
209
|
-
end
|
210
|
-
|
211
|
-
def sqs_client
|
212
|
-
::Aws::SQS::Client.new
|
213
|
-
end
|
214
|
-
|
215
|
-
def ui
|
216
|
-
ElasticBeans::UI.new(verbose: verbose?)
|
217
|
-
end
|
218
|
-
|
219
|
-
def verbose?
|
220
|
-
@verbose
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.exit_on_failure?
|
224
|
-
true
|
225
|
-
end
|
226
|
-
end
|
3
|
+
require "elastic_beans/cli"
|
227
4
|
|
228
5
|
ElasticBeans::CLI.start(ARGV)
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
require "thor"
|
3
|
+
require "elastic_beans"
|
4
|
+
require "elastic_beans/error"
|
5
|
+
require "elastic_beans/command"
|
6
|
+
require "elastic_beans/ui"
|
7
|
+
|
8
|
+
# :nodoc: all
|
9
|
+
# @!visibility private
|
10
|
+
class ElasticBeans::CLI < Thor
|
11
|
+
APPLICATION_DESC = "The name of the Elastic Beanstalk application and CloudFormation stack that contains application settings"
|
12
|
+
|
13
|
+
class_option :verbose, type: :boolean, aliases: %w(-v)
|
14
|
+
|
15
|
+
desc ElasticBeans::Command::Configure::USAGE, ElasticBeans::Command::Configure::DESC
|
16
|
+
long_desc ElasticBeans::Command::Configure::LONG_DESC
|
17
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
18
|
+
option :network, aliases: %w(-n), required: true, desc: "The name of the CloudFormation stack that contains networking settings"
|
19
|
+
option :database_url, aliases: %w(-d), desc: "The DATABASE_URL for the Rails application"
|
20
|
+
option :image_id, aliases: %w(-i), desc: "A custom AMI to use instead of the default Ruby Elastic Beanstalk AMI"
|
21
|
+
option :instance_type, aliases: %w(-t), desc: "A default instance type to use for all environments instead of c4.large"
|
22
|
+
option :keypair, aliases: %w(-k), desc: "Required on first run. The EC2 keypair to use for Elastic Beanstalk instances"
|
23
|
+
option :logging_endpoint, aliases: %w(-l), desc: "An HTTP endpoint that can receive logs from one-off commands"
|
24
|
+
option :public_key, aliases: %w(-p), desc: "For end-to-end encryption. The public key of the SSL certificate the ELB will verify to communicate with your Rails app"
|
25
|
+
option :secret_key_base, aliases: %w(-b), desc: "The SECRET_KEY_BASE for the Rails application"
|
26
|
+
option :ssl_certificate_arn, aliases: %w(-s), desc: "The ARN of the SSL server certificate stored in IAM to attach to the ELB"
|
27
|
+
def configure
|
28
|
+
@verbose = options[:verbose]
|
29
|
+
ElasticBeans::Command::Configure.new(
|
30
|
+
database_url: options[:database_url],
|
31
|
+
image_id: options[:image_id],
|
32
|
+
instance_type: options[:instance_type],
|
33
|
+
keypair: options[:keypair],
|
34
|
+
logging_endpoint: options[:logging_endpoint],
|
35
|
+
public_key: options[:public_key],
|
36
|
+
secret_key_base: options[:secret_key_base],
|
37
|
+
ssl_certificate_arn: options[:ssl_certificate_arn],
|
38
|
+
application: application(name: options[:application]),
|
39
|
+
network: network(stack_name: options[:network]),
|
40
|
+
elastic_beanstalk: elastic_beanstalk_client,
|
41
|
+
iam: iam_client,
|
42
|
+
ui: ui,
|
43
|
+
).run
|
44
|
+
rescue StandardError => e
|
45
|
+
error(e)
|
46
|
+
end
|
47
|
+
|
48
|
+
desc ElasticBeans::Command::Create::USAGE, ElasticBeans::Command::Create::DESC
|
49
|
+
long_desc ElasticBeans::Command::Create::LONG_DESC
|
50
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
51
|
+
option :dns, aliases: %w(-d), desc: "A Route53 DNS entry to create or update for a new webserver environment"
|
52
|
+
option :queue, aliases: %w(-q), desc: "The name of the queue a new worker environment should listen to, e.g. `default`"
|
53
|
+
option :tags, type: :hash, default: {}, desc: "EC2 tags to apply to the new environment as a Hash, e.g. `--tags=Environment:development Team:mine`"
|
54
|
+
def create(environment_type)
|
55
|
+
@verbose = options[:verbose]
|
56
|
+
ElasticBeans::Command::Create.new(
|
57
|
+
environment_type: environment_type,
|
58
|
+
dns: options[:dns],
|
59
|
+
queue: options[:queue],
|
60
|
+
tags: options[:tags],
|
61
|
+
application: application(name: options[:application]),
|
62
|
+
elastic_beanstalk: elastic_beanstalk_client,
|
63
|
+
route53: route53_client,
|
64
|
+
s3: s3_client,
|
65
|
+
ui: ui,
|
66
|
+
).run
|
67
|
+
rescue StandardError => e
|
68
|
+
error(e)
|
69
|
+
end
|
70
|
+
|
71
|
+
desc ElasticBeans::Command::Deploy::USAGE, ElasticBeans::Command::Deploy::DESC
|
72
|
+
long_desc ElasticBeans::Command::Deploy::LONG_DESC
|
73
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
74
|
+
def deploy
|
75
|
+
@verbose = options[:verbose]
|
76
|
+
ElasticBeans::Command::Deploy.new(
|
77
|
+
application: application(
|
78
|
+
name: options[:application],
|
79
|
+
),
|
80
|
+
elastic_beanstalk: elastic_beanstalk_client,
|
81
|
+
s3: s3_client,
|
82
|
+
ui: ui,
|
83
|
+
).run
|
84
|
+
rescue StandardError => e
|
85
|
+
error(e)
|
86
|
+
end
|
87
|
+
|
88
|
+
desc ElasticBeans::Command::Exec::USAGE, ElasticBeans::Command::Exec::DESC
|
89
|
+
long_desc ElasticBeans::Command::Exec::LONG_DESC
|
90
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
91
|
+
def exec(*command_parts)
|
92
|
+
@verbose = options[:verbose]
|
93
|
+
ElasticBeans::Command::Exec.new(
|
94
|
+
application: application(
|
95
|
+
name: options[:application],
|
96
|
+
),
|
97
|
+
sqs: sqs_client,
|
98
|
+
ui: ui,
|
99
|
+
).run(*command_parts)
|
100
|
+
rescue StandardError => e
|
101
|
+
error(e)
|
102
|
+
end
|
103
|
+
|
104
|
+
desc ElasticBeans::Command::Scale::USAGE, ElasticBeans::Command::Scale::DESC
|
105
|
+
long_desc ElasticBeans::Command::Scale::LONG_DESC
|
106
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
107
|
+
option :minimum, aliases: %w(-i --min), required: true, desc: "The minimum number of healthy instances to keep"
|
108
|
+
option :maximum, aliases: %w(-m --max), required: true, desc: "The maximum number of healthy instances to keep"
|
109
|
+
option :queue, aliases: %w(-q), desc: "The name of the queue to identify the worker environment to scale, e.g. `default`"
|
110
|
+
def scale(environment_type)
|
111
|
+
@verbose = options[:verbose]
|
112
|
+
ElasticBeans::Command::Scale.new(
|
113
|
+
application: application(
|
114
|
+
name: options[:application],
|
115
|
+
),
|
116
|
+
minimum: options[:minimum],
|
117
|
+
maximum: options[:maximum],
|
118
|
+
queue: options[:queue],
|
119
|
+
elastic_beanstalk: elastic_beanstalk_client,
|
120
|
+
ui: ui,
|
121
|
+
).run(environment_type)
|
122
|
+
rescue StandardError => e
|
123
|
+
error(e)
|
124
|
+
end
|
125
|
+
|
126
|
+
desc ElasticBeans::Command::SetEnv::USAGE, ElasticBeans::Command::SetEnv::DESC
|
127
|
+
long_desc ElasticBeans::Command::SetEnv::LONG_DESC
|
128
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
129
|
+
def setenv(*env_pairs)
|
130
|
+
@verbose = options[:verbose]
|
131
|
+
ElasticBeans::Command::SetEnv.new(
|
132
|
+
application: application(
|
133
|
+
name: options[:application],
|
134
|
+
),
|
135
|
+
ui: ui,
|
136
|
+
).run(*env_pairs)
|
137
|
+
rescue StandardError => e
|
138
|
+
error(e)
|
139
|
+
end
|
140
|
+
|
141
|
+
desc "talk", ""
|
142
|
+
def talk
|
143
|
+
ElasticBeans::Command::Talk.new(ui: ui).run
|
144
|
+
end
|
145
|
+
|
146
|
+
map %w[--version] => :__print_version
|
147
|
+
desc "--version", "Print the version and exit"
|
148
|
+
def __print_version
|
149
|
+
ElasticBeans::Command::Version.new(ui: ui).run
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
|
154
|
+
def application(
|
155
|
+
name:,
|
156
|
+
cloudformation: cloudformation_client,
|
157
|
+
elastic_beanstalk: elastic_beanstalk_client,
|
158
|
+
s3: s3_client
|
159
|
+
)
|
160
|
+
@application ||= ElasticBeans::Application.new(
|
161
|
+
name: name,
|
162
|
+
cloudformation: cloudformation,
|
163
|
+
elastic_beanstalk: elastic_beanstalk,
|
164
|
+
s3: s3,
|
165
|
+
)
|
166
|
+
end
|
167
|
+
|
168
|
+
def cloudformation_client
|
169
|
+
::Aws::CloudFormation::Client.new
|
170
|
+
end
|
171
|
+
|
172
|
+
def elastic_beanstalk_client
|
173
|
+
::Aws::ElasticBeanstalk::Client.new
|
174
|
+
end
|
175
|
+
|
176
|
+
def error(e)
|
177
|
+
ui.debug { e.inspect }
|
178
|
+
ui.debug { e.backtrace }
|
179
|
+
|
180
|
+
case e
|
181
|
+
when ElasticBeans::Error
|
182
|
+
ui.error(e.message)
|
183
|
+
when ::Aws::Errors::MissingCredentialsError
|
184
|
+
ui.error("Missing AWS credentials, please set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and try again.")
|
185
|
+
else
|
186
|
+
raise e
|
187
|
+
end
|
188
|
+
|
189
|
+
exit 1
|
190
|
+
end
|
191
|
+
|
192
|
+
def iam_client
|
193
|
+
::Aws::IAM::Client.new
|
194
|
+
end
|
195
|
+
|
196
|
+
def network(stack_name:, cloudformation: cloudformation_client)
|
197
|
+
@network ||= ElasticBeans::Network.new(
|
198
|
+
stack_name: stack_name,
|
199
|
+
cloudformation: cloudformation,
|
200
|
+
)
|
201
|
+
end
|
202
|
+
|
203
|
+
def route53_client
|
204
|
+
::Aws::Route53::Client.new
|
205
|
+
end
|
206
|
+
|
207
|
+
def s3_client
|
208
|
+
::Aws::S3::Client.new
|
209
|
+
end
|
210
|
+
|
211
|
+
def sqs_client
|
212
|
+
::Aws::SQS::Client.new
|
213
|
+
end
|
214
|
+
|
215
|
+
def ui
|
216
|
+
ElasticBeans::UI.new(verbose: verbose?)
|
217
|
+
end
|
218
|
+
|
219
|
+
def verbose?
|
220
|
+
@verbose
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.exit_on_failure?
|
224
|
+
true
|
225
|
+
end
|
226
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "stringio"
|
2
|
+
require "elastic_beans/cli"
|
3
|
+
|
4
|
+
# :nodoc: all
|
5
|
+
# @!visibility private
|
6
|
+
class ElasticBeans::CLI::StringShell < Thor::Shell::Basic
|
7
|
+
attr_reader :stdout, :stderr
|
8
|
+
|
9
|
+
def initialize(*args, stdout: StringIO.new, stderr: StringIO.new)
|
10
|
+
super(*args)
|
11
|
+
@stdout = stdout
|
12
|
+
@stderr = stderr
|
13
|
+
end
|
14
|
+
end
|
@@ -52,7 +52,8 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
52
52
|
raise EnvironmentsNotReady.new(environments: unready_environments)
|
53
53
|
end
|
54
54
|
|
55
|
-
|
55
|
+
config_templates = 4 + application.worker_queues.size
|
56
|
+
progressbar = ProgressBar.create(title: "Configuring", total: config_templates, output: ui.stdout)
|
56
57
|
progressbar.log("Updating configuration templates in #{application.name}...")
|
57
58
|
progressbar.log("Updating base configuration template...")
|
58
59
|
base_config = ElasticBeans::ConfigurationTemplate::Base.new(
|
@@ -135,26 +136,30 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
135
136
|
)
|
136
137
|
progressbar.increment
|
137
138
|
end
|
139
|
+
progressbar.finish
|
138
140
|
|
139
|
-
|
140
|
-
progressbar.
|
141
|
-
|
142
|
-
environment.
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
if environments.any?
|
142
|
+
progressbar = ProgressBar.create(title: "Updating", total: nil, output: ui.stdout)
|
143
|
+
threads = environments.map { |environment|
|
144
|
+
progressbar.log("Updating `#{environment.name}'...")
|
145
|
+
thread = Thread.new do
|
146
|
+
environment.update_configuration
|
147
|
+
end
|
148
|
+
progressbar.increment
|
149
|
+
thread
|
150
|
+
}
|
147
151
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
152
|
+
loop do
|
153
|
+
sleep 0.5
|
154
|
+
progressbar.increment
|
155
|
+
if threads.none?(&:alive?)
|
156
|
+
progressbar.total = progressbar.progress
|
157
|
+
break
|
158
|
+
end
|
154
159
|
end
|
155
|
-
end
|
156
160
|
|
157
|
-
|
161
|
+
threads.each(&:join)
|
162
|
+
end
|
158
163
|
end
|
159
164
|
|
160
165
|
private
|
@@ -28,7 +28,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
28
28
|
end
|
29
29
|
|
30
30
|
ui.debug { "Creating application version from code at #{Dir.pwd}..." }
|
31
|
-
progressbar = ProgressBar.create(title: "
|
31
|
+
progressbar = ProgressBar.create(title: "Uploading", total: nil, output: ui.stdout)
|
32
32
|
version = nil
|
33
33
|
version_thread = Thread.new do
|
34
34
|
version = ElasticBeans::ApplicationVersion.create(
|
@@ -40,7 +40,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
40
40
|
end
|
41
41
|
|
42
42
|
loop do
|
43
|
-
sleep
|
43
|
+
sleep 0.5
|
44
44
|
progressbar.increment
|
45
45
|
if !version_thread.alive?
|
46
46
|
break
|
@@ -49,6 +49,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
49
49
|
version_thread.join
|
50
50
|
|
51
51
|
progressbar.log("Deploying version #{version} to #{application.name}...")
|
52
|
+
progressbar.title = "Deploying"
|
52
53
|
deploy_threads = environments.map { |environment|
|
53
54
|
progressbar.log("Deploying version '#{version}' to environment `#{environment.name}'...")
|
54
55
|
thread = Thread.new do
|
@@ -59,7 +60,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
59
60
|
}
|
60
61
|
|
61
62
|
loop do
|
62
|
-
sleep
|
63
|
+
sleep 0.5
|
63
64
|
progressbar.increment
|
64
65
|
if deploy_threads.none?(&:alive?)
|
65
66
|
progressbar.total = progressbar.progress
|
@@ -172,14 +172,19 @@ module ElasticBeans
|
|
172
172
|
end
|
173
173
|
|
174
174
|
def message
|
175
|
-
require "elastic_beans/
|
175
|
+
require "elastic_beans/cli"
|
176
|
+
require "elastic_beans/cli/string_shell"
|
176
177
|
msg = <<-MESSAGE
|
177
178
|
Some configuration is missing and must be set before creating or updating an environment.
|
178
179
|
MESSAGE
|
179
180
|
if nested
|
180
181
|
msg << "The error from AWS was \"#{nested.message}\"\n#{msg}\n"
|
181
182
|
else
|
182
|
-
msg <<
|
183
|
+
msg << <<-MESSAGE
|
184
|
+
Please re-run `#{command_as_string "configure"}`.
|
185
|
+
|
186
|
+
#{command_help "configure"}"
|
187
|
+
MESSAGE
|
183
188
|
end
|
184
189
|
msg
|
185
190
|
end
|
@@ -61,7 +61,11 @@ module ElasticBeans
|
|
61
61
|
database_url_setting = template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "DATABASE_URL", override: database_url)
|
62
62
|
secret_key_base_setting = template_option_setting(namespace: "aws:elasticbeanstalk:application:environment", option_name: "SECRET_KEY_BASE", override: secret_key_base)
|
63
63
|
if database_url_setting[:value].nil? || secret_key_base_setting[:value].nil? || keypair_setting[:value].nil?
|
64
|
-
raise
|
64
|
+
raise MissingOptionsError.new(
|
65
|
+
database_url: database_url_setting[:value],
|
66
|
+
secret_key_base: secret_key_base_setting[:value],
|
67
|
+
keypair: keypair_setting[:value],
|
68
|
+
)
|
65
69
|
end
|
66
70
|
|
67
71
|
config_path = "#{application.bucket_name}/#{application.env_vars.s3_key}"
|
@@ -143,6 +147,38 @@ module ElasticBeans
|
|
143
147
|
" http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/AWSHowTo.iam.html"
|
144
148
|
end
|
145
149
|
end
|
150
|
+
|
151
|
+
# :nodoc: all
|
152
|
+
# @!visibility private
|
153
|
+
class MissingOptionsError < ElasticBeans::Error
|
154
|
+
def initialize(database_url:, secret_key_base:, keypair:)
|
155
|
+
@database_url = database_url
|
156
|
+
@secret_key_base = secret_key_base
|
157
|
+
@keypair = keypair
|
158
|
+
end
|
159
|
+
|
160
|
+
def message
|
161
|
+
require "elastic_beans/cli"
|
162
|
+
require "elastic_beans/cli/string_shell"
|
163
|
+
msg = "Some required options are missing and must be set when configuring an application:\n\n"
|
164
|
+
if @database_url.nil?
|
165
|
+
msg << "--database-url DATABASE_URL must point to a valid database, and is required for running a Rails application\n"
|
166
|
+
end
|
167
|
+
if @keypair.nil?
|
168
|
+
msg << "--keypair KEYPAIR must be a valid EC2 key pair, and will be used on Elastic Beanstalk instances\n"
|
169
|
+
end
|
170
|
+
if @secret_key_base.nil?
|
171
|
+
msg << "--secret-key-base SECRET_KEY_BASE can be any value, and is required for running a Rails application\n"
|
172
|
+
end
|
173
|
+
msg << <<-MESSAGE
|
174
|
+
|
175
|
+
Please re-run `#{command_as_string "configure"}` with these options.
|
176
|
+
|
177
|
+
#{command_help "configure"}
|
178
|
+
MESSAGE
|
179
|
+
msg
|
180
|
+
end
|
181
|
+
end
|
146
182
|
end
|
147
183
|
end
|
148
184
|
end
|
@@ -50,12 +50,13 @@ module ElasticBeans
|
|
50
50
|
# @!visibility private
|
51
51
|
class NoEncryptionSettingsError < ElasticBeans::Error
|
52
52
|
def message
|
53
|
-
require "elastic_beans/
|
53
|
+
require "elastic_beans/cli"
|
54
|
+
require "elastic_beans/cli/string_shell"
|
54
55
|
<<-MESSAGE
|
55
56
|
Missing required end-to-end encryption settings.
|
56
57
|
Please re-run `#{command_as_string "configure"}` and make sure to specify SSL certificate ARN and internal public key.
|
57
58
|
|
58
|
-
#{
|
59
|
+
#{command_help "configure"}
|
59
60
|
MESSAGE
|
60
61
|
end
|
61
62
|
end
|
@@ -260,7 +260,7 @@ module ElasticBeans
|
|
260
260
|
status = wait_status[0]
|
261
261
|
health = "Grey"
|
262
262
|
health_status = wait_health_status[0]
|
263
|
-
Timeout.timeout(
|
263
|
+
Timeout.timeout(3600) do
|
264
264
|
while wait_status.include?(status) || wait_health_status.include?(health_status)
|
265
265
|
sleep 5
|
266
266
|
environment = environment_description
|
@@ -302,12 +302,13 @@ module ElasticBeans
|
|
302
302
|
# @!visibility private
|
303
303
|
class MissingConfigurationError < ElasticBeans::Error
|
304
304
|
def message
|
305
|
-
require "elastic_beans/
|
305
|
+
require "elastic_beans/cli"
|
306
|
+
require "elastic_beans/cli/string_shell"
|
306
307
|
<<-MESSAGE
|
307
308
|
Some configuration is missing and must be set before creating an environment.
|
308
309
|
Please re-run `#{command_as_string "configure"}`.
|
309
310
|
|
310
|
-
#{
|
311
|
+
#{command_help "configure"}
|
311
312
|
MESSAGE
|
312
313
|
end
|
313
314
|
end
|
data/lib/elastic_beans/error.rb
CHANGED
@@ -12,5 +12,14 @@ module ElasticBeans
|
|
12
12
|
|
13
13
|
"beans #{args}"
|
14
14
|
end
|
15
|
+
|
16
|
+
def command_help(command)
|
17
|
+
require "elastic_beans/cli"
|
18
|
+
require "elastic_beans/cli/string_shell"
|
19
|
+
|
20
|
+
shell = ElasticBeans::CLI::StringShell.new
|
21
|
+
ElasticBeans::CLI.command_help(shell, command)
|
22
|
+
shell.stdout.string
|
23
|
+
end
|
15
24
|
end
|
16
25
|
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.
|
4
|
+
version: 0.4.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
|
+
date: 2016-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -160,6 +160,8 @@ files:
|
|
160
160
|
- lib/elastic_beans/application.rb
|
161
161
|
- lib/elastic_beans/application_version.rb
|
162
162
|
- lib/elastic_beans/aws/cloudformation_stack.rb
|
163
|
+
- lib/elastic_beans/cli.rb
|
164
|
+
- lib/elastic_beans/cli/string_shell.rb
|
163
165
|
- lib/elastic_beans/command.rb
|
164
166
|
- lib/elastic_beans/command/configure.rb
|
165
167
|
- lib/elastic_beans/command/create.rb
|