fix: broken inlining of python block moved to script
This commit is contained in:
40
Makefile
40
Makefile
@@ -7,12 +7,20 @@ GITEA ?= gitea.example.com
|
||||
OWNER ?= coulomb
|
||||
REPO ?= railiance-hosts
|
||||
|
||||
# New-host defaults (can be overridden: make new-host NAME=... TYPE=...)
|
||||
TYPE ?= cpx21
|
||||
REGION ?= nbg1
|
||||
ROLE ?= generic
|
||||
IMG ?= ubuntu-24.04
|
||||
USER ?= admin
|
||||
|
||||
# Decrypt Hetzner token at runtime (requires SOPS_AGE_KEY or keys.txt locally)
|
||||
HCLOUD_TOKEN := $(shell sops -d --extract '["ops"]["hcloud_token"]' inventory/group_vars/secrets.sops.yaml 2>/dev/null)
|
||||
|
||||
# ---- Help ----
|
||||
help: ## Show this help
|
||||
@echo "RailianceHosts Commands"; \ grep -E '^[a-zA-Z0-9_-]+:.*?## ' $(MAKEFILE_LIST) | sort | sed 's/:.*##/: /'
|
||||
@echo "RailianceHosts Commands"; \
|
||||
grep -E '^[a-zA-Z0-9_-]+:.*?## ' $(MAKEFILE_LIST) | sort | sed 's/:.*##/: /'
|
||||
|
||||
# ---- Git hooks ----
|
||||
hooks: ## Configure git to use repo-local hooks (.githooks)
|
||||
@@ -22,7 +30,12 @@ hooks: ## Configure git to use repo-local hooks (.githooks)
|
||||
hooks-test: ## Test secrets hook blocks plaintext in secrets/
|
||||
@mkdir -p secrets && echo 'PLAINTEXT_TEST=true' > secrets/_hook_test.yaml
|
||||
@git add secrets/_hook_test.yaml || true
|
||||
@if git commit -m "TEST: should be blocked" 2>/dev/null; then \ echo "❌ Hook did NOT block plaintext (check .githooks/pre-commit)"; \ git reset --soft HEAD~1; \ else \ echo "✔ Hook blocked plaintext as expected"; \ fi
|
||||
@if git commit -m "TEST: should be blocked" 2>/dev/null; then \
|
||||
echo "❌ Hook did NOT block plaintext (check .githooks/pre-commit)"; \
|
||||
git reset --soft HEAD~1; \
|
||||
else \
|
||||
echo "✔ Hook blocked plaintext as expected"; \
|
||||
fi
|
||||
@git restore --staged secrets/_hook_test.yaml || true
|
||||
@rm -f secrets/_hook_test.yaml
|
||||
|
||||
@@ -50,7 +63,8 @@ sops-rotate: ## Rotate recipients on a SOPS file (after updating .sops.yaml)
|
||||
sops --rotate --in-place $(FILE)
|
||||
|
||||
check-secrets: ## Fail if any file in secrets/ is not SOPS-encrypted
|
||||
@! (git ls-files secrets | xargs -r grep -L -E '(^sops:$$|\"sops\"[[:space:]]*:)' | tee /dev/stderr | read) \ || (echo "❌ Unencrypted secrets detected above. Encrypt with: sops --encrypt --in-place <file>"; exit 1)
|
||||
@! (git ls-files secrets | xargs -r grep -L -E '(^sops:$$|\"sops\"[[:space:]]*:)' | tee /dev/stderr | read) \
|
||||
|| (echo "❌ Unencrypted secrets detected above. Encrypt with: sops --encrypt --in-place <file>"; exit 1)
|
||||
@echo "✔ All files in secrets/ appear SOPS-encrypted"
|
||||
|
||||
# ---- Terraform (Hetzner) ----
|
||||
@@ -84,12 +98,24 @@ apply: tf-fmt tf-apply ansible-bootstrap ## Provision via Terraform then converg
|
||||
|
||||
# ---- Utilities ----
|
||||
doctor: ## Check tools and basic repo setup
|
||||
@bash -ceu ' \ ok(){ printf "✔ %s\\n" "$$1"; }; fail(){ printf "❌ %s\\n" "$$1"; exit 1; }; \ command -v git >/dev/null && ok "git: $$(git --version)" || fail "git missing"; \ command -v terraform >/dev/null && ok "terraform: $$(terraform version | head -1)"; \ command -v ansible >/dev/null && ok "ansible: $$(ansible --version | head -1)"; \ command -v sops >/dev/null && ok "sops: $$(sops --version)"; \ command -v age >/dev/null && ok "age: $$(age --version)"; \ test -f keys/admin_ssh.pub && ok "keys/admin_ssh.pub present" || echo "ℹ add your SSH pubkey to keys/admin_ssh.pub"; \ test -f inventory/group_vars/secrets.sops.yaml && ok "secrets.sops.yaml present" || echo "ℹ create inventory/group_vars/secrets.sops.yaml"; \ grep -q "age1" .sops.yaml && ok ".sops.yaml has an age recipient" || echo "ℹ add your age public key to .sops.yaml"; \ git config --get core.hooksPath >/dev/null && ok "git hooksPath: $$(git config --get core.hooksPath)" || echo "ℹ run: make hooks"; \ '
|
||||
@bash -ceu ' \
|
||||
ok(){ printf "✔ %s\n" "$$1"; }; fail(){ printf "❌ %s\n" "$$1"; exit 1; }; \
|
||||
command -v git >/dev/null && ok "git: $$(git --version)" || fail "git missing"; \
|
||||
command -v terraform >/dev/null && ok "terraform: $$(terraform version | head -1)"; \
|
||||
command -v ansible >/dev/null && ok "ansible: $$(ansible --version | head -1)"; \
|
||||
command -v sops >/dev/null && ok "sops: $$(sops --version)"; \
|
||||
command -v age >/dev/null && ok "age: $$(age --version)"; \
|
||||
test -f keys/admin_ssh.pub && ok "keys/admin_ssh.pub present" || echo "ℹ add your SSH pubkey to keys/admin_ssh.pub"; \
|
||||
test -f inventory/group_vars/secrets.sops.yaml && ok "secrets.sops.yaml present" || echo "ℹ create inventory/group_vars/secrets.sops.yaml"; \
|
||||
grep -q "age1" .sops.yaml && ok ".sops.yaml has an age recipient" || echo "ℹ add your age public key to .sops.yaml"; \
|
||||
git config --get core.hooksPath >/dev/null && ok "git hooksPath: $$(git config --get core.hooksPath)" || echo "ℹ run: make hooks"; \
|
||||
'
|
||||
|
||||
# ---- Inventory convenience ----
|
||||
new-host: ## Add a new host quickly: make new-host NAME=web-01 TYPE=cpx21 REGION=nbg1 ROLE=web
|
||||
@[ -n "$(NAME)" ] || (echo "Usage: make new-host NAME=..." && exit 1)
|
||||
@TYPE?=cpx21; REGION?=nbg1; ROLE?=generic; IMG?=ubuntu-24.04; USER?=admin; \ python3 - <<'PY' \import sys, yaml; \p="inventory/servers.yaml"; d=yaml.safe_load(open(p)) ; d['servers'].append({"name":"$(NAME)","labels":[],"role":"$(ROLE)","region":"$(REGION)","type":"$(TYPE)","image":"$(IMG)","ssh_user":"$(USER)"}); \yaml.safe_dump(d, open(p,"w"), sort_keys=False); \print("✔ Added host $(NAME) to inventory/servers.yaml")
|
||||
PY
|
||||
@[ -n "$(NAME)" ] || (echo "Usage: make new-host NAME=... [TYPE=...] [REGION=...] [ROLE=...] [IMG=...] [USER=...]" && exit 1)
|
||||
@python3 scripts/new_host.py --name "$(NAME)" --type "$(TYPE)" --region "$(REGION)" --role "$(ROLE)" --image "$(IMG)" --user "$(USER)"
|
||||
@echo "✔ Added host $(NAME) to inventory/servers.yaml"
|
||||
|
||||
remote-set: ## Set origin to your Gitea repo (GITEA/OWNER/REPO vars)
|
||||
git remote remove origin 2>/dev/null || true
|
||||
|
||||
45
scripts/new_host.py
Normal file
45
scripts/new_host.py
Normal file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse, os, sys
|
||||
try:
|
||||
import yaml
|
||||
except Exception as e:
|
||||
print("ERROR: PyYAML is required. Install with: pip install pyyaml", file=sys.stderr)
|
||||
sys.exit(2)
|
||||
|
||||
def main():
|
||||
p = argparse.ArgumentParser(description="Add a host to inventory/servers.yaml")
|
||||
p.add_argument("--name", required=True)
|
||||
p.add_argument("--type", default="cpx21")
|
||||
p.add_argument("--region", default="nbg1")
|
||||
p.add_argument("--role", default="generic")
|
||||
p.add_argument("--image", default="ubuntu-24.04")
|
||||
p.add_argument("--user", default="admin")
|
||||
args = p.parse_args()
|
||||
|
||||
inv_path = os.path.join("inventory", "servers.yaml")
|
||||
data = {}
|
||||
if os.path.exists(inv_path):
|
||||
with open(inv_path, "r", encoding="utf-8") as f:
|
||||
data = yaml.safe_load(f) or {}
|
||||
servers = data.setdefault("servers", [])
|
||||
|
||||
# Prevent duplicates
|
||||
if any(s.get("name") == args.name for s in servers):
|
||||
print(f"ERROR: host '{args.name}' already exists in {inv_path}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
servers.append({
|
||||
"name": args.name,
|
||||
"labels": [],
|
||||
"role": args.role,
|
||||
"region": args.region,
|
||||
"type": args.type,
|
||||
"image": args.image,
|
||||
"ssh_user": args.user,
|
||||
})
|
||||
|
||||
with open(inv_path, "w", encoding="utf-8") as f:
|
||||
yaml.safe_dump(data, f, sort_keys=False)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user