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
parent
36bf9c24b9
commit
8d6f6e306a
|
@ -150,3 +150,10 @@ export class KubernetesApplicationAutoScalerFormValue {
|
||||||
Object.assign(this, JSON.parse(JSON.stringify(_KubernetesApplicationAutoScalerFormValue)));
|
Object.assign(this, JSON.parse(JSON.stringify(_KubernetesApplicationAutoScalerFormValue)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function KubernetesApplicationFormValidationDuplicate() {
|
||||||
|
return {
|
||||||
|
refs: {},
|
||||||
|
hasDuplicates: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -944,17 +944,17 @@
|
||||||
|
|
||||||
<div class="col-sm-12 small text-muted" ng-if="ctrl.formValues.Placements.length > 0" style="margin-top: 10px;">
|
<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>
|
<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>
|
||||||
|
|
||||||
<div class="col-sm-12 form-inline" style="margin-top: 10px;">
|
<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 }">
|
<div class="col-sm-5 input-group" ng-class="{ striked: placement.NeedsDeletion }">
|
||||||
<select
|
<select
|
||||||
class="form-control"
|
class="form-control"
|
||||||
ng-model="placement.Label"
|
ng-model="placement.Label"
|
||||||
ng-options="label as (label.Key | kubernetesNodeLabelHumanReadbleText) for label in ctrl.nodesLabels"
|
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)"
|
ng-disabled="ctrl.isEditAndNotNewPlacement($index)"
|
||||||
>
|
>
|
||||||
</select>
|
</select>
|
||||||
|
@ -978,6 +978,15 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
<div ng-if="ctrl.showPlacementPolicySection()">
|
<div ng-if="ctrl.showPlacementPolicySection()">
|
||||||
|
|
|
@ -20,6 +20,7 @@ import {
|
||||||
KubernetesApplicationPersistedFolderFormValue,
|
KubernetesApplicationPersistedFolderFormValue,
|
||||||
KubernetesApplicationPublishedPortFormValue,
|
KubernetesApplicationPublishedPortFormValue,
|
||||||
KubernetesApplicationPlacementFormValue,
|
KubernetesApplicationPlacementFormValue,
|
||||||
|
KubernetesApplicationFormValidationDuplicate,
|
||||||
} from 'Kubernetes/models/application/formValues';
|
} from 'Kubernetes/models/application/formValues';
|
||||||
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
|
import KubernetesFormValidationHelper from 'Kubernetes/helpers/formValidationHelper';
|
||||||
import KubernetesApplicationConverter from 'Kubernetes/converters/application';
|
import KubernetesApplicationConverter from 'Kubernetes/converters/application';
|
||||||
|
@ -259,10 +260,12 @@ class KubernetesCreateApplicationController {
|
||||||
placement.Label = label;
|
placement.Label = label;
|
||||||
placement.Value = label.Values[0];
|
placement.Value = label.Values[0];
|
||||||
this.formValues.Placements.push(placement);
|
this.formValues.Placements.push(placement);
|
||||||
|
this.onChangePlacement();
|
||||||
}
|
}
|
||||||
|
|
||||||
restorePlacement(index) {
|
restorePlacement(index) {
|
||||||
this.formValues.Placements[index].NeedsDeletion = false;
|
this.formValues.Placements[index].NeedsDeletion = false;
|
||||||
|
this.onChangePlacement();
|
||||||
}
|
}
|
||||||
|
|
||||||
removePlacement(index) {
|
removePlacement(index) {
|
||||||
|
@ -271,10 +274,25 @@ class KubernetesCreateApplicationController {
|
||||||
} else {
|
} else {
|
||||||
this.formValues.Placements.splice(index, 1);
|
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.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 */
|
/* #endregion */
|
||||||
|
@ -816,40 +834,17 @@ class KubernetesCreateApplicationController {
|
||||||
availableSizeUnits: ['MB', 'GB', 'TB'],
|
availableSizeUnits: ['MB', 'GB', 'TB'],
|
||||||
alreadyExists: false,
|
alreadyExists: false,
|
||||||
duplicates: {
|
duplicates: {
|
||||||
environmentVariables: {
|
environmentVariables: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
refs: {},
|
persistedFolders: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
hasDuplicates: false,
|
configurationPaths: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
},
|
existingVolumes: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
persistedFolders: {
|
|
||||||
refs: {},
|
|
||||||
hasDuplicates: false,
|
|
||||||
},
|
|
||||||
configurationPaths: {
|
|
||||||
refs: {},
|
|
||||||
hasDuplicates: false,
|
|
||||||
},
|
|
||||||
existingVolumes: {
|
|
||||||
refs: {},
|
|
||||||
hasDuplicates: false,
|
|
||||||
},
|
|
||||||
publishedPorts: {
|
publishedPorts: {
|
||||||
containerPorts: {
|
containerPorts: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
refs: {},
|
nodePorts: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
hasDuplicates: false,
|
ingressRoutes: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
},
|
loadBalancerPorts: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
nodePorts: {
|
|
||||||
refs: {},
|
|
||||||
hasDuplicates: false,
|
|
||||||
},
|
|
||||||
ingressRoutes: {
|
|
||||||
refs: {},
|
|
||||||
hasDuplicates: false,
|
|
||||||
},
|
|
||||||
loadBalancerPorts: {
|
|
||||||
refs: {},
|
|
||||||
hasDuplicates: false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
placements: new KubernetesApplicationFormValidationDuplicate(),
|
||||||
},
|
},
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
params: {
|
params: {
|
||||||
|
|
Loading…
Reference in New Issue