Class: VMC::Client

Inherits:
Object show all
Defined in:
lib/vmc/client.rb

Defined Under Namespace

Classes: AuthError, BadResponse, BadTarget, HTTPException, NotFound, TargetError

Constant Summary collapse

VMC_HTTP_ERROR_CODES =

Error codes

[ 400, 500 ]
HTTP_TIMEOUT =
ENV['TIMEOUT'] ? ENV['TIMEOUT'].to_i : 10*60

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(target_url = VMC::DEFAULT_TARGET, auth_token = nil) ⇒ Client

Initialize new client to the target_uri with optional auth_token



41
42
43
44
45
46
# File 'lib/vmc/client.rb', line 41

def initialize(target_url=VMC::DEFAULT_TARGET, auth_token=nil)
  target_url = "https://#{target_url}" unless /^https?/ =~ target_url
  target_url = target_url.gsub(/\/+$/, '')
  @target = target_url
  @auth_token = auth_token
end

Instance Attribute Details

#auth_tokenObject (readonly)

Returns the value of attribute auth_token.



24
25
26
# File 'lib/vmc/client.rb', line 24

def auth_token
  @auth_token
end

#hostObject (readonly)

Returns the value of attribute host.



24
25
26
# File 'lib/vmc/client.rb', line 24

def host
  @host
end

#infraObject

Returns the value of attribute infra.



25
26
27
# File 'lib/vmc/client.rb', line 25

def infra
  @infra
end

#proxyObject

Returns the value of attribute proxy.



24
25
26
# File 'lib/vmc/client.rb', line 24

def proxy
  @proxy
end

#targetObject (readonly)

Returns the value of attribute target.



24
25
26
# File 'lib/vmc/client.rb', line 24

def target
  @target
end

#traceObject

Returns the value of attribute trace.



25
26
27
# File 'lib/vmc/client.rb', line 25

def trace
  @trace
end

#userObject (readonly)

Returns the value of attribute user.



24
25
26
# File 'lib/vmc/client.rb', line 24

def user
  @user
end

Class Method Details

.path(*path) ⇒ Object



359
360
361
362
363
# File 'lib/vmc/client.rb', line 359

def self.path(*path)
  path.flatten.collect { |x|
    URI.encode x.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
  }.join("/")
end

.versionObject



20
21
22
# File 'lib/vmc/client.rb', line 20

def self.version
  VMC::VERSION
end

Instance Method Details

#add_user(user_email, password) ⇒ Object



348
349
350
# File 'lib/vmc/client.rb', line 348

def add_user(user_email, password)
  json_post(VMC::USERS_PATH, { :email => user_email, :password => password })
end

#app_crashes(name) ⇒ Object



147
148
149
150
# File 'lib/vmc/client.rb', line 147

def app_crashes(name)
  
  json_get(path(VMC::APPS_PATH, name, "crashes"))
end

#app_download(name, path) ⇒ Object



162
163
164
165
166
167
168
169
# File 'lib/vmc/client.rb', line 162

def app_download(name,path)
  
  url = path(VMC::APPS_PATH, name, "application")
  status, body, headers = http_get(url,'application/octet-stream')
  file = File.new(path,"wb")
  file.write(body)
  file.close
end

#app_files(name, path, instance = '0') ⇒ Object

List the directory or download the actual file indicated by the path.



154
155
156
157
158
159
160
# File 'lib/vmc/client.rb', line 154

def app_files(name, path, instance='0')
  
  path = path.gsub('//', '/')
  url = path(VMC::APPS_PATH, name, "instances", instance, "files", path)
  _, body, headers = http_get(url)
  body
end

#app_info(name) ⇒ Object



118
119
120
121
# File 'lib/vmc/client.rb', line 118

def app_info(name)
  
  json_get(path(VMC::APPS_PATH, name))
end

#app_instances(name) ⇒ Object



142
143
144
145
# File 'lib/vmc/client.rb', line 142

def app_instances(name)
  
  json_get(path(VMC::APPS_PATH, name, "instances"))
end

#app_pull(name, dir) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
# File 'lib/vmc/client.rb', line 171

def app_pull(name, dir)
  
  url = path(VMC::APPS_PATH, name, "application")
  status, body, headers = http_get(url,'application/octet-stream')
  file = Tempfile.new(name)
  file.binmode
  file.write(body)
  file.close
  ::VMC::Cli::ZipUtil.unpack(file.path, dir)
  file.unlink
end

#app_stats(name) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/vmc/client.rb', line 128

def app_stats(name)
  
  stats_raw = json_get(path(VMC::APPS_PATH, name, "stats"))
  stats = []
  stats_raw.each_pair do |k, entry|
    # Skip entries with no stats
    next unless entry[:stats]
    entry[:instance] = k.to_s.to_i
    entry[:state] = entry[:state].to_sym if entry[:state]
    stats << entry
  end
  stats.sort { |a,b| a[:instance] - b[:instance] }
