use docker_compose::v2 as dc;
use std::ffi::{OsStr, OsString};
use std::marker::PhantomData;
use ovr::Override;
use pod::Pod;
use project::Project;
use util::Error;
pub trait ToArgs {
fn to_args(&self) -> Vec<OsString>;
}
#[derive(Debug, Clone)]
pub struct Options {
pub detached: bool,
pub privileged: bool,
pub user: Option<String>,
pub allocate_tty: bool,
#[doc(hidden)]
pub _nonexhaustive: PhantomData<()>,
}
impl ToArgs for Options {
fn to_args(&self) -> Vec<OsString> {
let mut args: Vec<OsString> = vec!();
if self.detached {
args.push(OsStr::new("-d").to_owned());
}
if self.privileged {
args.push(OsStr::new("--privileged").to_owned());
}
if let Some(ref user) = self.user {
args.push(OsStr::new("--user").to_owned());
args.push(user.into());
}
if !self.allocate_tty {
args.push(OsStr::new("-T").to_owned());
}
args
}
}
#[test]
fn options_to_args_returns_empty_for_default_opts() {
assert_eq!(Options::default().to_args(), Vec::<OsString>::new());
}
#[test]
fn options_to_args_returns_appropriate_flags() {
let opts = Options {
detached: true,
privileged: true,
user: Some("root".to_owned()),
allocate_tty: false,
..Default::default()
};
let raw_expected = &["-d", "--privileged", "--user", "root", "-T"];
let expected: Vec<OsString> = raw_expected.iter()
.map(|s| OsStr::new(s).to_owned())
.collect();
assert_eq!(opts.to_args(), expected);
}
impl Default for Options {
fn default() -> Options {
Options {
detached: false,
privileged: false,
user: None,
allocate_tty: true, _nonexhaustive: PhantomData,
}
}
}
pub struct Target<'a> {
ovr: &'a Override,
pod: &'a Pod,
service_name: &'a str,
service: dc::Service,
}
impl<'a> Target<'a> {
pub fn new(project: &'a Project, ovr: &'a Override,
pod_name: &'a str, service_name: &'a str) ->
Result<Target<'a>, Error>
{
let pod = try!(project.pod(pod_name).ok_or_else(|| {
err!("Cannot find pod {}", pod_name)
}));
let file = try!(pod.merged_file(ovr));
let service = try!(file.services.get(service_name).ok_or_else(|| {
err!("Cannot find service {}", service_name)
}));
Ok(Target {
ovr: ovr,
pod: pod,
service_name: service_name,
service: service.to_owned(),
})
}
pub fn ovr(&self) -> &Override {
self.ovr
}
pub fn pod(&self) -> &Pod {
self.pod
}
pub fn service_name(&self) -> &str {
self.service_name
}
pub fn service(&self) -> &dc::Service {
&self.service
}
}
pub struct Command {
pub command: OsString,
pub args: Vec<OsString>,
}
impl Command {
pub fn new<S: AsRef<OsStr>>(command: S) -> Command {
Command {
command: command.as_ref().to_owned(),
args: vec!(),
}
}
pub fn with_args<S: AsRef<OsStr>>(mut self, args: &[S]) -> Command {
self.args = args.iter().map(|a| a.as_ref().to_owned()).collect();
self
}
}
impl ToArgs for Command {
fn to_args(&self) -> Vec<OsString> {
let mut result: Vec<OsString> = vec!();
result.push(self.command.clone());
if !self.args.is_empty() {
result.push(OsStr::new("--").to_owned());
for arg in &self.args {
result.push(arg.clone());
}
}
result
}
}
#[test]
fn command_to_args_converts_to_arguments() {
assert_eq!(Command::new("foo").to_args(),
vec!(OsStr::new("foo")));
assert_eq!(Command::new("foo").with_args(&["--opt"]).to_args(),
vec!(OsStr::new("foo"), OsStr::new("--"), OsStr::new("--opt")));
}