elastic_beans 0.10.0.alpha1 → 0.10.0.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|