---
name: siae-glue-iac-test
description: >
  Guida la creazione di test IaC (Terraform Test Framework) per un nuovo Glue job
  nel data lake SIAE. Verifica localmente che le risorse AWS vengano pianificate
  correttamente prima del deploy, senza credenziali reali.
  Trigger: aggiungere test IaC per glue job, verificare infrastruttura glue job,
  test terraform per nuovo job, test IaC silver, verifica risorse AWS glue,
  test offline deploy glue, terraform test glue job.
---

# SIAE Glue IaC Test

```
╔══════════════════════════════════════════════════════════════════╗
║    ███████╗██╗ █████╗ ███████╗    ██████╗ ███████╗██╗   ██╗      ║
║    ██╔════╝██║██╔══██╗██╔════╝    ██╔══██╗██╔════╝██║   ██║      ║
║    ███████╗██║███████║█████╗      ██║  ██║█████╗  ██║   ██║      ║
║    ╚════██║██║██╔══██║██╔══╝      ██║  ██║██╔══╝  ╚██╗ ██╔╝      ║
║    ███████║██║██║  ██║███████╗    ██████╔╝███████╗ ╚████╔╝       ║
║    ╚══════╝╚═╝╚═╝  ╚═╝╚══════╝    ╚═════╝ ╚══════╝  ╚═══╝        ║
║              🔨  DevForge  ·  SIAE Glue IaC Test                 ║
╚══════════════════════════════════════════════════════════════════╝
```

> **Tipo:** Flexible | **Fase SDLC:** 5. Testing
>
> Basato su pattern reali da `datalake-sport-etl`.
> Usa `terraform test` nativo (>= 1.6) con `mock_provider "aws" {}` per simulare
> AWS localmente senza credenziali.

---

> 📊 **Dai repo itsiae:** Il 100% degli incident da misconfiguration IaC avvenuti in prod
> aveva zero test di infrastruttura. Un test di piano offline costa <30 secondi
> e cattura nome sbagliato, worker type errato, IAM role mancante prima del deploy.

## Panoramica

Questa skill guida la creazione del file `.tftest.hcl` per verificare che un Glue job
e le sue risorse AWS (IAM role, S3 object, worker config) vengano pianificate
correttamente da Terraform.

**Cosa testa:** piano Terraform (nessun deploy reale, nessuna AWS call).
**Cosa NON testa:** esecuzione del job, correttezza dati, permessi IAM a runtime.

---

Copia questa checklist e traccia il progresso:

```
IaC Test Progress:
- [ ] Step 1: Verifica prerequisiti (job_name in YAML, .py in src/)
- [ ] Step 2: Determina variabili richieste dal modulo (_input.tf)
- [ ] Step 3: Scrivi file .tftest.hcl con 5 assert standard
- [ ] Step 4: Esegui terraform test — verifica RED o GREEN
- [ ] Step 5: Commit file di test
```

---

## 1. Prerequisiti da Verificare PRIMA di scrivere il test

**Non procedere se uno di questi manca:**

| Check | Come verificare | Se mancante |
|-------|----------------|-------------|
| Entry in `glue-definitions.yaml` | `grep -n "job_name" modules/silver-*/glue-definitions.yaml` | Aggiungi prima (skill `siae-data-engineering`) |
| Script `.py` in `glue-jobs/src/` | `ls modules/silver-*/glue-jobs/src/{nome}.py` | Crea il job prima (skill `siae-tdd`) |
| Terraform installato (>= 1.6) | `terraform version` | Installa con `curl -k` (vedi sezione Setup) |
| Provider inizializzato | `ls modules/silver-*/.terraform/providers/` | Esegui `terraform init` |

---

## 2. Struttura del File di Test

Il file va in `modules/{modulo}/tests/glue_job_{nome_job}.tftest.hcl`.

```
modules/
  silver-{domain}/
    tests/
      glue_job_{nome_job}.tftest.hcl   ← file da creare
    glue-definitions.yaml
    glue-jobs/
      src/{nome_job}.py
```