end

#app_update_info(name) ⇒ Object



123
124
125
126
# File 'lib/vmc/client.rb', line 123

def app_update_info(name)
  
  json_get(path(VMC::APPS_PATH, name, "update"))
end

#appsObject

Apps



76
77
78
79
# File 'lib/vmc/client.rb', line 76

def apps
  
  json_get(VMC::APPS_PATH)
end

#base_for_infra(name) ⇒ Object



379
380
381
382
# File 'lib/vmc/client.rb', line 379

def base_for_infra(name)
  info = infras.detect { |i| i[:infra] == name }
  info ? info[:base] : default_base
end

#bind_service(service, appname) ⇒ Object



230
231
232
233
234
235
236
237
238
239
240
# File 'lib/vmc/client.rb', line 230

def bind_service(service, appname)
  
  svc = services.detect { |s| s[:name] == service }
  app = app_info(appname)
  if infra_supported? && ! infras_match?(app,svc)
    raise TargetError, "Service #{service} and App #{appname} are not on the same infra"
  end
  services = app[:services] || []
  app[:services] = services << service
  update_app(appname, app)
end

#change_password(new_password) ⇒ Object

sets the password for the current logged user



322
323
324
325
326
327
328
329
# File 'lib/vmc/client.rb', line 322

def change_password(new_password)
  
   = json_get(path(VMC::USERS_PATH, @user))
  if 
    [:password] = new_password
    json_put(path(VMC::USERS_PATH, @user), )
  end
end

#check_resources(resources, infra = nil) ⇒ Object

Send in a resources manifest array to the system to have it check what is needed to actually send. Returns array indicating what is needed. This returned manifest should be sent in with the upload if resources were removed. E.g. [=> xxx, :size => xxx, :fn => filename]



268
269
270
271
272
273
274
275
276
# File 'lib/vmc/client.rb', line 268

def check_resources(resources,infra=nil)
  
  url = VMC::RESOURCES_PATH
  unless infra.nil?
    url += "?infra=#{infra}"
  end
  status, body, headers = json_post(url, resources)
  json_parse(body)
end

#create_app(name, manifest = {}) ⇒ Object



81
82
83
84
85
86
87
# File 'lib/vmc/client.rb', line 81

def create_app(name, manifest={})
  
  app = manifest.dup
  app[:name] = name
  app[:instances] ||= 1
  json_post(VMC::APPS_PATH, app)
end

#create_service(infra, service, name) ⇒ Object

Raises:



193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/vmc/client.rb', line 193

def create_service(infra,service, name)
  
  services = services_info
  services ||= []
  service_hash = nil

  service = service.to_s

  # FIXME!
  services.each do |service_type, value|
    value.each do |vendor, version|
      version.each do |version_str, service_descr|
        if service == service_descr[:vendor]
          service_hash = {
            :type => service_descr[:type], :tier => 'free',
            :vendor => service, :version => version_str
          }
          service_hash[:infra] = { :provider => infra } if infra
          break
        end
      end
    end
  end

  raise TargetError, "Service [#{service}] is not a valid service choice" unless service_hash
  service_hash[:name] = name
  json_post(path(VMC::SERVICES_PATH), service_hash)
end

#default_baseObject



384
385
386
387
# File 'lib/vmc/client.rb', line 384

def default_base
  return "vcap.me" if @target =~ /https?:\/\/api.vcap.me/
  "aws.as.cm"
end

#delete_app(name) ⇒ Object



113
114
115
116
# File 'lib/vmc/client.rb', line 113

def delete_app(name)
  
  http_delete(path(VMC::APPS_PATH, name))
end

#delete_service(name) ⇒ Object

Raises:



222
223
224
225
226
227
228
# File 'lib/vmc/client.rb', line 222

def delete_service(name)
  
  svcs = services || []
  names = svcs.collect { |s| s[:name] }
  raise TargetError, "Service [#{name}] not a valid service" unless names.include? name
  http_delete(path(VMC::SERVICES_PATH, name))
end

#delete_user(user_email) ⇒ Object



352
353
354
355
# File 'lib/vmc/client.rb', line 352

def delete_user(user_email)
  
  http_delete(path(VMC::USERS_PATH, user_email))
end

#export_service(service) ⇒ Object



251
252
253
# File 'lib/vmc/client.rb', line 251

def export_service(service)
  json_get(path(VMC::SERVICE_EXPORT_PATH, service))
end

#import_service(service, uri) ⇒ Object



255
256
257
# File 'lib/vmc/client.rb', line 255

def import_service(service,uri)
  json_post(path(VMC::SERVICE_IMPORT_PATH, service),{:uri => uri})
end

#infoObject

Retrieves information on the target cloud, and optionally the logged in user



53
54
55
56
# File 'lib/vmc/client.rb', line 53

