From 4e99e80c4a7e70dc306973152fc15465a4300d2d Mon Sep 17 00:00:00 2001 From: Dusty Mabe Date: Thu, 28 Sep 2023 16:52:31 -0400 Subject: [PATCH] osbuild/util: hoist ostree code into util/ostree Prep for sharing with other stages later. --- osbuild/util/ostree.py | 19 +++++++++++++++++++ stages/org.osbuild.ostree.config | 16 +++------------- stages/org.osbuild.ostree.deploy | 20 +++++--------------- stages/org.osbuild.ostree.init | 10 ++-------- stages/org.osbuild.ostree.init-fs | 16 +++------------- stages/org.osbuild.ostree.os-init | 14 ++------------ stages/org.osbuild.ostree.passwd | 24 ++++++++---------------- stages/org.osbuild.ostree.pull | 28 +++++----------------------- stages/org.osbuild.ostree.remotes | 30 ++++++++++-------------------- 9 files changed, 57 insertions(+), 120 deletions(-) diff --git a/osbuild/util/ostree.py b/osbuild/util/ostree.py index 6c5e4232..5c810a70 100644 --- a/osbuild/util/ostree.py +++ b/osbuild/util/ostree.py @@ -153,6 +153,25 @@ def show(repo: PathLike, checksum: str) -> str: return msg +def cli(*args, _input=None, **kwargs): + """Thin wrapper for running the ostree CLI""" + args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] + print("ostree " + " ".join(args), file=sys.stderr) + subprocess.run(["ostree"] + args, + encoding="utf8", + stdout=sys.stderr, + input=_input, + check=True) + + +def parse_input_commits(commits): + """Parse ostree input commits and return the repo path and refs specified""" + data = commits["data"] + refs = data["refs"] + assert refs, "Need at least one commit" + return commits["path"], data["refs"] + + def deployment_path(root: PathLike, osname: str, ref: str, serial: int): """Return the path to a deployment given the parameters""" diff --git a/stages/org.osbuild.ostree.config b/stages/org.osbuild.ostree.config index b004fbaf..91df555d 100755 --- a/stages/org.osbuild.ostree.config +++ b/stages/org.osbuild.ostree.config @@ -11,10 +11,10 @@ See `ostree.repo-config(5)` for more information. """ import os -import subprocess import sys import osbuild.api +from osbuild.util import ostree SCHEMA = """ "additionalProperties": false, @@ -51,28 +51,18 @@ SCHEMA = """ """ -def ostree(*args, _input=None, **kwargs): - args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] - print("ostree " + " ".join(args), file=sys.stderr) - subprocess.run(["ostree"] + args, - encoding="utf8", - stdout=sys.stderr, - input=_input, - check=True) - - def main(tree, options): repo = os.path.join(tree, options["repo"].lstrip("/")) sysroot_options = options["config"].get("sysroot", {}) bootloader = sysroot_options.get("bootloader") if bootloader: - ostree("config", "set", "sysroot.bootloader", bootloader, repo=repo) + ostree.cli("config", "set", "sysroot.bootloader", bootloader, repo=repo) readonly = sysroot_options.get("readonly") if readonly is not None: # can be False, which we would want to set ro = "true" if readonly else "false" - ostree("config", "set", "sysroot.readonly", ro, repo=repo) + ostree.cli("config", "set", "sysroot.readonly", ro, repo=repo) if __name__ == '__main__': diff --git a/stages/org.osbuild.ostree.deploy b/stages/org.osbuild.ostree.deploy index 3d65ec70..c0c52730 100755 --- a/stages/org.osbuild.ostree.deploy +++ b/stages/org.osbuild.ostree.deploy @@ -20,10 +20,10 @@ the sysroot and the deployments. Additional kernel options can be passed via """ import os -import subprocess import sys import osbuild.api +from osbuild.util import ostree from osbuild.util.mnt import MountGuard CAPABILITIES = ["CAP_MAC_ADMIN"] @@ -85,16 +85,6 @@ SCHEMA_2 = """ """ -def ostree(*args, _input=None, **kwargs): - args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] - print("ostree " + " ".join(args), file=sys.stderr) - subprocess.run(["ostree"] + args, - encoding="utf8", - stdout=sys.stderr, - input=_input, - check=True) - - def make_fs_identifier(desc): for key in ["uuid", "label"]: val = desc.get(key) @@ -129,10 +119,10 @@ def main(tree, options): path = os.path.join(tree, path) mounter.mount(path, path) - ostree("admin", "deploy", ref, - *kargs, - sysroot=tree, - os=osname) + ostree.cli("admin", "deploy", ref, + *kargs, + sysroot=tree, + os=osname) if __name__ == '__main__': diff --git a/stages/org.osbuild.ostree.init b/stages/org.osbuild.ostree.init index 47d79dc7..66ec5621 100755 --- a/stages/org.osbuild.ostree.init +++ b/stages/org.osbuild.ostree.init @@ -10,10 +10,10 @@ See the ostree-init(1) man page for more details. """ import os -import subprocess import sys import osbuild.api +from osbuild.util import ostree SCHEMA = """ "additionalProperties": false, @@ -41,13 +41,7 @@ def main(tree, options): parent = os.path.dirname(repo) os.makedirs(parent, exist_ok=True) - subprocess.run(["ostree", - "init", - "-v", - f"--mode={mode}", - f"--repo={repo}"], - stdout=sys.stderr, - check=True) + ostree.cli("init", "-v", mode=mode, repo=repo) if __name__ == '__main__': diff --git a/stages/org.osbuild.ostree.init-fs b/stages/org.osbuild.ostree.init-fs index 9cc29a55..7b7187b2 100755 --- a/stages/org.osbuild.ostree.init-fs +++ b/stages/org.osbuild.ostree.init-fs @@ -6,30 +6,20 @@ Creates the basic file system layout for an OSTree based system. """ -import subprocess import sys import osbuild.api +from osbuild.util import ostree SCHEMA = """ "additionalProperties": false """ -def ostree(*args, _input=None, **kwargs): - args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] - print("ostree " + " ".join(args), file=sys.stderr) - subprocess.run(["ostree"] + args, - encoding="utf8", - stdout=sys.stderr, - input=_input, - check=True) - - def main(tree): - ostree("admin", "init-fs", "--modern", tree, - sysroot=tree) + ostree.cli("admin", "init-fs", "--modern", tree, + sysroot=tree) return 0 diff --git a/stages/org.osbuild.ostree.os-init b/stages/org.osbuild.ostree.os-init index 8c71bd50..654e2825 100755 --- a/stages/org.osbuild.ostree.os-init +++ b/stages/org.osbuild.ostree.os-init @@ -8,10 +8,10 @@ name `osname`. [1] https://ostree.readthedocs.io/en/latest/manual/deployment/ """ -import subprocess import sys import osbuild.api +from osbuild.util import ostree SCHEMA = """ "required": ["osname"], @@ -24,20 +24,10 @@ SCHEMA = """ """ -def ostree(*args, _input=None, **kwargs): - args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] - print("ostree " + " ".join(args), file=sys.stderr) - subprocess.run(["ostree"] + args, - encoding="utf8", - stdout=sys.stderr, - input=_input, - check=True) - - def main(tree, options): osname = options["osname"] - ostree("admin", "os-init", osname, sysroot=tree) + ostree.cli("admin", "os-init", osname, sysroot=tree) return 0 diff --git a/stages/org.osbuild.ostree.passwd b/stages/org.osbuild.ostree.passwd index 5e2bddbf..85fd8775 100755 --- a/stages/org.osbuild.ostree.passwd +++ b/stages/org.osbuild.ostree.passwd @@ -17,7 +17,7 @@ import os import sys import osbuild.api -from osbuild.util.ostree import PasswdLike, SubIdsDB +from osbuild.util import ostree SCHEMA_2 = """ "options": { @@ -41,24 +41,16 @@ SUBUID_PATH = "etc/subuid" SUBGID_PATH = "etc/subgid" -def parse_input(inputs): - commits = inputs["commits"] - source_root = commits["path"] - data = commits["data"] - refs = data["refs"] - assert refs, "Need at least one commit" - assert len(refs) == 1, "Only one commit is currently supported" - return source_root, refs - - # pylint: disable=too-many-statements def main(tree, inputs, _options): - source_root, refs = parse_input(inputs) + source_root, refs = ostree.parse_input_commits(inputs["commits"]) + assert refs, "Need at least one commit" + assert len(refs) == 1, "Only one commit is currently supported" os.makedirs(os.path.join(tree, "etc"), exist_ok=True) - subuids = SubIdsDB() - subgids = SubIdsDB() + subuids = ostree.SubIdsDB() + subgids = ostree.SubIdsDB() # Only once ref (commit) is currently supported, so this loop will run exactly once for commit, data in refs.items(): @@ -68,14 +60,14 @@ def main(tree, inputs, _options): # Merge /usr/etc/passwd with /usr/lib/passwd from the checkout and store it in the buildroot # "tree" directory. Entries in /usr/etc/passwd have a precedence, but the file does not # necessarily exist. - passwd = PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/passwd"), allow_missing_file=True) + passwd = ostree.PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/passwd"), allow_missing_file=True) passwd.merge_with_file(os.path.join(checkout_root, "usr/lib/passwd"), allow_missing_file=False) passwd.dump_to_file(os.path.join(tree, "etc/passwd")) # Merge /usr/etc/group with /usr/lib/group from the checkout and store it in the buildroot # "tree" directory. Entries in /usr/etc/group have a precedence, but the file does not # necessarily exist. - passwd = PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/group"), allow_missing_file=True) + passwd = ostree.PasswdLike.from_file(os.path.join(checkout_root, "usr/etc/group"), allow_missing_file=True) passwd.merge_with_file(os.path.join(checkout_root, "usr/lib/group"), allow_missing_file=False) passwd.dump_to_file(os.path.join(tree, "etc/group")) diff --git a/stages/org.osbuild.ostree.pull b/stages/org.osbuild.ostree.pull index 9fb40e7c..c862bd85 100755 --- a/stages/org.osbuild.ostree.pull +++ b/stages/org.osbuild.ostree.pull @@ -12,10 +12,10 @@ that to pull the commits. import os -import subprocess import sys import osbuild.api +from osbuild.util import ostree CAPABILITIES = ["CAP_MAC_ADMIN"] @@ -49,27 +49,9 @@ SCHEMA_2 = """ """ -def ostree(*args, _input=None, **kwargs): - args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] - print("ostree " + " ".join(args), file=sys.stderr) - subprocess.run(["ostree"] + args, - encoding="utf8", - stdout=sys.stderr, - input=_input, - check=True) - - -def parse_input(inputs): - commits = inputs["commits"] - data = commits["data"] - refs = data["refs"] - assert refs, "Need at least one commit" - return commits["path"], data["refs"] - - # pylint: disable=too-many-statements def main(tree, inputs, options): - source_repo, commits = parse_input(inputs) + source_repo, commits = ostree.parse_input_commits(inputs["commits"]) repo = options["repo"] remote = options.get("remote") target = os.path.join(tree, repo.lstrip("/")) @@ -81,9 +63,9 @@ def main(tree, inputs, options): if remote: extra_args.append(f'--remote={remote}') - ostree("pull-local", source_repo, ref, - *extra_args, - repo=target) + ostree.cli("pull-local", source_repo, ref, + *extra_args, + repo=target) if __name__ == '__main__': diff --git a/stages/org.osbuild.ostree.remotes b/stages/org.osbuild.ostree.remotes index 60fe21de..928bdffe 100755 --- a/stages/org.osbuild.ostree.remotes +++ b/stages/org.osbuild.ostree.remotes @@ -5,10 +5,10 @@ Configure OSTree remotes for a repository. import os -import subprocess import sys import osbuild.api +from osbuild.util import ostree SCHEMA = """ "additionalProperties": false, @@ -66,16 +66,6 @@ SCHEMA = """ """ -def ostree(*args, _input=None, **kwargs): - args = list(args) + [f'--{k}={v}' for k, v in kwargs.items()] - print("ostree " + " ".join(args), file=sys.stderr) - subprocess.run(["ostree"] + args, - encoding="utf8", - stdout=sys.stderr, - input=_input, - check=True) - - def main(tree, options): repo = options["repo"] remotes = options.get("remotes", []) @@ -101,17 +91,17 @@ def main(tree, options): if contenturl: extra_args.append(f"--set=contenturl={contenturl}") - ostree("remote", "add", - "--if-not-exists", - *extra_args, - name, url, - *branches, - repo=target) + ostree.cli("remote", "add", + "--if-not-exists", + *extra_args, + name, url, + *branches, + repo=target) for key in gpgkeys: - ostree("remote", "gpg-import", "--stdin", name, - repo=target, - _input=key) + ostree.cli("remote", "gpg-import", "--stdin", name, + repo=target, + _input=key) if __name__ == '__main__':