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