Repository: osbuild/osbuild
Pull request #1488 (2023-12-07 09:40:02)

stages(kickstart): add `ostreecontainer`
Add support for the `ostreecontainer` kickstart command, see: https://pykickstart.readthedocs.io/en/latest/kickstart-docs.html#ostreecontainer

supakeen: ## TODO

- [ ] `ostreesetup` and `ostreecontainer` are mutually exclusive in kickstarts. This needs to be denoted in either schema or runtime.

Patch:
diff --git a/schutzbot/terraform b/schutzbot/terraform
index b1c3b3d0..125e1d86 100644
--- a/schutzbot/terraform
+++ b/schutzbot/terraform
@@ -1,1 +1,1 @@
-f127f38ebe23ef9a6ef4e6dcaf6d5cd9389f0a08
+40e5f0c5d7da48ef4521e051bcf0ceaab429d02f
diff --git a/stages/org.osbuild.kickstart b/stages/org.osbuild.kickstart
index 9d5f5372..03d30cf1 100755
--- a/stages/org.osbuild.kickstart
+++ b/stages/org.osbuild.kickstart
@@ -92,7 +92,11 @@ SCHEMA = r"""
   }
 },
 "additionalProperties": false,
-"required": ["path"],
+"anyOf": [
+    {"required": ["path", "ostree"], "not": {"required": ["ostreecontainer"]}},
+    {"required": ["path", "ostreecontainer"], "not": {"required": ["ostree"]}},
+    {"required": ["path"], "not": {"required": ["ostree", "ostreecontainer"]}}
+],
 "properties": {
   "path": {
     "type": "string",
@@ -122,6 +126,31 @@ SCHEMA = r"""
       }
     }
   },
+  "ostreecontainer": {
+    "type": "object",
+    "required": ["url"],
+    "additionalProperties": false,
+    "properties": {
+      "stateroot": {
+        "type": "string"
+      },
+      "url": {
+        "type": "string"
+      },
+      "transport": {
+        "type": "string",
+        "enum": ["registry", "oci", "oci-archive"],
+        "description": "Use the given transport, Anaconda's default is 'registry'"
+      },
+      "remote": {
+        "type": "string"
+      },
+      "signatureverification": {
+        "type": "boolean",
+        "default": true
+      }
+    }
+  },
   "liveimg": {
     "type": "object",
     "required": ["url"],
@@ -514,6 +543,24 @@ def main(tree, options):  # pylint: disable=too-many-branches
 
         config += [cmd]
 
+    ostreecontainer = options.get("ostreecontainer")
+
+    if ostreecontainer:
+        url = ostreecontainer["url"]
+
+        cmd = f"ostreecontainer --url={url}"
+
+        for name in ["stateroot", "transport", "remote"]:
+            value = ostreecontainer.get(name)
+            if value:
+                cmd += f" --{name}={value}"
+
+        signature_verification = ostreecontainer.get("signatureverification", True)
+        if not signature_verification:
+            cmd += " --no-signature-verification"
+
+        config += [cmd]
+
     liveimg = options.get("liveimg")
     if liveimg:
         url = liveimg["url"]


Test patch:
diff --git a/stages/test/test_kickstart.py b/stages/test/test_kickstart.py
index 8428a266..d2ca7340 100644
--- a/stages/test/test_kickstart.py
+++ b/stages/test/test_kickstart.py
@@ -191,6 +191,27 @@ TEST_INPUT = [
     # hostname can also be written as a QFDN
     ({"network": [{"device": "foo", "hostname": "foo.bar.com"}]},
      "network --device=foo --hostname=foo.bar.com"),
+    # ostreecontainer
+    (
+        {
+            "ostreecontainer": {
+                "stateroot": "some-osname",
+                "url": "http://some-ostree-url.com/foo",
+                "transport": "registry",
+                "remote": "some-remote",
+                "signatureverification": False,
+            },
+        },
+        "ostreecontainer --url=http://some-ostree-url.com/foo --stateroot=some-osname --transport=registry --remote=some-remote --no-signature-verification",
+    ),
+    (
+        {
+            "ostreecontainer": {
+                "url": "http://some-ostree-url.com/foo",
+            },
+        },
+        "ostreecontainer --url=http://some-ostree-url.com/foo",
+    ),
 ]
 
 
@@ -318,6 +339,26 @@ def test_kickstart_valid(tmp_path, test_input, expected):  # pylint: disable=unu
                        ".123456789012345678901234567890123456789012345678901234567890123" +
                        ".12345678901234567890123456789012345678901234567890123456789012"
                        }]}, " does not match "),
+        # ostreecontainer
+        ({"ostreecontainer": {"url": "http://some-ostree-url.com/foo",
+         "transport": "not-valid"}}, "'not-valid' is not one of ["),
+        # not both ostreecontainer and ostree
+        (
+            {
+                "ostreecontainer": {
+                    "url": "http://some-ostree-url.com/foo",
+                },
+                "ostree": {
+                    "osname": "some-osname",
+                    "url": "http://some-ostree-url.com/foo",
+                    "ref": "some-ref",
+                    "remote": "some-remote",
+                    "gpg": True,
+                },
+            },
+            "is not valid under any of the given schemas",
+        ),
+
     ],
 )
 def test_schema_validation_bad_apples(test_data, expected_err):