rds-rotate-db-snapshots 0.5.2 → 1.0.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.
data/.rubocop.yml DELETED
@@ -1,93 +0,0 @@
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 DELETED
@@ -1,127 +0,0 @@
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
@@ -1,26 +0,0 @@
1
- require 'aws-sdk-rds'
2
-
3
- class RdsRotateDbSnapshots
4
- module ActionWrappers
5
- def with_backoff(*method_names)
6
- method_names.each do |m|
7
- wrapper = Module.new do
8
- define_method(m) do |*args|
9
- reset_backoff
10
- begin
11
- super(*args)
12
- rescue Aws::RDS::Errors::ServiceError => e
13
- raise if e.is_a? Aws::RDS::Errors::ExpiredToken
14
-
15
- # TODO: re-work
16
- puts "Error: #{e}"
17
- backoff
18
- retry
19
- end
20
- end
21
- end
22
- prepend wrapper
23
- end
24
- end
25
- end
26
- end
@@ -1,112 +0,0 @@
1
- class RdsRotateDbSnapshots
2
- module Actions
3
- def rotate_em(snapshots)
4
- snapshots.each do |snapshot|
5
- time = snapshot[:snapshot_create_time]
6
- snapshot_id = snapshot[:db_snapshot_identifier]
7
- description = snapshot_id
8
-
9
- if options[:pattern] && description !~ /#{options[:pattern]}/
10
- puts " #{time.strftime '%Y-%m-%d %H:%M:%S'} #{snapshot_id} Skipping snapshot with description #{description}"
11
- next
12
- 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)
17
- end
18
- end
19
-
20
- def create_snapshot(name, db_indentifier_ids)
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
29
- end
30
- end
31
-
32
- def get_db_snapshots(options)
33
- snapshots = []
34
- response = client.describe_db_snapshots(options)
35
- loop do
36
- snapshots += response.db_snapshots
37
- break unless response[:marker]
38
-
39
- response = client.describe_db_snapshots(options.merge(marker: response[:marker]))
40
- end
41
- snapshots
42
- end
43
-
44
- def rotate_by_tags
45
- snapshots = []
46
- options[:by_tags].each do |tag, value|
47
- snapshots = rrds.client.describe_tags(
48
- snapshot_type: 'manual', filters: { 'resource-type' => "snapshot", 'key' => tag, 'value' => value }
49
- ).delete_if { |e| e.status != 'available' }
50
- # TODO: re-work
51
- if snapshots.empty?
52
- puts "(tag,value)=(#{tag},#{value}) found no snapshots; nothing to rotate!"
53
- exit 0
54
- end
55
- end
56
-
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] }
60
-
61
- rotate_em snapshots
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
111
- end
112
- end
@@ -1,80 +0,0 @@
1
- class RdsRotateDbSnapshots
2
- class OptionsParser
3
- module Options
4
- def split_tag(hash, value)
5
- value.split(',').each do |pair|
6
- tag, value = pair.split('=', 2)
7
- raise InvalidArgument, "invalid tag=value format" if value.nil?
8
-
9
- hash[tag] = value
10
- end
11
- end
12
-
13
- def banner_opts(opt)
14
- opt.banner = "Usage: #{script_name} [options] <db_indentifier>\nUsage: #{script_name} " \
15
- "--by-tags <tag=value,...> [other options]"
16
- opt.separator ""
17
- end
18
-
19
- def aws_opts(opt)
20
- opt.on("--aws-access-key ACCESS_KEY", "AWS Access Key") do |v|
21
- @options[:aws_access_key] = v
22
- end
23
-
24
- opt.on("--aws-secret-access-key SECRET_KEY", "AWS Secret Access Key") do |v|
25
- @options[:aws_secret_access_key] = v
26
- end
27
-
28
- opt.on("--aws-region REGION", "AWS Region") do |v|
29
- @options[:aws_region] = v
30
- end
31
-
32
- opt.on("--aws-session-token SESSION_TOKEN", "AWS session token") do |v|
33
- @options[:aws_session_token] = v
34
- end
35
- end
36
-
37
- def not_supported_opts(opt)
38
- opt.on("--by-tags TAG=VALUE,TAG=VALUE",
39
- "Instead of rotating specific snapshots, rotate over all the snapshots having the intersection of all " \
40
- "given TAG=VALUE pairs.") do |_v|
41
- @options[:by_tags] = {}
42
- raise NotImplementedError,
43
- 'Hey! It\'s not implemented in RDS yet. Who knows, maybe they will add Tagging in RDS later.'
44
- # split_tag(@options[:by_tags], v)
45
- end
46
- end
47
-
48
- def snapshot_create_opts(opt)
49
- opt.on("--create-snapshot STRING", "Use this option if you want to create a snapshot") do |v|
50
- @options[:create_snapshot] = v
51
- end
52
- end
53
-
54
- def time_period_opts(opt)
55
- @time_periods.keys.sort { |a, b| @time_periods[a][:seconds] <=> @time_periods[b][:seconds] }.each do |period|
56
- opt.on("--keep-#{period} NUMBER", Integer, "Number of #{period} snapshots to keep") do |v|
57
- @time_periods[period][:keep] = v
58
- end
59
- end
60
-
61
- opt.on("--keep-last", "Keep the most recent snapshot, regardless of time-based policy") do |_v|
62
- @options[:keep_last] = true
63
- end
64
- end
65
-
66
- def extra_opts(opt)
67
- opt.on("--pattern STRING", "Snapshots without this string in the description will be ignored") do |v|
68
- @options[:pattern] = v
69
- end
70
- opt.on("--backoff-limit LIMIT",
71
- "Backoff and retry when hitting RDS Error exceptions no more than this many times. Default is 15") do |v|
72
- @options[:backoff_limit] = v
73
- end
74
- opt.on("--dry-run", "Shows what would happen without doing anything") do |_v|
75
- @options[:dry_run] = true
76
- end
77
- end
78
- end
79
- end
80
- end
@@ -1,58 +0,0 @@
1
- require 'optparse'
2
- require_relative 'options_parser/options'
3
- class RdsRotateDbSnapshots
4
- class OptionsParser
5
- class NotImplementedError < StandardError; end
6
- class InvalidArgument < StandardError; end
7
-
8
- include RdsRotateDbSnapshots::OptionsParser::Options
9
-
10
- attr_reader :options, :script_name, :time_periods
11
-
12
- def initialize(script_name: nil, cli: false)
13
- @script_name = script_name
14
- @options = {
15
- aws_access_key: ENV.fetch("AWS_ACCESS_KEY_ID", nil),
16
- aws_secret_access_key: ENV.fetch("AWS_SECRET_ACCESS_KEY", nil),
17
- aws_session_token: ENV.fetch("AWS_SESSION_TOKEN", nil),
18
- aws_region: ENV.fetch("AWS_REGION", nil),
19
- pattern: nil,
20
- by_tags: nil,
21
- dry_run: false,
22
- backoff_limit: 15,
23
- create_snapshot: nil
24
- }
25
- @time_periods = {
26
- hourly: { seconds: 60 * 60, format: '%Y-%m-%d-%H', keep: 0, keeping: {} },
27
- daily: { seconds: 24 * 60 * 60, format: '%Y-%m-%d', keep: 0, keeping: {} },
28
- weekly: { seconds: 7 * 24 * 60 * 60, format: '%Y-%W', keep: 0, keeping: {} },
29
- monthly: { seconds: 30 * 24 * 60 * 60, format: '%Y-%m', keep: 0, keeping: {} },
30
- yearly: { seconds: 12 * 30 * 24 * 60 * 60, format: '%Y', keep: 0, keeping: {} }
31
- }
32
- @cli = cli
33
- init_cli_parser if cli?
34
- end
35
-
36
- def parse!
37
- @parser.parse!
38
- @options.merge(time_periods: @time_periods)
39
- end
40
-
41
- private
42
-
43
- def cli?
44
- !!@cli
45
- end
46
-
47
- def init_cli_parser
48
- @parser ||= OptionParser.new do |o|
49
- banner_opts o
50
- aws_opts o
51
- snapshot_create_opts o
52
- time_period_opts o
53
- extra_opts o
54
- not_supported_opts o
55
- end
56
- end
57
- end
58
- end
@@ -1,20 +0,0 @@
1
- require 'forwardable'
2
- require 'aws-sdk-rds'
3
-
4
- class RdsRotateDbSnapshots
5
- class RdsClient
6
- extend Forwardable
7
-
8
- def_delegators :@client, :describe_db_snapshots, :create_db_snapshot, :delete_db_snapshot
9
-
10
- def initialize(options)
11
- Aws.config.update(
12
- access_key_id: options[:aws_access_key],
13
- secret_access_key: options[:aws_secret_access_key],
14
- region: options[:aws_region],
15
- session_token: options[:aws_session_token]
16
- )
17
- @client = Aws::RDS::Client.new
18
- end
19
- end
20
- end
@@ -1,59 +0,0 @@
1
- require 'rubygems'
2
- require_relative 'rds_rotate_db_snapshots/actions'
3
- require_relative 'rds_rotate_db_snapshots/action_wrappers'
4
- require_relative 'rds_rotate_db_snapshots/options_parser'
5
- require_relative 'rds_rotate_db_snapshots/rds_client'
6
-
7
- class RdsRotateDbSnapshots
8
- extend RdsRotateDbSnapshots::ActionWrappers
9
- include RdsRotateDbSnapshots::Actions
10
-
11
- attr_reader :options
12
-
13
- with_backoff :get_db_snapshots, :create_snapshot, :rotate_em
14
-
15
- def initialize(script_name: nil, cli: false, options: {})
16
- @script_name = script_name
17
- @options = options
18
- @cli = cli
19
- parse_options if cli?
20
- @backoff_counter = 0
21
- end
22
-
23
- def rds_client
24
- @rds_client ||= RdsRotateDbSnapshots::RdsClient.new(@options)
25
- end
26
- alias client rds_client
27
-
28
- def reset_backoff
29
- @backoff_counter = 0
30
- end
31
-
32
- def time_periods
33
- @options[:time_periods]
34
- end
35
-
36
- private
37
-
38
- def cli?
39
- !!@cli
40
- end
41
-
42
- def parse_options
43
- @options = RdsRotateDbSnapshots::OptionsParser.new(script_name: @script_name, cli: @cli).parse!
44
- end
45
-
46
- def backoff
47
- @backoff_counter += 1
48
-
49
- # TODO: re-work
50
- if options && options[:backoff_limit].positive? && options[:backoff_limit] < @backoff_counter
51
- puts "Too many backoff attempts. Sorry it didn't work out."
52
- exit 2
53
- end
54
-
55
- naptime = rand(60) * @backoff_counter
56
- puts "Backing off for #{naptime} seconds..."
57
- sleep naptime
58
- end
59
- end
data/spec/helper.rb DELETED
@@ -1,81 +0,0 @@
1
- $TESTING = true
2
-
3
- require "simplecov"
4
-
5
- SimpleCov.start do
6
- add_filter "/spec"
7
- minimum_coverage(75)
8
-
9
- if ENV['CI']
10
- require 'simplecov-lcov'
11
-
12
- SimpleCov::Formatter::LcovFormatter.config do |c|
13
- c.report_with_single_file = true
14
- c.single_report_path = 'coverage/lcov.info'
15
- end
16
-
17
- formatter SimpleCov::Formatter::LcovFormatter
18
- end
19
- end
20
-
21
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
22
- require "rds_rotate_db_snapshots"
23
-
24
- require "rdoc"
25
- require "rspec"
26
- require "diff/lcs" # You need diff/lcs installed to run specs.
27
- # require 'stringio'
28
- require "webmock/rspec"
29
-
30
- WebMock.disable_net_connect!(allow: "coveralls.io")
31
-
32
- $0 = "rds_rotate_db_snapshots"
33
- ARGV.clear
34
-
35
- RSpec.configure do |config|
36
- config.before do
37
- ARGV.replace []
38
- end
39
-
40
- config.expect_with :rspec do |c|
41
- c.syntax = :expect
42
- end
43
-
44
- # def capture(stream)
45
- # begin
46
- # stream = stream.to_s
47
- # eval "$#{stream} = StringIO.new"
48
- # yield
49
- # result = eval("$#{stream}").string
50
- # ensure
51
- # eval("$#{stream} = #{stream.upcase}")
52
- # end
53
-
54
- # result
55
- # end
56
-
57
- def source_root
58
- File.join(File.dirname(__FILE__), "fixtures")
59
- end
60
-
61
- def destination_root
62
- File.join(File.dirname(__FILE__), "sandbox")
63
- end
64
-
65
- def silence_warnings
66
- old_verbose = $VERBOSE
67
- $VERBOSE = nil
68
- yield
69
- ensure
70
- $VERBOSE = old_verbose
71
- end
72
-
73
- # true if running on windows, used for conditional spec skips
74
- #
75
- # @return [TrueClass/FalseClass]
76
- def windows?
77
- Gem.win_platform?
78
- end
79
-
80
- # alias silence capture
81
- end
@@ -1,45 +0,0 @@
1
- require 'helper'
2
-
3
- class TestClass
4
- def initialize
5
- @backoff_counter = 0
6
- @options = { backoff_limit: 5 }
7
- end
8
-
9
- def test_method
10
- raise Aws::RDS::Errors::ServiceError.new(nil, 'service error')
11
- end
12
-
13
- def reset_backoff
14
- @backoff_counter = 0
15
- end
16
-
17
- def backoff
18
- @backoff_counter += 1
19
-
20
- raise StandardError, 'gave up' if @options[:backoff_limit] > 0 && @options[:backoff_limit] < @backoff_counter
21
- end
22
-
23
- extend RdsRotateDbSnapshots::ActionWrappers
24
-
25
- with_backoff :test_method
26
- end
27
-
28
- describe RdsRotateDbSnapshots::ActionWrappers do
29
- subject { TestClass.new }
30
-
31
- describe "#with_backoff" do
32
- it "does not retry if the exception raised is Aws::RDS::Errors::ExpiredToken" do
33
- allow(subject).to receive(:test_method).and_raise(Aws::RDS::Errors::ExpiredToken.new(nil, 'token expired'))
34
- expect(subject).not_to receive(:reset_backoff)
35
- expect(subject).not_to receive(:backoff)
36
- expect { subject.test_method }.to raise_error(Aws::RDS::Errors::ExpiredToken)
37
- end
38
-
39
- it "retries if the exception raised is Aws::RDS::Errors::ServiceError" do
40
- expect(subject).to receive(:backoff).exactly(6).and_call_original
41
-
42
- expect { subject.test_method }.to raise_error(StandardError, 'gave up')
43
- end
44
- end
45
- end