mirror of
https://github.com/portainer/portainer.git
synced 2025-07-25 16:29:44 +02:00
* fix(services): replicas numbers display is now correct with constraints and down nodes * refactor(helpers): constraint helper has less complexity * feat(services): constraints on node/engine labels are now supported * refactor(helpers): ConstraintsHelper - remove regex patterns and improve code lisibility * refactor(helpers): rework matchesConstraint() for better code lisibility and lodash find() instead for IE compatibility
106 lines
No EOL
3.3 KiB
JavaScript
106 lines
No EOL
3.3 KiB
JavaScript
function ConstraintModel(op, key, value) {
|
|
this.op = op;
|
|
this.value = value;
|
|
this.key = key;
|
|
}
|
|
|
|
var patterns = {
|
|
id: {
|
|
nodeId: 'node.id',
|
|
nodeHostname: 'node.hostname',
|
|
nodeRole: 'node.role',
|
|
nodeLabels: 'node.labels.',
|
|
engineLabels: 'engine.labels.'
|
|
},
|
|
op: {
|
|
eq: '==',
|
|
neq: '!='
|
|
}
|
|
};
|
|
|
|
function matchesConstraint(value, constraint) {
|
|
if (!constraint ||
|
|
(constraint.op === patterns.op.eq && value === constraint.value) ||
|
|
(constraint.op === patterns.op.neq && value !== constraint.value)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
function matchesLabel(labels, constraint) {
|
|
if (!constraint) {
|
|
return true;
|
|
}
|
|
var found = _.find(labels, function (label) {
|
|
return label.key === constraint.key && label.value === constraint.value;
|
|
});
|
|
return found !== undefined;
|
|
}
|
|
|
|
function extractValue(constraint, op) {
|
|
return constraint.split(op).pop().trim();
|
|
}
|
|
|
|
function extractCustomLabelKey(constraint, op, baseLabelKey) {
|
|
return constraint.split(op).shift().trim().replace(baseLabelKey, '');
|
|
}
|
|
|
|
angular.module('portainer.docker')
|
|
.factory('ConstraintsHelper', [function ConstraintsHelperFactory() {
|
|
'use strict';
|
|
return {
|
|
transformConstraints: function (constraints) {
|
|
var transform = {};
|
|
for (var i = 0; i < constraints.length; i++) {
|
|
var constraint = constraints[i];
|
|
|
|
var op;
|
|
if (constraint.includes(patterns.op.eq)) {
|
|
op = patterns.op.eq;
|
|
} else if (constraint.includes(patterns.op.neq)) {
|
|
op = patterns.op.neq;
|
|
}
|
|
|
|
var value = extractValue(constraint, op);
|
|
var key = '';
|
|
switch (true) {
|
|
case constraint.includes(patterns.id.nodeId):
|
|
transform.nodeId = new ConstraintModel(op, key, value);
|
|
break;
|
|
case constraint.includes(patterns.id.nodeHostname):
|
|
transform.nodeHostname = new ConstraintModel(op, key, value);
|
|
break;
|
|
case constraint.includes(patterns.id.nodeRole):
|
|
transform.nodeRole = new ConstraintModel(op, key, value);
|
|
break;
|
|
case constraint.includes(patterns.id.nodeLabels):
|
|
key = extractCustomLabelKey(constraint, op, patterns.id.nodeLabels);
|
|
transform.nodeLabels = new ConstraintModel(op, key, value);
|
|
break;
|
|
case constraint.includes(patterns.id.engineLabels):
|
|
key = extractCustomLabelKey(constraint, op, patterns.id.engineLabels);
|
|
transform.engineLabels = new ConstraintModel(op, key, value);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return transform;
|
|
},
|
|
matchesServiceConstraints: function (service, node) {
|
|
if (service.Constraints === undefined || service.Constraints.length === 0) {
|
|
return true;
|
|
}
|
|
var constraints = this.transformConstraints(angular.copy(service.Constraints));
|
|
if (matchesConstraint(node.Id, constraints.nodeId) &&
|
|
matchesConstraint(node.Hostname, constraints.nodeHostname) &&
|
|
matchesConstraint(node.Role, constraints.nodeRole) &&
|
|
matchesLabel(node.Labels, constraints.nodeLabels) &&
|
|
matchesLabel(node.EngineLabels, constraints.engineLabels)
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
}]); |