fluvio_extension_common/
lib.rs1use serde::{Deserialize, Serialize};
2pub mod output;
3mod common;
4
5#[cfg(feature = "target")]
6pub mod tls;
7
8#[cfg(feature = "installation")]
9pub mod installation;
10
11pub use common::*;
12pub use crate::output::Terminal;
13use fluvio_index::{PackageId, MaybeVersion};
14
15pub const COMMAND_TEMPLATE: &str = "{about}
16
17{usage}
18
19{all-args}
20";
21
22#[macro_export]
23macro_rules! t_print {
24 ($out:expr,$($arg:tt)*) => ( $out.print(&format!($($arg)*)))
25}
26
27#[macro_export]
28macro_rules! t_println {
29 ($out:expr,$($arg:tt)*) => ( $out.println(&format!($($arg)*)))
30}
31
32#[macro_export]
33macro_rules! t_print_cli_err {
34 ($out:expr,$x:expr) => {
35 t_println!($out, "\x1B[1;31merror:\x1B[0m {}", $x);
36 };
37}
38
39#[derive(Debug, Serialize, Deserialize)]
44pub struct FluvioExtensionMetadata {
45 #[serde(alias = "command")]
47 pub title: String,
48 #[serde(default)]
52 pub package: Option<PackageId<MaybeVersion>>,
53 pub description: String,
55 pub version: semver::Version,
57}
58
59#[derive(Debug)]
60pub struct PrintTerminal {}
61
62impl PrintTerminal {
63 pub fn new() -> Self {
64 Self {}
65 }
66}
67
68impl Default for PrintTerminal {
69 fn default() -> Self {
70 Self::new()
71 }
72}
73
74impl Terminal for PrintTerminal {
75 fn print(&self, msg: &str) {
76 print!("{msg}");
77 }
78
79 fn println(&self, msg: &str) {
80 println!("{msg}");
81 }
82}
83
84#[cfg(feature = "target")]
85pub mod target {
86 use std::io::Error as IoError;
87 use std::convert::TryInto;
88 use clap::Parser;
89
90 use anyhow::Result;
91
92 use fluvio::FluvioClusterConfig;
93 use fluvio::FluvioError;
94 use fluvio::Fluvio;
95 use fluvio::config::ConfigFile;
96 use crate::tls::TlsClientOpt;
97
98 #[derive(thiserror::Error, Debug)]
99 pub enum TargetError {
100 #[error(transparent)]
101 IoError(#[from] IoError),
102 #[error("Fluvio client error")]
103 ClientError(#[from] FluvioError),
104 #[error("Invalid argument: {0}")]
105 InvalidArg(String),
106 #[error("Unknown error: {0}")]
107 Other(String),
108 }
109
110 impl TargetError {
111 pub fn invalid_arg(reason: impl Into<String>) -> Self {
112 Self::InvalidArg(reason.into())
113 }
114 }
115
116 #[derive(Debug, Parser, Default, Clone)]
118 pub struct ClusterTarget {
119 #[arg(short = 'c', long, value_name = "host:port")]
121 pub cluster: Option<String>,
122
123 #[clap(flatten)]
124 pub tls: TlsClientOpt,
125
126 #[arg(short = 'P', long, value_name = "profile")]
127 pub profile: Option<String>,
128 }
129
130 impl ClusterTarget {
131 pub async fn connect(self) -> Result<Fluvio> {
133 let fluvio_config = self.load()?;
134 Fluvio::connect_with_config(&fluvio_config).await
135 }
136
137 pub fn load(self) -> Result<FluvioClusterConfig> {
139 let tls = self.tls.try_into()?;
140
141 use fluvio::config::TlsPolicy::*;
142 match (self.profile, self.cluster) {
143 (Some(_profile), Some(_cluster)) => Err(TargetError::invalid_arg(
145 "cluster addr is not valid when profile is used",
146 )
147 .into()),
148 (Some(profile), _) => {
149 if let Anonymous | Verified(_) = tls {
151 return Err(TargetError::invalid_arg(
152 "tls is not valid when profile is is used",
153 )
154 .into());
155 }
156
157 let cluster = FluvioClusterConfig::load_with_profile(&profile)?
158 .ok_or_else(|| IoError::other("Cluster not found for profile"))?;
159 Ok(cluster.clone())
160 }
161 (None, Some(cluster)) => {
162 let cluster = FluvioClusterConfig::new(cluster).with_tls(tls);
163 Ok(cluster)
164 }
165 (None, None) => {
166 if let Anonymous | Verified(_) = tls {
168 return Err(TargetError::invalid_arg(
169 "tls is only valid if cluster addr is used",
170 )
171 .into());
172 }
173
174 let config_file = ConfigFile::load(None)?;
176 let cluster = config_file.config().current_cluster()?;
177 Ok(cluster.clone())
178 }
179 }
180 }
181 }
182}