tansu_cli/
cli.rs

1// Copyright ⓒ 2024-2025 Peter Morgan <peter.james.morgan@gmail.com>
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Tansu CLI
16//!
17//! The CLI is a single statically linked binary that contains:
18//! - Broker
19//! - Cat: produce, validate (if backed by a schema) and fetch messages
20//! - Generator: use fake data generators to produce messages with a rate limit
21//! - Proxy: a Kafka API proxy
22//! - Topic: Topic administration
23
24use std::process;
25
26use crate::Result;
27use clap::{Parser, Subcommand};
28use tansu_sans_io::ErrorCode;
29use tracing::debug;
30
31mod broker;
32mod cat;
33mod generator;
34mod proxy;
35mod topic;
36
37const DEFAULT_BROKER: &str = "tcp://localhost:9092";
38
39#[derive(Clone, Debug, Parser)]
40#[command(name = "tansu", version, about, long_about = None, args_conflicts_with_subcommands = true)]
41pub struct Cli {
42    #[command(subcommand)]
43    command: Option<Command>,
44
45    #[clap(flatten)]
46    broker: broker::Arg,
47}
48
49#[derive(Clone, Debug, Subcommand)]
50enum Command {
51    /// Apache Kafka compatible broker with Avro, JSON, Protobuf schema validation [default if no command supplied]
52    Broker(Box<broker::Arg>),
53
54    /// Easily consume or produce Avro, JSON or Protobuf messages to a topic
55    Cat {
56        #[command(subcommand)]
57        command: cat::Command,
58    },
59
60    /// Traffic Generator for schema backed topics
61    Generator(Box<generator::Arg>),
62
63    /// Apache Kafka compatible proxy
64    Proxy(Box<proxy::Arg>),
65
66    /// Create or delete topics managed by the broker
67    Topic {
68        #[command(subcommand)]
69        command: topic::Command,
70    },
71}
72
73impl Cli {
74    pub async fn main() -> Result<ErrorCode> {
75        debug!(pid = process::id());
76
77        let cli = Cli::parse();
78
79        match cli.command.unwrap_or(Command::Broker(Box::new(cli.broker))) {
80            Command::Broker(arg) => arg
81                .main()
82                .await
83                .inspect(|result| debug!(?result))
84                .inspect_err(|err| debug!(?err)),
85
86            Command::Cat { command } => command.main().await,
87
88            Command::Generator(arg) => arg
89                .main()
90                .await
91                .inspect(|result| debug!(?result))
92                .inspect_err(|err| debug!(?err)),
93
94            Command::Proxy(arg) => tansu_proxy::Proxy::main(
95                arg.listener_url.into_inner(),
96                arg.origin_url.into_inner(),
97                arg.otlp_endpoint_url
98                    .map(|otlp_endpoint_url| otlp_endpoint_url.into_inner()),
99            )
100            .await
101            .map_err(Into::into),
102
103            Command::Topic { command } => command.main().await,
104        }
105    }
106}