Merge "Remove Container panel and action"

This commit is contained in:
Jenkins 2016-05-12 23:16:59 +00:00 committed by Gerrit Code Review
commit 5b8f93deb3
39 changed files with 19 additions and 1680 deletions

View File

@ -51,7 +51,6 @@ And enable it in Horizon::
cp ../magnum-ui/enabled/_50_project_containers_panelgroup.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_51_project_containers_bays_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_52_project_containers_baymodels_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_53_project_containers_containers_panel.py openstack_dashboard/local/enabled
To run horizon with the newly enabled Magnum UI plugin run::

View File

@ -8,8 +8,16 @@ Magnum Dashboard
* Source: http://git.openstack.org/cgit/openstack/magnum-ui
* Bugs: http://bugs.launchpad.net/magnum-ui
Installation instructions
=========================
Enabling in DevStack
====================
Add this repo as an external repository into your ``local.conf`` file::
[[local|localrc]]
enable_plugin magnum-ui https://github.com/openstack/magnum-ui
Manual Installation
===================
Begin by cloning the Horizon and Magnum UI repositories::
@ -34,7 +42,6 @@ editor. You will want to customize several settings:
environment. (They should be correct unless you modified your
OpenStack server to change them.)
Install Magnum UI with all dependencies in your virtual environment::
tools/with_venv.sh pip install -e ../magnum-ui/
@ -44,7 +51,13 @@ And enable it in Horizon::
cp ../magnum-ui/enabled/_50_project_containers_panelgroup.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_51_project_containers_bays_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_52_project_containers_baymodels_panel.py openstack_dashboard/local/enabled
cp ../magnum-ui/enabled/_53_project_containers_containers_panel.py openstack_dashboard/local/enabled
To run horizon with the newly enabled Magnum UI plugin run::
./run_tests.sh --runserver 0.0.0.0:8080
to have the application start on port 8080 and the horizon dashboard will be
available in your browser at http://localhost:8080/
Release Notes
=============

View File

@ -1,23 +0,0 @@
# Copyright 2015 NEC Corporation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'bays.containers'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'containers'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# Python panel class of the PANEL to be added.
ADD_PANEL = 'magnum_ui.content.bays.containers.panel.Containers'

View File

@ -112,49 +112,3 @@ def bay_list(request, limit=None, marker=None, sort_key=None,
def bay_show(request, id):
return magnumclient(request).bays.get(id)
def container_create(request, bay_uuid, **kwargs):
"""Creates a container object
:param request: Request context
:param bay_uuid: ID of a bay (Required)
:param kwargs: Image ID, Name, Command, Memory
:returns: Container object
"""
return magnumclient(request).containers.create(bay_uuid=bay_uuid, **kwargs)
def container_delete(request, id):
"""Deletes a container
:param request: Request context
:param id: The ID of the container to delete
"""
magnumclient(request).containers.delete(id)
def container_list(request, marker=None, limit=None, sort_key=None,
sort_dir=None, detail=False):
"""Lists all containers
:param request: Request context
:param marker: Optional, ID of last container in previous results
:param limit: '==0' return all, '> 0' specifies max, None respects max
imposed by Magnum API
:param sort_key: Optional, key to sort by
:param sort_dir: Optional, direction of sorting ('asc' or 'desc')
:param detail: Optional, boolean, return detailed info about containers
"""
return magnumclient(request).containers.list(
marker=marker, limit=limit, sort_key=sort_key, sort_dir=sort_dir,
detail=detail)
def container_show(request, id):
"""Get an individual container
:param request: Request context
:param id: ID of the container to get
"""
return magnumclient(request).containers.get(id)

View File

@ -122,50 +122,3 @@ class Bays(generic.View):
return rest_utils.CreatedResponse(
'/api/containers/bay/%s' % new_bay.uuid,
new_bay.to_dict())
@urls.register
class Container(generic.View):
"""API for retrieving a single container"""
url_regex = r'containers/containers/(?P<container_id>[^/]+)$'
@rest_utils.ajax()
def get(self, request, container_id):
"""Get a specific container"""
return magnum.container_show(request, container_id).to_dict()
@urls.register
class Containers(generic.View):
"""API for Magnum Containers"""
url_regex = r'containers/containers/$'
@rest_utils.ajax()
def get(self, request):
"""Get a list of the Containers for a project.
The returned result is an object with property 'items' and each
item under this is a Container.
"""
result = magnum.container_list(request)
return {'items': [change_to_id(n.to_dict()) for n in result]}
@rest_utils.ajax(data_required=True)
def delete(self, request):
"""Delete one or more Containers by ID.
Returns HTTP 204 (no content) on successful deletion.
"""
for container_id in request.DATA:
magnum.container_delete(request, container_id)
@rest_utils.ajax(data_required=True)
def post(self, request):
"""Create a new Container.
Returns the new Container object on success.
"""
container = magnum.container_create(request, **request.DATA)
return rest_utils.CreatedResponse(
'/api/containers/container/%s' % container.uuid,
container.to_dict())

View File

@ -1,21 +0,0 @@
# Copyright 2015 Cisco Systems
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.utils.translation import ugettext_lazy as _
import horizon
class Containers(horizon.Panel):
name = _("Containers")
slug = "bays.containers"

View File

@ -1,36 +0,0 @@
# Copyright 2015 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
# from django.core.urlresolvers import reverse
# import horizon
# from magnum_ui.containers.containers.panel import Containers
from openstack_dashboard.test import helpers as test
class ContainerTests(test.TestCase):
def test_me(self):
self.assertTrue(1 + 1 == 2)
# FIXME(shu-mutou): this tests seems not to work in new Horizon's plugin
# registration system
# def test_registration(self):
# dashboard = horizon.get_dashboard('project')
# registered_panel = dashboard.get_panel('containers.containers')
# self.assertEqual(registered_panel.slug, Containers.slug)
# def test_index(self):
# index = reverse('horizon:bays:containers:index')
# res = self.client.get(index)
# self.assertTemplateUsed(
# res, 'project/bays/containers/index.html')

View File

@ -1,22 +0,0 @@
# Copyright 2015 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from django.conf.urls import url
from magnum_ui.content.bays.containers import views
urlpatterns = [
url(r'^[0-9a-f\-]{36}$', views.IndexView.as_view(), name='detail'),
url(r'^$', views.IndexView.as_view(), name='index'),
]

View File

@ -1,19 +0,0 @@
# Copyright 2015 Cisco Systems
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from horizon import views
class IndexView(views.APIView):
template_name = 'bays.containers/index.html'

View File

@ -12,14 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from django.conf.urls import include
from django.conf.urls import url
from magnum_ui.content.bays.containers import urls as containers_urls
from magnum_ui.content.bays.views import IndexView
urlpatterns = [
url(r'^containers/', include(containers_urls, namespace='containers')),
url(r'^[0-9a-f\-]{36}$', IndexView.as_view(), name='detail'),
url(r'^$', IndexView.as_view(), name='index'),
]

View File

@ -30,7 +30,6 @@
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.containers.bays.create.service',
'horizon.dashboard.containers.bays.delete.service',
'horizon.dashboard.containers.containers.create.service',
'horizon.dashboard.containers.bays.resourceType',
];
@ -39,18 +38,10 @@
gettext,
createBayService,
deleteBayService,
createContainerService,
resourceType)
{
var bayResourceType = registry.getResourceType(resourceType);
bayResourceType.itemActions
.append({
id: 'createContainerAction',
service: createContainerService,
template: {
text: gettext('Create Container')
}
})
.append({
id: 'deleteBayAction',
service: deleteBayService,

View File

@ -27,13 +27,12 @@
'$routeParams',
'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.bays.events',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.bays.resourceType'
];
function BayDetailController(
$scope, $window, $location, $routeParams, magnum, events, containerEvents, registry, bayResourceType
$scope, $window, $location, $routeParams, magnum, events, registry, bayResourceType
) {
var ctrl = this;
ctrl.bay = {};
@ -43,7 +42,6 @@
var bayId = $routeParams.bayId;
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
var createContainerWatcher = $scope.$on(containerEvents.CREATE_SUCCESS, onCreateContainerSuccess);
$scope.$on('$destroy', destroy);
@ -70,14 +68,8 @@
$location.path("/project/bays");
}
function onCreateContainerSuccess(e, createdItem) {
e.stopPropagation();
$location.path("/project/bays/containers");
}
function destroy() {
deleteWatcher();
createContainerWatcher();
}
}
})();

View File

@ -34,12 +34,11 @@
'$location',
'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.bays.events',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.bays.resourceType'
];
function containersBaysTableController($scope, $location, magnum, events, containerEvents, registry, bayResourceType) {
function containersBaysTableController($scope, $location, magnum, events, registry, bayResourceType) {
var ctrl = this;
ctrl.bays = [];
ctrl.baysSrc = [];
@ -78,7 +77,6 @@
];
var createWatcher = $scope.$on(events.CREATE_SUCCESS, onCreateSuccess);
var createContainerWatcher = $scope.$on(containerEvents.CREATE_SUCCESS, onCreateContainerSuccess);
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
$scope.$on('$destroy', destroy);
@ -99,11 +97,6 @@
e.stopPropagation();
}
function onCreateContainerSuccess(e, createdItem) {
e.stopPropagation();
$location.path("/project/bays/containers");
}
function onDeleteSuccess(e, removedIds) {
ctrl.baysSrc = difference(ctrl.baysSrc, removedIds, 'id');
e.stopPropagation();
@ -125,7 +118,6 @@
function destroy() {
createWatcher();
createContainerWatcher();
deleteWatcher();
}
}

View File

@ -28,7 +28,6 @@
.module('horizon.dashboard.containers', [
'horizon.dashboard.containers.bays',
'horizon.dashboard.containers.baymodels',
'horizon.dashboard.containers.containers',
'ngRoute'
])
.config(config)
@ -41,12 +40,6 @@
$provide.constant('horizon.dashboard.containers.basePath', path);
$routeProvider
.when('/project/bays/containers', {
templateUrl: path + 'containers/table/table.html'
})
.when('/project/bays/containers/:containerId', {
templateUrl: path + 'containers/detail/detail.html'
})
.when('/project/baymodels', {
templateUrl: path + 'baymodels/table/table.html'
})

