Add policy support to workflow steps
This updates the workflow decorator service to check policy rules to determine whether or not to display a workflow step. Each workflow step can have a policy property which specifies the policy rule to check. Related to blueprint add-scheduler-hints Change-Id: Id9270a4f20d785283372c182d178fe9b59e3259b
This commit is contained in:
parent
a59195914e
commit
52f988cd78
@ -29,7 +29,9 @@
|
||||
});
|
||||
return spec;
|
||||
};
|
||||
$provide.value('horizon.app.core.openstack-service-api.serviceCatalog', {});
|
||||
$provide.value('horizon.app.core.openstack-service-api.serviceCatalog', {
|
||||
ifTypeEnabled: angular.noop
|
||||
});
|
||||
$provide.value('horizon.framework.util.workflow.service', workflow);
|
||||
}));
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
|
||||
* Copyright 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,14 +27,16 @@
|
||||
* @kind function
|
||||
* @description
|
||||
*
|
||||
* A workflow decorator function that adds checkReadiness method to step in
|
||||
* the work flow. checkReadiness function will check if a bunch of certain
|
||||
* types of OpenStack services is enabled in the cloud for that step to show
|
||||
* on the user interface.
|
||||
* A workflow decorator function that looks for the requiredServiceTypes or policy
|
||||
* properties on each step in the workflow. If either of these properties exist then
|
||||
* the checkReadiness method is added to the step. The checkReadiness method will
|
||||
* make sure the necessary OpenStack services are enabled and the policy check passes
|
||||
* in order for the step to be displayed.
|
||||
*
|
||||
* Injected dependencies:
|
||||
* - $q
|
||||
* - serviceCatalog horizon.app.core.openstack-service-api.serviceCatalog
|
||||
* - policy horizon.app.core.openstack-service-api.policy
|
||||
*
|
||||
* @param {Object} spec The input workflow specification object.
|
||||
* @returns {Object} The decorated workflow specification object, the same
|
||||
@ -46,12 +49,13 @@
|
||||
|
||||
dashboardWorkflowDecorator.$inject = [
|
||||
'$q',
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog'
|
||||
'horizon.app.core.openstack-service-api.serviceCatalog',
|
||||
'horizon.app.core.openstack-service-api.policy'
|
||||
];
|
||||
|
||||
/////////////
|
||||
|
||||
function dashboardWorkflowDecorator($q, serviceCatalog) {
|
||||
function dashboardWorkflowDecorator($q, serviceCatalog, policy) {
|
||||
return decorator;
|
||||
|
||||
function decorator(spec) {
|
||||
@ -64,12 +68,19 @@
|
||||
}
|
||||
|
||||
function decorateStep(step) {
|
||||
var promises = [];
|
||||
var types = step.requiredServiceTypes;
|
||||
if (types && types.length > 0) {
|
||||
promises = promises.concat(types.map(function checkServiceEnabled(type) {
|
||||
return serviceCatalog.ifTypeEnabled(type);
|
||||
}));
|
||||
}
|
||||
if (step.policy) {
|
||||
promises.push(policy.ifAllowed(step.policy));
|
||||
}
|
||||
if (promises.length > 0) {
|
||||
step.checkReadiness = function () {
|
||||
return $q.all(types.map(function (type) {
|
||||
return serviceCatalog.ifTypeEnabled(type);
|
||||
}));
|
||||
return $q.all(promises);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2016 IBM Corp.
|
||||
*
|
||||
* 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('Workflow Decorator', function () {
|
||||
var decoratorService, catalogService, policyService, $scope, deferred;
|
||||
var steps = [
|
||||
{ id: '1' },
|
||||
{ id: '2', requiredServiceTypes: ['foo-service'] },
|
||||
{ id: '3', policy: 'foo-policy' }
|
||||
];
|
||||
var spec = { steps: steps };
|
||||
|
||||
beforeEach(module('horizon.app.core'));
|
||||
beforeEach(module('horizon.framework.util'));
|
||||
beforeEach(module('horizon.framework.conf'));
|
||||
beforeEach(module('horizon.framework.widgets.toast'));
|
||||
|
||||
beforeEach(inject(function($injector) {
|
||||
$scope = $injector.get('$rootScope').$new();
|
||||
deferred = $injector.get('$q').defer();
|
||||
decoratorService = $injector.get('horizon.app.core.workflow.decorator');
|
||||
catalogService = $injector.get('horizon.app.core.openstack-service-api.serviceCatalog');
|
||||
policyService = $injector.get('horizon.app.core.openstack-service-api.policy');
|
||||
spyOn(catalogService, 'ifTypeEnabled').and.returnValue(deferred.promise);
|
||||
spyOn(policyService, 'ifAllowed').and.returnValue(deferred.promise);
|
||||
}));
|
||||
|
||||
it('is a function', function() {
|
||||
expect(angular.isFunction(decoratorService)).toBe(true);
|
||||
});
|
||||
|
||||
it('checks each step for required services and policies', function() {
|
||||
decoratorService(spec);
|
||||
expect(steps[0].checkReadiness).toBeUndefined();
|
||||
expect(steps[1].checkReadiness).toBeDefined();
|
||||
expect(steps[2].checkReadiness).toBeDefined();
|
||||
expect(catalogService.ifTypeEnabled.calls.count()).toBe(1);
|
||||
expect(catalogService.ifTypeEnabled).toHaveBeenCalledWith('foo-service');
|
||||
expect(policyService.ifAllowed.calls.count()).toBe(1);
|
||||
expect(policyService.ifAllowed).toHaveBeenCalledWith('foo-policy');
|
||||
});
|
||||
|
||||
it('step checkReadiness function returns correct results', function() {
|
||||
decoratorService(spec);
|
||||
var readinessResult;
|
||||
deferred.resolve('foo');
|
||||
steps[1].checkReadiness().then(function(result) {
|
||||
readinessResult = result;
|
||||
});
|
||||
$scope.$apply();
|
||||
expect(readinessResult).toEqual(['foo']);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
@ -28,6 +28,35 @@
|
||||
* - dashboardWorkflowDecorator {@link horizon.app.core.workflow.factory
|
||||
* :horizon.app.core.workflow.decorator `dashboardWorkflowDecorator`}
|
||||
*
|
||||
* @example
|
||||
* ```
|
||||
* var workflow = workflowService({
|
||||
* title: gettext('Create Volume'),
|
||||
* btnText: { finish: gettext('Create Volume') },
|
||||
* steps: [{
|
||||
* title: gettext('Step 1'),
|
||||
* templateUrl: basePath + 'steps/create-volume/step1.html',
|
||||
* helpUrl: basePath + 'steps/create-volume/step1.help.html',
|
||||
* formName: 'step1Form'
|
||||
* },{
|
||||
* title: gettext('Step 2'),
|
||||
* templateUrl: basePath + 'steps/create-volume/step2.html',
|
||||
* helpUrl: basePath + 'steps/create-volume/step2.help.html',
|
||||
* formName: 'step2Form',
|
||||
* requiredServiceTypes: ['network']
|
||||
* },{
|
||||
* title: gettext('Step 3'),
|
||||
* templateUrl: basePath + 'steps/create-volume/step3.html',
|
||||
* helpUrl: basePath + 'steps/create-volume/step3.help.html',
|
||||
* formName: 'step3Form',
|
||||
* policy: { rules: [['compute', 'os_compute_api:os-scheduler-hints:discoverable']] }
|
||||
* }]
|
||||
* });
|
||||
* ```
|
||||
* For each step, the requiredServiceTypes property specifies the service types that must
|
||||
* be available in the service catalog for the step to be displayed. The policy property
|
||||
* specifies the policy check that must pass in order for the step to be displayed.
|
||||
*
|
||||
* @param {Object} The input workflow specification object
|
||||
* @returns {Object} The decorated workflow specification object, the same
|
||||
* reference to the input spec object.
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- Added policy support to the angular workflow service so each step in a
|
||||
workflow can specify a policy check that must pass in order for the step
|
||||
to be displayed.
|
Loading…
x
Reference in New Issue
Block a user