mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-04-05 03:38:12 +08:00
Add test_submit_module_build
This commit is contained in:
@@ -33,7 +33,7 @@ def pkg_util(test_env):
|
||||
"""Fixture to interact with the packaging utility
|
||||
|
||||
:return: Packaging utility configured for the tests
|
||||
:rtype: object of utils.PackagingUtility
|
||||
:rtype: utils.PackagingUtility
|
||||
"""
|
||||
return utils.PackagingUtility(test_env["packaging_utility"], test_env["mbs_api"])
|
||||
|
||||
@@ -99,10 +99,7 @@ def clone_and_start_build(repo, pkg_util):
|
||||
builds = pkg_util.run("--optional", "rebuild_strategy=all")
|
||||
yield repo, builds
|
||||
for build in builds:
|
||||
try:
|
||||
pkg_util.cancel(build)
|
||||
except sh.ErrorReturnCode:
|
||||
pass # we don't need to bother with clean-up errors
|
||||
pkg_util.cancel(build, ignore_errors=True)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
|
||||
@@ -136,3 +136,6 @@ testdata:
|
||||
static_context:
|
||||
module: testmodule
|
||||
branch: test-static-context
|
||||
rest_submit_module_build:
|
||||
module: testmodule
|
||||
branch: test-submit-module
|
||||
|
||||
48
tests/integration/test_rest_submit_build.py
Normal file
48
tests/integration/test_rest_submit_build.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from requests import HTTPError
|
||||
|
||||
|
||||
def assert_build_in_build_state(mbs, build):
|
||||
"""Assert build state was reached and then cancel the build using REST."""
|
||||
try:
|
||||
mbs.wait_for_module_build(build, lambda bld: bld.get("state") == 2, timeout=10)
|
||||
finally:
|
||||
mbs.cancel_module_build(build.id)
|
||||
|
||||
|
||||
def test_rest_submit_module_build(pkg_util, scenario, repo, mbs):
|
||||
"""Test module build submission. Tests only whether or not
|
||||
build gets accepted and transitions successfully to the build state.
|
||||
|
||||
Two variants:
|
||||
* submit module build with modulemd yaml (test YAMLFileHandler)
|
||||
* submit module build with scmurl (test SCMHandler)
|
||||
..are combined into one method to reuse 1 single test branch.
|
||||
|
||||
Steps:
|
||||
* Submit module build using module's SCM URL (HTTP POST).
|
||||
* Assert that build reaches 'build' state.
|
||||
* Cancel the build (HTTP PATCH)
|
||||
"""
|
||||
|
||||
# 1) SCMURL submission
|
||||
repo.bump()
|
||||
|
||||
scmurl = pkg_util.giturl().replace("#", "?#")
|
||||
branch = scenario["branch"]
|
||||
data = {"scmurl": scmurl, "branch": branch}
|
||||
|
||||
builds = mbs.submit_module_build(data)
|
||||
assert len(builds) == 1
|
||||
assert_build_in_build_state(mbs, builds[0])
|
||||
|
||||
# 2) YAML submission (might not be enabled, but if it is, let's test it)
|
||||
repo.bump()
|
||||
|
||||
data = {"modulemd": str(repo.modulemd)}
|
||||
try:
|
||||
builds = mbs.submit_module_build(data)
|
||||
except HTTPError as e:
|
||||
if "YAML submission is not enabled" not in e.response.text:
|
||||
raise
|
||||
else:
|
||||
assert_build_in_build_state(mbs, builds[0])
|
||||
@@ -20,6 +20,13 @@ our_sh = sh(_out=sys.stdout, _err=sys.stderr, _tee=True)
|
||||
from our_sh import Command, git, pushd # noqa
|
||||
|
||||
|
||||
def get_kerberos_auth():
|
||||
"""Get the 'default' Kerberos auth header field"""
|
||||
# (!) User executing this request must be allowed to do so on the target MBS instance.
|
||||
# MBS server does not support mutual auth, so make it optional (inspired by mbs-cli).
|
||||
return requests_kerberos.HTTPKerberosAuth(mutual_authentication=requests_kerberos.OPTIONAL)
|
||||
|
||||
|
||||
class Koji:
|
||||
"""Wrapper class to work with Koji
|
||||
|
||||
@@ -113,14 +120,12 @@ class Repo:
|
||||
|
||||
:attribute string module_name: name of the module stored in this repo
|
||||
:attribute string branch: name of the branch, the repo is checked-out
|
||||
:attribute string giturl: GIT URL of the repo/branch
|
||||
:attribute dict _modulemd: Modulemd file as read from the repo
|
||||
"""
|
||||
|
||||
def __init__(self, module_name, branch):
|
||||
self.module_name = module_name
|
||||
self.branch = branch
|
||||
|
||||
self._modulemd = None
|
||||
self._version = None
|
||||
|
||||
@@ -243,18 +248,23 @@ class PackagingUtility:
|
||||
|
||||
return stdout
|
||||
|
||||
def cancel(self, build):
|
||||
def cancel(self, build, ignore_errors=False):
|
||||
"""Cancel the module build
|
||||
|
||||
:param Build build: the Build object of the module build to be cancelled.
|
||||
:param bool ignore_errors: ignore when command fails (ErrorReturnCode exception)
|
||||
:return: Standard output of the "module-build-cancel <build id=""> command
|
||||
:rtype: str
|
||||
"""
|
||||
stdout = self._packaging_utility("module-build-cancel", build.id).stdout.decode(
|
||||
"utf-8")
|
||||
return stdout
|
||||
cmd = "module-build-cancel"
|
||||
try:
|
||||
return self._packaging_utility(cmd, build.id).stdout.decode("utf-8")
|
||||
except sh.ErrorReturnCode:
|
||||
if not ignore_errors:
|
||||
raise
|
||||
|
||||
def giturl(self):
|
||||
"""Get target URL of the current repository/branch"""
|
||||
return self._packaging_utility("giturl").stdout.decode("utf-8").strip()
|
||||
|
||||
def clone(self, *args):
|
||||
@@ -519,9 +529,10 @@ class MBS:
|
||||
:param str stream: Stream name
|
||||
:param str order_desc_by: Optional sorting parameter e.g. "version"
|
||||
:return: list of Build objects
|
||||
:rtype: list
|
||||
:rtype: list[Build]
|
||||
"""
|
||||
url = f"{self._mbs_api}module-builds/"
|
||||
|
||||
payload = {'name': module, "stream": stream}
|
||||
if order_desc_by:
|
||||
payload.update({"order_desc_by": order_desc_by})
|
||||
@@ -530,40 +541,25 @@ class MBS:
|
||||
return [Build(self._mbs_api, build["id"]) for build in r.json()["items"]]
|
||||
|
||||
def import_module(self, scmurl):
|
||||
"""Import module from SCM URL (modulemd).
|
||||
"""Import module from SCM URL.
|
||||
|
||||
:param str scmurl:
|
||||
:return: requests response
|
||||
:rtype: requests response object
|
||||
"""
|
||||
url = f"{self._mbs_api}import-module/"
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
data = json.dumps({'scmurl': scmurl})
|
||||
|
||||
# (!) User executing this request must be allowed to do so on the target MBS instance.
|
||||
# MBS server does not support mutual auth, so make it optional (inspired by mbs-cli).
|
||||
auth = requests_kerberos.HTTPKerberosAuth(mutual_authentication=requests_kerberos.OPTIONAL)
|
||||
|
||||
response = requests.post(
|
||||
url,
|
||||
auth=auth,
|
||||
headers=headers,
|
||||
verify=False,
|
||||
data=data
|
||||
)
|
||||
try:
|
||||
response.raise_for_status()
|
||||
return response
|
||||
except requests.exceptions.HTTPError:
|
||||
# response message contains useful information, which requests module omits
|
||||
pytest.fail(response.text)
|
||||
r = requests.post(url, auth=get_kerberos_auth(), verify=False, data=data)
|
||||
r.raise_for_status()
|
||||
return r
|
||||
|
||||
def get_module_builds(self, **kwargs):
|
||||
"""Query MBS API on module-builds endpoint
|
||||
|
||||
:attribute **kwargs: options for the HTTP GET
|
||||
:return: list of Build objects
|
||||
:rtype: list
|
||||
:return: matched build entries
|
||||
:rtype: list[Build]
|
||||
:Keyword Arguments: passed directly to the request as HTTP params.
|
||||
"""
|
||||
url = f"{self._mbs_api}module-builds/"
|
||||
r = requests.get(url, params=kwargs)
|
||||
@@ -574,9 +570,10 @@ class MBS:
|
||||
def get_module_build(self, build_data, **kwargs):
|
||||
"""Query MBS API on module-builds endpoint for a specific build
|
||||
|
||||
:attribute build_data (int|Build): build ID
|
||||
:param int|Build build_data: build ID
|
||||
:return: module build object
|
||||
:rtype: Build
|
||||
:Keyword Arguments: passed directly to the request as HTTP params.
|
||||
"""
|
||||
build_id = self._get_build_id(build_data)
|
||||
url = f"{self._mbs_api}module-builds/{build_id}"
|
||||
@@ -585,6 +582,29 @@ class MBS:
|
||||
r.raise_for_status()
|
||||
return Build(self._mbs_api, r.json()["id"])
|
||||
|
||||
def submit_module_build(self, data):
|
||||
"""Submit a module build with arbitrary payload.
|
||||
|
||||
:param dict data: payload of the POST request
|
||||
1) SCMURL submission: data = {scmurl, branch}
|
||||
2) YAML submission: data = {modulemd: <str(modulemd as dict)>}
|
||||
:return: submitted build(s)
|
||||
:rtype: list[Build]
|
||||
"""
|
||||
url = f"{self._mbs_api}module-builds/"
|
||||
|
||||
r = requests.post(url, verify=False, auth=get_kerberos_auth(), data=json.dumps(data))
|
||||
r.raise_for_status()
|
||||
return [Build(self._mbs_api, build["id"]) for build in r.json()]
|
||||
|
||||
def cancel_module_build(self, build_id):
|
||||
"""PATCH the state field of a module build to cancel it"""
|
||||
url = f"{self._mbs_api}module-builds/{build_id}"
|
||||
|
||||
data = json.dumps({"state": "failed"})
|
||||
response = requests.patch(url, auth=get_kerberos_auth(), verify=False, data=data)
|
||||
response.raise_for_status()
|
||||
|
||||
def wait_for_module_build(self, build_data, predicate_func, timeout=60, interval=5):
|
||||
"""Wait for module build. Wait until the specified function returns True.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user