View File

@ -1,6 +1,5 @@
@import "baymodels/baymodels";
@import "bays/bays";
@import "containers/containers";
.table > thead > .action-row > th > actions {
float: right;

View File

@ -1,73 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @ngname horizon.dashboard.containers.containers.actions
*
* @description
* Provides all of the actions for containers.
*/
angular.module('horizon.dashboard.containers.containers.actions', ['horizon.framework', 'horizon.dashboard.containers'])
.run(registerContainerActions);
registerContainerActions.$inject = [
'horizon.framework.conf.resource-type-registry.service',
'horizon.framework.util.i18n.gettext',
'horizon.dashboard.containers.containers.create.service',
'horizon.dashboard.containers.containers.delete.service',
'horizon.dashboard.containers.containers.resourceType',
];
function registerContainerActions(
registry,
gettext,
createContainerService,
deleteContainerService,
resourceType)
{
var containerResourceType = registry.getResourceType(resourceType);
containerResourceType.itemActions
.append({
id: 'deleteContainerAction',
service: deleteContainerService,
template: {
type: 'delete',
text: gettext('Delete Container')
}
});
containerResourceType.batchActions
.append({
id: 'createContainerAction',
service: createContainerService,
template: {
type: 'create',
text: gettext('Create Container')
}
})
.append({
id: 'batchDeleteContainerAction',
service: deleteContainerService,
template: {
type: 'delete-selected',
text: gettext('Delete Containers')
}
});
}
})();

View File

@ -1,46 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @name horizon.dashboard.containers.containers
* @ngModule
*
* @description
* Provides all the services and widgets require to display the containers
* panel
*/
angular
.module('horizon.dashboard.containers.containers', ['horizon.dashboard.containers.containers.actions'])
.constant('horizon.dashboard.containers.containers.events', events())
.constant('horizon.dashboard.containers.containers.resourceType', 'OS::Magnum::Container');
/**
* @ngdoc constant
* @name horizon.dashboard.containers.containers.events
* @description A list of events used by Containers
*/
function events() {
return {
CREATE_SUCCESS: 'horizon.dashboard.containers.containers.CREATE_SUCCESS',
DELETE_SUCCESS: 'horizon.dashboard.containers.containers.DELETE_SUCCESS'
};
}
})();

View File

@ -1,25 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
describe('horizon.dashboard.containers.containers', function() {
it('should exist', function() {
expect(angular.module('horizon.dashboard.containers.containers')).toBeDefined();
});
});
})();

View File

@ -1,74 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.containers.containers')
.factory('horizon.dashboard.containers.containers.containerModel', containerModel);
containerModel.$inject = [
'horizon.app.core.openstack-service-api.magnum'
];
function containerModel(magnum) {
var model = {
newContainerSpec: {},
// API methods
init: init,
createContainer: createContainer
};
function initNewContainerSpec() {
model.newContainerSpec = {
name: null,
bay_uuid: null,
image: null,
memory: null,
memory_size: null,
memory_unit: "m",
command: null
};
}
function init() {
// Reset the new Bay spec
initNewContainerSpec();
}
function createContainer() {
var finalSpec = angular.copy(model.newContainerSpec);
cleanNullProperties(finalSpec);
return magnum.createContainer(finalSpec);
}
function cleanNullProperties(finalSpec) {
// Initially clean fields that don't have any value.
for (var key in finalSpec) {
if (finalSpec.hasOwnProperty(key) && finalSpec[key] === null
|| key === "memory_size" || key === "memory_unit") {
delete finalSpec[key];
}
}
}
return model;
}
})();

View File

@ -1,58 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.containers.containers')
.factory('horizon.dashboard.containers.containers.workflow', containerWorkflow);
containerWorkflow.$inject = [
'horizon.dashboard.containers.basePath',
'horizon.app.core.workflow.factory',
'horizon.framework.util.i18n.gettext'
];
function containerWorkflow(basePath, dashboardWorkflow, gettext) {
return dashboardWorkflow({
title: gettext('Create Container'),
steps: [
{
title: gettext('Info'),
templateUrl: basePath + 'containers/create/info/info.html',
helpUrl: basePath + 'containers/create/info/info.help.html',
formName: 'containerInfoForm'
},
{
title: gettext('Spec'),
templateUrl: basePath + 'containers/create/spec/spec.html',
helpUrl: basePath + 'containers/create/spec/spec.help.html',
formName: 'containerSpecForm'
}
],
btnText: {
finish: gettext('Create')
},
btnIcon: {
finish: 'fa fa-check'
}
});
}
})();

View File

