as 0.3.18.11

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of as might be problematic. Click here for more details.

Files changed (44) hide show
  1. data/LICENSE +24 -0
  2. data/README.md +105 -0
  3. data/Rakefile +101 -0
  4. data/bin/as +6 -0
  5. data/caldecott_helper/Gemfile +10 -0
  6. data/caldecott_helper/Gemfile.lock +48 -0
  7. data/caldecott_helper/server.rb +43 -0
  8. data/config/clients.yml +17 -0
  9. data/config/micro/offline.conf +2 -0
  10. data/config/micro/paths.yml +22 -0
  11. data/config/micro/refresh_ip.rb +20 -0
  12. data/lib/cli/commands/admin.rb +80 -0
  13. data/lib/cli/commands/apps.rb +1208 -0
  14. data/lib/cli/commands/base.rb +233 -0
  15. data/lib/cli/commands/manifest.rb +56 -0
  16. data/lib/cli/commands/micro.rb +115 -0
  17. data/lib/cli/commands/misc.rb +140 -0
  18. data/lib/cli/commands/services.rb +217 -0
  19. data/lib/cli/commands/user.rb +65 -0
  20. data/lib/cli/config.rb +170 -0
  21. data/lib/cli/console_helper.rb +163 -0
  22. data/lib/cli/core_ext.rb +122 -0
  23. data/lib/cli/errors.rb +19 -0
  24. data/lib/cli/file_helper.rb +123 -0
  25. data/lib/cli/frameworks.rb +265 -0
  26. data/lib/cli/manifest_helper.rb +316 -0
  27. data/lib/cli/runner.rb +568 -0
  28. data/lib/cli/services_helper.rb +104 -0
  29. data/lib/cli/tunnel_helper.rb +336 -0
  30. data/lib/cli/usage.rb +125 -0
  31. data/lib/cli/version.rb +7 -0
  32. data/lib/cli/zip_util.rb +77 -0
  33. data/lib/cli.rb +48 -0
  34. data/lib/vmc/client.rb +558 -0
  35. data/lib/vmc/const.rb +27 -0
  36. data/lib/vmc/micro/switcher/base.rb +97 -0
  37. data/lib/vmc/micro/switcher/darwin.rb +19 -0
  38. data/lib/vmc/micro/switcher/dummy.rb +15 -0
  39. data/lib/vmc/micro/switcher/linux.rb +16 -0
  40. data/lib/vmc/micro/switcher/windows.rb +31 -0
  41. data/lib/vmc/micro/vmrun.rb +158 -0
  42. data/lib/vmc/micro.rb +56 -0
  43. data/lib/vmc.rb +3 -0
  44. metadata +270 -0
