Files
scadalink-design/docs/requirements/Component-CLI.md
Joseph Doherty d91aa83665 refactor(docs): move requirements and test infra docs into docs/ subdirectories
Organize documentation by moving requirements (HighLevelReqs, Component-*,
lmxproxy_protocol) to docs/requirements/ and test infrastructure docs to
docs/test_infra/. Updates all cross-references in README, CLAUDE.md,
infra/README, component docs, and 23 plan files.
2026-03-21 01:11:35 -04:00

11 KiB

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 Central Host's HTTP Management API (POST /management), which dispatches commands to the ManagementActor. Authentication and role resolution are handled server-side — the CLI sends credentials via HTTP Basic Auth. 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 machine with HTTP access to a central node.

src/ScadaLink.CLI/

Responsibilities

  • Parse command-line arguments and dispatch to the appropriate management operation.
  • Send HTTP requests to the Central Host's Management API endpoint with Basic Auth credentials.
  • Display structured responses from the Management API.
  • 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: HTTP client connecting to the Central Host's POST /management endpoint. Authentication is via HTTP Basic Auth — the server performs LDAP bind and role resolution.
  • Serialization: Commands serialized as JSON with a type discriminator (command field). Message contracts from Commons define the command types.

Authentication

The CLI sends user credentials to the Management API via HTTP Basic Auth:

  1. The user provides credentials via --username / --password options.
  2. On each request, the CLI encodes credentials as a Basic Auth header and sends them with the command.
  3. The server performs LDAP authentication, group lookup, and role resolution — the CLI does not communicate with LDAP directly.
  4. Credentials are not stored or cached between invocations. Each CLI invocation requires fresh credentials.

Connection

The CLI connects to the Central Host via HTTP:

  • Management URL: The URL of a central node's web server (e.g., http://localhost:9001). The management API is served at POST /management on the same host as the Central UI.
  • Failover: For HA, use a load balancer URL in front of both central nodes. The management API is stateless (Basic Auth per request), so any central node can handle any request without sticky sessions.
  • No Akka.NET dependency: The CLI is a pure HTTP client with no Akka.NET runtime.

Command Structure

The CLI uses a hierarchical subcommand structure mirroring the Management Service message groups:

scadalink <group> <action> [options]

Template Commands

scadalink template list [--format json|table]
scadalink template get <name> [--format json|table]
scadalink template create --name <name> [--parent <parent>] --file <path>
scadalink template update <name> --file <path>
scadalink template delete <name>
scadalink template validate <name>
scadalink template diff <instance-code>
scadalink template attribute add --template-id <id> --name <name> --data-type <type> [--default-value <value>] [--tag-path <path>]
scadalink template attribute update --template-id <id> --name <name> [--data-type <type>] [--default-value <value>] [--tag-path <path>]
scadalink template attribute delete --template-id <id> --name <name>
scadalink template alarm add --template-id <id> --name <name> --trigger-attribute <attr> --condition <cond> --setpoint <value> [--severity <level>] [--notification-list <name>]
scadalink template alarm update --template-id <id> --name <name> [--condition <cond>] [--setpoint <value>] [--severity <level>] [--notification-list <name>]
scadalink template alarm delete --template-id <id> --name <name>
scadalink template script add --template-id <id> --name <name> --trigger-type <type> [--trigger-attribute <attr>] [--interval <ms>] --code <code>
scadalink template script update --template-id <id> --name <name> [--trigger-type <type>] [--trigger-attribute <attr>] [--interval <ms>] [--code <code>]
scadalink template script delete --template-id <id> --name <name>
scadalink template composition add --template-id <id> --module-template-id <id> --instance-name <name>
scadalink template composition delete --template-id <id> --instance-name <name>

Instance Commands

scadalink instance list [--site <site>] [--area <area>] [--format json|table]
scadalink instance get <code> [--format json|table]
scadalink instance create --template <name> --site <site> --code <code> [--area <area>]
scadalink instance set-overrides <code> --file <path>
scadalink instance set-bindings <code> --bindings <json>
scadalink instance bind-connections <code> --file <path>
scadalink instance assign-area <code> --area <area>
scadalink instance enable <code>
scadalink instance disable <code>
scadalink instance delete <code>

Site Commands

scadalink site list [--format json|table]
scadalink site get <site-id> [--format json|table]
scadalink site create --name <name> --id <site-id>
scadalink site update <site-id> --file <path>
scadalink site delete <site-id>
scadalink site area list <site-id>
scadalink site area create <site-id> --name <name> [--parent <parent-area>]
scadalink site area update <site-id> --name <name> [--new-name <name>] [--parent <parent-area>]
scadalink site area delete <site-id> --name <name>

Deployment Commands

