containers / bootc

Boot and upgrade via container images
https://containers.github.io/bootc/
Apache License 2.0
705 stars 80 forks source link

Consider designing bootc as a library to be used by installer applications #542

Open jmpolom opened 5 months ago

jmpolom commented 5 months ago

Right now bootc only seems envisioned as a simple CLI application to install and lifecycle an ostree based system using ostree containers as the install/update payload. Given the inevitability that a use case will necessitate a higher level "installer", bootc could have an API available to use in a higher level rust application that could function itself as the installer. This would enable a distro to create a proper installer application while fully integrating the capabilities of bootc (IE: more evolved than a shell script installer).

jeckersb commented 5 months ago

The vast majority of the code already lives as a separate library crate under https://github.com/containers/bootc/tree/main/lib. The current bootc cli is really just a thin wrapper around the library. It looks like we don't currently publish that on crates.io for general use, but we could start doing so. At the very least if someone wanted to use it as a dependency today they could do so via a cargo git dependency.

jmpolom commented 5 months ago

Yeah I think my point was to perhaps consider this as more of a prominent feature. Obviously it could be included somehow today but the focus seems on it being a standalone tool at the CLI level.

cgwalters commented 5 months ago

Having higher level installers wrap/integrate with bootc install was very much a big design goal from the start. I think we have the essentials of that now with bootc install to-filesystem being there.

This intersects with both https://github.com/containers/bootc/issues/440 and https://github.com/containers/bootc/issues/522

What specific issues for an installer though do you forsee being improved with an API versus a fork/exec model? The main ones are usually things like progress reporting, but we could also do that via either e.g. capnpnp or varlink over a fd.

I'd tend to lean to mark this as a dup of https://github.com/containers/bootc/issues/522 per above.

jmpolom commented 5 months ago

Having higher level installers wrap/integrate with bootc install was very much a big design goal from the start. I think we have the essentials of that now with bootc install to-filesystem being there.

This intersects with both #440 and #522

What specific issues for an installer though do you forsee being improved with an API versus a fork/exec model? The main ones are usually things like progress reporting, but we could also do that via either e.g. capnpnp or varlink over a fd.

Better integration potential and not bringing in a secondary IPC scheme to support (thus requiring whatever interacts with bootc to also support said scheme).

I could agree that just using bootc as an external process checks all the boxes but unfortunately the CLI output right now is not very useful/helpful for integrating with an installer that uses install to-filesystem. See #536.

If the idea is to keep relations with bootc to being something that's just exec'd via the shell or some wrapping application there need to be serious improvements to the ability to configure it to to produce useful, parseable output (such as outputting a path to the ostree deployment directory -- there are probably others here). ostree container image deploy has a flag to get the deployed commit hash. Accoutrements like this are needed for full viability of this model. You could probably cover the vast majority of needs with a few options to tailor the outputs.

For the cases where the bootc CLI interface doesn't cleanly provide what's needed though, an API affords the installer creator maximum ability to get whatever is needed pretty much just subject to the limitations of the language and libraries they're willing to bring in.

I'm also not a huge fan of just creating more CLI apps that output json. It is common but feels like a unix anti-pattern to me. Doing this for a CLI app implicitly required that jq is included in the build if interaction is via shell or bootc gets exec'd from a wrapping application that can deal with the json. Clean simple parseable text ouput would be best for CLI/exec interaction, a la what you can configure from dnf and rpm.

I'd tend to lean to mark this as a dup of #522 per above.

I am certainly not suggesting bootc needs an IPC abstraction beyond what you get from stdin/stdout. If bootc isn't a long lived daemon process I'm really unclear what additional IPC interfaces get you or your users. Either a clean and useful CLI interface or actual native rust API. A whole other IPC interface seems like more to support for minimal additional value but a rust API could be low cost (sounds like bootc is already a good chunk there). Same goes for a CLI. Perhaps separate the business logic into a crate and create a CLI that just uses the available API from the crate. That is all I am really suggesting here.

The ostree-ext API already has a lot but one shouldn't have to create a completely new (competing?) tool from that level up.

cgwalters commented 5 months ago

I am certainly not suggesting bootc needs an IPC abstraction beyond what you get from stdin/stdout. If bootc isn't a long lived daemon process I'm really unclear what additional IPC interfaces get you or your users.

Note that varlink in particular is very much designed to operate over a socketpair() between a parent and child process. When people hear "IPC" they often think about the other end being e.g. a systemd service listening on a socket (or all the way to a DBus like model). But, so can capnpnp (and for that matter, dbus can operate point-to-point, though it is inherently always bidirectional).

Clean simple parseable text ouput would be best for CLI/exec interaction, a la what you can configure from dnf and rpm.

What text output are people parsing from those tools? With rpm there's stuff like --queryformat, sure; but for things like installs - I'm not aware of much that's intended to be machine-parsable from either tool, especially dnf.

jmpolom commented 5 months ago

I am certainly not suggesting bootc needs an IPC abstraction beyond what you get from stdin/stdout. If bootc isn't a long lived daemon process I'm really unclear what additional IPC interfaces get you or your users.

Note that varlink in particular is very much designed to operate over a socketpair() between a parent and child process. When people hear "IPC" they often think about the other end being e.g. a systemd service listening on a socket (or all the way to a DBus like model). But, so can capnpnp (and for that matter, dbus can operate point-to-point, though it is inherently always bidirectional).

Still not convinced an IPC would really vastly improve the user experience. Maybe for some real time updates like status or something as you suggested. Not my need though. That is not the problem that generated this issue.

Definitely think you could get the same effect as an IPC from an API though, at lower cost, and leave the IPC business (if such business is even warranted) to whatever installer application resides above bootc. Instead of choosing what IPC will be used and dictating this to downstream users. I only see more problems this route.

At the moment the bootc CLI is too simplistic to really be of great use to a wrapping installer script or an application that would exec this off and just get to deal with stdin/stdout. One should not have to ostree admin status their way to finding the deployment directory when bootc internally uses that info but just doesn't make it accessible to the user. This is a problem.

Seems like it would be pretty easy to have bootc output an installation summary file somewhere or suppress the status messages (-q flag?) and produce it on stdout? These are the types of improvements that would enhance the user experience.

Clean simple parseable text ouput would be best for CLI/exec interaction, a la what you can configure from dnf and rpm.

What text output are people parsing from those tools? With rpm there's stuff like --queryformat, sure; but for things like installs - I'm not aware of much that's intended to be machine-parsable from either tool, especially dnf.

Parseable might've been the wrong word. Point is clean text output with useful information in it that can be readily used in an ad-hoc shell command or non-interactively in a script. Currently bootc does not today really have much to offer here for installing. bootc status tries to provide this but it only works for a booted system. Maybe bootc status should grow some features to provide install details before first boot?

rpm queryformat is a good example of how that tool can be configured very flexibly to produce useful output for routine shell tasks/scripts. dnf supports the same formats with repoquery. The systemd CLI tools often have similar options to configure output for non-interactive use in scripts.