Skip to content

Commit

Permalink
install: Add to-existing-root
Browse files Browse the repository at this point in the history
This is just mild sugar on top of the existing `to-filesystem`
right now.  But, I think we can do more with this later.

Partially addresses #380
  • Loading branch information
cgwalters committed Mar 8, 2024
1 parent 5390a98 commit e3aba49
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 8 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,5 @@ jobs:
sudo chattr -i /ostree/deploy/default/deploy/*
sudo rm /ostree/deploy/default -rf
sudo podman run --rm -ti --privileged --env BOOTC_SKIP_SELINUX_HOST_CHECK=1 --env RUST_LOG=debug -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
quay.io/centos-bootc/centos-bootc-dev:stream9 bootc install to-filesystem \
--replace=alongside /target
quay.io/centos-bootc/centos-bootc-dev:stream9 bootc install to-existing-root
sudo ls -ldZ / /ostree/deploy/default/deploy/* /ostree/deploy/default/deploy/*/etc
20 changes: 15 additions & 5 deletions docs/src/bootc-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ podman run --rm --privileged --pid=host --security-opt label=type:unconfined_t

Notice that we use `--generic-image` for this use case.

### Using `bootc install to-filesystem --replace=alongside`
### Using `bootc install to-existing-root`

This is a variant of `install to-filesystem`, which maximizes convenience for using
an existing Linux system, converting it into the target container image. Note that
Expand All @@ -241,13 +241,23 @@ The core command should look like this (root/elevated permission required):
podman run --rm --privileged -v /var/lib/containers:/var/lib/containers -v /:/target \
--pid=host --security-opt label=type:unconfined_t \
<image> \
bootc install to-filesystem --replace=alongside /target
bootc install to-existing-root
```

At the current time, leftover data in `/` is **NOT** automatically cleaned up. This can
It is assumed in this command that the target rootfs is pased via `-v /:/target` at this time.

As noted above, the data in `/boot` will be wiped, but everything else in the existing
operating `/` is **NOT** automatically cleaned up. This can
be useful, because it allows the new image to automatically import data from the previous
host system! For example, things like SSH keys or container images can be copied
and then deleted from the original.
host system! For example, container images, database, user home directory data, config
files in `/etc` are all available after the subsequent reboot in `/sysroot` (which
is the "physical root").

A special case of this trick is using the `--root-ssh-authorized-keys` flag to inherit
root's SSH keys (which may have been injected from e.g. cloud instance userdata
via a tool like `cloud-init`). To do this, just add
`--root-ssh-authorized-keys /target/root/.ssh/authorized_keys`
to the above.

### Using `bootc install to-filesystem --source-imgref <imgref>`

Expand Down
4 changes: 4 additions & 0 deletions lib/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ pub(crate) enum InstallOpts {
ToDisk(crate::install::InstallToDiskOpts),
/// Install to the target filesystem
ToFilesystem(crate::install::InstallToFilesystemOpts),
ToExistingRoot(crate::install::InstallToExistingRootOpts),
/// Output JSON to stdout that contains the merged installation configuration
/// as it may be relevant to calling processes using `install to-filesystem`
/// that want to honor e.g. `root-fs-type`.
Expand Down Expand Up @@ -533,6 +534,9 @@ async fn run_from_opt(opt: Opt) -> Result<()> {
Opt::Install(opts) => match opts {
InstallOpts::ToDisk(opts) => crate::install::install_to_disk(opts).await,
InstallOpts::ToFilesystem(opts) => crate::install::install_to_filesystem(opts).await,
InstallOpts::ToExistingRoot(opts) => {
crate::install::install_to_existing_root(opts).await
}
InstallOpts::PrintConfiguration => crate::install::print_configuration(),
},
#[cfg(feature = "install")]
Expand Down
38 changes: 38 additions & 0 deletions lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,28 @@ pub(crate) struct InstallToFilesystemOpts {
pub(crate) config_opts: InstallConfigOpts,
}

/// Perform an installation to the host root filesystem.
#[derive(Debug, Clone, clap::Parser)]
pub(crate) struct InstallToExistingRootOpts {
/// Configure how existing data is treated.
#[clap(long, default_value = "alongside")]
pub(crate) replace: Option<ReplaceMode>,

#[clap(flatten)]
pub(crate) source_opts: InstallSourceOpts,

#[clap(flatten)]
pub(crate) target_opts: InstallTargetOpts,

#[clap(flatten)]
pub(crate) config_opts: InstallConfigOpts,

/// Path to the mounted root; it's expected to invoke podman with
/// `-v /:/target`, then supplying this argument is unnecessary.
#[clap(default_value = "/target")]
pub(crate) root_path: Utf8PathBuf,
}

/// Global state captured from the container.
#[derive(Debug, Clone)]
pub(crate) struct SourceInfo {
Expand Down Expand Up @@ -1355,6 +1377,22 @@ pub(crate) async fn install_to_filesystem(opts: InstallToFilesystemOpts) -> Resu
Ok(())
}

pub(crate) async fn install_to_existing_root(opts: InstallToExistingRootOpts) -> Result<()> {
let opts = InstallToFilesystemOpts {
filesystem_opts: InstallTargetFilesystemOpts {
root_path: opts.root_path,
root_mount_spec: None,
boot_mount_spec: None,
replace: opts.replace,
},
source_opts: opts.source_opts,
target_opts: opts.target_opts,
config_opts: opts.config_opts,
};

install_to_filesystem(opts).await
}

#[test]
fn install_opts_serializable() {
let c: InstallToDiskOpts = serde_json::from_value(serde_json::json!({
Expand Down
2 changes: 1 addition & 1 deletion tests/integration/playbooks/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
-v /var/lib/containers:/var/lib/containers \
--security-opt label=type:unconfined_t \
{{ test_image_url }} \
bootc install to-filesystem --replace=alongside /target"
bootc install to-existing-root"
become: true

- name: Reboot to deploy new system
Expand Down

0 comments on commit e3aba49

Please sign in to comment.