libs/hooks/bin: add one-line module docstrings and # purpose: headers

every libs/*.py and hooks/*.py now starts with a one-line module
docstring; every bin/* script starts with a `# purpose:` header.
discovery-by-`ls`-and-read instead of by index.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
CroneKorkN 2026-05-10 15:36:19 +02:00
parent 136313e9c3
commit 730625e36c
Signed by: cronekorkn
SSH key fingerprint: SHA256:v0410ZKfuO1QHdgKBsdQNF64xmTxOF8osF1LIqwTcVw
33 changed files with 60 additions and 0 deletions

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: upgrade RouterOS and routerboard firmware on `bundle:routeros` (or any selector) — usage: mikrotik-firmware-updater [<selector>...] [--yes].
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep from time import sleep

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: print node.password and selected metadata-key passwords for one node — usage: passwords-for <node>.
from bundlewrap.repo import Repository from bundlewrap.repo import Repository
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: send an RCON command to a left4dead2 server defined in node metadata — usage: rcon (list) | rcon <server> <command>.
from sys import argv from sys import argv
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: starter template for new operator scripts under bin/.
from bundlewrap.repo import Repository from bundlewrap.repo import Repository
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: upsert one 1Password login per `bundle:routeros` node, keyed on the bw node id.
from bundlewrap.repo import Repository from bundlewrap.repo import Repository
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: add missing EXIF/QuickTime timestamps to photos in a directory using mdls + exiftool — usage: timestamp_icloud_photos_for_nextcloud -d <dir>.
from subprocess import check_output, CalledProcessError from subprocess import check_output, CalledProcessError
from datetime import datetime, timedelta from datetime import datetime, timedelta

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: apt-update and full-upgrade every non-dummy debian node, then reboot in WireGuard-aware order.
from bundlewrap.repo import Repository from bundlewrap.repo import Repository
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: wake one node via WoL by name — usage: wake <node>.
from bundlewrap.repo import Repository from bundlewrap.repo import Repository
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# purpose: print or QR-render a WireGuard client config from htz.mails metadata — usage: wireguard-client-config <client>.
from bundlewrap.repo import Repository from bundlewrap.repo import Repository
from os.path import realpath, dirname from os.path import realpath, dirname

View file

@ -1,3 +1,5 @@
"""known_hosts: pre-apply hook that writes all nodes' ssh/is_known_as entries to ~/.ssh/known_hosts_ckn."""
from os.path import expanduser from os.path import expanduser

View file

@ -1,3 +1,5 @@
"""skip_local_nodes: skip apply on `localhost` nodes whose metadata `id` doesn't match this host's local_id."""
from bundlewrap.exceptions import SkipNode from bundlewrap.exceptions import SkipNode
def node_apply_start(repo, node, interactive, **kwargs): def node_apply_start(repo, node, interactive, **kwargs):

View file

@ -1,3 +1,5 @@
"""test_ptr_records: bw-test gate verifying live A/PTR DNS records for the `mailserver` group via `dig @9.9.9.9`."""
from subprocess import check_output from subprocess import check_output

View file

@ -1,3 +1,6 @@
"""unique_node_ids: bw-test + pre-apply gate ensuring metadata `id` is unique across all nodes."""
def test_unique_node_ids(repo): def test_unique_node_ids(repo):
ids = {} ids = {}
for node in repo.nodes: for node in repo.nodes:

View file

@ -1,3 +1,6 @@
"""wake_on_lan: pre-apply / pre-run hook that wakes a node via libs.wol before bw connects to it."""
def wake_on_lan(node): def wake_on_lan(node):
node.repo.libs.wol.wake(node) node.repo.libs.wol.wake(node)

View file

@ -1,3 +1,5 @@
"""apt: render sources.list.d entries and resolve apt-key file extensions, with codename/version templating."""
from re import match from re import match
from glob import glob from glob import glob
from os.path import join, basename, exists from os.path import join, basename, exists

View file

@ -1,3 +1,5 @@
"""bind: DNS view-routing helpers — match A/AAAA records against internal vs external views via repo-wide collation."""
from ipaddress import ip_address from ipaddress import ip_address
def _values_from_all_nodes(type, name, zone): def _values_from_all_nodes(type, name, zone):

View file

@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
"""derive_string: deterministic byte-string derivation from a seed via ChaCha20 keystream."""
from hashlib import sha3_256 from hashlib import sha3_256
from itertools import count, islice from itertools import count, islice

View file

@ -1,3 +1,5 @@
"""grafana: panel and Flux-query generators for Mako-templated dashboards under data/grafana/rows/."""
from mako.template import Template from mako.template import Template
from copy import deepcopy from copy import deepcopy

View file

@ -1,3 +1,5 @@
"""hashable: dict/set subclasses with stable __hash__ via canonical JSON — lets you nest dicts/sets inside sets in metadata."""
import json import json
from functools import total_ordering from functools import total_ordering

View file

@ -1,3 +1,5 @@
"""hmac: base64-encoded HMAC-SHA512 helper."""
import hmac, hashlib, base64 import hmac, hashlib, base64
def hmac_sha512(secret, iv): def hmac_sha512(secret, iv):

View file

@ -1,3 +1,5 @@
"""ini: case-preserving ConfigParser parse/dumps for INI-style files where exact key casing must round-trip."""
from configparser import ConfigParser from configparser import ConfigParser
import json import json
from bundlewrap.metadata import MetadataJSONEncoder from bundlewrap.metadata import MetadataJSONEncoder

View file

@ -1,3 +1,5 @@
"""ip: A/AAAA-record derivation from a node's `network` metadata + cross-node IP collection."""
from ipaddress import ip_address, ip_interface from ipaddress import ip_address, ip_interface

View file

@ -1,3 +1,5 @@
"""local: identifier of the bw host itself (read from ~/.config/bundlewrap/local_id) — paired with hooks/skip_local_nodes.py."""
from os.path import expanduser, exists from os.path import expanduser, exists
from functools import cache from functools import cache

View file

@ -1,2 +1,5 @@
"""nextcloud: build `sudo -u www-data php occ ...` shell strings for use in actions."""
def occ(command, *args, **kwargs): def occ(command, *args, **kwargs):
return f"""sudo -u www-data php /opt/nextcloud/occ {command} {' '.join(args)} {' '.join(f'--{name.replace("_", "-")}' + (f'={value}' if value else '') for name, value in kwargs.items())}""" return f"""sudo -u www-data php /opt/nextcloud/occ {command} {' '.join(args)} {' '.join(f'--{name.replace("_", "-")}' + (f'={value}' if value else '') for name, value in kwargs.items())}"""

View file

@ -1,3 +1,6 @@
"""nginx: recursive nginx config-block rendering from a nested dict."""
def render_config(config): def render_config(config):
return '\n'.join(render_lines(config)) return '\n'.join(render_lines(config))

View file

@ -1,3 +1,5 @@
"""postgres: SCRAM-SHA-256 password-hash generation for postgres role provisioning."""
from base64 import standard_b64encode from base64 import standard_b64encode
from hashlib import pbkdf2_hmac, sha256 from hashlib import pbkdf2_hmac, sha256
import hmac import hmac

View file

@ -1,3 +1,5 @@
"""rsa: deterministic RSA private-key generation backed by a seeded PRNG."""
# https://stackoverflow.com/a/18266970 # https://stackoverflow.com/a/18266970
from Crypto.PublicKey import RSA from Crypto.PublicKey import RSA

View file

@ -1,3 +1,5 @@
"""ssh: deterministic ed25519 keypair generation and salted known_hosts hashing."""
from base64 import b64decode, b64encode from base64 import b64decode, b64encode
from hashlib import sha3_224, sha1 from hashlib import sha3_224, sha1
from functools import cache from functools import cache

View file

@ -1,3 +1,5 @@
"""systemd: unit-file rendering (Mako) and a reusable hardening-options dict for sandboxed services."""
from mako.template import Template from mako.template import Template
template = ''' template = '''

View file

@ -1,3 +1,5 @@
"""tools: identifier→IPs resolver (node|group|cidr), subnet-set deduplication, and bundle-requirement assertion."""
from ipaddress import ip_address, ip_network, IPv4Address, IPv4Network from ipaddress import ip_address, ip_network, IPv4Address, IPv4Network
from bundlewrap.exceptions import NoSuchGroup, NoSuchNode, BundleError from bundlewrap.exceptions import NoSuchGroup, NoSuchNode, BundleError

View file

@ -1,3 +1,5 @@
"""version: comparable Version class for dotted-int version strings."""
from functools import total_ordering from functools import total_ordering

View file

@ -1,3 +1,5 @@
"""wireguard: deterministic WireGuard private/public key + PSK derivation, backed by repo.vault.random_bytes_as_base64_for."""
import base64 import base64
from nacl.public import PrivateKey from nacl.public import PrivateKey
from nacl.encoding import Base64Encoder from nacl.encoding import Base64Encoder

View file

@ -1,3 +1,5 @@
"""wol: trigger a `wol-sleeper` waker node to run its configured wake command."""
from bundlewrap.utils.ui import io from bundlewrap.utils.ui import io
from bundlewrap.utils.text import yellow, bold from bundlewrap.utils.text import yellow, bold