refactor(cli): split decnet/cli.py monolith into decnet/cli/ package
The 1,878-line cli.py held every Typer command plus process/HTTP helpers and mode-gating logic. Split into one module per command using a register(app) pattern so submodules never import app at module scope, eliminating circular-import risk. - utils.py: process helpers, _http_request, _kill_all_services, console, log - gating.py: MASTER_ONLY_* sets, _require_master_mode, _gate_commands_by_mode - deploy.py: deploy + _deploy_swarm (tightly coupled) - lifecycle.py: status, teardown, redeploy - workers.py: probe, collect, mutate, correlate - inventory.py, swarm.py, db.py, and one file per remaining command __init__.py calls register(app) on each module then runs the mode gate last, and re-exports the private symbols tests patch against (_db_reset_mysql_async, _kill_all_services, _require_master_mode, etc.). Test patches retargeted to the submodule where each name now resolves. Enroll-bundle tarball test updated to assert decnet/cli/__init__.py. No behavioral change.
This commit is contained in:
80
decnet/cli/__init__.py
Normal file
80
decnet/cli/__init__.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""
|
||||
DECNET CLI — entry point for all commands.
|
||||
|
||||
Usage:
|
||||
decnet deploy --mode unihost --deckies 5 --randomize-services
|
||||
decnet status
|
||||
decnet teardown [--all | --id decky-01]
|
||||
decnet services
|
||||
|
||||
Layout: each command module exports ``register(app)`` which attaches its
|
||||
commands to the passed Typer app. ``__init__.py`` builds the root app,
|
||||
calls every module's ``register`` in order, then runs the master-only
|
||||
gate. The gate must fire LAST so it sees the fully-populated dispatch
|
||||
table before filtering.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import typer
|
||||
|
||||
from . import (
|
||||
agent,
|
||||
api,
|
||||
db,
|
||||
deploy,
|
||||
forwarder,
|
||||
inventory,
|
||||
lifecycle,
|
||||
listener,
|
||||
profiler,
|
||||
sniffer,
|
||||
swarm,
|
||||
swarmctl,
|
||||
updater,
|
||||
web,
|
||||
workers,
|
||||
)
|
||||
from .gating import _gate_commands_by_mode
|
||||
from .utils import console as console, log as log
|
||||
|
||||
app = typer.Typer(
|
||||
name="decnet",
|
||||
help="Deploy a deception network of honeypot deckies on your LAN.",
|
||||
no_args_is_help=True,
|
||||
)
|
||||
|
||||
# Order matches the old flat layout so `decnet --help` reads the same.
|
||||
for _mod in (
|
||||
api, swarmctl, agent, updater, listener, forwarder,
|
||||
swarm,
|
||||
deploy, lifecycle, workers, inventory,
|
||||
web, profiler, sniffer, db,
|
||||
):
|
||||
_mod.register(app)
|
||||
|
||||
_gate_commands_by_mode(app)
|
||||
|
||||
# Backwards-compat re-exports. Tests and third-party tooling import these
|
||||
# directly from ``decnet.cli``; the refactor must keep them resolvable.
|
||||
from .db import _db_reset_mysql_async # noqa: E402,F401
|
||||
from .gating import ( # noqa: E402,F401
|
||||
MASTER_ONLY_COMMANDS,
|
||||
MASTER_ONLY_GROUPS,
|
||||
_agent_mode_active,
|
||||
_require_master_mode,
|
||||
)
|
||||
from .utils import ( # noqa: E402,F401
|
||||
_daemonize,
|
||||
_http_request,
|
||||
_is_running,
|
||||
_kill_all_services,
|
||||
_pid_dir,
|
||||
_service_registry,
|
||||
_spawn_detached,
|
||||
_swarmctl_base_url,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
app()
|
||||
Reference in New Issue
Block a user