relay/
cliapp.rs

1//! This module implements the definition of the command line app.
2
3use std::net::SocketAddr;
4
5use clap::builder::ValueParser;
6use clap::{Arg, ArgAction, ArgGroup, Command, ValueHint};
7use clap_complete::Shell;
8
9pub const VERSION: &str = env!("CARGO_PKG_VERSION");
10pub const ABOUT: &str = "The official Sentry Relay.";
11
12pub fn make_app() -> Command {
13    Command::new("relay")
14        .disable_help_subcommand(true)
15        .subcommand_required(true)
16        .propagate_version(true)
17        .max_term_width(79)
18        .version(VERSION)
19        .about(ABOUT)
20        .arg(
21            Arg::new("config")
22                .long("config")
23                .short('c')
24                .global(true)
25                .value_hint(ValueHint::DirPath)
26                .value_parser(ValueParser::path_buf())
27                .help("The path to the config folder."),
28        )
29        .subcommand(
30            Command::new("run")
31                .about("Run the relay")
32                .after_help(
33                    "This runs the relay in the foreground until it's shut down.  It will bind \
34                    to the port and network interface configured in the config file.",
35                )
36                .arg(
37                    Arg::new("mode")
38                        .long("mode")
39                        .help("The relay mode to set")
40                        .value_parser(["managed", "proxy", "static"]),
41                )
42                .arg(
43                    Arg::new("log_level")
44                        .long("log-level")
45                        .help("The relay log level")
46                        .value_parser(["info", "warn", "error", "debug", "trace"]),
47                )
48                .arg(
49                    Arg::new("log_format")
50                        .long("log-format")
51                        .help("The relay log format")
52                        .value_parser(["auto", "pretty", "simplified", "json"]),
53                )
54                .arg(
55                    Arg::new("secret_key")
56                        .long("secret-key")
57                        .short('s')
58                        .requires("public_key")
59                        .help("The secret key to set"),
60                )
61                .arg(
62                    Arg::new("public_key")
63                        .long("public-key")
64                        .short('p')
65                        .requires("secret_key")
66                        .help("The public key to set"),
67                )
68                .arg(
69                    Arg::new("id")
70                        .long("id")
71                        .short('i')
72                        .help("The relay ID to set"),
73                )
74                .arg(
75                    Arg::new("upstream")
76                        .value_name("url")
77                        .value_hint(ValueHint::Url)
78                        .short('u')
79                        .long("upstream")
80                        .help("The upstream server URL."),
81                )
82                .arg(
83                    Arg::new("upstream_dsn")
84                        .value_name("dsn")
85                        .long("upstream-dsn")
86                        .conflicts_with("upstream")
87                        .help(
88                            "Alternate upstream provided through a Sentry DSN, compatible with the \
89                            SENTRY_DSN environment variable. Key and project of the DSN will be \
90                            ignored.",
91                        ),
92                )
93                .arg(
94                    Arg::new("host")
95                        .value_name("HOST")
96                        .short('H')
97                        .long("host")
98                        .help("The host dns name."),
99                )
100                .arg(
101                    Arg::new("port")
102                        .value_name("PORT")
103                        .short('P')
104                        .long("port")
105                        .help("The server port."),
106                )
107                .arg(
108                    Arg::new("processing")
109                        .long("processing")
110                        .help("Enable processing.")
111                        .action(ArgAction::SetTrue),
112                )
113                .arg(
114                    Arg::new("no_processing")
115                        .long("no-processing")
116                        .help("Disable processing.")
117                        .action(ArgAction::SetTrue),
118                )
119                .group(
120                    ArgGroup::new("processing_group")
121                        .args(["processing", "no_processing"])
122                        .multiple(false),
123                )
124                .arg(
125                    Arg::new("kafka_broker_url")
126                        .value_name("url")
127                        .value_hint(ValueHint::Url)
128                        .long("kafka-broker-url")
129                        .help("Kafka broker URL."),
130                )
131                .arg(
132                    Arg::new("redis_url")
133                        .value_name("url")
134                        .value_hint(ValueHint::Url)
135                        .long("redis-url")
136                        .help("Redis server URL."),
137                )
138                .arg(
139                    Arg::new("source_id")
140                        .long("source-id")
141                        .env("RELAY_SOURCE_ID")
142                        .help("Names the current relay in the outcome source."),
143                )
144                .arg(
145                    Arg::new("shutdown_timeout")
146                        .value_name("seconds")
147                        .long("shutdown-timeout")
148                        .help(
149                            "Maximum number of seconds to wait for pending envelopes on shutdown.",
150                        ),
151                )
152                .arg(
153                    Arg::new("instance")
154                        .long("instance")
155                        .help("The instance type of this Relay."),
156                )
157                .arg(
158                    Arg::new("server_name")
159                        .long("server-name")
160                        .help("The server name reported to Sentry."),
161                ),
162        )
163        .subcommand(
164            Command::new("credentials")
165                .subcommand_required(true)
166                .about("Manage the relay credentials")
167                .after_help(
168                    "This command can be used to manage the stored credentials of \
169                     the relay.  These credentials are used to authenticate with the \
170                     upstream sentry.  A sentry organization trusts a certain public \
171                     key and each relay is identified with a unique relay ID.\n\
172                     \n\
173                     Multiple relays can share the same public/secret key pair for as \
174                     long as they use different relay IDs.  Once a relay (as identified \
175                     by the ID) has signed in with a certain key it cannot be changed \
176                     any more.",
177                )
178                .subcommand(
179                    Command::new("generate")
180                        .about("Generate new credentials")
181                        .after_help(
182                            "This generates new credentials for the relay and stores \
183                             them.  In case the relay already has credentials stored \
184                             this command will error unless the '--overwrite' option \
185                             has been passed.",
186                        )
187                        .arg(
188                            Arg::new("overwrite")
189                                .long("overwrite")
190                                .action(ArgAction::SetTrue)
191                                .help("Overwrite already existing credentials instead of failing"),
192                        )
193                        .arg(
194                            Arg::new("stdout")
195                                .long("stdout")
196                                .action(ArgAction::SetTrue)
197                                .help("Write credentials to stdout instead of credentials.json"),
198                        ),
199                )
200                .subcommand(
201                    Command::new("remove")
202                        .about("Remove credentials")
203                        .after_help(
204                            "This command removes already stored credentials from the \
205                             relay.",
206                        )
207                        .arg(
208                            Arg::new("yes")
209                                .long("yes")
210                                .action(ArgAction::SetTrue)
211                                .help("Do not prompt for confirmation"),
212                        ),
213                )
214                .subcommand(
215                    Command::new("show")
216                        .about("Show currently stored credentials.")
217                        .after_help("This prints out the agent ID and public key."),
218                )
219                .subcommand(
220                    Command::new("set")
221                        .about("Set new credentials")
222                        .after_help(
223                            "Credentials can be stored by providing them on the command \
224                             line.  If just an agent id (or secret/public key pair) is \
225                             provided that part of the credentials are overwritten.  If \
226                             no credentials are stored yet at all and no parameters are \
227                             supplied the command will prompt for the appropriate values.",
228                        )
229                        .arg(
230                            Arg::new("mode")
231                                .long("mode")
232                                .help("The relay mode to set")
233                                .value_parser(["managed", "proxy", "static"]),
234                        )
235                        .arg(
236                            Arg::new("secret_key")
237                                .long("secret-key")
238                                .short('s')
239                                .requires("public_key")
240                                .help("The secret key to set"),
241                        )
242                        .arg(
243                            Arg::new("public_key")
244                                .long("public-key")
245                                .short('p')
246                                .requires("secret_key")
247                                .help("The public key to set"),
248                        )
249                        .arg(
250                            Arg::new("id")
251                                .long("id")
252                                .short('i')
253                                .help("The relay ID to set"),
254                        ),
255                ),
256        )
257        .subcommand(
258            Command::new("config")
259                .about("Manage the relay config")
260                .after_help(
261                    "This command provides basic config management.  It can be \
262                     used primarily to initialize a new relay config and to \
263                     print out the current config.",
264                )
265                .subcommand_required(true)
266                .subcommand(
267                    Command::new("init")
268                        .about("Initialize a new relay config")
269                        .after_help(
270                            "For new relay installations this will guide through \
271                             the initial config process and create the necessary \
272                             files.  It will create an initial config as well as \
273                             set of credentials.",
274                        ),
275                )
276                .subcommand(
277                    Command::new("show")
278                        .about("Show the entire config out for debugging purposes")
279                        .after_help(
280                            "This dumps out the entire config including the values \
281                             which are not in the config file but filled in from \
282                             defaults.  The default output format is YAML but \
283                             a debug format can also be specific which is useful \
284                             to understand how the relay interprets the individual \
285                             values.",
286                        )
287                        .arg(
288                            Arg::new("format")
289                                .short('f')
290                                .long("format")
291                                .value_parser(["debug", "yaml"])
292                                .default_value("yaml")
293                                .help("The output format"),
294                        ),
295                ),
296        )
297        .subcommand(
298            Command::new("generate-completions")
299                .about("Generate shell completion file")
300                .after_help(
301                    "This generates a completions file for the shell of choice. \
302                     The default selection will be an educated guess for the currently \
303                     running shell.",
304                )
305                .arg(
306                    Arg::new("format")
307                        .short('f')
308                        .long("format")
309                        .value_name("SHELL")
310                        .value_parser(clap::value_parser!(Shell))
311                        .help(
312                            "Explicitly pick the shell to generate a completion file \
313                             for. The default is autodetection.",
314                        ),
315                ),
316        )
317        .subcommand(
318            Command::new("healthcheck")
319                .about("Check the health of the relay")
320                .after_help(
321                    "This command checks the health of the relay. It will create \
322                     HTTP request to relay's healthcheck endpoints.",
323                )
324                .arg(
325                    Arg::new("mode")
326                        .long("mode")
327                        .help("The relay health check status to check. Possible values are `live` and `ready`.")
328                        .default_value("live")
329                        .value_parser(clap::builder::PossibleValuesParser::new(["live", "ready"]))
330                        .required(false),
331                )
332                .arg(
333                    Arg::new("timeout")
334                        .long("timeout")
335                        .help("The timeout in seconds to wait for the healthcheck")
336                        .default_value("30")
337                        .value_parser(clap::value_parser!(u64))
338                        .required(false),
339                )
340                .arg(
341                    Arg::new("addr")
342                        .long("addr")
343                        .help("Address where Relay is running. Defaults to the Relay configuration.")
344                        .value_parser(clap::value_parser!(SocketAddr))
345                        .required(false),
346                )
347        )
348}