#!/usr/bin/env python3
# tests/phase-02/make_fixtures.py [OUTDIR]
# Generate juju-status fixtures for the phase-02-vault-preflight regression.
# One healthy fixture + four single-fault fixtures (one broken gate each).
# ASCII + LF.
import json, copy, os, sys

OUTDIR = sys.argv[1] if len(sys.argv) > 1 else "."

def unit(cur, msg, agent="idle", subs=None):
    u = {"workload-status": {"current": cur, "message": msg},
         "agent-status": {"current": agent}}
    if subs:
        u["subordinates"] = subs
    return u

base = {
  "model": {"name": "openstack"},
  "machines": {str(i): {"juju-status": {"current": "started"}, "hostname": f"openstack{i}"} for i in range(4)},
  "applications": {
    "mysql-innodb-cluster": {"units": {
        "mysql-innodb-cluster/0": unit("active", "Unit is ready: Mode: R/W, Cluster is ONLINE and can tolerate up to ONE failure.",
                                       subs={"mysql-router/0": unit("active", "Unit is ready")}),
        "mysql-innodb-cluster/1": unit("active", "Unit is ready: Mode: R/O, Cluster is ONLINE and can tolerate up to ONE failure.",
                                       subs={"mysql-router/1": unit("active", "Unit is ready")}),
        "mysql-innodb-cluster/2": unit("active", "Unit is ready: Mode: R/O, Cluster is ONLINE and can tolerate up to ONE failure.",
                                       subs={"mysql-router/2": unit("active", "Unit is ready")}),
    }},
    "vault": {"units": {
        "vault/0": unit("blocked", "Vault needs to be initialized",
                        subs={"vault-mysql-router/0": unit("active", "Unit is ready")}),
    }},
    "octavia": {"units": {"octavia/0": unit("blocked", "Awaiting configure-resources action.")}},
    "ovn-central": {"units": {f"ovn-central/{i}": unit("waiting", "ovsdb-peer/certificates") for i in range(3)}},
    "nova-compute": {"units": {
        f"nova-compute/{i}": unit("active", "Unit is ready", subs={f"ovn-chassis/{i}": unit("waiting", "certificates")})
        for i in range(3)
    }},
    "neutron-api": {"units": {
        "neutron-api/0": unit("active", "Unit is ready", subs={"neutron-api-plugin-ovn/0": unit("waiting", "ovsdb-cms")}),
    }},
    "ceph-osd": {"units": {f"ceph-osd/{i}": unit("active", "Unit is ready (1 OSD)") for i in range(4)}},
    "ceph-mon": {"units": {f"ceph-mon/{i}": unit("active", "Unit is ready and clustered") for i in range(3)}},
    "glance-simplestreams-sync": {"units": {"glance-simplestreams-sync/0": unit("unknown", "")}},
  }
}

def dump(name, obj):
    path = os.path.join(OUTDIR, name)
    with open(path, "w") as f:
        json.dump(obj, f, indent=2)
    print(f"  wrote {path}")

# healthy
dump("pass.json", base)

# FAIL D: vault already initialized (not the fresh blocked-needs-init state)
f = copy.deepcopy(base)
f["applications"]["vault"]["units"]["vault/0"]["workload-status"] = {"current": "active", "message": "Unit is ready"}
dump("fail-vault-initialized.json", f)

# FAIL C: one mysql unit OFFLINE (no ONLINE, not active)
f = copy.deepcopy(base)
f["applications"]["mysql-innodb-cluster"]["units"]["mysql-innodb-cluster/2"]["workload-status"] = \
    {"current": "blocked", "message": "Cluster is inaccessible from this instance (OFFLINE)."}
dump("fail-mysql-degraded.json", f)

# FAIL E: a hook failure (agent-status error) on an otherwise-maintenance unit
f = copy.deepcopy(base)
f["applications"]["nova-compute"]["units"]["nova-compute/0"]["workload-status"] = {"current": "maintenance", "message": "installing"}
f["applications"]["nova-compute"]["units"]["nova-compute/0"]["agent-status"] = {"current": "error", "message": 'hook failed: "install"'}
dump("fail-hook-error.json", f)

# FAIL B: a machine not started
f = copy.deepcopy(base)
f["machines"]["2"]["juju-status"] = {"current": "down"}
dump("fail-machine-down.json", f)
