Use zunclient instead of stub
Use python-zunclient instead of stub client in skeleton. Then Zun-UI interacts with Zun API. This patch enable CRUD operation of containers. Change-Id: Idc869c0d4d40895e42ccf941f7fcb9d6d1dfb662 Implements: blueprint use-zunclient
This commit is contained in:
parent
325380b7b2
commit
543a2a02f4
@ -8,8 +8,8 @@
|
||||
#
|
||||
# PBR should always appear first
|
||||
pbr>=1.6 # Apache-2.0
|
||||
# If python-higginsclient will be created, we will use it.
|
||||
#python-higginsclient>=0.1.0 # Apache-2.0
|
||||
# If python-zunclient will be released, we will use it.
|
||||
#python-zunclient>=0.0.1 # Apache-2.0
|
||||
Babel>=2.3.4 # BSD
|
||||
Django<1.9,>=1.8 # BSD
|
||||
django-babel>=0.5.1 # BSD
|
||||
|
7
tox.ini
7
tox.ini
@ -16,6 +16,13 @@ deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python manage.py test {posargs} --settings=zun_ui.test.settings
|
||||
|
||||
# Until python-zunclient released, install from github temporary.
|
||||
[testenv:py27]
|
||||
basepython = python2.7
|
||||
commands =
|
||||
pip install git+https://github.com/openstack/python-zunclient.git
|
||||
python manage.py test {posargs} --settings=zun_ui.test.settings
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8 {posargs}
|
||||
|
||||
|
@ -11,45 +11,20 @@
|
||||
# under the License.
|
||||
|
||||
|
||||
from __future__ import absolute_import
|
||||
import logging
|
||||
# from zunclient.v1 import client as zun_client
|
||||
|
||||
from horizon import exceptions
|
||||
from horizon.utils.memoized import memoized
|
||||
# from openstack_dashboard.api import base
|
||||
|
||||
# for stab, should remove when use CLI API
|
||||
import copy
|
||||
import uuid
|
||||
import logging
|
||||
from openstack_dashboard.api import base
|
||||
from zunclient.v1 import client as zun_client
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
CONTAINER_CREATE_ATTRS = ['name']
|
||||
|
||||
STUB_DATA = {}
|
||||
|
||||
|
||||
# for stab, should be removed when use CLI API
|
||||
class StubResponse(object):
|
||||
|
||||
def __init__(self, info):
|
||||
self._info = info
|
||||
|
||||
def __repr__(self):
|
||||
reprkeys = sorted(k for k in self.__dict__.keys() if k[0] != '_')
|
||||
info = ", ".join("%s=%s" % (k, getattr(self, k)) for k in reprkeys)
|
||||
return "<%s %s>" % (self.__class__.__name__, info)
|
||||
|
||||
def to_dict(self):
|
||||
return copy.deepcopy(self._info)
|
||||
CONTAINER_CREATE_ATTRS = ['name', 'image', 'command', 'memory', 'environment']
|
||||
|
||||
|
||||
@memoized
|
||||
def zunclient(request):
|
||||
pass
|
||||
""""
|
||||
zun_url = ""
|
||||
try:
|
||||
zun_url = base.url_for(request, 'container')
|
||||
@ -60,11 +35,10 @@ def zunclient(request):
|
||||
LOG.debug('zunclient connection created using the token "%s" and url'
|
||||
'"%s"' % (request.user.token.id, zun_url))
|
||||
c = zun_client.Client(username=request.user.username,
|
||||
project_id=request.user.tenant_id,
|
||||
input_auth_token=request.user.token.id,
|
||||
zun_url=zun_url)
|
||||
project_id=request.user.tenant_id,
|
||||
input_auth_token=request.user.token.id,
|
||||
zun_url=zun_url)
|
||||
return c
|
||||
"""
|
||||
|
||||
|
||||
def container_create(request, **kwargs):
|
||||
@ -75,41 +49,28 @@ def container_create(request, **kwargs):
|
||||
else:
|
||||
raise exceptions.BadRequest(
|
||||
"Key must be in %s" % ",".join(CONTAINER_CREATE_ATTRS))
|
||||
if key == "labels":
|
||||
labels = {}
|
||||
if key == "environment":
|
||||
envs = {}
|
||||
vals = value.split(",")
|
||||
for v in vals:
|
||||
kv = v.split("=", 1)
|
||||
labels[kv[0]] = kv[1]
|
||||
args["labels"] = labels
|
||||
# created = zunclient(request).containers.create(**args)
|
||||
|
||||
# create dummy response
|
||||
args["uuid"] = uuid.uuid1().hex
|
||||
created = StubResponse(args)
|
||||
for k in args:
|
||||
setattr(created, k, args[k])
|
||||
STUB_DATA[created.uuid] = created
|
||||
|
||||
return created
|
||||
envs[kv[0]] = kv[1]
|
||||
args["environment"] = envs
|
||||
return zunclient(request).containers.create(**args)
|
||||
|
||||
|
||||
def container_delete(request, id):
|
||||
# deleted = zunclient(request).containers.delete(id)
|
||||
deleted = STUB_DATA.pop(id)
|
||||
|
||||
return deleted
|
||||
def container_delete(request, id, force=False):
|
||||
# TODO(shu-mutou): force option should be provided by user.
|
||||
return zunclient(request).containers.delete(id, force)
|
||||
|
||||
|
||||
def container_list(request, limit=None, marker=None, sort_key=None,
|
||||
sort_dir=None, detail=True):
|
||||
# list = zunclient(request).containers.list(limit, marker, sort_key,
|
||||
# sort_dir, detail)
|
||||
list = [STUB_DATA[data] for data in STUB_DATA]
|
||||
return list
|
||||
# TODO(shu-mutou): detail option should be added, if it is
|
||||
# implemented in Zun API
|
||||
return zunclient(request).containers.list(limit, marker, sort_key,
|
||||
sort_dir)
|
||||
|
||||
|
||||
def container_show(request, id):
|
||||
# show = zunclient(request).containers.get(id)
|
||||
show = STUB_DATA.get(id)
|
||||
return show
|
||||
return zunclient(request).containers.get(id)
|
||||
|
@ -65,6 +65,12 @@
|
||||
.setProperty('id', {
|
||||
label: gettext('ID')
|
||||
})
|
||||
.setProperty('image', {
|
||||
label: gettext('Image')
|
||||
})
|
||||
.setProperty('status', {
|
||||
label: gettext('Status')
|
||||
})
|
||||
.setListFunction(listFunction)
|
||||
.tableColumns
|
||||
.append({
|
||||
@ -77,6 +83,14 @@
|
||||
.append({
|
||||
id: 'id',
|
||||
priority: 2
|
||||
})
|
||||
.append({
|
||||
id: 'image',
|
||||
priority: 2
|
||||
})
|
||||
.append({
|
||||
id: 'status',
|
||||
priority: 2
|
||||
});
|
||||
// for magic-search
|
||||
registry.getResourceType(resourceType).filterFacets
|
||||
@ -89,6 +103,16 @@
|
||||
'label': gettext('ID'),
|
||||
'name': 'id',
|
||||
'singleton': true
|
||||
})
|
||||
.append({
|
||||
'label': gettext('Image'),
|
||||
'name': 'image',
|
||||
'singleton': true
|
||||
})
|
||||
.append({
|
||||
'label': gettext('Status'),
|
||||
'name': 'status',
|
||||
'singleton': true
|
||||
});
|
||||
|
||||
function listFunction(params) {
|
||||
|
@ -34,7 +34,14 @@
|
||||
|
||||
function initNewContainerSpec() {
|
||||
model.newContainerSpec = {
|
||||
uuid: null,
|
||||
name: null,
|
||||
image: null,
|
||||
command: null,
|
||||
memory: null,
|
||||
memory_size: null,
|
||||
memory_unit: "m",
|
||||
environment: null
|
||||
};
|
||||
}
|
||||
|
||||
@ -56,7 +63,8 @@
|
||||
// Not only "null", blank too.
|
||||
for (var key in finalSpec) {
|
||||
if (finalSpec.hasOwnProperty(key) && finalSpec[key] === null
|
||||
|| finalSpec[key] === "") {
|
||||
|| finalSpec[key] === ""
|
||||
|| key === "memory_size" || key === "memory_unit") {
|
||||
delete finalSpec[key];
|
||||
}
|
||||
}
|
||||
|
@ -36,5 +36,23 @@
|
||||
|
||||
function createContainerInfoController($q, $scope, basePath, zun, gettext) {
|
||||
var ctrl = this;
|
||||
ctrl.memory_units = [{unit: "b", label: gettext("bytes")},
|
||||
{unit: "k", label: gettext("KB")},
|
||||
{unit: "m", label: gettext("MB")},
|
||||
{unit: "g", label: gettext("GB")}];
|
||||
|
||||
$scope.changeMemory = function(){
|
||||
if($scope.model.newContainerSpec.memory_size > 0){
|
||||
$scope.model.newContainerSpec.memory = $scope.model.newContainerSpec.memory_size + $scope.model.newContainerSpec.memory_unit;
|
||||
}else{
|
||||
$scope.model.newContainerSpec.memory = null;
|
||||
}
|
||||
};
|
||||
$scope.changeMemoryUnit = function(){
|
||||
$scope.changeMemory();
|
||||
};
|
||||
$scope.changeMemorySize = function(){
|
||||
$scope.changeMemory();
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
@ -1,4 +1,13 @@
|
||||
<dl>
|
||||
<!-- TODO(shu-mutou): descript more! -->
|
||||
<dt translate>Container Name</dt>
|
||||
<dd translate>An arbitrary human-readable name</dd>
|
||||
<dt translate>Image</dt>
|
||||
<dd translate>Name or ID of container image</dd>
|
||||
<dt translate>Command</dt>
|
||||
<dd translate>Command sent to the container</dd>
|
||||
<dt translate>Memory</dt>
|
||||
<dd translate>The container memory size</dd>
|
||||
<dt translate>Environment Variables</dt>
|
||||
<dd translate>The environment variables in comma separated KEY=VALUE pairs</dd>
|
||||
</dl>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div ng-controller="createContainerInfoController as ctrl">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="container-name" translate>Container Name</label>
|
||||
<input name="container-name" type="text" class="form-control" id="container-name"
|
||||
@ -8,5 +8,51 @@
|
||||
placeholder="{$ 'Name of the container to create.'|translate $}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="container-image">
|
||||
<translate>Image</translate>
|
||||
<span class="hz-icon-required fa fa-asterisk"></span>
|
||||
</label>
|
||||
<input name="container-image" type="text" class="form-control" id="container-image"
|
||||
ng-model="model.newContainerSpec.image"
|
||||
ng-required="true"
|
||||
placeholder="{$ 'Name or ID of the container image.'|translate $}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="container-command" translate>Command</label>
|
||||
<input name="container-command" type="text" class="form-control" id="container-command"
|
||||
ng-model="model.newContainerSpec.command"
|
||||
placeholder="{$ 'A command that will be sent to the container.'|translate $}">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="container-memory-size" translate>Memory Size</label>
|
||||
<input name="container-memory-size" type="number" min="1"
|
||||
class="form-control" ng-model="model.newContainerSpec.memory_size"
|
||||
placeholder="{$ 'The container memory size.'|translate $}"
|
||||
ng-change="changeMemorySize()" id="container-memory-size">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="container-memory-unit" translate>Memory Unit</label>
|
||||
<select name="container-memory-unit" id="container-memory-unit"
|
||||
class="form-control" ng-options="mu.unit as mu.label for mu in ctrl.memory_units"
|
||||
ng-model="model.newContainerSpec.memory_unit" ng-change="changeMemoryUnit()">
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="container-environment" translate>Environment Variables</label>
|
||||
<input name="container-environment" type="text" class="form-control" id="container-environment"
|
||||
ng-model="model.newContainerSpec.environment"
|
||||
placeholder="{$ 'KEY1=VALUE1,KEY2=VALUE2...'|translate $}">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -28,12 +28,9 @@
|
||||
.controller('horizon.dashboard.container.containers.DrawerController', controller);
|
||||
|
||||
controller.$inject = [
|
||||
'horizon.app.core.openstack-service-api.zun',
|
||||
'horizon.dashboard.container.containers.resourceType'
|
||||
];
|
||||
|
||||
function controller(zun, resourceType) {
|
||||
var ctrl = this;
|
||||
function controller() {
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -5,12 +5,24 @@
|
||||
<dt translate>ID</dt>
|
||||
<dd>{$ item.id $}</dd>
|
||||
</dl>
|
||||
<dl class="col-md-4">
|
||||
<dt translate>Image</dt>
|
||||
<dd>{$ item.image $}</dd>
|
||||
</dl>
|
||||
<dl class="col-md-3">
|
||||
<dt translate>Status</dt>
|
||||
<dd>{$ item.status $}</dd>
|
||||
</dl>
|
||||
</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<dl class="col-md-5">
|
||||
<dt translate>Name</dt>
|
||||
<dd>{$ item.name $}</dd>
|
||||
<dl class="col-md-9">
|
||||
<dt translate>Command</dt>
|
||||
<dd>{$ item.command $}</dd>
|
||||
</dl>
|
||||
<dl class="col-md-3">
|
||||
<dt translate>Memory</dt>
|
||||
<dd>{$ item.memory $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,6 +6,24 @@
|
||||
<dl class="dl-horizontal">
|
||||
<dt translate>Name</dt>
|
||||
<dd>{$ ctrl.container.name|noName $}</dd>
|
||||
<dt translate>Status</dt>
|
||||
<dd>{$ ctrl.container.status $}</dd>
|
||||
<dt translate>Image</dt>
|
||||
<dd>{$ ctrl.container.image $}</dd>
|
||||
<dt translate>Command</dt>
|
||||
<dd>{$ ctrl.container.command $}</dd>
|
||||
<dt translate>Memory</dt>
|
||||
<dd>{$ ctrl.container.memory $}</dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="col-md-6 detail">
|
||||
<h3 translate>Environment</h3>
|
||||
<hr>
|
||||
<dl class="dl-horizontal">
|
||||
<div ng-repeat="(key, value) in ctrl.container.environment">
|
||||
<dt>{$ key $}</dt>
|
||||
<dd>{$ value $}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user