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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2b231170798c366604081d7d0800c0c332a386d6
4
- data.tar.gz: 661c9aca9b2ae4fdc6402cd02c5b3d37c4f62d76
3
+ metadata.gz: 661efbe2cb8fd10a68a49a3ebc7899ec3b30b61a
4
+ data.tar.gz: 6dee6beefb1f0dcd55f5cf7c8f7f73898c9e1432
5
5
  SHA512:
6
- metadata.gz: 71da843ae45cfac1cf6fa2061df76383849d16cdb359c1ff7145975c25042ca8985d7501b2e57d09d2968d4b8b0246cf40f89ef73d98b6a165b4cb15ae17f8fa
7
- data.tar.gz: 928d9e71798950eb693d0a9ad4a9ac720ca48e56de71b8cf074d0fd409e2c957119d2dd83fcc6dd8b757ef122e08bda185ff25fad6dacddedcf5db7d327bbfb0
6
+ metadata.gz: 63dc0a28f1482b67a2d96fa6edefd65f768acbbe377357acec498bc7b34dafe9242f7ef4c365c82c15d24c80ea6e81a5d6c41cc92e85d3c39002cc969e2f04fc
7
+ data.tar.gz: ca7b8ffd98f6218a0bb935aea9bfce0cf3d3e804467a709e20d9d0adf83f313ba606ff9057aebffdb2e7dbf80d42e360f2689f0bdc6cc07f8ac5f0ddc6e2de84
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /.elasticbeanstalk
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 "aws-sdk"
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
- progressbar = ProgressBar.create(title: "Configuring", total: nil, output: ui.stdout)
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
- threads = environments.map { |environment|
140
- progressbar.log("Updating `#{environment.name}'...")
141
- thread = Thread.new do
142
- environment.update_configuration
143
- end
144
- progressbar.increment
145
- thread
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
- loop do
149
- sleep 1
150
- progressbar.increment
151
- if threads.none?(&:alive?)
152
- progressbar.total = progressbar.progress
153
- break
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
- threads.each(&:join)
161
+ threads.each(&:join)
162
+ end
158
163
  end
159
164
 
160
165
  private
@@ -76,7 +76,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
76
76
  end
77
77
 
78
78
  loop do
79
- sleep 1
79
+ sleep 0.5
80
80
  progressbar.increment
81
81
  if !environment_thread.alive? && !dns_thread.alive?
82
82
  progressbar.total = progressbar.progress
@@ -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: "Deploying", total: nil, output: ui.stdout)
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 1
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 1
63
+ sleep 0.5
63
64
  progressbar.increment
64
65
  if deploy_threads.none?(&:alive?)
65
66
  progressbar.total = progressbar.progress
@@ -48,7 +48,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
48
48
  }
49
49
 
50
50
  loop do
51
- sleep 1
51
+ sleep 0.5
52
52
  progressbar.increment
53
53
  if threads.none?(&:alive?)
54
54
  progressbar.total = progressbar.progress
@@ -172,14 +172,19 @@ module ElasticBeans
172
172
  end
173
173
 
174
174
  def message
175
- require "elastic_beans/command/configure"
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 << "Please re-run `#{command_as_string "configure"}`.\n\n#{`#{$0} help configure`}"
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 MissingConfigurationError
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/command/configure"
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
- #{`#{$0} help configure`}
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(1800) do
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/command/configure"
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
- #{`#{$0} help configure`}
311
+ #{command_help "configure"}
311
312
  MESSAGE
312
313
  end
313
314
  end
@@ -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
@@ -14,7 +14,7 @@ class Init
14
14
  def self.run(command)
15
15
  init = new
16
16
  unless init.respond_to?(command)
17
- abort "Usage: $0 {start}"
17
+ abort "Usage: #{$0} {start}"
18
18
  end
19
19
  init.send(command)
20
20
  end
@@ -1,3 +1,3 @@
1
1
  module ElasticBeans
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic_beans
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.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-15 00:00:00.000000000 Z
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