rds-rotate-db-snapshots 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca82ea61b9da51d2888c98f21fda30ce73850b265dcb01b75c2e99c0b84d597d
4
- data.tar.gz: 778fc695f23d0c713bedad76b2ce4893401c50d270df596c1324b52dcd0546b7
3
+ metadata.gz: 867b60671bdab535228d9730a2b7fbee3e1b9e44568f07215cc0c2eee6881a4b
4
+ data.tar.gz: f204ef40c89395f6fc652d049854fd04cf10759e915907c9b04172873b1a0772
5
5
  SHA512:
6
- metadata.gz: f8bca5be1bb1d4324ae674677f574707782f92cb9717ec66010a8686ceca450d0127017c109289738c487f25131f6cf355ad60d4a33d8c71d0b2c2278ea24b68
7
- data.tar.gz: b00fe71aab391fa82e64b52f1de28bfc68632f0ae5a7961b5e1358fb55a28d19f1d9dd44dbcd59e81ce06204b8d26f290c2c253e303386144b0525c75ff1c3ec
6
+ metadata.gz: 85ff15bc60ddf07b213671d9449005135428cb477b9c6bc51ee570d459ce238b4672dac8945e14ec5dc543fb8d538b52dad742bfd5e342c6901573bda390309e
7
+ data.tar.gz: 8b01afd618121cf7f6f8e237f81fadd782f056f6a1ab20eb1d9d7e469e0fb2e49c6872ed2a2fe7ecbfb008b418a0db2967ff281bfa358b0fafa372dea5f294ca
@@ -6,38 +6,58 @@ on:
6
6
  pull_request:
7
7
  branches: ["main"]
8
8
 
9
+ env:
10
+ RUBY_MAIN_VERSION: '3.2'
11
+
9
12
  jobs:
13
+ rubocop:
14
+ runs-on: ubuntu-20.04
15
+ steps:
16
+ - name: Checkout code
17
+ uses: actions/checkout@v3
18
+ - name: Install Ruby and gems
19
+ uses: ruby/setup-ruby@319066216501fbd5e2d568f14b7d68c19fb67a5d #v1.133.1
20
+ with:
21
+ bundler-cache: true
22
+ ruby-version: ${{ env.RUBY_MAIN_VERSION }}.0
23
+ - name: Install Bundler
24
+ run: gem install bundler
25
+ - name: Bundle Install
26
+ run: bundle install
27
+ - name: Rubocop
28
+ run: bundle exec rubocop
29
+
10
30
  test:
11
31
  runs-on: ubuntu-20.04
12
32
  strategy:
13
33
  matrix:
14
- ruby_version: [2.7, 3.0, 3.1]
34
+ ruby_version: ['2.7', '3.0', '3.1', '3.2']
15
35
  steps:
16
36
  - name: Checkout code
17
37
  uses: actions/checkout@v3
18
38
  - name: Install Ruby and gems
19
- uses: ruby/setup-ruby@03b78bdda287ae04217ee12e4b64996630a03542 #v1.131.0
39
+ uses: ruby/setup-ruby@319066216501fbd5e2d568f14b7d68c19fb67a5d #v1.133.1
20
40
  with:
21
41
  bundler-cache: true
22
42
  ruby-version: ${{ matrix.ruby_version }}
23
43
  - name: Install Bundler
24
44
  run: gem install bundler
45
+ - name: Setup Code Climate test-reporter
46
+ if: ${{ matrix.ruby_version == env.RUBY_MAIN_VERSION }}
47
+ run: |
48
+ curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
49
+ chmod +x ./cc-test-reporter
50
+ ./cc-test-reporter before-build
25
51
  - name: Bundle Install
26
52
  run: bundle install
27
53
  - name: Test
28
54
  run: bundle exec rspec
55
+ - name: Publish Codeclimate Code Coverage
56
+ if: ${{ matrix.ruby_version == env.RUBY_MAIN_VERSION }}
57
+ run: |
58
+ ./cc-test-reporter after-build -r ${{secrets.CC_TEST_REPORTER_ID}}
29
59
  - name: Coveralls Parallel
60
+ if: ${{ matrix.ruby_version == env.RUBY_MAIN_VERSION }}
30
61
  uses: coverallsapp/github-action@master
31
62
  with:
32
63
  github-token: ${{ secrets.github_token }}
