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
// Copyright (c) 2025 Erick Bourgeois, firestoned
// SPDX-License-Identifier: MIT
//! CLI argument parsing for the bindcar binary.
//!
//! bindcar supports two operating modes selected via subcommand:
//!
//! - **`run`** (default) — sidecar mode: runs alongside a local BIND9 instance inside a
//! Kubernetes pod, communicating over shared volumes and local RNDC.
//!
//! - **`drone`** — standalone mode: runs as an independent process on a bare-metal or VM
//! host, managing a remote BIND9 instance. Authentication is performed via the
//! Kubernetes TokenReview API using explicit credentials (`KUBE_API_SERVER`,
//! `KUBE_TOKEN_PATH`, `KUBE_CA_CERT_PATH`).
//!
//! When no subcommand is given, `run` is the default, preserving backwards compatibility
//! for existing deployments and process supervisors that call `bindcar` directly.
use clap::{Parser, Subcommand};
/// bindcar — HTTP REST API for managing BIND9 zones via RNDC
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Cli {
/// Enable debug-level logging (overrides RUST_LOG)
#[arg(long, short = 'd', global = true)]
pub debug: bool,
/// Acknowledge and allow starting with weak/disabled authentication on a
/// non-loopback interface. Without this (or a loopback bind / real auth),
/// bindcar refuses to start to avoid silently exposing an unauthenticated API.
#[arg(long, global = true)]
pub i_know_this_is_insecure: bool,
/// PEM certificate chain (leaf first) for the HTTPS listener.
///
/// Must be given together with `--tls-key`. When neither is set bindcar
/// serves plaintext HTTP, preserving existing behaviour.
#[arg(long, env = "BIND_TLS_CERT", global = true)]
pub tls_cert: Option<String>,
/// PEM private key for the HTTPS listener (PKCS#8, PKCS#1 or SEC1).
///
/// Must be given together with `--tls-cert`.
#[arg(long, env = "BIND_TLS_KEY", global = true)]
pub tls_key: Option<String>,
/// How often to re-check the TLS certificate files for a renewal, in seconds.
///
/// Defaults to 60. Set to `0` to disable reloading entirely, restoring the
/// startup-only behaviour of earlier releases. A renewal that fails to load
/// never interrupts service: the previous certificate keeps serving and the
/// next poll retries.
#[arg(long, env = "BIND_TLS_RELOAD_INTERVAL", global = true)]
pub tls_reload_interval: Option<u64>,
/// PEM CA bundle used to verify client certificates.
///
/// Setting this turns on mutual TLS: a client presenting no certificate, or
/// one not chaining to this bundle, is rejected at the TLS handshake. In the
/// bindy topology both ends have stable in-cluster identities, so mTLS is a
/// better fit than server-only TLS and keeps the bearer token off the wire.
#[arg(long, env = "BIND_TLS_CLIENT_CA", global = true)]
pub tls_client_ca: Option<String>,
#[command(subcommand)]
pub command: Option<Commands>,
}
/// bindcar operating modes
#[derive(Subcommand, Debug, PartialEq, Clone)]
pub enum Commands {
/// Run as a Kubernetes sidecar alongside a local BIND9 instance (default)
Run,
/// Run standalone, managing a remote BIND9 instance from outside the cluster
Drone,
}
impl Cli {
/// Return the resolved command, defaulting to [`Commands::Run`] when no subcommand
/// was given. This preserves backwards compatibility: `bindcar` with no args
/// behaves identically to `bindcar run`.
pub fn resolved_command(&self) -> &Commands {
self.command.as_ref().unwrap_or(&Commands::Run)
}
}