kumo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/kumo +135 -0
- data/lib/kumo/commands.rb +125 -0
- data/lib/kumo/config.rb +67 -0
- data/lib/kumo/server.rb +112 -0
- data/lib/kumo/version.rb +3 -0
- data/lib/kumo.rb +13 -0
- metadata +135 -0
data/bin/kumo
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gli'
|
3
|
+
require 'kumo'
|
4
|
+
require 'kumo/commands'
|
5
|
+
|
6
|
+
include GLI::App
|
7
|
+
version Kumo::VERSION
|
8
|
+
|
9
|
+
if ARGV[0] == '--version'
|
10
|
+
puts Kumo::VERSION
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
|
14
|
+
program_desc 'Manage workspaces in EC2'
|
15
|
+
|
16
|
+
desc 'config file path'
|
17
|
+
arg_name 'PATH'
|
18
|
+
default_value '~/.kumorc'
|
19
|
+
flag [:c, :'config-file']
|
20
|
+
|
21
|
+
desc 'List instances in a set'
|
22
|
+
command :list do |c|
|
23
|
+
c.desc 'keypair'
|
24
|
+
c.flag [:keypair]
|
25
|
+
c.desc 'region'
|
26
|
+
c.flag [:region]
|
27
|
+
c.desc 'type id'
|
28
|
+
c.flag [:'type-id']
|
29
|
+
c.desc 'AMI'
|
30
|
+
c.flag [:'image-id']
|
31
|
+
c.desc 'name tag'
|
32
|
+
c.flag [:t, :tag]
|
33
|
+
c.desc 'configuration sets'
|
34
|
+
c.arg_name 'SET1,SET2,...'
|
35
|
+
c.flag [:s, :sets]
|
36
|
+
c.action do |global_options, options, args|
|
37
|
+
Kumo::Commands.list(global_options, options, args)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Launch an instance'
|
42
|
+
command :launch do |c|
|
43
|
+
c.desc 'keypair'
|
44
|
+
c.flag [:keypair]
|
45
|
+
c.desc 'region'
|
46
|
+
c.flag [:region]
|
47
|
+
c.desc 'type id'
|
48
|
+
c.flag [:'type-id']
|
49
|
+
c.desc 'AMI'
|
50
|
+
c.flag [:'image-id']
|
51
|
+
c.desc 'name tag'
|
52
|
+
c.flag [:t, :tag]
|
53
|
+
c.desc 'configuration sets'
|
54
|
+
c.arg_name 'SET1,SET2,...'
|
55
|
+
c.flag [:s, :sets]
|
56
|
+
c.desc 'security groups'
|
57
|
+
c.arg_name 'GROUP1,GROUP2,...'
|
58
|
+
c.flag [:g, :groups]
|
59
|
+
c.action do |global_options, options, args|
|
60
|
+
Kumo::Commands.launch(global_options, options, args)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
desc 'Terminate an instance'
|
65
|
+
arg_name '[INSTANCE_ID]'
|
66
|
+
command :terminate do |c|
|
67
|
+
c.desc 'region'
|
68
|
+
c.flag [:region]
|
69
|
+
c.desc 'name tag'
|
70
|
+
c.flag [:t, :tag]
|
71
|
+
c.desc 'configuration sets'
|
72
|
+
c.arg_name 'SET1,SET2,...'
|
73
|
+
c.flag [:s, :sets]
|
74
|
+
c.action do |global_options,options,args|
|
75
|
+
Kumo::Commands.terminate(global_options, options, args)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
desc 'Start an instance'
|
80
|
+
arg_name '[INSTANCE_ID]'
|
81
|
+
command :start do |c|
|
82
|
+
c.desc 'region'
|
83
|
+
c.flag [:region]
|
84
|
+
c.desc 'name tag'
|
85
|
+
c.flag [:t, :tag]
|
86
|
+
c.desc 'configuration sets'
|
87
|
+
c.arg_name 'SET1,SET2,...'
|
88
|
+
c.flag [:s, :sets]
|
89
|
+
c.action do |global_options, options, args|
|
90
|
+
Kumo::Commands.start(global_options, options, args)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
desc 'Stop an instance'
|
95
|
+
arg_name '[INSTANCE_ID]'
|
96
|
+
command :stop do |c|
|
97
|
+
c.desc 'region'
|
98
|
+
c.flag [:region]
|
99
|
+
c.desc 'name tag'
|
100
|
+
c.flag [:t, :tag]
|
101
|
+
c.desc 'configuration sets'
|
102
|
+
c.arg_name 'SET1,SET2,...'
|
103
|
+
c.flag [:s, :sets]
|
104
|
+
c.action do |global_options, options, args|
|
105
|
+
Kumo::Commands.stop(global_options, options, args)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
desc 'DNS of an instance'
|
110
|
+
arg_name '[INSTANCE_ID]'
|
111
|
+
command :dns do |c|
|
112
|
+
c.desc 'region'
|
113
|
+
c.flag [:region]
|
114
|
+
c.desc 'name tag'
|
115
|
+
c.flag [:t, :tag]
|
116
|
+
c.desc 'configuration sets'
|
117
|
+
c.arg_name 'SET1,SET2,...'
|
118
|
+
c.flag [:s, :sets]
|
119
|
+
c.action do |global_options, options, args|
|
120
|
+
Kumo::Commands.dns(global_options, options, args)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
pre do |global, command, options, args|
|
125
|
+
true
|
126
|
+
end
|
127
|
+
|
128
|
+
post do |global, command, options, args|
|
129
|
+
end
|
130
|
+
|
131
|
+
on_error do |exception|
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
exit run(ARGV)
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module Kumo
|
2
|
+
# Commands for managing instances
|
3
|
+
class Commands
|
4
|
+
class << self
|
5
|
+
# List all instances with the same tag
|
6
|
+
#
|
7
|
+
# Example:
|
8
|
+
#
|
9
|
+
# kumo list
|
10
|
+
def list(global_options, options, args)
|
11
|
+
Kumo.initialize_config(File.expand_path(global_options[:'config-file']), sanitize_options(options), parse_sets(options))
|
12
|
+
Kumo::Server.find_all.each { |server| puts "%-15s%-15s%-15s%-30s%-45s" % [server.id, server.tag, server.state, server.launch_time.localtime, server.public_dns] }
|
13
|
+
end
|
14
|
+
|
15
|
+
# Launch an instance
|
16
|
+
#
|
17
|
+
# Examples:
|
18
|
+
#
|
19
|
+
# kumo launch
|
20
|
+
def launch(global_options, options, args)
|
21
|
+
Kumo.initialize_config(File.expand_path(global_options[:'config-file']), sanitize_options(options), parse_sets(options))
|
22
|
+
puts Kumo::Server.launch.id
|
23
|
+
end
|
24
|
+
|
25
|
+
# Terminate an instance
|
26
|
+
#
|
27
|
+
# Examples:
|
28
|
+
#
|
29
|
+
# kumo terminate
|
30
|
+
def terminate(global_options, options, args)
|
31
|
+
Kumo.initialize_config(File.expand_path(global_options[:'config-file']), sanitize_options(options))
|
32
|
+
if args[0]
|
33
|
+
Kumo::Server.find_by_id(args[0]).terminate
|
34
|
+
else
|
35
|
+
last_server.terminate
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Start an instance
|
40
|
+
#
|
41
|
+
# Examples:
|
42
|
+
#
|
43
|
+
# kumo start
|
44
|
+
def start(global_options, options, args)
|
45
|
+
Kumo.initialize_config(File.expand_path(global_options[:'config-file']), sanitize_options(options))
|
46
|
+
if args[0]
|
47
|
+
Kumo::Server.find_by_id(args[0]).start
|
48
|
+
else
|
49
|
+
last_server.start
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Stop an instance
|
54
|
+
#
|
55
|
+
# Examples:
|
56
|
+
#
|
57
|
+
# kumo stop
|
58
|
+
def stop(global_options, options, args)
|
59
|
+
Kumo.initialize_config(File.expand_path(global_options[:'config-file']), sanitize_options(options))
|
60
|
+
if args[0]
|
61
|
+
Kumo::Server.find_by_id(args[0]).stop
|
62
|
+
else
|
63
|
+
last_server.stop
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Print the public DNS of an instance
|
68
|
+
#
|
69
|
+
# Examples:
|
70
|
+
#
|
71
|
+
# kumo dns
|
72
|
+
def dns(global_options, options, args)
|
73
|
+
Kumo.initialize_config(File.expand_path(global_options[:'config-file']), sanitize_options(options))
|
74
|
+
if args[0]
|
75
|
+
puts Kumo::Server.find_by_id(args[0]).public_dns
|
76
|
+
else
|
77
|
+
puts last_server.public_dns
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
# Parse the sets
|
84
|
+
def parse_sets(options)
|
85
|
+
if options[:sets]
|
86
|
+
options[:sets].split(',').map { |s| s.to_sym }
|
87
|
+
else
|
88
|
+
[]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Parse the groups
|
93
|
+
#
|
94
|
+
# +groups_string+:: a string containing a list of comma separated groups
|
95
|
+
#
|
96
|
+
# Returns an +array+ of +symbols+
|
97
|
+
def parse_groups(groups_string)
|
98
|
+
groups_string.split(',').map { |g| g.to_sym }
|
99
|
+
end
|
100
|
+
|
101
|
+
# Sanitize the options, keeping only those that are defined
|
102
|
+
#
|
103
|
+
# +options+:: configuration options
|
104
|
+
#
|
105
|
+
# Returns a +hash+ suitable to initialize the main configuration
|
106
|
+
def sanitize_options(options)
|
107
|
+
sanitized = {}
|
108
|
+
[:keypair, :region, :'type-id', :tag].each do |o|
|
109
|
+
sanitized[o] = options[o] unless options[o].nil?
|
110
|
+
end
|
111
|
+
|
112
|
+
unless options[:groups].nil?
|
113
|
+
sanitized[:groups] = parse_groups(options[:groups])
|
114
|
+
end
|
115
|
+
|
116
|
+
sanitized
|
117
|
+
end
|
118
|
+
|
119
|
+
# Returns the last server that was launched/started
|
120
|
+
def last_server
|
121
|
+
Kumo::Server.find_all.last
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/kumo/config.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Kumo
|
4
|
+
# Configuration for EC2
|
5
|
+
class Config
|
6
|
+
attr_reader :config
|
7
|
+
|
8
|
+
# New configuration
|
9
|
+
#
|
10
|
+
# +config_file_path+:: configuration file path (YAML)
|
11
|
+
# +options+:: instance options
|
12
|
+
# +sets+:: configuration sets (applied in order)
|
13
|
+
def initialize(config_file_path, options = {}, sets = [])
|
14
|
+
set_default_config
|
15
|
+
merge_config_file(config_file_path, sets)
|
16
|
+
merge_extra_config(options)
|
17
|
+
validate_config
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Validate the configuration
|
23
|
+
def validate_config
|
24
|
+
if @config[:'access-key-id'].nil? || @config[:'secret-access-key'].nil?
|
25
|
+
raise Exception, 'AWS "access key id" and "secret access key" must be included in the configuration file'
|
26
|
+
elsif @config[:keypair].nil?
|
27
|
+
raise Exception, 'AWS "keypair" is missing'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Sets the default configuration. This is the base configuration,
|
32
|
+
# which will be merged with other configurations later.
|
33
|
+
def set_default_config
|
34
|
+
@config = {
|
35
|
+
:region => 'us-east-1',
|
36
|
+
:'type-id' => 't1.micro',
|
37
|
+
:'image-id' => 'ami-a29943cb', # Ubuntu 12.04
|
38
|
+
:groups => ['kumo'],
|
39
|
+
:tag => 'kumo'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# Merge the configuration file, overriding the previous configuration
|
44
|
+
def merge_config_file(config_file_path, sets)
|
45
|
+
begin
|
46
|
+
config_file = YAML.load_file(config_file_path)
|
47
|
+
rescue
|
48
|
+
raise Exception, "Could not load config file: " + config_file_path
|
49
|
+
end
|
50
|
+
|
51
|
+
sets.unshift :default
|
52
|
+
sets.each do |set|
|
53
|
+
begin
|
54
|
+
@config.merge!(config_file[:sets][set])
|
55
|
+
rescue
|
56
|
+
raise Exception, "The set '" + set.to_s + "' was not found"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Merge the extra configuration, overriding the previous configuration
|
62
|
+
def merge_extra_config(options)
|
63
|
+
options[:groups] = @config[:groups] if options[:groups] && options[:groups].empty?
|
64
|
+
@config.merge!(options)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/kumo/server.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'fog'
|
2
|
+
|
3
|
+
module Kumo
|
4
|
+
# The server is an EC2 instance
|
5
|
+
class Server
|
6
|
+
include Comparable
|
7
|
+
|
8
|
+
# Find an instance by id
|
9
|
+
#
|
10
|
+
# +id+:: the id of the instance
|
11
|
+
def self.find_by_id(id)
|
12
|
+
Server.new(infra.servers.get(id))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Find all instances
|
16
|
+
def self.find_all
|
17
|
+
infra.servers.select do |server|
|
18
|
+
(server.tags["Name"] == Kumo.config[:tag]) && (server.state != "terminated")
|
19
|
+
end.map do |server|
|
20
|
+
Server.new(server)
|
21
|
+
end.sort
|
22
|
+
end
|
23
|
+
|
24
|
+
# Launch an instance
|
25
|
+
def self.launch
|
26
|
+
Server.new(infra.servers.create(
|
27
|
+
:image_id => Kumo.config[:'image-id'],
|
28
|
+
:flavor_id => Kumo.config[:'type-id'],
|
29
|
+
:key_name => Kumo.config[:keypair],
|
30
|
+
:groups => Kumo.config[:groups],
|
31
|
+
:tags => { 'Name' => Kumo.config[:tag] }
|
32
|
+
))
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create a new instance based on a fog server
|
36
|
+
def initialize(fog_server)
|
37
|
+
@server = fog_server
|
38
|
+
end
|
39
|
+
|
40
|
+
# Get the ID of the instance
|
41
|
+
def id
|
42
|
+
@server.id
|
43
|
+
end
|
44
|
+
|
45
|
+
# Get the launch time of the instance
|
46
|
+
def launch_time
|
47
|
+
@server.created_at
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get the running state of the instance
|
51
|
+
def state
|
52
|
+
@server.state
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the tag of the instance
|
56
|
+
def tag
|
57
|
+
@server.tags['Name']
|
58
|
+
end
|
59
|
+
|
60
|
+
# Get the public DNS of the instance
|
61
|
+
def public_dns
|
62
|
+
@server.dns_name
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get the private DNS of the instance
|
66
|
+
def private_dns
|
67
|
+
@server.private_dns_name
|
68
|
+
end
|
69
|
+
|
70
|
+
# Terminate the instance
|
71
|
+
def terminate
|
72
|
+
@server.destroy
|
73
|
+
end
|
74
|
+
|
75
|
+
# Start the instance
|
76
|
+
def start
|
77
|
+
if @server.state == "stopped"
|
78
|
+
@server.start
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Stop the instance
|
83
|
+
def stop
|
84
|
+
if @server.state == "running"
|
85
|
+
@server.stop
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# :nodoc:
|
90
|
+
def <=>(other_server)
|
91
|
+
if self.launch_time < other_server.launch_time
|
92
|
+
-1
|
93
|
+
elsif self.launch_time > other_server.launch_time
|
94
|
+
1
|
95
|
+
else
|
96
|
+
0
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
# The connection to EC2
|
103
|
+
def self.infra
|
104
|
+
@fog ||= Fog::Compute.new(
|
105
|
+
:provider => 'AWS',
|
106
|
+
:region => Kumo.config[:region],
|
107
|
+
:aws_access_key_id => Kumo.config[:'access-key-id'],
|
108
|
+
:aws_secret_access_key => Kumo.config[:'secret-access-key']
|
109
|
+
)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
data/lib/kumo/version.rb
ADDED
data/lib/kumo.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'kumo/version'
|
2
|
+
|
3
|
+
require 'kumo/config'
|
4
|
+
require 'kumo/server'
|
5
|
+
|
6
|
+
module Kumo
|
7
|
+
def self.config
|
8
|
+
@config
|
9
|
+
end
|
10
|
+
def self.initialize_config(file_path, options = {}, sets = [])
|
11
|
+
@config = Config.new(file_path, options, sets).config
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kumo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael V. O'Brien
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rdoc
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: debugger
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: gli
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 2.0.0
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 2.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: fog
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :runtime
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description:
|
95
|
+
email: michael@michaelvobrien.com
|
96
|
+
executables:
|
97
|
+
- kumo
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- bin/kumo
|
102
|
+
- lib/kumo/commands.rb
|
103
|
+
- lib/kumo/config.rb
|
104
|
+
- lib/kumo/server.rb
|
105
|
+
- lib/kumo/version.rb
|
106
|
+
- lib/kumo.rb
|
107
|
+
homepage: https://github.com/notbrien/kumo
|
108
|
+
licenses: []
|
109
|
+
post_install_message:
|
110
|
+
rdoc_options:
|
111
|
+
- --title
|
112
|
+
- kumo
|
113
|
+
- -ri
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
- lib
|
117
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ! '>='
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '0'
|
123
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
|
+
none: false
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
requirements: []
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 1.8.23
|
132
|
+
signing_key:
|
133
|
+
specification_version: 3
|
134
|
+
summary: Manage workspaces in EC2
|
135
|
+
test_files: []
|