3af12180fd
## Why The k8s puppetserver compilers classify nodes via an exec ENC that today queries legacy Cobbler (`https://cobbler.main.unkin.net`) over TLS. `encapi` now runs in-cluster and exposes a cobbler-wire-compatible endpoint (`GET /cblr/svc/op/puppet/hostname/<certname>`), a drop-in for the Cobbler URL. This cuts the puppet-on-k8s ENC over from Cobbler to encapi — a prerequisite for migrating VM agents onto puppet-on-k8s. ## Changes - Rename the ENC script `resources/cobbler-enc` -> `resources/encapi-enc`, and its configmap `puppet-cobbler-enc` -> `puppet-encapi-enc` (kustomization configMapGenerator + deployment volume, initContainer copy path, and volumeMount subPath). - Point `external_nodes` in the compiler `puppet.conf` at `/opt/bin/encapi-enc`. - Target the in-cluster encapi service `http://encapi.encapi.svc.cluster.local` (plain HTTP), overridable via the `ENCAPI_URL` env var. - Drop the `/opt/vault-ca-cert.crt` verify for the ENC request (no TLS needed in-cluster). - Leave the response normalization identical: classes coerced to a list, `enc_role`/`enc_env` params set, `environment` stripped when it equals `testing`. Verified with `kubectl kustomize apps/overlays/au-syd1/puppet` (builds clean, exit 0); the generated `puppet-encapi-enc` configmap contains the new URL and env var. ## 🚨 Merge gate **Do not merge until encapi is seeded** (terraform-incus `benvin/encapi-seed` PR applied). An empty encapi means every node resolves to a 404. On 404 the ENC script exits non-zero, so puppet fails the compile rather than classifying the node with zero classes — nodes will fail to run until they exist in encapi. Seed encapi first so real nodes classify correctly; only unknown nodes should 404. Reviewed-on: #272 Co-authored-by: Ben Vincent <ben@unkin.net> Co-committed-by: Ben Vincent <ben@unkin.net>
56 lines
1.8 KiB
Python
Executable File
56 lines
1.8 KiB
Python
Executable File
#!/usr/bin/env -S /opt/bin/uv run --quiet --cache-dir /opt/bin/.cache/uv --script
|
|
# /// script
|
|
# requires-python = ">=3.11"
|
|
# dependencies = ['pyyaml','requests']
|
|
# ///
|
|
"""
|
|
External Node Classifier (ENC) for Puppet.
|
|
|
|
If the environment specified in the YAML file is 'testing',
|
|
the environment is not included in the output.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import yaml
|
|
import requests
|
|
|
|
# In-cluster encapi service (cobbler-wire-compatible endpoint). Plain HTTP,
|
|
# so no CA bundle is needed. Overridable via ENCAPI_URL.
|
|
ENCAPI_URL = os.environ.get("ENCAPI_URL", "http://encapi.encapi.svc.cluster.local")
|
|
|
|
def fetch_enc_data(base_url: str, hostname: str) -> str:
|
|
"""
|
|
Fetches and modifies ENC data from a given URL to ensure classes are in list format.
|
|
"""
|
|
url = f"{base_url}/cblr/svc/op/puppet/hostname/{hostname}"
|
|
try:
|
|
response = requests.get(url)
|
|
response.raise_for_status()
|
|
except requests.RequestException as e:
|
|
sys.exit(f"Request failed: {e}")
|
|
|
|
data = yaml.safe_load(response.text)
|
|
data["parameters"] = data.get("parameters", {})
|
|
|
|
# Ensure 'classes' is in the desired list format
|
|
if "classes" in data:
|
|
if isinstance(data["classes"], dict):
|
|
data["parameters"]["enc_role"] = list(data["classes"].keys())
|
|
data["classes"] = list(data["classes"].keys())
|
|
else:
|
|
data["parameters"]["enc_role"] = list(data["classes"])
|
|
data["classes"] = list(data["classes"])
|
|
|
|
if "environment" in data:
|
|
data["parameters"]["enc_env"] = data["environment"]
|
|
if data["environment"] == "testing":
|
|
del data["environment"]
|
|
|
|
return yaml.dump(data)
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 2:
|
|
sys.exit(f"Usage: {sys.argv[0]} <hostname>")
|
|
print(fetch_enc_data(ENCAPI_URL, sys.argv[1]))
|