@@ -0,0 +1,336 @@
1
+ # Copyright (c) 2009-2011 VMware, Inc.
2
+
3
+ require 'addressable/uri'
4
+
5
+ begin
6
+ require 'caldecott'
7
+ rescue LoadError
8
+ end
9
+
10
+ module VMC::Cli
11
+ module TunnelHelper
12
+ PORT_RANGE = 10
13
+
14
+ HELPER_APP = File.expand_path("../../../caldecott_helper", __FILE__)
15
+
16
+ # bump this AND the version info reported by HELPER_APP/server.rb
17
+ # this is to keep the helper in sync with any updates here
18
+ HELPER_VERSION = '0.0.4'
19
+
20
+ def tunnel_uniquename(infra)
21
+ random_service_name(tunnel_appname(infra))
22
+ end
23
+
24
+ def tunnel_appname(infra)
25
+ infra ? "caldecott-#{infra}" : "caldecott"
26
+ end
27
+
28
+ def tunnel_app_info(infra)
29
+ begin
30
+ client.app_info(tunnel_appname(infra))
31
+ rescue => e
32
+ nil
33
+ end
34
+ end
35
+
36
+ def tunnel_auth(infra)
37
+ tunnel_app_info(infra)[:env].each do |e|
38
+ name, val = e.split("=", 2)
39
+ return val if name == "CALDECOTT_AUTH"
40
+ end
41
+ nil
42
+ end
43
+
44
+ def tunnel_url(infra)
45
+
46
+ tun_url = tunnel_app_info(infra)[:uris][0]
47
+
48
+ ["https", "http"].each do |scheme|
49
+ url = "#{scheme}://#{tun_url}"
50
+ begin
51
+ RestClient.get(url)
52
+
53
+ # https failed
54
+ rescue Errno::ECONNREFUSED
55
+
56
+ # we expect a 404 since this request isn't auth'd
57
+ rescue RestClient::ResourceNotFound
58
+ return url
59
+ end
60
+ end
61
+
62
+ err "Cannot determine URL for #{tun_url}"
63
+ end
64
+
65
+ def invalidate_tunnel_app_info(infra)
66
+ end
67
+
68
+ def tunnel_pushed?(infra)
69
+ not tunnel_app_info(infra).nil?
70
+ end
71
+
72
+ def tunnel_healthy?(token,infra)
73
+ return false unless tunnel_app_info(infra)[:state] == 'STARTED'
74
+
75
+ begin
76
+ response = RestClient.get(
77
+ "#{tunnel_url(infra)}/info",
78
+ "Auth-Token" => token
79
+ )
80
+ info = JSON.parse(response)
81
+ if info["version"] == HELPER_VERSION
82
+ true
83
+ else
84
+ stop_caldecott(infra)
85
+ false
86
+ end
87
+ rescue RestClient::Exception
88
+ stop_caldecott(infra)
89
+ false
90
+ end
91
+ end
92
+
93
+ def tunnel_bound?(service,infra)
94
+ tunnel_app_info(infra)[:services].include?(service)
95
+ end
96
+
97
+ def tunnel_connection_info(type, service, token, infra)
98
+ display "Getting tunnel connection info: ", false
99
+ response = nil
100
+ 10.times do
101
+ begin
102
+ response = RestClient.get(tunnel_url(infra) + "/" + VMC::Client.path("services", service), "Auth-Token" => token)
103
+ break
104
+ rescue RestClient::Exception => e
105
+ puts "Error infra: #{infra}, url: #{tunnel_url(infra)}"
106
+ display tunnel_url(infra)
107
+ puts e.message.red
108
+ sleep 1
109
+ end
110
+
111
+ display ".", false
112
+ end
113
+
114
+ unless response
115
+ err "Expected remote tunnel to know about #{service}, but it doesn't"
116
+ end
117
+
118
+ display "OK".green
119
+
120
+ info = JSON.parse(response)
121
+ info["infra"] = infra
122
+ case type
123
+ when "rabbitmq"
124
+ uri = Addressable::URI.parse info["url"]
125
+ info["hostname"] = uri.host
126
+ info["port"] = uri.port
127
+ info["vhost"] = uri.path[1..-1]
128
+ info["user"] = uri.user
129
+ info["password"] = uri.password
130
+ info.delete "url"
131
+
132
+ # we use "db" as the "name" for mongo
133
+ # existing "name" is junk
134
+ when "mongodb"
135
+ info["name"] = info["db"]
136
+ info.delete "db"
137
+
138
+ # our "name" is irrelevant for redis
139
+ when "redis"
140
+ info.delete "name"
141
+ end
142
+
143
+ ['hostname', 'port', 'password'].each do |k|
144
+ err "Could not determine #{k} for #{service}" if info[k].nil?
145
+ end
146
+
147
+ info
148
+ end
149
+
150
+ def display_tunnel_connection_info(info)
151
+ display ''
152
+ display "Service connection info: "
153
+
154
+ to_show = [nil, nil, nil] # reserved for user, pass, db name
155
+ info.keys.each do |k|
156
+ case k
157
+ when "host", "hostname", "port", "node_id"
158
+ # skip
159
+ when "user", "username"
160
+ # prefer "username" over "user"
161
+ to_show[0] = k unless to_show[0] == "username"
162
+ when "password"
163
+ to_show[1] = k
164
+ when "name"
165
+ to_show[2] = k
166
+ else
167
+ to_show << k
168
+ end
169
+ end
170
+ to_show.compact!
171
+
172
+ align_len = to_show.collect(&:size).max + 1
173
+
174
+ to_show.each do |k|
175
+ # TODO: modify the server services rest call to have explicit knowledge
176
+ # about the items to return. It should return all of them if
177
+ # the service is unknown so that we don't have to do this weird
178
+ # filtering.
179
+ display " #{k.ljust align_len}: ", false
180
+ display "#{info[k]}".yellow
181
+ end
182
+ display ''
183
+ end
184
+
185
+ def start_tunnel(local_port, conn_info, auth, infra)
186
+ @local_tunnel_thread = Thread.new do
187
+ Caldecott::Client.start({
188
+ :local_port => local_port,
189
+ :tun_url => tunnel_url(infra),
190
+ :dst_host => conn_info['hostname'],
191
+ :dst_port => conn_info['port'],
192
+ :log_file => STDOUT,
193
+ :log_level => ENV["VMC_TUNNEL_DEBUG"] || "ERROR",
194
+ :auth_token => auth,
195
+ :quiet => true
196
+ })
197
+ end
198
+
199
+ at_exit { @local_tunnel_thread.kill }
200
+ end
201
+
202
+
203
+
204
+ def pick_tunnel_port(port)
205
+ original = port
206
+
207
+ PORT_RANGE.times do |n|
208
+ begin
209
+ TCPSocket.open('localhost', port)
210
+ port += 1
211
+ rescue
212
+ return port
213
+ end
214
+ end
215
+
216
+ grab_ephemeral_port
217
+ end
218
+
219
+ def grab_ephemeral_port
220
+ socket = TCPServer.new('0.0.0.0', 0)
221
+ socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
222
+ Socket.do_not_reverse_lookup = true
223
+ port = socket.addr[1]
224
+ socket.close
225
+ return port
226
+ end
227
+
228
+ def wait_for_tunnel_start(port)
229
+ 10.times do |n|
230
+ begin
231
+ client = TCPSocket.open('localhost', port)
232
+ display '' if n > 0
233
+ client.close
234
+ return true
235
+ rescue => e
236
+ display "Waiting for local tunnel to become available", false if n == 0
237
+ display '.', false
238
+ sleep 1
239
+ end
240
+ end
241
+ err "Could not connect to local tunnel."
242
+ end
243
+
244
+ def wait_for_tunnel_end
245
+ display "Open another shell to run command-line clients or"
246
+ display "use a UI tool to connect using the displayed information."
247
+ display "Press Ctrl-C to exit..."
248
+ @local_tunnel_thread.join
249
+ end
250
+
251
+ def resolve_symbols(str, info, local_port)
252
+ str.gsub(/\$\{\s*([^\}]+)\s*\}/) do
253
+ case $1
254
+ when "host"
255
+ # TODO: determine proper host
256
+ "localhost"
257
+ when "port"
258
+ local_port
259
+ when "user", "username"
260
+ info["username"]
261
+ else
262
+ info[$1] || ask($1)
263
+ end
264
+ end
265
+ end
266
+
267
+ def start_local_prog(clients, command, info, port)
268
+ client = clients[File.basename(command)]
269
+
270
+ cmdline = "#{command} "
271
+
272
+ case client
273
+ when Hash
274
+ cmdline << resolve_symbols(client["command"], info, port)
275
+ client["environment"].each do |e|
276
+ if e =~ /([^=]+)=(["']?)([^"']*)\2/
277
+ ENV[$1] = resolve_symbols($3, info, port)
278
+ else
279
+ err "Invalid environment variable: #{e}"
280
+ end
281
+ end
282
+ when String
283
+ cmdline << resolve_symbols(client, info, port)
284
+ else
285
+ err "Unknown client info: #{client.inspect}."
286
+ end
287
+
288
+ display "Launching '#{cmdline}'"
289
+ display ''
290
+
291
+ system(cmdline)
292
+ end
293
+
294
+ def push_caldecott(token,infra)
295
+ manifest = {
296
+ :name => tunnel_appname(infra),
297
+ :staging => {:framework => "sinatra", :runtime => "ruby18" },
298
+ :uris => ["#{tunnel_uniquename(infra)}.#{client.base_for_infra(infra)}"],
299
+ :instances => 1,
300
+ :resources => {:memory => 64},
301
+ :env => ["CALDECOTT_AUTH=#{token}"]
302
+ }
303
+ manifest[:infra] = { :provider => infra } if infra
304
+
305
+ client.create_app(
306
+ tunnel_appname(infra),
307
+ manifest
308
+ )
309
+
310
+ apps_cmd.send(:upload_app_bits, tunnel_appname(infra), HELPER_APP, infra)
311
+
312
+ invalidate_tunnel_app_info(infra)
313
+ end
314
+
315
+ def stop_caldecott(infra)
316
+ apps_cmd.stop(tunnel_appname(infra))
317
+
318
+ invalidate_tunnel_app_info(infra)
319
+ end
320
+
321
+ def start_caldecott(infra)
322
+ apps_cmd.start(tunnel_appname(infra))
323
+
324
+ invalidate_tunnel_app_info(infra)
325
+ end
326
+
327
+ private
328
+
329
+ def apps_cmd
330
+ a = Command::Apps.new(@options)
331
+ a.client client
332
+ a
333
+ end
334
+
335
+ end
336
+ end
data/lib/cli/usage.rb ADDED
@@ -0,0 +1,125 @@
1
+ class VMC::Cli::Runner
2
+
3
+ def basic_usage
4
+ "Usage: as [options] command [<args>] [command_options]\n" +
5
+ "Try 'as help [command]' or 'as help options' for more information."
6
+ end
7
+
8
+ def display_usage
9
+ if @usage
10
+ say @usage_error if @usage_error
11
+ say "Usage: #{@usage}"
12
+ return
13
+ elsif @verb_usage
14
+ say @verb_usage
15
+ return
16
+ end
17
+ say command_usage
18
+ end
19
+
20
+ def command_usage
21
+ <<-USAGE
22
+
23
+ #{basic_usage}
24
+
25
+ Currently available as commands are:
26
+
27
+ Getting Started
28
+ target [url] Reports current target or sets a new target
29
+ login [email] [--email, --passwd] Login
30
+ info System and account information
31
+
32
+ Applications
33
+ apps List deployed applications
34
+
35
+ Application Creation
36
+ push [appname] Create, push, map, and start a new application
37
+ push [appname] --infra Push application to specified infrastructure
38
+ push [appname] --path Push application from specified path
39
+ push [appname] --url Set the url for the application
40
+ push [appname] --instances <N> Set the expected number <N> of instances
41
+ push [appname] --mem M Set the memory reservation for the application
42
+ push [appname] --runtime RUNTIME Set the runtime to use for the application
43
+ push [appname] --debug [MODE] Push application and start in a debug mode
44
+ push [appname] --no-start Do not auto-start the application
45
+
46
+ Application Operations
47
+ start <appname> [--debug [MODE]] Start the application
48
+ stop <appname> Stop the application
49
+ restart <appname> [--debug [MODE]] Restart the application
50
+ delete <appname> Delete the application
51
+ clone <src-app> <dest-app> [infra] Clone the application and services
52
+
53
+ Application Updates
54
+ update <appname> [--path,--debug [MODE]] Update the application bits
55
+ mem <appname> [memsize] Update the memory reservation for an application
56
+ map <appname> <url> Register the application to the url
57
+ unmap <appname> <url> Unregister the application from the url
58
+ instances <appname> <num|delta> Scale the application instances up or down
59
+
60
+ Application Information
61
+ crashes <appname> List recent application crashes
62
+ crashlogs <appname> Display log information for crashed applications
63
+ logs <appname> [--all] Display log information for the application
64
+ files <appname> [path] [--all] Display directory listing or file download for [path]
65
+ stats <appname> Display resource usage for the application
66
+ instances <appname> List application instances
67
+
68
+ Application Download
69
+ pull <appname> [path] Downloads last pushed source to <appname> or [path]
70
+ download <appname> [path] Downloads last pushed source to zipfile
71
+
72
+ Application Environment
73
+ env <appname> List application environment variables
74
+ env-add <appname> <variable[=]value> Add an environment variable to an application
75
+ env-del <appname> <variable> Delete an environment variable to an application
76
+
77
+ Services
78
+ services Lists of services available and provisioned
79
+ create-service <service> [--name,--bind] Create a provisioned service
80
+ create-service <service> --infra Create a provisioned service on a specified infrastructure
81
+ create-service <service> <name> Create a provisioned service and assign it <name>
82
+ create-service <service> <name> <app> Create a provisioned service and assign it <name>, and bind to <app>
83
+ delete-service [servicename] Delete a provisioned service
84
+ bind-service <servicename> <appname> Bind a service to an application
85
+ unbind-service <servicename> <appname> Unbind service from the application
86
+ clone-services <src-app> <dest-app> Clone service bindings from <src-app> application to <dest-app>
87
+ export-service <service> Export the data from a service
88
+ import-service <service> <url> Import data into a service
89
+ tunnel <servicename> [--port] Create a local tunnel to a service
90
+ tunnel <servicename> <clientcmd> Create a local tunnel to a service and start a local client
91
+
92
+ Administration
93
+ user Display user account information
94
+ passwd Change the password for the current user
95
+ logout Logs current user out of the target system
96
+ add-user [--email, --passwd] Register a new user (requires admin privileges)
97
+ delete-user <user> Delete a user and all apps and services (requires admin privileges)
98
+
99
+ System
100
+ runtimes Display the supported runtimes of the target system
101
+ frameworks Display the recognized frameworks of the target system
102
+ infras Display the available infrastructures
103
+
104
+ Micro Cloud Foundry
105
+ micro status Display Micro Cloud Foundry VM status
106
+ micro offline Configure Micro Cloud Foundry VM for offline mode
107
+ micro online Configure Micro Cloud Foundry VM for online mode
108
+ [--vmx file] Path to micro.vmx
109
+ [--vmrun executable] Path to vmrun executable
110
+ [--password cleartext] Cleartext password for guest VM vcap user
111
+ [--save] Save cleartext password in ~/.as_micro
112
+
113
+ Misc
114
+ aliases List aliases
115
+ alias <alias[=]command> Create an alias for a command
116
+ unalias <alias> Remove an alias
117
+ targets List known targets and associated authorization tokens
118
+
119
+ Help
120
+ help [command] Get general help or help on a specific command
121
+ help options Get help on available options
122
+ USAGE
123
+
124
+ end
125
+ end
@@ -0,0 +1,7 @@
1
+ module VMC
2
+ module Cli
3
+ # This version number is used as the RubyGem release version.
4
+ # The internal VMC version number is VMC::VERSION.
5
+ VERSION = '0.3.18.11'
6
+ end
7
+ end
@@ -0,0 +1,77 @@
1
+
2
+ require 'zip/zipfilesystem'
3
+
4
+ module VMC::Cli
5
+
6
+ class ZipUtil
7
+
8
+ PACK_EXCLUSION_GLOBS = ['..', '.', '*~', '#*#', '*.log']
9
+
10
+ class << self
11
+
12
+ def to_dev_null
13
+ if WINDOWS
14
+ 'nul'
15
+ else
16
+ '/dev/null'
17
+ end
18
+ end
19
+
20
+ def entry_lines(file)
21
+ contents = nil
22
+ unless VMC::Cli::Config.nozip
23
+ contents = `unzip -l #{file} 2> #{to_dev_null}`
24
+ contents = nil if $? != 0
25
+ end
26
+ # Do Ruby version if told to or native version failed
27
+ unless contents
28
+ entries = []
29
+ Zip::ZipFile.foreach(file) { |zentry| entries << zentry }
30
+ contents = entries.join("\n")
31
+ end
32
+ contents
33
+ end
34
+
35
+ def unpack(file, dest)
36
+ unless VMC::Cli::Config.nozip
37
+ FileUtils.mkdir(dest)
38
+ `unzip -q #{file} -d #{dest} 2> #{to_dev_null}`
39
+ return unless $? != 0
40
+ end
41
+ # Do Ruby version if told to or native version failed
42
+ Zip::ZipFile.foreach(file) do |zentry|
43
+ epath = "#{dest}/#{zentry}"
44
+ dirname = File.dirname(epath)
45
+ FileUtils.mkdir_p(dirname) unless File.exists?(dirname)
46
+ zentry.extract(epath) unless File.exists?(epath)
47
+ end
48
+ end
49
+
50
+ def get_files_to_pack(dir)
51
+ Dir.glob("#{dir}/**/*", File::FNM_DOTMATCH).select do |f|
52
+ process = true
53
+ PACK_EXCLUSION_GLOBS.each { |e| process = false if File.fnmatch(e, File.basename(f)) }
54
+ process && File.exists?(f)
55
+ end
56
+ end
57
+
58
+ def pack(dir, zipfile)
59
+ unless VMC::Cli::Config.nozip
60
+ excludes = PACK_EXCLUSION_GLOBS.map { |e| "\\#{e}" }
61
+ excludes = excludes.join(' ')
62
+ Dir.chdir(dir) do
63
+ `zip -y -q -r #{zipfile} . -x #{excludes} 2> #{to_dev_null}`
64
+ return unless $? != 0
65
+ end
66
+ end
67
+ # Do Ruby version if told to or native version failed
68
+ Zip::ZipFile::open(zipfile, true) do |zf|
69
+ get_files_to_pack(dir).each do |f|
70
+ zf.add(f.sub("#{dir}/",''), f)
71
+ end
72
+ end
73
+ end
74
+
75
+ end
76
+ end
77
+ end
data/lib/cli.rb ADDED
@@ -0,0 +1,48 @@
1
+ require "rbconfig"
2
+
3
+ ROOT = File.expand_path(File.dirname(__FILE__))
4
+ WINDOWS = !!(RbConfig::CONFIG['host_os'] =~ /mingw|mswin32|cygwin/)
5
+
6
+ module VMC
7
+ autoload :Client, "#{ROOT}/vmc/client"
8
+ autoload :Micro, "#{ROOT}/vmc/micro"
9
+
10
+ module Micro
11
+ module Switcher
12
+ autoload :Base, "#{ROOT}/vmc/micro/switcher/base"
13
+ autoload :Darwin, "#{ROOT}/vmc/micro/switcher/darwin"
14
+ autoload :Dummy, "#{ROOT}/vmc/micro/switcher/dummy"
15
+ autoload :Linux, "#{ROOT}/vmc/micro/switcher/linux"
16
+ autoload :Windows, "#{ROOT}/vmc/micro/switcher/windows"
17
+ end
18
+ autoload :VMrun, "#{ROOT}/vmc/micro/vmrun"
19
+ end
20
+
21
+ module Cli
22
+ autoload :Config, "#{ROOT}/cli/config"
23
+ autoload :Framework, "#{ROOT}/cli/frameworks"
24
+ autoload :Runner, "#{ROOT}/cli/runner"
25
+ autoload :ZipUtil, "#{ROOT}/cli/zip_util"
26
+ autoload :ServicesHelper, "#{ROOT}/cli/services_helper"
27
+ autoload :TunnelHelper, "#{ROOT}/cli/tunnel_helper"
28
+ autoload :ManifestHelper, "#{ROOT}/cli/manifest_helper"
29
+ autoload :ConsoleHelper, "#{ROOT}/cli/console_helper"
30
+ autoload :FileHelper, "#{ROOT}/cli/file_helper"
31
+
32
+ module Command
33
+ autoload :Base, "#{ROOT}/cli/commands/base"
34
+ autoload :Admin, "#{ROOT}/cli/commands/admin"
35
+ autoload :Apps, "#{ROOT}/cli/commands/apps"
36
+ autoload :Micro, "#{ROOT}/cli/commands/micro"
37
+ autoload :Misc, "#{ROOT}/cli/commands/misc"
38
+ autoload :Services, "#{ROOT}/cli/commands/services"
39
+ autoload :User, "#{ROOT}/cli/commands/user"
40
+ autoload :Manifest, "#{ROOT}/cli/commands/manifest"
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ require "#{ROOT}/cli/version"
47
+ require "#{ROOT}/cli/core_ext"
48
+ require "#{ROOT}/cli/errors"