fix: resolve CLI serialization failures and add README
Two Akka.NET deserialization bugs prevented CLI commands from reaching ManagementActor: IReadOnlyList<string> in AuthenticatedUser serialized as a compiler-generated internal type unknown to the server, and ManagementSuccess.Data carried server-side assembly types the CLI couldn't resolve on receipt. Fixed by using string[] for roles and pre-serializing response data to JSON in ManagementActor before sending. Adds full CLI reference documentation covering all 10 command groups.
This commit is contained in:
@@ -18,7 +18,6 @@ internal static class CommandHelpers
|
|||||||
object command)
|
object command)
|
||||||
{
|
{
|
||||||
var contactPointsRaw = result.GetValue(contactPointsOption);
|
var contactPointsRaw = result.GetValue(contactPointsOption);
|
||||||
var format = result.GetValue(formatOption) ?? "json";
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(contactPointsRaw))
|
if (string.IsNullOrWhiteSpace(contactPointsRaw))
|
||||||
{
|
{
|
||||||
@@ -41,18 +40,15 @@ internal static class CommandHelpers
|
|||||||
var envelope = new ManagementEnvelope(PlaceholderUser, command, NewCorrelationId());
|
var envelope = new ManagementEnvelope(PlaceholderUser, command, NewCorrelationId());
|
||||||
var response = await connection.AskManagementAsync(envelope, TimeSpan.FromSeconds(30));
|
var response = await connection.AskManagementAsync(envelope, TimeSpan.FromSeconds(30));
|
||||||
|
|
||||||
return HandleResponse(response, format);
|
return HandleResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static int HandleResponse(object response, string format)
|
internal static int HandleResponse(object response)
|
||||||
{
|
{
|
||||||
switch (response)
|
switch (response)
|
||||||
{
|
{
|
||||||
case ManagementSuccess success:
|
case ManagementSuccess success:
|
||||||
if (format == "table")
|
Console.WriteLine(success.JsonData);
|
||||||
WriteAsTable(success.Data);
|
|
||||||
else
|
|
||||||
OutputFormatter.WriteJson(success.Data);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case ManagementError error:
|
case ManagementError error:
|
||||||
@@ -68,10 +64,4 @@ internal static class CommandHelpers
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void WriteAsTable(object? data)
|
|
||||||
{
|
|
||||||
// For table format, delegate to JSON if data shape is unknown
|
|
||||||
OutputFormatter.WriteJson(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
558
src/ScadaLink.CLI/README.md
Normal file
558
src/ScadaLink.CLI/README.md
Normal file
@@ -0,0 +1,558 @@
|
|||||||
|
# ScadaLink CLI
|
||||||
|
|
||||||
|
Command-line tool for managing the ScadaLink SCADA system. Connects to a Central node via Akka.NET ClusterClient and routes commands through the ManagementActor.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
dotnet build src/ScadaLink.CLI
|
||||||
|
```
|
||||||
|
|
||||||
|
The output binary is `scadalink` (or `scadalink.exe` on Windows).
|
||||||
|
|
||||||
|
## Connection
|
||||||
|
|
||||||
|
Every command requires a connection to a running Central node. Contact points can be supplied three ways, evaluated in this priority order:
|
||||||
|
|
||||||
|
1. `--contact-points` flag on the command line
|
||||||
|
2. `SCADALINK_CONTACT_POINTS` environment variable
|
||||||
|
3. `contactPoints` array in `~/.scadalink/config.json`
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points akka.tcp://scadalink@central-host:8081 <command>
|
||||||
|
```
|
||||||
|
|
||||||
|
For a two-node HA cluster, supply both nodes comma-separated:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points akka.tcp://scadalink@node1:8081,akka.tcp://scadalink@node2:8082 <command>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Global Options
|
||||||
|
|
||||||
|
These options are accepted by the root command and inherited by all subcommands.
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--contact-points <value>` | Comma-separated Akka cluster contact point URIs |
|
||||||
|
| `--username <value>` | LDAP username (reserved for future auth integration) |
|
||||||
|
| `--password <value>` | LDAP password (reserved for future auth integration) |
|
||||||
|
| `--format <json\|table>` | Output format (default: `json`) |
|
||||||
|
|
||||||
|
## Configuration File
|
||||||
|
|
||||||
|
`~/.scadalink/config.json` is loaded at startup. All fields are optional.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"contactPoints": ["akka.tcp://scadalink@central-host:8081"],
|
||||||
|
"ldap": {
|
||||||
|
"server": "ldap.company.com",
|
||||||
|
"port": 636,
|
||||||
|
"useTls": true
|
||||||
|
},
|
||||||
|
"defaultFormat": "json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `SCADALINK_CONTACT_POINTS` | Comma-separated contact point URIs (overrides config file) |
|
||||||
|
| `SCADALINK_LDAP_SERVER` | LDAP server hostname (overrides config file) |
|
||||||
|
| `SCADALINK_FORMAT` | Default output format (overrides config file) |
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
All commands write JSON to stdout on success. Errors are written as JSON to stderr:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "error": "Human-readable message", "code": "ERROR_CODE" }
|
||||||
|
```
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
|
||||||
|
| Code | Meaning |
|
||||||
|
|------|---------|
|
||||||
|
| `0` | Success |
|
||||||
|
| `1` | Command error |
|
||||||
|
| `2` | Authorization failure |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Command Reference
|
||||||
|
|
||||||
|
### `template` — Manage templates
|
||||||
|
|
||||||
|
#### `template list`
|
||||||
|
|
||||||
|
List all templates with their full attribute, alarm, script, and composition definitions.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> template list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `template get`
|
||||||
|
|
||||||
|
Get a single template by ID.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> template get --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Template ID |
|
||||||
|
|
||||||
|
#### `template create`
|
||||||
|
|
||||||
|
Create a new template, optionally inheriting from a parent.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> template create --name <string> [--description <string>] [--parent-id <int>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Template name |
|
||||||
|
| `--description` | no | Template description |
|
||||||
|
| `--parent-id` | no | Parent template ID for inheritance |
|
||||||
|
|
||||||
|
#### `template delete`
|
||||||
|
|
||||||
|
Delete a template by ID.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> template delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Template ID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `instance` — Manage instances
|
||||||
|
|
||||||
|
#### `instance list`
|
||||||
|
|
||||||
|
List instances, with optional filters.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> instance list [--site-id <int>] [--template-id <int>] [--search <string>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--site-id` | no | Filter by site ID |
|
||||||
|
| `--template-id` | no | Filter by template ID |
|
||||||
|
| `--search` | no | Search term matched against instance name |
|
||||||
|
|
||||||
|
#### `instance create`
|
||||||
|
|
||||||
|
Create a new instance of a template at a site.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> instance create --name <string> --template-id <int> --site-id <int> [--area-id <int>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Unique instance name |
|
||||||
|
| `--template-id` | yes | Template to instantiate |
|
||||||
|
| `--site-id` | yes | Site where the instance will run |
|
||||||
|
| `--area-id` | no | Area within the site |
|
||||||
|
|
||||||
|
#### `instance deploy`
|
||||||
|
|
||||||
|
Deploy an instance to its site. Acquires the per-instance operation lock.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> instance deploy --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Instance ID |
|
||||||
|
|
||||||
|
#### `instance enable`
|
||||||
|
|
||||||
|
Enable a previously disabled instance.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> instance enable --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Instance ID |
|
||||||
|
|
||||||
|
#### `instance disable`
|
||||||
|
|
||||||
|
Disable a running instance without deleting it.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> instance disable --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Instance ID |
|
||||||
|
|
||||||
|
#### `instance delete`
|
||||||
|
|
||||||
|
Delete an instance. The instance must be disabled first.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> instance delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Instance ID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `site` — Manage sites
|
||||||
|
|
||||||
|
#### `site list`
|
||||||
|
|
||||||
|
List all registered sites.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> site list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `site create`
|
||||||
|
|
||||||
|
Register a new site.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> site create --name <string> --identifier <string> [--description <string>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Human-readable site name |
|
||||||
|
| `--identifier` | yes | Unique machine identifier used for cluster routing (e.g. `site-a`) |
|
||||||
|
| `--description` | no | Site description |
|
||||||
|
|
||||||
|
#### `site delete`
|
||||||
|
|
||||||
|
Delete a site. Fails if any instances are assigned to it.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> site delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Site ID |
|
||||||
|
|
||||||
|
#### `site deploy-artifacts`
|
||||||
|
|
||||||
|
Push compiled artifacts to one or all sites.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> site deploy-artifacts [--site-id <int>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--site-id` | no | Target site ID; omit to deploy to all sites |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `deploy` — Deployment operations
|
||||||
|
|
||||||
|
#### `deploy instance`
|
||||||
|
|
||||||
|
Deploy a single instance (same as `instance deploy`).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> deploy instance --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Instance ID |
|
||||||
|
|
||||||
|
#### `deploy artifacts`
|
||||||
|
|
||||||
|
Deploy compiled artifacts to one or all sites (same as `site deploy-artifacts`).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> deploy artifacts [--site-id <int>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--site-id` | no | Target site ID; omit for all sites |
|
||||||
|
|
||||||
|
#### `deploy status`
|
||||||
|
|
||||||
|
Query deployment records, with optional filters and pagination.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> deploy status [--instance-id <int>] [--status <string>] [--page <int>] [--page-size <int>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Default | Description |
|
||||||
|
|--------|----------|---------|-------------|
|
||||||
|
| `--instance-id` | no | — | Filter by instance ID |
|
||||||
|
| `--status` | no | — | Filter by deployment status string |
|
||||||
|
| `--page` | no | `1` | Page number |
|
||||||
|
| `--page-size` | no | `50` | Results per page |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `data-connection` — Manage data connections
|
||||||
|
|
||||||
|
#### `data-connection list`
|
||||||
|
|
||||||
|
List all configured data connections.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> data-connection list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `data-connection create`
|
||||||
|
|
||||||
|
Create a new data connection definition.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> data-connection create --name <string> --protocol <string> [--configuration <json>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Connection name |
|
||||||
|
| `--protocol` | yes | Protocol identifier (e.g. `OpcUa`) |
|
||||||
|
| `--configuration` | no | Protocol-specific configuration as a JSON string |
|
||||||
|
|
||||||
|
#### `data-connection delete`
|
||||||
|
|
||||||
|
Delete a data connection.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> data-connection delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Data connection ID |
|
||||||
|
|
||||||
|
#### `data-connection assign`
|
||||||
|
|
||||||
|
Assign a data connection to a site.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> data-connection assign --connection-id <int> --site-id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--connection-id` | yes | Data connection ID |
|
||||||
|
| `--site-id` | yes | Site ID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `external-system` — Manage external HTTP systems
|
||||||
|
|
||||||
|
#### `external-system list`
|
||||||
|
|
||||||
|
List all external system definitions.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> external-system list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `external-system create`
|
||||||
|
|
||||||
|
Register an external HTTP system that scripts can call.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> external-system create --name <string> --endpoint-url <url> --auth-type <string> [--auth-config <json>]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Display name |
|
||||||
|
| `--endpoint-url` | yes | Base URL of the external system |
|
||||||
|
| `--auth-type` | yes | Authentication type: `ApiKey` or `BasicAuth` |
|
||||||
|
| `--auth-config` | no | Auth credentials as a JSON string |
|
||||||
|
|
||||||
|
#### `external-system delete`
|
||||||
|
|
||||||
|
Delete an external system definition.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> external-system delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | External system ID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `notification` — Manage notification lists
|
||||||
|
|
||||||
|
#### `notification list`
|
||||||
|
|
||||||
|
List all notification lists.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> notification list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `notification create`
|
||||||
|
|
||||||
|
Create a notification list with one or more recipients.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> notification create --name <string> --emails <email1,email2,...>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Notification list name |
|
||||||
|
| `--emails` | yes | Comma-separated list of recipient email addresses |
|
||||||
|
|
||||||
|
#### `notification delete`
|
||||||
|
|
||||||
|
Delete a notification list.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> notification delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Notification list ID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `security` — Security settings
|
||||||
|
|
||||||
|
#### `security api-key list`
|
||||||
|
|
||||||
|
List all inbound API keys.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> security api-key list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `security api-key create`
|
||||||
|
|
||||||
|
Create a new inbound API key. The generated key value is returned in the response and not stored in plaintext — save it immediately.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> security api-key create --name <string>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--name` | yes | Descriptive label for the key |
|
||||||
|
|
||||||
|
#### `security api-key delete`
|
||||||
|
|
||||||
|
Revoke and delete an API key.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> security api-key delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | API key ID |
|
||||||
|
|
||||||
|
#### `security role-mapping list`
|
||||||
|
|
||||||
|
List all LDAP group → role mappings.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> security role-mapping list
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `security role-mapping create`
|
||||||
|
|
||||||
|
Map an LDAP group to a ScadaLink role.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> security role-mapping create --ldap-group <string> --role <string>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--ldap-group` | yes | LDAP group distinguished name or CN |
|
||||||
|
| `--role` | yes | ScadaLink role: `Admin`, `Design`, or `Deployment` |
|
||||||
|
|
||||||
|
#### `security role-mapping delete`
|
||||||
|
|
||||||
|
Remove an LDAP role mapping.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> security role-mapping delete --id <int>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--id` | yes | Mapping ID |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `health` — Health monitoring
|
||||||
|
|
||||||
|
#### `health summary`
|
||||||
|
|
||||||
|
Return the current health state for all known sites as a JSON object keyed by site identifier.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> health summary
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `health site`
|
||||||
|
|
||||||
|
Return the health state for a single site.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> health site --identifier <string>
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Description |
|
||||||
|
|--------|----------|-------------|
|
||||||
|
| `--identifier` | yes | Site identifier (e.g. `site-a`) |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `audit-log` — Audit log queries
|
||||||
|
|
||||||
|
#### `audit-log query`
|
||||||
|
|
||||||
|
Query the central audit log with optional filters and pagination.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scadalink --contact-points <uri> audit-log query [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
| Option | Required | Default | Description |
|
||||||
|
|--------|----------|---------|-------------|
|
||||||
|
| `--user` | no | — | Filter by username |
|
||||||
|
| `--entity-type` | no | — | Filter by entity type (e.g. `Template`, `Instance`) |
|
||||||
|
| `--action` | no | — | Filter by action (e.g. `Create`, `Delete`) |
|
||||||
|
| `--from` | no | — | Start timestamp in ISO 8601 format |
|
||||||
|
| `--to` | no | — | End timestamp in ISO 8601 format |
|
||||||
|
| `--page` | no | `1` | Page number |
|
||||||
|
| `--page-size` | no | `50` | Results per page |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Architecture Notes
|
||||||
|
|
||||||
|
The CLI connects to the Central cluster using Akka.NET's `ClusterClient`. It does not join the cluster — it contacts the `ClusterClientReceptionist` on one of the configured Central nodes and sends commands to the `ManagementActor` at path `/user/management`.
|
||||||
|
|
||||||
|
The connection is established per-command invocation and torn down cleanly via `CoordinatedShutdown` when the command completes.
|
||||||
|
|
||||||
|
Role enforcement is applied by the ManagementActor on the server side. The current CLI placeholder user carries `Admin`, `Design`, and `Deployment` roles; production use will integrate LDAP authentication via `--username` / `--password`.
|
||||||
@@ -2,10 +2,10 @@ namespace ScadaLink.Commons.Messages.Management;
|
|||||||
|
|
||||||
public record AuthenticatedUser(
|
public record AuthenticatedUser(
|
||||||
string Username, string DisplayName,
|
string Username, string DisplayName,
|
||||||
IReadOnlyList<string> Roles, IReadOnlyList<string> PermittedSiteIds);
|
string[] Roles, string[] PermittedSiteIds);
|
||||||
|
|
||||||
public record ManagementEnvelope(AuthenticatedUser User, object Command, string CorrelationId);
|
public record ManagementEnvelope(AuthenticatedUser User, object Command, string CorrelationId);
|
||||||
|
|
||||||
public record ManagementSuccess(string CorrelationId, object? Data);
|
public record ManagementSuccess(string CorrelationId, string JsonData);
|
||||||
public record ManagementError(string CorrelationId, string Error, string ErrorCode);
|
public record ManagementError(string CorrelationId, string Error, string ErrorCode);
|
||||||
public record ManagementUnauthorized(string CorrelationId, string Message);
|
public record ManagementUnauthorized(string CorrelationId, string Message);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using Akka.Actor;
|
using Akka.Actor;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using ScadaLink.Commons.Entities.ExternalSystems;
|
using ScadaLink.Commons.Entities.ExternalSystems;
|
||||||
@@ -56,7 +57,8 @@ public class ManagementActor : ReceiveActor
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await DispatchCommand(scope.ServiceProvider, envelope.Command, user.Username);
|
var result = await DispatchCommand(scope.ServiceProvider, envelope.Command, user.Username);
|
||||||
sender.Tell(new ManagementSuccess(correlationId, result));
|
var json = JsonConvert.SerializeObject(result, Formatting.None);
|
||||||
|
sender.Tell(new ManagementSuccess(correlationId, json));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user