33
- flag-name: run-${{ matrix.ruby_version }}
34
- parallel: true
35
- finish:
36
- needs: test
37
- runs-on: ubuntu-latest
38
- steps:
39
- - name: Coveralls Finished
40
- uses: coverallsapp/github-action@master
41
- with:
42
- github-token: ${{ secrets.github_token }}
43
- parallel-finished: true
data/.rubocop.yml ADDED
@@ -0,0 +1,93 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ require:
4
+ - rubocop-rspec
5
+
6
+ AllCops:
7
+ NewCops: enable
8
+ TargetRubyVersion: 3.2.0
9
+ Exclude:
10
+ - 'bin/{bundle,rails,rake}'
11
+ - vendor/**/*
12
+
13
+ Layout/LineLength:
14
+ Max: 120
15
+
16
+ Bundler/OrderedGems:
17
+ Enabled: false
18
+
19
+ Lint/RescueException:
20
+ Enabled: true
21
+
22
+ Style/EmptyElse:
23
+ EnforcedStyle: empty
24
+
25
+ Style/FrozenStringLiteralComment:
26
+ Enabled: false
27
+
28
+ Style/RescueStandardError:
29
+ Enabled: false
30
+
31
+ Style/StringLiterals:
32
+ Enabled: false
33
+
34
+ Layout/SpaceInLambdaLiteral:
35
+ Enabled: false
36
+
37
+ Style/Lambda:
38
+ Enabled: false
39
+
40
+ Style/NumericLiteralPrefix:
41
+ Enabled: false
42
+
43
+ Style/EmptyMethod:
44
+ Enabled: false
45
+
46
+ Style/ParallelAssignment:
47
+ Enabled: false
48
+
49
+ Layout/EmptyLinesAroundExceptionHandlingKeywords:
50
+ Enabled: false
51
+
52
+ Layout/FirstHashElementIndentation:
53
+ Enabled: false
54
+
55
+ Layout/ParameterAlignment:
56
+ Enabled: false
57
+
58
+ Naming/RescuedExceptionsVariableName:
59
+ Enabled: false
60
+
61
+ Style/Documentation:
62
+ Enabled: false
63
+
64
+ Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
65
+ Enabled: true
66
+ Lint/EmptyBlock: # (new in 1.1)
67
+ Enabled: true
68
+ Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
69
+ Enabled: true
70
+ Lint/ToEnumArguments: # (new in 1.1)
71
+ Enabled: true
72
+ Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
73
+ Enabled: true
74
+ Style/ArgumentsForwarding: # (new in 1.1)
75
+ Enabled: true
76
+ Style/CollectionCompact: # (new in 1.2)
77
+ Enabled: true
78
+ Style/DocumentDynamicEvalDefinition: # (new in 1.1)
79
+ Enabled: true
80
+ Style/NegatedIfElseCondition: # (new in 1.2)
81
+ Enabled: true
82
+ Style/SwapValues: # (new in 1.1)
83
+ Enabled: true
84
+
85
+ Metrics/BlockLength:
86
+ Exclude:
87
+ - 'spec/**/*' # Swagger specs require large blocks
88
+
89
+ Style/HashSyntax:
90
+ EnforcedShorthandSyntax: never
91
+
92
+ RSpec/MultipleMemoizedHelpers:
93
+ Enabled: false
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,127 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2023-01-10 16:06:29 UTC using RuboCop version 1.43.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: Severity, Include.
11
+ # Include: **/*.gemspec
12
+ Gemspec/RequiredRubyVersion:
13
+ Exclude:
14
+ - 'rds-rotate-db-snapshots.gemspec'
15
+
16
+ # Offense count: 3
17
+ # This cop supports safe autocorrection (--autocorrect).
18
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
19
+ # URISchemes: http, https
20
+ Layout/LineLength:
21
+ Max: 146
22
+
23
+ # Offense count: 1
24
+ Lint/UnreachableCode:
25
+ Exclude:
26
+ - 'lib/rds_rotate_db_snapshots/options_parser.rb'
27
+
28
+ # Offense count: 4
29
+ Lint/UselessAssignment:
30
+ Exclude:
31
+ - 'bin/rds-rotate-db-snapshots'
32
+ - 'lib/rds_rotate_db_snapshots/actions.rb'
33
+
34
+ # Offense count: 5
35
+ # Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, CountRepeatedAttributes.
36
+ Metrics/AbcSize:
37
+ Max: 56
38
+
39
+ # Offense count: 2
40
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods, inherit_mode.
41
+ # AllowedMethods: refine
42
+ Metrics/BlockLength:
43
+ Max: 42
44
+
45
+ # Offense count: 1
46
+ # Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
47
+ Metrics/CyclomaticComplexity:
48
+ Max: 15
49
+
50
+ # Offense count: 6
51
+ # Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods.
52
+ Metrics/MethodLength:
53
+ Max: 44
54
+
55
+ # Offense count: 1
56
+ # Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
57
+ Metrics/PerceivedComplexity:
58
+ Max: 16
59
+
60
+ # Offense count: 1
61
+ # Configuration parameters: EnforcedStyleForLeadingUnderscores.
62
+ # SupportedStylesForLeadingUnderscores: disallowed, required, optional
63
+ Naming/MemoizedInstanceVariableName:
64
+ Exclude:
65
+ - 'lib/rds_rotate_db_snapshots/options_parser.rb'
66
+
67
+ # Offense count: 1
68
+ # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
69
+ # AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
70
+ Naming/MethodParameterName:
71
+ Exclude:
72
+ - 'lib/rds_rotate_db_snapshots/options_parser.rb'
73
+
74
+ # Offense count: 3
75
+ # Configuration parameters: CountAsOne.
76
+ RSpec/ExampleLength:
77
+ Max: 9
78
+
79
+ # Offense count: 10
80
+ # Configuration parameters: .
81
+ # SupportedStyles: have_received, receive
82
+ RSpec/MessageSpies:
83
+ EnforcedStyle: receive
84
+
85
+ # Offense count: 6
86
+ RSpec/MultipleExpectations:
87
+ Max: 6
88
+
89
+ # Offense count: 17
90
+ # Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
91
+ # SupportedStyles: always, named_only
92
+ RSpec/NamedSubject:
93
+ Exclude:
94
+ - 'spec/lib/rds_rotate_db_snapshots/action_wrappers_spec.rb'
95
+ - 'spec/lib/rds_rotate_db_snapshots/options_parser_spec.rb'
96
+ - 'spec/lib/rds_rotate_db_snapshots_spec.rb'
97
+
98
+ # Offense count: 1
99
+ RSpec/StubbedMock:
100
+ Exclude:
101
+ - 'spec/lib/rds_rotate_db_snapshots/actions_spec.rb'
102
+
103
+ # Offense count: 6
104
+ RSpec/SubjectStub:
105
+ Exclude:
106
+ - 'spec/lib/rds_rotate_db_snapshots/action_wrappers_spec.rb'
107
+ - 'spec/lib/rds_rotate_db_snapshots/actions_spec.rb'
108
+ - 'spec/lib/rds_rotate_db_snapshots_spec.rb'
109
+
110
+ # Offense count: 1
111
+ # Configuration parameters: IgnoreNameless, IgnoreSymbolicNames.
112
+ RSpec/VerifiedDoubles:
113
+ Exclude:
114
+ - 'spec/lib/rds_rotate_db_snapshots/actions_spec.rb'
115
+
116
+ # Offense count: 1
117
+ # Configuration parameters: AllowedVariables.
118
+ Style/GlobalVars:
119
+ Exclude:
120
+ - 'spec/helper.rb'
121
+
122
+ # Offense count: 3
123
+ # This cop supports safe autocorrection (--autocorrect).
124
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
125
+ # URISchemes: http, https
126
+ Layout/LineLength:
127
+ Max: 146
data/Gemfile CHANGED
@@ -1,18 +1,19 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gem 'aws-sdk-rds', '~> 1'
4
- gem "rake"
5
4
 
