multipass 0.2.0

Rust SDK for Canonical Multipass
Documentation
use crate::multipass::Instance;
use std::process::Command;

const NAME: &str = "Name:";
const STATE: &str = "State:";
const IPV4: &str = "IPv4:";
const RELEASE: &str = "Release:";
const IMAGE_HASH: &str = "Image hash:";
const LOAD: &str = "Load:";
const DISK_USAGE: &str = "Disk usage:";
const MEMORY_USAGE: &str = "Memory usage:";

pub struct InfoRequest {
    pub name: String,
}

pub fn info(req: InfoRequest) -> Result<Instance, &'static str> {
    let output = Command::new("sh")
        .arg("-c")
        .arg(format!("multipass info {}", req.name))
        .output()
        .expect("failed to execute process");
    let stdout = String::from_utf8(output.stdout).unwrap();
    parse_info(stdout)
}

fn parse_info(out: String) -> Result<Instance, &'static str> {
    let mut instance = Instance::new();
    for line in out.split("\n") {
        if line.contains(NAME) && !line.ends_with("--") {
            instance.name = line.replace(NAME, "").trim().to_string();
        }

        if line.contains(STATE) && !line.ends_with("--") {
            instance.state = line.replace(STATE, "").trim().to_string();
        }

        if line.contains(IPV4) && !line.ends_with("--") {
            instance.ip = line.replace(IPV4, "").trim().to_string();
        }

        if line.contains(RELEASE) && !line.ends_with("--") {
            instance.image = line.replace(RELEASE, "").trim().to_string();
        }

        if line.contains(IMAGE_HASH) && !line.ends_with("--") {
            instance.image_hash = line.replace(IMAGE_HASH, "").trim().to_string();
        }

        if line.contains(LOAD) && !line.ends_with("--") {
            instance.load = line.replace(LOAD, "").trim().to_string();
        }

        if line.contains(DISK_USAGE) && !line.ends_with("--") {
            let disk_usage = line.replace(DISK_USAGE, "").trim().to_string();
            let disk_usage_out: Vec<_> = disk_usage.split("out of").collect();
            instance.disk_usage = disk_usage_out[0].trim().to_string();
            instance.total_disk = disk_usage_out[1].trim().to_string();
        }

        if line.contains(MEMORY_USAGE) && !line.ends_with("--") {
            let memory_usage = line.replace(MEMORY_USAGE, "").trim().to_string();
            let memory_usage_out: Vec<_> = memory_usage.split("out of").collect();
            instance.memory_usage = memory_usage_out[0].trim().to_string();
            instance.memory_total = memory_usage_out[1].trim().to_string();
        }
    }
    match instance.is_empty() {
        true => Err("No instances found."),
        false => Ok(instance),
    }
}