Make Validation actions use startWorkflow

This patch makes runValidation use startWorkflow wrapper to properly
handle it's execution. This change makes handling validations much
simpler as there is no specific onFinished callback needed as validations
only operate on incoming workflow executions which is handled by
WorkflowActions by default.

To properly distinguish between start validation and finished validation
messages (which use the same type) additional logic to zaqar action
was added.

runValidationGroups action remains the same as we handle validations
individually

Partial-Bug: #1753474
Change-Id: Ie0f2f1c5175ca8b87fe7ed672548bc9c59865ae0
This commit is contained in:
Jiri Tomasek 2018-03-06 14:55:38 +01:00
parent 494af34c9b
commit 6e55c9f0a5
3 changed files with 23 additions and 92 deletions

View File

@ -14,13 +14,10 @@
* under the License.
*/
import { Map } from 'immutable';
import MistralApiService from '../../js/services/MistralApiService';
import ValidationsActions from '../../js/actions/ValidationsActions';
import ValidationsConstants from '../../js/constants/ValidationsConstants';
import WorkflowExecutionsActions from '../../js/actions/WorkflowExecutionsActions';
import { WorkflowExecution } from '../../js/immutableRecords/workflowExecutions';
import * as WorkflowActions from '../../js/actions/WorkflowActions';
import MistralConstants from '../../js/constants/MistralConstants';
import { mockStore } from './utils';
@ -95,7 +92,7 @@ describe('FetchValidations action', () => {
describe('RunValidation action', () => {
const store = mockStore({});
const addWorkflowExecutionResponse = {
const execution = {
state_info: null,
created_at: '2016-07-19 13:22:29.588140',
description: '',
@ -112,76 +109,22 @@ describe('RunValidation action', () => {
};
beforeEach(() => {
MistralApiService.runWorkflow = jest
WorkflowActions.startWorkflow = jest
.fn()
.mockReturnValue(() => Promise.resolve(addWorkflowExecutionResponse));
.mockReturnValue(() => Promise.resolve(execution));
});
it('dispatches appropriate actions', () =>
store
.dispatch(ValidationsActions.runValidation('512e', 'overcloud'))
.then(() => {
expect(MistralApiService.runWorkflow).toHaveBeenCalledWith(
expect(WorkflowActions.startWorkflow).toHaveBeenCalledWith(
MistralConstants.VALIDATIONS_RUN,
{
validation_name: '512e',
plan: 'overcloud'
}
);
expect(store.getActions()).toEqual([
WorkflowExecutionsActions.addWorkflowExecution(
addWorkflowExecutionResponse
)
]);
expect(store.getActions()).toEqual([]);
}));
});
// TODO(jtomasek): this test compares 2 immutable records and even though they're the same
// the test resolves as failing
xdescribe('runValidationMessage action', () => {
beforeEach(() => {
spyOn(WorkflowExecutionsActions, 'addWorkflowExecutionFromMessage');
});
it('creates WorkflowExecution from message and adds it', () => {
const messagePayload = {
status: 'RUNNING',
validation_name: 'check-network-gateway',
execution: {
input: {
validation_name: 'check-network-gateway',
queue_name: 'tripleo',
plan: 'plan'
},
params: {},
id: '6e610e0d-b87d-408e-8800-34de0dada52b'
},
plan: 'plan'
};
const expectedExecution = new WorkflowExecution({
description: undefined,
id: '6e610e0d-b87d-408e-8800-34de0dada52b',
input: Map({
validation_name: 'check-network-gateway',
queue_name: 'tripleo',
plan: 'plan'
}),
output: Map({
status: 'RUNNING',
validation_name: 'check-network-gateway',
plan: 'plan'
}),
params: Map(),
state: 'RUNNING',
state_info: undefined,
updated_at: undefined,
workflow_name: MistralConstants.VALIDATIONS_RUN
});
ValidationsActions.runValidationMessage(messagePayload)(() => {}, () => {});
expect(
WorkflowExecutionsActions.addWorkflowExecutionFromMessage
).toHaveBeenCalledWith(expectedExecution);
});
});

View File

@ -15,14 +15,13 @@
*/
import { normalize } from 'normalizr';
import { omit } from 'lodash';
import { handleErrors } from './ErrorActions';
import MistralApiService from '../services/MistralApiService';
import WorkflowExecutionsActions from './WorkflowExecutionsActions';
import ValidationsConstants from '../constants/ValidationsConstants';
import { validationSchema } from '../normalizrSchemas/validations';
import MistralConstants from '../constants/MistralConstants';
import { startWorkflow } from './WorkflowActions';
export default {
fetchValidations() {
@ -65,34 +64,13 @@ export default {
runValidation(id, currentPlanName) {
return (dispatch, getState) =>
dispatch(
MistralApiService.runWorkflow(MistralConstants.VALIDATIONS_RUN, {
startWorkflow(MistralConstants.VALIDATIONS_RUN, {
validation_name: id,
plan: currentPlanName
})
)
.then(response => {
dispatch(WorkflowExecutionsActions.addWorkflowExecution(response));
})
.catch(error => {
dispatch(handleErrors(error, 'Error running validation'));
});
},
runValidationMessage(messagePayload) {
return (dispatch, getState) => {
// convert messagePayload to execution-like response
const execution = {
id: messagePayload.execution.id,
input: messagePayload.execution.input,
output: omit(messagePayload, 'execution'),
params: messagePayload.execution.params,
state: messagePayload.status,
workflow_name: MistralConstants.VALIDATIONS_RUN,
// TODO(jtomasek): replace this with messagePayload.execution.updated_at once message provides it
updated_at: new Date(Date.now()) // setting this explicitly as message does not provide it
};
dispatch(WorkflowExecutionsActions.addWorkflowExecution(execution));
};
).catch(error => {
dispatch(handleErrors(error, 'Error running validation'));
});
},
runValidationGroups(groups, currentPlanName) {

View File

@ -20,7 +20,6 @@ import NodesActions from './NodesActions';
import PlansActions from './PlansActions';
import RegisterNodesActions from './RegisterNodesActions';
import RolesActions from './RolesActions';
import ValidationsActions from './ValidationsActions';
import MistralConstants from '../constants/MistralConstants';
import ZaqarWebSocketService from '../services/ZaqarWebSocketService';
import { handleWorkflowMessage } from './WorkflowActions';
@ -67,7 +66,18 @@ export default {
break;
case MistralConstants.VALIDATIONS_RUN: {
dispatch(ValidationsActions.runValidationMessage(payload));
// TODO(jtomasek): this conditional is a workaround for proper handling
// of a message notifying that validation workflow has started. In that
// case we want to keep original polling interval.
// Ideally, validation workflow would send a message with
// different type rather than sending the same type on start and end
let pollTimeout;
if (payload.status === 'RUNNING') {
pollTimeout = 30000;
}
dispatch(
handleWorkflowMessage(payload.execution.id, undefined, pollTimeout)
);
break;
}