Skip to content

Architecture Overview

The dapcli is a headless CLI built on Click, designed to manage the Dell Automation Platform. The architecture centers on a single entry point that constructs a shared Invocation context from global flags, which is then passed to subcommands. This context resolves configuration, credentials, and output preferences in one place, ensuring consistent behavior across generic REST verbs and specialized plugin engines. The CLI supports extensibility through a kubectl-style mechanism that delegates unknown commands to external dap-* executables on the system PATH.

The CLI entry point is the cli function in src/dap/cli.py, registered as the dap console script 1. It uses a Click group with a custom ExtensibleGroup class to support both built-in commands and external plugins 2. Commands are registered by adding sub-packages that expose their own commands, which are then added to the main group. The entry point handles global options such as output format, context selection, namespace, and debugging flags like --dry-run and --curl.

diagram

The Invocation class in src/dap/rest/context.py is the central object for per-invocation state 3. It is built once from the root group’s global flags and stashed on Click’s ctx.obj. This object contains the resolved configuration, credential store, output preferences, and flags for debugging. Subcommands pull the necessary configuration and a ready-to-use RestClient from this context, ensuring that auth resolution and flag plumbing are handled in a single location. The Invocation.build method loads the configuration and initializes the credential store.

The CLI provides generic REST verbs for interacting with the DAP portal and orchestrator 2. These are built using build_portal_group() and build_orchestrator_group() functions. The Invocation class maps CLI components like portal, neo, dpc, and ai to either the portal or orchestrator registry keys 3. The client_for method in Invocation builds an authenticated RestClient for a given component, handling server and token overrides if provided. If overrides are not provided, it resolves the binding from the configuration and uses the TokenProvider to obtain a bearer token.

The CLI supports a kubectl-style extension mechanism for third-party plugins 4. The ExtensibleGroup class in src/dap/rest/extension.py falls back to executing dap-* plugins found on the system PATH for unknown commands. When an unknown command is encountered, the CLI searches for an executable with the dap- prefix. If found, it executes the plugin with the remaining arguments passed through verbatim. The extension command provides a way to list discovered extensions.

The CLI uses a custom DapError exception type in src/dap/errors.py for user-facing errors 5. This exception is a subclass of click.ClickException and provides a clean, actionable message without showing a Python traceback. It is used for failures that the operator is responsible for resolving, such as missing configuration or bad credentials. Unexpected bugs are allowed to raise normally to show a traceback.