@ -1,90 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @name horizon.dashboard.containers.containers.create.service
* @description Service for the container create modal
*/
angular
.module('horizon.dashboard.containers.containers')
.factory('horizon.dashboard.containers.containers.create.service', createService);
createService.$inject = [
'horizon.dashboard.containers.containers.containerModel',
'horizon.framework.widgets.modal.wizard-modal.service',
'horizon.framework.widgets.toast.service',
'horizon.dashboard.containers.containers.workflow',
'horizon.dashboard.containers.containers.events',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions'
];
function createService(
model, wizardModalService, toast, createWorkflow, events, policy, gettext, $qExtensions
) {
var scope;
var message = {
success: gettext('Container %s was successfully created.')
};
var service = {
initScope: initScope,
perform: perform,
allowed: allowed
};
return service;
//////////////
function initScope($scope) {
scope = $scope;
scope.workflow = createWorkflow;
scope.model = model;
scope.$on('$destroy', function() {
});
}
function perform(selected) {
scope.model.init();
scope.selected = selected;
wizardModalService.modal({
scope: scope,
workflow: createWorkflow,
submit: submit
});
}
function allowed(selected) {
return $qExtensions.booleanAsPromise(true);
}
function submit(){
return model.createContainer().then(success);
}
function success(response) {
response.data.id = response.data.uuid;
toast.add('success', interpolate(message.success, [response.data.id]));
scope.$emit(events.CREATE_SUCCESS, response.data);
}
}
})();

View File

@ -1,83 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc controller
* @name createContainerInfoController
* @ngController
*
* @description
* Controller for the container info step in create workflow
*/
angular
.module('horizon.dashboard.containers.containers')
.controller('createContainerInfoController', createContainerInfoController);
createContainerInfoController.$inject = [
'$q',
'$scope',
'horizon.dashboard.containers.basePath',
'horizon.app.core.openstack-service-api.magnum'
];
function createContainerInfoController($q, $scope, basePath, magnum) {
var ctrl = this;
ctrl.bays = [{id:"", name: gettext("Choose a Bay")}];
$scope.model.newContainerSpec.bay_uuid = "";
$scope.baydetail = {
name: "",
id: "",
baymodel: "",
master_count: "",
node_count: "",
discovery_url: "",
timeout: ""
};
$scope.changeBay = function(){
angular.forEach(ctrl.bays, function(bay, idx){
if($scope.model.newContainerSpec.bay_uuid === bay.id){
$("#bay_detail").show();
$("#bay_detail_none").hide();
$scope.baydetail.name = bay.name;
$scope.baydetail.id = bay.id;
$scope.baydetail.baymodel_id = bay.baymodel_id;
$scope.baydetail.master_count = bay.master_count;
$scope.baydetail.node_count = bay.node_count;
$scope.baydetail.discovery_url = bay.discovery_url;
$scope.baydetail.timeout = bay.timeout;
}
});
};
init();
function init() {
magnum.getBays({paginate: false}).success(onGetBays);
}
function onGetBays(response) {
Array.prototype.push.apply(ctrl.bays, response.items);
if($scope.selected instanceof Object){
$scope.model.newContainerSpec.bay_uuid = $scope.selected.id;
$scope.changeBay();
}
}
}
})();

View File

@ -1 +0,0 @@
<p translate>Specify container name and choose bay.</p>

View File

@ -1,46 +0,0 @@
<div ng-controller="createContainerInfoController as ctrl">
<div class="row">
<div class="col-xs-12">
<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"
ng-model="model.newContainerSpec.name"
placeholder="{$ 'Name of the container to create.'|translate $}">
</div>
<div class="form-group">
<label class="control-label" for="container-bay">
<translate>Bay</translate>
<span class="hz-icon-required fa fa-asterisk"></span>
</label>
<select class="form-control" name="container-bay" id="container-bay"
ng-model="model.newContainerSpec.bay_uuid"
ng-required="true"
ng-options="bay.id as bay.name|noName for bay in ctrl.bays"
ng-change="changeBay()">
</select>
</div>
<div class="detail" ng-show="model.newContainerSpec.bay_uuid">
<span translate class="h4">Bay Detail</span>
<dl class="dl-horizontal">
<dt translate>Name</dt>
<dd><a ng-href="project/bays/{$ baydetail.id $}" ng-click="cancel()">
{$ baydetail.name|noName $}
</a></dd>
<dt translate>ID</dt>
<dd>{$ baydetail.id $}</dd>
<dt translate>Baymodel ID</dt>
<dd>{$ baydetail.baymodel_id $}</dd>
<dt translate>Master Count</dt>
<dd>{$ baydetail.master_count $}</dd>
<dt translate>Node Count</dt>
<dd>{$ baydetail.node_count $}</dd>
<dt translate>Timeout</dt>
<dd>{$ baydetail.timeout $}</dd>
</dl>
</div>
</div>
</div>
</div>

View File

