diff --git a/BREAKINGCHANGES_dev.md b/BREAKINGCHANGES_dev.md index e69de29b..6b4a6c7c 100644 --- a/BREAKINGCHANGES_dev.md +++ b/BREAKINGCHANGES_dev.md @@ -0,0 +1,3 @@ +# Containers step + ++ New default behavior: Docker is the runtime selected by default. This can be overridden by setting the `container.runtime` option in the configuration TOML to "podman". diff --git a/config.example.toml b/config.example.toml index 68beee63..c86fc99d 100644 --- a/config.example.toml +++ b/config.example.toml @@ -244,6 +244,8 @@ [containers] # Specify the containers to ignore while updating (Wildcard supported) # ignored_containers = ["ghcr.io/rancher-sandbox/rancher-desktop/rdx-proxy:latest", "docker.io*"] +# Specify the runtime to use for containers (default: "docker", allowed values: "docker", "podman") +# runtime = "podman" [lensfun] # If disabled, Topgrade invokes `lensfun‑update‑data` without root priviledge, diff --git a/src/config.rs b/src/config.rs index 638d268b..0f65a02e 100644 --- a/src/config.rs +++ b/src/config.rs @@ -5,7 +5,7 @@ use std::fs::{write, File}; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::Command; -use std::{env, fs}; +use std::{env, fmt, fs}; use clap::{Parser, ValueEnum}; use clap_complete::Shell; @@ -181,6 +181,7 @@ pub struct Include { pub struct Containers { #[merge(strategy = crate::utils::merge_strategies::vec_prepend_opt)] ignored_containers: Option>, + runtime: Option, } #[derive(Deserialize, Default, Debug, Merge)] @@ -287,6 +288,22 @@ pub enum ArchPackageManager { Yay, } +#[derive(Clone, Copy, Debug, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ContainerRuntime { + Docker, + Podman, +} + +impl fmt::Display for ContainerRuntime { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + ContainerRuntime::Docker => write!(f, "docker"), + ContainerRuntime::Podman => write!(f, "podman"), + } + } +} + #[derive(Deserialize, Default, Debug, Merge)] #[serde(deny_unknown_fields)] pub struct Linux { @@ -885,6 +902,16 @@ impl Config { .and_then(|containers| containers.ignored_containers.as_ref()) } + /// The preferred runtime for container updates (podman / docker). + pub fn containers_runtime(&self) -> ContainerRuntime { + self.config_file + .containers + .as_ref() + .unwrap() + .runtime + .unwrap_or(ContainerRuntime::Docker) // defaults to a popular choice + } + /// Tell whether the specified step should run. /// /// If the step appears either in the `--disable` command line argument diff --git a/src/steps/containers.rs b/src/steps/containers.rs index 218009e8..89871c58 100644 --- a/src/steps/containers.rs +++ b/src/steps/containers.rs @@ -120,8 +120,9 @@ fn list_containers(crt: &Path, ignored_containers: Option<&Vec>) -> Resu } pub fn run_containers(ctx: &ExecutionContext) -> Result<()> { - // Prefer podman, fall back to docker if not present - let crt = require("podman").or_else(|_| require("docker"))?; + // Check what runtime is specified in the config + let container_runtime = ctx.config().containers_runtime().to_string(); + let crt = require(container_runtime)?; debug!("Using container runtime '{}'", crt.display()); print_separator("Containers");