preserve-rds-snapshot 0.2.0 → 0.3.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/README.md +14 -0
- data/lib/preserve-rds-snapshot/cli.rb +168 -15
- data/lib/preserve-rds-snapshot/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af7578d5b6ba4324962222bf6bd9cf4644e62989
|
4
|
+
data.tar.gz: 13a489abbdce7d030d46814c6580546b4392029e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfdcfa7f4f7c88dbf8425130c1b1ad54e04b6edf947b46a1ff248d45402c52ba3066a943cfa671fa88da2cdad08eb9284a009e4a231d8b567d73d4faff5e41d4
|
7
|
+
data.tar.gz: 767ffdf614c32684300dda5b69aa508814f099b6f3610f825f8e590e0a4cbb1b3c7d7bdcf7a74669a68dcc13aab4d0fe07f130253911f712fcea419f57a46323
|
data/README.md
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
|
3
3
|
Amazon RDS create a snapshot automatically. Snapshot that is created automatically, will be lost when the instance is terminated. This script preserve db snapshots by copy snapshots.
|
4
4
|
|
5
|
+
### AWS API requirement
|
6
|
+
|
7
|
+
* RDS
|
8
|
+
* describe_db_instances
|
9
|
+
* describe_db_snapshots
|
10
|
+
* copy_db_snapshot
|
11
|
+
* delete_db_snapshots
|
12
|
+
* list_tags_for_resources
|
13
|
+
* EC2
|
14
|
+
* describe_security_groups
|
15
|
+
|
16
|
+
NOTE: describe_security_groups is required to get the AWS Account Number. You can use the '--aws-account-number' option instead.
|
17
|
+
|
5
18
|
## Installation
|
6
19
|
|
7
20
|
Add this line to your application's Gemfile:
|
@@ -45,6 +58,7 @@ Options:
|
|
45
58
|
i, [--instance=INSTANCE] # target DB Instance
|
46
59
|
```
|
47
60
|
|
61
|
+
|
48
62
|
## Development
|
49
63
|
|
50
64
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. Run `bundle exec preserve-rds-snapshot` to use the code located in this directory, ignoring other installed copies of this gem.
|
@@ -4,11 +4,19 @@ require 'thor/aws'
|
|
4
4
|
module PreserveRdsSnapshot
|
5
5
|
class CLI < Thor
|
6
6
|
include Thor::Aws
|
7
|
+
PRESERVE_TAG_NAME = 'preserve-rds-snapshot'
|
7
8
|
|
8
9
|
class_option :instance,
|
9
10
|
aliases: [:i],
|
10
11
|
type: :string,
|
11
12
|
desc: 'target DB Instance'
|
13
|
+
class_option :aws_account_number,
|
14
|
+
aliases: [:n],
|
15
|
+
type: :string,
|
16
|
+
desc: 'AWS Account Number (ex: 012345678901)'
|
17
|
+
class_option :dry_run,
|
18
|
+
type: :boolean,
|
19
|
+
desc: "show only, don't modify"
|
12
20
|
|
13
21
|
desc :list, 'Show list of RDS Snapshots'
|
14
22
|
option :snapshot_type,
|
@@ -29,21 +37,55 @@ module PreserveRdsSnapshot
|
|
29
37
|
end
|
30
38
|
end
|
31
39
|
|
40
|
+
desc :init, "initialize instance"
|
41
|
+
option :generations,
|
42
|
+
aliases: [:g],
|
43
|
+
type: :numeric,
|
44
|
+
desc: "preserved snapshot generations",
|
45
|
+
default: 10
|
46
|
+
def init
|
47
|
+
begin
|
48
|
+
rds.db_instances.each do |instance|
|
49
|
+
if options[:dry_run]
|
50
|
+
puts "init(dry run)\t#{instance.db_instance_identifier}\t#{options[:generations]}"
|
51
|
+
else
|
52
|
+
if enable_preserve(instance.db_instance_identifier, options[:generations])
|
53
|
+
puts "init\t#{instance.db_instance_identifier}\t#{options[:generations]}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
fix_tags
|
58
|
+
rescue ::Aws::Errors::ServiceError => e
|
59
|
+
$stderr.puts e
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
32
63
|
desc :preserve, 'copy automated snapshot to manual'
|
33
64
|
def preserve
|
34
65
|
begin
|
35
66
|
instances = db_instances(options[:instance])
|
36
67
|
instances.each do |i|
|
37
|
-
|
68
|
+
instance = i.db_instance_identifier
|
69
|
+
latest = latest_auto_snapshot(instance)
|
38
70
|
if latest
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
71
|
+
if options[:dry_run]
|
72
|
+
puts "#{latest.db_snapshot_identifier}\t-\t-"
|
73
|
+
else
|
74
|
+
s = copy_snapshot(latest.db_snapshot_identifier)
|
75
|
+
puts "copy\t#{latest.db_snapshot_identifier}\t#{s.db_snapshot_identifier}\t#{s.snapshot_create_time}" if s
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
tag = preserve_tag(instance, 'db')
|
80
|
+
expireds = expired_snapshots(instance, tag[:value].to_i)
|
81
|
+
dry_run_msg = '(dry run)' if options[:dry_run]
|
82
|
+
expireds.each do |expired|
|
83
|
+
unless options[:dry_run]
|
84
|
+
rds.client.delete_db_snapshot(
|
85
|
+
db_snapshot_identifier: expired.db_snapshot_identifier
|
86
|
+
)
|
87
|
+
end
|
88
|
+
puts "delete#{dry_run_msg}\t#{expired.db_snapshot_identifier}"
|
47
89
|
end
|
48
90
|
end
|
49
91
|
rescue ::Aws::Errors::ServiceError => e
|
@@ -60,14 +102,20 @@ module PreserveRdsSnapshot
|
|
60
102
|
option :target_db_snapshot_identifier,
|
61
103
|
aliases: [:t],
|
62
104
|
type: :string,
|
63
|
-
desc: 'target snapshot identifier'
|
64
|
-
required: true
|
105
|
+
desc: 'target snapshot identifier'
|
65
106
|
def copy
|
107
|
+
if options[:target_db_snapshot_identifier]
|
108
|
+
target = options[:target_db_snapshot_identifier]
|
109
|
+
else
|
110
|
+
target = preserve_snapshot_name(options[:source_db_snapshot_identifier])
|
111
|
+
end
|
112
|
+
source = options[:source_db_snapshot_identifier]
|
113
|
+
|
66
114
|
begin
|
67
115
|
resp = rds.client.copy_db_snapshot(
|
68
|
-
source_db_snapshot_identifier:
|
69
|
-
target_db_snapshot_identifier:
|
70
|
-
tags: [key:
|
116
|
+
source_db_snapshot_identifier: source,
|
117
|
+
target_db_snapshot_identifier: target,
|
118
|
+
tags: [key: PRESERVE_TAG_NAME, value: 'true']
|
71
119
|
)
|
72
120
|
s = resp.db_snapshot
|
73
121
|
puts "#{s.db_snapshot_identifier}\t#{s.snapshot_create_time}"
|
@@ -107,15 +155,120 @@ module PreserveRdsSnapshot
|
|
107
155
|
if db_instance_identifier
|
108
156
|
list << rds.db_instance(db_instance_identifier)
|
109
157
|
else
|
110
|
-
|
158
|
+
rds.db_instances.each do |i|
|
159
|
+
list << i if preserve_tag(i.db_instance_identifier, 'db')
|
160
|
+
end
|
111
161
|
end
|
112
162
|
rescue ::Aws::Errors::ServiceError => e
|
113
163
|
$stderr.puts e
|
114
164
|
end
|
165
|
+
list
|
115
166
|
end
|
116
167
|
|
117
168
|
def preserve_snapshot_name(db_snapshot_identifier)
|
118
169
|
'preserve-' + db_snapshot_identifier.gsub(/^rds:/, '')
|
119
170
|
end
|
171
|
+
|
172
|
+
def aws_account_number
|
173
|
+
if options[:aws_account_number]
|
174
|
+
return options[:aws_account_number]
|
175
|
+
else
|
176
|
+
begin
|
177
|
+
return ec2.security_groups(group_names: ['default']).first.owner_id
|
178
|
+
rescue ::Aws::Errors::ServiceError => e
|
179
|
+
$stderr.puts e
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
def rds_arn(resource_id, type)
|
185
|
+
"arn:aws:rds:#{options[:region]}:#{aws_account_number}:#{type}:#{resource_id}"
|
186
|
+
end
|
187
|
+
|
188
|
+
def preserve_tag(resource_id, type)
|
189
|
+
tag = nil
|
190
|
+
begin
|
191
|
+
resp = rds.client.list_tags_for_resource(
|
192
|
+
resource_name: rds_arn(resource_id, type)
|
193
|
+
)
|
194
|
+
tag = resp.tag_list.find {|t| t[:key] == PRESERVE_TAG_NAME}
|
195
|
+
rescue ::Aws::Errors::ServiceError => e
|
196
|
+
$stderr.puts e
|
197
|
+
end
|
198
|
+
tag
|
199
|
+
end
|
200
|
+
|
201
|
+
def enable_preserve(resource_id, generations)
|
202
|
+
return false unless generations.kind_of? Integer
|
203
|
+
begin
|
204
|
+
tag = preserve_tag(resource_id, 'db')
|
205
|
+
unless tag
|
206
|
+
resp = rds.client.add_tags_to_resource(
|
207
|
+
resource_name: rds_arn(resource_id, 'db'),
|
208
|
+
tags: [{key: PRESERVE_TAG_NAME, value: generations.to_s}]
|
209
|
+
)
|
210
|
+
return resp.successful?
|
211
|
+
end
|
212
|
+
rescue ::Aws::Errors::ServiceError => e
|
213
|
+
$stderr.puts e
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# fix v0.2.0 format tag to latest
|
218
|
+
def fix_tags
|
219
|
+
begin
|
220
|
+
rds.client.describe_db_snapshots(
|
221
|
+
snapshot_type: 'manual'
|
222
|
+
).db_snapshots.each do |s|
|
223
|
+
arn = rds_arn(s.db_snapshot_identifier, 'snapshot')
|
224
|
+
resp = rds.client.list_tags_for_resource(
|
225
|
+
resource_name: arn
|
226
|
+
)
|
227
|
+
tag = resp.tag_list.find {|t| t[:key] == 'type' && t[:value] == 'preserve'}
|
228
|
+
if tag
|
229
|
+
rds.client.add_tags_to_resource(
|
230
|
+
resource_name: arn,
|
231
|
+
tags: [{key: PRESERVE_TAG_NAME, value: 'true'}]
|
232
|
+
)
|
233
|
+
rds.client.remove_tags_from_resource(
|
234
|
+
resource_name: arn,
|
235
|
+
tag_keys: ['type']
|
236
|
+
)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
rescue ::Aws::Errors::ServiceError => e
|
240
|
+
$stderr.puts e
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
def copy_snapshot(db_snapshot_identifier)
|
245
|
+
begin
|
246
|
+
resp = rds.client.copy_db_snapshot(
|
247
|
+
source_db_snapshot_identifier: db_snapshot_identifier,
|
248
|
+
target_db_snapshot_identifier: preserve_snapshot_name(db_snapshot_identifier),
|
249
|
+
tags: [key: PRESERVE_TAG_NAME, value: 'true']
|
250
|
+
)
|
251
|
+
return resp.db_snapshot
|
252
|
+
rescue ::Aws::Errors::ServiceError => e
|
253
|
+
$stderr.puts e
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def expired_snapshots(db_instance_identifier, generations)
|
258
|
+
expired_snapshots = []
|
259
|
+
begin
|
260
|
+
resp = rds.client.describe_db_snapshots(
|
261
|
+
snapshot_type: 'manual',
|
262
|
+
db_instance_identifier: db_instance_identifier
|
263
|
+
)
|
264
|
+
snapshots = resp.db_snapshots.select {|s|
|
265
|
+
preserve_tag(s.db_snapshot_identifier, 'snapshot')
|
266
|
+
}.sort_by(&:snapshot_create_time).reverse
|
267
|
+
expired_snapshots = snapshots[generations..-1] if snapshots.size > generations
|
268
|
+
rescue ::Aws::Errors::ServiceError => e
|
269
|
+
$stderr.puts e
|
270
|
+
end
|
271
|
+
expired_snapshots
|
272
|
+
end
|
120
273
|
end
|
121
274
|
end
|