feat(k8s/application): add placement constraints validation (#4214)

* feat(k8s/application): add constraints validation

* feat(k8s/application): minor UI update

Co-authored-by: Anthony Lapenna <lapenna.anthony@gmail.com>
pull/4217/head
xAt0mZ 2020-08-16 00:11:56 +02:00 committed by GitHub
parent 36bf9c24b9
commit 8d6f6e306a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 36 deletions

View File

@ -150,3 +150,10 @@ export class KubernetesApplicationAutoScalerFormValue {
Object.assign(this, JSON.parse(JSON.stringify(_KubernetesApplicationAutoScalerFormValue)));
}
}
export function KubernetesApplicationFormValidationDuplicate() {
return {
refs: {},
hasDuplicates: false,
};
}

View File

@ -944,17 +944,17 @@
<div class="col-sm-12 small text-muted" ng-if="ctrl.formValues.Placements.length > 0" style="margin-top: 10px;">
<i class="fa fa-info-circle blue-icon" aria-hidden="true" style="margin-right: 2px;"></i>
Deploy this application on nodes that respect <b>ALL</b> of the following placement rules.
Deploy this application on nodes that respect <b>ALL</b> of the following placement rules. Placement rules are based on node labels.
</div>
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
<div ng-repeat="placement in ctrl.formValues.Placements" style="margin-top: 2px;">
<div ng-repeat-start="placement in ctrl.formValues.Placements" style="margin-top: 2px;">
<div class="col-sm-5 input-group" ng-class="{ striked: placement.NeedsDeletion }">
<select
class="form-control"
ng-model="placement.Label"
ng-options="label as (label.Key | kubernetesNodeLabelHumanReadbleText) for label in ctrl.nodesLabels"
ng-change="ctrl.onPlacementLabelChange($index)"
ng-change="ctrl.onChangePlacementLabel($index)"
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
>
</select>
@ -978,6 +978,15 @@
</button>
</div>
</div>
<div ng-repeat-end ng-show="ctrl.state.duplicates.placements.refs[$index] !== undefined">
<div class="col-sm-5 input-group">
<div class="small text-warning" style="margin-top: 5px;" ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
<p ng-if="ctrl.state.duplicates.placements.refs[$index] !== undefined">
<i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This label is already defined.
</p>
</div>
</div>
</div>
</div>
</div>
<div ng-if="ctrl.showPlacementPolicySection()">

View File

@ -20,6 +20,7 @@ import {
KubernetesApplicationPersistedFolderFormValue,
KubernetesApplicationPublishedPortFormValue,
KubernetesApplicationPlacementFormValue,
KubernetesApplicationFormValidationDuplicate,
} from 'Kubernetes/models/application/formValues';
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
import KubernetesApplicationConverter from 'Kubernetes/converters/application';
@ -259,10 +260,12 @@ class KubernetesCreateApplicationController {
placement.Label = label;
placement.Value = label.Values[0];
this.formValues.Placements.push(placement);
this.onChangePlacement();
}
restorePlacement(index) {
this.formValues.Placements[index].NeedsDeletion = false;
this.onChangePlacement();
}
removePlacement(index) {
@ -271,10 +274,25 @@ class KubernetesCreateApplicationController {
} else {
this.formValues.Placements.splice(index, 1);
}
this.onChangePlacement();
}
onPlacementLabelChange(index) {
// call all validation functions when a placement is added/removed/restored
onChangePlacement() {
this.onChangePlacementLabelValidate();
}
onChangePlacementLabel(index) {
this.formValues.Placements[index].Value = this.formValues.Placements[index].Label.Values[0];
this.onChangePlacementLabelValidate();
}
onChangePlacementLabelValidate() {
const state = this.state.duplicates.placements;
const source = _.map(this.formValues.Placements, (p) => (p.NeedsDeletion ? undefined : p.Label.Key));
const duplicates = KubernetesFormValidationHelper.getDuplicates(source);
state.refs = duplicates;
state.hasDuplicates = Object.keys(duplicates).length > 0;
}
/* #endregion */
@ -816,40 +834,17 @@ class KubernetesCreateApplicationController {
availableSizeUnits: ['MB', 'GB', 'TB'],
alreadyExists: false,
duplicates: {
environmentVariables: {
refs: {},
hasDuplicates: false,
},
persistedFolders: {
refs: {},
hasDuplicates: false,
},
configurationPaths: {
refs: {},
hasDuplicates: false,
},
existingVolumes: {
refs: {},
hasDuplicates: false,
},
environmentVariables: new KubernetesApplicationFormValidationDuplicate(),
persistedFolders: new KubernetesApplicationFormValidationDuplicate(),
configurationPaths: new KubernetesApplicationFormValidationDuplicate(),
existingVolumes: new KubernetesApplicationFormValidationDuplicate(),
publishedPorts: {
containerPorts: {
refs: {},
hasDuplicates: false,
},
nodePorts: {
refs: {},
hasDuplicates: false,
},
ingressRoutes: {
refs: {},
hasDuplicates: false,
},
loadBalancerPorts: {
refs: {},
hasDuplicates: false,
},
containerPorts: new KubernetesApplicationFormValidationDuplicate(),
nodePorts: new KubernetesApplicationFormValidationDuplicate(),
ingressRoutes: new KubernetesApplicationFormValidationDuplicate(),
loadBalancerPorts: new KubernetesApplicationFormValidationDuplicate(),
},
placements: new KubernetesApplicationFormValidationDuplicate(),
},
isEdit: false,
params: {