claws 1.0.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/README.md +80 -0
- data/bin/claws +36 -0
- data/lib/claws.rb +6 -0
- data/lib/claws/capistrano.rb +63 -0
- data/lib/claws/collection/base.rb +19 -0
- data/lib/claws/collection/ec2.rb +17 -0
- data/lib/claws/command/ec2.rb +43 -0
- data/lib/claws/command/initialize.rb +63 -0
- data/lib/claws/configuration.rb +25 -0
- data/lib/claws/options.rb +37 -0
- data/lib/claws/presenter/ec2.rb +43 -0
- data/lib/claws/report/ec2.rb +54 -0
- data/lib/claws/support.rb +12 -0
- data/lib/claws/version.rb +3 -0
- data/spec/base_spec.rb +6 -0
- data/spec/capistrano_spec.rb +74 -0
- data/spec/collection/base_spec.rb +30 -0
- data/spec/collection/ec2_spec.rb +18 -0
- data/spec/command/ec2_spec.rb +179 -0
- data/spec/command/initialize_spec.rb +19 -0
- data/spec/configuration_spec.rb +98 -0
- data/spec/options_spec.rb +73 -0
- data/spec/presenter/ec2_spec.rb +94 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/support/helpers/stdout_helper.rb +11 -0
- data/spec/support_spec.rb +17 -0
- metadata +120 -0
data/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
## Command Line AWS (CLAWS) [](http://travis-ci.org/wbailey/claws)
|
2
|
+
|
3
|
+
This tool provides a simple and powerful way to interact with the hosts in your Amazon Web Services
|
4
|
+
account via the command line.
|
5
|
+
|
6
|
+
It provides a configurable text based interface of the status of your hosts similar to the AWS web
|
7
|
+
console. An example of its usage appears below:
|
8
|
+
|
9
|
+

|
10
|
+
|
11
|
+
It gives you a choice of which host to connect to and invokes the proper ssh command:
|
12
|
+
|
13
|
+

