Defining Custom Actions
Step 1: Define the Action Resource
First, define a resource facets_action
block. This block serves as the container for your entire Action definition. Give it a unique local name (e.g., db_snapshot
) and a human-readable name that will be displayed in the Facets UI.
The target_resource_type
argument is crucial; it links the Action to a specific module (e.g., aws-rds
), ensuring it only appears on resources of that type.
In actions.tf
:
resource "facets_action" "db_snapshot" {
name = "Create Database Snapshot"
target_resource_type = "aws-rds"
#... further configuration will be added in the next steps
}
Step 2: Add a Clear Description
Write a concise, one-sentence description
that clearly explains what the Action does. This description appears in the UI and helps users understand the purpose of the Action before running it.
resource "facets_action" "db_snapshot" {
name = "Create Database Snapshot"
description = "Creates a manual snapshot of the RDS database instance."
target_resource_type = "aws-rds"
#...
}
Step 3: Define User Inputs
If your Action requires parameters from the user at runtime, define them in an inputs
block. This block uses standard HCL variable syntax and will render as a form in the Facets UI when a user runs the Action.
You can specify the type, description, a default value, and whether the input is required.
resource "facets_action" "db_snapshot" {
#... name, description, target_resource_type
inputs {
variable "snapshot_identifier" {
type = string
description = "A unique name for the database snapshot."
required = true
}
variable "is_replicated" {
type = bool
description = "Replicate this snapshot to a DR region."
default = false
}
}
#...
}
Note on Standard Inputs:
Facets automatically provides context about the target resource. You can access details like instance_name
and environment
within the Terraform phase using the data "facets_resource" "target" {}
data source.
Step 4: Create the Execution Steps
The core logic of an Action is defined in two phases:
- Terraform phase (
terraform_config
) — gathers context. - Container phase (
container_config
) — executes the task.
Phase 1: Gather Context with terraform_config
terraform_config
The terraform_config
block contains an ephemeral Terraform script that runs to gather necessary information from your cloud environment.
resource "facets_action" "db_snapshot" {
#... name, description, target_resource_type, inputs
terraform_config = <<-EOT
# Access the target resource's attributes
data "facets_resource" "target" {}
# Expose the database instance ID as an output
output "db_instance_identifier" {
value = data.facets_resource.target.attributes.identifier
}
EOT
#... container_config to follow
}
Phase 2: Execute the Task with container_config
container_config
The container_config
block defines the containerized step that performs the actual work.
-
Pick a container image:
- AWS tasks →
amazon/aws-cli:latest
- Kubernetes tasks →
bitnami/kubectl:latest
- General scripting →
alpine:latest
- Database tasks →
redis:latest
,postgres:latest
- AWS tasks →
-
Define environment variables: Use the
env
map to pass data from Terraform outputs and user inputs. -
Add a script: Use
command
andargs
to define the execution logic.
resource "facets_action" "db_snapshot" {
#... name, description, target_resource_type, inputs, terraform_config
container_config {
image = "amazon/aws-cli:latest"
command = ["/bin/sh", "-c"]
args = [
<<-EOT
set -eou pipefail
echo "Creating snapshot for database instance: $DB_ID"
aws rds create-db-snapshot --db-instance-identifier "$DB_ID" --db-snapshot-identifier "$SNAPSHOT_ID"
echo "Snapshot creation initiated successfully."
EOT
]
env = {
"DB_ID" = terraform.outputs.db_instance_identifier
"SNAPSHOT_ID" = var.snapshot_identifier
}
}
}
Step 5: Test the Script Logic Manually
Before embedding a complex script into the actions.tf
file, test it locally with Docker.
# Example of local testing using Docker
docker run --rm -it -e DB_ID="my-test-db" -e SNAPSHOT_ID="my-test-snapshot-local" -e AWS_ACCESS_KEY_ID="YOUR_KEY" -e AWS_SECRET_ACCESS_KEY="YOUR_SECRET" -e AWS_REGION="us-east-1" amazon/aws-cli:latest /bin/sh -c '
set -eou pipefail
echo "Testing snapshot for database instance: $DB_ID"
aws rds create-db-snapshot --db-instance-identifier "$DB_ID" --db-snapshot-identifier "$SNAPSHOT_ID"
echo "Test successful."
'
This local feedback loop is much faster than committing and running the Action through the UI for every change.
Step 6: Make the Action Reusable
Design your Actions for reusability across different environments and resources.
- Use input parameters: Parameterize values like names, flags, or patterns.
- Avoid hardcoding: Always fetch values dynamically in the
terraform_config
phase.
By following these principles, you can build a library of robust, reusable automation components that scale with your organization.
Updated about 3 hours ago