Skip to content

Latest commit

Β 

History

26 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

oud-tools

A command-line utility to parse Oracle Unified Directory (OUD) proxy configuration files and print a human-readable load-balancing architecture diagram.


Scope

This tool targets Oracle Unified Directory Proxy (formerly Oracle Directory Server Enterprise Edition / Directory Proxy Server β€” "DPS") configurations specifically, identified by com.sun.dps.server.workflowelement.* Java classes (ProxyLdapWorkflowElement, LoadBalancingWorkflowElement, LDAPServerExtension).

It does not apply to a plain OUD Directory Server instance (one that stores data locally via a db-local-backend-workflow-element / JE backend rather than proxying to remote servers). Running it against such a config will produce an empty or near-empty diagram, since no proxy/LB workflow elements will be found.

OUD Directory Server OUD Proxy
Data backend Local (JE/DB) None β€” routes to remote directories
Typical WE db-local-backend-workflow-element proxy-ldap-workflow-element, load-balancing-workflow-element
Java namespace org.opends.server.* only org.opends.server.* (shared base) + com.sun.dps.server.workflowelement.*
This tool Not applicable βœ… Supported

Requirements

  • Python 3.6+
  • No external dependencies (standard library only β€” re, base64, collections)

Usage

python oud_lb_diagram.py <path-to-config.ldif>
python oud_lb_diagram.py --version                             # print version and exit
python oud_lb_diagram.py <config> --output <file>               # save diagram to file
python oud_lb_diagram.py <config> --no-tree                     # skip workflow tree(s), print only summary + backend table
python oud_lb_diagram.py <config> --anonymize                   # mask real backend IPs with RFC 5737 placeholders
python oud_lb_diagram.py <config> --format json                 # output the parsed model as JSON (pipeable β€” diagnostics go to stderr)
python oud_lb_diagram.py <config> --format json --anonymize | jq .model.extensions
python oud_lb_diagram.py <config> --output report.txt --no-tree --anonymize  # combine flags freely

--format json is the only alternative to the default text format. YAML isn't offered β€” it isn't in the Python standard library and this project has zero external dependencies β€” pipe the JSON through a converter (yq, python -c "import sys,yaml,json; ...", etc.) if you need YAML.

If no argument is provided, the script looks for config.ldif in the current directory.


What it does

The script reads the OUD proxy config.ldif file and:

  1. Parses all LDIF entries β€” network groups, workflows, load-balancing workflow elements, proxy workflow elements, and backend extensions
  2. Builds the routing tree dynamically, at any depth, without hardcoded assumptions on the architecture
  3. Prints a text diagram showing:
    • The full workflow element hierarchy from entry point down to backend IPs
    • The load-balancing algorithm at each node (PROPORTIONAL, FAILOVER, ROUND-ROBIN)
    • Per-operation weights for proportional nodes (e.g. add/modify/delete:1 search/bind:0)
    • Per-operation priorities for failover nodes (e.g. all:1 or search/bind:1 add/modify:2)
    • switch-back: ON flag where present
    • Backend IP, port, SSL port, SSL policy, connection pool size, credential mode
  4. Prints a backend servers table summarising all proxy WEs and their resolved extensions
  5. Prints a legend explaining the notation
  6. Adapts the diagram width automatically to the longest line of content (with safety bounds), so the frame never looks cramped or needlessly wide
  7. Parses LDIF robustly β€” handles RFC 4511 line folding (continuation lines), base64-encoded values, and case-insensitive DN references
  8. Warns on unresolved references β€” flags any workflow-element or extension DN that cannot be resolved in the parsed config
  9. Can anonymize backend IPs on demand (--anonymize) β€” replaces real IPs with stable RFC 5737 documentation-range placeholders, useful when sharing diagrams outside the team
  10. Highlights disabled components β€” proxy WEs and their backend extensions each track their own ds-cfg-enabled state; either one being false shows a !! DISABLED marker in both the workflow tree and the backend servers table
  11. Can emit structured JSON (--format json) instead of the ASCII diagram, for scripting/automation β€” diagnostics go to stderr so stdout stays pure, pipeable JSON

Example output

[+] Parsed 316 LDIF entries from: config_proxyoud_test.ldif
[+] Found: 2 network group(s)  1 workflow(s)  6 LB WE(s)  6 proxy WE(s)  6 backend extension(s)

