elastic_beans 0.3.0 → 0.4.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 +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
|