aebus 0.0.2 → 0.0.3
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 -1
- data/bin/aebus +11 -5
- data/lib/aebus.rb +140 -56
- data/lib/aebus/logging.rb +27 -0
- data/lib/aebus/version.rb +1 -1
- data/lib/aebus/volume_status.rb +23 -0
- data/lib/config/volume.rb +30 -16
- data/lib/ec2/snapshot.rb +1 -2
- metadata +10 -8
data/.gitignore
CHANGED
data/bin/aebus
CHANGED
@@ -12,6 +12,7 @@ program :version, Aebus::VERSION
|
|
12
12
|
program :description, 'Automatic EC2 BackUp Software'
|
13
13
|
|
14
14
|
global_option('-c','--config FILE', 'The YAML file containing the backup configuration')
|
15
|
+
global_option('-l', '--logfile FILE', 'A log file which will receive the output')
|
15
16
|
|
16
17
|
default_command :help
|
17
18
|
|
@@ -28,8 +29,13 @@ command :status do |c|
|
|
28
29
|
c.when_called do |args, options|
|
29
30
|
options.default \
|
30
31
|
:config => DEFAULT_CONFIG_NAME
|
31
|
-
|
32
|
-
|
32
|
+
begin
|
33
|
+
FileTest.exist?(Pathname.new(options.config).realpath)
|
34
|
+
rescue Errno::ENOENT => e
|
35
|
+
puts ("Configuration file not found")
|
36
|
+
exit(2)
|
37
|
+
end
|
38
|
+
aebus = Aebus::Core.new
|
33
39
|
aebus.status(args,options)
|
34
40
|
end
|
35
41
|
end
|
@@ -41,9 +47,9 @@ command :backup do |c|
|
|
41
47
|
Backs up a set of EC2 Volumes, according to the configuration file. If no volume is specified in the
|
42
48
|
command line, all volumes defined in the config file are backed up
|
43
49
|
eos
|
44
|
-
c.example 'Manually creates backup of vol1 and vol2', 'aebus backup
|
50
|
+
c.example 'Manually creates backup of vol1 and vol2', 'aebus backup -m vol1 vol2'
|
45
51
|
c.example 'Create, if needed, backups for all volumes', 'aebus backup'
|
46
|
-
c.option '--manual', 'Starts a manual backup (always creates a snapshot for each volume)'
|
52
|
+
c.option '-m', '--manual', 'Starts a manual backup (always creates a snapshot for each volume)'
|
47
53
|
c.option '--[no-]purge', 'Do not purge expired backups, defaults to --purge'
|
48
54
|
c.when_called do |args, options|
|
49
55
|
options.default \
|
@@ -51,7 +57,7 @@ command :backup do |c|
|
|
51
57
|
:manual => false,
|
52
58
|
:purge => true
|
53
59
|
raise ("Config file does not exist") unless FileTest.exist?(Pathname.new(options.config).realpath)
|
54
|
-
aebus = Aebus::
|
60
|
+
aebus = Aebus::Core.new
|
55
61
|
aebus.backup(args,options)
|
56
62
|
end
|
57
63
|
end
|
data/lib/aebus.rb
CHANGED
@@ -4,73 +4,133 @@ require 'rubygems'
|
|
4
4
|
require 'AWS'
|
5
5
|
require_relative 'config/config'
|
6
6
|
require_relative 'aebus/version'
|
7
|
+
require_relative 'aebus/logging'
|
8
|
+
require_relative 'aebus/volume_status'
|
7
9
|
require_relative 'ec2/zones'
|
8
10
|
require_relative 'ec2/snapshot'
|
9
11
|
|
10
12
|
module Aebus
|
11
13
|
|
12
|
-
class
|
14
|
+
class Core
|
15
|
+
|
16
|
+
include Logging
|
13
17
|
|
14
18
|
AWS_NAME_TAG = "Name"
|
15
19
|
AEBUS_TAG = "Aebus"
|
16
20
|
|
17
21
|
def status(args, options)
|
18
|
-
current_time_utc = Time.now.utc
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
@current_time_utc = Time.now.utc
|
23
|
+
init_logger options
|
24
|
+
logger.info("status check started at #{@current_time_utc}")
|
25
|
+
|
26
|
+
@config = Config::Config.new(File.join(File.dirname("."), options.config), @current_time_utc)
|
27
|
+
@ec2 = AWS::EC2::Base.new(:access_key_id => @config.defaults["access_key_id"],
|
28
|
+
:secret_access_key => @config.defaults["secret_access_key"],
|
29
|
+
:server => EC2::zone_to_url(@config.defaults["zone"]))
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
target_volumes = target_volumes(args)
|
34
|
+
|
35
|
+
abort("Configuration contains invalid volumes") unless validate_target_volumes(target_volumes)
|
36
|
+
|
37
|
+
status = check_status(target_volumes)
|
38
|
+
|
39
|
+
message = "status check completed - #{status[:total]} volume(s) checked, #{status[:to_backup]} to be backed up, max delay detected #{status[:delay]}s, #{status[:to_purge]} snapshots to be purged"
|
40
|
+
logger.info message
|
41
|
+
puts message
|
23
42
|
|
24
|
-
target_volumes = calculate_target_volumes(config, args)
|
25
|
-
snap_map = get_snapshots_map
|
26
43
|
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
def check_status(target_volumes)
|
48
|
+
result = {}
|
49
|
+
result[:timestamp] = @current_time_utc
|
50
|
+
snap_map = get_snapshots_map
|
51
|
+
result[:volumes] = Array.new
|
52
|
+
to_backup = 0
|
53
|
+
to_purge = 0
|
27
54
|
target_volumes.each do |target|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
55
|
+
vs = VolumeStatus.new(target)
|
56
|
+
volume = @config.volumes[target]
|
57
|
+
vs.last_backup = volume.last_backup
|
58
|
+
vs.next_backup = volume.next_backup
|
59
|
+
to_be_run = volume.backups_to_be_run(snap_map[target], @current_time_utc)
|
60
|
+
|
61
|
+
vs.delay = to_be_run[0]
|
62
|
+
vs.tags = to_be_run[1]
|
63
|
+
|
64
|
+
if (vs.needs_backup?) then
|
65
|
+
logger.info("Volume #{target} needs to be backed up. Tags: #{vs.tags.join(',')}, max delay #{vs.delay}")
|
66
|
+
to_backup += 1
|
32
67
|
else
|
33
|
-
|
68
|
+
logger.info("Volume #{target} does not need to be backed up")
|
34
69
|
end
|
35
70
|
|
36
|
-
|
37
|
-
|
71
|
+
vs.purgeable_snapshot_ids = volume.purgeable_snapshot_ids(snap_map[target])
|
72
|
+
to_purge += vs.purgeable_snapshot_ids.count if vs.purgeable_snapshot_ids
|
73
|
+
logger.info("Volume #{target} has #{vs.purgeable_snapshot_ids.count} purgeable snapshot(s): #{vs.purgeable_snapshot_ids.join(',')}")
|
38
74
|
|
39
|
-
|
75
|
+
result[:volumes] << vs
|
40
76
|
|
77
|
+
end
|
78
|
+
result[:to_backup] = to_backup
|
79
|
+
result[:to_purge] = to_purge
|
80
|
+
result[:delay] = result[:volumes].inject([0]) {|acc, vs| acc << vs.delay}.max
|
81
|
+
result[:total] = result[:volumes].count
|
82
|
+
result
|
41
83
|
|
42
84
|
end
|
43
85
|
|
86
|
+
|
87
|
+
|
44
88
|
def backup(args, options)
|
45
89
|
|
46
|
-
current_time_utc = Time.now.utc
|
47
|
-
config = Config::Config.new(File.join(File.dirname("."), options.config), current_time_utc)
|
48
|
-
@ec2 = AWS::EC2::Base.new(:access_key_id => config.defaults["access_key_id"],
|
49
|
-
:secret_access_key => config.defaults["secret_access_key"],
|
50
|
-
:server => EC2::zone_to_url(config.defaults["zone"]))
|
51
90
|
|
52
|
-
|
91
|
+
backed_up = 0
|
92
|
+
max_delay = 0
|
93
|
+
purged = 0
|
94
|
+
to_purge = 0
|
95
|
+
to_backup = 0
|
96
|
+
@current_time_utc = Time.now.utc
|
97
|
+
@config = Config::Config.new(File.join(File.dirname("."), options.config), @current_time_utc)
|
98
|
+
|
99
|
+
init_logger options
|
100
|
+
logger.info("backup started at #{@current_time_utc}")
|
101
|
+
|
102
|
+
@ec2 = AWS::EC2::Base.new(:access_key_id => @config.defaults["access_key_id"],
|
103
|
+
:secret_access_key => @config.defaults["secret_access_key"],
|
104
|
+
:server => EC2::zone_to_url(@config.defaults["zone"]))
|
105
|
+
|
106
|
+
target_volumes = target_volumes(args)
|
53
107
|
if (options.manual) then
|
54
108
|
|
55
109
|
target_volumes.each do |volume|
|
56
|
-
|
57
|
-
backup_volume(volume,
|
110
|
+
to_backup += 1
|
111
|
+
break unless backup_volume(volume, [EC2::AEBUS_MANUAL_TAG])
|
112
|
+
backed_up += 1
|
58
113
|
|
59
114
|
end
|
60
115
|
|
61
116
|
else
|
62
117
|
|
63
118
|
snap_map = get_snapshots_map
|
119
|
+
|
64
120
|
target_volumes.each do |target|
|
65
121
|
|
66
|
-
volume = config.volumes[target]
|
67
|
-
|
122
|
+
volume = @config.volumes[target]
|
123
|
+
to_be_run = volume.backups_to_be_run(snap_map[target], @current_time_utc)
|
124
|
+
max_delay = [max_delay, to_be_run[0]].max
|
125
|
+
tags = to_be_run[1]
|
68
126
|
if (tags.count > 0) then
|
69
127
|
tags << EC2::AEBUS_AUTO_TAG
|
70
|
-
|
71
|
-
|
128
|
+
logger.info("Creating backup for volume #{target} with tags #{tags.join(',')}, max delay #{max_delay}")
|
129
|
+
to_backup +=1
|
130
|
+
break unless backup_volume(target, tags)
|
131
|
+
backed_up += 1
|
72
132
|
else
|
73
|
-
|
133
|
+
logger.info("Volume #{target} does not need to be backed up")
|
74
134
|
end
|
75
135
|
|
76
136
|
end
|
@@ -78,21 +138,29 @@ module Aebus
|
|
78
138
|
snap_map = get_snapshots_map # we reload the map since we may have created more snapshots
|
79
139
|
if (options.purge) then
|
80
140
|
target_volumes.each do |target|
|
81
|
-
volume = config.volumes[target]
|
82
|
-
|
83
|
-
|
141
|
+
volume = @config.volumes[target]
|
142
|
+
purgeable_snapshot_ids = volume.purgeable_snapshot_ids(snap_map[target])
|
143
|
+
purgeable_snapshot_ids.each do |snapshot_id|
|
144
|
+
to_purge += 1
|
145
|
+
purged += 1 if purge_snapshot(snapshot_id)
|
146
|
+
|
147
|
+
end
|
84
148
|
end
|
85
149
|
else
|
86
|
-
|
150
|
+
logger.info("Skipping purging phase")
|
87
151
|
end
|
88
152
|
|
89
153
|
end
|
90
154
|
|
155
|
+
message = "Backup Completed at #{Time.now}. Checked #{target_volumes.count} volume(s), backed up #{backed_up}, max delay detected #{max_delay}, #{to_purge} purgeable snapshot(s), #{purged} purged"
|
156
|
+
logger.info(message)
|
157
|
+
puts(message)
|
158
|
+
|
91
159
|
end
|
92
160
|
|
93
|
-
def
|
161
|
+
def target_volumes(args)
|
94
162
|
|
95
|
-
result = config.volume_ids
|
163
|
+
result = @config.volume_ids
|
96
164
|
if (args && (args.count > 0)) then
|
97
165
|
result &= args
|
98
166
|
end
|
@@ -101,35 +169,31 @@ module Aebus
|
|
101
169
|
|
102
170
|
end
|
103
171
|
|
104
|
-
def
|
105
|
-
|
106
|
-
puts(response)
|
172
|
+
def init_logger(options)
|
173
|
+
Logging.log_to_file(options.logfile) unless options.logfile.nil?
|
107
174
|
end
|
108
175
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
176
|
+
# backs up a given volume using the given time as part of the name and setting the given tags to the snapshot
|
177
|
+
# @param volume_id [String] the id of the volume to be backed up
|
178
|
+
# @param tags [Array] an array of String to be used as tags for the snapshot
|
179
|
+
# @return [boolean] true if the backup was successful, false otherwise
|
180
|
+
def backup_volume(volume_id, tags)
|
113
181
|
begin
|
114
182
|
volume_info = @ec2.describe_volumes(:volume_id => volume_id)
|
115
183
|
|
116
184
|
rescue AWS::Error => e
|
117
|
-
|
185
|
+
logger.error("Volume Id #{volume_id} not found. Underlying message #{e.message}")
|
118
186
|
return false
|
119
187
|
end
|
120
188
|
|
121
189
|
begin
|
122
|
-
puts(volume_info)
|
123
190
|
volume_tags = volume_info.volumeSet.item[0].tagSet.item
|
124
|
-
puts(volume_tags)
|
125
191
|
|
126
|
-
name_and_desc =
|
127
|
-
puts(name_and_desc)
|
192
|
+
name_and_desc = Core.name_and_desc(volume_id, volume_tags, @current_time_utc)
|
128
193
|
create_response = @ec2.create_snapshot(:volume_id => volume_id, :description => name_and_desc[1])
|
129
|
-
puts(create_response)
|
130
194
|
|
131
195
|
rescue AWS::Error => e
|
132
|
-
|
196
|
+
logger.error("Volume Id #{volume_id} could not be backed up. Underlying message #{e.message}")
|
133
197
|
return false
|
134
198
|
end
|
135
199
|
|
@@ -138,18 +202,22 @@ module Aebus
|
|
138
202
|
@ec2.create_tags(:resource_id => create_response.snapshotId,
|
139
203
|
:tag => [{AWS_NAME_TAG => name_and_desc[0]}, {AEBUS_TAG => tags.join(',')}])
|
140
204
|
rescue AWS::Error => e
|
141
|
-
|
205
|
+
logger.error("[WARNING] Could not set tags to snapshot #{create_response.snapshotId}. Underlying message #{e.message}")
|
142
206
|
return false
|
143
207
|
end
|
144
208
|
|
145
|
-
|
209
|
+
logger.info("Created snapshot #{create_response.snapshotId} for volume #{volume_id}")
|
146
210
|
|
147
|
-
|
211
|
+
true
|
148
212
|
|
149
213
|
end
|
150
214
|
|
151
|
-
|
152
|
-
|
215
|
+
# calculates the name and the description to be set to a snapshot
|
216
|
+
# @param volume_id [String] the id of the volume whose snapshot we are creating
|
217
|
+
# @param tags [Array] the tags currently associated with the Volume
|
218
|
+
# @param utc_time [Time] the UTC time at which the backup process started (used to generate the correct name)
|
219
|
+
# @return [Array] an array in the form of [name, description]]
|
220
|
+
def self.name_and_desc(volume_id, tags, utc_time)
|
153
221
|
|
154
222
|
name = "backup_#{utc_time.strftime("%Y%m%d")}_#{volume_id}"
|
155
223
|
volume_name = volume_id
|
@@ -192,10 +260,26 @@ module Aebus
|
|
192
260
|
begin
|
193
261
|
response = @ec2.delete_snapshot(:snapshot_id => snapshot_id)
|
194
262
|
if (response["return"]) then
|
195
|
-
|
263
|
+
logger.info("Purged snapshot #{snapshot_id}")
|
264
|
+
true
|
265
|
+
else
|
266
|
+
false
|
196
267
|
end
|
197
268
|
rescue AWS::Error => e
|
198
|
-
|
269
|
+
logger.warn("Could not purge snapshot #{snapshot_id}; underlying message #{e.message}")
|
270
|
+
false
|
271
|
+
end
|
272
|
+
|
273
|
+
end
|
274
|
+
|
275
|
+
def validate_target_volumes(target_volumes)
|
276
|
+
begin
|
277
|
+
@ec2.describe_volumes(:volume_id => target_volumes)
|
278
|
+
logger.info("Target volumes validated")
|
279
|
+
true
|
280
|
+
rescue AWS::Error => e
|
281
|
+
logger.error("Target validation failed with message '#{e.message}' Check your configuration")
|
282
|
+
false
|
199
283
|
end
|
200
284
|
|
201
285
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Aebus
|
4
|
+
|
5
|
+
module Logging
|
6
|
+
|
7
|
+
def logger
|
8
|
+
Logging.logger
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger
|
12
|
+
@logger ||= Logger.new(STDOUT)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.log_to_file(file)
|
16
|
+
begin
|
17
|
+
@logger = Logger.new(file, 'daily')
|
18
|
+
rescue Errno::EACCES => e
|
19
|
+
logger.warn("Could not create log file, '#{e.message}'. Defaulting to STDOUT")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
data/lib/aebus/version.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Aebus
|
2
|
+
|
3
|
+
class VolumeStatus
|
4
|
+
|
5
|
+
attr_accessor :id, :last_backup, :next_backup, :delay, :purgeable_snapshot_ids, :tags
|
6
|
+
|
7
|
+
def initialize(volume_id)
|
8
|
+
@id = volume_id
|
9
|
+
end
|
10
|
+
|
11
|
+
def needs_backup?
|
12
|
+
(!@tags.nil? && (@tags.count > 0))
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"Volume: id => #{id}, :last_backup => #{last_backup}, next_backup=> #{next_backup}, needs_backup? => #{needs_backup?}, delay => #{delay}, tags => #{tags}, purgeable_snapshot => #{purgeable_snapshots}"
|
17
|
+
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/lib/config/volume.rb
CHANGED
@@ -16,6 +16,8 @@ module Aebus
|
|
16
16
|
calculate_deadlines(current_time_utc, backup_config["when"])
|
17
17
|
end
|
18
18
|
@keep = backup_config["keep"]
|
19
|
+
# we use Infinity to model the keep all
|
20
|
+
@keep = 1.0 / 0 if (@keep.nil? || @keep.eql?(KEEP_ALL))
|
19
21
|
|
20
22
|
end
|
21
23
|
|
@@ -39,7 +41,7 @@ module Aebus
|
|
39
41
|
result = Hash.new
|
40
42
|
|
41
43
|
backups_config.each_pair do |key,value|
|
42
|
-
|
44
|
+
result.store(key, BackupSchedule.new(current_time_utc, key, value))
|
43
45
|
end
|
44
46
|
|
45
47
|
result
|
@@ -62,20 +64,23 @@ module Aebus
|
|
62
64
|
end
|
63
65
|
end
|
64
66
|
|
65
|
-
def backups_to_be_run(snapshots)
|
67
|
+
def backups_to_be_run(snapshots,current_time_utc)
|
66
68
|
|
67
69
|
result = Array.new
|
68
|
-
|
70
|
+
max_delay = 0
|
69
71
|
@backups.each_pair do |k,v|
|
70
72
|
|
71
|
-
|
73
|
+
unless recent_backup?(k, snapshots, v.last_deadline)
|
74
|
+
result << k
|
75
|
+
max_delay = [max_delay, current_time_utc.to_i - v.last_deadline.to_i].max
|
76
|
+
end
|
72
77
|
|
73
78
|
end
|
74
|
-
result
|
79
|
+
[max_delay, result]
|
75
80
|
end
|
76
81
|
|
77
82
|
def recent_backup?(label, snapshots, last_deadline)
|
78
|
-
|
83
|
+
return false unless snapshots
|
79
84
|
snapshots.each do |snapshot|
|
80
85
|
|
81
86
|
if (snapshot.aebus_tags_include?(label) && (snapshot.start_time > last_deadline))
|
@@ -86,31 +91,40 @@ module Aebus
|
|
86
91
|
false
|
87
92
|
end
|
88
93
|
|
89
|
-
|
90
|
-
|
94
|
+
|
95
|
+
def purgeable_snapshot_ids(snapshots)
|
96
|
+
return [] unless snapshots
|
91
97
|
removables = snapshots.select{|snapshot| snapshot.aebus_removable_snapshot?}
|
92
|
-
puts(removables.count)
|
93
98
|
available_backups = @backups.each_with_object({}) { | (k, v) , h | h[k] = v.keep}
|
94
99
|
removables.each do |snapshot|
|
95
100
|
snapshot.aebus_tags.each do |tag|
|
96
|
-
if (available_backups.include? tag) then
|
97
|
-
if (KEEP_ALL.eql?(available_backups[tag])) then
|
98
|
-
puts("Keeping snapshot #{snapshot.id} because of all on #{tag}")
|
99
|
-
snapshot.keep = true
|
100
|
-
elsif (available_backups[tag] > 0) then
|
101
|
+
if ((available_backups.include? tag) && (available_backups[tag] > 0)) then
|
101
102
|
snapshot.keep = true
|
102
103
|
available_backups[tag] -= 1
|
103
|
-
end
|
104
104
|
end
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
|
-
removables.
|
108
|
+
removables.inject([]) do |acc, snapshot|
|
109
|
+
acc << snapshot.id unless snapshot.keep?
|
110
|
+
acc
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
def last_backup
|
116
|
+
@backups.values.map{|backup| backup.last_deadline}.max
|
117
|
+
end
|
109
118
|
|
119
|
+
def next_backup
|
120
|
+
@backups.values.map{|backup| backup.next_deadline}.min
|
110
121
|
end
|
111
122
|
|
123
|
+
|
112
124
|
end
|
113
125
|
|
126
|
+
|
127
|
+
|
114
128
|
end
|
115
129
|
|
116
130
|
end
|
data/lib/ec2/snapshot.rb
CHANGED
@@ -35,7 +35,6 @@ module Aebus
|
|
35
35
|
|
36
36
|
def aebus_tags_include?(label)
|
37
37
|
if aebus_snapshot? then
|
38
|
-
aebus_tags = @tags[AEBUS_TAG].split(',')
|
39
38
|
return aebus_tags.include? label
|
40
39
|
end
|
41
40
|
false
|
@@ -46,11 +45,11 @@ module Aebus
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def aebus_removable_snapshot?
|
48
|
+
return false unless aebus_snapshot?
|
49
49
|
(aebus_tags & [AEBUS_MANUAL_TAG, AEBUS_KEEP_TAG]).count == 0
|
50
50
|
end
|
51
51
|
|
52
52
|
def aebus_tags
|
53
|
-
return nil unless aebus_snapshot?
|
54
53
|
@tags[AEBUS_TAG].split(',')
|
55
54
|
end
|
56
55
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aebus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-11-28 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: commander
|
16
|
-
requirement: &
|
16
|
+
requirement: &70278571512580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 4.0.6
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70278571512580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: parse-cron
|
27
|
-
requirement: &
|
27
|
+
requirement: &70278571512080 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.1.1
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70278571512080
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: amazon-ec2
|
38
|
-
requirement: &
|
38
|
+
requirement: &70278571511620 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,7 +43,7 @@ dependencies:
|
|
43
43
|
version: 0.9.17
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70278571511620
|
47
47
|
description: A tool to automate snapshot management in EC2
|
48
48
|
email:
|
49
49
|
- nessche@gmail.com
|
@@ -59,7 +59,9 @@ files:
|
|
59
59
|
- aebus.gemspec
|
60
60
|
- bin/aebus
|
61
61
|
- lib/aebus.rb
|
62
|
+
- lib/aebus/logging.rb
|
62
63
|
- lib/aebus/version.rb
|
64
|
+
- lib/aebus/volume_status.rb
|
63
65
|
- lib/config/config.rb
|
64
66
|
- lib/config/volume.rb
|
65
67
|
- lib/ec2/snapshot.rb
|