af 0.3.22 → 0.5.0.beta.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.
Files changed (157) hide show
  1. checksums.yaml +14 -6
  2. data/LICENSE +1277 -24
  3. data/Rakefile +24 -87
  4. data/bin/af +7 -2
  5. data/lib/af/version.rb +3 -0
  6. data/lib/vmc.rb +7 -2
  7. data/lib/vmc/cli.rb +475 -0
  8. data/lib/vmc/cli/app/app.rb +45 -0
  9. data/lib/vmc/cli/app/apps.rb +105 -0
  10. data/lib/vmc/cli/app/base.rb +82 -0
  11. data/lib/vmc/cli/app/crashes.rb +46 -0
  12. data/lib/vmc/cli/app/delete.rb +95 -0
  13. data/lib/vmc/cli/app/deprecated.rb +11 -0
  14. data/lib/vmc/cli/app/env.rb +78 -0
  15. data/lib/vmc/cli/app/files.rb +137 -0
  16. data/lib/vmc/cli/app/health.rb +26 -0
  17. data/lib/vmc/cli/app/instances.rb +53 -0
  18. data/lib/vmc/cli/app/logs.rb +76 -0
  19. data/lib/vmc/cli/app/push.rb +107 -0
  20. data/lib/vmc/cli/app/push/create.rb +150 -0
  21. data/lib/vmc/cli/app/push/interactions.rb +100 -0
  22. data/lib/vmc/cli/app/push/sync.rb +64 -0
  23. data/lib/vmc/cli/app/rename.rb +39 -0
  24. data/lib/vmc/cli/app/restart.rb +20 -0
  25. data/lib/vmc/cli/app/scale.rb +71 -0
  26. data/lib/vmc/cli/app/start.rb +93 -0
  27. data/lib/vmc/cli/app/stats.rb +67 -0
  28. data/lib/vmc/cli/app/stop.rb +27 -0
  29. data/lib/vmc/cli/domain/base.rb +12 -0
  30. data/lib/vmc/cli/domain/domains.rb +40 -0
  31. data/lib/vmc/cli/domain/map.rb +55 -0
  32. data/lib/vmc/cli/domain/unmap.rb +56 -0
  33. data/lib/vmc/cli/help.rb +16 -0
  34. data/lib/vmc/cli/interactive.rb +105 -0
  35. data/lib/vmc/cli/organization/base.rb +14 -0
  36. data/lib/vmc/cli/organization/create.rb +32 -0
  37. data/lib/vmc/cli/organization/delete.rb +73 -0
  38. data/lib/vmc/cli/organization/org.rb +45 -0
  39. data/lib/vmc/cli/organization/orgs.rb +35 -0
  40. data/lib/vmc/cli/organization/rename.rb +36 -0
  41. data/lib/vmc/cli/route/base.rb +12 -0
  42. data/lib/vmc/cli/route/map.rb +80 -0
  43. data/lib/vmc/cli/route/routes.rb +26 -0
  44. data/lib/vmc/cli/route/unmap.rb +94 -0
  45. data/lib/vmc/cli/service/base.rb +8 -0
  46. data/lib/vmc/cli/service/bind.rb +44 -0
  47. data/lib/vmc/cli/service/create.rb +126 -0
  48. data/lib/vmc/cli/service/delete.rb +86 -0
  49. data/lib/vmc/cli/service/rename.rb +35 -0
  50. data/lib/vmc/cli/service/service.rb +42 -0
  51. data/lib/vmc/cli/service/services.rb +115 -0
  52. data/lib/vmc/cli/service/unbind.rb +38 -0
  53. data/lib/vmc/cli/space/base.rb +21 -0
  54. data/lib/vmc/cli/space/create.rb +56 -0
  55. data/lib/vmc/cli/space/delete.rb +95 -0
  56. data/lib/vmc/cli/space/rename.rb +39 -0
  57. data/lib/vmc/cli/space/space.rb +64 -0
  58. data/lib/vmc/cli/space/spaces.rb +55 -0
  59. data/lib/vmc/cli/space/take.rb +16 -0
  60. data/lib/vmc/cli/start/base.rb +80 -0
  61. data/lib/vmc/cli/start/colors.rb +13 -0
  62. data/lib/vmc/cli/start/info.rb +122 -0
  63. data/lib/vmc/cli/start/login.rb +92 -0
  64. data/lib/vmc/cli/start/logout.rb +13 -0
  65. data/lib/vmc/cli/start/target.rb +64 -0
  66. data/lib/vmc/cli/start/target_interactions.rb +37 -0
  67. data/lib/vmc/cli/start/targets.rb +16 -0
  68. data/lib/vmc/cli/user/base.rb +29 -0
  69. data/lib/vmc/cli/user/create.rb +39 -0
  70. data/lib/vmc/cli/user/delete.rb +25 -0
  71. data/lib/vmc/cli/user/passwd.rb +50 -0
  72. data/lib/vmc/cli/user/register.rb +42 -0
  73. data/lib/vmc/cli/user/users.rb +32 -0
  74. data/lib/vmc/constants.rb +13 -0
  75. data/lib/vmc/detect.rb +134 -0
  76. data/lib/vmc/errors.rb +17 -0
  77. data/lib/vmc/plugin.rb +56 -0
  78. data/lib/vmc/spacing.rb +89 -0
  79. data/lib/vmc/spec_helper.rb +1 -0
  80. data/lib/vmc/test_support.rb +4 -0
  81. data/lib/vmc/test_support/command_helper.rb +32 -0
  82. data/lib/vmc/test_support/common_input_examples.rb +14 -0
  83. data/lib/vmc/test_support/fake_home_dir.rb +16 -0
  84. data/lib/vmc/test_support/interact_helper.rb +29 -0
  85. data/lib/vmc/version.rb +3 -0
  86. data/spec/assets/hello-sinatra/Gemfile +3 -0
  87. data/spec/assets/hello-sinatra/main.rb +6 -0
  88. data/spec/features/new_user_flow_spec.rb +71 -0
  89. data/spec/spec_helper.rb +63 -0
  90. data/spec/vmc/cli/app/base_spec.rb +17 -0
  91. data/spec/vmc/cli/app/delete_spec.rb +188 -0
  92. data/spec/vmc/cli/app/instances_spec.rb +65 -0
  93. data/spec/vmc/cli/app/push/create_spec.rb +571 -0
  94. data/spec/vmc/cli/app/push_spec.rb +369 -0
  95. data/spec/vmc/cli/app/rename_spec.rb +104 -0
  96. data/spec/vmc/cli/app/scale_spec.rb +81 -0
  97. data/spec/vmc/cli/app/stats_spec.rb +62 -0
  98. data/spec/vmc/cli/domain/map_spec.rb +140 -0
  99. data/spec/vmc/cli/domain/unmap_spec.rb +73 -0
  100. data/spec/vmc/cli/organization/orgs_spec.rb +108 -0
  101. data/spec/vmc/cli/organization/rename_spec.rb +113 -0
  102. data/spec/vmc/cli/route/map_spec.rb +138 -0
  103. data/spec/vmc/cli/route/unmap_spec.rb +215 -0
  104. data/spec/vmc/cli/service/bind_spec.rb +25 -0
  105. data/spec/vmc/cli/service/delete_spec.rb +22 -0
  106. data/spec/vmc/cli/service/rename_spec.rb +105 -0
  107. data/spec/vmc/cli/service/service_spec.rb +23 -0
  108. data/spec/vmc/cli/service/unbind_spec.rb +25 -0
  109. data/spec/vmc/cli/space/rename_spec.rb +102 -0
  110. data/spec/vmc/cli/space/spaces_spec.rb +104 -0
  111. data/spec/vmc/cli/start/info_spec.rb +153 -0
  112. data/spec/vmc/cli/start/login_spec.rb +71 -0
  113. data/spec/vmc/cli/user/create_spec.rb +54 -0
  114. data/spec/vmc/cli/user/passwd_spec.rb +102 -0
  115. data/spec/vmc/cli/user/register_spec.rb +148 -0
  116. data/spec/vmc/cli_spec.rb +448 -0
  117. data/spec/vmc/detect_spec.rb +54 -0
  118. metadata +231 -124
  119. data/README.md +0 -155
  120. data/caldecott_helper/Gemfile +0 -10
  121. data/caldecott_helper/Gemfile.lock +0 -48
  122. data/caldecott_helper/server.rb +0 -43
  123. data/config/clients.yml +0 -17
  124. data/config/micro/offline.conf +0 -2
  125. data/config/micro/paths.yml +0 -22
  126. data/config/micro/refresh_ip.rb +0 -20
  127. data/lib/cli.rb +0 -48
  128. data/lib/cli/commands/admin.rb +0 -81
  129. data/lib/cli/commands/apps.rb +0 -1358
  130. data/lib/cli/commands/base.rb +0 -233
  131. data/lib/cli/commands/manifest.rb +0 -56
  132. data/lib/cli/commands/micro.rb +0 -115
  133. data/lib/cli/commands/misc.rb +0 -147
  134. data/lib/cli/commands/services.rb +0 -217
  135. data/lib/cli/commands/user.rb +0 -70
  136. data/lib/cli/config.rb +0 -176
  137. data/lib/cli/console_helper.rb +0 -163
  138. data/lib/cli/core_ext.rb +0 -122
  139. data/lib/cli/errors.rb +0 -19
  140. data/lib/cli/file_helper.rb +0 -123
  141. data/lib/cli/frameworks.rb +0 -265
  142. data/lib/cli/manifest_helper.rb +0 -316
  143. data/lib/cli/runner.rb +0 -633
  144. data/lib/cli/services_helper.rb +0 -104
  145. data/lib/cli/tunnel_helper.rb +0 -336
  146. data/lib/cli/usage.rb +0 -129
  147. data/lib/cli/version.rb +0 -7
  148. data/lib/cli/zip_util.rb +0 -102
  149. data/lib/vmc/client.rb +0 -574
  150. data/lib/vmc/const.rb +0 -27
  151. data/lib/vmc/micro.rb +0 -56
  152. data/lib/vmc/micro/switcher/base.rb +0 -97
  153. data/lib/vmc/micro/switcher/darwin.rb +0 -19
  154. data/lib/vmc/micro/switcher/dummy.rb +0 -15
  155. data/lib/vmc/micro/switcher/linux.rb +0 -16
  156. data/lib/vmc/micro/switcher/windows.rb +0 -31
  157. data/lib/vmc/micro/vmrun.rb +0 -158
