Browse Source

Merge "Add allowed-labels tenant setting"

tags/3.3.1
Zuul 5 months ago
parent
commit
21f29820c4

+ 7
- 0
doc/source/admin/tenants.rst View File

@@ -247,3 +247,10 @@ configuration. Some examples of tenant definitions are:
247 247
       The list of connections a tenant can report to. When set, this setting
248 248
       can be used to restrict what connections a tenant can use as reporter.
249 249
       Without this setting, the tenant can report to any connection.
250
+
251
+   .. attr:: allowed-labels
252
+      :default: []
253
+
254
+      The list of labels regexp a tenant can use in job's nodeset. When set,
255
+      this setting can be used to restrict what labels a tenant can use.
256
+      Without this setting, the tenant can use any labels.

+ 5
- 0
releasenotes/notes/allowed-labels-d3ca17f3c7e167c8.yaml View File

@@ -0,0 +1,5 @@
1
+---
2
+features:
3
+  - |
4
+    A new tenant option :attr:`tenant.allowed-labels`
5
+    can be used to restrict what labels a tenant has access to.

+ 1
- 1
tests/fixtures/config/multi-tenant/git/tenant-one-config/zuul.d/config.yaml View File

@@ -23,7 +23,7 @@
23 23
     name: nodeset1
24 24
     nodes:
25 25
       - name: controller
26
-        label: controller-label
26
+        label: tenant-one-controller-label
27 27
 
28 28
 - job:
29 29
     name: project1-test1

+ 4
- 0
tests/fixtures/config/multi-tenant/main.yaml View File

@@ -3,6 +3,10 @@
3 3
     max-job-timeout: 1800
4 4
     allowed-reporters:
5 5
       - gerrit
6
+    allowed-labels:
7
+      - tenant-one-.*
8
+      - ubuntu-trusty
9
+      - fake
6 10
     source:
7 11
       gerrit:
8 12
         config-projects:

+ 25
- 0
tests/unit/test_v3.py View File

@@ -3235,6 +3235,31 @@ class TestAllowedConnection(AnsibleZuulTestCase):
3235 3235
             "B should not fail because of allowed-reporters")
3236 3236
 
3237 3237
 
3238
+class TestAllowedLabels(AnsibleZuulTestCase):
3239
+    config_file = 'zuul-connections-gerrit-and-github.conf'
3240
+    tenant_config_file = 'config/multi-tenant/main.yaml'
3241
+
3242
+    def test_allowed_labels(self):
3243
+        in_repo_conf = textwrap.dedent(
3244
+            """
3245
+            - job:
3246
+                name: test
3247
+                nodeset:
3248
+                  nodes:
3249
+                    - name: controller
3250
+                      label: tenant-two-label
3251
+            """)
3252
+        file_dict = {'zuul.d/test.yaml': in_repo_conf}
3253
+        A = self.fake_gerrit.addFakeChange(
3254
+            'tenant-one-config', 'master', 'A', files=file_dict)
3255
+        self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(1))
3256
+        self.waitUntilSettled()
3257
+        self.assertIn(
3258
+            'Label named "tenant-two-label" is not part of the allowed',
3259
+            A.messages[0],
3260
+            "A should fail because of allowed-labels")
3261
+
3262
+
3238 3263
 class TestPragma(ZuulTestCase):
3239 3264
     tenant_config_file = 'config/pragma/main.yaml'
3240 3265
 

+ 21
- 0
zuul/configloader.py View File

@@ -22,6 +22,7 @@ import io
22 22
 import re
23 23
 import subprocess
24 24
 
25
+import re2
25 26
 import voluptuous as vs
26 27
 
27 28
 from zuul import model
@@ -79,6 +80,17 @@ class UnknownConnection(Exception):
79 80
         super(UnknownConnection, self).__init__(message)
80 81
 
81 82
 
83
+class LabelForbiddenError(Exception):
84
+    def __init__(self, label, allowed_labels):
85
+        message = textwrap.dedent("""\
86
+        Label named "{label}" is not part of the allowed
87
+        labels ({allowed_labels}) for this tenant.""")
88
+        message = textwrap.fill(message.format(
89
+            label=label,
90
+            allowed_labels=", ".join(allowed_labels)))
91
+        super(LabelForbiddenError, self).__init__(message)
92
+
93
+
82 94
 class MaxTimeoutError(Exception):
83 95
     def __init__(self, job, tenant):
84 96
         message = textwrap.dedent("""\
@@ -452,7 +464,14 @@ class NodeSetParser(object):
452 464
         ns.start_mark = conf.get('_start_mark')
453 465
         node_names = set()
454 466
         group_names = set()
467
+        allowed_labels = self.pcontext.tenant.allowed_labels
455 468
         for conf_node in as_list(conf['nodes']):
469
+            if allowed_labels:
470
+                if not [True for allowed_label in allowed_labels if
471
+                        re2.match(allowed_label, conf_node['label'])]:
472
+                    raise LabelForbiddenError(
473
+                        label=conf_node['label'],
474
+                        allowed_labels=allowed_labels)
456 475
             for name in as_list(conf_node['name']):
457 476
                 if name in node_names:
458 477
                     raise DuplicateNodeError(name, conf_node['name'])
@@ -1293,6 +1312,7 @@ class TenantParser(object):
1293 1312
                   'exclude-unprotected-branches': bool,
1294 1313
                   'allowed-triggers': to_list(str),
1295 1314
                   'allowed-reporters': to_list(str),
1315
+                  'allowed-labels': to_list(str),
1296 1316
                   'default-parent': str,
1297 1317
                   }
1298 1318
         return vs.Schema(tenant)
@@ -1309,6 +1329,7 @@ class TenantParser(object):
1309 1329
                 conf['exclude-unprotected-branches']
1310 1330
         tenant.allowed_triggers = conf.get('allowed-triggers')
1311 1331
         tenant.allowed_reporters = conf.get('allowed-reporters')
1332
+        tenant.allowed_labels = conf.get('allowed-labels')
1312 1333
         tenant.default_base_job = conf.get('default-parent', 'base')
1313 1334
 
1314 1335
         tenant.unparsed_config = conf

Loading…
Cancel
Save