From 10358c1ae179166a5410b9161378fe528e7a918b Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Thu, 18 Aug 2022 22:00:08 +0200 Subject: [PATCH 01/26] docs: Cache option doc --- src/build.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/build.rs b/src/build.rs index a8b0f50..a75d041 100644 --- a/src/build.rs +++ b/src/build.rs @@ -29,9 +29,13 @@ pub struct Build { #[derive(clap::ValueEnum, Clone, Debug)] pub enum Cache { + /// Handle cache with a local directory ".lenra/dockercache" Local, + /// Handle cache in the built image "lenra/app:latest" Inline, + /// Handle cache with a specific image "lenra/app:cache" Image, + /// Disable cache No, } @@ -137,6 +141,11 @@ impl Build { } } + fn generate_docker_compose(&self, dockerfile: Option) { + + } + + #[deprecated] /// Builds a Dockerfile. If None, get's it at the default path: ./.lenra/Dockerfile fn build_docker_image(&self, dockerfile: Option) { log::info!("Build the Docker image"); From 0fd6b264f0235d4783a13ae8a191599e5b484d77 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Mon, 22 Aug 2022 18:45:46 +0200 Subject: [PATCH 02/26] feat: use docker-compose --- Cargo.lock | 119 +++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 2 + src/build.rs | 77 +++++++++++++-------------- src/config.rs | 8 ++- src/docker_compose.rs | 66 +++++++++++++++++++++++ src/main.rs | 1 + src/start.rs | 63 +++++++++++++++++++++- 7 files changed, 290 insertions(+), 46 deletions(-) create mode 100644 src/docker_compose.rs diff --git a/Cargo.lock b/Cargo.lock index 4bf7809..d1197f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -79,6 +79,81 @@ dependencies = [ "os_str_bytes", ] +[[package]] +name = "darling" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07adf7be193b71cc36b193d0f5fe60b918a3a9db4dad0449f57bcfd519704a3" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "docker-compose-types" +version = "0.2.0" +dependencies = [ + "derive_builder", + "serde", + "serde_yaml 0.8.26", +] + [[package]] name = "dofigen" version = "1.0.0" @@ -88,7 +163,7 @@ dependencies = [ "clap", "serde", "serde_json", - "serde_yaml", + "serde_yaml 0.9.9", "thiserror", ] @@ -105,6 +180,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "hashbrown" version = "0.12.3" @@ -132,6 +213,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "indexmap" version = "1.9.1" @@ -159,6 +246,7 @@ name = "lenra_cli" version = "0.0.0" dependencies = [ "clap", + "docker-compose-types", "dofigen", "env_logger", "lazy_static", @@ -166,7 +254,7 @@ dependencies = [ "regex", "serde", "serde_json", - "serde_yaml", + "serde_yaml 0.9.9", ] [[package]] @@ -175,6 +263,12 @@ version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "log" version = "0.4.17" @@ -298,6 +392,18 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" +dependencies = [ + "indexmap", + "ryu", + "serde", + "yaml-rust", +] + [[package]] name = "serde_yaml" version = "0.9.9" @@ -411,3 +517,12 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] diff --git a/Cargo.toml b/Cargo.toml index 6b64d92..075fb14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,5 @@ env_logger = "0.9.0" regex = "1.6.0" lazy_static = "1.4.0" dofigen = "1" +docker-compose-types = { version = "0.2.0", path = "../docker-compose-types" } +# docker-compose-types = "0.2.0" diff --git a/src/build.rs b/src/build.rs index a75d041..5af9fad 100644 --- a/src/build.rs +++ b/src/build.rs @@ -10,11 +10,12 @@ use dofigen_lib::{ }; use crate::cli::CliCommand; -use crate::config::{load_config_file, Generator, DEFAULT_CONFIG_FILE, LENRA_CACHE_DIRECTORY}; +use crate::config::{load_config_file, Generator, DEFAULT_CONFIG_FILE, LENRA_CACHE_DIRECTORY, DOCKERFILE_DEFAULT_PATH, DOCKERIGNORE_DEFAULT_PATH, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::docker_compose::generate_docker_compose_file; -static OF_WATCHDOG_BUILDER: &str = "of-watchdog"; -static OF_WATCHDOG_IMAGE: &str = "ghcr.io/openfaas/of-watchdog"; -static OF_WATCHDOG_VERSION: &str = "0.9.6"; +const OF_WATCHDOG_BUILDER: &str = "of-watchdog"; +const OF_WATCHDOG_IMAGE: &str = "ghcr.io/openfaas/of-watchdog"; +const OF_WATCHDOG_VERSION: &str = "0.9.6"; #[derive(clap::Args)] pub struct Build { @@ -22,7 +23,7 @@ pub struct Build { #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] pub config: std::path::PathBuf, - /// The app configuration file. + /// The cache management. #[clap(value_enum, long, default_value = "local")] pub cache: Cache, } @@ -50,8 +51,11 @@ impl Build { let dockerignore = generate_dockerignore(&of_overlay); self.save_docker_content(dockerfile, Some(dockerignore)); + // Generate docker-compose file + self.generate_docker_compose(None); + // build the generated Dockerfile - self.build_docker_image(None); + self.build_docker_compose(); } /// Add an overlay to the given Dofigen structure to manage OpenFaaS @@ -132,8 +136,8 @@ impl Build { dockerfile_content: String, dockerignore_content: Option, ) { - let dockerfile_path: PathBuf = [LENRA_CACHE_DIRECTORY, "Dockerfile"].iter().collect(); - let dockerignore_path: PathBuf = [LENRA_CACHE_DIRECTORY, ".dockerignore"].iter().collect(); + let dockerfile_path: PathBuf = DOCKERFILE_DEFAULT_PATH.iter().collect(); + let dockerignore_path: PathBuf = DOCKERIGNORE_DEFAULT_PATH.iter().collect(); fs::write(dockerfile_path, dockerfile_content).expect("Unable to write the Dockerfile"); if let Some(content) = dockerignore_content { @@ -141,49 +145,31 @@ impl Build { } } + /// Generates the docker-compose.yml file fn generate_docker_compose(&self, dockerfile: Option) { - + let compose_content = generate_docker_compose_file( + dockerfile.unwrap_or(DOCKERFILE_DEFAULT_PATH.iter().collect()), + ); + let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); } - #[deprecated] /// Builds a Dockerfile. If None, get's it at the default path: ./.lenra/Dockerfile - fn build_docker_image(&self, dockerfile: Option) { + fn build_docker_compose(&self) { log::info!("Build the Docker image"); - let dockerfile_path: PathBuf = - dockerfile.unwrap_or([LENRA_CACHE_DIRECTORY, "Dockerfile"].iter().collect()); - let cache_directory: PathBuf = [LENRA_CACHE_DIRECTORY, "dockercache"].iter().collect(); + let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); let mut command = Command::new("docker"); - let image_name = "lenra/app"; // TODO: display std out & err command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); command .arg("buildx") - .arg("build") + .arg("bake") .arg("-f") - .arg(dockerfile_path); - - match self.cache { - Cache::Inline => command - .arg("--cache-to=type=inline") - .arg(format!("--cache-from={}", image_name)), - Cache::Local => command - .arg(format!( - "--cache-to=type=local,dest={}", - cache_directory.display() - )) - .arg(format!( - "--cache-from=type=local,src={}", - cache_directory.display() - )), - Cache::Image => command - .arg(format!("--cache-to={}:cache", image_name)) - .arg(format!("--cache-from={}:cache", image_name)), - Cache::No => &command, - }; - command.arg("-t").arg(image_name).arg("--load").arg("."); + .arg(dockercompose_path) + .arg("--load"); - log::debug!("Build image: {:?}", command); + log::debug!("Build: {:?}", command); let output = command.output().expect("Failed building the Docker image"); if !output.status.success() { panic!( @@ -212,10 +198,21 @@ impl CliCommand for Build { Generator::DofigenError { dofigen: _ } => { panic!("Your Dofigen configuration is not correct") } - Generator::Dockerfile(dockerfile) => self.build_docker_image(Some(dockerfile.docker)), + Generator::Dockerfile(dockerfile) => { + // Generate docker-compose file + self.generate_docker_compose(Some(dockerfile.docker)); + + // build the Dockerfile + self.build_docker_compose(); + } Generator::Docker(docker) => { self.save_docker_content(docker.docker, docker.ignore); - self.build_docker_image(None); + + // Generate docker-compose file + self.generate_docker_compose(None); + + // build the Dockerfile + self.build_docker_compose(); } } } diff --git a/src/config.rs b/src/config.rs index 72d5526..0498e54 100644 --- a/src/config.rs +++ b/src/config.rs @@ -4,8 +4,12 @@ use dofigen_lib::Image; use serde::{Deserialize, Serialize}; use serde_yaml::Value; -pub static DEFAULT_CONFIG_FILE: &str = "lenra.yml"; -pub static LENRA_CACHE_DIRECTORY: &str = ".lenra"; +pub const DEFAULT_CONFIG_FILE: &str = "lenra.yml"; +pub const LENRA_CACHE_DIRECTORY: &str = ".lenra"; + +pub const DOCKERFILE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfile"]; +pub const DOCKERIGNORE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, ".dockerignore"]; +pub const DOCKERCOMPOSE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "docker-compose.yml"]; pub fn load_config_file(path: &std::path::PathBuf) -> Application { let file = fs::File::open(path).unwrap(); diff --git a/src/docker_compose.rs b/src/docker_compose.rs new file mode 100644 index 0000000..0c5d144 --- /dev/null +++ b/src/docker_compose.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +use docker_compose_types::{ + AdvancedBuildStep, BuildStep, Compose, DependsOnOptions, Environment, Service, Services, +}; + +pub const APP_SERVICE_NAME: &str = "app"; +pub const DEVTOOL_SERVICE_NAME: &str = "devtool"; +pub const POSTGRES_SERVICE_NAME: &str = "postgres"; +const DEVTOOL_IMAGE: &str = "lenra/devtools:beta"; +const DEVTOOL_PORT: u16 = 4000; + +pub fn generate_docker_compose_file(dockerfile: PathBuf) -> String { + let postgres_envs = [ + ("POSTGRES_USER".to_string(), Some("postgres".to_string())), + ( + "POSTGRES_PASSWORD".to_string(), + Some("postgres".to_string()), + ), + ("POSTGRES_HOST".to_string(), Some("postgres".to_string())), + ("POSTGRES_DB".to_string(), Some("lenra_devtool".to_string())), + ]; + let compose = Compose { + services: Some(Services( + [ + ( + APP_SERVICE_NAME.into(), + Some(Service { + build_: Some(BuildStep::Advanced(AdvancedBuildStep { + context: "..".into(), + dockerfile: Some(dockerfile.to_str().unwrap().into()), + ..Default::default() + })), + depends_on: Some(DependsOnOptions::Simple(vec![ + DEVTOOL_SERVICE_NAME.into() + ])), + ..Default::default() + }), + ), + ( + DEVTOOL_SERVICE_NAME.into(), + Some(Service { + image: Some(DEVTOOL_IMAGE.into()), + ports: Some(vec![format!("{}", DEVTOOL_PORT)]), + environment: Some(Environment::KvPair(postgres_envs.clone().into())), + depends_on: Some(DependsOnOptions::Simple(vec![ + POSTGRES_SERVICE_NAME.into() + ])), + ..Default::default() + }), + ), + ( + POSTGRES_SERVICE_NAME.into(), + Some(Service { + image: Some(DEVTOOL_IMAGE.into()), + environment: Some(Environment::KvPair(postgres_envs.into())), + ..Default::default() + }), + ), + ] + .into(), + )), + ..Default::default() + }; + serde_yaml::to_string(&compose).expect("Error generating the docker-compose file content") +} diff --git a/src/main.rs b/src/main.rs index 030563a..9522d4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use env_logger; mod build; mod cli; mod config; +mod docker_compose; mod new; mod start; diff --git a/src/start.rs b/src/start.rs index 6626f53..417d89b 100644 --- a/src/start.rs +++ b/src/start.rs @@ -1,17 +1,76 @@ +use std::path::PathBuf; +use std::process::{Command, Stdio}; + pub use clap::Args; use crate::cli::CliCommand; -use crate::config::DEFAULT_CONFIG_FILE; +use crate::config::{DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::docker_compose::APP_SERVICE_NAME; #[derive(Args)] pub struct Start { /// The app configuration file. #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] pub config: std::path::PathBuf, + + /// The service attached. + #[clap(value_enum, long, default_value = "app")] + pub attach: Attach, +} + +#[derive(clap::ValueEnum, Clone, Debug)] +pub enum Attach { + /// Attach app service + App, + /// Attach devtool service + Devtool, + /// Attach database service + Database, + /// Attach all services + All, + /// Detach + None, +} + +impl Start { + /// Starts the docker-compose + fn start_docker_compose(&self) { + let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + let mut command = Command::new("docker"); + + // TODO: display std out & err + command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); + command + .arg("compose") + .arg("-f") + .arg(dockercompose_path) + .arg("up"); + match self.attach { + Attach::App => command.arg("--attach").arg(APP_SERVICE_NAME), + Attach::Devtool => command.arg("--attach").arg(APP_SERVICE_NAME), + Attach::Database => command.arg("--attach").arg(APP_SERVICE_NAME), + Attach::All => &command, + Attach::None => command.arg("-d"), + }; + + log::debug!("Start: {:?}", command); + let output = command + .output() + .expect("Failed to start the docker-compose app"); + if !output.status.success() { + panic!( + "An error occured while running the docker-compose app:\n{}\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ) + } + } } impl CliCommand for Start { fn run(&self) { - todo!() + log::info!("Starting the app"); + self.start_docker_compose(); + log::info!("App is stopped"); } } From fec4e73356fd9584e612217b6faca8cd4e5755a4 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 24 Aug 2022 12:31:54 +0200 Subject: [PATCH 03/26] refactor: Moves the files generation in config --- Cargo.lock | 2 + src/build.rs | 203 +---------------------------------------- src/config.rs | 207 +++++++++++++++++++++++++++++++++++++++++- src/docker_compose.rs | 2 +- src/start.rs | 4 + 5 files changed, 215 insertions(+), 203 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1197f2..8992e99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,6 +150,7 @@ name = "docker-compose-types" version = "0.2.0" dependencies = [ "derive_builder", + "indexmap", "serde", "serde_yaml 0.8.26", ] @@ -227,6 +228,7 @@ checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] diff --git a/src/build.rs b/src/build.rs index 5af9fad..976470f 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,22 +1,14 @@ use log; -use std::collections::HashMap; use std::fs; use std::path::PathBuf; use std::process::{Command, Stdio}; use clap; -use dofigen_lib::{ - from_file_path, generate_dockerfile, generate_dockerignore, Artifact, Builder, Image, -}; use crate::cli::CliCommand; -use crate::config::{load_config_file, Generator, DEFAULT_CONFIG_FILE, LENRA_CACHE_DIRECTORY, DOCKERFILE_DEFAULT_PATH, DOCKERIGNORE_DEFAULT_PATH, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERFILE_DEFAULT_PATH, DOCKERCOMPOSE_DEFAULT_PATH}; use crate::docker_compose::generate_docker_compose_file; -const OF_WATCHDOG_BUILDER: &str = "of-watchdog"; -const OF_WATCHDOG_IMAGE: &str = "ghcr.io/openfaas/of-watchdog"; -const OF_WATCHDOG_VERSION: &str = "0.9.6"; - #[derive(clap::Args)] pub struct Build { /// The app configuration file. @@ -41,119 +33,6 @@ pub enum Cache { } impl Build { - /// Builds a Docker image from a Dofigen structure - fn build_dofigen(&self, image: Image) { - // Generate the Dofigen config with OpenFaaS overlay to handle the of-watchdog - let of_overlay = self.dofigen_of_overlay(image); - - // generate the Dockerfile and .dockerignore files with Dofigen - let dockerfile = generate_dockerfile(&of_overlay); - let dockerignore = generate_dockerignore(&of_overlay); - self.save_docker_content(dockerfile, Some(dockerignore)); - - // Generate docker-compose file - self.generate_docker_compose(None); - - // build the generated Dockerfile - self.build_docker_compose(); - } - - /// Add an overlay to the given Dofigen structure to manage OpenFaaS - fn dofigen_of_overlay(&self, image: Image) -> Image { - log::info!("Adding OpenFaaS overlay to the Dofigen descriptor"); - let mut builders = if let Some(vec) = image.builders { - vec - } else { - Vec::new() - }; - builders.push(Builder { - name: Some(String::from(OF_WATCHDOG_BUILDER)), - image: format!("{}:{}", OF_WATCHDOG_IMAGE, OF_WATCHDOG_VERSION), - ..Default::default() - }); - - let mut artifacts = if let Some(arts) = image.artifacts { - arts - } else { - Vec::new() - }; - artifacts.push(Artifact { - builder: OF_WATCHDOG_BUILDER.to_string(), - source: "/fwatchdog".to_string(), - destination: "/fwatchdog".to_string(), - }); - - let mut envs = if let Some(envs) = image.envs { - envs - } else { - HashMap::new() - }; - - if let Some(ports) = image.ports { - if ports.len() == 1 { - envs.insert("mode".to_string(), "http".to_string()); - envs.insert( - "upstream_url".to_string(), - format!("http://127.0.0.1:{}", ports[0]), - ); - } else if ports.len() > 1 { - panic!("More than one port has been defined in the Dofigen descriptor"); - } - }; - - if image.entrypoint.is_some() { - panic!("The Dofigen descriptor can't have entrypoint defined. Use cmd instead"); - } - - if let Some(cmd) = image.cmd { - envs.insert("fprocess".to_string(), cmd.join(" ")); - } else { - panic!("The Dofigen cmd property is not defined"); - } - - Image { - image: image.image, - builders: Some(builders), - artifacts: Some(artifacts), - ports: Some(vec![8080]), - envs: Some(envs), - entrypoint: None, - cmd: Some(vec!["/fwatchdog".to_string()]), - user: image.user, - workdir: image.workdir, - adds: image.adds, - root: image.root, - script: image.script, - caches: image.caches, - healthcheck: image.healthcheck, - ignores: image.ignores, - } - } - - /// Saves the Dockerfile and dockerignore (if present) files from their contents - fn save_docker_content( - &self, - dockerfile_content: String, - dockerignore_content: Option, - ) { - let dockerfile_path: PathBuf = DOCKERFILE_DEFAULT_PATH.iter().collect(); - let dockerignore_path: PathBuf = DOCKERIGNORE_DEFAULT_PATH.iter().collect(); - - fs::write(dockerfile_path, dockerfile_content).expect("Unable to write the Dockerfile"); - if let Some(content) = dockerignore_content { - fs::write(dockerignore_path, content).expect("Unable to write the .dockerignore file"); - } - } - - /// Generates the docker-compose.yml file - fn generate_docker_compose(&self, dockerfile: Option) { - let compose_content = generate_docker_compose_file( - dockerfile.unwrap_or(DOCKERFILE_DEFAULT_PATH.iter().collect()), - ); - let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); - fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); - } - /// Builds a Dockerfile. If None, get's it at the default path: ./.lenra/Dockerfile fn build_docker_compose(&self) { log::info!("Build the Docker image"); @@ -187,84 +66,8 @@ impl CliCommand for Build { let conf = load_config_file(&self.config); // TODO: check the components API version - // create the `.lenra` cache directory - fs::create_dir_all(LENRA_CACHE_DIRECTORY).unwrap(); - - match conf.generator { - Generator::Dofigen(dofigen) => self.build_dofigen(dofigen.dofigen), - Generator::DofigenFile(dofigen_file) => self.build_dofigen( - from_file_path(&dofigen_file.dofigen).expect("Failed loading the Dofigen file"), - ), - Generator::DofigenError { dofigen: _ } => { - panic!("Your Dofigen configuration is not correct") - } - Generator::Dockerfile(dockerfile) => { - // Generate docker-compose file - self.generate_docker_compose(Some(dockerfile.docker)); - - // build the Dockerfile - self.build_docker_compose(); - } - Generator::Docker(docker) => { - self.save_docker_content(docker.docker, docker.ignore); - - // Generate docker-compose file - self.generate_docker_compose(None); + conf.generate_files(); - // build the Dockerfile - self.build_docker_compose(); - } - } - } -} - -#[cfg(test)] -mod dofigen_of_overlay_tests { - use super::*; - - #[test] - fn simple_image() { - let build = Build { - config: DEFAULT_CONFIG_FILE.into(), - cache: Cache::Inline, - }; - let image = Image { - image: "my-dockerimage".into(), - cmd: Some(vec!["/app/my-app".into()]), - ..Default::default() - }; - let overlayed_image = Image { - builders: Some(vec![Builder { - name: Some("of-watchdog".into()), - image: format!("ghcr.io/openfaas/of-watchdog:{}", OF_WATCHDOG_VERSION), - ..Default::default() - }]), - image: String::from("my-dockerimage"), - envs: Some([("fprocess".to_string(), "/app/my-app".to_string())].into()), - artifacts: Some(vec![Artifact { - builder: "of-watchdog".into(), - source: "/fwatchdog".into(), - destination: "/fwatchdog".into(), - }]), - ports: Some(vec![8080]), - cmd: Some(vec!["/fwatchdog".into()]), - ..Default::default() - }; - - assert_eq!(build.dofigen_of_overlay(image), overlayed_image); - } - - #[test] - #[should_panic] - fn no_cmd() { - let build = Build { - config: DEFAULT_CONFIG_FILE.into(), - cache: Cache::Inline, - }; - let image = Image { - image: "my-dockerimage".into(), - ..Default::default() - }; - build.dofigen_of_overlay(image); + self.build_docker_compose(); } } diff --git a/src/config.rs b/src/config.rs index 0498e54..109efd1 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,9 +1,11 @@ -use std::fs; +use std::{fs, path::PathBuf, collections::HashMap}; -use dofigen_lib::Image; +use dofigen_lib::{from_file_path, generate_dockerfile, generate_dockerignore, Image, Builder, Artifact}; use serde::{Deserialize, Serialize}; use serde_yaml::Value; +use crate::docker_compose::generate_docker_compose_file; + pub const DEFAULT_CONFIG_FILE: &str = "lenra.yml"; pub const LENRA_CACHE_DIRECTORY: &str = ".lenra"; @@ -11,6 +13,10 @@ pub const DOCKERFILE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfi pub const DOCKERIGNORE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, ".dockerignore"]; pub const DOCKERCOMPOSE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "docker-compose.yml"]; +pub const OF_WATCHDOG_BUILDER: &str = "of-watchdog"; +pub const OF_WATCHDOG_IMAGE: &str = "ghcr.io/openfaas/of-watchdog"; +pub const OF_WATCHDOG_VERSION: &str = "0.9.6"; + pub fn load_config_file(path: &std::path::PathBuf) -> Application { let file = fs::File::open(path).unwrap(); match path.extension() { @@ -67,3 +73,200 @@ pub struct Docker { pub struct Dockerfile { pub docker: std::path::PathBuf, } + +impl Application { + /// Generates all the files needed to build and run the application + pub fn generate_files(&self) { + self.generate_docker_files(); + self.generate_docker_compose_files(); + } + + pub fn generate_docker_files(&self) { + // create the `.lenra` cache directory + fs::create_dir_all(LENRA_CACHE_DIRECTORY).unwrap(); + + match &self.generator { + Generator::Dofigen(dofigen) => self.build_dofigen(dofigen.dofigen.clone()), + Generator::DofigenFile(dofigen_file) => self.build_dofigen( + from_file_path(&dofigen_file.dofigen).expect("Failed loading the Dofigen file"), + ), + Generator::DofigenError { dofigen: _ } => { + panic!("Your Dofigen configuration is not correct") + } + Generator::Dockerfile(_dockerfile) => (), + Generator::Docker(docker) => { + self.save_docker_content(docker.docker.clone(), docker.ignore.clone()); + } + } + } + + pub fn generate_docker_compose_files(&self) { + // create the `.lenra` cache directory + fs::create_dir_all(LENRA_CACHE_DIRECTORY).unwrap(); + + let dockerfile: PathBuf = if let Generator::Dockerfile(file_conf) = &self.generator { + file_conf.docker.clone() + } else { + DOCKERFILE_DEFAULT_PATH.iter().collect() + }; + + let compose_content = generate_docker_compose_file(&dockerfile); + let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); + } + + /// Builds a Docker image from a Dofigen structure + fn build_dofigen(&self, image: Image) { + // Generate the Dofigen config with OpenFaaS overlay to handle the of-watchdog + let of_overlay = self.dofigen_of_overlay(image); + + // generate the Dockerfile and .dockerignore files with Dofigen + let dockerfile = generate_dockerfile(&of_overlay); + let dockerignore = generate_dockerignore(&of_overlay); + self.save_docker_content(dockerfile, Some(dockerignore)); + } + + /// Add an overlay to the given Dofigen structure to manage OpenFaaS + fn dofigen_of_overlay(&self, image: Image) -> Image { + log::info!("Adding OpenFaaS overlay to the Dofigen descriptor"); + let mut builders = if let Some(vec) = image.builders { + vec + } else { + Vec::new() + }; + builders.push(Builder { + name: Some(String::from(OF_WATCHDOG_BUILDER)), + image: format!("{}:{}", OF_WATCHDOG_IMAGE, OF_WATCHDOG_VERSION), + ..Default::default() + }); + + let mut artifacts = if let Some(arts) = image.artifacts { + arts + } else { + Vec::new() + }; + artifacts.push(Artifact { + builder: OF_WATCHDOG_BUILDER.to_string(), + source: "/fwatchdog".to_string(), + destination: "/fwatchdog".to_string(), + }); + + let mut envs = if let Some(envs) = image.envs { + envs + } else { + HashMap::new() + }; + + if let Some(ports) = image.ports { + if ports.len() == 1 { + envs.insert("mode".to_string(), "http".to_string()); + envs.insert( + "upstream_url".to_string(), + format!("http://127.0.0.1:{}", ports[0]), + ); + } else if ports.len() > 1 { + panic!("More than one port has been defined in the Dofigen descriptor"); + } + }; + + if image.entrypoint.is_some() { + panic!("The Dofigen descriptor can't have entrypoint defined. Use cmd instead"); + } + + if let Some(cmd) = image.cmd { + envs.insert("fprocess".to_string(), cmd.join(" ")); + } else { + panic!("The Dofigen cmd property is not defined"); + } + + Image { + image: image.image, + builders: Some(builders), + artifacts: Some(artifacts), + ports: Some(vec![8080]), + envs: Some(envs), + entrypoint: None, + cmd: Some(vec!["/fwatchdog".to_string()]), + user: image.user, + workdir: image.workdir, + adds: image.adds, + root: image.root, + script: image.script, + caches: image.caches, + healthcheck: image.healthcheck, + ignores: image.ignores, + } + } + + /// Saves the Dockerfile and dockerignore (if present) files from their contents + fn save_docker_content( + &self, + dockerfile_content: String, + dockerignore_content: Option, + ) { + let dockerfile_path: PathBuf = DOCKERFILE_DEFAULT_PATH.iter().collect(); + let dockerignore_path: PathBuf = DOCKERIGNORE_DEFAULT_PATH.iter().collect(); + + fs::write(dockerfile_path, dockerfile_content).expect("Unable to write the Dockerfile"); + if let Some(content) = dockerignore_content { + fs::write(dockerignore_path, content).expect("Unable to write the .dockerignore file"); + } + } +} + + + +#[cfg(test)] +mod dofigen_of_overlay_tests { + use super::*; + + #[test] + fn simple_image() { + let image = Image { + image: "my-dockerimage".into(), + cmd: Some(vec!["/app/my-app".into()]), + ..Default::default() + }; + let overlayed_image = Image { + builders: Some(vec![Builder { + name: Some("of-watchdog".into()), + image: format!("ghcr.io/openfaas/of-watchdog:{}", OF_WATCHDOG_VERSION), + ..Default::default() + }]), + image: String::from("my-dockerimage"), + envs: Some([("fprocess".to_string(), "/app/my-app".to_string())].into()), + artifacts: Some(vec![Artifact { + builder: "of-watchdog".into(), + source: "/fwatchdog".into(), + destination: "/fwatchdog".into(), + }]), + ports: Some(vec![8080]), + cmd: Some(vec!["/fwatchdog".into()]), + ..Default::default() + }; + let config = Application { + components_api: "".to_string(), + generator: Generator::Dofigen(Dofigen { + dofigen: image.clone() + }) + }; + + assert_eq!(config.dofigen_of_overlay(image), overlayed_image); + } + + #[test] + #[should_panic] + fn no_cmd() { + let image = Image { + image: "my-dockerimage".into(), + ..Default::default() + }; + let config = Application { + components_api: "".to_string(), + generator: Generator::Dofigen(Dofigen { + dofigen: image.clone() + }) + }; + config.dofigen_of_overlay(image); + } +} diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 0c5d144..24300f4 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -10,7 +10,7 @@ pub const POSTGRES_SERVICE_NAME: &str = "postgres"; const DEVTOOL_IMAGE: &str = "lenra/devtools:beta"; const DEVTOOL_PORT: u16 = 4000; -pub fn generate_docker_compose_file(dockerfile: PathBuf) -> String { +pub fn generate_docker_compose_file(dockerfile: &PathBuf) -> String { let postgres_envs = [ ("POSTGRES_USER".to_string(), Some("postgres".to_string())), ( diff --git a/src/start.rs b/src/start.rs index 417d89b..1a21d91 100644 --- a/src/start.rs +++ b/src/start.rs @@ -36,6 +36,10 @@ impl Start { /// Starts the docker-compose fn start_docker_compose(&self) { let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + if !dockercompose_path.exists() { + + } + let mut command = Command::new("docker"); // TODO: display std out & err From 49cbb8c3cd251922b3d68bfa893176cf6e46f652 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 24 Aug 2022 12:32:47 +0200 Subject: [PATCH 04/26] refactor: Remove olf imports --- src/build.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/build.rs b/src/build.rs index 976470f..615043d 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,13 +1,11 @@ use log; -use std::fs; use std::path::PathBuf; use std::process::{Command, Stdio}; use clap; use crate::cli::CliCommand; -use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERFILE_DEFAULT_PATH, DOCKERCOMPOSE_DEFAULT_PATH}; -use crate::docker_compose::generate_docker_compose_file; +use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; #[derive(clap::Args)] pub struct Build { From 3fc362901698d0c6186459c5b545d3a09551439b Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Mon, 22 Aug 2022 22:08:30 +0200 Subject: [PATCH 05/26] refactor: Move docker-compose generation --- Cargo.lock | 2 -- src/docker_compose.rs | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8992e99..d1197f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -150,7 +150,6 @@ name = "docker-compose-types" version = "0.2.0" dependencies = [ "derive_builder", - "indexmap", "serde", "serde_yaml 0.8.26", ] @@ -228,7 +227,6 @@ checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", - "serde", ] [[package]] diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 24300f4..842b609 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -1,16 +1,27 @@ -use std::path::PathBuf; +use std::{path::PathBuf, fs}; use docker_compose_types::{ AdvancedBuildStep, BuildStep, Compose, DependsOnOptions, Environment, Service, Services, }; +use crate::config::{DOCKERFILE_DEFAULT_PATH, DOCKERCOMPOSE_DEFAULT_PATH}; + pub const APP_SERVICE_NAME: &str = "app"; pub const DEVTOOL_SERVICE_NAME: &str = "devtool"; pub const POSTGRES_SERVICE_NAME: &str = "postgres"; const DEVTOOL_IMAGE: &str = "lenra/devtools:beta"; const DEVTOOL_PORT: u16 = 4000; -pub fn generate_docker_compose_file(dockerfile: &PathBuf) -> String { +/// Generates the docker-compose.yml file +pub fn generate_docker_compose(dockerfile: Option) { + let compose_content = generate_docker_compose_content( + dockerfile.unwrap_or(DOCKERFILE_DEFAULT_PATH.iter().collect()), + ); + let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); +} + +pub fn generate_docker_compose_content(dockerfile: PathBuf) -> String { let postgres_envs = [ ("POSTGRES_USER".to_string(), Some("postgres".to_string())), ( From a9132463ef81a3190d3ce4ca81c4a64ad6de17c8 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 24 Aug 2022 14:33:35 +0200 Subject: [PATCH 06/26] fix: Better --- src/config.rs | 22 ++++++++++------------ src/docker_compose.rs | 10 ++++------ src/start.rs | 4 +--- 3 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/config.rs b/src/config.rs index 109efd1..d677053 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,12 @@ -use std::{fs, path::PathBuf, collections::HashMap}; +use std::{collections::HashMap, fs, path::PathBuf}; -use dofigen_lib::{from_file_path, generate_dockerfile, generate_dockerignore, Image, Builder, Artifact}; +use dofigen_lib::{ + from_file_path, generate_dockerfile, generate_dockerignore, Artifact, Builder, Image, +}; use serde::{Deserialize, Serialize}; use serde_yaml::Value; -use crate::docker_compose::generate_docker_compose_file; +use crate::docker_compose::generate_docker_compose; pub const DEFAULT_CONFIG_FILE: &str = "lenra.yml"; pub const LENRA_CACHE_DIRECTORY: &str = ".lenra"; @@ -110,9 +112,7 @@ impl Application { DOCKERFILE_DEFAULT_PATH.iter().collect() }; - let compose_content = generate_docker_compose_file(&dockerfile); - let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); - fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); + generate_docker_compose(dockerfile); } /// Builds a Docker image from a Dofigen structure @@ -214,8 +214,6 @@ impl Application { } } - - #[cfg(test)] mod dofigen_of_overlay_tests { use super::*; @@ -247,8 +245,8 @@ mod dofigen_of_overlay_tests { let config = Application { components_api: "".to_string(), generator: Generator::Dofigen(Dofigen { - dofigen: image.clone() - }) + dofigen: image.clone(), + }), }; assert_eq!(config.dofigen_of_overlay(image), overlayed_image); @@ -264,8 +262,8 @@ mod dofigen_of_overlay_tests { let config = Application { components_api: "".to_string(), generator: Generator::Dofigen(Dofigen { - dofigen: image.clone() - }) + dofigen: image.clone(), + }), }; config.dofigen_of_overlay(image); } diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 842b609..8fb1cfd 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -1,10 +1,10 @@ -use std::{path::PathBuf, fs}; +use std::{fs, path::PathBuf}; use docker_compose_types::{ AdvancedBuildStep, BuildStep, Compose, DependsOnOptions, Environment, Service, Services, }; -use crate::config::{DOCKERFILE_DEFAULT_PATH, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::config::DOCKERCOMPOSE_DEFAULT_PATH; pub const APP_SERVICE_NAME: &str = "app"; pub const DEVTOOL_SERVICE_NAME: &str = "devtool"; @@ -13,10 +13,8 @@ const DEVTOOL_IMAGE: &str = "lenra/devtools:beta"; const DEVTOOL_PORT: u16 = 4000; /// Generates the docker-compose.yml file -pub fn generate_docker_compose(dockerfile: Option) { - let compose_content = generate_docker_compose_content( - dockerfile.unwrap_or(DOCKERFILE_DEFAULT_PATH.iter().collect()), - ); +pub fn generate_docker_compose(dockerfile: PathBuf) { + let compose_content = generate_docker_compose_content(dockerfile); let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); } diff --git a/src/start.rs b/src/start.rs index 1a21d91..ba169ac 100644 --- a/src/start.rs +++ b/src/start.rs @@ -36,9 +36,7 @@ impl Start { /// Starts the docker-compose fn start_docker_compose(&self) { let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); - if !dockercompose_path.exists() { - - } + if !dockercompose_path.exists() {} let mut command = Command::new("docker"); From d87e75579100ce0630a541489d30bf0902d81aec Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 24 Aug 2022 18:24:32 +0200 Subject: [PATCH 07/26] feat: Complite compose file --- src/config.rs | 6 ++-- src/docker_compose.rs | 79 +++++++++++++++++++++++++++++++++++++------ src/start.rs | 15 +++++--- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/src/config.rs b/src/config.rs index d677053..d1695d8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -80,10 +80,11 @@ impl Application { /// Generates all the files needed to build and run the application pub fn generate_files(&self) { self.generate_docker_files(); - self.generate_docker_compose_files(); + self.generate_docker_compose_file(); } pub fn generate_docker_files(&self) { + log::info!("Docker files generation"); // create the `.lenra` cache directory fs::create_dir_all(LENRA_CACHE_DIRECTORY).unwrap(); @@ -102,7 +103,8 @@ impl Application { } } - pub fn generate_docker_compose_files(&self) { + pub fn generate_docker_compose_file(&self) { + log::info!("Docker Compose file generation"); // create the `.lenra` cache directory fs::create_dir_all(LENRA_CACHE_DIRECTORY).unwrap(); diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 8fb1cfd..5a1c404 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -1,7 +1,8 @@ use std::{fs, path::PathBuf}; use docker_compose_types::{ - AdvancedBuildStep, BuildStep, Compose, DependsOnOptions, Environment, Service, Services, + AdvancedBuildStep, BuildStep, Compose, DependsCondition, DependsOnOptions, Environment, + Healthcheck, HealthcheckTest, Service, Services, }; use crate::config::DOCKERCOMPOSE_DEFAULT_PATH; @@ -10,6 +11,8 @@ pub const APP_SERVICE_NAME: &str = "app"; pub const DEVTOOL_SERVICE_NAME: &str = "devtool"; pub const POSTGRES_SERVICE_NAME: &str = "postgres"; const DEVTOOL_IMAGE: &str = "lenra/devtools:beta"; +const POSTGRES_IMAGE: &str = "postgres:13"; +const OF_WATCHDOG_PORT: u16 = 8080; const DEVTOOL_PORT: u16 = 4000; /// Generates the docker-compose.yml file @@ -26,23 +29,46 @@ pub fn generate_docker_compose_content(dockerfile: PathBuf) -> String { "POSTGRES_PASSWORD".to_string(), Some("postgres".to_string()), ), - ("POSTGRES_HOST".to_string(), Some("postgres".to_string())), ("POSTGRES_DB".to_string(), Some("lenra_devtool".to_string())), ]; + let devtool_envs: [(String, Option); 6] = [ + postgres_envs.clone(), + [ + ("POSTGRES_HOST".to_string(), Some(POSTGRES_SERVICE_NAME.to_string())), + ( + "OF_WATCHDOG_URL".to_string(), + Some(format!("http://{}:{}", APP_SERVICE_NAME, OF_WATCHDOG_PORT)), + ), + ( + "LENRA_API_URL".to_string(), + Some(format!("http://{}:{}", DEVTOOL_SERVICE_NAME, DEVTOOL_PORT)), + ), + ], + ] + .concat() + .try_into() + .unwrap(); let compose = Compose { services: Some(Services( [ ( APP_SERVICE_NAME.into(), Some(Service { + image: Some("lenra/my-app".into()), build_: Some(BuildStep::Advanced(AdvancedBuildStep { context: "..".into(), dockerfile: Some(dockerfile.to_str().unwrap().into()), ..Default::default() })), - depends_on: Some(DependsOnOptions::Simple(vec![ - DEVTOOL_SERVICE_NAME.into() - ])), + depends_on: Some(DependsOnOptions::Conditional( + [( + DEVTOOL_SERVICE_NAME.into(), + DependsCondition { + condition: "service_healthy".into(), + }, + )] + .into(), + )), ..Default::default() }), ), @@ -50,19 +76,50 @@ pub fn generate_docker_compose_content(dockerfile: PathBuf) -> String { DEVTOOL_SERVICE_NAME.into(), Some(Service { image: Some(DEVTOOL_IMAGE.into()), - ports: Some(vec![format!("{}", DEVTOOL_PORT)]), - environment: Some(Environment::KvPair(postgres_envs.clone().into())), - depends_on: Some(DependsOnOptions::Simple(vec![ - POSTGRES_SERVICE_NAME.into() - ])), + ports: Some(vec![format!("{}:{}", DEVTOOL_PORT, DEVTOOL_PORT)]), + environment: Some(Environment::KvPair(devtool_envs.into())), + depends_on: Some(DependsOnOptions::Conditional( + [( + POSTGRES_SERVICE_NAME.into(), + DependsCondition { + condition: "service_healthy".into(), + }, + )] + .into(), + )), + healthcheck: Some(Healthcheck { + test: Some(HealthcheckTest::Multiple(vec![ + "CMD".into(), + "wget".into(), + "--spider".into(), + "-q".into(), + "http://localhost:4000".into(), + ])), + interval: Some("10s".into()), + timeout: Some("5s".into()), + retries: 5, + disable: false, + }), ..Default::default() }), ), ( POSTGRES_SERVICE_NAME.into(), Some(Service { - image: Some(DEVTOOL_IMAGE.into()), + image: Some(POSTGRES_IMAGE.into()), environment: Some(Environment::KvPair(postgres_envs.into())), + healthcheck: Some(Healthcheck { + test: Some(HealthcheckTest::Multiple(vec![ + "CMD".into(), + "pg_isready".into(), + "-U".into(), + "postgres".into(), + ])), + interval: Some("5s".into()), + timeout: None, + retries: 5, + disable: false, + }), ..Default::default() }), ), diff --git a/src/start.rs b/src/start.rs index ba169ac..8e2153b 100644 --- a/src/start.rs +++ b/src/start.rs @@ -4,8 +4,8 @@ use std::process::{Command, Stdio}; pub use clap::Args; use crate::cli::CliCommand; -use crate::config::{DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; -use crate::docker_compose::APP_SERVICE_NAME; +use crate::config::{DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH, load_config_file}; +use crate::docker_compose::{APP_SERVICE_NAME, DEVTOOL_SERVICE_NAME, POSTGRES_SERVICE_NAME}; #[derive(Args)] pub struct Start { @@ -36,7 +36,12 @@ impl Start { /// Starts the docker-compose fn start_docker_compose(&self) { let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); - if !dockercompose_path.exists() {} + if !dockercompose_path.exists() { + let conf = load_config_file(&self.config); + // TODO: check the components API version + + conf.generate_files(); + } let mut command = Command::new("docker"); @@ -49,8 +54,8 @@ impl Start { .arg("up"); match self.attach { Attach::App => command.arg("--attach").arg(APP_SERVICE_NAME), - Attach::Devtool => command.arg("--attach").arg(APP_SERVICE_NAME), - Attach::Database => command.arg("--attach").arg(APP_SERVICE_NAME), + Attach::Devtool => command.arg("--attach").arg(DEVTOOL_SERVICE_NAME), + Attach::Database => command.arg("--attach").arg(POSTGRES_SERVICE_NAME), Attach::All => &command, Attach::None => command.arg("-d"), }; From 71881547822177a713232be5f7c76c8c5dfdd841 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Mon, 29 Aug 2022 16:57:24 +0200 Subject: [PATCH 08/26] feat: Build and start --- src/build.rs | 16 ++++++++++++---- src/config.rs | 30 ++++++++++++++++++++++++++++-- src/docker_compose.rs | 17 +++++++++-------- src/start.rs | 4 ++++ 4 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/build.rs b/src/build.rs index 615043d..af85ba8 100644 --- a/src/build.rs +++ b/src/build.rs @@ -5,7 +5,9 @@ use std::process::{Command, Stdio}; use clap; use crate::cli::CliCommand; -use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::config::{ + load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH +}; #[derive(clap::Args)] pub struct Build { @@ -40,11 +42,16 @@ impl Build { // TODO: display std out & err command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); command - .arg("buildx") - .arg("bake") + .arg("compose") .arg("-f") .arg(dockercompose_path) - .arg("--load"); + .arg("build"); + // command + // .arg("buildx") + // .arg("bake") + // .arg("-f") + // .arg(dockercompose_path) + // .arg("--load"); log::debug!("Build: {:?}", command); let output = command.output().expect("Failed building the Docker image"); @@ -66,6 +73,7 @@ impl CliCommand for Build { conf.generate_files(); + // self.build_docker_image(conf); self.build_docker_compose(); } } diff --git a/src/config.rs b/src/config.rs index d1695d8..a5a71a8 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,6 +11,8 @@ use crate::docker_compose::generate_docker_compose; pub const DEFAULT_CONFIG_FILE: &str = "lenra.yml"; pub const LENRA_CACHE_DIRECTORY: &str = ".lenra"; +pub const DEVTOOL_TAG: &str = "beta"; + pub const DOCKERFILE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfile"]; pub const DOCKERIGNORE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, ".dockerignore"]; pub const DOCKERCOMPOSE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "docker-compose.yml"]; @@ -33,11 +35,21 @@ pub fn load_config_file(path: &std::path::PathBuf) -> Application { } /** The main component of the config file */ -#[derive(Serialize, Deserialize, Debug, PartialEq)] +#[derive(Serialize, Deserialize, Debug, PartialEq, Default)] +#[serde(rename_all = "camelCase")] pub struct Application { #[serde(rename = "componentsApi")] pub components_api: String, pub generator: Generator, + pub dev: Dev, +} + +/** The dev specific configuration */ +#[derive(Serialize, Deserialize, Debug, PartialEq, Default)] +#[serde(rename_all = "camelCase")] +pub struct Dev { + #[serde(default = "devtool_default_tag")] + pub devtool_tag: String, } /** The application generator configuration */ @@ -49,6 +61,7 @@ pub enum Generator { DofigenError { dofigen: Value }, Dockerfile(Dockerfile), Docker(Docker), + Unknow, } /** The Dofigen configuration */ @@ -100,6 +113,7 @@ impl Application { Generator::Docker(docker) => { self.save_docker_content(docker.docker.clone(), docker.ignore.clone()); } + Generator::Unknow => panic!("Not managed generator"), } } @@ -114,7 +128,7 @@ impl Application { DOCKERFILE_DEFAULT_PATH.iter().collect() }; - generate_docker_compose(dockerfile); + generate_docker_compose(dockerfile, &self.dev); } /// Builds a Docker image from a Dofigen structure @@ -216,6 +230,16 @@ impl Application { } } +fn devtool_default_tag() -> String { + DEVTOOL_TAG.to_string() +} + +impl Default for Generator { + fn default() -> Self { + Generator::Unknow + } +} + #[cfg(test)] mod dofigen_of_overlay_tests { use super::*; @@ -249,6 +273,7 @@ mod dofigen_of_overlay_tests { generator: Generator::Dofigen(Dofigen { dofigen: image.clone(), }), + ..Default::default() }; assert_eq!(config.dofigen_of_overlay(image), overlayed_image); @@ -266,6 +291,7 @@ mod dofigen_of_overlay_tests { generator: Generator::Dofigen(Dofigen { dofigen: image.clone(), }), + ..Default::default() }; config.dofigen_of_overlay(image); } diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 5a1c404..898621c 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -5,24 +5,25 @@ use docker_compose_types::{ Healthcheck, HealthcheckTest, Service, Services, }; -use crate::config::DOCKERCOMPOSE_DEFAULT_PATH; +use crate::config::{DOCKERCOMPOSE_DEFAULT_PATH, Dev}; pub const APP_SERVICE_NAME: &str = "app"; pub const DEVTOOL_SERVICE_NAME: &str = "devtool"; pub const POSTGRES_SERVICE_NAME: &str = "postgres"; -const DEVTOOL_IMAGE: &str = "lenra/devtools:beta"; -const POSTGRES_IMAGE: &str = "postgres:13"; +const DEVTOOL_IMAGE: &str = "lenra/devtools"; +const POSTGRES_IMAGE: &str = "postgres"; +const POSTGRES_IMAGE_TAG: &str = "13"; const OF_WATCHDOG_PORT: u16 = 8080; const DEVTOOL_PORT: u16 = 4000; /// Generates the docker-compose.yml file -pub fn generate_docker_compose(dockerfile: PathBuf) { - let compose_content = generate_docker_compose_content(dockerfile); +pub fn generate_docker_compose(dockerfile: PathBuf, dev_conf: &Dev) { + let compose_content = generate_docker_compose_content(dockerfile, dev_conf); let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); } -pub fn generate_docker_compose_content(dockerfile: PathBuf) -> String { +fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Dev) -> String { let postgres_envs = [ ("POSTGRES_USER".to_string(), Some("postgres".to_string())), ( @@ -75,7 +76,7 @@ pub fn generate_docker_compose_content(dockerfile: PathBuf) -> String { ( DEVTOOL_SERVICE_NAME.into(), Some(Service { - image: Some(DEVTOOL_IMAGE.into()), + image: Some(format!("{}:{}", DEVTOOL_IMAGE, dev_conf.devtool_tag)), ports: Some(vec![format!("{}:{}", DEVTOOL_PORT, DEVTOOL_PORT)]), environment: Some(Environment::KvPair(devtool_envs.into())), depends_on: Some(DependsOnOptions::Conditional( @@ -106,7 +107,7 @@ pub fn generate_docker_compose_content(dockerfile: PathBuf) -> String { ( POSTGRES_SERVICE_NAME.into(), Some(Service { - image: Some(POSTGRES_IMAGE.into()), + image: Some(format!("{}:{}", POSTGRES_IMAGE, POSTGRES_IMAGE_TAG)), environment: Some(Environment::KvPair(postgres_envs.into())), healthcheck: Some(Healthcheck { test: Some(HealthcheckTest::Multiple(vec![ diff --git a/src/start.rs b/src/start.rs index 8e2153b..59cb022 100644 --- a/src/start.rs +++ b/src/start.rs @@ -13,6 +13,10 @@ pub struct Start { #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] pub config: std::path::PathBuf, + // /// The cache management. + // #[clap(long, default_value = "beta")] + // pub devtool_tag: String, + /// The service attached. #[clap(value_enum, long, default_value = "app")] pub attach: Attach, From f6057e75f9e54c289d90f6eb935f3b7fcdf2e4ac Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Mon, 29 Aug 2022 17:11:47 +0200 Subject: [PATCH 09/26] feat: Stop command --- src/cli.rs | 5 ++++- src/main.rs | 1 + src/start.rs | 7 +------ src/stop.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 7 deletions(-) create mode 100644 src/stop.rs diff --git a/src/cli.rs b/src/cli.rs index c2b94ef..71124f1 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,6 +1,6 @@ pub use clap::{Args, Parser, Subcommand}; -use crate::{build::Build, new::New, start::Start}; +use crate::{build::Build, new::New, start::Start, stop::Stop}; /// The Lenra CLI arguments to manage your local app development. #[derive(Parser)] @@ -23,6 +23,8 @@ pub enum Command { Build(Build), /// Start your app previously built with the build command Start(Start), + /// Stop your app previously started with the start command + Stop(Stop), } impl CliCommand for Command { @@ -31,6 +33,7 @@ impl CliCommand for Command { Command::New(new) => new.run(), Command::Build(build) => build.run(), Command::Start(start) => start.run(), + Command::Stop(stop) => stop.run(), }; } } diff --git a/src/main.rs b/src/main.rs index 9522d4c..039e58d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ mod config; mod docker_compose; mod new; mod start; +mod stop; fn main() { env_logger::init(); diff --git a/src/start.rs b/src/start.rs index 59cb022..5a7c258 100644 --- a/src/start.rs +++ b/src/start.rs @@ -13,10 +13,6 @@ pub struct Start { #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] pub config: std::path::PathBuf, - // /// The cache management. - // #[clap(long, default_value = "beta")] - // pub devtool_tag: String, - /// The service attached. #[clap(value_enum, long, default_value = "app")] pub attach: Attach, @@ -64,7 +60,7 @@ impl Start { Attach::None => command.arg("-d"), }; - log::debug!("Start: {:?}", command); + log::debug!("cmd: {:?}", command); let output = command .output() .expect("Failed to start the docker-compose app"); @@ -82,6 +78,5 @@ impl CliCommand for Start { fn run(&self) { log::info!("Starting the app"); self.start_docker_compose(); - log::info!("App is stopped"); } } diff --git a/src/stop.rs b/src/stop.rs new file mode 100644 index 0000000..d2e8f7e --- /dev/null +++ b/src/stop.rs @@ -0,0 +1,53 @@ +use std::path::PathBuf; +use std::process::{Command, Stdio}; + +pub use clap::Args; + +use crate::cli::CliCommand; +use crate::config::{DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; + +#[derive(Args)] +pub struct Stop { + /// The app configuration file. + #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] + pub config: std::path::PathBuf, +} + +impl Stop { + /// Starts the docker-compose + fn stop_docker_compose(&self) { + let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + if !dockercompose_path.exists() { + + } + + let mut command = Command::new("docker"); + + // TODO: display std out & err + command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); + command + .arg("compose") + .arg("-f") + .arg(dockercompose_path) + .arg("down"); + + log::debug!("cmd: {:?}", command); + let output = command + .output() + .expect("Failed to stop the docker-compose app"); + if !output.status.success() { + panic!( + "An error occured while stoping the docker-compose app:\n{}\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ) + } + } +} + +impl CliCommand for Stop { + fn run(&self) { + log::info!("Stoping the app"); + self.stop_docker_compose(); + } +} From 6b5eb6f3aa369e55649b02a999a96b18df6b2e44 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Mon, 29 Aug 2022 17:39:02 +0200 Subject: [PATCH 10/26] fix: Docker ignore file path --- src/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.rs b/src/config.rs index a5a71a8..4f363fe 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,7 +14,7 @@ pub const LENRA_CACHE_DIRECTORY: &str = ".lenra"; pub const DEVTOOL_TAG: &str = "beta"; pub const DOCKERFILE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfile"]; -pub const DOCKERIGNORE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, ".dockerignore"]; +pub const DOCKERIGNORE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfile.dockerignore"]; pub const DOCKERCOMPOSE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "docker-compose.yml"]; pub const OF_WATCHDOG_BUILDER: &str = "of-watchdog"; From 8bb7c7e542e9b2438bc1b51920e8031a00190d60 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Tue, 30 Aug 2022 17:27:28 +0200 Subject: [PATCH 11/26] feat: Remove cache management --- Cargo.lock | 6 +++++- Cargo.toml | 3 +-- src/build.rs | 16 ---------------- src/docker_compose.rs | 1 + 4 files changed, 7 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1197f2..d6ef34e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -147,9 +147,12 @@ dependencies = [ [[package]] name = "docker-compose-types" -version = "0.2.0" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7213b15aa1b9e80b202b9e8c95dd0e2df45805dba8301dda2f72549436be67" dependencies = [ "derive_builder", + "indexmap", "serde", "serde_yaml 0.8.26", ] @@ -227,6 +230,7 @@ checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 075fb14..4c27833 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,5 +26,4 @@ env_logger = "0.9.0" regex = "1.6.0" lazy_static = "1.4.0" dofigen = "1" -docker-compose-types = { version = "0.2.0", path = "../docker-compose-types" } -# docker-compose-types = "0.2.0" +docker-compose-types = "0.2.1" diff --git a/src/build.rs b/src/build.rs index af85ba8..a168a63 100644 --- a/src/build.rs +++ b/src/build.rs @@ -14,22 +14,6 @@ pub struct Build { /// The app configuration file. #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] pub config: std::path::PathBuf, - - /// The cache management. - #[clap(value_enum, long, default_value = "local")] - pub cache: Cache, -} - -#[derive(clap::ValueEnum, Clone, Debug)] -pub enum Cache { - /// Handle cache with a local directory ".lenra/dockercache" - Local, - /// Handle cache in the built image "lenra/app:latest" - Inline, - /// Handle cache with a specific image "lenra/app:cache" - Image, - /// Disable cache - No, } impl Build { diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 898621c..c267ada 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -70,6 +70,7 @@ fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Dev) -> Strin )] .into(), )), + // TODO: Add resources management when managed by the docker-compose-types lib ..Default::default() }), ), From 9a9ca0e2eadb62433f0fe1251b9c582e0ffaf7e6 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 31 Aug 2022 17:20:22 +0200 Subject: [PATCH 12/26] fix: Dev is optional --- src/config.rs | 6 +++--- src/docker_compose.rs | 19 ++++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/config.rs b/src/config.rs index 4f363fe..74d5334 100644 --- a/src/config.rs +++ b/src/config.rs @@ -11,7 +11,7 @@ use crate::docker_compose::generate_docker_compose; pub const DEFAULT_CONFIG_FILE: &str = "lenra.yml"; pub const LENRA_CACHE_DIRECTORY: &str = ".lenra"; -pub const DEVTOOL_TAG: &str = "beta"; +pub const DEVTOOL_DEFAULT_TAG: &str = "beta"; pub const DOCKERFILE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfile"]; pub const DOCKERIGNORE_DEFAULT_PATH: [&str; 2] = [LENRA_CACHE_DIRECTORY, "Dockerfile.dockerignore"]; @@ -41,7 +41,7 @@ pub struct Application { #[serde(rename = "componentsApi")] pub components_api: String, pub generator: Generator, - pub dev: Dev, + pub dev: Option, } /** The dev specific configuration */ @@ -231,7 +231,7 @@ impl Application { } fn devtool_default_tag() -> String { - DEVTOOL_TAG.to_string() + DEVTOOL_DEFAULT_TAG.to_string() } impl Default for Generator { diff --git a/src/docker_compose.rs b/src/docker_compose.rs index c267ada..7b66acc 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -5,7 +5,7 @@ use docker_compose_types::{ Healthcheck, HealthcheckTest, Service, Services, }; -use crate::config::{DOCKERCOMPOSE_DEFAULT_PATH, Dev}; +use crate::config::{Dev, DEVTOOL_DEFAULT_TAG, DOCKERCOMPOSE_DEFAULT_PATH}; pub const APP_SERVICE_NAME: &str = "app"; pub const DEVTOOL_SERVICE_NAME: &str = "devtool"; @@ -17,13 +17,13 @@ const OF_WATCHDOG_PORT: u16 = 8080; const DEVTOOL_PORT: u16 = 4000; /// Generates the docker-compose.yml file -pub fn generate_docker_compose(dockerfile: PathBuf, dev_conf: &Dev) { +pub fn generate_docker_compose(dockerfile: PathBuf, dev_conf: &Option) { let compose_content = generate_docker_compose_content(dockerfile, dev_conf); let compose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); fs::write(compose_path, compose_content).expect("Unable to write the docker-compose file"); } -fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Dev) -> String { +fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Option) -> String { let postgres_envs = [ ("POSTGRES_USER".to_string(), Some("postgres".to_string())), ( @@ -35,7 +35,10 @@ fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Dev) -> Strin let devtool_envs: [(String, Option); 6] = [ postgres_envs.clone(), [ - ("POSTGRES_HOST".to_string(), Some(POSTGRES_SERVICE_NAME.to_string())), + ( + "POSTGRES_HOST".to_string(), + Some(POSTGRES_SERVICE_NAME.to_string()), + ), ( "OF_WATCHDOG_URL".to_string(), Some(format!("http://{}:{}", APP_SERVICE_NAME, OF_WATCHDOG_PORT)), @@ -49,6 +52,12 @@ fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Dev) -> Strin .concat() .try_into() .unwrap(); + + let devtool_tag = if let Some(conf) = dev_conf { + conf.devtool_tag.as_str() + } else { + DEVTOOL_DEFAULT_TAG + }; let compose = Compose { services: Some(Services( [ @@ -77,7 +86,7 @@ fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Dev) -> Strin ( DEVTOOL_SERVICE_NAME.into(), Some(Service { - image: Some(format!("{}:{}", DEVTOOL_IMAGE, dev_conf.devtool_tag)), + image: Some(format!("{}:{}", DEVTOOL_IMAGE, devtool_tag)), ports: Some(vec![format!("{}:{}", DEVTOOL_PORT, DEVTOOL_PORT)]), environment: Some(Environment::KvPair(devtool_envs.into())), depends_on: Some(DependsOnOptions::Conditional( From ae0d58cf88812e1906b6080cb6a83b011d3e2c75 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Fri, 2 Sep 2022 16:48:38 +0200 Subject: [PATCH 13/26] fix: SImplification of the start command --- src/start.rs | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/start.rs b/src/start.rs index 5a7c258..858cc55 100644 --- a/src/start.rs +++ b/src/start.rs @@ -5,31 +5,12 @@ pub use clap::Args; use crate::cli::CliCommand; use crate::config::{DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH, load_config_file}; -use crate::docker_compose::{APP_SERVICE_NAME, DEVTOOL_SERVICE_NAME, POSTGRES_SERVICE_NAME}; #[derive(Args)] pub struct Start { /// The app configuration file. #[clap(parse(from_os_str), long, default_value = DEFAULT_CONFIG_FILE)] pub config: std::path::PathBuf, - - /// The service attached. - #[clap(value_enum, long, default_value = "app")] - pub attach: Attach, -} - -#[derive(clap::ValueEnum, Clone, Debug)] -pub enum Attach { - /// Attach app service - App, - /// Attach devtool service - Devtool, - /// Attach database service - Database, - /// Attach all services - All, - /// Detach - None, } impl Start { @@ -51,14 +32,8 @@ impl Start { .arg("compose") .arg("-f") .arg(dockercompose_path) - .arg("up"); - match self.attach { - Attach::App => command.arg("--attach").arg(APP_SERVICE_NAME), - Attach::Devtool => command.arg("--attach").arg(DEVTOOL_SERVICE_NAME), - Attach::Database => command.arg("--attach").arg(POSTGRES_SERVICE_NAME), - Attach::All => &command, - Attach::None => command.arg("-d"), - }; + .arg("up") + .arg("-d"); log::debug!("cmd: {:?}", command); let output = command From 4fee2cda4d33b97525c37ee3b7a0480c80e9ee97 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Fri, 2 Sep 2022 18:53:07 +0200 Subject: [PATCH 14/26] docs: README --- Cargo.toml | 2 +- README.md | 53 ++++++++++++++++++++++++++++++++++++++++++---------- src/build.rs | 18 +++++++----------- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4c27833..bfeaf99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "lenra_cli" version = "0.0.0" edition = "2021" license = "MIT" -description = "THe Lenra's command line interface" +description = "The Lenra's command line interface" readme = "../README.md" repository = "https://github.com/lenra-io/lenra_cli" keywords = ["cli", "lenra"] diff --git a/README.md b/README.md index 0242657..5790f76 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,11 @@ The Lenra's command line interface. ### Prerequisites -Install the Lenra's cli using one of the next possibilities. +To build and run the Lenra elements that handle your app, the Lenra CLI needs [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/). + +You also can install the [Docker buildx command](https://docs.docker.com/build/buildx/install/) to use the [Buildkit optimization given by Dofigen](https://github.com/lenra-io/dofigen). + +Install the Lenra CLI using one of the next possibilities. #### Cargo install @@ -52,14 +56,6 @@ cargo install lenra_cli You can download the binary from [the release page](https://github.com/lenra-io/lenra_cli/releases) and add it to your path environment variable. -#### Use it with Docker - -You can run cli directly from it Docker image with the next command: - -```bash -docker run --rm -it -v $(pwd):/app lenra/cli -``` -

(back to top)

### How to use it @@ -69,7 +65,7 @@ Use the help options to understand how to use it: ```bash $ lenra --help lenra_cli 0.0.0 -A Dockerfile generator using a simplified description in YAML or JSON format command line tool +The Lenra's command line interface USAGE: lenra @@ -83,6 +79,7 @@ SUBCOMMANDS: help Print this message or the help of the given subcommand(s) new Create a new Lenra app project start Start your app previously built with the build command + stop Stop your app previously started with the start command ``` ### Subcommands @@ -91,6 +88,8 @@ This tools contains many subcommands to help you doing what you need. - [new](#new): creates a new Lenra app project - [build](#build): builds the Lenra app of the current directory +- [start](#start): start your app previously built with the build command +- [stop](#stop): stop your app previously started with the start command #### new @@ -136,6 +135,40 @@ OPTIONS: -h, --help Print help information ``` +#### start + +This subcommand starts the Lenra app of the current directory previously built. + +```bash +$ lenra start --help +lenra-start +Start your app previously built with the build command + +USAGE: + lenra start [OPTIONS] + +OPTIONS: + --config The app configuration file [default: lenra.yml] + -h, --help Print help information +``` + +#### stop + +This subcommand stops the Lenra app of the current directory and removes the Docker Compose elements. + +```bash +$ lenra stop --help +lenra-stop +Stop your app previously started with the start command + +USAGE: + lenra stop [OPTIONS] + +OPTIONS: + --config The app configuration file [default: lenra.yml] + -h, --help Print help information +``` + ### Configuration file The Lenra's configuration file describes your Lenra app configurations, like API versions or how to build it. diff --git a/src/build.rs b/src/build.rs index a168a63..77535e7 100644 --- a/src/build.rs +++ b/src/build.rs @@ -5,9 +5,7 @@ use std::process::{Command, Stdio}; use clap; use crate::cli::CliCommand; -use crate::config::{ - load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH -}; +use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; #[derive(clap::Args)] pub struct Build { @@ -23,19 +21,17 @@ impl Build { let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); let mut command = Command::new("docker"); - // TODO: display std out & err - command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); command .arg("compose") .arg("-f") .arg(dockercompose_path) .arg("build"); - // command - // .arg("buildx") - // .arg("bake") - // .arg("-f") - // .arg(dockercompose_path) - // .arg("--load"); + + // Use Buildkit to improve performance + command.env("DOCKER_BUILDKIT", "1"); + + // Display std out & err + command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); log::debug!("Build: {:?}", command); let output = command.output().expect("Failed building the Docker image"); From a5036890c97968866dd5204bb0778a8a5e99738c Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Sun, 4 Sep 2022 01:22:51 +0200 Subject: [PATCH 15/26] feat: Invalidate cache on start --- Cargo.lock | 17 +++++++++ Cargo.toml | 1 + src/build.rs | 32 +++-------------- src/docker_compose.rs | 84 ++++++++++++++++++++++++++++++++++++++++++- src/start.rs | 39 ++++++++------------ 5 files changed, 121 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6ef34e..3c3162f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -255,6 +255,7 @@ dependencies = [ "env_logger", "lazy_static", "log", + "open", "regex", "serde", "serde_json", @@ -294,12 +295,28 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +[[package]] +name = "open" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcea7a30d6b81a2423cc59c43554880feff7b57d12916f231a79f8d6d9470201" +dependencies = [ + "pathdiff", + "winapi", +] + [[package]] name = "os_str_bytes" version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "proc-macro-error" version = "1.0.4" diff --git a/Cargo.toml b/Cargo.toml index bfeaf99..46aad54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,3 +27,4 @@ regex = "1.6.0" lazy_static = "1.4.0" dofigen = "1" docker-compose-types = "0.2.1" +open = "1" diff --git a/src/build.rs b/src/build.rs index 77535e7..89a3849 100644 --- a/src/build.rs +++ b/src/build.rs @@ -1,11 +1,10 @@ use log; -use std::path::PathBuf; -use std::process::{Command, Stdio}; use clap; use crate::cli::CliCommand; -use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::config::{load_config_file, DEFAULT_CONFIG_FILE}; +use crate::docker_compose::compose_build; #[derive(clap::Args)] pub struct Build { @@ -18,30 +17,9 @@ impl Build { /// Builds a Dockerfile. If None, get's it at the default path: ./.lenra/Dockerfile fn build_docker_compose(&self) { log::info!("Build the Docker image"); - let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); - let mut command = Command::new("docker"); - - command - .arg("compose") - .arg("-f") - .arg(dockercompose_path) - .arg("build"); - - // Use Buildkit to improve performance - command.env("DOCKER_BUILDKIT", "1"); - - // Display std out & err - command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); - - log::debug!("Build: {:?}", command); - let output = command.output().expect("Failed building the Docker image"); - if !output.status.success() { - panic!( - "An error occured while building the Docker image:\n{}\n{}", - String::from_utf8(output.stdout).unwrap(), - String::from_utf8(output.stderr).unwrap() - ) - } + + compose_build(); + log::info!("Image built"); } } diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 7b66acc..0867fc2 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -1,4 +1,8 @@ -use std::{fs, path::PathBuf}; +use std::{ + fs, + path::PathBuf, + process::{Command, Stdio}, +}; use docker_compose_types::{ AdvancedBuildStep, BuildStep, Compose, DependsCondition, DependsOnOptions, Environment, @@ -141,3 +145,81 @@ fn generate_docker_compose_content(dockerfile: PathBuf, dev_conf: &Option) }; serde_yaml::to_string(&compose).expect("Error generating the docker-compose file content") } + +pub fn create_compose_command() -> Command { + let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); + let mut cmd = Command::new("docker"); + + cmd.arg("compose").arg("-f").arg(dockercompose_path); + + cmd +} + +pub fn compose_up() { + let mut command = create_compose_command(); + + command + .arg("up") + .arg("-d") + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()); + + log::debug!("cmd: {:?}", command); + let output = command + .output() + .expect("Failed to start the docker-compose app"); + + if !output.status.success() { + panic!( + "An error occured while running the docker-compose app:\n{}\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ) + } +} + +pub fn compose_build() { + let mut command = create_compose_command(); + command.arg("build"); + + // Use Buildkit to improve performance + command.env("DOCKER_BUILDKIT", "1"); + + // Display std out & err + command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); + + log::debug!("Build: {:?}", command); + let output = command.output().expect("Failed building the Docker image"); + if !output.status.success() { + panic!( + "An error occured while building the Docker image:\n{}\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ) + } +} + +pub fn execute_compose_service_command(service: &str, cmd: &[&str]) { + let mut command = create_compose_command(); + + command.arg("exec").arg(service); + + cmd.iter().for_each(|&part| { + command.arg(part); + () + }); + + let output = command + .output() + .expect("Failed to execute the docker-compose exec command"); + + if !output.status.success() { + panic!( + "docker-compose exec exited with code {}:\n\tcmd: {:?}\n\tstdout: {}\n\tstderr: {}", + output.status.code().unwrap(), + command, + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ) + } +} diff --git a/src/start.rs b/src/start.rs index 858cc55..eee821c 100644 --- a/src/start.rs +++ b/src/start.rs @@ -1,10 +1,10 @@ use std::path::PathBuf; -use std::process::{Command, Stdio}; pub use clap::Args; use crate::cli::CliCommand; -use crate::config::{DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH, load_config_file}; +use crate::config::{load_config_file, DEFAULT_CONFIG_FILE, DOCKERCOMPOSE_DEFAULT_PATH}; +use crate::docker_compose::{compose_up, execute_compose_service_command, DEVTOOL_SERVICE_NAME}; #[derive(Args)] pub struct Start { @@ -24,28 +24,19 @@ impl Start { conf.generate_files(); } - let mut command = Command::new("docker"); - - // TODO: display std out & err - command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); - command - .arg("compose") - .arg("-f") - .arg(dockercompose_path) - .arg("up") - .arg("-d"); - - log::debug!("cmd: {:?}", command); - let output = command - .output() - .expect("Failed to start the docker-compose app"); - if !output.status.success() { - panic!( - "An error occured while running the docker-compose app:\n{}\n{}", - String::from_utf8(output.stdout).unwrap(), - String::from_utf8(output.stderr).unwrap() - ) - } + // Start the containers + compose_up(); + // Stop the devtool app env to reset cache + execute_compose_service_command( + DEVTOOL_SERVICE_NAME, + &[ + "bin/dev_tools", + "rpc", + "ApplicationRunner.Environments.Managers.stop_env(1)", + ], + ); + // Open the app + open::that("http://localhost:4000").unwrap(); } } From b6a6fbd950bab62e99147b53e3e72b53dfbe49df Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:42:53 +0200 Subject: [PATCH 16/26] Update Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 46aad54..238f651 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "lenra_cli" version = "0.0.0" edition = "2021" license = "MIT" -description = "The Lenra's command line interface" +description = "The Lenra command line interface" readme = "../README.md" repository = "https://github.com/lenra-io/lenra_cli" keywords = ["cli", "lenra"] From 59da705ccedf4e343587ec5e0fff22ee48a44913 Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:42:58 +0200 Subject: [PATCH 17/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5790f76..d4322ce 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The Lenra's command line interface. To build and run the Lenra elements that handle your app, the Lenra CLI needs [Docker](https://docs.docker.com/engine/install/) and [Docker Compose](https://docs.docker.com/compose/install/). -You also can install the [Docker buildx command](https://docs.docker.com/build/buildx/install/) to use the [Buildkit optimization given by Dofigen](https://github.com/lenra-io/dofigen). +You can also install the [Docker buildx command](https://docs.docker.com/build/buildx/install/) to use the [Buildkit optimization given by Dofigen](https://github.com/lenra-io/dofigen). Install the Lenra CLI using one of the next possibilities. From 10b4753111b838cb50da92e90f5a9f1502c38473 Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:43:03 +0200 Subject: [PATCH 18/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d4322ce..987e4a6 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Use the help options to understand how to use it: ```bash $ lenra --help lenra_cli 0.0.0 -The Lenra's command line interface +The Lenra command line interface USAGE: lenra From 3ea31e99ea6719e933999c20331978b33f9bd16a Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:43:08 +0200 Subject: [PATCH 19/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 987e4a6..704a3c0 100644 --- a/README.md +++ b/README.md @@ -142,7 +142,7 @@ This subcommand starts the Lenra app of the current directory previously built. ```bash $ lenra start --help lenra-start -Start your app previously built with the build command +Starts your app previously built with the build command USAGE: lenra start [OPTIONS] From 13e9de02ad200019f9e252f104fa1951d8eef563 Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:43:12 +0200 Subject: [PATCH 20/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 704a3c0..aebb6a2 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ This subcommand stops the Lenra app of the current directory and removes the Doc ```bash $ lenra stop --help lenra-stop -Stop your app previously started with the start command +Stops your app previously started with the start command USAGE: lenra stop [OPTIONS] From 29da12e0f8d94bd1101607ccaa9170a7f0d615e0 Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:43:17 +0200 Subject: [PATCH 21/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aebb6a2..e8fd162 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ SUBCOMMANDS: help Print this message or the help of the given subcommand(s) new Create a new Lenra app project start Start your app previously built with the build command - stop Stop your app previously started with the start command + stop Stops your app previously started with the start command ``` ### Subcommands From c60fe70b48e64f396767febd077a5ff4a363055a Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:43:22 +0200 Subject: [PATCH 22/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8fd162..b218e27 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ This tools contains many subcommands to help you doing what you need. - [new](#new): creates a new Lenra app project - [build](#build): builds the Lenra app of the current directory -- [start](#start): start your app previously built with the build command +- [start](#start): starts your app previously built with the build command - [stop](#stop): stop your app previously started with the start command #### new From 50739147eba7a0954148ce438e988b97ddc14bfc Mon Sep 17 00:00:00 2001 From: Jonas Martinez <36544012+jonas-martinez@users.noreply.github.com> Date: Tue, 6 Sep 2022 15:43:26 +0200 Subject: [PATCH 23/26] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b218e27..3694597 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ This tools contains many subcommands to help you doing what you need. - [new](#new): creates a new Lenra app project - [build](#build): builds the Lenra app of the current directory - [start](#start): starts your app previously built with the build command -- [stop](#stop): stop your app previously started with the start command +- [stop](#stop): stops your app previously started with the start command #### new From d2c3b7da101ea43a7af542254260160a600796d7 Mon Sep 17 00:00:00 2001 From: jonas-martinez Date: Tue, 6 Sep 2022 15:45:37 +0200 Subject: [PATCH 24/26] fix format --- src/docker_compose.rs | 34 +++++++++++++++++----------------- src/stop.rs | 4 +--- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/docker_compose.rs b/src/docker_compose.rs index 0867fc2..d048f9e 100644 --- a/src/docker_compose.rs +++ b/src/docker_compose.rs @@ -180,23 +180,23 @@ pub fn compose_up() { pub fn compose_build() { let mut command = create_compose_command(); - command.arg("build"); - - // Use Buildkit to improve performance - command.env("DOCKER_BUILDKIT", "1"); - - // Display std out & err - command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); - - log::debug!("Build: {:?}", command); - let output = command.output().expect("Failed building the Docker image"); - if !output.status.success() { - panic!( - "An error occured while building the Docker image:\n{}\n{}", - String::from_utf8(output.stdout).unwrap(), - String::from_utf8(output.stderr).unwrap() - ) - } + command.arg("build"); + + // Use Buildkit to improve performance + command.env("DOCKER_BUILDKIT", "1"); + + // Display std out & err + command.stdout(Stdio::inherit()).stderr(Stdio::inherit()); + + log::debug!("Build: {:?}", command); + let output = command.output().expect("Failed building the Docker image"); + if !output.status.success() { + panic!( + "An error occured while building the Docker image:\n{}\n{}", + String::from_utf8(output.stdout).unwrap(), + String::from_utf8(output.stderr).unwrap() + ) + } } pub fn execute_compose_service_command(service: &str, cmd: &[&str]) { diff --git a/src/stop.rs b/src/stop.rs index d2e8f7e..67f4b60 100644 --- a/src/stop.rs +++ b/src/stop.rs @@ -17,9 +17,7 @@ impl Stop { /// Starts the docker-compose fn stop_docker_compose(&self) { let dockercompose_path: PathBuf = DOCKERCOMPOSE_DEFAULT_PATH.iter().collect(); - if !dockercompose_path.exists() { - - } + if !dockercompose_path.exists() {} let mut command = Command::new("docker"); From 6dbd70a5258429c7852ad6ecff5523bd845a0eb1 Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 7 Sep 2022 08:14:48 +0200 Subject: [PATCH 25/26] feat: Move cli elements in a mod --- README.md | 21 ++++++++++++++++----- src/{ => cli}/build.rs | 0 src/{cli.rs => cli/mod.rs} | 9 +++++++-- src/{ => cli}/new.rs | 0 src/{ => cli}/start.rs | 0 src/{ => cli}/stop.rs | 0 src/main.rs | 4 ---- 7 files changed, 23 insertions(+), 11 deletions(-) rename src/{ => cli}/build.rs (100%) rename src/{cli.rs => cli/mod.rs} (85%) rename src/{ => cli}/new.rs (100%) rename src/{ => cli}/start.rs (100%) rename src/{ => cli}/stop.rs (100%) diff --git a/README.md b/README.md index 3694597..1d0d309 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,10 @@ You can also install the [Docker buildx command](https://docs.docker.com/build/b Install the Lenra CLI using one of the next possibilities. +#### Download the binary + +You can download the binary from [the release page](https://github.com/lenra-io/lenra_cli/releases) and add it to your path environment variable. + #### Cargo install First install Cargo, the Rust package manager: https://doc.rust-lang.org/cargo/getting-started/installation.html @@ -52,9 +56,16 @@ Then use the next command to install the Lenra's cli: cargo install lenra_cli ``` -#### Download the binary +#### Build it from sources -You can download the binary from [the release page](https://github.com/lenra-io/lenra_cli/releases) and add it to your path environment variable. +First install Cargo, the Rust package manager: https://doc.rust-lang.org/cargo/getting-started/installation.html + +Then clone this repository and install it with Cargo: + +```bash +git clone https://github.com/lenra-io/lenra_cli.git +cargo install --path . +```

(back to top)

@@ -79,7 +90,7 @@ SUBCOMMANDS: help Print this message or the help of the given subcommand(s) new Create a new Lenra app project start Start your app previously built with the build command - stop Stops your app previously started with the start command + stop Stop your app previously started with the start command ``` ### Subcommands @@ -142,7 +153,7 @@ This subcommand starts the Lenra app of the current directory previously built. ```bash $ lenra start --help lenra-start -Starts your app previously built with the build command +Start your app previously built with the build command USAGE: lenra start [OPTIONS] @@ -159,7 +170,7 @@ This subcommand stops the Lenra app of the current directory and removes the Doc ```bash $ lenra stop --help lenra-stop -Stops your app previously started with the start command +Stop your app previously started with the start command USAGE: lenra stop [OPTIONS] diff --git a/src/build.rs b/src/cli/build.rs similarity index 100% rename from src/build.rs rename to src/cli/build.rs diff --git a/src/cli.rs b/src/cli/mod.rs similarity index 85% rename from src/cli.rs rename to src/cli/mod.rs index 71124f1..017c76d 100644 --- a/src/cli.rs +++ b/src/cli/mod.rs @@ -1,8 +1,13 @@ pub use clap::{Args, Parser, Subcommand}; -use crate::{build::Build, new::New, start::Start, stop::Stop}; +use self::{build::Build, new::New, start::Start, stop::Stop}; -/// The Lenra CLI arguments to manage your local app development. +mod build; +mod new; +mod start; +mod stop; + +/// The Lenra command line interface #[derive(Parser)] #[clap(author, version, about, long_about = None)] pub struct Cli { diff --git a/src/new.rs b/src/cli/new.rs similarity index 100% rename from src/new.rs rename to src/cli/new.rs diff --git a/src/start.rs b/src/cli/start.rs similarity index 100% rename from src/start.rs rename to src/cli/start.rs diff --git a/src/stop.rs b/src/cli/stop.rs similarity index 100% rename from src/stop.rs rename to src/cli/stop.rs diff --git a/src/main.rs b/src/main.rs index 039e58d..b301bd9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,13 +6,9 @@ use clap::Parser; use cli::{Cli, CliCommand}; use env_logger; -mod build; mod cli; mod config; mod docker_compose; -mod new; -mod start; -mod stop; fn main() { env_logger::init(); From e8f48c03e6670215b56266689eeeb33a578227bc Mon Sep 17 00:00:00 2001 From: Thomas DA ROCHA Date: Wed, 7 Sep 2022 08:19:46 +0200 Subject: [PATCH 26/26] ci: Fix cargo publish --- Cargo.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 238f651..cd8f03f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,11 @@ readme = "../README.md" repository = "https://github.com/lenra-io/lenra_cli" keywords = ["cli", "lenra"] categories = ["command-line-utilities"] +include = [ + "**/*.rs", + "Cargo.toml", + "README.md", +] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html