dynamo-autoscale 0.1.4 → 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.
- data/.gitignore +1 -1
- data/CHANGELOG +6 -0
- data/Gemfile.lock +27 -8
- data/README.md +85 -47
- data/bin/dynamo-autoscale +15 -113
- data/config/dynamo-autoscale-test.yml +11 -0
- data/config/environment/common.rb +100 -25
- data/config/environment/test.rb +3 -0
- data/config/services/aws.rb +2 -19
- data/config/services/logger.rb +23 -27
- data/config/services/signals.rb +15 -0
- data/dynamo-autoscale.gemspec +1 -0
- data/dynamo-autoscale.sample.yml +79 -0
- data/lib/dynamo-autoscale/actioner.rb +27 -13
- data/lib/dynamo-autoscale/cw_poller.rb +1 -0
- data/lib/dynamo-autoscale/dispatcher.rb +10 -2
- data/lib/dynamo-autoscale/dynamo_actioner.rb +6 -5
- data/lib/dynamo-autoscale/local_actioner.rb +15 -2
- data/lib/dynamo-autoscale/local_data_poll.rb +2 -0
- data/lib/dynamo-autoscale/logger.rb +4 -0
- data/lib/dynamo-autoscale/metrics.rb +1 -1
- data/lib/dynamo-autoscale/poller.rb +7 -5
- data/lib/dynamo-autoscale/rule.rb +1 -0
- data/lib/dynamo-autoscale/rule_set.rb +4 -0
- data/lib/dynamo-autoscale/scale_report.rb +39 -0
- data/lib/dynamo-autoscale/table_tracker.rb +26 -19
- data/lib/dynamo-autoscale/version.rb +1 -1
- data/script/historic_data +17 -8
- data/script/monitor +9 -26
- data/script/simulator +16 -14
- data/script/test +29 -23
- data/script/validate_ruleset +1 -3
- data/spec/actioner_spec.rb +6 -0
- data/spec/rule_spec.rb +6 -0
- data/templates/scale_report_email.erb +17 -0
- metadata +23 -3
- data/config/logger.yml +0 -11
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
v0.2
|
2
|
+
|
3
|
+
- Completely reworked configuration. Got rid of the massive number of flags and
|
4
|
+
options required to launch dynamo-autoscale and moved them into a config file.
|
5
|
+
- Added the ability to send and email whenever a scale happens.
|
6
|
+
|
1
7
|
v0.1.4
|
2
8
|
|
3
9
|
- Fixed a bug that stopped all rule evaluation after the first rule passed. Now
|
data/Gemfile.lock
CHANGED
@@ -1,19 +1,25 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
dynamo-autoscale (0.1)
|
4
|
+
dynamo-autoscale (0.1.4)
|
5
|
+
activesupport
|
5
6
|
aws-sdk
|
6
7
|
colored
|
8
|
+
pony
|
7
9
|
rbtree
|
8
10
|
ruby-prof
|
9
11
|
|
10
12
|
GEM
|
11
13
|
remote: https://rubygems.org/
|
12
14
|
specs:
|
13
|
-
activesupport (
|
14
|
-
i18n (
|
15
|
-
|
16
|
-
|
15
|
+
activesupport (4.0.0)
|
16
|
+
i18n (~> 0.6, >= 0.6.4)
|
17
|
+
minitest (~> 4.2)
|
18
|
+
multi_json (~> 1.3)
|
19
|
+
thread_safe (~> 0.1)
|
20
|
+
tzinfo (~> 0.3.37)
|
21
|
+
atomic (1.1.10)
|
22
|
+
aws-sdk (1.11.3)
|
17
23
|
json (~> 1.4)
|
18
24
|
nokogiri (< 1.6.0)
|
19
25
|
uuidtools (~> 2.1)
|
@@ -21,11 +27,19 @@ GEM
|
|
21
27
|
coderay (1.0.9)
|
22
28
|
colored (1.2)
|
23
29
|
diff-lcs (1.2.4)
|
24
|
-
i18n (0.6.
|
30
|
+
i18n (0.6.4)
|
25
31
|
json (1.8.0)
|
32
|
+
mail (2.5.4)
|
33
|
+
mime-types (~> 1.16)
|
34
|
+
treetop (~> 1.4.8)
|
26
35
|
method_source (0.8.1)
|
27
|
-
|
36
|
+
mime-types (1.23)
|
37
|
+
minitest (4.7.5)
|
38
|
+
multi_json (1.7.7)
|
28
39
|
nokogiri (1.5.10)
|
40
|
+
polyglot (0.3.3)
|
41
|
+
pony (1.5)
|
42
|
+
mail (> 2.0)
|
29
43
|
pry (0.9.12.2)
|
30
44
|
coderay (~> 1.0.5)
|
31
45
|
method_source (~> 0.8)
|
@@ -43,14 +57,19 @@ GEM
|
|
43
57
|
rspec-mocks (2.13.1)
|
44
58
|
ruby-prof (0.13.0)
|
45
59
|
slop (3.4.5)
|
60
|
+
thread_safe (0.1.0)
|
61
|
+
atomic
|
46
62
|
timecop (0.6.1)
|
63
|
+
treetop (1.4.14)
|
64
|
+
polyglot
|
65
|
+
polyglot (>= 0.3.1)
|
66
|
+
tzinfo (0.3.37)
|
47
67
|
uuidtools (2.1.4)
|
48
68
|
|
49
69
|
PLATFORMS
|
50
70
|
ruby
|
51
71
|
|
52
72
|
DEPENDENCIES
|
53
|
-
activesupport
|
54
73
|
dynamo-autoscale!
|
55
74
|
pry
|
56
75
|
ripl
|
data/README.md
CHANGED
@@ -37,7 +37,26 @@ This project aims to take all of this into consideration and automatically scale
|
|
37
37
|
your throughputs to enable you to deal with spikes and save money where
|
38
38
|
possible.
|
39
39
|
|
40
|
-
#
|
40
|
+
# Usage
|
41
|
+
|
42
|
+
First of all, you'll need to install this project as a gem:
|
43
|
+
|
44
|
+
$ gem install dynamo-autoscale
|
45
|
+
|
46
|
+
This will give you access to the `dynamo-autoscale` executable. The executable
|
47
|
+
takes a single argument, the path to a config file.
|
48
|
+
|
49
|
+
## Configuration
|
50
|
+
|
51
|
+
The configuration file is the central thing that `dynamo-autoscale` requires to
|
52
|
+
function. It specifies what tables to monitor, maximum and minimum throughputs
|
53
|
+
and where your ruleset is located.
|
54
|
+
|
55
|
+
The `dynamo-autoscale` executable takes a single argument, and that is the path
|
56
|
+
to the configuration file you want to use.
|
57
|
+
|
58
|
+
**A sample config can be found in the project root directory.** It documents all
|
59
|
+
of the options you can specify.
|
41
60
|
|
42
61
|
This library requires AWS keys that have access to both CloudWatch and DynamoDB,
|
43
62
|
for retriving data and sending scaling requests. Using IAM, create a new user, and
|
@@ -52,29 +71,30 @@ The ARN for the custom policy can be specified as '\*' to allow access to all ta
|
|
52
71
|
or alternatively you can refer to the IAM documentation to limit access to specific
|
53
72
|
tables only.
|
54
73
|
|
55
|
-
|
56
|
-
|
57
|
-
- ./aws.yml
|
58
|
-
- ENV['AWS_CONFIG']
|
59
|
-
|
60
|
-
If it doesn't find an AWS YAML config in any of those locations, the process
|
61
|
-
prints an error and exits.
|
62
|
-
|
63
|
-
**A sample config can be found in the project root directory.**
|
74
|
+
### Minimal "getting started" configuration
|
64
75
|
|
65
|
-
|
76
|
+
``` yaml
|
77
|
+
:aws:
|
78
|
+
:access_key_id: "your_id"
|
79
|
+
:secret_access_key: "your_key"
|
80
|
+
:dynamo_db_endpoint: "dynamodb.us-east-1.amazonaws.com"
|
66
81
|
|
67
|
-
|
82
|
+
# There are some example rulesets in the rulesets/ directory of this project.
|
83
|
+
:ruleset: "path_to_your_ruleset.rb"
|
68
84
|
|
69
|
-
|
85
|
+
:tables:
|
86
|
+
- "your_table_name"
|
70
87
|
|
71
|
-
|
72
|
-
|
88
|
+
# In dry-run mode, the program will do exactly what it would normally except it
|
89
|
+
# won't touch DynamoDB at all. It will just log the changes it would have made
|
90
|
+
# in production locally.
|
91
|
+
:dry_run: true
|
92
|
+
```
|
73
93
|
|
74
|
-
|
94
|
+
Save this somewhere on your filesystem and point the `dynamo-autoscale`
|
95
|
+
executable to it:
|
75
96
|
|
76
|
-
|
77
|
-
expects.
|
97
|
+
$ dynamo-autoscale path/to/config.yml
|
78
98
|
|
79
99
|
## Logging
|
80
100
|
|
@@ -84,16 +104,8 @@ variable set to `true`:
|
|
84
104
|
|
85
105
|
$ DEBUG=true dynamo-autoscale <args...>
|
86
106
|
|
87
|
-
Also, if you want pretty coloured logging, you can set the `PRETTY_LOG`
|
88
|
-
environment variable to `true`:
|
89
|
-
|
90
|
-
$ PRETTY_LOG=true DEBUG=true dynamo-autoscale <args...>
|
91
|
-
|
92
107
|
## Rulesets
|
93
108
|
|
94
|
-
One of the first things you'll notice upon looking into the `--help` on the
|
95
|
-
executable is that it's looking for a "rule set". What on earth is a rule set?
|
96
|
-
|
97
109
|
A rule set is the primary user input for dynamo-autoscale. It is a DSL for
|
98
110
|
specifying when to increase and decrease your provisioned throughputs. Here is a
|
99
111
|
very basic rule set:
|
@@ -236,10 +248,13 @@ your four downscales for the current day. Or, you can downscale reads and writes
|
|
236
248
|
at the same time and this also costs you one of your four. (Reference:
|
237
249
|
http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html)
|
238
250
|
|
239
|
-
Because of this, the actioner can handle the grouping up of downscales
|
240
|
-
|
251
|
+
Because of this, the actioner can handle the grouping up of downscales by adding
|
252
|
+
the following to your config:
|
241
253
|
|
242
|
-
|
254
|
+
``` yaml
|
255
|
+
:group_downscales: true
|
256
|
+
:flush_after: 300
|
257
|
+
```
|
243
258
|
|
244
259
|
What this is saying is that if a write downscale came in, the actioner wouldn't
|
245
260
|
fire it off immediately. It would wait 300 seconds, or 5 minutes, to see if a
|
@@ -248,11 +263,11 @@ time. If no corresponding read came in, after 5 minutes the pending write
|
|
248
263
|
downscale would get "flushed" and applied without a read downscale.
|
249
264
|
|
250
265
|
This technique helps to save downscales on tables that may have unpredictable
|
251
|
-
consumption. You may need to tweak the
|
252
|
-
situation. By default, there is no
|
253
|
-
indefinitely, this may not be desirable.
|
266
|
+
consumption. You may need to tweak the `flush_after` value to match your own
|
267
|
+
situation. By default, there is no `flush_after` and downscales will wait
|
268
|
+
indefinitely, but this may not be desirable.
|
254
269
|
|
255
|
-
##
|
270
|
+
## Signalling
|
256
271
|
|
257
272
|
The `dynamo-autoscale` process responds to the SIGUSR1 and SIGUSR2 signals. What
|
258
273
|
we've done may be a dramatic bastardisation of what signals are intended for or
|
@@ -266,7 +281,7 @@ files in the directory it was run in.
|
|
266
281
|
|
267
282
|
Example:
|
268
283
|
|
269
|
-
$ dynamo-autoscale
|
284
|
+
$ dynamo-autoscale path/to/config.yml
|
270
285
|
# Runs as PID 1234. Wait for some time to pass...
|
271
286
|
$ kill -USR1 1234
|
272
287
|
$ cat some_table.csv
|
@@ -286,7 +301,34 @@ The CSV is in the following format:
|
|
286
301
|
If you send SIGUSR2 to the process as it's running, the process will take all of
|
287
302
|
the data it has on all of its tables and generate a graph for each table using R
|
288
303
|
(see the Graphs section below). This is handy for visualising what the process
|
289
|
-
is doing, especially after doing a few hours of a
|
304
|
+
is doing, especially after doing a few hours of a `dry_run`.
|
305
|
+
|
306
|
+
## Scale Report Emails
|
307
|
+
|
308
|
+
If you would like to receive email notifications whenever a scale event happens,
|
309
|
+
you can specify some email options in your configuration. Specifying the email
|
310
|
+
options implicitly activates email reports. Not including your email config
|
311
|
+
implicitly turns it off.
|
312
|
+
|
313
|
+
Sample email config:
|
314
|
+
|
315
|
+
``` yaml
|
316
|
+
:email:
|
317
|
+
:to: "john.doe@example.com"
|
318
|
+
:from: "dynamo-autoscale@example.com"
|
319
|
+
:via: :smtp
|
320
|
+
:via_options:
|
321
|
+
:port: 25
|
322
|
+
:enable_starttls_auto: false
|
323
|
+
:authentication: :plain
|
324
|
+
:address: "mailserver.example.com"
|
325
|
+
:user_name: "user"
|
326
|
+
:password: "password"
|
327
|
+
```
|
328
|
+
|
329
|
+
We're using Pony internally to send email and this part of the config just gets
|
330
|
+
passed to Pony verbatim. Check out the [Pony](https://github.com/benprew/pony)
|
331
|
+
documentation for more details on the options it supports.
|
290
332
|
|
291
333
|
# Developers / Tooling
|
292
334
|
|
@@ -333,25 +375,21 @@ with the `script/historic_data` executable.
|
|
333
375
|
If you want to test rules on your local machine without having to query
|
334
376
|
CloudWatch or hit DynamoDB, there are tools that facilitate that nicely.
|
335
377
|
|
336
|
-
The first thing you would need to do is gather some historic data. There's a
|
337
|
-
script called `script/historic_data` that you can run to gather data on a
|
338
|
-
specific table and store it into the `data/` directory in a format that all of
|
339
|
-
the other scripts are familiar with.
|
340
|
-
|
341
|
-
Next there are a couple of things you can do.
|
342
|
-
|
343
378
|
### Running a test
|
344
379
|
|
345
380
|
You can run a big batch of data all in one go with the `script/test` script.
|
346
381
|
This script can be invoked like this:
|
347
382
|
|
348
|
-
$ script/test
|
383
|
+
$ script/test path/to/config.yml
|
384
|
+
|
385
|
+
You will need to make sure you have historic data available for whatever tables
|
386
|
+
you have listed in your config file. If you don't, it's easy to gather it:
|
349
387
|
|
350
|
-
|
351
|
-
This will run through all of the data for that table in time order, logging
|
352
|
-
along the way and triggering rules from the rule set if any were defined.
|
388
|
+
$ script/historic_data path/to/config.yml
|
353
389
|
|
354
|
-
|
390
|
+
This script goes off to CloudWatch and pulls down about a week of data for each
|
391
|
+
table you have listed in your config. Then you can continue to re-run the
|
392
|
+
`script/test` command and watch a tonne of log output fly by.
|
355
393
|
|
356
394
|
#### Graphs
|
357
395
|
|
data/bin/dynamo-autoscale
CHANGED
@@ -1,85 +1,24 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
require 'optparse'
|
5
|
-
require 'active_support/all'
|
6
|
-
|
7
|
-
# Force this script into production mode as it's the only thing that will
|
8
|
-
# actually hit DynamoDB in the entire project.
|
9
|
-
ENV['RACK_ENV'] = "production"
|
10
|
-
|
11
|
-
actioner_opts = {}
|
12
|
-
general_opts = {}
|
13
|
-
|
14
|
-
OptionParser.new do |opts|
|
15
|
-
opts.banner = "Usage: dynamo-autoscale ruleset_path table_name [more table names] [options]"
|
16
|
-
|
17
|
-
doc = 'Makes read and write downscales happen at the same time to save ' +
|
18
|
-
'downscales per day.'
|
19
|
-
|
20
|
-
opts.on('-g', '--group-downscales', doc) do
|
21
|
-
actioner_opts[:group_downscales] = true
|
22
|
-
end
|
23
|
-
|
24
|
-
doc = 'Only works in conjunction with --group-downscales. Sets a maximum ' +
|
25
|
-
'amount of time for an operation to be pending before it gets applied to Dynamo'
|
26
|
-
|
27
|
-
opts.on('--flush-after SECONDS', Integer, doc) do |seconds|
|
28
|
-
actioner_opts[:flush_after] = seconds.to_i.seconds
|
29
|
-
end
|
30
|
-
|
31
|
-
doc = 'Stops dynamo-autoscale from talking to DynamoDB. Instead, it just ' +
|
32
|
-
'tracks the changes it would have made locally.'
|
33
|
-
|
34
|
-
opts.on('--dry-run', doc) do
|
35
|
-
general_opts[:dry_run] = true
|
36
|
-
end
|
37
|
-
|
38
|
-
doc = "Sets a minimum value for throughputs to be set to. " +
|
39
|
-
"Defaults to 10."
|
40
|
-
|
41
|
-
opts.on('--minimum-throughput VALUE', Float, doc) do |value|
|
42
|
-
if value < 1.0
|
43
|
-
STDERR.puts "Cannot set minimum throughput to less than 1."
|
44
|
-
exit 1
|
45
|
-
end
|
46
|
-
|
47
|
-
general_opts[:minimum_throughput] = value
|
48
|
-
end
|
49
|
-
|
50
|
-
doc = "Sets a maximum value for throughputs to be set to. " +
|
51
|
-
"Defaults to 20,000."
|
52
|
-
|
53
|
-
opts.on('--maximum-throughput VALUE', Float, doc) do |value|
|
54
|
-
general_opts[:maximum_throughput] = value
|
55
|
-
end
|
56
|
-
|
57
|
-
opts.on( '-h', '--help', 'Display this screen' ) do
|
58
|
-
puts opts
|
59
|
-
exit
|
60
|
-
end
|
61
|
-
end.parse!
|
3
|
+
require_relative '../config/environment/common'
|
62
4
|
|
63
|
-
|
64
|
-
|
5
|
+
if ARGV[0]
|
6
|
+
DynamoAutoscale.setup_from_config(ARGV[0])
|
7
|
+
elsif ARGV[0].nil?
|
8
|
+
STDERR.puts "Usage: dynamo-autoscale path/to/config.yml"
|
65
9
|
|
66
|
-
if tables.empty? or ruleset.nil?
|
67
|
-
STDERR.puts "Usage: dynamo-autoscale ruleset table_name [another_table_name ... ]"
|
68
10
|
exit 1
|
69
|
-
|
11
|
+
elsif ARGV[0] and !File.exists?(ARGV[0])
|
12
|
+
STDERR.puts "Usage: dynamo-autoscale path/to/config.yml"
|
13
|
+
STDERR.puts "Error: The path you specified is to a file that does not exist."
|
70
14
|
|
71
|
-
if actioner_opts[:flush_after] and actioner_opts[:group_downscales].nil?
|
72
|
-
STDERR.puts "Cannot specify a flush_after value with setting --group-downscales."
|
73
15
|
exit 1
|
74
16
|
end
|
75
17
|
|
76
|
-
|
77
|
-
include DynamoAutoscale
|
78
|
-
extend DynamoAutoscale
|
79
|
-
|
80
|
-
logger.debug "Ensuring tables exist in DynamoDB..."
|
18
|
+
DynamoAutoscale.logger.info "Ensuring tables exist in DynamoDB..."
|
81
19
|
dynamo = AWS::DynamoDB.new
|
82
|
-
|
20
|
+
|
21
|
+
DynamoAutoscale.poller_opts[:tables].select! do |table_name|
|
83
22
|
if dynamo.tables[table_name].exists?
|
84
23
|
true
|
85
24
|
else
|
@@ -88,48 +27,11 @@ tables.select! do |table_name|
|
|
88
27
|
end
|
89
28
|
end
|
90
29
|
|
91
|
-
|
92
|
-
STDERR.puts "No valid tables specified."
|
93
|
-
exit 1
|
94
|
-
end
|
95
|
-
|
96
|
-
poller_opts = { tables: tables }
|
97
|
-
|
98
|
-
if general_opts[:dry_run]
|
99
|
-
poller_opts[:filters] = LocalActioner.faux_provisioning_filters
|
100
|
-
end
|
101
|
-
|
102
|
-
logger.debug "Assigning global objects..."
|
103
|
-
DynamoAutoscale.rules = RuleSet.new(ruleset)
|
104
|
-
DynamoAutoscale.dispatcher = Dispatcher.new
|
105
|
-
DynamoAutoscale.poller = CWPoller.new(poller_opts)
|
106
|
-
DynamoAutoscale.actioner_class = general_opts[:dry_run] ? LocalActioner : DynamoActioner
|
107
|
-
DynamoAutoscale.actioner_opts = actioner_opts
|
30
|
+
DynamoAutoscale.poller_class = DynamoAutoscale::CWPoller
|
108
31
|
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
if general_opts[:maximum_throughput]
|
114
|
-
Actioner.maximum_throughput = general_opts[:maximum_throughput]
|
115
|
-
end
|
116
|
-
|
117
|
-
logger.debug "Registering signal handlers..."
|
118
|
-
Signal.trap("USR1") do
|
119
|
-
logger.info "[signal] Caught SIGUSR1. Dumping CSV for all tables in #{Dir.pwd}"
|
120
|
-
|
121
|
-
DynamoAutoscale.tables.each do |name, table|
|
122
|
-
table.to_csv! path: File.join(Dir.pwd, "#{table.name}.csv")
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
Signal.trap("USR2") do
|
127
|
-
logger.info "[signal] Caught SIGUSR2. Dumping graphs for all tables in #{Dir.pwd}"
|
128
|
-
|
129
|
-
DynamoAutoscale.tables.each do |name, table|
|
130
|
-
table.graph! path: File.join(Dir.pwd, "#{table.name}.png")
|
131
|
-
end
|
32
|
+
unless DynamoAutoscale.config[:dry_run]
|
33
|
+
DynamoAutoscale.actioner_class = DynamoAutoscale::DynamoActioner
|
132
34
|
end
|
133
35
|
|
134
|
-
logger.info "Finished setup. Starting polling loop."
|
36
|
+
DynamoAutoscale.logger.info "Finished setup. Starting polling loop."
|
135
37
|
DynamoAutoscale.poller.run
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'logger'
|
2
|
+
require 'optparse'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'timecop'
|
2
5
|
require 'time'
|
3
6
|
require 'csv'
|
4
7
|
require 'tempfile'
|
@@ -6,6 +9,9 @@ require 'aws-sdk'
|
|
6
9
|
require 'active_support/all'
|
7
10
|
require 'rbtree'
|
8
11
|
require 'colored'
|
12
|
+
require 'pp'
|
13
|
+
require 'erb'
|
14
|
+
require 'pony'
|
9
15
|
|
10
16
|
require_relative '../../lib/dynamo-autoscale/logger'
|
11
17
|
require_relative '../../lib/dynamo-autoscale/poller'
|
@@ -24,28 +30,77 @@ module DynamoAutoscale
|
|
24
30
|
File.join(self.root, 'data')
|
25
31
|
end
|
26
32
|
|
27
|
-
def self.
|
28
|
-
|
33
|
+
def self.config
|
34
|
+
@@config ||= {}
|
29
35
|
end
|
30
36
|
|
31
|
-
def self.
|
32
|
-
|
37
|
+
def self.config= new_config
|
38
|
+
@@config = new_config
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.setup_from_config path, overrides = {}
|
42
|
+
logger.debug "[setup] Loading config..."
|
43
|
+
self.config = YAML.load_file(path).merge(overrides)
|
44
|
+
|
45
|
+
if config[:tables].nil? or config[:tables].empty?
|
46
|
+
STDERR.puts "You need to specify at least one table in your config's " +
|
47
|
+
":tables section."
|
33
48
|
|
34
|
-
|
35
|
-
|
49
|
+
exit 1
|
50
|
+
end
|
51
|
+
|
52
|
+
filters = config[:dry_run] ? DynamoAutoscale::LocalActioner.faux_provisioning_filters : []
|
53
|
+
if filters.empty?
|
54
|
+
logger.debug "[setup] Not running as a dry run. Hitting production Dynamo."
|
36
55
|
else
|
37
|
-
|
56
|
+
logger.debug "[setup] Running as dry run. No throughputs will be changed."
|
57
|
+
end
|
58
|
+
|
59
|
+
DynamoAutoscale.poller_opts = {
|
60
|
+
tables: config[:tables],
|
61
|
+
filters: filters,
|
62
|
+
}
|
63
|
+
|
64
|
+
logger.debug "[setup] Poller options are: #{DynamoAutoscale.poller_opts}"
|
65
|
+
|
66
|
+
DynamoAutoscale.actioner_opts = {
|
67
|
+
group_downscales: config[:group_downscales],
|
68
|
+
flush_after: config[:flush_after],
|
69
|
+
}
|
70
|
+
|
71
|
+
logger.debug "[setup] Actioner options are: #{DynamoAutoscale.actioner_opts}"
|
72
|
+
|
73
|
+
if config[:minimum_throughput]
|
74
|
+
DynamoAutoscale::Actioner.minimum_throughput = config[:minimum_throughput]
|
38
75
|
end
|
39
76
|
|
40
|
-
|
41
|
-
|
42
|
-
|
77
|
+
if config[:maximum_throughput]
|
78
|
+
DynamoAutoscale::Actioner.maximum_throughput = config[:maximum_throughput]
|
79
|
+
end
|
80
|
+
|
81
|
+
logger.debug "[setup] Minimum throughput set to: " +
|
82
|
+
"#{DynamoAutoscale::Actioner.minimum_throughput}"
|
83
|
+
logger.debug "[setup] Maximum throughput set to: " +
|
84
|
+
"#{DynamoAutoscale::Actioner.maximum_throughput}"
|
85
|
+
|
86
|
+
logger.debug "[setup] Ruleset loading from: #{config[:ruleset]}"
|
87
|
+
DynamoAutoscale.ruleset_location = config[:ruleset]
|
88
|
+
|
89
|
+
logger.debug "[setup] Loaded #{DynamoAutoscale.rules.rules.values.flatten.count} rules."
|
90
|
+
|
91
|
+
DynamoAutoscale.load_services
|
43
92
|
end
|
44
93
|
|
45
94
|
def self.require_all path
|
46
95
|
Dir[File.join(root, path, '*.rb')].each { |file| require file }
|
47
96
|
end
|
48
97
|
|
98
|
+
def self.load_services
|
99
|
+
Dir[File.join(DynamoAutoscale.root, 'config', 'services', '*.rb')].each do |path|
|
100
|
+
load path
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
49
104
|
def self.dispatcher= new_dispatcher
|
50
105
|
@@dispatcher = new_dispatcher
|
51
106
|
end
|
@@ -54,12 +109,28 @@ module DynamoAutoscale
|
|
54
109
|
@@dispatcher ||= Dispatcher.new
|
55
110
|
end
|
56
111
|
|
112
|
+
def self.poller_opts= new_poller_opts
|
113
|
+
@@poller_opts = new_poller_opts
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.poller_opts
|
117
|
+
@@poller_opts ||= {}
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.poller_class= new_poller_class
|
121
|
+
@@poller_class = new_poller_class
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.poller_class
|
125
|
+
@@poller_class ||= LocalDataPoll
|
126
|
+
end
|
127
|
+
|
57
128
|
def self.poller= new_poller
|
58
129
|
@@poller = new_poller
|
59
130
|
end
|
60
131
|
|
61
132
|
def self.poller
|
62
|
-
@@poller ||=
|
133
|
+
@@poller ||= poller_class.new(poller_opts)
|
63
134
|
end
|
64
135
|
|
65
136
|
def self.actioner_class= klass
|
@@ -79,37 +150,41 @@ module DynamoAutoscale
|
|
79
150
|
end
|
80
151
|
|
81
152
|
def self.actioners
|
82
|
-
@@actioners ||= Hash.new
|
153
|
+
@@actioners ||= Hash.new do |h, k|
|
154
|
+
h[k] = actioner_class.new(k, actioner_opts)
|
155
|
+
end
|
83
156
|
end
|
84
157
|
|
85
|
-
def self.
|
86
|
-
@@tables =
|
158
|
+
def self.reset_tables
|
159
|
+
@@tables = Hash.new { |h, k| h[k] = TableTracker.new(k) }
|
87
160
|
end
|
88
161
|
|
89
162
|
def self.tables
|
90
163
|
@@tables ||= Hash.new { |h, k| h[k] = TableTracker.new(k) }
|
91
164
|
end
|
92
165
|
|
93
|
-
def self.
|
94
|
-
@@
|
166
|
+
def self.ruleset_location
|
167
|
+
@@ruleset_location ||= nil
|
95
168
|
end
|
96
169
|
|
97
|
-
def self.
|
98
|
-
@@
|
170
|
+
def self.ruleset_location= new_ruleset_location
|
171
|
+
@@ruleset_location = new_ruleset_location
|
99
172
|
end
|
100
173
|
|
101
|
-
def self.rules
|
102
|
-
@@rules
|
174
|
+
def self.rules
|
175
|
+
@@rules ||= RuleSet.new(ruleset_location)
|
103
176
|
end
|
104
177
|
|
105
|
-
def self.
|
106
|
-
@@
|
178
|
+
def self.current_table= new_current_table
|
179
|
+
@@current_table = new_current_table
|
180
|
+
end
|
181
|
+
|
182
|
+
def self.current_table
|
183
|
+
@@current_table
|
107
184
|
end
|
108
185
|
end
|
109
186
|
|
110
187
|
DynamoAutoscale.require_all 'lib/dynamo-autoscale'
|
111
188
|
DynamoAutoscale.require_all 'lib/dynamo-autoscale/ext/**'
|
112
189
|
|
113
|
-
|
114
|
-
load path
|
115
|
-
end
|
190
|
+
DynamoAutoscale.load_services
|
data/config/environment/test.rb
CHANGED
data/config/services/aws.rb
CHANGED
@@ -1,20 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
if File.exists? './aws.yml'
|
4
|
-
config_location = './aws.yml'
|
5
|
-
elsif ENV['AWS_CONFIG'] and File.exists? ENV['AWS_CONFIG']
|
6
|
-
config_location = ENV['AWS_CONFIG']
|
7
|
-
elsif File.exists?(File.join(DynamoAutoscale.root, 'config', 'aws.yml'))
|
8
|
-
config_location = File.join(DynamoAutoscale.root, 'config', 'aws.yml')
|
9
|
-
end
|
10
|
-
|
11
|
-
if config_location.nil?
|
12
|
-
STDERR.puts "Could not load AWS configuration. Searched in: ./aws.yml and " +
|
13
|
-
"ENV['AWS_CONFIG']"
|
14
|
-
|
15
|
-
exit 1
|
16
|
-
end
|
17
|
-
|
18
|
-
DynamoAutoscale.with_config(config_location, absolute: true) do |config|
|
19
|
-
AWS.config(config)
|
1
|
+
if DynamoAutoscale.config[:aws]
|
2
|
+
AWS.config(DynamoAutoscale.config[:aws])
|
20
3
|
end
|