# Component: CLI ## Purpose The CLI is a standalone command-line tool for scripting and automating administrative operations against the ScadaLink central cluster. It connects to the ManagementActor via Akka.NET ClusterClient — it does not join the cluster as a full member and does not use HTTP/REST. The CLI provides the same administrative capabilities as the Central UI, enabling automation, batch operations, and integration with CI/CD pipelines. ## Location Standalone executable, not part of the Host binary. Deployed on any Windows machine with network access to the central cluster. `src/ScadaLink.CLI/` ## Responsibilities - Parse command-line arguments and dispatch to the appropriate management operation. - Authenticate the user via LDAP credentials and include identity in every message sent to the ManagementActor. - Connect to the central cluster via Akka.NET ClusterClient using configured contact points. - Send management messages to the ManagementActor and display structured responses. - Support both JSON and human-readable table output formats. ## Technology - **Argument parsing**: `System.CommandLine` library for command/subcommand/option parsing with built-in help generation. - **Transport**: Akka.NET `ClusterClient` connecting to `ClusterClientReceptionist` on the central cluster. The CLI does not join the cluster — it is a lightweight external client. - **Serialization**: Message contracts from Commons (`Messages/Management/`), same as ManagementActor expects. ## Authentication The CLI authenticates the user against LDAP/AD before any operation: 1. The user provides credentials via `--username` / `--password` options, or is prompted interactively if omitted. 2. The CLI performs a direct LDAP bind against the configured LDAP server (same mechanism as the Central UI login). 3. On successful bind, the CLI queries group memberships to determine roles and permitted sites. 4. Every message sent to the ManagementActor includes the `AuthenticatedUser` envelope with the user's identity, roles, and site permissions. 5. Credentials are not stored or cached between invocations. Each CLI invocation requires fresh authentication. LDAP connection settings are read from the CLI configuration (see Configuration section). ## Connection The CLI uses Akka.NET ClusterClient to connect to the central cluster: - **Contact points**: One or more seed node addresses for the ClusterClientReceptionist. The CLI sends an initial contact to these addresses; the receptionist responds with the current set of cluster nodes hosting the ManagementActor. - **No cluster membership**: The CLI does not join the Akka.NET cluster. It is an external process that communicates via the ClusterClient protocol. - **Failover**: If the active central node fails over, ClusterClient transparently reconnects to the new active node via the receptionist. In-flight commands may time out and need to be retried. ## Command Structure The CLI uses a hierarchical subcommand structure mirroring the Management Service message groups: ``` scadalink [options] ``` ### Template Commands ``` scadalink template list [--format json|table] scadalink template get [--format json|table] scadalink template create --name [--parent ] --file scadalink template update --file scadalink template delete scadalink template validate scadalink template diff ``` ### Instance Commands ``` scadalink instance list [--site ] [--area ] [--format json|table] scadalink instance get [--format json|table] scadalink instance create --template --site --code [--area ] scadalink instance set-overrides --file scadalink instance bind-connections --file scadalink instance assign-area --area scadalink instance enable scadalink instance disable scadalink instance delete ``` ### Site Commands ``` scadalink site list [--format json|table] scadalink site get [--format json|table] scadalink site create --name --id scadalink site update --file scadalink site delete scadalink site area list scadalink site area create --name [--parent ] scadalink site area delete --name ``` ### Deployment Commands ``` scadalink deploy instance scadalink deploy artifacts [--site ] [--type ] scadalink deploy status [--format json|table] ``` ### Data Connection Commands ``` scadalink data-connection list [--format json|table] scadalink data-connection get [--format json|table] scadalink data-connection create --file scadalink data-connection update --file scadalink data-connection delete scadalink data-connection assign --site scadalink data-connection unassign --site ``` ### External System Commands ``` scadalink external-system list [--format json|table] scadalink external-system get [--format json|table] scadalink external-system create --file scadalink external-system update --file scadalink external-system delete ``` ### Notification Commands ``` scadalink notification list [--format json|table] scadalink notification get [--format json|table] scadalink notification create --file scadalink notification update --file scadalink notification delete scadalink notification smtp get [--format json|table] scadalink notification smtp update --file ``` ### Security Commands ``` scadalink security api-key list [--format json|table] scadalink security api-key create --name scadalink security api-key enable scadalink security api-key disable scadalink security api-key delete scadalink security role-mapping list [--format json|table] scadalink security role-mapping create --group --role [--site ] scadalink security role-mapping delete --group --role ``` ### Audit Log Commands ``` scadalink audit-log query [--user ] [--entity-type ] [--from ] [--to ] [--format json|table] ``` ### Health Commands ``` scadalink health summary [--format json|table] scadalink health site [--format json|table] ``` ## Configuration Configuration is resolved in the following priority order (highest wins): 1. **Command-line options**: `--contact-points`, `--username`, `--password`, `--format`. 2. **Environment variables**: - `SCADALINK_CONTACT_POINTS` — Comma-separated list of central cluster contact point addresses (e.g., `akka.tcp://ScadaLink@central1:8081,akka.tcp://ScadaLink@central2:8081`). - `SCADALINK_LDAP_SERVER` — LDAP server address. - `SCADALINK_LDAP_PORT` — LDAP port (default: 636 for LDAPS). - `SCADALINK_FORMAT` — Default output format (`json` or `table`). 3. **Configuration file**: `~/.scadalink/config.json` — Persistent defaults for contact points, LDAP settings, and output format. ### Configuration File Format ```json { "contactPoints": [ "akka.tcp://ScadaLink@central1:8081", "akka.tcp://ScadaLink@central2:8081" ], "ldap": { "server": "ad.example.com", "port": 636, "useTls": true }, "defaultFormat": "json" } ``` ## Output Formats - **JSON** (default): Machine-readable JSON output to stdout. Suitable for piping to `jq` or processing in scripts. Errors are written to stderr as JSON objects with `error` and `code` fields. - **Table** (`--format table` or `--table`): Human-readable tabular output with aligned columns. Suitable for interactive use. ## Exit Codes | Code | Meaning | |------|---------| | 0 | Success | | 1 | General error (command failed) | | 2 | Authentication failure (LDAP bind failed) | | 3 | Authorization failure (insufficient role) | | 4 | Connection failure (cannot reach central cluster) | | 5 | Validation failure (e.g., template validation errors) | ## Error Handling - **Connection failure**: If the CLI cannot establish a ClusterClient connection within a timeout (default 10 seconds), it exits with code 4 and a descriptive error message. - **Command timeout**: If the ManagementActor does not respond within 30 seconds (configurable), the command fails with a timeout error. - **Authentication failure**: If the LDAP bind fails, the CLI exits with code 2 before sending any commands. - **Authorization failure**: If the ManagementActor returns an Unauthorized response, the CLI exits with code 3. ## Dependencies - **Commons**: Message contracts (`Messages/Management/`), shared types. - **System.CommandLine**: Command-line argument parsing. - **Akka.NET (Akka.Cluster.Tools)**: ClusterClient for communication with the central cluster. - **LDAP client library**: For direct LDAP bind authentication (same approach as Security & Auth component). ## Interactions - **Management Service (ManagementActor)**: The CLI's sole runtime dependency. All operations are sent as messages to the ManagementActor via ClusterClient. - **Security & Auth**: The CLI performs LDAP authentication independently (same LDAP server, same bind mechanism) and passes the authenticated identity to the ManagementActor. The ManagementActor enforces authorization. - **LDAP/Active Directory**: Direct bind for user authentication before any operation.