╔════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
β•‘                                  OUD PROXY β€” LOAD BALANCING ARCHITECTURE                                   β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  NETWORK GROUPS                                                                                            β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  cn=network-group  priority:1  enabled:true  β†’  workflow:workflowLB  base-dn:dc=example,dc=com             β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  WORKFLOW TREE  β€”  workflowLB  β€”  base-dn: dc=example,dc=com                                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  └─ LB_MS  [PROPORTIONAL]                                                                                  β”‚
β”‚     β”œβ”€ LB_MS_routeR  weights: search/bind/compare/extended:1  add/modify/delete/modifydn:0                 β”‚
β”‚     β”‚  └─ LB-Slave  [PROPORTIONAL]                                                                         β”‚
β”‚     β”‚     β”œβ”€ LB-Slave_S1  weights: search/bind/add/modify/delete/compare/modifydn/extended:1               β”‚
β”‚     β”‚     β”‚  └─ FO_S1  [FAILOVER  switch-back:ON]                                                          β”‚
β”‚     β”‚     β”‚     β”œβ”€ FO_S1_routeS3  prio: all:1                                                              β”‚
β”‚     β”‚     β”‚     β”‚  └─ proxy-we5  β†’  198.51.100.21  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β”‚     β”‚     β”‚     β”œβ”€ FO_S1_routeS4  prio: all:2                                                              β”‚
β”‚     β”‚     β”‚     β”‚  └─ proxy-we6  β†’  198.51.100.22  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β”‚     β”‚     β”‚     β”œβ”€ FO_S1_routeS1  prio: all:3                                                              β”‚
β”‚     β”‚     β”‚     β”‚  └─ proxy-we3  β†’  198.51.100.11  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β”‚     β”‚     β”‚     └─ FO_S1_routeS2  prio: all:4                                                              β”‚
β”‚     β”‚     β”‚        └─ proxy-we4  β†’  198.51.100.12  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β”‚     β”‚     └─ LB-Slave_S2  weights: search/bind/add/modify/delete/compare/modifydn/extended:1               β”‚
β”‚     β”‚        └─ FO_S2  [FAILOVER  switch-back:ON]                                                          β”‚
β”‚     β”‚           β”œβ”€ FO_S2_routeS4  prio: all:1                                                              β”‚
β”‚     β”‚           β”‚  └─ proxy-we6  β†’  198.51.100.22  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β”‚     β”‚           └─ ...                                                                                     β”‚
β”‚     └─ LB_MS_routeW  weights: add/modify/delete/modifydn:1  search/bind/compare/extended:0                 β”‚
β”‚        └─ LB-Master  [PROPORTIONAL]                                                                        β”‚
β”‚           └─ LB-Master_M  weights: search/bind/add/modify/delete/compare/modifydn/extended:1               β”‚
β”‚              └─ FO_M  [FAILOVER  switch-back:ON]                                                           β”‚
β”‚                 β”œβ”€ FO_M_routeM2  prio: all:1                                                               β”‚
β”‚                 β”‚  └─ proxy-we2  β†’  198.51.100.20  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β”‚                 └─ FO_M_routeM1  prio: all:2                                                               β”‚
β”‚                    └─ proxy-we1  β†’  198.51.100.10  port:389  SSL:1636  (always)  cred:use-client-identity  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  BACKEND SERVERS                                                                                           β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  Extension   WE              IP Address          Port    SSL     Policy    Pool     Cred-mode              β”‚
β”‚  --------------------------------------------------------------------------------------------------------  β”‚
β”‚  proxy1      proxy-we1       198.51.100.10       389     1636    always    10000    use-client-identity    β”‚
β”‚  proxy2      proxy-we2       198.51.100.20       389     1636    always    10000    use-client-identity    β”‚
β”‚  proxy3      proxy-we3       198.51.100.11       389     1636    always    10000    use-client-identity    β”‚
β”‚  proxy4      proxy-we4       198.51.100.12       389     1636    always    10000    use-client-identity    β”‚
β”‚  proxy5      proxy-we5       198.51.100.21       389     1636    always    10000    use-client-identity    β”‚
β”‚  proxy6      proxy-we6       198.51.100.22       389     1636    always    10000    use-client-identity    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  LEGEND                                                                                                    β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  PROPORTIONAL   Distributes traffic by weight per operation type.                                          β”‚
β”‚                 weights shown as  ops:value  β€”  e.g. add/modify/delete:1  search/bind:0                    β”‚
β”‚  FAILOVER       One active node at a time; lower [prio] = preferred.                                       β”‚
β”‚                 switch-back:ON = auto-restore to primary when it recovers.                                 β”‚
β”‚  ROUND-ROBIN    Cycles through available routes in order.                                                  β”‚
β”‚  └─ <node>      Leaf node = backend proxy WE resolved to IP:port.                                          β”‚
β”‚  cred-mode      How client credentials are forwarded to the backend.                                       β”‚
β”‚  !! DISABLED    ds-cfg-enabled: false on this WE or its backend extension β€” inactive.                      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Note: the diagram frame width above adapts automatically to the longest line in the loaded config (bounded between MIN_W=60 and MAX_W=200 columns) β€” your output may be narrower or wider depending on attribute lengths, DN depth, and IP formats.

