Skip to main content
Version: 0.3 · v0.3.0

Read reports

The operator writes two kinds of report, both JSON with a top-level kind:

ReportWritten byHolds
<name>.miropsa ClusterMirror, on every rebuildThe cluster's current state and risk.
<name>.miropsan UpgradeAnalysis, on every runThe upgrade verdict for one target version.

The mirror report​

FieldUse
generatedAt, clusterVersionWhen the mirror was rebuilt, and the version the cluster runs.
summaryComponents, edges, components at risk, namespaces at risk.
atRiskEach component with risk 50 or higher, what depends on it, and where its risk comes from (inheritedFrom).
risk.byNamespacePer namespace: highest component risk, components, components at risk.
issues, pods, workloadsLive problems, pod health, and the inventory.
addonsAdd-ons detected (compatibility is the upgrade report's job).
graphThe full dependency graph.
upgradeenabled — whether this install runs upgrade analysis — and analyses[]: each UpgradeAnalysis's name, target version, decision, score, and where its report is.

The upgrade report​

FieldUse
decision.levelThe verdict — SAFE / WARNING / CRITICAL.
decision.allowBoolean gate — false means blocked.
decision.blockersEvery reason it's CRITICAL. Fix them all.
scores.totalThe readiness gauge (0–100). Not the gate.
addonsEach add-on's compatibility with the target version, and the version to upgrade to.
upgradeImpactFor each add-on the target version breaks, everything that depends on it.
workloads.*, risk, graphThe inventory at analysis time, as in 0.1.0.

From the CLI​

# the impact of a change, judged against the mirror report
mirops scan --source s3://my-reports/prod/default.mirops -f k8s/ -n payments --enforce

# a namespace's current state, from the mirror report
mirops scan --source s3://my-reports/prod/default.mirops -n payments

# the upgrade verdict
mirops scan --source s3://my-reports/prod/default.mirops \
--upgrade --upgrade-source s3://my-reports/prod/to-1-35.mirops

# machine-readable
mirops scan --source ./default.mirops -n all --output json | jq '.checks.namespaces'

--source is the mirror report. For the upgrade check, --upgrade-source is the analysis report — you give its URL; the CLI doesn't look it up. Pointing --source straight at a .mirops, as in 0.1.0, still gates on that analysis.

note

A local path reads a file on the CLI's own filesystem — not the operator's pod. A file-destination report lives inside the pod and is served over HTTP; read it with http://… (see below) or use a remote destination for CI outside the cluster.

From a remote destination​

The CLI reads S3, Azure Blob, and HTTP directly, each with the pipeline's own credentials for its scheme:

# S3 (IRSA / env vars / static keys)
mirops scan --source s3://my-bucket/clusters/default.mirops -n all

# Azure Blob (az login / Workload Identity)
mirops scan --source azure://mystorageacct/reports/default.mirops -n all

# the operator's in-cluster HTTP endpoint — it reads any destination back for you
mirops scan --source "http://mirops-reports.mirops:8084/reports/default.mirops?kind=ClusterMirror" -n all

Azure Blob source format: azure://<storageaccount>/<container>/<blob>. S3: s3://<bucket>/<key>.

Configure with environment variables​

Every flag has an environment-variable equivalent, MIROPS_<FLAG>, so a pipeline sets its config once and runs a bare mirops scan. Flags take precedence over env vars.

Env varFlagDefaultExample
MIROPS_SOURCE--source—s3://my-bucket/prod/default.mirops
MIROPS_FILE-f, --file—k8s/, deploy.yaml, - (stdin)
MIROPS_NAMESPACE-n, --namespace—payments, payments,checkout, all
MIROPS_MAX_MIRROR_AGE--max-mirror-age1h30m
MIROPS_UPGRADE--upgradefalsetrue
MIROPS_UPGRADE_SOURCE--upgrade-source—s3://my-bucket/prod/to-1-35.mirops
MIROPS_OUTPUT--outputtabletable | json
MIROPS_ENFORCE--enforcefalsetrue
MIROPS_ENFORCE_LEVEL--enforce-levelcriticalcritical | warning

For remote sources, the usual cloud-credential env vars apply too — AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY for S3, or AZURE_CLIENT_ID / AZURE_TENANT_ID / AZURE_CLIENT_SECRET for Azure Blob. Or use a role (OIDC in CI, IRSA / Workload Identity in the cluster) and set nothing — see Credentials.

From Kubernetes status​

You don't always need the full report — the headline numbers live on the CRs:

kubectl get clustermirror default \
-o jsonpath='{.status.atRisk} at risk, rebuilt {.status.lastSync}{"\n"}'

kubectl get upgradeanalysis to-1-35 \
-o jsonpath='{.status.decision} {.status.totalScore}{"\n"}'

From the HTTP endpoint​

The mirops-reports service serves both reports, wherever they're stored:

kubectl -n mirops port-forward svc/mirops-reports 8084:8084
curl "http://localhost:8084/reports/default.mirops?kind=ClusterMirror" | jq '.summary'
curl http://localhost:8084/reports/to-1-35.mirops | jq '.decision'

In the Web UI​

The Web UI renders both — the Cluster Mirror page from the mirror report, each analysis from its upgrade report — reading them through the operator's endpoint.