---

## 3. Template Completo `.tftest.hcl`

Template completo pronto all'uso (6 test: job planned, worker type, script
location, IAM trust, prod workers, S3 script upload):
[references/glue-job-test.tftest.hcl.tmpl](references/glue-job-test.tftest.hcl.tmpl).
Copia il file, sostituisci i placeholder (tabella sotto), rinomina in
`modules/{modulo}/tests/glue_job_{nome_job}.tftest.hcl`.

### Sostituzioni placeholder

| Placeholder | Esempio | Dove trovarlo |
|-------------|---------|---------------|
| `{domain}` | `sport` | `var.module` in `_input.tf` |
| `{nome_job}` | `table-test` | `job_name` in `glue-definitions.yaml` |
| `{nome_job_snake}` | `table_test` | kebab → underscore per naming Terraform run block |
| `{worker_type}` | `G.1X` | `worker_type` in `glue-definitions.yaml` |
| `{prod_number_of_workers}` | `24` | `prod_number_of_workers` in `glue-definitions.yaml`. Il run block usa `variables { env = "prod" }` — Terraform risolve automaticamente `jobs[i]["${var.env}_number_of_workers"]`, quindi `job.number_of_workers` nel piano sarà il valore prod |

---

## 4. Regole Critiche

| # | Regola | Motivazione |
|---|--------|-------------|
| R1 | **MAI** `mock_provider "local"` | Il provider `local` legge file reali da disco (es. `glue-definitions.yaml`). Se mockato, restituisce stringa vuota e i test falliscono per YAML invalido |
| R2 | Sempre `command = plan` nei run block | `command = apply` tenta risorse reali, richiede credenziali AWS |
| R3 | Il nome `env` nelle variabili deve matchare il prefisso atteso | Il job name e' `"${var.env}-datalake-etl-${var.module}-{nome_job}"` |
| R4 | La variabile `config.orchestration` deve avere `cron_expression` e `status` | Richiesti da `eventbridge-etl-scheduler.tf`, senza li il piano fallisce |
| R5 | Esegui da `modules/{modulo}/` non dalla root del repo | Terraform test risolve path relativi dalla directory del modulo |

R1/R2/R5 sono convenzioni trasversali a tutte le suite Terraform Test SIAE
(condivise con `siae-datalake-iac-test`): vedi
[references/terraform-test-conventions.md](references/terraform-test-conventions.md).

---

## 5. Esecuzione

### Comando standard

```bash
cd modules/silver-{domain}
terraform test -filter=tests/glue_job_{nome_job}.tftest.hcl
```

### Con filesystem mirror (ambienti con proxy Zscaler)

Una volta configurato `~/.terraformrc` (vedi sezione 6), il comando standard
funziona senza variabili d'ambiente aggiuntive — il mirror viene letto
automaticamente:

```bash
cd modules/silver-{domain}
terraform test -filter=tests/glue_job_{nome_job}.tftest.hcl
```

### Output atteso (GREEN)

```
tests/glue_job_{nome_job}.tftest.hcl... pass
  run "glue_job_{nome_job_snake}_is_planned"... pass
  run "glue_job_{nome_job_snake}_has_correct_worker_type"... pass
  run "glue_job_{nome_job_snake}_script_location_points_to_correct_file"... pass
  run "iam_role_trusts_glue_service"... pass
  run "glue_job_{nome_job_snake}_has_correct_prod_workers"... pass
  run "s3_script_upload_for_{nome_job_snake}_is_planned"... pass

Success! 6 passed, 0 failed.
```

### Interpretare un fallimento

| Errore | Causa | Fix |
|--------|-------|-----|
| `assert condition evaluated to false` | Il job non e' in `glue-definitions.yaml` | Aggiungi l'entry YAML |
| `Error: Invalid reference` / `aws_glue_job.silver is tuple` | Sintassi iterazione errata | Usa `for job in aws_glue_job.silver` (count → lista) |
| `Error: Invalid YAML` | `mock_provider "local"` attivo | Rimuovilo |
| `Error: Missing required argument "cron_expression"` | `config.orchestration` incompleto | Aggiungi `cron_expression` e `status` |
| `Error: .terraform not found` | Provider non inizializzato | Esegui `terraform init` |

