vgh 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 +28 -0
- data/.rspec +2 -0
- data/.travis.yml +7 -0
- data/.yardopts +2 -0
- data/Gemfile +2 -0
- data/LICENSE +22 -0
- data/README.rdoc +121 -0
- data/Rakefile +25 -0
- data/bin/vgh +7 -0
- data/lib/vgh/apps/ec2_backup.rb +63 -0
- data/lib/vgh/apps.rb +22 -0
- data/lib/vgh/cli.rb +185 -0
- data/lib/vgh/configuration.rb +176 -0
- data/lib/vgh/extended_aws/extended_ec2/metadata.rb +46 -0
- data/lib/vgh/extended_aws/extended_ec2/snapshot.rb +90 -0
- data/lib/vgh/extended_aws/extended_ec2/volume.rb +66 -0
- data/lib/vgh/extended_aws/extended_ec2.rb +10 -0
- data/lib/vgh/extended_aws.rb +10 -0
- data/lib/vgh/logging.rb +66 -0
- data/lib/vgh/output.rb +113 -0
- data/lib/vgh/system/lvm.rb +81 -0
- data/lib/vgh/system/mysql.rb +56 -0
- data/lib/vgh/system.rb +21 -0
- data/lib/vgh/version.rb +9 -0
- data/lib/vgh.rb +60 -0
- data/spec/cli_spec.rb +25 -0
- data/spec/misc_spec.rb +25 -0
- data/spec/spec_helper.rb +7 -0
- data/tasks/documentation.rake +56 -0
- data/vgh.gemspec +27 -0
- metadata +185 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
module VGH
|
6
|
+
module Extended_AWS
|
7
|
+
module Extended_EC2
|
8
|
+
|
9
|
+
# This class gathers metadata information about the current instance, used by
|
10
|
+
# the applications in this gem.
|
11
|
+
#
|
12
|
+
# == Usage
|
13
|
+
#
|
14
|
+
# data = Metadata.new
|
15
|
+
# id = data.instance_id
|
16
|
+
# root = data.root_device
|
17
|
+
#
|
18
|
+
class MetaData
|
19
|
+
|
20
|
+
# Query the API server for the instance ID
|
21
|
+
# @return [String, nil] The current instance's ID
|
22
|
+
def instance_id
|
23
|
+
begin
|
24
|
+
@instance_id = open('http://instance-data/latest/meta-data/instance-id').read
|
25
|
+
rescue
|
26
|
+
message.fatal 'Could not get Instance ID!'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Query the API server for the root device
|
31
|
+
# @return [String, nil] The root device of the current instance
|
32
|
+
def root_device
|
33
|
+
begin
|
34
|
+
@root_device = open('http://instance-data/latest/meta-data/block-device-mapping/root').read
|
35
|
+
rescue
|
36
|
+
message.fatal 'Could not get the root device!'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end # module Extended_EC2
|
43
|
+
end # module Extended_AWS
|
44
|
+
end # module VGH
|
45
|
+
|
46
|
+
require 'vgh/output'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module VGH
|
2
|
+
module Extended_AWS
|
3
|
+
module Extended_EC2
|
4
|
+
|
5
|
+
# Creates a snapshot of the specified volume.
|
6
|
+
#
|
7
|
+
# == Usage
|
8
|
+
#
|
9
|
+
# snap = Snapshot.new.
|
10
|
+
# snap.create(id, tag)
|
11
|
+
#
|
12
|
+
class Snapshot
|
13
|
+
|
14
|
+
# Load all needed classes
|
15
|
+
def initialize
|
16
|
+
@instance_id = MetaData.new.instance_id
|
17
|
+
@fqdn = System.fqdn
|
18
|
+
end
|
19
|
+
|
20
|
+
# The workflow to create a snapshot:
|
21
|
+
# - create snapshot
|
22
|
+
# - add a name tag
|
23
|
+
# - add an info tag
|
24
|
+
# @param [String] volume_id The ID of the volume to snapshot
|
25
|
+
# @param [String] volume_tag The Tag of the volume to snapshot
|
26
|
+
def create(volume_id, volume_tag)
|
27
|
+
snapshot(volume_id, volume_tag)
|
28
|
+
name_tag
|
29
|
+
info_tag(volume_id)
|
30
|
+
message.info "Creating and tagging snapshot \"#{@snapshot.id}\""
|
31
|
+
end
|
32
|
+
|
33
|
+
# Creates a snapshot for the specified volume
|
34
|
+
# @param [String] volume_id The ID of the volume to snapshot
|
35
|
+
# @param [String] volume_tag The tag of the volume to snapshot
|
36
|
+
# @return [String, nil] The newly created snapshot object
|
37
|
+
def snapshot(volume_id, volume_tag)
|
38
|
+
@snapshot = ec2.volumes[volume_id].
|
39
|
+
create_snapshot("Backup for #{volume_id}(#{volume_tag})")
|
40
|
+
end
|
41
|
+
|
42
|
+
# Creates a name tag for the newly created snapshot.
|
43
|
+
# The name is the FQDN of the current instance.
|
44
|
+
def name_tag
|
45
|
+
ec2.snapshots[@snapshot.id].tag('Name', :value => @fqdn)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Creates an info tag for the newly created snapshot
|
49
|
+
def info_tag(volume_id)
|
50
|
+
ec2.snapshots[@snapshot.id].tag("Backup_#{@instance_id}", :value => volume_id)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Purges expired snapshots
|
54
|
+
def purge
|
55
|
+
expired.each do |snapshot|
|
56
|
+
message.info "Deleting expired snapshot (#{snapshot.id})"
|
57
|
+
snapshot.delete
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Creates a list of expired snapshots according to the expiration time
|
62
|
+
# specified in the app's configuration file
|
63
|
+
# @return [Array] An array of expired snapshot objects
|
64
|
+
def expired
|
65
|
+
@expired = []
|
66
|
+
all.each {|snapshot|
|
67
|
+
if snapshot.start_time < (Time.now - $cfg[:expiration]*24*60*60)
|
68
|
+
@expired.push snapshot
|
69
|
+
end
|
70
|
+
}
|
71
|
+
return @expired
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a list of snapshots that are named the same with the current FQDN.
|
75
|
+
def all
|
76
|
+
@all ||= ec2.snapshots.
|
77
|
+
with_owner('self').
|
78
|
+
tagged('Name').tagged_values(@fqdn)
|
79
|
+
end
|
80
|
+
|
81
|
+
end # class Snapshot
|
82
|
+
|
83
|
+
end # module Extended_EC2
|
84
|
+
end # module Extended_AWS
|
85
|
+
end # module VGH
|
86
|
+
|
87
|
+
require 'vgh/system'
|
88
|
+
require 'vgh/output'
|
89
|
+
require 'vgh/configuration'
|
90
|
+
require 'vgh/extended_aws/extended_ec2/metadata'
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module VGH
|
2
|
+
module Extended_AWS
|
3
|
+
module Extended_EC2
|
4
|
+
|
5
|
+
# Collects information about the EBS volumes attached to the current instance.
|
6
|
+
# == Usage
|
7
|
+
# @volume = Volume.new
|
8
|
+
# @volume.list.map {|id, info|
|
9
|
+
# puts id
|
10
|
+
# puts info[:tag]
|
11
|
+
# puts info[:device)
|
12
|
+
# }
|
13
|
+
#
|
14
|
+
class Volume
|
15
|
+
|
16
|
+
# Collects all needed variables
|
17
|
+
def initialize
|
18
|
+
@instance_id = MetaData.new.instance_id
|
19
|
+
end
|
20
|
+
|
21
|
+
# Creates a Hash collection of volumes containing their id, tag and device
|
22
|
+
# @return [Hash]
|
23
|
+
def list
|
24
|
+
@list = {}
|
25
|
+
mappings.map {|device, info|
|
26
|
+
volume_id = info.volume.id
|
27
|
+
@list[volume_id] = {
|
28
|
+
:device => device,
|
29
|
+
:tag => tag(volume_id)
|
30
|
+
}
|
31
|
+
}
|
32
|
+
return @list
|
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 ||= ec2.instances[@instance_id].block_device_mappings
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get volume's Name tag
|
43
|
+
# @return [String] The tag of the volume or (NOTAG) if a tag does not exists.
|
44
|
+
def tag(volume_id)
|
45
|
+
v_tags = tags(volume_id)
|
46
|
+
v_tags.count == 0 ? @tag = '(NOTAG)' : @tag = v_tags.first.value
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns a collection of tags for the specified volume.
|
50
|
+
# @param [String] volume_id The id of the volume to query for tags.
|
51
|
+
def tags(volume_id)
|
52
|
+
@tags = ec2.tags.
|
53
|
+
filter('resource-type', 'volume').
|
54
|
+
filter('key', 'Name').
|
55
|
+
filter('resource-id', volume_id)
|
56
|
+
end
|
57
|
+
|
58
|
+
end # class Volume
|
59
|
+
|
60
|
+
end # module Extended_EC2
|
61
|
+
end # module Extended_AWS
|
62
|
+
end # module VGH
|
63
|
+
|
64
|
+
require 'vgh/output'
|
65
|
+
require 'vgh/configuration'
|
66
|
+
require 'vgh/extended_aws/extended_ec2/metadata'
|
data/lib/vgh/logging.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module VGH
|
4
|
+
|
5
|
+
# Returns log state
|
6
|
+
def log
|
7
|
+
if logging?
|
8
|
+
$log ||= Logging.new.log
|
9
|
+
else
|
10
|
+
$log ||= Logger.new('/dev/null')
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# == Description:
|
15
|
+
#
|
16
|
+
# This class logs messages if logging is enabled from the command line
|
17
|
+
# options. The default location of the log files is +/var/log/vgh.log+.
|
18
|
+
#
|
19
|
+
# This class uses the Ruby Logger standard library.
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# == Usage:
|
23
|
+
#
|
24
|
+
# log = Logging.new.log
|
25
|
+
# log.info "This is an info message"
|
26
|
+
#
|
27
|
+
class Logging
|
28
|
+
|
29
|
+
# Defaults
|
30
|
+
def defaults
|
31
|
+
@path = '/var/log/vgh.log'
|
32
|
+
@level = Logger::INFO
|
33
|
+
end
|
34
|
+
|
35
|
+
# Check log file existence
|
36
|
+
def initialize
|
37
|
+
defaults
|
38
|
+
validate_log_directory
|
39
|
+
end
|
40
|
+
|
41
|
+
# Creates a log directory and file if it does not already exist
|
42
|
+
def validate_log_directory
|
43
|
+
dir = File.dirname(@path)
|
44
|
+
Dir.mkdir(dir) unless File.exists?(dir)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Opens the log file
|
48
|
+
def log_file
|
49
|
+
File.open(@path, File::WRONLY | File::APPEND | File::CREAT)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Global, memoized, lazy initialized instance of a logger
|
53
|
+
def log
|
54
|
+
# Logger
|
55
|
+
@log ||= Logger.new(log_file)
|
56
|
+
@log.level = @level
|
57
|
+
@log.datetime_format = "%Y-%m-%d %H:%M " # simplify time output
|
58
|
+
@log
|
59
|
+
end
|
60
|
+
|
61
|
+
end # class Logging
|
62
|
+
|
63
|
+
end # module VGH
|
64
|
+
|
65
|
+
require 'vgh/cli'
|
66
|
+
|
data/lib/vgh/output.rb
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
module VGH
|
2
|
+
|
3
|
+
# Creates a global message method
|
4
|
+
def message
|
5
|
+
$message ||= Output.new
|
6
|
+
end
|
7
|
+
|
8
|
+
# == Description:
|
9
|
+
#
|
10
|
+
# This class sends messages to +STDOUT+ or to a log file. It takes the following
|
11
|
+
# standard methods:
|
12
|
+
# - +debug+
|
13
|
+
# - +info+
|
14
|
+
# - +warn+
|
15
|
+
# - +error+
|
16
|
+
# - +fatal+
|
17
|
+
#
|
18
|
+
# If +stdout+ is called then the message is only sent to +STDOUT+.
|
19
|
+
#
|
20
|
+
# If +header+ or +footer+ is called then it displays them.
|
21
|
+
#
|
22
|
+
#
|
23
|
+
# == Usage:
|
24
|
+
# # Load output
|
25
|
+
# message = Output.new
|
26
|
+
#
|
27
|
+
# message.header
|
28
|
+
#
|
29
|
+
# message.info "Starting code"
|
30
|
+
# # Your code here
|
31
|
+
# message.info "End code"
|
32
|
+
#
|
33
|
+
# message.footer
|
34
|
+
#
|
35
|
+
class Output
|
36
|
+
|
37
|
+
# Debug message
|
38
|
+
attr_reader :debug
|
39
|
+
# Inforational message
|
40
|
+
attr_reader :info
|
41
|
+
# Warning message
|
42
|
+
attr_reader :warn
|
43
|
+
# Error message
|
44
|
+
attr_reader :error
|
45
|
+
# Fatal Error message
|
46
|
+
attr_reader :fatal
|
47
|
+
# Header
|
48
|
+
attr_reader :header
|
49
|
+
# Footer
|
50
|
+
attr_reader :footer
|
51
|
+
|
52
|
+
# Writes a debug log message and outputs to screen
|
53
|
+
def debug(message)
|
54
|
+
log.debug(message)
|
55
|
+
stdout message
|
56
|
+
end
|
57
|
+
|
58
|
+
# Writes an info log message and outputs to screen
|
59
|
+
def info(message)
|
60
|
+
log.info(message)
|
61
|
+
stdout message
|
62
|
+
end
|
63
|
+
|
64
|
+
# Writes an warn log message and outputs to screen
|
65
|
+
def warn(message)
|
66
|
+
log.warn(message)
|
67
|
+
stdout message
|
68
|
+
end
|
69
|
+
|
70
|
+
# Writes an error log message and outputs to screen
|
71
|
+
def error(message)
|
72
|
+
log.error(message)
|
73
|
+
stdout message
|
74
|
+
end
|
75
|
+
|
76
|
+
# Writes a fatal log message and outputs to screen
|
77
|
+
def fatal(message)
|
78
|
+
log.fatal(message)
|
79
|
+
stdout message
|
80
|
+
end
|
81
|
+
|
82
|
+
# Outputs a message to screen
|
83
|
+
def stdout(message)
|
84
|
+
puts message if verbose?
|
85
|
+
end
|
86
|
+
|
87
|
+
# Returns the header
|
88
|
+
def header
|
89
|
+
stdout <<END_HEADER
|
90
|
+
###############################################################################
|
91
|
+
VladGh.com - Scripts (v#{VERSION})
|
92
|
+
#{Time.now.strftime("%m/%d/%Y %H:%M:%S(%Z)")}
|
93
|
+
###############################################################################
|
94
|
+
|
95
|
+
END_HEADER
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns the footer
|
99
|
+
def footer
|
100
|
+
stdout <<END_FOOTER
|
101
|
+
|
102
|
+
###############################################################################
|
103
|
+
RUBY ROCKS!!!
|
104
|
+
###############################################################################"
|
105
|
+
END_FOOTER
|
106
|
+
end
|
107
|
+
|
108
|
+
end # class Output
|
109
|
+
end # module VGH
|
110
|
+
|
111
|
+
require 'vgh/cli'
|
112
|
+
require 'vgh/configuration'
|
113
|
+
require 'vgh/logging'
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module VGH
|
2
|
+
module System
|
3
|
+
|
4
|
+
# This class is able to suspend or resume logical volumes. The +lvm2+ package
|
5
|
+
# needs to be installed for this to work.
|
6
|
+
#
|
7
|
+
# Suspending a volume becomes useful if you want for example a consistent
|
8
|
+
# EC2 snapshot of it. Any I/O that has already been mapped by the device but
|
9
|
+
# has not yet completed will be flushed. Any further I/O to that device will
|
10
|
+
# be postponed for as long as the device is suspended.
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# == Usage:
|
14
|
+
#
|
15
|
+
# lvm = System::LV.new
|
16
|
+
# lvm.suspend_lvs
|
17
|
+
# # run the code that takes the snapshot
|
18
|
+
# lvm.resume_lvs
|
19
|
+
#
|
20
|
+
class LV
|
21
|
+
|
22
|
+
# Loads variables and checks if LVM Tools are installed
|
23
|
+
def initialize
|
24
|
+
@dmcmd = '/sbin/dmsetup'
|
25
|
+
installed?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Warn message if LVM tools are not installed
|
29
|
+
def installed?
|
30
|
+
message.warn "LVM Tools are not installed" unless File.exists?(@dmcmd)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Test if logical volumes are present
|
34
|
+
# @return [Boolean]
|
35
|
+
def lvs_are_present?
|
36
|
+
lvs_are_present = false
|
37
|
+
@lvlist = `#{@dmcmd} ls | /bin/grep -E -v 'swap|root'`
|
38
|
+
if @lvlist != "No devices found\n" then
|
39
|
+
lvs_are_present = true
|
40
|
+
end
|
41
|
+
return lvs_are_present
|
42
|
+
end
|
43
|
+
|
44
|
+
# Suspend all logical volume
|
45
|
+
def suspend
|
46
|
+
if lvs_are_present?
|
47
|
+
suspend_lvs
|
48
|
+
else
|
49
|
+
message.info "No logical volumes found."
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# The actual suspend action
|
54
|
+
def suspend_lvs
|
55
|
+
for lv_name in @lvlist.split[0]
|
56
|
+
message.info "Suspending Logical Volume '#{lv_name}'..."
|
57
|
+
`#{@dmcmd} suspend #{lv_name}`
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Resume all logical volumes
|
62
|
+
def resume
|
63
|
+
if lvs_are_present?
|
64
|
+
resume_lvs
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# The actual resume action
|
69
|
+
def resume_lvs
|
70
|
+
for lv_name in @lvlist.split[0]
|
71
|
+
message.info "Resuming Logical Volume '#{lv_name}'..."
|
72
|
+
`#{@dmcmd} resume #{lv_name}`
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
end # class LV
|
77
|
+
end # module System
|
78
|
+
end # module VGH
|
79
|
+
|
80
|
+
require 'vgh/output'
|
81
|
+
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module VGH
|
2
|
+
module System
|
3
|
+
|
4
|
+
# This class checks if a local MySQL server is present and running.
|
5
|
+
# The credentials need to be specified in the app's configuration file.
|
6
|
+
#
|
7
|
+
#
|
8
|
+
# == Usage
|
9
|
+
#
|
10
|
+
# mysql = MySQL.new
|
11
|
+
# mysql.flush
|
12
|
+
# # run backup
|
13
|
+
# mysql.unlock
|
14
|
+
#
|
15
|
+
class MySQL
|
16
|
+
|
17
|
+
# Load defaults
|
18
|
+
def initialize
|
19
|
+
@mysqladmin = '/usr/bin/mysqladmin'
|
20
|
+
@mysql = '/usr/bin/mysql'
|
21
|
+
@user = $cfg[:mysql_user]
|
22
|
+
@password = $cfg[:mysql_pwd]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Check if server is running and we have access to the credentials file
|
26
|
+
# @return [Boolean]
|
27
|
+
def mysql_exists?
|
28
|
+
mysql_exists = false
|
29
|
+
if File.exists?(@mysqladmin)
|
30
|
+
mysql_exists = system "#{@mysqladmin} -s ping"
|
31
|
+
end
|
32
|
+
return mysql_exists
|
33
|
+
end
|
34
|
+
|
35
|
+
# Lock & Flush the MySQL tables
|
36
|
+
def flush
|
37
|
+
if mysql_exists?
|
38
|
+
message.info 'Locking MySQL tables...'
|
39
|
+
`#{@mysql} -u#{@user} -p#{@password} -e "FLUSH TABLES WITH READ LOCK"`
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Unlock the MySQL tables
|
44
|
+
def unlock
|
45
|
+
if mysql_exists?
|
46
|
+
message.info 'Unlocking MySQL tables...'
|
47
|
+
`#{@mysql} -u#{@user} -p#{@password} -e "UNLOCK TABLES"`
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end # class MySQL
|
52
|
+
end # module System
|
53
|
+
end # module VGH
|
54
|
+
|
55
|
+
require 'vgh/output'
|
56
|
+
require 'vgh/configuration'
|
data/lib/vgh/system.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module VGH
|
2
|
+
|
3
|
+
# This is a parent class for different system actions performed by the scripts
|
4
|
+
# included in this gem. For more information see the classes defined under
|
5
|
+
# this namespace.
|
6
|
+
#
|
7
|
+
# == Usage
|
8
|
+
#
|
9
|
+
# fqdn = System.fqdn
|
10
|
+
#
|
11
|
+
module System
|
12
|
+
|
13
|
+
# FQDN
|
14
|
+
# @return [String] The FQDN of the current machine.
|
15
|
+
def self.fqdn
|
16
|
+
$fqdn ||= `hostname -f`
|
17
|
+
end
|
18
|
+
|
19
|
+
end # module System
|
20
|
+
|
21
|
+
end # module VGH
|
data/lib/vgh/version.rb
ADDED
data/lib/vgh.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Try to load rubygems. Hey rubygems, I hate you.
|
2
|
+
begin
|
3
|
+
require 'rubygems'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'aws-sdk'
|
8
|
+
require 'sinatra'
|
9
|
+
|
10
|
+
require 'yaml'
|
11
|
+
require 'logger'
|
12
|
+
require 'erb'
|
13
|
+
require 'open-uri'
|
14
|
+
require 'net/http'
|
15
|
+
require 'uri'
|
16
|
+
require 'optparse'
|
17
|
+
|
18
|
+
# See the {file:README.rdoc README} file.
|
19
|
+
module VGH
|
20
|
+
|
21
|
+
# The main run method
|
22
|
+
def run
|
23
|
+
|
24
|
+
# Check if this script is run with root credentials
|
25
|
+
root_check
|
26
|
+
|
27
|
+
# Display header
|
28
|
+
show_header
|
29
|
+
|
30
|
+
# Run apps
|
31
|
+
case app
|
32
|
+
when 'ec2-backup'
|
33
|
+
APPS::EC2_Backup.new.run
|
34
|
+
end
|
35
|
+
|
36
|
+
# Display footer
|
37
|
+
show_footer
|
38
|
+
|
39
|
+
end # end run method
|
40
|
+
|
41
|
+
# Returns the header
|
42
|
+
def show_header
|
43
|
+
message.header
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns the footer
|
47
|
+
def show_footer
|
48
|
+
message.footer
|
49
|
+
end
|
50
|
+
|
51
|
+
# Raise error if this app is not run as root
|
52
|
+
def root_check
|
53
|
+
raise 'Must run as root' unless Process.uid == 0
|
54
|
+
end
|
55
|
+
|
56
|
+
end # module VGH
|
57
|
+
|
58
|
+
require "vgh/output"
|
59
|
+
require "vgh/apps"
|
60
|
+
require "vgh/apps/ec2_backup"
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'vgh'
|
3
|
+
require 'vgh/apps'
|
4
|
+
require 'vgh/cli'
|
5
|
+
|
6
|
+
describe "Command Line" do
|
7
|
+
VGH::APPS.list.map {|app_name|
|
8
|
+
it "Should accept '#{app_name}' as the first argument" do
|
9
|
+
ARGV[0] = app_name
|
10
|
+
VGH::CLI.new.options[:app].should eq app_name
|
11
|
+
end
|
12
|
+
}
|
13
|
+
|
14
|
+
it "Should enable verbosity" do
|
15
|
+
ARGV[0] = VGH::APPS.list.shuffle.first
|
16
|
+
ARGV.push('-v')
|
17
|
+
VGH::CLI.new.options[:verbose].should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "Should enable logging" do
|
21
|
+
ARGV[0] = VGH::APPS.list.shuffle.first
|
22
|
+
ARGV.push('-l')
|
23
|
+
VGH::CLI.new.options[:logging].should be_true
|
24
|
+
end
|
25
|
+
end
|
data/spec/misc_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'vgh'
|
3
|
+
require 'vgh/cli'
|
4
|
+
require 'vgh/apps'
|
5
|
+
require 'vgh/output'
|
6
|
+
require 'vgh/logging'
|
7
|
+
require 'vgh/configuration'
|
8
|
+
|
9
|
+
describe "Various Tests" do
|
10
|
+
it "Should have an array of supported apps" do
|
11
|
+
VGH::APPS.list.should be_an Array
|
12
|
+
end
|
13
|
+
|
14
|
+
it "Should write logs" do
|
15
|
+
log = VGH::Logging.new.log
|
16
|
+
log.should_receive(:info).with("RSpec Test")
|
17
|
+
log.info("RSpec Test")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "Should write messages" do
|
21
|
+
message = VGH::Output.new
|
22
|
+
message.should_receive(:stdout).with("RSpec Test")
|
23
|
+
message.stdout("RSpec Test")
|
24
|
+
end
|
25
|
+
end
|