ebs_prune_snapshot 0.0.1

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 ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ebs_prune_snapshot.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Dusty Doris
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.txt ADDED
@@ -0,0 +1,60 @@
1
+ # EbsPruneSnapshot
2
+
3
+ Manage your EBS snapshots on a daily, weekly, and monthly rotation schedule.
4
+
5
+ Features
6
+ - Keep at least one snapshot of each volume, regardless of the rotation schedule.
7
+ - Saves the youngest snapshot of a particular day as a daily snapshot.
8
+ - Saves the oldest snapshot of any week as a weekly snapshot (Sundays).
9
+ - Saves the oldest snapshot of any 4 week period as a monthly snapshot (Sunday).
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'ebs_prune_snapshot'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install ebs_prune_snapshot
24
+
25
+ ## Usage
26
+
27
+ AWS Access Key and AWS Secret Access Key are required. These options can be
28
+ provided through the command line or they may be stored in the environmental
29
+ variables of AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY. Any options
30
+ provided through the command line will override the environmental variables.
31
+
32
+ A daily, weekly, and monthly rotation are also required. The monthly rotation
33
+ is every 4 weeks, so provide 13 to go back a full year.
34
+
35
+ If you only want to see what would happen if you ran the schedule, then pass
36
+ the --dry-run (-n) argument.
37
+
38
+ Usage: ebs_prune_snapshot [options]
39
+ eg: ebs_snapshot -d 7 -w 12 -m 14
40
+
41
+ Required rotation configuration
42
+ -d, --daily DAILY Number of daily snapshots to keep
43
+ -w, --weekly WEEKLY Number of weekly snapshots to keep
44
+ -m, --monthly MONTHLY Number of monthly snapshots to keep
45
+
46
+ AWS Identifications, required unless environmental variables set
47
+ -k, --key KEY AWS Access Key (AMAZON_ACCESS_KEY_ID)
48
+ -s, --secret SECRET AWS Secret Access Key (AMAZON_SECRET_ACCESS_KEY)
49
+
50
+ Informational arguments
51
+ -n, --dry-run Describe what would be done (SAFE)
52
+ -h, --help Show Command Help
53
+
54
+ ## Contributing
55
+
56
+ 1. Fork it
57
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
58
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
59
+ 4. Push to the branch (`git push origin my-new-feature`)
60
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ desc "Run tests"
5
+ task :test do
6
+ sh "bundle exec test/test_ebs_prune_snapshot.rb"
7
+ end
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env ruby
2
+ require 'ebs_prune_snapshot'
3
+ require 'optparse'
4
+
5
+ def send_error(message)
6
+ puts @opts
7
+ puts ""
8
+ puts "ERROR: #{message}"
9
+ puts ""
10
+ exit(1)
11
+ end
12
+
13
+ @options = {}
14
+ @opts = OptionParser.new
15
+
16
+ @opts.banner = <<-EOD
17
+ EbsPruneSnapshot
18
+
19
+ Manage your EBS snapshots on a daily, weekly, and monthly rotation schedule.
20
+
21
+ AWS Access Key and AWS Secret Access Key are required. These options can be
22
+ provided through the command line or they may be stored in the environmental
23
+ variables of AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY. Any options
24
+ provided through the command line will override the environmental variables.
25
+
26
+ A daily, weekly, and monthly rotation are also required. The monthly rotation
27
+ is every 4 weeks, so provide 13 to go back a full year.
28
+
29
+ If you only want to see what would happen if you ran the schedule, then pass
30
+ the --dry-run (-n) argument.
31
+
32
+ Usage: ebs_prune_snapshot [options]
33
+ eg: ebs_snapshot -d 7 -w 12 -m 13"
34
+ EOD
35
+
36
+ @opts.separator ""
37
+ @opts.separator "Required rotation configuration"
38
+
39
+ @opts.on(
40
+ "-d", "--daily DAILY", "Number of daily snapshots to keep"
41
+ ) { |value| @options[:daily]= value }
42
+
43
+ @opts.on(
44
+ "-w", "--weekly WEEKLY", "Number of weekly snapshots to keep"
45
+ ) { |value| @options[:weekly] = value }
46
+
47
+ @opts.on(
48
+ '-m', "--monthly MONTHLY", "Number of monthly snapshots to keep"
49
+ ) { |value| @options[:monthly] = value }
50
+
51
+ @opts.separator ""
52
+ @opts.separator "AWS Identifications, required unless environmental variables set"
53
+
54
+ @opts.on(
55
+ "-k", "--key KEY", "AWS Access Key (AMAZON_ACCESS_KEY_ID)"
56
+ ) { |value| @options[:access_key] = value }
57
+
58
+ @opts.on(
59
+ "-s", "--secret SECRET", "AWS Secret Access Key (AMAZON_SECRET_ACCESS_KEY)"
60
+ ) { |value| @options[:secret_key] = value }
61
+
62
+ @opts.separator ""
63
+ @opts.separator "Informational arguments"
64
+
65
+ @opts.on(
66
+ "-n", "--dry-run", "Describe what would be done (DOES NOT delete snapshots)"
67
+ ) { |value| @options[:verbose] = true }
68
+
69
+ @opts.on_tail("-h", "--help", "Show Command Help") do
70
+ puts @opts
71
+ puts ""
72
+ exit(1)
73
+ end
74
+
75
+ begin
76
+ @opts.parse!
77
+ rescue StandardError => e
78
+ send_error e.message
79
+ end
80
+
81
+ @options[:access_key] ||= ENV['AMAZON_ACCESS_KEY_ID']
82
+ @options[:secret_key] ||= ENV['AMAZON_SECRET_ACCESS_KEY']
83
+
84
+ unless @options[:access_key] && @options[:secret_key]
85
+ send_error "Missing Arguments: --key and --secret are required
86
+ NOTE: AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY env variables are accepted"
87
+ end
88
+
89
+ unless @options[:daily] && @options[:weekly] && @options[:monthly]
90
+ send_error "Missing Arguments: --daily, --weekly and --monthly are required"
91
+ end
92
+
93
+ ebs = EbsPruneSnapshot::Base.new(
94
+ :aws => {
95
+ :access_key => @options[:access_key],
96
+ :secret_key => @options[:secret_key]
97
+ },
98
+ :rotation => {
99
+ :daily => @options[:daily].to_i,
100
+ :weekly => @options[:weekly].to_i,
101
+ :monthly => @options[:monthly].to_i
102
+ }
103
+ )
104
+
105
+ if @options[:verbose]
106
+ ebs.describe
107
+ else
108
+ ebs.prune
109
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/ebs_prune_snapshot/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Dusty Doris"]
6
+ gem.email = ["dusty@doris.name"]
7
+ gem.description = %q{Prune EBS snapshots}
8
+ gem.summary = %q{Prune EBS snapshots on a daily, weekly, and monthly rotation}
9
+ gem.homepage = "https://github.com/dusty/ebs_prune_snapshot"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "ebs_prune_snapshot"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = EbsPruneSnapshot::VERSION
17
+
18
+ gem.add_runtime_dependency('amazon-ec2')
19
+ end
@@ -0,0 +1,249 @@
1
+ require "ebs_prune_snapshot/version"
2
+ require 'AWS'
3
+
4
+ module EbsPruneSnapshot
5
+ class Base
6
+
7
+ attr_reader :rotation, :aws
8
+
9
+ def initialize(args={})
10
+ @aws = Aws.new(args[:aws])
11
+ @rotation = Rotation.new(args[:rotation])
12
+ end
13
+
14
+ def volumes
15
+ @volumes ||= begin
16
+ volumes = {}
17
+ aws.snapshots.each do |snapshot|
18
+ _snapshot = Snapshot.new(snapshot)
19
+ volumes[_snapshot.volume_id] ||= []
20
+ volumes[_snapshot.volume_id].push(_snapshot)
21
+ end
22
+ volumes
23
+ end
24
+ end
25
+
26
+ def volume(volume_id)
27
+ volumes[volume_id]
28
+ end
29
+
30
+ def describe
31
+ puts rotation
32
+ volumes.keys.each { |volume_id| describe_volume(volume_id) }
33
+ end
34
+
35
+ def prune
36
+ volumes.keys.each { |volume_id| prune_volume(volume_id) }
37
+ end
38
+
39
+ def describe_volume(volume_id)
40
+ analyzer = SnapshotAnalyzer.new(volume(volume_id), rotation)
41
+ puts "VOLUME: #{volume_id}"
42
+ analyzer.to_skip.each {|snapshot| puts " SKIP: #{snapshot.snapshot_id} : #{snapshot.date}"}
43
+ analyzer.to_save.each {|snapshot| puts " KEEP: #{snapshot.snapshot_id} : #{snapshot.date}"}
44
+ analyzer.to_delete.each {|snapshot| puts " DELE: #{snapshot.snapshot_id} : #{snapshot.date}"}
45
+ end
46
+
47
+ def prune_volume(volume_id)
48
+ analyzer = SnapshotAnalyzer.new(volume(volume_id), rotation)
49
+ analyzer.to_delete.each { |snapshot| aws.delete(snapshot) }
50
+ end
51
+
52
+ end
53
+
54
+
55
+ class Aws
56
+
57
+ attr_reader :access_key, :secret_key
58
+
59
+ def initialize(args={})
60
+ args ||= {}
61
+ @access_key = args[:access_key] || ENV['AMAZON_ACCESS_KEY_ID']
62
+ @secret_key = args[:secret_key] || ENV['AMAZON_SECRET_ACCESS_KEY']
63
+ end
64
+
65
+ def connection
66
+ @aws ||= ::AWS::EC2::Base.new(
67
+ :access_key_id => access_key, :secret_access_key => secret_key
68
+ )
69
+ end
70
+
71
+ def snapshots
72
+ snapshots = connection.describe_snapshots(:owner => 'self')['snapshotSet']
73
+ snapshots ? snapshots["item"] : []
74
+ end
75
+
76
+ def delete(snapshot)
77
+ connection.delete_snapshot(:snapshot_id => snapshot.snapshot_id)
78
+ end
79
+
80
+ end
81
+
82
+ class SnapshotAnalyzer
83
+
84
+ attr_reader :snapshots, :rotation, :to_skip
85
+
86
+ def initialize(snapshots, rotation)
87
+ @snapshots = snapshots.sort
88
+ @rotation = rotation
89
+ @to_skip = []
90
+ @to_delete = []
91
+ @to_save = {}
92
+ analyze_snapshots
93
+ end
94
+
95
+ def to_save
96
+ @to_save.empty? ? [snapshots[-1]] : @to_save.values
97
+ end
98
+
99
+ def to_delete
100
+ snapshots - to_save - to_skip
101
+ end
102
+
103
+ def now
104
+ @now ||= Time.now.utc
105
+ end
106
+
107
+ protected
108
+
109
+ def save_newest_snapshot(snapshot, day)
110
+ @to_save[day_key(day)] = snapshot
111
+ end
112
+
113
+ def save_oldest_snapshot(snapshot, day)
114
+ @to_save[day_key(day)] ||= snapshot
115
+ end
116
+
117
+ def skip_snapshot(snapshot)
118
+ @to_skip.push(snapshot) unless @to_skip.include?(snapshot)
119
+ end
120
+
121
+ def analyze_snapshots
122
+ snapshots.each do |snapshot|
123
+ if snapshot.completed?
124
+ prune_daily(snapshot) || prune_weekly(snapshot) || prune_monthly(snapshot)
125
+ else
126
+ skip_snapshot(snapshot)
127
+ end
128
+ end
129
+ to_save.sort!
130
+ to_skip.sort!
131
+ to_delete.sort!
132
+ end
133
+
134
+ ## Save newest snapshot on a day
135
+ def prune_daily(snapshot)
136
+ catch :found do
137
+ (0..rotation.daily - 1).each do |count|
138
+ day = in_days(count)
139
+ if day_key(snapshot.created_at) == day_key(day)
140
+ save_newest_snapshot(snapshot, day)
141
+ throw :found, true
142
+ end
143
+ end
144
+ false
145
+ end
146
+ end
147
+
148
+ ## Save oldest snapshot on a week
149
+ def prune_weekly(snapshot)
150
+ catch :found do
151
+ (0..rotation.weekly - 1).each do |count|
152
+ week_beg = beginning_of_week(in_weeks(count))
153
+ week_end = end_of_week(in_weeks(count))
154
+ if snapshot.created_at >= week_beg && snapshot.created_at <= week_end
155
+ save_oldest_snapshot(snapshot, week_beg)
156
+ throw :found, true
157
+ end
158
+ end
159
+ false
160
+ end
161
+ end
162
+
163
+ ## Save oldest snapshot of every 4 weeks
164
+ def prune_monthly(snapshot)
165
+ catch :found do
166
+ (0..rotation.monthly - 1).each do |count|
167
+ month_beg = beginning_of_week(in_months(count))
168
+ month_end = end_of_week(in_months(count))
169
+ if snapshot.created_at >= month_beg && snapshot.created_at <= month_end
170
+ save_oldest_snapshot(snapshot, month_beg)
171
+ throw :found, true
172
+ end
173
+ end
174
+ false
175
+ end
176
+ end
177
+
178
+ def in_months(months)
179
+ in_weeks(months * 4)
180
+ end
181
+
182
+ def in_weeks(weeks)
183
+ in_days(weeks * 7)
184
+ end
185
+
186
+ def in_days(days)
187
+ now - (86400 * days)
188
+ end
189
+
190
+ def beginning_of_week(date)
191
+ days_from_sunday = date.wday
192
+ bow = (date - (86400 * days_from_sunday))
193
+ Time.utc(bow.year, bow.month, bow.day, 0, 0, 0)
194
+ end
195
+
196
+ def end_of_week(date)
197
+ days_till_saturday = (6 - date.wday)
198
+ eow = (date + (86400 * days_till_saturday))
199
+ Time.utc(eow.year, eow.month, eow.day, 23, 59, 59)
200
+ end
201
+
202
+ def day_key(day)
203
+ day.strftime("%Y%m%d")
204
+ end
205
+
206
+ end
207
+
208
+ class Snapshot
209
+
210
+ attr_reader :snapshot_id, :volume_id, :status, :created_at
211
+
212
+ def initialize(params={})
213
+ @snapshot_id = params['snapshotId']
214
+ @volume_id = params['volumeId']
215
+ @status = params['status']
216
+ @created_at = Time.parse(params['startTime']).utc
217
+ end
218
+
219
+ def completed?
220
+ status == 'completed'
221
+ end
222
+
223
+ def <=>(other)
224
+ created_at <=> other.created_at
225
+ end
226
+
227
+ def date
228
+ created_at.strftime("%Y%m%d")
229
+ end
230
+
231
+ end
232
+
233
+ class Rotation
234
+
235
+ attr_reader :daily, :weekly, :monthly
236
+
237
+ def initialize(args={})
238
+ @daily = args[:daily] ? args[:daily].to_i : 7
239
+ @weekly = args[:weekly] ? args[:weekly].to_i : 12
240
+ @monthly = args[:monthly] ? args[:monthly].to_i : 14
241
+ end
242
+
243
+ def to_s
244
+ "Rotation: Daily #{daily}, Weekly #{weekly}, Monthly #{monthly}"
245
+ end
246
+
247
+ end
248
+
249
+ end
@@ -0,0 +1,3 @@
1
+ module EbsPruneSnapshot
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #require 'time'
4
+ require 'ebs_prune_snapshot'
5
+ require 'minitest/autorun'
6
+
7
+ ##
8
+ # Generates snapshots that simulate amazon-ec describe snapshots
9
+ # - 400 daily completed snapshots for 2 different volumes
10
+ # - 1 daily pending snapshot for 2 volumes
11
+ # - 1 really old single snapshot for a 3rd volume
12
+ module EbsPruneSnapshot
13
+ class Tester
14
+
15
+ def self.snapshots
16
+ @snapshots ||= new.snapshots
17
+ end
18
+
19
+ def self.now
20
+ Time.utc(2012,5,1)
21
+ end
22
+
23
+ def generate_snapshot(snapshot_id, volume_id, start_time)
24
+ {
25
+ "snapshotId" => snapshot_id,
26
+ "volumeId" => volume_id,
27
+ "status" => 'completed',
28
+ "startTime" => start_time.xmlschema,
29
+ "progress" => '100%',
30
+ "ownerId" => '00000000',
31
+ "volumeSize" => '1',
32
+ "description" => "test #{snapshot_id}"
33
+ }
34
+ end
35
+
36
+ def initialize
37
+ @volumes = ['vol-000000', 'vol-000001']
38
+ @now = Tester.now
39
+ @days = 400
40
+ end
41
+
42
+ def snapshots
43
+ @items ||= begin
44
+ items = []
45
+ count = 0
46
+ # generate snapshots for each day for the previous 400 days for each volume
47
+ @volumes[0..1].each do |volume_id|
48
+ (0..@days - 1).each do |day|
49
+ snapshot_id = "%06d" % count
50
+ start_time = @now - (86400 * day)
51
+ items << generate_snapshot(snapshot_id, volume_id, start_time)
52
+ count += 1
53
+ end
54
+ end
55
+ # add pending snapshots
56
+ items << generate_snapshot("111111", @volumes[0], @now - 86400).update("status" => "pending")
57
+ items << generate_snapshot("222222", @volumes[1], @now - 86400).update("status" => "pending")
58
+
59
+ # add 2 really old snapshots under another volume
60
+ items << generate_snapshot("333333", @volumes[3], @now - 86400 * 7 * 60)
61
+ items << generate_snapshot("444444", @volumes[3], @now - 86400 * 7 * 90)
62
+ end
63
+ end
64
+
65
+ # Starting on 5/1/12, assuming a snapshot taken every day, with a 7/12/13 rotation
66
+ def self.expectations
67
+ day = [
68
+ Time.utc(2012,5,1), Time.utc(2012,4,30), Time.utc(2012,4,29), Time.utc(2012,4,28), Time.utc(2012,4,27),
69
+ Time.utc(2012,4,26), Time.utc(2012,4,25)
70
+ ]
71
+ week = [
72
+ Time.utc(2012,4,29), Time.utc(2012,4,22), Time.utc(2012,4,15), Time.utc(2012,4,8), Time.utc(2012,4,1),
73
+ Time.utc(2012,3,25), Time.utc(2012,3,18), Time.utc(2012,3,11), Time.utc(2012,3,4), Time.utc(2012,2,26),
74
+ Time.utc(2012,2,19), Time.utc(2012,2,12)
75
+ ]
76
+ month = [
77
+ Time.utc(2012,4,29), Time.utc(2012,4,1), Time.utc(2012,3,4), Time.utc(2012,2,5), Time.utc(2012,1,8),
78
+ Time.utc(2011,12,11), Time.utc(2011,11,13), Time.utc(2011,10,16), Time.utc(2011,9,18), Time.utc(2011,8,21),
79
+ Time.utc(2011,7,24), Time.utc(2011,6,26), Time.utc(2011,5,29), Time.utc(2011,5,1)
80
+ ]
81
+ (day + week + month).uniq.sort
82
+ end
83
+ end
84
+ end
85
+
86
+ ##
87
+ # Stub snapshots
88
+ class EbsPruneSnapshot::Aws
89
+ def snapshots
90
+ EbsPruneSnapshot::Tester.snapshots
91
+ end
92
+ def delete(snapshot)
93
+ puts "running delete on #{snapshot.snapshot_id}"
94
+ end
95
+ end
96
+ class EbsPruneSnapshot::SnapshotAnalyzer
97
+ def now
98
+ EbsPruneSnapshot::Tester.now
99
+ end
100
+ end
101
+
102
+
103
+ class TestEbsPruneSnapshot < MiniTest::Unit::TestCase
104
+ def self.ebs
105
+ @ebs ||= EbsPruneSnapshot::Base.new(:rotation => {:daily => 7, :weekly => 12, :monthly => 14})
106
+ end
107
+
108
+ def setup
109
+ @ebs = self.class.ebs
110
+ end
111
+
112
+ def self.now
113
+ Time.utc(2012,5,1)
114
+ end
115
+
116
+ def in_days(days)
117
+ self.class.now - (86400 * days)
118
+ end
119
+
120
+ def test_sort_by_volume
121
+ assert_equal self.class.ebs.volumes.count, 3
122
+ end
123
+
124
+ def test_volume_analyzer
125
+ vol1 = @ebs.volumes[@ebs.volumes.keys[0]]
126
+ vol2 = @ebs.volumes[@ebs.volumes.keys[1]]
127
+ [vol1, vol2].each do |snapshots|
128
+ analyzer = EbsPruneSnapshot::SnapshotAnalyzer.new(snapshots, @ebs.rotation)
129
+ assert_equal analyzer.to_save.count, 29
130
+ assert_equal analyzer.to_skip.count, 1
131
+ assert_equal analyzer.to_delete.count, 371
132
+ end
133
+ end
134
+
135
+ def test_safety_mechanism
136
+ snapshots = @ebs.volumes[@ebs.volumes.keys[2]]
137
+ analyzer = EbsPruneSnapshot::SnapshotAnalyzer.new(snapshots, @ebs.rotation)
138
+ assert_equal analyzer.to_save.count, 1
139
+ assert_equal analyzer.to_skip.count, 0
140
+ assert_equal analyzer.to_delete.count, 1
141
+ assert_equal analyzer.to_save.first.snapshot_id, "333333"
142
+ end
143
+
144
+ def test_actual_expected_dates
145
+ vol1 = @ebs.volumes[@ebs.volumes.keys[0]]
146
+ vol2 = @ebs.volumes[@ebs.volumes.keys[1]]
147
+ [vol1, vol2].each do |snapshots|
148
+ analyzer = EbsPruneSnapshot::SnapshotAnalyzer.new(snapshots, @ebs.rotation)
149
+ assert_equal analyzer.to_save.map {|s| s.created_at} , EbsPruneSnapshot::Tester.expectations
150
+ end
151
+ end
152
+
153
+ def test_describe
154
+ skip
155
+ @ebs.describe
156
+ end
157
+
158
+ def test_prune
159
+ skip
160
+ @ebs.prune
161
+ end
162
+
163
+ end
164
+
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ebs_prune_snapshot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dusty Doris
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: amazon-ec2
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Prune EBS snapshots
31
+ email:
32
+ - dusty@doris.name
33
+ executables:
34
+ - ebs_prune_snapshot
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.txt
42
+ - Rakefile
43
+ - bin/ebs_prune_snapshot
44
+ - ebs_prune_snapshot.gemspec
45
+ - lib/ebs_prune_snapshot.rb
46
+ - lib/ebs_prune_snapshot/version.rb
47
+ - test/test_ebs_prune_snapshot.rb
48
+ homepage: https://github.com/dusty/ebs_prune_snapshot
49
+ licenses: []
50
+ post_install_message:
51
+ rdoc_options: []
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ requirements: []
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.22
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: Prune EBS snapshots on a daily, weekly, and monthly rotation
72
+ test_files:
73
+ - test/test_ebs_prune_snapshot.rb