#![deny(missing_docs)]
pub use command_run;
use command_run::Command;
use std::ffi::OsString;
use std::path::{Path, PathBuf};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Docker {
pub sudo: bool,
pub program: PathBuf,
}
impl Docker {
pub fn new() -> Self {
Self::default()
}
pub fn command(&self) -> Command {
if self.sudo {
Command::with_args("sudo", &["docker"])
} else {
Command::new("docker")
}
}
pub fn build(&self, opt: BuildOpt) -> Command {
let mut cmd = self.command();
cmd.add_arg("build");
if let Some(dockerfile) = &opt.dockerfile {
cmd.add_arg_pair("--file", dockerfile);
}
if let Some(tag) = &opt.tag {
cmd.add_arg_pair("--tag", tag);
}
cmd.add_arg(opt.context);
cmd
}
pub fn run(&self, opt: RunOpt) -> Command {
let mut cmd = self.command();
cmd.add_arg("run");
if opt.detach {
cmd.add_arg("--detach");
}
if opt.init {
cmd.add_arg("--init");
}
if let Some(name) = &opt.name {
cmd.add_arg_pair("--name", name);
}
if let Some(network) = &opt.network {
cmd.add_arg_pair("--network", network);
}
if opt.read_only {
cmd.add_arg("--read-only");
}
if opt.remove {
cmd.add_arg("--rm");
}
if let Some(user) = &opt.user {
cmd.add_arg_pair("--user", user.arg());
}
for vol in &opt.volumes {
cmd.add_arg_pair("--volume", vol.arg());
}
cmd.add_arg(opt.image);
if let Some(command) = &opt.command {
cmd.add_arg(command);
}
cmd.add_args(&opt.args);
cmd
}
}
impl Default for Docker {
fn default() -> Self {
Docker {
sudo: false,
program: Path::new("docker").into(),
}
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BuildOpt {
pub context: PathBuf,
pub dockerfile: Option<PathBuf>,
pub tag: Option<String>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum NameOrId {
Name(String),
Id(u32),
}
impl NameOrId {
pub fn arg(&self) -> String {
match self {
NameOrId::Name(name) => name.clone(),
NameOrId::Id(id) => id.to_string(),
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct User {
pub user: NameOrId,
pub group: Option<NameOrId>,
}
impl User {
pub fn current() -> User {
User {
user: NameOrId::Id(users::get_current_uid()),
group: Some(NameOrId::Id(users::get_current_gid())),
}
}
pub fn arg(&self) -> String {
let mut out = self.user.arg();
if let Some(group) = &self.group {
out.push(':');
out.push_str(&group.arg());
}
out
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Volume {
pub src: PathBuf,
pub dst: PathBuf,
pub read_write: bool,
pub options: Vec<String>,
}
impl Volume {
pub fn arg(&self) -> OsString {
let mut out = OsString::new();
out.push(&self.src);
out.push(":");
out.push(&self.dst);
if self.read_write {
out.push(":rw");
} else {
out.push(":ro");
}
for opt in &self.options {
out.push(",");
out.push(opt);
}
out
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct RunOpt {
pub image: String,
pub detach: bool,
pub init: bool,
pub name: Option<String>,
pub network: Option<String>,
pub user: Option<User>,
pub read_only: bool,
pub remove: bool,
pub volumes: Vec<Volume>,
pub command: Option<PathBuf>,
pub args: Vec<OsString>,
}