virtualmaster 0.0.3
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 +6 -0
- data/Gemfile +4 -0
- data/README.mdown +55 -0
- data/Rakefile +1 -0
- data/bin/virtualmaster +22 -0
- data/lib/vmaster.rb +9 -0
- data/lib/vmaster/cli.rb +32 -0
- data/lib/vmaster/config_command.rb +50 -0
- data/lib/vmaster/helpers.rb +71 -0
- data/lib/vmaster/server_commands.rb +163 -0
- data/lib/vmaster/version.rb +3 -0
- data/spec/commands_spec.rb +17 -0
- data/spec/spec_helper.rb +13 -0
- data/virtualmaster.gemspec +31 -0
- metadata +117 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.mdown
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# VirtualMaster command line interface
|
2
|
+
|
3
|
+
Proof of concept of VirtualMaster command line interface
|
4
|
+
|
5
|
+
# virtualmaster config
|
6
|
+
Running virtualmaster for first time.
|
7
|
+
Setting up environment.
|
8
|
+
|
9
|
+
Your API credentials are available from http://www.virtualmaster.cz/en/api#settings
|
10
|
+
|
11
|
+
Enter your API username:
|
12
|
+
Enter your API password:
|
13
|
+
|
14
|
+
Settings stored within ~/.virtualmaster
|
15
|
+
|
16
|
+
# virtualmaster create demo1 --image lucid
|
17
|
+
Using image 'lucid' with id (999).
|
18
|
+
Creating 'micro' instance (512 MB memory/5 GB storage).
|
19
|
+
Instance launch request accepted (instance id 44444).
|
20
|
+
|
21
|
+
Default password 'AdVc:PBi8&7L'.
|
22
|
+
|
23
|
+
# virtualmaster instances
|
24
|
+
+-------+---------+----------------+
|
25
|
+
| name | state | ip_address |
|
26
|
+
+-------+---------+----------------+
|
27
|
+
| demo1 | RUNNING | 195.140.253.88 |
|
28
|
+
+-------+---------+----------------+
|
29
|
+
|
30
|
+
## Install
|
31
|
+
|
32
|
+
The current version of `virtualmaster` command line interface should work with Ruby 1.8.7+.
|
33
|
+
|
34
|
+
## Automatically install SSH keys
|
35
|
+
|
36
|
+
VirtualMaster CLI can install your SSH keys to a remote machine automatically using `--copy-id` switch.
|
37
|
+
|
38
|
+
|
39
|
+
virtualmaster create demo1 --image ubuntu_lucid --copy-id
|
40
|
+
Using image 'ubuntu_lucid' with ID 124
|
41
|
+
Creating 'micro' instance (512 MB memory/10 GB storage)
|
42
|
+
Instance launch request accepted. Instance ID 45387
|
43
|
+
|
44
|
+
Default password 'vBK7i!kK'
|
45
|
+
Waiting for instance............
|
46
|
+
Loading identity file
|
47
|
+
|
48
|
+
Instance ready!
|
49
|
+
Try to login using `ssh root@195.140.253.130'
|
50
|
+
|
51
|
+
If you want to specify other key (ie. not ~/.ssh/id_rsa) use option `--identity IDENTITY_FILE`.
|
52
|
+
|
53
|
+
## More information
|
54
|
+
|
55
|
+
Additional topics are available in [the wiki](https://github.com/Virtualmaster/virtualmaster-cli/wiki).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/virtualmaster
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'vmaster'
|
5
|
+
rescue LoadError
|
6
|
+
vmaster_path = File.expand_path('../../lib', __FILE__)
|
7
|
+
|
8
|
+
$:.unshift(vmaster_path)
|
9
|
+
|
10
|
+
require 'vmaster'
|
11
|
+
end
|
12
|
+
|
13
|
+
program :name, "virtualmaster"
|
14
|
+
program :version, VirtualMaster::VERSION
|
15
|
+
program :description, "VirtualMaster command line interface"
|
16
|
+
program :help_formatter, :compact
|
17
|
+
|
18
|
+
default_command :help
|
19
|
+
|
20
|
+
VirtualMaster::CLI.run do
|
21
|
+
end
|
22
|
+
|
data/lib/vmaster.rb
ADDED
data/lib/vmaster/cli.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'deltacloud'
|
3
|
+
|
4
|
+
module VirtualMaster
|
5
|
+
class CLI
|
6
|
+
@@api = nil
|
7
|
+
@@config = nil
|
8
|
+
|
9
|
+
def self.run
|
10
|
+
# load config
|
11
|
+
config_file = File.join(ENV["HOME"], ".virtualmaster")
|
12
|
+
if File.exists? config_file
|
13
|
+
config = YAML::load(File.open(config_file))
|
14
|
+
|
15
|
+
@@config = config.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
16
|
+
|
17
|
+
@@api = DeltaCloud.new(@@config[:username], @@config[:password], VirtualMaster::DEFAULT_URL)
|
18
|
+
end
|
19
|
+
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.api
|
24
|
+
abort "No configuration available! Please run 'virtualmaster config' first!" unless @@api
|
25
|
+
@@api
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.config
|
29
|
+
@@config
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
|
4
|
+
command :config do |c|
|
5
|
+
c.description = "Configure VirtualMaster API username and password"
|
6
|
+
|
7
|
+
c.option '--username NAME', String, 'API username'
|
8
|
+
c.option '--password PASSWD', String, 'API password'
|
9
|
+
|
10
|
+
c.action do |args, options|
|
11
|
+
config_file = File.join(ENV['HOME'], VirtualMaster::CONFIG_FILE)
|
12
|
+
if File.exists?(config_file)
|
13
|
+
abort "Default configuration file already exists: #{config_file}"
|
14
|
+
else
|
15
|
+
say "Running virtualmaster for first time"
|
16
|
+
end
|
17
|
+
|
18
|
+
unless options.username && options.password
|
19
|
+
say "\n"
|
20
|
+
say "Your API credentials are available from http://www.virtualmaster.cz/en/api#settings"
|
21
|
+
say "\n"
|
22
|
+
end
|
23
|
+
|
24
|
+
options.username = ask("Enter API username:") unless options.username
|
25
|
+
options.password = password("Enter API password:", "*") unless options.password
|
26
|
+
|
27
|
+
# verify and store credentials
|
28
|
+
begin
|
29
|
+
api = DeltaCloud.new(options.username, options.password, VirtualMaster::DEFAULT_URL)
|
30
|
+
|
31
|
+
config = {
|
32
|
+
'username' => options.username,
|
33
|
+
'password' => options.password,
|
34
|
+
'default_image' => VirtualMaster::DEFAULT_IMAGE,
|
35
|
+
'images' => VirtualMaster::IMAGES
|
36
|
+
}
|
37
|
+
|
38
|
+
File.open(config_file, 'w') do |f|
|
39
|
+
f.puts YAML.dump(config)
|
40
|
+
end
|
41
|
+
|
42
|
+
say "Setting stored under #{config_file}"
|
43
|
+
rescue DeltaCloud::API::BackendError => e
|
44
|
+
say "Unable to connect to VirtualMaster API: #{e.message}"
|
45
|
+
rescue Exception => e
|
46
|
+
say "Unable to configure environment: #{e.message}"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module VirtualMaster
|
2
|
+
|
3
|
+
CONFIG_FILE = ".virtualmaster"
|
4
|
+
DEFAULT_URL = "https://www.virtualmaster.cz/services/deltacloud"
|
5
|
+
|
6
|
+
DEFAULT_IMAGE = 124
|
7
|
+
DEFAULT_PROFILE = "micro"
|
8
|
+
|
9
|
+
# pre-defined list of images
|
10
|
+
IMAGES = {
|
11
|
+
:ubuntu_lucid => 124,
|
12
|
+
:debian_squeeze => 1741,
|
13
|
+
:centos_6 => 1743
|
14
|
+
}
|
15
|
+
|
16
|
+
PROFILES = {
|
17
|
+
:nano => {
|
18
|
+
:memory => 256,
|
19
|
+
:storage => 3840
|
20
|
+
},
|
21
|
+
:micro => {
|
22
|
+
:memory => 512,
|
23
|
+
:storage => 6144
|
24
|
+
},
|
25
|
+
:milli => {
|
26
|
+
:memory => 1024,
|
27
|
+
:storage => 20480,
|
28
|
+
},
|
29
|
+
:small => {
|
30
|
+
:memory => 2048,
|
31
|
+
:storage => 30720
|
32
|
+
},
|
33
|
+
:medium => {
|
34
|
+
:memory => 4096,
|
35
|
+
:storage => 40960
|
36
|
+
}
|
37
|
+
#:large => {
|
38
|
+
# :memory => 8192,
|
39
|
+
# :storage => 8192
|
40
|
+
#}
|
41
|
+
}
|
42
|
+
|
43
|
+
|
44
|
+
module Helpers
|
45
|
+
def self.get_instances
|
46
|
+
VirtualMaster::CLI.api.instances
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.get_instance(name)
|
50
|
+
get_instances.each do |instance|
|
51
|
+
return instance if instance.name == name
|
52
|
+
end
|
53
|
+
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.get_hw_profile(memory, storage)
|
58
|
+
api = VirtualMaster::CLI.api
|
59
|
+
|
60
|
+
profile_list = api.hardware_profiles.reject { |p| p.memory.value.to_i != memory && p.storage.value.to_i != storage }
|
61
|
+
|
62
|
+
profile_list.first
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.create_instance(name, image_id, profile_id)
|
66
|
+
api = VirtualMaster::CLI.api
|
67
|
+
|
68
|
+
api.create_instance(image_id, :name => name, :hwp_id => profile_id)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'terminal-table'
|
2
|
+
require 'net/ssh'
|
3
|
+
require 'logger'
|
4
|
+
require "base64"
|
5
|
+
require 'openssl'
|
6
|
+
|
7
|
+
log = Logger.new(STDOUT)
|
8
|
+
log.level = Logger::WARN
|
9
|
+
|
10
|
+
# SSH copy id
|
11
|
+
# FIXME how to select the right key
|
12
|
+
|
13
|
+
command :create do |c|
|
14
|
+
c.description = "Launch new server instance"
|
15
|
+
c.option '--image TEMPLATE', String, 'instance template to use'
|
16
|
+
c.option '--profile PROFILE', String, 'instance hardware profile'
|
17
|
+
c.option '--copy-id', 'install public key on a machine'
|
18
|
+
c.option '--identity IDENTITY', String, 'SSH identity to use (with --copy-id)'
|
19
|
+
c.option '--wait', 'wait for instance to become operational'
|
20
|
+
c.action do |args, options|
|
21
|
+
# default values
|
22
|
+
options.default :identity => File.join(ENV['HOME'], '.ssh/id_rsa')
|
23
|
+
|
24
|
+
name = args.shift || abort('Server name required')
|
25
|
+
|
26
|
+
# verify server name
|
27
|
+
abort("Virtual server with name #{name} already exists!") if VirtualMaster::Helpers.get_instance(name)
|
28
|
+
|
29
|
+
# image
|
30
|
+
image_name = nil
|
31
|
+
image_id = VirtualMaster::CLI.config[:default_image] || VirtualHost::DEFAULT_IMAGE
|
32
|
+
|
33
|
+
if options.image
|
34
|
+
image_name = options.image
|
35
|
+
|
36
|
+
if image_name.match /^id:/
|
37
|
+
# use image_id directly
|
38
|
+
image_id = image_name[3..-1].to_i
|
39
|
+
|
40
|
+
image_name = nil
|
41
|
+
else
|
42
|
+
# lookup predefined images
|
43
|
+
image_id = VirtualMaster::CLI.config[:images][image_name.to_sym]
|
44
|
+
|
45
|
+
abort "Image '#{image_name}' not recognized!" unless image_id
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
say image_name ? "Using image '#{image_name}' with ID #{image_id}" : "Using image with ID #{image_id}"
|
50
|
+
|
51
|
+
# instance hardware profile
|
52
|
+
profile_name = options.profile || VirtualMaster::DEFAULT_PROFILE
|
53
|
+
|
54
|
+
profile = VirtualMaster::PROFILES[profile_name.to_sym]
|
55
|
+
abort "Image name '#{options.profile}' not recognized!" unless profile
|
56
|
+
|
57
|
+
hwp = VirtualMaster::Helpers.get_hw_profile(profile[:memory], profile[:storage])
|
58
|
+
abort "Internal error: hardware profile not available" unless hwp
|
59
|
+
|
60
|
+
say "Creating '#{profile_name}' instance (#{profile[:memory]} MB memory/#{profile[:storage]/1024} GB storage)"
|
61
|
+
|
62
|
+
instance = VirtualMaster::Helpers.create_instance(name, image_id, hwp.id)
|
63
|
+
|
64
|
+
# TODO handle exceptions (invalid image/profile, limits, etc.)
|
65
|
+
|
66
|
+
say "Instance launch request accepted. Instance ID #{instance.id}"
|
67
|
+
|
68
|
+
# FIXME authentication is missrepresented within Ruby object
|
69
|
+
password = instance.authentication[:username]
|
70
|
+
say "\n"
|
71
|
+
say "Default password '#{password}'"
|
72
|
+
|
73
|
+
# copy-id implies waiting for instance to become operational
|
74
|
+
if options.wait || options.copy_id
|
75
|
+
print 'Waiting for instance'
|
76
|
+
|
77
|
+
while (instance = VirtualMaster::Helpers.get_instance(name)).state != "RUNNING" do
|
78
|
+
print '.'
|
79
|
+
|
80
|
+
sleep(5)
|
81
|
+
end
|
82
|
+
|
83
|
+
puts
|
84
|
+
|
85
|
+
# copy ssh id
|
86
|
+
if options.copy_id
|
87
|
+
authorized_key = nil
|
88
|
+
|
89
|
+
abort "Specified identity file #{options.identity} doesn't exists!" unless File.exist?(options.identity)
|
90
|
+
|
91
|
+
say "Loading identity file\n"
|
92
|
+
key = OpenSSL::PKey::RSA.new File.read options.identity
|
93
|
+
|
94
|
+
# build authorized key output string
|
95
|
+
authtype = key.class.to_s.split('::').last.downcase
|
96
|
+
b64pub = ::Base64.encode64(key.to_blob).strip.gsub(/[\r\n]/, '')
|
97
|
+
authorized_key = "ssh-%s %s\n" % [authtype, b64pub] # => ssh-rsa AAAAB3NzaC1...=
|
98
|
+
|
99
|
+
Net::SSH.start(instance.public_addresses.first[:address], 'root', :password => password) do |ssh|
|
100
|
+
# TODO exception handling
|
101
|
+
output = ssh.exec!("mkdir ~/.ssh")
|
102
|
+
output = ssh.exec!("echo '#{authorized_key}' >>~/.ssh/authorized_keys")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
puts
|
107
|
+
puts "Instance ready!"
|
108
|
+
puts "Try to login using `ssh root@#{instance.public_addresses.first[:address]}'"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
command :list do |c|
|
114
|
+
c.description = "List all running servers"
|
115
|
+
c.action do |args, options|
|
116
|
+
instances = []
|
117
|
+
|
118
|
+
VirtualMaster::Helpers.get_instances.each do |instance|
|
119
|
+
unless instance.public_addresses.first.nil?
|
120
|
+
ip_address = instance.public_addresses.first[:address]
|
121
|
+
else
|
122
|
+
ip_address = "(not assigned)"
|
123
|
+
end
|
124
|
+
|
125
|
+
instances << [instance.name, instance.state, ip_address]
|
126
|
+
end
|
127
|
+
|
128
|
+
abort "No instances found" if instances.empty?
|
129
|
+
|
130
|
+
table = Terminal::Table.new :headings => ['name','state','ip_address'], :rows => instances
|
131
|
+
puts table
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def instance_action(action, args)
|
136
|
+
name = args.shift || abort('server name required')
|
137
|
+
|
138
|
+
instance = VirtualMaster::Helpers.get_instance(name)
|
139
|
+
instance.send("#{action}!")
|
140
|
+
end
|
141
|
+
|
142
|
+
%w{start reboot stop shutdown destroy}.each do |cmd|
|
143
|
+
command cmd do |c|
|
144
|
+
c.syntax = "virtualmaster #{c.name} SERVER"
|
145
|
+
|
146
|
+
case c.name
|
147
|
+
when "start"
|
148
|
+
c.description = "Start server (when stopped)"
|
149
|
+
when "reboot"
|
150
|
+
c.description = "Reboot server"
|
151
|
+
when "stop"
|
152
|
+
c.description = "Stop server"
|
153
|
+
when "shutdown"
|
154
|
+
c.description = "Shutdown server (ACPI)"
|
155
|
+
when "destroy"
|
156
|
+
c.description = "Remove server"
|
157
|
+
end
|
158
|
+
|
159
|
+
c.action do |args, options|
|
160
|
+
instance_action(c.name, args)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "VirtualMaster commands" do
|
4
|
+
before :each do
|
5
|
+
@runner = Commander::Runner.instance
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should have command :config" do
|
9
|
+
@runner.commands.should have_key('config')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have command server commands" do
|
13
|
+
%w{create list start reboot stop shutdown destroy}.each do |cmd|
|
14
|
+
@runner.commands.should have_key(cmd)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
|
3
|
+
require 'vmaster'
|
4
|
+
|
5
|
+
program :name, "virtualmaster"
|
6
|
+
program :version, VirtualMaster::VERSION
|
7
|
+
program :description, "VirtualMaster command line interface"
|
8
|
+
program :help_formatter, :compact
|
9
|
+
|
10
|
+
default_command :test
|
11
|
+
|
12
|
+
command :test do |c|
|
13
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "vmaster/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "virtualmaster"
|
7
|
+
s.version = VirtualMaster::VERSION
|
8
|
+
s.authors = ["Radim Marek"]
|
9
|
+
s.email = ["radim@laststation.net"]
|
10
|
+
s.homepage = "https://github.com/virtualmaster/virtualmaster-cli"
|
11
|
+
s.summary = %q{Command line interface to VirtualMaster}
|
12
|
+
s.description = %q{Command line interface to VirtualMaster. Control your virtual infrastructure.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "vmaster"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
# s.add_runtime_dependency "rest-client"
|
24
|
+
|
25
|
+
s.add_dependency "commander", "~> 4.1.2"
|
26
|
+
s.add_dependency "deltacloud-client", "~> 0.5.0"
|
27
|
+
s.add_dependency "terminal-table", "~> 1.4.4"
|
28
|
+
s.add_dependency "net-ssh", "~> 2.3.0"
|
29
|
+
|
30
|
+
s.add_development_dependency "rspec", "~> 2"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: virtualmaster
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Radim Marek
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-03-13 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: commander
|
16
|
+
requirement: &70220237000360 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 4.1.2
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70220237000360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: deltacloud-client
|
27
|
+
requirement: &70220236995660 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.5.0
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70220236995660
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: terminal-table
|
38
|
+
requirement: &70220236993960 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.4.4
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70220236993960
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: net-ssh
|
49
|
+
requirement: &70220236992760 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.3.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70220236992760
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rspec
|
60
|
+
requirement: &70220236991620 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '2'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70220236991620
|
69
|
+
description: Command line interface to VirtualMaster. Control your virtual infrastructure.
|
70
|
+
email:
|
71
|
+
- radim@laststation.net
|
72
|
+
executables:
|
73
|
+
- virtualmaster
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- README.mdown
|
80
|
+
- Rakefile
|
81
|
+
- bin/virtualmaster
|
82
|
+
- lib/vmaster.rb
|
83
|
+
- lib/vmaster/cli.rb
|
84
|
+
- lib/vmaster/config_command.rb
|
85
|
+
- lib/vmaster/helpers.rb
|
86
|
+
- lib/vmaster/server_commands.rb
|
87
|
+
- lib/vmaster/version.rb
|
88
|
+
- spec/commands_spec.rb
|
89
|
+
- spec/spec_helper.rb
|
90
|
+
- virtualmaster.gemspec
|
91
|
+
homepage: https://github.com/virtualmaster/virtualmaster-cli
|
92
|
+
licenses: []
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
none: false
|
105
|
+
requirements:
|
106
|
+
- - ! '>='
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '0'
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project: vmaster
|
111
|
+
rubygems_version: 1.8.11
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Command line interface to VirtualMaster
|
115
|
+
test_files:
|
116
|
+
- spec/commands_spec.rb
|
117
|
+
- spec/spec_helper.rb
|