def info
  # TODO: Should merge for new version IMO, general, services, user_account
  json_get(VMC::INFO_PATH)
end

#infra_descriptionsObject



393
394
395
# File 'lib/vmc/client.rb', line 393

def infra_descriptions
  infras.map { |i| i[:description] }
end

#infra_name_for_description(desc) ⇒ Object



397
398
399
400
# File 'lib/vmc/client.rb', line 397

def infra_name_for_description(desc) 
  info = infras.detect { |i| i[:description] == desc }
  info ? info[:infra] : ""
end

#infra_supported?Boolean

Returns:

  • (Boolean)


375
376
377
# File 'lib/vmc/client.rb', line 375

def infra_supported?
  !infras.empty?
end

#infra_valid?(name) ⇒ Boolean

Returns:

  • (Boolean)


389
390
391
# File 'lib/vmc/client.rb', line 389

def infra_valid?(name) 
  infras.detect { |i| i[:infra] == name }
end

#infrasObject

Infrastructure



369
370
371
372
373
# File 'lib/vmc/client.rb', line 369

def infras
  json_get(path(VMC::GLOBAL_INFRAS_PATH))
rescue
  []
end

#logged_in?Boolean

Checks that the auth_token is valid

Returns:

  • (Boolean)


295
296
297
298
299
300
301
302
303
# File 'lib/vmc/client.rb', line 295

def logged_in?
  descr = info
  if descr
    return false unless descr[:user]
    return false unless descr[:usage]
    @user = descr[:user]
    true
  end
end

#login(user, password) ⇒ Object

login and return an auth_token Auth token can be retained and used in creating new clients, avoiding login.



312
313
314
315
316
317
318
319
# File 'lib/vmc/client.rb', line 312

def (user, password)
  status, body, headers = json_post(path(VMC::USERS_PATH, user, "tokens"), {:password => password})
  response_info = json_parse(body)
  if response_info
    @user = user
    @auth_token = response_info[:token]
  end
end

#proxy_for(proxy) ⇒ Object



339
340
341
# File 'lib/vmc/client.rb', line 339

def proxy_for(proxy)
  @proxy = proxy
end

#raw_infoObject



58
59
60
# File 'lib/vmc/client.rb', line 58

def raw_info
  http_get(VMC::INFO_PATH)
end

#runtimes_infoObject



68
69
70
# File 'lib/vmc/client.rb', line 68

def runtimes_info
  json_get(path(VMC::GLOBAL_RUNTIMES_PATH))
end

#servicesObject

listing of services that are available in the system



188
189
190
191
# File 'lib/vmc/client.rb', line 188

def services
  
  json_get(VMC::SERVICES_PATH)
end

#services_infoObject

Global listing of services that are available on the target system



63
64
65
66
# File 'lib/vmc/client.rb', line 63

def services_info
  
  json_get(path(VMC::GLOBAL_SERVICES_PATH))
end

#suggest_url(infra = nil) ⇒ Object



402
403
404
# File 'lib/vmc/client.rb', line 402

def suggest_url(infra=nil)
  @suggest_url ||= base_for_infra(infra || @infra)
end

#target_valid?Boolean

Checks that the target is valid

Returns:

  • (Boolean)


283
284
285
286
287
288
289
290
291
292
# File 'lib/vmc/client.rb', line 283

def target_valid?
  return false unless descr = info
  return false unless descr[:name]
  return false unless descr[:build]
  return false unless descr[:version]
  return false unless descr[:support]
  true
rescue
  false
end

#unbind_service(service, appname) ⇒ Object



242
243
244
245
246
247
248
249
# File 'lib/vmc/client.rb', line 242

def unbind_service(service, appname)
  
  app = app_info(appname)
  services = app[:services] || []
  services.delete(service)
  app[:services] = services
  update_app(appname, app)
end

#update_app(name, manifest) ⇒ Object



89
90
91
92
# File 'lib/vmc/client.rb', line 89

def update_app(name, manifest)
  
  json_put(path(VMC::APPS_PATH, name), manifest)
end

#upload_app(name, zipfile, resource_manifest = nil) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/vmc/client.rb', line 94

def upload_app(name, zipfile, resource_manifest=nil)
  #FIXME, manifest should be allowed to be null, here for compatability with old cc's
  resource_manifest ||= []
  
  upload_data = {:_method => 'put'}
  if zipfile
    if zipfile.is_a? File
      file = zipfile
    else
      file = File.new(zipfile, 'rb')
    end
    upload_data[:application] = file
  end
  upload_data[:resources] = resource_manifest.to_json if resource_manifest
  http_post(path(VMC::APPS_PATH, name, "application"), upload_data)
rescue RestClient::ServerBrokeConnection
  retry
end

#usersObject



343
344
345
346
# File 'lib/vmc/client.rb', line 343

def users
  
  json_get(VMC::USERS_PATH)
end