|
14
|
+
|
15
|
+
### Installation
|
16
|
+
|
17
|
+
It is up on rubygems.org so add it to your bundle in the Gemfile
|
18
|
+
|
19
|
+
```bash
|
20
|
+
gem 'claws'
|
21
|
+
```
|
22
|
+
|
23
|
+
or do it the old fashioned way:
|
24
|
+
|
25
|
+
```bash
|
26
|
+
gem install claws
|
27
|
+
```
|
28
|
+
|
29
|
+
After you have the gem installed you will need to _initialize_ it to install a configuation file:
|
30
|
+
|
31
|
+
```bash
|
32
|
+
claws --init
|
33
|
+
```
|
34
|
+
|
35
|
+
Read more about the configuration file in this [wiki post](https://github.com/wbailey/claws/wiki/Configuration-file)
|
36
|
+
|
37
|
+
### Usage
|
38
|
+
|
39
|
+
Once the initial configuration is completed you can simply run claws from the command line:
|
40
|
+
|
41
|
+
```bash
|
42
|
+
claws
|
43
|
+
```
|
44
|
+
|
45
|
+
The full list of options includes:
|
46
|
+
|
47
|
+
```bash
|
48
|
+
Usage: claws [options]
|
49
|
+
-s, --status-only Display host status only and exit
|
50
|
+
-c, --choice N Enter the number of the host to automatically connect to
|
51
|
+
-i, --init Install the default configuration file for the application
|
52
|
+
```
|
53
|
+
|
54
|
+
### To Do
|
55
|
+
|
56
|
+
* Add filtering by regular expression for any field
|
57
|
+
|
58
|
+
* Integrate with your projects Capistrano definitions so that one can filter by environment and
|
59
|
+
roles.
|
60
|
+
|
61
|
+
* Add RDS and ELB support
|
62
|
+
|
63
|
+
### License
|
64
|
+
|
65
|
+
Copyright (c) 2011-2012 Wes Bailey
|
66
|
+
|
67
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
68
|
+
associated documentation files (the "Software"), to deal in the Software without restriction,
|
69
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
70
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
71
|
+
furnished to do so, subject to the following conditions:
|
72
|
+
|
73
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
74
|
+
portions of the Software.
|
75
|
+
|
76
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
77
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
78
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
79
|
+
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
80
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/bin/claws
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
require 'claws'
|
3
|
+
require 'optparse'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
options = OpenStruct.new(
|
8
|
+
{
|
9
|
+
:config_file => nil,
|
10
|
+
:connect => true,
|
11
|
+
:initialize => false,
|
12
|
+
:selection => nil,
|
13
|
+
}
|
14
|
+
)
|
15
|
+
|
16
|
+
OptionParser.new do |opts|
|
17
|
+
opts.banner = 'Usage: claws [options]'
|
18
|
+
|
19
|
+
opts.on('-s', '--status-only', 'Display host status only and exit') do
|
20
|
+
options.connect = false
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on('-c', '--choice N', Float, 'Enter the number of the host to automatically connect to') do |n|
|
24
|
+
options.selection = n.to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on('-i', '--init', 'Install the default configuration file for the application') do
|
28
|
+
options.initialize = true
|
29
|
+
end
|
30
|
+
end.parse!
|
31
|
+
|
32
|
+
if options.initialize
|
33
|
+
Claws::Command::Initialize.exec
|
34
|
+
else
|
35
|
+
Claws::Command::EC2.exec options
|
36
|
+
end
|
data/lib/claws.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
module Claws
|
2
|
+
class Capistrano
|
3
|
+
attr_accessor :home
|
4
|
+
|
5
|
+
def initialize(home = nil)
|
6
|
+
self.home = home || File.join('config', 'deploy')
|
7
|
+
end
|
8
|
+
|
9
|
+
def all_host_roles
|
10
|
+
@all_roles ||= begin
|
11
|
+
roles = Hash.new
|
12
|
+
|
13
|
+
Dir.glob(File.join(self.home, '**/*.rb')).each do |f|
|
14
|
+
environment = File.basename(f)[0..-4]
|
15
|
+
roles[environment.to_sym] = get_roles(environment)
|
16
|
+
end
|
17
|
+
|
18
|
+
roles
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def roles(host)
|
23
|
+
self.all_host_roles.each do |env, hh|
|
24
|
+
hh.each do |k,v|
|
25
|
+
return v if k == host
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def get_roles(environment)
|
33
|
+
role_records = File.readlines(File.join(self.home, "#{environment}.rb")).select {|r| r.match(/^role/)}
|
34
|
+
|
35
|
+
# At this point we have an array of strings with:
|
36
|
+
#
|
37
|
+
# [
|
38
|
+
# "role :app, \"ec2-263-56-231-91.compute-1.amazonaws.com\", 'ec2-263-23-118-57.compute-1.amazonaws.com'",
|
39
|
+
# "role :web, \"ec2-263-56-231-91.compute-1.amazonaws.com\", 'ec2-263-23-118-57.compute-1.amazonaws.com', \"ec2-23-20-43-198.compute-1.amazonaws.com\"",
|
40
|
+
# ]
|
41
|
+
#
|
42
|
+
# and we want to convert that to:
|
43
|
+
#
|
44
|
+
# {
|
45
|
+
# 'ec2-263-56-231-91.compute-1.amazonaws.com' => ["app", "web"],
|
46
|
+
# 'ec2-263-23-118-57.compute-1.amazonaws.com' => ["app", "web"],
|
47
|
+
# 'ec2-23-20-43-198.compute-1.amazonaws.com' => ["web"],
|
48
|
+
# }
|
49
|
+
|
50
|
+
roles = Hash.new {|h,k| h[k] = Array.new}
|
51
|
+
|
52
|
+
role_records.each do |record|
|
53
|
+
role, *hosts = record.split(',').map {|v| v.strip.chomp.gsub(/"|'/, '')}
|
54
|
+
|
55
|
+
hosts.each do |host|
|
56
|
+
roles[host] << role.split(':')[1]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
roles
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
module Claws
|
4
|
+
module Collection
|
5
|
+
class Base
|
6
|
+
def self.connect(credentials)
|
7
|
+
AWS.config(credentials)
|
8
|
+
AWS.start_memoizing
|
9
|
+
end
|
10
|
+
|
11
|
+
# Seems unnecessary
|
12
|
+
def self.build
|
13
|
+
collection = []
|
14
|
+
yield(collection)
|
15
|
+
collection
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'claws/collection/base'
|
3
|
+
require 'claws/presenter/ec2'
|
4
|
+
|
5
|
+
module Claws
|
6
|
+
module Collection
|
7
|
+
class EC2 < Claws::Collection::Base
|
8
|
+
def self.get(filters = {})
|
9
|
+
collection = []
|
10
|
+
AWS::EC2.new.instances.each do |instance|
|
11
|
+
collection << Claws::EC2::Presenter.new(instance)
|
12
|
+
end
|
13
|
+
collection
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Claws
|
2
|
+
module Command
|
3
|
+
class EC2
|
4
|
+
def self.exec(options)
|
5
|
+
begin
|
6
|
+
config = Claws::Configuration.new( options.config_file )
|
7
|
+
rescue Claws::ConfigurationError => e
|
8
|
+
puts e.message
|
9
|
+
puts 'Use the --init option to create a configuration file.'
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
Claws::Collection::EC2.connect( config.aws )
|
14
|
+
|
15
|
+
begin
|
16
|
+
instances = Claws::Collection::EC2.get
|
17
|
+
rescue Exception => e
|
18
|
+
puts e.message
|
19
|
+
end
|
20
|
+
|
21
|
+
Claws::Report::EC2.new( config, instances ).run
|
22
|
+
|
23
|
+
if options.connect
|
24
|
+
if instances.size == 1
|
25
|
+
puts
|
26
|
+
selection = 0
|
27
|
+
elsif options.selection
|
28
|
+
puts
|
29
|
+
selection = options.selection
|
30
|
+
else
|
31
|
+
print "Select server (enter q to quit): "
|
32
|
+
selection = gets.chomp
|
33
|
+
exit 0 if selection.match(/^q.*/i)
|
34
|
+
end
|
35
|
+
|
36
|
+
puts 'connecting to server...'
|
37
|
+
|
38
|
+
system "ssh #{config.ssh.user}@#{instances[selection.to_i].dns_name}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Claws
|
4
|
+
module Command
|
5
|
+
class Initialize
|
6
|
+
def self.exec
|
7
|
+
h = {
|
8
|
+
'capistrano' => {
|
9
|
+
'home' => nil,
|
10
|
+
},
|
11
|
+
'ssh' => {
|
12
|
+
'user' => nil,
|
13
|
+
},
|
14
|
+
'aws' => {
|
15
|
+
'access_key_id' => nil,
|
16
|
+
'secret_access_key' => nil,
|
17
|
+
},
|
18
|
+
'ec2' => {
|
19
|
+
'fields' => {
|
20
|
+
'id' => {
|
21
|
+
'width' => 10,
|
22
|
+
'title' => 'ID',
|
23
|
+
},
|
24
|
+
'name' => {
|
25
|
+
'width' => 20,
|
26
|
+
'title' => 'Name',
|
27
|
+
},
|
28
|
+
'status' => {
|
29
|
+
'width' => 8,
|
30
|
+
'title' => 'Status',
|
31
|
+
},
|
32
|
+
'dns_name' => {
|
33
|
+
'width' => 42,
|
34
|
+
'title' => 'DNS Name',
|
35
|
+
},
|
36
|
+
'instance_type' => {
|
37
|
+
'width' => 13,
|
38
|
+
'title' => 'Instance Type',
|
39
|
+
},
|
40
|
+
'public_ip_address' => {
|
41
|
+
'width' => 16,
|
42
|
+
'title' => 'Public IP',
|
43
|
+
},
|
44
|
+
'private_ip_address' => {
|
45
|
+
'width' => 16,
|
46
|
+
'title' => 'Private IP',
|
47
|
+
},
|
48
|
+
'tags' => {
|
49
|
+
'width' => 30,
|
50
|
+
'title' => 'tags',
|
51
|
+
},
|
52
|
+
},
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
conf = File.join(ENV['HOME'], '.claws.yml')
|
57
|
+
puts "Creating configuration file: #{conf}\n..."
|
58
|
+
File.open(conf, 'w').write(h.to_yaml)
|
59
|
+
puts 'Complete!'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
module Claws
|
5
|
+
class ConfigurationError < StandardError; end
|
6
|
+
|
7
|
+
class Configuration
|
8
|
+
attr_accessor :path, :capistrano, :ssh, :aws, :ec2
|
9
|
+
|
10
|
+
def initialize(use_path = nil)
|
11
|
+
self.path = use_path || File.join(ENV['HOME'], '.claws.yml')
|
12
|
+
|
13
|
+
begin
|
14
|
+
yaml = YAML.load_file(path)
|
15
|
+
rescue Exception
|
16
|
+
raise ConfigurationError, "Unable to locate configuration file: #{self.path}"
|
17
|
+
end
|
18
|
+
|
19
|
+
self.capistrano = OpenStruct.new( yaml['capistrano'] )
|
20
|
+
self.ssh = OpenStruct.new( yaml['ssh'] )
|
21
|
+
self.aws = yaml['aws']
|
22
|
+
self.ec2 = OpenStruct.new( { :fields => yaml['ec2']['fields'] } )
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
module Claws
|
4
|
+
class Options
|
5
|
+
def self.parse
|
6
|
+
options = OpenStruct.new(
|
7
|
+
{
|
8
|
+
:connect => true,
|
9
|
+
:source => 'ec2',
|
10
|
+
:choice => nil,
|
11
|
+
}
|
12
|
+
)
|
13
|
+
|
14
|
+
OptionParser.new do |opts|
|
15
|
+
opts.banner = "Usage: script/aws [options] [environment] [role]"
|
16
|
+
|
17
|
+
opts.on('-d', '--display-only', 'display host information only and exit') do
|
18
|
+
options.connect = false
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on('-c', '--choice N', Float, 'enter the identity number of the host to automatically connect to') do |n|
|
22
|
+
options.choice = n.to_i
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on('-s', '--source', 'define the AWS source - default is ec2') do
|
26
|
+
options.source = 'elb'
|
27
|
+
options.connect = false
|
28
|
+
end
|
29
|
+
end.parse!
|
30
|
+
|
31
|
+
options.environment = ARGV.shift
|
32
|
+
options.role = ARGV.shift
|
33
|
+
|
34
|
+
options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'claws/capistrano'
|
2
|
+
require 'claws/support'
|
3
|
+
|
4
|
+
module Claws
|
5
|
+
module EC2
|
6
|
+
class Presenter
|
7
|
+
attr_writer :roles
|
8
|
+
|
9
|
+
def initialize(instance, has_roles = [])
|
10
|
+
@ec2 = instance.extend(Claws::Support)
|
11
|
+
@roles = has_roles
|
12
|
+
freeze
|
13
|
+
end
|
14
|
+
|
15
|
+
def roles
|
16
|
+
@roles.empty? ? 'N/A' : @roles.join(', ')
|
17
|
+
end
|
18
|
+
|
19
|
+
def tags
|
20
|
+
@ec2.try(:tags) ? @ec2.tags.select {|k,v| [k,v] unless k.downcase == 'name'}.map{|k,v| "#{k}: #{v}"}.join(', ') : 'N/A'
|
21
|
+
end
|
22
|
+
|
23
|
+
def security_groups
|
24
|
+
@ec2.try(:security_groups) ? @ec2.security_groups.map {|sg| "#{sg.id}: #{sg.name}"}.join(', ') : 'N/A'
|
25
|
+
end
|
26
|
+
|
27
|
+
def method_missing(meth)
|
28
|
+
case meth
|
29
|
+
when :name
|
30
|
+
@ec2.send(:tags)['Name'] || 'N/A'
|
31
|
+
when @ec2.try(:tags) && @ec2.tags.has_key?(meth)
|
32
|
+
@ec2.tags[meth] || 'N/A'
|
33
|
+
else
|
34
|
+
begin
|
35
|
+
@ec2.send(meth)
|
36
|
+
rescue Exception
|
37
|
+
'N/A'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'command_line_reporter'
|
2
|
+
|
3
|
+
module Claws
|
4
|
+
module Report
|
5
|
+
class EC2
|
6
|
+
attr_accessor :config, :instances
|
7
|
+
|
8
|
+
include CommandLineReporter
|
9
|
+
|
10
|
+
def initialize config, instances
|
11
|
+
self.config = config
|
12
|
+
self.instances = instances
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
table :border => true do
|
17
|
+
row :header => true do
|
18
|
+
column 'Choice', :width => 6, :color => 'blue', :bold => true, :align => 'right'
|
19
|
+
|
20
|
+
self.config.ec2.fields.each do |field, properties|
|
21
|
+
text = properties['title'] || field
|
22
|
+
width = properties['width'] || nil
|
23
|
+
column text, :width => width, :color => 'blue', :bold => true
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
choice = 0
|
28
|
+
|
29
|
+
self.instances.each do |i|
|
30
|
+
color = case i.status
|
31
|
+
when :running
|
32
|
+
'green'
|
33
|
+
when :stopped
|
34
|
+
'red'
|
35
|
+
else
|
36
|
+
'white'
|
37
|
+
end
|
38
|
+
|
39
|
+
row do
|
40
|
+
column choice
|
41
|
+
|
42
|
+
self.config.ec2.fields.each do |field, properties|
|
43
|
+
props = ( field == 'status' ) ? {:color => color} : {}
|
44
|
+
column i.send( field ), props
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
choice += 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'claws/capistrano'
|
3
|
+
|
4
|
+
describe Claws::Capistrano do
|
5
|
+
before :each do
|
6
|
+
@roles = {
|
7
|
+
:staging => [
|
8
|
+
%q{role :app, 'ec2-175-65-213-31.compute-1.amazonaws.com'},
|
9
|
+
%q{role :web, 'ec2-175-65-213-31.compute-1.amazonaws.com'},
|
10
|
+
%q{role :batch, "ec2-175-65-213-31.compute-1.amazonaws.com"},
|
11
|
+
%q{role :redis, "ec2-223-40-143-23.compute-1.amazonaws.com"},
|
12
|
+
%q{role :search, "ec2-147-32-151-54.compute-1.amazonaws.com"},
|
13
|
+
%q{role :search_slave, "ec2-147-32-151-54.compute-1.amazonaws.com"},
|
14
|
+
],
|
15
|
+
|
16
|
+
:production => [
|
17
|
+
%q{role :app, "ec2-263-56-231-91.compute-1.amazonaws.com", 'ec2-263-23-118-57.compute-1.amazonaws.com'},
|
18
|
+
%q{role :web, "ec2-263-56-231-91.compute-1.amazonaws.com", 'ec2-263-23-118-57.compute-1.amazonaws.com', "ec2-23-20-43-198.compute-1.amazonaws.com"},
|
19
|
+
%q{role :batch, "ec2-23-20-43-198.compute-1.amazonaws.com"},
|
20
|
+
%q{role :redis, "ec2-23-20-43-198.compute-1.amazonaws.com"},
|
21
|
+
%q{role :search, "ec2-107-21-131-545.compute-1.amazonaws.com"},
|
22
|
+
%q{role :search_slave, "ec2-263-23-144-120.compute-1.amazonaws.com"},
|
23
|
+
]
|
24
|
+
}
|
25
|
+
@mappings = {
|
26
|
+
:staging => {
|
27
|
+
'ec2-175-65-213-31.compute-1.amazonaws.com' => %w{app web batch},
|
28
|
+
'ec2-223-40-143-23.compute-1.amazonaws.com' => %w{redis},
|
29
|
+
'ec2-147-32-151-54.compute-1.amazonaws.com' => %w{search search_slave},
|
30
|
+
},
|
31
|
+
:production => {
|
32
|
+
'ec2-263-56-231-91.compute-1.amazonaws.com' => %w{app web},
|
33
|
+
'ec2-263-23-118-57.compute-1.amazonaws.com' => %w{app web},
|
34
|
+
'ec2-23-20-43-198.compute-1.amazonaws.com' => %w{web batch redis},
|
35
|
+
'ec2-107-21-131-545.compute-1.amazonaws.com' => %w{search},
|
36
|
+
'ec2-263-23-144-120.compute-1.amazonaws.com' => %w{search_slave},
|
37
|
+
},
|
38
|
+
}
|
39
|
+
|
40
|
+
@default_path = 'config/deploy'
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'defines roles hash per environment per host' do
|
44
|
+
it 'from default path' do
|
45
|
+
Dir.should_receive(:glob).and_return(%W{#{@default_path}/staging.rb #{@default_path}/production.rb})
|
46
|
+
File.should_receive(:readlines).with("#{@default_path}/staging.rb").and_return(@roles[:staging])
|
47
|
+
File.should_receive(:readlines).with("#{@default_path}/production.rb").and_return(@roles[:production])
|
48
|
+
|
49
|
+
cap = Claws::Capistrano.new
|
50
|
+
cap.home.should == @default_path
|
51
|
+
cap.all_host_roles.should == @mappings
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'from custom path' do
|
55
|
+
custom_path = '/home/app/config/deploy'
|
56
|
+
Dir.should_receive(:glob).and_return(%W{#{custom_path}/staging.rb #{custom_path}/production.rb})
|
57
|
+
File.should_receive(:readlines).with("#{custom_path}/staging.rb").and_return(@roles[:staging])
|
58
|
+
File.should_receive(:readlines).with("#{custom_path}/production.rb").and_return(@roles[:production])
|
59
|
+
|
60
|
+
cap = Claws::Capistrano.new(custom_path)
|
61
|
+
cap.home.should == custom_path
|
62
|
+
cap.all_host_roles.should == @mappings
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'returns roles for host' do
|
67
|
+
Dir.should_receive(:glob).and_return(%W{#{@default_path}/staging.rb #{@default_path}/production.rb})
|
68
|
+
File.should_receive(:readlines).with("#{@default_path}/staging.rb").and_return(@roles[:staging])
|
69
|
+
File.should_receive(:readlines).with("#{@default_path}/production.rb").and_return(@roles[:production])
|
70
|
+
|
71
|
+
cap = Claws::Capistrano.new
|
72
|
+
cap.roles('ec2-263-56-231-91.compute-1.amazonaws.com').should == %w{app web}
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'claws/collection/base'
|
3
|
+
require 'claws/configuration'
|
4
|
+
|
5
|
+
describe Claws::Collection::Base do
|
6
|
+
subject { Claws::Collection::Base }
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@yaml = {"capistrano_home"=>"test", "access_key_id"=>"asdf", "secret_access_key"=>"qwer"}
|
10
|
+
@credentials = {:access_key_id => 'asdf', :secret_access_key => 'qwer'}
|
11
|
+
|
12
|
+
@config = double('Claws::Configuration', :aws_credentials => @credentials)
|
13
|
+
AWS.should_receive(:config).with(@credentials).and_return(true)
|
14
|
+
AWS.should_receive(:start_memoizing).and_return(nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'establishes a connection to the mothership' do
|
18
|
+
expect {
|
19
|
+
subject.connect(@config.aws_credentials)
|
20
|
+
}.to_not raise_exception
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'builds a collection' do
|
24
|
+
subject.connect(@config.aws_credentials)
|
25
|
+
|
26
|
+
subject.build do |collection|
|
27
|
+
10.times {|i| collection << i}
|
28
|
+
end.should == (0..9).to_a
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'aws-sdk'
|
3
|
+
require 'claws/collection/ec2'
|
4
|
+
|
5
|
+
describe Claws::Collection::EC2 do
|
6
|
+
subject { Claws::Collection::EC2 }
|
7
|
+
|
8
|
+
it 'gets all instances' do
|
9
|
+
subject.should_receive(:get).with(no_args).and_return(
|
10
|
+
[
|
11
|
+
double('AWS::EC2::Instance'),
|
12
|
+
double('AWS::EC2::Instance'),
|
13
|
+
]
|
14
|
+
)
|
15
|
+
|
16
|
+
subject.get.size.should == 2
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Claws::Command::EC2 do
|
4
|
+
subject { Claws::Command::EC2 }
|
5
|
+
|
6
|
+
describe '#exec' do
|
7
|
+
context 'configuration files' do
|
8
|
+
let(:options) { OpenStruct.new( { :config_file => '/doesnotexist', } ) }
|
9
|
+
|
10
|
+
it 'missing files' do
|
11
|
+
subject.should_receive(:puts).twice
|
12
|
+
|
13
|
+
expect {
|
14
|
+
subject.exec options
|
15
|
+
}.should raise_exception SystemExit
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'invalid file' do
|
19
|
+
YAML.should_receive(:load_file).and_raise(Exception)
|
20
|
+
|
21
|
+
subject.should_receive(:puts).twice
|
22
|
+
|
23
|
+
expect {
|
24
|
+
subject.exec options
|
25
|
+
}.should raise_exception SystemExit
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'valid config file' do
|
30
|
+
before :each do
|
31
|
+
Claws::Configuration.stub(:new).and_return(
|
32
|
+
OpenStruct.new(
|
33
|
+
{
|
34
|
+
:ssh => OpenStruct.new(
|
35
|
+
{ :user => 'test' }
|
36
|
+
),
|
37
|
+
:ec2 => OpenStruct.new(
|
38
|
+
:fields => {
|
39
|
+
:id => {
|
40
|
+
:width => 10,
|
41
|
+
:title => 'ID',
|
42
|
+
}
|
43
|
+
}
|
44
|
+
)
|
45
|
+
}
|
46
|
+
)
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:options) { OpenStruct.new( { :config_file => nil, } ) }
|
51
|
+
|
52
|
+
context 'instance collections' do
|
53
|
+
|
54
|
+
it 'retrieves' do
|
55
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
56
|
+
Claws::Collection::EC2.should_receive(:get).and_return([])
|
57
|
+
|
58
|
+
capture_stdout {
|
59
|
+
subject.exec options
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'handles errors retrieving' do
|
64
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
65
|
+
Claws::Collection::EC2.should_receive(:get).and_raise(Exception)
|
66
|
+
subject.should_receive(:puts).once
|
67
|
+
|
68
|
+
expect {
|
69
|
+
subject.exec options
|
70
|
+
}.should raise_exception
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'performs report' do
|
75
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
76
|
+
Claws::Collection::EC2.should_receive(:get).and_return([])
|
77
|
+
|
78
|
+
expect {
|
79
|
+
capture_stdout {
|
80
|
+
subject.exec options
|
81
|
+
}
|
82
|
+
}.should_not raise_exception
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'connect options' do
|
87
|
+
let(:options) { OpenStruct.new( { :config_file => nil, :connect => true } ) }
|
88
|
+
|
89
|
+
before :each do
|
90
|
+
Claws::Configuration.stub(:new).and_return(
|
91
|
+
OpenStruct.new(
|
92
|
+
{
|
93
|
+
:ssh => OpenStruct.new(
|
94
|
+
{ :user => 'test' }
|
95
|
+
),
|
96
|
+
:ec2 => OpenStruct.new(
|
97
|
+
:fields => {
|
98
|
+
:id => {
|
99
|
+
:width => 10,
|
100
|
+
:title => 'ID',
|
101
|
+
}
|
102
|
+
}
|
103
|
+
)
|
104
|
+
}
|
105
|
+
)
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'single instance' do
|
110
|
+
let(:instances) do
|
111
|
+
[
|
112
|
+
double(AWS::EC2::Instance, :id => 'test', :status => 'running', :dns_name => 'test.com')
|
113
|
+
]
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'automatically connects to the server' do
|
117
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
118
|
+
Claws::Collection::EC2.should_receive(:get).and_return(instances)
|
119
|
+
|
120
|
+
subject.should_receive(:puts).twice
|
121
|
+
subject.should_receive(:system).with('ssh test@test.com').and_return(0)
|
122
|
+
|
123
|
+
capture_stdout {
|
124
|
+
subject.exec options
|
125
|
+
}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'multiple instances' do
|
130
|
+
let(:instances) do
|
131
|
+
[
|
132
|
+
double(AWS::EC2::Instance, :id => 'test1', :status => 'running', :dns_name => 'test1.com'),
|
133
|
+
double(AWS::EC2::Instance, :id => 'test2', :status => 'running', :dns_name => 'test2.com'),
|
134
|
+
double(AWS::EC2::Instance, :id => 'test3', :status => 'running', :dns_name => 'test3.com'),
|
135
|
+
]
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'handles user inputed selection from the command line' do
|
139
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
140
|
+
Claws::Collection::EC2.should_receive(:get).and_return(instances)
|
141
|
+
|
142
|
+
subject.should_receive(:puts).twice
|
143
|
+
subject.should_receive(:system).with('ssh test@test2.com').and_return(0)
|
144
|
+
|
145
|
+
capture_stdout {
|
146
|
+
subject.exec OpenStruct.new( {:selection => 1, :config_file => nil, :connect => true} )
|
147
|
+
}
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'presents a selection and connects to the server' do
|
152
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
153
|
+
Claws::Collection::EC2.should_receive(:get).and_return(instances)
|
154
|
+
|
155
|
+
subject.should_receive(:gets).and_return('1\n')
|
156
|
+
subject.should_receive(:puts).once
|
157
|
+
subject.should_receive(:system).with('ssh test@test2.com').and_return(0)
|
158
|
+
|
159
|
+
capture_stdout {
|
160
|
+
subject.exec options
|
161
|
+
}
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'presents a selection and allows a user to quit' do
|
165
|
+
Claws::Collection::EC2.should_receive(:connect).and_return(true)
|
166
|
+
Claws::Collection::EC2.should_receive(:get).and_return(instances)
|
167
|
+
|
168
|
+
subject.should_receive(:gets).and_return('q\n')
|
169
|
+
|
170
|
+
expect {
|
171
|
+
capture_stdout {
|
172
|
+
subject.exec options
|
173
|
+
}
|
174
|
+
}.should raise_exception SystemExit
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Claws::Command::Initialize do
|
4
|
+
subject { Claws::Command::Initialize }
|
5
|
+
|
6
|
+
let(:config) { 'test/.test.yml' }
|
7
|
+
|
8
|
+
it 'works' do
|
9
|
+
File.should_receive(:join).and_return(config)
|
10
|
+
subject.should_receive(:puts)
|
11
|
+
|
12
|
+
fh = double( File, :write => true )
|
13
|
+
|
14
|
+
File.should_receive(:open).with(config, 'w').and_return(fh)
|
15
|
+
subject.should_receive(:puts)
|
16
|
+
|
17
|
+
subject.exec
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'claws/configuration'
|
3
|
+
|
4
|
+
describe Claws::Configuration do
|
5
|
+
let (:yaml) do
|
6
|
+
{
|
7
|
+
'capistrano' => {
|
8
|
+
'home' => 'test',
|
9
|
+
},
|
10
|
+
'aws' => {
|
11
|
+
'access_key_id' => 'asdf',
|
12
|
+
'secret_access_key' => 'qwer',
|
13
|
+
'aws_user' => 'test',
|
14
|
+
},
|
15
|
+
'ec2' => {
|
16
|
+
'fields' => {
|
17
|
+
'id' => {
|
18
|
+
'width' => 10,
|
19
|
+
'title' => 'ID'
|
20
|
+
},
|
21
|
+
'name' => {
|
22
|
+
'width' => 20,
|
23
|
+
'title' => 'Name'
|
24
|
+
},
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
let (:config) { Claws::Configuration.new }
|
31
|
+
|
32
|
+
describe '#initialize' do
|
33
|
+
it 'defines default path' do
|
34
|
+
YAML.should_receive(:load_file).and_return( yaml )
|
35
|
+
c = Claws::Configuration.new
|
36
|
+
c.path.should == File.join(ENV['HOME'], '.claws.yml')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'defines a custom path' do
|
40
|
+
YAML.should_receive(:load_file).and_return( yaml )
|
41
|
+
c = Claws::Configuration.new '/home/test'
|
42
|
+
c.path.should == '/home/test'
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'raises ConfigurationError' do
|
46
|
+
YAML.should_receive(:load_file).and_raise( Exception.new )
|
47
|
+
|
48
|
+
expect {
|
49
|
+
Claws::Configuration.new
|
50
|
+
}.should raise_exception Claws::ConfigurationError
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'Capistrano' do
|
54
|
+
it 'defines home' do
|
55
|
+
YAML.should_receive(:load_file).and_return(yaml)
|
56
|
+
config.capistrano.home.should == 'test'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'AWS' do
|
61
|
+
before :each do
|
62
|
+
YAML.should_receive(:load_file).and_return(yaml)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'defines user' do
|
66
|
+
config.aws['aws_user'].should == 'test'
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'defines secret access key' do
|
70
|
+
config.aws['secret_access_key'].should == 'qwer'
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'defines access key id' do
|
74
|
+
config.aws['access_key_id'].should == 'asdf'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'EC2' do
|
79
|
+
before :each do
|
80
|
+
YAML.should_receive(:load_file).and_return(yaml)
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'fields' do
|
84
|
+
it 'defines id hash' do
|
85
|
+
id = config.ec2.fields['id']
|
86
|
+
id['width'].should == 10
|
87
|
+
id['title'].should == 'ID'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'defines name hash' do
|
91
|
+
name = config.ec2.fields['name']
|
92
|
+
name['width'].should == 20
|
93
|
+
name['title'].should == 'Name'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'claws/options'
|
3
|
+
|
4
|
+
ARGV.clear
|
5
|
+
|
6
|
+
def cli(args)
|
7
|
+
ARGV.push(*args)
|
8
|
+
yield
|
9
|
+
ARGV.clear
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Claws::Options do
|
13
|
+
it 'defines default options' do
|
14
|
+
cli %w{production app} do
|
15
|
+
options = Claws::Options.parse
|
16
|
+
options.connect.should be_true
|
17
|
+
options.source.should == 'ec2'
|
18
|
+
options.choice.should be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'accepts display only flag' do
|
23
|
+
# By default we want to connect to the instance
|
24
|
+
Claws::Options.parse.connect.should be_true
|
25
|
+
|
26
|
+
# Allow the user to override and just display information
|
27
|
+
cli %w{-d} do
|
28
|
+
Claws::Options.parse.connect.should be_false
|
29
|
+
end
|
30
|
+
|
31
|
+
cli %w{--display-only} do
|
32
|
+
Claws::Options.parse.connect.should be_false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'accepts a choice flag' do
|
37
|
+
cli %w{-c 10} do
|
38
|
+
Claws::Options.parse.choice.should == 10
|
39
|
+
end
|
40
|
+
|
41
|
+
cli %w{--choice 10} do
|
42
|
+
Claws::Options.parse.choice.should == 10
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'accepts a source flag' do
|
47
|
+
cli %w{-s elb} do
|
48
|
+
options = Claws::Options.parse
|
49
|
+
options.source.should == 'elb'
|
50
|
+
options.connect.should be_false
|
51
|
+
end
|
52
|
+
|
53
|
+
cli %w{--source elb} do
|
54
|
+
options = Claws::Options.parse
|
55
|
+
options.source.should == 'elb'
|
56
|
+
options.connect.should be_false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'capistrano' do
|
61
|
+
it 'defines the environment' do
|
62
|
+
cli %w{-s production app} do
|
63
|
+
Claws::Options.parse.environment.should == 'production'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'defines the role' do
|
68
|
+
cli %w{-s production app} do
|
69
|
+
Claws::Options.parse.role.should == 'app'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'aws-sdk'
|
3
|
+
require 'claws/presenter/ec2'
|
4
|
+
require 'claws/capistrano'
|
5
|
+
|
6
|
+
describe Claws::EC2::Presenter do
|
7
|
+
subject { Claws::EC2::Presenter }
|
8
|
+
|
9
|
+
before :each do
|
10
|
+
host = 'ec2-263-56-231-91.compute-1.amazonaws.com'
|
11
|
+
|
12
|
+
full_instance = double('AWS::EC2',
|
13
|
+
:public_dns => host,
|
14
|
+
:security_groups => [
|
15
|
+
double(AWS::EC2::SecurityGroup, :name => 'search', :id => 'sg-0f0f0f0f'),
|
16
|
+
double(AWS::EC2::SecurityGroup, :name => 'mongo', :id => 'sg-0d0d0d0d'),
|
17
|
+
double(AWS::EC2::SecurityGroup, :name => 'app', :id => 'sg-0c0c0c0c'),
|
18
|
+
],
|
19
|
+
:tags => double(AWS::EC2::ResourceTagCollection, :select => [
|
20
|
+
['environment', 'production'],
|
21
|
+
['function', 'master'],
|
22
|
+
],
|
23
|
+
'has_key?'.to_sym => true
|
24
|
+
),
|
25
|
+
:elastic_ip => '11.111.111.111'
|
26
|
+
)
|
27
|
+
|
28
|
+
cap = double('Claws::Capistrano')
|
29
|
+
cap.stub(:roles).with(host).and_return(%w{app web})
|
30
|
+
|
31
|
+
@full_presenter = subject.new(full_instance, cap.roles(full_instance.public_dns))
|
32
|
+
|
33
|
+
less_instance = double(AWS::EC2, :tags => nil)
|
34
|
+
@less_presenter = subject.new(less_instance)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#initialize' do
|
38
|
+
it 'requires a valid ec2 instance' do
|
39
|
+
expect {
|
40
|
+
subject.new
|
41
|
+
}.to raise_error =~ /ArgumentError/
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#roles' do
|
46
|
+
it 'can be defined' do
|
47
|
+
@full_presenter.roles.should == 'app, web'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'are not required' do
|
51
|
+
@less_presenter.roles.should == 'N/A'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#tags' do
|
56
|
+
it 'present a string summary' do
|
57
|
+
@full_presenter.tags.should == 'environment: production, function: master'
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'are not required' do
|
61
|
+
@less_presenter.tags.should == 'N/A'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#security_groups' do
|
66
|
+
it 'presents summary of names' do
|
67
|
+
@full_presenter.security_groups.should == 'sg-0f0f0f0f: search, sg-0d0d0d0d: mongo, sg-0c0c0c0c: app'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'are not required' do
|
71
|
+
@less_presenter.security_groups.should == 'N/A'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#public_dns' do
|
76
|
+
it 'displays when available' do
|
77
|
+
@full_presenter.public_dns.should == 'ec2-263-56-231-91.compute-1.amazonaws.com'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'is not required' do
|
81
|
+
@less_presenter.public_dns.should == 'N/A'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#elastic_ip' do
|
86
|
+
it 'displays when available' do
|
87
|
+
@full_presenter.elastic_ip.should == '11.111.111.111'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'is not required' do
|
91
|
+
@less_presenter.elastic_ip.should == 'N/A'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'claws/support'
|
3
|
+
|
4
|
+
describe Claws::Support do
|
5
|
+
subject { Array.new }
|
6
|
+
|
7
|
+
describe '#try' do
|
8
|
+
it 'handles undefined methods sanely' do
|
9
|
+
subject.try('asdf').should be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'performs defined methods' do
|
13
|
+
subject.try('push', 2)
|
14
|
+
subject.should == [2]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: claws
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wes
|
9
|
+
- Bailey
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-05-24 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bundler
|
17
|
+
requirement: &2156422520 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.0.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2156422520
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: command_line_reporter
|
28
|
+
requirement: &2156421940 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *2156421940
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: aws-sdk
|
39
|
+
requirement: &2156420960 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '1.0'
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *2156420960
|
48
|
+
description: A command line tool that provides a configurable report on the status
|
49
|
+
of all of your EC2 hosts and provides trivial ssh access for connectivity. Never
|
50
|
+
copy and paste the public dns for a host again!
|
51
|
+
email: baywes@gmail.com
|
52
|
+
executables:
|
53
|
+
- claws
|
54
|
+
extensions: []
|
55
|
+
extra_rdoc_files: []
|
56
|
+
files:
|
57
|
+
- lib/claws/capistrano.rb
|
58
|
+
- lib/claws/collection/base.rb
|
59
|
+
- lib/claws/collection/ec2.rb
|
60
|
+
- lib/claws/command/ec2.rb
|
61
|
+
- lib/claws/command/initialize.rb
|
62
|
+
- lib/claws/configuration.rb
|
63
|
+
- lib/claws/options.rb
|
64
|
+
- lib/claws/presenter/ec2.rb
|
65
|
+
- lib/claws/report/ec2.rb
|
66
|
+
- lib/claws/support.rb
|
67
|
+
- lib/claws/version.rb
|
68
|
+
- lib/claws.rb
|
69
|
+
- README.md
|
70
|
+
- spec/base_spec.rb
|
71
|
+
- spec/capistrano_spec.rb
|
72
|
+
- spec/collection/base_spec.rb
|
73
|
+
- spec/collection/ec2_spec.rb
|
74
|
+
- spec/command/ec2_spec.rb
|
75
|
+
- spec/command/initialize_spec.rb
|
76
|
+
- spec/configuration_spec.rb
|
77
|
+
- spec/options_spec.rb
|
78
|
+
- spec/presenter/ec2_spec.rb
|
79
|
+
- spec/spec_helper.rb
|
80
|
+
- spec/support/helpers/stdout_helper.rb
|
81
|
+
- spec/support_spec.rb
|
82
|
+
- !binary |-
|
83
|
+
YmluL2NsYXdz
|
84
|
+
homepage: http://github.com/wbailey/claws
|
85
|
+
licenses: []
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options: []
|
88
|
+
require_paths:
|
89
|
+
- lib
|
90
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.8.15
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: A Command Line Tool For Amazon Web Services
|
108
|
+
test_files:
|
109
|
+
- spec/base_spec.rb
|
110
|
+
- spec/capistrano_spec.rb
|
111
|
+
- spec/collection/base_spec.rb
|
112
|
+
- spec/collection/ec2_spec.rb
|
113
|
+
- spec/command/ec2_spec.rb
|
114
|
+
- spec/command/initialize_spec.rb
|
115
|
+
- spec/configuration_spec.rb
|
116
|
+
- spec/options_spec.rb
|
117
|
+
- spec/presenter/ec2_spec.rb
|
118
|
+
- spec/spec_helper.rb
|
119
|
+
- spec/support/helpers/stdout_helper.rb
|
120
|
+
- spec/support_spec.rb
|