Stack operations
An operation is a named action that you or an agent run in a customer's environment, such as s3/head-bucket or kubernetes/restart-pod. The name has two parts: the plugin, then the operation. Each operation has a risk tier: read-only, mutating, or destructive.
Declare the plugins a stack uses with .operations({...}) on the Stack in alien.ts. A deployment runs only the operations of plugins its release declares. When you invoke an operation from a plugin that the release does not declare, the request fails with OPERATIONS_PLUGIN_NOT_DECLARED.
Operations are different from Remote Commands. A command calls a handler in your own code and has no approval rules. Use an operation when a person should approve the action before it runs.
List the plugins you can declare
Run alien operations list to see every built-in plugin and every custom plugin published in the project:
alien operations listThe command prints one line per plugin, with its version, whether it is builtin or custom, and its risk tier. Add --json to see each plugin's operations and the tier of each one. Add --deployment <group>/<name> to list only the plugins that a deployment declares.
Declare built-in plugins
Add a key for each built-in plugin, named as alien operations list prints it. This stack declares the read-only CloudWatch and AWS VPC plugins and lets every operation in them run without approval:
export default new alien.Stack("byoc-database")
.platforms(["aws", "gcp", "azure", "kubernetes", "machines"])
.operations({
cloudwatch: { approval: { "*": "auto" } },
"aws-vpc": { approval: { "*": "auto" } },
})
.add(storage, "frozen")
// ...
.build()Some plugins take settings. Put them next to approval in the plugin's object. A setting value is one of these:
- A string.
- A stack input, such as
inputs.dbUrl. - A stack resource, or an array of stack resources.
const inputs = alien.inputs({
dbUrl: alien.string({
label: "Database URL",
description: "ClickHouse URL",
providedBy: "deployer",
required: true,
}),
dbPassword: alien.secret({
label: "Database password",
description: "ClickHouse password",
providedBy: "deployer",
required: true,
}),
})
const data = new alien.Storage("data").build()
export default new alien.Stack("app")
.inputs(inputs)
.add(data, "frozen")
.operations({
clickhouse: { url: inputs.dbUrl, password: inputs.dbPassword, database: "app" },
s3: { buckets: [data] },
})
.build()The plugin's manifest declares the settings it accepts. A secret setting, such as the ClickHouse password, must come from an alien.secret input. A resource setting must list resources of the type the plugin needs. The s3 plugin's buckets setting takes Storage resources and scopes the plugin's object permissions to them. See Stack inputs to declare inputs.
Declare custom plugins
Put custom plugins in the plugins array. Pin each one to an exact version that you published with alien operations publish. Write it as "name@version", or as an object with name and version when it needs settings or approval rules:
export default new alien.Stack("app")
.operations({
kubernetes: { approval: { "*": "auto" } },
plugins: [
"mine@1.2.0",
{ name: "other", version: "0.1.0", approval: { "*": "manual" } },
],
})
.build().operations() throws when a string entry has no version, such as "mine". It also throws when you call it with no plugins.
Declare each custom plugin once. A custom plugin cannot have the same name as a built-in plugin that the stack also declares.
Set approval rules
The approval object maps an operation name to a rule. Write the name without the plugin prefix: restart-pod, not kubernetes/restart-pod. The key * matches every operation of the plugin.
Alien finds the rule for an operation in this order:
- The rule for the exact operation name.
- The
*rule. - No rule: the operation needs approval.
A rule is "auto" or "manual". With "auto", the operation runs when invoked. With "manual", it waits for approval. This declaration runs every Kubernetes operation automatically, except the two mutating ones:
.operations({
kubernetes: {
approval: {
"*": "auto",
"restart-pod": "manual",
scale: "manual",
},
},
})A rule can also be an object with a decision and a maxRisk. decision is "auto" or "manual". maxRisk is the highest risk tier that a wildcard access request for the plugin can cover. Alien reads maxRisk only from the * rule:
.operations({
kubernetes: {
approval: { "*": { decision: "manual", maxRisk: "mutating" } },
},
})With this rule, every Kubernetes operation needs approval. A wildcard access request, such as alien access-requests create --deployment acme/production --operation "kubernetes/*" --max-risk mutating, can cover the plugin's read-only and mutating operations. Without maxRisk on the * rule, a wildcard request covers only read-only operations.
An operation that needs approval runs after the customer approves an access request for it. See Request access for an operation.
Create a release to apply changes
The operations declaration is part of the release. Changes to .operations() take effect only in a new release:
alien releaseA deployment uses the declaration of the release it runs. It gets the new plugins and approval rules when it updates to the new release.
Alien checks the declaration when it creates the release. Release creation fails when the declaration has any of these problems:
- A name is not a built-in plugin.
- A custom plugin version is not published in the project.
- A required setting is missing, or a setting value does not match the plugin's manifest.
- An approval rule names an operation that the plugin does not have.
- A
maxRiskis notread-only,mutating, ordestructive.