automan 2.3.8 → 2.4.0
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/lib/automan/cli/snapper.rb +43 -26
- data/lib/automan/rds/snapshot.rb +65 -73
- data/lib/automan/version.rb +1 -1
- data/spec/rds/snapshot_spec.rb +1 -72
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 556e8ef30f82380e1d0aa07bf033feb1dd2bf574
|
4
|
+
data.tar.gz: cf5aea391bdafeb455f5c9e9b0084797fced6881
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cac1683af9f00f2215e4430bc3787b1ada1f86d23a6de920b7e55cc800de2383aa7d8bbe4ab198474f134b79fdf5df006c88e8f8cb711f4f9d1cd4570379984
|
7
|
+
data.tar.gz: 90f61b9c7ccc3f75250e9c2c1efea0f405c31027ed9ae5c18aa6d42414a85cba396650d40630de830d6fe81299a5b97cdcce9e0fa9e03556be164c9365d3dcb3
|
data/lib/automan/cli/snapper.rb
CHANGED
@@ -7,28 +7,37 @@ module Automan::Cli
|
|
7
7
|
desc "create", "create a snapshot"
|
8
8
|
|
9
9
|
option :environment,
|
10
|
-
|
11
|
-
|
10
|
+
aliases: "-e",
|
11
|
+
desc: "environment of database to snapshot"
|
12
12
|
|
13
13
|
option :database,
|
14
|
-
|
15
|
-
|
14
|
+
aliases: "-d",
|
15
|
+
desc: "name of the database to snapshot"
|
16
16
|
|
17
17
|
option :name,
|
18
|
-
|
19
|
-
|
18
|
+
aliases: "-n",
|
19
|
+
desc: "what to name the snapshot"
|
20
20
|
|
21
21
|
option :prune,
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
aliases: "-p",
|
23
|
+
type: :boolean,
|
24
|
+
default: true,
|
25
|
+
desc: "make this snapshot prunable and delete other prunable snapshots older than 30 days"
|
26
|
+
|
27
|
+
option :type,
|
28
|
+
aliases: "-t",
|
29
|
+
desc: "type of snapshot. When pruning, only snapshots of the specified type will be deleted."
|
30
|
+
|
31
|
+
option :max_snapshots,
|
32
|
+
aliases: "-m",
|
33
|
+
desc: "Maximum number of snapshots of this type to retain",
|
34
|
+
type: :numeric
|
26
35
|
|
27
36
|
option :wait_for_completion,
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
37
|
+
aliases: "-w",
|
38
|
+
type: :boolean,
|
39
|
+
default: false,
|
40
|
+
desc: "wait until snapshot is finished before exiting script"
|
32
41
|
|
33
42
|
def create
|
34
43
|
if options[:database].nil? && options[:environment].nil?
|
@@ -37,6 +46,14 @@ module Automan::Cli
|
|
37
46
|
exit 1
|
38
47
|
end
|
39
48
|
|
49
|
+
if options[:prune]
|
50
|
+
if options[:type].nil? || options[:max_snapshots].nil?
|
51
|
+
puts "Must specify snapshot type and max snapshots to retain when pruning"
|
52
|
+
help "create"
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
40
57
|
aws_opts = options.dup
|
41
58
|
aws_opts[:log_aws] = true
|
42
59
|
s = Automan::RDS::Snapshot.new(aws_opts)
|
@@ -47,9 +64,9 @@ module Automan::Cli
|
|
47
64
|
desc "delete", "delete a snapshot"
|
48
65
|
|
49
66
|
option :name,
|
50
|
-
|
51
|
-
|
52
|
-
|
67
|
+
required: true,
|
68
|
+
aliases: "-n",
|
69
|
+
desc: "name of snapshot to delete"
|
53
70
|
|
54
71
|
def delete
|
55
72
|
Automan::RDS::Snapshot.new(options).delete
|
@@ -58,12 +75,12 @@ module Automan::Cli
|
|
58
75
|
desc "latest", "find the most recent snapshot"
|
59
76
|
|
60
77
|
option :database,
|
61
|
-
|
62
|
-
|
78
|
+
aliases: "-d",
|
79
|
+
desc: "name of the database to snapshot"
|
63
80
|
|
64
81
|
option :environment,
|
65
|
-
|
66
|
-
|
82
|
+
aliases: "-e",
|
83
|
+
desc: "environment of database to snapshot"
|
67
84
|
|
68
85
|
def latest
|
69
86
|
if options[:database].nil? && options[:environment].nil?
|
@@ -78,12 +95,12 @@ module Automan::Cli
|
|
78
95
|
desc "count", "return the number of snapshots"
|
79
96
|
|
80
97
|
option :environment,
|
81
|
-
|
82
|
-
|
98
|
+
aliases: "-e",
|
99
|
+
desc: "environment of database to snapshot"
|
83
100
|
|
84
101
|
option :database,
|
85
|
-
|
86
|
-
|
102
|
+
aliases: "-d",
|
103
|
+
desc: "name of the database to snapshot"
|
87
104
|
|
88
105
|
def count
|
89
106
|
if options[:database].nil? && options[:environment].nil?
|
@@ -94,6 +111,6 @@ module Automan::Cli
|
|
94
111
|
|
95
112
|
Automan::RDS::Snapshot.new(options).count_snapshots
|
96
113
|
end
|
97
|
-
|
114
|
+
|
98
115
|
end
|
99
116
|
end
|
data/lib/automan/rds/snapshot.rb
CHANGED
@@ -8,13 +8,14 @@ module Automan::RDS
|
|
8
8
|
:name,
|
9
9
|
:environment,
|
10
10
|
:prune,
|
11
|
+
:type,
|
12
|
+
:max_snapshots,
|
11
13
|
:wait_for_completion
|
12
14
|
|
13
|
-
attr_accessor :max_snapshots
|
14
|
-
|
15
15
|
def initialize(options={})
|
16
16
|
@prune = true
|
17
17
|
@wait_for_completion = false
|
18
|
+
@max_snapshots = 50
|
18
19
|
super
|
19
20
|
@wait = Wait.new({
|
20
21
|
delay: 30,
|
@@ -24,9 +25,8 @@ module Automan::RDS
|
|
24
25
|
logger: @logger
|
25
26
|
})
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
else
|
28
|
+
# DEPRECATED: use --max-snapshots instead
|
29
|
+
if ENV['MAX_SNAPSHOTS']
|
30
30
|
@max_snapshots = ENV['MAX_SNAPSHOTS'].to_i
|
31
31
|
end
|
32
32
|
end
|
@@ -83,22 +83,12 @@ module Automan::RDS
|
|
83
83
|
|
84
84
|
wait_until_database_available(db)
|
85
85
|
|
86
|
-
if snapshot_count >= max_snapshots
|
87
|
-
logger.info "Too many snapshots (>= #{max_snapshots}), deleting oldest prunable."
|
88
|
-
old = nil
|
89
|
-
AWS.memoize do
|
90
|
-
old = oldest_prunable_snapshot
|
91
|
-
end
|
92
|
-
logger.info "Deleting #{old.id}"
|
93
|
-
old.delete
|
94
|
-
end
|
95
|
-
|
96
86
|
logger.info "Creating snapshot #{myname} for #{db.id}"
|
97
87
|
snap = db.create_snapshot(myname)
|
98
88
|
|
99
89
|
if prune == true
|
100
90
|
logger.info "Setting snapshot to be prunable and tagging environment"
|
101
|
-
set_prunable_and_env(snap
|
91
|
+
set_prunable_and_env(snap)
|
102
92
|
end
|
103
93
|
|
104
94
|
if wait_for_completion == true
|
@@ -118,8 +108,7 @@ module Automan::RDS
|
|
118
108
|
end
|
119
109
|
|
120
110
|
def db_environment(db)
|
121
|
-
|
122
|
-
return tags(arn)['Name']
|
111
|
+
return db_tags(db)['Name']
|
123
112
|
end
|
124
113
|
|
125
114
|
def default_snapshot_name(db)
|
@@ -149,10 +138,14 @@ module Automan::RDS
|
|
149
138
|
end
|
150
139
|
|
151
140
|
# tag with CanPrune
|
152
|
-
def set_prunable_and_env(snapshot
|
141
|
+
def set_prunable_and_env(snapshot)
|
153
142
|
opts = {
|
154
143
|
resource_name: snapshot_arn(snapshot),
|
155
|
-
tags: [
|
144
|
+
tags: [
|
145
|
+
{ key: 'CanPrune', value: 'yes'},
|
146
|
+
{ key: 'Environment', value: environment},
|
147
|
+
{ key: 'Type', value: type }
|
148
|
+
]
|
156
149
|
}
|
157
150
|
response = rds.client.add_tags_to_resource opts
|
158
151
|
|
@@ -168,7 +161,17 @@ module Automan::RDS
|
|
168
161
|
rds.db_snapshots[name].delete
|
169
162
|
end
|
170
163
|
|
171
|
-
def
|
164
|
+
def db_tags(db)
|
165
|
+
arn = db_arn(db)
|
166
|
+
resource_tags(arn)
|
167
|
+
end
|
168
|
+
|
169
|
+
def snapshot_tags(snapshot)
|
170
|
+
arn = snapshot_arn(snapshot)
|
171
|
+
resource_tags(arn)
|
172
|
+
end
|
173
|
+
|
174
|
+
def resource_tags(arn)
|
172
175
|
opts = {
|
173
176
|
resource_name: arn
|
174
177
|
}
|
@@ -185,67 +188,63 @@ module Automan::RDS
|
|
185
188
|
result
|
186
189
|
end
|
187
190
|
|
188
|
-
def can_prune?(snapshot)
|
189
|
-
tagged_can_prune?(snapshot) && available?(snapshot) && manual?(snapshot)
|
190
|
-
end
|
191
|
-
|
192
|
-
def is_env?(snapshot,environment)
|
193
|
-
tagged_env?(snapshot,environment) && available?(snapshot) && manual?(snapshot)
|
194
|
-
end
|
195
|
-
|
196
|
-
def tagged_env?(snapshot,environment)
|
197
|
-
arn = snapshot_arn(snapshot)
|
198
|
-
tags(arn)['Environment'] == environment
|
199
|
-
end
|
200
|
-
|
201
|
-
def tagged_can_prune?(snapshot)
|
202
|
-
arn = snapshot_arn(snapshot)
|
203
|
-
tags(arn)['CanPrune'] == 'yes'
|
204
|
-
end
|
205
|
-
|
206
191
|
def available?(snapshot)
|
207
192
|
snapshot.status == 'available'
|
208
193
|
end
|
209
194
|
|
210
|
-
def manual?(snapshot)
|
211
|
-
snapshot.snapshot_type == 'manual'
|
212
|
-
end
|
213
|
-
|
214
|
-
# older than a month?
|
215
|
-
def too_old?(time)
|
216
|
-
time.utc < (Time.now.utc - 60*60*24*30)
|
217
|
-
end
|
218
|
-
|
219
195
|
def get_all_snapshots
|
220
196
|
rds.snapshots
|
221
197
|
end
|
222
198
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
199
|
+
# tags = {'mytagkey' => 'mytagvalue', ...}
|
200
|
+
def snapshot_has_tags?(snapshot, tags)
|
201
|
+
snap_tags = snapshot_tags(snapshot)
|
202
|
+
tags.each do |tk,tv|
|
203
|
+
if snap_tags[tk] != tv
|
204
|
+
#logger.info("qtags: #{tags.to_json} snap_tags: #{snap_tags.to_json}")
|
205
|
+
return false
|
206
|
+
end
|
207
|
+
end
|
208
|
+
true
|
230
209
|
end
|
231
210
|
|
232
|
-
|
233
|
-
|
211
|
+
# tags = {'mytagkey' => 'mytagvalue', ...}
|
212
|
+
def snapshots_with_tags(tags)
|
213
|
+
rds.snapshots.select {|s| snapshot_has_tags?(s, tags)}
|
234
214
|
end
|
235
215
|
|
216
|
+
#
|
217
|
+
# There is a big broken assumption here!
|
218
|
+
# We enumerate all snapshots of the *current* environment db
|
219
|
+
# What if that db is new and we have snapshots from previous
|
220
|
+
# dbs? The dev1 db is replaced every day!
|
221
|
+
# So prunable_snapshots will only return the list of snapshots
|
222
|
+
# from the *current* dev1 db and ignore all others!
|
223
|
+
#
|
236
224
|
def prune_snapshots
|
237
225
|
logger.info "Pruning old db snapshots"
|
238
226
|
|
227
|
+
tags = {
|
228
|
+
'Environment' => environment,
|
229
|
+
'Type' => type,
|
230
|
+
'CanPrune' => 'yes'
|
231
|
+
}
|
232
|
+
sorted_snaps = nil
|
239
233
|
AWS.memoize do
|
240
|
-
|
234
|
+
sorted_snaps = snapshots_with_tags(tags).sort_by {|s| s.created_at}
|
235
|
+
end
|
241
236
|
|
242
|
-
|
243
|
-
snapshot_name = snapshot.db_snapshot_identifier
|
237
|
+
logger.info "snaps #{sorted_snaps.count} max #{max_snapshots}"
|
244
238
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
239
|
+
if sorted_snaps.count >= max_snapshots
|
240
|
+
logger.info "Too many snapshots ( #{sorted_snaps.count} >= #{max_snapshots})."
|
241
|
+
number_to_delete = sorted_snaps.count - max_snapshots + 1
|
242
|
+
logger.info "deleting #{number_to_delete}."
|
243
|
+
|
244
|
+
condemned = sorted_snaps.take(number_to_delete)
|
245
|
+
condemned.each do |snap|
|
246
|
+
logger.info "Deleting #{snap.id}"
|
247
|
+
snap.delete
|
249
248
|
end
|
250
249
|
end
|
251
250
|
end
|
@@ -265,16 +264,9 @@ module Automan::RDS
|
|
265
264
|
log_options
|
266
265
|
logger.info "Finding most recent snapshot for #{environment}"
|
267
266
|
|
268
|
-
|
269
|
-
|
270
|
-
envsnaps=[]
|
271
|
-
allsnaps.each do |onesnap|
|
272
|
-
if is_env?(onesnap,environment)
|
273
|
-
envsnaps.push(onesnap)
|
274
|
-
end
|
275
|
-
end
|
267
|
+
tags = { 'Environment' => environment }
|
268
|
+
s = snapshots_with_tags(tags).sort_by {|s| s.created_at}.last
|
276
269
|
|
277
|
-
s=envsnaps.sort_by {|i| i.created_at }.last
|
278
270
|
logger.info "Most recent snapshot is #{s.id}"
|
279
271
|
s.id
|
280
272
|
end
|
data/lib/automan/version.rb
CHANGED
data/spec/rds/snapshot_spec.rb
CHANGED
@@ -58,36 +58,6 @@ describe Automan::RDS::Snapshot do
|
|
58
58
|
|
59
59
|
end
|
60
60
|
|
61
|
-
describe '#tagged_can_prune?' do
|
62
|
-
subject() do
|
63
|
-
AWS.stub!
|
64
|
-
s = Automan::RDS::Snapshot.new
|
65
|
-
s.logger = Logger.new('/dev/null')
|
66
|
-
allow(s).to receive(:snapshot_arn)
|
67
|
-
s
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'returns true if snapshot is tagged with CanPrune=yes' do
|
71
|
-
allow(subject).to receive(:tags).and_return( {'CanPrune' => 'yes'} )
|
72
|
-
expect(subject.tagged_can_prune?( double() )).to be_truthy
|
73
|
-
end
|
74
|
-
|
75
|
-
it 'returns false if snapshot is missing CanPrune tag' do
|
76
|
-
allow(subject).to receive(:tags).and_return( {} )
|
77
|
-
expect(subject.tagged_can_prune?( double() )).to be_falsey
|
78
|
-
end
|
79
|
-
|
80
|
-
it 'returns false if snapshot is tagged with CanPrune=nil' do
|
81
|
-
allow(subject).to receive(:tags).and_return( {'CanPrune' => nil} )
|
82
|
-
expect(subject.tagged_can_prune?( double() )).to be_falsey
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'returns false if snapshot is tagged with CanPrune=foo' do
|
86
|
-
allow(subject).to receive(:tags).and_return( {'CanPrune' => 'foo'} )
|
87
|
-
expect(subject.tagged_can_prune?( double() )).to be_falsey
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
61
|
describe '#available?' do
|
92
62
|
subject() do
|
93
63
|
AWS.stub!
|
@@ -106,45 +76,4 @@ describe Automan::RDS::Snapshot do
|
|
106
76
|
expect(subject.available?(snap)).to be_falsey
|
107
77
|
end
|
108
78
|
end
|
109
|
-
|
110
|
-
describe '#manual?' do
|
111
|
-
let(:snap) { double }
|
112
|
-
subject() do
|
113
|
-
AWS.stub!
|
114
|
-
s = Automan::RDS::Snapshot.new
|
115
|
-
s.logger = Logger.new('/dev/null')
|
116
|
-
s
|
117
|
-
end
|
118
|
-
|
119
|
-
it 'returns true if type is "manual"' do
|
120
|
-
allow(snap).to receive(:snapshot_type).and_return('manual')
|
121
|
-
expect(subject.manual?(snap)).to be_truthy
|
122
|
-
end
|
123
|
-
|
124
|
-
it 'returns false if type is foo' do
|
125
|
-
allow(snap).to receive(:snapshot_type).and_return('foo')
|
126
|
-
expect(subject.manual?(snap)).to be_falsey
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe '#prunable_snapshots' do
|
131
|
-
let(:snap) { double }
|
132
|
-
subject() do
|
133
|
-
AWS.stub!
|
134
|
-
s = Automan::RDS::Snapshot.new
|
135
|
-
s.logger = Logger.new('/dev/null')
|
136
|
-
allow(s).to receive(:get_all_snapshots).and_return( [ snap ] )
|
137
|
-
s
|
138
|
-
end
|
139
|
-
|
140
|
-
it 'includes snapshots which can be pruned' do
|
141
|
-
allow(subject).to receive(:can_prune?).and_return(true)
|
142
|
-
expect(subject.prunable_snapshots).to include(snap)
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'excludes snapshots which should not be pruned' do
|
146
|
-
allow(subject).to receive(:can_prune?).and_return(false)
|
147
|
-
expect(subject.prunable_snapshots).to_not include(snap)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: automan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Chalfant
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-11-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -262,7 +262,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
262
262
|
version: '0'
|
263
263
|
requirements: []
|
264
264
|
rubyforge_project:
|
265
|
-
rubygems_version: 2.
|
265
|
+
rubygems_version: 2.2.2
|
266
266
|
signing_key:
|
267
267
|
specification_version: 4
|
268
268
|
summary: Automates common AWS ops
|