Merge "Extract allow/disallow filter into util function"

This commit is contained in:
Zuul 2020-02-11 09:21:48 +00:00 committed by Gerrit Code Review
commit 9ce06b4a73
3 changed files with 62 additions and 35 deletions

View File

@ -22,7 +22,6 @@ import io
import re
import subprocess
import re2
import voluptuous as vs
from zuul import model
@ -32,6 +31,7 @@ import zuul.manager.independent
import zuul.manager.supercedent
from zuul.lib import encryption
from zuul.lib.keystorage import KeyStorage
from zuul.lib.re2util import filter_allowed_disallowed
# Several forms accept either a single item or a list, this makes
@ -509,24 +509,17 @@ class NodeSetParser(object):
group_names = set()
allowed_labels = self.pcontext.tenant.allowed_labels
disallowed_labels = self.pcontext.tenant.disallowed_labels
requested_labels = [n['label'] for n in as_list(conf['nodes'])]
filtered_labels = filter_allowed_disallowed(
requested_labels, allowed_labels, disallowed_labels)
rejected_labels = set(requested_labels) - set(filtered_labels)
for name in rejected_labels:
raise LabelForbiddenError(
label=name,
allowed_labels=allowed_labels,
disallowed_labels=disallowed_labels)
for conf_node in as_list(conf['nodes']):
allowed = True
if allowed_labels:
allowed = False
for pattern in allowed_labels:
if re2.match(pattern, conf_node['label']):
allowed = True
break
if disallowed_labels:
for pattern in disallowed_labels:
if re2.match(pattern, conf_node['label']):
allowed = False
break
if not allowed:
raise LabelForbiddenError(
label=conf_node['label'],
allowed_labels=allowed_labels,
disallowed_labels=disallowed_labels)
for name in as_list(conf_node['name']):
if name in node_names:
raise DuplicateNodeError(name, conf_node['name'])

47
zuul/lib/re2util.py Normal file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python
# Copyright (C) 2020 Red Hat, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import re2
def filter_allowed_disallowed(
subjects, allowed_patterns, disallowed_patterns):
"""Filter a list using allowed and disallowed patterns.
:param list subjects: A list of strings to filter.
:param allowed_patterns: A list of re2-compatible patterns to allow.
If empty, all subjects are allowed (see next).
:param disallowed_patterns: A list of re2-compatible patterns to
reject. A more-specific pattern here may override a less-specific
allowed pattern. If empty, all allowed subjects will pass.
"""
ret = []
for subject in subjects:
allowed = True
if allowed_patterns:
allowed = False
for pattern in allowed_patterns:
if re2.match(pattern, subject):
allowed = True
break
if allowed and disallowed_patterns:
for pattern in disallowed_patterns:
if re2.match(pattern, subject):
allowed = False
break
if allowed:
ret.append(subject)
return ret

View File

@ -29,9 +29,8 @@ import time
import select
import threading
import re2
import zuul.lib.repl
from zuul.lib.re2util import filter_allowed_disallowed
import zuul.model
from zuul import exceptions
import zuul.rpcclient
@ -749,21 +748,9 @@ class ZuulWebAPI(object):
disallowed_labels = data['disallowed_labels']
labels = set()
for launcher in self.zk.getRegisteredLaunchers():
for label in launcher.supported_labels:
allowed = True
if allowed_labels:
allowed = False
for pattern in allowed_labels:
if re2.match(pattern, label):
allowed = True
break
if disallowed_labels:
for pattern in disallowed_labels:
if re2.match(pattern, label):
allowed = False
break
if allowed:
labels.add(label)
labels.update(filter_allowed_disallowed(
launcher.supported_labels,
allowed_labels, disallowed_labels))
ret = [{'name': label} for label in sorted(labels)]
resp = cherrypy.response
resp.headers['Access-Control-Allow-Origin'] = '*'