Skip to main content

link_assistant_router/cli/
configure.rs

1//! `router configure <client>` — the one name for permanent client setup.
2//!
3//! Pointing a client at the router permanently is the first thing an operator
4//! does after standing a deployment up, and it had no single name. Two
5//! commands wrote the same file and disagreed on almost everything else: the
6//! address (`clients setup` used this CLI's own `--host`/`--port` default even
7//! with a server selected), the credential (`with --global` stored none and
8//! told the user to go set an environment variable), how to reverse it, and
9//! which clients it worked for. `configure` exists in the codebase — it is
10//! what both paths call — but was not a name a user could type (issue #296).
11
12use clap::Args;
13
14use super::AuthTarget;
15use crate::clients::ClientKind;
16
17/// Point a client at the router permanently.
18#[derive(Clone, Debug, Args)]
19pub struct ConfigureArgs {
20    /// Client to configure. Omit when `--all` is given.
21    #[arg(value_enum, required_unless_present = "all")]
22    pub client: Option<ClientKind>,
23    /// Configure every client this machine has that can be configured.
24    ///
25    /// Clients whose vendor gates prevent it are skipped and named in the
26    /// summary rather than failing the run — a workstation being pointed at a
27    /// deployment wants the ones that work.
28    #[arg(long, conflicts_with = "client")]
29    pub all: bool,
30    /// Restore the exact configuration saved by a previous `configure`.
31    ///
32    /// The restore is hash-verified: an edit made after `configure` is
33    /// preserved rather than overwritten.
34    #[arg(long)]
35    pub undo: bool,
36    #[command(flatten)]
37    pub target: AuthTarget,
38    /// Existing router token to configure instead of minting one.
39    ///
40    /// Prefer `--token-stdin` or `LINK_ASSISTANT_ROUTER_TOKEN` over argv,
41    /// which is visible in shell history and process listings.
42    #[arg(long, hide_env_values = true, conflicts_with = "token_stdin")]
43    pub token: Option<String>,
44    /// Read an existing router token as one line from standard input.
45    #[arg(long, conflicts_with = "token")]
46    pub token_stdin: bool,
47    /// Lifetime of an automatically minted token, in hours.
48    ///
49    /// A year by default, because this is the permanent path: a credential
50    /// that lapses next week makes "configured" mean "configured until
51    /// Tuesday". Re-run `configure` to renew it.
52    #[arg(long, default_value_t = 8760)]
53    pub ttl_hours: i64,
54}
55
56impl ConfigureArgs {
57    /// The clients this invocation acts on.
58    #[must_use]
59    pub fn clients(&self) -> Vec<ClientKind> {
60        self.client
61            .map_or_else(|| ClientKind::ALL.to_vec(), |client| vec![client])
62    }
63}