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 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-2011, VMware, Inc. Licensed under the
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
- ROOT = File.expand_path(File.dirname(__FILE__))
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"
@@ -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
- t << [app[:name], app[:instances], health(app), app[:uris].join(', '), app[:services].join(', ')]
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
- if not tunnel_healthy?(auth)
81
- display "Redeploying tunnel application '#{tunnel_appname}'."
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)
@@ -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
- if not tunnel_pushed?
122
- display "Deploying tunnel application '#{tunnel_appname}'."
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}' executation failed; is it in your $PATH?"
177
+ err "'#{client_name}' execution failed; is it in your $PATH?"
171
178
  end
172
179
  end
173
180
  end
@@ -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 ||= "aws.af.cm"
46
+ @suggest_url ||= VMC::Cli::InfraHelper.base_for_infra(@infra)
46
47
  end
47
48
 
48
49
  def store_target(target_host)
@@ -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 = {'hostname' => entry[:console_ip], 'port' => entry[:console_port]}
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"]) {|line|
54
- if line =~ /[$%#>] \z/n
55
- prompt = line
56
- elsif line =~ /Login failed/
57
- err_msg = line
58
- end
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.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
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
- 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
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
- if !cmd.empty?
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
@@ -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
- 'Rack' => ['rack', { :mem => '128M', :description => 'Rack Application'}]
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
- FRAMEWORKS.keys
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[\s\(]*['"]sinatra['"]/))
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
- # Node.js
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
@@ -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}"
@@ -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!
@@ -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
- t << [ service[:name], service[:vendor] ]
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
 
@@ -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
- @tun_app_info = client.app_info(tunnel_appname)
30
+ client.app_info(tunnel_appname(infra))
32
31
  rescue => e
33
- @tun_app_info = nil
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 @tunnel_url = url
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
- client.create_app(
297
- tunnel_appname,
298
- { :name => tunnel_appname,
299
- :staging => {:framework => "sinatra"},
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
@@ -2,6 +2,6 @@ module VMC
2
2
  module Cli
3
3
  # This version number is used as the RubyGem release version.
4
4
  # The internal VMC version number is VMC::VERSION.
5
- VERSION = '0.3.16.5'
5
+ VERSION = '0.3.18.1'
6
6
  end
7
7
  end
@@ -10,7 +10,7 @@ module VMC::Cli
10
10
  class << self
11
11
 
12
12
  def to_dev_null
13
- if !!RUBY_PLATFORM['mingw'] || !!RUBY_PLATFORM['mswin32'] || !!RUBY_PLATFORM['cygwin']
13
+ if WINDOWS
14
14
  'nul'
15
15
  else
16
16
  '/dev/null'
@@ -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 => 120, :open_timeout => 120
389
+ :timeout => HTTP_TIMEOUT, :open_timeout => HTTP_TIMEOUT
386
390
  }
387
391
  status, body, response_headers = perform_http_request(req)
388
392
 
@@ -2,7 +2,7 @@ module VMC
2
2
 
3
3
  # This is the internal VMC version number, and is not necessarily
4
4
  # the same as the RubyGem version (VMC::Cli::VERSION).
5
- VERSION = '0.3.16.5'
5
+ VERSION = '0.3.18.1'
6
6
 
7
7
  # Targets
8
8
  DEFAULT_TARGET = 'https://api.appfog.com'
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.16.5
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-06-14 00:00:00.000000000 -07:00
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: &2153510720 !ruby/object:Gem::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: *2153510720
27
+ version_requirements: *70266170534240
29
28
  - !ruby/object:Gem::Dependency
30
29
  name: rubyzip
31
- requirement: &2153509940 !ruby/object:Gem::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: *2153509940
38
+ version_requirements: *70266170533480
40
39
  - !ruby/object:Gem::Dependency
41
40
  name: rest-client
42
- requirement: &2153509420 !ruby/object:Gem::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: *2153509420
52
+ version_requirements: *70266170533000
54
53
  - !ruby/object:Gem::Dependency
55
54
  name: terminal-table
56
- requirement: &2153508660 !ruby/object:Gem::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: *2153508660
63
+ version_requirements: *70266170532280
65
64
  - !ruby/object:Gem::Dependency
66
65
  name: interact
67
- requirement: &2153508160 !ruby/object:Gem::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: *2153508160
74
+ version_requirements: *70266170531820
76
75
  - !ruby/object:Gem::Dependency
77
76
  name: addressable
78
- requirement: &2153507580 !ruby/object:Gem::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: *2153507580
85
+ version_requirements: *70266170531360
87
86
  - !ruby/object:Gem::Dependency
88
87
  name: uuidtools
89
- requirement: &2153507040 !ruby/object:Gem::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: *2153507040
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: &2153506640 !ruby/object:Gem::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: *2153506640
118
+ version_requirements: *70266170550520
109
119
  - !ruby/object:Gem::Dependency
110
120
  name: rspec
111
- requirement: &2153506080 !ruby/object:Gem::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: *2153506080
129
+ version_requirements: *70266170549980
120
130
  - !ruby/object:Gem::Dependency
121
131
  name: webmock
122
- requirement: &2153505580 !ruby/object:Gem::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: *2153505580
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.2
213
+ rubygems_version: 1.8.6
204
214
  signing_key:
205
215
  specification_version: 3
206
216
  summary: AppFog.com CLI