Chapter 4: Building Capabilities
This chapter focuses on how Ops teams can build reusable infrastructure capabilities in Facets.cloud by creating and managing Terraform modules. The goal is to empower developers with modular, declarative configurations while embedding operational best practices and governance into the modules.
Anatomy of a Facets Module
A Facets module is a structured collection of Terraform files and metadata that defines reusable infrastructure capabilities. At its core, a Facets module comprises:
-
Terraform Files:
- main.tf: Contains the resource definitions and logic.
- variables.tf: Defines the input parameters required for the module.
- outputs.tf: Specifies the outputs exposed by the module for downstream use.
-
Metadata File (facets.yaml):
- The central configuration file that defines the Intent, Flavor, supported clouds, schema for inputs, and sample configurations. This file bridges the abstraction layer between Ops-defined capabilities and developer-friendly usage.
Understanding facets.yaml
The facets.yaml
file is the metadata blueprint for a Facets module. It specifies critical details about the module, including its intent, flavor, supported cloud environments, input schema, and sample configurations.
Key Fields in facets.yaml:
- intent: The high-level capability or resource type (e.g., "database", "storage").
- flavor: The specific implementation of the intent (e.g., "AWS RDS", "Google AlloyDB").
- version: The version of the module, allowing for version control and updates.
- clouds: The list of supported cloud providers (e.g., AWS, GCP).
- spec:
- Defines the input schema, including field names, types, and optional default values.
- Example: Fields for bucket name, access control, and environment.
- sample:
- Provides a boilerplate configuration for developers to reference when using the module.
Example facets.yaml for an S3 Module:
intent: storage
flavor: aws_s3_bucket
version: 1.0
clouds:
- aws
spec:
properties:
bucket_name:
type: string
description: "Name of the S3 bucket"
acl:
type: string
description: "Access control list"
default: "private"
environment:
type: string
description: "Deployment environment"
sample:
bucket_name: "example-bucket"
acl: "private"
environment: "prod"
Facets Standard Variables
Facets.cloud provides predefined variables to simplify module development and integration. These variables ensure consistency across modules and facilitate dynamic configurations:
instance
: Contains the content of the entire declarative configuration JSON, allowing access to all input parameters.environment
: Provides details of the Facets environment, such as namespace and other contextual information.instance_name
: Holds the name of the resource instance being created.cluster
: Includes details of the cluster created within the environment.
These variables should be used within Terraform code to dynamically adapt configurations to the current environment.
outputs.tf
Outputs are defined at the intent level and remain the same for all the modules of that particular intent. The file needs to have at least the following two variables defined; otherwise, the module will fail during releases:
locals {
output_attributes = {}
output_interfaces = {}
}
These variables can be empty or set with specific values but must be defined. The values will be visible on the overview page of the resource once it is enabled and released.
Sample Module: AWS S3 Bucket
Below is a sample directory structure and file contents for an AWS S3 bucket module:
Directory Structure:
custom_s3_module/
├── main.tf
├── variables.tf
├── outputs.tf
├── facets.yaml
main.tf:
locals {
spec = lookup(var.instance, "spec", {})
}
module "s3_bucket" {
source = "./terraform-s3-bucket"
bucket_name = var.instance_name
cluster_name = var.cluster.name
namespace = var.environment.namespace
extra_tag = lookup(local.spec, "extra_tag", "null")
}
variables.tf:
variable "cluster" {
type = any
}
variable "instance" {
type = any
}
variable "instance_name" {
type = string
}
variable "environment" {
type = any
}
outputs.tf:
locals {
output_attributes = {
Bucket_ID = module.s3_bucket.bucket_id
Bucket_ARN = module.s3_bucket.bucket_arn
}
output_interfaces = {}
}
Updated 4 days ago