From 1b7d42a3e870e4bdef20fff7e3ead302edfb1d6b Mon Sep 17 00:00:00 2001 From: Adrian Benavides Date: Fri, 17 Mar 2023 10:32:27 +0700 Subject: [PATCH] feat(rust): add examples and about sections to markdown generated docs --- Cargo.lock | 13 +- .../rust/ockam/ockam_command/Cargo.toml | 1 + .../rust/ockam/ockam_command/src/admin/mod.rs | 4 +- .../ockam_command/src/admin/subscription.rs | 4 +- .../ockam/ockam_command/src/authenticated.rs | 4 +- .../ockam_command/src/authority/create.rs | 5 +- .../ockam/ockam_command/src/authority/mod.rs | 8 +- .../ockam/ockam_command/src/completion/mod.rs | 11 +- .../src/completion/static/after_long_help.txt | 10 ++ .../src/completion/static/long_about.txt | 8 ++ .../ockam_command/src/configuration/mod.rs | 4 +- .../src/constants/completion/help_detail.txt | 20 --- .../src/constants/forwarder/help_detail.txt | 39 ------ .../src/constants/lib/help_detail.txt | 76 ----------- .../src/constants/message/help_detail.txt | 74 ----------- .../src/constants/node/help_detail.txt | 94 -------------- .../constants/secure_channel/help_detail.txt | 120 ------------------ .../src/constants/tcp/inlet/help_detail.txt | 19 --- .../src/constants/tcp/outlet/help_detail.txt | 19 --- .../ockam/ockam_command/src/credential/mod.rs | 6 +- .../ockam_command/src/{help.rs => docs.rs} | 49 +++++-- .../rust/ockam/ockam_command/src/enroll.rs | 4 +- .../ockam_command/src/forwarder/create.rs | 9 +- .../ockam/ockam_command/src/forwarder/mod.rs | 10 +- .../static/create/after_long_help.txt | 33 +++++ .../forwarder/static/create/long_about.txt | 3 + .../ockam/ockam_command/src/lease/create.rs | 4 +- .../ockam/ockam_command/src/lease/list.rs | 4 +- .../ockam/ockam_command/src/lease/revoke.rs | 4 +- .../ockam/ockam_command/src/lease/show.rs | 4 +- .../rust/ockam/ockam_command/src/lib.rs | 19 +-- .../rust/ockam/ockam_command/src/manpages.rs | 4 +- .../rust/ockam/ockam_command/src/markdown.rs | 33 +++-- .../ockam/ockam_command/src/message/mod.rs | 10 +- .../ockam/ockam_command/src/message/send.rs | 11 +- .../message/static/send/after_long_help.txt | 25 ++++ .../src/message/static/send/long_about.txt | 46 +++++++ .../ockam/ockam_command/src/node/create.rs | 5 +- .../ockam/ockam_command/src/node/default.rs | 3 +- .../ockam/ockam_command/src/node/delete.rs | 4 +- .../rust/ockam/ockam_command/src/node/list.rs | 3 +- .../rust/ockam/ockam_command/src/node/logs.rs | 5 +- .../rust/ockam/ockam_command/src/node/mod.rs | 8 +- .../rust/ockam/ockam_command/src/node/show.rs | 4 +- .../ockam/ockam_command/src/node/start.rs | 5 +- .../src/node/static/after_long_help.txt | 46 +++++++ .../src/node/static/long_about.txt | 46 +++++++ .../rust/ockam/ockam_command/src/node/stop.rs | 5 +- .../ockam/ockam_command/src/policy/mod.rs | 6 +- .../src/project/addon/configure_confluent.rs | 4 +- .../src/project/addon/configure_influxdb.rs | 4 +- .../src/secure_channel/create.rs | 4 +- .../src/secure_channel/delete.rs | 4 +- .../ockam_command/src/secure_channel/list.rs | 5 +- .../src/secure_channel/listener/create.rs | 5 +- .../src/secure_channel/listener/delete.rs | 5 +- .../src/secure_channel/listener/list.rs | 5 +- .../src/secure_channel/listener/mod.rs | 9 +- .../ockam_command/src/secure_channel/mod.rs | 8 +- .../ockam_command/src/secure_channel/show.rs | 4 +- .../secure_channel/static/after_long_help.txt | 115 +++++++++++++++++ .../src/secure_channel/static/long_about.txt | 2 + .../ockam/ockam_command/src/service/mod.rs | 4 +- .../src/{constants/lib => static}/about.txt | 0 .../src/static/after_long_help.txt | 65 ++++++++++ .../ockam_command/src/static/long_about.txt | 7 + .../ockam/ockam_command/src/subscription.rs | 4 +- .../ockam_command/src/tcp/inlet/create.rs | 5 +- .../ockam_command/src/tcp/inlet/delete.rs | 1 - .../ockam/ockam_command/src/tcp/inlet/mod.rs | 9 +- .../ockam_command/src/tcp/outlet/create.rs | 5 +- .../ockam_command/src/tcp/outlet/delete.rs | 1 - .../ockam_command/src/tcp/outlet/list.rs | 5 +- .../ockam/ockam_command/src/tcp/outlet/mod.rs | 9 +- .../src/tcp/static/inlet/after_long_help.txt | 17 +++ .../src/tcp/static/outlet/after_long_help.txt | 17 +++ .../rust/ockam/ockam_command/src/vault/mod.rs | 10 +- .../ockam/ockam_command/src/worker/list.rs | 4 +- .../ockam/ockam_command/src/worker/mod.rs | 4 +- 79 files changed, 647 insertions(+), 645 deletions(-) create mode 100644 implementations/rust/ockam/ockam_command/src/completion/static/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/completion/static/long_about.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/completion/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/forwarder/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/lib/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/message/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/node/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/secure_channel/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/tcp/inlet/help_detail.txt delete mode 100644 implementations/rust/ockam/ockam_command/src/constants/tcp/outlet/help_detail.txt rename implementations/rust/ockam/ockam_command/src/{help.rs => docs.rs} (70%) create mode 100644 implementations/rust/ockam/ockam_command/src/forwarder/static/create/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/forwarder/static/create/long_about.txt create mode 100644 implementations/rust/ockam/ockam_command/src/message/static/send/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/message/static/send/long_about.txt create mode 100644 implementations/rust/ockam/ockam_command/src/node/static/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/node/static/long_about.txt create mode 100644 implementations/rust/ockam/ockam_command/src/secure_channel/static/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/secure_channel/static/long_about.txt rename implementations/rust/ockam/ockam_command/src/{constants/lib => static}/about.txt (100%) create mode 100644 implementations/rust/ockam/ockam_command/src/static/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/static/long_about.txt create mode 100644 implementations/rust/ockam/ockam_command/src/tcp/static/inlet/after_long_help.txt create mode 100644 implementations/rust/ockam/ockam_command/src/tcp/static/outlet/after_long_help.txt diff --git a/Cargo.lock b/Cargo.lock index ed6d093bb83..e11f84db56c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -142,7 +142,7 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.5", + "syn 2.0.7", ] [[package]] @@ -153,7 +153,7 @@ checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.5", + "syn 2.0.7", ] [[package]] @@ -3277,6 +3277,7 @@ dependencies = [ "syntect", "sysinfo", "tempfile", + "termcolor", "termimad", "thiserror", "tokio", @@ -4532,7 +4533,7 @@ checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.5", + "syn 2.0.7", ] [[package]] @@ -4915,9 +4916,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.5" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c2d1c76a26822187a1fbb5964e3fff108bc208f02e820ab9dac1234f6b388a" +checksum = "9a9a90d19f27bb60792270bb90225f96d97fc5705395134b2ca1dcbb3acc27f4" dependencies = [ "proc-macro2", "quote", @@ -5060,7 +5061,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.5", + "syn 2.0.7", ] [[package]] diff --git a/implementations/rust/ockam/ockam_command/Cargo.toml b/implementations/rust/ockam/ockam_command/Cargo.toml index 1c0585f486f..4c5b72a93a9 100644 --- a/implementations/rust/ockam/ockam_command/Cargo.toml +++ b/implementations/rust/ockam/ockam_command/Cargo.toml @@ -95,6 +95,7 @@ rustls = "0.20.8" rustls-native-certs = "0.6.2" pem-rfc7468 = { version = "0.7.0", features = ["std"]} termimad = "0.23" +termcolor = "1.2.0" once_cell = "1.17" ockam = { path = "../ockam", version = "^0.82.0", features = ["software_vault"] } ockam_abac = { path = "../ockam_abac", version = "0.16.0", features = ["std"] } diff --git a/implementations/rust/ockam/ockam_command/src/admin/mod.rs b/implementations/rust/ockam/ockam_command/src/admin/mod.rs index b7d1597a86f..00b0181cb37 100644 --- a/implementations/rust/ockam/ockam_command/src/admin/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/admin/mod.rs @@ -1,14 +1,14 @@ use clap::{Args, Subcommand}; use crate::util::api::CloudOpts; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; mod subscription; const HELP_DETAIL: &str = ""; #[derive(Clone, Debug, Args)] -#[command(hide = help::hide(), after_long_help = help::template(HELP_DETAIL))] +#[command(hide = docs::hide(), after_long_help = docs::after_help(HELP_DETAIL))] pub struct AdminCommand { #[command(subcommand)] pub subcommand: AdminSubCommand, diff --git a/implementations/rust/ockam/ockam_command/src/admin/subscription.rs b/implementations/rust/ockam/ockam_command/src/admin/subscription.rs index 783d1e7c6c6..a2ec523023a 100644 --- a/implementations/rust/ockam/ockam_command/src/admin/subscription.rs +++ b/implementations/rust/ockam/ockam_command/src/admin/subscription.rs @@ -14,12 +14,12 @@ use crate::node::util::delete_embedded_node; use crate::subscription::utils; use crate::util::api::CloudOpts; use crate::util::{node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; const HELP_DETAIL: &str = ""; #[derive(Clone, Debug, Args)] -#[command(hide = help::hide(), after_long_help = help::template(HELP_DETAIL))] +#[command(hide = docs::hide(), after_long_help = docs::after_help(HELP_DETAIL))] pub struct SubscriptionCommand { #[command(subcommand)] subcommand: SubscriptionSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/authenticated.rs b/implementations/rust/ockam/ockam_command/src/authenticated.rs index 5aa24d8afb2..e7892c9871a 100644 --- a/implementations/rust/ockam/ockam_command/src/authenticated.rs +++ b/implementations/rust/ockam/ockam_command/src/authenticated.rs @@ -1,4 +1,4 @@ -use crate::help; +use crate::docs; use crate::util::embedded_node; use crate::Result; use anyhow::{anyhow, Context as _}; @@ -29,7 +29,7 @@ ${identity "#; #[derive(Clone, Debug, Args)] -#[command(hide = help::hide(), after_long_help = help::template(HELP_DETAIL))] +#[command(hide = docs::hide(), after_long_help = docs::after_help(HELP_DETAIL))] pub struct AuthenticatedCommand { #[command(subcommand)] subcommand: AuthenticatedSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/authority/create.rs b/implementations/rust/ockam/ockam_command/src/authority/create.rs index e4d04324250..e16b72f3d0f 100644 --- a/implementations/rust/ockam/ockam_command/src/authority/create.rs +++ b/implementations/rust/ockam/ockam_command/src/authority/create.rs @@ -1,10 +1,9 @@ use crate::authority::HELP_DETAIL; -use crate::help; use crate::node::util::init_node_state; use crate::node::util::run_ockam; use crate::util::node_rpc; use crate::util::{embedded_node_that_is_not_stopped, exitcode}; -use crate::{identity, CommandGlobalOpts, Result}; +use crate::{docs, identity, CommandGlobalOpts, Result}; use anyhow::anyhow; use clap::{ArgGroup, Args}; use ockam::AsyncTryClone; @@ -25,7 +24,7 @@ use tracing::error; /// Create a node #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] +#[command(after_long_help = docs::after_help(HELP_DETAIL))] #[clap(group(ArgGroup::new("okta").args(&["tenant_base_url", "certificate", "attributes"])))] #[clap(group(ArgGroup::new("trusted").required(true).args(&["trusted_identities", "reload_from_trusted_identities_file"])))] pub struct CreateCommand { diff --git a/implementations/rust/ockam/ockam_command/src/authority/mod.rs b/implementations/rust/ockam/ockam_command/src/authority/mod.rs index 09ffc20e472..1031c9e908a 100644 --- a/implementations/rust/ockam/ockam_command/src/authority/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/authority/mod.rs @@ -1,5 +1,5 @@ use crate::authority::create::CreateCommand; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; use clap::Args; use clap::Subcommand; mod create; @@ -9,9 +9,9 @@ const HELP_DETAIL: &str = include_str!("../constants/authority/help_detail.txt") /// Create an Authority node #[derive(Clone, Debug, Args)] #[command( -arg_required_else_help = true, -subcommand_required = true, -after_long_help = help::template(HELP_DETAIL) + arg_required_else_help = true, + subcommand_required = true, + after_long_help = docs::after_help(HELP_DETAIL) )] pub struct AuthorityCommand { #[command(subcommand)] diff --git a/implementations/rust/ockam/ockam_command/src/completion/mod.rs b/implementations/rust/ockam/ockam_command/src/completion/mod.rs index 3fe8159b110..85cdf90a30f 100644 --- a/implementations/rust/ockam/ockam_command/src/completion/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/completion/mod.rs @@ -1,13 +1,18 @@ -use crate::{help, OckamCommand}; +use crate::{docs, OckamCommand}; use clap::{Args, CommandFactory}; use clap_complete::{generate, Shell}; use std::io; -const HELP_DETAIL: &str = include_str!("../constants/completion/help_detail.txt"); +const LONG_ABOUT: &str = include_str!("../static/long_about.txt"); +const AFTER_LONG_HELP: &str = include_str!("../static/after_long_help.txt"); /// Generate Shell Completion Scripts #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command( + arg_required_else_help = true, + long_about = docs::about(LONG_ABOUT), + after_long_help = docs::after_help(AFTER_LONG_HELP) +)] pub struct CompletionCommand { /// The type of shell (bash, zsh, fish) #[arg(display_order = 900, long, short)] diff --git a/implementations/rust/ockam/ockam_command/src/completion/static/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/completion/static/after_long_help.txt new file mode 100644 index 00000000000..6a52fc5d908 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/completion/static/after_long_help.txt @@ -0,0 +1,10 @@ +```sh +# BASH +$ ockam completion --shell bash > /usr/share/bash-completion/completions/ockam.bash + +# ZSH +$ ockam completion --shell zsh > /usr/local/share/zsh/site-functions/_ockam + +# FISH +$ ockam completion --shell fish > ~/.config/fish/completions/ockam.fish +``` diff --git a/implementations/rust/ockam/ockam_command/src/completion/static/long_about.txt b/implementations/rust/ockam/ockam_command/src/completion/static/long_about.txt new file mode 100644 index 00000000000..2ebce1c30f6 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/completion/static/long_about.txt @@ -0,0 +1,8 @@ +Generate shell completion scripts for Ockam commands. + +If you’ve installed `ockam` command using a package manager, you likely +don't need to do any additional shell configuration to gain completion support. + +If you need to set up completions manually, follow the instructions below. +The exact configuration file locations might vary based on your system. Remember +to restart your shell before testing whether completions are working. diff --git a/implementations/rust/ockam/ockam_command/src/configuration/mod.rs b/implementations/rust/ockam/ockam_command/src/configuration/mod.rs index 0cd15e7f46a..2c0d790905a 100644 --- a/implementations/rust/ockam/ockam_command/src/configuration/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/configuration/mod.rs @@ -8,14 +8,14 @@ use get_default_node::GetDefaultNodeCommand; use list::ListCommand; use set_default_node::SetDefaultNodeCommand; -use crate::help; +use crate::docs; use crate::CommandGlobalOpts; use clap::{Args, Subcommand}; const HELP_DETAIL: &str = ""; #[derive(Clone, Debug, Args)] -#[command(hide = help::hide(), after_long_help = help::template(HELP_DETAIL))] +#[command(hide = docs::hide(), after_long_help = docs::after_help(HELP_DETAIL))] pub struct ConfigurationCommand { #[command(subcommand)] subcommand: ConfigurationSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/constants/completion/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/completion/help_detail.txt deleted file mode 100644 index f60e30d45ae..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/completion/help_detail.txt +++ /dev/null @@ -1,20 +0,0 @@ -About: - Generate shell completion scripts for Ockam commands. - - If you’ve installed `ockam` command using a package manager, you likely - don't need to do any additional shell configuration to gain completion support. - - If you need to set up completions manually, follow the instructions below. - The exact configuration file locations might vary based on your system. Remember - to restart your shell before testing whether completions are working. - -```sh - # BASH - $ ockam completion --shell bash > /usr/share/bash-completion/completions/ockam.bash - - # ZSH - $ ockam completion --shell zsh > /usr/local/share/zsh/site-functions/_ockam - - # FISH - $ ockam completion --shell fish > ~/.config/fish/completions/ockam.fish -``` diff --git a/implementations/rust/ockam/ockam_command/src/constants/forwarder/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/forwarder/help_detail.txt deleted file mode 100644 index 8e6ac50ca23..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/forwarder/help_detail.txt +++ /dev/null @@ -1,39 +0,0 @@ -About: - Forwarders enable an ockam node to register a forwarding address on another node. - Any message that arrives at this forwarding address is immediately dispatched - to the node that registered the forwarding address. - -```sh - # Create two nodes blue and green - $ ockam node create blue - $ ockam node create green - - # Create a forwarder to node n2 at node n1 - $ ockam forwarder create blue --at /node/green --to /node/blue - /service/forward_to_blue - - # Send a message to the uppercase service on blue via its forwarder on green - $ ockam message send hello --to /node/green/service/forward_to_blue/service/uppercase -``` - - This can be very useful in establishing communication between applications - that cannot otherwise reach each other over the network. - - For instance, we can use forwarders to create an end-to-end secure channel between - two nodes that are behind private NATs - -```sh - # Create another node called yellow - $ ockam node create yellow - - # Create an end-to-end secure channel between yellow and blue. - # This secure channel is created through blue's forwarder at green and we can - # send end-to-end encrypted messages through it. - $ ockam secure-channel create --from /node/yellow --to /node/green/service/forward_to_blue/service/api \\ - | ockam message send hello --from /node/yellow --to -/service/uppercase -``` - - In this topology green acts an an encrypted relay between yellow and blue. Yellow and - blue can be running in completely separate private networks. Green needs to be reachable - from both yellow and blue and only sees encrypted traffic. - diff --git a/implementations/rust/ockam/ockam_command/src/constants/lib/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/lib/help_detail.txt deleted file mode 100644 index 7e204071510..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/lib/help_detail.txt +++ /dev/null @@ -1,76 +0,0 @@ -About: - Orchestrate end-to-end encryption, mutual authentication, key management, - credential management, and authorization policy enforcement — at scale. - - Modern applications are distributed and have an unwieldy number of - interconnections that must trustfully exchange data. Ockam makes it simple - to build secure by-design applications that have granular control over every - trust and access decision. - -Examples: - - Let's walk through a simple example to create an end-to-end encrypted, - mutually authenticated, secure and private cloud relay – for any application. - - First let's enroll with Ockam Orchestrator where we'll create a managed cloud - based relay that will move end-to-end encrypted data between distributed parts - of our application. - -```sh - # Create a cryptographic identity and enroll with Ockam Orchestrator. - # This will sign you up for an account with Ockam Orchestrator and setup a - # hobby space and project for you. - $ ockam enroll -``` - - You can also create encrypted relays outside the orchestrator. - See `ockam forwarder --help`. - - Application Service - ------ - - Next let's prepare the service side of our application. - -```sh - # Start our application service, listening on a local ip and port, that clients - # would access through the cloud relay. We'll use a simple http server for our - # first example but this could be some other application service. - $ python3 -m http.server --bind 127.0.0.1 5000 - - # Setup an ockam node, called blue, as a sidecar next to our application service. - $ ockam node create blue - - # Create a tcp outlet on the blue node to send raw tcp traffic to the application service. - $ ockam tcp-outlet create --at /node/blue --from /service/outlet --to 127.0.0.1:5000 - - # Then create a forwarding relay at your default orchestrator project to blue. - $ ockam forwarder create blue --at /project/default --to /node/blue -``` - - Application Client - ------ - - Now on the client side: - -```sh - # Setup an ockam node, called green, as a sidecar next to our application service. - $ ockam node create green - - # Then create an end-to-end encrypted secure channel with blue, through the cloud relay. - # Then tunnel traffic from a local tcp inlet through this end-to-end secure channel. - $ ockam secure-channel create --from /node/green \\ - --to /project/default/service/forward_to_blue/service/api \\ - | ockam tcp-inlet create --at /node/green --from 127.0.0.1:7000 --to -/service/outlet - - # Access the application service though the end-to-end encrypted, secure relay. - $ curl 127.0.0.1:7000 -``` - - We just created end-to-end encrypted, mutually authenticated, and authorized - secure communication between a tcp client and server. This client and server - can be running in separate private networks / NATs. We didn't have to expose - our server by opening a port on the Internet or punching a hole in our firewall. - - The two sides authenticated and authorized each other's known, cryptographically - provable identifiers. In later examples we'll see how we can build granular, - attribute-based access control with authorization policies. diff --git a/implementations/rust/ockam/ockam_command/src/constants/message/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/message/help_detail.txt deleted file mode 100644 index 482ff6b8d68..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/message/help_detail.txt +++ /dev/null @@ -1,74 +0,0 @@ -About: - An Ockam node is any running application that can communicate with other applications - using various Ockam protocols like Routing, Secure Channels, Forwarding etc. - - We can create Ockam nodes using this command line or using various Ockam programming - libraries like our Rust and Elixir libraries. - - Workers - ------ - - Ockam nodes run very lightweight, concurrent, stateful actors called Ockam Workers. - Workers have addresses and a node can deliver messages to workers on the same node or - on a different node using the Ockam Routing Protocol and its Transports. - - - Routing - ------ - - The Ockam Routing Protocol is a very simple application layer protocol that allows - the sender of a message to describe the `onward_route` and `return_route` of message. - - The routing layer in a node can then be used route these messages between workers within - a node or across nodes using transports. Messages can be sent over multiple hops, within - one node or across many nodes. - - - Transports - ------ - - Transports are plugins to the Ockam Routing layer that allow Ockam Routing messages - to travel across nodes over transport layer protocols like TCP, UDP, BLUETOOTH etc. - - - Services - ------ - - One or more Ockam Workers can work as a team to offer a Service. Services have - addressed represented by /service/{ADDRESS}. Services can be attached to identities and - authorization policies to enforce attribute based access control rules. - - Nodes created using `ockam` command usually start a pre-defined set of default services. - - This includes: - - A uppercase service at /service/uppercase - - A secure channel listener at /service/api - - A tcp listener listening at some TCP port - -Examples: - -```sh - # Create two nodes - $ ockam node create n1 - $ ockam node create n2 - - # Send a message to the uppercase service on node 2 - $ ockam message send hello --to /node/n2/service/uppercase - HELLO - - # A more verbose version of the above would be, - # assuming n2 started its tcp listener on port 4000. - $ ockam message send hello --to /ip4/127.0.0.1/tcp/4000/service/uppercase - HELLO - - # Send a message to the uppercase service on node n2 from node n1 - $ ockam message send hello --from /node/n1 --to /node/n2/service/uppercase - HELLO - - # Create a secure channel from node n1 to the api service on node n2 - # The /service/api is a secure channel listener that is started on every node - # Send a message through this encrypted channel to the uppercase service - $ ockam secure-channel create --from /node/n1 --to /node/n2/service/api \\ - | ockam message send hello --from /node/n1 --to -/service/uppercase - HELLO -``` diff --git a/implementations/rust/ockam/ockam_command/src/constants/node/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/node/help_detail.txt deleted file mode 100644 index 502dec37db0..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/node/help_detail.txt +++ /dev/null @@ -1,94 +0,0 @@ -About: - An Ockam node is any running application that can communicate with other applications - using various Ockam protocols like Routing, Secure Channels, Forwarding etc. - - We can create Ockam nodes using this command line or using various Ockam programming - libraries like our Rust and Elixir libraries. - - Workers - ------ - - Ockam nodes run very lightweight, concurrent, stateful actors called Ockam Workers. - Workers have addresses and a node can deliver messages to workers on the same node or - on a different node using the Ockam Routing Protocol and its Transports. - - - Routing - ------ - - The Ockam Routing Protocol is a very simple application layer protocol that allows - the sender of a message to describe the `onward_route` and `return_route` of message. - - The routing layer in a node can then be used to route these messages between workers within - a node or across nodes using transports. Messages can be sent over multiple hops, within - one node or across many nodes. - - - Transports - ------ - - Transports are plugins to the Ockam Routing layer that allow Ockam Routing messages - to travel across nodes over transport layer protocols like TCP, UDP, BLUETOOTH etc. - - - Services - ------ - - One or more Ockam Workers can work as a team to offer a Service. Services have - addresses represented by /service/{ADDRESS}. Services can be attached to identities and - authorization policies to enforce attribute based access control rules. - - Nodes created using `ockam` command usually start a pre-defined set of default services. - - This includes: - - A uppercase service at /service/uppercase - - A secure channel listener at /service/api - - A tcp listener listening at some TCP port - -Examples: -```sh - # Create two nodes - $ ockam node create n1 - $ ockam node create n2 - - # Send a message to the uppercase service on node 2 - $ ockam message send hello --to /node/n2/service/uppercase - HELLO - - # A more verbose version of the above would be, - # assuming n2 started its tcp listener on port 4000. - $ ockam message send hello --to /ip4/127.0.0.1/tcp/4000/service/uppercase - HELLO - - # Send a message to the uppercase service on node n2 from node n1 - $ ockam message send hello --from /node/n1 --to /node/n2/service/uppercase - HELLO - - # Create a secure channel from node n1 to the api service on node n2 - # The /service/api is a secure channel listener that is started on every node - # Send a message through this encrypted channel to the uppercase service - $ ockam secure-channel create --from /node/n1 --to /node/n2/service/api \\ - | ockam message send hello --from /node/n1 --to -/service/uppercase - HELLO - - # Create a node, with a specified tcp listener address - $ ockam node create n1 --tcp-listener-address 127.0.0.1:6001 - - # Create a node, and run it in the foreground with verbose traces - $ ockam node create n1 --foreground -vvv - - # Show information about a specific node - $ ockam node show n1 - - # List all created nodes - $ ockam node list - - # Delete the node - $ ockam node delete n1 - - # Delete all nodes - $ ockam node delete --all - - # Delete all nodes and force cleanup - $ ockam node delete --all --force -``` diff --git a/implementations/rust/ockam/ockam_command/src/constants/secure_channel/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/secure_channel/help_detail.txt deleted file mode 100644 index 9d50f79fe05..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/secure_channel/help_detail.txt +++ /dev/null @@ -1,120 +0,0 @@ -About: - Secure Channels provide end-to-end encrypted and mutually authenticated communication - that is safe against eavesdropping, tampering, and forgery of messages en-route. - - To create a secure channel, we first need a secure channel listener. Every node that - is started with ockam command, by convention, starts a secure channel listener at the - address /service/api. - - So the simplest example of creating a secure channel would be: - -```sh - $ ockam node create n1 - $ ockam node create n1 - - $ ockam secure-channel create --from /node/n1 --to /node/n2/service/api - /service/09738b73c54b81d48531f659aaa22533 -``` - - The Ockam Secure Channels protocol is based on handshake designs proposed in the - Noise Protocol Framework. The Noise framework proposes several handshake designs - that make different tradeoffs to achieve various security properties like mutual - authentication, forward secrecy, and resistance to key compromise impersonation etc. - These design have been scrutinized by many experts and have, openly published, - formal proofs. - - Ockam Secure Channels protocol is an opinionated implementation of one such proven - design and `ockam` command makes it super simple to create mutually authenticated - noise based secure channels. - - This secure channels protocol is layered above Ockam Routing and is decoupled - from transport protocols like TCP, UDP, Bluetooth etc. This allows Ockam Secure Channels - to be end-to-end over multiple transport layer hops. - - For instance we can create a secure channel over two TCP connection hops, as follows, - and then send a message through it. - -```sh - # Create three nodes and make them start tcp transport listeners at specific ports - $ ockam node create n1 --tcp-listener-address 127.0.0.1:6001 - $ ockam node create n2 --tcp-listener-address 127.0.0.1:6002 - $ ockam node create n3 --tcp-listener-address 127.0.0.1:6003 - - $ ockam secure-channel create --from /node/n1 \\ - --to /ip4/127.0.0.1/tcp/6002/ip4/127.0.0.1/tcp/6003/service/api \\ - | ockam message send hello --from /node/n1 --to -/service/uppercase - HELLO - - # Or the more concise: - $ ockam secure-channel create --from /node/n1 --to /node/n2/node/n3/service/api \\ - | ockam message send hello --from /node/n1 --to -/service/uppercase - HELLO -``` - - - Combining Secure Channels and Forwarders - ------ - - We can also create a secure channel through Ockam Forwarders. - - Forwarders enable an ockam node to register a forwarding address on another node. - Any message that arrives at this forwarding address is immediately dispatched - to the node that registered the forwarding address. - -```sh - # Create three nodes - $ ockam node create relay - - # Create a forwarder to node n2 at node relay - $ ockam forwarder create blue --at /node/relay --to /node/n2 - /service/forward_to_n2 - - # Create an end-to-end secure channel between n1 and n2. - # This secure channel is created through n2's forwarder at relay and we can - # send end-to-end encrypted messages through it. - $ ockam secure-channel create --from /node/n1 --to /node/relay/service/forward_to_n2/service/api \\ - | ockam message send hello --from /node/n1 --to -/service/uppercase -``` - - In this topology `relay` acts an an encrypted relay between n1 and n2. n1 and - n2 can be running in completely separate private networks. The relay only sees encrypted - traffic and needs to be reachable from both n1 and n2. - - This can be very useful in establishing end-to-end trustful communication between - applications that cannot otherwise reach each other over the network. - - For instance, we can use forwarders to create an end-to-end secure channel between - two nodes that are behind private NATs. - - - List Secure Channels initiated from a node - ------ - -```sh - $ ockam secure-channel list --node n1 -``` - - - Delete Secure Channels initiated from a node - ------ - -```sh - $ ockam secure-channel delete 5f84acc6bf4cb7686e3103555980c05b --at n1 -``` - - - Custom Secure Channel Listeners - ------ - - All node start with a secure channel listener at `/service/api` but you can also - start a custom listener with specific authorization policies. - -```sh - # Create a secure channel listener on n1 - $ ockam secure-channel-listener create test --at n2 - /service/test - - # Create a secure channel listener from n1 to our test secure channel listener on n2 - $ ockam secure-channel create --from /node/n1 --to /node/n2/service/test - /service/09738b73c54b81d48531f659aaa22533 -``` diff --git a/implementations/rust/ockam/ockam_command/src/constants/tcp/inlet/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/tcp/inlet/help_detail.txt deleted file mode 100644 index d3a831ba370..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/tcp/inlet/help_detail.txt +++ /dev/null @@ -1,19 +0,0 @@ -Examples: - -```sh - # Create a target service, we'll use a simple http server for this example - $ python3 -m http.server --bind 127.0.0.1 5000 - - # Create two nodes - $ ockam node create n1 - $ ockam node create n2 - - # Create a TCP outlet from n1 to the target server - $ ockam tcp-outlet create --at /node/n1 --from /service/outlet --to 127.0.0.1:5000 - - # Create a TCP inlet from n2 to the outlet on n1 - $ ockam tcp-inlet create --at /node/n2 --from 127.0.0.1:6000 --to /node/n1/service/outlet - - # Access the service via the inlet/outlet pair - $ curl 127.0.0.1:6000 -``` diff --git a/implementations/rust/ockam/ockam_command/src/constants/tcp/outlet/help_detail.txt b/implementations/rust/ockam/ockam_command/src/constants/tcp/outlet/help_detail.txt deleted file mode 100644 index d3a831ba370..00000000000 --- a/implementations/rust/ockam/ockam_command/src/constants/tcp/outlet/help_detail.txt +++ /dev/null @@ -1,19 +0,0 @@ -Examples: - -```sh - # Create a target service, we'll use a simple http server for this example - $ python3 -m http.server --bind 127.0.0.1 5000 - - # Create two nodes - $ ockam node create n1 - $ ockam node create n2 - - # Create a TCP outlet from n1 to the target server - $ ockam tcp-outlet create --at /node/n1 --from /service/outlet --to 127.0.0.1:5000 - - # Create a TCP inlet from n2 to the outlet on n1 - $ ockam tcp-inlet create --at /node/n2 --from 127.0.0.1:6000 --to /node/n1/service/outlet - - # Access the service via the inlet/outlet pair - $ curl 127.0.0.1:6000 -``` diff --git a/implementations/rust/ockam/ockam_command/src/credential/mod.rs b/implementations/rust/ockam/ockam_command/src/credential/mod.rs index ae098eaae20..304cfee656a 100644 --- a/implementations/rust/ockam/ockam_command/src/credential/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/credential/mod.rs @@ -22,15 +22,15 @@ pub(crate) use store::StoreCommand; pub(crate) use verify::VerifyCommand; use crate::CommandGlobalOpts; -use crate::{help, Result}; +use crate::{docs, Result}; use clap::{Args, Subcommand}; const HELP_DETAIL: &str = ""; #[derive(Clone, Debug, Args)] #[command( - hide = help::hide(), - after_long_help = help::template(HELP_DETAIL), + hide = docs::hide(), + after_long_help = docs::after_help(HELP_DETAIL), arg_required_else_help = true, subcommand_required = true )] diff --git a/implementations/rust/ockam/ockam_command/src/help.rs b/implementations/rust/ockam/ockam_command/src/docs.rs similarity index 70% rename from implementations/rust/ockam/ockam_command/src/help.rs rename to implementations/rust/ockam/ockam_command/src/docs.rs index e1e4928af43..0ca5ebfd5f2 100644 --- a/implementations/rust/ockam/ockam_command/src/help.rs +++ b/implementations/rust/ockam/ockam_command/src/docs.rs @@ -1,6 +1,7 @@ use crate::terminal::TerminalBackground; use colorful::Colorful; use once_cell::sync::Lazy; +use std::io::Write; use syntect::highlighting::Theme; use syntect::{ easy::HighlightLines, @@ -9,6 +10,7 @@ use syntect::{ parsing::SyntaxSet, util::{as_24_bit_terminal_escaped, LinesWithEndings}, }; +use termcolor::WriteColor; const TEMPLATE_BOTTOM: &str = " Learn More: @@ -20,15 +22,6 @@ Feedback: on Github https://github.com/build-trust/ockam/discussions/new "; -pub(crate) fn template(body: &str) -> &'static str { - let mut template: String = body.to_string(); - - template.push_str(TEMPLATE_BOTTOM); - let highlighted = highlight_syntax(template); - - Box::leak(highlighted.into_boxed_str()) -} - static SYNTAX_SET: Lazy = Lazy::new(SyntaxSet::load_defaults_newlines); static RE: Lazy = Lazy::new(|| Regex::new("^[A-Za-z][A-Za-z0-9 ]+:$".into())); static THEME: Lazy> = Lazy::new(|| { @@ -42,6 +35,44 @@ static THEME: Lazy> = Lazy::new(|| { Some(theme) }); +pub(crate) fn about(body: &str) -> &'static str { + Box::leak(highlight_syntax(body.to_string()).into_boxed_str()) +} + +#[allow(unused)] +pub(crate) fn before_help(body: &str) -> &'static str { + Box::leak(highlight_syntax(body.to_string()).into_boxed_str()) +} + +pub(crate) fn after_help(body: &str) -> &'static str { + let mut template = String::new(); + if is_markdown() { + template.push_str("### Examples\n\n"); + } else { + let mut buffer = termcolor::Buffer::ansi(); + let mut color = termcolor::ColorSpec::new(); + color.set_bold(true); + color.set_underline(true); + let err_msg = "Failed to create styled header"; + buffer.set_color(&color).expect(err_msg); + buffer.write_all(template.as_bytes()).expect(err_msg); + buffer.reset().expect(err_msg); + } + template.push_str(body); + if !is_markdown() { + template.push_str(TEMPLATE_BOTTOM); + } + let highlighted = highlight_syntax(template); + Box::leak(highlighted.into_boxed_str()) +} + +pub(crate) fn is_markdown() -> bool { + match std::env::var("MARKDOWN_RENDER") { + Ok(v) => v.eq_ignore_ascii_case("true") || v.eq_ignore_ascii_case("1"), + Err(_e) => false, + } +} + pub fn highlight_syntax(input: String) -> String { let mut highlighted: Vec = Vec::new(); let mut in_fenced_block = false; diff --git a/implementations/rust/ockam/ockam_command/src/enroll.rs b/implementations/rust/ockam/ockam_command/src/enroll.rs index 01e43e18197..6fe53abe14f 100644 --- a/implementations/rust/ockam/ockam_command/src/enroll.rs +++ b/implementations/rust/ockam/ockam_command/src/enroll.rs @@ -24,13 +24,13 @@ use crate::space::util::config; use crate::util::api::CloudOpts; use crate::util::output::Output; use crate::util::{api, node_rpc, RpcBuilder}; -use crate::{help, CommandGlobalOpts, Result}; +use crate::{docs, CommandGlobalOpts, Result}; const HELP_DETAIL: &str = ""; /// Enroll with Ockam Orchestrator #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] +#[command(after_long_help = docs::after_help(HELP_DETAIL))] pub struct EnrollCommand { #[command(flatten)] pub cloud_opts: CloudOpts, diff --git a/implementations/rust/ockam/ockam_command/src/forwarder/create.rs b/implementations/rust/ockam/ockam_command/src/forwarder/create.rs index 24e2098fa6e..02555ef555c 100644 --- a/implementations/rust/ockam/ockam_command/src/forwarder/create.rs +++ b/implementations/rust/ockam/ockam_command/src/forwarder/create.rs @@ -10,17 +10,20 @@ use ockam_api::nodes::models::forwarder::{CreateForwarder, ForwarderInfo}; use ockam_core::api::Request; use ockam_multiaddr::{MultiAddr, Protocol}; -use crate::forwarder::HELP_DETAIL; use crate::util::output::Output; use crate::util::{extract_address_value, node_rpc, process_nodes_multiaddr, RpcBuilder}; use crate::Result; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; + +const LONG_ABOUT: &str = include_str!("./static/create/long_about.txt"); +const AFTER_LONG_HELP: &str = include_str!("./static/create/after_long_help.txt"); /// Create Forwarders #[derive(Clone, Debug, Args)] #[command( arg_required_else_help = true, - after_long_help = help::template(HELP_DETAIL) + long_about = docs::about(LONG_ABOUT), + after_long_help = docs::after_help(AFTER_LONG_HELP) )] pub struct CreateCommand { /// Name of the forwarder (optional) diff --git a/implementations/rust/ockam/ockam_command/src/forwarder/mod.rs b/implementations/rust/ockam/ockam_command/src/forwarder/mod.rs index 837a1a6fc6d..f48b90697c5 100644 --- a/implementations/rust/ockam/ockam_command/src/forwarder/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/forwarder/mod.rs @@ -2,19 +2,13 @@ use clap::{Args, Subcommand}; pub(crate) use create::CreateCommand; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; mod create; -const HELP_DETAIL: &str = include_str!("../constants/forwarder/help_detail.txt"); - /// Manage Forwarders #[derive(Clone, Debug, Args)] -#[command( - arg_required_else_help = true, - subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) -)] +#[command(arg_required_else_help = true, subcommand_required = true)] pub struct ForwarderCommand { #[command(subcommand)] subcommand: ForwarderSubCommand, diff --git a/implementations/rust/ockam/ockam_command/src/forwarder/static/create/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/forwarder/static/create/after_long_help.txt new file mode 100644 index 00000000000..e060ded42c8 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/forwarder/static/create/after_long_help.txt @@ -0,0 +1,33 @@ +```sh +# Create two nodes blue and green +$ ockam node create blue +$ ockam node create green + +# Create a forwarder to node n2 at node n1 +$ ockam forwarder create blue --at /node/green --to /node/blue +/service/forward_to_blue + +# Send a message to the uppercase service on blue via its forwarder on green +$ ockam message send hello --to /node/green/service/forward_to_blue/service/uppercase +``` + +This can be very useful in establishing communication between applications +that cannot otherwise reach each other over the network. + +For instance, we can use forwarders to create an end-to-end secure channel between +two nodes that are behind private NATs + +```sh +# Create another node called yellow +$ ockam node create yellow + +# Create an end-to-end secure channel between yellow and blue. +# This secure channel is created through blue's forwarder at green and we can +# send end-to-end encrypted messages through it. +$ ockam secure-channel create --from /node/yellow --to /node/green/service/forward_to_blue/service/api \\ + | ockam message send hello --from /node/yellow --to -/service/uppercase +``` + +In this topology green acts an an encrypted relay between yellow and blue. Yellow and +blue can be running in completely separate private networks. Green needs to be reachable +from both yellow and blue and only sees encrypted traffic. diff --git a/implementations/rust/ockam/ockam_command/src/forwarder/static/create/long_about.txt b/implementations/rust/ockam/ockam_command/src/forwarder/static/create/long_about.txt new file mode 100644 index 00000000000..eda0abb3fbd --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/forwarder/static/create/long_about.txt @@ -0,0 +1,3 @@ +Forwarders enable an ockam node to register a forwarding address on another node. +Any message that arrives at this forwarding address is immediately dispatched +to the node that registered the forwarding address. diff --git a/implementations/rust/ockam/ockam_command/src/lease/create.rs b/implementations/rust/ockam/ockam_command/src/lease/create.rs index 843c6d2173f..c6693eddda6 100644 --- a/implementations/rust/ockam/ockam_command/src/lease/create.rs +++ b/implementations/rust/ockam/ockam_command/src/lease/create.rs @@ -9,7 +9,7 @@ use ockam_multiaddr::MultiAddr; use termimad::{minimad::TextTemplate, MadSkin}; use crate::{ - help, + docs, util::{ api::{CloudOpts, ProjectOpts}, node_rpc, @@ -24,7 +24,7 @@ const HELP_DETAIL: &str = ""; /// Create a token within the lease token manager #[derive(Clone, Debug, Args)] -#[command(help_template = help::template(HELP_DETAIL))] +#[command(help_template = docs::after_help(HELP_DETAIL))] pub struct CreateCommand {} impl CreateCommand { diff --git a/implementations/rust/ockam/ockam_command/src/lease/list.rs b/implementations/rust/ockam/ockam_command/src/lease/list.rs index 4e3b2ab1dbf..f45e0745c47 100644 --- a/implementations/rust/ockam/ockam_command/src/lease/list.rs +++ b/implementations/rust/ockam/ockam_command/src/lease/list.rs @@ -9,7 +9,7 @@ use ockam_multiaddr::MultiAddr; use termimad::{minimad::TextTemplate, MadSkin}; use crate::{ - help, + docs, util::{ api::{CloudOpts, ProjectOpts}, node_rpc, @@ -37,7 +37,7 @@ ${token /// List tokens within the lease token manager #[derive(Clone, Debug, Args)] -#[command(help_template = help::template(HELP_DETAIL))] +#[command(help_template = docs::after_help(HELP_DETAIL))] pub struct ListCommand; impl ListCommand { diff --git a/implementations/rust/ockam/ockam_command/src/lease/revoke.rs b/implementations/rust/ockam/ockam_command/src/lease/revoke.rs index fedf105f267..9889b900122 100644 --- a/implementations/rust/ockam/ockam_command/src/lease/revoke.rs +++ b/implementations/rust/ockam/ockam_command/src/lease/revoke.rs @@ -6,7 +6,7 @@ use ockam_core::api::Request; use ockam_multiaddr::MultiAddr; use crate::{ - help, + docs, util::{ api::{CloudOpts, ProjectOpts}, node_rpc, @@ -19,7 +19,7 @@ const HELP_DETAIL: &str = ""; /// Revoke a token within the lease token manager #[derive(Clone, Debug, Args)] -#[command(help_template = help::template(HELP_DETAIL))] +#[command(help_template = docs::after_help(HELP_DETAIL))] pub struct RevokeCommand { /// ID of the token to revoke #[arg(long, short, id = "token_id", value_name = "TOKEN_ID")] diff --git a/implementations/rust/ockam/ockam_command/src/lease/show.rs b/implementations/rust/ockam/ockam_command/src/lease/show.rs index f4b86010bf9..fdabadf304c 100644 --- a/implementations/rust/ockam/ockam_command/src/lease/show.rs +++ b/implementations/rust/ockam/ockam_command/src/lease/show.rs @@ -9,7 +9,7 @@ use ockam_multiaddr::MultiAddr; use termimad::{minimad::TextTemplate, MadSkin}; use crate::{ - help, + docs, util::{ api::{CloudOpts, ProjectOpts}, node_rpc, @@ -24,7 +24,7 @@ const HELP_DETAIL: &str = ""; /// Show detailed token information within the lease token manager #[derive(Clone, Debug, Args)] -#[command(help_template = help::template(HELP_DETAIL))] +#[command(help_template = docs::after_help(HELP_DETAIL))] pub struct ShowCommand { /// ID of the token to retrieve #[arg(short, long, value_name = "TOKEN_ID")] diff --git a/implementations/rust/ockam/ockam_command/src/lib.rs b/implementations/rust/ockam/ockam_command/src/lib.rs index 39cc2001985..93a9c23c816 100644 --- a/implementations/rust/ockam/ockam_command/src/lib.rs +++ b/implementations/rust/ockam/ockam_command/src/lib.rs @@ -7,10 +7,10 @@ mod authority; mod completion; mod configuration; mod credential; +mod docs; mod enroll; mod error; mod forwarder; -mod help; mod identity; mod lease; mod manpages; @@ -71,16 +71,17 @@ use console::Term; use ockam_api::cli_state::CliState; use upgrade::check_if_an_upgrade_is_available; -const ABOUT: &str = include_str!("constants/lib/about.txt"); -const HELP_DETAIL: &str = include_str!("constants/lib/help_detail.txt"); +const ABOUT: &str = include_str!("./static/about.txt"); +const LONG_ABOUT: &str = include_str!("./static/long_about.txt"); +const AFTER_LONG_HELP: &str = include_str!("./static/after_long_help.txt"); #[derive(Debug, Parser)] #[command( name = "ockam", term_width = 100, - about = ABOUT, - long_about = ABOUT, - after_long_help = help::template(HELP_DETAIL), + about = docs::about(ABOUT), + long_about = docs::about(LONG_ABOUT), + after_long_help = docs::after_help(AFTER_LONG_HELP), version, long_version = Version::long(), next_help_heading = "Global Options", @@ -122,16 +123,16 @@ pub struct GlobalArgs { verbose: u8, /// Output without any colors - #[arg(hide = help::hide(), global = true, long)] + #[arg(hide = docs::hide(), global = true, long)] no_color: bool, /// Disable tty functionality - #[arg(hide = help::hide(), global = true, long)] + #[arg(hide = docs::hide(), global = true, long)] no_input: bool, /// Output format #[arg( - hide = help::hide(), + hide = docs::hide(), global = true, long = "output", value_enum, diff --git a/implementations/rust/ockam/ockam_command/src/manpages.rs b/implementations/rust/ockam/ockam_command/src/manpages.rs index 2452091d914..bfe06cc7884 100644 --- a/implementations/rust/ockam/ockam_command/src/manpages.rs +++ b/implementations/rust/ockam/ockam_command/src/manpages.rs @@ -1,4 +1,4 @@ -use crate::help; +use crate::docs; use crate::OckamCommand; use clap::builder::NonEmptyStringValueParser; use clap::{ArgAction, Args, Command, CommandFactory}; @@ -17,7 +17,7 @@ Fallback: \"ockam_man_pages/\" in the current working directory."; /// Generate Ockam man pages #[derive(Clone, Debug, Args)] -#[command(hide = help::hide())] +#[command(hide = docs::hide())] pub struct ManpagesCommand { #[arg( short, diff --git a/implementations/rust/ockam/ockam_command/src/markdown.rs b/implementations/rust/ockam/ockam_command/src/markdown.rs index 4c95fd79564..e2c12e0155a 100644 --- a/implementations/rust/ockam/ockam_command/src/markdown.rs +++ b/implementations/rust/ockam/ockam_command/src/markdown.rs @@ -1,4 +1,4 @@ -use crate::help; +use crate::docs; use crate::OckamCommand; use clap::builder::NonEmptyStringValueParser; use clap::{Args, Command, CommandFactory}; @@ -14,7 +14,7 @@ Fallback: \"ockam_markdown_pages/\" in the current working directory."; /// Generate Ockam markdown pages #[derive(Clone, Debug, Args)] -#[command(hide = help::hide())] +#[command(hide = docs::hide())] pub struct MarkdownCommand { #[arg( short, @@ -32,6 +32,7 @@ impl MarkdownCommand { Ok(path) => path, Err(error) => panic!("Error getting markdown page directory: {error:?}"), }; + env::set_var("MARKDOWN_RENDER", "1"); let clap_command = ::command(); generate_markdown_pages(mark_dir.as_path(), &clap_command, None, Vec::new()); } @@ -125,17 +126,24 @@ fn generate_markdown_page( // append parent commands in beginning of the usage writeln!(buffer, "`{}{}`\n", p_cmd, usage)?; - // About - // prints the long about if provided else moves to short about + // Before help + if let Some(s) = cmd.get_before_long_help() { + writeln!(buffer, "{}\n", s)?; + } else if let Some(s) = cmd.get_before_help() { + writeln!(buffer, "{}\n", s)?; + } + + // About: print the short version first, then the long version. + if let Some(about) = cmd.get_about() { + writeln!(buffer, "{}.\n", about.to_string().trim_end_matches('.'))?; + } if let Some(about) = cmd.get_long_about() { writeln!(buffer, "{}\n", about)?; - } else if let Some(about) = cmd.get_about() { - writeln!(buffer, "{}\n", about)?; } // Subcommands list if cmd.get_subcommands().next().is_some() { - writeln!(buffer, "#### **Subcommands:**\n")?; + writeln!(buffer, "### Subcommands\n")?; for s_cmd in cmd.get_subcommands() { if s_cmd.is_hide_set() { @@ -161,7 +169,7 @@ fn generate_markdown_page( // Arguments if cmd.get_positionals().next().is_some() { - writeln!(buffer, "#### **Arguments:**\n")?; + writeln!(buffer, "### Arguments\n")?; for pos_arg in cmd.get_positionals() { generate_arg_markdown(buffer, pos_arg)?; @@ -177,7 +185,7 @@ fn generate_markdown_page( .collect(); if !non_pos.is_empty() { - writeln!(buffer, "#### **Options:**\n")?; + writeln!(buffer, "### Options\n")?; for arg in non_pos { generate_arg_markdown(buffer, arg)?; @@ -186,6 +194,13 @@ fn generate_markdown_page( writeln!(buffer)?; } + // After help + if let Some(s) = cmd.get_after_long_help() { + writeln!(buffer, "{}\n", s)?; + } else if let Some(s) = cmd.get_after_help() { + writeln!(buffer, "{}\n", s)?; + } + // make a .md file and add the buffer to it let mut name = name.to_owned(); name.push_str(".md"); diff --git a/implementations/rust/ockam/ockam_command/src/message/mod.rs b/implementations/rust/ockam/ockam_command/src/message/mod.rs index 43927ac706a..c22595e2676 100644 --- a/implementations/rust/ockam/ockam_command/src/message/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/message/mod.rs @@ -1,18 +1,12 @@ -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::{Args, Subcommand}; pub use send::SendCommand; mod send; -const HELP_DETAIL: &str = include_str!("../constants/message/help_detail.txt"); - /// Send and Receive Messages #[derive(Clone, Debug, Args)] -#[command( - arg_required_else_help = true, - subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) -)] +#[command(arg_required_else_help = true, subcommand_required = true)] pub struct MessageCommand { #[command(subcommand)] subcommand: MessageSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/message/send.rs b/implementations/rust/ockam/ockam_command/src/message/send.rs index 6077435be5a..2e574a88743 100644 --- a/implementations/rust/ockam/ockam_command/src/message/send.rs +++ b/implementations/rust/ockam/ockam_command/src/message/send.rs @@ -11,11 +11,18 @@ use crate::node::util::{delete_embedded_node, start_embedded_node_with_vault_and use crate::util::api::{CloudOpts, ProjectOpts}; use crate::util::{clean_nodes_multiaddr, extract_address_value, node_rpc, RpcBuilder}; use crate::Result; -use crate::{help, message::HELP_DETAIL, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; + +const LONG_ABOUT: &str = include_str!("./static/send/long_about.txt"); +const AFTER_LONG_HELP: &str = include_str!("./static/send/after_long_help.txt"); /// Send messages #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command( + arg_required_else_help = true, + long_about = docs::about(LONG_ABOUT), + after_long_help = docs::after_help(AFTER_LONG_HELP) +)] pub struct SendCommand { /// The node to send messages from #[arg(short, long, value_name = "NODE")] diff --git a/implementations/rust/ockam/ockam_command/src/message/static/send/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/message/static/send/after_long_help.txt new file mode 100644 index 00000000000..6729cdac40d --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/message/static/send/after_long_help.txt @@ -0,0 +1,25 @@ +```sh +# Create two nodes +$ ockam node create n1 +$ ockam node create n2 + +# Send a message to the uppercase service on node 2 +$ ockam message send hello --to /node/n2/service/uppercase +HELLO + +# A more verbose version of the above would be, +# assuming n2 started its tcp listener on port 4000. +$ ockam message send hello --to /ip4/127.0.0.1/tcp/4000/service/uppercase +HELLO + +# Send a message to the uppercase service on node n2 from node n1 +$ ockam message send hello --from /node/n1 --to /node/n2/service/uppercase +HELLO + +# Create a secure channel from node n1 to the api service on node n2 +# The /service/api is a secure channel listener that is started on every node +# Send a message through this encrypted channel to the uppercase service +$ ockam secure-channel create --from /node/n1 --to /node/n2/service/api \\ + | ockam message send hello --from /node/n1 --to -/service/uppercase +HELLO +``` diff --git a/implementations/rust/ockam/ockam_command/src/message/static/send/long_about.txt b/implementations/rust/ockam/ockam_command/src/message/static/send/long_about.txt new file mode 100644 index 00000000000..07db4c0cd84 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/message/static/send/long_about.txt @@ -0,0 +1,46 @@ +An Ockam node is any running application that can communicate with other applications +using various Ockam protocols like Routing, Secure Channels, Forwarding etc. + +We can create Ockam nodes using this command line or using various Ockam programming +libraries like our Rust and Elixir libraries. + + +Workers +------ + +Ockam nodes run very lightweight, concurrent, stateful actors called Ockam Workers. +Workers have addresses and a node can deliver messages to workers on the same node or +on a different node using the Ockam Routing Protocol and its Transports. + + +Routing +------ + +The Ockam Routing Protocol is a very simple application layer protocol that allows +the sender of a message to describe the `onward_route` and `return_route` of message. + +The routing layer in a node can then be used route these messages between workers within +a node or across nodes using transports. Messages can be sent over multiple hops, within +one node or across many nodes. + + +Transports +------ + +Transports are plugins to the Ockam Routing layer that allow Ockam Routing messages +to travel across nodes over transport layer protocols like TCP, UDP, BLUETOOTH etc. + + +Services +------ + +One or more Ockam Workers can work as a team to offer a Service. Services have +addressed represented by /service/{ADDRESS}. Services can be attached to identities and +authorization policies to enforce attribute based access control rules. + +Nodes created using `ockam` command usually start a pre-defined set of default services. + +This includes: + - A uppercase service at /service/uppercase + - A secure channel listener at /service/api + - A tcp listener listening at some TCP port diff --git a/implementations/rust/ockam/ockam_command/src/node/create.rs b/implementations/rust/ockam/ockam_command/src/node/create.rs index 0df10cbb75d..1d1bcd36c49 100644 --- a/implementations/rust/ockam/ockam_command/src/node/create.rs +++ b/implementations/rust/ockam/ockam_command/src/node/create.rs @@ -21,8 +21,8 @@ use crate::service::start; use crate::util::node_rpc; use crate::util::{bind_to_port_check, embedded_node_that_is_not_stopped, exitcode}; use crate::{ - help, identity, node::show::print_query_status, node::HELP_DETAIL, project, - util::find_available_port, CommandGlobalOpts, Result, + identity, node::show::print_query_status, project, util::find_available_port, + CommandGlobalOpts, Result, }; use crate::{node::util::spawn_node, util::parse_node_name}; use crate::{ @@ -48,7 +48,6 @@ use ockam_core::{AllowAll, LOCAL}; /// Create a node #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] pub struct CreateCommand { /// Name of the node (Optional). #[arg(hide_default_value = true, default_value_t = hex::encode(&random::<[u8;4]>()))] diff --git a/implementations/rust/ockam/ockam_command/src/node/default.rs b/implementations/rust/ockam/ockam_command/src/node/default.rs index 316db4b2148..b16cd2cf060 100644 --- a/implementations/rust/ockam/ockam_command/src/node/default.rs +++ b/implementations/rust/ockam/ockam_command/src/node/default.rs @@ -1,11 +1,10 @@ use crate::node::default_node_name; use crate::node::util::{check_default, set_default_node}; -use crate::{help, node::HELP_DETAIL, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::Args; /// Changes default node #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] pub struct DefaultCommand { /// Name of the node. #[arg(default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/node/delete.rs b/implementations/rust/ockam/ockam_command/src/node/delete.rs index 3a4da3b6cf7..7eea1252027 100644 --- a/implementations/rust/ockam/ockam_command/src/node/delete.rs +++ b/implementations/rust/ockam/ockam_command/src/node/delete.rs @@ -1,12 +1,12 @@ use crate::node::default_node_name; use crate::node::util::{delete_all_nodes, delete_node}; -use crate::{help, node::HELP_DETAIL, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::Args; use colorful::Colorful; /// Delete a node #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct DeleteCommand { /// Name of the node. #[arg(default_value_t = default_node_name(), group = "nodes")] diff --git a/implementations/rust/ockam/ockam_command/src/node/list.rs b/implementations/rust/ockam/ockam_command/src/node/list.rs index 718365c3b8e..c28dc1d62e8 100644 --- a/implementations/rust/ockam/ockam_command/src/node/list.rs +++ b/implementations/rust/ockam/ockam_command/src/node/list.rs @@ -1,5 +1,5 @@ use crate::util::{api, exitcode, node_rpc, RpcBuilder}; -use crate::{help, node::show::print_query_status, node::HELP_DETAIL, CommandGlobalOpts}; +use crate::{node::show::print_query_status, CommandGlobalOpts}; use anyhow::{anyhow, Context as _}; use clap::Args; use ockam::{Context, TcpTransport}; @@ -8,7 +8,6 @@ use std::time::Duration; /// List nodes #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] pub struct ListCommand {} impl ListCommand { diff --git a/implementations/rust/ockam/ockam_command/src/node/logs.rs b/implementations/rust/ockam/ockam_command/src/node/logs.rs index c22c9cee9b9..b4c5c88c621 100644 --- a/implementations/rust/ockam/ockam_command/src/node/logs.rs +++ b/implementations/rust/ockam/ockam_command/src/node/logs.rs @@ -1,13 +1,10 @@ use crate::node::default_node_name; -use crate::{help, node::HELP_DETAIL, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::Args; use std::path::PathBuf; /// Get the stdout/stderr log file of a node #[derive(Clone, Debug, Args)] -#[command( - after_long_help = help::template(HELP_DETAIL) -)] pub struct LogCommand { /// Name of the node. #[arg(default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/node/mod.rs b/implementations/rust/ockam/ockam_command/src/node/mod.rs index a4c1006bed2..b6bd1b5db3d 100644 --- a/implementations/rust/ockam/ockam_command/src/node/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/node/mod.rs @@ -10,7 +10,7 @@ use show::ShowCommand; use start::StartCommand; use stop::StopCommand; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; mod create; mod default; @@ -23,14 +23,16 @@ mod stop; pub mod util; pub use create::*; -const HELP_DETAIL: &str = include_str!("../constants/node/help_detail.txt"); +const LONG_ABOUT: &str = include_str!("./static/long_about.txt"); +const AFTER_LONG_HELP: &str = include_str!("../static/after_long_help.txt"); /// Manage Nodes #[derive(Clone, Debug, Args)] #[command( arg_required_else_help = true, subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) + long_about = docs::about(LONG_ABOUT), + after_long_help = docs::after_help(AFTER_LONG_HELP) )] pub struct NodeCommand { #[command(subcommand)] diff --git a/implementations/rust/ockam/ockam_command/src/node/show.rs b/implementations/rust/ockam/ockam_command/src/node/show.rs index 0b9ecdcd760..5061ebd7e92 100644 --- a/implementations/rust/ockam/ockam_command/src/node/show.rs +++ b/implementations/rust/ockam/ockam_command/src/node/show.rs @@ -1,6 +1,6 @@ use crate::node::default_node_name; use crate::util::{api, node_rpc, Rpc, RpcBuilder}; -use crate::{help, node::HELP_DETAIL, CommandGlobalOpts, Result}; +use crate::{CommandGlobalOpts, Result}; use clap::Args; use colorful::Colorful; use ockam::TcpTransport; @@ -19,7 +19,7 @@ const IS_NODE_UP_MAX_ATTEMPTS: usize = 20; // 1 second /// Show node details #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct ShowCommand { /// Name of the node. #[arg(default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/node/start.rs b/implementations/rust/ockam/ockam_command/src/node/start.rs index 5a7b5b07462..1f3a26eb036 100644 --- a/implementations/rust/ockam/ockam_command/src/node/start.rs +++ b/implementations/rust/ockam/ockam_command/src/node/start.rs @@ -6,13 +6,10 @@ use crate::node::default_node_name; use crate::node::show::print_query_status; use crate::node::util::spawn_node; use crate::util::{node_rpc, RpcBuilder}; -use crate::{help, node::HELP_DETAIL, CommandGlobalOpts}; +use crate::CommandGlobalOpts; /// Start a node #[derive(Clone, Debug, Args)] -#[command( - after_long_help = help::template(HELP_DETAIL) -)] pub struct StartCommand { /// Name of the node. #[arg(default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/node/static/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/node/static/after_long_help.txt new file mode 100644 index 00000000000..01bdba74d2b --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/node/static/after_long_help.txt @@ -0,0 +1,46 @@ +```sh +# Create two nodes +$ ockam node create n1 +$ ockam node create n2 + +# Send a message to the uppercase service on node 2 +$ ockam message send hello --to /node/n2/service/uppercase +HELLO + +# A more verbose version of the above would be, +# assuming n2 started its tcp listener on port 4000. +$ ockam message send hello --to /ip4/127.0.0.1/tcp/4000/service/uppercase +HELLO + +# Send a message to the uppercase service on node n2 from node n1 +$ ockam message send hello --from /node/n1 --to /node/n2/service/uppercase +HELLO + +# Create a secure channel from node n1 to the api service on node n2 +# The /service/api is a secure channel listener that is started on every node +# Send a message through this encrypted channel to the uppercase service +$ ockam secure-channel create --from /node/n1 --to /node/n2/service/api \\ + | ockam message send hello --from /node/n1 --to -/service/uppercase +HELLO + +# Create a node, with a specified tcp listener address +$ ockam node create n1 --tcp-listener-address 127.0.0.1:6001 + +# Create a node, and run it in the foreground with verbose traces +$ ockam node create n1 --foreground -vvv + +# Show information about a specific node +$ ockam node show n1 + +# List all created nodes +$ ockam node list + +# Delete the node +$ ockam node delete n1 + +# Delete all nodes +$ ockam node delete --all + +# Delete all nodes and force cleanup +$ ockam node delete --all --force +``` diff --git a/implementations/rust/ockam/ockam_command/src/node/static/long_about.txt b/implementations/rust/ockam/ockam_command/src/node/static/long_about.txt new file mode 100644 index 00000000000..3693c009526 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/node/static/long_about.txt @@ -0,0 +1,46 @@ +An Ockam node is any running application that can communicate with other applications +using various Ockam protocols like Routing, Secure Channels, Forwarding etc. + +We can create Ockam nodes using this command line or using various Ockam programming +libraries like our Rust and Elixir libraries. + + +Workers +------ + +Ockam nodes run very lightweight, concurrent, stateful actors called Ockam Workers. +Workers have addresses and a node can deliver messages to workers on the same node or +on a different node using the Ockam Routing Protocol and its Transports. + + +Routing +------ + +The Ockam Routing Protocol is a very simple application layer protocol that allows +the sender of a message to describe the `onward_route` and `return_route` of message. + +The routing layer in a node can then be used to route these messages between workers within +a node or across nodes using transports. Messages can be sent over multiple hops, within +one node or across many nodes. + + +Transports +------ + +Transports are plugins to the Ockam Routing layer that allow Ockam Routing messages +to travel across nodes over transport layer protocols like TCP, UDP, BLUETOOTH etc. + + +Services +------ + +One or more Ockam Workers can work as a team to offer a Service. Services have +addresses represented by /service/{ADDRESS}. Services can be attached to identities and +authorization policies to enforce attribute based access control rules. + +Nodes created using `ockam` command usually start a pre-defined set of default services. + +This includes: + - An uppercase service at /service/uppercase + - A secure channel listener at /service/api + - A tcp listener listening at some TCP port diff --git a/implementations/rust/ockam/ockam_command/src/node/stop.rs b/implementations/rust/ockam/ockam_command/src/node/stop.rs index d6fd4a99079..be442e56002 100644 --- a/implementations/rust/ockam/ockam_command/src/node/stop.rs +++ b/implementations/rust/ockam/ockam_command/src/node/stop.rs @@ -1,12 +1,9 @@ use crate::node::default_node_name; -use crate::{help, node::HELP_DETAIL, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::Args; /// Stop a node #[derive(Clone, Debug, Args)] -#[command( - after_long_help = help::template(HELP_DETAIL) -)] pub struct StopCommand { /// Name of the node. #[arg(default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/policy/mod.rs b/implementations/rust/ockam/ockam_command/src/policy/mod.rs index 954ab023ed2..2d1dedea29f 100644 --- a/implementations/rust/ockam/ockam_command/src/policy/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/policy/mod.rs @@ -6,14 +6,12 @@ use crate::policy::delete::DeleteCommand; use crate::policy::get::GetCommand; use crate::policy::list::ListCommand; use crate::policy::set::SetCommand; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; use clap::{Args, Subcommand}; use ockam_abac::{Action, Resource}; -const HELP_DETAIL: &str = ""; - #[derive(Clone, Debug, Args)] -#[command(hide = help::hide(), after_long_help = help::template(HELP_DETAIL))] +#[command(hide = docs::hide())] pub struct PolicyCommand { #[command(subcommand)] subcommand: PolicySubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/project/addon/configure_confluent.rs b/implementations/rust/ockam/ockam_command/src/project/addon/configure_confluent.rs index 5cb65d2fb25..786a9c38ac5 100644 --- a/implementations/rust/ockam/ockam_command/src/project/addon/configure_confluent.rs +++ b/implementations/rust/ockam/ockam_command/src/project/addon/configure_confluent.rs @@ -16,7 +16,7 @@ use crate::project::util::check_project_readiness; use crate::util::api::CloudOpts; use crate::util::{api, node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts, Result}; +use crate::{docs, CommandGlobalOpts, Result}; const CONFLUENT_HELP_DETAIL: &str = r#" About: @@ -29,7 +29,7 @@ Examples: /// Configure the Confluent Cloud addon for a project #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(CONFLUENT_HELP_DETAIL))] +#[command(after_long_help = docs::after_help(CONFLUENT_HELP_DETAIL))] pub struct AddonConfigureConfluentSubcommand { /// Ockam project name #[arg( diff --git a/implementations/rust/ockam/ockam_command/src/project/addon/configure_influxdb.rs b/implementations/rust/ockam/ockam_command/src/project/addon/configure_influxdb.rs index b97f43edcca..07c5d511350 100644 --- a/implementations/rust/ockam/ockam_command/src/project/addon/configure_influxdb.rs +++ b/implementations/rust/ockam/ockam_command/src/project/addon/configure_influxdb.rs @@ -18,7 +18,7 @@ use crate::project::util::check_project_readiness; use crate::util::api::CloudOpts; use crate::util::{api, exitcode, node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts, Result}; +use crate::{docs, CommandGlobalOpts, Result}; const INFLUXDB_HELP_DETAIL: &str = r#" About: @@ -31,7 +31,7 @@ Examples: /// Configure the InfluxDB Cloud addon for a project #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(INFLUXDB_HELP_DETAIL))] +#[command(after_long_help = docs::after_help(INFLUXDB_HELP_DETAIL))] pub struct AddonConfigureInfluxdbSubcommand { /// Ockam Project Name #[arg( diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/create.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/create.rs index 968ea55341f..211d6755518 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/create.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/create.rs @@ -1,5 +1,4 @@ use crate::{ - help, util::{exitcode, extract_address_value, node_rpc}, CommandGlobalOpts, OutputFormat, Result, }; @@ -10,7 +9,6 @@ use colorful::Colorful; use ockam_core::api::Request; use serde_json::json; -use crate::secure_channel::HELP_DETAIL; use crate::util::api::CloudOpts; use crate::util::{clean_nodes_multiaddr, is_tty, RpcBuilder}; use ockam::{identity::IdentityIdentifier, route, Context, TcpTransport}; @@ -21,7 +19,7 @@ use ockam_multiaddr::MultiAddr; /// Create Secure Channels #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct CreateCommand { /// Node from which to initiate the secure channel (required) #[arg(value_name = "NODE", long, display_order = 800)] diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/delete.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/delete.rs index 1e38fe3b9a0..1d38a838246 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/delete.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/delete.rs @@ -1,6 +1,4 @@ -use crate::secure_channel::HELP_DETAIL; use crate::{ - help, util::{api, exitcode, extract_address_value, node_rpc, Rpc}, CommandGlobalOpts, OutputFormat, Result, }; @@ -17,7 +15,7 @@ use ockam_core::{Address, AddressParseError}; /// Delete Secure Channels #[derive(Clone, Debug, Parser)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct DeleteCommand { /// Node from which to initiate the secure channel (required) #[arg(value_name = "NODE", long, display_order = 800)] diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/list.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/list.rs index 4e65a2a29f8..084d8430d8c 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/list.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/list.rs @@ -8,17 +8,16 @@ use ockam_core::{route, Address}; use serde_json::json; -use crate::secure_channel::HELP_DETAIL; use crate::util::{is_tty, RpcBuilder}; use crate::{ - exitcode, help, + exitcode, util::{api, node_rpc}, CommandGlobalOpts, OutputFormat, }; /// List Secure Channels #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct ListCommand { /// Node at which the returned secure channels were initiated (required) #[arg(value_name = "NODE", long, display_order = 800)] diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/create.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/create.rs index 6836261c7ca..21833bb6805 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/create.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/create.rs @@ -9,13 +9,12 @@ use ockam_core::api::{Request, Status}; use ockam_core::{Address, Route}; use super::common::SecureChannelListenerNodeOpts; -use crate::secure_channel::HELP_DETAIL; use crate::util::{api, exitcode, extract_address_value, node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts, Result}; +use crate::{CommandGlobalOpts, Result}; /// Create Secure Channel Listeners #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct CreateCommand { #[command(flatten)] node_opts: SecureChannelListenerNodeOpts, diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/delete.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/delete.rs index f889a3182c5..728adcd06f4 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/delete.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/delete.rs @@ -4,13 +4,12 @@ use ockam::Context; use ockam_core::Address; use super::common::SecureChannelListenerNodeOpts; -use crate::secure_channel::HELP_DETAIL; use crate::util::{api, extract_address_value, node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; /// Delete Secure Channel Listeners #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct DeleteCommand { /// Address at which the channel listener to be deleted is running (required) address: Address, diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/list.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/list.rs index 5c2087eb728..cdbc46ee714 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/list.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/list.rs @@ -3,14 +3,13 @@ use clap::Args; use ockam::Context; use crate::node::NodeOpts; -use crate::secure_channel::HELP_DETAIL; use crate::util::api; use crate::util::{node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; /// List Secure Channel Listeners #[derive(Args, Clone, Debug)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct ListCommand { /// Node of which secure listeners shall be listed #[command(flatten)] diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/mod.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/mod.rs index 38f296d1dc8..d031c4ddf4a 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/listener/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/listener/mod.rs @@ -7,17 +7,12 @@ pub(crate) use create::CreateCommand; pub(crate) use delete::DeleteCommand; pub(crate) use list::ListCommand; -use crate::secure_channel::HELP_DETAIL; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::{Args, Subcommand}; /// Manage Secure Channel Listeners #[derive(Clone, Debug, Args)] -#[command( - arg_required_else_help = true, - subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) -)] +#[command(arg_required_else_help = true, subcommand_required = true)] pub struct SecureChannelListenerCommand { #[command(subcommand)] subcommand: SecureChannelListenerSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/mod.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/mod.rs index ab12890cf8c..59e54453bcc 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/mod.rs @@ -10,17 +10,19 @@ pub use delete::DeleteCommand; pub use list::ListCommand; pub use show::ShowCommand; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; use clap::{Args, Subcommand}; -const HELP_DETAIL: &str = include_str!("../constants/secure_channel/help_detail.txt"); +const LONG_ABOUT: &str = include_str!("./static/long_about.txt"); +const AFTER_LONG_HELP: &str = include_str!("./static/after_long_help.txt"); /// Manage Secure Channels. #[derive(Clone, Debug, Args)] #[command( arg_required_else_help = true, subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) + long_about = docs::about(LONG_ABOUT), + after_long_help = docs::after_help(AFTER_LONG_HELP) )] pub struct SecureChannelCommand { #[command(subcommand)] diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/show.rs b/implementations/rust/ockam/ockam_command/src/secure_channel/show.rs index 3e11e987de6..77f7f0bcc18 100644 --- a/implementations/rust/ockam/ockam_command/src/secure_channel/show.rs +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/show.rs @@ -1,6 +1,4 @@ -use crate::secure_channel::HELP_DETAIL; use crate::{ - help, util::{api, extract_address_value, node_rpc, Rpc}, CommandGlobalOpts, Result, }; @@ -12,7 +10,7 @@ use ockam_core::Address; /// Show Secure Channels #[derive(Clone, Debug, Args)] -#[command(arg_required_else_help = true, after_long_help = help::template(HELP_DETAIL))] +#[command(arg_required_else_help = true)] pub struct ShowCommand { /// Node #[arg(value_name = "NODE", long, display_order = 800)] diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/static/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/secure_channel/static/after_long_help.txt new file mode 100644 index 00000000000..f2cbf5160eb --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/static/after_long_help.txt @@ -0,0 +1,115 @@ +To create a secure channel, we first need a secure channel listener. Every node that +is started with ockam command, by convention, starts a secure channel listener at the +address /service/api. + +So the simplest example of creating a secure channel would be: + +```sh +$ ockam node create n1 +$ ockam node create n1 + +$ ockam secure-channel create --from /node/n1 --to /node/n2/service/api +/service/09738b73c54b81d48531f659aaa22533 +``` + +The Ockam Secure Channels protocol is based on handshake designs proposed in the +Noise Protocol Framework. The Noise framework proposes several handshake designs +that make different tradeoffs to achieve various security properties like mutual +authentication, forward secrecy, and resistance to key compromise impersonation etc. +These design have been scrutinized by many experts and have, openly published, +formal proofs. + +Ockam Secure Channels protocol is an opinionated implementation of one such proven +design and `ockam` command makes it super simple to create mutually authenticated +noise based secure channels. + +This secure channels protocol is layered above Ockam Routing and is decoupled +from transport protocols like TCP, UDP, Bluetooth etc. This allows Ockam Secure Channels +to be end-to-end over multiple transport layer hops. + +For instance we can create a secure channel over two TCP connection hops, as follows, +and then send a message through it. + +```sh +# Create three nodes and make them start tcp transport listeners at specific ports +$ ockam node create n1 --tcp-listener-address 127.0.0.1:6001 +$ ockam node create n2 --tcp-listener-address 127.0.0.1:6002 +$ ockam node create n3 --tcp-listener-address 127.0.0.1:6003 + +$ ockam secure-channel create --from /node/n1 \\ + --to /ip4/127.0.0.1/tcp/6002/ip4/127.0.0.1/tcp/6003/service/api \\ + | ockam message send hello --from /node/n1 --to -/service/uppercase +HELLO + +# Or the more concise: +$ ockam secure-channel create --from /node/n1 --to /node/n2/node/n3/service/api \\ + | ockam message send hello --from /node/n1 --to -/service/uppercase +HELLO +``` + + +Combining Secure Channels and Forwarders +------ + +We can also create a secure channel through Ockam Forwarders. + +Forwarders enable an ockam node to register a forwarding address on another node. +Any message that arrives at this forwarding address is immediately dispatched +to the node that registered the forwarding address. + +```sh +# Create three nodes +$ ockam node create relay + +# Create a forwarder to node n2 at node relay +$ ockam forwarder create blue --at /node/relay --to /node/n2 +/service/forward_to_n2 + +# Create an end-to-end secure channel between n1 and n2. +# This secure channel is created through n2's forwarder at relay and we can +# send end-to-end encrypted messages through it. +$ ockam secure-channel create --from /node/n1 --to /node/relay/service/forward_to_n2/service/api \\ + | ockam message send hello --from /node/n1 --to -/service/uppercase +``` + +In this topology `relay` acts an an encrypted relay between n1 and n2. n1 and +n2 can be running in completely separate private networks. The relay only sees encrypted +traffic and needs to be reachable from both n1 and n2. + +This can be very useful in establishing end-to-end trustful communication between +applications that cannot otherwise reach each other over the network. + +For instance, we can use forwarders to create an end-to-end secure channel between +two nodes that are behind private NATs. + + +List Secure Channels initiated from a node +------ + +```sh +$ ockam secure-channel list --node n1 +``` + +Delete Secure Channels initiated from a node +------ + +```sh +$ ockam secure-channel delete 5f84acc6bf4cb7686e3103555980c05b --at n1 +``` + + +Custom Secure Channel Listeners +------ + +All node start with a secure channel listener at `/service/api` but you can also +start a custom listener with specific authorization policies. + +```sh +# Create a secure channel listener on n1 +$ ockam secure-channel-listener create test --at n2 +/service/test + +# Create a secure channel listener from n1 to our test secure channel listener on n2 +$ ockam secure-channel create --from /node/n1 --to /node/n2/service/test +/service/09738b73c54b81d48531f659aaa22533 +``` diff --git a/implementations/rust/ockam/ockam_command/src/secure_channel/static/long_about.txt b/implementations/rust/ockam/ockam_command/src/secure_channel/static/long_about.txt new file mode 100644 index 00000000000..19105a44597 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/secure_channel/static/long_about.txt @@ -0,0 +1,2 @@ +Secure Channels provide end-to-end encrypted and mutually authenticated communication +that is safe against eavesdropping, tampering, and forgery of messages en-route. diff --git a/implementations/rust/ockam/ockam_command/src/service/mod.rs b/implementations/rust/ockam/ockam_command/src/service/mod.rs index 6a908f42280..282792fa0c1 100644 --- a/implementations/rust/ockam/ockam_command/src/service/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/service/mod.rs @@ -5,14 +5,14 @@ pub(crate) mod util; pub(crate) use start::StartCommand; -use crate::help; +use crate::docs; use crate::CommandGlobalOpts; use clap::{Args, Subcommand}; use list::ListCommand; #[derive(Clone, Debug, Args)] -#[command(hide = help::hide())] +#[command(hide = docs::hide())] pub struct ServiceCommand { #[command(subcommand)] subcommand: ServiceSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/constants/lib/about.txt b/implementations/rust/ockam/ockam_command/src/static/about.txt similarity index 100% rename from implementations/rust/ockam/ockam_command/src/constants/lib/about.txt rename to implementations/rust/ockam/ockam_command/src/static/about.txt diff --git a/implementations/rust/ockam/ockam_command/src/static/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/static/after_long_help.txt new file mode 100644 index 00000000000..9232ab16c90 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/static/after_long_help.txt @@ -0,0 +1,65 @@ +Let's walk through a simple example to create an end-to-end encrypted, +mutually authenticated, secure and private cloud relay – for any application. + +First let's enroll with Ockam Orchestrator where we'll create a managed cloud +based relay that will move end-to-end encrypted data between distributed parts +of our application. + +```sh +# Create a cryptographic identity and enroll with Ockam Orchestrator. +# This will sign you up for an account with Ockam Orchestrator and setup a +# hobby space and project for you. +$ ockam enroll +``` + +You can also create encrypted relays outside the orchestrator. +See `ockam forwarder --help`. + +Application Service +------ + +Next let's prepare the service side of our application. + +```sh +# Start our application service, listening on a local ip and port, that clients +# would access through the cloud relay. We'll use a simple http server for our +# first example but this could be some other application service. +$ python3 -m http.server --bind 127.0.0.1 5000 + +# Setup an ockam node, called blue, as a sidecar next to our application service. +$ ockam node create blue + +# Create a tcp outlet on the blue node to send raw tcp traffic to the application service. +$ ockam tcp-outlet create --at /node/blue --from /service/outlet --to 127.0.0.1:5000 + +# Then create a forwarding relay at your default orchestrator project to blue. +$ ockam forwarder create blue --at /project/default --to /node/blue +``` + +Application Client +------ + +Now on the client side: + +```sh +# Setup an ockam node, called green, as a sidecar next to our application service. +$ ockam node create green + +# Then create an end-to-end encrypted secure channel with blue, through the cloud relay. +# Then tunnel traffic from a local tcp inlet through this end-to-end secure channel. +$ ockam secure-channel create --from /node/green \\ + --to /project/default/service/forward_to_blue/service/api \\ + | ockam tcp-inlet create --at /node/green --from 127.0.0.1:7000 --to -/service/outlet + +# Access the application service though the end-to-end encrypted, secure relay. +$ curl 127.0.0.1:7000 +``` + +We just created end-to-end encrypted, mutually authenticated, and authorized +secure communication between a tcp client and server. This client and server +can be running in separate private networks / NATs. We didn't have to expose +our server by opening a port on the Internet or punching a hole in our firewall. + +The two sides authenticated and authorized each other's known, cryptographically +provable identifiers. In later examples we'll see how we can build granular, +attribute-based access control with authorization policies. diff --git a/implementations/rust/ockam/ockam_command/src/static/long_about.txt b/implementations/rust/ockam/ockam_command/src/static/long_about.txt new file mode 100644 index 00000000000..45110071ff3 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/static/long_about.txt @@ -0,0 +1,7 @@ +Orchestrate end-to-end encryption, mutual authentication, key management, +credential management, and authorization policy enforcement — at scale. + +Modern applications are distributed and have an unwieldy number of +interconnections that must trustfully exchange data. Ockam makes it simple +to build secure by-design applications that have granular control over every +trust and access decision. diff --git a/implementations/rust/ockam/ockam_command/src/subscription.rs b/implementations/rust/ockam/ockam_command/src/subscription.rs index 2c4be85b171..f982511b0cd 100644 --- a/implementations/rust/ockam/ockam_command/src/subscription.rs +++ b/implementations/rust/ockam/ockam_command/src/subscription.rs @@ -13,12 +13,12 @@ use crate::node::util::delete_embedded_node; use crate::util::api::CloudOpts; use crate::util::output::Output; use crate::util::{node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts, Result}; +use crate::{docs, CommandGlobalOpts, Result}; const HELP_DETAIL: &str = ""; #[derive(Clone, Debug, Args)] -#[command(hide = help::hide(), after_long_help = help::template(HELP_DETAIL))] +#[command(hide = docs::hide(), after_long_help = docs::after_help(HELP_DETAIL))] pub struct SubscriptionCommand { #[command(subcommand)] subcommand: SubscriptionSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/tcp/inlet/create.rs b/implementations/rust/ockam/ockam_command/src/tcp/inlet/create.rs index fa881372c13..0b683067249 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/inlet/create.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/inlet/create.rs @@ -4,7 +4,7 @@ use crate::util::{ bind_to_port_check, exitcode, extract_address_value, node_rpc, process_nodes_multiaddr, RpcBuilder, }; -use crate::{help, CommandGlobalOpts, Result}; +use crate::{CommandGlobalOpts, Result}; use anyhow::anyhow; use clap::Args; @@ -17,11 +17,8 @@ use ockam_multiaddr::proto::Project; use ockam_multiaddr::{MultiAddr, Protocol as _}; use std::net::SocketAddr; -const HELP_DETAIL: &str = include_str!("../../constants/tcp/inlet/help_detail.txt"); - /// Create TCP Inlets #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] pub struct CreateCommand { /// Node on which to start the tcp inlet. #[arg(long, display_order = 900, id = "NODE", default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/tcp/inlet/delete.rs b/implementations/rust/ockam/ockam_command/src/tcp/inlet/delete.rs index 8e55d6307f5..f6cb7178be2 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/inlet/delete.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/inlet/delete.rs @@ -9,7 +9,6 @@ use ockam_core::api::{Request, RequestBuilder}; /// Delete a TCP Outlet #[derive(Clone, Debug, Args)] -#[command()] pub struct DeleteCommand { /// Name assigned to inlet that will be deleted #[arg(display_order = 900, required = true, id = "ALIAS", value_parser = alias_parser)] diff --git a/implementations/rust/ockam/ockam_command/src/tcp/inlet/mod.rs b/implementations/rust/ockam/ockam_command/src/tcp/inlet/mod.rs index 90f2abe33b6..c31b22465dc 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/inlet/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/inlet/mod.rs @@ -3,15 +3,22 @@ mod delete; mod list; mod show; -use crate::CommandGlobalOpts; +use crate::{docs, CommandGlobalOpts}; use clap::{Args, Subcommand}; use create::CreateCommand; use delete::DeleteCommand; pub(crate) use list::ListCommand; pub(crate) use show::ShowCommand; +const AFTER_LONG_HELP: &str = include_str!("../static/inlet/after_long_help.txt"); + /// Manage TCP Inlets #[derive(Clone, Debug, Args)] +#[command( + arg_required_else_help = true, + subcommand_required = true, + after_long_help = docs::after_help(AFTER_LONG_HELP) +)] pub struct TcpInletCommand { #[command(subcommand)] subcommand: TcpInletSubCommand, diff --git a/implementations/rust/ockam/ockam_command/src/tcp/outlet/create.rs b/implementations/rust/ockam/ockam_command/src/tcp/outlet/create.rs index 544ce93a513..49166b553b6 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/outlet/create.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/outlet/create.rs @@ -1,7 +1,7 @@ use crate::node::default_node_name; use crate::tcp::util::alias_parser; use crate::util::{extract_address_value, node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::Args; use ockam::Context; use ockam_api::{ @@ -13,11 +13,8 @@ use ockam_core::api::{Request, RequestBuilder}; use ockam_core::route; use std::net::SocketAddr; -const HELP_DETAIL: &str = include_str!("../../constants/tcp/outlet/help_detail.txt"); - /// Create TCP Outlets #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] pub struct CreateCommand { /// Node on which to start the tcp outlet. #[arg(long, display_order = 900, id = "NODE", default_value_t = default_node_name())] diff --git a/implementations/rust/ockam/ockam_command/src/tcp/outlet/delete.rs b/implementations/rust/ockam/ockam_command/src/tcp/outlet/delete.rs index 291429609ac..02b284e919e 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/outlet/delete.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/outlet/delete.rs @@ -9,7 +9,6 @@ use ockam_core::api::{Request, RequestBuilder}; /// Delete a TCP Outlet #[derive(Clone, Debug, Args)] -#[command()] pub struct DeleteCommand { /// Name assigned to outlet that will be deleted #[arg(display_order = 900, required = true, id = "ALIAS", value_parser = alias_parser)] diff --git a/implementations/rust/ockam/ockam_command/src/tcp/outlet/list.rs b/implementations/rust/ockam/ockam_command/src/tcp/outlet/list.rs index 09e7f69bd50..16ff4ab4374 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/outlet/list.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/outlet/list.rs @@ -1,18 +1,15 @@ use crate::node::NodeOpts; use crate::util::{exitcode, extract_address_value, node_rpc, Rpc}; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use anyhow::anyhow; use clap::Args; use ockam_api::nodes::models::portal::OutletList; use ockam_api::{error::ApiError, route_to_multiaddr}; use ockam_core::api::Request; use ockam_core::route; -const HELP_DETAIL: &str = include_str!("../../constants/tcp/outlet/help_detail.txt"); /// List TCP Outlets #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] - pub struct ListCommand { #[command(flatten)] node_opts: NodeOpts, diff --git a/implementations/rust/ockam/ockam_command/src/tcp/outlet/mod.rs b/implementations/rust/ockam/ockam_command/src/tcp/outlet/mod.rs index 02ebf0354d1..b6ea098356b 100644 --- a/implementations/rust/ockam/ockam_command/src/tcp/outlet/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/tcp/outlet/mod.rs @@ -3,15 +3,22 @@ mod delete; mod list; mod show; -use crate::CommandGlobalOpts; +use crate::{docs, CommandGlobalOpts}; use clap::{Args, Subcommand}; use create::CreateCommand; use delete::DeleteCommand; use list::ListCommand; use show::ShowCommand; +const AFTER_LONG_HELP: &str = include_str!("../static/outlet/after_long_help.txt"); + /// Manage TCP Outlets #[derive(Clone, Debug, Args)] +#[command( + arg_required_else_help = true, + subcommand_required = true, + after_long_help = docs::after_help(AFTER_LONG_HELP) +)] pub struct TcpOutletCommand { #[command(subcommand)] subcommand: TcpOutletSubCommand, diff --git a/implementations/rust/ockam/ockam_command/src/tcp/static/inlet/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/tcp/static/inlet/after_long_help.txt new file mode 100644 index 00000000000..39dc1978f71 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/tcp/static/inlet/after_long_help.txt @@ -0,0 +1,17 @@ +```sh +# Create a target service, we'll use a simple http server for this example +$ python3 -m http.server --bind 127.0.0.1 5000 + +# Create two nodes +$ ockam node create n1 +$ ockam node create n2 + +# Create a TCP outlet from n1 to the target server +$ ockam tcp-outlet create --at /node/n1 --from /service/outlet --to 127.0.0.1:5000 + +# Create a TCP inlet from n2 to the outlet on n1 +$ ockam tcp-inlet create --at /node/n2 --from 127.0.0.1:6000 --to /node/n1/service/outlet + +# Access the service via the inlet/outlet pair +$ curl 127.0.0.1:6000 +``` diff --git a/implementations/rust/ockam/ockam_command/src/tcp/static/outlet/after_long_help.txt b/implementations/rust/ockam/ockam_command/src/tcp/static/outlet/after_long_help.txt new file mode 100644 index 00000000000..39dc1978f71 --- /dev/null +++ b/implementations/rust/ockam/ockam_command/src/tcp/static/outlet/after_long_help.txt @@ -0,0 +1,17 @@ +```sh +# Create a target service, we'll use a simple http server for this example +$ python3 -m http.server --bind 127.0.0.1 5000 + +# Create two nodes +$ ockam node create n1 +$ ockam node create n2 + +# Create a TCP outlet from n1 to the target server +$ ockam tcp-outlet create --at /node/n1 --from /service/outlet --to 127.0.0.1:5000 + +# Create a TCP inlet from n2 to the outlet on n1 +$ ockam tcp-inlet create --at /node/n2 --from 127.0.0.1:6000 --to /node/n1/service/outlet + +# Access the service via the inlet/outlet pair +$ curl 127.0.0.1:6000 +``` diff --git a/implementations/rust/ockam/ockam_command/src/vault/mod.rs b/implementations/rust/ockam/ockam_command/src/vault/mod.rs index 2ab2ed6ea41..02086ec6fd6 100644 --- a/implementations/rust/ockam/ockam_command/src/vault/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/vault/mod.rs @@ -12,20 +12,14 @@ use crate::vault::default::DefaultCommand; use crate::vault::delete::DeleteCommand; use crate::vault::list::ListCommand; use crate::vault::show::ShowCommand; -use crate::{help, CommandGlobalOpts}; +use crate::CommandGlobalOpts; use clap::{Args, Subcommand}; use ockam_api::cli_state::CliState; -const HELP_DETAIL: &str = ""; - /// Manage vaults #[derive(Clone, Debug, Args)] -#[command( - arg_required_else_help = true, - subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) -)] +#[command(arg_required_else_help = true, subcommand_required = true)] pub struct VaultCommand { #[command(subcommand)] subcommand: VaultSubcommand, diff --git a/implementations/rust/ockam/ockam_command/src/worker/list.rs b/implementations/rust/ockam/ockam_command/src/worker/list.rs index 7425f3d0d6b..17e2561d450 100644 --- a/implementations/rust/ockam/ockam_command/src/worker/list.rs +++ b/implementations/rust/ockam/ockam_command/src/worker/list.rs @@ -1,6 +1,6 @@ use crate::node::default_node_name; use crate::util::{api, node_rpc, RpcBuilder}; -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; use clap::Args; use ockam::{Context, TcpTransport}; use ockam_api::nodes::models::workers::WorkerList; @@ -11,7 +11,7 @@ const HELP_DETAIL: &str = ""; /// List workers #[derive(Clone, Debug, Args)] -#[command(after_long_help = help::template(HELP_DETAIL))] +#[command(after_long_help = docs::after_help(HELP_DETAIL))] pub struct ListCommand { /// Node at which to lookup workers (required) #[arg(value_name = "NODE", long, default_value_t = default_node_name(), display_order = 800)] diff --git a/implementations/rust/ockam/ockam_command/src/worker/mod.rs b/implementations/rust/ockam/ockam_command/src/worker/mod.rs index c929e5cc450..02f85a42c36 100644 --- a/implementations/rust/ockam/ockam_command/src/worker/mod.rs +++ b/implementations/rust/ockam/ockam_command/src/worker/mod.rs @@ -1,4 +1,4 @@ -use crate::{help, CommandGlobalOpts}; +use crate::{docs, CommandGlobalOpts}; use clap::{Args, Subcommand}; use list::ListCommand; @@ -12,7 +12,7 @@ const HELP_DETAIL: &str = ""; #[command( arg_required_else_help = true, subcommand_required = true, - after_long_help = help::template(HELP_DETAIL) + after_long_help = docs::after_help(HELP_DETAIL) )] pub struct WorkerCommand { #[command(subcommand)]