If the config contains a network group without an associated workflow, or a workflow-element / extension reference that cannot be resolved, warnings are printed before the diagram:

[+] Parsed 316 LDIF entries from: config.ldif
[WARN] network-group "Network Group" references unknown workflow: 
[WARN] proxy-we "proxy-we7" references unknown extension: cn=proxy7,cn=extensions,cn=config
[+] Found: 2 network group(s)  1 workflow(s)  6 LB WE(s)  7 proxy WE(s)  6 backend extension(s)

How to read the diagram

Notation Meaning
[PROPORTIONAL] Traffic distributed by weight across routes
[FAILOVER switch-back:ON] One active node at a time; lower prio = preferred; auto-restore to primary
weights: add/modify:1 search:0 Operations with weight > 0 are routed here; 0 = blocked
prio: all:1 All operation types have the same priority on this route
prio: search/bind:1 add/modify:2 Per-operation priorities differ (route preferred for reads, backup for writes)
β†’ x.x.x.151 port:389 SSL:1636 Resolved backend IP and ports
cred:use-client-identity Client credentials passed through as-is to the backend

Architecture notes

The script makes no assumptions about the number of levels, branch names, or routing semantics. It explores the tree generically and reports what is in the config. Semantic interpretation (e.g. which branch is WRITE vs READ) is left to the reader and can be inferred from the weights.

Supported load-balancing algorithm types:

  • PROPORTIONAL β€” weight-based distribution per operation
  • FAILOVER β€” single active node with priority-based fallback
  • ROUND-ROBIN β€” sequential cycling (if present in config)

Parser

The LDIF parser is RFC 4511 compliant:

  • Continuation lines (starting with a single space) are folded into the previous logical line
  • Base64-encoded values (attr:: <b64>) are decoded to UTF-8, with hex fallback for binary content
  • URL references (attr:< <url>) are recognised and stored as-is
  • All DNs (entry keys and cross-references) are normalised to lowercase for consistent lookup, regardless of the original casing in the config; display labels still use the original-case cn attribute value

Limitations

  • Only parses LDAPServerExtension backends (OUD proxy mode)
  • Local backends (JE/DB), replication domains, virtual ACIs and other config objects are ignored
  • Tested on OUD 11g/12c proxy config format

Versioning

This project follows Semantic Versioning. See CHANGELOG.md for the full version history.

Check the installed version with:

python oud_lb_diagram.py --version

Testing

Unit test suites cover LDIF parsing, model extraction, and backend/replication reporting (66 tests total, no external dependencies β€” standard library unittest only):

python3 -m unittest test_oud_ldif_core.py -v          # shared parser (14 tests)
python3 -m unittest test_oud_lb_diagram.py -v          # diagram tool (38 tests)
python3 -m unittest test_oud_backend_report.py -v      # backend report tool (6 tests)
python3 -m unittest test_oud_config_lint.py -v          # config linter (8 tests)

# or run everything at once:
python3 -m unittest discover -p "test_*.py" -v

Architecture: shared core

oud_lb_diagram.py, oud_config_type.py, oud_backend_report.py, and oud_config_lint.py all build on a shared parsing layer, oud_ldif_core.py, which contains the generic LDIF parser (parse_ldif) and small DN/attribute utilities (first, cn_of) β€” nothing specific to any one tool's object model. All files must stay in the same directory:

                              oud_ldif_core.py
              (shared: parse_ldif, first, cn_of β€” no dependency on the tools below)
                 β–²         β–²              β–²              β–²
                 β”‚         β”‚              β”‚              β”‚
      oud_lb_diagram.py  oud_config_type.py  oud_backend_report.py  oud_config_lint.py
      (proxy load          (instance          (Directory Server      (validator β€”
       balancing            classifier)        backend/replication    imports models from
       diagram)                                 report)                the two tools above)

oud_lb_diagram.py and oud_backend_report.py each call into oud_config_type.py at runtime for an early, direction-appropriate scope warning (B7) β€” oud_lb_diagram.py warns if the config doesn't look like a Proxy, oud_backend_report.py warns if it doesn't look like a Directory Server. oud_config_lint.py goes further: it imports extract_model from oud_lb_diagram.py and extract_backends/extract_replication_domains from oud_backend_report.py directly, reusing their object models instead of re-deriving them, and uses oud_config_type.py to decide which rule set(s) to run.

All cross-tool links (oud_config_type.py, and the model-reuse imports in oud_config_lint.py) are soft dependencies: if the imported file isn't present, that part is silently skipped rather than failing. oud_ldif_core.py, by contrast, is a hard dependency for all four tools β€” parsing is impossible without it, so its absence fails fast with a clear error.


Files

