From 1d4c80e34f3862d94d4c059cf32262e80d1439db Mon Sep 17 00:00:00 2001 From: Justin Patriquin Date: Thu, 27 Oct 2022 13:58:36 -0300 Subject: [PATCH] add nitrogen start command (#29) --- Cargo.lock | 250 ++++++++++++++++++++++++++++++++++++----- Cargo.toml | 2 + src/bin/nitrogen.rs | 112 +++++++++++++++++- src/commands/deploy.rs | 4 +- 4 files changed, 335 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e7e8fa7..ea96287 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,9 +346,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" @@ -356,6 +356,15 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", +] + [[package]] name = "bumpalo" version = "3.11.1" @@ -392,9 +401,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.0.17" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06badb543e734a2d6568e19a40af66ed5364360b9226184926f89d229b4b4267" +checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b" dependencies = [ "atty", "bitflags", @@ -407,9 +416,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.0.13" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad" +checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3" dependencies = [ "heck", "proc-macro-error", @@ -443,6 +452,25 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +[[package]] +name = "cpufeatures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "ct-logs" version = "0.8.0" @@ -452,6 +480,16 @@ dependencies = [ "sct", ] +[[package]] +name = "digest" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "either" version = "1.8.0" @@ -506,24 +544,24 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-macro" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", @@ -532,21 +570,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-macro", @@ -556,6 +594,27 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.26.2" @@ -564,9 +623,9 @@ checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "h2" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca32592cf21ac7ccab1825cd87f6c9b3d9022c44d086172ed0966bec8af30be" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ "bytes", "fnv", @@ -734,9 +793,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.135" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "lock_api" @@ -783,14 +842,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi", - "windows-sys 0.36.1", + "windows-sys 0.42.0", ] [[package]] @@ -802,6 +861,8 @@ dependencies = [ "clap", "failure", "home", + "rand", + "rust-embed", "tokio", "tracing", "tracing-subscriber", @@ -949,6 +1010,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -991,6 +1058,36 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -1041,6 +1138,40 @@ dependencies = [ "winapi", ] +[[package]] +name = "rust-embed" +version = "6.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283ffe2f866869428c92e0d61c2f35dfb4355293cdfdc48f49e895c15f1333d1" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31ab23d42d71fb9be1b643fe6765d292c5e14d46912d13f3ae2815ca048ea04d" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1669d81dfabd1b5f8e2856b8bbe146c6192b0ba22162edc738ac0a5de18f054" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.21" @@ -1087,6 +1218,15 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.20" @@ -1142,6 +1282,23 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" +[[package]] +name = "serde" +version = "1.0.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.4" @@ -1199,9 +1356,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", @@ -1240,12 +1397,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c" +checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" dependencies = [ "libc", "num_threads", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + +[[package]] +name = "time-macros" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +dependencies = [ + "time-core", ] [[package]] @@ -1412,6 +1587,12 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-ident" version = "1.0.5" @@ -1448,6 +1629,17 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 6ff10d4..f3dfb9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,5 @@ tokio = { version = "1", features = ["full"] } tracing = "0.1" tracing-subscriber = {version = "0.3", features = ["env-filter"]} home = "0.5.4" +rust-embed = "6.4.2" +rand = "0.8.5" diff --git a/src/bin/nitrogen.rs b/src/bin/nitrogen.rs index 74299b0..c515aee 100644 --- a/src/bin/nitrogen.rs +++ b/src/bin/nitrogen.rs @@ -1,4 +1,10 @@ +use rand::{distributions::Alphanumeric, Rng}; +use std::env::temp_dir; +use std::fs::{create_dir, File}; use std::io; +use std::io::Write; +use std::path::Path; +use std::time::Duration; use aws_sdk_cloudformation::Client; use clap::{Parser, Subcommand}; @@ -7,6 +13,12 @@ use nitrogen::commands::{build, delete, deploy, setup}; use nitrogen::template::SETUP_TEMPLATE; use tracing::{debug, info}; +use rust_embed::{EmbeddedFile, RustEmbed}; + +#[derive(RustEmbed)] +#[folder = "examples/"] +struct Asset; + #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Cli { @@ -57,7 +69,7 @@ enum Commands { ssh_key: String, /// Number of CPUs to provision for the enclave #[arg(short, long, default_value_t = 2)] - cpu_count: u8, + cpu_count: u64, /// Memory in MB to provision for the enclave. Defaults to 5x EIF size if not supplied. #[arg(short, long)] memory: Option, @@ -68,6 +80,25 @@ enum Commands { /// Name of the provisioned instance name: String, }, + + Start { + name: String, + + /// EC2 key-pair to use for the provisioned instance + key_name: String, + + /// EC2 key-pair to use for the provisioned instance + public_key: String, + /// EC2-instance type. Must be Nitro compatible + #[arg(long, default_value_t = String::from("m5a.xlarge"))] + instance_type: String, + /// EC2-instance port for socat enclave connection + #[arg(short, long, default_value_t = 5000)] + port: usize, + /// IP address range that can be used to SSH to the EC2 instance. + #[arg(short, long, default_value_t = String::from("0.0.0.0/0"))] + ssh_location: String, + }, } #[tokio::main] @@ -140,7 +171,7 @@ async fn main() -> Result<(), Error> { info!(eif, "Deploying EIF to {}", instance); let shared_config = aws_config::from_env().load().await; let client = Client::new(&shared_config); - let out = deploy(&client, &instance, &eif, &ssh_key, &cpu_count, memory).await?; + let out = deploy(&client, &instance, &eif, &ssh_key, cpu_count, memory).await?; debug!("{:?}", out); Ok(()) } @@ -152,5 +183,82 @@ async fn main() -> Result<(), Error> { delete(&client, &name).await?; Ok(()) } + Commands::Start { + name, + key_name, + port, + instance_type, + ssh_location, + public_key, + } => { + let dockerfile = + Asset::get(&format!("{}/Dockerfile", name)).expect("unable to get dockerfile"); + let appsh = Asset::get(&format!("{}/app.sh", name)).expect("unable to get app.sh"); + let runsh = Asset::get(&format!("{}/run.sh", name)).expect("unable to get run.sh"); + + let dir = temp_dir(); + + let random_id: String = rand::thread_rng() + .sample_iter(&Alphanumeric) + .take(7) + .map(char::from) + .collect(); + + let id = format!("{}-{}", name, random_id); + + let proj_dir = dir.as_path().join(&id); + + create_dir(&proj_dir)?; + + let dockerfile_path = &proj_dir.join("Dockerfile"); + + create_file(dockerfile_path, dockerfile)?; + create_file(&proj_dir.join("run.sh"), appsh)?; + create_file(&proj_dir.join("app.sh"), runsh)?; + + let ssh_location = ssh_location.to_string(); + let instance_type = instance_type.to_string(); + let setup_template = SETUP_TEMPLATE.to_string(); + let shared_config = aws_config::from_env().load().await; + let client = Client::new(&shared_config); + setup( + &client, + &setup_template, + &id, + &instance_type, + &port, + &key_name, + &ssh_location, + ) + .await?; + + // TODO should save this somewhere else than their current directory + let eif_path = &format!("{}.eif", name); + + build( + &dockerfile_path.to_str().unwrap().to_string(), + &proj_dir.to_str().unwrap().to_string(), + eif_path, + ) + .await?; + + println!("Sleeping for 20s to give ec2 instance a chance to boot..."); + tokio::time::sleep(Duration::from_secs(20)).await; + + let out = deploy(&client, &id, eif_path, &public_key, 2, None).await?; + + println!("{:?}", out); + + Ok(()) + } } } + +fn create_file(path: &Path, embedded: EmbeddedFile) -> Result<(), Error> { + let mut f = File::create(path)?; + let bytes = embedded.data.as_ref(); + + f.write_all(bytes)?; + + Ok(()) +} diff --git a/src/commands/deploy.rs b/src/commands/deploy.rs index 65834a5..f3af5b1 100644 --- a/src/commands/deploy.rs +++ b/src/commands/deploy.rs @@ -129,7 +129,7 @@ fn deploy_eif(eif_path: &str, ssh_key: &str, url: &str) -> Result<(), Error> { fn run_eif( eif_path: &str, - cpu_count: &u8, + cpu_count: u64, mem: &u64, ssh_key: &str, url: &str, @@ -170,7 +170,7 @@ pub async fn deploy( instance: &str, eif: &String, ssh_key: &String, - cpu_count: &u8, + cpu_count: u64, memory: Option, ) -> Result { let this_stack = get_stack(client, instance).await?;