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}