@ -1,61 +0,0 @@
/**
* Copyright 2015 NEC Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc controller
* @name createContainerSpecController
* @ngController
*
* @description
* Controller for the container spec step in create workflow
*/
angular
.module('horizon.dashboard.containers.containers')
.controller('createContainerSpecController', createContainerSpecController);
createContainerSpecController.$inject = [
'$q',
'$scope',
'horizon.dashboard.containers.basePath',
'horizon.app.core.openstack-service-api.magnum'
];
function createContainerSpecController($q, $scope, basePath, magnum) {
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 +0,0 @@
<p translate>Specify the specs for the container.</p>

View File

@ -1,48 +0,0 @@
<div ng-controller="createContainerSpecController as ctrl">
<div class="row">
<div class="col-xs-12">
<div class="form-group">
<label class="control-label" for="container-image" translate>
<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-required="true" ng-model="model.newContainerSpec.image"
placeholder="{$ 'Name of the container image.'|translate $}">
</div>
</div>
</div>
<div class="row">
<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>
<div class="row">
<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="{$ 'Send command to the contaier in a line.'|translate $}">
</div>
</div>
</div>
</div>

View File

@ -1,125 +0,0 @@
/**
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use self file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
angular
.module('horizon.dashboard.containers.containers')
.factory('horizon.dashboard.containers.containers.delete.service', deleteService);
deleteService.$inject = [
'horizon.app.core.openstack-service-api.magnum',
'horizon.app.core.openstack-service-api.policy',
'horizon.framework.widgets.modal.deleteModalService',
'horizon.framework.util.i18n.gettext',
'horizon.framework.util.q.extensions',
'horizon.dashboard.containers.containers.events'
];
/**
* @ngDoc factory
* @name horizon.dashboard.containers.containers.delete.service
*
* @Description
* Brings up the delete containers confirmation modal dialog.
* On submit, delete selected resources.
* On cancel, do nothing.
*/
function deleteService(
magnum, policy, deleteModalService, gettext, $qExtensions, events
) {
var scope;
var context = {
labels: null,
deleteEntity: deleteEntity,
successEvent: events.DELETE_SUCCESS
};
var service = {
initScope: initScope,
allowed: allowed,
perform: perform
};
return service;
//////////////
// include this function in your service
// if you plan to emit events to the parent controller
function initScope($scope) {
scope = $scope;
}
function allowed() {
return $qExtensions.booleanAsPromise(true);
}
// delete selected resource objects
function perform(selected) {
if(!selected.hasOwnProperty('id')){
// batch (multi)
context.labels = labelize(selected.length);
$qExtensions.allSettled(selected.map(checkPermission)).then(afterCheck);
}else{
// row (single)
context.labels = labelize(1);
deleteModalService.open(scope, [selected], context);
}
}
function labelize(count){
return {
title: ngettext('Confirm Delete Container',
'Confirm Delete Containers', count),
/* eslint-disable max-len */
message: ngettext('You have selected "%s". Please confirm your selection. Deleted container is not recoverable.',
'You have selected "%s". Please confirm your selection. Deleted containers are not recoverable.', count),
/* eslint-enable max-len */
submit: ngettext('Delete Container',
'Delete Containers', count),
success: ngettext('Deleted Container: %s.',
'Deleted Containers: %s.', count),
error: ngettext('Unable to delete Container: %s.',
'Unable to delete Containers: %s.', count)
};
}
// for batch delete
function checkPermission(selected) {
return {promise: allowed(selected), context: selected};
}
// for batch delete
function afterCheck(result){
if (result.fail.length > 0) {
toast.add('error', getMessage(notAllowedMessage, result.fail));
}
if (result.pass.length > 0) {
deleteModalService.open(scope, result.pass.map(getEntity), context);
}
}
// for batch delete
function getEntity(result) {
return result.context;
}
// call delete REST API
function deleteEntity(id){
return magnum.deleteContainer(id, true);
}
}
})();

View File

