vgh 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -1
- data/CHANGELOG.rdoc +6 -0
- data/README.rdoc +36 -46
- data/Rakefile +7 -0
- data/conf/config.yml.example +27 -6
- data/lib/vgh/apps/checkpoint.rb +55 -0
- data/lib/vgh/apps/ec2_backup.rb +21 -45
- data/lib/vgh/apps.rb +2 -1
- data/lib/vgh/cli.rb +9 -9
- data/lib/vgh/configuration.rb +60 -71
- data/lib/vgh/{extended_aws/extended_ec2 → ec2}/metadata.rb +5 -6
- data/lib/vgh/ec2/snapshot.rb +112 -0
- data/lib/vgh/ec2/volume.rb +77 -0
- data/lib/vgh/ec2.rb +15 -0
- data/lib/vgh/output.rb +0 -2
- data/lib/vgh/system/lvm.rb +38 -24
- data/lib/vgh/system/mysql.rb +16 -6
- data/lib/vgh/system.rb +50 -10
- data/lib/vgh/version.rb +1 -1
- data/lib/vgh.rb +3 -1
- data/spec/cli_spec.rb +14 -22
- data/spec/configuration_spec.rb +44 -0
- data/spec/ec2/metadata_spec.rb +14 -0
- data/spec/ec2/snapshot_spec.rb +39 -0
- data/spec/ec2/volume_spec.rb +47 -0
- data/spec/helpers/aws_mock.rb +49 -0
- data/spec/helpers/spec.rb +4 -22
- data/spec/logging_spec.rb +29 -4
- data/spec/output_spec.rb +30 -4
- data/spec/version_spec.rb +11 -0
- data/vgh.gemspec +1 -0
- metadata +41 -14
- data/conf/ec2-backup.config.yml.example +0 -12
- data/lib/vgh/extended_aws/extended_ec2/snapshot.rb +0 -87
- data/lib/vgh/extended_aws/extended_ec2/volume.rb +0 -66
- data/lib/vgh/extended_aws/extended_ec2.rb +0 -10
- data/lib/vgh/extended_aws.rb +0 -10
- data/spec/extended_aws/extended_ec2/metadata_spec.rb +0 -24
- data/spec/extended_aws/extended_ec2/snapshot_spec.rb +0 -48
- data/spec/extended_aws/extended_ec2/volume_spec.rb +0 -27
@@ -0,0 +1,112 @@
|
|
1
|
+
module VGH
|
2
|
+
|
3
|
+
# Creates the snapshots
|
4
|
+
def snap_and_tag(*args)
|
5
|
+
EC2::Snapshot.new(*args)
|
6
|
+
end
|
7
|
+
|
8
|
+
module EC2
|
9
|
+
|
10
|
+
# Creates a snapshot of the specified volume.
|
11
|
+
#
|
12
|
+
# == Usage
|
13
|
+
#
|
14
|
+
# Snapshot.new(volume_id, description, tags)
|
15
|
+
#
|
16
|
+
class Snapshot
|
17
|
+
|
18
|
+
# Create and tag snapshot, and also purge expired ones
|
19
|
+
# @param [String] volume_id The ID of the volume to snapshot
|
20
|
+
# @param [String] description The description for the new snapshot
|
21
|
+
# @param [Hash] tags A Hash containing the names and values of the tags
|
22
|
+
# @return [Snapshot] The Snapshot object.
|
23
|
+
def initialize(volume_id, description, tags)
|
24
|
+
@volume_id = volume_id
|
25
|
+
@description = description
|
26
|
+
@tags = tags
|
27
|
+
create_snapshot
|
28
|
+
tag_snapshot
|
29
|
+
purge_backups
|
30
|
+
return snapshot
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String] The Volume ID
|
34
|
+
attr_reader :volume_id
|
35
|
+
|
36
|
+
# @return [String] The description of the snapshot
|
37
|
+
attr_reader :description
|
38
|
+
|
39
|
+
# @return [Hash] The tags hash
|
40
|
+
attr_reader :tags
|
41
|
+
|
42
|
+
# @return [Object] The Snapshot object
|
43
|
+
attr_reader :snapshot
|
44
|
+
|
45
|
+
# Creates a snapshot for the specified volume
|
46
|
+
# @return [Object] The newly created snapshot object
|
47
|
+
def create_snapshot
|
48
|
+
@snapshot = ec2.volumes[volume_id].
|
49
|
+
create_snapshot("#{description}")
|
50
|
+
message.info "Created snapshot \"#{snapshot.id}\""
|
51
|
+
return @snapshot
|
52
|
+
end
|
53
|
+
|
54
|
+
# Tags a Snapshot
|
55
|
+
def tag_snapshot
|
56
|
+
snap = snapshot
|
57
|
+
message.info "Tagging snapshot \"#{snap.id}\""
|
58
|
+
tags.map {|key, value|
|
59
|
+
ec2.tags.create(snap, key, {:value => value})
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# Purges expired snapshots
|
64
|
+
def purge_backups
|
65
|
+
expired_backups.each do |snap|
|
66
|
+
message.info "Deleting expired snapshot (#{snap.id})"
|
67
|
+
snap.delete
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Creates a list of expired snapshots according to the expiration time
|
72
|
+
# specified in the app's configuration file
|
73
|
+
# @return [Array] An array of expired snapshot objects
|
74
|
+
def expired_backups
|
75
|
+
@expired_backups = []
|
76
|
+
all_backups.each {|snap|
|
77
|
+
if snap.start_time < (Time.now - backup_expiration*24*60*60)
|
78
|
+
@expired_backups.push snap
|
79
|
+
end
|
80
|
+
}
|
81
|
+
return @expired_backups
|
82
|
+
end
|
83
|
+
|
84
|
+
# Check for a an expiration period in the configuration file
|
85
|
+
def backup_expiration
|
86
|
+
expiration = config[:expiration]
|
87
|
+
if expiration.nil?
|
88
|
+
@backup_expiration = 7
|
89
|
+
else
|
90
|
+
@backup_expiration = expiration
|
91
|
+
end
|
92
|
+
return @backup_expiration.to_i
|
93
|
+
end
|
94
|
+
|
95
|
+
# Returns a list of snapshots that are named the same with the current FQDN.
|
96
|
+
def all_backups
|
97
|
+
@all ||= ec2.snapshots.
|
98
|
+
with_owner('self').
|
99
|
+
tagged('Name').tagged_values(fqdn)
|
100
|
+
end
|
101
|
+
|
102
|
+
end # class Snapshot
|
103
|
+
|
104
|
+
end # module EC2
|
105
|
+
end # module VGH
|
106
|
+
|
107
|
+
require 'vgh/system'
|
108
|
+
require 'vgh/output'
|
109
|
+
require 'vgh/configuration'
|
110
|
+
require 'vgh/ec2'
|
111
|
+
require 'vgh/ec2/metadata'
|
112
|
+
require 'vgh/ec2/volume'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module VGH
|
2
|
+
module EC2
|
3
|
+
|
4
|
+
# Collects information about the EBS volumes attached to the current instance.
|
5
|
+
# == Usage
|
6
|
+
# volumes = Volume.new
|
7
|
+
# puts volumes.list
|
8
|
+
# puts volumes.list_tagged('MyTag')
|
9
|
+
#
|
10
|
+
class Volume
|
11
|
+
|
12
|
+
# Creates an array with the IDs of all the volumes attached to the current
|
13
|
+
# instance
|
14
|
+
# @return [Array]
|
15
|
+
def list
|
16
|
+
@list = []
|
17
|
+
mappings.map {|device, info| @list.push(info.volume.id)}
|
18
|
+
return @list
|
19
|
+
end
|
20
|
+
|
21
|
+
# Creates an array with the IDs of all the volumes attached to the current
|
22
|
+
# instance, that contain a specific tag key
|
23
|
+
# @param [String] tag_key The Tag to look for
|
24
|
+
# @return [Array]
|
25
|
+
def list_tagged(tag_key)
|
26
|
+
@list_tagged = []
|
27
|
+
list.each {|vid|
|
28
|
+
volume_tags(vid).map {|volume_tag|
|
29
|
+
@list_tagged.push(vid) if volume_tag.key == tag_key
|
30
|
+
}
|
31
|
+
}
|
32
|
+
return @list_tagged
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a Hash containing the block device mappings of the current instance.
|
36
|
+
# @return [Hash]
|
37
|
+
def mappings
|
38
|
+
message.info "Creating a list of volumes..."
|
39
|
+
@mappings ||= instance.block_device_mappings
|
40
|
+
end
|
41
|
+
|
42
|
+
# The current instance object
|
43
|
+
# @return [Instance] An instance object
|
44
|
+
def instance
|
45
|
+
@instance ||= ec2.instances[instance_id]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get volume's Name tag
|
49
|
+
# @param [String] volume_id The ID of the volume
|
50
|
+
# @return [String] The tag of the volume or (NOTAG) if a tag does not exists.
|
51
|
+
def name_tag(volume_id)
|
52
|
+
@name_tag = 'NOTAG'
|
53
|
+
volume_tags(volume_id).each {|tag|
|
54
|
+
@name_tag = tag.value if tag.key == 'Name'
|
55
|
+
}
|
56
|
+
return @name_tag
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a collection of tags for the specified volume.
|
60
|
+
# @param [String] volume_id The id of the volume to query for tags.
|
61
|
+
# @return [TagsCollection] An array of tag objects
|
62
|
+
def volume_tags(volume_id)
|
63
|
+
@volume_tags = ec2.tags.
|
64
|
+
filter('resource-type', 'volume').
|
65
|
+
filter('resource-id', volume_id)
|
66
|
+
end
|
67
|
+
|
68
|
+
end # class Volume
|
69
|
+
|
70
|
+
end # module EC2
|
71
|
+
end # module VGH
|
72
|
+
|
73
|
+
|
74
|
+
require 'vgh/output'
|
75
|
+
require 'vgh/configuration'
|
76
|
+
require 'vgh/ec2'
|
77
|
+
require 'vgh/ec2/metadata'
|
data/lib/vgh/ec2.rb
ADDED
data/lib/vgh/output.rb
CHANGED
@@ -99,8 +99,6 @@ END_HEADER
|
|
99
99
|
def footer
|
100
100
|
stdout <<END_FOOTER
|
101
101
|
|
102
|
-
###############################################################################
|
103
|
-
RUBY ROCKS!!!
|
104
102
|
###############################################################################"
|
105
103
|
END_FOOTER
|
106
104
|
end
|
data/lib/vgh/system/lvm.rb
CHANGED
@@ -12,70 +12,84 @@ module System
|
|
12
12
|
#
|
13
13
|
# == Usage:
|
14
14
|
#
|
15
|
-
# lvm = System::
|
16
|
-
# lvm.
|
15
|
+
# lvm = System::LVM.new
|
16
|
+
# lvm.suspend
|
17
17
|
# # run the code that takes the snapshot
|
18
|
-
# lvm.
|
18
|
+
# lvm.resume
|
19
19
|
#
|
20
|
-
class
|
20
|
+
class LVM
|
21
21
|
|
22
22
|
# Loads variables and checks if LVM Tools are installed
|
23
23
|
def initialize
|
24
|
-
@dmcmd = '/sbin/dmsetup'
|
25
24
|
installed?
|
26
25
|
end
|
27
26
|
|
27
|
+
# @return [String] The dmsetup system command
|
28
|
+
def dm_cmd
|
29
|
+
@dmcmd ||= '/sbin/dmsetup'
|
30
|
+
end
|
31
|
+
|
28
32
|
# Warn message if LVM tools are not installed
|
29
33
|
def installed?
|
30
|
-
|
34
|
+
if File.exists?(dm_cmd)
|
35
|
+
return true
|
36
|
+
else
|
37
|
+
message.warn "LVM Tools are not installed"
|
38
|
+
return false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [String] A list of logical volumes present
|
43
|
+
def lvs
|
44
|
+
if ( installed? and System.is_root? )
|
45
|
+
@lvs ||= `#{dm_cmd} ls | /bin/grep -E -v 'swap|root'`
|
46
|
+
else
|
47
|
+
message.warn "Listing logical volume needs root privileges!"
|
48
|
+
return nil
|
49
|
+
end
|
31
50
|
end
|
32
51
|
|
33
52
|
# Test if logical volumes are present
|
34
53
|
# @return [Boolean]
|
35
54
|
def lvs_are_present?
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
55
|
+
if lvs != "No devices found\n" then
|
56
|
+
return true
|
57
|
+
else
|
58
|
+
message.info "No logical volumes found."
|
59
|
+
return false
|
40
60
|
end
|
41
|
-
return lvs_are_present
|
42
61
|
end
|
43
62
|
|
44
63
|
# Suspend all logical volume
|
45
64
|
def suspend
|
46
|
-
if lvs_are_present?
|
47
|
-
suspend_lvs
|
48
|
-
else
|
49
|
-
message.info "No logical volumes found."
|
50
|
-
end
|
65
|
+
suspend_lvs if lvs_are_present?
|
51
66
|
end
|
52
67
|
|
53
68
|
# The actual suspend action
|
54
69
|
def suspend_lvs
|
55
|
-
for lv_name in
|
70
|
+
for lv_name in lvs.split[0]
|
56
71
|
message.info "Suspending Logical Volume '#{lv_name}'..."
|
57
|
-
`#{
|
72
|
+
`#{dm_cmd} suspend #{lv_name}`
|
58
73
|
end
|
59
74
|
end
|
60
75
|
|
61
76
|
# Resume all logical volumes
|
62
77
|
def resume
|
63
|
-
if lvs_are_present?
|
64
|
-
resume_lvs
|
65
|
-
end
|
78
|
+
resume_lvs if lvs_are_present?
|
66
79
|
end
|
67
80
|
|
68
81
|
# The actual resume action
|
69
82
|
def resume_lvs
|
70
|
-
|
83
|
+
for lv_name in lvs.split[0]
|
71
84
|
message.info "Resuming Logical Volume '#{lv_name}'..."
|
72
|
-
`#{
|
85
|
+
`#{dm_cmd} resume #{lv_name}`
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
76
|
-
end # class
|
89
|
+
end # class LVM
|
77
90
|
end # module System
|
78
91
|
end # module VGH
|
79
92
|
|
80
93
|
require 'vgh/output'
|
94
|
+
require 'vgh/system'
|
81
95
|
|
data/lib/vgh/system/mysql.rb
CHANGED
@@ -16,20 +16,30 @@ class MySQL
|
|
16
16
|
|
17
17
|
# Load defaults
|
18
18
|
def initialize
|
19
|
-
cfg = app_config
|
20
19
|
@mysqladmin = '/usr/bin/mysqladmin'
|
21
20
|
@mysql = '/usr/bin/mysql'
|
22
|
-
@user = cfg[:mysql_user]
|
23
|
-
@password = cfg[:mysql_pwd]
|
24
21
|
end
|
25
22
|
|
23
|
+
# Get MySQL user
|
24
|
+
# @return [String]
|
25
|
+
def mysql_user
|
26
|
+
@mysql_user ||= config[:mysql_user]
|
27
|
+
end
|
28
|
+
|
29
|
+
# Get MySQL password
|
30
|
+
# @return [String]
|
31
|
+
def mysql_password
|
32
|
+
@mysql_password ||= config[:mysql_password]
|
33
|
+
end
|
34
|
+
|
35
|
+
|
26
36
|
# Check if server is running and we have the right credentials
|
27
37
|
# @return [Boolean]
|
28
38
|
def mysql_exists?
|
29
39
|
mysql_exists = false
|
30
40
|
if File.exists?(@mysqladmin)
|
31
41
|
mysql_exists = system "#{@mysqladmin} -s ping"
|
32
|
-
if !
|
42
|
+
if ! mysql_user and ! mysql_password
|
33
43
|
message.warning 'WARNING: MySQL exists but no credentials were found!'
|
34
44
|
mysql_exists = false
|
35
45
|
end
|
@@ -41,7 +51,7 @@ class MySQL
|
|
41
51
|
def flush
|
42
52
|
if mysql_exists?
|
43
53
|
message.info 'Locking MySQL tables...'
|
44
|
-
`#{@mysql} -u#{
|
54
|
+
`#{@mysql} -u#{mysql_user} -p#{mysql_password} -e "FLUSH TABLES WITH READ LOCK"`
|
45
55
|
end
|
46
56
|
end
|
47
57
|
|
@@ -49,7 +59,7 @@ class MySQL
|
|
49
59
|
def unlock
|
50
60
|
if mysql_exists?
|
51
61
|
message.info 'Unlocking MySQL tables...'
|
52
|
-
`#{@mysql} -u#{
|
62
|
+
`#{@mysql} -u#{mysql_user} -p#{mysql_password} -e "UNLOCK TABLES"`
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
data/lib/vgh/system.rb
CHANGED
@@ -4,7 +4,7 @@ module VGH
|
|
4
4
|
# the system's one)
|
5
5
|
# @return [String]
|
6
6
|
def fqdn
|
7
|
-
remote_fqdn =
|
7
|
+
remote_fqdn = config[:fqdn]
|
8
8
|
if remote_fqdn
|
9
9
|
$fqdn ||= remote_fqdn
|
10
10
|
else
|
@@ -12,15 +12,6 @@ module VGH
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
# Check if the script is run as root
|
16
|
-
# @return [Boolean]
|
17
|
-
def is_root?
|
18
|
-
if Process.uid == 0
|
19
|
-
return true
|
20
|
-
else
|
21
|
-
return false
|
22
|
-
end
|
23
|
-
end
|
24
15
|
|
25
16
|
# This is a parent class for different system actions performed by the scripts
|
26
17
|
# included in this gem. For more information see the classes defined under
|
@@ -32,12 +23,61 @@ module VGH
|
|
32
23
|
#
|
33
24
|
module System
|
34
25
|
|
26
|
+
# Check if the script is run as root
|
27
|
+
# @return [Boolean]
|
28
|
+
def self.is_root?
|
29
|
+
if Process.uid == 0
|
30
|
+
return true
|
31
|
+
else
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
35
36
|
# Returns the current system's FQDN
|
36
37
|
# @return [String]
|
37
38
|
def self.fqdn
|
38
39
|
$fqdn ||= `hostname -f`
|
39
40
|
end
|
40
41
|
|
42
|
+
# Returns the current system's FQDN
|
43
|
+
# @return [String]
|
44
|
+
def self.lock
|
45
|
+
unless remotely?
|
46
|
+
mysql.flush
|
47
|
+
lvm.suspend
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns the current system's FQDN
|
52
|
+
# @return [String]
|
53
|
+
def self.unlock
|
54
|
+
unless remotely?
|
55
|
+
mysql.unlock
|
56
|
+
lvm.resume
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Checks if this script is run remotely.
|
61
|
+
# @return [Boolean]
|
62
|
+
def self.remotely?
|
63
|
+
cfg = config
|
64
|
+
if cfg[:instance] or cfg[:fqdn]
|
65
|
+
return true
|
66
|
+
else
|
67
|
+
return false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Initializes the MySQL class
|
72
|
+
def self.mysql
|
73
|
+
mysql ||= System::MySQL.new
|
74
|
+
end
|
75
|
+
|
76
|
+
# Initializes the LVM class
|
77
|
+
def self.lvm
|
78
|
+
lvm ||= System::LVM.new
|
79
|
+
end
|
80
|
+
|
41
81
|
end # module System
|
42
82
|
|
43
83
|
end # module VGH
|
data/lib/vgh/version.rb
CHANGED
data/lib/vgh.rb
CHANGED
@@ -28,6 +28,8 @@ module VGH
|
|
28
28
|
case app
|
29
29
|
when 'ec2-backup'
|
30
30
|
APPS::EC2_Backup.new.run
|
31
|
+
when 'checkpoint'
|
32
|
+
APPS::Checkpoint.new.run
|
31
33
|
end
|
32
34
|
|
33
35
|
# Display footer
|
@@ -48,6 +50,6 @@ module VGH
|
|
48
50
|
end # module VGH
|
49
51
|
|
50
52
|
require "vgh/output"
|
51
|
-
require "vgh/system"
|
52
53
|
require "vgh/apps"
|
53
54
|
require "vgh/apps/ec2_backup"
|
55
|
+
require "vgh/apps/checkpoint"
|
data/spec/cli_spec.rb
CHANGED
@@ -11,34 +11,26 @@ describe VGH::CLI do
|
|
11
11
|
ARGV[0] = app
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
context "When '-v' passed to the command line" do
|
19
|
-
it "Verbosity should be enabled" do
|
20
|
-
ARGV.push('-v')
|
21
|
-
VGH::CLI.new.options[:verbose].should be_true
|
22
|
-
end
|
14
|
+
it 'Should get the app name as the first argument' do
|
15
|
+
subject.options[:app].should eq app
|
23
16
|
end
|
24
17
|
|
25
|
-
|
26
|
-
|
27
|
-
VGH::CLI.new.options[:verbose].should be_false
|
28
|
-
end
|
18
|
+
it 'Verbosity' do
|
19
|
+
subject.options[:verbose].should be_false
|
29
20
|
end
|
30
21
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
VGH::CLI.new.options[:logging].should be_true
|
35
|
-
end
|
22
|
+
it 'No Verbosity' do
|
23
|
+
ARGV.push('--verbose')
|
24
|
+
subject.options[:verbose].should be_true
|
36
25
|
end
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
27
|
+
it 'Logging' do
|
28
|
+
ARGV.push('--logging')
|
29
|
+
subject.options[:logging].should be_true
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'No Logging' do
|
33
|
+
subject.options[:logging].should be_false
|
42
34
|
end
|
43
35
|
|
44
36
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'helpers/spec'
|
2
|
+
require 'vgh'
|
3
|
+
require 'vgh/configuration'
|
4
|
+
|
5
|
+
describe VGH::Configuration do
|
6
|
+
|
7
|
+
let(:configuration) {VGH::Configuration.allocate}
|
8
|
+
let(:cli_confdir) {'/tmp'}
|
9
|
+
let(:config_hash) {"---
|
10
|
+
:key1: 'value1'
|
11
|
+
:key2: 'value2'"}
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
configuration.stub(:cli).and_return({:confdir => nil})
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'Should return the default config directory' do
|
18
|
+
configuration.global_config_dir.should eq('/etc/vgh')
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'Should return the user config directory' do
|
22
|
+
configuration.user_config_dir =~ /.*\.vgh$/
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'Should return a config directory from cli or return users directory' do
|
26
|
+
configuration.confdir.should =~ /.*\.vgh/
|
27
|
+
configuration.stub(:cli).and_return({:confdir => cli_confdir})
|
28
|
+
configuration.confdir.should eq(cli_confdir)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'Should return the main configuration file' do
|
32
|
+
configuration.config_file.should =~ /.*\.vgh\/config\.yml/
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'Should initialize clean' do
|
36
|
+
cfg = VGH::Configuration
|
37
|
+
[:message, :cli, :log, :aws_config].each {|s|
|
38
|
+
cfg.any_instance.stub(s).and_return(Dummy.new)
|
39
|
+
}
|
40
|
+
cfg.any_instance.stub(:validate).and_return(config_hash)
|
41
|
+
subject.config.should eq(config_hash)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'helpers/spec'
|
2
|
+
require 'vgh/ec2/metadata'
|
3
|
+
|
4
|
+
describe VGH::EC2::MetaData do
|
5
|
+
|
6
|
+
let(:response) {'Remote server response'}
|
7
|
+
it 'Should receive valid response from the AWS metadata server' do
|
8
|
+
subject.stub_chain(:open, :read).and_return(response)
|
9
|
+
subject.instance_id.should eq(response)
|
10
|
+
subject.root_device.should eq(response)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'helpers/spec'
|
2
|
+
require 'aws-sdk'
|
3
|
+
require 'vgh/ec2/snapshot'
|
4
|
+
require 'vgh/system'
|
5
|
+
|
6
|
+
describe VGH::EC2::Snapshot do
|
7
|
+
|
8
|
+
include_context 'AWS Dummy'
|
9
|
+
let(:snap) {VGH::EC2::Snapshot.allocate}
|
10
|
+
|
11
|
+
before(:each) do
|
12
|
+
snap.stub(:snapshot).and_return(@snapshot)
|
13
|
+
snap.stub(:message).and_return(Dummy.new)
|
14
|
+
snap.stub(:tags).and_return(@tag_hash)
|
15
|
+
snap.stub(:ec2).and_return(@ec2)
|
16
|
+
snap.stub(:fqdn).and_return(@fqdn)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "Should tag a snapshot" do
|
20
|
+
snap.tag_snapshot.each{|t|
|
21
|
+
t.should be_a AWS::EC2::Tag
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
it "Should list all snapshots" do
|
26
|
+
snap.all_backups.should be_an AWS::EC2::SnapshotCollection
|
27
|
+
end
|
28
|
+
|
29
|
+
it "Should create a list of expired backups" do
|
30
|
+
snap.expired_backups.should be_an Array
|
31
|
+
end
|
32
|
+
|
33
|
+
it "Should return a backup expiration integer" do
|
34
|
+
snap.stub(:config).and_return({:expiration => 5})
|
35
|
+
snap.backup_expiration.should eq(5)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'helpers/spec'
|
2
|
+
|
3
|
+
require 'aws-sdk'
|
4
|
+
require 'vgh/ec2/volume'
|
5
|
+
|
6
|
+
describe VGH::EC2::Volume do
|
7
|
+
|
8
|
+
include_context 'AWS Dummy'
|
9
|
+
|
10
|
+
let(:volume) {VGH::EC2::Volume.new}
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
volume.stub(:message).and_return(Dummy.new)
|
14
|
+
volume.stub(:ec2).and_return(@ec2)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "Should return an instance" do
|
18
|
+
volume.stub(:instance_id).and_return(@instance.id)
|
19
|
+
volume.instance.should be_a(AWS::EC2::Instance)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "Should create a hash with block device mappings" do
|
23
|
+
volume.stub_chain(:instance, :block_device_mappings).
|
24
|
+
and_return(@instance_mappings)
|
25
|
+
volume.mappings.should be_a_kind_of Hash
|
26
|
+
end
|
27
|
+
|
28
|
+
it "Should return a collection of volume tags" do
|
29
|
+
volume.volume_tags(@volume2.id).should be_a(@tag_collection)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "Should return the value of the name tag or (NOTAG)" do
|
33
|
+
volume.name_tag(@volume1.id).should be_a String
|
34
|
+
end
|
35
|
+
|
36
|
+
it "Should create a list of volumes" do
|
37
|
+
volume.stub(:mappings).and_return(@instance_mappings)
|
38
|
+
volume.list.should be_a Array
|
39
|
+
end
|
40
|
+
|
41
|
+
it "Should return a list of volumes that need a checkpoint" do
|
42
|
+
volume.stub(:list).and_return([])
|
43
|
+
volume.list_tagged('CHECKPOINT').should be_a Array
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|