While it is technically possible to build more than one image type as part of a Koji compose in osbuild-composer, this option is not used in reality and it also makes very little sense. If the user wants to build more than one image type, they should submit multiple Koji builds. Adjust affected unit tests.
345 lines
10 KiB
Python
345 lines
10 KiB
Python
#
|
|
# koji command line interface plugin unit tests
|
|
#
|
|
|
|
|
|
import contextlib
|
|
import io
|
|
import json
|
|
import os
|
|
import tempfile
|
|
|
|
import koji
|
|
import koji_cli.lib as kl
|
|
from flexmock import flexmock
|
|
|
|
from plugintest import PluginTest
|
|
|
|
|
|
@PluginTest.load_plugin("cli")
|
|
class TestCliPlugin(PluginTest):
|
|
|
|
@staticmethod
|
|
def mock_koji_lib(*, bg=False, task_result=0):
|
|
kojilib = flexmock(OptionParser=kl.OptionParser)
|
|
|
|
kojilib.should_receive("get_usage_str").and_return("usage")
|
|
kojilib.should_receive("activate_session").once()
|
|
kojilib.should_receive("_running_in_bg").and_return(bg)
|
|
kojilib.should_receive("watch_tasks").and_return(task_result)
|
|
|
|
return kojilib
|
|
|
|
@staticmethod
|
|
def mock_options(*, quiet=False):
|
|
options = flexmock(
|
|
quiet=quiet,
|
|
weburl="http://osbuild.org/"
|
|
)
|
|
return options
|
|
|
|
|
|
@staticmethod
|
|
def mock_session_add_valid_tag(session):
|
|
build_target = {
|
|
"build_tag": 23,
|
|
"build_tag_name": "target-build",
|
|
"dest_tag": 42,
|
|
"dest_tag_name": "target-dest"
|
|
}
|
|
|
|
tag_info = {
|
|
"id": build_target["dest_tag"],
|
|
"name": build_target["dest_tag_name"],
|
|
"locked": False
|
|
}
|
|
|
|
session.should_receive("getBuildTarget") \
|
|
.with_args("target") \
|
|
.and_return(build_target) \
|
|
.once()
|
|
|
|
session.should_receive("getTag") \
|
|
.with_args(build_target["dest_tag"]) \
|
|
.and_return(tag_info) \
|
|
.once()
|
|
|
|
return session
|
|
|
|
def test_basic_invocation(self):
|
|
# check we get the right amount of arguments
|
|
# i.e. we are missing the architecture here
|
|
argv = ["name", "version", "distro", "target"]
|
|
|
|
f = io.StringIO()
|
|
with self.assertRaises(SystemExit) as cm, \
|
|
contextlib.redirect_stderr(f):
|
|
self.plugin.handle_osbuild_image(None, None, argv)
|
|
self.assertEqual(cm.exception.code, 2)
|
|
self.assertIn("osbuild-image", f.getvalue())
|
|
f.close()
|
|
|
|
# check one successful invocation
|
|
|
|
argv = [
|
|
# the required positional arguments
|
|
"name", "version", "distro", "target", "arch1",
|
|
# optional keyword arguments
|
|
"--repo", "https://first.repo",
|
|
"--repo", "https://second.repo",
|
|
"--release", "20200202.n2",
|
|
"--skip-tag"
|
|
]
|
|
|
|
expected_args = ["name", "version", "distro",
|
|
'guest-image', # the default image type
|
|
"target",
|
|
['arch1']]
|
|
|
|
expected_opts = {
|
|
"release": "20200202.n2",
|
|
"repo": ["https://first.repo", "https://second.repo"],
|
|
"skip_tag": True
|
|
}
|
|
|
|
task_result = {"compose_id": "42", "build_id": 23}
|
|
task_id = 1
|
|
koji_lib = self.mock_koji_lib()
|
|
|
|
options = self.mock_options()
|
|
session = flexmock()
|
|
|
|
self.mock_session_add_valid_tag(session)
|
|
|
|
session.should_receive("osbuildImage") \
|
|
.with_args(*expected_args, opts=expected_opts) \
|
|
.and_return(task_id) \
|
|
.once()
|
|
|
|
session.should_receive("logout") \
|
|
.with_args() \
|
|
.once()
|
|
|
|
session.should_receive("getTaskResult") \
|
|
.with_args(task_id) \
|
|
.and_return(task_result) \
|
|
.once()
|
|
|
|
setattr(self.plugin, "kl", koji_lib)
|
|
r = self.plugin.handle_osbuild_image(options, session, argv)
|
|
self.assertEqual(r, 0)
|
|
|
|
def test_customizations_options(self):
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
|
|
customizations = {
|
|
"packages": [
|
|
"emacs"
|
|
]
|
|
}
|
|
|
|
path = os.path.join(tmpdir, "customizations.json")
|
|
|
|
with open(path, "w", encoding="utf-8") as f:
|
|
json.dump(customizations, f)
|
|
|
|
argv = [
|
|
# the required positional arguments
|
|
"name", "version", "distro", "target", "arch1",
|
|
# optional keyword arguments
|
|
"--repo", "https://first.repo",
|
|
"--repo", "https://second.repo",
|
|
"--release", "20200202.n2",
|
|
"--customizations", path
|
|
]
|
|
|
|
expected_args = ["name", "version", "distro",
|
|
'guest-image', # the default image type
|
|
"target",
|
|
['arch1']]
|
|
|
|
expected_opts = {
|
|
"release": "20200202.n2",
|
|
"repo": ["https://first.repo", "https://second.repo"],
|
|
"customizations": customizations
|
|
}
|
|
|
|
task_result = {"compose_id": "42", "build_id": 23}
|
|
task_id = 1
|
|
koji_lib = self.mock_koji_lib()
|
|
|
|
options = self.mock_options()
|
|
session = flexmock()
|
|
|
|
self.mock_session_add_valid_tag(session)
|
|
|
|
session.should_receive("osbuildImage") \
|
|
.with_args(*expected_args, opts=expected_opts) \
|
|
.and_return(task_id) \
|
|
.once()
|
|
|
|
session.should_receive("logout") \
|
|
.with_args() \
|
|
.once()
|
|
|
|
session.should_receive("getTaskResult") \
|
|
.with_args(task_id) \
|
|
.and_return(task_result) \
|
|
.once()
|
|
|
|
setattr(self.plugin, "kl", koji_lib)
|
|
r = self.plugin.handle_osbuild_image(options, session, argv)
|
|
self.assertEqual(r, 0)
|
|
|
|
def test_ostree_options(self):
|
|
# Check we properly handle ostree specific options
|
|
|
|
argv = [
|
|
# the required positional arguments
|
|
"name", "version", "distro", "target", "arch1",
|
|
# optional keyword arguments
|
|
"--repo", "https://first.repo",
|
|
"--repo", "https://second.repo",
|
|
"--release", "20200202.n2",
|
|
"--ostree-parent", "ostree/$arch/staging",
|
|
"--ostree-ref", "ostree/$arch/production",
|
|
"--ostree-url", "https://osbuild.org/repo",
|
|
]
|
|
|
|
expected_args = ["name", "version", "distro",
|
|
'guest-image', # the default image type
|
|
"target",
|
|
['arch1']]
|
|
|
|
expected_opts = {
|
|
"release": "20200202.n2",
|
|
"repo": ["https://first.repo", "https://second.repo"],
|
|
"ostree": {
|
|
"parent": "ostree/$arch/staging",
|
|
"ref": "ostree/$arch/production",
|
|
"url": "https://osbuild.org/repo",
|
|
}
|
|
}
|
|
|
|
task_result = {"compose_id": "42", "build_id": 23}
|
|
task_id = 1
|
|
koji_lib = self.mock_koji_lib()
|
|
|
|
options = self.mock_options()
|
|
session = flexmock()
|
|
|
|
self.mock_session_add_valid_tag(session)
|
|
|
|
session.should_receive("osbuildImage") \
|
|
.with_args(*expected_args, opts=expected_opts) \
|
|
.and_return(task_id) \
|
|
.once()
|
|
|
|
session.should_receive("logout") \
|
|
.with_args() \
|
|
.once()
|
|
|
|
session.should_receive("getTaskResult") \
|
|
.with_args(task_id) \
|
|
.and_return(task_result) \
|
|
.once()
|
|
|
|
setattr(self.plugin, "kl", koji_lib)
|
|
r = self.plugin.handle_osbuild_image(options, session, argv)
|
|
self.assertEqual(r, 0)
|
|
|
|
def test_repo_package_sets(self):
|
|
# Check we properly handle ostree specific options
|
|
|
|
argv = [
|
|
# the required positional arguments
|
|
"name", "version", "distro", "target", "arch1",
|
|
# optional keyword arguments
|
|
"--repo", "https://first.repo",
|
|
"--repo-package-sets", "a; b; c",
|
|
"--repo-package-sets", "d",
|
|
"--repo", "https://second.repo",
|
|
"--repo-package-sets", "alpha",
|
|
"--repo", "https://third.repo", # NB: no `--repo-package-set`
|
|
"--release", "20200202.n2",
|
|
]
|
|
|
|
expected_args = ["name", "version", "distro",
|
|
'guest-image', # the default image type
|
|
"target",
|
|
['arch1']]
|
|
|
|
expected_opts = {
|
|
"release": "20200202.n2",
|
|
"repo": [
|
|
{"baseurl": "https://first.repo",
|
|
"package_sets": ["a", "b", "c", "d"]},
|
|
{"baseurl": "https://second.repo",
|
|
"package_sets": ["alpha"]},
|
|
{"baseurl": "https://third.repo"}
|
|
],
|
|
}
|
|
|
|
task_result = {"compose_id": "42", "build_id": 23}
|
|
task_id = 1
|
|
koji_lib = self.mock_koji_lib()
|
|
|
|
options = self.mock_options()
|
|
session = flexmock()
|
|
|
|
self.mock_session_add_valid_tag(session)
|
|
|
|
session.should_receive("osbuildImage") \
|
|
.with_args(*expected_args, opts=expected_opts) \
|
|
.and_return(task_id) \
|
|
.once()
|
|
|
|
session.should_receive("logout") \
|
|
.with_args() \
|
|
.once()
|
|
|
|
session.should_receive("getTaskResult") \
|
|
.with_args(task_id) \
|
|
.and_return(task_result) \
|
|
.once()
|
|
|
|
setattr(self.plugin, "kl", koji_lib)
|
|
r = self.plugin.handle_osbuild_image(options, session, argv)
|
|
self.assertEqual(r, 0)
|
|
|
|
def test_target_check(self):
|
|
# unknown build target
|
|
session = flexmock()
|
|
|
|
session.should_receive("getBuildTarget") \
|
|
.with_args("target") \
|
|
.and_return(None) \
|
|
.once()
|
|
|
|
argv = ["name", "version", "distro", "target", "arch1"]
|
|
with self.assertRaises(koji.GenericError):
|
|
self.plugin.handle_osbuild_image(None, session, argv)
|
|
|
|
# unknown destination tag
|
|
build_target = {
|
|
"build_tag": 23,
|
|
"build_tag_name": "target-build",
|
|
"dest_tag": 42,
|
|
"dest_tag_name": "target-dest" # missing!
|
|
}
|
|
|
|
session = flexmock()
|
|
|
|
session.should_receive("getBuildTarget") \
|
|
.with_args("target") \
|
|
.and_return(build_target) \
|
|
.once()
|
|
|
|
session.should_receive("getTag") \
|
|
.with_args(build_target["dest_tag"]) \
|
|
.and_return(None) \
|
|
.once()
|
|
|
|
argv = ["name", "version", "distro", "target", "arch1"]
|
|
with self.assertRaises(koji.GenericError):
|
|
self.plugin.handle_osbuild_image(None, session, argv)
|