Newer
Older
openstack-caracal-ipv4 / scripts / trust_filter.py
#!/usr/bin/env python3
"""Filter an `openstack trust list -f json` payload read from stdin.

S4 consolidation: replaces three near-identical inline python-in-bash blocks
(tenant-offboard sweep-preamble + audit inventory, tenant-acceptance trustee
lookup) with one fixture-tested tool. Keeps the DOCFIX-094 posture: the caller
captures stdout only (stderr of the openstack call goes to its own tempfile),
so a benign CLI warning cannot corrupt the parse.

Usage:
  trust_filter.py --fields ID,TRUSTOR,TRUSTEE [--trustor-in "u1 u2,u3"] \
                  [--first] [--error-token TOKEN]

  --fields       comma list from {ID,TRUSTOR,TRUSTEE}, printed space-joined,
                 one line per kept trust.
  --trustor-in   whitespace/comma-separated Trustor User IDs to keep
                 (default: keep every trust).
  --first        emit only the first kept trust.
  --error-token  printed to stdout on a JSON parse failure so the caller can
                 detect it (default 'trust-parse-error'); pass '' to print
                 nothing on error.

Exit: 0 always on well-formed invocation (parse errors are reported in-band via
--error-token, matching the callers' fail-closed grep); 2 on a bad --fields.
"""
import sys
import json
import argparse
import re

FIELD_KEYS = {"ID": "ID", "TRUSTOR": "Trustor User ID", "TRUSTEE": "Trustee User ID"}


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--fields", required=True)
    ap.add_argument("--trustor-in", default=None)
    ap.add_argument("--first", action="store_true")
    ap.add_argument("--error-token", default="trust-parse-error")
    a = ap.parse_args()

    fields = [f.strip().upper() for f in a.fields.split(",") if f.strip()]
    bad = [f for f in fields if f not in FIELD_KEYS]
    if not fields or bad:
        sys.stderr.write("trust_filter: bad --fields %r\n" % a.fields)
        return 2

    uids = None
    if a.trustor_in is not None:
        uids = set(re.split(r"[\s,]+", a.trustor_in.strip())) - {""}

    try:
        trusts = json.load(sys.stdin)
    except Exception as e:  # noqa: BLE001 -- report in-band, never traceback
        if a.error_token:
            print(a.error_token, e)
        return 0

    for t in trusts:
        if uids is not None and t.get("Trustor User ID") not in uids:
            continue
        print(" ".join(str(t.get(FIELD_KEYS[f], "")) for f in fields))
        if a.first:
            break
    return 0


if __name__ == "__main__":
    sys.exit(main())