vmc 0.3.23 → 0.4.0.beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/vmc +11 -2
- data/vmc-ng/LICENSE +746 -0
- data/vmc-ng/Rakefile +11 -0
- data/vmc-ng/bin/vmc +14 -0
- data/vmc-ng/lib/vmc.rb +2 -0
- data/vmc-ng/lib/vmc/cli.rb +327 -0
- data/vmc-ng/lib/vmc/cli/app.rb +622 -0
- data/vmc-ng/lib/vmc/cli/better_help.rb +193 -0
- data/vmc-ng/lib/vmc/cli/command.rb +523 -0
- data/vmc-ng/lib/vmc/cli/dots.rb +133 -0
- data/vmc-ng/lib/vmc/cli/service.rb +122 -0
- data/vmc-ng/lib/vmc/cli/user.rb +72 -0
- data/vmc-ng/lib/vmc/constants.rb +10 -0
- data/vmc-ng/lib/vmc/detect.rb +64 -0
- data/vmc-ng/lib/vmc/errors.rb +17 -0
- data/vmc-ng/lib/vmc/plugin.rb +40 -0
- data/vmc-ng/lib/vmc/version.rb +3 -0
- data/{LICENSE → vmc/LICENSE} +0 -0
- data/{README.md → vmc/README.md} +1 -5
- data/{Rakefile → vmc/Rakefile} +0 -0
- data/vmc/bin/vmc +6 -0
- data/{caldecott_helper → vmc/caldecott_helper}/Gemfile +0 -0
- data/{caldecott_helper → vmc/caldecott_helper}/Gemfile.lock +0 -0
- data/{caldecott_helper → vmc/caldecott_helper}/server.rb +0 -0
- data/{config → vmc/config}/clients.yml +0 -0
- data/{config → vmc/config}/micro/offline.conf +0 -0
- data/{config → vmc/config}/micro/paths.yml +0 -0
- data/{config → vmc/config}/micro/refresh_ip.rb +0 -0
- data/{lib → vmc/lib}/cli.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/admin.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/apps.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/base.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/manifest.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/micro.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/misc.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/services.rb +0 -0
- data/{lib → vmc/lib}/cli/commands/user.rb +2 -6
- data/{lib → vmc/lib}/cli/config.rb +0 -0
- data/{lib → vmc/lib}/cli/console_helper.rb +4 -14
- data/{lib → vmc/lib}/cli/core_ext.rb +0 -0
- data/{lib → vmc/lib}/cli/errors.rb +0 -0
- data/{lib → vmc/lib}/cli/frameworks.rb +1 -1
- data/{lib → vmc/lib}/cli/manifest_helper.rb +0 -0
- data/{lib → vmc/lib}/cli/runner.rb +0 -0
- data/{lib → vmc/lib}/cli/services_helper.rb +0 -0
- data/{lib → vmc/lib}/cli/tunnel_helper.rb +0 -0
- data/{lib → vmc/lib}/cli/usage.rb +0 -0
- data/{lib → vmc/lib}/cli/version.rb +1 -1
- data/{lib → vmc/lib}/cli/zip_util.rb +0 -0
- data/{lib → vmc/lib}/vmc.rb +0 -0
- data/{lib → vmc/lib}/vmc/client.rb +0 -0
- data/{lib → vmc/lib}/vmc/const.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro/switcher/base.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro/switcher/darwin.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro/switcher/dummy.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro/switcher/linux.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro/switcher/windows.rb +0 -0
- data/{lib → vmc/lib}/vmc/micro/vmrun.rb +1 -11
- metadata +177 -93
@@ -0,0 +1,133 @@
|
|
1
|
+
module VMC
|
2
|
+
module Dots
|
3
|
+
DOT_COUNT = 3
|
4
|
+
DOT_TICK = 0.15
|
5
|
+
|
6
|
+
class Skipper
|
7
|
+
def initialize(&ret)
|
8
|
+
@return = ret
|
9
|
+
end
|
10
|
+
|
11
|
+
def skip(&callback)
|
12
|
+
@return.call("SKIPPED", :yellow, callback)
|
13
|
+
end
|
14
|
+
|
15
|
+
def give_up(&callback)
|
16
|
+
@return.call("GAVE UP", :red, callback)
|
17
|
+
end
|
18
|
+
|
19
|
+
def fail(&callback)
|
20
|
+
@return.call("FAILED", :red, callback)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def with_progress(message)
|
25
|
+
unless simple_output?
|
26
|
+
print message
|
27
|
+
dots!
|
28
|
+
end
|
29
|
+
|
30
|
+
skipper = Skipper.new do |status, color, callback|
|
31
|
+
unless simple_output?
|
32
|
+
stop_dots!
|
33
|
+
puts "... #{c(status, color)}"
|
34
|
+
end
|
35
|
+
|
36
|
+
return callback && callback.call
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
res = yield skipper
|
41
|
+
unless simple_output?
|
42
|
+
stop_dots!
|
43
|
+
puts "... #{c("OK", :green)}"
|
44
|
+
end
|
45
|
+
res
|
46
|
+
rescue
|
47
|
+
unless simple_output?
|
48
|
+
stop_dots!
|
49
|
+
puts "... #{c("FAILED", :red)}"
|
50
|
+
end
|
51
|
+
|
52
|
+
raise
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def color?
|
57
|
+
$stdout.tty?
|
58
|
+
end
|
59
|
+
|
60
|
+
COLOR_CODES = {
|
61
|
+
:black => 0,
|
62
|
+
:red => 1,
|
63
|
+
:green => 2,
|
64
|
+
:yellow => 3,
|
65
|
+
:blue => 4,
|
66
|
+
:magenta => 5,
|
67
|
+
:cyan => 6,
|
68
|
+
:white => 7
|
69
|
+
}
|
70
|
+
|
71
|
+
# colored text
|
72
|
+
#
|
73
|
+
# shouldn't use bright colors, as some color themes abuse
|
74
|
+
# the bright palette (I'm looking at you, Solarized)
|
75
|
+
def c(str, color)
|
76
|
+
return str unless color?
|
77
|
+
"\e[3#{COLOR_CODES[color]}m#{str}\e[0m"
|
78
|
+
end
|
79
|
+
module_function :c
|
80
|
+
|
81
|
+
# bold text
|
82
|
+
def b(str)
|
83
|
+
return str unless color?
|
84
|
+
"\e[1m#{str}\e[0m"
|
85
|
+
end
|
86
|
+
module_function :b
|
87
|
+
|
88
|
+
def dots!
|
89
|
+
@dots ||=
|
90
|
+
Thread.new do
|
91
|
+
before_sync = $stdout.sync
|
92
|
+
|
93
|
+
$stdout.sync = true
|
94
|
+
|
95
|
+
printed = false
|
96
|
+
i = 1
|
97
|
+
until @stop_dots
|
98
|
+
if printed
|
99
|
+
print "\b" * DOT_COUNT
|
100
|
+
end
|
101
|
+
|
102
|
+
print ("." * i).ljust(DOT_COUNT)
|
103
|
+
printed = true
|
104
|
+
|
105
|
+
if i == DOT_COUNT
|
106
|
+
i = 0
|
107
|
+
else
|
108
|
+
i += 1
|
109
|
+
end
|
110
|
+
|
111
|
+
sleep DOT_TICK
|
112
|
+
end
|
113
|
+
|
114
|
+
if printed
|
115
|
+
print "\b" * DOT_COUNT
|
116
|
+
print " " * DOT_COUNT
|
117
|
+
print "\b" * DOT_COUNT
|
118
|
+
end
|
119
|
+
|
120
|
+
$stdout.sync = before_sync
|
121
|
+
@stop_dots = nil
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def stop_dots!
|
126
|
+
return unless @dots
|
127
|
+
return if @stop_dots
|
128
|
+
@stop_dots = true
|
129
|
+
@dots.join
|
130
|
+
@dots = nil
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require "vmc/cli/command"
|
2
|
+
|
3
|
+
module VMC
|
4
|
+
class Service < Command
|
5
|
+
desc "create", "Create a service"
|
6
|
+
group :services, :manage
|
7
|
+
flag(:type) { |choices|
|
8
|
+
ask "What kind?", :choices => choices
|
9
|
+
}
|
10
|
+
flag(:name) { |vendor|
|
11
|
+
random = sprintf("%x", rand(1000000))
|
12
|
+
ask "Name?", :default => "#{vendor}-#{random}"
|
13
|
+
}
|
14
|
+
def create
|
15
|
+
choices = []
|
16
|
+
manifests = {}
|
17
|
+
client.system_services.each do |type, vendors|
|
18
|
+
vendors.each do |vendor, versions|
|
19
|
+
versions.each do |version, _|
|
20
|
+
choice = "#{vendor} #{version}"
|
21
|
+
manifests[choice] = {
|
22
|
+
:type => type,
|
23
|
+
:vendor => vendor,
|
24
|
+
:version => version
|
25
|
+
}
|
26
|
+
|
27
|
+
choices << choice
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
type = input(:type, choices)
|
33
|
+
meta = manifests[type]
|
34
|
+
|
35
|
+
# --type redis should work, and just ignore version
|
36
|
+
unless meta
|
37
|
+
_, meta = manifests.find { |k, _| k.split.first == type }
|
38
|
+
fail "Unknown service type." unless meta
|
39
|
+
end
|
40
|
+
|
41
|
+
service = client.service(input(:name, meta[:vendor]))
|
42
|
+
service.type = meta[:type]
|
43
|
+
service.vendor = meta[:vendor]
|
44
|
+
service.version = meta[:version]
|
45
|
+
service.tier = "free"
|
46
|
+
|
47
|
+
with_progress("Creating service") do
|
48
|
+
service.create!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "bind", "Bind a service to an application"
|
53
|
+
group :services, :manage
|
54
|
+
flag(:name) { |choices|
|
55
|
+
ask "Which service?", :choices => choices
|
56
|
+
}
|
57
|
+
flag(:app) { |choices|
|
58
|
+
ask "Which application?", :choices => choices
|
59
|
+
}
|
60
|
+
def bind(name = nil, appname = nil)
|
61
|
+
name ||= input(:name, client.services.collect(&:name))
|
62
|
+
appname ||= input(:app, client.apps.collect(&:name))
|
63
|
+
|
64
|
+
with_progress("Binding #{c(name, :blue)} to #{c(appname, :blue)}") do
|
65
|
+
client.app(appname).bind(name)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "unbind", "Unbind a service from an application"
|
70
|
+
group :services, :manage
|
71
|
+
flag(:name) { |choices|
|
72
|
+
ask "Which service?", :choices => choices
|
73
|
+
}
|
74
|
+
flag(:app) { |choices|
|
75
|
+
ask "Which application?", :choices => choices
|
76
|
+
}
|
77
|
+
def unbind(name = nil, appname = nil)
|
78
|
+
appname ||= input(:app, client.apps.collect(&:name))
|
79
|
+
|
80
|
+
app = client.app(appname)
|
81
|
+
name ||= input(:name, app.services)
|
82
|
+
|
83
|
+
with_progress("Unbinding #{c(name, :blue)} from #{c(appname, :blue)}") do
|
84
|
+
app.unbind(name)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
desc "delete", "Delete a service"
|
89
|
+
group :services, :manage
|
90
|
+
flag(:really) { |name, color|
|
91
|
+
force? || ask("Really delete #{c(name, color)}?", :default => false)
|
92
|
+
}
|
93
|
+
flag(:name) { |choices|
|
94
|
+
ask "Delete which service?", :choices => choices
|
95
|
+
}
|
96
|
+
flag(:all, :default => false)
|
97
|
+
def delete(name = nil)
|
98
|
+
if input(:all)
|
99
|
+
return unless input(:really, "ALL SERVICES", :red)
|
100
|
+
|
101
|
+
with_progress("Deleting all services") do
|
102
|
+
client.services.collect(&:delete!)
|
103
|
+
end
|
104
|
+
|
105
|
+
return
|
106
|
+
end
|
107
|
+
|
108
|
+
unless name
|
109
|
+
services = client.services
|
110
|
+
fail "No services." if services.empty?
|
111
|
+
|
112
|
+
name = input(:name, services.collect(&:name))
|
113
|
+
end
|
114
|
+
|
115
|
+
return unless input(:really, name, :blue)
|
116
|
+
|
117
|
+
with_progress("Deleting #{c(name, :blue)}") do
|
118
|
+
client.service(name).delete!
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "vmc/cli/command"
|
2
|
+
|
3
|
+
module VMC
|
4
|
+
class User < Command
|
5
|
+
desc "create [EMAIL]", "Create a user"
|
6
|
+
group :admin, :user, :hidden => true
|
7
|
+
flag(:email) {
|
8
|
+
ask("Email")
|
9
|
+
}
|
10
|
+
flag(:password) {
|
11
|
+
ask("Password", :echo => "*", :forget => true)
|
12
|
+
}
|
13
|
+
flag(:verify) {
|
14
|
+
ask("Verify Password", :echo => "*", :forget => true)
|
15
|
+
}
|
16
|
+
def create(email = nil)
|
17
|
+
email ||= input(:email)
|
18
|
+
password = input(:password)
|
19
|
+
verify = input(:verify)
|
20
|
+
|
21
|
+
if password != verify
|
22
|
+
fail "Passwords don't match."
|
23
|
+
end
|
24
|
+
|
25
|
+
with_progress("Creating user") do
|
26
|
+
client.register(email, password)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "delete [EMAIL]", "Delete a user"
|
31
|
+
group :admin, :user, :hidden => true
|
32
|
+
flag(:really) { |email|
|
33
|
+
force? || ask("Really delete user #{c(email, :blue)}?", :default => false)
|
34
|
+
}
|
35
|
+
def delete(email)
|
36
|
+
return unless input(:really, email)
|
37
|
+
|
38
|
+
with_progress("Deleting #{c(email, :blue)}") do
|
39
|
+
client.user(email).delete!
|
40
|
+
end
|
41
|
+
ensure
|
42
|
+
forget(:really)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "passwd [EMAIL]", "Update a user's password"
|
46
|
+
group :admin, :user, :hidden => true
|
47
|
+
flag(:email) {
|
48
|
+
ask("Email")
|
49
|
+
}
|
50
|
+
flag(:password) {
|
51
|
+
ask("Password", :echo => "*", :forget => true)
|
52
|
+
}
|
53
|
+
flag(:verify) {
|
54
|
+
ask("Verify Password", :echo => "*", :forget => true)
|
55
|
+
}
|
56
|
+
def passwd(email = nil)
|
57
|
+
email ||= input(:email)
|
58
|
+
password = input(:password)
|
59
|
+
verify = input(:verify)
|
60
|
+
|
61
|
+
if password != verify
|
62
|
+
fail "Passwords don't match."
|
63
|
+
end
|
64
|
+
|
65
|
+
with_progress("Changing password") do
|
66
|
+
user = client.user(email)
|
67
|
+
user.password = password
|
68
|
+
user.update!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module VMC
|
2
|
+
OLD_TARGET_FILE = "~/.vmc_target"
|
3
|
+
OLD_TOKENS_FILE = "~/.vmc_token"
|
4
|
+
|
5
|
+
CONFIG_DIR = "~/.vmc"
|
6
|
+
PLUGINS_FILE = "#{CONFIG_DIR}/plugins.yml"
|
7
|
+
TARGET_FILE = "#{CONFIG_DIR}/target"
|
8
|
+
TOKENS_FILE = "#{CONFIG_DIR}/tokens.yml"
|
9
|
+
CRASH_FILE = "#{CONFIG_DIR}/crash"
|
10
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module VMC
|
2
|
+
class Detector
|
3
|
+
def initialize(client, path)
|
4
|
+
@client = client
|
5
|
+
@path = path
|
6
|
+
end
|
7
|
+
|
8
|
+
def all_frameworks
|
9
|
+
info = @client.info
|
10
|
+
info["frameworks"] || {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def frameworks
|
14
|
+
info = @client.info
|
15
|
+
|
16
|
+
matches = {}
|
17
|
+
all_frameworks.each do |name, meta|
|
18
|
+
matched = false
|
19
|
+
|
20
|
+
# e.g. standalone has no detection
|
21
|
+
next if meta["detection"].nil?
|
22
|
+
|
23
|
+
meta["detection"].first.each do |file, match|
|
24
|
+
files =
|
25
|
+
if File.file? @path
|
26
|
+
if File.fnmatch(file, @path)
|
27
|
+
[@path]
|
28
|
+
else
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
else
|
32
|
+
Dir.glob("#@path/#{file}")
|
33
|
+
end
|
34
|
+
|
35
|
+
unless files.empty?
|
36
|
+
if match == true
|
37
|
+
matched = true
|
38
|
+
elsif match == false
|
39
|
+
matched = false
|
40
|
+
break
|
41
|
+
else
|
42
|
+
files.each do |f|
|
43
|
+
contents = File.open(f, &:read)
|
44
|
+
if contents =~ Regexp.new(match)
|
45
|
+
matched = true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if matched
|
53
|
+
matches[name] = meta
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
if matches.size == 1
|
58
|
+
default = matches.keys.first
|
59
|
+
end
|
60
|
+
|
61
|
+
[matches, default]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "set"
|
2
|
+
require "yaml"
|
3
|
+
|
4
|
+
require "vmc/constants"
|
5
|
+
require "vmc/cli"
|
6
|
+
|
7
|
+
module VMC
|
8
|
+
module Plugin
|
9
|
+
@@plugins = []
|
10
|
+
|
11
|
+
def self.load_all
|
12
|
+
# auto-load gems with 'vmc-plugin' in their name
|
13
|
+
enabled =
|
14
|
+
Set.new(
|
15
|
+
Gem::Specification.find_all { |s|
|
16
|
+
s.name =~ /vmc-plugin/
|
17
|
+
}.collect(&:name))
|
18
|
+
|
19
|
+
# allow explicit enabling/disabling of gems via config
|
20
|
+
plugins = File.expand_path(VMC::PLUGINS_FILE)
|
21
|
+
if File.exists?(plugins) && yaml = YAML.load_file(plugins)
|
22
|
+
enabled += yaml["enabled"] if yaml["enabled"]
|
23
|
+
enabled -= yaml["disabled"] if yaml["disabled"]
|
24
|
+
end
|
25
|
+
|
26
|
+
# load up each gem's 'plugin' file
|
27
|
+
#
|
28
|
+
# we require this file specifically so people can require the gem
|
29
|
+
# without it plugging into VMC
|
30
|
+
enabled.each do |gemname|
|
31
|
+
require "#{gemname}/plugin"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.Plugin(target = CLI, &blk)
|
37
|
+
# SUPER FANCY PLUGIN SYSTEM
|
38
|
+
target.class_eval &blk
|
39
|
+
end
|
40
|
+
end
|