From ab7b22fa5a9adbc99f795ba71b41432abb409859 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sat, 16 Dec 2017 16:55:25 -0500 Subject: [PATCH 01/14] learned a touch of rust --- rust/.gitignore | 2 ++ rust/Cargo.toml | 9 ++++++ rust/README.md | 0 rust/examples/hello.rs | 34 ++++++++++++++++++++ rust/src/lib.rs | 71 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 116 insertions(+) create mode 100644 rust/.gitignore create mode 100644 rust/Cargo.toml create mode 100644 rust/README.md create mode 100644 rust/examples/hello.rs create mode 100644 rust/src/lib.rs diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 0000000..869df07 --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock \ No newline at end of file diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000..0e6fb5b --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "metaparticle" +version = "0.0.1" + +[[example]] +name = "hello" +path = "examples/hello.rs" + +[dependencies] \ No newline at end of file diff --git a/rust/README.md b/rust/README.md new file mode 100644 index 0000000..e69de29 diff --git a/rust/examples/hello.rs b/rust/examples/hello.rs new file mode 100644 index 0000000..77ce5ef --- /dev/null +++ b/rust/examples/hello.rs @@ -0,0 +1,34 @@ +//#![feature(custom_attribute)] +extern crate metaparticle; + +// static runtime: metaparticle::Runtime = metaparticle::Runtime{ +// replicas: Some(1444444), +// ..Default::default() +// }; + +// static package: metaparticle::Package = metaparticle::Package{ +// verbose: Some(true), +// ..Default::default() +// }; + +// #[containerize(runtime, package)] +// fn main() { +// println!("Hello World!"); +// metaparticle::nothing() +// } + +fn run() { + println!("Hello World!"); +} + +fn main() { + let runtime = metaparticle::Runtime{ + executor: Some("docker".to_string()), + ..Default::default() + }; + let package = metaparticle::Package{ + builder: Some("also docker".to_string()), + ..Default::default() + }; + metaparticle::containerize(run, runtime, package) +} \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 0000000..f651667 --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,71 @@ +#[derive(Debug)] +pub struct Runtime { + pub replicas: Option, + pub shards: Option, + pub url_shard_pattern: Option, + pub executor: Option, + pub ports: Option, + pub public_address: Option, +} + + +impl Default for Runtime { + fn default() -> Runtime { + Runtime { + replicas: Some(1), + shards: Some(2), + url_shard_pattern: Some("something".to_string()), + executor: Some("exec".to_string()), + ports: Some(3), + public_address: Some(false) + } + } +} + + +#[derive(Debug)] +pub struct Package { + pub repository: Option, + pub verbose: Option, + pub quiet: Option, + pub builder: Option, + pub publish: Option, +} + + +impl Default for Package { + fn default() -> Package { + Package { + repository: Some("repository".to_string()), + verbose: Some(false), + quiet: Some(false), + builder: Some("builder".to_string()), + publish: Some(false) + } + } +} + + +pub fn nothing() { + let package = Package { + repository: Some("repository".to_string()), + verbose: Some(false), + quiet: Some(false), + builder: Some("builder".to_string()), + publish: Some(false) + }; + println!("Nothing... {:?}", package); +} + + + +// pub fn containerize(runtime: Runtime, package: Package) { +// println!("Hello Metaparticle! package: {:?}", package); +// println!("Hello Metaparticle! runtime: {:?}", runtime); +// } + +pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { + println!("Hello Metaparticle! package: {:?}", package); + println!("Hello Metaparticle! runtime: {:?}", runtime); + f() +} \ No newline at end of file From 6f747cc308c46146a99620826c889f8a6a0b0879 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sun, 17 Dec 2017 15:55:05 -0500 Subject: [PATCH 02/14] no decorator --- rust/examples/hello.rs | 17 ----------------- rust/src/lib.rs | 19 ------------------- 2 files changed, 36 deletions(-) diff --git a/rust/examples/hello.rs b/rust/examples/hello.rs index 77ce5ef..82c2932 100644 --- a/rust/examples/hello.rs +++ b/rust/examples/hello.rs @@ -1,22 +1,5 @@ -//#![feature(custom_attribute)] extern crate metaparticle; -// static runtime: metaparticle::Runtime = metaparticle::Runtime{ -// replicas: Some(1444444), -// ..Default::default() -// }; - -// static package: metaparticle::Package = metaparticle::Package{ -// verbose: Some(true), -// ..Default::default() -// }; - -// #[containerize(runtime, package)] -// fn main() { -// println!("Hello World!"); -// metaparticle::nothing() -// } - fn run() { println!("Hello World!"); } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index f651667..041c806 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -45,25 +45,6 @@ impl Default for Package { } } - -pub fn nothing() { - let package = Package { - repository: Some("repository".to_string()), - verbose: Some(false), - quiet: Some(false), - builder: Some("builder".to_string()), - publish: Some(false) - }; - println!("Nothing... {:?}", package); -} - - - -// pub fn containerize(runtime: Runtime, package: Package) { -// println!("Hello Metaparticle! package: {:?}", package); -// println!("Hello Metaparticle! runtime: {:?}", runtime); -// } - pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { println!("Hello Metaparticle! package: {:?}", package); println!("Hello Metaparticle! runtime: {:?}", runtime); From 6c74f17a8d9c09793034923ccd1731d1ebdc56b8 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Sun, 17 Dec 2017 17:29:45 -0500 Subject: [PATCH 03/14] base rust entrypoint --- rust/src/lib.rs | 127 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 124 insertions(+), 3 deletions(-) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 041c806..695db72 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,3 +1,12 @@ +use std::env; +use std::error::Error; +use std::fs::File; +use std::ffi::OsStr; +use std::io; +use std::io::prelude::*; +use std::path::Path; + + #[derive(Debug)] pub struct Runtime { pub replicas: Option, @@ -45,8 +54,120 @@ impl Default for Package { } } +pub trait Executor { + fn placeholder(&self); +} + + + +struct DockerExecutor{} + +struct FakeExecutor{} + +impl Executor for DockerExecutor { + fn placeholder(&self) { + println!("Docker executor"); + } +} + +impl Executor for FakeExecutor { + fn placeholder(&self) { + println!("Fake executor"); + } +} + +pub trait Builder { + fn placeholder(&self); +} + +struct DockerBuilder{} + +impl Builder for DockerBuilder { + fn placeholder(&self) { + println!("Docker builder!"); + } +} + +struct FakeBuilder{} + +impl Builder for FakeBuilder { + fn placeholder(&self) { + println!("Fake builder!"); + } +} + +fn in_docker_container() -> bool { + let env_var_key = OsStr::new("METAPARTICLE_IN_CONTAINER"); + let env_var = env::var(env_var_key); + if let Ok(value) = env_var { + return value == "true" || value == "1"; + } + + let mut buffer = String::with_capacity(256); // kind of a guess on initial capacity + let mut file_result = File::open("/proc/1/cgroup"); + + if let Ok(mut file) = File::open("/proc/1/cgroup") { + if let Ok(_) = file.read_to_string(&mut buffer) { + return buffer.contains("docker"); + } + } + false +} + +fn executor_from_runtime(executor_name: Option) -> Box { + if let Some(name) = executor_name { + let executor : Box = match name.as_ref() { + "docker" => Box::new(DockerExecutor{}), + "fake" => Box::new(FakeExecutor{}), + _ => panic!("Unsupported executor type {}", name), + }; + return executor; + } + Box::new(DockerExecutor{}) +} + +fn build_from_runtime(builder_name: Option) -> Box { + if let Some(name) = builder_name { + let builder : Box = match name.as_ref() { + "docker" => Box::new(DockerBuilder{}), + "fake" => Box::new(FakeBuilder{}), + _ => panic!("Unsupported builder type {}", name), + }; + builder + } else { + Box::new(DockerBuilder{}) + } +} + +fn write_dockerfile(name: &str) { + let dockerfile = &b"FROM rust:latest + FOO + HELLO WORLD + "[..]; + let path = Path::new("Dockerfile"); + let display = path.display(); + + let mut file = match File::create(&path) { + Err(why) => panic!("couldn't create {}: {}", + display, + why.description()), + Ok(file) => file, + }; + + if let Err(why) = file.write_all(dockerfile) { + panic!("Could not write dockerfile at {} because {}", display, why.description()); + } +} + pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { - println!("Hello Metaparticle! package: {:?}", package); - println!("Hello Metaparticle! runtime: {:?}", runtime); - f() + if(in_docker_container()) { + f(); + } else { + let executor = executor_from_runtime(runtime.executor.clone()); + executor.placeholder(); + + let builder = build_from_runtime(package.builder.clone()); + builder.placeholder(); + write_dockerfile("foo"); + } } \ No newline at end of file From ef4bddf4d4681ced27daf0a6936a66ac37892e5a Mon Sep 17 00:00:00 2001 From: Alex Goodman Date: Sun, 17 Dec 2017 17:32:04 -0500 Subject: [PATCH 04/14] with bare docker builder and executor (#3) --- rust/src/builder/docker.rs | 53 +++++++++++++++++++++++++++++++++++++ rust/src/builder/mod.rs | 1 + rust/src/executor/docker.rs | 5 ++++ rust/src/executor/mod.rs | 1 + rust/src/lib.rs | 4 ++- 5 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 rust/src/builder/docker.rs create mode 100644 rust/src/builder/mod.rs create mode 100644 rust/src/executor/docker.rs create mode 100644 rust/src/executor/mod.rs diff --git a/rust/src/builder/docker.rs b/rust/src/builder/docker.rs new file mode 100644 index 0000000..ab0e8df --- /dev/null +++ b/rust/src/builder/docker.rs @@ -0,0 +1,53 @@ +use std::process; + +pub fn build(dir: String, image: String) { + let mut child = process::Command::new("docker") + .arg("build") + .arg(image) + .arg(dir) + .spawn() + .expect("failed to execute 'docker build'"); + + child.wait(); +} + +pub fn push(image: String) { + let mut child = process::Command::new("docker") + .arg("push") + .arg(image) + .spawn() + .expect("failed to execute 'docker push'"); + + child.wait(); + +} + +pub fn logs(name: String) { + let mut child = process::Command::new("docker") + .arg("logs") + .arg("-f") + .arg(name) + .spawn() + .expect("failed to execute 'docker logs'"); + + child.wait(); +} + +pub fn cancel(name: String) { + let mut child = process::Command::new("docker") + .arg("stop") + .arg(name.clone()) + .spawn() + .expect("failed to execute 'docker stop'"); + + child.wait(); + + child = process::Command::new("docker") + .arg("rm") + .arg("-f") + .arg(name.clone()) + .spawn() + .expect("failed to execute 'docker rm'"); + + child.wait(); +} diff --git a/rust/src/builder/mod.rs b/rust/src/builder/mod.rs new file mode 100644 index 0000000..af75ddd --- /dev/null +++ b/rust/src/builder/mod.rs @@ -0,0 +1 @@ +pub mod docker; \ No newline at end of file diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs new file mode 100644 index 0000000..2d56d2e --- /dev/null +++ b/rust/src/executor/docker.rs @@ -0,0 +1,5 @@ +use std::process + +pub fn run(image: String, name: String, config: Runtime) { + +} diff --git a/rust/src/executor/mod.rs b/rust/src/executor/mod.rs new file mode 100644 index 0000000..af75ddd --- /dev/null +++ b/rust/src/executor/mod.rs @@ -0,0 +1 @@ +pub mod docker; \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 695db72..5597289 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,3 +1,6 @@ + +mod builder; + use std::env; use std::error::Error; use std::fs::File; @@ -6,7 +9,6 @@ use std::io; use std::io::prelude::*; use std::path::Path; - #[derive(Debug)] pub struct Runtime { pub replicas: Option, From a581508048b0aac3065a0433004f799587d66359 Mon Sep 17 00:00:00 2001 From: William Murphy Date: Wed, 27 Dec 2017 20:28:11 -0500 Subject: [PATCH 05/14] Real traits jim (#4) * add placeholder functions for actual interface * move builder trait into builder module * move docker builder struct into correct module * move existing functions onto trait implementation * move executor trait to appropriate module * move executor struct into correct module --- rust/src/builder/docker.rs | 92 +++++++++++++++++++------------------ rust/src/builder/mod.rs | 10 +++- rust/src/executor/docker.rs | 16 ++++++- rust/src/executor/mod.rs | 8 +++- rust/src/lib.rs | 41 ++++++----------- 5 files changed, 91 insertions(+), 76 deletions(-) diff --git a/rust/src/builder/docker.rs b/rust/src/builder/docker.rs index ab0e8df..de6ee00 100644 --- a/rust/src/builder/docker.rs +++ b/rust/src/builder/docker.rs @@ -1,53 +1,57 @@ use std::process; +use Builder; -pub fn build(dir: String, image: String) { - let mut child = process::Command::new("docker") - .arg("build") - .arg(image) - .arg(dir) - .spawn() - .expect("failed to execute 'docker build'"); - - child.wait(); -} +pub struct DockerBuilder{} -pub fn push(image: String) { - let mut child = process::Command::new("docker") +impl Builder for DockerBuilder { + fn placeholder(&self) { + println!("Docker builder!"); + } + fn build(&self, dir: String, image: String) { + let mut child = process::Command::new("docker") + .arg("build") + .arg(image) + .arg(dir) + .spawn() + .expect("failed to execute 'docker build'"); + + child.wait(); + } + fn push(&self, image: String) { + let mut child = process::Command::new("docker") .arg("push") .arg(image) .spawn() .expect("failed to execute 'docker push'"); - child.wait(); - -} - -pub fn logs(name: String) { - let mut child = process::Command::new("docker") - .arg("logs") - .arg("-f") - .arg(name) - .spawn() - .expect("failed to execute 'docker logs'"); - - child.wait(); -} - -pub fn cancel(name: String) { - let mut child = process::Command::new("docker") - .arg("stop") - .arg(name.clone()) - .spawn() - .expect("failed to execute 'docker stop'"); - - child.wait(); + child.wait(); + } + fn logs(&self, name: String) { + let mut child = process::Command::new("docker") + .arg("logs") + .arg("-f") + .arg(name) + .spawn() + .expect("failed to execute 'docker logs'"); + + child.wait(); + } + fn cancel(&self, name: String) { + let mut child = process::Command::new("docker") + .arg("stop") + .arg(name.clone()) + .spawn() + .expect("failed to execute 'docker stop'"); + + child.wait(); - child = process::Command::new("docker") - .arg("rm") - .arg("-f") - .arg(name.clone()) - .spawn() - .expect("failed to execute 'docker rm'"); - - child.wait(); -} + child = process::Command::new("docker") + .arg("rm") + .arg("-f") + .arg(name.clone()) + .spawn() + .expect("failed to execute 'docker rm'"); + + child.wait(); + } +} \ No newline at end of file diff --git a/rust/src/builder/mod.rs b/rust/src/builder/mod.rs index af75ddd..c3c0f19 100644 --- a/rust/src/builder/mod.rs +++ b/rust/src/builder/mod.rs @@ -1 +1,9 @@ -pub mod docker; \ No newline at end of file +pub mod docker; + +pub trait Builder { + fn placeholder(&self); + fn build(&self, dir: String, image: String); + fn push(&self, image: String); + fn logs(&self, name: String); + fn cancel(&self, name: String); +} \ No newline at end of file diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs index 2d56d2e..1662c4c 100644 --- a/rust/src/executor/docker.rs +++ b/rust/src/executor/docker.rs @@ -1,5 +1,17 @@ -use std::process +use std::process; +use super::Runtime; +use Executor; -pub fn run(image: String, name: String, config: Runtime) { +pub struct DockerExecutor{} +impl Executor for DockerExecutor { + fn placeholder(&self) { + println!("Docker Executor"); + } + + + fn run(&self, image: String, name: String, config: Runtime) { + + } } + diff --git a/rust/src/executor/mod.rs b/rust/src/executor/mod.rs index af75ddd..62a41f3 100644 --- a/rust/src/executor/mod.rs +++ b/rust/src/executor/mod.rs @@ -1 +1,7 @@ -pub mod docker; \ No newline at end of file +pub mod docker; +use super::Runtime; + +pub trait Executor { + fn placeholder(&self); + fn run(&self, image: String, name: String, config: Runtime); +} \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 5597289..f4e9f30 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -1,5 +1,9 @@ mod builder; +mod executor; + +use builder::Builder; +use executor::Executor; use std::env; use std::error::Error; @@ -56,38 +60,15 @@ impl Default for Package { } } -pub trait Executor { - fn placeholder(&self); -} - - - -struct DockerExecutor{} struct FakeExecutor{} -impl Executor for DockerExecutor { - fn placeholder(&self) { - println!("Docker executor"); - } -} impl Executor for FakeExecutor { fn placeholder(&self) { println!("Fake executor"); } -} - -pub trait Builder { - fn placeholder(&self); -} - -struct DockerBuilder{} - -impl Builder for DockerBuilder { - fn placeholder(&self) { - println!("Docker builder!"); - } + fn run(&self, image: String, name: String, config: Runtime) {} } struct FakeBuilder{} @@ -96,6 +77,10 @@ impl Builder for FakeBuilder { fn placeholder(&self) { println!("Fake builder!"); } + fn build(&self, dir: String, image: String) {} + fn push(&self, image: String) {} + fn logs(&self, name: String) {} + fn cancel(&self, name: String) {} } fn in_docker_container() -> bool { @@ -119,25 +104,25 @@ fn in_docker_container() -> bool { fn executor_from_runtime(executor_name: Option) -> Box { if let Some(name) = executor_name { let executor : Box = match name.as_ref() { - "docker" => Box::new(DockerExecutor{}), + "docker" => Box::new(executor::docker::DockerExecutor{}), "fake" => Box::new(FakeExecutor{}), _ => panic!("Unsupported executor type {}", name), }; return executor; } - Box::new(DockerExecutor{}) + Box::new(executor::docker::DockerExecutor{}) } fn build_from_runtime(builder_name: Option) -> Box { if let Some(name) = builder_name { let builder : Box = match name.as_ref() { - "docker" => Box::new(DockerBuilder{}), + "docker" => Box::new(builder::docker::DockerBuilder{}), "fake" => Box::new(FakeBuilder{}), _ => panic!("Unsupported builder type {}", name), }; builder } else { - Box::new(DockerBuilder{}) + Box::new(builder::docker::DockerBuilder{}) } } From 03c05ef08ac0d4cdea7a46230aa02a210d994cc1 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Wed, 27 Dec 2017 21:45:04 -0500 Subject: [PATCH 06/14] initial builder working --- rust/examples/hello.rs | 2 -- rust/src/builder/docker.rs | 2 +- rust/src/lib.rs | 25 ++++++++++++------------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/rust/examples/hello.rs b/rust/examples/hello.rs index 82c2932..d4e047c 100644 --- a/rust/examples/hello.rs +++ b/rust/examples/hello.rs @@ -6,11 +6,9 @@ fn run() { fn main() { let runtime = metaparticle::Runtime{ - executor: Some("docker".to_string()), ..Default::default() }; let package = metaparticle::Package{ - builder: Some("also docker".to_string()), ..Default::default() }; metaparticle::containerize(run, runtime, package) diff --git a/rust/src/builder/docker.rs b/rust/src/builder/docker.rs index de6ee00..18e47d9 100644 --- a/rust/src/builder/docker.rs +++ b/rust/src/builder/docker.rs @@ -10,7 +10,7 @@ impl Builder for DockerBuilder { fn build(&self, dir: String, image: String) { let mut child = process::Command::new("docker") .arg("build") - .arg(image) + .arg("-t".to_string()+&image) .arg(dir) .spawn() .expect("failed to execute 'docker build'"); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index f4e9f30..ac78bc1 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -9,7 +9,6 @@ use std::env; use std::error::Error; use std::fs::File; use std::ffi::OsStr; -use std::io; use std::io::prelude::*; use std::path::Path; @@ -30,7 +29,7 @@ impl Default for Runtime { replicas: Some(1), shards: Some(2), url_shard_pattern: Some("something".to_string()), - executor: Some("exec".to_string()), + executor: Some("docker".to_string()), ports: Some(3), public_address: Some(false) } @@ -54,7 +53,7 @@ impl Default for Package { repository: Some("repository".to_string()), verbose: Some(false), quiet: Some(false), - builder: Some("builder".to_string()), + builder: Some("docker".to_string()), publish: Some(false) } } @@ -127,10 +126,10 @@ fn build_from_runtime(builder_name: Option) -> Box { } fn write_dockerfile(name: &str) { - let dockerfile = &b"FROM rust:latest - FOO - HELLO WORLD - "[..]; + let dockerfile = &format!("FROM alpine:latest + COPY ./{name} /runtime/{name} + CMD /runtime/{name} + ", name=name); let path = Path::new("Dockerfile"); let display = path.display(); @@ -141,20 +140,20 @@ fn write_dockerfile(name: &str) { Ok(file) => file, }; - if let Err(why) = file.write_all(dockerfile) { + if let Err(why) = file.write_all(dockerfile.as_bytes()) { panic!("Could not write dockerfile at {} because {}", display, why.description()); } } pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { - if(in_docker_container()) { + if in_docker_container() { f(); } else { + write_dockerfile("hello"); //TODO: replace this + let builder = build_from_runtime(package.builder.clone()); + builder.build(".".to_string(), "dummy".to_string()); + let executor = executor_from_runtime(runtime.executor.clone()); executor.placeholder(); - - let builder = build_from_runtime(package.builder.clone()); - builder.placeholder(); - write_dockerfile("foo"); } } \ No newline at end of file From 8e6ae33ea60256e59e9889d5fc0c4e6dd37501bc Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sun, 7 Jan 2018 17:46:55 -0500 Subject: [PATCH 07/14] added docker run support; cleaned up command execs --- rust/examples/hello.rs | 2 + rust/src/builder/docker.rs | 50 ++--------------- rust/src/builder/mod.rs | 5 +- rust/src/executor/docker.rs | 17 ++++-- rust/src/executor/mod.rs | 4 +- rust/src/lib.rs | 103 ++++++++++++++++-------------------- 6 files changed, 70 insertions(+), 111 deletions(-) diff --git a/rust/examples/hello.rs b/rust/examples/hello.rs index d4e047c..6a7e589 100644 --- a/rust/examples/hello.rs +++ b/rust/examples/hello.rs @@ -6,9 +6,11 @@ fn run() { fn main() { let runtime = metaparticle::Runtime{ + ports: Some(80), ..Default::default() }; let package = metaparticle::Package{ + name: "hello".to_string(), ..Default::default() }; metaparticle::containerize(run, runtime, package) diff --git a/rust/src/builder/docker.rs b/rust/src/builder/docker.rs index 18e47d9..ad43dc0 100644 --- a/rust/src/builder/docker.rs +++ b/rust/src/builder/docker.rs @@ -1,57 +1,13 @@ -use std::process; +use super::run_docker_process; use Builder; pub struct DockerBuilder{} impl Builder for DockerBuilder { - fn placeholder(&self) { - println!("Docker builder!"); - } fn build(&self, dir: String, image: String) { - let mut child = process::Command::new("docker") - .arg("build") - .arg("-t".to_string()+&image) - .arg(dir) - .spawn() - .expect("failed to execute 'docker build'"); - - child.wait(); + run_docker_process(vec!["build".to_string(), "-t".to_string()+&image, dir]); } fn push(&self, image: String) { - let mut child = process::Command::new("docker") - .arg("push") - .arg(image) - .spawn() - .expect("failed to execute 'docker push'"); - - child.wait(); - } - fn logs(&self, name: String) { - let mut child = process::Command::new("docker") - .arg("logs") - .arg("-f") - .arg(name) - .spawn() - .expect("failed to execute 'docker logs'"); - - child.wait(); - } - fn cancel(&self, name: String) { - let mut child = process::Command::new("docker") - .arg("stop") - .arg(name.clone()) - .spawn() - .expect("failed to execute 'docker stop'"); - - child.wait(); - - child = process::Command::new("docker") - .arg("rm") - .arg("-f") - .arg(name.clone()) - .spawn() - .expect("failed to execute 'docker rm'"); - - child.wait(); + run_docker_process(vec!["push".to_string(), image.to_string()]); } } \ No newline at end of file diff --git a/rust/src/builder/mod.rs b/rust/src/builder/mod.rs index c3c0f19..7da0996 100644 --- a/rust/src/builder/mod.rs +++ b/rust/src/builder/mod.rs @@ -1,9 +1,8 @@ pub mod docker; +use super::run_docker_process; + pub trait Builder { - fn placeholder(&self); fn build(&self, dir: String, image: String); fn push(&self, image: String); - fn logs(&self, name: String); - fn cancel(&self, name: String); } \ No newline at end of file diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs index 1662c4c..c61be0c 100644 --- a/rust/src/executor/docker.rs +++ b/rust/src/executor/docker.rs @@ -1,17 +1,26 @@ -use std::process; +use super::run_docker_process; use super::Runtime; use Executor; pub struct DockerExecutor{} impl Executor for DockerExecutor { - fn placeholder(&self) { - println!("Docker Executor"); + fn cancel(&self, name: String) { + run_docker_process(vec!["stop".to_string(), name.clone()]); + run_docker_process(vec!["rm".to_string(), "-f".to_string(), name.clone()]); } + fn logs(&self, name: String) { + run_docker_process(vec!["logs".to_string(), "-f".to_string(), name]); + } fn run(&self, image: String, name: String, config: Runtime) { - + let mut args = vec!["run".to_string(), "-d".to_string(), "--name".to_string(), name]; + if let Some(port) = config.ports { + args.extend(vec!["-p".to_string(), port.to_string()]); + } + args.extend(vec![image]); + run_docker_process(args); } } diff --git a/rust/src/executor/mod.rs b/rust/src/executor/mod.rs index 62a41f3..22a1708 100644 --- a/rust/src/executor/mod.rs +++ b/rust/src/executor/mod.rs @@ -1,7 +1,9 @@ pub mod docker; use super::Runtime; +use super::run_docker_process; pub trait Executor { - fn placeholder(&self); + fn cancel(&self, name: String); + fn logs(&self, name: String); fn run(&self, image: String, name: String, config: Runtime); } \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index ac78bc1..c39d7ec 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -11,13 +11,14 @@ use std::fs::File; use std::ffi::OsStr; use std::io::prelude::*; use std::path::Path; +use std::process; #[derive(Debug)] pub struct Runtime { pub replicas: Option, pub shards: Option, pub url_shard_pattern: Option, - pub executor: Option, + pub executor: String, pub ports: Option, pub public_address: Option, } @@ -26,23 +27,23 @@ pub struct Runtime { impl Default for Runtime { fn default() -> Runtime { Runtime { - replicas: Some(1), - shards: Some(2), + replicas: None, + shards: None, url_shard_pattern: Some("something".to_string()), - executor: Some("docker".to_string()), - ports: Some(3), + executor: "docker".to_string(), + ports: None, public_address: Some(false) } } } - #[derive(Debug)] pub struct Package { - pub repository: Option, + pub name: String, + pub repository: String, pub verbose: Option, pub quiet: Option, - pub builder: Option, + pub builder: String, pub publish: Option, } @@ -50,36 +51,32 @@ pub struct Package { impl Default for Package { fn default() -> Package { Package { - repository: Some("repository".to_string()), + name: "name".to_string(), + repository: "repository".to_string(), verbose: Some(false), quiet: Some(false), - builder: Some("docker".to_string()), + builder: "docker".to_string(), publish: Some(false) } } } +pub fn run_docker_process(args: Vec) { + let name = args[0].clone(); + let mut child = process::Command::new("docker") + .args(&args) + .spawn() + .expect(&format!("failed to execute 'docker {name}'", name=name)); -struct FakeExecutor{} - + let status = child.wait() + .ok().expect(&format!("couldn't wait for 'docker {name}'", name=name)); -impl Executor for FakeExecutor { - fn placeholder(&self) { - println!("Fake executor"); - } - fn run(&self, image: String, name: String, config: Runtime) {} -} - -struct FakeBuilder{} - -impl Builder for FakeBuilder { - fn placeholder(&self) { - println!("Fake builder!"); + if !status.success() { + match status.code() { + Some(code) => panic!("'docker {}' failed with code {:?}", name, code), + None => panic!("'docker {}' failed", name) + } } - fn build(&self, dir: String, image: String) {} - fn push(&self, image: String) {} - fn logs(&self, name: String) {} - fn cancel(&self, name: String) {} } fn in_docker_container() -> bool { @@ -90,7 +87,6 @@ fn in_docker_container() -> bool { } let mut buffer = String::with_capacity(256); // kind of a guess on initial capacity - let mut file_result = File::open("/proc/1/cgroup"); if let Ok(mut file) = File::open("/proc/1/cgroup") { if let Ok(_) = file.read_to_string(&mut buffer) { @@ -100,35 +96,27 @@ fn in_docker_container() -> bool { false } -fn executor_from_runtime(executor_name: Option) -> Box { - if let Some(name) = executor_name { - let executor : Box = match name.as_ref() { - "docker" => Box::new(executor::docker::DockerExecutor{}), - "fake" => Box::new(FakeExecutor{}), - _ => panic!("Unsupported executor type {}", name), - }; - return executor; - } - Box::new(executor::docker::DockerExecutor{}) +fn executor_from_runtime(executor_name: String) -> Box { + let executor : Box = match executor_name.as_ref() { + "docker" => Box::new(executor::docker::DockerExecutor{}), + _ => panic!("Unsupported executor type {}", executor_name), + }; + return executor; } -fn build_from_runtime(builder_name: Option) -> Box { - if let Some(name) = builder_name { - let builder : Box = match name.as_ref() { - "docker" => Box::new(builder::docker::DockerBuilder{}), - "fake" => Box::new(FakeBuilder{}), - _ => panic!("Unsupported builder type {}", name), - }; - builder - } else { - Box::new(builder::docker::DockerBuilder{}) - } +fn build_from_runtime(builder_name: String) -> Box { + let builder : Box = match builder_name.as_ref() { + "docker" => Box::new(builder::docker::DockerBuilder{}), + _ => panic!("Unsupported builder type {}", builder_name), + }; + builder + } fn write_dockerfile(name: &str) { - let dockerfile = &format!("FROM alpine:latest - COPY ./{name} /runtime/{name} - CMD /runtime/{name} + let dockerfile = &format!("FROM ubuntu:16.04 + COPY ./{name} /tmp/{name} + CMD /tmp/{name} ", name=name); let path = Path::new("Dockerfile"); let display = path.display(); @@ -149,11 +137,14 @@ pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { if in_docker_container() { f(); } else { - write_dockerfile("hello"); //TODO: replace this + let image = &format!("{repo}/{name}:latest", repo=package.repository, name=package.name); + + write_dockerfile(&package.name); let builder = build_from_runtime(package.builder.clone()); - builder.build(".".to_string(), "dummy".to_string()); + builder.build(".".to_string(), image.clone()); let executor = executor_from_runtime(runtime.executor.clone()); - executor.placeholder(); + executor.run(image.clone(), package.name.clone(), runtime); + executor.logs(package.name.clone()); } } \ No newline at end of file From e424107447559a331c47e761b6d538eada214611 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sun, 14 Jan 2018 20:48:01 -0500 Subject: [PATCH 08/14] refactor to str refs; added readme --- rust/README.md | 52 +++++++++++++++++++++++++++++++++++++ rust/src/builder/docker.rs | 8 +++--- rust/src/builder/mod.rs | 4 +-- rust/src/executor/docker.rs | 16 ++++++------ rust/src/executor/mod.rs | 6 ++--- rust/src/lib.rs | 8 +++--- 6 files changed, 73 insertions(+), 21 deletions(-) diff --git a/rust/README.md b/rust/README.md index e69de29..4b5dc39 100644 --- a/rust/README.md +++ b/rust/README.md @@ -0,0 +1,52 @@ +# Metaparticle for Python +Metaparticle/Package is a collection of libraries intended to +make building and deploying containers a seamless and idiomatic +experience for developers. + +This is the implementation for Rust. + +## Introduction +Metaparticle/Package simplifies and centralizes the task of +building and deploying a container image. + +Here is a quick example. + +Consider this simple Python application: +```rust +fn main() { + println!("Hello World!"); +} +``` + +To containerize this application, you need to use the `metaparticle` crate and +the `containerize` wrapper function like this: + +```rust +fn run() { + println!("Hello World!"); +} + +fn main() { + let runtime = metaparticle::Runtime{ + ..Default::default() + }; + let package = metaparticle::Package{ + name: "hello".to_string(), + ..Default::default() + }; + metaparticle::containerize(run, runtime, package) +} +``` + +When you run this application, instead of printing "Hello world", it first packages itself as a container, and +then (optionally) deploys itself inside that container. + +## Tutorial + +```bash +git clone https://github.com/metaparticle-io/package/ +cd package/rust + +cargo build --example hello +./target/debug/examples/hello +``` \ No newline at end of file diff --git a/rust/src/builder/docker.rs b/rust/src/builder/docker.rs index ad43dc0..c323a65 100644 --- a/rust/src/builder/docker.rs +++ b/rust/src/builder/docker.rs @@ -4,10 +4,10 @@ use Builder; pub struct DockerBuilder{} impl Builder for DockerBuilder { - fn build(&self, dir: String, image: String) { - run_docker_process(vec!["build".to_string(), "-t".to_string()+&image, dir]); + fn build(&self, dir: &str, image: &str) { + run_docker_process(vec!["build", &*format!("-t{}", image), dir]); } - fn push(&self, image: String) { - run_docker_process(vec!["push".to_string(), image.to_string()]); + fn push(&self, image: &str) { + run_docker_process(vec!["push", image]); } } \ No newline at end of file diff --git a/rust/src/builder/mod.rs b/rust/src/builder/mod.rs index 7da0996..17e443f 100644 --- a/rust/src/builder/mod.rs +++ b/rust/src/builder/mod.rs @@ -3,6 +3,6 @@ use super::run_docker_process; pub trait Builder { - fn build(&self, dir: String, image: String); - fn push(&self, image: String); + fn build(&self, dir: &str, image: &str); + fn push(&self, image: &str); } \ No newline at end of file diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs index c61be0c..83ebe2c 100644 --- a/rust/src/executor/docker.rs +++ b/rust/src/executor/docker.rs @@ -5,19 +5,19 @@ use Executor; pub struct DockerExecutor{} impl Executor for DockerExecutor { - fn cancel(&self, name: String) { - run_docker_process(vec!["stop".to_string(), name.clone()]); - run_docker_process(vec!["rm".to_string(), "-f".to_string(), name.clone()]); + fn cancel(&self, name: &str) { + run_docker_process(vec!["stop", name]); + run_docker_process(vec!["rm", "-f", name]); } - fn logs(&self, name: String) { - run_docker_process(vec!["logs".to_string(), "-f".to_string(), name]); + fn logs(&self, name: &str) { + run_docker_process(vec!["logs", "-f", name]); } - fn run(&self, image: String, name: String, config: Runtime) { - let mut args = vec!["run".to_string(), "-d".to_string(), "--name".to_string(), name]; + fn run(&self, image: &str, name: &str, config: Runtime) { + let mut args = vec!["run", "-d", "--name", name]; if let Some(port) = config.ports { - args.extend(vec!["-p".to_string(), port.to_string()]); + args.extend(vec!["-p",&*format!("-p{}", port)]); } args.extend(vec![image]); run_docker_process(args); diff --git a/rust/src/executor/mod.rs b/rust/src/executor/mod.rs index 22a1708..9221027 100644 --- a/rust/src/executor/mod.rs +++ b/rust/src/executor/mod.rs @@ -3,7 +3,7 @@ use super::Runtime; use super::run_docker_process; pub trait Executor { - fn cancel(&self, name: String); - fn logs(&self, name: String); - fn run(&self, image: String, name: String, config: Runtime); + fn cancel(&self, name: &str); + fn logs(&self, name: &str); + fn run(&self, image: &str, name: &str, config: Runtime); } \ No newline at end of file diff --git a/rust/src/lib.rs b/rust/src/lib.rs index c39d7ec..368762e 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -61,7 +61,7 @@ impl Default for Package { } } -pub fn run_docker_process(args: Vec) { +pub fn run_docker_process(args: Vec<&str>) { let name = args[0].clone(); let mut child = process::Command::new("docker") .args(&args) @@ -141,10 +141,10 @@ pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { write_dockerfile(&package.name); let builder = build_from_runtime(package.builder.clone()); - builder.build(".".to_string(), image.clone()); + builder.build(".", image); let executor = executor_from_runtime(runtime.executor.clone()); - executor.run(image.clone(), package.name.clone(), runtime); - executor.logs(package.name.clone()); + executor.run(image, &package.name, runtime); + executor.logs(&package.name); } } \ No newline at end of file From 7ea033ad21e53c6d5d37711117344bdc25fb38c1 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Mon, 15 Jan 2018 06:51:31 -0500 Subject: [PATCH 09/14] We need strings here, I think The result of the format! call is a string, (as is the result of other ways of getting a u64 into a string). This change makes the method compile without changing anything's type signature. There might be other was to accomplish this, but I haven't found one. --- rust/src/executor/docker.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs index 83ebe2c..5d63b8a 100644 --- a/rust/src/executor/docker.rs +++ b/rust/src/executor/docker.rs @@ -2,6 +2,8 @@ use super::run_docker_process; use super::Runtime; use Executor; +use std::iter::Iterator; + pub struct DockerExecutor{} impl Executor for DockerExecutor { @@ -15,12 +17,21 @@ impl Executor for DockerExecutor { } fn run(&self, image: &str, name: &str, config: Runtime) { - let mut args = vec!["run", "-d", "--name", name]; + let mut args = vec![ "run".to_string(), + "-d".to_string(), + "--name".to_string(), + name.to_string()]; + if let Some(port) = config.ports { - args.extend(vec!["-p",&*format!("-p{}", port)]); + args.push(format!("-p {}", port)); } - args.extend(vec![image]); - run_docker_process(args); + + args.push(image.to_string()); + let args_refs = args.iter() + .map(|a| a.as_ref()) + .collect(); + + run_docker_process(args_refs); } } From 5d199e6dd7ad829122769ff92fca192ccf896126 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sat, 27 Jan 2018 18:52:31 -0500 Subject: [PATCH 10/14] added web example --- rust/.gitignore | 3 +- rust/Cargo.toml | 4 +++ rust/examples/hello.rs | 2 +- rust/examples/web.rs | 61 +++++++++++++++++++++++++++++++++++++ rust/src/executor/docker.rs | 3 +- rust/src/lib.rs | 13 ++++++-- 6 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 rust/examples/web.rs diff --git a/rust/.gitignore b/rust/.gitignore index 869df07..fa1050b 100644 --- a/rust/.gitignore +++ b/rust/.gitignore @@ -1,2 +1,3 @@ /target -Cargo.lock \ No newline at end of file +Cargo.lock +Dockerfile diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0e6fb5b..f8697af 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -6,4 +6,8 @@ version = "0.0.1" name = "hello" path = "examples/hello.rs" +[[example]] +name = "web" +path = "examples/web.rs" + [dependencies] \ No newline at end of file diff --git a/rust/examples/hello.rs b/rust/examples/hello.rs index 6a7e589..8d0145b 100644 --- a/rust/examples/hello.rs +++ b/rust/examples/hello.rs @@ -6,11 +6,11 @@ fn run() { fn main() { let runtime = metaparticle::Runtime{ - ports: Some(80), ..Default::default() }; let package = metaparticle::Package{ name: "hello".to_string(), + repository: "brendanburns".to_string(), ..Default::default() }; metaparticle::containerize(run, runtime, package) diff --git a/rust/examples/web.rs b/rust/examples/web.rs new file mode 100644 index 0000000..a54f647 --- /dev/null +++ b/rust/examples/web.rs @@ -0,0 +1,61 @@ +extern crate metaparticle; + +use std::net::{TcpStream, TcpListener}; +use std::io::{Read, Write}; +use std::thread; + + +fn handle_read(mut stream: &TcpStream) { + let mut buf = [0u8 ;4096]; + match stream.read(&mut buf) { + Ok(_) => { + let req_str = String::from_utf8_lossy(&buf); + println!("{}", req_str); + }, + Err(e) => println!("Unable to read stream: {}", e), + } +} + +fn handle_write(mut stream: TcpStream) { + let response = b"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\nHello world\r\n"; + match stream.write(response) { + Ok(_) => println!("Response sent"), + Err(e) => println!("Failed sending response: {}", e), + } +} + +fn handle_client(stream: TcpStream) { + handle_read(&stream); + handle_write(stream); +} + +fn run() { + let listener = TcpListener::bind("127.0.0.1:8080").unwrap(); + println!("Listening for connections on port {}", 8080); + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + thread::spawn(|| { + handle_client(stream) + }); + } + Err(e) => { + println!("Unable to connect: {}", e); + } + } + } +} + +fn main() { + let runtime = metaparticle::Runtime{ + ports: Some(8080), + ..Default::default() + }; + let package = metaparticle::Package{ + name: "hello".to_string(), + repository: "brendanburns".to_string(), + ..Default::default() + }; + metaparticle::containerize(run, runtime, package) +} \ No newline at end of file diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs index 5d63b8a..d1142ac 100644 --- a/rust/src/executor/docker.rs +++ b/rust/src/executor/docker.rs @@ -19,11 +19,12 @@ impl Executor for DockerExecutor { fn run(&self, image: &str, name: &str, config: Runtime) { let mut args = vec![ "run".to_string(), "-d".to_string(), + "--rm".to_string(), "--name".to_string(), name.to_string()]; if let Some(port) = config.ports { - args.push(format!("-p {}", port)); + args.push(format!("-p {port}", port=port)); } args.push(image.to_string()); diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 368762e..6f1b10a 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -29,7 +29,7 @@ impl Default for Runtime { Runtime { replicas: None, shards: None, - url_shard_pattern: Some("something".to_string()), + url_shard_pattern: Some("".to_string()), executor: "docker".to_string(), ports: None, public_address: Some(false) @@ -51,8 +51,8 @@ pub struct Package { impl Default for Package { fn default() -> Package { Package { - name: "name".to_string(), - repository: "repository".to_string(), + name: "".to_string(), + repository: "".to_string(), verbose: Some(false), quiet: Some(false), builder: "docker".to_string(), @@ -137,6 +137,13 @@ pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { if in_docker_container() { f(); } else { + + if package.repository.len() == 0 { + panic!("A package must be given a 'repository' value"); + } + if package.name.len() == 0 { + panic!("A package must be given a 'name' value"); + } let image = &format!("{repo}/{name}:latest", repo=package.repository, name=package.name); write_dockerfile(&package.name); From 493b3b61ce6a761b49754b34dfdaa49b9174b372 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Sat, 27 Jan 2018 19:35:12 -0500 Subject: [PATCH 11/14] use executable's path as Docker context --- rust/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 368762e..24fbd53 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -141,7 +141,12 @@ pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { write_dockerfile(&package.name); let builder = build_from_runtime(package.builder.clone()); - builder.build(".", image); + + let arg_0 = env::args().nth(0).unwrap(); + let path = Path::new(&arg_0); + let docker_context = Path::new(path.parent().unwrap()); + + builder.build(docker_context.to_str().unwrap(), image); let executor = executor_from_runtime(runtime.executor.clone()); executor.run(image, &package.name, runtime); From 886fb0102f80de432dac42ffbf4920efd7d42a33 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sat, 27 Jan 2018 19:39:50 -0500 Subject: [PATCH 12/14] wrapped docker cmds in sh --- rust/examples/web.rs | 2 +- rust/src/builder/docker.rs | 4 ++-- rust/src/executor/docker.rs | 27 ++++++++++----------------- rust/src/lib.rs | 9 ++++++--- 4 files changed, 19 insertions(+), 23 deletions(-) diff --git a/rust/examples/web.rs b/rust/examples/web.rs index a54f647..8a9645a 100644 --- a/rust/examples/web.rs +++ b/rust/examples/web.rs @@ -53,7 +53,7 @@ fn main() { ..Default::default() }; let package = metaparticle::Package{ - name: "hello".to_string(), + name: "web".to_string(), repository: "brendanburns".to_string(), ..Default::default() }; diff --git a/rust/src/builder/docker.rs b/rust/src/builder/docker.rs index c323a65..83f6e7e 100644 --- a/rust/src/builder/docker.rs +++ b/rust/src/builder/docker.rs @@ -5,9 +5,9 @@ pub struct DockerBuilder{} impl Builder for DockerBuilder { fn build(&self, dir: &str, image: &str) { - run_docker_process(vec!["build", &*format!("-t{}", image), dir]); + run_docker_process(vec!["docker", "build", &*format!("-t{}", image), dir]); } fn push(&self, image: &str) { - run_docker_process(vec!["push", image]); + run_docker_process(vec!["docker", "push", image]); } } \ No newline at end of file diff --git a/rust/src/executor/docker.rs b/rust/src/executor/docker.rs index d1142ac..31610af 100644 --- a/rust/src/executor/docker.rs +++ b/rust/src/executor/docker.rs @@ -2,37 +2,30 @@ use super::run_docker_process; use super::Runtime; use Executor; -use std::iter::Iterator; - pub struct DockerExecutor{} impl Executor for DockerExecutor { fn cancel(&self, name: &str) { - run_docker_process(vec!["stop", name]); - run_docker_process(vec!["rm", "-f", name]); + run_docker_process(vec!["docker", "stop", name]); + run_docker_process(vec!["docker", "rm", "-f", name]); } fn logs(&self, name: &str) { - run_docker_process(vec!["logs", "-f", name]); + run_docker_process(vec!["docker", "logs", "-f", name]); } fn run(&self, image: &str, name: &str, config: Runtime) { - let mut args = vec![ "run".to_string(), - "-d".to_string(), - "--rm".to_string(), - "--name".to_string(), - name.to_string()]; - + let mut ports = String::new(); + let mut args = vec!["docker", "run", "-d", "--rm", "--name", name]; + if let Some(port) = config.ports { - args.push(format!("-p {port}", port=port)); + ports.push_str(&format!("-p {port}", port=port)); + args.push(&ports); } - args.push(image.to_string()); - let args_refs = args.iter() - .map(|a| a.as_ref()) - .collect(); + args.push(image); - run_docker_process(args_refs); + run_docker_process(args); } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 6f1b10a..b543371 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -62,9 +62,12 @@ impl Default for Package { } pub fn run_docker_process(args: Vec<&str>) { - let name = args[0].clone(); - let mut child = process::Command::new("docker") - .args(&args) + let name = args[1].clone(); + let cmd = args.join(" "); + + let mut child = process::Command::new("sh") + .arg("-c") + .arg(cmd) .spawn() .expect(&format!("failed to execute 'docker {name}'", name=name)); From aff0386d9e57a523519370439f8b9b9ac13ce1b7 Mon Sep 17 00:00:00 2001 From: wagoodman Date: Sat, 27 Jan 2018 20:14:49 -0500 Subject: [PATCH 13/14] write dockerfile to docker context explicitly --- rust/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index d514fa2..532752f 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -116,12 +116,13 @@ fn build_from_runtime(builder_name: String) -> Box { } -fn write_dockerfile(name: &str) { +fn write_dockerfile(name: &str, dest: &Path) { let dockerfile = &format!("FROM ubuntu:16.04 COPY ./{name} /tmp/{name} CMD /tmp/{name} ", name=name); - let path = Path::new("Dockerfile"); + let file = Path::new("Dockerfile"); + let path = dest.join(&file); let display = path.display(); let mut file = match File::create(&path) { @@ -149,13 +150,13 @@ pub fn containerize(f: F, runtime: Runtime, package: Package) where F: Fn() { } let image = &format!("{repo}/{name}:latest", repo=package.repository, name=package.name); - write_dockerfile(&package.name); - let builder = build_from_runtime(package.builder.clone()); - let arg_0 = env::args().nth(0).unwrap(); let path = Path::new(&arg_0); let docker_context = Path::new(path.parent().unwrap()); + write_dockerfile(&package.name, docker_context); + let builder = build_from_runtime(package.builder.clone()); + builder.build(docker_context.to_str().unwrap(), image); let executor = executor_from_runtime(runtime.executor.clone()); From dd3c9ef8ea4f69f3fcedc866f29654aacfab9dd7 Mon Sep 17 00:00:00 2001 From: Will Murphy Date: Fri, 23 Feb 2018 07:29:02 -0500 Subject: [PATCH 14/14] fix copy paste error in README --- rust/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rust/README.md b/rust/README.md index 4b5dc39..80f44d4 100644 --- a/rust/README.md +++ b/rust/README.md @@ -1,4 +1,4 @@ -# Metaparticle for Python +# Metaparticle for Rust Metaparticle/Package is a collection of libraries intended to make building and deploying containers a seamless and idiomatic experience for developers. @@ -11,7 +11,7 @@ building and deploying a container image. Here is a quick example. -Consider this simple Python application: +Consider this simple Rust application: ```rust fn main() { println!("Hello World!");