Skip to content

Commit

Permalink
feat(rust): improve json output of ockam node show
Browse files Browse the repository at this point in the history
Improves the output of the command `ockam node show --output json`
adding all the information that is being displayed with the plain
output. Refactors the plain response to build it using the Output
trait erasing the clippy alert in the process.

Closes build-trust#6142
  • Loading branch information
kriogenia authored and adrianbenavides committed Oct 6, 2023
1 parent 8ef79f8 commit ba24ca5
Show file tree
Hide file tree
Showing 8 changed files with 372 additions and 191 deletions.
1 change: 1 addition & 0 deletions implementations/rust/ockam/ockam_command/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ mod default;
mod delete;
mod list;
mod logs;
mod models;
mod show;
mod start;
mod stop;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod portal;
pub mod secure_channel;
pub mod services;
pub mod show;
pub mod transport;
44 changes: 44 additions & 0 deletions implementations/rust/ockam/ockam_command/src/node/models/portal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
use std::net::SocketAddr;

use ockam_api::{
addr_to_multiaddr,
nodes::models::portal::{InletStatus, OutletStatus},
route_to_multiaddr,
};
use ockam_core::Route;
use ockam_multiaddr::MultiAddr;
use serde::Serialize;

/// Information to display of the inlets in the `ockam node show` command
#[derive(Debug, Serialize)]
pub struct ShowInletStatus {
pub listen_address: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub route_to_outlet: Option<MultiAddr>,
}

impl From<InletStatus> for ShowInletStatus {
fn from(value: InletStatus) -> Self {
Self {
listen_address: value.bind_addr,
route_to_outlet: Route::parse(value.outlet_route).and_then(|r| route_to_multiaddr(&r)),
}
}
}

/// Information to display of the inlets in the `ockam node show` command
#[derive(Debug, Serialize)]
pub struct ShowOutletStatus {
pub forward_address: SocketAddr,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<MultiAddr>,
}

impl From<OutletStatus> for ShowOutletStatus {
fn from(value: OutletStatus) -> Self {
Self {
forward_address: value.socket_addr,
address: addr_to_multiaddr(value.worker_addr),
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use ockam_api::{
addr_to_multiaddr, nodes::models::secure_channel::ShowSecureChannelListenerResponse,
};
use ockam_core::flow_control::FlowControlId;
use ockam_multiaddr::MultiAddr;
use serde::Serialize;

/// Information to display of the secure channel listeners in the `ockam node show` command
#[derive(Debug, Serialize)]
pub struct ShowSecureChannelListener {
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<MultiAddr>,
pub flow_control: FlowControlId,
}

impl From<ShowSecureChannelListenerResponse> for ShowSecureChannelListener {
fn from(value: ShowSecureChannelListenerResponse) -> Self {
Self {
address: addr_to_multiaddr(value.addr),
flow_control: value.flow_control_id,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use ockam_api::{addr_to_multiaddr, nodes::models::services::ServiceStatus};
use ockam_multiaddr::MultiAddr;
use serde::Serialize;

/// Information to display of the services in the `ockam node show` command
#[derive(Debug, Serialize)]
pub struct ShowServiceStatus {
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<MultiAddr>,
#[serde(rename = "type")]
pub service_type: String,
}

impl From<ServiceStatus> for ShowServiceStatus {
fn from(value: ServiceStatus) -> Self {
Self {
address: addr_to_multiaddr(value.addr),
service_type: value.service_type,
}
}
}
163 changes: 163 additions & 0 deletions implementations/rust/ockam/ockam_command/src/node/models/show.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
use std::fmt::Display;

use colorful::Colorful;

use ockam_multiaddr::{
proto::{DnsAddr, Node, Tcp},
MultiAddr,
};
use serde::Serialize;

use crate::output::Output;

use super::{
portal::{ShowInletStatus, ShowOutletStatus},
secure_channel::ShowSecureChannelListener,
services::ShowServiceStatus,
transport::ShowTransportStatus,
};

/// Information to display in the `ockam node show` command
#[derive(Debug, Serialize)]
pub struct ShowNodeResponse {
pub is_default: bool,
pub name: String,
pub is_up: bool,
pub route: RouteToNode,
#[serde(skip_serializing_if = "Option::is_none")]
pub identity: Option<String>,
pub transports: Vec<ShowTransportStatus>,
pub secure_channel_listeners: Vec<ShowSecureChannelListener>,
pub inlets: Vec<ShowInletStatus>,
pub outlets: Vec<ShowOutletStatus>,
pub services: Vec<ShowServiceStatus>,
}
#[derive(Debug, Serialize)]
pub struct RouteToNode {
#[serde(skip_serializing_if = "Option::is_none")]
pub short: Option<MultiAddr>,
#[serde(skip_serializing_if = "Option::is_none")]
pub verbose: Option<MultiAddr>,
}

impl ShowNodeResponse {
pub fn new(
is_default: bool,
name: &str,
is_up: bool,
node_port: Option<u16>,
) -> ShowNodeResponse {
let mut m = MultiAddr::default();
let short = m.push_back(Node::new(name)).ok().map(|_| m);

let verbose = node_port.and_then(|port| {
let mut m = MultiAddr::default();
if m.push_back(DnsAddr::new("localhost")).is_ok() && m.push_back(Tcp::new(port)).is_ok()
{
Some(m)
} else {
None
}
});

ShowNodeResponse {
is_default,
name: name.to_owned(),
is_up,
route: RouteToNode { short, verbose },
identity: None,
transports: Default::default(),
secure_channel_listeners: Default::default(),
inlets: Default::default(),
outlets: Default::default(),
services: Default::default(),
}
}
}

impl Display for ShowNodeResponse {
fn fmt(&self, buffer: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(buffer, "Node:")?;

if self.is_default {
writeln!(buffer, " Name: {} (default)", self.name)?;
} else {
writeln!(buffer, " Name: {}", self.name)?;
}

writeln!(
buffer,
" Status: {}",
match self.is_up {
true => "UP".light_green(),
false => "DOWN".light_red(),
}
)?;

writeln!(buffer, " Route To Node:")?;
if let Some(short) = &self.route.short {
writeln!(buffer, " Short: {short}")?;
}
if let Some(verbose) = &self.route.verbose {
writeln!(buffer, " Verbose: {verbose}")?;
}

if let Some(identity) = &self.identity {
writeln!(buffer, " Identity: {}", identity)?;
}

writeln!(buffer, " Transports:")?;
for e in &self.transports {
writeln!(buffer, " Transport:")?;
writeln!(buffer, " Type: {}", &e.tt)?;
writeln!(buffer, " Mode: {}", &e.mode)?;
writeln!(buffer, " Socket: {}", &e.socket)?;
writeln!(buffer, " Worker: {}", &e.worker)?;
writeln!(buffer, " FlowControlId: {}", &e.flow_control)?;
}

writeln!(buffer, " Secure Channel Listeners:")?;
for e in &self.secure_channel_listeners {
writeln!(buffer, " Listener:")?;
if let Some(ma) = &e.address {
writeln!(buffer, " Address: {ma}")?;
}
writeln!(buffer, " FlowControlId: {}", &e.flow_control)?;
}

writeln!(buffer, " Inlets:")?;
for e in &self.inlets {
writeln!(buffer, " Inlet:")?;
writeln!(buffer, " Listen Address: {}", e.listen_address)?;
if let Some(r) = &e.route_to_outlet {
writeln!(buffer, " Route To Outlet: {r}")?;
}
}

writeln!(buffer, " Outlets:")?;
for e in &self.outlets {
writeln!(buffer, " Outlet:")?;
writeln!(buffer, " Forward Address: {}", e.forward_address)?;
if let Some(ma) = &e.address {
writeln!(buffer, " Address: {ma}")?;
}
}

writeln!(buffer, " Services:")?;
for e in &self.services {
writeln!(buffer, " Service:")?;
writeln!(buffer, " Type: {}", e.service_type)?;
if let Some(ma) = &e.address {
writeln!(buffer, " Address: {ma}")?;
}
}

Ok(())
}
}

impl Output for ShowNodeResponse {
fn output(&self) -> crate::error::Result<String> {
Ok(self.to_string())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use ockam_api::nodes::models::transport::{TransportMode, TransportStatus, TransportType};
use ockam_core::flow_control::FlowControlId;
use serde::Serialize;

/// Information to display of the transports in the `ockam node show` command
#[derive(Debug, Serialize)]
pub struct ShowTransportStatus {
#[serde(rename = "type")]
pub tt: TransportType,
pub mode: TransportMode,
pub socket: String,
pub worker: String,
pub flow_control: FlowControlId,
}

impl From<TransportStatus> for ShowTransportStatus {
fn from(value: TransportStatus) -> Self {
Self {
tt: value.tt,
mode: value.tm,
socket: value.socket_addr,
worker: value.worker_addr,
flow_control: value.flow_control_id,
}
}
}
Loading

0 comments on commit ba24ca5

Please sign in to comment.