Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 36 additions & 37 deletions jstests/tests/home/mock_jsapi.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,50 @@ define(['jquery'], function ($) {

return {
Application: {
data: {
"12345": {
image: {
name: "app1",
ui_name: "Application 1",
icon_128: "",
description: "description",
policy: {
allow_home: true,
volume_source: "",
volume_target: "",
volume_mode: ""
},
configurables: [
"resolution"
]
}
},
"67890": {
image: {
name: "app2",
ui_name: "Application 2",
icon_128: "",
description: "description",
policy: {
allow_home: true,
volume_source: "",
volume_target: "",
volume_mode: ""
},
configurables: []
}
}
},
create: function() {
},
delete: function() {
},
retrieve: function(id) {
var data = {
"12345": {
image: {
name: "app1",
ui_name: "Application 1",
icon_128: "",
description: "description",
policy: {
allow_home: true,
volume_source: "",
volume_target: "",
volume_mode: ""
},
configurables: [
"resolution"
]
}
},
"67890": {
image: {
name: "app2",
ui_name: "Application 2",
icon_128: "",
description: "description",
policy: {
allow_home: true,
volume_source: "",
volume_target: "",
volume_mode: ""
},
configurables: []
}
}
};

return $.when(data[id]);
return $.when(this.data[id]);

},
items: function() {
return $.when(["12345", "67890"]);
return $.when(["12345", "67890"], this.data);
}
},
Container: {
Expand Down
2 changes: 1 addition & 1 deletion jstests/tests/home/test_models.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ define([
"home/models"
], function (models) {
"use strict";

QUnit.module("home.models");
QUnit.test("instantiation", function (assert) {
var model = new models.ApplicationListModel();
Expand Down
8 changes: 4 additions & 4 deletions remoteappmanager/admin_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ class AdminApplication(BaseApplication):
"""Tornado main application"""

def _webapi_resources(self):
return [admin.Container,
admin.Application,
admin.User,
admin.Accounting]
return [admin.ContainerHandler,
admin.ApplicationHandler,
admin.UserHandler,
admin.AccountingHandler]

def _web_handlers(self):
base_urlpath = self.command_line_config.base_urlpath
Expand Down
4 changes: 2 additions & 2 deletions remoteappmanager/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ class Application(BaseApplication):
"""Tornado main application"""

def _webapi_resources(self):
return [webapi.Application,
webapi.Container]
return [webapi.ApplicationHandler,
webapi.ContainerHandler]

def _web_handlers(self):
base_urlpath = self.command_line_config.base_urlpath
Expand Down
4 changes: 2 additions & 2 deletions remoteappmanager/base_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ def _user_default(self):
def _registry_default(self):
reg = Registry()
reg.authenticator = HubAuthenticator
for resource_class in self._webapi_resources():
reg.register(resource_class)
for resource_handler in self._webapi_resources():
reg.register(resource_handler)
return reg

# Public
Expand Down
56 changes: 7 additions & 49 deletions remoteappmanager/static/js/home/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,54 +25,12 @@ define([
var promise = $.Deferred();

resources.Application.items()
.done(function (ids) {
// We neutralize the potential error from a jXHR request
// and make sure that all our requests "succeed" so that
// all/when can guarantee everything is done.

// These will go out of scope but they are still alive
// and performing to completion
var requests = [];
for (var i = 0; i < ids.length; i++) {
requests.push($.Deferred());
}

// We need to bind with the current i index in the loop
// Hence we create these closures to grab the index for
// each new index
var done_callback = function(index) {
return function(rep) {
requests[index].resolve(rep);
};
};
var fail_callback = function(index) {
return function() {
requests[index].resolve(null);
};
};

for (i = 0; i < ids.length; i++) {
var id = ids[i];
resources.Application.retrieve(id)
.done(done_callback(i))
.fail(fail_callback(i));

}

utils.all(requests)
.done(function (promises) {
// Fills the local application model with the results of the
// retrieve promises.
var data = [];
for (var i = 0; i < promises.length; i++) {
var result = promises[i];
if (result !== null) {
data.push(result);
}
}
promise.resolve(data);
});

.done(function (identifiers, items) {
var result = [];
Object.keys(items).forEach(function(key) {
result.push(items[key]);
});
promise.resolve(result);
})
.fail(function() {
promise.resolve([]);
Expand Down Expand Up @@ -163,7 +121,7 @@ define([
var self = this;
var app_data = self.app_data[index];

if (app_data.container === null) {
if (app_data.container === undefined) {
self.status[index] = Status.STOPPED;
} else {
self.status[index] = Status.RUNNING;
Expand Down
4 changes: 3 additions & 1 deletion remoteappmanager/tests/webapi_test_case.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
from tornado import escape
from tornado.testing import LogTrapTestCase

from .utils import AsyncHTTPTestCase


class WebAPITestCase(AsyncHTTPTestCase):
class WebAPITestCase(AsyncHTTPTestCase, LogTrapTestCase):
"""Base class for tests accessing the Web API,
providing basic methods to issue web requests, get results, and compare
against the expected HTTP code.
Expand Down
4 changes: 2 additions & 2 deletions remoteappmanager/webapi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .container import Container # noqa
from .application import Application # noqa
from .container import ContainerHandler # noqa
from .application import ApplicationHandler # noqa
8 changes: 4 additions & 4 deletions remoteappmanager/webapi/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .container import Container # noqa
from .application import Application # noqa
from .user import User # noqa
from .accounting import Accounting # noqa
from .container import ContainerHandler # noqa
from .application import ApplicationHandler # noqa
from .user import UserHandler # noqa
from .accounting import AccountingHandler # noqa
48 changes: 25 additions & 23 deletions remoteappmanager/webapi/admin/accounting.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from tornado import gen
from tornadowebapi.resource_handler import ResourceHandler
from tornadowebapi.traitlets import Absent, Unicode, Bool

from remoteappmanager.utils import parse_volume_string
from tornadowebapi import exceptions
Expand All @@ -9,47 +11,47 @@


class Accounting(Resource):
__collection_name__ = "accounting"

def validate_representation(self, representation):
representation["user_name"] = _not_empty_str(
representation["user_name"])
representation["image_name"] = _not_empty_str(
representation["image_name"])
representation["allow_home"] = bool(
representation["allow_home"])

if "volume" in representation:
representation["volume"] = _not_empty_str(
representation["volume"])
parse_volume_string(representation["volume"])
return representation
user_name = Unicode(allow_empty=False, strip=True)
image_name = Unicode(allow_empty=False, strip=True)
allow_home = Bool()
volume = Unicode(optional=True, allow_empty=False, strip=True)

@classmethod
def collection_name(cls):
return "accounting"


class AccountingHandler(ResourceHandler):
resource_class = Accounting

@gen.coroutine
@authenticated
def create(self, representation):
def create(self, resource, **kwargs):
db = self.application.db

volume = {} if resource.volume == Absent else resource.volume
parse_volume_string(volume)

try:
id = db.grant_access(
representation["image_name"],
representation["user_name"],
representation["allow_home"],
resource.image_name,
resource.user_name,
resource.allow_home,
True,
representation.get("volume")
volume,
)
except db_exceptions.NotFound:
raise exceptions.NotFound()

return id
resource.identifier = id

@gen.coroutine
@authenticated
def delete(self, identifier):
def delete(self, resource, **kwargs):
db = self.application.db

try:
db.revoke_access_by_id(identifier)
db.revoke_access_by_id(resource.identifier)
except db_exceptions.NotFound:
raise exceptions.NotFound()

Expand Down
30 changes: 15 additions & 15 deletions remoteappmanager/webapi/admin/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,47 @@

from tornadowebapi import exceptions
from tornadowebapi.resource import Resource
from tornadowebapi.resource_handler import ResourceHandler
from tornadowebapi.traitlets import Unicode

from remoteappmanager.webapi.decorators import authenticated
from remoteappmanager.db import exceptions as db_exceptions


class Application(Resource):
def validate_representation(self, representation):
representation["image_name"] = str(representation["image_name"])
if len(representation["image_name"]) == 0:
raise ValueError("image_name cannot be empty")
image_name = Unicode(allow_empty=False, strip=True)

return representation

def validate_identifier(self, identifier):
return int(identifier)
class ApplicationHandler(ResourceHandler):
resource_class = Application

@gen.coroutine
@authenticated
def delete(self, identifier):
def delete(self, resource, **kwargs):
"""Removes the application."""
db = self.application.db
try:
id = int(resource.identifier)
except ValueError:
raise exceptions.NotFound()

try:
db.remove_application(id=identifier)
self.log.info("Removed application with id {}".format(identifier))
db.remove_application(id=id)
self.log.info("Removed application with id {}".format(id))
except db_exceptions.NotFound:
raise exceptions.NotFound()
except db_exceptions.UnsupportedOperation:
raise exceptions.Unable()

@gen.coroutine
@authenticated
def create(self, representation):
image_name = representation["image_name"]

def create(self, resource, **kwargs):
db = self.application.db
try:
id = db.create_application(image_name)
id = db.create_application(resource.image_name)
except db_exceptions.Exists:
raise exceptions.Exists()
except db_exceptions.UnsupportedOperation:
raise exceptions.Unable()

return id
resource.identifier = str(id)
Loading