From 5b0487f47c4c630200f2344a91407043db0198cc Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 22 Jul 2020 15:02:19 -0700 Subject: [PATCH] composer-cli: Make start-ostree parent and ref optional This changes the start-ostree command to: compose start-ostree [--size XXXX] [--parent PARENT] [--ref REF] [ ] Both of them are optional, and if missing a "" is passed to osbuild-composer. Also adds more tests for all the various possible options and removes the provider and profile arguments. --- src/composer/cli/compose.py | 55 +++++++++------ tests/composer/test_compose.py | 125 +++++++++++++++++++++++++++++++-- 2 files changed, 152 insertions(+), 28 deletions(-) diff --git a/src/composer/cli/compose.py b/src/composer/cli/compose.py index ef623ea7..2aa1bef8 100644 --- a/src/composer/cli/compose.py +++ b/src/composer/cli/compose.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2018 Red Hat, Inc. +# Copyright (C) 2018-2020 Red Hat, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -72,7 +72,7 @@ def compose_cmd(opts): return cmd_map[opts.args[1]](opts.socket, opts.api_version, opts.args[2:], opts.json, opts.testmode, api=api) def get_size(args): - """Return optional size argument, and remaining args + """Return optional --size argument, and remaining args :param args: list of arguments :type args: list of strings @@ -90,6 +90,29 @@ def get_size(args): value = value * 1024**2 if value is not None else 0 return (args, value) +def get_parent(args): + """Return optional --parent argument, and remaining args + + :param args: list of arguments + :type args: list of strings + :returns: (args, parent) + :rtype: tuple + """ + args, value = get_arg(args, "--parent") + value = value if value is not None else "" + return (args, value) + +def get_ref(args): + """Return optional --ref argument, and remaining args + + :param args: list of arguments + :type args: list of strings + :returns: (args, parent) + :rtype: tuple + """ + args, value = get_arg(args, "--ref") + value = value if value is not None else "" + return (args, value) def compose_list(socket_path, api_version, args, show_json=False, testmode=0, api=None): """Return a simple list of compose identifiers""" @@ -314,7 +337,7 @@ def compose_start(socket_path, api_version, args, show_json=False, testmode=0, a return rc def compose_ostree(socket_path, api_version, args, show_json=False, testmode=0, api=None): - """Start a new compose using the selected blueprint and type + """Start a new ostree compose using the selected blueprint and type :param socket_path: Path to the Unix socket to use for API communication :type socket_path: str @@ -329,7 +352,7 @@ def compose_ostree(socket_path, api_version, args, show_json=False, testmode=0, :param api: Details about the API server, "version" and "backend" :type api: dict - compose start [--size XXX] [ | ] + compose start-ostree [--size XXXX] [--parent PARENT] [--ref REF] [ ] """ if api == None: log.error("Missing api version/backend") @@ -342,6 +365,8 @@ def compose_ostree(socket_path, api_version, args, show_json=False, testmode=0, # Get the optional size before checking other parameters try: args, size = get_size(args) + args, parent = get_parent(args) + args, ref = get_ref(args) except (RuntimeError, ValueError) as e: log.error(str(e)) return 1 @@ -352,39 +377,27 @@ def compose_ostree(socket_path, api_version, args, show_json=False, testmode=0, if len(args) == 1: log.error("start-ostree is missing the output type") return 1 - if len(args) == 2: - log.error("start-ostree is missing the ostree reference") - return 1 if len(args) == 3: - log.error("start-ostree is missing the ostree parent") - return 1 - if len(args) == 5: - log.error("start-ostree is missing the provider and profile details") + log.error("start-ostree is missing the provider TOML file") return 1 config = { "blueprint_name": args[0], "compose_type": args[1], "branch": "master", - "ostree": {"ref": args[2], "parent": args[3]}, + "ostree": {"ref": ref, "parent": parent}, } if size > 0: config["size"] = size - if len(args) == 6: - config["upload"] = {"image_name": args[4]} + if len(args) == 4: + config["upload"] = {"image_name": args[2]} # profile TOML file (maybe) try: - config["upload"].update(toml.load(args[5])) + config["upload"].update(toml.load(args[3])) except toml.TomlDecodeError as e: log.error(str(e)) return 1 - elif len(args) == 7: - config["upload"] = { - "image_name": args[4], - "provider": args[5], - "profile": args[6] - } if testmode: test_url = "?test=%d" % testmode diff --git a/tests/composer/test_compose.py b/tests/composer/test_compose.py index 258e1db1..d45675ea 100644 --- a/tests/composer/test_compose.py +++ b/tests/composer/test_compose.py @@ -153,7 +153,8 @@ class ComposeTestCase(unittest.TestCase): LAST_REQUEST = {} p = composer_cli_parser() opts = p.parse_args(args) - cli.main(opts) + status = cli.main(opts) + LAST_REQUEST["cli_status"] = status return LAST_REQUEST @@ -346,26 +347,136 @@ class ComposeOsBuildV1TestCase(ComposeTestCase): "upload": {"image_name": "httpimage", "provider": "aws", "settings": {"aws_access_key": "AWS Access Key", "aws_bucket": "AWS Bucket", "aws_region": "AWS Region", "aws_secret_key": "AWS Secret Key"}}}) - def test_compose_start_ostree(self): - result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "http-server", "fedora-iot-commit", "referenceid", "parenturl"]) + def test_compose_start_ostree_noargs(self): + """Test start-ostree with no parent and no ref""" + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "http-server", "fedora-iot-commit"]) self.assertTrue(result is not None) self.assertTrue("body" in result) self.assertGreater(len(result["body"]), 0) jd = json.loads(result["body"]) self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", - "ostree": {"ref": "referenceid", "parent": "parenturl"}}) + "ostree": {"ref": "", "parent": ""}}) - def test_compose_start_ostree_upload(self): + def test_compose_start_ostree_parent(self): + """Test start-ostree with --parent""" + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--parent", "parenturl", "http-server", "fedora-iot-commit"]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "ostree": {"ref": "", "parent": "parenturl"}}) + + def test_compose_start_ostree_ref(self): + """Test start-ostree with --ref""" + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--ref", "refid", "http-server", "fedora-iot-commit"]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "ostree": {"ref": "refid", "parent": ""}}) + + def test_compose_start_ostree_refparent(self): + """Test start-ostree with --ref and --parent""" + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--ref", "refid", "--parent", "parenturl", "http-server", "fedora-iot-commit"]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "ostree": {"ref": "refid", "parent": "parenturl"}}) + + def test_compose_start_ostree_size(self): + """Test start-ostree with --size, --ref and --parent""" + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--size", "2048", "--ref", "refid", "--parent", "parenturl", "http-server", "fedora-iot-commit"]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "size": 2147483648, + "ostree": {"ref": "refid", "parent": "parenturl"}}) + + def test_compose_start_ostree_missing(self): + """Test start-ostree with missing argument""" + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "http-server"]) + self.assertTrue(result is not None) + self.assertTrue("cli_status" in result) + self.assertEqual(result["cli_status"], 1) + + def test_compose_start_ostree_upload_parent(self): + """Test start-ostree upload with --parent""" with tempfile.NamedTemporaryFile(prefix="composer-cli.test.") as f: f.write(PROFILE_TOML.encode("UTF-8")) f.seek(0) - result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "http-server", "fedora-iot-commit", "referenceid", "parenturl", "httpimage", f.name]) + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--parent", "parenturl", "http-server", "fedora-iot-commit", "httpimage", f.name]) self.assertTrue(result is not None) self.assertTrue("body" in result) self.assertGreater(len(result["body"]), 0) jd = json.loads(result["body"]) self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", - "ostree": {"ref": "referenceid", "parent": "parenturl"}, + "ostree": {"ref": "", "parent": "parenturl"}, + "upload": {"image_name": "httpimage", "provider": "aws", + "settings": {"aws_access_key": "AWS Access Key", "aws_bucket": "AWS Bucket", "aws_region": "AWS Region", "aws_secret_key": "AWS Secret Key"}}}) + + def test_compose_start_ostree_upload_ref(self): + """Test start-ostree upload with --ref""" + with tempfile.NamedTemporaryFile(prefix="composer-cli.test.") as f: + f.write(PROFILE_TOML.encode("UTF-8")) + f.seek(0) + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--ref", "refid", "http-server", "fedora-iot-commit", "httpimage", f.name]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "ostree": {"ref": "refid", "parent": ""}, + "upload": {"image_name": "httpimage", "provider": "aws", + "settings": {"aws_access_key": "AWS Access Key", "aws_bucket": "AWS Bucket", "aws_region": "AWS Region", "aws_secret_key": "AWS Secret Key"}}}) + + def test_compose_start_ostree_upload_refparent(self): + """Test start-ostree upload with --ref and --parent""" + with tempfile.NamedTemporaryFile(prefix="composer-cli.test.") as f: + f.write(PROFILE_TOML.encode("UTF-8")) + f.seek(0) + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--parent", "parenturl", "--ref", "refid", "http-server", "fedora-iot-commit", "httpimage", f.name]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "ostree": {"ref": "refid", "parent": "parenturl"}, + "upload": {"image_name": "httpimage", "provider": "aws", + "settings": {"aws_access_key": "AWS Access Key", "aws_bucket": "AWS Bucket", "aws_region": "AWS Region", "aws_secret_key": "AWS Secret Key"}}}) + + def test_compose_start_ostree_upload_size(self): + """Test start-ostree upload with --size, --ref and --parent""" + with tempfile.NamedTemporaryFile(prefix="composer-cli.test.") as f: + f.write(PROFILE_TOML.encode("UTF-8")) + f.seek(0) + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "--size", "2048", "--parent", "parenturl", "--ref", "refid", "http-server", "fedora-iot-commit", "httpimage", f.name]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "size": 2147483648, + "ostree": {"ref": "refid", "parent": "parenturl"}, + "upload": {"image_name": "httpimage", "provider": "aws", + "settings": {"aws_access_key": "AWS Access Key", "aws_bucket": "AWS Bucket", "aws_region": "AWS Region", "aws_secret_key": "AWS Secret Key"}}}) + + def test_compose_start_ostree_upload(self): + with tempfile.NamedTemporaryFile(prefix="composer-cli.test.") as f: + f.write(PROFILE_TOML.encode("UTF-8")) + f.seek(0) + result = self.run_test(["--socket", self.socket, "--api", "1", "compose", "start-ostree", "http-server", "fedora-iot-commit", "httpimage", f.name]) + self.assertTrue(result is not None) + self.assertTrue("body" in result) + self.assertGreater(len(result["body"]), 0) + jd = json.loads(result["body"]) + self.assertEqual(jd, {"blueprint_name": "http-server", "compose_type": "fedora-iot-commit", "branch": "master", + "ostree": {"ref": "", "parent": ""}, "upload": {"image_name": "httpimage", "provider": "aws", "settings": {"aws_access_key": "AWS Access Key", "aws_bucket": "AWS Bucket", "aws_region": "AWS Region", "aws_secret_key": "AWS Secret Key"}}})