File Description
oud_lb_diagram.py Load balancing diagram for OUD Proxy configs
oud_backend_report.py Backend/index/replication report for OUD Directory Server configs
oud_config_lint.py Validator/linter for both Proxy and Directory Server configs
oud_config_type.py OUD instance classifier (Proxy / Directory Server / Hybrid). Run standalone or used automatically by the tools above for an early scope warning.
oud_ldif_core.py Shared LDIF parser and DN utilities, used by all three tools above
test_oud_lb_diagram.py Unit test suite for the diagram tool (38 tests)
test_oud_backend_report.py Unit test suite for the backend report tool (6 tests)
test_oud_config_lint.py Unit test suite for the config linter (8 tests)
config_ds_test.ldif Safe, synthetic OUD Directory Server config fixture for testing oud_backend_report.py
test_oud_ldif_core.py Unit test suite for the shared parser (14 tests)
README.md This file
CHANGELOG.md Version history
BACKLOG.md Planned work

Companion tool: oud_config_type.py

Detects what kind of OUD instance a config belongs to, based on ds-cfg-java-class and objectClass evidence β€” useful to check before running the diagram tool, since oud_lb_diagram.py only supports OUD Proxy configs.

python oud_config_type.py <path-to-config.ldif>

Reports one of: OUD Proxy, OUD Directory Server, Hybrid (both proxy-LB and a real local data backend present β€” unusual), or Unknown / inconclusive, plus the matching DNs as evidence. If placed in the same directory as oud_lb_diagram.py, the diagram tool calls it automatically and prints a [WARN] up front when the config doesn't look like a Proxy instance.


Companion tool: oud_backend_report.py

Reads an OUD Directory Server config (not proxy) and reports local user-data backends, their indexes, and replication domains β€” the counterpart to oud_lb_diagram.py for non-proxy instances.

python oud_backend_report.py <path-to-config.ldif>
python oud_backend_report.py --version
python oud_backend_report.py <config> --output <file>
python oud_backend_report.py <config> --anonymize    # mask replication-server IPs with RFC 5737 placeholders

Reports:

  • Local data backends β€” base-dn, writability, txn-durability, db-directory, compression, default index-entry-limit, index count, and a !! DISABLED marker if applicable. System/private backends (schema, tasks, admin, trust store, backup) are excluded automatically, same distinction oud_config_type.py uses for classification.
  • Indexes per backend β€” attribute, index type(s), entry limit.
  • Replication domains β€” base-dn, server-id, group-id, replication servers, isolation policy, window size.

Like oud_lb_diagram.py, it calls into oud_config_type.py automatically (soft dependency) and warns if the loaded config looks like a Proxy rather than a Directory Server.

A safe, synthetic test fixture is included β€” config_ds_test.ldif (19 entries, RFC 5737 addresses, 1 user-data backend, 9 indexes, 3 replication domains) β€” so you can try the tool without needing a real config:

python oud_backend_report.py config_ds_test.ldif

Companion tool: oud_config_lint.py

Validator/linter for both OUD Proxy and Directory Server configs. Uses oud_config_type.py to detect the profile and runs the matching rule set(s); on a Hybrid config, runs both.

python oud_config_lint.py <path-to-config.ldif>
python oud_config_lint.py --version
python oud_config_lint.py <config> --output <file>
python oud_config_lint.py <config> --format json

Findings are grouped by severity: ERROR, WARNING, INFO. Exit codes are CI-friendly:

Exit code Meaning
0 Rules ran, no ERROR-severity findings (WARNING/INFO are fine)
1 At least one ERROR-severity finding
2 No rules were run (profile undetermined or tool modules missing) β€” distinct from 0 so a pipeline can never pass green on zero executed checks

Proxy rules:

Rule Severity Checks
P-REF-1 ERROR Broken workflow-element / extension references
P-ARCH-1 WARNING Workflow element unreachable from any network group
P-ARCH-2 WARNING Disabled component (proxy WE, its extension, or LB WE) still reachable/referenced
P-SEC-1 WARNING ssl-trust-all: true (backend certificate not validated)
P-SEC-2 INFO ssl-policy not always
P-PERF-1 WARNING Connection pool size missing or zero
P-PERF-2 INFO Connect/read timeout set to 0 (no timeout)
P-HYG-1 INFO Duplicate CNs across workflow elements
P-HYG-2 WARNING Network group with no workflow configured

Directory Server rules:

Rule Severity Checks
D-ARCH-1 INFO Backend with no replication domain (standalone?)
D-ARCH-2 WARNING Replication domain with no matching local backend
D-HYG-1 WARNING Duplicate server-id across replication domains
D-PERF-1 INFO Commonly-queried attribute (uid/mail) with no index at all β€” a suggestion, not a confirmed usage pattern
python oud_config_lint.py config_ds_test.ldif   # clean config β†’ 0 findings

About

Parses Oracle Unified Directory (OUD) proxy config files (LDIF) and prints a text-based load-balancing architecture diagram showing algorithms, weights, priorities and backend IPs.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages