Skip to content

Configuration Audit Report

Generate an audit report showing where values come from across the tree.

from hrcp import ResourceTree, PropagationMode, get_value

tree = ResourceTree(root_name="services")

# Set up services with inherited and local values
tree.root.set_attribute("env", "prod")
tree.root.set_attribute("timeout", 30)
tree.create("/services/api", attributes={"port": 8080, "replicas": 3})
tree.create("/services/worker", attributes={"replicas": 5})
tree.create("/services/cache", attributes={"port": 6379, "timeout": 60})

def audit_report(tree, attrs):
    """Generate an audit report showing value provenance."""
    print("Configuration Audit Report")
    print("=" * 60)

    for resource in tree.query("/**"):
        print(f"\n{resource.path}")

        for attr in attrs:
            prov = get_value(resource, attr, PropagationMode.INHERIT, with_provenance=True)
            if prov is not None:
                source = "(local)" if prov.source_path == resource.path else f"(from {prov.source_path})"
                print(f"  {attr}: {prov.value} {source}")
            else:
                print(f"  {attr}: not set")

audit_report(tree, ["env", "port", "replicas", "timeout"])

Output

Configuration Audit Report
============================================================

/services
  env: prod (local)
  port: not set
  replicas: not set
  timeout: 30 (local)

/services/api
  env: prod (from /services)
  port: 8080 (local)
  replicas: 3 (local)
  timeout: 30 (from /services)

/services/worker
  env: prod (from /services)
  port: not set
  replicas: 5 (local)
  timeout: 30 (from /services)

/services/cache
  env: prod (from /services)
  port: 6379 (local)
  replicas: not set
  timeout: 60 (local)

Enhanced Audit with Diff

Compare configuration between environments:

def config_diff(resource1, resource2, attributes):
    """Compare configuration between two resources."""
    print(f"Comparing {resource1.path} vs {resource2.path}\n")

    for attr in attributes:
        p1 = get_value(resource1, attr, PropagationMode.INHERIT, with_provenance=True)
        p2 = get_value(resource2, attr, PropagationMode.INHERIT, with_provenance=True)

        v1 = p1.value if p1 else None
        v2 = p2.value if p2 else None

        if v1 != v2:
            print(f"  {attr}:")
            print(f"    {resource1.path}: {v1} (from {p1.source_path if p1 else 'N/A'})")
            print(f"    {resource2.path}: {v2} (from {p2.source_path if p2 else 'N/A'})")

Key Patterns

  • Wildcard queries (/**) to iterate all resources
  • Provenance tracking shows local vs inherited
  • Audit utilities for compliance and debugging
  • Diff reports for comparing environments