Docs

Operations

An operation is a named action, such as kubernetes/get-pods or kubernetes/restart-pod, that Remote Operator runs in a customer's deployment to check or fix something. Operations are grouped into plugins, take typed parameters, and declare a risk tier.

When no operation answers your question, a debug session runs kubectl or a cloud CLI instead.

Run an operation

List the plugins, then invoke an operation the deployment declares:

alien operations list --deployment customer-1/us-east-1

alien operations invoke \
  --deployment customer-1/us-east-1 \
  --operation kubernetes/get-pods \
  --params '{"namespace":"checkout","maxResults":10}'

The CLI waits up to 60 seconds for the result (--timeout changes it). An operation from a plugin the deployment's release doesn't declare fails with OPERATIONS_PLUGIN_NOT_DECLARED.

If the operation needs approval, the CLI prints Access is required to run <plugin>/<operation>. and the command to request it. With --json, the result has "status": "pending-approval". Add --request-access to create the request, wait for approval, and run:

alien operations invoke \
  --deployment customer-1/us-east-1 \
  --operation kubernetes/restart-pod \
  --params '{"namespace":"checkout","pod":"api-7c9d"}' \
  --request-access --access-duration 1h

Operations are not commands. A command calls a handler in your own code with alien commands invoke and has no approval rules. Use an operation when a customer should decide whether it runs.

Risk tiers

TierMeaningExample
Read-onlyReads state. Changes nothing.postgres/locks
MutatingChanges a running system in a bounded, reversible way.kubernetes/scale
DestructiveCan delete or lose data.Custom plugins only today

Built-in catalog

Every built-in operation is read-only except kubernetes/restart-pod and kubernetes/scale.

PluginOperations
kubernetesget-pods, pod-details, logs, events, workload-status, rollout-status, services-and-endpoints, resource-usage, restart-pod (mutating), scale (mutating)
postgreshealth, version, activity, locks, long-running-queries
redisping, info, slowlog, client-list
kafkaconsumer-lag, topic-describe
clickhousehealth, running-queries, table-sizes
elasticsearchcluster-health, index-stats
s3head-bucket, list-objects, head-object
sqslist-queues, queue-stats, redrive-policy
cloudwatchquery-metrics, alarms, log-groups
ec2instances, instance-status, volumes
rdsinstances, clusters, events
elbv2load-balancers, target-groups, target-health
aws-vpcvpcs, subnets, route-tables, security-group-rules
gcslist-objects, bucket-usage, object-head
pubsubtopics, subscriptions, subscription-stats
gceinstances, disks, instance-groups
gcp-vpcnetworks, subnetworks, routes, firewall-rules

The dashboard lists the same catalog under Operations → Catalog, with Built-in and Custom sections. Azure resource operations aren't available yet.

Declare operations in alien.ts

A deployment runs only the plugins its release declares. Declare them with .operations() on the stack. Each plugin takes its settings and an approval map:

alien.ts
import * as alien from "@alienplatform/core"

const data = new alien.Storage("data").build()

export default new alien.Stack("acme")
  .add(data, "frozen")
  .operations({
    kubernetes: {
      approval: {
        "*": "auto",
        "restart-pod": "manual",
        scale: "manual",
      },
    },
    s3: { buckets: [data] },
    cloudwatch: { approval: { "*": "auto" } },
  })
  .build()

This stack:

  • runs every Kubernetes read without approval
  • requires approval for the two mutating Kubernetes operations
  • scopes s3 to the data bucket; s3 has no rule, so its operations need approval
  • runs CloudWatch reads freely

Approval rules

Alien picks the rule for an operation in this order:

  1. The exact operation name, without the plugin prefix: restart-pod, not kubernetes/restart-pod.
  2. *.
  3. None. No rule means the operation needs approval.

A rule is "auto" or "manual", or an object with a decision and a maxRisk. Alien reads maxRisk only from the * rule: it's the highest tier a wildcard access request for the plugin can cover. Without it, a wildcard request covers only read-only operations.

This stack takes ClickHouse settings from inputs and lets wildcard requests reach mutating Kubernetes operations:

alien.ts
import * as alien from "@alienplatform/core"

const inputs = alien.inputs({
  clickhouseUrl: alien.string({
    label: "ClickHouse URL",
    description: "The URL of your ClickHouse server",
    providedBy: "deployer",
    required: true,
  }),
  clickhousePassword: alien.secret({
    label: "ClickHouse password",
    description: "Password for the read-only ClickHouse user",
    providedBy: "deployer",
    required: true,
  }),
})

