Add create action into Receiver panel
This patch adds create action into Receiver panel as global action. And add "params" attribute for receiver. Change-Id: Ibb0a5afd90f57a9a76ca15960b496675f41eeb62
This commit is contained in:
parent
ae382d7a78
commit
1ace5bac93
|
@ -19,7 +19,7 @@ from senlin_dashboard.api import senlin
|
|||
from senlin_dashboard.api import utils as api_utils
|
||||
from senlin_dashboard.cluster.nodes import forms as node_forms
|
||||
from senlin_dashboard.cluster.profiles import forms
|
||||
|
||||
from senlin_dashboard.cluster.receivers import forms as receiver_forms
|
||||
|
||||
CLIENT_KEYWORDS = {'marker', 'sort_dir', 'sort_key', 'paginate'}
|
||||
|
||||
|
@ -40,12 +40,37 @@ class Receivers(generic.View):
|
|||
receivers, has_more_data, has_prev_data = senlin.receiver_list(
|
||||
request, filters=filters, **kwargs)
|
||||
|
||||
receivers_dict = []
|
||||
for r in receivers:
|
||||
r = r.to_dict()
|
||||
r["params"] = api_utils.convert_to_yaml(r["params"])
|
||||
r["channel"] = api_utils.convert_to_yaml(r["channel"])
|
||||
receivers_dict.append(r)
|
||||
|
||||
return {
|
||||
'items': [r.to_dict() for r in receivers],
|
||||
'items': receivers_dict,
|
||||
'has_more_data': has_more_data,
|
||||
'has_prev_data': has_prev_data,
|
||||
}
|
||||
|
||||
@rest_utils.ajax(data_required=True)
|
||||
def post(self, request):
|
||||
"""Create a new Receiver.
|
||||
|
||||
Returns the new Receiver object on success.
|
||||
"""
|
||||
request_param = request.DATA
|
||||
params = receiver_forms._populate_receiver_params(
|
||||
request_param.get("name"),
|
||||
request_param.get("type"),
|
||||
request_param.get("cluster_id"),
|
||||
request_param.get("action"),
|
||||
request_param.get("params"))
|
||||
new_receiver = senlin.receiver_create(request, **params)
|
||||
return rest_utils.CreatedResponse(
|
||||
'/api/senlin/receivers/%s' % new_receiver.id,
|
||||
new_receiver.to_dict())
|
||||
|
||||
|
||||
@urls.register
|
||||
class Receiver(generic.View):
|
||||
|
@ -63,7 +88,10 @@ class Receiver(generic.View):
|
|||
|
||||
The result is a receiver object.
|
||||
"""
|
||||
return senlin.receiver_get(request, receiver_id).to_dict()
|
||||
receiver = senlin.receiver_get(request, receiver_id).to_dict()
|
||||
receiver["params"] = api_utils.convert_to_yaml(receiver["params"])
|
||||
receiver["channel"] = api_utils.convert_to_yaml(receiver["channel"])
|
||||
return receiver
|
||||
|
||||
@rest_utils.ajax()
|
||||
def delete(self, request, receiver_id):
|
||||
|
|
|
@ -75,7 +75,7 @@ class Event(base.APIResourceWrapper):
|
|||
|
||||
class Receiver(base.APIResourceWrapper):
|
||||
_attrs = ['id', 'name', 'type', 'cluster_id', 'action', 'created_at',
|
||||
'updated_at', 'channel']
|
||||
'updated_at', 'params', 'channel']
|
||||
|
||||
|
||||
@memoized.memoized
|
||||
|
@ -450,7 +450,7 @@ def receiver_list(request, sort_dir='desc', sort_key='created_at',
|
|||
return [Receiver(r) for r in receivers], has_more_data, has_prev_data
|
||||
|
||||
|
||||
def receiver_create(request, params):
|
||||
def receiver_create(request, **params):
|
||||
"""Create receiver"""
|
||||
receiver = senlinclient(request).create_receiver(**params)
|
||||
return Receiver(receiver)
|
||||
|
|
|
@ -30,6 +30,24 @@ from senlin_dashboard.api import senlin
|
|||
INDEX_URL = "horizon:cluster:receivers:index"
|
||||
|
||||
|
||||
def _populate_receiver_params(name, type_name, cluster_id, action, params):
|
||||
if not params:
|
||||
params_dict = {}
|
||||
else:
|
||||
try:
|
||||
params_dict = yaml.load(params)
|
||||
except Exception as ex:
|
||||
raise Exception(_('The specified params is not a valid '
|
||||
'YAML: %s') % six.text_type(ex))
|
||||
params = {"name": name,
|
||||
"type": type_name,
|
||||
"cluster_id": cluster_id,
|
||||
"action": action,
|
||||
"params": params_dict}
|
||||
|
||||
return params
|
||||
|
||||
|
||||
class CreateReceiverForm(forms.SelfHandlingForm):
|
||||
name = forms.CharField(max_length=255, label=_("Name"))
|
||||
cluster_id = forms.ThemableChoiceField(
|
||||
|
|
|
@ -70,12 +70,19 @@ class ReceiversTest(test.TestCase):
|
|||
'action': 'CLUSTER_SCALE_IN',
|
||||
'params': ''
|
||||
}
|
||||
formdata = {
|
||||
'name': 'test-receiver',
|
||||
'type': 'webhook',
|
||||
'cluster_id': '123456',
|
||||
'action': 'CLUSTER_SCALE_IN',
|
||||
'params': ''
|
||||
}
|
||||
|
||||
api.senlin.cluster_list(
|
||||
IsA(http.HttpRequest)).AndReturn((clusters, False, False))
|
||||
api.senlin.receiver_create(
|
||||
IsA(http.HttpRequest), data).AndReturn(receiver)
|
||||
IsA(http.HttpRequest), **data).AndReturn(receiver)
|
||||
self.mox.ReplayAll()
|
||||
|
||||
res = self.client.post(CREATE_URL, data)
|
||||
res = self.client.post(CREATE_URL, formdata)
|
||||
self.assertNoFormErrors(res)
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
getEvents: getEvents,
|
||||
getReceivers: getReceivers,
|
||||
getReceiver: getReceiver,
|
||||
createReceiver: createReceiver,
|
||||
deleteReceiver: deleteReceiver,
|
||||
getCluster: getCluster,
|
||||
getClusters: getClusters
|
||||
|
@ -216,6 +217,27 @@
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name createReceiver
|
||||
* @description
|
||||
* Create new Receiver.
|
||||
*
|
||||
* @param {Object} params
|
||||
* JSON object to create new receiver like name, type, cluster_id, action
|
||||
* and params.
|
||||
* @param {boolean} suppressError
|
||||
* If passed in, this will not show the default error handling
|
||||
* @returns {Object} The result of the API call
|
||||
*/
|
||||
function createReceiver(params, suppressError) {
|
||||
var promise = apiService.post('/api/senlin/receivers/', params);
|
||||
|
||||
return suppressError ? promise : promise.error(function() {
|
||||
var msg = gettext('Unable to create the receiver with name: %(name)s');
|
||||
toastService.add('error', interpolate(msg, { name: params.name }, true));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @name deleteReceiver
|
||||
* @description
|
||||
|
|
|
@ -30,16 +30,29 @@
|
|||
|
||||
registerReceiverActions.$inject = [
|
||||
'horizon.framework.conf.resource-type-registry.service',
|
||||
'horizon.app.core.receivers.actions.delete.service',
|
||||
'horizon.cluster.receivers.actions.create.service',
|
||||
'horizon.cluster.receivers.actions.delete.service',
|
||||
'horizon.app.core.receivers.resourceType'
|
||||
];
|
||||
|
||||
function registerReceiverActions(
|
||||
registry,
|
||||
createReceiverService,
|
||||
deleteReceiverService,
|
||||
receiverResourceType
|
||||
) {
|
||||
var receiverResource = registry.getResourceType(receiverResourceType);
|
||||
|
||||
receiverResource.globalActions
|
||||
.append({
|
||||
id: 'createReceiverAction',
|
||||
service: createReceiverService,
|
||||
template: {
|
||||
text: gettext('Create Receiver'),
|
||||
type: 'create'
|
||||
}
|
||||
});
|
||||
|
||||
receiverResource.itemActions
|
||||
.append({
|
||||
id: 'deleteReceiverAction',
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* 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 factory
|
||||
* @name horizon.cluster.receivers.actions.create.service
|
||||
* @description
|
||||
* Service for the cluster receiver create modal
|
||||
*/
|
||||
angular
|
||||
.module('horizon.cluster.receivers.actions')
|
||||
.factory('horizon.cluster.receivers.actions.create.service', createService);
|
||||
|
||||
createService.$inject = [
|
||||
'$location',
|
||||
'horizon.app.core.openstack-service-api.policy',
|
||||
'horizon.app.core.openstack-service-api.senlin',
|
||||
'horizon.app.core.receivers.basePath',
|
||||
'horizon.app.core.receivers.resourceType',
|
||||
'horizon.framework.util.actions.action-result.service',
|
||||
'horizon.framework.util.i18n.gettext',
|
||||
'horizon.framework.widgets.form.ModalFormService',
|
||||
'horizon.framework.widgets.toast.service',
|
||||
'horizon.cluster.receivers.actions.workflow'
|
||||
];
|
||||
|
||||
function createService(
|
||||
$location, policy, senlin, basePath, resourceType, actionResult, gettext,
|
||||
modal, toast, workflow
|
||||
) {
|
||||
|
||||
var message = {
|
||||
success: gettext('Receiver %s was successfully created.')
|
||||
};
|
||||
|
||||
var service = {
|
||||
initAction: initAction,
|
||||
perform: perform,
|
||||
allowed: allowed
|
||||
};
|
||||
|
||||
return service;
|
||||
|
||||
//////////////
|
||||
|
||||
function initAction() {
|
||||
}
|
||||
|
||||
function perform() {
|
||||
// modal title, buttons
|
||||
var title, submitText, submitIcon, helpUrl;
|
||||
title = gettext('Create Receiver');
|
||||
submitText = gettext('Create');
|
||||
submitIcon = 'fa fa-check';
|
||||
helpUrl = basePath + 'actions/receiver.help.html';
|
||||
|
||||
var config = workflow.init('create', title, submitText, submitIcon, helpUrl);
|
||||
return modal.open(config).then(submit);
|
||||
}
|
||||
|
||||
function allowed() {
|
||||
return policy.ifAllowed({ rules: [['cluster', 'receivers:create']] });
|
||||
}
|
||||
|
||||
function submit(context) {
|
||||
delete context.model.id;
|
||||
return senlin.createReceiver(context.model, false).then(success, true);
|
||||
}
|
||||
|
||||
function success(response) {
|
||||
toast.add('success', interpolate(message.success, [response.data.id]));
|
||||
var result = actionResult.getActionResult()
|
||||
.created(resourceType, response.data.id);
|
||||
if (result.result.failed.length === 0 && result.result.created.length > 0) {
|
||||
$location.path("/cluster/receivers");
|
||||
} else {
|
||||
return result.result;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* 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.cluster.receivers.actions.create.service', function() {
|
||||
|
||||
var service, $scope, $q, deferred, senlin, basePath;
|
||||
|
||||
var workflow = {
|
||||
init: function (actionType, title, submitText, submitIcon, helpUrl) {
|
||||
actionType = title = submitText = submitIcon = helpUrl;
|
||||
return {then: angular.noop, dummy: actionType};
|
||||
}
|
||||
};
|
||||
|
||||
var modal = {
|
||||
open: function (config) {
|
||||
deferred = $q.defer();
|
||||
deferred.resolve(config.model);
|
||||
return deferred.promise;
|
||||
}
|
||||
};
|
||||
|
||||
var selected = {id: 1};
|
||||
|
||||
///////////////////
|
||||
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.framework'));
|
||||
beforeEach(module('horizon.cluster.receivers'));
|
||||
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.value('horizon.framework.widgets.form.ModalFormService', modal);
|
||||
$provide.value('horizon.cluster.receivers.actions.workflow', workflow);
|
||||
}));
|
||||
|
||||
beforeEach(inject(function($injector, _$rootScope_, _$q_) {
|
||||
$q = _$q_;
|
||||
$scope = _$rootScope_.$new();
|
||||
service = $injector.get('horizon.cluster.receivers.actions.create.service');
|
||||
senlin = $injector.get('horizon.app.core.openstack-service-api.senlin');
|
||||
basePath = $injector.get('horizon.app.core.receivers.basePath');
|
||||
deferred = $q.defer();
|
||||
deferred.resolve({data: {id: 1}});
|
||||
spyOn(senlin, 'createReceiver').and.returnValue(deferred.promise);
|
||||
spyOn(workflow, 'init').and.callThrough();
|
||||
spyOn(modal, 'open').and.callThrough();
|
||||
}));
|
||||
|
||||
it('should check the policy if the user is allowed to create receiver', function() {
|
||||
var allowed = service.allowed();
|
||||
expect(allowed).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should initialize workflow', function() {
|
||||
service.initAction();
|
||||
service.perform(selected, $scope);
|
||||
|
||||
expect(workflow.init).toHaveBeenCalled();
|
||||
|
||||
var modalArgs = workflow.init.calls.mostRecent().args;
|
||||
expect(modalArgs[0]).toEqual('create');
|
||||
expect(modalArgs[1]).toEqual('Create Receiver');
|
||||
expect(modalArgs[2]).toEqual('Create');
|
||||
expect(modalArgs[3]).toEqual('fa fa-check');
|
||||
expect(modalArgs[4]).toEqual(basePath + 'actions/receiver.help.html');
|
||||
|
||||
expect(modal.open).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
})();
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
angular
|
||||
.module('horizon.cluster.receivers')
|
||||
.factory('horizon.app.core.receivers.actions.delete.service', deleteReceiverService);
|
||||
.factory('horizon.cluster.receivers.actions.delete.service', deleteReceiverService);
|
||||
|
||||
deleteReceiverService.$inject = [
|
||||
'$q',
|
||||
|
@ -33,7 +33,7 @@
|
|||
|
||||
/*
|
||||
* @ngdoc factory
|
||||
* @name horizon.app.core.receivers.actions.delete.service
|
||||
* @name horizon.cluster.receivers.actions.delete.service
|
||||
*
|
||||
* @Description
|
||||
* Brings up the delete receivers confirmation modal dialog.
|
||||
|
@ -100,18 +100,17 @@
|
|||
function createResult(deleteModalResult) {
|
||||
// To make the result of this action generically useful, reformat the return
|
||||
// from the deleteModal into a standard form
|
||||
var actionResult = actionResultService.getActionResult();
|
||||
var result = actionResultService.getActionResult();
|
||||
deleteModalResult.pass.forEach(function markDeleted(item) {
|
||||
actionResult.deleted(receiversResourceType, getEntity(item).id);
|
||||
result.deleted(receiversResourceType, getEntity(item).id);
|
||||
});
|
||||
deleteModalResult.fail.forEach(function markFailed(item) {
|
||||
actionResult.failed(receiversResourceType, getEntity(item).id);
|
||||
result.failed(receiversResourceType, getEntity(item).id);
|
||||
});
|
||||
if (actionResult.result.failed.length === 0 &&
|
||||
actionResult.result.deleted.length > 0) {
|
||||
if (result.result.failed.length === 0 && result.result.deleted.length > 0) {
|
||||
$location.path('/cluster/receivers');
|
||||
} else {
|
||||
return actionResult.result;
|
||||
return result.result;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
describe('horizon.app.core.receivers.actions.delete.service', function() {
|
||||
describe('horizon.cluster.receivers.actions.delete.service', function() {
|
||||
|
||||
var service, $scope, deferredModal;
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
|||
|
||||
beforeEach(inject(function($injector, _$rootScope_, $q) {
|
||||
$scope = _$rootScope_.$new();
|
||||
service = $injector.get('horizon.app.core.receivers.actions.delete.service');
|
||||
service = $injector.get('horizon.cluster.receivers.actions.delete.service');
|
||||
deferredModal = $q.defer();
|
||||
}));
|
||||
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<dl>
|
||||
<dt translate>Name</dt>
|
||||
<dd translate>An arbitrary human-readable name.</dd>
|
||||
<dt translate>Type</dt>
|
||||
<dd translate>Type of the receiver to create. Default to webhook</dd>
|
||||
<dt translate>Cluster</dt>
|
||||
<dd translate>Targeted cluster for this receiver.</dd>
|
||||
<dt translate>Action</dt>
|
||||
<dd translate>Name or ID of the targeted action to be triggered.</dd>
|
||||
<dt translate>Params</dt>
|
||||
<dd translate>YAML formatted parameters that will be passed to target action when the receiver is triggered.</dd>
|
||||
</dl>
|
|
@ -0,0 +1,160 @@
|
|||
/**
|
||||
* 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 factory
|
||||
* @name horizon.cluster.receivers.actions.workflow
|
||||
* @ngController
|
||||
*
|
||||
* @description
|
||||
* Workflow for creating/updating receiver
|
||||
*/
|
||||
angular
|
||||
.module('horizon.cluster.receivers.actions')
|
||||
.factory('horizon.cluster.receivers.actions.workflow', workflow);
|
||||
|
||||
workflow.$inject = [
|
||||
'horizon.app.core.openstack-service-api.senlin',
|
||||
'horizon.framework.util.i18n.gettext'
|
||||
];
|
||||
|
||||
function workflow(senlin, gettext) {
|
||||
var workflow = {
|
||||
init: init
|
||||
};
|
||||
|
||||
function init(actionType, title, submitText, submitIcon, helpUrl) {
|
||||
var schema, form, model;
|
||||
|
||||
// schema
|
||||
schema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: {
|
||||
title: gettext('Name'),
|
||||
type: 'string'
|
||||
},
|
||||
type: {
|
||||
title: gettext('Type'),
|
||||
type: 'string',
|
||||
default: ''
|
||||
},
|
||||
cluster_id: {
|
||||
title: gettext('Cluster'),
|
||||
type: 'string',
|
||||
default: ''
|
||||
},
|
||||
action: {
|
||||
title: gettext('Action'),
|
||||
type: 'string'
|
||||
},
|
||||
params: {
|
||||
title: gettext('Params'),
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// form
|
||||
form = [
|
||||
{
|
||||
type: 'section',
|
||||
htmlClass: 'row',
|
||||
items: [
|
||||
{
|
||||
type: 'section',
|
||||
htmlClass: 'col-sm-6',
|
||||
items: [
|
||||
{
|
||||
key: 'name',
|
||||
placeholder: gettext('Name of the receiver.'),
|
||||
required: true
|
||||
},
|
||||
{
|
||||
key: 'type',
|
||||
type: 'select',
|
||||
titleMap: [
|
||||
{value: '', name: gettext('Select type for the receiver.')},
|
||||
{value: 'webhook', name: gettext('Webhook')},
|
||||
{value: 'message', name: gettext('Message')}
|
||||
],
|
||||
required: true
|
||||
},
|
||||
{
|
||||
key: 'cluster_id',
|
||||
type: 'select',
|
||||
titleMap: [
|
||||
{value: '', name: gettext('Select cluster for the receiver.')}
|
||||
],
|
||||
required: "model.type === 'webhook' || model.type === ''"
|
||||
},
|
||||
{
|
||||
key: 'action',
|
||||
type: 'select',
|
||||
titleMap: [
|
||||
{value: '', name: gettext('Select action for the receiver.')},
|
||||
{value: 'CLUSTER_SCALE_IN', name: gettext('Scale In the Cluster')},
|
||||
{value: 'CLUSTER_SCALE_OUT', name: gettext('Scale Out the Cluster')}
|
||||
],
|
||||
required: "model.type === 'webhook' || model.type === ''"
|
||||
},
|
||||
{
|
||||
key: 'params',
|
||||
type: 'textarea',
|
||||
placeholder: gettext('Parameters of the receiver in YAML format.')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
type: 'template',
|
||||
templateUrl: helpUrl
|
||||
}
|
||||
]
|
||||
}
|
||||
]; // form
|
||||
|
||||
// Get clusters
|
||||
senlin.getClusters().then(onGetClusters);
|
||||
function onGetClusters(response) {
|
||||
angular.forEach(response.data.items, function(item) {
|
||||
form[0].items[0].items[2].titleMap.push({value: item.id, name: item.name});
|
||||
});
|
||||
}
|
||||
|
||||
model = {
|
||||
id: '',
|
||||
name: '',
|
||||
type: '',
|
||||
cluster_id: '',
|
||||
action: '',
|
||||
params: ''
|
||||
};
|
||||
|
||||
var config = {
|
||||
title: title,
|
||||
submitText: submitText,
|
||||
schema: schema,
|
||||
form: form,
|
||||
model: model
|
||||
};
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
return workflow;
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* 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.cluster.receivers.actions.workflow', function() {
|
||||
|
||||
var workflow, senlin;
|
||||
|
||||
function fakePromise() {
|
||||
return { then: angular.noop };
|
||||
}
|
||||
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.framework'));
|
||||
beforeEach(module('horizon.cluster.receivers'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
workflow = $injector.get('horizon.cluster.receivers.actions.workflow');
|
||||
senlin = $injector.get('horizon.app.core.openstack-service-api.senlin');
|
||||
spyOn(senlin, 'getProfiles').and.callFake(fakePromise);
|
||||
spyOn(senlin, 'getClusters').and.callFake(fakePromise);
|
||||
}));
|
||||
|
||||
function testInitWorkflow(actionType, title, submitText) {
|
||||
var submitIcon, helpUrl;
|
||||
submitIcon = 'fa fa-check';
|
||||
helpUrl = 'receiver.help.html';
|
||||
|
||||
var config = workflow.init(actionType, title, submitText, submitIcon, helpUrl);
|
||||
|
||||
expect(senlin.getClusters).toHaveBeenCalled();
|
||||
|
||||
expect(config.title).toEqual(title);
|
||||
expect(config.submitText).toEqual(submitText);
|
||||
expect(config.schema).toBeDefined();
|
||||
expect(config.form).toBeDefined();
|
||||
return config;
|
||||
}
|
||||
|
||||
it('should be create workflow config for create', function() {
|
||||
var config = testInitWorkflow('create', 'Create Receiver', 'Create');
|
||||
expect(config.form[0].items[0].items[1].required).toEqual(true);
|
||||
});
|
||||
});
|
||||
})();
|
|
@ -1,6 +1,6 @@
|
|||
<hz-resource-property-list
|
||||
resource-type-name="OS::Senlin::Receiver"
|
||||
item="item"
|
||||
property-groups="[['id', 'channel'],
|
||||
property-groups="[['id', 'params', 'channel'],
|
||||
['created_at', 'updated_at']]">
|
||||
</hz-resource-property-list>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
cls="dl-horizontal"
|
||||
item="ctrl.receiver"
|
||||
property-groups="[['id', 'name', 'created_at', 'updated_at'],
|
||||
['type', 'cluster_id', 'action', 'channel']]">
|
||||
['type', 'cluster_id', 'action', 'params', 'channel']]">
|
||||
</hz-resource-property-list>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<hz-resource-panel resource-type-name="OS::Senlin::Receiver">
|
||||
<hz-resource-table resource-type-name="OS::Senlin::Receiver">
|
||||
<hz-resource-table resource-type-name="OS::Senlin::Receiver" track-by="trackBy">
|
||||
</hz-resource-table>
|
||||
</hz-resource-panel>
|
||||
|
|
|
@ -106,10 +106,11 @@
|
|||
return {
|
||||
id: { label: gettext('ID'), filters: ['noValue'] },
|
||||
name: { label: gettext('Name'), filters: ['noName'] },
|
||||
type: { label: gettext('Type'), filters: ['noName'] },
|
||||
type: { label: gettext('Type'), filters: ['noValue'] },
|
||||
cluster_id: { label: gettext('Cluster ID'), filters: ['noValue'] },
|
||||
action: { label: gettext('Action'), filters: ['noValue'] },
|
||||
channel: { label: gettext('Channel'), filters: ['noValue', 'json'] },
|
||||
params: { label: gettext('Parameters'), filters: ['noValue'] },
|
||||
channel: { label: gettext('Channel'), filters: ['noValue'] },
|
||||
created_at: { label: gettext('Created'), filters: ['simpleDate'] },
|
||||
updated_at: { label: gettext('Updated'), filters: ['simpleDate'] }
|
||||
};
|
||||
|
|
|
@ -66,7 +66,17 @@
|
|||
* receivers. This is used in displaying lists of Receivers.
|
||||
*/
|
||||
function getReceiversPromise(params) {
|
||||
return senlin.getReceivers(params);
|
||||
return senlin.getReceivers(params).then(modifyResponse);
|
||||
}
|
||||
|
||||
function modifyResponse(response) {
|
||||
return {data: {items: response.data.items.map(modifyItem)}};
|
||||
|
||||
function modifyItem(item) {
|
||||
var timestamp = item.updated_at ? item.updated_at : item.created_at;
|
||||
item.trackBy = item.id + timestamp;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
|
@ -22,12 +22,33 @@ class SenlinRestTestCase(test.TestCase):
|
|||
# Receiver
|
||||
#
|
||||
|
||||
_receivers = [
|
||||
{
|
||||
'id': '1',
|
||||
'name': 'test-receiver1',
|
||||
'type': 'webhook',
|
||||
'cluster_id': 'c1',
|
||||
'action': 'CLUSTER_SCALE_OUT',
|
||||
'params': None,
|
||||
'channel': None
|
||||
},
|
||||
{
|
||||
'id': '2',
|
||||
'name': 'test-receiver2',
|
||||
'type': 'message',
|
||||
'cluster_id': None,
|
||||
'action': None,
|
||||
'params': None,
|
||||
'channel': None
|
||||
},
|
||||
]
|
||||
|
||||
@mock.patch.object(senlin, 'senlin')
|
||||
def test_receivers_get(self, client):
|
||||
request = self.mock_rest_request(**{'GET': {}})
|
||||
client.receiver_list.return_value = ([
|
||||
mock.Mock(**{'to_dict.return_value': {'id': 'one'}}),
|
||||
mock.Mock(**{'to_dict.return_value': {'id': 'two'}}),
|
||||
mock.Mock(**{'to_dict.return_value': self._receivers[0]}),
|
||||
mock.Mock(**{'to_dict.return_value': self._receivers[1]}),
|
||||
], False, True)
|
||||
|
||||
response = senlin.Receivers().get(request)
|
||||
|
@ -39,15 +60,15 @@ class SenlinRestTestCase(test.TestCase):
|
|||
@mock.patch.object(senlin, 'senlin')
|
||||
def test_receiver_get_single(self, client):
|
||||
request = self.mock_rest_request()
|
||||
client.receiver_get.return_value.to_dict.return_value = {
|
||||
'name': 'test-receiver'}
|
||||
client.receiver_get.return_value.to_dict.return_value = \
|
||||
self._receivers[0]
|
||||
|
||||
response = senlin.Receiver().get(request, '1')
|
||||
self.assertStatusCode(response, 200)
|
||||
self.assertEqual('test-receiver', response.json['name'])
|
||||
self.assertEqual('test-receiver1', response.json['name'])
|
||||
|
||||
@mock.patch.object(senlin, 'senlin')
|
||||
def test_receiver_delete(self, client):
|
||||
request = self.mock_rest_request()
|
||||
senlin.Receiver().delete(request, "1")
|
||||
client.receiver_delete.assert_called_once_with(request, "1")
|
||||
senlin.Receiver().delete(request, '1')
|
||||
client.receiver_delete.assert_called_once_with(request, '1')
|
||||
|
|
|
@ -110,7 +110,7 @@ class SenlinApiTests(test.APITestCase):
|
|||
senlinclient.receivers.return_value = receivers
|
||||
|
||||
ret_val, _more, _prev = api.senlin.receiver_list(self.request)
|
||||
for receiver in ret_val:
|
||||
for receiver in ret_val[0]:
|
||||
self.assertIsInstance(receiver, api.senlin.Receiver)
|
||||
|
||||
senlinclient.receivers.assert_called_once_with(**params)
|
||||
|
|
Loading…
Reference in New Issue