ship: phase-09 v1-spike-ir-and-l1-and-adapter (v1.1.4)
---ci--- project: acdl phase: 9 milestone: v1.1 status: shipped release: tag: v1.1.4 ---/ci--- Squash merge of phase/09-v1-spike-ir-and-l1-and-adapter. The IR-typed L1 module l1-s3 (interface.json typed contract + spike_instance.json IR-schema-valid instance + registry.json) + the Terraform adapter (adapters/terraform/adapter.py, IR -> Terraform root module) + generated terraform/spike/*.tf + scripts/run_spike_plan.sh. Real terraform plan against AWS succeeded: 1 to add (the S3 bucket), outputs computed, no long-lived credential in the workflow (rotated spike key from gitignored .env.secrets per D-039). verify_phase09.sh green.
This commit is contained in:
@@ -122,8 +122,8 @@
|
|||||||
| REQ-21 | 07 | complete (v1.1.2) |
|
| REQ-21 | 07 | complete (v1.1.2) |
|
||||||
| REQ-22 | 07 | complete (v1.1.2) |
|
| REQ-22 | 07 | complete (v1.1.2) |
|
||||||
| REQ-23 | 08 | complete (v1.1.3) |
|
| REQ-23 | 08 | complete (v1.1.3) |
|
||||||
| REQ-24 | 09 | pending |
|
| REQ-24 | 09 | complete (v1.1.4) |
|
||||||
| REQ-25 | 10 | pending |
|
| REQ-25 | 10 | pending |
|
||||||
| REQ-26 | 09 | pending |
|
| REQ-26 | 09 | complete (v1.1.4) |
|
||||||
| REQ-27 | 10 | pending |
|
| REQ-27 | 10 | pending |
|
||||||
| REQ-28 | 10 | pending |
|
| REQ-28 | 10 | pending |
|
||||||
+1
-1
@@ -112,7 +112,7 @@ milestone COMPLETE: `v1.2.0` (feature milestone, next minor per ship.md).
|
|||||||
|
|
||||||
### Phase 09 — v1-spike-ir-and-l1-and-adapter
|
### Phase 09 — v1-spike-ir-and-l1-and-adapter
|
||||||
- **Description:** Implement the Target Stack IR, one real L1 `l1-s3` (IR-typed interface, registered), and the Terraform adapter that compiles the IR → Terraform `variable`/`output` + root module and emits a real `terraform plan` against AWS (via the rotated-key secret per D-039; OIDC is v1.2). State in S3 + DynamoDB.
|
- **Description:** Implement the Target Stack IR, one real L1 `l1-s3` (IR-typed interface, registered), and the Terraform adapter that compiles the IR → Terraform `variable`/`output` + root module and emits a real `terraform plan` against AWS (via the rotated-key secret per D-039; OIDC is v1.2). State in S3 + DynamoDB.
|
||||||
- **Status:** pending
|
- **Status:** complete (v1.1.4)
|
||||||
- **Depends on:** [08]
|
- **Depends on:** [08]
|
||||||
- **Requirements:** REQ-24, REQ-26
|
- **Requirements:** REQ-24, REQ-26
|
||||||
- **Success Criteria:**
|
- **Success Criteria:**
|
||||||
|
|||||||
+4
-1
@@ -9,4 +9,7 @@ audit.json
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
runner-data/
|
runner-data/
|
||||||
.env.secrets
|
.env.secrets
|
||||||
terraform/bootstrap/.bootstrap_state.json
|
terraform/bootstrap/.bootstrap_state.json
|
||||||
|
terraform/spike/.terraform/
|
||||||
|
terraform/spike/tfplan
|
||||||
|
terraform/spike/*.tfstate*
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
"""ACDL Terraform adapter — compile a Target Stack IR instance to Terraform.
|
||||||
|
|
||||||
|
ARCHITECTURE.md §12.2: the adapter translates the IR-typed L1 interface
|
||||||
|
to a Terraform variable/output block, the L2 thin-composition tree to a
|
||||||
|
root module that calls the L1 modules, the IR-typed relationships to
|
||||||
|
Terraform module references, and emits a Terraform plan from the IR.
|
||||||
|
|
||||||
|
The adapter is a THIN LAYER; it does not own L1/L2 content — it only
|
||||||
|
translates. Substrate-agnostic in, Terraform out.
|
||||||
|
|
||||||
|
Spike scope (Phase 09): handles one L1 (l1-s3, IR type aws:s3:bucket).
|
||||||
|
L2 thin-composition + relationships land in Phase 10.
|
||||||
|
|
||||||
|
CLI: adapter.py <ir_instance.json> <out_dir>
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# IR type -> Terraform resource type. The only substrate-specific table.
|
||||||
|
# As more L1s land, this grows; the L1 content + IR do not change.
|
||||||
|
TYPE_MAP = {
|
||||||
|
"aws:s3:bucket": "aws_s3_bucket",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _tf_block(block_type, name, body_lines, indent=2):
|
||||||
|
head = f'{block_type} "{name}" {{'
|
||||||
|
body = "\n".join(f" {l}" for l in body_lines)
|
||||||
|
return f"{head}\n{body}\n}}\n"
|
||||||
|
|
||||||
|
|
||||||
|
def _emit_resource(resource):
|
||||||
|
rtype = resource["type"]
|
||||||
|
rid = resource["id"]
|
||||||
|
tf_type = TYPE_MAP.get(rtype)
|
||||||
|
if not tf_type:
|
||||||
|
raise ValueError(f"unknown IR type {rtype!r} (adapter spike handles aws:s3:bucket only)")
|
||||||
|
body = []
|
||||||
|
inputs = resource.get("inputs", {})
|
||||||
|
# S3 bucket: bucket_name -> bucket arg; region -> provider (handled separately)
|
||||||
|
if "bucket_name" in inputs:
|
||||||
|
body.append(f'bucket = "{inputs["bucket_name"]}"')
|
||||||
|
# NFR: versioning (default true)
|
||||||
|
nfrs = resource.get("nfrs", {})
|
||||||
|
versioning = nfrs.get("versioning", True) if isinstance(nfrs, dict) else True
|
||||||
|
body.append("versioning {")
|
||||||
|
body.append(f' enabled = {"true" if versioning else "false"}')
|
||||||
|
body.append("}")
|
||||||
|
return _tf_block("resource", f'aws_s3_bucket.{rid}', body) if False else _resource_block(rid, tf_type, body)
|
||||||
|
|
||||||
|
|
||||||
|
def _resource_block(rid, tf_type, body):
|
||||||
|
"""Emit a top-level resource block."""
|
||||||
|
head = f'resource "{tf_type}" "{rid}" {{'
|
||||||
|
body_str = "\n".join(f" {l}" for l in body)
|
||||||
|
return f"{head}\n{body_str}\n}}\n"
|
||||||
|
|
||||||
|
|
||||||
|
def _emit_output(output_name, value_expr):
|
||||||
|
return f'output "{output_name}" {{\n value = {value_expr}\n}}\n'
|
||||||
|
|
||||||
|
|
||||||
|
def adapt(ir_instance, out_dir):
|
||||||
|
"""Emit main.tf + terraform.tf + providers.tf to out_dir for the IR instance."""
|
||||||
|
os.makedirs(out_dir, exist_ok=True)
|
||||||
|
stack = ir_instance["stack"]
|
||||||
|
resources = ir_instance["resources"]
|
||||||
|
|
||||||
|
# --- providers.tf: aws provider, region from the first resource's inputs.region ---
|
||||||
|
region = "us-east-1"
|
||||||
|
for r in resources:
|
||||||
|
if "region" in r.get("inputs", {}):
|
||||||
|
region = r["inputs"]["region"]
|
||||||
|
break
|
||||||
|
providers_tf = (
|
||||||
|
f'provider "aws" {{\n'
|
||||||
|
f' region = "{region}"\n'
|
||||||
|
f'}}\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- terraform.tf: required_version + required_providers + S3 backend (no DynamoDB lock per D-P09-1) ---
|
||||||
|
terraform_tf = (
|
||||||
|
'terraform {\n'
|
||||||
|
' required_version = ">= 1.9, < 1.10"\n'
|
||||||
|
' required_providers {\n'
|
||||||
|
' aws = {\n'
|
||||||
|
' source = "hashicorp/aws"\n'
|
||||||
|
' version = "~> 5.0"\n'
|
||||||
|
' }\n'
|
||||||
|
' }\n'
|
||||||
|
' backend "s3" {\n'
|
||||||
|
' bucket = "acdl-tfstate-581513795199-us-east-1"\n'
|
||||||
|
' key = "spike/l1-s3/terraform.tfstate"\n'
|
||||||
|
' region = "us-east-1"\n'
|
||||||
|
' }\n'
|
||||||
|
'}\n'
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- main.tf: resources + outputs ---
|
||||||
|
main_tf_parts = []
|
||||||
|
for r in resources:
|
||||||
|
main_tf_parts.append(_emit_resource(r))
|
||||||
|
rid = r["id"]
|
||||||
|
outputs = r.get("outputs", {})
|
||||||
|
for out_name in outputs:
|
||||||
|
if out_name == "bucket_arn":
|
||||||
|
main_tf_parts.append(_emit_output("bucket_arn", f"aws_s3_bucket.{rid}.arn"))
|
||||||
|
elif out_name == "bucket_name":
|
||||||
|
main_tf_parts.append(_emit_output("bucket_name", f"aws_s3_bucket.{rid}.id"))
|
||||||
|
main_tf = "\n".join(main_tf_parts)
|
||||||
|
|
||||||
|
with open(os.path.join(out_dir, "main.tf"), "w") as fh:
|
||||||
|
fh.write(main_tf)
|
||||||
|
with open(os.path.join(out_dir, "terraform.tf"), "w") as fh:
|
||||||
|
fh.write(terraform_tf)
|
||||||
|
with open(os.path.join(out_dir, "providers.tf"), "w") as fh:
|
||||||
|
fh.write(providers_tf)
|
||||||
|
return out_dir
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("usage: adapter.py <ir_instance.json> <out_dir>", file=sys.stderr)
|
||||||
|
sys.exit(2)
|
||||||
|
with open(sys.argv[1], "r") as fh:
|
||||||
|
ir = json.load(fh)
|
||||||
|
adapt(ir, sys.argv[2])
|
||||||
|
print(f"adapter: emitted terraform to {sys.argv[2]}", file=sys.stderr)
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# l1-s3 — S3 bucket primitive
|
||||||
|
|
||||||
|
The first real L1 module for the v1.1 spike. Single-purpose,
|
||||||
|
substrate-agnostic (the IR type is `aws:s3:bucket`, not a Terraform
|
||||||
|
resource type).
|
||||||
|
|
||||||
|
## Interface (the IR-typed contract)
|
||||||
|
|
||||||
|
See `interface.json`: inputs `bucket_name` + `region` (strings), outputs
|
||||||
|
`bucket_arn` (arn) + `bucket_name` (string), NFR `versioning` (bool,
|
||||||
|
default true).
|
||||||
|
|
||||||
|
## IR → Terraform mapping (performed by the adapter)
|
||||||
|
|
||||||
|
The Terraform adapter (`adapters/terraform/adapter.py`) translates this
|
||||||
|
L1's IR shape to Terraform:
|
||||||
|
|
||||||
|
| IR | Terraform |
|
||||||
|
|----|-----------|
|
||||||
|
| `resource.type = aws:s3:bucket` | `resource "aws_s3_bucket" "<id>" { ... }` |
|
||||||
|
| `resource.inputs.bucket_name` | `bucket = <value>` arg |
|
||||||
|
| `resource.inputs.region` | `provider "aws" { region = <value> }` |
|
||||||
|
| `resource.outputs.bucket_arn` | `output "bucket_arn" { value = aws_s3_bucket.<id>.arn }` |
|
||||||
|
| `resource.outputs.bucket_name` | `output "bucket_name" { value = aws_s3_bucket.<id>.id }` |
|
||||||
|
|
||||||
|
The adapter is a thin layer (ARCHITECTURE.md §12.2); it does not own L1
|
||||||
|
content — it only translates.
|
||||||
|
|
||||||
|
## Spike instance
|
||||||
|
|
||||||
|
`spike_instance.json` is a concrete stack instance (with values
|
||||||
|
`bucket_name=acdl-spike-bucket`, `region=us-east-1`) that validates
|
||||||
|
against `schemas/ir.schema.json`. The adapter consumes this instance
|
||||||
|
(not the interface contract) to emit Terraform.
|
||||||
|
|
||||||
|
## Versioning (W3.D)
|
||||||
|
|
||||||
|
`1.0.0` — interface MAJOR, behavior MINOR, lifecycle PATCH. MAJOR bumps
|
||||||
|
require a new registry entry (immutable publication); old entries enter
|
||||||
|
a 12-month deprecation window.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"name": "l1-s3",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"kind": "l1",
|
||||||
|
"type": "aws:s3:bucket",
|
||||||
|
"description": "S3 bucket primitive (substrate-agnostic IR type aws:s3:bucket; the Terraform adapter translates to aws_s3_bucket).",
|
||||||
|
"inputs": {
|
||||||
|
"bucket_name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Globally-unique S3 bucket name.",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "AWS region the bucket is created in.",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"outputs": {
|
||||||
|
"bucket_arn": {
|
||||||
|
"type": "arn",
|
||||||
|
"description": "The S3 bucket ARN."
|
||||||
|
},
|
||||||
|
"bucket_name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The bucket name (echoes the input)."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nfrs": {
|
||||||
|
"versioning": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enable S3 versioning (default true).",
|
||||||
|
"default": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0.0",
|
||||||
|
"stack": {
|
||||||
|
"name": "l1-s3",
|
||||||
|
"kind": "l1",
|
||||||
|
"depth": 1
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"id": "s3",
|
||||||
|
"type": "aws:s3:bucket",
|
||||||
|
"module": "l1-s3@1.0.0",
|
||||||
|
"inputs": {
|
||||||
|
"bucket_name": "acdl-spike-bucket",
|
||||||
|
"region": "us-east-1"
|
||||||
|
},
|
||||||
|
"outputs": {
|
||||||
|
"bucket_arn": {"type": "arn", "description": "The S3 bucket ARN."},
|
||||||
|
"bucket_name": {"type": "string", "description": "The bucket name."}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"l1-s3": {
|
||||||
|
"1.0.0": {
|
||||||
|
"interface": "modules-ir/l1/l1-s3/interface.json",
|
||||||
|
"published_at": "2026-07-21T19:00:00Z",
|
||||||
|
"deprecated": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+29
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# scripts/run_spike_plan.sh - run the v1.1 spike's real terraform plan against AWS.
|
||||||
|
#
|
||||||
|
# Uses the rotated spike key (D-039) from gitignored .env.secrets.
|
||||||
|
# Plan-only (no apply); -lock=false per D-P09-1 (the spike's DynamoDB
|
||||||
|
# outbox table PK is contractId, not Terraform's expected LockID; plan
|
||||||
|
# does not write state so locking is unnecessary; v1.2 creates a proper
|
||||||
|
# LockID-keyed acdl-tflock table).
|
||||||
|
set -u
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
|
||||||
|
ENV_FILE="$ROOT/.env.secrets"
|
||||||
|
[ -f "$ENV_FILE" ] || { echo "FAIL: .env.secrets missing (run scripts/rotate_spike_key.sh)" >&2; exit 1; }
|
||||||
|
set -a
|
||||||
|
. "$ENV_FILE"
|
||||||
|
set +a
|
||||||
|
export AWS_ACCESS_KEY_ID="$ACDL_AWS_ACCESS_KEY_ID"
|
||||||
|
export AWS_SECRET_ACCESS_KEY="$ACDL_AWS_SECRET_ACCESS_KEY"
|
||||||
|
export AWS_DEFAULT_REGION="$AWS_DEFAULT_REGION"
|
||||||
|
|
||||||
|
cd terraform/spike
|
||||||
|
echo "=== terraform init -lock=false -input=false ==="
|
||||||
|
terraform init -lock=false -input=false
|
||||||
|
echo "=== terraform validate ==="
|
||||||
|
terraform validate
|
||||||
|
echo "=== terraform plan -lock=false -input=false -out=tfplan ==="
|
||||||
|
terraform plan -lock=false -input=false -out=tfplan
|
||||||
|
echo "spike plan OK"
|
||||||
Executable
+77
@@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# scripts/verify_phase09.sh - Phase 09 v1-spike-ir-and-l1-and-adapter gate.
|
||||||
|
set -u
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
cd "$ROOT"
|
||||||
|
fail() { echo "FAIL: $*" >&2; exit 1; }
|
||||||
|
ok() { echo "ok: $*"; }
|
||||||
|
|
||||||
|
# --- Check 1: L1 module files exist ---
|
||||||
|
for f in modules-ir/l1/l1-s3/interface.json \
|
||||||
|
modules-ir/l1/l1-s3/spike_instance.json \
|
||||||
|
modules-ir/l1/l1-s3/README.md \
|
||||||
|
modules-ir/registry.json \
|
||||||
|
adapters/terraform/adapter.py \
|
||||||
|
terraform/spike/main.tf \
|
||||||
|
terraform/spike/terraform.tf \
|
||||||
|
terraform/spike/providers.tf \
|
||||||
|
scripts/run_spike_plan.sh; do
|
||||||
|
[ -f "$f" ] || fail "missing $f"
|
||||||
|
done
|
||||||
|
ok "all 9 deliverable files exist"
|
||||||
|
|
||||||
|
# --- Check 2: spike_instance.json validates against ir.schema.json ---
|
||||||
|
( cd /tmp && python3 -c "
|
||||||
|
import json, jsonschema
|
||||||
|
inst = json.load(open('$ROOT/modules-ir/l1/l1-s3/spike_instance.json'))
|
||||||
|
schema = json.load(open('$ROOT/schemas/ir.schema.json'))
|
||||||
|
jsonschema.validate(inst, schema)
|
||||||
|
" ) || fail "spike_instance.json does not validate against ir.schema.json"
|
||||||
|
ok "spike_instance.json validates against ir.schema.json"
|
||||||
|
|
||||||
|
# --- Check 3: registry has the l1-s3@1.0.0 entry ---
|
||||||
|
python3 -c "
|
||||||
|
import json
|
||||||
|
r = json.load(open('modules-ir/registry.json'))
|
||||||
|
assert 'l1-s3' in r and '1.0.0' in r['l1-s3'], 'l1-s3@1.0.0 missing'
|
||||||
|
print('l1-s3@1.0.0 present')
|
||||||
|
" || fail "registry missing l1-s3@1.0.0"
|
||||||
|
ok "registry has l1-s3@1.0.0"
|
||||||
|
|
||||||
|
# --- Check 4: adapter py_compiles + generates terraform containing aws_s3_bucket ---
|
||||||
|
python3 -m py_compile adapters/terraform/adapter.py || fail "adapter.py py_compile failed"
|
||||||
|
TMP=$(mktemp -d)
|
||||||
|
python3 adapters/terraform/adapter.py modules-ir/l1/l1-s3/spike_instance.json "$TMP" 2>/dev/null
|
||||||
|
grep -q 'resource "aws_s3_bucket"' "$TMP/main.tf" || fail "adapter did not emit aws_s3_bucket resource"
|
||||||
|
grep -q 'output "bucket_arn"' "$TMP/main.tf" || fail "adapter did not emit bucket_arn output"
|
||||||
|
ok "adapter.py py_compiles + emits aws_s3_bucket + bucket_arn output"
|
||||||
|
|
||||||
|
# --- Check 5: generated terraform/spike/*.tf match a fresh adapter run (D-P09-4 reproducibility) ---
|
||||||
|
diff "$TMP/main.tf" terraform/spike/main.tf || fail "terraform/spike/main.tf is stale (differs from a fresh adapter run)"
|
||||||
|
diff "$TMP/terraform.tf" terraform/spike/terraform.tf || fail "terraform/spike/terraform.tf is stale"
|
||||||
|
diff "$TMP/providers.tf" terraform/spike/providers.tf || fail "terraform/spike/providers.tf is stale"
|
||||||
|
ok "terraform/spike/*.tf match a fresh adapter run (reproducible)"
|
||||||
|
rm -rf "$TMP"
|
||||||
|
|
||||||
|
# --- Check 6: no long-lived credential (AKIA) in committed files ---
|
||||||
|
# Skip .terraform/ (provider binaries contain AKIA bytes; gitignored anyway).
|
||||||
|
if grep -rn --exclude-dir=.terraform "AKIA" terraform/spike/ adapters/ modules-ir/ 2>/dev/null; then
|
||||||
|
fail "AKIA key id found in committed files (terraform/spike/ adapters/ modules-ir/)"
|
||||||
|
fi
|
||||||
|
ok "no AKIA in committed files (excluding .terraform/ provider binaries)"
|
||||||
|
|
||||||
|
# --- Check 7: .env.secrets + terraform working artifacts are gitignored ---
|
||||||
|
git check-ignore -q .env.secrets || fail ".env.secrets not gitignored"
|
||||||
|
git check-ignore -q terraform/spike/.terraform/ || fail "terraform/spike/.terraform/ not gitignored"
|
||||||
|
git check-ignore -q terraform/spike/tfplan || fail "terraform/spike/tfplan not gitignored"
|
||||||
|
ok "secrets + TF working artifacts gitignored"
|
||||||
|
|
||||||
|
# --- Check 8: real terraform plan against AWS succeeds (uses rotated spike key) ---
|
||||||
|
bash scripts/run_spike_plan.sh > /tmp/verify_phase09_plan.log 2>&1 || {
|
||||||
|
cat /tmp/verify_phase09_plan.log >&2
|
||||||
|
fail "scripts/run_spike_plan.sh failed (see /tmp/verify_phase09_plan.log)"
|
||||||
|
}
|
||||||
|
grep -q "spike plan OK" /tmp/verify_phase09_plan.log || fail "run_spike_plan.sh did not print 'spike plan OK'"
|
||||||
|
ok "real terraform plan against AWS succeeded (rotated spike key, plan-only, -lock=false)"
|
||||||
|
|
||||||
|
echo "VERIFIED — Phase 09: IR + l1-s3 + Terraform adapter; real terraform plan succeeds"
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
resource "aws_s3_bucket" "s3" {
|
||||||
|
bucket = "acdl-spike-bucket"
|
||||||
|
versioning {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output "bucket_arn" {
|
||||||
|
value = aws_s3_bucket.s3.arn
|
||||||
|
}
|
||||||
|
|
||||||
|
output "bucket_name" {
|
||||||
|
value = aws_s3_bucket.s3.id
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
provider "aws" {
|
||||||
|
region = "us-east-1"
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.9, < 1.10"
|
||||||
|
required_providers {
|
||||||
|
aws = {
|
||||||
|
source = "hashicorp/aws"
|
||||||
|
version = "~> 5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
backend "s3" {
|
||||||
|
bucket = "acdl-tfstate-581513795199-us-east-1"
|
||||||
|
key = "spike/l1-s3/terraform.tfstate"
|
||||||
|
region = "us-east-1"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user