Skip to main content

pact_broker_cli/
main.rs

1pub mod cli;
2pub use cli::build_cli;
3
4use clap::ArgMatches;
5use clap::error::ErrorKind;
6use clap_complete::{Shell, generate_to};
7use tracing::span;
8
9use std::process::ExitCode;
10use std::str::FromStr;
11
12use crate::cli::otel::OtelConfig;
13use crate::cli::otel::init_logging;
14pub fn handle_matches(
15    matches: &Result<ArgMatches, clap::Error>,
16    raw_args: Option<Vec<String>>,
17) -> Result<(), ExitCode> {
18    let raw_args = if let Some(args) = raw_args {
19        args
20    } else {
21        // `env::args` panics on non-UTF-8 input before clap can report it.
22        std::env::args_os()
23            .skip(1)
24            .map(|arg| arg.to_string_lossy().into_owned())
25            .collect()
26    };
27    match matches {
28        Ok(results) => {
29            let (
30                enable_otel,
31                enable_otel_logs,
32                enable_otel_traces,
33                otel_exporter,
34                otel_exporter_endpoint,
35                otel_exporter_protocol,
36                log_level,
37            ) = match &matches {
38                Ok(m) => (
39                    m.get_flag("enable-otel"),
40                    m.get_flag("enable-otel-logs"),
41                    m.get_flag("enable-otel-traces"),
42                    m.get_one::<String>("otel-exporter").map(|s| {
43                        s.split(',')
44                            .map(|v| v.trim().to_string())
45                            .collect::<Vec<String>>()
46                    }),
47                    m.get_one::<String>("otel-exporter-endpoint"),
48                    m.get_one::<String>("otel-exporter-protocol"),
49                    m.get_one::<String>("log-level")
50                        .and_then(|lvl| lvl.parse::<tracing::Level>().ok()),
51                ),
52                Err(_) => (false, false, false, None, None, None, None),
53            };
54            let otel_config = OtelConfig {
55                enable_otel: Some(enable_otel),
56                enable_logs: Some(enable_otel_logs),
57                enable_traces: Some(enable_otel_traces),
58                exporter: otel_exporter,
59                endpoint: otel_exporter_endpoint.cloned(),
60                protocol: otel_exporter_protocol.cloned(),
61                log_level,
62            };
63            let tracer_provider = init_logging(otel_config);
64            let _tracer_provider_dropper;
65            if let Some(tp) = tracer_provider {
66                _tracer_provider_dropper = crate::cli::otel::TracerProviderDropper(tp);
67            }
68
69            let span = if tracing::Span::current().is_none() {
70                span!(tracing::Level::INFO, "pact-broker-cli")
71            } else {
72                tracing::Span::current()
73            };
74            let _enter = span.enter();
75
76            match results.subcommand() {
77                Some(("pactflow", args)) => match cli::pactflow_client::run(args) {
78                    Ok(_) => Ok(()),
79                    Err(error) => Err(ExitCode::from(error as u8)),
80                },
81                Some(("completions", args)) => {
82                    generate_completions(args);
83                    Ok(())
84                }
85                _ => match cli::pact_broker_client::run(results, raw_args) {
86                    Ok(_) => Ok(()),
87                    Err(error) => Err(ExitCode::from(error as u8)),
88                },
89            }
90        }
91        Err(err) => match err.kind() {
92            ErrorKind::DisplayHelp => {
93                let _ = err.print();
94                Ok(())
95            }
96            ErrorKind::DisplayVersion => {
97                let _ = err.print();
98                Ok(())
99            }
100            ErrorKind::DisplayHelpOnMissingArgumentOrSubcommand => {
101                let _ = err.print();
102                Ok(())
103            }
104            _ => err.exit(),
105        },
106    }
107}
108
109fn generate_completions(args: &ArgMatches) {
110    let shell = args
111        .get_one::<String>("shell")
112        .expect("a shell is required");
113    let out_dir = args
114        .get_one::<String>("dir")
115        .expect("a directory is expected")
116        .to_string();
117    let mut cmd = cli::build_cli();
118    let shell_enum = Shell::from_str(shell).unwrap();
119    let _ = generate_to(
120        shell_enum,
121        &mut cmd,
122        "pact-broker-cli".to_string(),
123        &out_dir,
124    );
125    println!(
126        "ℹ️  {} shell completions for pact-broker-cli written to {}",
127        shell_enum, out_dir
128    );
129}