loe-super-ebs-pruner-9000 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/.gitignore +2 -0
- data/Rakefile +26 -0
- data/VERSION +1 -0
- data/bin/pruner +47 -0
- data/lib/pruner.rb +102 -0
- data/lib/pruner/silence_ssl_warning.rb +8 -0
- data/lib/pruner/version.rb +3 -0
- data/super-ebs-pruner-9000.gemspec +46 -0
- data/test/test_pruner.rb +205 -0
- metadata +71 -0
data/.gitignore
ADDED
data/Rakefile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'rake/testtask'
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'jeweler'
|
|
5
|
+
Jeweler::Tasks.new do |gemspec|
|
|
6
|
+
gemspec.name = "super-ebs-pruner-9000"
|
|
7
|
+
gemspec.summary = "Thins EBS volume snapshots."
|
|
8
|
+
gemspec.description = "Thins EBS volume snapshots."
|
|
9
|
+
gemspec.email = "andrew@andrewloe.com"
|
|
10
|
+
gemspec.homepage = "http://github.com/loe/super-ebs-pruner-9000"
|
|
11
|
+
gemspec.authors = ["W. Andrew Loe III"]
|
|
12
|
+
gemspec.add_dependency('right_aws', '>=1.10.0')
|
|
13
|
+
end
|
|
14
|
+
rescue LoadError
|
|
15
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
task :default => :test
|
|
19
|
+
|
|
20
|
+
Rake::TestTask.new(:test) do |test|
|
|
21
|
+
test.test_files = FileList.new('test/**/test_*.rb') do |list|
|
|
22
|
+
list.exclude 'test/test_helper.rb'
|
|
23
|
+
end
|
|
24
|
+
test.libs << 'test'
|
|
25
|
+
test.verbose = true
|
|
26
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.0.0
|
data/bin/pruner
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
require 'optparse'
|
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/pruner')
|
|
4
|
+
|
|
5
|
+
options = {}
|
|
6
|
+
|
|
7
|
+
OptionParser.new do |opts|
|
|
8
|
+
opts.banner = 'Usage: pruner [options] vol-1 vol-2... providing no volumes will default to all volumes associated with the account.'
|
|
9
|
+
|
|
10
|
+
opts.on('-i', '--aws-id ID', 'AWS ID') do |id|
|
|
11
|
+
options[:aws_id] = id
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
opts.on('-k', '--aws-key KEY', 'AWS Secret Key') do |key|
|
|
15
|
+
options[:aws_key] = key
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
options[:verbose] = true
|
|
19
|
+
opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
|
|
20
|
+
options[:verbose] = v
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
options[:live] = false
|
|
24
|
+
opts.on('-l', '--[no-]live', 'Run live') do |l|
|
|
25
|
+
options[:live] = l
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
|
29
|
+
puts "Super Pruner 9000 - #{Pruner::VERSION}"
|
|
30
|
+
puts opts
|
|
31
|
+
exit
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
begin
|
|
35
|
+
opts.parse!
|
|
36
|
+
|
|
37
|
+
raise 'You must provide AWS credentials.' unless options[:aws_id] && options[:aws_key]
|
|
38
|
+
rescue Exception => e
|
|
39
|
+
print "ERROR: #{e}\n\n"
|
|
40
|
+
puts opts
|
|
41
|
+
exit
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
options[:volumes] = ARGV
|
|
46
|
+
|
|
47
|
+
Pruner.new(options).prune!
|
data/lib/pruner.rb
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'right_aws'
|
|
2
|
+
require 'activesupport'
|
|
3
|
+
|
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/pruner/version')
|
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/pruner/silence_ssl_warning')
|
|
6
|
+
|
|
7
|
+
class Pruner
|
|
8
|
+
attr_reader :options
|
|
9
|
+
attr_accessor :ec2, :volumes, :all_snapshots, :old_snapshots
|
|
10
|
+
|
|
11
|
+
NOW = Time.now
|
|
12
|
+
|
|
13
|
+
HOURLY_AFTER_A_DAY = {:after => NOW - 1.week,
|
|
14
|
+
:before => NOW - 1.day,
|
|
15
|
+
:interval => 1.hour,
|
|
16
|
+
:name => 'Hourly After A Day'}
|
|
17
|
+
DAILY_AFTER_A_WEEK = {:after => NOW - 1.month,
|
|
18
|
+
:before => NOW - 1.week,
|
|
19
|
+
:interval => 24.hours,
|
|
20
|
+
:name => 'Daily After A Week'}
|
|
21
|
+
EVERY_OTHER_DAY_AFTER_A_MONTH = {:after => NOW - 3.month,
|
|
22
|
+
:before => NOW - 1.month,
|
|
23
|
+
:interval => 48.hours,
|
|
24
|
+
:name => 'Every Other Day After A Month'}
|
|
25
|
+
WEEKLY_AFTER_A_QUARTER = {:after => NOW - 2.years,
|
|
26
|
+
:before => NOW - 3.months,
|
|
27
|
+
:interval => 1.week,
|
|
28
|
+
:name => 'Weekly After A Quarter'}
|
|
29
|
+
EVERY_THREE_WEEKS_AFTER_TWO_YEARS = {:after => NOW - 10.years,
|
|
30
|
+
:before => NOW - 2.years,
|
|
31
|
+
:interval => 3.weeks,
|
|
32
|
+
:name => 'Every Three Weeks After Two Years'}
|
|
33
|
+
|
|
34
|
+
RULES = [HOURLY_AFTER_A_DAY, DAILY_AFTER_A_WEEK, EVERY_OTHER_DAY_AFTER_A_MONTH, WEEKLY_AFTER_A_QUARTER, EVERY_THREE_WEEKS_AFTER_TWO_YEARS]
|
|
35
|
+
|
|
36
|
+
def initialize(options ={})
|
|
37
|
+
@options = options
|
|
38
|
+
@old_snapshots = []
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def prune!
|
|
42
|
+
apply_rules
|
|
43
|
+
remove_snapshots
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def apply_rules
|
|
47
|
+
RULES.each do |rule|
|
|
48
|
+
cached_size = old_snapshots.size if options[:verbose]
|
|
49
|
+
apply_rule(rule)
|
|
50
|
+
puts "#{rule[:name]}: #{old_snapshots.size - cached_size}" if options[:verbose]
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def apply_rule(rule)
|
|
55
|
+
volumes.each do |volume|
|
|
56
|
+
|
|
57
|
+
# Gather the snapshots that might fall in the rule's time window.
|
|
58
|
+
vulnerable_snaps = snapshots(volume).select { |snap| snap[:aws_started_at] > rule[:after] && snap[:aws_started_at] < rule[:before]}
|
|
59
|
+
|
|
60
|
+
# Step across the rule's time window one interval at a time, keeping the last snapshot in that window.
|
|
61
|
+
window_start = rule[:before] - rule[:interval]
|
|
62
|
+
while window_start > rule[:after] do
|
|
63
|
+
# Gather snaps in the window
|
|
64
|
+
snaps_in_window = vulnerable_snaps.select { |snap| snap[:aws_started_at] >= window_start && snap[:aws_started_at] < window_start + rule[:interval]}
|
|
65
|
+
# The first one in the selection survives
|
|
66
|
+
keeper = snaps_in_window.pop
|
|
67
|
+
# Send the rest to die.
|
|
68
|
+
@old_snapshots += snaps_in_window
|
|
69
|
+
# Shrink the window
|
|
70
|
+
window_start -= rule[:interval]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
old_snapshots
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def remove_snapshots
|
|
78
|
+
puts "Removing #{old_snapshots.size} Snapshots:" if options[:verbose]
|
|
79
|
+
old_snapshots.each do |snap|
|
|
80
|
+
puts " #{snap[:aws_id]} - #{snap[:aws_started_at]} (#{snap[:aws_volume_id]})" if options[:verbose]
|
|
81
|
+
ec2.delete_snapshot(snap[:aws_id]) if options[:live]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
old_snapshots
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def ec2
|
|
88
|
+
@ec2 ||= RightAws::Ec2.new(options[:aws_id], options[:aws_key])
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def volumes
|
|
92
|
+
@volumes ||= options[:volumes].empty? ? ec2.describe_volumes.map {|vol| vol[:aws_id] } : options[:volumes]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def all_snapshots
|
|
96
|
+
@all_snapshots ||= ec2.describe_snapshots
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def snapshots(volume)
|
|
100
|
+
all_snapshots.select { |snap| volume == snap[:aws_volume_id] }
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
Gem::Specification.new do |s|
|
|
4
|
+
s.name = %q{super-ebs-pruner-9000}
|
|
5
|
+
s.version = "1.0.0"
|
|
6
|
+
|
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
|
+
s.authors = ["W. Andrew Loe III"]
|
|
9
|
+
s.date = %q{2009-07-24}
|
|
10
|
+
s.default_executable = %q{pruner}
|
|
11
|
+
s.description = %q{Thins EBS volume snapshots.}
|
|
12
|
+
s.email = %q{andrew@andrewloe.com}
|
|
13
|
+
s.executables = ["pruner"]
|
|
14
|
+
s.files = [
|
|
15
|
+
".gitignore",
|
|
16
|
+
"Rakefile",
|
|
17
|
+
"VERSION",
|
|
18
|
+
"bin/pruner",
|
|
19
|
+
"lib/pruner.rb",
|
|
20
|
+
"lib/pruner/silence_ssl_warning.rb",
|
|
21
|
+
"lib/pruner/version.rb",
|
|
22
|
+
"super-ebs-pruner-9000.gemspec",
|
|
23
|
+
"test/test_pruner.rb"
|
|
24
|
+
]
|
|
25
|
+
s.homepage = %q{http://github.com/loe/super-ebs-pruner-9000}
|
|
26
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
27
|
+
s.require_paths = ["lib"]
|
|
28
|
+
s.rubygems_version = %q{1.3.4}
|
|
29
|
+
s.summary = %q{Thins EBS volume snapshots.}
|
|
30
|
+
s.test_files = [
|
|
31
|
+
"test/test_pruner.rb"
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
if s.respond_to? :specification_version then
|
|
35
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
36
|
+
s.specification_version = 3
|
|
37
|
+
|
|
38
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
39
|
+
s.add_runtime_dependency(%q<right_aws>, ["= 1.10.0"])
|
|
40
|
+
else
|
|
41
|
+
s.add_dependency(%q<right_aws>, ["= 1.10.0"])
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
s.add_dependency(%q<right_aws>, ["= 1.10.0"])
|
|
45
|
+
end
|
|
46
|
+
end
|
data/test/test_pruner.rb
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require 'rubygems'
|
|
3
|
+
require 'mocha'
|
|
4
|
+
require 'pruner'
|
|
5
|
+
|
|
6
|
+
class TestPruner < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
NOW = Time.now
|
|
9
|
+
|
|
10
|
+
# From RightAws::Ec2#describe_instances documentation.
|
|
11
|
+
def volumes_array
|
|
12
|
+
[{:aws_id => "vol-foo"},
|
|
13
|
+
{:aws_id => "vol-bar"},
|
|
14
|
+
{:aws_id => "vol-baz"}]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Generate twice hourly for yesterday
|
|
18
|
+
# Should result in 24 deleted snapshots.
|
|
19
|
+
def twice_hourly_yesterday(vol)
|
|
20
|
+
yesterday = NOW - 1.day
|
|
21
|
+
(1..48).map do |i|
|
|
22
|
+
{:aws_progress => "100%",
|
|
23
|
+
:aws_status => "completed",
|
|
24
|
+
:aws_id => "snap-yesterday-#{i}-#{vol}",
|
|
25
|
+
:aws_volume_id => vol,
|
|
26
|
+
:aws_started_at => yesterday - i * 30.minutes}
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Generate 2 times daily for last week.
|
|
31
|
+
# Should result in 7 deleted snapshots.
|
|
32
|
+
def twice_daily_last_week(vol)
|
|
33
|
+
last_week = NOW - 1.week
|
|
34
|
+
(1..14).map do |i|
|
|
35
|
+
{:aws_progress => "100%",
|
|
36
|
+
:aws_status => "completed",
|
|
37
|
+
:aws_id => "snap-last-week-#{i}-#{vol}",
|
|
38
|
+
:aws_volume_id => vol,
|
|
39
|
+
:aws_started_at => last_week - i * 12.hours}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Generate daily for last month.
|
|
44
|
+
# Should result in 15 deleted snapshots
|
|
45
|
+
def daily_last_month(vol)
|
|
46
|
+
last_month = NOW - 1.month
|
|
47
|
+
(1..30).map do |i|
|
|
48
|
+
{:aws_progress => "100%",
|
|
49
|
+
:aws_status => "completed",
|
|
50
|
+
:aws_id => "snap-last-month-#{i}-#{vol}",
|
|
51
|
+
:aws_volume_id => vol,
|
|
52
|
+
:aws_started_at => last_month - i * 1.day}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Generate 2 weekly for last quarter.
|
|
57
|
+
# Should result in 6 deleted snapshots.
|
|
58
|
+
def twice_weekly_last_quarter(vol)
|
|
59
|
+
last_quarter = NOW - 3.months
|
|
60
|
+
(1..12).map do |i|
|
|
61
|
+
{:aws_progress => "100%",
|
|
62
|
+
:aws_status => "completed",
|
|
63
|
+
:aws_id => "snap-last-quarter-#{i}-#{vol}",
|
|
64
|
+
:aws_volume_id => vol,
|
|
65
|
+
:aws_started_at => last_quarter - i * 3.days}
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Generate weekly for last two years.
|
|
70
|
+
# Should result in 16 deleted snapshots.
|
|
71
|
+
def weekly_two_years_ago(vol)
|
|
72
|
+
two_years_ago = NOW - 2.years
|
|
73
|
+
(1..48).map do |i|
|
|
74
|
+
{:aws_progress => "100%",
|
|
75
|
+
:aws_status => "completed",
|
|
76
|
+
:aws_id => "snap-two-years-ago-#{i}-#{vol}",
|
|
77
|
+
:aws_volume_id => vol,
|
|
78
|
+
:aws_started_at => two_years_ago - i * 1.week}
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Generate a set that we can prune from with known results.
|
|
83
|
+
# RULES = [HOURLY_AFTER_A_DAY, DAILY_AFTER_A_WEEK, EVERY_OTHER_DAY_AFTER_A_MONTH, WEEKLY_AFTER_A_QUARTER, EVERY_THREE_WEEKS_AFTER_TWO_YEARS]
|
|
84
|
+
def snapshots_array_foo
|
|
85
|
+
twice_hourly_yesterday('vol-foo') + twice_daily_last_week('vol-foo') + daily_last_month('vol-foo') + twice_weekly_last_quarter('vol-foo') + weekly_two_years_ago('vol-foo')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def snapshots_array_bar
|
|
89
|
+
twice_hourly_yesterday('vol-bar') + twice_daily_last_week('vol-bar') + daily_last_month('vol-bar') + twice_weekly_last_quarter('vol-bar') + weekly_two_years_ago('vol-bar')
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def snapshots_array_baz
|
|
93
|
+
twice_hourly_yesterday('vol-baz') + twice_daily_last_week('vol-baz') + daily_last_month('vol-baz') + twice_weekly_last_quarter('vol-baz') + weekly_two_years_ago('vol-baz')
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def mock_aws
|
|
97
|
+
@mock_ec2 = mock()
|
|
98
|
+
RightAws::Ec2.stubs(:new).returns(@mock_ec2)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def new_pruner
|
|
102
|
+
@pruner = Pruner.new({:volumes => [], :verbose => true, :live => true})
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def setup
|
|
106
|
+
mock_aws
|
|
107
|
+
new_pruner
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def teardown
|
|
111
|
+
@pruner = nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_no_window_overlap
|
|
115
|
+
windows = [twice_hourly_yesterday('vol-foo'), twice_daily_last_week('vol-foo'), daily_last_month('vol-foo'), twice_weekly_last_quarter('vol-foo'), weekly_two_years_ago('vol-foo')]
|
|
116
|
+
windows.each do |window|
|
|
117
|
+
assert_equal window & (windows.flatten - window), []
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def test_version
|
|
122
|
+
assert_not_nil Pruner::VERSION
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def test_ec2
|
|
126
|
+
assert_not_nil @pruner.ec2
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_volumes
|
|
130
|
+
@mock_ec2.expects(:describe_volumes).returns(volumes_array).once
|
|
131
|
+
assert_equal @pruner.volumes, ['vol-foo', 'vol-bar', 'vol-baz']
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def test_snapshots
|
|
135
|
+
@mock_ec2.expects(:describe_snapshots).returns(snapshots_array_foo).once
|
|
136
|
+
assert_equal @pruner.snapshots('vol-foo'), snapshots_array_foo
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_apply_rule_HOURLY_AFTER_A_DAY
|
|
140
|
+
@pruner.volumes = ['vol-foo']
|
|
141
|
+
@mock_ec2.expects(:describe_snapshots).returns(twice_hourly_yesterday('vol-foo'))
|
|
142
|
+
@pruner.apply_rule(Pruner::HOURLY_AFTER_A_DAY)
|
|
143
|
+
assert_equal @pruner.old_snapshots.size, 24
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_apply_rule_DAILY_AFTER_A_WEEK
|
|
147
|
+
@pruner.volumes = ['vol-foo']
|
|
148
|
+
@mock_ec2.expects(:describe_snapshots).returns(twice_daily_last_week('vol-foo'))
|
|
149
|
+
@pruner.apply_rule(Pruner::DAILY_AFTER_A_WEEK)
|
|
150
|
+
assert_equal @pruner.old_snapshots.size, 7
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test_apply_rule_EVERY_OTHER_DAY_AFTER_A_MONTH
|
|
154
|
+
@pruner.volumes = ['vol-foo']
|
|
155
|
+
@mock_ec2.expects(:describe_snapshots).returns(daily_last_month('vol-foo'))
|
|
156
|
+
@pruner.apply_rule(Pruner::EVERY_OTHER_DAY_AFTER_A_MONTH)
|
|
157
|
+
assert_equal @pruner.old_snapshots.size, 15
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_apply_rule_WEEKLY_AFTER_A_QUARTER
|
|
161
|
+
@pruner.volumes = ['vol-foo']
|
|
162
|
+
@mock_ec2.expects(:describe_snapshots).returns(twice_weekly_last_quarter('vol-foo'))
|
|
163
|
+
@pruner.apply_rule(Pruner::WEEKLY_AFTER_A_QUARTER)
|
|
164
|
+
assert_equal @pruner.old_snapshots.size, 6
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def test_apply_rule_EVERY_THREE_WEEKS_AFTER_TWO_YEARS
|
|
168
|
+
@pruner.volumes = ['vol-foo']
|
|
169
|
+
@mock_ec2.expects(:describe_snapshots).returns(weekly_two_years_ago('vol-foo'))
|
|
170
|
+
@pruner.apply_rule(Pruner::EVERY_THREE_WEEKS_AFTER_TWO_YEARS)
|
|
171
|
+
assert_equal @pruner.old_snapshots.size, 32
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def test_apply_rules
|
|
175
|
+
@pruner.volumes = ['vol-foo']
|
|
176
|
+
@mock_ec2.expects(:describe_snapshots).returns(snapshots_array_foo)
|
|
177
|
+
@pruner.apply_rules
|
|
178
|
+
assert_equal @pruner.old_snapshots.size, 24 + 7 + 15 + 6 + 32
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def test_remove_snapshots
|
|
182
|
+
dead_snaps = 24 + 7 + 15 + 6 + 32
|
|
183
|
+
@pruner.volumes = ['vol-foo']
|
|
184
|
+
@mock_ec2.expects(:describe_snapshots).returns(snapshots_array_foo)
|
|
185
|
+
@mock_ec2.expects(:delete_snapshot).times(dead_snaps)
|
|
186
|
+
@pruner.apply_rules
|
|
187
|
+
@pruner.remove_snapshots
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_one_volume_prune!
|
|
191
|
+
dead_snaps = 24 + 7 + 15 + 6 + 32
|
|
192
|
+
@mock_ec2.expects(:describe_volumes).returns([{:aws_id => "vol-foo"}]).once
|
|
193
|
+
@mock_ec2.expects(:describe_snapshots).returns(snapshots_array_foo).once
|
|
194
|
+
@mock_ec2.expects(:delete_snapshot).times(dead_snaps)
|
|
195
|
+
@pruner.prune!
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_multiple_volumes_prune!
|
|
199
|
+
dead_snaps = (24 + 7 + 15 + 6 + 32) * 3 # one for each array!
|
|
200
|
+
@mock_ec2.expects(:describe_volumes).returns(volumes_array).once
|
|
201
|
+
@mock_ec2.expects(:describe_snapshots).returns(snapshots_array_foo + snapshots_array_bar + snapshots_array_baz).once
|
|
202
|
+
@mock_ec2.expects(:delete_snapshot).times(dead_snaps)
|
|
203
|
+
@pruner.prune!
|
|
204
|
+
end
|
|
205
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: loe-super-ebs-pruner-9000
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- W. Andrew Loe III
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
|
|
12
|
+
date: 2009-07-24 00:00:00 -07:00
|
|
13
|
+
default_executable: pruner
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: right_aws
|
|
17
|
+
type: :runtime
|
|
18
|
+
version_requirement:
|
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
- - "="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: 1.10.0
|
|
24
|
+
version:
|
|
25
|
+
description: Thins EBS volume snapshots.
|
|
26
|
+
email: andrew@andrewloe.com
|
|
27
|
+
executables:
|
|
28
|
+
- pruner
|
|
29
|
+
extensions: []
|
|
30
|
+
|
|
31
|
+
extra_rdoc_files: []
|
|
32
|
+
|
|
33
|
+
files:
|
|
34
|
+
- .gitignore
|
|
35
|
+
- Rakefile
|
|
36
|
+
- VERSION
|
|
37
|
+
- bin/pruner
|
|
38
|
+
- lib/pruner.rb
|
|
39
|
+
- lib/pruner/silence_ssl_warning.rb
|
|
40
|
+
- lib/pruner/version.rb
|
|
41
|
+
- super-ebs-pruner-9000.gemspec
|
|
42
|
+
- test/test_pruner.rb
|
|
43
|
+
has_rdoc: false
|
|
44
|
+
homepage: http://github.com/loe/super-ebs-pruner-9000
|
|
45
|
+
licenses:
|
|
46
|
+
post_install_message:
|
|
47
|
+
rdoc_options:
|
|
48
|
+
- --charset=UTF-8
|
|
49
|
+
require_paths:
|
|
50
|
+
- lib
|
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - ">="
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: "0"
|
|
56
|
+
version:
|
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: "0"
|
|
62
|
+
version:
|
|
63
|
+
requirements: []
|
|
64
|
+
|
|
65
|
+
rubyforge_project:
|
|
66
|
+
rubygems_version: 1.3.5
|
|
67
|
+
signing_key:
|
|
68
|
+
specification_version: 3
|
|
69
|
+
summary: Thins EBS volume snapshots.
|
|
70
|
+
test_files:
|
|
71
|
+
- test/test_pruner.rb
|