Learn best practices for using the Azion Terraform Provider efficiently and securely.


Code Organization

Directory Structure

Organize your Terraform files logically:

terraform/
├── main.tf # Provider and main configurations
├── variables.tf # Input variables
├── outputs.tf # Outputs
├── providers.tf # Provider configurations
├── backend.tf # Backend configuration
├── modules/
│ ├── workload/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── outputs.tf
│ └── application/
│ ├── main.tf
│ ├── variables.tf
│ └── outputs.tf
└── environments/
├── dev/
│ ├── main.tf
│ └── terraform.tfvars
├── staging/
└── prod/

Naming Conventions

Use descriptive and consistent names:

# Good
resource "azion_workload" "api_gateway" {
name = "api-gateway-prod"
}
# Avoid
resource "azion_workload" "w1" {
name = "w1"
}

State Management

Remote Backend

Always use a remote backend to store state:

backend.tf
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "azion/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}

Locking

Use locking to prevent conflicts:

# With S3 + DynamoDB
terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "azion/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}

Security

Sensitive Variables

Mark sensitive variables as sensitive:

variable "api_token" {
type = string
description = "Azion Personal Token"
sensitive = true
}

Don’t Commit Secrets

Add to .gitignore:

# Terraform
*.tfstate
*.tfstate.backup
*.tfvars
.terraform/
terraform.tfvars
secrets.tf

Use Environment Variables

Terminal window
export TF_VAR_api_token="your-token"

Modularization

Creating Modules

Create reusable modules:

modules/workload/main.tf
variable "name" {
type = string
}
variable "environment" {
type = string
}
resource "azion_workload" "this" {
name = "${var.name}-${var.environment}"
}
output "workload_id" {
value = azion_workload.this.id
}

Using Modules

main.tf
module "api_workload" {
source = "./modules/workload"
name = "api"
environment = "prod"
}

CI/CD

Basic Pipeline

Example with GitHub Actions:

.github/workflows/terraform.yml
name: Terraform
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: hashicorp/setup-terraform@v2
- name: Terraform Init
run: terraform init
- name: Terraform Plan
run: terraform plan
env:
AZION_API_TOKEN: ${{ secrets.AZION_API_TOKEN }}
- name: Terraform Apply
if: github.ref == 'refs/heads/main'
run: terraform apply -auto-approve
env:
AZION_API_TOKEN: ${{ secrets.AZION_API_TOKEN }}

Versioning

Pin Versions

Always pin the provider version:

terraform {
required_providers {
azion = {
source = "aziontech/azion"
version = "2.0.0" # Pin the version
}
}
}

Use .terraform-version

For projects with multiple versions:

1.41.0

Outputs

Export Important IDs

output "workload_id" {
description = "ID of the created workload"
value = azion_workload.main.id
}
output "application_id" {
description = "ID of the created application"
value = azion_application_main_setting.main.id
}

Use Outputs in Modules

modules/application/outputs.tf
output "application_id" {
value = azion_application_main_setting.this.id
}
output "application_name" {
value = azion_application_main_setting.this.name
}

Dependencies

Depends_On

Use depends_on for implicit dependencies:

resource "azion_workload" "main" {
name = "my-workload"
}
resource "azion_workload_deployment" "main" {
workload_id = azion_workload.main.id
depends_on = [azion_workload.main]
}

Implicit References

Prefer direct references:

# Good
resource "azion_application_rule_engine" "example" {
application_id = azion_application_main_setting.example.id
}
# Avoid
resource "azion_application_rule_engine" "example" {
application_id = "12345" # Hardcoded
}

Documentation

Comment Your Code

# Workload for the main API
# This workload manages the production API
resource "azion_workload" "api" {
name = "api-prod"
}

README

Create a README.md for each module:

# Workload Module
## Usage
```hcl
module "workload" {
source = "./modules/workload"
name = "api"
}

Inputs

NameDescriptionTypeDefault
nameWorkload namestringn/a

Outputs

NameDescription
workload_idWorkload ID
---