From b1d9ea9bb6b9436ad932209689e8b39e11c61948 Mon Sep 17 00:00:00 2001
From: skycastlelily <lnie@redhat.com>
Date: Mon, 13 Jan 2025 05:50:01 -0500
Subject: [PATCH] Support creating Beaker jobs using `beaker-job-group` key for
 `mrack` (#3397)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Petr Šplíchal <psplicha@redhat.com>
---
 docs/releases.rst                 |  5 +++++
 pyproject.toml                    |  2 +-
 tmt/schemas/provision/beaker.yaml |  3 +++
 tmt/steps/provision/mrack.py      | 24 ++++++++++++++++++++++--
 4 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/docs/releases.rst b/docs/releases.rst
index c22382f7a2..b051a1f667 100644
--- a/docs/releases.rst
+++ b/docs/releases.rst
@@ -17,6 +17,11 @@ The :ref:`/plugins/report/reportportal` plugin now exports all
 test contact information, rather than just the first contact
 instance.
 
+The :ref:`/plugins/provision/beaker` provision plugin gains
+support for submitting jobs on behalf of a group through the
+``beaker-job-group`` key. The submitting user must be a member of
+the given job group.
+
 
 tmt-1.40.0
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/pyproject.toml b/pyproject.toml
index efcdc37c58..a2ee924ee4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -55,7 +55,7 @@ export-polarion = [
     "pylero>=0.0.8",
     ]
 provision-beaker = [
-    "mrack>=1.15.1",
+    "mrack>=1.23.1",
     ]
 provision-virtual = [
     "testcloud>=0.11.3",
diff --git a/tmt/schemas/provision/beaker.yaml b/tmt/schemas/provision/beaker.yaml
index 01953b01fc..73e4e0aa0b 100644
--- a/tmt/schemas/provision/beaker.yaml
+++ b/tmt/schemas/provision/beaker.yaml
@@ -54,5 +54,8 @@ properties:
     items:
       type: string
 
+  beaker-job-group:
+    type: string
+
 required:
   - how
diff --git a/tmt/steps/provision/mrack.py b/tmt/steps/provision/mrack.py
index 07233b060e..354e6fd861 100644
--- a/tmt/steps/provision/mrack.py
+++ b/tmt/steps/provision/mrack.py
@@ -930,6 +930,14 @@ class BeakerGuestData(tmt.steps.provision.GuestSshData):
         multiple=True,
         normalize=tmt.utils.normalize_string_list)
 
+    beaker_job_group: Optional[str] = field(
+        default=None,
+        option='--beaker-job-group',
+        metavar='GROUPNAME',
+        help="""
+             If set, Beaker jobs will be submitted on behalf of ``GROUPNAME``.
+             """)
+
 
 @dataclasses.dataclass
 class ProvisionBeakerData(BeakerGuestData, tmt.steps.provision.ProvisionStepData):
@@ -966,7 +974,7 @@ class CreateJobParameters:
     whiteboard: Optional[str]
     beaker_job_owner: Optional[str]
     public_key: list[str]
-    group: str = 'linux'
+    group: Optional[str]
 
     def to_mrack(self) -> dict[str, Any]:
         data = dataclasses.asdict(self)
@@ -1090,6 +1098,7 @@ class GuestBeaker(tmt.steps.provision.GuestSsh):
     kickstart: dict[str, str]
 
     beaker_job_owner: Optional[str] = None
+    beaker_job_group: Optional[str] = None
 
     # Provided in Beaker response
     job_id: Optional[str]
@@ -1167,7 +1176,8 @@ def _create(self, tmt_name: str) -> None:
             name=f'{self.image}-{self.arch}',
             whiteboard=self.whiteboard or tmt_name,
             beaker_job_owner=self.beaker_job_owner,
-            public_key=self.public_key)
+            public_key=self.public_key,
+            group=self.beaker_job_group)
 
         try:
             response = self.api.create(data)
@@ -1188,6 +1198,16 @@ def _create(self, tmt_name: str) -> None:
                         f"Failed to create Beaker job, job owner '{self.beaker_job_owner}' "
                         "is not a valid submission delegate.") from exc
 
+                if 'is not a valid group' in cause.faultString:
+                    raise ProvisionError(
+                        f"Failed to create Beaker job, job group '{self.beaker_job_group}' "
+                        "was refused as unknown.") from exc
+
+                if 'is not a member of group' in cause.faultString:
+                    raise ProvisionError(
+                        "Failed to create Beaker job, submitting user is not "
+                        "a member of group '{self.beaker_job_group}'") from exc
+
             raise ProvisionError('Failed to create Beaker job') from exc
 
         if response: