docker_credential 1.4.0

Reads a user's docker credentials from config
Documentation
use super::{CredentialRetrievalError, DockerCredential, Result};
use serde::Deserialize;
use std::io::Write;
use std::process::{Command, Stdio};

#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct HelperResponse {
    username: String,
    secret: String,
}

fn response_from_helper(address: &str, helper: &str) -> Result<HelperResponse> {
    let full_helper_name = format!("docker-credential-{}", helper);
    let mut process = Command::new(&full_helper_name)
        .arg("get")
        .stdin(Stdio::piped())
        .stderr(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .map_err(|_| CredentialRetrievalError::HelperCommunicationError)?;

    process
        .stdin
        .as_mut()
        .ok_or(CredentialRetrievalError::HelperCommunicationError)?
        .write_all(address.as_bytes())
        .map_err(|_| CredentialRetrievalError::HelperCommunicationError)?;

    let output = process
        .wait_with_output()
        .map_err(|_| CredentialRetrievalError::HelperCommunicationError)?;

    if output.status.success() {
        let parsed = serde_json::from_slice(&output.stdout)
            .map_err(|_| CredentialRetrievalError::MalformedHelperResponse)?;
        Ok(parsed)
    } else {
        Err(CredentialRetrievalError::HelperFailure {
            helper: full_helper_name,
            stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
            stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
        })
    }
}

pub fn credential_from_helper(address: &str, helper: &str) -> Result<DockerCredential> {
    let response = response_from_helper(address, helper)?;

    if response.username == "<token>" {
        Ok(DockerCredential::IdentityToken(response.secret))
    } else {
        Ok(DockerCredential::UsernamePassword(
            response.username,
            response.secret,
        ))
    }
}