Stacks and Resources data storing in app state
* Normalize Stacks * Update stack Record to contain more data * Store Stack Resource as Immutable Record * Extract Delployment status messages into constants Closes-Bug: 1626481 Change-Id: I771443272881733270f8bc49724ea357002f2e28
This commit is contained in:
parent
915d907760
commit
def7a4e205
|
@ -27,6 +27,9 @@ describe('StacksActions', () => {
|
|||
const serviceResponse = {
|
||||
stacks: [{ stack_name: 'overcloud', stack_status: 'CREATE_COMPLETE' }]
|
||||
};
|
||||
const normalizedStacks = {
|
||||
overcloud: { stack_name: 'overcloud', stack_status: 'CREATE_COMPLETE' }
|
||||
};
|
||||
|
||||
beforeEach(done => {
|
||||
spyOn(HeatApiService, 'getStacks').and.callFake(createResolvingPromise(serviceResponse));
|
||||
|
@ -46,7 +49,7 @@ describe('StacksActions', () => {
|
|||
});
|
||||
|
||||
it('dispatches fetchStacksSuccess', () => {
|
||||
expect(StacksActions.fetchStacksSuccess).toHaveBeenCalledWith(serviceResponse.stacks);
|
||||
expect(StacksActions.fetchStacksSuccess).toHaveBeenCalledWith(normalizedStacks);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -46,9 +46,9 @@ describe('stacksReducer state', () => {
|
|||
beforeEach(() => {
|
||||
state = stacksReducer(
|
||||
new StacksState({ isFetching: true }),
|
||||
StacksActions.fetchStacksSuccess([
|
||||
{ stack_name: 'overcloud', stack_status: 'CREATE_COMPLETE' }
|
||||
])
|
||||
StacksActions.fetchStacksSuccess({
|
||||
overcloud: { stack_name: 'overcloud', stack_status: 'CREATE_COMPLETE' }
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -63,8 +63,19 @@ describe('stacksReducer state', () => {
|
|||
it('sets stacks in state', () => {
|
||||
expect(state.stacks).toEqualImmutable(Map({
|
||||
overcloud: new Stack({
|
||||
creation_time: undefined,
|
||||
deletion_time: undefined,
|
||||
description: undefined,
|
||||
id: undefined,
|
||||
parent: undefined,
|
||||
resources: Map(),
|
||||
stack_name: 'overcloud',
|
||||
stack_status: 'CREATE_COMPLETE'
|
||||
stack_owner: undefined,
|
||||
stack_status: 'CREATE_COMPLETE',
|
||||
stack_status_reason: undefined,
|
||||
stack_user_project_id: undefined,
|
||||
tags: Map(),
|
||||
updated_time: undefined
|
||||
})
|
||||
}));
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@ import HeatApiErrorHandler from '../services/HeatApiErrorHandler';
|
|||
import HeatApiService from '../services/HeatApiService';
|
||||
import NotificationActions from '../actions/NotificationActions';
|
||||
import StacksConstants from '../constants/StacksConstants';
|
||||
import { stackResourceSchema } from '../normalizrSchemas/stacks';
|
||||
import { stackSchema, stackResourceSchema } from '../normalizrSchemas/stacks';
|
||||
|
||||
export default {
|
||||
fetchStacksPending() {
|
||||
|
@ -30,7 +30,8 @@ export default {
|
|||
return dispatch => {
|
||||
dispatch(this.fetchStacksPending());
|
||||
HeatApiService.getStacks().then(response => {
|
||||
dispatch(this.fetchStacksSuccess(response.stacks));
|
||||
const stacks = normalize(response.stacks, arrayOf(stackSchema)).entities.stacks || {};
|
||||
dispatch(this.fetchStacksSuccess(stacks));
|
||||
}).catch(error => {
|
||||
console.error('Error retrieving stacks StackActions.fetchStacks', error); //eslint-disable-line no-console
|
||||
let errorHandler = new HeatApiErrorHandler(error);
|
||||
|
@ -64,12 +65,12 @@ export default {
|
|||
};
|
||||
},
|
||||
|
||||
fetchResources(stackName, stackId) {
|
||||
fetchResources(stack) {
|
||||
return (dispatch) => {
|
||||
dispatch(this.fetchResourcesPending());
|
||||
HeatApiService.getResources(stackName, stackId).then((response) => {
|
||||
HeatApiService.getResources(stack.stack_name, stack.id).then((response) => {
|
||||
dispatch(this.fetchResourcesSuccess(
|
||||
stackName,
|
||||
stack.stack_name,
|
||||
normalize(response.resources, arrayOf(stackResourceSchema)).entities.stackResources));
|
||||
}).catch((error) => {
|
||||
console.error('Error retrieving resources StackActions.fetchResources', error); //eslint-disable-line no-console
|
||||
|
|
|
@ -153,9 +153,7 @@ function mapDispatchToProps(dispatch) {
|
|||
},
|
||||
fetchNodes: () => dispatch(NodesActions.fetchNodes()),
|
||||
fetchRoles: () => dispatch(RolesActions.fetchRoles()),
|
||||
fetchResources: (name, id) => {
|
||||
dispatch(StacksActions.fetchResources(name, id));
|
||||
},
|
||||
fetchResources: (stack) => dispatch(StacksActions.fetchResources(stack)),
|
||||
fetchStacks: () => dispatch(StacksActions.fetchStacks()),
|
||||
notify: notification => dispatch(NotificationActions.notify(notification)),
|
||||
runValidationStage: (uuid) => {
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import React from 'react';
|
||||
|
||||
const statusMessages = {
|
||||
CREATE_IN_PROGRESS: 'Deployment in progress.',
|
||||
CREATE_SUCCESS: 'Deployment succeeded.',
|
||||
CREATE_FAILED: 'The deployment failed.',
|
||||
DELETE_IN_PROGRESS: 'Deletion in progress.',
|
||||
UPDATE_IN_PROGRESS: 'Update in progress.',
|
||||
UPDATE_FAILED: 'The update failed.',
|
||||
UPDATE_SUCCESS: 'The update succeeded.'
|
||||
};
|
||||
import { deploymentStatusMessages as statusMessages } from '../../constants/StacksConstants';
|
||||
|
||||
export default class DeploymentStatus extends React.Component {
|
||||
|
||||
|
@ -25,7 +17,7 @@ export default class DeploymentStatus extends React.Component {
|
|||
componentWillMount() {
|
||||
let intervalId = setInterval(() => {
|
||||
this.props.fetchStacks();
|
||||
this.props.fetchResources(this.props.stack.stack_name, this.props.stack.id);
|
||||
this.props.fetchResources(this.props.stack);
|
||||
}, 5000);
|
||||
this.setState({ intervalId: intervalId });
|
||||
}
|
||||
|
@ -78,7 +70,9 @@ export default class DeploymentStatus extends React.Component {
|
|||
return (
|
||||
<div className={statusClass}>
|
||||
<span className={iconClass}></span>
|
||||
{msg}
|
||||
<strong>{msg}</strong>
|
||||
<br/>
|
||||
{stack.stack_status_reason}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,3 +8,14 @@ export default keyMirror({
|
|||
FETCH_STACKS_SUCCESS: null,
|
||||
FETCH_STACKS_FAILED: null
|
||||
});
|
||||
|
||||
export const deploymentStatusMessages = {
|
||||
CREATE_IN_PROGRESS: 'Deployment in progress',
|
||||
CREATE_SUCCESS: 'Deployment succeeded',
|
||||
CREATE_FAILED: 'Deployment failed',
|
||||
DELETE_IN_PROGRESS: 'Deletion in progress',
|
||||
DELETE_FAILED: 'Deployment deletion failed',
|
||||
UPDATE_IN_PROGRESS: 'Update in progress',
|
||||
UPDATE_FAILED: 'Update failed',
|
||||
UPDATE_SUCCESS: 'Update succeeded'
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Map, Record } from 'immutable';
|
||||
import { List, Map, Record } from 'immutable';
|
||||
|
||||
export const StacksState = Record({
|
||||
isLoaded: false,
|
||||
|
@ -7,8 +7,29 @@ export const StacksState = Record({
|
|||
});
|
||||
|
||||
export const Stack = Record({
|
||||
id: '',
|
||||
creation_time: undefined,
|
||||
deletion_time: undefined,
|
||||
description: undefined,
|
||||
id: undefined,
|
||||
parent: undefined,
|
||||
resources: Map(),
|
||||
stack_name: '',
|
||||
stack_status: ''
|
||||
stack_name: undefined,
|
||||
stack_owner: undefined,
|
||||
stack_status: undefined,
|
||||
stack_status_reason: undefined,
|
||||
stack_user_project_id: undefined,
|
||||
tags: Map(),
|
||||
updated_time: undefined
|
||||
});
|
||||
|
||||
export const StackResource = Record({
|
||||
creation_time: undefined,
|
||||
logical_resource_id: undefined,
|
||||
physical_resource_id: undefined,
|
||||
required_by: List(),
|
||||
resource_name: undefined,
|
||||
resource_status: undefined,
|
||||
resource_status_reason: undefined,
|
||||
resource_type: undefined,
|
||||
updated_time: undefined
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { Schema } from 'normalizr';
|
||||
|
||||
export const stackSchema = new Schema('stacks', { idAttribute: 'stack_name' });
|
||||
export const stackResourceSchema = new Schema('stackResources', { idAttribute: 'resource_name' });
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { fromJS, Map } from 'immutable';
|
||||
|
||||
import { Stack, StacksState } from '../immutableRecords/stacks';
|
||||
import { Stack, StackResource, StacksState } from '../immutableRecords/stacks';
|
||||
import StacksConstants from '../constants/StacksConstants';
|
||||
|
||||
const initialState = new StacksState;
|
||||
|
@ -15,10 +15,7 @@ export default function stacksReducer(state = initialState, action) {
|
|||
return state
|
||||
.set('isLoaded', true)
|
||||
.set('isFetching', false)
|
||||
.set('stacks', Map(action.payload.reduce((obj, val) => {
|
||||
obj[val.stack_name] = Stack(val);
|
||||
return obj;
|
||||
}, {})));
|
||||
.set('stacks', fromJS(action.payload).map(stack => new Stack(stack)));
|
||||
|
||||
case StacksConstants.FETCH_STACKS_FAILED:
|
||||
return state
|
||||
|
@ -28,8 +25,10 @@ export default function stacksReducer(state = initialState, action) {
|
|||
|
||||
case StacksConstants.FETCH_RESOURCES_SUCCESS:
|
||||
if (state.stacks.get(action.payload.stackName)) {
|
||||
return state.setIn(['stacks', action.payload.stackName, 'resources'],
|
||||
fromJS(action.payload.resources));
|
||||
return state.setIn(
|
||||
['stacks', action.payload.stackName, 'resources'],
|
||||
fromJS(action.payload.resources).map(resource => new StackResource(resource))
|
||||
);
|
||||
}
|
||||
return state;
|
||||
|
||||
|
|
|
@ -21,6 +21,6 @@ export const getCurrentStack = createSelector(
|
|||
export const getCurrentStackDeploymentProgress = createSelector(
|
||||
[stacksSelector, currentPlanNameSelector],
|
||||
(stacks, currentPlanName) => {
|
||||
return stacks.get(currentPlanName, Stack({})).stack_status === 'CREATE_IN_PROGRESS';
|
||||
return stacks.get(currentPlanName, new Stack()).stack_status === 'CREATE_IN_PROGRESS';
|
||||
}
|
||||
);
|
||||
|
|
|
@ -31,7 +31,6 @@ class HeatApiService {
|
|||
getResources(stackName, stackId) {
|
||||
return this.defaultRequest(`/stacks/${stackName}/${stackId}/resources`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default new HeatApiService();
|
||||
|
|
Loading…
Reference in New Issue