elastic_beans 0.10.0.alpha1 → 0.10.0.alpha2
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/.circleci/config.yml +20 -0
- data/elastic_beans.gemspec +1 -1
- data/lib/elastic_beans/application.rb +55 -31
- data/lib/elastic_beans/aws/cloudformation_stack.rb +3 -0
- data/lib/elastic_beans/cli.rb +15 -0
- data/lib/elastic_beans/command/exec.rb +3 -2
- data/lib/elastic_beans/command/kill.rb +38 -0
- data/lib/elastic_beans/command/ps.rb +5 -13
- data/lib/elastic_beans/command.rb +1 -0
- data/lib/elastic_beans/env_vars.rb +2 -15
- data/lib/elastic_beans/error/access_denied.rb +38 -0
- data/lib/elastic_beans/exec/sqs_consumer.rb +56 -1
- data/lib/elastic_beans/version.rb +1 -1
- metadata +7 -5
- data/circle.yml +0 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c681be8f1584e92ac3326f36602a6f006739fae
|
4
|
+
data.tar.gz: 2d7efd88e9401d2c8ff327f15992de92ba94323d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03076cb44db365dcf4d20fdfe45aad0a1d845b9ad346fdb8b6074be7073045c4f94fe411e637aafd965ddce9bf54dbd03cde18f1e675d89ce75fbde5be9e462d
|
7
|
+
data.tar.gz: fefcc5407eb3a0f5a19e317b85fb1f6c2aa0453d5ad1513648a5260fb3e01b9b55e17489641e2a9e0f63b8da6544f15f6825c16ba07bc52eab1aa2c1e77fc8bc
|
@@ -0,0 +1,20 @@
|
|
1
|
+
version: 2
|
2
|
+
jobs:
|
3
|
+
build:
|
4
|
+
docker:
|
5
|
+
- image: ruby:latest
|
6
|
+
working_directory: /elastic_beans
|
7
|
+
steps:
|
8
|
+
- checkout
|
9
|
+
- run:
|
10
|
+
name: Configure git
|
11
|
+
command: |
|
12
|
+
git config --global user.name "CircleCI"
|
13
|
+
git config --global user.email "ops-ro@onemedical.com"
|
14
|
+
- run: bundle install --jobs=4 --retry=3
|
15
|
+
- run:
|
16
|
+
command: bundle exec rake
|
17
|
+
environment:
|
18
|
+
SPEC_OPTS: --format progress --format RspecJunitFormatter -o tmp/test_results/rspec/junit.xml
|
19
|
+
- store_test_results:
|
20
|
+
path: tmp/test_results/
|
data/elastic_beans.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency "ruby-progressbar", "~> 1.2"
|
26
26
|
spec.add_dependency "rubyzip", "~> 1.2"
|
27
27
|
spec.add_dependency "thor", "~> 0.19.0"
|
28
|
-
spec.add_dependency "tty-table", "~> 0.
|
28
|
+
spec.add_dependency "tty-table", "~> 0.8.0"
|
29
29
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 1.12"
|
31
31
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -3,6 +3,7 @@ require "timeout"
|
|
3
3
|
require "aws-sdk"
|
4
4
|
require "elastic_beans/aws/cloudformation_stack"
|
5
5
|
require "elastic_beans/error"
|
6
|
+
require "elastic_beans/error/access_denied"
|
6
7
|
|
7
8
|
module ElasticBeans
|
8
9
|
# An Elastic Beanstalk application which should exist.
|
@@ -42,7 +43,7 @@ module ElasticBeans
|
|
42
43
|
response = elastic_beanstalk.describe_applications(application_names: [name])
|
43
44
|
application = response.applications[0]
|
44
45
|
unless application
|
45
|
-
raise MissingApplicationError
|
46
|
+
raise MissingApplicationError.new(application: self)
|
46
47
|
end
|
47
48
|
|
48
49
|
templates = application.configuration_templates
|
@@ -61,7 +62,7 @@ module ElasticBeans
|
|
61
62
|
# Returns the ElasticBeans::EnvVars for this application.
|
62
63
|
def env_vars
|
63
64
|
unless exists?
|
64
|
-
raise MissingApplicationError
|
65
|
+
raise MissingApplicationError.new(application: self)
|
65
66
|
end
|
66
67
|
|
67
68
|
EnvVars.new(application: self, s3: s3)
|
@@ -96,6 +97,8 @@ module ElasticBeans
|
|
96
97
|
raise MissingBucketError
|
97
98
|
end
|
98
99
|
@bucket_name = bucket.name
|
100
|
+
rescue ::Aws::S3::Errors::AccessDenied
|
101
|
+
raise AccessDeniedS3Error.new
|
99
102
|
end
|
100
103
|
|
101
104
|
# Enqueues a one-off Exec::Command to be run on the application's +exec+ environment.
|
@@ -112,45 +115,31 @@ module ElasticBeans
|
|
112
115
|
end
|
113
116
|
command.metadata[:bucket] = bucket_name
|
114
117
|
command.metadata[:key] = "#{command_key_prefix}#{command.id}.json"
|
118
|
+
s3.put_object(
|
119
|
+
bucket: bucket_name,
|
120
|
+
key: command.metadata[:key],
|
121
|
+
body: command.to_json,
|
122
|
+
)
|
115
123
|
|
116
124
|
sqs.send_message(
|
117
125
|
queue_url: exec_queue_url,
|
118
126
|
message_body: command.to_json,
|
119
127
|
)
|
128
|
+
rescue ::Aws::S3::Errors::AccessDenied
|
129
|
+
raise AccessDeniedS3Error.new(bucket: bucket_name, key: command.metadata[:key])
|
120
130
|
end
|
121
131
|
|
122
|
-
# Fetches
|
123
|
-
#
|
124
|
-
#
|
125
|
-
#
|
132
|
+
# Fetches up to 100 previously-enqueued commands that are running or scheduled to run.
|
133
|
+
# Commands are deserialized from metadata files in a well-known location in S3.
|
134
|
+
# The metadata is created when the command is enqueued.
|
135
|
+
# The instances in the exec environment update the metadata when executing a command, and remove the metadata when they are done.
|
126
136
|
#
|
127
|
-
# Raises an error if the
|
137
|
+
# Raises an error if the application does not exist.
|
128
138
|
def enqueued_commands
|
129
|
-
|
130
|
-
|
131
|
-
loop do
|
132
|
-
messages += sqs.receive_message(
|
133
|
-
queue_url: exec_queue_url,
|
134
|
-
max_number_of_messages: 10,
|
135
|
-
visibility_timeout: 5,
|
136
|
-
wait_time_seconds: 5,
|
137
|
-
).messages
|
138
|
-
end
|
139
|
+
unless exists?
|
140
|
+
raise MissingApplicationError.new(application: self)
|
139
141
|
end
|
140
|
-
rescue Timeout::Error
|
141
|
-
messages.map { |msg| Exec::Command.from_json(msg.body) }
|
142
|
-
end
|
143
142
|
|
144
|
-
def exec_queue_url
|
145
|
-
stack.stack_output("ExecQueueUrl")
|
146
|
-
end
|
147
|
-
|
148
|
-
# Fetches commands running in the Environment::Exec environment.
|
149
|
-
# Commands are deserialized from metadata files in a well-known location in S3.
|
150
|
-
# The instances update the metadata when executing a command, and remove the metadata when they are done.
|
151
|
-
#
|
152
|
-
# Raises an error if the exec environment cannot be found.
|
153
|
-
def running_commands
|
154
143
|
# Ignoring truncation for simplicity; >100 commands will just have to suffer.
|
155
144
|
objects = s3.list_objects_v2(
|
156
145
|
bucket: bucket_name,
|
@@ -168,6 +157,36 @@ module ElasticBeans
|
|
168
157
|
}
|
169
158
|
end
|
170
159
|
|
160
|
+
# Fetches the +ExecQueueUrl+ Output from the application CloudFormation stack.
|
161
|
+
# The stack must have the same name as the application.
|
162
|
+
def exec_queue_url
|
163
|
+
stack.stack_output("ExecQueueUrl")
|
164
|
+
end
|
165
|
+
|
166
|
+
# Schedules the given ElasticBeans::Exec::Command or +id+ for termination.
|
167
|
+
# Removes the metadata for the command and relies on the SQSConsumer to terminate it.
|
168
|
+
#
|
169
|
+
# Raises an error if the application does not exist.
|
170
|
+
def kill_command(command_or_id)
|
171
|
+
unless exists?
|
172
|
+
raise MissingApplicationError.new(application: self)
|
173
|
+
end
|
174
|
+
|
175
|
+
if command_or_id.is_a?(ElasticBeans::Exec::Command)
|
176
|
+
command_id = command_or_id.id
|
177
|
+
else
|
178
|
+
command_id = command_or_id
|
179
|
+
end
|
180
|
+
|
181
|
+
key = "#{command_key_prefix}#{command_id}.json"
|
182
|
+
s3.delete_object(
|
183
|
+
bucket: bucket_name,
|
184
|
+
key: key,
|
185
|
+
)
|
186
|
+
rescue ::Aws::S3::Errors::AccessDenied
|
187
|
+
raise AccessDeniedS3Error.new(bucket: bucket_name, key: key)
|
188
|
+
end
|
189
|
+
|
171
190
|
# Returns an ElasticBeans::ApplicationVersion for each version of the Elastic Beanstalk application.
|
172
191
|
def versions
|
173
192
|
response = elastic_beanstalk.describe_application_versions(application_name: name)
|
@@ -199,6 +218,7 @@ module ElasticBeans
|
|
199
218
|
|
200
219
|
attr_reader :elastic_beanstalk, :s3, :stack
|
201
220
|
|
221
|
+
# Returns the S3 prefix under which command metadata is stored.
|
202
222
|
def command_key_prefix
|
203
223
|
@command_key_prefix ||= "#{name}/exec/command/"
|
204
224
|
end
|
@@ -217,8 +237,12 @@ module ElasticBeans
|
|
217
237
|
# :nodoc: all
|
218
238
|
# @!visibility private
|
219
239
|
class MissingApplicationError < ElasticBeans::Error
|
240
|
+
def initialize(application:)
|
241
|
+
@application = application
|
242
|
+
end
|
243
|
+
|
220
244
|
def message
|
221
|
-
"Application `#{@
|
245
|
+
"Application `#{@application.name}' does not exist. Please create the Elastic Beanstalk application using a CloudFormation stack."
|
222
246
|
end
|
223
247
|
end
|
224
248
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "aws-sdk"
|
2
2
|
require "elastic_beans/error"
|
3
|
+
require "elastic_beans/error/access_denied"
|
3
4
|
|
4
5
|
module ElasticBeans
|
5
6
|
# :nodoc: all
|
@@ -39,6 +40,8 @@ module ElasticBeans
|
|
39
40
|
s
|
40
41
|
rescue ::Aws::CloudFormation::Errors::ValidationError
|
41
42
|
raise MissingStackError.new(stack_name: stack_name)
|
43
|
+
rescue ::Aws::CloudFormation::Errors::AccessDenied
|
44
|
+
raise AccessDeniedCloudFormationError.new(stack_name: stack_name)
|
42
45
|
end
|
43
46
|
|
44
47
|
class MissingStackError < ElasticBeans::Error
|
data/lib/elastic_beans/cli.rb
CHANGED
@@ -98,6 +98,21 @@ class ElasticBeans::CLI < Thor
|
|
98
98
|
error(e)
|
99
99
|
end
|
100
100
|
|
101
|
+
desc ElasticBeans::Command::Kill::USAGE, ElasticBeans::Command::Kill::DESC
|
102
|
+
long_desc ElasticBeans::Command::Kill::LONG_DESC
|
103
|
+
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
104
|
+
def kill(command_id)
|
105
|
+
@verbose = options[:verbose]
|
106
|
+
ElasticBeans::Command::Kill.new(
|
107
|
+
application: application(
|
108
|
+
name: options[:application],
|
109
|
+
),
|
110
|
+
ui: ui,
|
111
|
+
).run(command_id)
|
112
|
+
rescue StandardError => e
|
113
|
+
error(e)
|
114
|
+
end
|
115
|
+
|
101
116
|
desc ElasticBeans::Command::Ps::USAGE, ElasticBeans::Command::Ps::DESC
|
102
117
|
long_desc ElasticBeans::Command::Ps::LONG_DESC
|
103
118
|
option :application, aliases: %w(-a), required: true, desc: APPLICATION_DESC
|
@@ -21,8 +21,9 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def run(*command_parts)
|
24
|
-
|
25
|
-
application.
|
24
|
+
command = command(command_parts)
|
25
|
+
ui.info("Running `#{command.command_string}' on #{application.name}... (ID=#{command.id})")
|
26
|
+
application.enqueue_command(command)
|
26
27
|
end
|
27
28
|
|
28
29
|
private
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
require "elastic_beans/error/access_denied"
|
3
|
+
|
4
|
+
module ElasticBeans
|
5
|
+
module Command
|
6
|
+
# :nodoc: all
|
7
|
+
class Kill
|
8
|
+
USAGE = "kill COMMAND_ID"
|
9
|
+
DESC = "Kill a running command or cancel a scheduled command that was enqueued with `exec`"
|
10
|
+
LONG_DESC = <<-LONG_DESC
|
11
|
+
Kill a running command or cancel a scheduled command that was enqueued with `exec`.
|
12
|
+
You can find an enqueued command's ID by running `ps`.
|
13
|
+
|
14
|
+
Commands are run in an "exec" environment, separate from your webserver or worker environments.
|
15
|
+
When they are enqueued, metadata is created in S3 and removed when the command is complete.
|
16
|
+
Removing that metadata cancels the command.
|
17
|
+
The command is sent a SIGTERM, and then a SIGKILL if it has not yet died.
|
18
|
+
|
19
|
+
Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.
|
20
|
+
LONG_DESC
|
21
|
+
|
22
|
+
def initialize(application:, ui:)
|
23
|
+
@application = application
|
24
|
+
@ui = ui
|
25
|
+
end
|
26
|
+
|
27
|
+
def run(command_id)
|
28
|
+
ui.info("Scheduling command '#{command_id}' on #{application.name} for termination...")
|
29
|
+
application.kill_command(command_id)
|
30
|
+
ui.info("It may be a few moments before the command terminates.")
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :application, :ui
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -12,6 +12,7 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
12
12
|
LONG_DESC
|
13
13
|
|
14
14
|
COLUMNS = {
|
15
|
+
"COMMAND ID" => ->(command) { command.id },
|
15
16
|
"INSTANCE" => ->(command) { command.instance_id || SCHEDULED_INSTANCE },
|
16
17
|
"RUN TIME" => ->(command) {
|
17
18
|
if command.start_time
|
@@ -34,23 +35,14 @@ Requires AWS credentials to be set in the environment, i.e. AWS_ACCESS_KEY_ID an
|
|
34
35
|
end
|
35
36
|
|
36
37
|
def run
|
37
|
-
|
38
|
-
|
39
|
-
ui.debug { "Fetching enqueued and running commands from #{application.name}..." }
|
40
|
-
threads = [
|
41
|
-
Thread.new do
|
42
|
-
enqueued_commands = application.enqueued_commands
|
43
|
-
end,
|
44
|
-
Thread.new do
|
45
|
-
running_commands = application.running_commands
|
46
|
-
end,
|
47
|
-
]
|
48
|
-
threads.each(&:join)
|
38
|
+
ui.debug { "Fetching enqueued commands from #{application.name}..." }
|
39
|
+
enqueued_commands = application.enqueued_commands
|
49
40
|
|
41
|
+
enqueued_commands, running_commands = enqueued_commands.partition { |cmd| cmd.start_time.nil? }
|
50
42
|
running_commands.sort_by!(&:start_time)
|
51
43
|
commands = running_commands + enqueued_commands
|
52
44
|
if commands.any?
|
53
|
-
ui.table(level: :info, columns: COLUMNS, rows:
|
45
|
+
ui.table(level: :info, columns: COLUMNS, rows: commands)
|
54
46
|
else
|
55
47
|
ui.info("No commands enqueued or running")
|
56
48
|
end
|
@@ -2,6 +2,7 @@ require "elastic_beans/command/configure"
|
|
2
2
|
require "elastic_beans/command/create"
|
3
3
|
require "elastic_beans/command/deploy"
|
4
4
|
require "elastic_beans/command/exec"
|
5
|
+
require "elastic_beans/command/kill"
|
5
6
|
require "elastic_beans/command/ps"
|
6
7
|
require "elastic_beans/command/restart"
|
7
8
|
require "elastic_beans/command/scale"
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "json"
|
2
2
|
require "aws-sdk"
|
3
3
|
require "elastic_beans/error"
|
4
|
+
require "elastic_beans/error/access_denied"
|
4
5
|
|
5
6
|
module ElasticBeans
|
6
7
|
# Interfaces with environment variable storage for the Elastic Beanstalk application.
|
@@ -24,7 +25,7 @@ module ElasticBeans
|
|
24
25
|
rescue ::Aws::S3::Errors::NotFound
|
25
26
|
{}
|
26
27
|
rescue ::Aws::S3::Errors::Forbidden
|
27
|
-
raise
|
28
|
+
raise AccessDeniedS3Error.new(bucket: application.bucket_name, key: s3_key)
|
28
29
|
end
|
29
30
|
|
30
31
|
# Updates the environment variables stored in S3 by merging it with the given +env_hash+.
|
@@ -51,19 +52,5 @@ module ElasticBeans
|
|
51
52
|
def env_script(env_hash)
|
52
53
|
JSON.dump(env_hash)
|
53
54
|
end
|
54
|
-
|
55
|
-
# :nodoc: all
|
56
|
-
# @!visibility private
|
57
|
-
class CannotAccessConfigError < ElasticBeans::Error
|
58
|
-
def initialize(bucket_name:, key:)
|
59
|
-
@bucket_name = bucket_name
|
60
|
-
@key = key
|
61
|
-
end
|
62
|
-
|
63
|
-
def message
|
64
|
-
"Cannot access configuration stored in S3 with bucket `#{@bucket_name}' and key `#{@key}'." \
|
65
|
-
" Please ask an administrator of your AWS account administrator to give you access."
|
66
|
-
end
|
67
|
-
end
|
68
55
|
end
|
69
56
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "elastic_beans/error"
|
2
|
+
|
3
|
+
# :nodoc: all
|
4
|
+
# @!visibility private
|
5
|
+
class AccessDeniedCloudFormationError < ElasticBeans::Error
|
6
|
+
def initialize(stack_name:)
|
7
|
+
@stack_name = stack_name
|
8
|
+
end
|
9
|
+
|
10
|
+
def message
|
11
|
+
<<-MESSAGE
|
12
|
+
Access to CloudFormation stack '#{@stack_name}' was denied.
|
13
|
+
|
14
|
+
Please check with your AWS administrator to give you full permission to access that stack in CloudFormation.
|
15
|
+
MESSAGE
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# :nodoc: all
|
20
|
+
# @!visibility private
|
21
|
+
class AccessDeniedS3Error < ElasticBeans::Error
|
22
|
+
def initialize(bucket: nil, key: nil)
|
23
|
+
@bucket = bucket
|
24
|
+
@key = key
|
25
|
+
end
|
26
|
+
|
27
|
+
def message
|
28
|
+
msg = ""
|
29
|
+
if @bucket || @key
|
30
|
+
msg << "Access to bucket '#{@bucket}' key '#{@key}' was denied.\n"
|
31
|
+
else
|
32
|
+
msg << "Access to S3 was denied.\n"
|
33
|
+
end
|
34
|
+
msg + <<-MESSAGE
|
35
|
+
Please check with your AWS administrator to give you full permission to access elastic_beans resources in S3.
|
36
|
+
MESSAGE
|
37
|
+
end
|
38
|
+
end
|
@@ -6,6 +6,8 @@ require "time"
|
|
6
6
|
# :nodoc: all
|
7
7
|
# @!visibility private
|
8
8
|
class SQSConsumer
|
9
|
+
LOOP_PERIOD = 1
|
10
|
+
|
9
11
|
def initialize(instance_id:, logdir:, queue_url:, s3:, sqs:)
|
10
12
|
@instance_id = instance_id
|
11
13
|
@logdir = logdir
|
@@ -23,9 +25,15 @@ class SQSConsumer
|
|
23
25
|
log("Starting message receive loop")
|
24
26
|
loop do
|
25
27
|
begin
|
26
|
-
sleep
|
28
|
+
sleep(LOOP_PERIOD)
|
27
29
|
if (message = receive_message)
|
28
30
|
command = command_from_message(message)
|
31
|
+
unless metadata_exists?(command: command)
|
32
|
+
delete_message(message)
|
33
|
+
log_command("Skipping command ID=#{command['id']} `#{command['command']}' because it was killed")
|
34
|
+
next
|
35
|
+
end
|
36
|
+
|
29
37
|
log_command("Executing command ID=#{command['id']} `#{command['command']}' on host #{`hostname`.chomp} pid #{command_pid}...")
|
30
38
|
start_time = Time.now
|
31
39
|
@command_pid = Process.spawn(
|
@@ -35,10 +43,38 @@ class SQSConsumer
|
|
35
43
|
)
|
36
44
|
delete_message(message)
|
37
45
|
update_metadata(command: command, start_time: start_time)
|
46
|
+
|
47
|
+
# poll command metadata to see if it is still available, if it disappears then kill the process
|
48
|
+
killed_thread = Thread.new do
|
49
|
+
loop do
|
50
|
+
sleep 5
|
51
|
+
|
52
|
+
if !metadata_exists?(command: command)
|
53
|
+
if already_killed?
|
54
|
+
log_command(
|
55
|
+
"Sending KILL signal to command ID=#{command['id']} `#{command['command']}' on host #{`hostname`.chomp} pid #{command_pid}" \
|
56
|
+
" because it was killed and has not terminated yet"
|
57
|
+
)
|
58
|
+
Process.kill("KILL", command_pid)
|
59
|
+
break
|
60
|
+
else
|
61
|
+
log_command(
|
62
|
+
"Sending TERM signal to command ID=#{command['id']} `#{command['command']}' on host #{`hostname`.chomp} pid #{command_pid}" \
|
63
|
+
" because it was killed"
|
64
|
+
)
|
65
|
+
Process.kill("TERM", command_pid)
|
66
|
+
@killed = true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
38
72
|
_, status = Process.wait2(command_pid)
|
73
|
+
killed_thread.kill if killed_thread.alive?
|
39
74
|
log_command("Command ID=#{command['id']} `#{command['command']}' exited on host #{`hostname`.chomp}: #{status}")
|
40
75
|
|
41
76
|
@command_pid = nil
|
77
|
+
@killed = nil
|
42
78
|
remove_metadata(command: command)
|
43
79
|
end
|
44
80
|
rescue StandardError => e
|
@@ -89,6 +125,10 @@ class SQSConsumer
|
|
89
125
|
$stderr.puts e.backtrace.join("\n")
|
90
126
|
end
|
91
127
|
|
128
|
+
def already_killed?
|
129
|
+
@killed
|
130
|
+
end
|
131
|
+
|
92
132
|
def receive_message
|
93
133
|
sqs.receive_message(
|
94
134
|
queue_url: queue_url,
|
@@ -123,6 +163,21 @@ class SQSConsumer
|
|
123
163
|
log("[update_metadata] #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}")
|
124
164
|
end
|
125
165
|
|
166
|
+
def metadata_exists?(command:)
|
167
|
+
metadata = command['metadata']
|
168
|
+
if metadata && metadata['bucket'] && metadata['key']
|
169
|
+
s3.head_object(
|
170
|
+
bucket: metadata['bucket'],
|
171
|
+
key: metadata['key'],
|
172
|
+
)
|
173
|
+
true
|
174
|
+
end
|
175
|
+
rescue ::Aws::S3::Errors::NotFound
|
176
|
+
false
|
177
|
+
rescue StandardError => e
|
178
|
+
log("[metadata_exists] #{e.class.name}: #{e.message}\n#{e.backtrace.join("\n")}")
|
179
|
+
end
|
180
|
+
|
126
181
|
def remove_metadata(command:)
|
127
182
|
metadata = command['metadata']
|
128
183
|
if metadata && metadata['bucket'] && metadata['key']
|
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.10.0.
|
4
|
+
version: 0.10.0.alpha2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Stegman
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
@@ -114,14 +114,14 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.
|
117
|
+
version: 0.8.0
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.
|
124
|
+
version: 0.8.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: bundler
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -173,6 +173,7 @@ executables:
|
|
173
173
|
extensions: []
|
174
174
|
extra_rdoc_files: []
|
175
175
|
files:
|
176
|
+
- ".circleci/config.yml"
|
176
177
|
- ".gitignore"
|
177
178
|
- ".rspec"
|
178
179
|
- Gemfile
|
@@ -181,7 +182,6 @@ files:
|
|
181
182
|
- Rakefile
|
182
183
|
- bin/console
|
183
184
|
- bin/setup
|
184
|
-
- circle.yml
|
185
185
|
- elastic_beans.gemspec
|
186
186
|
- exe/beans
|
187
187
|
- lib/elastic_beans.rb
|
@@ -196,6 +196,7 @@ files:
|
|
196
196
|
- lib/elastic_beans/command/deploy.rb
|
197
197
|
- lib/elastic_beans/command/exec.rb
|
198
198
|
- lib/elastic_beans/command/get_env.rb
|
199
|
+
- lib/elastic_beans/command/kill.rb
|
199
200
|
- lib/elastic_beans/command/ps.rb
|
200
201
|
- lib/elastic_beans/command/restart.rb
|
201
202
|
- lib/elastic_beans/command/scale.rb
|
@@ -219,6 +220,7 @@ files:
|
|
219
220
|
- lib/elastic_beans/environment/webserver.rb
|
220
221
|
- lib/elastic_beans/environment/worker.rb
|
221
222
|
- lib/elastic_beans/error.rb
|
223
|
+
- lib/elastic_beans/error/access_denied.rb
|
222
224
|
- lib/elastic_beans/error/environments_not_ready.rb
|
223
225
|
- lib/elastic_beans/exec.rb
|
224
226
|
- lib/elastic_beans/exec/command.rb
|
data/circle.yml
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
---
|
2
|
-
machine:
|
3
|
-
environment:
|
4
|
-
RSPEC_OPTS: "-r rspec_junit_formatter --format progress --format RspecJunitFormatter -o $CIRCLE_TEST_REPORTS/rspec/junit.xml"
|
5
|
-
|
6
|
-
dependencies:
|
7
|
-
override:
|
8
|
-
- |
|
9
|
-
case $CIRCLE_NODE_INDEX in
|
10
|
-
0)
|
11
|
-
rvm-exec 2.3.1 bash -c "bundle check --path=vendor/bundle_2.3 || bundle install --path=vendor/bundle_2.3 --jobs=4 --retry=3"
|
12
|
-
;;
|
13
|
-
1)
|
14
|
-
rvm-exec 2.2.5 bash -c "bundle check --path=vendor/bundle_2.2 || bundle install --path=vendor/bundle_2.2 --jobs=4 --retry=3"
|
15
|
-
;;
|
16
|
-
esac
|
17
|
-
post:
|
18
|
-
- git config --global user.name "CircleCI"
|
19
|
-
- git config --global user.email "ops-ro@onemedical.com"
|
20
|
-
|
21
|
-
test:
|
22
|
-
override:
|
23
|
-
- case $CIRCLE_NODE_INDEX in 0) rvm-exec 2.3.1 bash -c "bundle check --path=vendor/bundle_2.3 && bundle exec rake" ;; 1) rvm-exec 2.2.5 bash -c "bundle check --path=vendor/bundle_2.2 && bundle exec rake" ;; esac:
|
24
|
-
parallel: true
|