vmc 0.3.16.beta.2 → 0.3.16.beta.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/README.md +0 -1
- data/lib/cli.rb +1 -0
- data/lib/cli/commands/apps.rb +79 -33
- data/lib/cli/commands/base.rb +4 -7
- data/lib/cli/commands/services.rb +2 -1
- data/lib/cli/config.rb +4 -9
- data/lib/cli/console_helper.rb +157 -0
- data/lib/cli/frameworks.rb +9 -2
- data/lib/cli/manifest_helper.rb +32 -8
- data/lib/cli/runner.rb +5 -4
- data/lib/cli/tunnel_helper.rb +17 -9
- data/lib/cli/usage.rb +0 -1
- data/lib/cli/version.rb +1 -1
- data/lib/vmc/client.rb +3 -3
- metadata +4 -3
data/README.md
CHANGED
@@ -31,7 +31,6 @@ MIT license, please see the LICENSE file. All rights reserved._
|
|
31
31
|
stop <appname> Stop the application
|
32
32
|
restart <appname> Restart the application
|
33
33
|
delete <appname> Delete the application
|
34
|
-
rename <appname> <newname> Rename the application
|
35
34
|
|
36
35
|
Application Updates
|
37
36
|
update <appname> [--path] Update the application bits
|
data/lib/cli.rb
CHANGED
@@ -13,6 +13,7 @@ module VMC
|
|
13
13
|
autoload :ServicesHelper, "#{ROOT}/cli/services_helper"
|
14
14
|
autoload :TunnelHelper, "#{ROOT}/cli/tunnel_helper"
|
15
15
|
autoload :ManifestHelper, "#{ROOT}/cli/manifest_helper"
|
16
|
+
autoload :ConsoleHelper, "#{ROOT}/cli/console_helper"
|
16
17
|
|
17
18
|
module Command
|
18
19
|
autoload :Base, "#{ROOT}/cli/commands/base"
|
data/lib/cli/commands/apps.rb
CHANGED
@@ -4,12 +4,16 @@ require 'pathname'
|
|
4
4
|
require 'tempfile'
|
5
5
|
require 'tmpdir'
|
6
6
|
require 'set'
|
7
|
+
require "uuidtools"
|
8
|
+
require 'socket'
|
7
9
|
|
8
10
|
module VMC::Cli::Command
|
9
11
|
|
10
12
|
class Apps < Base
|
11
13
|
include VMC::Cli::ServicesHelper
|
12
14
|
include VMC::Cli::ManifestHelper
|
15
|
+
include VMC::Cli::TunnelHelper
|
16
|
+
include VMC::Cli::ConsoleHelper
|
13
17
|
|
14
18
|
def list
|
15
19
|
apps = client.apps
|
@@ -43,6 +47,52 @@ module VMC::Cli::Command
|
|
43
47
|
@options[what] || (@app_info && @app_info[what.to_s]) || default
|
44
48
|
end
|
45
49
|
|
50
|
+
def console(appname, interactive=true)
|
51
|
+
unless defined? Caldecott
|
52
|
+
display "To use `vmc rails-console', you must first install Caldecott:"
|
53
|
+
display ""
|
54
|
+
display "\tgem install caldecott"
|
55
|
+
display ""
|
56
|
+
display "Note that you'll need a C compiler. If you're on OS X, Xcode"
|
57
|
+
display "will provide one. If you're on Windows, try DevKit."
|
58
|
+
display ""
|
59
|
+
display "This manual step will be removed in the future."
|
60
|
+
display ""
|
61
|
+
err "Caldecott is not installed."
|
62
|
+
end
|
63
|
+
|
64
|
+
#Make sure there is a console we can connect to first
|
65
|
+
conn_info = console_connection_info appname
|
66
|
+
|
67
|
+
port = pick_tunnel_port(@options[:port] || 20000)
|
68
|
+
|
69
|
+
raise VMC::Client::AuthError unless client.logged_in?
|
70
|
+
|
71
|
+
if not tunnel_pushed?
|
72
|
+
display "Deploying tunnel application '#{tunnel_appname}'."
|
73
|
+
auth = UUIDTools::UUID.random_create.to_s
|
74
|
+
push_caldecott(auth)
|
75
|
+
start_caldecott
|
76
|
+
else
|
77
|
+
auth = tunnel_auth
|
78
|
+
end
|
79
|
+
|
80
|
+
if not tunnel_healthy?(auth)
|
81
|
+
display "Redeploying tunnel application '#{tunnel_appname}'."
|
82
|
+
# We don't expect caldecott not to be running, so take the
|
83
|
+
# most aggressive restart method.. delete/re-push
|
84
|
+
client.delete_app(tunnel_appname)
|
85
|
+
invalidate_tunnel_app_info
|
86
|
+
push_caldecott(auth)
|
87
|
+
start_caldecott
|
88
|
+
end
|
89
|
+
|
90
|
+
start_tunnel(port, conn_info, auth)
|
91
|
+
wait_for_tunnel_start(port)
|
92
|
+
start_local_console(port, appname) if interactive
|
93
|
+
port
|
94
|
+
end
|
95
|
+
|
46
96
|
def start(appname=nil, push=false)
|
47
97
|
if appname
|
48
98
|
do_start(appname, push)
|
@@ -73,14 +123,6 @@ module VMC::Cli::Command
|
|
73
123
|
start(appname)
|
74
124
|
end
|
75
125
|
|
76
|
-
def rename(appname, newname)
|
77
|
-
app = client.app_info(appname)
|
78
|
-
app[:name] = newname
|
79
|
-
display 'Renaming Appliction: '
|
80
|
-
client.update_app(newname, app)
|
81
|
-
display 'OK'.green
|
82
|
-
end
|
83
|
-
|
84
126
|
def mem(appname, memsize=nil)
|
85
127
|
app = client.app_info(appname)
|
86
128
|
mem = current_mem = mem_quota_to_choice(app[:resources][:memory])
|
@@ -136,7 +178,7 @@ module VMC::Cli::Command
|
|
136
178
|
def delete(appname=nil)
|
137
179
|
force = @options[:force]
|
138
180
|
if @options[:all]
|
139
|
-
if no_prompt || force || ask("Delete ALL applications
|
181
|
+
if no_prompt || force || ask("Delete ALL applications?", :default => false)
|
140
182
|
apps = client.apps
|
141
183
|
apps.each { |app| delete_app(app[:name], force) }
|
142
184
|
end
|
@@ -151,7 +193,7 @@ module VMC::Cli::Command
|
|
151
193
|
instance = @options[:instance] || '0'
|
152
194
|
content = client.app_files(appname, path, instance)
|
153
195
|
display content
|
154
|
-
rescue VMC::Client::
|
196
|
+
rescue VMC::Client::TargetError
|
155
197
|
err 'No such file or directory'
|
156
198
|
end
|
157
199
|
|
@@ -651,7 +693,7 @@ module VMC::Cli::Command
|
|
651
693
|
begin
|
652
694
|
content = client.app_files(appname, path, instance)
|
653
695
|
display_logfile(path, content, instance)
|
654
|
-
rescue VMC::Client::
|
696
|
+
rescue VMC::Client::TargetError
|
655
697
|
end
|
656
698
|
end
|
657
699
|
end
|
@@ -665,13 +707,14 @@ module VMC::Cli::Command
|
|
665
707
|
instance = map[instance] if map[instance]
|
666
708
|
|
667
709
|
%w{
|
668
|
-
/logs/err.log /logs/staging.log /
|
669
|
-
/app/logs/
|
710
|
+
/logs/err.log /logs/staging.log /logs/migration.log
|
711
|
+
/app/logs/stderr.log /app/logs/stdout.log /app/logs/startup.log
|
712
|
+
/app/logs/migration.log
|
670
713
|
}.each do |path|
|
671
714
|
begin
|
672
715
|
content = client.app_files(appname, path, instance)
|
673
716
|
display_logfile(path, content, instance)
|
674
|
-
rescue VMC::Client::
|
717
|
+
rescue VMC::Client::TargetError
|
675
718
|
end
|
676
719
|
end
|
677
720
|
end
|
@@ -689,6 +732,8 @@ module VMC::Cli::Command
|
|
689
732
|
display tail.join("\n") if new_lines > 0
|
690
733
|
end
|
691
734
|
since + new_lines
|
735
|
+
rescue VMC::Client::TargetError
|
736
|
+
0
|
692
737
|
end
|
693
738
|
|
694
739
|
def provisioned_services_apps_hash
|
@@ -744,10 +789,11 @@ module VMC::Cli::Command
|
|
744
789
|
|
745
790
|
def do_start(appname, push=false)
|
746
791
|
app = client.app_info(appname)
|
747
|
-
|
748
792
|
return display "Application '#{appname}' could not be found".red if app.nil?
|
749
793
|
return display "Application '#{appname}' already started".yellow if app[:state] == 'STARTED'
|
750
794
|
|
795
|
+
|
796
|
+
|
751
797
|
if @options[:debug]
|
752
798
|
runtimes = client.runtimes_info
|
753
799
|
return display "Cannot get runtime information." unless runtimes
|
@@ -784,6 +830,7 @@ module VMC::Cli::Command
|
|
784
830
|
|
785
831
|
app[:state] = 'STARTED'
|
786
832
|
app[:debug] = @options[:debug]
|
833
|
+
app[:console] = VMC::Cli::Framework.lookup_by_framework(app[:staging][:model]).console
|
787
834
|
client.update_app(appname, app)
|
788
835
|
|
789
836
|
Thread.kill(t)
|
@@ -800,24 +847,23 @@ module VMC::Cli::Command
|
|
800
847
|
loop do
|
801
848
|
display '.', false unless count > TICKER_TICKS
|
802
849
|
sleep SLEEP_TIME
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
failed = true
|
814
|
-
break
|
815
|
-
elsif count > TAIL_TICKS
|
816
|
-
log_lines_displayed = grab_startup_tail(appname, log_lines_displayed)
|
850
|
+
|
851
|
+
break if app_started_properly(appname, count > HEALTH_TICKS)
|
852
|
+
|
853
|
+
if !crashes(appname, false, start_time).empty?
|
854
|
+
# Check for the existance of crashes
|
855
|
+
display "\nError: Application [#{appname}] failed to start, logs information below.\n".red
|
856
|
+
grab_crash_logs(appname, '0', true)
|
857
|
+
if push and !no_prompt
|
858
|
+
display "\n"
|
859
|
+
delete_app(appname, false) if ask "Delete the application?", :default => true
|
817
860
|
end
|
818
|
-
|
819
|
-
|
861
|
+
failed = true
|
862
|
+
break
|
863
|
+
elsif count > TAIL_TICKS
|
864
|
+
log_lines_displayed = grab_startup_tail(appname, log_lines_displayed)
|
820
865
|
end
|
866
|
+
|
821
867
|
count += 1
|
822
868
|
if count > GIVEUP_TICKS # 2 minutes
|
823
869
|
display "\nApplication is taking too long to start, check your logs".yellow
|
@@ -889,7 +935,7 @@ module VMC::Cli::Command
|
|
889
935
|
err "Application '#{appname}' already exists, use update or delete."
|
890
936
|
end
|
891
937
|
|
892
|
-
default_url = "#{appname}.#{
|
938
|
+
default_url = "#{appname}.#{target_base}"
|
893
939
|
|
894
940
|
unless no_prompt || url
|
895
941
|
url = ask(
|
@@ -1018,7 +1064,7 @@ module VMC::Cli::Command
|
|
1018
1064
|
entry[:index],
|
1019
1065
|
"====> [#{entry[:index]}: #{path}] <====\n".bold
|
1020
1066
|
)
|
1021
|
-
rescue VMC::Client::
|
1067
|
+
rescue VMC::Client::TargetError
|
1022
1068
|
end
|
1023
1069
|
end
|
1024
1070
|
end
|
data/lib/cli/commands/base.rb
CHANGED
@@ -8,7 +8,6 @@ module VMC::Cli
|
|
8
8
|
|
9
9
|
class Base
|
10
10
|
include Interactive
|
11
|
-
disable_rewind
|
12
11
|
|
13
12
|
attr_reader :no_prompt, :prompt_ok
|
14
13
|
|
@@ -173,15 +172,13 @@ module VMC::Cli
|
|
173
172
|
end
|
174
173
|
|
175
174
|
def target_url(ctx = [])
|
176
|
-
find_symbol("target", ctx) ||
|
175
|
+
find_symbol("target", ctx) ||
|
176
|
+
(@client && @client.target) ||
|
177
|
+
VMC::Cli::Config.target_url
|
177
178
|
end
|
178
179
|
|
179
180
|
def target_base(ctx = [])
|
180
|
-
|
181
|
-
VMC::Cli::Config.base_of(tgt)
|
182
|
-
else
|
183
|
-
VMC::Cli::Config.suggest_url
|
184
|
-
end
|
181
|
+
VMC::Cli::Config.base_of(find_symbol("target", ctx) || target_url)
|
185
182
|
end
|
186
183
|
|
187
184
|
# Inject a client to help in testing.
|
@@ -147,7 +147,8 @@ module VMC::Cli::Command
|
|
147
147
|
|
148
148
|
conn_info = tunnel_connection_info info[:vendor], service, auth
|
149
149
|
display_tunnel_connection_info(conn_info)
|
150
|
-
|
150
|
+
display "Starting tunnel to #{service.bold} on port #{port.to_s.bold}."
|
151
|
+
start_tunnel(port, conn_info, auth)
|
151
152
|
|
152
153
|
clients = get_clients_for(info[:vendor])
|
153
154
|
|
data/lib/cli/config.rb
CHANGED
@@ -8,7 +8,6 @@ module VMC::Cli
|
|
8
8
|
class Config
|
9
9
|
|
10
10
|
DEFAULT_TARGET = 'api.vcap.me'
|
11
|
-
DEFAULT_SUGGEST = 'vcap.me'
|
12
11
|
|
13
12
|
TARGET_FILE = '~/.vmc_target'
|
14
13
|
TOKEN_FILE = '~/.vmc_token'
|
@@ -42,12 +41,7 @@ module VMC::Cli
|
|
42
41
|
end
|
43
42
|
|
44
43
|
def suggest_url
|
45
|
-
|
46
|
-
ha = target_url.split('.')
|
47
|
-
ha.shift
|
48
|
-
@suggest_url = ha.join('.')
|
49
|
-
@suggest_url = DEFAULT_SUGGEST if @suggest_url.empty?
|
50
|
-
@suggest_url
|
44
|
+
@suggest_url ||= base_of(target_url)
|
51
45
|
end
|
52
46
|
|
53
47
|
def store_target(target_host)
|
@@ -124,8 +118,9 @@ module VMC::Cli
|
|
124
118
|
return @clients if @clients
|
125
119
|
|
126
120
|
stock = YAML.load_file(STOCK_CLIENTS)
|
127
|
-
|
128
|
-
|
121
|
+
clients = File.expand_path CLIENTS_FILE
|
122
|
+
if File.exists? clients
|
123
|
+
user = YAML.load_file(clients)
|
129
124
|
@clients = deep_merge(stock, user)
|
130
125
|
else
|
131
126
|
@clients = stock
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'net/telnet'
|
2
|
+
require 'readline'
|
3
|
+
|
4
|
+
module VMC::Cli
|
5
|
+
module ConsoleHelper
|
6
|
+
|
7
|
+
def console_connection_info(appname)
|
8
|
+
app = client.app_info(appname)
|
9
|
+
fw = VMC::Cli::Framework.lookup_by_framework(app[:staging][:model])
|
10
|
+
if !fw.console
|
11
|
+
err "'#{appname}' is a #{fw.name} application. " +
|
12
|
+
"Console access is not supported for #{fw.name} applications."
|
13
|
+
end
|
14
|
+
instances_info_envelope = client.app_instances(appname)
|
15
|
+
instances_info_envelope = {} if instances_info_envelope.is_a?(Array)
|
16
|
+
|
17
|
+
instances_info = instances_info_envelope[:instances] || []
|
18
|
+
err "No running instances for [#{appname}]" if instances_info.empty?
|
19
|
+
|
20
|
+
entry = instances_info[0]
|
21
|
+
if !entry[:console_port]
|
22
|
+
begin
|
23
|
+
client.app_files(appname, '/app/cf-rails-console')
|
24
|
+
err "Console port not provided for [#{appname}]. Try restarting the app."
|
25
|
+
rescue VMC::Client::TargetError, VMC::Client::NotFound
|
26
|
+
err "Console access not supported for [#{appname}]. " +
|
27
|
+
"Please redeploy your app to enable support."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
conn_info = {'hostname' => entry[:console_ip], 'port' => entry[:console_port]}
|
31
|
+
end
|
32
|
+
|
33
|
+
def start_local_console(port, appname)
|
34
|
+
auth_info = console_credentials(appname)
|
35
|
+
display "Connecting to '#{appname}' console: ", false
|
36
|
+
prompt = console_login(auth_info, port)
|
37
|
+
display "OK".green
|
38
|
+
display "\n"
|
39
|
+
initialize_readline
|
40
|
+
run_console prompt
|
41
|
+
end
|
42
|
+
|
43
|
+
def console_login(auth_info, port)
|
44
|
+
if !auth_info["username"] || !auth_info["password"]
|
45
|
+
err "Unable to verify console credentials."
|
46
|
+
end
|
47
|
+
@telnet_client = telnet_client(port)
|
48
|
+
prompt = nil
|
49
|
+
err_msg = "Login attempt timed out."
|
50
|
+
5.times do
|
51
|
+
begin
|
52
|
+
results = @telnet_client.login("Name"=>auth_info["username"],
|
53
|
+
"Password"=>auth_info["password"]) {|line|
|
54
|
+
if line =~ /[$%#>] \z/n
|
55
|
+
prompt = line
|
56
|
+
elsif line =~ /Login failed/
|
57
|
+
err_msg = line
|
58
|
+
end
|
59
|
+
}
|
60
|
+
break
|
61
|
+
rescue TimeoutError
|
62
|
+
sleep 1
|
63
|
+
rescue EOFError
|
64
|
+
#This may happen if we login right after app starts
|
65
|
+
close_console
|
66
|
+
sleep 5
|
67
|
+
@telnet_client = telnet_client(port)
|
68
|
+
end
|
69
|
+
display ".", false
|
70
|
+
end
|
71
|
+
unless prompt
|
72
|
+
close_console
|
73
|
+
err err_msg
|
74
|
+
end
|
75
|
+
prompt
|
76
|
+
end
|
77
|
+
|
78
|
+
def send_console_command(cmd)
|
79
|
+
results = @telnet_client.cmd(cmd)
|
80
|
+
results.split("\n")
|
81
|
+
end
|
82
|
+
|
83
|
+
def console_credentials(appname)
|
84
|
+
content = client.app_files(appname, '/app/cf-rails-console/.consoleaccess', '0')
|
85
|
+
YAML.load(content)
|
86
|
+
end
|
87
|
+
|
88
|
+
def close_console
|
89
|
+
@telnet_client.close
|
90
|
+
end
|
91
|
+
|
92
|
+
def console_tab_completion_data(cmd)
|
93
|
+
begin
|
94
|
+
results = @telnet_client.cmd("String"=> cmd + "\t", "Match"=>/\S*\n$/, "Timeout"=>10)
|
95
|
+
results.chomp.split(",")
|
96
|
+
rescue TimeoutError
|
97
|
+
[] #Just return empty results if timeout occurred on tab completion
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
def telnet_client(port)
|
103
|
+
Net::Telnet.new({"Port"=>port, "Prompt"=>/[$%#>] \z|Login failed/n, "Timeout"=>30, "FailEOF"=>true})
|
104
|
+
end
|
105
|
+
|
106
|
+
def readline_with_history(prompt)
|
107
|
+
line = Readline.readline(prompt, true)
|
108
|
+
return '' if line.nil?
|
109
|
+
#Don't keep blank or repeat commands in history
|
110
|
+
if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line
|
111
|
+
Readline::HISTORY.pop
|
112
|
+
end
|
113
|
+
line
|
114
|
+
end
|
115
|
+
|
116
|
+
def run_console(prompt)
|
117
|
+
while(cmd = readline_with_history(prompt))
|
118
|
+
if(cmd == "exit" || cmd == "quit")
|
119
|
+
#TimeoutError expected, as exit doesn't return anything
|
120
|
+
@telnet_client.cmd("String"=>cmd,"Timeout"=>1) rescue TimeoutError
|
121
|
+
close_console
|
122
|
+
break
|
123
|
+
end
|
124
|
+
if !cmd.empty?
|
125
|
+
prompt = send_console_command_display_results(cmd, prompt)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def send_console_command_display_results(cmd, prompt)
|
131
|
+
begin
|
132
|
+
lines = send_console_command cmd
|
133
|
+
#Assumes the last line is a prompt
|
134
|
+
prompt = lines.pop
|
135
|
+
lines.each {|line| display line if line != cmd}
|
136
|
+
rescue TimeoutError
|
137
|
+
display "Timed out sending command to server.".red
|
138
|
+
rescue EOFError
|
139
|
+
err "The console connection has been terminated. Perhaps the app was stopped or deleted?"
|
140
|
+
end
|
141
|
+
prompt
|
142
|
+
end
|
143
|
+
|
144
|
+
def initialize_readline
|
145
|
+
if Readline.respond_to?("basic_word_break_characters=")
|
146
|
+
Readline.basic_word_break_characters= " \t\n`><=;|&{("
|
147
|
+
end
|
148
|
+
Readline.completion_append_character = nil
|
149
|
+
#Assumes that sending a String ending with tab will return a non-empty
|
150
|
+
#String of comma-separated completion options, terminated by a new line
|
151
|
+
#For example, "app.\t" might result in "to_s,nil?,etc\n"
|
152
|
+
Readline.completion_proc = proc {|s|
|
153
|
+
console_tab_completion_data s
|
154
|
+
}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
data/lib/cli/frameworks.rb
CHANGED
@@ -6,7 +6,7 @@ module VMC::Cli
|
|
6
6
|
DEFAULT_MEM = '256M'
|
7
7
|
|
8
8
|
FRAMEWORKS = {
|
9
|
-
'Rails' => ['rails3', { :mem => '256M', :description => 'Rails Application'}],
|
9
|
+
'Rails' => ['rails3', { :mem => '256M', :description => 'Rails Application', :console=>true}],
|
10
10
|
'Spring' => ['spring', { :mem => '512M', :description => 'Java SpringSource Spring Application'}],
|
11
11
|
'Grails' => ['grails', { :mem => '512M', :description => 'Java SpringSource Grails Application'}],
|
12
12
|
'Lift' => ['lift', { :mem => '512M', :description => 'Scala Lift Application'}],
|
@@ -29,6 +29,12 @@ module VMC::Cli
|
|
29
29
|
return Framework.new(*FRAMEWORKS[name])
|
30
30
|
end
|
31
31
|
|
32
|
+
def lookup_by_framework(name)
|
33
|
+
FRAMEWORKS.each do |key,fw|
|
34
|
+
return Framework.new(fw[0], fw[1]) if fw[0] == name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
32
38
|
def detect(path)
|
33
39
|
Dir.chdir(path) do
|
34
40
|
|
@@ -106,7 +112,7 @@ module VMC::Cli
|
|
106
112
|
|
107
113
|
end
|
108
114
|
|
109
|
-
attr_reader :name, :description, :memory
|
115
|
+
attr_reader :name, :description, :memory, :console
|
110
116
|
attr_accessor :exec
|
111
117
|
|
112
118
|
alias :mem :memory
|
@@ -116,6 +122,7 @@ module VMC::Cli
|
|
116
122
|
@memory = opts[:mem] || DEFAULT_MEM
|
117
123
|
@description = opts[:description] || 'Unknown Application Type'
|
118
124
|
@exec = opts[:exec]
|
125
|
+
@console = opts[:console] || false
|
119
126
|
end
|
120
127
|
|
121
128
|
def to_s
|
data/lib/cli/manifest_helper.rb
CHANGED
@@ -125,10 +125,20 @@ module VMC::Cli::ManifestHelper
|
|
125
125
|
), "instances"
|
126
126
|
|
127
127
|
unless manifest "services"
|
128
|
+
user_services = client.services
|
129
|
+
user_services.sort! {|a, b| a[:name] <=> b[:name] }
|
130
|
+
|
131
|
+
unless user_services.empty?
|
132
|
+
if ask "Bind existing services to '#{name}'?", :default => false
|
133
|
+
bind_services(user_services)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
128
137
|
services = client.services_info
|
129
138
|
unless services.empty?
|
130
|
-
|
131
|
-
|
139
|
+
if ask "Create services to bind to '#{name}'?", :default => false
|
140
|
+
create_services(services.values.collect(&:keys).flatten)
|
141
|
+
end
|
132
142
|
end
|
133
143
|
end
|
134
144
|
|
@@ -174,20 +184,34 @@ module VMC::Cli::ManifestHelper
|
|
174
184
|
framework
|
175
185
|
end
|
176
186
|
|
177
|
-
def bind_services(
|
187
|
+
def bind_services(user_services, chosen = 0)
|
188
|
+
svcname = ask(
|
189
|
+
"Which one?",
|
190
|
+
:indexed => true,
|
191
|
+
:choices => user_services.collect { |p| p[:name] })
|
192
|
+
|
193
|
+
svc = user_services.find { |p| p[:name] == svcname }
|
194
|
+
|
195
|
+
set svc[:vendor], "services", svcname, "type"
|
196
|
+
|
197
|
+
if chosen + 1 < user_services.size && ask("Bind another?", :default => false)
|
198
|
+
bind_services(user_services, chosen + 1)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def create_services(services)
|
178
203
|
svcs = services.collect(&:to_s).sort!
|
179
204
|
|
180
|
-
display "The following system services are available"
|
181
205
|
configure_service(
|
182
206
|
ask(
|
183
|
-
"
|
207
|
+
"What kind of service?",
|
184
208
|
:indexed => true,
|
185
209
|
:choices => svcs
|
186
|
-
)
|
210
|
+
)
|
187
211
|
)
|
188
212
|
|
189
|
-
if ask "
|
190
|
-
|
213
|
+
if ask "Create another?", :default => false
|
214
|
+
create_services(services)
|
191
215
|
end
|
192
216
|
end
|
193
217
|
|
data/lib/cli/runner.rb
CHANGED
@@ -238,10 +238,6 @@ class VMC::Cli::Runner
|
|
238
238
|
usage('vmc restart <appname>')
|
239
239
|
set_cmd(:apps, :restart, @args.size == 1 ? 1 : 0)
|
240
240
|
|
241
|
-
when 'rename'
|
242
|
-
usage('vmc rename <appname> <newname>')
|
243
|
-
set_cmd(:apps, :rename, 2)
|
244
|
-
|
245
241
|
when 'mem'
|
246
242
|
usage('vmc mem <appname> [memsize]')
|
247
243
|
if @args.size == 2
|
@@ -380,6 +376,10 @@ class VMC::Cli::Runner
|
|
380
376
|
set_cmd(:services, :tunnel, 1) if @args.size == 1
|
381
377
|
set_cmd(:services, :tunnel, 2) if @args.size == 2
|
382
378
|
|
379
|
+
when 'rails-console'
|
380
|
+
usage('vmc rails-console <appname>')
|
381
|
+
set_cmd(:apps, :console, 1)
|
382
|
+
|
383
383
|
when 'help'
|
384
384
|
display_help if @args.size == 0
|
385
385
|
@help_only = true
|
@@ -478,6 +478,7 @@ class VMC::Cli::Runner
|
|
478
478
|
@exit_status = false
|
479
479
|
rescue VMC::Client::TargetError, VMC::Client::NotFound, VMC::Client::BadTarget => e
|
480
480
|
puts e.message.red
|
481
|
+
puts e.backtrace
|
481
482
|
@exit_status = false
|
482
483
|
rescue VMC::Client::HTTPException => e
|
483
484
|
puts e.message.red
|
data/lib/cli/tunnel_helper.rb
CHANGED
@@ -39,7 +39,6 @@ module VMC::Cli
|
|
39
39
|
name, val = e.split("=", 2)
|
40
40
|
return val if name == "CALDECOTT_AUTH"
|
41
41
|
end
|
42
|
-
|
43
42
|
nil
|
44
43
|
end
|
45
44
|
|
@@ -184,9 +183,7 @@ module VMC::Cli
|
|
184
183
|
display ''
|
185
184
|
end
|
186
185
|
|
187
|
-
def start_tunnel(
|
188
|
-
display "Starting tunnel to #{service.bold} on port #{local_port.to_s.bold}."
|
189
|
-
|
186
|
+
def start_tunnel(local_port, conn_info, auth)
|
190
187
|
@local_tunnel_thread = Thread.new do
|
191
188
|
Caldecott::Client.start({
|
192
189
|
:local_port => local_port,
|
@@ -203,6 +200,8 @@ module VMC::Cli
|
|
203
200
|
at_exit { @local_tunnel_thread.kill }
|
204
201
|
end
|
205
202
|
|
203
|
+
|
204
|
+
|
206
205
|
def pick_tunnel_port(port)
|
207
206
|
original = port
|
208
207
|
|
@@ -230,8 +229,9 @@ module VMC::Cli
|
|
230
229
|
def wait_for_tunnel_start(port)
|
231
230
|
10.times do |n|
|
232
231
|
begin
|
233
|
-
TCPSocket.open('localhost', port)
|
232
|
+
client = TCPSocket.open('localhost', port)
|
234
233
|
display '' if n > 0
|
234
|
+
client.close
|
235
235
|
return true
|
236
236
|
rescue => e
|
237
237
|
display "Waiting for local tunnel to become available", false if n == 0
|
@@ -297,28 +297,36 @@ module VMC::Cli
|
|
297
297
|
tunnel_appname,
|
298
298
|
{ :name => tunnel_appname,
|
299
299
|
:staging => {:framework => "sinatra"},
|
300
|
-
:uris => ["#{tunnel_uniquename}.#{
|
300
|
+
:uris => ["#{tunnel_uniquename}.#{target_base}"],
|
301
301
|
:instances => 1,
|
302
302
|
:resources => {:memory => 64},
|
303
303
|
:env => ["CALDECOTT_AUTH=#{token}"]
|
304
304
|
}
|
305
305
|
)
|
306
306
|
|
307
|
-
|
307
|
+
apps_cmd.send(:upload_app_bits, tunnel_appname, HELPER_APP)
|
308
308
|
|
309
309
|
invalidate_tunnel_app_info
|
310
310
|
end
|
311
311
|
|
312
312
|
def stop_caldecott
|
313
|
-
|
313
|
+
apps_cmd.stop(tunnel_appname)
|
314
314
|
|
315
315
|
invalidate_tunnel_app_info
|
316
316
|
end
|
317
317
|
|
318
318
|
def start_caldecott
|
319
|
-
|
319
|
+
apps_cmd.start(tunnel_appname)
|
320
320
|
|
321
321
|
invalidate_tunnel_app_info
|
322
322
|
end
|
323
|
+
|
324
|
+
private
|
325
|
+
|
326
|
+
def apps_cmd
|
327
|
+
a = Command::Apps.new(@options)
|
328
|
+
a.client client
|
329
|
+
a
|
330
|
+
end
|
323
331
|
end
|
324
332
|
end
|
data/lib/cli/usage.rb
CHANGED
@@ -47,7 +47,6 @@ Currently available vmc commands are:
|
|
47
47
|
stop <appname> Stop the application
|
48
48
|
restart <appname> [--debug [MODE]] Restart the application
|
49
49
|
delete <appname> Delete the application
|
50
|
-
rename <appname> <newname> Rename the application
|
51
50
|
|
52
51
|
Application Updates
|
53
52
|
update <appname> [--path,--debug [MODE]] Update the application bits
|
data/lib/cli/version.rb
CHANGED
data/lib/vmc/client.rb
CHANGED
@@ -39,7 +39,7 @@ class VMC::Client
|
|
39
39
|
def initialize(target_url=VMC::DEFAULT_TARGET, auth_token=nil)
|
40
40
|
target_url = "http://#{target_url}" unless /^https?/ =~ target_url
|
41
41
|
target_url = target_url.gsub(/\/+$/, '')
|
42
|
-
@target =
|
42
|
+
@target = target_url
|
43
43
|
@auth_token = auth_token
|
44
44
|
end
|
45
45
|
|
@@ -149,7 +149,7 @@ class VMC::Client
|
|
149
149
|
|
150
150
|
# List the directory or download the actual file indicated by
|
151
151
|
# the path.
|
152
|
-
def app_files(name, path, instance=0)
|
152
|
+
def app_files(name, path, instance='0')
|
153
153
|
check_login_status
|
154
154
|
path = path.gsub('//', '/')
|
155
155
|
url = path(VMC::APPS_PATH, name, "instances", instance, "files", path)
|
@@ -318,7 +318,7 @@ class VMC::Client
|
|
318
318
|
|
319
319
|
def self.path(*path)
|
320
320
|
path.flatten.collect { |x|
|
321
|
-
URI.encode x, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
|
321
|
+
URI.encode x.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
|
322
322
|
}.join("/")
|
323
323
|
end
|
324
324
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: vmc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease: 7
|
5
|
-
version: 0.3.16.beta.
|
5
|
+
version: 0.3.16.beta.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- VMware
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-02-07 00:00:00 -08:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -71,7 +71,7 @@ dependencies:
|
|
71
71
|
requirements:
|
72
72
|
- - ~>
|
73
73
|
- !ruby/object:Gem::Version
|
74
|
-
version: 0.
|
74
|
+
version: 0.4.0
|
75
75
|
type: :runtime
|
76
76
|
version_requirements: *id005
|
77
77
|
- !ruby/object:Gem::Dependency
|
@@ -151,6 +151,7 @@ files:
|
|
151
151
|
- lib/cli/commands/services.rb
|
152
152
|
- lib/cli/commands/user.rb
|
153
153
|
- lib/cli/config.rb
|
154
|
+
- lib/cli/console_helper.rb
|
154
155
|
- lib/cli/core_ext.rb
|
155
156
|
- lib/cli/errors.rb
|
156
157
|
- lib/cli/frameworks.rb
|