scadalink deploy instance <code>
scadalink deploy artifacts [--site <site>] [--type <artifact-type>]
scadalink deploy status [--format json|table]

Data Connection Commands

scadalink data-connection list [--format json|table]
scadalink data-connection get <name> [--format json|table]
scadalink data-connection create --file <path>
scadalink data-connection update <name> --file <path>
scadalink data-connection delete <name>
scadalink data-connection assign <name> --site <site-id>
scadalink data-connection unassign <name> --site <site-id>

External System Commands

scadalink external-system list [--format json|table]
scadalink external-system get <name> [--format json|table]
scadalink external-system create --file <path>
scadalink external-system update <name> --file <path>
scadalink external-system delete <name>

Notification Commands

scadalink notification list [--format json|table]
scadalink notification get <name> [--format json|table]
scadalink notification create --file <path>
scadalink notification update <name> --file <path>
scadalink notification delete <name>
scadalink notification smtp list [--format json|table]
scadalink notification smtp update --file <path>

Security Commands

scadalink security api-key list [--format json|table]
scadalink security api-key create --name <name>
scadalink security api-key update <name> [--name <new-name>] [--enabled <bool>]
scadalink security api-key enable <name>
scadalink security api-key disable <name>
scadalink security api-key delete <name>
scadalink security role-mapping list [--format json|table]
scadalink security role-mapping create --group <ldap-group> --role <role> [--site <site>]
scadalink security role-mapping update --id <id> [--group <ldap-group>] [--role <role>]
scadalink security role-mapping delete --group <ldap-group> --role <role>
scadalink security scope-rule list [--role-mapping-id <id>] [--format json|table]
scadalink security scope-rule add --role-mapping-id <id> --site-id <site-id>
scadalink security scope-rule delete --id <id>

Audit Log Commands

scadalink audit-log query [--user <username>] [--entity-type <type>] [--from <date>] [--to <date>] [--format json|table]

Health Commands

scadalink health summary [--format json|table]
scadalink health site <site-id> [--format json|table]
scadalink health event-log --site-identifier <site-id> [--from <date>] [--to <date>] [--search <term>] [--page <n>] [--page-size <n>] [--format json|table]
scadalink health parked-messages --site-identifier <site-id> [--page <n>] [--page-size <n>] [--format json|table]

Debug Commands

scadalink debug snapshot --id <id> [--format json|table]

Shared Script Commands

scadalink shared-script list [--format json|table]
scadalink shared-script get --id <id> [--format json|table]
scadalink shared-script create --name <name> --code <code>
scadalink shared-script update --id <id> [--name <name>] [--code <code>]
scadalink shared-script delete --id <id>

Database Connection Commands

scadalink db-connection list [--format json|table]
scadalink db-connection get --id <id> [--format json|table]
scadalink db-connection create --name <name> --connection-string <string> [--provider <provider>]
scadalink db-connection update --id <id> [--name <name>] [--connection-string <string>] [--provider <provider>]
scadalink db-connection delete --id <id>

Inbound API Method Commands

scadalink api-method list [--format json|table]
scadalink api-method get --id <id> [--format json|table]
scadalink api-method create --name <name> --code <code> [--description <desc>]
scadalink api-method update --id <id> [--name <name>] [--code <code>] [--description <desc>]
scadalink api-method delete --id <id>

Configuration

Configuration is resolved in the following priority order (highest wins):

  1. Command-line options: --url, --username, --password, --format.
  2. Environment variables:
    • SCADALINK_MANAGEMENT_URL — Management API URL (e.g., http://central-host:5000).
    • SCADALINK_FORMAT — Default output format (json or table).
  3. Configuration file: ~/.scadalink/config.json — Persistent defaults for management URL and output format.

Configuration File Format

{
  "managementUrl": "http://central-host:5000"
}

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, connection failure, or authentication failure)
2 Authorization failure (insufficient role)

Error Handling

  • Connection failure: If the CLI cannot connect to the management URL (e.g., DNS failure, connection refused), it exits with code 1 and a descriptive error message.
  • Command timeout: If the server does not respond within 30 seconds, the command fails with a timeout error (HTTP 504).
  • Authentication failure: If the server returns HTTP 401 (LDAP bind failed), the CLI exits with code 1.
  • Authorization failure: If the server returns HTTP 403, the CLI exits with code 2.

Dependencies

  • Commons: Message contracts (Messages/Management/) for command type definitions and registry.
  • System.CommandLine: Command-line argument parsing.

Interactions

  • Management Service (via HTTP): The CLI's sole runtime dependency. All operations are sent as HTTP POST requests to the Management API endpoint on a central node, which dispatches to the ManagementActor.
  • Central Host: Serves the Management API at POST /management. Handles LDAP authentication, role resolution, and ManagementActor dispatch.