Files
factory/iac/cloudflare.tf
Gabriel Radureau a0fbe5c655 fix(iac): import existing EU R2 bucket into state
Run #28 applied cleanly except cloudflare_r2_bucket.arcodange_tf: the bucket
exists in the EU jurisdiction, but its prior state entry lacked the jurisdiction,
so cloudflare provider >=5.20 read it as not-found, removed it from state, and
then failed to recreate it ("already exists"). Add a config-driven import block
with the jurisdiction-qualified id (<account_id>/<bucket_name>/<jurisdiction>) so
the next apply adopts the real bucket. No-op once reconciled; removable after.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 13:19:32 +02:00

112 lines
3.5 KiB
HCL

data "cloudflare_account" "arcodange" {
filter = {
name = "arcodange@gmail.com"
}
}
locals {
cloudflare_account_id = data.cloudflare_account.arcodange.account_id
}
resource "cloudflare_r2_bucket" "arcodange_tf" {
account_id = local.cloudflare_account_id
name = "arcodange-tf"
jurisdiction = "eu"
}
# One-time state reconcile. The arcodange-tf R2 bucket already exists in the EU jurisdiction, but its
# prior state entry lacked the jurisdiction, so cloudflare provider >= 5.20 read it as "not found" and
# tried to recreate it (which fails: "already exists"). Re-import it with the jurisdiction-qualified id
# (<account_id>/<bucket_name>/<jurisdiction>) so the next apply adopts the real bucket instead.
# This block is a no-op once the bucket is in state and can be removed afterwards.
import {
to = cloudflare_r2_bucket.arcodange_tf
id = "f7fcf28c0823cecb44e53b6e92d5144f/arcodange-tf/eu"
}
module "cf_r2_arcodange_tf_token" {
source = "./modules/cloudflare_token"
account_id = local.cloudflare_account_id
bucket = cloudflare_r2_bucket.arcodange_tf
token_name = "r2_arcodange_tf_token"
permissions = {
bucket = [
"account:Workers R2 Storage Read",
"bucket:Workers R2 Storage Bucket Item Write",
]
account = [
"account:Account Settings Read",
]
}
}
resource "vault_kv_secret" "cf_r2_arcodange_tf" {
path = "kvv1/cloudflare/r2/arcodange-tf"
data_json = jsonencode({
S3_SECRET_ACCESS_KEY = module.cf_r2_arcodange_tf_token.r2_credentials.secret_access_key
S3_ACCESS_KEY = module.cf_r2_arcodange_tf_token.r2_credentials.access_key_id
S3_ENDPOINT = "https://${local.cloudflare_account_id}.eu.r2.cloudflarestorage.com"
})
}
data "vault_policy_document" "cf_r2_arcodange_tf" {
rule {
path = "kvv1/cloudflare/r2/arcodange-tf"
capabilities = ["read"]
}
rule {
path = "kvv1/zoho/self_client" # zoho mail client is created manually
capabilities = ["read"]
}
}
resource "vault_policy" "cf_r2_arcodange_tf" {
name = "factory__cf_r2_arcodange_tf"
policy = data.vault_policy_document.cf_r2_arcodange_tf.hcl
}
data "gitea_repo" "cms" {
name = "cms"
username = "arcodange-org"
}
module "cf_arcodange_cms_token" {
source = "./modules/cloudflare_token"
account_id = local.cloudflare_account_id
bucket = cloudflare_r2_bucket.arcodange_tf
token_name = "cf_arcodange_cms_token"
permissions = {
account = [
"account:Pages Write",
"account:Account DNS Settings Write",
"account:Account Settings Read",
"zone:Zone Write",
"zone:Zone Settings Write",
"zone:DNS Write",
"account:Cloudflare Tunnel Write",
"account:Turnstile Sites Write",
]
}
}
resource "gitea_repository_actions_secret" "cf_arcodange_cms_token" {
repository = data.gitea_repo.cms.name
repository_owner = data.gitea_repo.cms.username
secret_name = "CLOUDFLARE_API_TOKEN"
secret_value = module.cf_arcodange_cms_token.token
}
resource "gitea_repository_actions_secret" "cf_account_id_cms" {
repository = data.gitea_repo.cms.name
repository_owner = data.gitea_repo.cms.username
secret_name = "CLOUDFLARE_ACCOUNT_ID"
secret_value = local.cloudflare_account_id
}
output "token" {
value = module.cf_arcodange_cms_token.token
sensitive = true
}
resource "vault_kv_secret" "cf_arcodange_cms_token" {
path = "kvv1/cloudflare/cms/cf_arcodange_cms_token"
data_json = jsonencode({
token = module.cf_arcodange_cms_token.token
})
}