Skip to content

Commit

Permalink
install: Check if running in container earlier
Browse files Browse the repository at this point in the history
Previously, the check to verify install to-filesystem is being run
within a container happened fairly late in prepare_install. This moves
the check up before some of the other container specific checks. Now,
the error should occur when trying a basic install to-filesystem
invocation, e.g. `bootc install to-filesystem /var/mnt`.

This also adds a test to verify the error occurs with minimal arguments
and adds host_is_container to the global state.

Signed-off-by: Chris Kyrouac <[email protected]>
  • Loading branch information
ckyrouac committed Nov 8, 2024
1 parent 66b5aaa commit c0c4ccf
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
4 changes: 4 additions & 0 deletions lib/src/containerenv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub(crate) struct ContainerExecutionInfo {
pub(crate) rootless: Option<String>,
}

pub(crate) fn is_container(rootfs: &Dir) -> bool {
rootfs.exists(PATH)
}

/// Load and parse the `/run/.containerenv` file.
#[context("Querying container")]
pub(crate) fn get_container_execution_info(rootfs: &Dir) -> Result<ContainerExecutionInfo> {
Expand Down
10 changes: 8 additions & 2 deletions lib/src/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ pub(crate) struct State {
pub(crate) install_config: Option<config::InstallConfiguration>,
/// The parsed contents of the authorized_keys (not the file path)
pub(crate) root_ssh_authorized_keys: Option<String>,
#[allow(dead_code)]
pub(crate) host_is_container: bool,
/// The root filesystem of the running container
pub(crate) container_root: Dir,
pub(crate) tempdir: TempDir,
Expand Down Expand Up @@ -1159,14 +1161,17 @@ async fn prepare_install(
tracing::trace!("Preparing install");
// We need full root privileges, i.e. --privileged in podman
crate::cli::require_root()?;
require_host_pidns()?;

let rootfs = cap_std::fs::Dir::open_ambient_dir("/", cap_std::ambient_authority())
.context("Opening /")?;

let host_is_container = crate::containerenv::is_container(&rootfs);
let external_source = source_opts.source_imgref.is_some();
let source = match source_opts.source_imgref {
None => {
if !host_is_container {
anyhow::bail!("Either --source-imgref must be defined or this command must be executed inside a podman container.")
}
require_host_pidns()?;
// Out of conservatism we only verify the host userns path when we're expecting
// to do a self-install (e.g. not bootc-image-builder or equivalent).
require_host_userns()?;
Expand Down Expand Up @@ -1274,6 +1279,7 @@ async fn prepare_install(
root_ssh_authorized_keys,
container_root: rootfs,
tempdir,
host_is_container,
});

Ok(state)
Expand Down
9 changes: 9 additions & 0 deletions plans/test-23-install-outside-container.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
provision:
how: virtual
# Generated by make test-tmt
image: file://./target/testvm/disk.qcow2
disk: 20
summary: Execute tests for installing outside of a container
execute:
how: tmt
script: exec nu tests/booted/test-install-outside-container.nu
14 changes: 14 additions & 0 deletions tests/booted/test-install-outside-container.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use std assert
use tap.nu

# setup filesystem
mkdir /var/mnt
truncate -s 100M disk.img
mkfs.ext4 disk.img
mount -o loop disk.img /var/mnt

# attempt to install to filesystem without specifying a source-imgref
let result = bootc install to-filesystem /var/mnt e>| ansi strip
assert equal $result "ERROR Installing to filesystem: Either --source-imgref must be defined or this command must be executed inside a podman container."

tap ok

0 comments on commit c0c4ccf

Please sign in to comment.