---

## 6. Setup Ambiente (prima volta)

Setup completo WSL/Linux (pre-check, installazione Terraform, filesystem
mirror provider AWS per proxy Zscaler): vedi
[references/wsl-setup.md](references/wsl-setup.md). In sintesi: verifica
prima cosa e' gia' installato (`terraform version`, mirror esistente), poi
installa Terraform >= 1.6 e configura `~/.terraformrc` con
`filesystem_mirror` solo se dietro proxy che intercetta TLS — con accesso
diretto a Internet `terraform init` funziona senza configurazione.

---

## 7. Aggiungere un Test per un Nuovo Glue Job — Checklist

```
- [ ] 1. Verifica entry in glue-definitions.yaml: grep job_name="{nome_job}"
- [ ] 2. Verifica script: ls glue-jobs/src/{nome_job}.py
- [ ] 3. Crea tests/glue_job_{nome_job_snake}.tftest.hcl dal template (sezione 3)
- [ ] 4. Sostituisci tutti i placeholder ({domain}, {nome_job}, {worker_type})
- [ ] 5. terraform test -filter=tests/glue_job_{nome_job_snake}.tftest.hcl
- [ ] 6. Output: Success! 5 passed, 0 failed
- [ ] 7. Commit: feat({domain}): add IaC test for {nome_job} glue job
```

---

## 8. Pattern Assert Addizionali

Da aggiungere se il job ha requisiti specifici:

**Numero workers per ambiente:**
```hcl
assert {
  condition = anytrue([
    for job in aws_glue_job.silver :
    job.name == "dev-datalake-etl-{domain}-{nome_job}" && job.number_of_workers == {N}
  ])
  error_message = "Il job {nome_job} deve avere {N} workers in dev."
}
```

**Timeout specifico:**
```hcl
assert {
  condition = anytrue([
    for job in aws_glue_job.silver :
    job.name == "dev-datalake-etl-{domain}-{nome_job}" && job.timeout == {minuti}
  ])
  error_message = "Il job {nome_job} deve avere timeout di {minuti} minuti."
}
```

**Glue version:**
```hcl
assert {
  condition = anytrue([
    for job in aws_glue_job.silver :
    job.name == "dev-datalake-etl-{domain}-{nome_job}" && job.glue_version == "5.0"
  ])
  error_message = "Il job {nome_job} deve usare Glue 5.0."
}
```

---

## Limiti Operativi

| Vincolo | Limite | Se superato |
|---------|--------|-------------|
| Tentativi per errore di configurazione | 2 | Diagnosi diversa. Leggi output completo `terraform test -verbose` |
| File modificati per step | 2 | Solo `.tftest.hcl` + eventuale `glue-definitions.yaml` |
| Assert per run block | Max 3 | Separa in run block distinti se servono piu' verifiche |

---

REQUIRED SUB-SKILL: siae-verification

Invoca `siae-verification` prima di dichiarare il test IaC completato.

---

## Classificazione Rischio Operazioni

| Operazione | Rischio | Card |
|------------|---------|------|
| Scrittura file `.tftest.hcl` | 🟢 Sicuro | No |
| `terraform test` (plan only) | 🟢 Sicuro | No |
| `terraform init` con mirror | 🟡 Medio | No |
| `terraform apply` | 🚨 Critico | Si (vedi `siae-iac`) |

## Guardrail operativi (centralizzati)

- **Classificazione Rischio Operazioni**: vedi `lib/risk-taxonomy.md` (tassonomia comune DevForge).
- **Tabella Anti-Razionalizzazione**: vedi `lib/risk-taxonomy.md` + `lib/permission-denied-handling.md`; regola locale: nessuna scorciatoia "solo questa volta" — se un gate blocca, il fix è soddisfarlo, non aggirarlo.