@ -1,79 +0,0 @@
/*
* Copyright 2015 NEC Corporation
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
(function() {
"use strict";
angular
.module('horizon.dashboard.containers.containers')
.controller('ContainerDetailController', ContainerDetailController);
ContainerDetailController.$inject = [
'$scope',
'$window',
'$location',
'$routeParams',
'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.containers.resourceType'
];
function ContainerDetailController($scope, $window, $location, $routeParams, magnum, events, registry, containerResourceType) {
var ctrl = this;
ctrl.container = {};
ctrl.bay = {};
ctrl.baymodel = {};
ctrl.containerResource = registry.getResourceType(containerResourceType);
var containerId = $routeParams.containerId;
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
$scope.$on('$destroy', destroy);
init();
function init() {
registry.initActions(containerResourceType, $scope);
// Load the elements that are used in the overview.
magnum.getContainer(containerId).success(onGetContainer);
}
function onGetContainer(container) {
ctrl.container = container;
ctrl.container.id = container.uuid;
magnum.getBay(ctrl.container.bay_uuid).success(onGetBay);
}
function onGetBay(bay) {
ctrl.bay = bay;
magnum.getBaymodel(ctrl.bay.baymodel_id).success(onGetBaymodel);
}
function onGetBaymodel(baymodel) {
ctrl.baymodel = baymodel;
}
function onDeleteSuccess(e, removedIds) {
e.stopPropagation();
$location.path("/project/bays/containers");
}
function destroy() {
deleteWatcher();
}
}
})();

View File

@ -1,107 +0,0 @@
<div class="content" ng-controller="ContainerDetailController as ctrl">
<div class="page-header">
<ol class="breadcrumb">
<li><a ng-href="project/bays/containers" translate>Containers</a></li>
<li class="active">{$ ctrl.container.name|noName $}</li>
<div class="pull-right">
<actions allowed="ctrl.containerResource.itemActions" type="row" item="ctrl.container"></actions>
</div>
</ol>
</div>
<tabset>
<tab heading="{$ 'Overview' | translate $}">
<div class="row">
<div class="col-md-6">
<h3 translate>Spec</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Image</dt>
<dd>{$ ctrl.container.image $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Memory</dt>
<dd>{$ ctrl.container.memorysize $} {$ ctrl.container.memoryunit $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Command</dt>
<dd>{$ ctrl.container.command $}</dd>
</div>
</dl>
</div>
<div class="col-md-6">
<h3 translate>Bay</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Name</dt>
<dd><a ng-href="project/bays/{$ ctrl.bay.uuid $}">{$ ctrl.bay.name|noName $}</a></dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>ID</dt>
<dd>{$ ctrl.bay.uuid $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Status</dt>
<dd>{$ ctrl.bay.status $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Master Count</dt>
<dd>{$ ctrl.bay.master_count $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Node Count</dt>
<dd>{$ ctrl.bay.node_count $}</dd>
</div>
</dl>
</div>
</div>
<div class="row">
<div class="col-md-6">
<h3 translate>Baymodel</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Name</dt>
<dd><a ng-href="project/baymodels/{$ ctrl.baymodel.uuid $}">{$ ctrl.baymodel.name|noName $}</a></dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>ID</dt>
<dd>{$ ctrl.baymodel.uuid $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>COE</dt>
<dd>{$ ctrl.baymodel.coe $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Image ID</dt>
<dd>{$ ctrl.baymodel.image_id $}</dd>
</div>
</dl>
</div>
<div class="col-md-6">
<h3 translate>Record Properties</h3>
<hr class="header-rule">
<dl class="dl-horizontal">
<div class="{$ propertyClasses $}">
<dt translate>Created</dt>
<dd>{$ ctrl.container.created_at | date:'short' $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Updated</dt>
<dd>{$ ctrl.container.updated_at | date:'short' $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>ID</dt>
<dd>{$ ctrl.container.uuid $}</dd>
</div>
<div class="{$ propertyClasses $}">
<dt translate>Status</dt>
<dd>{$ ctrl.container.status $}</dd>
</div>
</dl>
</div>
</div>
</tab>
</tabset>
</div>

View File

@ -1,136 +0,0 @@
/**
* Copyright 2015 Cisco Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
(function() {
'use strict';
/**
* @ngdoc overview
* @name containersContainersTableController
* @ngController
*
* @description
* Controller for the Magnum containers table
*/
angular
.module('horizon.dashboard.containers.containers')
.controller('containersContainersTableController', containersContainersTableController);
containersContainersTableController.$inject = [
'$scope',
'horizon.app.core.openstack-service-api.magnum',
'horizon.dashboard.containers.containers.events',
'horizon.framework.conf.resource-type-registry.service',
'horizon.dashboard.containers.containers.resourceType'
];
function containersContainersTableController($scope, magnum, events, registry, containerResourceType) {
var ctrl = this;
ctrl.containers = [];
ctrl.containersSrc = [];
ctrl.containerResource = registry.getResourceType(containerResourceType);
/**
* Filtering - client-side MagicSearch
* all facets for container table
*/
ctrl.containerFacets = [
{
'label': gettext('Name'),
'name': 'name',
'singleton': true
},
{
'label': gettext('UUID'),
'name': 'id',
'singleton': true
},
{
'label': gettext('Status'),
'name': 'status',
'singleton': true
},
{
'label': gettext('Bay'),
'name': 'bay-uuid',
'singleton': true
},
{
'label': gettext('Image'),
'name': 'image',
'singleton': true
},
{
'label': gettext('Memory'),
'name': 'memory',
'singleton': true
},
{
'label': gettext('Command'),
'name': 'command',
'singleton': true
}
];
var createWatcher = $scope.$on(events.CREATE_SUCCESS, onCreateSuccess);
var deleteWatcher = $scope.$on(events.DELETE_SUCCESS, onDeleteSuccess);
$scope.$on('$destroy', destroy);
init();
function init() {
registry.initActions(containerResourceType, $scope);
magnum.getContainers().success(getContainersSuccess);
}
function getContainersSuccess(response) {
ctrl.containersSrc = response.items;
}
function onCreateSuccess(e, createdItem) {
ctrl.containersSrc.push(createdItem);
e.stopPropagation();
}
function onDeleteSuccess(e, removedIds) {
ctrl.containersSrc = difference(ctrl.containersSrc, removedIds, 'id');
e.stopPropagation();
// after deleting the items
// we need to clear selected items from table controller
$scope.$emit('hzTable:clearSelected');
}
function difference(currentList, otherList, key) {
return currentList.filter(filter);
function filter(elem) {
return otherList.filter(function filterDeletedItem(deletedItem) {
return deletedItem === elem[key];
}).length === 0;
}
}
function destroy() {
createWatcher();
deleteWatcher();
}
}
})();

View File

