diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d7175c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.terraform +.terraform.lock.hcl +env +.terragrunt-cache +tfplan diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..0439d93 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: end-of-file-fixer + types: [yaml] + - id: trailing-whitespace + types: [yaml] + - repo: https://github.com/gruntwork-io/pre-commit + rev: v0.1.30 + hooks: + - id: tofu-fmt + - id: terragrunt-hcl-fmt + - repo: https://github.com/adrienverge/yamllint.git + rev: v1.37.1 + hooks: + - id: yamllint + args: + [ + "-d {extends: relaxed, rules: {line-length: disable}}", + "-s", + ] diff --git a/.woodpecker/apply.yaml b/.woodpecker/apply.yaml new file mode 100644 index 0000000..e388fb8 --- /dev/null +++ b/.woodpecker/apply.yaml @@ -0,0 +1,22 @@ +when: + - event: push + branch: main + +steps: + - name: apply + image: git.unkin.net/unkin/almalinux9-opentofu:20260606 + environment: + VAULT_AUTH_METHOD: kubernetes + commands: + - dnf install vault -y + - make apply + backend_options: + kubernetes: + serviceAccountName: terraform-enc + resources: + requests: + memory: 512Mi + cpu: 1 + limits: + memory: 2Gi + cpu: 2 diff --git a/.woodpecker/plan.yaml b/.woodpecker/plan.yaml new file mode 100644 index 0000000..2aab11a --- /dev/null +++ b/.woodpecker/plan.yaml @@ -0,0 +1,21 @@ +when: + - event: pull_request + +steps: + - name: plan + image: git.unkin.net/unkin/almalinux9-opentofu:20260606 + environment: + VAULT_AUTH_METHOD: kubernetes + commands: + - dnf install vault -y + - make plan + backend_options: + kubernetes: + serviceAccountName: terraform-enc + resources: + requests: + memory: 512Mi + cpu: 1 + limits: + memory: 2Gi + cpu: 2 diff --git a/.woodpecker/pre-commit.yaml b/.woodpecker/pre-commit.yaml new file mode 100644 index 0000000..5c5738f --- /dev/null +++ b/.woodpecker/pre-commit.yaml @@ -0,0 +1,18 @@ +when: + - event: pull_request + +steps: + - name: pre-commit + image: git.unkin.net/unkin/almalinux9-opentofu:20260606 + commands: + - uvx pre-commit run --all-files + backend_options: + kubernetes: + serviceAccountName: default + resources: + requests: + memory: 512Mi + cpu: 1 + limits: + memory: 2Gi + cpu: 2 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..23f02e5 --- /dev/null +++ b/Makefile @@ -0,0 +1,51 @@ +.PHONY: init plan apply apply-if-changes format pre-commit + +VAULT_AUTH_METHOD ?= approle +VAULT_K8S_ROLE ?= woodpecker_terraform_enc +VAULT_K8S_MOUNT ?= auth/k8s/au/syd1 +VAULT_K8S_JWT_PATH ?= /var/run/secrets/kubernetes.io/serviceaccount/token + +define vault_env + @export VAULT_ADDR="https://vault.service.consul:8200" && \ + if [ "$(VAULT_AUTH_METHOD)" = "kubernetes" ]; then \ + export VAULT_TOKEN=$$(vault write -field=token $(VAULT_K8S_MOUNT)/login role=$(VAULT_K8S_ROLE) jwt=$$(cat $(VAULT_K8S_JWT_PATH))); \ + else \ + export VAULT_TOKEN=$$(vault write -field=token auth/approle/login role_id=$$VAULT_ROLEID); \ + fi && \ + export CONSUL_HTTP_TOKEN=$$(vault read -field=token consul_root/au/syd1/creds/terraform-enc) && \ + export ENCAPI_WRITE_TOKEN=$$(vault kv get -field=ENCAPI_WRITE_TOKEN kv/kubernetes/namespace/encapi/default/environment) +endef + +init: + @$(call vault_env) && \ + terragrunt run --all --non-interactive init -- -upgrade + +plan: init + @$(call vault_env) && \ + terragrunt run --all --parallelism 4 --non-interactive plan + +apply-if-changes: init + @$(call vault_env) && \ + terragrunt run --all --parallelism 4 --non-interactive plan -- -detailed-exitcode -out=tfplan; \ + EXIT_CODE=$$?; \ + if [ $$EXIT_CODE -eq 2 ]; then \ + $(call vault_env) && \ + terragrunt run --all --parallelism 2 --non-interactive apply -- tfplan; \ + elif [ $$EXIT_CODE -eq 0 ]; then \ + echo "No changes detected, skipping apply."; \ + else \ + exit $$EXIT_CODE; \ + fi + +apply: init + @$(call vault_env) && \ + terragrunt run --all --parallelism 2 --non-interactive apply + +format: + @echo "Formatting OpenTofu files..." + @tofu fmt -recursive . + @echo "Formatting Terragrunt files..." + @terragrunt hcl fmt + +pre-commit: + @uvx pre-commit run --all-files diff --git a/README.md b/README.md index a1786f0..1ee3ac3 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,60 @@ # terragrunt-enc -Single source of truth for encapi ENC data (statuses, roles, nodes), managed via Terraform/Terragrunt. Supersedes Cobbler node classification for Puppet. \ No newline at end of file +Single source of truth for [encapi](https://git.unkin.net/unkin/encapi) ENC +data, managed with Terraform/Terragrunt. This repo owns every Puppet node +classification the estate has: + +- **statuses** — Puppet environments (`production`, `develop`, `testing`) +- **roles** — the Puppet role classes (`roles::…`) a node can be assigned +- **nodes** — the certname → role + environment mapping for all 143 hosts + (130 container VMs + 13 `prodnxsr*` physicals) + +It **supersedes Cobbler** as the classification source for Puppet: encapi is the +live ENC, and this repo is the declarative, reviewed input to it. It also +supersedes the dual-write approach that was prototyped in terraform-incus +(PR #39) — terraform-incus is no longer involved in ENC data. + +## Layout + +``` +config/ + root.hcl # terragrunt root: consul backend (infra/terraform/enc//state) + encapi/ + terragrunt.hcl # leaf: feeds the three YAMLs into modules/encapi + statuses.yaml # Puppet environments + roles.yaml # Puppet role classes + nodes.yaml # certname -> {role, environment} for all 143 hosts +modules/ + encapi/ # encapi_status / encapi_role / encapi_node resources, + # ordered so nodes depend on their role + status (FK) +ci/ + extract_incus_nodes.py # regenerates the container-VM block of nodes.yaml + # from a terraform-incus checkout +``` + +The encapi provider comes from the internal registry +(`artifactapi.k8s.syd1.au.unkin.net/terraform-unkin/encapi` v0.1.0). Writes to +encapi are authenticated with `ENCAPI_WRITE_TOKEN`, read from Vault by the +Makefile. + +## Data provenance + +- **130 container VMs** (`environment: production`) are extracted from + terraform-incus `config/instances//config.yaml`: certname is + `.main.unkin.net`, role is `cobbler_mgmt_classes[0]` (default + `roles::base`). terraform-incus itself is not modified — the data is copied in + here as plain config. Re-run `ci/extract_incus_nodes.py --incus-repo ` + to refresh after VM changes. +- **13 `prodnxsr*` physical nodes** (`environment: develop`) are the bare-metal + hypervisor / k8s nodes, not managed by the incus module. Their roles come from + the PuppetDB `enc_role` fact and are maintained by hand in `nodes.yaml`. + +## Usage + +CI (Woodpecker) plans on every PR and applies on merge to `main`, authenticating +to Vault via kubernetes auth (`terraform-enc` ServiceAccount). Locally: + +```sh +make plan # approle auth by default (needs env with VAULT_ROLEID) +make apply +``` diff --git a/ci/extract_incus_nodes.py b/ci/extract_incus_nodes.py new file mode 100755 index 0000000..d63a048 --- /dev/null +++ b/ci/extract_incus_nodes.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Regenerate the container-VM portion of config/encapi/nodes.yaml from a +checkout of terraform-incus. + +encapi is the single source of truth for Puppet ENC data, but the 130 container +VMs are *defined* in terraform-incus (config/instances//config.yaml). This +script lifts that classification into plain config data here: + + certname = . (cobbler_domain = main.unkin.net) + role = cobbler_mgmt_classes[0] (default roles::base) + environment = production + +It only rewrites the "container VMs" block; the prodnxsr physical nodes below +the marker are maintained by hand and left untouched. + +Usage: + python3 ci/extract_incus_nodes.py --incus-repo /path/to/terraform-incus +""" +import argparse +import os +import sys + +try: + import yaml +except ImportError: + sys.exit("PyYAML required: pip install pyyaml") + +PHYS_MARKER = "# --- prodnxsr physical nodes (develop) ---" +VM_MARKER = "# --- container VMs (production) ---" + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--incus-repo", required=True, + help="Path to a terraform-incus checkout") + ap.add_argument("--domain", default="main.unkin.net") + ap.add_argument("--nodes-file", + default=os.path.join(os.path.dirname(__file__), + "..", "config", "encapi", "nodes.yaml")) + args = ap.parse_args() + + inst = os.path.join(args.incus_repo, "config", "instances") + dirs = sorted(d for d in os.listdir(inst) + if os.path.isdir(os.path.join(inst, d)) + and os.path.exists(os.path.join(inst, d, "config.yaml"))) + + vm_lines = [] + for d in dirs: + with open(os.path.join(inst, d, "config.yaml")) as f: + cfg = yaml.safe_load(f) or {} + classes = cfg.get("cobbler_mgmt_classes") or [] + role = classes[0] if classes else "roles::base" + vm_lines.append(f"{d}.{args.domain}:") + vm_lines.append(f" role: {role}") + vm_lines.append(" environment: production") + + nodes_file = os.path.abspath(args.nodes_file) + with open(nodes_file) as f: + existing = f.read().splitlines() + + # Preserve everything from the physical-nodes marker onward. + try: + idx = existing.index(PHYS_MARKER) + except ValueError: + sys.exit(f"marker not found in {nodes_file}: {PHYS_MARKER!r}") + tail = existing[idx:] + + # Preserve only the top-of-file comment block, stopping at the VM marker. + header = [] + for ln in existing[:idx]: + if ln == VM_MARKER: + break + header.append(ln) + while header and header[-1] == "": + header.pop() + + out = header + ["", VM_MARKER] + vm_lines + ["", *tail] + with open(nodes_file, "w") as f: + f.write("\n".join(out).rstrip("\n") + "\n") + print(f"wrote {len(dirs)} container VM records to {nodes_file}") + + +if __name__ == "__main__": + main() diff --git a/config/encapi/nodes.yaml b/config/encapi/nodes.yaml new file mode 100644 index 0000000..6ccbd27 --- /dev/null +++ b/config/encapi/nodes.yaml @@ -0,0 +1,444 @@ +# encapi node classifications. +# +# 130 container VMs (environment=production): extracted from +# terraform-incus config/instances//config.yaml. certname is +# .main.unkin.net (dir basename + cobbler_domain), role is +# cobbler_mgmt_classes[0] (defaulting to roles::base if absent). See +# ci/extract_incus_nodes.py, which regenerates this section. +# +# 13 prodnxsr* physical hypervisor/k8s nodes (environment=develop): NOT +# managed by the incus instance module; roles come from the PuppetDB +# enc_role fact. Maintained by hand below. + +# --- container VMs (production) --- +ausyd1nxvm2000.main.unkin.net: + role: roles::infra::storage::vault + environment: production +ausyd1nxvm2001.main.unkin.net: + role: roles::infra::storage::vault + environment: production +ausyd1nxvm2002.main.unkin.net: + role: roles::infra::storage::vault + environment: production +ausyd1nxvm2003.main.unkin.net: + role: roles::infra::storage::vault + environment: production +ausyd1nxvm2004.main.unkin.net: + role: roles::infra::storage::vault + environment: production +ausyd1nxvm2005.main.unkin.net: + role: roles::infra::storage::consul + environment: production +ausyd1nxvm2006.main.unkin.net: + role: roles::infra::storage::consul + environment: production +ausyd1nxvm2007.main.unkin.net: + role: roles::infra::storage::consul + environment: production +ausyd1nxvm2008.main.unkin.net: + role: roles::infra::storage::consul + environment: production +ausyd1nxvm2009.main.unkin.net: + role: roles::infra::storage::consul + environment: production +ausyd1nxvm2010.main.unkin.net: + role: roles::infra::puppetdb::api + environment: production +ausyd1nxvm2011.main.unkin.net: + role: roles::infra::puppetdb::api + environment: production +ausyd1nxvm2012.main.unkin.net: + role: roles::infra::puppetdb::api + environment: production +ausyd1nxvm2013.main.unkin.net: + role: roles::infra::puppetboard::server + environment: production +ausyd1nxvm2014.main.unkin.net: + role: roles::infra::puppetboard::server + environment: production +ausyd1nxvm2015.main.unkin.net: + role: roles::infra::metrics::grafana + environment: production +ausyd1nxvm2016.main.unkin.net: + role: roles::infra::metrics::grafana + environment: production +ausyd1nxvm2017.main.unkin.net: + role: roles::infra::auth::glauth + environment: production +ausyd1nxvm2018.main.unkin.net: + role: roles::infra::auth::glauth + environment: production +ausyd1nxvm2019.main.unkin.net: + role: roles::infra::auth::glauth + environment: production +ausyd1nxvm2020.main.unkin.net: + role: roles::infra::proxy::jumphost + environment: production +ausyd1nxvm2021.main.unkin.net: + role: roles::infra::proxy::jumphost + environment: production +ausyd1nxvm2022.main.unkin.net: + role: roles::infra::proxy::jumphost + environment: production +ausyd1nxvm2023.main.unkin.net: + role: roles::infra::git::runner + environment: production +ausyd1nxvm2024.main.unkin.net: + role: roles::infra::git::runner + environment: production +ausyd1nxvm2025.main.unkin.net: + role: roles::infra::git::runner + environment: production +ausyd1nxvm2026.main.unkin.net: + role: roles::infra::nomad::server + environment: production +ausyd1nxvm2027.main.unkin.net: + role: roles::infra::nomad::server + environment: production +ausyd1nxvm2028.main.unkin.net: + role: roles::infra::nomad::server + environment: production +ausyd1nxvm2029.main.unkin.net: + role: roles::infra::dns::master + environment: production +ausyd1nxvm2030.main.unkin.net: + role: roles::infra::dns::master + environment: production +ausyd1nxvm2031.main.unkin.net: + role: roles::infra::dns::master + environment: production +ausyd1nxvm2032.main.unkin.net: + role: roles::infra::dns::resolver + environment: production +ausyd1nxvm2033.main.unkin.net: + role: roles::infra::dns::resolver + environment: production +ausyd1nxvm2034.main.unkin.net: + role: roles::infra::dns::resolver + environment: production +ausyd1nxvm2035.main.unkin.net: + role: roles::apps::music::gonic + environment: production +ausyd1nxvm2036.main.unkin.net: + role: roles::apps::music::gonic + environment: production +ausyd1nxvm2037.main.unkin.net: + role: roles::apps::music::gonic + environment: production +ausyd1nxvm2038.main.unkin.net: + role: roles::infra::metrics::prometheus + environment: production +ausyd1nxvm2039.main.unkin.net: + role: roles::infra::metrics::prometheus + environment: production +ausyd1nxvm2040.main.unkin.net: + role: roles::infra::nomad::agentv2 + environment: production +ausyd1nxvm2041.main.unkin.net: + role: roles::infra::nomad::agentv2 + environment: production +ausyd1nxvm2042.main.unkin.net: + role: roles::infra::nomad::agentv2 + environment: production +ausyd1nxvm2043.main.unkin.net: + role: roles::infra::nomad::agentv2 + environment: production +ausyd1nxvm2044.main.unkin.net: + role: roles::infra::nomad::agentv2 + environment: production +ausyd1nxvm2045.main.unkin.net: + role: roles::apps::media::nzbget + environment: production +ausyd1nxvm2046.main.unkin.net: + role: roles::apps::media::sonarr + environment: production +ausyd1nxvm2047.main.unkin.net: + role: roles::apps::media::radarr + environment: production +ausyd1nxvm2048.main.unkin.net: + role: roles::apps::media::lidarr + environment: production +ausyd1nxvm2049.main.unkin.net: + role: roles::apps::media::readarr + environment: production +ausyd1nxvm2050.main.unkin.net: + role: roles::apps::media::prowlarr + environment: production +ausyd1nxvm2051.main.unkin.net: + role: roles::apps::media::jellyfin + environment: production +ausyd1nxvm2052.main.unkin.net: + role: roles::infra::puppet::master + environment: production +ausyd1nxvm2053.main.unkin.net: + role: roles::infra::puppet::master + environment: production +ausyd1nxvm2054.main.unkin.net: + role: roles::infra::puppet::master + environment: production +ausyd1nxvm2055.main.unkin.net: + role: roles::infra::puppet::master + environment: production +ausyd1nxvm2056.main.unkin.net: + role: roles::infra::puppet::master + environment: production +ausyd1nxvm2057.main.unkin.net: + role: roles::infra::pki::certbot + environment: production +ausyd1nxvm2058.main.unkin.net: + role: roles::infra::reposync::syncer + environment: production +ausyd1nxvm2059.main.unkin.net: + role: roles::infra::reposync::repo + environment: production +ausyd1nxvm2060.main.unkin.net: + role: roles::infra::reposync::repo + environment: production +ausyd1nxvm2061.main.unkin.net: + role: roles::infra::reposync::repo + environment: production +ausyd1nxvm2062.main.unkin.net: + role: roles::infra::incus::imagehost + environment: production +ausyd1nxvm2063.main.unkin.net: + role: roles::infra::storage::edgecache + environment: production +ausyd1nxvm2064.main.unkin.net: + role: roles::infra::storage::edgecache + environment: production +ausyd1nxvm2065.main.unkin.net: + role: roles::infra::puppetdb::sql + environment: production +ausyd1nxvm2066.main.unkin.net: + role: roles::infra::puppetdb::sql + environment: production +ausyd1nxvm2067.main.unkin.net: + role: roles::infra::puppetdb::sql + environment: production +ausyd1nxvm2068.main.unkin.net: + role: roles::apps::jupyter::hub + environment: production +ausyd1nxvm2069.main.unkin.net: + role: roles::infra::halb::haproxy2 + environment: production +ausyd1nxvm2070.main.unkin.net: + role: roles::infra::halb::haproxy2 + environment: production +ausyd1nxvm2071.main.unkin.net: + role: roles::infra::halb::haproxy2 + environment: production +ausyd1nxvm2072.main.unkin.net: + role: roles::infra::halb::haproxy2 + environment: production +ausyd1nxvm2073.main.unkin.net: + role: roles::infra::halb::haproxy2 + environment: production +ausyd1nxvm2074.main.unkin.net: + role: roles::infra::dhcp::server + environment: production +ausyd1nxvm2075.main.unkin.net: + role: roles::infra::dhcp::server + environment: production +ausyd1nxvm2076.main.unkin.net: + role: roles::infra::dhcp::server + environment: production +ausyd1nxvm2077.main.unkin.net: + role: roles::infra::sql::shared + environment: production +ausyd1nxvm2078.main.unkin.net: + role: roles::infra::sql::shared + environment: production +ausyd1nxvm2079.main.unkin.net: + role: roles::infra::sql::shared + environment: production +ausyd1nxvm2080.main.unkin.net: + role: roles::infra::git::server + environment: production +ausyd1nxvm2081.main.unkin.net: + role: roles::infra::git::server + environment: production +ausyd1nxvm2082.main.unkin.net: + role: roles::infra::git::server + environment: production +ausyd1nxvm2083.main.unkin.net: + role: roles::infra::git::redis + environment: production +ausyd1nxvm2084.main.unkin.net: + role: roles::infra::git::redis + environment: production +ausyd1nxvm2085.main.unkin.net: + role: roles::infra::git::redis + environment: production +ausyd1nxvm2086.main.unkin.net: + role: roles::infra::metrics::vmstorage + environment: production +ausyd1nxvm2087.main.unkin.net: + role: roles::infra::metrics::vmstorage + environment: production +ausyd1nxvm2088.main.unkin.net: + role: roles::infra::metrics::vmstorage + environment: production +ausyd1nxvm2089.main.unkin.net: + role: roles::infra::metrics::vmstorage + environment: production +ausyd1nxvm2090.main.unkin.net: + role: roles::infra::metrics::vmstorage + environment: production +ausyd1nxvm2091.main.unkin.net: + role: roles::infra::metrics::vminsert + environment: production +ausyd1nxvm2092.main.unkin.net: + role: roles::infra::metrics::vminsert + environment: production +ausyd1nxvm2093.main.unkin.net: + role: roles::infra::metrics::vminsert + environment: production +ausyd1nxvm2094.main.unkin.net: + role: roles::infra::metrics::vmselect + environment: production +ausyd1nxvm2095.main.unkin.net: + role: roles::infra::metrics::vmselect + environment: production +ausyd1nxvm2096.main.unkin.net: + role: roles::infra::metrics::vmselect + environment: production +ausyd1nxvm2097.main.unkin.net: + role: roles::infra::puppet::master + environment: production +ausyd1nxvm2098.main.unkin.net: + role: roles::infra::cobbler::server + environment: production +ausyd1nxvm2099.main.unkin.net: + role: roles::infra::metrics::vmagent + environment: production +ausyd1nxvm2100.main.unkin.net: + role: roles::infra::metrics::vmagent + environment: production +ausyd1nxvm2101.main.unkin.net: + role: roles::infra::metrics::vmagent + environment: production +ausyd1nxvm2102.main.unkin.net: + role: roles::infra::logs::vlinsert + environment: production +ausyd1nxvm2103.main.unkin.net: + role: roles::infra::logs::vlinsert + environment: production +ausyd1nxvm2104.main.unkin.net: + role: roles::infra::logs::vlinsert + environment: production +ausyd1nxvm2105.main.unkin.net: + role: roles::infra::logs::vlselect + environment: production +ausyd1nxvm2106.main.unkin.net: + role: roles::infra::logs::vlselect + environment: production +ausyd1nxvm2107.main.unkin.net: + role: roles::infra::logs::vlselect + environment: production +ausyd1nxvm2108.main.unkin.net: + role: roles::infra::logs::vlstorage + environment: production +ausyd1nxvm2109.main.unkin.net: + role: roles::infra::logs::vlstorage + environment: production +ausyd1nxvm2110.main.unkin.net: + role: roles::infra::logs::vlstorage + environment: production +ausyd1nxvm2111.main.unkin.net: + role: roles::infra::logs::vlstorage + environment: production +ausyd1nxvm2112.main.unkin.net: + role: roles::infra::logs::vlstorage + environment: production +ausyd1nxvm2113.main.unkin.net: + role: roles::infra::logs::vlagent + environment: production +ausyd1nxvm2114.main.unkin.net: + role: roles::infra::logs::vlagent + environment: production +ausyd1nxvm2115.main.unkin.net: + role: roles::infra::ceph::rgw + environment: production +ausyd1nxvm2116.main.unkin.net: + role: roles::infra::ceph::rgw + environment: production +ausyd1nxvm2117.main.unkin.net: + role: roles::infra::ceph::rgw + environment: production +ausyd1nxvm2118.main.unkin.net: + role: roles::infra::ceph::rgw + environment: production +ausyd1nxvm2119.main.unkin.net: + role: roles::infra::ceph::rgw + environment: production +ausyd1nxvm2120.main.unkin.net: + role: roles::base + environment: production +ausyd1nxvm2121.main.unkin.net: + role: roles::infra::mail::gateway + environment: production +ausyd1nxvm2122.main.unkin.net: + role: roles::infra::mail::gateway + environment: production +ausyd1nxvm2123.main.unkin.net: + role: roles::infra::mail::gateway + environment: production +ausyd1nxvm2124.main.unkin.net: + role: roles::infra::mail::backend + environment: production +ausyd1nxvm2125.main.unkin.net: + role: roles::infra::mail::backend + environment: production +ausyd1nxvm2126.main.unkin.net: + role: roles::infra::mail::backend + environment: production +ausyd1nxvm2127.main.unkin.net: + role: roles::infra::dns::externaldns + environment: production +ausyd1nxvm2128.main.unkin.net: + role: roles::infra::dns::externaldns + environment: production +ausyd1nxvm2129.main.unkin.net: + role: roles::infra::dns::externaldns + environment: production + +# --- prodnxsr physical nodes (develop) --- +prodnxsr0001.main.unkin.net: + role: roles::infra::k8s::control + environment: develop +prodnxsr0002.main.unkin.net: + role: roles::infra::k8s::control + environment: develop +prodnxsr0003.main.unkin.net: + role: roles::infra::k8s::control + environment: develop +prodnxsr0004.main.unkin.net: + role: roles::infra::k8s::compute + environment: develop +prodnxsr0005.main.unkin.net: + role: roles::infra::k8s::compute + environment: develop +prodnxsr0006.main.unkin.net: + role: roles::infra::k8s::compute + environment: develop +prodnxsr0007.main.unkin.net: + role: roles::infra::k8s::compute + environment: develop +prodnxsr0008.main.unkin.net: + role: roles::infra::k8s::compute + environment: develop +prodnxsr0009.main.unkin.net: + role: roles::infra::incus::node + environment: develop +prodnxsr0010.main.unkin.net: + role: roles::infra::incus::node + environment: develop +prodnxsr0011.main.unkin.net: + role: roles::infra::incus::node + environment: develop +prodnxsr0012.main.unkin.net: + role: roles::infra::incus::node + environment: develop +prodnxsr0013.main.unkin.net: + role: roles::infra::incus::node + environment: develop diff --git a/config/encapi/roles.yaml b/config/encapi/roles.yaml new file mode 100644 index 0000000..573ea14 --- /dev/null +++ b/config/encapi/roles.yaml @@ -0,0 +1,55 @@ +# encapi roles: every distinct Puppet role class used across +# config/instances/*/config.yaml (cobbler_mgmt_classes[0]) PLUS the roles +# run by the 13 prodnxsr physical nodes (from PuppetDB enc_role fact). +# Values are empty maps; add description/default_params here when needed. +roles::apps::jupyter::hub: {} +roles::apps::media::jellyfin: {} +roles::apps::media::lidarr: {} +roles::apps::media::nzbget: {} +roles::apps::media::prowlarr: {} +roles::apps::media::radarr: {} +roles::apps::media::readarr: {} +roles::apps::media::sonarr: {} +roles::apps::music::gonic: {} +roles::base: {} +roles::infra::auth::glauth: {} +roles::infra::ceph::rgw: {} +roles::infra::cobbler::server: {} +roles::infra::dhcp::server: {} +roles::infra::dns::externaldns: {} +roles::infra::dns::master: {} +roles::infra::dns::resolver: {} +roles::infra::git::redis: {} +roles::infra::git::runner: {} +roles::infra::git::server: {} +roles::infra::halb::haproxy2: {} +roles::infra::incus::imagehost: {} +roles::infra::incus::node: {} +roles::infra::k8s::compute: {} +roles::infra::k8s::control: {} +roles::infra::logs::vlagent: {} +roles::infra::logs::vlinsert: {} +roles::infra::logs::vlselect: {} +roles::infra::logs::vlstorage: {} +roles::infra::mail::backend: {} +roles::infra::mail::gateway: {} +roles::infra::metrics::grafana: {} +roles::infra::metrics::prometheus: {} +roles::infra::metrics::vmagent: {} +roles::infra::metrics::vminsert: {} +roles::infra::metrics::vmselect: {} +roles::infra::metrics::vmstorage: {} +roles::infra::nomad::agentv2: {} +roles::infra::nomad::server: {} +roles::infra::pki::certbot: {} +roles::infra::proxy::jumphost: {} +roles::infra::puppetboard::server: {} +roles::infra::puppetdb::api: {} +roles::infra::puppetdb::sql: {} +roles::infra::puppet::master: {} +roles::infra::reposync::repo: {} +roles::infra::reposync::syncer: {} +roles::infra::sql::shared: {} +roles::infra::storage::consul: {} +roles::infra::storage::edgecache: {} +roles::infra::storage::vault: {} diff --git a/config/encapi/statuses.yaml b/config/encapi/statuses.yaml new file mode 100644 index 0000000..64617a4 --- /dev/null +++ b/config/encapi/statuses.yaml @@ -0,0 +1,10 @@ +# encapi statuses == Puppet environments (Cobbler "status"). +# Seeded from what the estate actually runs (all nodes today report +# catalog_environment=develop) plus production (the environment the incus +# instance module pins via puppetca_certificate) and testing (implicit). +production: + description: Production environment +develop: + description: Development environment (current default across the estate) +testing: + description: Implicit/transient environment diff --git a/config/encapi/terragrunt.hcl b/config/encapi/terragrunt.hcl new file mode 100644 index 0000000..f168050 --- /dev/null +++ b/config/encapi/terragrunt.hcl @@ -0,0 +1,19 @@ +locals { + statuses = yamldecode(file("${get_terragrunt_dir()}/statuses.yaml")) + roles = yamldecode(file("${get_terragrunt_dir()}/roles.yaml")) + nodes = yamldecode(file("${get_terragrunt_dir()}/nodes.yaml")) +} + +include "root" { + path = find_in_parent_folders("root.hcl") +} + +terraform { + source = "${get_repo_root()}/modules/encapi" +} + +inputs = { + statuses = local.statuses + roles = local.roles + nodes = local.nodes +} diff --git a/config/root.hcl b/config/root.hcl new file mode 100644 index 0000000..1712361 --- /dev/null +++ b/config/root.hcl @@ -0,0 +1,15 @@ +generate "backend" { + path = "backend.tf" + if_exists = "overwrite_terragrunt" + contents = <