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:
Shu Muto 2016-10-04 16:16:49 +09:00
parent 325380b7b2
commit 543a2a02f4
11 changed files with 170 additions and 70 deletions

View File

@ -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

View File

@ -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}

View File

@ -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)

View File

@ -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) {

View File

@ -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];
}
}

View File

@ -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();
};
}
})();

View File

@ -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>

View File

@ -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>

View File

@ -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() {
}
})();

View File

@ -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>

View File

@ -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>