# Best Practices - Terraform Provider

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:

```hcl
# 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:

```hcl
# 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:

```hcl
# 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`:

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

### Don't Commit Secrets

Add to `.gitignore`:

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

### Use Environment Variables

```bash
export TF_VAR_api_token="your-token"
```

---

## Modularization

### Creating Modules

Create reusable modules:

```hcl
# 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

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

---

## CI/CD

### Basic Pipeline

Example with GitHub Actions:

```yaml
# .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:

```hcl
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

```hcl
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

```hcl
# 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:

```hcl
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:

```hcl
# 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

```hcl
# 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:

```markdown
# Workload Module

## Usage

```hcl
module "workload" {
  source = "./modules/workload"
  name   = "api"
}
```

## Inputs

| Name | Description | Type | Default |
|------|-------------|------|---------|
| name | Workload name | string | n/a |

## Outputs

| Name | Description |
|------|-------------|
| workload_id | Workload ID |
```

---