export default new alien.Stack("acme")
  .inputs(inputs)
  .operations({
    clickhouse: {
      url: inputs.clickhouseUrl,
      password: inputs.clickhousePassword,
      database: "default",
      approval: { "*": "auto" },
    },
    kubernetes: {
      approval: { "*": { decision: "manual", maxRisk: "mutating" } },
    },
    plugins: ["acme-admin@1.2.0"],
  })
  .build()

Settings and custom plugins

Plugin settings are a string, a stack input, or stack resources:

  • A secret setting must come from an alien.secret input.
  • A resource setting lists resources of the type the plugin needs. The s3 plugin's buckets setting takes Storage resources and scopes its object permissions to them.

Custom plugins go under plugins, pinned to an exact published version: "name@version", or { name, version, approval } when the plugin needs settings or rules.

  • .operations() throws when a string entry has no version, or when it has no plugins at all.
  • Declare each custom plugin once, and don't give it the name of a built-in plugin the stack also declares.

Release checks

The declaration is part of the release. Changes take effect after alien release, when each deployment updates. Release creation fails if:

  • a plugin name isn't built in
  • a custom version isn't published in the project
  • a setting is missing or invalid
  • a rule names an operation the plugin doesn't have
  • a maxRisk isn't read-only, mutating, or destructive

Push deployments

A push deployment on AWS or Google Cloud has no Operator. When its release declares .operations(), the release adds an operations Worker (Lambda on AWS, Cloud Run on Google Cloud) that runs the declared plugins in the customer's account.

The customer's initial setup, the one-time step their admin runs, owns the Worker's role. The admin reruns initial setup the first time, and again whenever the plugins' permissions change. Until then, operations fail with OPERATIONS_NOT_ENABLED.

An operation, retries included, must finish within 900 seconds on AWS and 600 seconds on Google Cloud.

For an Operator added to your own Helm chart, declare the same thing in the Helm value remoteOperator.operations. See Add to an existing product.

Build a custom plugin

A custom plugin is a Rust program that exposes your own operations, for example a health check against your application's admin API. Each operation has a name, a risk tier, typed parameters, a typed result, and the permissions it needs.

alien operations init acme-admin     # scaffold, with one read-only health operation
cd acme-admin
cargo run --bin generate-metadata    # regenerate metadata.json after each change
alien operations check               # validate metadata against the typed operations
alien operations test                # run cargo test
alien operations permissions --cloud aws   # preview the IAM grants, offline
alien operations package             # build a Linux binary and zip the bundle
alien operations publish ./acme-admin-0.1.0.zip
  • init, check, test, permissions, docs, and package work offline.
  • package builds for the machine's architecture. Build on each architecture to ship both amd64 and arm64.
  • alien operations check --manifest-only validates a plugin you don't trust without building it.

Custom plugins need the Enterprise plan.

Each operation is defined once in Rust with OperationDefinition in a TypedOperations registry, and metadata.json is generated from those definitions. check, package, and publish reject metadata that wasn't generated:

MessageFix
'<directory>' has no metadata generator; plugins must generate metadata.json from typed operations.Add the src/bin/generate-metadata.rs binary that alien operations init creates, and register operations with OperationDefinition.
generated metadata in '<directory>' is stale or invalidRun cargo run --bin generate-metadata.
bundle '<path>' has operations without valid inputSchema and outputSchema objectsRegenerate metadata.json and rebuild with alien operations package.

To use a published plugin, add "<name>@<version>" to plugins in .operations().

Preview a plugin's permissions

alien operations permissions ./acme-admin --cloud aws --json

This prints the grants a plugin's operations declare, using the same compiler as initial setup.

  • --cloud also takes gcp, azure, or kubernetes.
  • Pass the exact resources the installation will allow with repeated --s3-bucket-arn, --sqs-queue-arn, or --gcs-bucket. A grant that needs a resource list fails without one.
  • For Kubernetes, --permission diagnostics (the default) grants reads, and --permission remediation adds the Pod deletion and workload scaling the plugin declares.

The installation, not the plugin, decides namespace or cluster scope.

The custom operations example has a read-only doctor operation and a mutating one that call an application's admin API.

Keep each operation narrow: one question or one repair. Avoid general shells, arbitrary SQL, or an unrestricted Kubernetes proxy, and keep results free of customer records and secrets.

Next

On this page