@ -1,156 +0,0 @@
<table ng-controller="containersContainersTableController as table"
hz-table ng-cloak
st-table="table.containers"
st-safe-src="table.containersSrc"
default-sort="name"
default-sort-reverse="false"
class="table table-striped table-rsp table-detail">
<thead>
<!--
Table-batch-actions:
This is where batch actions like searching, creating, and deleting.
-->
<tr>
<th colspan="100" class="search-header">
<hz-magic-search-bar group-classes="input-group-sm" icon-classes="fa-search"
filter-facets="table.containerFacets">
</hz-magic-search-bar>
</th>
</tr>
<tr class="action-row">
<th colspan="100">
<actions allowed="table.containerResource.batchActions" type="batch"></actions>
</th>
</tr>
<!--
Table-column-headers:
The headers for the table columns
-->
<tr>
<th class="multi_select_column">
<input type="checkbox" hz-select-all="table.containers">
</th>
<th class="expander"></th>
<th class="rsp-p1" st-sort="name" st-sort-default translate>
Name
</th>
<th class="rsp-p2" st-sort="id" translate>
ID
</th>
<th class="rsp-p1" st-sort="status" translate>
Status
</th>
<th class="rsp-p3" st-sort="bay" translate>
Bay ID
</th>
<th class="rsp-p2" st-sort="image" translate>
Image
</th>
<th class="rsp-p3" st-sort="memory" translate>
Memory
</th>
<th class="actions_column" translate>
Actions
</th>
</tr>
</thead>
<tbody>
<!--
Table-rows:
This is where we declaratively define the table columns.
Include multi_select_column if you want to select all.
Include expander if you want to inline details.
Include actions_column if you want to perform actions.
rsp-p1 rsp-p2 are responsive priority as user resizes window.
-->
<tr ng-repeat-start="c in table.containers track by c.id">
<td class="multi_select_column">
<input type="checkbox"
ng-model="tCtrl.selections[c.id].checked"
hz-select="c">
</td>
<td class="expander">
<i class="fa fa-chevron-right"
hz-expand-detail
duration="200">
</i>
</td>
<td class="rsp-p1"><a ng-href="project/bays/containers/{$ c.id $}">{$ c.name|noName $}</a></td>
<td class="rsp-p2">{$ c.id $}</td>
<td class="rsp-p1">{$ c.status $}</td>
<td class="rsp-p3"><a ng-href="project/bays/{$ c.bay_uuid $}">{$ c.bay_uuid $}</a></td>
<td class="rsp-p2">{$ c.image $}</td>
<td class="rsp-p3">{$ c.memorysize $} {$ c.memoryunit $}</td>
<td class="actions_column">
<!--
Table-row-action-column:
Actions taken here applies to a single item/row.
-->
<actions allowed="table.containerResource.itemActions" type="row" item="c"></actions>
</td>
</tr>
<tr ng-repeat-end class="detail-row">
<!--
Detail-row:
Contains detailed information on this item.
Can be toggled using the chevron button.
Ensure colspan is greater or equal to number of column-headers.
-->
<td class="detail" colspan="100">
<!--
The responsive columns that disappear typically should reappear here
with the same responsive priority that they disappear.
E.g. table header with rsp-p2 should be here with rsp-alt-p2
-->
<div class="row">
<span class="rsp-alt-p2">
<dl class="col-xs-5">
<dt translate>ID</dt>
<dd>{$ c.id $}</dd>
</dl>
<dl class="col-xs-5">
<dt translate>Image</dt>
<dd>{$ c.image $}</dd>
</dl>
</span>
<span class="rsp-alt-p3">
<dl class="col-xs-5">
<dt translate>Bay ID</dt>
<dd><a ng-href="project/bays/{$ c.bay_uuid $}">{$ c.bay_uuid $}</a></dd>
</dl>
<dl class="col-xs-2">
<dt translate>Memory</dt>
<dd>{$ c.memorysize $} {$ c.memoryunit $}</dd>
</dl>
</span>
</div>
<div class="row">
<dl class="col-xs-12">
<dt translate>Command</dt>
<dd>{$ c.command $}</dd>
</dl>
</div>
</td>
</tr>
<tr hz-no-items items="table.containers"></tr>
</tbody>
<!--
Table-footer:
This is where we display number of items and pagination controls.
-->
<tfoot hz-table-footer items="table.containers"></tfoot>
</table>

View File

