asger 0.2.1 → 1.0.2
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/.ruby-version +1 -0
- data/README.md +1 -1
- data/asger.gemspec +3 -2
- data/lib/asger/cli.rb +25 -12
- data/lib/asger/runner.rb +63 -26
- data/lib/asger/task.rb +56 -17
- data/lib/asger/version.rb +1 -1
- data/stock_scripts/chef_deregister.rb +7 -7
- data/stock_scripts/echo.rb +16 -5
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c91487b1cd2ad1031fc3d9b1e72a789dd446ca4
|
4
|
+
data.tar.gz: fc47bf1f5b779029ef2a69d8219777c653422462
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: daad5b8b810429b6989cfda98b67da0384022edb68970071ec00a339ec6cee7a7013edde5d7ce27fc60990ea63e7337112aede22ba23c5d85915f77023a591e8
|
7
|
+
data.tar.gz: 090c4f37a0f6e461e74f4933fcb5fe921f5c3a0f65e7b5e908de355dbd52ea640ee510c5e78906c8ad04ffc4d29cf5940a658201a599293bcc88f52bcfc15a2d
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.0
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# `asger` #
|
2
2
|
|
3
|
-
`asger` is a tool designed to field notifications from Amazon EC2 auto-scaling groups via a SNS topic subscribed to an SQS queue. (Which probably sounds alarmingly specific, but it's the most common way to do this!) Once a notification is fielded, the user can define Tasks that then perform actions on instance creation ("up" functions) and termination ("down" functions).
|
3
|
+
`asger` is a tool designed to field notifications from Amazon EC2 auto-scaling groups via a SNS topic subscribed to an SQS queue. (Which probably sounds alarmingly specific, but it's the most common way to do this!) Once a notification is fielded, the user can define Tasks that then perform actions on instance creation ("up" functions) and termination ("down" functions), as well as their associated failure events.
|
4
4
|
|
5
5
|
### Important Notes ###
|
6
6
|
- When multiple tasks are running in a single `asger` instance, they will be run in order on instance creation and _in reverse order_ on instance termination.
|
data/asger.gemspec
CHANGED
@@ -21,8 +21,9 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.add_development_dependency "rake", "~> 10.0"
|
22
22
|
spec.add_development_dependency "pry"
|
23
23
|
|
24
|
-
spec.add_runtime_dependency 'aws-sdk',
|
25
|
-
spec.add_runtime_dependency 'trollop',
|
24
|
+
spec.add_runtime_dependency 'aws-sdk', '~> 2.2.22'
|
25
|
+
spec.add_runtime_dependency 'trollop', '~> 2.1.1'
|
26
26
|
spec.add_runtime_dependency "hashie", "~> 3.3"
|
27
|
+
spec.add_runtime_dependency 'ice_nine', '~> 0.11.2'
|
27
28
|
spec.add_runtime_dependency 'activesupport', '~> 4.2.0'
|
28
29
|
end
|
data/lib/asger/cli.rb
CHANGED
@@ -20,17 +20,19 @@ module Asger
|
|
20
20
|
:type => :string, :multi => true
|
21
21
|
opt :queue_url, "URL of the SQS queue to read from",
|
22
22
|
:type => :string
|
23
|
-
opt :pause_time, "Time (in seconds) to pause between polls.",
|
24
|
-
:default => 0
|
25
23
|
opt :verbose, "enables verbose logging",
|
26
24
|
:default => false
|
27
25
|
opt :die_on_error, "Terminates if an exception is thrown within the task runner.",
|
28
26
|
:default => true
|
29
27
|
|
28
|
+
opt :delete_messages, 'Delete messages from the SQS queue after processing (off is useful for development).',
|
29
|
+
:default => true
|
30
|
+
|
30
31
|
opt :aws_logging, "Provides the Asger logger to AWS (use for deep debugging).", :default => false
|
31
32
|
|
32
33
|
opt :shared_credentials, "Tells Asger to use shared credentials from '~/.aws/credentials'.", :type => :string
|
33
34
|
opt :iam, "Tells Asger to use IAM credentials.", :default => false
|
35
|
+
opt :region, 'Specifies an AWS region.', :type => :string
|
34
36
|
end
|
35
37
|
|
36
38
|
logger = Logger.new($stderr)
|
@@ -47,9 +49,10 @@ module Asger
|
|
47
49
|
exit(1)
|
48
50
|
end
|
49
51
|
|
50
|
-
logger.warn "No tasks configured; Asger will run, but won't do much."
|
52
|
+
logger.warn "No tasks configured; Asger will run, but won't do much." \
|
53
|
+
unless (opts[:task_file] && !opts[:task_file].empty?)
|
51
54
|
|
52
|
-
param_files =
|
55
|
+
param_files =
|
53
56
|
opts[:parameter_file].map do |pf|
|
54
57
|
logger.debug "Parsing parameter file '#{pf}'."
|
55
58
|
case File.extname(pf)
|
@@ -76,8 +79,12 @@ module Asger
|
|
76
79
|
end
|
77
80
|
|
78
81
|
aws_logger = opts[:aws_logging] ? logger : nil
|
79
|
-
sqs_client = Aws::SQS::Client.new(logger: aws_logger,
|
80
|
-
|
82
|
+
sqs_client = Aws::SQS::Client.new(logger: aws_logger,
|
83
|
+
region: opts[:region], credentials: credentials)
|
84
|
+
ec2_client = Aws::EC2::Client.new(logger: aws_logger,
|
85
|
+
region: opts[:region], credentials: credentials)
|
86
|
+
asg_client = Aws::AutoScaling::Client.new(logger: aws_logger,
|
87
|
+
region: opts[:region], credentials: credentials)
|
81
88
|
|
82
89
|
|
83
90
|
stock_scripts_dir = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "stock_scripts"))
|
@@ -85,12 +92,17 @@ module Asger
|
|
85
92
|
|
86
93
|
logger.info "Using task files:"
|
87
94
|
task_files.each { |tf| logger.info " - #{tf}" }
|
88
|
-
runner = Runner.new(logger
|
89
|
-
|
90
|
-
|
95
|
+
runner = Runner.new(logger: logger, aws_logger: aws_logger,
|
96
|
+
region: opts[:region], credentials: credentials,
|
97
|
+
queue_url: opts[:queue_url],
|
98
|
+
parameters: parameters,
|
99
|
+
task_files: task_files,
|
100
|
+
no_delete_messages: !opts[:delete_messages])
|
101
|
+
|
102
|
+
logger.info "Beginning poll loop."
|
91
103
|
loop do
|
92
104
|
begin
|
93
|
-
runner.
|
105
|
+
runner.poll
|
94
106
|
rescue StandardError => err
|
95
107
|
logger.error "Encountered an error."
|
96
108
|
logger.error "#{err.class.name}: #{err.message}"
|
@@ -98,10 +110,11 @@ module Asger
|
|
98
110
|
|
99
111
|
if opts[:die_on_error]
|
100
112
|
raise err
|
113
|
+
else
|
114
|
+
logger.error "re-entering poll."
|
101
115
|
end
|
102
116
|
end
|
103
|
-
sleep opts[:pause_time] unless opts[:pause_time] == 0
|
104
117
|
end
|
105
118
|
end
|
106
119
|
end
|
107
|
-
end
|
120
|
+
end
|
data/lib/asger/runner.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'logger'
|
2
2
|
require 'aws-sdk'
|
3
|
-
require '
|
3
|
+
require 'ice_nine'
|
4
|
+
require 'active_support/all'
|
4
5
|
|
5
6
|
require 'asger/task'
|
6
7
|
|
@@ -9,66 +10,102 @@ module Asger
|
|
9
10
|
# @param logger [Logger] the logger for Asger to use
|
10
11
|
# @param sqs_client [Aws::SQS::Client] the SQS client to use for polling
|
11
12
|
# @param ec2_client [Aws::EC2::Client] the EC2 client to use to get instance information
|
13
|
+
# @param asg_client [Aws::AutoScaling::Client] the ASG client to use to get ASG information
|
12
14
|
# @param queue_url [String] the queue URL to poll
|
13
15
|
# @param parameters [Hash] a hash of parameters to pass to {Task}s
|
14
16
|
# @param task_files [Array<String>] list of file paths to load as {Task}s
|
15
|
-
|
17
|
+
# @param no_delete_messages [TrueClass, FalseClass] if true, don't call sqs:DeleteMessage
|
18
|
+
def initialize(logger:, aws_logger:, credentials:,
|
19
|
+
region:, queue_url:,
|
20
|
+
parameters:, task_files:, no_delete_messages:)
|
16
21
|
@logger = logger
|
17
|
-
@
|
18
|
-
@
|
22
|
+
@region = region
|
23
|
+
@parameters = IceNine.deep_freeze(parameters.merge(
|
24
|
+
region: region, credentials: credentials
|
25
|
+
).deep_symbolize_keys)
|
26
|
+
|
27
|
+
@sqs_client = Aws::SQS::Client.new(logger: aws_logger,
|
28
|
+
region: region, credentials: credentials)
|
29
|
+
@ec2_client = Aws::EC2::Client.new(logger: aws_logger,
|
30
|
+
region: region, credentials: credentials)
|
31
|
+
@asg_client = Aws::AutoScaling::Client.new(logger: aws_logger,
|
32
|
+
region: region, credentials: credentials)
|
19
33
|
@ec2_resource_client = Aws::EC2::Resource.new(client: @ec2_client)
|
34
|
+
@asg_resource_client = Aws::AutoScaling::Resource.new(client: @asg_client)
|
20
35
|
@queue_url = queue_url
|
21
|
-
@parameters = Hashie::Mash.new(parameters)
|
22
36
|
@tasks = task_files.map { |tf| Task.from_file(@logger, tf) }
|
37
|
+
@no_delete_messages = no_delete_messages
|
23
38
|
|
24
39
|
@logger.info "#{@tasks.length} task(s) set up."
|
40
|
+
@logger.warn('no_delete_messages is set; will not clear SQS messages!') \
|
41
|
+
if @no_delete_messages
|
25
42
|
|
26
|
-
@tasks.each { |t| t.
|
43
|
+
@tasks.each { |t| t.invoke_init(@parameters) }
|
27
44
|
end
|
28
45
|
|
29
46
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
47
|
+
def poll()
|
48
|
+
poller = Aws::SQS::QueuePoller.new(@queue_url, client: @sqs_client,
|
49
|
+
max_number_of_messages: 10, skip_delete: true)
|
50
|
+
|
51
|
+
poller.poll do |msgs|
|
52
|
+
[ msgs ].flatten.each do |msg|
|
53
|
+
notification = JSON.parse(JSON.parse(msg.body)["Message"])
|
54
|
+
if notification["Event"] != nil
|
55
|
+
asg = @asg_resource_client.group(notification['AutoScalingGroupName'])
|
56
|
+
instance_id = notification["EC2InstanceId"]
|
57
|
+
|
58
|
+
@logger.warn("ASG '#{asg}' has fired event, but does not exist - already cleaned up?") \
|
59
|
+
unless asg.exists?
|
60
|
+
|
61
|
+
case notification["Event"].gsub("autoscaling:", "")
|
36
62
|
when "EC2_INSTANCE_LAUNCH"
|
37
|
-
|
38
|
-
@logger.info "Instance launched: #{instance_id}"
|
63
|
+
@logger.info "Instance launched in '#{asg.name}': #{instance_id}"
|
39
64
|
|
40
65
|
instance = @ec2_resource_client.instance(instance_id)
|
41
66
|
@tasks.each do |task|
|
42
|
-
task.invoke_up(instance, @parameters)
|
67
|
+
task.invoke_up(instance, asg, @parameters)
|
43
68
|
end
|
44
69
|
|
45
|
-
delete_message(msg)
|
70
|
+
delete_message(msg) unless @no_delete_messages
|
46
71
|
when "EC2_INSTANCE_LAUNCH_ERROR"
|
47
|
-
@logger.warn "Instance launch
|
48
|
-
|
72
|
+
@logger.warn "Instance failed to launch in '#{asg.name}'."
|
73
|
+
|
74
|
+
@tasks.each do |task|
|
75
|
+
task.invoke_up_failed(asg, @parameters)
|
76
|
+
end
|
77
|
+
|
78
|
+
delete_message(msg) unless @no_delete_messages
|
49
79
|
when "EC2_INSTANCE_TERMINATE"
|
50
|
-
|
51
|
-
@logger.info "Instance terminated: #{instance_id}"
|
80
|
+
@logger.info "Instance terminated in '#{asg.name}': #{instance_id}"
|
52
81
|
|
53
82
|
@tasks.reverse_each do |task|
|
54
|
-
task.invoke_down(instance_id, @parameters)
|
83
|
+
task.invoke_down(instance_id, asg, @parameters)
|
55
84
|
end
|
56
|
-
|
85
|
+
|
86
|
+
delete_message(msg) unless @no_delete_messages
|
57
87
|
when "EC2_INSTANCE_TERMINATE_ERROR"
|
58
|
-
@logger.warn "Instance terminate
|
59
|
-
|
88
|
+
@logger.warn "Instance failed to terminate in '#{asg.name}': #{instance_id}"
|
89
|
+
|
90
|
+
@tasks.reverse_each do |task|
|
91
|
+
task.invoke_down_failed(instance_id, asg, @parameters)
|
92
|
+
end
|
93
|
+
delete_message(msg) unless @no_delete_messages
|
60
94
|
when "TEST_NOTIFICATION"
|
61
|
-
@logger.
|
62
|
-
delete_message(msg)
|
95
|
+
@logger.info "Found test notification in queue."
|
96
|
+
delete_message(msg) unless @no_delete_messages
|
63
97
|
else
|
64
98
|
@logger.debug "Unrecognized notification '#{notification["Event"]}', ignoring."
|
99
|
+
end
|
65
100
|
end
|
66
101
|
end
|
67
102
|
end
|
68
103
|
end
|
69
104
|
|
70
105
|
private
|
106
|
+
|
71
107
|
def delete_message(msg)
|
108
|
+
@logger.debug "Deleting message '#{msg[:receipt_handle]}'"
|
72
109
|
@sqs_client.delete_message(queue_url: @queue_url, receipt_handle: msg[:receipt_handle])
|
73
110
|
end
|
74
111
|
end
|
data/lib/asger/task.rb
CHANGED
@@ -15,64 +15,103 @@ module Asger
|
|
15
15
|
instance_eval(code, filename, 1)
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
if @
|
20
|
-
logger.debug "
|
21
|
-
@
|
18
|
+
def invoke_init(parameters)
|
19
|
+
if @init_proc
|
20
|
+
logger.debug "Initializing for '#{@name}'..."
|
21
|
+
@init_proc.call(parameters)
|
22
22
|
else
|
23
|
-
logger.debug "No
|
23
|
+
logger.debug "No init for '#{@name}'."
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def invoke_up(instance, parameters)
|
27
|
+
def invoke_up(instance, asg, parameters)
|
28
28
|
if @up_proc
|
29
29
|
logger.debug "Invoking up for '#{@name}'..."
|
30
|
-
@up_proc.call(instance, parameters)
|
30
|
+
@up_proc.call(instance, asg, parameters)
|
31
31
|
logger.debug "Up invoked for '#{@name}'..."
|
32
32
|
else
|
33
33
|
logger.debug "No up for '#{@name}'."
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
def invoke_down(instance_id, parameters)
|
37
|
+
def invoke_down(instance_id, asg, parameters)
|
38
38
|
if @down_proc
|
39
39
|
logger.debug "Invoking down for '#{@name}'..."
|
40
|
-
@down_proc.call(instance_id, parameters)
|
40
|
+
@down_proc.call(instance_id, asg, parameters)
|
41
41
|
logger.debug "Down invoked for '#{@name}'..."
|
42
42
|
else
|
43
43
|
logger.debug "No down for '#{@name}'."
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
def invoke_up_failed(asg, parameters)
|
48
|
+
if @up_failed_proc
|
49
|
+
logger.debug "Invoking up_failed for '#{@name}'..."
|
50
|
+
@up_failed_proc.call(asg, parameters)
|
51
|
+
logger.debug "up_failed invoked for '#{@name}'..."
|
52
|
+
else
|
53
|
+
logger.debug "No up_failed for '#{@name}'."
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def invoke_down_failed(instance_id, asg, parameters)
|
58
|
+
if @down_failed_proc
|
59
|
+
logger.debug "Invoking down_failed for '#{@name}'..."
|
60
|
+
@down_failed_proc.call(instance_id, asg, parameters)
|
61
|
+
logger.debug "down_failed invoked for '#{@name}'..."
|
62
|
+
else
|
63
|
+
logger.debug "No down_failed for '#{@name}'."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
47
67
|
def self.from_file(logger, file)
|
48
68
|
Task.new(logger, File.read(file), file)
|
49
69
|
end
|
50
70
|
|
51
71
|
private
|
52
|
-
# Defines
|
53
|
-
# Asger before it does anything with the actual queue) if there's a
|
54
|
-
# the parameter set.
|
55
|
-
#
|
72
|
+
# Defines an init function, which should set member vars. Raise and fail (which
|
73
|
+
# will halt Asger before it does anything with the actual queue) if there's a
|
74
|
+
# problem with the parameter set.
|
75
|
+
#
|
56
76
|
# @yield [parameters]
|
57
77
|
# @yieldparam parameters [Hash] the parameters passed in to Asger
|
58
|
-
def
|
59
|
-
@
|
78
|
+
def init(&block)
|
79
|
+
@init_proc = block
|
60
80
|
end
|
61
81
|
|
62
|
-
# Defines an 'up' function
|
82
|
+
# Defines an 'up' function, addressing `EC2_INSTANCE_LAUNCH`.
|
63
83
|
# @yield [instance, parameters]
|
64
84
|
# @yieldparam instance [Aws::EC2::Instance] the instance that has been created
|
85
|
+
# @yieldparam asg [nil, Aws::AutoScaling::AutoScalingGroup] the ASG resource of the launched instance
|
65
86
|
# @yieldparam parameters [Hash] the parameters passed in to Asger
|
66
87
|
def up(&block)
|
67
88
|
@up_proc = block
|
68
89
|
end
|
69
90
|
|
70
|
-
# Defines a 'down' function
|
91
|
+
# Defines a 'down' function, addressing `EC2_INSTANCE_TERMINATE`.
|
71
92
|
# @yield [instance_id, parameters]
|
72
93
|
# @yieldparam instance_id [String] the ID of the recently terminated instance
|
94
|
+
# @yieldparam asg [nil, Aws::AutoScaling::AutoScalingGroup] the ASG resource of the terminated instance
|
73
95
|
# @yieldparam parameters [Hash] the parameters passed in to Asger
|
74
96
|
def down(&block)
|
75
97
|
@down_proc = block
|
76
98
|
end
|
99
|
+
|
100
|
+
# Defines an 'up_failed' function, addressing `EC2_INSTANCE_LAUNCH_ERROR`.
|
101
|
+
# @yield [asg, parameters]
|
102
|
+
# @yieldparam asg [nil, Aws::AutoScaling::AutoScalingGroup] the ASG resource of the failed instance
|
103
|
+
# @yieldparam parameters [Hash] the parameters passed in to Asger
|
104
|
+
def up_failed(&block)
|
105
|
+
@up_failed_proc = block
|
106
|
+
end
|
107
|
+
|
108
|
+
# Defines an 'up_failed' function, addressing `EC2_INSTANCE_TERMINATE_ERROR`.
|
109
|
+
# @yield [asg, parameters]
|
110
|
+
# @yieldparam instance_id [String] the ID of the instance that failed to terminate
|
111
|
+
# @yieldparam asg [nil, Aws::AutoScaling::AutoScalingGroup] the ASG resource of the failed instance
|
112
|
+
# @yieldparam parameters [Hash] the parameters passed in to Asger
|
113
|
+
def down_failed(&block)
|
114
|
+
@down_failed_proc = block
|
115
|
+
end
|
77
116
|
end
|
78
117
|
end
|
data/lib/asger/version.rb
CHANGED
@@ -2,31 +2,31 @@
|
|
2
2
|
# It will perform a Chef search for an 'instance_id' tag that matches the instance ID
|
3
3
|
# provided by the AWS notification. To tag a node with the instance_id from bash, do
|
4
4
|
# something like this on-node (probably in cloud-init):
|
5
|
-
#
|
5
|
+
#
|
6
6
|
# ```bash
|
7
7
|
# knife tag create -c /path/to/client.rb $NODE_NAME $INSTANCE_ID
|
8
8
|
# ```
|
9
|
-
#
|
9
|
+
#
|
10
10
|
# Which, in our naming scheme at Leaf, becomes:
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# ```bash
|
13
13
|
# knife tag create -c /etc/chef/client.rb vpn.test-cloud.infra.06f1d39c i-06f1d39c
|
14
14
|
# ```
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# PARAMETERS:
|
17
|
-
#
|
17
|
+
#
|
18
18
|
# chef_deregister.knife_config: the path to the knife config to use for search/node delete
|
19
19
|
|
20
20
|
require 'json'
|
21
21
|
|
22
|
-
|
22
|
+
init do |parameters|
|
23
23
|
knife_config = parameters[:chef_deregister][:knife_config]
|
24
24
|
raise "parameters[:chef_deregister][:knife_config] is not set" unless knife_config
|
25
25
|
|
26
26
|
raise "file '#{knife_config}' does not exist" unless File.exist?(knife_config)
|
27
27
|
end
|
28
28
|
|
29
|
-
down do |instance_id, parameters|
|
29
|
+
down do |instance_id, asg, parameters|
|
30
30
|
knife_config = parameters[:chef_deregister][:knife_config]
|
31
31
|
|
32
32
|
search_result = Asger::Util::run_command("knife search: #{instance_id}",
|
data/stock_scripts/echo.rb
CHANGED
@@ -1,9 +1,20 @@
|
|
1
1
|
# Just logs the instances being created and destroyed to the logger for testing.
|
2
|
+
init do |parameters|
|
3
|
+
logger.info 'echo - init'
|
4
|
+
end
|
5
|
+
|
6
|
+
up do |instance, asg, parameters|
|
7
|
+
logger.info "echo - upping instance in '#{asg.name}': #{instance}"
|
8
|
+
end
|
2
9
|
|
3
|
-
|
4
|
-
logger.
|
10
|
+
up_failed do |asg, parameters|
|
11
|
+
logger.warn "echo - failed to up instance in '#{asg.name}'"
|
5
12
|
end
|
6
13
|
|
7
|
-
down do |instance_id, parameters|
|
8
|
-
logger.info "downing instance: #{instance_id}"
|
9
|
-
end
|
14
|
+
down do |instance_id, asg, parameters|
|
15
|
+
logger.info "echo - downing instance in '#{asg.name}': #{instance_id}"
|
16
|
+
end
|
17
|
+
|
18
|
+
down_failed do |instance_id, asg, parameters|
|
19
|
+
logger.warn "echo - failed to down instance in '#{asg.name}': #{instance_id}"
|
20
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ed Ropple
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 2.
|
61
|
+
version: 2.2.22
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 2.
|
68
|
+
version: 2.2.22
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: trollop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: ice_nine
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.11.2
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.11.2
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: activesupport
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -117,6 +131,7 @@ extensions: []
|
|
117
131
|
extra_rdoc_files: []
|
118
132
|
files:
|
119
133
|
- ".gitignore"
|
134
|
+
- ".ruby-version"
|
120
135
|
- ".yardopts"
|
121
136
|
- Gemfile
|
122
137
|
- LICENSE.txt
|
@@ -152,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
152
167
|
version: '0'
|
153
168
|
requirements: []
|
154
169
|
rubyforge_project:
|
155
|
-
rubygems_version: 2.
|
170
|
+
rubygems_version: 2.5.1
|
156
171
|
signing_key:
|
157
172
|
specification_version: 4
|
158
173
|
summary: A persistent daemon that watches an AWS autoscaling group for changes and
|