mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
3529 invalid comments in 528 files, grandfathered in while the linter only saw the working-tree diff. Removal ran through the linter's own collectors, so detection and deletion cannot drift: a comment whose opener line is blank before it and whose closer line is blank after it loses all its lines, anything else loses only the comment region, and a line left holding a bare delimiter goes with it. Five files keep their comments behind a nocheck marker instead. Four are upstream configs whose inline docs are upstream's own (mautrix, systemd journald, nextcloud-oidc-login, MediaWiki). In littlejs the commented-out entries ARE the deactivation mechanism for an example tile, so deleting them would delete configuration. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
82 lines
2.9 KiB
Python
82 lines
2.9 KiB
Python
import argparse
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import yaml
|
|
from yaml.dumper import SafeDumper
|
|
|
|
from utils.handler.vault import VaultHandler, VaultScalar
|
|
from utils.handler.yaml import YamlHandler
|
|
|
|
|
|
def ask_for_confirmation(key: str) -> bool:
|
|
"""Prompt the user for confirmation to overwrite an existing value."""
|
|
confirmation = (
|
|
input(f"Do you want to encrypt the value for '{key}'? (y/n): ").strip().lower()
|
|
)
|
|
return confirmation == "y"
|
|
|
|
|
|
def encrypt_recursively(
|
|
data: Any,
|
|
vault_handler: VaultHandler,
|
|
ask_confirmation: bool = True,
|
|
prefix: str = "",
|
|
) -> Any:
|
|
"""Recursively encrypt values in the data."""
|
|
if isinstance(data, dict):
|
|
for key, value in data.items():
|
|
new_prefix = f"{prefix}.{key}" if prefix else key
|
|
data[key] = encrypt_recursively(
|
|
value, vault_handler, ask_confirmation, new_prefix
|
|
)
|
|
elif isinstance(data, list):
|
|
for i, item in enumerate(data):
|
|
data[i] = encrypt_recursively(item, vault_handler, ask_confirmation, prefix)
|
|
elif isinstance(data, str): # noqa: SIM102 outer guard, inner ask_confirmation block has independent siblings
|
|
if not data.lstrip().startswith("$ANSIBLE_VAULT"):
|
|
if ask_confirmation: # noqa: SIM102 combining changes semantics: encrypted_value below must run regardless of ask_confirmation
|
|
if not ask_for_confirmation(prefix):
|
|
print(f"Skipping encryption for '{prefix}'.")
|
|
return data
|
|
encrypted_value = vault_handler.encrypt_string(data, prefix)
|
|
lines = encrypted_value.splitlines()
|
|
indent = len(lines[1]) - len(lines[1].lstrip())
|
|
body = "\n".join(line[indent:] for line in lines[1:])
|
|
return VaultScalar(body)
|
|
return data
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="Encrypt all fields, ask for confirmation unless --all is specified."
|
|
)
|
|
parser.add_argument(
|
|
"--inventory-file", required=True, help="Host vars file to update"
|
|
)
|
|
parser.add_argument(
|
|
"--vault-password-file", required=True, help="Vault password file"
|
|
)
|
|
parser.add_argument(
|
|
"--all", action="store_true", help="Encrypt all fields without confirmation"
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
vault_handler = VaultHandler(vault_password_file=args.vault_password_file)
|
|
updated_inventory = YamlHandler.load_yaml(Path(args.inventory_file))
|
|
|
|
updated_inventory = encrypt_recursively(
|
|
updated_inventory, vault_handler, ask_confirmation=not args.all
|
|
)
|
|
|
|
with Path(args.inventory_file).open("w", encoding="utf-8") as f:
|
|
yaml.dump( # nocheck: direct-yaml
|
|
updated_inventory, f, sort_keys=False, Dumper=SafeDumper
|
|
)
|
|
|
|
print(f"✅ Inventory selectively vaulted → {args.inventory_file}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|