@ -38,13 +38,6 @@
getBaymodels: getBaymodels,
deleteBaymodel: deleteBaymodel,
deleteBaymodels: deleteBaymodels,
createContainer: createContainer,
getContainer: getContainer,
getContainers: getContainers,
deleteContainer: deleteContainer,
deleteContainers: deleteContainers,
memoryUnits: memoryUnits,
convertMemorySize: convertMemorySize,
};
return service;
@ -130,76 +123,5 @@
toastService.add('error', gettext('Unable to delete the Baymodels.'));
})
}
////////////////
// Containers //
////////////////
function createContainer(params) {
return apiService.post('/api/containers/containers/', params)
.error(function() {
toastService.add('error', gettext('Unable to create Container.'));
});
}
function getContainer(id) {
return apiService.get('/api/containers/containers/' + id)
.success(function(data, status, headers, config) {
convertMemorySize(data);
return data;
})
.error(function() {
toastService.add('error', gettext('Unable to retrieve the Container.'));
});
}
function getContainers() {
return apiService.get('/api/containers/containers/')
.success(function(data, status, headers, config) {
angular.forEach(data.items, function(container, idx){
convertMemorySize(container);
});
return data;
})
.error(function() {
toastService.add('error', gettext('Unable to retrieve the Containers.'));
});
}
function deleteContainer(id, suppressError) {
var promise = apiService.delete('/api/containers/containers/', [id]);
return suppressError ? promise : promise.error(function() {
var msg = gettext('Unable to delete the Container with id: %(id)s');
toastService.add('error', interpolate(msg, { id: id }, true));
});
}
// FIXME(shu-mutou): Unused for batch-delete in Horizon framework in Feb, 2016.
function deleteContainers(ids) {
return apiService.delete('/api/containers/containers/', ids)
.error(function() {
toastService.add('error', gettext('Unable to delete the Containers.'));
});
}
}
var memoryUnits = { "b": gettext("bytes"),
"k": gettext("KB"),
"m": gettext("MB"),
"g": gettext("GB")};
function convertMemorySize(container){
container.memorysize = "";
container.memoryunit = "";
if(container.memory !== null && container.memory !== ""){
// separate number and unit.
var regex = /(\d+)([bkmg]?)/;
var match = regex.exec(container.memory);
container.memorysize = match[1];
if(match[2]){
container.memoryunit = memoryUnits[match[2]];
}
}
};
}());

View File

@ -1,18 +0,0 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}
{% trans "Containers" %}
{% endblock %}
{% block page_header %}
<hz-page-header header="{$ 'Containers' | translate $}"/>
{% endblock page_header %}
{% block ng_route_base %}
<base href="{{ WEBROOT }}"></base>
{% endblock %}
{% block main %}
<div ng-view></div>
{% endblock %}

View File

@ -1,66 +0,0 @@
# Copyright 2015 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from magnum_ui import api
from magnum_ui.test import helpers as test
class MagnumApiTests(test.APITestCase):
def test_container_list(self):
containers = self.magnum_containers.list()
form_data = {'marker': None,
'limit': None,
'sort_key': None,
'sort_dir': None,
'detail': False}
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.list(**form_data).AndReturn(containers)
self.mox.ReplayAll()
api.magnum.container_list(self.request)
def test_container_get(self):
container = self.magnum_containers.first()
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.get(container['uuid']).AndReturn(container)
self.mox.ReplayAll()
api.magnum.container_show(self.request, container['uuid'])
def test_container_delete(self):
container = self.magnum_containers.first()
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.delete(container['uuid'])
self.mox.ReplayAll()
api.magnum.container_delete(self.request, container['uuid'])
def test_container_create(self):
container = self.magnum_containers.first()
form_data = {'bay_uuid': container['bay'],
'name': container['name']}
magnumclient = self.stub_magnumclient()
magnumclient.containers = self.mox.CreateMockAnything()
magnumclient.containers.create(**form_data)\
.AndReturn(container)
self.mox.ReplayAll()
api.magnum.container_create(self.request, **form_data)

View File

@ -103,46 +103,6 @@ class MagnumRestTestCase(test.TestCase):
request,
u'bay_id')
# Containers
@mock.patch.object(magnum, 'magnum')
def test_container_get(self, client):
request = self.mock_rest_request()
client.container_list.return_value = \
mock_resource(TEST.magnum_containers.list())
response = magnum.Containers().get(request)
self.assertStatusCode(response, 200)
self.assertItemsCollectionEqual(response,
TEST.magnum_containers.list())
client.container_list.assert_called_once_with(request)
@mock.patch.object(magnum, 'magnum')
def test_container_create(self, client):
test_conts = mock_resource(TEST.magnum_containers.list())
test_cont = test_conts[0]
test_body = json.dumps(test_cont.to_dict())
request = self.mock_rest_request(body=test_body)
client.container_create.return_value = test_cont
response = magnum.Containers().post(request)
self.assertStatusCode(response, 201)
self.assertEqual(response['location'],
'/api/containers/container/%s' % test_cont.uuid)
client.container_create.assert_called_once_with(request,
**test_cont.to_dict())
@mock.patch.object(magnum, 'magnum')
def test_container_delete(self, client):
test_container = TEST.magnum_containers.first()
request = self.mock_rest_request(
body='{"container_id":' + str(test_container['uuid']) + '}')
response = magnum.Containers().delete(request)
self.assertStatusCode(response, 204)
client.container_delete.assert_called_once_with(
request,
u'container_id')
def mock_resource(resource):
"""Utility function to make mocking more DRY"""

View File

@ -19,8 +19,6 @@ def data(TEST):
# Test Data Containers
TEST.baymodels = utils.TestDataContainer()
TEST.bays = utils.TestDataContainer()
# 'magnum_containers' to avoid Swift naming confusion
TEST.magnum_containers = utils.TestDataContainer()
# Bay Models
baymodel_dict_1 = {"uuid": 1,
@ -53,13 +51,3 @@ def data(TEST):
"timeout": 0}
TEST.bays.add(bay_dict_1)
# Containers
container_dict_1 = {"uuid": 1,
"name": "myapartmentsmellsofrichmahogany",
"image": "",
"bay": bay_dict_1["uuid"],
"command": "",
"memory": ""}
TEST.magnum_containers.add(container_dict_1)