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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ac1fad7b038d2f7714ce5775f6faca3f607865d
4
- data.tar.gz: 9c4b3e1d56a99892049df09479be7d2196a5164e
3
+ metadata.gz: af7578d5b6ba4324962222bf6bd9cf4644e62989
4
+ data.tar.gz: 13a489abbdce7d030d46814c6580546b4392029e
5
5
  SHA512:
6
- metadata.gz: 8b22cbca0519b61ada69d8ec3d0a2bfe29fd1af82c869d158694a493a5f23f22a1772ec42c599e944e0870eb6972814a281e8aecd5f22db33d7cea671beeb9e8
7
- data.tar.gz: 58ea25f44eaef6accac79fe4e6a811c9570034a362038d4464f67ef1269833b72184517bf80f1157c71a5999d9fe93e0cd361f8607d55520d3d90376da18d7df
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
- latest = latest_auto_snapshot(i.db_instance_identifier)
68
+ instance = i.db_instance_identifier
69
+ latest = latest_auto_snapshot(instance)
38
70
  if latest
39
- db_snapshot_identifier = latest.db_snapshot_identifier
40
- resp = rds.client.copy_db_snapshot(
41
- source_db_snapshot_identifier: db_snapshot_identifier,
42
- target_db_snapshot_identifier: preserve_snapshot_name(db_snapshot_identifier),
43
- tags: [key: 'type', value: 'preserve']
44
- )
45
- s = resp.db_snapshot
46
- puts "#{s.db_snapshot_identifier}\t#{s.snapshot_create_time}"
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: options[:source_db_snapshot_identifier],
69
- target_db_snapshot_identifier: options[:target_db_snapshot_identifier],
70
- tags: [key: 'type', value: 'preserve']
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
- list = rds.db_instances.to_a
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
@@ -1,3 +1,3 @@
1
1
  module PreserveRdsSnapshot
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: preserve-rds-snapshot
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ISOBE Kazuhiko