docker-generate 0.1.3

docker file read/write
Documentation


macro_rules! str_arr_to_string_vec {
    ($i:ident) => ($i.iter().map(|a| a.to_string()).collect::<Vec<String>>())
}

pub enum DockerFieldType<'a>{
    Docker(DockerFile<'a>),
    r#String(String),
    Array(Vec<&'a str>),
    TupleList(&'a[(&'a str, &'a str)]),
    MultiValue(Vec<String>),
    Protocal((i32, &'a str)),
    Int(i32),
}

impl<'a> From<Vec<String>> for DockerFieldType<'a>{
    fn from(value: Vec<String>) -> Self {
        DockerFieldType::MultiValue(value)
    }
}

impl<'a> From<Vec<&'a str>> for DockerFieldType<'a>{
    fn from(value: Vec<&'a str>) -> Self {
        DockerFieldType::MultiValue(str_arr_to_string_vec!(value))
    }
}


impl<'a> From<&'a [&'a str]> for DockerFieldType<'a>{
    fn from(value: &'a [&'a str]) -> Self {
        DockerFieldType::MultiValue(str_arr_to_string_vec!(value))
    }
}

impl<'a> From<&'a str> for DockerFieldType<'a>{
    fn from(value: &'a str) -> Self {
        DockerFieldType::String(value.to_string())
    }
}

impl<'a> From<String> for DockerFieldType<'a>{
    fn from(value: String) -> Self {
        DockerFieldType::String(value)
    }
}

impl<'a> From<DockerFile<'a>> for DockerFieldType<'a>{
    fn from(value: DockerFile<'a>) -> Self {
        DockerFieldType::Docker(value)
    }
}

impl<'a> From<&'a[(&'a str, &'a str)]> for DockerFieldType<'a>{
    fn from(value: &'a[(&'a str, &'a str)]) -> Self {
        DockerFieldType::TupleList(value)
    }
}

impl<'a> From<(i32, &'a str)> for DockerFieldType<'a>{
    fn from(value: (i32, &'a str)) -> Self {
        DockerFieldType::Protocal(value)
    }
}

impl<'a> From<i32> for DockerFieldType<'a>{
    fn from(value: i32) -> Self {
        DockerFieldType::Int(value)
    }
}

impl <'a> DockerFieldType<'a>{
    pub fn to_string(&self) -> String{
        match self {
            DockerFieldType::Docker(d) => d.to_string(),
            DockerFieldType::String(s) => s.to_string(),
            DockerFieldType::Int(i) => i.to_string(),
            DockerFieldType::Protocal((i,p)) => format!("{}/{}", i.to_string(), p),
            DockerFieldType::TupleList(l) => l.into_iter()
                                            .map(|(v1,v2)| format!("{}=\"{}\"", v1,v2))
                                            .collect::<Vec<String>>()
                                            .join(" "),
            DockerFieldType::Array(arr) =>  format!("[{}]", 
                                            arr.into_iter()
                                            .map(|i| format!("\"{}\"", i))
                                            .collect::<Vec<String>>()
                                            .join(", ")),
            DockerFieldType::MultiValue(arr) => arr.join(" "), 
        }
    }
}

pub struct DockerField<'a>{
    name: &'a str,
    value: DockerFieldType<'a>
}

impl<'a> DockerField<'a> {
    fn new(name: &'a str, value: DockerFieldType<'a>) -> Self{
        DockerField{
            name: name,
            value: value,
        }
    }
}

pub struct DockerFile<'a>{
    fields: Vec<DockerField<'a>>,
}

impl<'a> Default for DockerFile<'a>{
    fn default() -> Self {
        DockerFile{
            fields: Vec::new(),
        }
    }
}

impl<'a> DockerFile<'a>{
    pub fn new() -> Self{
        Default::default()
    }

    pub fn from_image(from: &'a str) -> Self{
        DockerFile::new().from(from)
    }

    pub fn add(mut self,  name: &'a str, val: DockerFieldType<'a>) -> Self {
        self.fields.push(DockerField::new(name, val));
        self
    }

    pub fn comment(self, cmt: &'a str) -> Self{
        self.add("#", cmt.into())
    }

    pub fn from(self, from: &'a str) -> Self {
        self.add("FROM", from.into())
    }

    pub fn from_alias(self, alias: &'a str, from: &'a str) -> Self{
        self.add("FROM", format!("{} as {}", from, alias).into())
    }

    pub fn run(self, from: &'a str) -> Self {
        self.add("RUN", from.into())
    }

    pub fn cmd(self, args: &'a[&'a str]) -> Self{
        self.add("CMD", DockerFieldType::Array(args.to_vec()))
    }

    pub fn label(self, labels: &'a[(&'a str, &'a str)])-> Self{
        self.add("LABEL", labels.into())
    }

    pub fn expose(self, port: i32) -> Self{
        self.add("EXPOSE", port.into())
    }

    pub fn expose_protocal(self, port:i32, prot: &'a str) -> Self{
        self.add("EXPOSE", (port, prot).into())
    }

    pub fn env(self, vals: &'a[(&'a str, &'a str)]) -> Self{
        self.add("ENV", vals.into())
    }

    pub fn workdir(self, dir: &'a str) -> Self{
        self.add("WORKDIR", dir.into())
    }

    pub fn copy(self, src: &'a str, dest: &'a str) -> Self{
        self.add("COPY", vec![src.to_string(),dest.to_string()].into())
    }

    pub fn copy_from(self, from: &'a str, src: &'a str, dest: &'a str) -> Self {
        self.add("COPY", vec![(&["--from=", from]).join(""), src.to_string(), dest.to_string()].into())
    }

    pub fn volume(self, vols: &'a[&'a str]) -> Self{
        self.add("VOLUME", DockerFieldType::Array(vols.to_vec()))
    }

    pub fn dockerfile(self, f: DockerFile<'a>) -> Self{
        self.add("", f.into())
    }

    pub fn entrypoint(self, args: &'a[&'a str]) -> Self{
        self.add("ENTRYPOINT", DockerFieldType::Array(args.to_vec()))
    }

    pub fn newline(self) -> Self{
        self.add("", "".into())
    }

    pub fn newlines(self, ammount: i32) -> Self{
        let mut s = self;
        for _ in 0..ammount{
            s = s.add("", "".into());
        }
        s
    }



    pub fn to_string(&self) -> String {
        let mut out = String::new();

        for f in self.fields.iter(){
            out.push_str(f.name);
            if !f.name.is_empty(){
                out.push(' ');
            }
            out.push_str(&f.value.to_string());
            out.push_str("\n\r");
        }
        out
    }
}