af 0.3.16.5 → 0.3.18.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/README.md +1 -1
- data/lib/cli.rb +4 -2
- data/lib/cli/commands/apps.rb +35 -17
- data/lib/cli/commands/base.rb +6 -1
- data/lib/cli/commands/services.rb +26 -19
- data/lib/cli/config.rb +2 -1
- data/lib/cli/console_helper.rb +29 -23
- data/lib/cli/frameworks.rb +42 -11
- data/lib/cli/infra_helper.rb +29 -0
- data/lib/cli/manifest_helper.rb +1 -1
- data/lib/cli/runner.rb +6 -2
- data/lib/cli/services_helper.rb +10 -3
- data/lib/cli/tunnel_helper.rb +46 -45
- data/lib/cli/version.rb +1 -1
- data/lib/cli/zip_util.rb +1 -1
- data/lib/vmc/client.rb +7 -3
- data/lib/vmc/const.rb +1 -1
- metadata +35 -25
data/README.md
CHANGED
@@ -4,7 +4,7 @@ The AppFog CLI. This is the command line interface to AppFog.com
|
|
4
4
|
|
5
5
|
af is based on vmc but will have features specific to the AppFog service as well as having the default target set to AppFog's service
|
6
6
|
|
7
|
-
_Copyright 2010-
|
7
|
+
_Copyright 2010-2012, VMware, Inc. Licensed under the
|
8
8
|
MIT license, please see the LICENSE file. All rights reserved._
|
9
9
|
|
10
10
|
Usage: af [options] command [<args>] [command_options]
|
data/lib/cli.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
|
-
WINDOWS = !!(RUBY_PLATFORM =~ /mingw|mswin32|cygwin/)
|
1
|
+
require "rbconfig"
|
3
2
|
|
3
|
+
ROOT = File.expand_path(File.dirname(__FILE__))
|
4
|
+
WINDOWS = !!(RbConfig::CONFIG['host_os'] =~ /mingw|mswin32|cygwin/)
|
4
5
|
|
5
6
|
module VMC
|
6
7
|
autoload :Client, "#{ROOT}/vmc/client"
|
@@ -26,6 +27,7 @@ module VMC
|
|
26
27
|
autoload :TunnelHelper, "#{ROOT}/cli/tunnel_helper"
|
27
28
|
autoload :ManifestHelper, "#{ROOT}/cli/manifest_helper"
|
28
29
|
autoload :ConsoleHelper, "#{ROOT}/cli/console_helper"
|
30
|
+
autoload :InfraHelper, "#{ROOT}/cli/infra_helper"
|
29
31
|
|
30
32
|
module Command
|
31
33
|
autoload :Base, "#{ROOT}/cli/commands/base"
|
data/lib/cli/commands/apps.rb
CHANGED
@@ -22,11 +22,18 @@ module VMC::Cli::Command
|
|
22
22
|
|
23
23
|
display "\n"
|
24
24
|
return display "No Applications" if apps.nil? || apps.empty?
|
25
|
+
|
26
|
+
infra_supported = !apps.detect { |a| a[:infra] }.nil?
|
25
27
|
|
26
28
|
apps_table = table do |t|
|
27
29
|
t.headings = 'Application', '# ', 'Health', 'URLS', 'Services'
|
30
|
+
t.headings << 'In' if infra_supported
|
28
31
|
apps.each do |app|
|
29
|
-
|
32
|
+
a = [app[:name], app[:instances], health(app), app[:uris].join(', '), app[:services].join(', ')]
|
33
|
+
if infra_supported
|
34
|
+
a << ( app[:infra] ? app[:infra][:provider] : " " )
|
35
|
+
end
|
36
|
+
t << a
|
30
37
|
end
|
31
38
|
end
|
32
39
|
display apps_table
|
@@ -48,6 +55,10 @@ module VMC::Cli::Command
|
|
48
55
|
end
|
49
56
|
|
50
57
|
def console(appname, interactive=true)
|
58
|
+
|
59
|
+
app = client.app_info(appname)
|
60
|
+
infra_name = app[:infra] ? app[:infra][:name] : 'aws' # FIXME
|
61
|
+
|
51
62
|
unless defined? Caldecott
|
52
63
|
display "To use `vmc rails-console', you must first install Caldecott:"
|
53
64
|
display ""
|
@@ -68,26 +79,27 @@ module VMC::Cli::Command
|
|
68
79
|
|
69
80
|
raise VMC::Client::AuthError unless client.logged_in?
|
70
81
|
|
71
|
-
if not tunnel_pushed?
|
72
|
-
display "Deploying tunnel application '#{tunnel_appname}'."
|
82
|
+
if not tunnel_pushed?(infra_name)
|
83
|
+
display "Deploying tunnel application '#{tunnel_appname(infra_name)}'."
|
73
84
|
auth = UUIDTools::UUID.random_create.to_s
|
74
|
-
push_caldecott(auth)
|
75
|
-
start_caldecott
|
85
|
+
push_caldecott(auth,infra_name)
|
86
|
+
start_caldecott(infra_name)
|
76
87
|
else
|
77
|
-
auth = tunnel_auth
|
88
|
+
auth = tunnel_auth(infra_name)
|
78
89
|
end
|
79
90
|
|
80
|
-
|
81
|
-
|
91
|
+
|
92
|
+
if not tunnel_healthy?(auth,infra_name)
|
93
|
+
display "Redeploying tunnel application '#{tunnel_appname(infra_name)}'."
|
82
94
|
# We don't expect caldecott not to be running, so take the
|
83
95
|
# 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
|
96
|
+
client.delete_app(tunnel_appname(infra_name))
|
97
|
+
invalidate_tunnel_app_info(infra_name)
|
98
|
+
push_caldecott(auth,infra_name)
|
99
|
+
start_caldecott(infra_name)
|
88
100
|
end
|
89
101
|
|
90
|
-
start_tunnel(port, conn_info, auth)
|
102
|
+
start_tunnel(port, conn_info, auth, infra_name)
|
91
103
|
wait_for_tunnel_start(port)
|
92
104
|
start_local_console(port, appname) if interactive
|
93
105
|
port
|
@@ -894,6 +906,7 @@ module VMC::Cli::Command
|
|
894
906
|
end
|
895
907
|
|
896
908
|
def do_push(appname=nil)
|
909
|
+
|
897
910
|
unless @app_info || no_prompt
|
898
911
|
@manifest = { "applications" => { @path => { "name" => appname } } }
|
899
912
|
|
@@ -920,6 +933,11 @@ module VMC::Cli::Command
|
|
920
933
|
memswitch = normalize_mem(memswitch) if memswitch
|
921
934
|
command = info(:command)
|
922
935
|
runtime = info(:runtime)
|
936
|
+
infra = info(:infra)
|
937
|
+
|
938
|
+
if infra
|
939
|
+
err "Infra '#{infra}' is not valid" unless VMC::Cli::InfraHelper.valid?(infra)
|
940
|
+
end
|
923
941
|
|
924
942
|
# Check app existing upfront if we have appname
|
925
943
|
app_checked = false
|
@@ -968,7 +986,6 @@ module VMC::Cli::Command
|
|
968
986
|
default_url = "None"
|
969
987
|
default_url = "#{appname}.#{VMC::Cli::Config.suggest_url}" if framework.require_url?
|
970
988
|
|
971
|
-
|
972
989
|
unless no_prompt || url || !framework.require_url?
|
973
990
|
url = ask(
|
974
991
|
"Application Deployed URL",
|
@@ -1015,18 +1032,19 @@ module VMC::Cli::Command
|
|
1015
1032
|
}
|
1016
1033
|
}
|
1017
1034
|
manifest[:staging][:command] = command if command
|
1018
|
-
|
1035
|
+
manifest[:infra] = { :provider => infra } if infra
|
1036
|
+
|
1019
1037
|
# Send the manifest to the cloud controller
|
1020
1038
|
client.create_app(appname, manifest)
|
1021
1039
|
display 'OK'.green
|
1022
1040
|
|
1023
|
-
|
1041
|
+
|
1024
1042
|
existing = Set.new(client.services.collect { |s| s[:name] })
|
1025
1043
|
|
1026
1044
|
if @app_info && services = @app_info["services"]
|
1027
1045
|
services.each do |name, info|
|
1028
1046
|
unless existing.include? name
|
1029
|
-
create_service_banner(info["type"], name, true)
|
1047
|
+
create_service_banner(info["type"], name, true, infra)
|
1030
1048
|
end
|
1031
1049
|
|
1032
1050
|
bind_service_banner(name, appname)
|
data/lib/cli/commands/base.rb
CHANGED
@@ -27,7 +27,7 @@ module VMC::Cli
|
|
27
27
|
|
28
28
|
load_manifest manifest_file if manifest_file
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
def manifest_file
|
32
32
|
return @options[:manifest] if @options[:manifest]
|
33
33
|
return @manifest_file if @manifest_file
|
@@ -221,6 +221,11 @@ module VMC::Cli
|
|
221
221
|
end
|
222
222
|
@frameworks
|
223
223
|
end
|
224
|
+
|
225
|
+
def default_infra
|
226
|
+
"aws"
|
227
|
+
end
|
228
|
+
|
224
229
|
end
|
225
230
|
end
|
226
231
|
end
|
@@ -38,7 +38,7 @@ module VMC::Cli::Command
|
|
38
38
|
name = random_service_name(service)
|
39
39
|
picked_name = true
|
40
40
|
end
|
41
|
-
create_service_banner(service, name, picked_name)
|
41
|
+
create_service_banner(service, name, picked_name, @options[:infra])
|
42
42
|
appname = @options[:bind] unless appname
|
43
43
|
bind_service_banner(name, appname) if appname
|
44
44
|
end
|
@@ -118,37 +118,44 @@ module VMC::Cli::Command
|
|
118
118
|
|
119
119
|
raise VMC::Client::AuthError unless client.logged_in?
|
120
120
|
|
121
|
-
|
122
|
-
|
121
|
+
infra_name = info[:infra] ? info[:infra][:name] : default_infra
|
122
|
+
|
123
|
+
if infra_name
|
124
|
+
err "Infra '#{infra_name}' is not valid" unless VMC::Cli::InfraHelper.valid?(infra_name)
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
if not tunnel_pushed?(infra_name)
|
129
|
+
display "Deploying tunnel application '#{tunnel_appname(infra_name)}'."
|
123
130
|
auth = UUIDTools::UUID.random_create.to_s
|
124
|
-
push_caldecott(auth)
|
125
|
-
bind_service_banner(service, tunnel_appname, false)
|
126
|
-
start_caldecott
|
131
|
+
push_caldecott(auth,infra_name)
|
132
|
+
bind_service_banner(service, tunnel_appname(infra_name), false)
|
133
|
+
start_caldecott(infra_name)
|
127
134
|
else
|
128
|
-
auth = tunnel_auth
|
135
|
+
auth = tunnel_auth(infra_name)
|
129
136
|
end
|
130
137
|
|
131
|
-
if not tunnel_healthy?(auth)
|
132
|
-
display "Redeploying tunnel application '#{tunnel_appname}'."
|
138
|
+
if not tunnel_healthy?(auth,infra_name)
|
139
|
+
display "Redeploying tunnel application '#{tunnel_appname(infra_name)}'."
|
133
140
|
|
134
141
|
# We don't expect caldecott not to be running, so take the
|
135
142
|
# most aggressive restart method.. delete/re-push
|
136
|
-
client.delete_app(tunnel_appname)
|
137
|
-
invalidate_tunnel_app_info
|
143
|
+
client.delete_app(tunnel_appname(infra_name))
|
144
|
+
invalidate_tunnel_app_info(infra_name)
|
138
145
|
|
139
|
-
push_caldecott(auth)
|
140
|
-
bind_service_banner(service, tunnel_appname, false)
|
141
|
-
start_caldecott
|
146
|
+
push_caldecott(auth,infra_name)
|
147
|
+
bind_service_banner(service, tunnel_appname(infra_name), false)
|
148
|
+
start_caldecott(infra_name)
|
142
149
|
end
|
143
150
|
|
144
|
-
if not tunnel_bound?(service)
|
145
|
-
bind_service_banner(service, tunnel_appname)
|
151
|
+
if not tunnel_bound?(service,infra_name)
|
152
|
+
bind_service_banner(service, tunnel_appname(infra_name))
|
146
153
|
end
|
147
154
|
|
148
|
-
conn_info = tunnel_connection_info info[:vendor], service, auth
|
155
|
+
conn_info = tunnel_connection_info info[:vendor], service, auth, infra_name
|
149
156
|
display_tunnel_connection_info(conn_info)
|
150
157
|
display "Starting tunnel to #{service.bold} on port #{port.to_s.bold}."
|
151
|
-
start_tunnel(port, conn_info, auth)
|
158
|
+
start_tunnel(port, conn_info, auth, infra_name)
|
152
159
|
|
153
160
|
clients = get_clients_for(info[:vendor])
|
154
161
|
|
@@ -167,7 +174,7 @@ module VMC::Cli::Command
|
|
167
174
|
else
|
168
175
|
wait_for_tunnel_start(port)
|
169
176
|
unless start_local_prog(clients, client_name, conn_info, port)
|
170
|
-
err "'#{client_name}'
|
177
|
+
err "'#{client_name}' execution failed; is it in your $PATH?"
|
171
178
|
end
|
172
179
|
end
|
173
180
|
end
|
data/lib/cli/config.rb
CHANGED
@@ -23,6 +23,7 @@ module VMC::Cli
|
|
23
23
|
attr_accessor :output
|
24
24
|
attr_accessor :trace
|
25
25
|
attr_accessor :nozip
|
26
|
+
attr_accessor :infra
|
26
27
|
|
27
28
|
def target_url
|
28
29
|
return @target_url if @target_url
|
@@ -42,7 +43,7 @@ module VMC::Cli
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def suggest_url
|
45
|
-
@suggest_url ||=
|
46
|
+
@suggest_url ||= VMC::Cli::InfraHelper.base_for_infra(@infra)
|
46
47
|
end
|
47
48
|
|
48
49
|
def store_target(target_host)
|
data/lib/cli/console_helper.rb
CHANGED
@@ -27,7 +27,10 @@ module VMC::Cli
|
|
27
27
|
"Please redeploy your app to enable support."
|
28
28
|
end
|
29
29
|
end
|
30
|
-
conn_info = {
|
30
|
+
conn_info = {
|
31
|
+
'hostname' => entry[:console_ip],
|
32
|
+
'port' => entry[:console_port]
|
33
|
+
}
|
31
34
|
end
|
32
35
|
|
33
36
|
def start_local_console(port, appname)
|
@@ -50,13 +53,14 @@ module VMC::Cli
|
|
50
53
|
5.times do
|
51
54
|
begin
|
52
55
|
results = @telnet_client.login("Name"=>auth_info["username"],
|
53
|
-
"Password"=>auth_info["password"])
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
"Password"=>auth_info["password"])
|
57
|
+
lines = results.sub("Login: Password: ", "").split("\n")
|
58
|
+
last_line = lines.pop
|
59
|
+
if last_line =~ /[$%#>] \z/n
|
60
|
+
prompt = last_line
|
61
|
+
elsif last_line =~ /Login failed/
|
62
|
+
err_msg = last_line
|
63
|
+
end
|
60
64
|
break
|
61
65
|
rescue TimeoutError
|
62
66
|
sleep 1
|
@@ -104,29 +108,31 @@ module VMC::Cli
|
|
104
108
|
end
|
105
109
|
|
106
110
|
def readline_with_history(prompt)
|
107
|
-
line = Readline
|
108
|
-
return ''
|
109
|
-
|
110
|
-
if line =~ /^\s*$/ or Readline::HISTORY.to_a[-2] == line
|
111
|
-
Readline::HISTORY.pop
|
112
|
-
end
|
111
|
+
line = Readline::readline(prompt)
|
112
|
+
return nil if line == nil || line == 'quit' || line == 'exit'
|
113
|
+
Readline::HISTORY.push(line) if not line =~ /^\s*$/ and Readline::HISTORY.to_a[-1] != line
|
113
114
|
line
|
114
115
|
end
|
115
116
|
|
116
117
|
def run_console(prompt)
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
118
|
+
prev = trap("INT") { |x| exit_console; prev.call(x); exit }
|
119
|
+
prev = trap("TERM") { |x| exit_console; prev.call(x); exit }
|
120
|
+
loop do
|
121
|
+
cmd = readline_with_history(prompt)
|
122
|
+
if(cmd == nil)
|
123
|
+
exit_console
|
122
124
|
break
|
123
125
|
end
|
124
|
-
|
125
|
-
prompt = send_console_command_display_results(cmd, prompt)
|
126
|
-
end
|
126
|
+
prompt = send_console_command_display_results(cmd, prompt)
|
127
127
|
end
|
128
128
|
end
|
129
129
|
|
130
|
+
def exit_console
|
131
|
+
#TimeoutError expected, as exit doesn't return anything
|
132
|
+
@telnet_client.cmd("String"=>"exit","Timeout"=>1) rescue TimeoutError
|
133
|
+
close_console
|
134
|
+
end
|
135
|
+
|
130
136
|
def send_console_command_display_results(cmd, prompt)
|
131
137
|
begin
|
132
138
|
lines = send_console_command cmd
|
@@ -154,4 +160,4 @@ module VMC::Cli
|
|
154
160
|
}
|
155
161
|
end
|
156
162
|
end
|
157
|
-
end
|
163
|
+
end
|
data/lib/cli/frameworks.rb
CHANGED
@@ -18,13 +18,19 @@ module VMC::Cli
|
|
18
18
|
'Erlang/OTP Rebar' => ['otp_rebar', { :mem => '64M', :description => 'Erlang/OTP Rebar Application'}],
|
19
19
|
'WSGI' => ['wsgi', { :mem => '64M', :description => 'Python WSGI Application'}],
|
20
20
|
'Django' => ['django', { :mem => '128M', :description => 'Python Django Application'}],
|
21
|
-
'
|
21
|
+
'dotNet' => ['dotNet', { :mem => '128M', :description => '.Net Web Application'}],
|
22
|
+
'Rack' => ['rack', { :mem => '128M', :description => 'Rack Application'}],
|
23
|
+
'Play' => ['play', { :mem => '256M', :description => 'Play Framework Application'}]
|
22
24
|
}
|
23
25
|
|
24
26
|
class << self
|
25
27
|
|
26
|
-
def known_frameworks
|
27
|
-
|
28
|
+
def known_frameworks(available_frameworks)
|
29
|
+
frameworks = []
|
30
|
+
FRAMEWORKS.each do |key,fw|
|
31
|
+
frameworks << key if available_frameworks.include? [fw[0]]
|
32
|
+
end
|
33
|
+
frameworks
|
28
34
|
end
|
29
35
|
|
30
36
|
def lookup(name)
|
@@ -49,6 +55,8 @@ module VMC::Cli
|
|
49
55
|
if !File.directory? path
|
50
56
|
if path.end_with?('.war')
|
51
57
|
return detect_framework_from_war path
|
58
|
+
elsif path.end_with?('.zip')
|
59
|
+
return detect_framework_from_zip path, available_frameworks
|
52
60
|
elsif available_frameworks.include?(["standalone"])
|
53
61
|
return Framework.lookup('Standalone')
|
54
62
|
else
|
@@ -78,7 +86,7 @@ module VMC::Cli
|
|
78
86
|
next if matched_file
|
79
87
|
File.open(fname, 'r') do |f|
|
80
88
|
str = f.read # This might want to be limited
|
81
|
-
matched_file = fname if (str && str.match(/^\s*require
|
89
|
+
matched_file = fname if (str && str.match(/^\s*\#?\s*require\s*\(?\s*['"]sinatra['"]/))
|
82
90
|
end
|
83
91
|
end
|
84
92
|
if matched_file
|
@@ -87,11 +95,7 @@ module VMC::Cli
|
|
87
95
|
f.exec = "ruby #{matched_file}"
|
88
96
|
return f
|
89
97
|
end
|
90
|
-
|
91
|
-
elsif !Dir.glob('*.js').empty?
|
92
|
-
if File.exist?('server.js') || File.exist?('app.js') || File.exist?('index.js') || File.exist?('main.js')
|
93
|
-
return Framework.lookup('Node')
|
94
|
-
end
|
98
|
+
|
95
99
|
# PHP
|
96
100
|
elsif !Dir.glob('*.php').empty?
|
97
101
|
return Framework.lookup('PHP')
|
@@ -108,6 +112,21 @@ module VMC::Cli
|
|
108
112
|
# Python
|
109
113
|
elsif !Dir.glob('wsgi.py').empty?
|
110
114
|
return Framework.lookup('WSGI')
|
115
|
+
|
116
|
+
# .Net
|
117
|
+
elsif !Dir.glob('web.config').empty?
|
118
|
+
return Framework.lookup('dotNet')
|
119
|
+
|
120
|
+
# Node.js
|
121
|
+
elsif !Dir.glob('*.js').empty?
|
122
|
+
if File.exist?('server.js') || File.exist?('app.js') || File.exist?('index.js') || File.exist?('main.js')
|
123
|
+
return Framework.lookup('Node')
|
124
|
+
end
|
125
|
+
|
126
|
+
# Play or Standalone Apps
|
127
|
+
elsif Dir.glob('*.zip').first
|
128
|
+
zip_file = Dir.glob('*.zip').first
|
129
|
+
return detect_framework_from_zip zip_file, available_frameworks
|
111
130
|
end
|
112
131
|
|
113
132
|
# Default to Standalone if no other match was made
|
@@ -115,7 +134,6 @@ module VMC::Cli
|
|
115
134
|
end
|
116
135
|
end
|
117
136
|
|
118
|
-
private
|
119
137
|
def detect_framework_from_war(war_file=nil)
|
120
138
|
if war_file
|
121
139
|
contents = ZipUtil.entry_lines(war_file)
|
@@ -139,6 +157,19 @@ module VMC::Cli
|
|
139
157
|
return Framework.lookup('JavaWeb')
|
140
158
|
end
|
141
159
|
end
|
160
|
+
|
161
|
+
def detect_framework_from_zip(zip_file, available_frameworks)
|
162
|
+
contents = ZipUtil.entry_lines(zip_file)
|
163
|
+
detect_framework_from_zip_contents(contents, available_frameworks)
|
164
|
+
end
|
165
|
+
|
166
|
+
def detect_framework_from_zip_contents(contents, available_frameworks)
|
167
|
+
if available_frameworks.include?(["play"]) && contents =~ /lib\/play\..*\.jar/
|
168
|
+
return Framework.lookup('Play')
|
169
|
+
elsif available_frameworks.include?(["standalone"])
|
170
|
+
return Framework.lookup('Standalone')
|
171
|
+
end
|
172
|
+
end
|
142
173
|
end
|
143
174
|
|
144
175
|
attr_reader :name, :description, :console
|
@@ -218,7 +249,7 @@ module VMC::Cli
|
|
218
249
|
def memory(runtime=nil)
|
219
250
|
default_mem = @memory
|
220
251
|
default_mem = '128M' if runtime =~ /\Aruby/ || runtime == "php"
|
221
|
-
default_mem = '512M' if runtime == "java"
|
252
|
+
default_mem = '512M' if runtime == "java" || runtime == "java7"
|
222
253
|
default_mem
|
223
254
|
end
|
224
255
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module VMC::Cli
|
4
|
+
module InfraHelper
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def base_for_infra(infra)
|
9
|
+
infras.has_key?(infra) ? infras[infra][:base] : "aws.af.cm"
|
10
|
+
end
|
11
|
+
|
12
|
+
def valid?(infra)
|
13
|
+
infra && infras.has_key?(infra)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def infras
|
18
|
+
{
|
19
|
+
"ap-aws" => { :base => "ap01.aws.af.cm" },
|
20
|
+
"eu-aws" => { :base => "eu01.aws.af.cm" },
|
21
|
+
"rs" => { :base => "rs.af.cm" },
|
22
|
+
"aws" => { :base => "aws.af.cm" }
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/cli/manifest_helper.rb
CHANGED
@@ -197,7 +197,7 @@ module VMC::Cli::ManifestHelper
|
|
197
197
|
"Select Application Type",
|
198
198
|
:indexed => true,
|
199
199
|
:default => framework,
|
200
|
-
:choices => VMC::Cli::Framework.known_frameworks
|
200
|
+
:choices => VMC::Cli::Framework.known_frameworks(frameworks_info)
|
201
201
|
)
|
202
202
|
)
|
203
203
|
display "Selected #{framework}"
|
data/lib/cli/runner.rb
CHANGED
@@ -98,6 +98,9 @@ class VMC::Cli::Runner
|
|
98
98
|
|
99
99
|
# Proxying for another user, requires admin privileges
|
100
100
|
opts.on('-u PROXY') { |proxy| @options[:proxy] = proxy }
|
101
|
+
|
102
|
+
# Select infrastructure
|
103
|
+
opts.on('--infra INFRA') { |infra| @options[:infra] = infra }
|
101
104
|
|
102
105
|
opts.on_tail('--options') { puts "#{opts}\n"; exit }
|
103
106
|
end
|
@@ -301,7 +304,7 @@ class VMC::Cli::Runner
|
|
301
304
|
set_cmd(:apps, :crashlogs, 1)
|
302
305
|
|
303
306
|
when 'push'
|
304
|
-
usage('af push [appname] [--path PATH] [--url URL] [--instances N] [--mem] [--runtime RUNTIME] [--no-start]')
|
307
|
+
usage('af push [appname] [--path PATH] [--url URL] [--instances N] [--mem] [--runtime RUNTIME] [--no-start] [--infra infraname]')
|
305
308
|
if @args.size == 1
|
306
309
|
set_cmd(:apps, :push, 1)
|
307
310
|
else
|
@@ -333,7 +336,7 @@ class VMC::Cli::Runner
|
|
333
336
|
set_cmd(:apps, :environment_del, 2)
|
334
337
|
|
335
338
|
when 'create-service', 'create_service'
|
336
|
-
usage('af create-service [service] [servicename] [appname] [--name servicename] [--bind appname]')
|
339
|
+
usage('af create-service [service] [servicename] [appname] [--name servicename] [--bind appname] [--infra infraname]')
|
337
340
|
set_cmd(:services, :create_service) if @args.size == 0
|
338
341
|
set_cmd(:services, :create_service, 1) if @args.size == 1
|
339
342
|
set_cmd(:services, :create_service, 2) if @args.size == 2
|
@@ -456,6 +459,7 @@ class VMC::Cli::Runner
|
|
456
459
|
VMC::Cli::Config.nozip = @options.delete(:nozip)
|
457
460
|
VMC::Cli::Config.trace = @options.delete(:trace)
|
458
461
|
VMC::Cli::Config.output ||= STDOUT unless @options[:quiet]
|
462
|
+
VMC::Cli::Config.infra = @options[:infra]
|
459
463
|
|
460
464
|
process_aliases!
|
461
465
|
parse_command!
|
data/lib/cli/services_helper.rb
CHANGED
@@ -33,19 +33,26 @@ module VMC::Cli
|
|
33
33
|
|
34
34
|
def display_provisioned_services_table(services)
|
35
35
|
return unless services && !services.empty?
|
36
|
+
|
37
|
+
infra_supported = !services.detect { |a| a[:infra] }.nil?
|
36
38
|
services_table = table do |t|
|
37
39
|
t.headings = 'Name', 'Service'
|
40
|
+
t.headings << 'In' if infra_supported
|
38
41
|
services.each do |service|
|
39
|
-
|
42
|
+
s = [ service[:name], service[:vendor] ]
|
43
|
+
if infra_supported
|
44
|
+
s << ( service[:infra] ? service[:infra][:provider] : " " )
|
45
|
+
end
|
46
|
+
t << s
|
40
47
|
end
|
41
48
|
end
|
42
49
|
display services_table
|
43
50
|
end
|
44
51
|
|
45
|
-
def create_service_banner(service, name, display_name=false)
|
52
|
+
def create_service_banner(service, name, display_name=false, infra=nil)
|
46
53
|
sn = " [#{name}]" if display_name
|
47
54
|
display "Creating Service#{sn}: ", false
|
48
|
-
client.create_service(service, name)
|
55
|
+
client.create_service(infra,service, name)
|
49
56
|
display 'OK'.green
|
50
57
|
end
|
51
58
|
|
data/lib/cli/tunnel_helper.rb
CHANGED
@@ -17,35 +17,33 @@ module VMC::Cli
|
|
17
17
|
# this is to keep the helper in sync with any updates here
|
18
18
|
HELPER_VERSION = '0.0.4'
|
19
19
|
|
20
|
-
def tunnel_uniquename
|
21
|
-
random_service_name(tunnel_appname)
|
20
|
+
def tunnel_uniquename(infra)
|
21
|
+
random_service_name(tunnel_appname(infra))
|
22
22
|
end
|
23
23
|
|
24
|
-
def tunnel_appname
|
25
|
-
"caldecott"
|
24
|
+
def tunnel_appname(infra)
|
25
|
+
infra ? "caldecott-#{infra}" : "caldecott"
|
26
26
|
end
|
27
27
|
|
28
|
-
def tunnel_app_info
|
29
|
-
return @tun_app_info if @tunnel_app_info
|
28
|
+
def tunnel_app_info(infra)
|
30
29
|
begin
|
31
|
-
|
30
|
+
client.app_info(tunnel_appname(infra))
|
32
31
|
rescue => e
|
33
|
-
|
32
|
+
nil
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
37
|
-
def tunnel_auth
|
38
|
-
tunnel_app_info[:env].each do |e|
|
36
|
+
def tunnel_auth(infra)
|
37
|
+
tunnel_app_info(infra)[:env].each do |e|
|
39
38
|
name, val = e.split("=", 2)
|
40
39
|
return val if name == "CALDECOTT_AUTH"
|
41
40
|
end
|
42
41
|
nil
|
43
42
|
end
|
44
43
|
|
45
|
-
def tunnel_url
|
46
|
-
return @tunnel_url if @tunnel_url
|
44
|
+
def tunnel_url(infra)
|
47
45
|
|
48
|
-
tun_url = tunnel_app_info[:uris][0]
|
46
|
+
tun_url = tunnel_app_info(infra)[:uris][0]
|
49
47
|
|
50
48
|
["https", "http"].each do |scheme|
|
51
49
|
url = "#{scheme}://#{tun_url}"
|
@@ -57,54 +55,51 @@ module VMC::Cli
|
|
57
55
|
|
58
56
|
# we expect a 404 since this request isn't auth'd
|
59
57
|
rescue RestClient::ResourceNotFound
|
60
|
-
return
|
58
|
+
return url
|
61
59
|
end
|
62
60
|
end
|
63
61
|
|
64
62
|
err "Cannot determine URL for #{tun_url}"
|
65
63
|
end
|
66
64
|
|
67
|
-
def invalidate_tunnel_app_info
|
68
|
-
@tunnel_url = nil
|
69
|
-
@tunnel_app_info = nil
|
65
|
+
def invalidate_tunnel_app_info(infra)
|
70
66
|
end
|
71
67
|
|
72
|
-
def tunnel_pushed?
|
73
|
-
not tunnel_app_info.nil?
|
68
|
+
def tunnel_pushed?(infra)
|
69
|
+
not tunnel_app_info(infra).nil?
|
74
70
|
end
|
75
71
|
|
76
|
-
def tunnel_healthy?(token)
|
77
|
-
return false unless tunnel_app_info[:state] == 'STARTED'
|
72
|
+
def tunnel_healthy?(token,infra)
|
73
|
+
return false unless tunnel_app_info(infra)[:state] == 'STARTED'
|
78
74
|
|
79
75
|
begin
|
80
76
|
response = RestClient.get(
|
81
|
-
"#{tunnel_url}/info",
|
77
|
+
"#{tunnel_url(infra)}/info",
|
82
78
|
"Auth-Token" => token
|
83
79
|
)
|
84
|
-
|
85
80
|
info = JSON.parse(response)
|
86
81
|
if info["version"] == HELPER_VERSION
|
87
82
|
true
|
88
83
|
else
|
89
|
-
stop_caldecott
|
84
|
+
stop_caldecott(infra)
|
90
85
|
false
|
91
86
|
end
|
92
87
|
rescue RestClient::Exception
|
93
|
-
stop_caldecott
|
88
|
+
stop_caldecott(infra)
|
94
89
|
false
|
95
90
|
end
|
96
91
|
end
|
97
92
|
|
98
|
-
def tunnel_bound?(service)
|
99
|
-
tunnel_app_info[:services].include?(service)
|
93
|
+
def tunnel_bound?(service,infra)
|
94
|
+
tunnel_app_info(infra)[:services].include?(service)
|
100
95
|
end
|
101
96
|
|
102
|
-
def tunnel_connection_info(type, service, token)
|
97
|
+
def tunnel_connection_info(type, service, token, infra)
|
103
98
|
display "Getting tunnel connection info: ", false
|
104
99
|
response = nil
|
105
100
|
10.times do
|
106
101
|
begin
|
107
|
-
response = RestClient.get(tunnel_url + "/" + VMC::Client.path("services", service), "Auth-Token" => token)
|
102
|
+
response = RestClient.get(tunnel_url(infra) + "/" + VMC::Client.path("services", service), "Auth-Token" => token)
|
108
103
|
break
|
109
104
|
rescue RestClient::Exception
|
110
105
|
sleep 1
|
@@ -120,6 +115,7 @@ module VMC::Cli
|
|
120
115
|
display "OK".green
|
121
116
|
|
122
117
|
info = JSON.parse(response)
|
118
|
+
info["infra"] = infra
|
123
119
|
case type
|
124
120
|
when "rabbitmq"
|
125
121
|
uri = Addressable::URI.parse info["url"]
|
@@ -183,11 +179,11 @@ module VMC::Cli
|
|
183
179
|
display ''
|
184
180
|
end
|
185
181
|
|
186
|
-
def start_tunnel(local_port, conn_info, auth)
|
182
|
+
def start_tunnel(local_port, conn_info, auth, infra)
|
187
183
|
@local_tunnel_thread = Thread.new do
|
188
184
|
Caldecott::Client.start({
|
189
185
|
:local_port => local_port,
|
190
|
-
:tun_url => tunnel_url,
|
186
|
+
:tun_url => tunnel_url(infra),
|
191
187
|
:dst_host => conn_info['hostname'],
|
192
188
|
:dst_port => conn_info['port'],
|
193
189
|
:log_file => STDOUT,
|
@@ -292,33 +288,37 @@ module VMC::Cli
|
|
292
288
|
system(cmdline)
|
293
289
|
end
|
294
290
|
|
295
|
-
def push_caldecott(token)
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
:
|
300
|
-
:uris => ["#{tunnel_uniquename}.#{target_base}"],
|
291
|
+
def push_caldecott(token,infra)
|
292
|
+
manifest = {
|
293
|
+
:name => tunnel_appname(infra),
|
294
|
+
:staging => {:framework => "sinatra", :runtime => "ruby18" },
|
295
|
+
:uris => ["#{tunnel_uniquename(infra)}.#{VMC::Cli::InfraHelper.base_for_infra(infra)}"],
|
301
296
|
:instances => 1,
|
302
297
|
:resources => {:memory => 64},
|
303
298
|
:env => ["CALDECOTT_AUTH=#{token}"]
|
304
299
|
}
|
300
|
+
manifest[:infra] = { :provider => infra } if infra
|
301
|
+
|
302
|
+
client.create_app(
|
303
|
+
tunnel_appname(infra),
|
304
|
+
manifest
|
305
305
|
)
|
306
306
|
|
307
|
-
apps_cmd.send(:upload_app_bits, tunnel_appname, HELPER_APP)
|
307
|
+
apps_cmd.send(:upload_app_bits, tunnel_appname(infra), HELPER_APP)
|
308
308
|
|
309
|
-
invalidate_tunnel_app_info
|
309
|
+
invalidate_tunnel_app_info(infra)
|
310
310
|
end
|
311
311
|
|
312
|
-
def stop_caldecott
|
313
|
-
apps_cmd.stop(tunnel_appname)
|
312
|
+
def stop_caldecott(infra)
|
313
|
+
apps_cmd.stop(tunnel_appname(infra))
|
314
314
|
|
315
|
-
invalidate_tunnel_app_info
|
315
|
+
invalidate_tunnel_app_info(infra)
|
316
316
|
end
|
317
317
|
|
318
|
-
def start_caldecott
|
319
|
-
apps_cmd.start(tunnel_appname)
|
318
|
+
def start_caldecott(infra)
|
319
|
+
apps_cmd.start(tunnel_appname(infra))
|
320
320
|
|
321
|
-
invalidate_tunnel_app_info
|
321
|
+
invalidate_tunnel_app_info(infra)
|
322
322
|
end
|
323
323
|
|
324
324
|
private
|
@@ -328,5 +328,6 @@ module VMC::Cli
|
|
328
328
|
a.client client
|
329
329
|
a
|
330
330
|
end
|
331
|
+
|
331
332
|
end
|
332
333
|
end
|
data/lib/cli/version.rb
CHANGED
data/lib/cli/zip_util.rb
CHANGED
data/lib/vmc/client.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# client = VMC::Client.new('api.vcap.me')
|
7
7
|
# client.login(:user, :pass)
|
8
8
|
# client.create('myapplication', manifest)
|
9
|
-
# client.create_service('redis', 'my_redis_service', opts);
|
9
|
+
# client.create_service('aws', 'redis', 'my_redis_service', opts);
|
10
10
|
#
|
11
11
|
|
12
12
|
require 'rubygems'
|
@@ -27,6 +27,9 @@ class VMC::Client
|
|
27
27
|
# Error codes
|
28
28
|
VMC_HTTP_ERROR_CODES = [ 400, 500 ]
|
29
29
|
|
30
|
+
HTTP_TIMEOUT = ENV['TIMEOUT'].to_i if ENV['TIMEOUT']
|
31
|
+
HTTP_TIMEOUT ||= 10*60
|
32
|
+
|
30
33
|
# Errors
|
31
34
|
class BadTarget < RuntimeError; end
|
32
35
|
class AuthError < RuntimeError; end
|
@@ -167,7 +170,7 @@ class VMC::Client
|
|
167
170
|
json_get(VMC::SERVICES_PATH)
|
168
171
|
end
|
169
172
|
|
170
|
-
def create_service(service, name)
|
173
|
+
def create_service(infra,service, name)
|
171
174
|
check_login_status
|
172
175
|
services = services_info
|
173
176
|
services ||= []
|
@@ -184,6 +187,7 @@ class VMC::Client
|
|
184
187
|
:type => service_descr[:type], :tier => 'free',
|
185
188
|
:vendor => service, :version => version_str
|
186
189
|
}
|
190
|
+
service_hash[:infra] = { :provider => infra } if infra
|
187
191
|
break
|
188
192
|
end
|
189
193
|
end
|
@@ -382,7 +386,7 @@ class VMC::Client
|
|
382
386
|
req = {
|
383
387
|
:method => method, :url => "#{@target}/#{path}",
|
384
388
|
:payload => payload, :headers => headers, :multipart => true,
|
385
|
-
:timeout =>
|
389
|
+
:timeout => HTTP_TIMEOUT, :open_timeout => HTTP_TIMEOUT
|
386
390
|
}
|
387
391
|
status, body, response_headers = perform_http_request(req)
|
388
392
|
|
data/lib/vmc/const.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: af
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.18.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,12 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
13
|
-
default_executable:
|
12
|
+
date: 2012-08-07 00:00:00.000000000Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: json_pure
|
17
|
-
requirement: &
|
16
|
+
requirement: &70266170534240 !ruby/object:Gem::Requirement
|
18
17
|
none: false
|
19
18
|
requirements:
|
20
19
|
- - ! '>='
|
@@ -25,10 +24,10 @@ dependencies:
|
|
25
24
|
version: 1.7.0
|
26
25
|
type: :runtime
|
27
26
|
prerelease: false
|
28
|
-
version_requirements: *
|
27
|
+
version_requirements: *70266170534240
|
29
28
|
- !ruby/object:Gem::Dependency
|
30
29
|
name: rubyzip
|
31
|
-
requirement: &
|
30
|
+
requirement: &70266170533480 !ruby/object:Gem::Requirement
|
32
31
|
none: false
|
33
32
|
requirements:
|
34
33
|
- - ~>
|
@@ -36,10 +35,10 @@ dependencies:
|
|
36
35
|
version: 0.9.4
|
37
36
|
type: :runtime
|
38
37
|
prerelease: false
|
39
|
-
version_requirements: *
|
38
|
+
version_requirements: *70266170533480
|
40
39
|
- !ruby/object:Gem::Dependency
|
41
40
|
name: rest-client
|
42
|
-
requirement: &
|
41
|
+
requirement: &70266170533000 !ruby/object:Gem::Requirement
|
43
42
|
none: false
|
44
43
|
requirements:
|
45
44
|
- - ! '>='
|
@@ -50,10 +49,10 @@ dependencies:
|
|
50
49
|
version: 1.7.0
|
51
50
|
type: :runtime
|
52
51
|
prerelease: false
|
53
|
-
version_requirements: *
|
52
|
+
version_requirements: *70266170533000
|
54
53
|
- !ruby/object:Gem::Dependency
|
55
54
|
name: terminal-table
|
56
|
-
requirement: &
|
55
|
+
requirement: &70266170532280 !ruby/object:Gem::Requirement
|
57
56
|
none: false
|
58
57
|
requirements:
|
59
58
|
- - ~>
|
@@ -61,10 +60,10 @@ dependencies:
|
|
61
60
|
version: 1.4.2
|
62
61
|
type: :runtime
|
63
62
|
prerelease: false
|
64
|
-
version_requirements: *
|
63
|
+
version_requirements: *70266170532280
|
65
64
|
- !ruby/object:Gem::Dependency
|
66
65
|
name: interact
|
67
|
-
requirement: &
|
66
|
+
requirement: &70266170531820 !ruby/object:Gem::Requirement
|
68
67
|
none: false
|
69
68
|
requirements:
|
70
69
|
- - ~>
|
@@ -72,10 +71,10 @@ dependencies:
|
|
72
71
|
version: 0.4.0
|
73
72
|
type: :runtime
|
74
73
|
prerelease: false
|
75
|
-
version_requirements: *
|
74
|
+
version_requirements: *70266170531820
|
76
75
|
- !ruby/object:Gem::Dependency
|
77
76
|
name: addressable
|
78
|
-
requirement: &
|
77
|
+
requirement: &70266170531360 !ruby/object:Gem::Requirement
|
79
78
|
none: false
|
80
79
|
requirements:
|
81
80
|
- - ~>
|
@@ -83,10 +82,10 @@ dependencies:
|
|
83
82
|
version: 2.2.6
|
84
83
|
type: :runtime
|
85
84
|
prerelease: false
|
86
|
-
version_requirements: *
|
85
|
+
version_requirements: *70266170531360
|
87
86
|
- !ruby/object:Gem::Dependency
|
88
87
|
name: uuidtools
|
89
|
-
requirement: &
|
88
|
+
requirement: &70266170530900 !ruby/object:Gem::Requirement
|
90
89
|
none: false
|
91
90
|
requirements:
|
92
91
|
- - ~>
|
@@ -94,10 +93,21 @@ dependencies:
|
|
94
93
|
version: 2.1.0
|
95
94
|
type: :runtime
|
96
95
|
prerelease: false
|
97
|
-
version_requirements: *
|
96
|
+
version_requirements: *70266170530900
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rb-readline
|
99
|
+
requirement: &70266170530440 !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ~>
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 0.4.2
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: *70266170530440
|
98
108
|
- !ruby/object:Gem::Dependency
|
99
109
|
name: rake
|
100
|
-
requirement: &
|
110
|
+
requirement: &70266170550520 !ruby/object:Gem::Requirement
|
101
111
|
none: false
|
102
112
|
requirements:
|
103
113
|
- - ! '>='
|
@@ -105,10 +115,10 @@ dependencies:
|
|
105
115
|
version: '0'
|
106
116
|
type: :development
|
107
117
|
prerelease: false
|
108
|
-
version_requirements: *
|
118
|
+
version_requirements: *70266170550520
|
109
119
|
- !ruby/object:Gem::Dependency
|
110
120
|
name: rspec
|
111
|
-
requirement: &
|
121
|
+
requirement: &70266170549980 !ruby/object:Gem::Requirement
|
112
122
|
none: false
|
113
123
|
requirements:
|
114
124
|
- - ~>
|
@@ -116,10 +126,10 @@ dependencies:
|
|
116
126
|
version: 1.3.0
|
117
127
|
type: :development
|
118
128
|
prerelease: false
|
119
|
-
version_requirements: *
|
129
|
+
version_requirements: *70266170549980
|
120
130
|
- !ruby/object:Gem::Dependency
|
121
131
|
name: webmock
|
122
|
-
requirement: &
|
132
|
+
requirement: &70266170549480 !ruby/object:Gem::Requirement
|
123
133
|
none: false
|
124
134
|
requirements:
|
125
135
|
- - ~>
|
@@ -127,7 +137,7 @@ dependencies:
|
|
127
137
|
version: 1.5.0
|
128
138
|
type: :development
|
129
139
|
prerelease: false
|
130
|
-
version_requirements: *
|
140
|
+
version_requirements: *70266170549480
|
131
141
|
description: AppFog.com CLI
|
132
142
|
email: support@appfog.com
|
133
143
|
executables:
|
@@ -157,6 +167,7 @@ files:
|
|
157
167
|
- lib/cli/core_ext.rb
|
158
168
|
- lib/cli/errors.rb
|
159
169
|
- lib/cli/frameworks.rb
|
170
|
+
- lib/cli/infra_helper.rb
|
160
171
|
- lib/cli/manifest_helper.rb
|
161
172
|
- lib/cli/runner.rb
|
162
173
|
- lib/cli/services_helper.rb
|
@@ -179,7 +190,6 @@ files:
|
|
179
190
|
- caldecott_helper/Gemfile.lock
|
180
191
|
- caldecott_helper/server.rb
|
181
192
|
- bin/af
|
182
|
-
has_rdoc: true
|
183
193
|
homepage: http://appfog.com
|
184
194
|
licenses: []
|
185
195
|
post_install_message:
|
@@ -200,7 +210,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
210
|
version: '0'
|
201
211
|
requirements: []
|
202
212
|
rubyforge_project:
|
203
|
-
rubygems_version: 1.6
|
213
|
+
rubygems_version: 1.8.6
|
204
214
|
signing_key:
|
205
215
|
specification_version: 3
|
206
216
|
summary: AppFog.com CLI
|