vgh 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -1,7 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 1.9.2
5
4
  - 1.8.7
6
5
  - ree
7
6
  script: "rvmsudo bundle exec rake spec"
data/.yardopts CHANGED
@@ -1,2 +1,6 @@
1
- --no-private --protected --readme=README.rdoc - LICENSE
2
-
1
+ --no-private
2
+ --protected
3
+ --readme=README.rdoc
4
+ -
5
+ LICENSE
6
+ CHANGELOG.rdoc
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,22 @@
1
+ === 0.1.0
2
+ [Features]
3
+ - Add remote backup option
4
+ - Remove extra AWS configuration file
5
+ - Provide MySQL credentials in the configuration file
6
+ - Check if run as root at application level
7
+ - If log file can not be created, return STDOUT
8
+ - Add `gemdir` command line option to return gem files path
9
+ - Add configuration examples
10
+ - Add CHANGELOG
11
+ [Bugs]
12
+ - Clean up code
13
+ - More tests
14
+ - Improve documentation
15
+ - Fix Rakefile
16
+
17
+ === 0.0.2
18
+ [Bugs]
19
+ - Minor code fixes
20
+
21
+ === 0.0.1
22
+ Initial release
data/README.rdoc CHANGED
@@ -1,4 +1,6 @@
1
- = VGH Scripts {<img src="https://secure.travis-ci.org/vladgh/vgh.png" alt="Build Status" />}[http://travis-ci.org/vladgh/vgh]
1
+ = VGH Scripts
2
+ {<img src="https://secure.travis-ci.org/vladgh/vgh.png" alt="Build Status" />}[http://travis-ci.org/vladgh/vgh]
3
+ {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/vladgh/vgh]
2
4
 
3
5
  A collection of custom scripts used on VladGh.com
4
6
 
@@ -29,10 +31,7 @@ This gem looks for the following configuration files inside "+/etc/vgh+" or the
29
31
 
30
32
  [+config.yml+]
31
33
  The main configuration file for this gem.
32
- <em>At this moment nothing needs to be configured here.</em>
33
-
34
- [+aws.config.yml+]
35
- The AWS specific configuration.
34
+ This file should include the AWS specific configuration.
36
35
  Available values:
37
36
  - +:access_key_id+ - [String] Your AWS credentials
38
37
  - +:secret_access_key+ - [String] Your AWS credentials
@@ -40,8 +39,9 @@ This gem looks for the following configuration files inside "+/etc/vgh+" or the
40
39
  Ex: +'us-west-1'+
41
40
 
42
41
  [+#APP_NAME.config.yml+]
43
- The application specific configuration (see below a list of available apps and
44
- values).
42
+ The application specific configuration (see
43
+ {file:README.rdoc#Applications Applications} below for a list of available
44
+ apps and values).
45
45
 
46
46
  This gem checks if the files exists and if they are in a correct YAML format.
47
47
 
@@ -58,6 +58,10 @@ All files should have the following format (where the keys are symbols):
58
58
  -
59
59
  :sub_key: 'sub value'
60
60
 
61
+ Example configuration files can be found in this gem's directory. You can
62
+ find were that is by specifying the +--gemdir+ command line option.
63
+
64
+ Ex: <tt>vgh --gemdir</tt>
61
65
 
62
66
  == Command line options
63
67
 
@@ -71,6 +75,7 @@ The following command line options are available:
71
75
  [+-v+ <tt>--[no-]verbose</tt>] Specify whether to display messages on the
72
76
  screen or not.
73
77
  [+-l+ <tt>--[no-]logging</tt>] Specify whether to log messages or not.
78
+ [+-g+ +--gemdir+] Gem files location.
74
79
  [+-h+ +--help+] Displays this list.
75
80
  [+-V+ +--version+] Displays the version number.
76
81
 
@@ -86,12 +91,18 @@ The following command line options are available:
86
91
  snapshots older than the expiration period specified in the configuration
87
92
  file. It is intended to be used as a cron job on an AWS instance running
88
93
  Ubuntu.
94
+
95
+ You can also backup a remote instance, if you specify an +:instance+ or
96
+ +fqdn+ value in the configuration file. But if you do so, you loose the
97
+ ability to suspend MySQL or Logical Volumes.
98
+
89
99
  If a MySQL server is running, and the script has access to the administrator
90
100
  credentials, then it closes all open tables and locks all tables for all
91
101
  databases with a global read lock. Everything is unlocked at the end of the
92
102
  script even if errors occur during the snapshot process. <em>You need to
93
103
  provide the necessary mysql credentials in the +ec2-backup.config.yml+ file.
94
104
  </em>
105
+
95
106
  If Logical Volumes are found on the system then they are suspended for the
96
107
  duration on the snapshot process.
97
108
  Suspending a volume becomes useful if you want for example a consistent
@@ -102,9 +113,21 @@ The following command line options are available:
102
113
 
103
114
  ==== EC2-Backup Configuration
104
115
  +ec2-backup.config.yml+
105
- - +:expiration+ -- [Integer] Number of days to keep the snapshots.
116
+ - +:expiration+ -- required [Integer] Number of days to keep the snapshots.
106
117
  # Ex:
107
118
  :expiration: 7
119
+ - +:mysql_user+ -- required [String] The MySQL user that can flush the tables.
120
+ # Ex:
121
+ :mysql_user: 'dbadmin'
122
+ - +:mysql_pwd+ -- required [String] The password of the above MySQL user.
123
+ # Ex:
124
+ :mysql_pwd: 'MyStrongPassword'
125
+ - +:instance+ -- optional [String] The id of the remote instance you want to backup.
126
+ # Ex:
127
+ :instance: 'i-12345678'
128
+ - +:fqdn+ -- optional [String] The FQDN of the remote instance you want to backup.
129
+ # Ex:
130
+ :fqdn: 'MyServer.Example.com'
108
131
 
109
132
 
110
133
  ==== Intended usage
@@ -118,4 +141,13 @@ The following command line options are available:
118
141
  2. Create your feature branch (<tt>git checkout -b my-new-feature</tt>)
119
142
  3. Commit your changes (<tt>git commit -am 'Add some feature'</tt>)
120
143
  4. Push to the branch (<tt>git push origin my-new-feature</tt>)
121
- 5. Create new Pull Request (http://help.github.com/articles/using-pull-requests)
144
+ 5. Create new Pull Request
145
+ ({http://help.github.com/articles/using-pull-requests Using Pull Requests})
146
+
147
+
148
+ == License
149
+ See {file:LICENSE LICENSE}
150
+
151
+
152
+ == Changelog
153
+ See {file:CHANGELOG.rdoc CHANGELOG}
data/Rakefile CHANGED
@@ -1,14 +1,15 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
- require "yard"
1
+ require 'bundler/gem_helper'
2
+ require 'rspec/core/rake_task'
3
+ require 'yard'
4
4
 
5
5
  $LOAD_PATH << File.join(File.dirname(__FILE__), 'tasks')
6
6
  Dir['tasks/**/*.rake'].each { |task| load task }
7
7
 
8
8
  RSpec::Core::RakeTask.new
9
+ Bundler::GemHelper.install_tasks
9
10
 
10
11
  task :default do
11
- `rake -T`
12
+ puts `rake -T`
12
13
  end
13
14
 
14
15
  task :test => :spec
@@ -0,0 +1,9 @@
1
+ # Main settings for VGH gem
2
+
3
+ # AWS Credentials:
4
+ :access_key_id: 'xxxxxxxxxxxxxxxxxx'
5
+ :secret_access_key: 'xxxxxxxxxxxxxxxxxx'
6
+
7
+ # AWS Region (optional). It defaults to 'us-east-1'
8
+ #:region: 'us-west-1'
9
+
@@ -0,0 +1,12 @@
1
+ # EC2-Backup app settings
2
+
3
+ # Expiration period
4
+ :expiration: 7 # Number of days to keep the snapshots
5
+
6
+ # MySQL Settings
7
+ :mysql_user: 'dbadmin' # The MySQL user that can flush the tables
8
+ :mysql_pwd: 'MyStrongPassword' # The password of the above MySQL user
9
+
10
+ # Remote settings
11
+ #:instance: 'i-12345678' # The id of the remote instance you want to backup
12
+ #:fqdn: 'MyServer.Example.com' # The FQDN of the remote instance you want to backup
@@ -14,7 +14,8 @@ module APPS
14
14
 
15
15
  # Loads the necessary classes
16
16
  def initialize
17
- $cfg = parse_config.app_config
17
+ # Check if this script is run with root credentials
18
+ abort "ERROR: This app needs to be run as root!" unless is_root?
18
19
  @mysql = System::MySQL.new
19
20
  @lv = System::LV.new
20
21
  @volume = Extended_AWS::Extended_EC2::Volume.new
@@ -40,14 +41,29 @@ module APPS
40
41
 
41
42
  # Flushes MySQL tables and suspends Logical Volumes
42
43
  def lock
43
- @mysql.flush
44
- @lv.suspend
44
+ unless remotely?
45
+ @mysql.flush
46
+ @lv.suspend
47
+ end
45
48
  end
46
49
 
47
50
  # Resumes MySQL and Logical Volumes
48
51
  def unlock
49
- @mysql.unlock
50
- @lv.resume
52
+ unless remotely?
53
+ @mysql.unlock
54
+ @lv.resume
55
+ end
56
+ end
57
+
58
+ # Checks if this script is run remotely.
59
+ # @return [Boolean]
60
+ def remotely?
61
+ cfg = app_config
62
+ if cfg[:instance] or cfg[:fqdn]
63
+ @remotely = true
64
+ else
65
+ @remotely = false
66
+ end
51
67
  end
52
68
 
53
69
  end # class EC2_Backup
data/lib/vgh/cli.rb CHANGED
@@ -70,6 +70,7 @@ module VGH
70
70
  confdir
71
71
  verbose
72
72
  logging
73
+ gemdir
73
74
  help
74
75
  version
75
76
  validate(args)
@@ -134,6 +135,14 @@ module VGH
134
135
  end
135
136
  end
136
137
 
138
+ # Displays the location of gem files
139
+ def gemdir
140
+ @optparse.on_tail('-g', '--gemdir', 'Gem files location') do
141
+ puts File.expand_path('../../', File.dirname(__FILE__))
142
+ exit
143
+ end
144
+ end
145
+
137
146
  # Loads the help argument
138
147
  def help
139
148
  @optparse.on_tail('-h', '--help', 'Show this message') do
@@ -176,7 +185,7 @@ module VGH
176
185
  exit
177
186
  end
178
187
 
179
- end # Class CLI
188
+ end # class CLI
180
189
 
181
190
  end # module VGH
182
191
 
@@ -6,34 +6,33 @@ require 'logger'
6
6
  module VGH
7
7
 
8
8
  # Initialize the configuration parser
9
+ # @return [Hash]
9
10
  def parse_config
10
- $config ||= Configuration.new
11
+ $parse_config ||= Configuration.new
11
12
  end
12
13
 
13
14
  # Returns a hash containing the main settings
14
- def main_config
15
- $main_config ||= parse_config.main_config
16
- end
17
-
18
- # Returns a hash containing the AWS settings
19
- def aws_config
20
- $aws_config ||= parse_config.aws_config
15
+ # @return [Hash]
16
+ def config
17
+ $config ||= parse_config.main_config
21
18
  end
22
19
 
23
20
  # Returns a hash containing the app settings
21
+ # @return [Hash]
24
22
  def app_config
25
23
  $app_config ||= parse_config.app_config
26
24
  end
27
25
 
28
26
  # Returns a single merged hash with all configurations
27
+ # @return [Hash]
29
28
  def global_config
30
- $global_config ||= [main_config, aws_config, app_config].inject(:merge)
29
+ $global_config ||= [config, app_config].inject(:merge)
31
30
  end
32
31
 
33
32
  # Creates a global ec2 method (passing the specified region).
34
33
  # The default region is us-east-1, so we overwrite it here.
35
34
  def ec2
36
- region = aws_config[:region]
35
+ region = config[:region]
37
36
  if region
38
37
  $ec2 = AWS::EC2.new.regions[region]
39
38
  else
@@ -49,13 +48,11 @@ module VGH
49
48
  #
50
49
  # == Usage:
51
50
  #
52
- # cfg = Configuration.new
53
- # main_config = cfg.main_config
54
- # aws_config = cfg.aws_config
55
- # app_config = cfg.app_config
51
+ # parse = Configuration.new
52
+ # main_config = parse.main_config
53
+ # app_config = parse.app_config
56
54
  #
57
55
  # pp main_config
58
- # pp aws_config
59
56
  # pp app_config
60
57
  #
61
58
  class Configuration
@@ -63,9 +60,6 @@ module VGH
63
60
  # Main configuration
64
61
  attr_reader :main_config
65
62
 
66
- # AWS configuration
67
- attr_reader :aws_config
68
-
69
63
  # App specific configuration
70
64
  attr_reader :app_config
71
65
 
@@ -73,12 +67,12 @@ module VGH
73
67
  def initialize
74
68
  @confdir = validate_config_dir('/etc/vgh')
75
69
  @main = "#{@confdir}/config.yml"
76
- @aws = "#{@confdir}/aws.config.yml"
77
70
  @app = "#{@confdir}/#{app}.config.yml"
78
71
  end
79
72
 
80
73
  # IF specified, use the confdir specified in the command line options
81
- def validate_config_dir(default_confdir, cli = cli_confdir)
74
+ def validate_config_dir(default_confdir)
75
+ cli = cli_confdir
82
76
  if cli.nil?
83
77
  return default_confdir
84
78
  else
@@ -94,11 +88,6 @@ module VGH
94
88
  end
95
89
  end
96
90
 
97
- # Returns a parsed configuration
98
- def parse(path)
99
- @parse = YAML.load(File.read(path))
100
- end
101
-
102
91
  # Checks if the configuration file exists
103
92
  def config_exists?(path)
104
93
  File.exist?(path)
@@ -109,30 +98,24 @@ module VGH
109
98
  parse(path).kind_of?(Hash)
110
99
  end
111
100
 
101
+ # Returns a parsed configuration
102
+ def parse(path)
103
+ @parse = YAML.load(File.read(path))
104
+ end
105
+
112
106
  # Parse the main configuration
113
107
  def main_config
114
108
  message.info "Loading main configuration..."
115
109
  validate(@main)
116
- parse(@main)
117
- end
118
-
119
- # Parse the AWS configuration
120
- def aws_config
121
- message.info "Loading AWS configuration..."
122
- validate(@aws)
123
- @aws_config = parse(@aws)
124
- load_aws
125
- return @aws_config
126
- end
127
-
128
- # Overwrite the AWS Core configuration
129
- def load_aws
130
- AWS.config(@aws_config)
110
+ @main_config = parse(@main)
131
111
  AWS.config({
132
- :logger => log,
133
- :log_formatter => AWS::Core::LogFormatter.colored,
134
- :max_retries => 2
112
+ :access_key_id => @main_config[:access_key_id],
113
+ :secret_access_key => @main_config[:secret_access_key],
114
+ :logger => log,
115
+ :log_formatter => AWS::Core::LogFormatter.colored,
116
+ :max_retries => 2
135
117
  })
118
+ return @main_config
136
119
  end
137
120
 
138
121
  # Parse app specific configuration
@@ -157,13 +140,14 @@ To run this script, you need to create a file named
157
140
  :integer: 123
158
141
  :boolean: true/false
159
142
  :array:
160
- - '1st'
161
- - '2nd'
143
+ - '1st'
144
+ - '2nd'
162
145
  :hash:
163
- -
164
- :sub_key: 'sub value'
146
+ -
147
+ :sub_key: 'sub value'
165
148
 
166
149
  END
150
+ return load_error
167
151
  end
168
152
 
169
153
  end # class Configuration
@@ -1,8 +1,19 @@
1
1
  require 'open-uri'
2
- require 'net/http'
3
- require 'uri'
4
2
 
5
3
  module VGH
4
+
5
+ # Looks for the instance id in the configuration. If it does not exist then it
6
+ # queries the API server for it.
7
+ # @return [String]
8
+ def instance_id
9
+ remote_instance = app_config[:instance]
10
+ if remote_instance
11
+ $instance_id ||= remote_instance
12
+ else
13
+ $instance_id ||= VGH::Extended_AWS::Extended_EC2::MetaData.new.instance_id
14
+ end
15
+ end
16
+
6
17
  module Extended_AWS
7
18
  module Extended_EC2
8
19
 
@@ -11,12 +11,6 @@ module Extended_EC2
11
11
  #
12
12
  class Snapshot
13
13
 
14
- # Load all needed classes
15
- def initialize
16
- @instance_id = MetaData.new.instance_id
17
- @fqdn = System.fqdn
18
- end
19
-
20
14
  # The workflow to create a snapshot:
21
15
  # - create snapshot
22
16
  # - add a name tag
@@ -27,7 +21,7 @@ class Snapshot
27
21
  snapshot(volume_id, volume_tag)
28
22
  name_tag
29
23
  info_tag(volume_id)
30
- message.info "Creating and tagging snapshot \"#{@snapshot.id}\""
24
+ message.info "Creating and tagging snapshot \"#{snapshot.id}\""
31
25
  end
32
26
 
33
27
  # Creates a snapshot for the specified volume
@@ -42,19 +36,19 @@ class Snapshot
42
36
  # Creates a name tag for the newly created snapshot.
43
37
  # The name is the FQDN of the current instance.
44
38
  def name_tag
45
- ec2.snapshots[@snapshot.id].tag('Name', :value => @fqdn)
39
+ ec2.snapshots[snapshot.id].tag('Name', :value => fqdn)
46
40
  end
47
41
 
48
42
  # Creates an info tag for the newly created snapshot
49
43
  def info_tag(volume_id)
50
- ec2.snapshots[@snapshot.id].tag("Backup_#{@instance_id}", :value => volume_id)
44
+ ec2.snapshots[snapshot.id].tag("Backup_#{instance_id}", :value => volume_id)
51
45
  end
52
46
 
53
47
  # Purges expired snapshots
54
48
  def purge
55
- expired.each do |snapshot|
56
- message.info "Deleting expired snapshot (#{snapshot.id})"
57
- snapshot.delete
49
+ expired.each do |snap|
50
+ message.info "Deleting expired snapshot (#{snap.id})"
51
+ snap.delete
58
52
  end
59
53
  end
60
54
 
@@ -63,9 +57,9 @@ class Snapshot
63
57
  # @return [Array] An array of expired snapshot objects
64
58
  def expired
65
59
  @expired = []
66
- all.each {|snapshot|
67
- if snapshot.start_time < (Time.now - $cfg[:expiration]*24*60*60)
68
- @expired.push snapshot
60
+ all.each {|snap|
61
+ if snap.start_time < (Time.now - app_config[:expiration]*24*60*60)
62
+ @expired.push snap
69
63
  end
70
64
  }
71
65
  return @expired
@@ -75,7 +69,7 @@ class Snapshot
75
69
  def all
76
70
  @all ||= ec2.snapshots.
77
71
  with_owner('self').
78
- tagged('Name').tagged_values(@fqdn)
72
+ tagged('Name').tagged_values(fqdn)
79
73
  end
80
74
 
81
75
  end # class Snapshot
@@ -13,9 +13,9 @@ module Extended_EC2
13
13
  #
14
14
  class Volume
15
15
 
16
- # Collects all needed variables
17
- def initialize
18
- @instance_id = MetaData.new.instance_id
16
+ # @return An instance object
17
+ def instance
18
+ @instance ||= ec2.instances[instance_id]
19
19
  end
20
20
 
21
21
  # Creates a Hash collection of volumes containing their id, tag and device
@@ -32,11 +32,11 @@ class Volume
32
32
  return @list
33
33
  end
34
34
 
35
- # Returns a Hash containing the block device mappings of the current instance
35
+ # Returns a Hash containing the block device mappings of the current instance.
36
36
  # @return [Hash]
37
37
  def mappings
38
38
  message.info "Creating a list of volumes..."
39
- @mappings ||= ec2.instances[@instance_id].block_device_mappings
39
+ @mappings ||= instance.block_device_mappings
40
40
  end
41
41
 
42
42
  # Get volume's Name tag
data/lib/vgh/logging.rb CHANGED
@@ -2,7 +2,7 @@ require 'logger'
2
2
 
3
3
  module VGH
4
4
 
5
- # Returns log state
5
+ # Log message
6
6
  def log
7
7
  if logging?
8
8
  $log ||= Logging.new.log
@@ -46,7 +46,11 @@ module VGH
46
46
 
47
47
  # Opens the log file
48
48
  def log_file
49
- File.open(@path, File::WRONLY | File::APPEND | File::CREAT)
49
+ begin
50
+ File.open(@path, File::WRONLY | File::APPEND | File::CREAT)
51
+ rescue
52
+ STDOUT
53
+ end
50
54
  end
51
55
 
52
56
  # Global, memoized, lazy initialized instance of a logger
@@ -63,4 +67,3 @@ module VGH
63
67
  end # module VGH
64
68
 
65
69
  require 'vgh/cli'
66
-
data/lib/vgh/output.rb CHANGED
@@ -109,5 +109,4 @@ END_FOOTER
109
109
  end # module VGH
110
110
 
111
111
  require 'vgh/cli'
112
- require 'vgh/configuration'
113
112
  require 'vgh/logging'
@@ -16,10 +16,11 @@ class MySQL
16
16
 
17
17
  # Load defaults
18
18
  def initialize
19
+ cfg = app_config
19
20
  @mysqladmin = '/usr/bin/mysqladmin'
20
21
  @mysql = '/usr/bin/mysql'
21
- @user = $cfg[:mysql_user]
22
- @password = $cfg[:mysql_pwd]
22
+ @user = cfg[:mysql_user]
23
+ @password = cfg[:mysql_pwd]
23
24
  end
24
25
 
25
26
  # Check if server is running and we have access to the credentials file
data/lib/vgh/system.rb CHANGED
@@ -1,5 +1,27 @@
1
1
  module VGH
2
2
 
3
+ # Returns the FQDN (either the one specified in the configuration file or
4
+ # the system's one)
5
+ # @return [String]
6
+ def fqdn
7
+ remote_fqdn = app_config[:fqdn]
8
+ if remote_fqdn
9
+ $fqdn ||= remote_fqdn
10
+ else
11
+ $fqdn ||= System.fqdn
12
+ end
13
+ end
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
+
3
25
  # This is a parent class for different system actions performed by the scripts
4
26
  # included in this gem. For more information see the classes defined under
5
27
  # this namespace.
@@ -10,8 +32,8 @@ module VGH
10
32
  #
11
33
  module System
12
34
 
13
- # FQDN
14
- # @return [String] The FQDN of the current machine.
35
+ # Returns the current system's FQDN
36
+ # @return [String]
15
37
  def self.fqdn
16
38
  $fqdn ||= `hostname -f`
17
39
  end
data/lib/vgh/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module VGH
2
2
  # Version number
3
- VERSION = "0.0.2"
3
+ VERSION = "0.1.0"
4
4
 
5
5
  # Returns the version number
6
6
  def version
data/lib/vgh.rb CHANGED
@@ -21,9 +21,6 @@ module VGH
21
21
  # The main run method
22
22
  def run
23
23
 
24
- # Check if this script is run with root credentials
25
- root_check
26
-
27
24
  # Display header
28
25
  show_header
29
26
 
@@ -48,13 +45,9 @@ module VGH
48
45
  message.footer
49
46
  end
50
47
 
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
48
  end # module VGH
57
49
 
58
50
  require "vgh/output"
51
+ require "vgh/system"
59
52
  require "vgh/apps"
60
53
  require "vgh/apps/ec2_backup"
data/spec/apps_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'helpers/spec'
2
+ require 'vgh/apps'
3
+
4
+ describe VGH::APPS do
5
+ it "Should have an array of supported apps" do
6
+ subject.list.should be_an Array
7
+ end
8
+ end
data/spec/cli_spec.rb CHANGED
@@ -1,25 +1,44 @@
1
- require 'spec_helper'
1
+ require 'helpers/spec'
2
2
  require 'vgh'
3
3
  require 'vgh/apps'
4
4
  require 'vgh/cli'
5
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
6
+ describe VGH::CLI do
7
+
8
+ let(:app) {VGH::APPS.list.shuffle.first}
9
+
10
+ before(:all) do
11
+ ARGV[0] = app
12
+ end
13
+
14
+ it "Should get the app name as the first argument" do
15
+ VGH::CLI.new.options[:app].should eq app
11
16
  end
12
- }
13
17
 
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
+ 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
18
23
  end
19
24
 
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
25
+ context "When '-v' NOT passed to the command line" do
26
+ it "Verbosity should be disabled" do
27
+ VGH::CLI.new.options[:verbose].should be_false
28
+ end
24
29
  end
30
+
31
+ context "When '-l' passed to the command line" do
32
+ it "Logging should be enabled" do
33
+ ARGV.push('-l')
34
+ VGH::CLI.new.options[:logging].should be_true
35
+ end
36
+ end
37
+
38
+ context "When '-l' NOT passed to the command line" do
39
+ it "Logging should be disabled" do
40
+ VGH::CLI.new.options[:logging].should be_false
41
+ end
42
+ end
43
+
25
44
  end
@@ -0,0 +1,24 @@
1
+ require 'helpers/spec'
2
+
3
+ require 'vgh/extended_aws/extended_ec2/metadata'
4
+
5
+ describe VGH::Extended_AWS::Extended_EC2::MetaData do
6
+
7
+ before(:each) do
8
+ subject.stub(:message).and_return(Dummy.new)
9
+ end
10
+
11
+ it "Should retrieve the instance id" do
12
+ unless subject.instance_id.nil?
13
+ subject.instance_id.should match(/i\-.*/)
14
+ end
15
+ end
16
+
17
+ it "Should retrieve the root device" do
18
+ unless subject.root_device.nil?
19
+ subject.root_device.should match(/\/dev\/.*/)
20
+ end
21
+ end
22
+
23
+ end
24
+
@@ -0,0 +1,48 @@
1
+ require 'helpers/spec'
2
+
3
+ require 'aws-sdk'
4
+ require 'vgh/extended_aws/extended_ec2/snapshot'
5
+ require 'vgh/system'
6
+
7
+ describe VGH::Extended_AWS::Extended_EC2::Snapshot do
8
+
9
+ include_context "Dummy Instance"
10
+
11
+ it "Should return a snapshot" do
12
+ subject.snapshot(@volume.id, 'test').should be_a(AWS::EC2::Snapshot)
13
+ end
14
+
15
+ it "Should add a Name tag to a snapshot" do
16
+ subject.name_tag.should be_a(AWS::EC2::Tag)
17
+ end
18
+
19
+ it "Should add an Info tag to a snapshot" do
20
+ subject.info_tag(@volume.id).should be_a(AWS::EC2::Tag)
21
+ end
22
+
23
+ it "Should get a list of all snapshots" do
24
+ subject.all.should be_a(AWS::EC2::SnapshotCollection)
25
+ end
26
+
27
+ it "Should create an array of expired snapshots" do
28
+ subject.expired.should be_empty
29
+ end
30
+
31
+ it "Should purge expired snapshots" do
32
+ subject.purge.should be_empty
33
+ end
34
+
35
+ #it "Should create a list of volumes" do
36
+ #subject.list.should be_a_kind_of Hash
37
+ #end
38
+
39
+ #it "Should get a collection of volume tags" do
40
+ #subject.tags(@volume.id).should be_a(AWS::EC2::TagCollection)
41
+ #end
42
+
43
+ #it "If no tags, it should return (NOTAG)" do
44
+ #subject.tag(@volume.id).should eq('(NOTAG)')
45
+ #end
46
+
47
+ end
48
+
@@ -0,0 +1,27 @@
1
+ require 'helpers/spec'
2
+
3
+ require 'aws-sdk'
4
+ require 'vgh/extended_aws/extended_ec2/volume'
5
+
6
+ describe VGH::Extended_AWS::Extended_EC2::Volume do
7
+
8
+ include_context "Dummy Instance"
9
+
10
+ it "Should create a hash with block device mappings" do
11
+ subject.mappings.should be_a_kind_of Hash
12
+ end
13
+
14
+ it "Should create a list of volumes" do
15
+ subject.list.should be_a_kind_of Hash
16
+ end
17
+
18
+ it "Should get a collection of volume tags" do
19
+ subject.tags(@volume.id).should be_a(AWS::EC2::TagCollection)
20
+ end
21
+
22
+ it "If no tags, it should return (NOTAG)" do
23
+ subject.tag(@volume.id).should eq('(NOTAG)')
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,39 @@
1
+ RSpec.configure do |config|
2
+ config.treat_symbols_as_metadata_keys_with_true_values = true
3
+ config.run_all_when_everything_filtered = true
4
+ config.filter_run :focus
5
+ config.order = 'random'
6
+ end
7
+
8
+ class Dummy
9
+ def method_missing(name, *args, &block)
10
+ #puts "Tried to handle unknown method %s" % name # name is a symbol
11
+ #unless args.empty?
12
+ #puts "It had arguments: %p" % [args]
13
+ #end
14
+ end
15
+ end
16
+
17
+ shared_context "Dummy Instance" do
18
+ before(:each) do
19
+ AWS.stub!
20
+ AWS.config({:access_key_id => '', :secret_access_key => ''})
21
+ @ec2 = AWS::EC2.new
22
+ @instance = AWS::EC2::Instance.new('i-12345678')
23
+ @fqdn = 'test.example.com'
24
+ @volume = AWS::EC2::Volume.new('vol-12345678')
25
+ @snapshot = AWS::EC2::Snapshot.new('snap-12345678')
26
+ @device = '/dev/test'
27
+ @attachment = AWS::EC2::Attachment.new(@volume, @instance, @device)
28
+ @instance.stub(:block_device_mappings).and_return({
29
+ @device => @attachment
30
+ })
31
+
32
+ subject.stub(:ec2).and_return(@ec2)
33
+ subject.stub(:instance_id).and_return(@instance.id)
34
+ subject.stub(:fqdn).and_return(@fqdn)
35
+ subject.stub(:instance).and_return(@instance)
36
+ subject.stub(:snapshot).and_return(@snapshot)
37
+ subject.stub(:message).and_return(Dummy.new)
38
+ end
39
+ end
@@ -0,0 +1,11 @@
1
+ require 'helpers/spec'
2
+ require 'vgh'
3
+ require 'vgh/logging'
4
+
5
+ describe VGH::Logging do
6
+ it "Should write logs" do
7
+ log = VGH::Logging.new.log
8
+ log.should_receive(:info).with("RSpec Test")
9
+ log.info("RSpec Test")
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'helpers/spec'
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 VGH::Output do
10
+ let(:message) {VGH::Output.new}
11
+ it "Should write messages" do
12
+ message.should_receive(:stdout).with("RSpec Test")
13
+ message.stdout("RSpec Test")
14
+ end
15
+ end
metadata CHANGED
@@ -1,129 +1,132 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: vgh
3
- version: !ruby/object:Gem::Version
4
- hash: 27
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 2
10
- version: 0.0.2
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Vlad Ghinea
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-10-14 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2012-11-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: aws-sdk
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
24
17
  none: false
25
- requirements:
26
- - - ">="
27
- - !ruby/object:Gem::Version
28
- hash: 3
29
- segments:
30
- - 1
31
- - 6
32
- - 6
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
33
21
  version: 1.6.6
34
22
  type: :runtime
35
- version_requirements: *id001
36
- - !ruby/object:Gem::Dependency
37
- name: sinatra
38
23
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.6.6
30
+ - !ruby/object:Gem::Dependency
31
+ name: sinatra
32
+ requirement: !ruby/object:Gem::Requirement
40
33
  none: false
41
- requirements:
42
- - - ">="
43
- - !ruby/object:Gem::Version
44
- hash: 29
45
- segments:
46
- - 1
47
- - 3
48
- - 3
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
49
37
  version: 1.3.3
50
38
  type: :runtime
51
- version_requirements: *id002
52
- - !ruby/object:Gem::Dependency
53
- name: rspec
54
39
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
40
+ version_requirements: !ruby/object:Gem::Requirement
56
41
  none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- hash: 3
61
- segments:
62
- - 0
63
- version: "0"
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 1.3.3
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
64
54
  type: :development
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: rake
68
55
  prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
56
+ version_requirements: !ruby/object:Gem::Requirement
70
57
  none: false
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- hash: 3
75
- segments:
76
- - 0
77
- version: "0"
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
78
70
  type: :development
79
- version_requirements: *id004
80
- - !ruby/object:Gem::Dependency
81
- name: yard
82
71
  prerelease: false
83
- requirement: &id005 !ruby/object:Gem::Requirement
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: yard
80
+ requirement: !ruby/object:Gem::Requirement
84
81
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
92
86
  type: :development
93
- version_requirements: *id005
94
- - !ruby/object:Gem::Dependency
95
- name: bundler
96
87
  prerelease: false
97
- requirement: &id006 !ruby/object:Gem::Requirement
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: bundler
96
+ requirement: !ruby/object:Gem::Requirement
98
97
  none: false
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- hash: 3
103
- segments:
104
- - 0
105
- version: "0"
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
106
102
  type: :development
107
- version_requirements: *id006
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
108
110
  description: Vlad's custom scripts
109
- email:
111
+ email:
110
112
  - vgit@vladgh.com
111
- executables:
113
+ executables:
112
114
  - vgh
113
115
  extensions: []
114
-
115
116
  extra_rdoc_files: []
116
-
117
- files:
117
+ files:
118
118
  - .gitignore
119
119
  - .rspec
120
120
  - .travis.yml
121
121
  - .yardopts
122
+ - CHANGELOG.rdoc
122
123
  - Gemfile
123
124
  - LICENSE
124
125
  - README.rdoc
125
126
  - Rakefile
126
127
  - bin/vgh
128
+ - conf/config.yml.example
129
+ - conf/ec2-backup.config.yml.example
127
130
  - lib/vgh.rb
128
131
  - lib/vgh/apps.rb
129
132
  - lib/vgh/apps/ec2_backup.rb
@@ -140,46 +143,47 @@ files:
140
143
  - lib/vgh/system/lvm.rb
141
144
  - lib/vgh/system/mysql.rb
142
145
  - lib/vgh/version.rb
146
+ - spec/apps_spec.rb
143
147
  - spec/cli_spec.rb
144
- - spec/misc_spec.rb
145
- - spec/spec_helper.rb
148
+ - spec/extended_aws/extended_ec2/metadata_spec.rb
149
+ - spec/extended_aws/extended_ec2/snapshot_spec.rb
150
+ - spec/extended_aws/extended_ec2/volume_spec.rb
151
+ - spec/helpers/spec.rb
152
+ - spec/logging_spec.rb
153
+ - spec/output_spec.rb
146
154
  - tasks/documentation.rake
147
155
  - vgh.gemspec
148
156
  homepage: https://github.com/vladgh/vgh
149
157
  licenses: []
150
-
151
158
  post_install_message:
152
159
  rdoc_options: []
153
-
154
- require_paths:
160
+ require_paths:
155
161
  - lib
156
- required_ruby_version: !ruby/object:Gem::Requirement
162
+ required_ruby_version: !ruby/object:Gem::Requirement
157
163
  none: false
158
- requirements:
159
- - - ">="
160
- - !ruby/object:Gem::Version
161
- hash: 3
162
- segments:
163
- - 0
164
- version: "0"
165
- required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ! '>='
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
169
  none: false
167
- requirements:
168
- - - ">="
169
- - !ruby/object:Gem::Version
170
- hash: 3
171
- segments:
172
- - 0
173
- version: "0"
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
174
  requirements: []
175
-
176
175
  rubyforge_project:
177
- rubygems_version: 1.8.24
176
+ rubygems_version: 1.8.23
178
177
  signing_key:
179
178
  specification_version: 3
180
179
  summary: A collection of custom scripts used on VladGh.com
181
- test_files:
180
+ test_files:
181
+ - spec/apps_spec.rb
182
182
  - spec/cli_spec.rb
183
- - spec/misc_spec.rb
184
- - spec/spec_helper.rb
183
+ - spec/extended_aws/extended_ec2/metadata_spec.rb
184
+ - spec/extended_aws/extended_ec2/snapshot_spec.rb
185
+ - spec/extended_aws/extended_ec2/volume_spec.rb
186
+ - spec/helpers/spec.rb
187
+ - spec/logging_spec.rb
188
+ - spec/output_spec.rb
185
189
  has_rdoc:
data/spec/misc_spec.rb DELETED
@@ -1,25 +0,0 @@
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
data/spec/spec_helper.rb DELETED
@@ -1,7 +0,0 @@
1
- RSpec.configure do |config|
2
- config.treat_symbols_as_metadata_keys_with_true_values = true
3
- config.run_all_when_everything_filtered = true
4
- config.filter_run :focus
5
- config.order = 'random'
6
- end
7
-