1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
use crate::{
config::{OsType, PackageType, Provisioner, VmConfig},
vm::ssh::SSHSession,
};
use anyhow::{Context, Result};
use std::fmt;
#[derive(Debug)]
pub enum Update {
Logs(Vec<String>),
Nothing,
}
/// Update system packages in a VM.
///
/// Note that this function is blocking.
pub fn packages(config: &VmConfig, guest_ip: std::net::IpAddr) -> Result<Update> {
match config.provisioner {
Provisioner::Noop => return Ok(Update::Nothing),
Provisioner::Ssh => (),
}
// User SSH session to execute package manager update command.
// This will of course be dependant on the target platform.
let commands = match (config.os_type, config.package_type) {
(OsType::Linux, Some(PackageType::Deb)) => {
Some(vec!["sudo apt-get update", "sudo apt-get upgrade"])
}
(OsType::Linux, Some(PackageType::Rpm)) => Some(vec!["sudo dnf update"]),
(OsType::Linux, _) => None,
(OsType::Macos | OsType::Windows, _) => None,
};
// Issue the update command(s).
let result = match commands {
None => {
log::info!("No update command was found");
log::debug!(
"Tried to invoke package update for platform {:?} with package type {:?}",
config.os_type,
config.package_type
);
Update::Nothing
}
Some(commands) => {
log::info!("retrieving SSH credentials");
let (username, password) = config.get_ssh_options().context("missing SSH config")?;
let ssh = SSHSession::connect(username.to_string(), password.to_string(), guest_ip)?;
let output: Result<Vec<_>> = commands
.iter()
.map(|command| {
log::info!("Running {command} in guest");
ssh.exec_blocking(command)
})
.collect();
Update::Logs(output?)
}
};
Ok(result)
}
// Pretty-printing for an `Update` action.
impl fmt::Display for Update {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Update::Nothing => write!(formatter, "Nothing was updated"),
Update::Logs(output) => output
.iter()
.try_for_each(|output| formatter.write_str(output)),
}
}
}
|