44from urllib .parse import urlparse , parse_qs
55import string
66import random
7+ import re
78import time
89
910from . import KubeHTTPClient , KubeHTTPException
@@ -275,8 +276,9 @@ def upsert_pods(controller, url):
275276
276277def filter_data (filters , path ):
277278 data = []
278- for item in cache .get (path , []):
279- item = cache .get (item )
279+ rows = cache .get (path , [])
280+ for row in rows :
281+ item = cache .get (row )
280282 if not item :
281283 # item is broken
282284 continue
@@ -288,7 +290,25 @@ def filter_data(filters, path):
288290 # Do extra filtering based on labelSelector
289291 add = True
290292 for label , value in filters ['labels' ].items ():
291- if (
293+ # set based filter
294+ if '__' in label :
295+ label , matcher = label .split ('__' )
296+ if matcher == 'in' :
297+ if (
298+ label not in item ['metadata' ]['labels' ] or
299+ item ['metadata' ]['labels' ][label ] not in value
300+ ):
301+ add = False
302+ continue
303+ elif matcher == 'notin' :
304+ if (
305+ label not in item ['metadata' ]['labels' ] or
306+ item ['metadata' ]['labels' ][label ] in value
307+ ):
308+ add = False
309+ continue
310+
311+ elif (
292312 label not in item ['metadata' ]['labels' ] or
293313 item ['metadata' ]['labels' ][label ] != value
294314 ):
@@ -325,12 +345,29 @@ def fetch_all(request, context):
325345def prepare_query_filters (query ):
326346 filters = {'labels' : {}, 'fields' : {}}
327347 if query :
348+ # set based regex - does not support only field
349+ labelRegex = re .compile ('^(?P<label>.*) (?P<matcher>notin|in)\s?\((?P<values>.*)\)$' )
350+
328351 queries = parse_qs (query )
329352 if 'labelSelector' in queries :
330353 for items in queries ['labelSelector' ]:
331- for item in items .split (',' ):
332- key , value = item .split ('=' )
333- filters ['labels' ][key ] = value
354+ # split on , but not inside ()
355+ r = re .compile (r'(?:[^,(]|\([^)]*\))+' )
356+ for item in r .findall (items ):
357+ if '=' in item :
358+ # equal based requirement
359+ key , value = item .split ('=' )
360+ filters ['labels' ][key ] = value
361+ else :
362+ # set based requirement
363+ matches = labelRegex .match (item )
364+ if matches is None :
365+ continue
366+
367+ # split and strip spaces
368+ values = [x .strip () for x in matches .group ('values' ).split (',' )]
369+ key = matches .group ('label' ) + '__' + matches .group ('matcher' )
370+ filters ['labels' ][key ] = values
334371
335372 if 'fieldSelector' in queries :
336373 for items in queries ['fieldSelector' ]:
0 commit comments