bootc_lib/bootc_composefs/
switch.rs1use anyhow::{Context, Result};
2use fn_error_context::context;
3
4use crate::{
5 bootc_composefs::{
6 state::update_target_imgref_in_origin,
7 status::get_composefs_status,
8 update::{DoUpgradeOpts, UpdateAction, do_upgrade, is_image_pulled, validate_update},
9 },
10 cli::{SwitchOpts, imgref_for_switch},
11 store::{BootedComposefs, Storage},
12};
13
14#[context("Composefs Switching")]
15pub(crate) async fn switch_composefs(
16 opts: SwitchOpts,
17 storage: &Storage,
18 booted_cfs: &BootedComposefs,
19) -> Result<()> {
20 let target = imgref_for_switch(&opts)?;
21 let host = get_composefs_status(storage, booted_cfs)
24 .await
25 .context("Getting composefs deployment status")?;
26
27 let new_spec = {
28 let mut new_spec = host.spec.clone();
29 new_spec.image = Some(target.clone());
30 new_spec
31 };
32
33 if new_spec == host.spec {
34 println!("Image specification is unchanged.");
35 return Ok(());
36 }
37
38 let Some(target_imgref) = new_spec.image else {
39 anyhow::bail!("Target image is undefined")
40 };
41
42 let repo = &*booted_cfs.repo;
43 let (image, img_config) = is_image_pulled(repo, &target_imgref).await?;
44
45 let do_upgrade_opts = DoUpgradeOpts {
46 soft_reboot: opts.soft_reboot,
47 apply: opts.apply,
48 download_only: false,
49 };
50
51 if let Some(cfg_verity) = image {
52 let action = validate_update(
53 storage,
54 booted_cfs,
55 &host,
56 img_config.manifest.config().digest().digest(),
57 &cfg_verity,
58 true,
59 )?;
60
61 match action {
62 UpdateAction::Skip => {
63 println!("No changes in image: {target_imgref:#}");
64 return Ok(());
65 }
66
67 UpdateAction::Proceed => {
68 return do_upgrade(
69 storage,
70 booted_cfs,
71 &host,
72 &target_imgref,
73 &img_config,
74 &do_upgrade_opts,
75 )
76 .await;
77 }
78
79 UpdateAction::UpdateOrigin => {
80 println!("Image already in composefs repository");
82 println!("Updating target image reference");
83 return update_target_imgref_in_origin(storage, booted_cfs, &target_imgref);
84 }
85 }
86 }
87
88 do_upgrade(
89 storage,
90 booted_cfs,
91 &host,
92 &target_imgref,
93 &img_config,
94 &do_upgrade_opts,
95 )
96 .await?;
97
98 Ok(())
99}