205 lines
6.1 KiB
JavaScript
205 lines
6.1 KiB
JavaScript
/**
|
|
* Copyright 2017 Red Hat Inc.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
import { createSelector } from 'reselect';
|
|
|
|
import { getCurrentPlanName } from './plans';
|
|
import { getFilterByName } from './filters';
|
|
import MistralConstants from '../constants/MistralConstants';
|
|
|
|
const validations = state => state.validations.get('validations');
|
|
const executions = state => state.executions.get('executions');
|
|
const validationsToolbarFilter = state =>
|
|
getFilterByName(state, 'validationsToolbar');
|
|
|
|
/**
|
|
* Filter workflow executions only to validations and current plan
|
|
*/
|
|
export const getValidationExecutionsForCurrentPlan = createSelector(
|
|
[executions, getCurrentPlanName],
|
|
(executions, currentPlanName) => {
|
|
const mostRecentPlanUpdate = getMostRecentPlanUpdate(
|
|
executions,
|
|
currentPlanName
|
|
);
|
|
return executions.filter(
|
|
execution =>
|
|
execution.get('workflow_name') === MistralConstants.VALIDATIONS_RUN &&
|
|
execution.getIn(['input', 'plan']) === currentPlanName &&
|
|
execution.get('updated_at') > mostRecentPlanUpdate
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Adds map of validation results to each validation
|
|
*/
|
|
export const getValidationsWithResults = createSelector(
|
|
[validations, getValidationExecutionsForCurrentPlan],
|
|
(validations, results) =>
|
|
validations.map(validation => {
|
|
const validationResults = getValidationResults(validation.id, results);
|
|
return validation
|
|
.set('results', validationResults)
|
|
.set('status', getValidationStatus(validationResults));
|
|
})
|
|
);
|
|
|
|
/**
|
|
* Filter validations using the active Toolbar filters.
|
|
* Only include validations younger than the most recent update to a plan.
|
|
*/
|
|
export const getFilteredValidations = createSelector(
|
|
[getValidationsWithResults, validationsToolbarFilter],
|
|
(validations, validationsToolbarFilter) => {
|
|
const activeFilters = validationsToolbarFilter.get('activeFilters');
|
|
return activeFilters
|
|
.reduce(
|
|
(filteredValidations, filter) =>
|
|
filteredValidations.filter(validation => {
|
|
switch (filter.filterBy) {
|
|
case 'name':
|
|
return validation.name
|
|
.toLowerCase()
|
|
.includes(filter.filterString.toLowerCase());
|
|
case 'group': {
|
|
return validation.groups.reduce(
|
|
(result, group) =>
|
|
result
|
|
? result
|
|
: group
|
|
.toLowerCase()
|
|
.includes(filter.filterString.toLowerCase()),
|
|
false
|
|
);
|
|
}
|
|
default:
|
|
return false;
|
|
}
|
|
}),
|
|
validations
|
|
)
|
|
.sortBy(validation =>
|
|
validation.getIn(validationsToolbarFilter.get('sortBy').split('.'))
|
|
)
|
|
.update(
|
|
validations =>
|
|
validationsToolbarFilter.get('sortDir') === 'desc'
|
|
? validations.reverse()
|
|
: validations
|
|
);
|
|
}
|
|
);
|
|
|
|
export const getValidationStatusCounts = createSelector(
|
|
[getValidationsWithResults],
|
|
validations => validations.countBy(v => v.status).sortBy((v, k) => k)
|
|
);
|
|
|
|
/**
|
|
* Helper function to get the most recent time a plan has been updated or
|
|
* created.
|
|
*/
|
|
export const getMostRecentPlanUpdate = (executions, planName) =>
|
|
executions
|
|
.filter(
|
|
execution =>
|
|
[MistralConstants.PLAN_UPDATE, MistralConstants.PLAN_CREATE].includes(
|
|
execution.workflow_name
|
|
) && execution.getIn(['input', 'container']) === planName
|
|
)
|
|
.map(execution => execution.get('updated_at'))
|
|
.sort()
|
|
.last() || 0;
|
|
|
|
/**
|
|
* Helper function to get a validation results by validation name
|
|
*/
|
|
const getValidationResults = (validationId, results) =>
|
|
results.filter(
|
|
result => result.getIn(['input', 'validation_name']) === validationId
|
|
);
|
|
|
|
/**
|
|
* Helper function to determine validation status based on validation's results
|
|
*/
|
|
const getValidationStatus = validationResults => {
|
|
switch (true) {
|
|
case validationResults.isEmpty():
|
|
return 'new';
|
|
case validationResults.last().state === 'RUNNING':
|
|
return 'running';
|
|
case validationResults.last().output.get('status') === 'SUCCESS':
|
|
if (
|
|
validationResults
|
|
.last()
|
|
.output.get('stdout', '')
|
|
.includes('Warnings:')
|
|
) {
|
|
return 'warning';
|
|
}
|
|
return 'success';
|
|
case validationResults.last().output.get('status') === 'FAILED':
|
|
return 'failed';
|
|
case validationResults.last().state === 'PAUSED':
|
|
return 'paused';
|
|
default:
|
|
return 'error';
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Selects pre deployment validations
|
|
*/
|
|
export const getPreDeploymentValidationsWithResults = createSelector(
|
|
getValidationsWithResults,
|
|
validations => {
|
|
const preDeploymentValidationGroups = [
|
|
'pre-deployment',
|
|
'pre',
|
|
'pre-introspection'
|
|
];
|
|
return validations.filter(
|
|
validation =>
|
|
!validation.groups
|
|
.toSet()
|
|
.intersect(preDeploymentValidationGroups)
|
|
.isEmpty()
|
|
);
|
|
}
|
|
);
|
|
|
|
/**
|
|
* Provides aggregate counts of pre-deployment validations by their status
|
|
*/
|
|
export const getPreDeploymentValidationsStatusCounts = createSelector(
|
|
getPreDeploymentValidationsWithResults,
|
|
validations => validations.countBy(validation => validation.status)
|
|
);
|
|
|
|
/**
|
|
* Provides aggregate counts of pre-deployment validations by their status
|
|
*/
|
|
export const allPreDeploymentValidationsSuccessful = createSelector(
|
|
getPreDeploymentValidationsStatusCounts,
|
|
counts =>
|
|
counts
|
|
.keySeq()
|
|
.toSet()
|
|
.intersect(['new', 'running', 'failed', 'paused', 'error'])
|
|
.isEmpty()
|
|
);
|