Skip to content

Commit

Permalink
Merge pull request #371 from orecham/iox2-98-add-services-list-command
Browse files Browse the repository at this point in the history
[#98] add `iox2 services` cli
  • Loading branch information
orecham committed Sep 19, 2024
2 parents 104a197 + 02fee0d commit a9df608
Show file tree
Hide file tree
Showing 15 changed files with 564 additions and 23 deletions.
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ members = [
"iceoryx2-cli/iox2-rpc",
"iceoryx2-cli/iox2-services",
"iceoryx2-cli/iox2-sub",
"iceoryx2-cli/utils",

"examples",

Expand Down Expand Up @@ -65,6 +66,8 @@ iceoryx2-pal-concurrency-sync = { version = "0.3.0", path = "iceoryx2-pal/concur
iceoryx2-pal-posix = { version = "0.3.0", path = "iceoryx2-pal/posix/" }
iceoryx2-pal-configuration = { version = "0.3.0", path = "iceoryx2-pal/configuration/" }

iceoryx2-cli-utils = { version = "0.3.0", path = "iceoryx2-cli/utils/" }

iceoryx2-cal = { version = "0.3.0", path = "iceoryx2-cal" }

iceoryx2-ffi = { version = "0.3.0", path = "iceoryx2-ffi/ffi" }
Expand All @@ -91,7 +94,10 @@ once_cell = { version = "1.19.0" }
ouroboros = { version = "0.18.4" }
proc-macro2 = { version = "1.0.84" }
quote = { version = "1.0.36" }
ron = { version = "0.8" }
serde = { version = "1.0.203", features = ["derive"] }
serde_yaml = { version = "0.9.34" }
serde_json = { version = "1.0" }
serde_test = { version = "1.0.176" }
sha1_smol = { version = "1.0.0" }
syn = { version = "2.0.66", features = ["full"] }
Expand Down
12 changes: 11 additions & 1 deletion iceoryx2-cli/iox2-services/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "iox2-services"
description = "Iceoryx2: CLI for managing iceoryx2 services"
description = "CLI for managing iceoryx2 services"
categories = { workspace = true }
edition = { workspace = true }
homepage = { workspace = true }
Expand All @@ -13,3 +13,13 @@ version = { workspace = true }
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
iceoryx2 = { workspace = true }
iceoryx2-bb-log = { workspace = true }
iceoryx2-cli-utils = { workspace = true }

anyhow = { workspace = true }
better-panic = { workspace = true }
clap = { workspace = true }
human-panic = { workspace = true }
serde = { workspace = true }

71 changes: 71 additions & 0 deletions iceoryx2-cli/iox2-services/src/cli.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright (c) 2024 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use clap::Args;
use clap::Parser;
use clap::Subcommand;
use clap::ValueEnum;

use iceoryx2_cli_utils::help_template;

use crate::Format;

#[derive(Parser)]
#[command(
name = "iox2-services",
about = "Query information about iceoryx2 services",
long_about = None,
version = env!("CARGO_PKG_VERSION"),
disable_help_subcommand = true,
arg_required_else_help = false,
help_template = help_template("iox2-services", false),
)]
pub struct Cli {
#[clap(subcommand)]
pub action: Option<Action>,

#[clap(long, short = 'f', value_enum, global = true)]
pub format: Option<Format>,
}

#[derive(Debug, Clone, ValueEnum)]
#[clap(rename_all = "PascalCase")]
#[derive(Default)]
pub enum MessagingPatternFilter {
PublishSubscribe,
Event,
#[default]
All,
}

#[derive(Debug, Clone, Args)]
pub struct DetailsFilter {
#[clap(short, long, value_enum, default_value_t = MessagingPatternFilter::All)]
pub pattern: MessagingPatternFilter,
}

#[derive(Parser)]
pub struct DetailsOptions {
#[clap(help = "Name of the service e.g. \"My Service\"")]
pub service: String,

#[command(flatten)]
pub filter: DetailsFilter,
}

#[derive(Subcommand)]
pub enum Action {
#[clap(about = "List all existing services")]
List,
#[clap(about = "Show details of an existing service")]
Details(DetailsOptions),
}
72 changes: 72 additions & 0 deletions iceoryx2-cli/iox2-services/src/commands.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2024 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use crate::cli::DetailsFilter;
use crate::output::*;
use anyhow::{Context, Error, Result};
use iceoryx2::prelude::*;
use iceoryx2_cli_utils::Filter;
use iceoryx2_cli_utils::Format;

pub fn list(format: Format) -> Result<()> {
let mut services = ServiceList::new();

ipc::Service::list(Config::global_config(), |service| {
services.push(ServiceDescriptor::from(service));
CallbackProgression::Continue
})
.context("failed to retrieve services")?;

services.sort_by_key(|pattern| match pattern {
ServiceDescriptor::PublishSubscribe(name) => (name.clone(), 0),
ServiceDescriptor::Event(name) => (name.clone(), 1),
ServiceDescriptor::Undefined(name) => (name.to_string(), 2),
});

print!("{}", format.as_string(&services)?);

Ok(())
}

pub fn details(service_name: String, filter: DetailsFilter, format: Format) -> Result<()> {
let mut error: Option<Error> = None;

ipc::Service::list(Config::global_config(), |service| {
if service_name == service.static_details.name().to_string() {
let description = ServiceDescription::from(&service);

if filter.matches(&description) {
match format.as_string(&description) {
Ok(output) => {
print!("{}", output);
CallbackProgression::Continue
}
Err(e) => {
error = Some(e);
CallbackProgression::Stop
}
}
} else {
// Filter did not match
CallbackProgression::Continue
}
} else {
// Service name did not match
CallbackProgression::Continue
}
})?;

if let Some(err) = error {
return Err(err);
}
Ok(())
}
36 changes: 36 additions & 0 deletions iceoryx2-cli/iox2-services/src/filter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2024 Contributors to the Eclipse Foundation
//
// See the NOTICE file(s) distributed with this work for additional
// information regarding copyright ownership.
//
// This program and the accompanying materials are made available under the
// terms of the Apache Software License 2.0 which is available at
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license
// which is available at https://opensource.org/licenses/MIT.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

use crate::cli::DetailsFilter;
use crate::cli::MessagingPatternFilter;
use crate::output::ServiceDescription;
use iceoryx2::service::static_config::messaging_pattern::MessagingPattern;
use iceoryx2_cli_utils::Filter;

impl Filter<ServiceDescription> for MessagingPatternFilter {
fn matches(&self, description: &ServiceDescription) -> bool {
matches!(
(self, &description.pattern),
(
MessagingPatternFilter::PublishSubscribe,
MessagingPattern::PublishSubscribe(_)
) | (MessagingPatternFilter::Event, MessagingPattern::Event(_))
| (MessagingPatternFilter::All, _)
)
}
}

impl Filter<ServiceDescription> for DetailsFilter {
fn matches(&self, description: &ServiceDescription) -> bool {
self.pattern.matches(description)
}
}
60 changes: 59 additions & 1 deletion iceoryx2-cli/iox2-services/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,64 @@
//
// SPDX-License-Identifier: Apache-2.0 OR MIT

#[cfg(not(debug_assertions))]
use human_panic::setup_panic;
#[cfg(debug_assertions)]
extern crate better_panic;

mod cli;
mod commands;
mod filter;
mod output;

use clap::CommandFactory;
use clap::Parser;
use cli::Action;
use cli::Cli;
use iceoryx2_bb_log::{set_log_level, LogLevel};
use iceoryx2_cli_utils::Format;

fn main() {
println!("Not implemented. Stay tuned!");
#[cfg(not(debug_assertions))]
{
setup_panic!();
}
#[cfg(debug_assertions)]
{
better_panic::Settings::debug()
.most_recent_first(false)
.lineno_suffix(true)
.verbosity(better_panic::Verbosity::Full)
.install();
}

set_log_level(LogLevel::Warn);

match Cli::try_parse() {
Ok(cli) => {
if let Some(action) = cli.action {
match action {
Action::List => {
if let Err(e) = commands::list(cli.format.unwrap_or(Format::Ron)) {
eprintln!("Failed to list services: {}", e);
}
}
Action::Details(options) => {
if let Err(e) = commands::details(
options.service,
options.filter,
cli.format.unwrap_or(Format::Ron),
) {
eprintln!("Failed to retrieve service details: {}", e);
}
}
}
} else {
Cli::command().print_help().expect("Failed to print help");
}
}
Err(e) => {
eprintln!("{}", e);
}
}
}
Loading

0 comments on commit a9df608

Please sign in to comment.