af 0.3.16.5 → 0.3.18.1

Sign up to get free protection for your applications and to get access to all the features.
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