vgh 0.1.2 → 0.2.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/.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
|
+
|