6
5
  group :development do
6
+ gem "rake"
7
7
  gem 'juwelier'
8
8
  gem "pry"
9
9
  gem "pry-byebug"
10
+ gem "rubocop"
11
+ gem "rubocop-rspec"
10
12
  end
11
13
 
12
14
  group :test do
13
15
  gem "rspec", ">= 3.2"
14
16
  gem "rspec-mocks", ">= 3"
15
- gem "rubocop", "~> 0.50.0"
16
17
  gem "simplecov", ">= 0.13"
17
18
  gem 'simplecov-lcov', '~> 0.8.0'
18
19
  gem "webmock"
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  [<img src="https://badge.fury.io/rb/rds-rotate-db-snapshots.svg" alt="Gem
4
4
  Version" />](https://badge.fury.io/rb/rds-rotate-db-snapshots) [![CI](https://github.com/serg-kovalev/rds-rotate-db-snapshots/actions/workflows/ci.yml/badge.svg?query=branch%3Amain+event%3Apush)](https://github.com/serg-kovalev/rds-rotate-db-snapshots/actions/workflows/ci.yml?query=branch%3Amain+event%3Apush) [![CodeQL](https://github.com/serg-kovalev/rds-rotate-db-snapshots/actions/workflows/codeql.yml/badge.svg?query=branch%3Amain+event%3Apush)](https://github.com/serg-kovalev/rds-rotate-db-snapshots/actions/workflows/codeql.yml?query=branch%3Amain+event%3Apush)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/45bfe7dc4f21ac1403cb/maintainability)](https://codeclimate.com/github/serg-kovalev/rds-rotate-db-snapshots/maintainability)
6
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/45bfe7dc4f21ac1403cb/test_coverage)](https://codeclimate.com/github/serg-kovalev/rds-rotate-db-snapshots/test_coverage)
5
7
 
6
8
  Provides a simple way to rotate db snapshots in Amazon Relational Database
7
9
  Service (RDS).
@@ -9,6 +11,7 @@ Service (RDS).
9
11
  ## Tested on Rubies
10
12
 
11
13
  - 2.7
14
+ - 3.0
12
15
  - 3.1
13
16
  - 3.2
14
17
 
@@ -32,18 +35,20 @@ Add this script to CRON (let's say it will run this script every X hours) and it
32
35
  #/usr/bin/bash
33
36
  AWS_ACCESS_KEY='xxxxxxxxxxxxxxxxxxxx'
34
37
  AWS_SECRET_ACCESS_KEY='yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
38
+ AWS_SESSION_TOKEN='session_token_goes_here'
35
39
  AWS_REGION='eu-west-1'
36
40
  DESCRIPTION_PREFIX='automatic-backup-'
37
41
  RDS_ROTATOR=/here/is/the/path/to/rds-rotate-db-snapshots
38
42
  DB_NAME='db_name_here'
39
43
 
40
- $RDS_ROTATOR --aws-region $AWS_REGION --aws-access-key $AWS_ACCESS_KEY --aws-secret-access-key $AWS_SECRET_ACCESS_KEY --pattern $DESCRIPTION_PREFIX --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 1 --keep-yearly 0 --create-snapshot $DESCRIPTION_PREFIX$DB_NAME $DB_NAME
44
+ $RDS_ROTATOR --aws-region $AWS_REGION --aws-access-key $AWS_ACCESS_KEY --aws-secret-access-key $AWS_SECRET_ACCESS_KEY --aws-session-token $AWS_SESSION_TOKEN --pattern $DESCRIPTION_PREFIX --keep-hourly 24 --keep-daily 7 --keep-weekly 4 --keep-monthly 1 --keep-yearly 0 --create-snapshot $DESCRIPTION_PREFIX$DB_NAME $DB_NAME
41
45
  ```
42
46
 
43
47
  ## Options
44
48
 
45
49
  - `--aws-access-key ACCESS_KEY` "AWS Access Key"
46
50
  - `--aws-secret-access-key SECRET_KEY` "AWS Secret Access Key"
51
+ - `--aws-session-token $AWS_SESSION_TOKEN` "AWS Session Token"
47
52
  - `--aws-region REGION` "AWS Region"
48
53
  - `--pattern STRING` "Snapshots without this string in the description will be ignored"
49
54
  - `--by-tags TAG=VALUE,TAG=VALUE` "Instead of rotating specific snapshots, rotate over all the snapshots having the intersection of all given TAG=VALUE pairs."
data/Rakefile CHANGED
@@ -3,8 +3,8 @@ require 'bundler'
3
3
  begin
4
4
  Bundler.setup(:default, :development)
5
5
  rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
6
+ warn e.message
7
+ warn "Run `bundle install` to install missing gems"
8
8
  exit e.status_code
9
9
  end
10
10
  require 'rake'
@@ -14,8 +14,8 @@ Juwelier::Tasks.new do |gem|
14
14
  gem.name = "rds-rotate-db-snapshots"
15
15
  gem.homepage = "http://github.com/serg-kovalev/rds-rotate-db-snapshots"
16
16
  gem.license = "MIT"
17
- gem.summary = %Q{Amazon RDS DB snapshot rotator}
18
- gem.description = %Q{Provides a simple way to rotate RDS DB snapshots with configurable retention periods.}
17
+ gem.summary = %(Amazon RDS DB snapshot rotator)
18
+ gem.description = %(Provides a simple way to rotate RDS DB snapshots with configurable retention periods.)
19
19
  gem.email = "kovserg@gmail.com"
20
20
  gem.authors = ["Siarhei Kavaliou"]
21
21
  gem.version = File.exist?('VERSION') ? File.read('VERSION') : ""
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.5.2
@@ -2,10 +2,11 @@
2
2
 
3
3
  require_relative '../lib/rds_rotate_db_snapshots'
4
4
 
5
- rrds = RdsRotateDbSnapshots.new(script_name: File.basename($0), cli: true)
5
+ rrds = RdsRotateDbSnapshots.new(script_name: File.basename($PROGRAM_NAME), cli: true)
6
6
 
7
7
  if rrds.options[:aws_access_key].nil? || rrds.options[:aws_secret_access_key].nil?
8
- puts "You must specify your Amazon credentials via --aws-access-key and --aws-secret_access-key and --aws-session-token"
8
+ puts "You must specify your Amazon credentials via --aws-access-key and --aws-secret_access-key and " \
9
+ "--aws-session-token"
9
10
  exit 1
10
11
  end
11
12
 
@@ -14,7 +15,7 @@ if rrds.options[:aws_region].nil?
14
15
  exit 1
15
16
  end
16
17
 
17
- if ARGV.empty? and rrds.options[:by_tags].nil?
18
+ if ARGV.empty? && rrds.options[:by_tags].nil?
18
19
  puts "You must provide at least one DB Indentifier when not rotating by tags"
19
20
  exit 1
20
21
  end
@@ -23,40 +24,36 @@ if rrds.options[:by_tags].nil?
23
24
  db_indentifier_ids = ARGV
24
25
 
25
26
  db_indentifier_ids.each do |db_id|
26
- if db_id.nil? or db_id.gsub(/\s/, '').size < 1
27
- # sanity check
28
- puts "Invalid db indentifier: #{db_id}"
29
- exit 1
30
- end
27
+ next unless db_id.nil? || db_id.gsub(/\s/, '').empty?
28
+
29
+ # sanity check
30
+ puts "Invalid db indentifier: #{db_id}"
31
+ exit 1
31
32
  end
32
33
  else
33
- if !ARGV.empty?
34
- puts "Ignoring supplied db_indentifier_ids because we're rotating by tags."
35
- end
36
- if rrds.options[:by_tags].length == 0
34
+ puts "Ignoring supplied db_indentifier_ids because we're rotating by tags." unless ARGV.empty?
35
+ if rrds.options[:by_tags].empty?
37
36
  puts "Rotating by tags but no tags specified? Refusing to rotate all snapshots!"
38
37
  exit 1
39
38
  end
40
39
  end
41
40
 
42
- if rrds.options[:backoff_limit] < 0
41
+ if rrds.options[:backoff_limit].negative?
43
42
  puts "A negative backoff limit doesn't make much sense."
44
43
  exit 1
45
44
  end
46
45
 
47
- if rrds.options[:create_snapshot]
48
- rrds.create_snapshot(rrds.options[:create_snapshot], db_indentifier_ids)
49
- end
46
+ rrds.create_snapshot(rrds.options[:create_snapshot], db_indentifier_ids) if rrds.options[:create_snapshot]
50
47
 
51
48
  all_snapshots = []
52
49
  if rrds.options[:by_tags]
53
50
  rrds.rotate_by_tags
54
51
  else
55
- snapshots = rrds.get_db_snapshots(snapshot_type: 'manual').delete_if{ |e| e[:status] != 'available' }
52
+ snapshots = rrds.get_db_snapshots(snapshot_type: 'manual').delete_if { |e| e[:status] != 'available' }
56
53
  db_indentifier_ids.each do |db_id|
57
54
  rrds.rotate_em(
58
- snapshots.select {|ss| ss[:db_instance_identifier] == db_id }.
59
- sort {|a,b| a[:snapshot_create_time] <=> b[:snapshot_create_time] }
55
+ snapshots.select { |ss| ss[:db_instance_identifier] == db_id }
56
+ .sort { |a, b| a[:snapshot_create_time] <=> b[:snapshot_create_time] }
60
57
  )
61
58
  end
62
59
  end
@@ -8,18 +8,18 @@ class RdsRotateDbSnapshots
8
8
  define_method(m) do |*args|
9
9
  reset_backoff
10
10
  begin
11
- super *args
11
+ super(*args)
12
12
  rescue Aws::RDS::Errors::ServiceError => e
13
13
  raise if e.is_a? Aws::RDS::Errors::ExpiredToken
14
+
14
15
  # TODO: re-work
15
16
  puts "Error: #{e}"
16
17
  backoff
17
18
  retry
18
19
  end
19
-
20
20
  end
21
21
  end
22
- self.prepend wrapper
22
+ prepend wrapper
23
23
  end
24
24
  end
25
25
  end
@@ -1,82 +1,41 @@
1
1
  class RdsRotateDbSnapshots
2
2
  module Actions
3
3
  def rotate_em(snapshots)
4
- # poor man's way to get a deep copy of our time_periods definition hash
5
- periods = Marshal.load(Marshal.dump(time_periods))
6
-
7
4
  snapshots.each do |snapshot|
8
5
  time = snapshot[:snapshot_create_time]
9
- db_id = snapshot[:db_instance_identifier]
10
6
  snapshot_id = snapshot[:db_snapshot_identifier]
11
7
  description = snapshot_id
12
- keep_reason = nil
13
-
8
+
14
9
  if options[:pattern] && description !~ /#{options[:pattern]}/
15
10
  puts " #{time.strftime '%Y-%m-%d %H:%M:%S'} #{snapshot_id} Skipping snapshot with description #{description}"
16
11
  next
17
12
  end
18
-
19
- periods.keys.sort { |a, b| periods[a][:seconds] <=> periods[b][:seconds] }.each do |period|
20
- period_info = periods[period]
21
- keep = period_info[:keep]
22
- keeping = period_info[:keeping]
23
-
24
- time_string = time.strftime period_info[:format]
25
- if Time.now - time < keep * period_info[:seconds]
26
- if !keeping.key?(time_string) && keeping.length < keep
27
- keep_reason = period
28
- keeping[time_string] = snapshot
29
- end
30
- break
31
- end
32
- end
33
-
34
- if keep_reason.nil? && snapshot == snapshots.last && options[:keep_last]
35
- keep_reason = 'last snapshot'
36
- end
37
-
38
- if !keep_reason.nil?
39
- puts " #{time.strftime '%Y-%m-%d %H:%M:%S'} #{snapshot_id} Keeping for #{keep_reason}"
40
- else
41
- puts " #{time.strftime '%Y-%m-%d %H:%M:%S'} #{snapshot_id} Deleting"
42
- begin
43
- client.delete_db_snapshot(db_snapshot_identifier: snapshot_id) unless options[:dry_run]
44
- rescue Aws::RDS::Errors => e
45
- backoff
46
- retry
47
- end
48
- end
13
+
14
+ keep_reason = rotate_period_based_decision_with(time, snapshot)
15
+ keep_reason = 'last snapshot' if keep_reason.nil? && snapshot == snapshots.last && options[:keep_last]
16
+ rotate_or_keep_snapshot(keep_reason, time, snapshot_id)
49
17
  end
50
18
  end
51
-
19
+
52
20
  def create_snapshot(name, db_indentifier_ids)
53
- if !!name
54
- name = name.gsub(/[^a-zA-Z0-9\-]/, '')
55
- if name.size > 0
56
- name = "#{name}-#{Time.now.strftime('%Y%m%d%H%M%S')}"
57
- db_indentifier_ids.each do |db_id|
58
- begin
59
- client.create_db_snapshot(db_snapshot_identifier: name, db_instance_identifier: db_id) unless options[:dry_run]
60
- puts " #{Time.now.strftime '%Y-%m-%d %H:%M:%S'} Creation snapshot #{name} is pending (db: #{db_id})"
61
- rescue Aws::RDS::Errors::InvalidDBInstanceStateFault => e
62
- backoff
63
- retry
64
- end
65
- end
66
- else
67
- puts "invalid snapshot name format - #{name}"
68
- exit 1
69
- end
21
+ return if name.nil?
22
+
23
+ name = name.gsub(/[^a-zA-Z0-9-]/, '')
24
+ if name.size.positive?
25
+ create_db_snapshots(name: name, db_indentifier_ids: db_indentifier_ids)
26
+ else
27
+ puts "invalid snapshot name format - #{name}"
28
+ exit 1
70
29
  end
71
30
  end
72
-
31
+
73
32
  def get_db_snapshots(options)
74
33
  snapshots = []
75
34
  response = client.describe_db_snapshots(options)
76
- while true do
35
+ loop do
77
36
  snapshots += response.db_snapshots
78
37
  break unless response[:marker]
79
-
38
+
80
39
  response = client.describe_db_snapshots(options.merge(marker: response[:marker]))
81
40
  end
82
41
  snapshots
@@ -86,20 +45,68 @@ class RdsRotateDbSnapshots
86
45
  snapshots = []
87
46
  options[:by_tags].each do |tag, value|
88
47
  snapshots = rrds.client.describe_tags(
89
- snapshot_type: 'manual', filters: {'resource-type'=>"snapshot", 'key'=>tag, 'value'=>value}
90
- ).delete_if{ |e| e.status != 'available' }
48
+ snapshot_type: 'manual', filters: { 'resource-type' => "snapshot", 'key' => tag, 'value' => value }
49
+ ).delete_if { |e| e.status != 'available' }
91
50
  # TODO: re-work
92
- if snapshots.length == 0
51
+ if snapshots.empty?
93
52
  puts "(tag,value)=(#{tag},#{value}) found no snapshots; nothing to rotate!"
94
53
  exit 0
95
54
  end
96
55
  end
97
56
 
98
- snapshots = get_db_snapshots(db_instance_identifier: snapshots.map(&:db_instance_identifier).uniq).
99
- delete_if{ |e| !snapshots.include?(e.db_snapshot_identifier) }.
100
- sort {|a,b| a[:snapshot_create_time] <=> b[:snapshot_create_time] }
57
+ snapshots = get_db_snapshots(db_instance_identifier: snapshots.map(&:db_instance_identifier).uniq)
58
+ .delete_if { |e| !snapshots.include?(e.db_snapshot_identifier) }
59
+ .sort { |a, b| a[:snapshot_create_time] <=> b[:snapshot_create_time] }
101
60
 
102
61
  rotate_em snapshots
103
62
  end
63
+
64
+ private
65
+
66
+ def rotate_period_based_decision_with(time, snapshot)
67
+ # poor man's way to get a deep copy of our time_periods definition hash
68
+ periods = Marshal.load(Marshal.dump(time_periods))
69
+ keep_reason = nil
70
+
71
+ periods.keys.sort { |a, b| periods[a][:seconds] <=> periods[b][:seconds] }.each do |period|
72
+ period_info = periods[period]
73
+ keep = period_info[:keep]
74
+ keeping = period_info[:keeping]
75
+
76
+ time_string = time.strftime period_info[:format]
77
+ next unless Time.now - time < keep * period_info[:seconds]
78
+
79
+ if !keeping.key?(time_string) && keeping.length < keep
80
+ keep_reason = period
81
+ keeping[time_string] = snapshot
82
+ end
83
+ break
84
+ end
85
+
86
+ keep_reason
87
+ end
88
+
89
+ def rotate_or_keep_snapshot(keep_reason, time, snapshot_id)
90
+ if keep_reason.nil?
91
+ puts " #{time.strftime '%Y-%m-%d %H:%M:%S'} #{snapshot_id} Deleting"
92
+ client.delete_db_snapshot(db_snapshot_identifier: snapshot_id) unless options[:dry_run]
93
+ else
94
+ puts " #{time.strftime '%Y-%m-%d %H:%M:%S'} #{snapshot_id} Keeping for #{keep_reason}"
95
+ end
96
+ end
97
+
98
+ def create_db_snapshots(name:, db_indentifier_ids:)
99
+ name = "#{name}-#{Time.now.strftime('%Y%m%d%H%M%S')}"
100
+ db_indentifier_ids.each do |db_id|
101
+ unless options[:dry_run]
102
+ client.create_db_snapshot(db_snapshot_identifier: name,
103
+ db_instance_identifier: db_id)
104
+ end
105
+ puts " #{Time.now.strftime '%Y-%m-%d %H:%M:%S'} Creation snapshot #{name} is pending (db: #{db_id})"
106
+ rescue Aws::RDS::Errors::InvalidDBInstanceStateFault
107
+ backoff
108
+ retry
109
+ end
110
+ end
104
111
  end
105
112
  end