diff --git a/src/builder/commands/docker.rs b/src/builder/commands/docker.rs index 5e29f5af..dd40d988 100644 --- a/src/builder/commands/docker.rs +++ b/src/builder/commands/docker.rs @@ -27,12 +27,16 @@ use quire::{ #[cfg(feature="containers")] use crate::{ + builder::commands::alpine, + builder::commands::ubuntu, builder::commands::tarcmd::TarCmd, + builder::distrib::DistroBox, capsule::packages as capsule, container::util::clean_dir, file_util::{Dir, Lock}, }; use crate::build_step::{BuildStep, Config, Digest, Guard, StepError, VersionError}; +use crate::builder::distrib::parse_release_file; const DEFAULT_REGISTRY_HOST: &str = "registry-1.docker.io"; const DEFAULT_IMAGE_NAMESPACE: &str = "library"; @@ -148,7 +152,8 @@ impl BuildStep for DockerImage { .entry_handler(whiteout_entry_handler) .unpack()?; } - Ok(()) + + detect_os_release(guard) } fn is_dependent_on(&self) -> Option<&str> { @@ -316,4 +321,48 @@ async fn download_blob( Err(e) => return Err(format!("{}", e)), } Ok(blob_path) -} \ No newline at end of file +} + +#[cfg(feature="containers")] +fn detect_os_release(guard: &mut Guard) -> Result<(), StepError> { + if let Ok(release_vars) = parse_release_file("/vagga/root/etc/os-release") { + let os_id = release_vars.get("ID").map(String::as_str); + match os_id { + Some("ubuntu") => { + if let Some(codename) = release_vars.get("UBUNTU_CODENAME") { + let release = ubuntu::UbuntuRelease { + codename: Some(codename.clone()), + version: None, + url: None, + arch: String::from("amd64"), // TODO(tailhook) detect + keep_chfn_command: false, + eatmydata: true, + }; + ubuntu::build::configure(guard, release)?; + guard.distro.specific(|u: &mut ubuntu::Distro| { + ubuntu::build::init_ubuntu_core(&mut guard.ctx, u) + .map_err(|e| StepError::Compat(e)) + })?; + } else { + warn!("Missing ubuntu codename"); + } + } + Some("alpine") => { + if let Some(version_id) = release_vars.get("VERSION_ID") { + if let Some((alpine_version, _)) = version_id.rsplit_once('.') { + let distro = alpine::Distro { + version: format!("v{}", alpine_version), + mirror: guard.ctx.settings.alpine_mirror().to_string(), + base_setup: false, + apk_update: true, + }; + guard.distro.set(distro)?; + } + } + } + Some(_) | None => {} + } + } + + Ok(()) +} diff --git a/src/builder/commands/ubuntu.rs b/src/builder/commands/ubuntu.rs index 5bfa1fd4..b9e61594 100644 --- a/src/builder/commands/ubuntu.rs +++ b/src/builder/commands/ubuntu.rs @@ -1,7 +1,7 @@ use std::fs::{remove_dir_all, rename, set_permissions, Permissions}; use std::os::unix::fs::{symlink}; use std::fs::File; -use std::io::{self, BufReader, Write}; +use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::ffi::OsStr; @@ -916,11 +916,11 @@ impl BuildStep for UbuntuRelease { } #[cfg(feature="containers")] -mod build { - use std::io::BufRead; +pub mod build { use std::os::unix::fs::PermissionsExt; use unshare::Command; + use crate::builder::distrib::parse_release_file; use crate::capsule::download::download_file; @@ -928,25 +928,10 @@ mod build { pub fn read_ubuntu_codename() -> Result { - let lsb_release_path = "/vagga/root/etc/lsb-release"; - let lsb_release_file = BufReader::new( - try_msg!(File::open(&Path::new(lsb_release_path)), - "Error reading /etc/lsb-release: {err}")); - - for line in lsb_release_file.lines() { - let line = try_msg!(line, "Error reading lsb file: {err}"); - if let Some(equals_pos) = line.find('=') { - let key = line[..equals_pos].trim(); - - if key == "DISTRIB_CODENAME" { - let value = line[(equals_pos + 1)..].trim(); - return Ok(value.to_string()); - } - } - } - - Err(format!("Coudn't read codename from '{lsb_release_path}'", - lsb_release_path=lsb_release_path)) + let release_vars = parse_release_file("/vagga/root/etc/lsb-release")?; + release_vars.get("DISTRIB_CODENAME") + .map(|v| v.clone()) + .ok_or(format!("Missing DISTRIB_CODENAME variable")) } pub fn fetch_ubuntu_core(ctx: &mut Context, rel: &UbuntuRelease) @@ -1103,7 +1088,7 @@ mod build { pub fn configure(guard: &mut Guard, config: UbuntuRelease) -> Result<(), StepError> { - guard.distro.set(Distro { + let distro = Distro { eatmydata: if config.eatmydata { EatMyData::Need } else { EatMyData::No }, config, codename: None, // unknown yet @@ -1112,8 +1097,10 @@ mod build { apt_hkps: AptHkps::No, has_indices: false, has_universe: false, - })?; - configure_common(&mut guard.ctx) + }; + guard.distro.set(distro)?; + configure_common(&mut guard.ctx)?; + Ok(()) } pub fn configure_common(ctx: &mut Context) -> Result<(), StepError> { diff --git a/src/builder/distrib.rs b/src/builder/distrib.rs index 8f19db17..4d52aa4d 100644 --- a/src/builder/distrib.rs +++ b/src/builder/distrib.rs @@ -1,3 +1,8 @@ +use std::collections::HashMap; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::Path; + use mopa::{Any, mopafy}; use crate::builder::commands::alpine; @@ -102,3 +107,30 @@ impl DistroBox for Box { Ok(()) } } + +pub fn parse_release_file( + path: impl AsRef +) -> Result, String> { + let release_path = path.as_ref(); + let release_file = BufReader::new( + try_msg!( + File::open(release_path), + "Error opening release file {path:?}: {err}", path=release_path + ) + ); + + let mut vars = HashMap::new(); + for line in release_file.lines() { + let line = try_msg!( + line, + "Error reading release file {path:?}: {err}", path=release_path + ); + if let Some(equals_pos) = line.find('=') { + let key = line[..equals_pos].trim(); + let value = line[(equals_pos + 1)..].trim(); + vars.insert(key.to_string(), value.to_string()); + } + } + + Ok(vars) +} diff --git a/tests/docker.bats b/tests/docker.bats index 4625c403..7c22a5cc 100644 --- a/tests/docker.bats +++ b/tests/docker.bats @@ -13,6 +13,24 @@ setup() { assert_line "Hello from Docker!" } +@test "docker: detect ubuntu" { + run vagga _build ubuntu + assert_success + + run vagga _run ubuntu sh -c 'echo 21*2 | bc' + assert_success + assert_output 42 +} + +@test "docker: detect alpine" { + run vagga _build alpine + assert_success + + run vagga _run alpine sh -c 'echo 21*2 | bc' + assert_success + assert_output 42 +} + @test "docker: python" { run vagga _build python assert_success diff --git a/tests/docker/vagga.yaml b/tests/docker/vagga.yaml index 818022bf..70921c6e 100644 --- a/tests/docker/vagga.yaml +++ b/tests/docker/vagga.yaml @@ -4,6 +4,16 @@ containers: - !DockerImage image: library/hello-world + ubuntu: + setup: + - !DockerImage ubuntu:focal + - !Install [bc] + + alpine: + setup: + - !DockerImage alpine:3.15 + - !Install [bc] + python: setup: - !DockerImage