bindcar/cli.rs
1// Copyright (c) 2025 Erick Bourgeois, firestoned
2// SPDX-License-Identifier: MIT
3
4//! CLI argument parsing for the bindcar binary.
5//!
6//! bindcar supports two operating modes selected via subcommand:
7//!
8//! - **`run`** (default) — sidecar mode: runs alongside a local BIND9 instance inside a
9//! Kubernetes pod, communicating over shared volumes and local RNDC.
10//!
11//! - **`drone`** — standalone mode: runs as an independent process on a bare-metal or VM
12//! host, managing a remote BIND9 instance. Authentication is performed via the
13//! Kubernetes TokenReview API using explicit credentials (`KUBE_API_SERVER`,
14//! `KUBE_TOKEN_PATH`, `KUBE_CA_CERT_PATH`).
15//!
16//! When no subcommand is given, `run` is the default, preserving backwards compatibility
17//! for existing deployments and process supervisors that call `bindcar` directly.
18
19use clap::{Parser, Subcommand};
20
21/// bindcar — HTTP REST API for managing BIND9 zones via RNDC
22#[derive(Parser, Debug)]
23#[command(version, about, long_about = None)]
24pub struct Cli {
25 /// Enable debug-level logging (overrides RUST_LOG)
26 #[arg(long, short = 'd', global = true)]
27 pub debug: bool,
28
29 /// Acknowledge and allow starting with weak/disabled authentication on a
30 /// non-loopback interface. Without this (or a loopback bind / real auth),
31 /// bindcar refuses to start to avoid silently exposing an unauthenticated API.
32 #[arg(long, global = true)]
33 pub i_know_this_is_insecure: bool,
34
35 #[command(subcommand)]
36 pub command: Option<Commands>,
37}
38
39/// bindcar operating modes
40#[derive(Subcommand, Debug, PartialEq, Clone)]
41pub enum Commands {
42 /// Run as a Kubernetes sidecar alongside a local BIND9 instance (default)
43 Run,
44 /// Run standalone, managing a remote BIND9 instance from outside the cluster
45 Drone,
46}
47
48impl Cli {
49 /// Return the resolved command, defaulting to [`Commands::Run`] when no subcommand
50 /// was given. This preserves backwards compatibility: `bindcar` with no args
51 /// behaves identically to `bindcar run`.
52 pub fn resolved_command(&self) -> &Commands {
53 self.command.as_ref().unwrap_or(&Commands::Run)
54 }
55}