Skip to main content

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