@@ -1,7 +0,0 @@
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.22'
6
- end
7
- end
@@ -1,102 +0,0 @@
1
- require 'fileutils'
2
- require 'zip/zipfilesystem'
3
- require 'pathname'
4
-
5
- module VMC::Cli
6
-
7
- class ZipUtil
8
-
9
- PACK_EXCLUSION_GLOBS = ['..', '.', '*~', '#*#', '*.log']
10
-
11
- class << self
12
-
13
- def to_dev_null
14
- if WINDOWS
15
- 'nul'
16
- else
17
- '/dev/null'
18
- end
19
- end
20
-
21
- def entry_lines(file)
22
- contents = nil
23
- unless VMC::Cli::Config.nozip
24
- contents = `unzip -l #{file} 2> #{to_dev_null}`
25
- contents = nil if $? != 0
26
- end
27
- # Do Ruby version if told to or native version failed
28
- unless contents
29
- entries = []
30
- Zip::ZipFile.foreach(file) { |zentry| entries << zentry }
31
- contents = entries.join("\n")
32
- end
33
- contents
34
- end
35
-
36
- def unpack(file, dest)
37
- unless VMC::Cli::Config.nozip
38
- FileUtils.mkdir(dest)
39
- `unzip -q #{file} -d #{dest} 2> #{to_dev_null}`
40
- return unless $? != 0
41
- end
42
- # Do Ruby version if told to or native version failed
43
- Zip::ZipFile.foreach(file) do |zentry|
44
- epath = "#{dest}/#{zentry}"
45
- dirname = File.dirname(epath)
46
- FileUtils.mkdir_p(dirname) unless File.exists?(dirname)
47
- zentry.extract(epath) unless File.exists?(epath)
48
- end
49
- end
50
-
51
- def get_files_to_pack(dir)
52
- Dir.glob("#{dir}/**/*", File::FNM_DOTMATCH).select do |f|
53
- process = true
54
- PACK_EXCLUSION_GLOBS.each { |e| process = false if File.fnmatch(e, File.basename(f)) }
55
- process && File.exists?(f)
56
- end
57
- end
58
-
59
- def pack(dir, zipfile)
60
- unless VMC::Cli::Config.nozip
61
- excludes = PACK_EXCLUSION_GLOBS.map { |e| "\\#{e}" }
62
- excludes = excludes.join(' ')
63
- Dir.chdir(dir) do
64
- `zip -y -q -r #{zipfile} . -x #{excludes} 2> #{to_dev_null}`
65
- return unless $? != 0
66
- end
67
- end
68
- # Do Ruby version if told to or native version failed
69
- Zip::ZipFile::open(zipfile, true) do |zf|
70
- get_files_to_pack(dir).each do |f|
71
- zf.add(f.sub("#{dir}/",''), f)
72
- end
73
- end
74
- end
75
-
76
- BLOCKSIZE_TO_READ = 1024 * 1000
77
-
78
- # not a valid tar file, since tar files include last modified date which breaks it for
79
- # use in hashing. this method just wraps up everything for use in hashing.
80
- def tar(path)
81
- tar_filename = Pathname.new(path).realpath.to_path + '.tar'
82
- File.open(tar_filename, 'wb') do |tarfile|
83
- get_files_to_pack(path).each do |file|
84
- if File.file?(file)
85
- File.open(file, 'rb') do |f|
86
- while buffer = f.read(BLOCKSIZE_TO_READ)
87
- tarfile.write buffer
88
- end
89
- end
90
- else
91
- tarfile.write file.gsub(path, '')
92
- end
93
- end
94
- end
95
-
96
- tar_filename
97
-
98
- end
99
-
100
- end
101
- end
102
- end
@@ -1,574 +0,0 @@
1
- # VMC client
2
- #
3
- # Example:
4
- #
5
- # require 'vmc'
6
- # client = VMC::Client.new('api.vcap.me')
7
- # client.login(:user, :pass)
8
- # client.create('myapplication', manifest)
9
- # client.create_service('aws', 'redis', 'my_redis_service', opts);
10
- #
11
-
12
- require 'rubygems'
13
- require 'json/pure'
14
- require 'open-uri'
15
-
16
- require File.expand_path('../const', __FILE__)
17
-
18
- class VMC::Client
19
-
20
- def self.version
21
- VMC::VERSION
22
- end
23
-
24
- attr_reader :target, :host, :user, :proxy, :auth_token
25
- attr_accessor :trace, :infra
26
-
27
- # Error codes
28
- VMC_HTTP_ERROR_CODES = [ 400, 500 ]
29
-
30
- HTTP_TIMEOUT = ENV['TIMEOUT'] ? ENV['TIMEOUT'].to_i : 10*60
31
-
32
- # Errors
33
- class BadTarget < RuntimeError; end
34
- class AuthError < RuntimeError; end
35
- class TargetError < RuntimeError; end
36
- class NotFound < RuntimeError; end
37
- class BadResponse < RuntimeError; end
38
- class HTTPException < RuntimeError; end
39
-
40
- # Initialize new client to the target_uri with optional auth_token
41
- def initialize(target_url=VMC::DEFAULT_TARGET, auth_token=nil)
42
- target_url = "https://#{target_url}" unless /^https?/ =~ target_url
43
- target_url = target_url.gsub(/\/+$/, '')
44
- @target = target_url
45
- @auth_token = auth_token
46
- end
47
-
48
- ######################################################
49
- # Target info
50
- ######################################################
51
-
52
- # Retrieves information on the target cloud, and optionally the logged in user
53
- def info
54
- # TODO: Should merge for new version IMO, general, services, user_account
55
- json_get(VMC::INFO_PATH)
56
- end
57
-
58
- def raw_info
59
- http_get(VMC::INFO_PATH)
60
- end
61
-
62
- # Global listing of services that are available on the target system
63
- def services_info
64
- check_login_status
65
- json_get(path(VMC::GLOBAL_SERVICES_PATH))
66
- end
67
-
68
- def runtimes_info
69
- json_get(path(VMC::GLOBAL_RUNTIMES_PATH))
70
- end
71
-
72
- ######################################################
73
- # Apps
74
- ######################################################
75
-
76
- def apps
77
- check_login_status
78
- json_get(VMC::APPS_PATH)
79
- end
80
-
81
- def create_app(name, manifest={})
82
- check_login_status
83
- app = manifest.dup
84
- app[:name] = name
85
- app[:instances] ||= 1
86
- json_post(VMC::APPS_PATH, app)
87
- end
88
-
89
- def update_app(name, manifest)
90
- check_login_status
91
- json_put(path(VMC::APPS_PATH, name), manifest)
92
- end
93
-
94
- def upload_app(name, zipfile, hash, label, resource_manifest=nil)
95
- #FIXME, manifest should be allowed to be null, here for compatability with old cc's
96
- resource_manifest ||= []
97
- check_login_status
98
- upload_data = {:_method => 'put'}
99
- if zipfile
100
- if zipfile.is_a? File
101
- file = zipfile
102
- else
103
- file = File.new(zipfile, 'rb')
104
- end
105
- upload_data[:application] = file
106
- end
107
- headers = {:hash => hash, :label => label}
108
- upload_data[:resources] = resource_manifest.to_json if resource_manifest
109
- http_post(path(VMC::APPS_PATH, name, "application"), upload_data, nil, headers)
110
- rescue RestClient::ServerBrokeConnection
111
- retry
112
- end
113
-
114
- def delete_app(name)
115
- check_login_status
116
- http_delete(path(VMC::APPS_PATH, name))
117
- end
118
-
119
- def app_info(name)
120
- check_login_status
121
- json_get(path(VMC::APPS_PATH, name))
122
- end
123
-
124
- def app_update_info(name)
125
- check_login_status
126
- json_get(path(VMC::APPS_PATH, name, "update"))
127
- end
128
-
129
- def app_stats(name)
130
- check_login_status
131
- stats_raw = json_get(path(VMC::APPS_PATH, name, "stats"))
132
- stats = []
133
- stats_raw.each_pair do |k, entry|
134
- # Skip entries with no stats
135
- next unless entry[:stats]
136
- entry[:instance] = k.to_s.to_i
137
- entry[:state] = entry[:state].to_sym if entry[:state]
138
- stats << entry
139
- end
140
- stats.sort { |a,b| a[:instance] - b[:instance] }
141
- end
142
-
143
- def app_instances(name)
144
- check_login_status
145
- json_get(path(VMC::APPS_PATH, name, "instances"))
146
- end
147
-
148
- def app_crashes(name)
149
- check_login_status
150
- json_get(path(VMC::APPS_PATH, name, "crashes"))
151
- end
152
-
153
- def app_history(name)
154
- check_login_status
155
- json_get(path(VMC::APPS_PATH, name, "history"))
156
- end
157
-
158
- def app_diff(name)
159
- check_login_status
160
- json_get(path(VMC::APPS_PATH, name, "diff"))
161
- end
162
-
163
- # List the directory or download the actual file indicated by
164
- # the path.
165
- def app_files(name, path, instance='0')
166
- check_login_status
167
- path = path.gsub('//', '/')
168
- url = path(VMC::APPS_PATH, name, "instances", instance, "files", path)
169
- _, body, headers = http_get(url)
170
- body
171
- end
172
-
173
- def app_download(name,path)
174
- check_login_status
175
- url = path(VMC::APPS_PATH, name, "application")
176
- status, body, headers = http_get(url,'application/octet-stream')
177
- file = File.new(path,"wb")
178
- file.write(body)
179
- file.close
180
- end
181
-
182
- def app_pull(name, dir)
183
- check_login_status
184
- url = path(VMC::APPS_PATH, name, "application")
185
- status, body, headers = http_get(url,'application/octet-stream')
186
- file = Tempfile.new(name)
187
- file.binmode
188
- file.write(body)
189
- file.close
190
- ::VMC::Cli::ZipUtil.unpack(file.path, dir)
191
- file.unlink
192
- end
193
-
194
- ######################################################
195
- # Services
196
- ######################################################
197
-
198
- # listing of services that are available in the system
199
- def services
200
- check_login_status
201
- json_get(VMC::SERVICES_PATH)
202
- end
203
-
204
- def create_service(infra,service, name)
205
- check_login_status
206
- services = services_info
207
- services ||= []
208
- service_hash = nil
209
-
210
- service = service.to_s
211
-
212
- # FIXME!
213
- services.each do |service_type, value|
214
- value.each do |vendor, version|
215
- version.each do |version_str, service_descr|
216
- if service == service_descr[:vendor]
217
- service_hash = {
218
- :type => service_descr[:type], :tier => 'free',
219
- :vendor => service, :version => version_str
220
- }
221
- service_hash[:infra] = { :provider => infra } if infra
222
- break
223
- end
224
- end
225
- end
226
- end
227
-
228
- raise TargetError, "Service [#{service}] is not a valid service choice" unless service_hash
229
- service_hash[:name] = name
230
- json_post(path(VMC::SERVICES_PATH), service_hash)
231
- end
232
-
233
- def delete_service(name)
234
- check_login_status
235
- svcs = services || []
236
- names = svcs.collect { |s| s[:name] }
237
- raise TargetError, "Service [#{name}] not a valid service" unless names.include? name
238
- http_delete(path(VMC::SERVICES_PATH, name))
239
- end
240
-
241
- def bind_service(service, appname)
242
- check_login_status
243
- svc = services.detect { |s| s[:name] == service }
244
- app = app_info(appname)
245
- if infra_supported? && ! infras_match?(app,svc)
246
- raise TargetError, "Service #{service} and App #{appname} are not on the same infra"
247
- end
248
- services = app[:services] || []
249
- app[:services] = services << service
250
- update_app(appname, app)
251
- end
252
-
253
- def unbind_service(service, appname)
254
- check_login_status
255
- app = app_info(appname)
256
- services = app[:services] || []
257
- services.delete(service)
258
- app[:services] = services
259
- update_app(appname, app)
260
- end
261
-
262
- def export_service(service)
263
- json_get(path(VMC::SERVICE_EXPORT_PATH, service))
264
- end
265
-
266
- def import_service(service,uri)
267
- json_post(path(VMC::SERVICE_IMPORT_PATH, service),{:uri => uri})
268
- end
269
-
270
- ######################################################
271
- # Resources
272
- ######################################################
273
-
274
- # Send in a resources manifest array to the system to have
275
- # it check what is needed to actually send. Returns array
276
- # indicating what is needed. This returned manifest should be
277
- # sent in with the upload if resources were removed.
278
- # E.g. [{:sha1 => xxx, :size => xxx, :fn => filename}]
279
- def check_resources(resources,infra=nil)
280
- check_login_status
281
- url = VMC::RESOURCES_PATH
282
- unless infra.nil?
283
- url += "?infra=#{infra}"
284
- end
285
- status, body, headers = json_post(url, resources)
286
- json_parse(body)
287
- end
288
-
289
- ######################################################
290
- # Validation Helpers
291
- ######################################################
292
-
293
- # Checks that the target is valid
294
- def target_valid?
295
- return false unless descr = info
296
- return false unless descr[:name]
297
- return false unless descr[:build]
298
- return false unless descr[:version]
299
- return false unless descr[:support]
300
- true
301
- rescue
302
- false
303
- end
304
-
305
- # Checks that the auth_token is valid
306
- def logged_in?
307
- descr = info
308
- if descr
309
- return false unless descr[:user]
310
- return false unless descr[:usage]
311
- @user = descr[:user]
312
- true
313
- end
314
- end
315
-
316
- ######################################################
317
- # User login/password
318
- ######################################################
319
-
320
- # login and return an auth_token
321
- # Auth token can be retained and used in creating
322
- # new clients, avoiding login.
323
- def login(user, password)
324
- status, body, headers = json_post(path(VMC::USERS_PATH, user, "tokens"), {:password => password})
325
- response_info = json_parse(body)
326
- if response_info
327
- @user = user
328
- @auth_token = response_info[:token]
329
- end
330
- end
331
-
332
- # sets the password for the current logged user
333
- def change_password(new_password)
334
- check_login_status
335
- user_info = json_get(path(VMC::USERS_PATH, @user))
336
- if user_info
337
- user_info[:password] = new_password
338
- json_put(path(VMC::USERS_PATH, @user), user_info)
339
- end
340
- end
341
-
342
- ######################################################
343
- # System administration
344
- ######################################################
345
-
346
- def proxy=(proxy)
347
- @proxy = proxy
348
- end
349
-
350
- def proxy_for(proxy)
351
- @proxy = proxy
352
- end
353
-
354
- def users
355
- check_login_status
356
- json_get(VMC::USERS_PATH)
357
- end
358
-
359
- def add_user(user_email, password)
360
- json_post(VMC::USERS_PATH, { :email => user_email, :password => password })
361
- end
362
-
363
- def delete_user(user_email)
364
- check_login_status
365
- http_delete(path(VMC::USERS_PATH, user_email))
366
- end
367
-
368
- ######################################################
369
-
370
- def self.path(*path)
371
- path.flatten.collect { |x|
372
- URI.encode x.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
373
- }.join("/")
374
- end
375
-
376
- ######################################################
377
- # Infrastructure
378
- ######################################################
379
-
380
- def infras
381
- json_get(path(VMC::GLOBAL_INFRAS_PATH))
382
- rescue
383
- []
384
- end
385
-
386
- def infra_supported?
387
- !infras.empty?
388
- end
389
-
390
- def base_for_infra(name)
391
- info = infras.detect { |i| i[:infra] == name }
392
- info ? info[:base] : default_base
393
- end
394
-
395
- def default_base
396
- # remove the protocol, and the first component of the url, which is normally api
397
- pattern = /https?:\/\/[^.]+\./
398
- if @target =~ pattern
399
- @target.sub(pattern,'')
400
- else
401
- "aws.af.cm"
402
- end
403
- end
404
-
405
- def infra_valid?(name)
406
- infras.detect { |i| i[:infra] == name }
407
- end
408
-
409
- def infra_descriptions
410
- infras.select{|i| !i.has_key?(:available) || i[:available] == true}.map { |i| i[:description] }
411
- end
412
-
413
- def infra_name_for_description(desc)
414
- info = infras.detect { |i| i[:description] == desc }
415
- info ? info[:infra] : ""
416
- end
417
-
418
- def suggest_url(infra=nil)
419
- @suggest_url ||= base_for_infra(infra || @infra)
420
- end
421
-
422
-
423
- private
424
-
425
- def path(*args, &blk)
426
- self.class.path(*args, &blk)
427
- end
428
-
429
- def json_get(url)
430
- status, body, headers = http_get(url, 'application/json')
431
- json_parse(body)
432
- rescue JSON::ParserError
433
- raise BadResponse, "Can't parse response into JSON", body
434
- end
435
-
436
- def json_post(url, payload)
437
- http_post(url, payload.to_json, 'application/json')
438
- end
439
-
440
- def json_put(url, payload)
441
- http_put(url, payload.to_json, 'application/json')
442
- end
443
-
444
- def json_parse(str)
445
- if str
446
- JSON.parse(str, :symbolize_names => true)
447
- end
448
- end
449
-
450
- require 'rest_client'
451
-
452
- # HTTP helpers
453
-
454
- def http_get(path, content_type=nil)
455
- request(:get, path, content_type)
456
- end
457
-
458
- def http_post(path, body, content_type=nil, headers = {})
459
- request(:post, path, content_type, body, headers)
460
- end
461
-
462
- def http_put(path, body, content_type=nil)
463
- request(:put, path, content_type, body)
464
- end
465
-
466
- def http_delete(path)
467
- request(:delete, path)
468
- end
469
-
470
- def request(method, path, content_type = nil, payload = nil, headers = {})
471
- headers = headers.dup
472
- headers['AUTHORIZATION'] = @auth_token if @auth_token
473
- headers['PROXY-USER'] = @proxy if @proxy
474
-
475
- if content_type
476
- headers['Content-Type'] = content_type
477
- headers['Accept'] = content_type
478
- end
479
-
480
- req = {
481
- :method => method, :url => "#{@target}/#{path}",
482
- :payload => payload, :headers => headers, :multipart => true,
483
- :timeout => HTTP_TIMEOUT, :open_timeout => HTTP_TIMEOUT
484
- }
485
- status, body, response_headers = perform_http_request(req)
486
-
487
- if request_failed?(status)
488
- # FIXME, old cc returned 400 on not found for file access
489
- err = (status == 404 || status == 400) ? NotFound : TargetError
490
- raise err, parse_error_message(status, body)
491
- else
492
- return status, body, response_headers
493
- end
494
- rescue URI::Error, SocketError, Errno::ECONNREFUSED => e
495
- raise BadTarget, "Cannot access target (%s)" % [ e.message ]
496
- end
497
-
498
- def request_failed?(status)
499
- VMC_HTTP_ERROR_CODES.detect{|error_code| status >= error_code}
500
- end
501
-
502
- def perform_http_request(req)
503
- proxy_uri = URI.parse(req[:url]).find_proxy()
504
- RestClient.proxy = proxy_uri.to_s if proxy_uri
505
-
506
- # Setup tracing if needed
507
- unless trace.nil?
508
- req[:headers]['X-VCAP-Trace'] = (trace == true ? '22' : trace)
509
- end
510
-
511
- result = nil
512
- RestClient::Request.execute(req) do |response, request|
513
- result = [ response.code, response.body, response.headers ]
514
- unless trace.nil?
515
- puts '>>>'
516
- puts "PROXY: #{RestClient.proxy}" if RestClient.proxy
517
- puts "REQUEST: #{req[:method]} #{req[:url]}"
518
- puts "RESPONSE_HEADERS:"
519
- response.headers.each do |key, value|
520
- puts " #{key} : #{value}"
521
- end
522
- puts "REQUEST_BODY: #{req[:payload]}" if req[:payload]
523
- puts "RESPONSE: [#{response.code}]"
524
- begin
525
- puts JSON.pretty_generate(JSON.parse(response.body))
526
- rescue
527
- puts "#{response.body}"
528
- end
529
- puts '<<<'
530
- end
531
- end
532
- result
533
- rescue Net::HTTPBadResponse => e
534
- raise BadTarget "Received bad HTTP response from target: #{e}"
535
- rescue SystemCallError, RestClient::Exception => e
536
- raise HTTPException, "HTTP exception: #{e.class}:#{e}"
537
- end
538
-
539
- def truncate(str, limit = 30)
540
- etc = '...'
541
- stripped = str.strip[0..limit]
542
- if stripped.length > limit
543
- stripped + etc
544
- else
545
- stripped
546
- end
547
- end
548
-
549
- def parse_error_message(status, body)
550
- parsed_body = json_parse(body.to_s)
551
- if parsed_body && parsed_body[:code] && parsed_body[:description]
552
- desc = parsed_body[:description].gsub("\"","'")
553
- "Error #{parsed_body[:code]}: #{desc}"
554
- else
555
- "Error (HTTP #{status}): #{body}"
556
- end
557
- rescue JSON::ParserError
558
- if body.nil? || body.empty?
559
- "Error (#{status}): No Response Received"
560
- else
561
- body_out = trace ? body : truncate(body)
562
- "Error (JSON #{status}): #{body_out}"
563
- end
564
- end
565
-
566
- def check_login_status
567
- raise AuthError unless @user || logged_in?
568
- end
569
-
570
- def infras_match?(o1,o2)
571
- o1 && o2 && ( o1[:infra] == o2[:infra])
572
- end
573
-
574
- end