Skip to content

Creating a command


We will create a command dda agent-release data that shows Agent release information.

Structure

If you run the root dda command, you'll notice that the subcommands are directories within the src/dda/cli directory:

src/dda/cli
├── build
├── bzl
├── config
├── env
├── info
├── inv
├── self
├── tools
└── validate

Every command and command group is defined as a Python package with an __init__.py file containing a function cmd that represents the command or command group. A command is a function decorated with @dynamic_command that performs a user-requested action and a command group is a function decorated with @dynamic_group that groups commands together.

Group

First, let's create the dda agent-release command group:

from __future__ import annotations

from dda.cli.base import dynamic_group


@dynamic_group(short_help="Agent release-related commands")
def cmd() -> None:
    """
    Commands related to managing Agent releases.
    """

Note

Directory names containing multiple words must be separated by underscores. For example, the agent-release command group is located in the src/dda/cli/agent_release directory.

Now running the dda command will show the agent-release command group:

$ dda
...
╭─ Commands ────────────────────────────────────╮
│ agent-release  Agent release-related commands │
...

Initial command

Next, let's create the initial dda agent-release data command and have it display a message:

from __future__ import annotations

from typing import TYPE_CHECKING

from dda.cli.base import dynamic_command, pass_app

if TYPE_CHECKING:
    from dda.cli.application import Application


@dynamic_command(
    short_help="Show Agent release data",
)
@pass_app
def cmd(app: Application) -> None:
    """
    Show Agent release data.
    """
    app.display("Agent release data")

Now running the dda agent-release data command will show:

$ dda agent-release data
Agent release data

Requiring dependencies

Fetching the Agent's release.json file requires using an HTTP client. Add the http feature to the command to make sure dependencies such as httpx are available:

from __future__ import annotations

from typing import TYPE_CHECKING

from dda.cli.base import dynamic_command, pass_app

if TYPE_CHECKING:
    from dda.cli.application import Application


@dynamic_command(
    short_help="Show Agent release data",
    features=["http"],
)
@pass_app
def cmd(app: Application) -> None:
    """
    Show Agent release data.
    """
    import httpx

    base = "https://raw.githubusercontent.com"
    repo = "DataDog/datadog-agent"
    branch = "main"
    path = "release.json"
    with app.status("Fetching Agent release data"):
        response = httpx.get(f"{base}/{repo}/{branch}/{path}")

    response.raise_for_status()
    app.display_table(response.json())

Running the command will now show the Agent release data:

$ dda agent-release data
┌───────────────────┬────────────────┐
│ base_branch       │ main           │
│ current_milestone │ 7.66.0         │
│ last_stable       │ ┌───┬────────┐ │
│                   │ │ 6 │ 6.53.1 │ │
│                   │ │ 7 │ 7.64.3 │ │
│                   │ └───┴────────┘ │
...

Using feature flags

You can guard behavior behind feature flags using the app.features manager. It evaluates a remote flag for the current user/machine with a default fallback.

Update the command to check a flag before performing the network request:

from __future__ import annotations

from typing import TYPE_CHECKING

from dda.cli.base import dynamic_command, pass_app

if TYPE_CHECKING:
    from dda.cli.application import Application


@dynamic_command(
    short_help="Show Agent release data",
    features=["http"],
)
@pass_app
def cmd(app: Application) -> None:
    """
    Show Agent release data.
    """
    # Check a feature flag to enable this command's behavior
    # Replace "agent-release-enabled" with your flag key
    enabled = app.features.enabled(
        "agent-release-enabled",
        default=True,
        scopes={"module": "agent-release"},
    )
    if not enabled:
        app.display_warning("This command is currently disabled by feature flag.")
        return

    import httpx

    base = "https://raw.githubusercontent.com"
    repo = "DataDog/datadog-agent"
    branch = "main"
    path = "release.json"
    with app.status("Fetching Agent release data"):
        response = httpx.get(f"{base}/{repo}/{branch}/{path}")

    response.raise_for_status()
    app.display_table(response.json())

Note

app.features.enabled(key, default, scopes) returns the evaluated value for key, or default if the flag is not found. The client automatically includes base context like platform, CI, environment, and user; you can add scopes to refine targeting.