This adds support for specifing the package sets for repositories; on the command line this can be done via `--repo-package-set` with and argument of `;` separated package set names. This will result in repo information being transported via dict instead of plain strings. Thus the hub plugin's schema was modified accordingly. Last but not least, the builder plugin now can decode these dicts and setup the repos accordingly. Test were added for plugins as well as the integration test changed to use this new feature. The first upstream commit that supports this feature is pinned.
279 lines
8.5 KiB
Python
279 lines
8.5 KiB
Python
#
|
|
# koji command line interface plugin unit tests
|
|
#
|
|
|
|
|
|
import contextlib
|
|
import io
|
|
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_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)
|