Skip to content

Commit 54cc2db

Browse files
authored
Merge pull request #28 from jwforres/complex-covers-check
Add support for complex label selectors in the covers method
2 parents ae9a396 + 701fb52 commit 54cc2db

File tree

2 files changed

+44
-9
lines changed

2 files changed

+44
-9
lines changed

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"dependencies": {
2929
"angular": "~1.3.8",
3030
"selectize": "~0.12.1",
31-
"fontawesome": "~4.3.0"
31+
"fontawesome": "~4.3.0",
32+
"lodash": "~3.10.1"
3233
},
3334
"devDependencies": {
3435
"patternfly": "3.5.1"

labelSelector.js

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ LabelSelector.prototype.hasConjunct = function(conjunct) {
151151
return this._conjuncts[this._getIdForConjunct(conjunct)] ? true : false;
152152
};
153153

154+
LabelSelector.prototype.findConjunctsMatching = function(operator, key) {
155+
return _.pick(this._conjuncts, _.matches({operator: operator, key: key}));
156+
};
157+
154158
// Test whether this label selector covers the given selector
155159
LabelSelector.prototype.covers = function(selector) {
156160
if (this.isEmpty()) {
@@ -159,15 +163,45 @@ LabelSelector.prototype.covers = function(selector) {
159163
return false;
160164
}
161165

162-
// TODO - currently k8s only returns key: value
163-
// which represents 'key in (value)' So we only handle
164-
// the IN operator with single values for now
165-
for (var id in this._conjuncts) {
166-
if (!selector.hasConjunct(this._conjuncts[id])) {
167-
return false;
166+
return _.every(this._conjuncts, function(conjunct) {
167+
// Return true immediately if we find an exact match for operator/key/values
168+
if (selector.hasConjunct(conjunct)) {
169+
return true;
168170
}
169-
}
170-
return true;
171+
172+
// If we can't find a conjunct that matches exactly, do a more detailed check
173+
switch(conjunct.operator) {
174+
case "exists":
175+
// If an Exists conjunct existed for the same key in selector it
176+
// would have passed the exact match, just need to check if an In
177+
// conjunct exists for the same key
178+
return !_.isEmpty(selector.findConjunctsMatching("in", conjunct.key));
179+
case "does not exist":
180+
// A DoesNotExist can only cover a DoesNotExist operator, if we got here
181+
// then we didn't have a DNE with the same key so we know we can't cover
182+
return false;
183+
case "in":
184+
// In (A,B,C) covers In (A,B) AND In (B,C)
185+
var inConjuncts = selector.findConjunctsMatching("in", conjunct.key);
186+
if (_.isEmpty(inConjuncts)) {
187+
return false;
188+
}
189+
return _.every(inConjuncts, function(inConjunct) {
190+
return inConjunct.values.length === _.intersection(inConjunct.values, conjunct.values).length;
191+
});
192+
case "not in":
193+
// NotIn (A,B) covers NotIn (A,B,C) AND NotIn (A,B,D)
194+
var notInConjuncts = selector.findConjunctsMatching("not in", conjunct.key);
195+
if (_.isEmpty(notInConjuncts)) {
196+
return false;
197+
}
198+
return _.every(notInConjuncts, function(notInConjunct) {
199+
return conjunct.values.length === _.intersection(notInConjunct.values, conjunct.values).length;
200+
});
201+
}
202+
203+
return true;
204+
});
171205
};
172206

173207
// Exports the labelSelector as a string in the API format, exports as matchExpressions

0 commit comments

Comments
 (0)