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