Fix stopping of HealthCheck tests
Closes-Bug: #1595856 Change-Id: I983b09322a85ed3f968705f6d0fd43e3f4dd9404
This commit is contained in:
parent
7d287a8a02
commit
f7b5774832
|
@ -28,7 +28,20 @@ var HealthCheckTab = React.createClass({
|
|||
modelOrCollection: (props) => props.cluster.get('tasks'),
|
||||
renderOn: 'update change:status'
|
||||
}),
|
||||
backboneMixin('cluster', 'change:status')
|
||||
backboneMixin('cluster', 'change:status'),
|
||||
backboneMixin({
|
||||
modelOrCollection: ({ostf}) => ostf.tests,
|
||||
renderOn: 'update change'
|
||||
}),
|
||||
backboneMixin({
|
||||
modelOrCollection: ({ostf}) => ostf.testsets,
|
||||
renderOn: 'update change:checked'
|
||||
}),
|
||||
backboneMixin({
|
||||
modelOrCollection: ({ostf}) => ostf.testruns,
|
||||
renderOn: 'update change:status'
|
||||
}),
|
||||
pollingMixin(3)
|
||||
],
|
||||
statics: {
|
||||
breadcrumbsPath() {
|
||||
|
@ -36,28 +49,33 @@ var HealthCheckTab = React.createClass({
|
|||
[i18n('cluster_page.tabs.healthcheck'), null, {active: true}]
|
||||
];
|
||||
},
|
||||
fetchData(options) {
|
||||
if (!options.cluster.get('ostf')) {
|
||||
var ostf = {};
|
||||
var clusterId = options.cluster.id;
|
||||
ostf.testsets = new models.TestSets();
|
||||
ostf.testsets.url = _.result(ostf.testsets, 'url') + '/' + clusterId;
|
||||
ostf.tests = new models.Tests();
|
||||
ostf.tests.url = _.result(ostf.tests, 'url') + '/' + clusterId;
|
||||
ostf.testruns = new models.TestRuns();
|
||||
ostf.testruns.url = _.result(ostf.testruns, 'url') + '/last/' + clusterId;
|
||||
return Promise.all([ostf.testsets.fetch(), ostf.tests.fetch(), ostf.testruns.fetch()])
|
||||
fetchData({cluster}) {
|
||||
if (!cluster.get('ostf')) {
|
||||
var testsets = new models.TestSets();
|
||||
testsets.url = _.result(testsets, 'url') + '/' + cluster.id;
|
||||
var tests = new models.Tests();
|
||||
tests.url = _.result(tests, 'url') + '/' + cluster.id;
|
||||
var testruns = new models.TestRuns();
|
||||
testruns.url = _.result(testruns, 'url') + '/last/' + cluster.id;
|
||||
|
||||
return Promise.all([testsets.fetch(), tests.fetch(), testruns.fetch()])
|
||||
.then(() => {
|
||||
options.cluster.set({ostf: ostf});
|
||||
return {};
|
||||
cluster.set('ostf', {testsets, tests, testruns});
|
||||
return {ostf: cluster.get('ostf')};
|
||||
})
|
||||
.catch(() => true);
|
||||
}
|
||||
return Promise.resolve();
|
||||
return Promise.resolve().then(() => ({ostf: cluster.get('ostf')}));
|
||||
}
|
||||
},
|
||||
shouldDataBeFetched() {
|
||||
return this.props.ostf.testruns.some({status: 'running'});
|
||||
},
|
||||
fetchData() {
|
||||
return this.props.ostf.testruns.fetch();
|
||||
},
|
||||
render() {
|
||||
var ostf = this.props.cluster.get('ostf');
|
||||
var {cluster, ostf} = this.props;
|
||||
return (
|
||||
<div className='row'>
|
||||
<div className='title'>
|
||||
|
@ -67,10 +85,9 @@ var HealthCheckTab = React.createClass({
|
|||
{ostf ?
|
||||
<HealthcheckTabContent
|
||||
ref='content'
|
||||
testsets={ostf.testsets}
|
||||
tests={ostf.tests}
|
||||
testruns={ostf.testruns}
|
||||
cluster={this.props.cluster}
|
||||
{...ostf}
|
||||
cluster={cluster}
|
||||
startPolling={this.startPolling}
|
||||
/>
|
||||
:
|
||||
<div className='alert alert-danger'>
|
||||
|
@ -84,37 +101,27 @@ var HealthCheckTab = React.createClass({
|
|||
});
|
||||
|
||||
var HealthcheckTabContent = React.createClass({
|
||||
mixins: [
|
||||
backboneMixin('tests', 'update change'),
|
||||
backboneMixin('testsets', 'update change:checked'),
|
||||
backboneMixin('testruns', 'update change'),
|
||||
pollingMixin(3)
|
||||
],
|
||||
shouldDataBeFetched() {
|
||||
return this.props.testruns.some({status: 'running'});
|
||||
},
|
||||
fetchData() {
|
||||
return this.props.testruns.fetch();
|
||||
},
|
||||
componentWillReceiveProps(newProps) {
|
||||
if (this.state.stoppingTestsInProgress &&
|
||||
!newProps.testruns.some((testrun) => {
|
||||
return _.includes(['running', 'stopped'], testrun.get('status'));
|
||||
})
|
||||
componentWillReceiveProps({testruns}) {
|
||||
if (
|
||||
this.state.stoppingTestsInProgress &&
|
||||
!testruns.some((testrun) => _.includes(['running', 'stopped'], testrun.get('status')))
|
||||
) {
|
||||
this.setState({stoppingTestsInProgress: false});
|
||||
}
|
||||
if (this.state.runningTestsInProgress && !testruns.some({status: 'running'})) {
|
||||
this.setState({runningTestsInProgress: false});
|
||||
}
|
||||
},
|
||||
getInitialState() {
|
||||
return {
|
||||
actionInProgress: false,
|
||||
credentialsVisible: null,
|
||||
credentials: _.transform(
|
||||
this.props.cluster.get('settings').get('access'),
|
||||
(result, value, key) => {
|
||||
result[key] = value.value;
|
||||
(result, {value}, key) => {
|
||||
result[key] = value;
|
||||
}
|
||||
),
|
||||
runningTestsInProgress: false,
|
||||
stoppingTestsInProgress: false
|
||||
};
|
||||
},
|
||||
|
@ -122,25 +129,24 @@ var HealthcheckTabContent = React.createClass({
|
|||
return !this.props.cluster.isHealthCheckAvailable() ||
|
||||
!!this.props.cluster.task({group: 'deployment', active: true});
|
||||
},
|
||||
getNumberOfCheckedTests() {
|
||||
return this.props.tests.filter({checked: true}).length;
|
||||
},
|
||||
toggleCredentials() {
|
||||
this.setState({credentialsVisible: !this.state.credentialsVisible});
|
||||
},
|
||||
handleSelectAllClick(name, value) {
|
||||
this.props.tests.invokeMap('set', {checked: value});
|
||||
handleSelectAllClick(name, checked) {
|
||||
this.props.tests.invokeMap('set', {checked});
|
||||
},
|
||||
handleInputChange(name, value) {
|
||||
var credentials = this.state.credentials;
|
||||
var {credentials} = this.state;
|
||||
credentials[name] = value;
|
||||
this.setState({credentials: credentials});
|
||||
this.setState({credentials});
|
||||
},
|
||||
runTests() {
|
||||
this.setState({runningTestsInProgress: true});
|
||||
|
||||
var testruns = new models.TestRuns();
|
||||
var oldTestruns = new models.TestRuns();
|
||||
var testsetIds = this.props.testsets.map('id');
|
||||
this.setState({actionInProgress: true});
|
||||
|
||||
_.each(testsetIds, (testsetId) => {
|
||||
var testsToRun = _.map(this.props.tests.filter({
|
||||
testset: testsetId,
|
||||
|
@ -157,7 +163,7 @@ var HealthcheckTabContent = React.createClass({
|
|||
return obj;
|
||||
};
|
||||
|
||||
if (this.props.testruns.filter({testset: testsetId}).length) {
|
||||
if (this.props.testruns.some({testset: testsetId})) {
|
||||
_.each(this.props.testruns.filter({testset: testsetId}), (testrun) => {
|
||||
_.extend(testrunConfig, addCredentials({
|
||||
id: testrun.id,
|
||||
|
@ -187,96 +193,81 @@ var HealthcheckTabContent = React.createClass({
|
|||
}
|
||||
Promise.all(requests)
|
||||
.then(
|
||||
() => {
|
||||
this.startPolling(true);
|
||||
this.setState({actionInProgress: false});
|
||||
},
|
||||
(response) => {
|
||||
this.setState({actionInProgress: false});
|
||||
utils.showErrorDialog({response: response});
|
||||
}
|
||||
() => this.props.startPolling(true),
|
||||
(response) => utils.showErrorDialog({response})
|
||||
);
|
||||
},
|
||||
getActiveTestRuns() {
|
||||
return this.props.testruns.filter({status: 'running'});
|
||||
},
|
||||
stopTests() {
|
||||
var testruns = new models.TestRuns(this.getActiveTestRuns());
|
||||
var testruns = new models.TestRuns(
|
||||
this.props.testruns.filter({status: 'running'})
|
||||
);
|
||||
if (testruns.length) {
|
||||
this.setState({
|
||||
actionInProgress: true,
|
||||
runningTestsInProgress: false,
|
||||
stoppingTestsInProgress: true
|
||||
});
|
||||
testruns.invokeMap('set', {status: 'stopped'});
|
||||
testruns.toJSON = function() {
|
||||
return this.map((testrun) =>
|
||||
_.pick(testrun.attributes, 'id', 'status')
|
||||
);
|
||||
return this.map((testrun) => _.pick(testrun.attributes, 'id', 'status'));
|
||||
};
|
||||
Backbone.sync('update', testruns).then(() => {
|
||||
this.setState({actionInProgress: false});
|
||||
this.startPolling(true);
|
||||
});
|
||||
Backbone.sync('update', testruns)
|
||||
.then(() => this.props.startPolling(true));
|
||||
}
|
||||
},
|
||||
render() {
|
||||
var disabledState = this.isLocked();
|
||||
// due to immediate response from server after stopping OSTF tests
|
||||
// returns 'stopped' state for testruns and the next polled
|
||||
// responses return 'running' state for testruns up to the
|
||||
// moment the tests are actually stopped, - added check for 'stopped' and
|
||||
// 'running' testruns state
|
||||
var {tests, testruns, testsets, cluster} = this.props;
|
||||
var {runningTestsInProgress, stoppingTestsInProgress, credentials} = this.state;
|
||||
var actionInProgress = runningTestsInProgress || stoppingTestsInProgress;
|
||||
var actionsAvailable = !this.isLocked();
|
||||
var ns = 'cluster_page.healthcheck_tab.';
|
||||
var hasRunningTests = testruns.some({status: 'running'});
|
||||
var hasStoppingTests = testruns.some({status: 'stopped'});
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!disabledState &&
|
||||
{actionsAvailable &&
|
||||
<div className='healthcheck-controls row well well-sm'>
|
||||
<div className='pull-left'>
|
||||
<Input
|
||||
type='checkbox'
|
||||
name='selectAll'
|
||||
onChange={this.handleSelectAllClick}
|
||||
checked={this.getNumberOfCheckedTests() === tests.length}
|
||||
disabled={hasRunningTests}
|
||||
checked={tests.every({checked: true})}
|
||||
disabled={actionInProgress}
|
||||
label={i18n('common.select_all')}
|
||||
wrapperClassName='select-all'
|
||||
/>
|
||||
</div>
|
||||
{(hasRunningTests || hasStoppingTests) ?
|
||||
(<ProgressButton
|
||||
{testruns.some((testrun) => _.includes(['running', 'stopped'], testrun.get('status'))) ?
|
||||
<ProgressButton
|
||||
className='btn btn-danger stop-tests-btn pull-right'
|
||||
disabled={this.state.actionInProgress || this.state.stoppingTestsInProgress}
|
||||
disabled={stoppingTestsInProgress}
|
||||
onClick={this.stopTests}
|
||||
progress={this.state.stoppingTestsInProgress}
|
||||
progress={stoppingTestsInProgress}
|
||||
>
|
||||
{i18n(ns + 'stop_tests_button')}
|
||||
</ProgressButton>)
|
||||
</ProgressButton>
|
||||
:
|
||||
(<ProgressButton
|
||||
<ProgressButton
|
||||
className='btn btn-success run-tests-btn pull-right'
|
||||
disabled={!this.getNumberOfCheckedTests() || this.state.actionInProgress}
|
||||
disabled={!tests.some({checked: true}) || runningTestsInProgress}
|
||||
onClick={this.runTests}
|
||||
progress={this.state.actionInProgress}
|
||||
progress={runningTestsInProgress}
|
||||
>
|
||||
{i18n(ns + 'run_tests_button')}
|
||||
</ProgressButton>)
|
||||
</ProgressButton>
|
||||
}
|
||||
<button
|
||||
className='btn btn-default toggle-credentials pull-right'
|
||||
data-toggle='collapse'
|
||||
data-target='.credentials'
|
||||
onClick={this.toggleCredentials}
|
||||
>
|
||||
>
|
||||
{i18n(ns + 'provide_credentials')}
|
||||
</button>
|
||||
|
||||
<HealthcheckCredentials
|
||||
credentials={this.state.credentials}
|
||||
credentials={credentials}
|
||||
onInputChange={this.handleInputChange}
|
||||
disabled={hasRunningTests}
|
||||
disabled={actionInProgress}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
@ -285,16 +276,19 @@ var HealthcheckTabContent = React.createClass({
|
|||
<div className='alert alert-warning'>{i18n(ns + 'deploy_alert')}</div>
|
||||
}
|
||||
<div key='testsets'>
|
||||
{testsets.map((testset) => {
|
||||
return <TestSet
|
||||
{testsets.map(
|
||||
(testset) => <TestSet
|
||||
key={testset.id}
|
||||
testset={testset}
|
||||
testrun={testruns.find({testset: testset.id}) ||
|
||||
new models.TestRun({testset: testset.id})}
|
||||
tests={new models.BaseCollection(tests.filter({testset: testset.id}))}
|
||||
disabled={disabledState || hasRunningTests}
|
||||
/>;
|
||||
})}
|
||||
testrun={
|
||||
testruns.find({testset: testset.id}) || new models.TestRun({testset: testset.id})
|
||||
}
|
||||
tests={
|
||||
new models.BaseCollection(tests.filter({testset: testset.id}))
|
||||
}
|
||||
disabled={!actionsAvailable || actionInProgress}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue