Merge "Ability to assign metadata to Murano Applications and Environments"
This commit is contained in:
commit
9fb1fcb83c
@ -11,4 +11,5 @@
|
||||
# limitations under the License.
|
||||
|
||||
# import REST API modules here
|
||||
from . import environments # noqa
|
||||
from . import packages # noqa
|
||||
|
158
muranodashboard/api/rest/environments.py
Normal file
158
muranodashboard/api/rest/environments.py
Normal file
@ -0,0 +1,158 @@
|
||||
# Copyright (c) 2016 Mirantis, 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.views import generic
|
||||
|
||||
from openstack_dashboard.api.rest import urls
|
||||
from openstack_dashboard.api.rest import utils as rest_utils
|
||||
|
||||
from muranodashboard import api
|
||||
from muranodashboard.environments import api as env_api
|
||||
|
||||
|
||||
@urls.register
|
||||
class ComponentsMetadata(generic.View):
|
||||
"""API for Murano components Metadata"""
|
||||
|
||||
url_regex = r'app-catalog/environments/(?P<environment>[^/]+)' \
|
||||
r'/components/(?P<component>[^/]+)/metadata/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, environment, component):
|
||||
"""Get a metadata object for a component in a given environment
|
||||
|
||||
Example GET:
|
||||
http://localhost/api/app-catalog/environments/123/components/456/metadata
|
||||
|
||||
The following get parameters may be passed in the GET
|
||||
request:
|
||||
|
||||
:param environment: identifier of the environment
|
||||
:param component: identifier of the component
|
||||
|
||||
Any additionally a "session" parameter should be passed through the API
|
||||
as a keyword.
|
||||
"""
|
||||
filters, keywords = rest_utils.parse_filters_kwargs(request,
|
||||
['session'])
|
||||
session = keywords.get('session')
|
||||
if not session:
|
||||
session = env_api.Session.get_or_create_or_delete(request,
|
||||
environment)
|
||||
component = api.muranoclient(request).services.get(
|
||||
environment, '/' + component, session)
|
||||
if component:
|
||||
return component.to_dict()['?'].get('metadata', {})
|
||||
return {}
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def post(self, request, environment, component):
|
||||
"""Set a metadata object for a component in a given environment
|
||||
|
||||
Example POST:
|
||||
http://localhost/api/app-catalog/environments/123/components/456/metadata
|
||||
|
||||
The following get parameters may be passed in the GET
|
||||
request:
|
||||
|
||||
:param environment: identifier of the environment
|
||||
:param component: identifier of the component
|
||||
|
||||
Any additionally a "session" parameter should be passed through the API
|
||||
as a keyword. Request body should contain 'updated' keyword, contain
|
||||
all the updated metadata attributes. If it is empty, the metadata is
|
||||
considered to be deleted.
|
||||
"""
|
||||
client = api.muranoclient(request)
|
||||
filters, keywords = rest_utils.parse_filters_kwargs(request,
|
||||
['session'])
|
||||
session = keywords.get('session')
|
||||
if not session:
|
||||
session = env_api.Session.get_or_create_or_delete(request,
|
||||
environment)
|
||||
updated = request.DATA.get('updated', {})
|
||||
path = '/{0}/%3F/metadata'.format(component)
|
||||
|
||||
if updated:
|
||||
client.services.put(environment, path, updated, session)
|
||||
else:
|
||||
client.services.delete(environment, path, session)
|
||||
|
||||
|
||||
@urls.register
|
||||
class EnvironmentsMetadata(generic.View):
|
||||
"""API for Murano components Metadata"""
|
||||
|
||||
url_regex = r'app-catalog/environments/(?P<environment>[^/]+)/metadata/$'
|
||||
|
||||
@rest_utils.ajax()
|
||||
def get(self, request, environment):
|
||||
"""Get a metadata object for an environment
|
||||
|
||||
Example GET:
|
||||
http://localhost/api/app-catalog/environments/123/metadata
|
||||
|
||||
The following get parameters may be passed in the GET
|
||||
request:
|
||||
|
||||
:param environment: identifier of the environment
|
||||
|
||||
Any additionally a "session" parameter should be passed through the API
|
||||
as a keyword.
|
||||
"""
|
||||
filters, keywords = rest_utils.parse_filters_kwargs(request,
|
||||
['session'])
|
||||
session = keywords.get('session')
|
||||
if not session:
|
||||
session = env_api.Session.get_or_create_or_delete(request,
|
||||
environment)
|
||||
env = api.muranoclient(request).environments.get_model(
|
||||
environment, '/', session)
|
||||
if env:
|
||||
return env['?'].get('metadata', {})
|
||||
return {}
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def post(self, request, environment):
|
||||
"""Set a metadata object for a given environment
|
||||
|
||||
Example POST:
|
||||
http://localhost/api/app-catalog/environments/123/metadata
|
||||
|
||||
The following get parameters may be passed in the GET
|
||||
request:
|
||||
|
||||
:param environment: identifier of the environment
|
||||
|
||||
Any additionally a "session" parameter should be passed through the API
|
||||
as a keyword. Request body should contain 'updated' keyword, contain
|
||||
all the updated metadata attributes. If it is empty, the metadata is
|
||||
considered to be deleted.
|
||||
"""
|
||||
client = api.muranoclient(request)
|
||||
filters, keywords = rest_utils.parse_filters_kwargs(request,
|
||||
['session'])
|
||||
|
||||
session = keywords.get('session')
|
||||
if not session:
|
||||
session = env_api.Session.get_or_create_or_delete(request,
|
||||
environment)
|
||||
updated = request.DATA.get('updated', {})
|
||||
patch = {
|
||||
"op": "replace",
|
||||
"path": "/?/metadata",
|
||||
"value": updated
|
||||
}
|
||||
client.environments.update_model(environment, [patch], session)
|
@ -117,6 +117,27 @@ class Session(object):
|
||||
"for the environment {0}".format(environment_id))
|
||||
return id
|
||||
|
||||
@staticmethod
|
||||
def get_if_available(request, environment_id):
|
||||
"""Get an id of open session if it exists and is not in deployed state.
|
||||
|
||||
Returns None otherwise
|
||||
"""
|
||||
sessions = request.session.get('sessions', {})
|
||||
client = api.muranoclient(request)
|
||||
|
||||
if environment_id in sessions:
|
||||
id = sessions[environment_id]
|
||||
try:
|
||||
session_data = client.sessions.get(environment_id, id)
|
||||
except exc.HTTPForbidden:
|
||||
return None
|
||||
else:
|
||||
if session_data.state in [consts.STATUS_ID_DEPLOY_FAILURE,
|
||||
consts.STATUS_ID_READY]:
|
||||
return None
|
||||
return id
|
||||
|
||||
@staticmethod
|
||||
def get(request, environment_id):
|
||||
"""Get an open session id
|
||||
|
@ -433,6 +433,36 @@ class UpdateName(tables.UpdateAction):
|
||||
return True
|
||||
|
||||
|
||||
class UpdateEnvMetadata(tables.LinkAction):
|
||||
name = "update_env_metadata"
|
||||
verbose_name = _("Update Metadata")
|
||||
ajax = False
|
||||
icon = "pencil"
|
||||
attrs = {"ng-controller": "MetadataModalHelperController as modal"}
|
||||
|
||||
def __init__(self, attrs=None, **kwargs):
|
||||
kwargs['preempt'] = True
|
||||
self.session_id = None
|
||||
super(UpdateEnvMetadata, self).__init__(attrs, **kwargs)
|
||||
|
||||
def get_link_url(self, environment):
|
||||
target = {
|
||||
'environment': str(environment.id),
|
||||
'session': str(self.session_id),
|
||||
}
|
||||
self.attrs['ng-click'] = (
|
||||
"modal.openMetadataModal('muranoenv', %s, true)" % target)
|
||||
return "javascript:void(0);"
|
||||
|
||||
def allowed(self, request, environment=None):
|
||||
return environment.status not in (consts.STATUS_ID_DEPLOYING,
|
||||
consts.STATUS_ID_DELETING)
|
||||
|
||||
def update(self, request, datum):
|
||||
env_id = self.table.kwargs.get('environment_id')
|
||||
self.session_id = api.Session.get_if_available(request, env_id)
|
||||
|
||||
|
||||
class EnvironmentsTable(tables.DataTable):
|
||||
name = md_utils.Column(
|
||||
'name',
|
||||
@ -472,7 +502,8 @@ class EnvironmentsTable(tables.DataTable):
|
||||
table_actions = (CreateEnvironment, DeployEnvironment,
|
||||
DeleteEnvironment, AbandonEnvironment)
|
||||
row_actions = (ShowEnvironmentServices, DeployEnvironment,
|
||||
DeleteEnvironment, AbandonEnvironment)
|
||||
DeleteEnvironment, AbandonEnvironment,
|
||||
UpdateEnvMetadata)
|
||||
|
||||
|
||||
def get_service_details_link(service):
|
||||
@ -484,6 +515,40 @@ def get_service_type(datum):
|
||||
return datum['?'].get(consts.DASHBOARD_ATTRS_KEY, {}).get('name')
|
||||
|
||||
|
||||
class UpdateMetadata(tables.LinkAction):
|
||||
name = "update_metadata"
|
||||
verbose_name = _("Update Metadata")
|
||||
ajax = False
|
||||
icon = "pencil"
|
||||
attrs = {"ng-controller": "MetadataModalHelperController as modal"}
|
||||
|
||||
def __init__(self, attrs=None, **kwargs):
|
||||
kwargs['preempt'] = True
|
||||
self.session_id = None
|
||||
super(UpdateMetadata, self).__init__(attrs, **kwargs)
|
||||
|
||||
def get_link_url(self, service):
|
||||
env_id = self.table.kwargs.get('environment_id')
|
||||
comp_id = service['?']['id']
|
||||
target = {
|
||||
'environment': str(env_id),
|
||||
'component': str(comp_id),
|
||||
'session': str(self.session_id),
|
||||
}
|
||||
self.attrs['ng-click'] = (
|
||||
"modal.openMetadataModal('muranoapp', %s, true)" % target)
|
||||
return "javascript:void(0);"
|
||||
|
||||
def allowed(self, request, service=None):
|
||||
status, version = _get_environment_status_and_version(request,
|
||||
self.table)
|
||||
return status != consts.STATUS_ID_DEPLOYING
|
||||
|
||||
def update(self, request, datum):
|
||||
env_id = self.table.kwargs.get('environment_id')
|
||||
self.session_id = api.Session.get_if_available(request, env_id)
|
||||
|
||||
|
||||
class ServicesTable(tables.DataTable):
|
||||
name = md_utils.Column(
|
||||
'name',
|
||||
@ -572,7 +637,7 @@ class ServicesTable(tables.DataTable):
|
||||
status_columns = ['status']
|
||||
row_class = UpdateServiceRow
|
||||
table_actions = (AddApplication, DeployThisEnvironment)
|
||||
row_actions = (DeleteService,)
|
||||
row_actions = (DeleteService, UpdateMetadata)
|
||||
multi_select = False
|
||||
|
||||
|
||||
|
@ -28,11 +28,14 @@ ADD_EXCEPTIONS = {
|
||||
'unauthorized': exceptions.UNAUTHORIZED,
|
||||
}
|
||||
|
||||
ADD_ANGULAR_MODULES = ['horizon.app.murano']
|
||||
|
||||
ADD_JS_FILES = [
|
||||
'muranodashboard/js/upload_form.js',
|
||||
'muranodashboard/js/import_bundle_form.js',
|
||||
'muranodashboard/js/more-less.js',
|
||||
|
||||
'app/murano/murano.service.js',
|
||||
'app/murano/murano.module.js'
|
||||
|
||||
]
|
||||
|
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright 2015, ThoughtWorks 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('metadata.service', function () {
|
||||
|
||||
/**
|
||||
* That's almost a copy-paste of original metadata.service.spec.js file,
|
||||
* with the exception that a murano module is added to modules registry to
|
||||
* check that murano decorator for metadata service doesn't break core
|
||||
* OpenStack services metadata.
|
||||
*/
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.app.murano'));
|
||||
|
||||
var nova = {getAggregateExtraSpecs: function() {},
|
||||
getFlavorExtraSpecs: function() {},
|
||||
editAggregateExtraSpecs: function() {},
|
||||
editFlavorExtraSpecs: function() {},
|
||||
getInstanceMetadata: function() {},
|
||||
editInstanceMetadata: function() {} };
|
||||
|
||||
var glance = {getImageProps: function() {},
|
||||
editImageProps: function() {},
|
||||
getNamespaces: function() {}};
|
||||
|
||||
var cinder = {getVolumeMetadata:function() {},
|
||||
getVolumeSnapshotMetadata:function() {},
|
||||
getVolumeTypeMetadata:function() {},
|
||||
editVolumeMetadata: function() {},
|
||||
editVolumeSnapshotMetadata: function() {}};
|
||||
|
||||
beforeEach(function() {
|
||||
module(function($provide) {
|
||||
$provide.value('horizon.app.core.openstack-service-api.nova', nova);
|
||||
$provide.value('horizon.app.core.openstack-service-api.glance', glance);
|
||||
$provide.value('horizon.app.core.openstack-service-api.cinder', cinder);
|
||||
});
|
||||
});
|
||||
|
||||
var metadataService;
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
metadataService = $injector.get('horizon.app.core.metadata.service');
|
||||
}));
|
||||
|
||||
it('should get aggregate metadata', function() {
|
||||
var expected = 'aggregate metadata';
|
||||
spyOn(nova, 'getAggregateExtraSpecs').and.returnValue(expected);
|
||||
var actual = metadataService.getMetadata('aggregate', '1');
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should edit aggregate metadata', function() {
|
||||
spyOn(nova, 'editAggregateExtraSpecs');
|
||||
metadataService.editMetadata('aggregate', '1', 'updated', ['removed']);
|
||||
expect(nova.editAggregateExtraSpecs).toHaveBeenCalledWith('1', 'updated', ['removed']);
|
||||
});
|
||||
|
||||
it('should get aggregate namespace', function() {
|
||||
spyOn(glance, 'getNamespaces');
|
||||
metadataService.getNamespaces('aggregate');
|
||||
expect(glance.getNamespaces)
|
||||
.toHaveBeenCalledWith({ resource_type: 'OS::Nova::Aggregate' }, false);
|
||||
});
|
||||
|
||||
it('should get flavor metadata', function() {
|
||||
var expected = 'flavor metadata';
|
||||
spyOn(nova, 'getFlavorExtraSpecs').and.returnValue(expected);
|
||||
var actual = metadataService.getMetadata('flavor', '1');
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should edit flavor metadata', function() {
|
||||
spyOn(nova, 'editFlavorExtraSpecs');
|
||||
metadataService.editMetadata('flavor', '1', 'updated', ['removed']);
|
||||
expect(nova.editFlavorExtraSpecs).toHaveBeenCalledWith('1', 'updated', ['removed']);
|
||||
});
|
||||
|
||||
it('should get flavor namespace', function() {
|
||||
spyOn(glance, 'getNamespaces');
|
||||
metadataService.getNamespaces('flavor');
|
||||
expect(glance.getNamespaces)
|
||||
.toHaveBeenCalledWith({ resource_type: 'OS::Nova::Flavor' }, false);
|
||||
});
|
||||
|
||||
it('should get image metadata', function() {
|
||||
var expected = 'image metadata';
|
||||
spyOn(glance, 'getImageProps').and.returnValue(expected);
|
||||
var actual = metadataService.getMetadata('image', '1');
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should edit image metadata', function() {
|
||||
spyOn(glance, 'editImageProps');
|
||||
metadataService.editMetadata('image', '1', 'updated', ['removed']);
|
||||
expect(glance.editImageProps).toHaveBeenCalledWith('1', 'updated', ['removed']);
|
||||
});
|
||||
|
||||
it('should edit volume metadata', function() {
|
||||
spyOn(cinder, 'editVolumeMetadata');
|
||||
metadataService.editMetadata('volume', '1', 'updated', ['removed']);
|
||||
expect(cinder.editVolumeMetadata).toHaveBeenCalledWith('1', 'updated', ['removed']);
|
||||
});
|
||||
|
||||
it('should edit volume snapshot metadata', function() {
|
||||
spyOn(cinder, 'editVolumeSnapshotMetadata');
|
||||
metadataService.editMetadata('volume_snapshot', '1', 'updated', ['removed']);
|
||||
expect(cinder.editVolumeSnapshotMetadata).toHaveBeenCalledWith('1', 'updated', ['removed']);
|
||||
});
|
||||
|
||||
it('should get image namespace', function() {
|
||||
spyOn(glance, 'getNamespaces');
|
||||
metadataService.getNamespaces('image');
|
||||
expect(glance.getNamespaces)
|
||||
.toHaveBeenCalledWith({ resource_type: 'OS::Glance::Image' }, false);
|
||||
});
|
||||
|
||||
it('should get instance metadata', function() {
|
||||
var expected = 'instance metadata';
|
||||
spyOn(nova, 'getInstanceMetadata').and.returnValue(expected);
|
||||
var actual = metadataService.getMetadata('instance', '1');
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should get volume metadata', function() {
|
||||
var expected = 'volume metadata';
|
||||
spyOn(cinder, 'getVolumeMetadata').and.returnValue(expected);
|
||||
var actual = metadataService.getMetadata('volume', '1');
|
||||
expect(actual).toBe(expected);
|
||||
});
|
||||
|
||||
it('should edit instance metadata', function() {
|
||||
spyOn(nova, 'editInstanceMetadata');
|
||||
metadataService.editMetadata('instance', '1', 'updated', ['removed']);
|
||||
expect(nova.editInstanceMetadata).toHaveBeenCalledWith('1', 'updated', ['removed']);
|
||||
});
|
||||
|
||||
it('should get instance namespace', function() {
|
||||
spyOn(glance, 'getNamespaces');
|
||||
metadataService.getNamespaces('instance', 'metadata');
|
||||
expect(glance.getNamespaces)
|
||||
.toHaveBeenCalledWith({ resource_type: 'OS::Nova::Server',
|
||||
properties_target: 'metadata' }, false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
100
muranodashboard/static/app/murano/murano.module.js
Normal file
100
muranodashboard/static/app/murano/murano.module.js
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* Copyright 2016, Mirantis, 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 horizon.app.murano
|
||||
* @ng-module
|
||||
* @description
|
||||
* Provides all of the services and widgets required
|
||||
* to support and display the Murano Packages panel.
|
||||
*/
|
||||
angular
|
||||
.module('horizon.app.murano', [])
|
||||
.config(config);
|
||||
|
||||
config.$inject = [
|
||||
'$injector',
|
||||
'$provide'
|
||||
];
|
||||
|
||||
function config($injector, $provide) {
|
||||
if ($injector.has('horizon.app.core.metadata.service')) {
|
||||
$provide.decorator('horizon.app.core.metadata.service', patchMetadata);
|
||||
}
|
||||
|
||||
patchMetadata.$inject = [
|
||||
'$delegate',
|
||||
'horizon.app.core.openstack-service-api.murano',
|
||||
'horizon.app.core.openstack-service-api.glance'
|
||||
];
|
||||
function patchMetadata($delegate, murano, glance) {
|
||||
var origEditMetadata = $delegate.editMetadata;
|
||||
var origGetMetadata = $delegate.getMetadata;
|
||||
var origGetNamespaces = $delegate.getNamespaces;
|
||||
|
||||
$delegate.editMetadata = editMetadata;
|
||||
$delegate.getMetadata = getMetadata;
|
||||
$delegate.getNamespaces = getNamespaces;
|
||||
|
||||
return $delegate;
|
||||
|
||||
function getMetadata(resource, id) {
|
||||
if (resource === 'muranoapp') {
|
||||
return murano.getComponentMeta(id);
|
||||
}
|
||||
if (resource === 'muranoenv') {
|
||||
return murano.getEnvironmentMeta(id);
|
||||
}
|
||||
return origGetMetadata(resource, id);
|
||||
}
|
||||
|
||||
function editMetadata(resource, id, updated, removed) {
|
||||
if (resource === 'muranoapp') {
|
||||
return murano.editComponentMeta(id, updated, removed);
|
||||
}
|
||||
if (resource === 'muranoenv') {
|
||||
return murano.editEnvironmentMeta(id, updated, removed);
|
||||
}
|
||||
return origEditMetadata(resource, id, updated, removed);
|
||||
}
|
||||
|
||||
function getNamespaces(resource, propertiesTarget) {
|
||||
var params;
|
||||
if (resource === 'muranoapp') {
|
||||
params = {resource_type: 'OS::Murano::Application'};
|
||||
if (propertiesTarget) {
|
||||
params.properties_target = propertiesTarget;
|
||||
}
|
||||
return glance.getNamespaces(params, false);
|
||||
}
|
||||
if (resource === 'muranoenv') {
|
||||
params = {resource_type: 'OS::Murano::Environment'};
|
||||
if (propertiesTarget) {
|
||||
params.properties_target = propertiesTarget;
|
||||
}
|
||||
return glance.getNamespaces(params, false);
|
||||
}
|
||||
|
||||
return origGetNamespaces(resource, propertiesTarget);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
113
muranodashboard/static/app/murano/murano.module.spec.js
Normal file
113
muranodashboard/static/app/murano/murano.module.spec.js
Normal file
@ -0,0 +1,113 @@
|
||||
/**
|
||||
* Copyright 2016, Mirantis, 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.app.murano', function () {
|
||||
it('should be defined', function () {
|
||||
expect(angular.module('horizon.app.murano')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('murano metadata patcher', function () {
|
||||
var metadataService, glance, murano;
|
||||
|
||||
var lastFakeCallArgs = [];
|
||||
var fakeResult = 'fakeMeta';
|
||||
|
||||
beforeEach(function () {
|
||||
murano = {
|
||||
getComponentMeta: fakeMeta,
|
||||
editComponentMeta: fakeMeta,
|
||||
getEnvironmentMeta: fakeMeta,
|
||||
editEnvironmentMeta: fakeMeta
|
||||
};
|
||||
module('horizon.framework');
|
||||
module('horizon.app.core');
|
||||
module('horizon.app.murano');
|
||||
module(function($provide) {
|
||||
$provide.value('horizon.app.core.openstack-service-api.murano', murano);
|
||||
});
|
||||
|
||||
function fakeMeta() {
|
||||
var i;
|
||||
for (i = 0, lastFakeCallArgs = []; i < arguments.length; i++) {
|
||||
lastFakeCallArgs.push(arguments[i]);
|
||||
}
|
||||
return fakeResult;
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
metadataService = $injector.get('horizon.app.core.metadata.service');
|
||||
glance = $injector.get('horizon.app.core.openstack-service-api.glance');
|
||||
}));
|
||||
|
||||
it('should get component metadata', function () {
|
||||
var actual = metadataService.getMetadata('muranoapp', 'compId');
|
||||
expect(actual).toBe(fakeResult);
|
||||
expect(lastFakeCallArgs).toEqual(['compId']);
|
||||
});
|
||||
|
||||
it('should get environment metadata', function () {
|
||||
var actual = metadataService.getMetadata('muranoenv', 'envId');
|
||||
expect(actual).toBe(fakeResult);
|
||||
expect(lastFakeCallArgs).toEqual(['envId']);
|
||||
});
|
||||
|
||||
it('should edit component metadata', function () {
|
||||
metadataService.editMetadata('muranoapp', 'compId',
|
||||
{'key1': 10}, ['key2']);
|
||||
expect(lastFakeCallArgs).toEqual(['compId', {'key1': 10}, ['key2']]);
|
||||
});
|
||||
|
||||
it('should edit environment metadata', function () {
|
||||
metadataService.editMetadata('muranoenv', 'envId',
|
||||
{'key1': 10}, ['key2']);
|
||||
expect(lastFakeCallArgs).toEqual(['envId', {'key1': 10}, ['key2']]);
|
||||
});
|
||||
|
||||
it('should get component namespace', function () {
|
||||
var params, flag;
|
||||
spyOn(glance, 'getNamespaces').and.callFake(function(_params, _flag) {
|
||||
params = _params;
|
||||
flag = _flag;
|
||||
});
|
||||
metadataService.getNamespaces('muranoapp', 'something');
|
||||
expect(params).toEqual({
|
||||
resource_type: 'OS::Murano::Application',
|
||||
properties_target: 'something'
|
||||
});
|
||||
expect(flag).toBe(false);
|
||||
});
|
||||
|
||||
it('should get environment namespace', function () {
|
||||
var params, flag;
|
||||
spyOn(glance, 'getNamespaces').and.callFake(function(_params, _flag) {
|
||||
params = _params;
|
||||
flag = _flag;
|
||||
});
|
||||
metadataService.getNamespaces('muranoenv', 'something');
|
||||
expect(params).toEqual({
|
||||
resource_type: 'OS::Murano::Environment',
|
||||
properties_target: 'something'
|
||||
});
|
||||
expect(flag).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -31,7 +31,11 @@
|
||||
|
||||
function muranoAPI(apiService, toastService) {
|
||||
var service = {
|
||||
getPackages: getPackages
|
||||
getPackages: getPackages,
|
||||
getComponentMeta: getComponentMeta,
|
||||
editComponentMeta: editComponentMeta,
|
||||
getEnvironmentMeta: getEnvironmentMeta,
|
||||
editEnvironmentMeta: editEnvironmentMeta
|
||||
};
|
||||
|
||||
return service;
|
||||
@ -70,5 +74,130 @@
|
||||
toastService.add('error', gettext('Unable to retrieve the packages.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.murano.getComponentMeta
|
||||
* @description
|
||||
* Get metadata attributes associated with a given component
|
||||
*
|
||||
* @param {Object} target
|
||||
* The object identifying the target component
|
||||
*
|
||||
* @param {string} target.environment
|
||||
* The identifier of the environment the component belongs to
|
||||
*
|
||||
* @param {string} target.component
|
||||
* The identifier of the component within the environment
|
||||
*
|
||||
* @param {string} target.session
|
||||
* The identifier of the configuration session for which the data should be
|
||||
* fetched
|
||||
*
|
||||
* @returns {Object} The metadata object
|
||||
*/
|
||||
function getComponentMeta(target) {
|
||||
var params = { params: { session: target.session} };
|
||||
var url = '/api/app-catalog/environments/' + target.environment +
|
||||
'/components/' + target.component + '/metadata/';
|
||||
return apiService.get(url, params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve component metadata.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.murano.editComponentMetadata
|
||||
* @description
|
||||
* Update metadata attributes associated with a given component
|
||||
*
|
||||
* @param {Object} target
|
||||
* The object identifying the target component
|
||||
*
|
||||
* @param {string} target.environment
|
||||
* The identifier of the environment the component belongs to
|
||||
*
|
||||
* @param {string} target.component
|
||||
* The identifier of the component within the environment
|
||||
*
|
||||
* @param {string} target.session
|
||||
* The identifier of the configuration session for which the data should be
|
||||
* updated
|
||||
*
|
||||
* @param {object} updated New metadata definitions.
|
||||
*
|
||||
* @param {[]} removed Names of removed metadata definitions.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function editComponentMeta(target, updated, removed) {
|
||||
var params = { params: { session: target.session} };
|
||||
var url = '/api/app-catalog/environments/' + target.environment +
|
||||
'/components/' + target.component + '/metadata/';
|
||||
return apiService.post(
|
||||
url, { updated: updated, removed: removed}, params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to edit component metadata.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.murano.getEnvironmentMeta
|
||||
* @description
|
||||
* Get metadata attributes associated with a given environment
|
||||
*
|
||||
* @param {Object} target
|
||||
* The object identifying the target environment
|
||||
*
|
||||
* @param {string} target.environment
|
||||
* The identifier of the target environment
|
||||
*
|
||||
* @param {string} target.session
|
||||
* The identifier of the configuration session for which the data should be
|
||||
* fetched
|
||||
*
|
||||
* @returns {Object} The metadata object
|
||||
*/
|
||||
function getEnvironmentMeta(target) {
|
||||
var params = { params: { session: target.session} };
|
||||
var url = '/api/app-catalog/environments/' + target.environment +
|
||||
'/metadata/';
|
||||
return apiService.get(url, params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to retrieve environment metadata.'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name horizon.app.core.openstack-service-api.murano.editEnvironmentMeta
|
||||
* @description
|
||||
* Update metadata attributes associated with a given environment
|
||||
*
|
||||
* @param {Object} target
|
||||
* The object identifying the target environment
|
||||
*
|
||||
* @param {string} target.environment
|
||||
* The identifier of the environment the component belongs to
|
||||
*
|
||||
* @param {string} target.session
|
||||
* The identifier of the configuration session for which the data should be
|
||||
* updated
|
||||
*
|
||||
* @param {object} updated New metadata definitions.
|
||||
*
|
||||
* @param {[]} removed Names of removed metadata definitions.
|
||||
*
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function editEnvironmentMeta(target, updated, removed) {
|
||||
var params = { params: { session: target.session} };
|
||||
var url = '/api/app-catalog/environments/' + target.environment +
|
||||
'/metadata/';
|
||||
return apiService.post(
|
||||
url, { updated: updated, removed: removed}, params)
|
||||
.error(function () {
|
||||
toastService.add('error', gettext('Unable to edit environment metadata.'));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
108
muranodashboard/static/app/murano/murano.service.spec.js
Normal file
108
muranodashboard/static/app/murano/murano.service.spec.js
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright 2016, Mirantis, 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('Murano API', function () {
|
||||
var testCall, service;
|
||||
var apiService = {};
|
||||
var toastService = {};
|
||||
|
||||
beforeEach(
|
||||
module('horizon.mock.openstack-service-api',
|
||||
function($provide, initServices) {
|
||||
testCall = initServices($provide, apiService, toastService);
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(module('horizon.app.core.openstack-service-api'));
|
||||
|
||||
beforeEach(inject([
|
||||
'horizon.app.core.openstack-service-api.murano',
|
||||
function(muranoAPI) {
|
||||
service = muranoAPI;
|
||||
}]));
|
||||
|
||||
it('defines the service', function () {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
var tests = [
|
||||
{
|
||||
func: 'getPackages',
|
||||
method: 'get',
|
||||
path: '/api/app-catalog/packages/',
|
||||
data: {params: 'config'},
|
||||
error: 'Unable to retrieve the packages.',
|
||||
testInput: [ 'config' ]
|
||||
}, {
|
||||
func: 'getComponentMeta',
|
||||
method: 'get',
|
||||
path: '/api/app-catalog/environments/1/components/2/metadata/',
|
||||
data: {params: {session: 'sessionId'}},
|
||||
error: 'Unable to retrieve component metadata.',
|
||||
testInput: [{session: 'sessionId', environment: '1', component: '2'}]
|
||||
}, {
|
||||
func: 'editComponentMeta',
|
||||
method: 'post',
|
||||
path: '/api/app-catalog/environments/1/components/2/metadata/',
|
||||
call_args: [
|
||||
'/api/app-catalog/environments/1/components/2/metadata/',
|
||||
{updated: {'key1': 10}, removed: ['key2']},
|
||||
{params: {session: 'sessionId'}}
|
||||
],
|
||||
error: 'Unable to edit component metadata.',
|
||||
testInput: [
|
||||
{session: 'sessionId', environment: '1', component: '2'},
|
||||
{'key1': 10},
|
||||
['key2']
|
||||
]
|
||||
}, {
|
||||
func: 'getEnvironmentMeta',
|
||||
method: 'get',
|
||||
path: '/api/app-catalog/environments/1/metadata/',
|
||||
data: {params: {session: 'sessionId'}},
|
||||
error: 'Unable to retrieve environment metadata.',
|
||||
testInput: [{session: 'sessionId', environment: '1'}]
|
||||
}, {
|
||||
func: 'editEnvironmentMeta',
|
||||
method: 'post',
|
||||
path: '/api/app-catalog/environments/1/metadata/',
|
||||
call_args: [
|
||||
'/api/app-catalog/environments/1/metadata/',
|
||||
{updated: {'key1': 10}, removed: ['key2']},
|
||||
{params: {session: 'sessionId'}}
|
||||
],
|
||||
error: 'Unable to edit environment metadata.',
|
||||
testInput: [
|
||||
{session: 'sessionId', environment: '1'},
|
||||
{'key1': 10},
|
||||
['key2']
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Iterate through the defined tests and apply as Jasmine specs.
|
||||
angular.forEach(tests, function(params) {
|
||||
it('defines the ' + params.func + ' call properly', function () {
|
||||
var callParams = [apiService, service, toastService, params];
|
||||
testCall.apply(this, callParams);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
Loading…
x
Reference in New Issue
Block a user