rds-rotate-db-snapshots 0.5.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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