ebs_snapshot_cleanup 0.5.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/README.rdoc +22 -0
- data/Rakefile +60 -0
- data/VERSION +1 -0
- data/bin/cleanup-ebs-snapshots +87 -0
- metadata +77 -0
data/README.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
= ebs_snapshot_cleanup
|
2
|
+
|
3
|
+
Command-line utility to clean up your EBS snapshots.
|
4
|
+
|
5
|
+
You'll be prompted before anything is removed. In this version:
|
6
|
+
|
7
|
+
* every snapshot in the current month is retained
|
8
|
+
* last snapshot for every prior month is returned, all others are removed
|
9
|
+
|
10
|
+
In addition, you're prompted to remove snapshots of volumes that no longer exist.
|
11
|
+
|
12
|
+
== USAGE
|
13
|
+
|
14
|
+
Make sure your have an /etc/aws.conf as per aws_credentials[http://github.com/bkoski/aws_credentials]. Then:
|
15
|
+
|
16
|
+
cleanup-ebs-snapshots
|
17
|
+
|
18
|
+
and follow the prompts.
|
19
|
+
|
20
|
+
== AUTHOR
|
21
|
+
|
22
|
+
Ben Koski, bkoski@nytimes.com
|
data/Rakefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ebs_snapshot_cleanup"
|
8
|
+
gem.summary = %Q{Command-line utility to clean up EBS snapshots}
|
9
|
+
gem.description = %Q{Command-line utility to clean up EBS snapshots}
|
10
|
+
gem.email = "bkoski@nytimes.com"
|
11
|
+
gem.homepage = "http://github.com/bkoski/ebs_snapshot_cleanup"
|
12
|
+
gem.authors = ["Ben Koski"]
|
13
|
+
gem.add_dependency 'amazon-ec2', '0.9.12'
|
14
|
+
gem.add_dependency 'aws_credentials'
|
15
|
+
gem.files = ['bin/cleanup-ebs-snapshots','Rakefile','README.rdoc','VERSION']
|
16
|
+
|
17
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
Rake::TestTask.new(:test) do |test|
|
26
|
+
test.libs << 'lib' << 'test'
|
27
|
+
test.pattern = 'test/**/*_test.rb'
|
28
|
+
test.verbose = true
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
require 'rcov/rcovtask'
|
33
|
+
Rcov::RcovTask.new do |test|
|
34
|
+
test.libs << 'test'
|
35
|
+
test.pattern = 'test/**/*_test.rb'
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
rescue LoadError
|
39
|
+
task :rcov do
|
40
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
task :test => :check_dependencies
|
45
|
+
|
46
|
+
task :default => :test
|
47
|
+
|
48
|
+
require 'rake/rdoctask'
|
49
|
+
Rake::RDocTask.new do |rdoc|
|
50
|
+
if File.exist?('VERSION')
|
51
|
+
version = File.read('VERSION')
|
52
|
+
else
|
53
|
+
version = ""
|
54
|
+
end
|
55
|
+
|
56
|
+
rdoc.rdoc_dir = 'rdoc'
|
57
|
+
rdoc.title = "ebs_snapshot_cleanup #{version}"
|
58
|
+
rdoc.rdoc_files.include('README*')
|
59
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
60
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.0
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'aws_credentials'
|
4
|
+
require 'AWS'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
@ec2 = AWS::EC2::Base.new(:access_key_id => AWSCredentials.access_key,
|
8
|
+
:secret_access_key => AWSCredentials.secret_access_key)
|
9
|
+
|
10
|
+
|
11
|
+
def get_snapshots_by_volume
|
12
|
+
snapshot_data = @ec2.describe_snapshots(:owner => 'self')['snapshotSet']['item']
|
13
|
+
|
14
|
+
by_volume = {}
|
15
|
+
snapshot_data.each do |s|
|
16
|
+
by_volume[s['volumeId']] ||= []
|
17
|
+
by_volume[s['volumeId']] << s
|
18
|
+
end
|
19
|
+
|
20
|
+
return by_volume
|
21
|
+
end
|
22
|
+
|
23
|
+
active_volume_ids = @ec2.describe_volumes['volumeSet']['item'].collect { |v| v['volumeId'] }
|
24
|
+
snapshots_by_volume = get_snapshots_by_volume
|
25
|
+
|
26
|
+
(snapshots_by_volume.keys - active_volume_ids).each do |orphaned_volume_id|
|
27
|
+
next unless snapshots_by_volume.has_key?(orphaned_volume_id)
|
28
|
+
|
29
|
+
puts
|
30
|
+
puts "There are #{snapshots_by_volume[orphaned_volume_id].length} snapshot(s) for #{orphaned_volume_id}, which doesn't appear to exist."
|
31
|
+
print "Okay to remove? (y/N) "
|
32
|
+
|
33
|
+
okay = gets.strip
|
34
|
+
if okay.downcase == 'y'
|
35
|
+
puts "Removing..."
|
36
|
+
snapshots_by_volume[orphaned_volume_id].each { |s| @ec2.delete_snapshot(:snapshot_id => s['snapshotId']) }
|
37
|
+
puts "Done!"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
get_snapshots_by_volume.each do |volume, snapshots|
|
42
|
+
|
43
|
+
snapshots_by_month = {}
|
44
|
+
snaps_to_remove = []
|
45
|
+
snapshots.each do |s|
|
46
|
+
next if s['status'] != 'completed'
|
47
|
+
taken_at = Time.parse(s['startTime'])
|
48
|
+
|
49
|
+
key = "#{taken_at.year}-#{'%02i' % taken_at.month}"
|
50
|
+
snapshots_by_month[key] ||= []
|
51
|
+
snapshots_by_month[key] << s
|
52
|
+
end
|
53
|
+
|
54
|
+
snapshots_by_month.each do |month, month_snaps|
|
55
|
+
next if month == "#{Time.now.year}-#{'%02i' % Time.now.month}"
|
56
|
+
next if month_snaps.length == 1
|
57
|
+
snaps_to_remove += month_snaps[0, month_snaps.length - 1]
|
58
|
+
end
|
59
|
+
|
60
|
+
next if snaps_to_remove.length == 0
|
61
|
+
|
62
|
+
puts
|
63
|
+
puts "Volume: #{volume}"
|
64
|
+
puts "#{snapshots.length} snapshots total, removing #{snaps_to_remove.length}"
|
65
|
+
|
66
|
+
puts "Snapshots that will remain:"
|
67
|
+
(snapshots - snaps_to_remove).sort { |a,b| a['startTime'] <=> b['startTime'] }.each do |remaining_snap|
|
68
|
+
puts "#{remaining_snap['snapshotId']}\t#{remaining_snap['startTime']}"
|
69
|
+
end
|
70
|
+
|
71
|
+
puts
|
72
|
+
puts "Snapshots to be removed:"
|
73
|
+
snaps_to_remove.sort { |a,b| a['startTime'] <=> b['startTime'] }.each do |snap_to_remove|
|
74
|
+
puts "#{snap_to_remove['snapshotId']}\t#{snap_to_remove['startTime']}"
|
75
|
+
end
|
76
|
+
|
77
|
+
puts
|
78
|
+
print "Okay to remove #{snaps_to_remove.length} snapshot(s) for volume #{volume}? (y/N) "
|
79
|
+
okay = gets.strip
|
80
|
+
|
81
|
+
if okay.downcase == 'y'
|
82
|
+
puts "Removing..."
|
83
|
+
snaps_to_remove.each { |s| @ec2.delete_snapshot(:snapshot_id => s['snapshotId']) }
|
84
|
+
puts "Done!"
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ebs_snapshot_cleanup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ben Koski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-05-10 00:00:00 -04:00
|
13
|
+
default_executable: cleanup-ebs-snapshots
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: amazon-ec2
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.12
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: aws_credentials
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description: Command-line utility to clean up EBS snapshots
|
36
|
+
email: bkoski@nytimes.com
|
37
|
+
executables:
|
38
|
+
- cleanup-ebs-snapshots
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files:
|
42
|
+
- README.rdoc
|
43
|
+
files:
|
44
|
+
- README.rdoc
|
45
|
+
- Rakefile
|
46
|
+
- VERSION
|
47
|
+
- bin/cleanup-ebs-snapshots
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://github.com/bkoski/ebs_snapshot_cleanup
|
50
|
+
licenses: []
|
51
|
+
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options:
|
54
|
+
- --charset=UTF-8
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.3.5
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Command-line utility to clean up EBS snapshots
|
76
|
+
test_files: []
|
77
|
+
|