Reports
A report is the full analysis output — the verdict, score breakdown, add-on compatibility, dependency graph, per-namespace risk, and the workload inventory — as JSON. The operator writes one per analysis to the destination you choose.
Destinations
spec.source.type selects where the report goes:
| Type | Where | Key fields |
|---|---|---|
file (default) | Ephemeral file in the operator pod (emptyDir), served over HTTP (:8084). Lost on pod restart. | path |
pvc | In-cluster persistent storage — a PersistentVolumeClaim mounted into the operator. Same as file but survives pod restarts; no cloud needed. | path (mount dir) |
s3 | Amazon S3 — no local replica | bucket, region, key, credentialsSecret |
blob | Azure Blob — no local replica | accountName, containerName, blobName, credentialsSecret |
Remote destinations keep no local replica — the operator writes only to the destination and reads it back on demand (in memory) to serve it, using its own credentials so the connection never leaves the operator.
Which destination for which consumer
Where a report lives determines who can read it:
| Destination | Where it lives | How the CLI reads it |
|---|---|---|
file | Inside the operator pod (ephemeral) | In-cluster only — the HTTP endpoint --source http://mirops-reports.<ns>:8084/reports/<name>.mirops. Not on the CLI runner's disk. |
pvc | In-cluster persistent volume | In-cluster only — the HTTP endpoint (above), or mount the same PVC and read the file (--source /mnt/reports/<name>.mirops). Mounting alongside the operator needs ReadWriteMany, or ReadWriteOnce on the same node. |
s3 / blob | Object storage | From anywhere — --source s3://… / azure://…. |
file and pvc reports live inside the cluster, so a CI runner outside the cluster can't reach them. You have two options:
- Use a remote destination (
s3/blob) — the runner reads it directly from anywhere. This is the recommended pattern for external CI. - Pull the file into the pipeline manually — fetch the
.miropsonto the runner (e.g.kubectl cpit out of the pod, or download it from the PVC), then gate on the local copy:mirops scan --source ./report.mirops --enforce. The CLI's--sourceaccepts any local path, so however the file gets onto the runner, it works.
Naming
Every destination uses the .mirops extension (the content is JSON). For s3/blob you own the object name via key/blobName; leave it empty and it defaults to <analysis-name>.mirops. For pvc and the local file destination the report is <analysis-name>.mirops. The .mirops extension keeps reports distinct from config files sharing a destination — filter them with *.mirops.
Failures are surfaced, not hidden
When the operator can't write to (or read back from) a destination, it records the outcome on the CR so it shows in kubectl describe and the UI instead of only the pod logs:
| Status field | Meaning |
|---|---|
status.reportState | written or failed |
status.reportError | The failure message |
status.reportLocation | Where it tried to write |
Deleting the UpgradeAnalysis never deletes the report from S3/Blob/PVC — there is no cleanup finalizer, so your data is never removed without your action.
Consuming reports
- CLI —
mirops scan --source <report>reads any destination. See read reports. - Web UI — reads through the operator's report endpoint.
- Your tools — the report is plain JSON with a stable schema.