diff --git a/src/bootupd.rs b/src/bootupd.rs index 13a04424..f912d439 100644 --- a/src/bootupd.rs +++ b/src/bootupd.rs @@ -243,8 +243,13 @@ pub(crate) fn print_status(status: &Status) -> Result<()> { if status.adoptable.is_empty() { println!("No components are adoptable."); } - for (name, version) in status.adoptable.iter() { - println!("Adoptable: {}: {}", name, version.version); + for (name, adopt) in status.adoptable.iter() { + let ver = &adopt.version.version; + if adopt.confident { + println!("Detected: {}: {}", name, ver); + } else { + println!("Adoptable: {}: {}", name, ver); + } } if let Some(coreos_aleph) = coreos::get_aleph_version()? { @@ -266,7 +271,7 @@ pub(crate) fn print_status(status: &Status) -> Result<()> { pub(crate) fn client_run_update(c: &mut ipc::ClientToDaemonConnection) -> Result<()> { let status: Status = c.send(&ClientRequest::Status)?; - if status.components.is_empty() { + if status.components.is_empty() && status.adoptable.is_empty() { println!("No components installed."); return Ok(()); } @@ -303,6 +308,17 @@ pub(crate) fn client_run_update(c: &mut ipc::ClientToDaemonConnection) -> Result } updated = true; } + for (name, adoptable) in status.adoptable.iter() { + if adoptable.confident { + let r: ContentMetadata = c.send(&ClientRequest::AdoptAndUpdate { + component: name.to_string(), + })?; + println!("Adopted and updated: {}: {}", name, r.version); + updated = true; + } else { + println!("Component {} requires explicit adopt-and-update", name); + } + } if !updated { println!("No update available for any component."); } diff --git a/src/component.rs b/src/component.rs index 141a5cde..089c9ad6 100644 --- a/src/component.rs +++ b/src/component.rs @@ -27,7 +27,7 @@ pub(crate) trait Component { /// In an operating system whose initially booted disk image is not /// using bootupd, detect whether it looks like the component exists /// and "synthesize" content metadata from it. - fn query_adopt(&self) -> Result>; + fn query_adopt(&self) -> Result>; /// Given an adoptable system and an update, perform the update. fn adopt_update(&self, update: &ContentMetadata) -> Result; diff --git a/src/efi.rs b/src/efi.rs index d0ce8796..007a4d55 100644 --- a/src/efi.rs +++ b/src/efi.rs @@ -49,7 +49,7 @@ impl Component for EFI { "EFI" } - fn query_adopt(&self) -> Result> { + fn query_adopt(&self) -> Result> { let esp = self.open_esp_optional()?; if esp.is_none() { log::trace!("No ESP detected"); @@ -67,7 +67,10 @@ impl Component for EFI { version: coreos_aleph.aleph.imgid, }; log::trace!("EFI adoptable: {:?}", &meta); - Ok(Some(meta)) + Ok(Some(Adoptable { + version: meta, + confident: true, + })) } /// Given an adoptable system and an update, perform the update. @@ -90,7 +93,7 @@ impl Component for EFI { Ok(InstalledContent { meta: updatemeta.clone(), filetree: Some(updatef), - adopted_from: Some(meta), + adopted_from: Some(meta.version), }) } diff --git a/src/model.rs b/src/model.rs index eee23a7e..89018d02 100644 --- a/src/model.rs +++ b/src/model.rs @@ -95,6 +95,16 @@ pub(crate) struct ComponentStatus { pub(crate) adopted_from: Option, } +/// Information on a component that can be adopted +#[derive(Serialize, Deserialize, Debug)] +#[serde(rename_all = "kebab-case")] +pub(crate) struct Adoptable { + /// A synthetic version + pub(crate) version: ContentMetadata, + /// True if we are likely to be able to reliably update this system + pub(crate) confident: bool, +} + /// Representation of bootupd's worldview at a point in time. /// This is intended to be a stable format that is output by `bootupctl status --json` /// and parsed by higher level management tools. Transitively then @@ -106,7 +116,7 @@ pub(crate) struct Status { /// Maps a component name to status pub(crate) components: BTreeMap, /// Components that appear to be installed, not via bootupd - pub(crate) adoptable: BTreeMap, + pub(crate) adoptable: BTreeMap, } #[cfg(test)] diff --git a/tests/e2e-adopt/e2e-adopt-in-vm.sh b/tests/e2e-adopt/e2e-adopt-in-vm.sh index f7f6c4dc..9d90d4a9 100755 --- a/tests/e2e-adopt/e2e-adopt-in-vm.sh +++ b/tests/e2e-adopt/e2e-adopt-in-vm.sh @@ -96,7 +96,7 @@ fi bootupctl status | tee out.txt assert_file_has_content_literal out.txt 'No components installed.' -assert_file_has_content out.txt 'Adoptable: EFI: .*coreos.*-qemu.*' +assert_file_has_content out.txt 'Detected: EFI: .*coreos.*-qemu.*' bootupctl validate | tee out.txt assert_file_has_content_literal out.txt 'No components installed.' @@ -105,7 +105,8 @@ assert_not_file_has_content_literal out.txt "Validated" assert_not_has_file /boot/bootupd-state.json ok validate -bootupctl adopt-and-update | tee out.txt +# Explicitly testing https://github.com/coreos/bootupd/issues/103 +bootupctl update | tee out.txt assert_file_has_content out.txt 'Adopted and updated: EFI: grub2-efi-x64' ok adoption