CLI Policy Result Processing#
Overview#
The kubectl-kyverno apply command processes multiple policy types through distinct execution paths that all converge on a shared ResultCounts struct and a unified output pipeline. The primary entry point is applyCommandHelper in command.go.
Key files:
cmd/cli/kubectl-kyverno/commands/apply/command.go— top-level orchestrationcmd/cli/kubectl-kyverno/processor/policy_processor.go— per-resource policy executioncmd/cli/kubectl-kyverno/processor/result.go—ResultCountsand all accumulator methodscmd/cli/kubectl-kyverno/commands/apply/table.go— table output formattercmd/cli/kubectl-kyverno/report/report.go— policy report generation
Separate Processing Paths#
Loaded policies are split into typed slices (kpols, vps, ivps, dps, cps, mps, etc.) and dispatched through independent processing functions :
| Policy Type | Processing Function | Result Accumulator |
|---|---|---|
Legacy Policy/ClusterPolicy + VAPs, ValidatingPolicies, MutatingPolicies, GeneratingPolicies | applyPolicies → PolicyProcessor.ApplyPoliciesOnResource() | addEngineResponses, addMutateResponse, AddValidatingPolicyResponse, etc. |
ImageValidatingPolicy | applyImageValidatingPolicies | AddValidatingPolicyResponse |
DeletingPolicy | applyDeletingPolicies | AddValidatingPolicyResponse |
CleanupPolicy | applyCleanupPolicies | AddValidatingPolicyResponse |
| HTTP/Envoy policies | authzProcessor.Apply* | separate response lists |
Within ApplyPoliciesOnResource, legacy Kyverno policies are processed in a fixed order: mutate → verify images → validate → generate . ValidatingPolicies are additionally split by evaluation mode: EvaluationModeJSON policies are evaluated against raw JSON via celengine.RequestFromJSON, while default Kubernetes-mode policies go through the standard admission path . Kubernetes-mode policies are silently skipped when the input is a raw JSON payload .
All response slices are merged into a single []engineapi.EngineResponse before being passed to the output stage .
Shared Result Counting (ResultCounts)#
ResultCounts holds five integer counters: Pass, Fail, Warn, Error, Skip. Each policy type has a dedicated accumulator method with different audit-warn semantics:
addEngineResponse(legacy Kyverno policies): only processes responses whereAsKyvernoPolicy() != nil. ARuleStatusFailis downgraded toWarnif the policy is unscored (annotations.Scoredreturns false) or if--audit-warnis set and the failure action isAudit.addValidatingAdmissionResponse(VAPs): countsPass/Fail/Erroronly — no warn downgrade .AddValidatingPolicyResponse(ValidatingPolicy, DeletingPolicy, CleanupPolicy, ImageValidatingPolicy): countsPass/Fail/Error/Skip— no audit-warn logic .addMutateResponse: handles Kyverno, MAP, and MutatingPolicy types separately; returns a boolean indicating whether the patched resource should be printed .addGenerateResponse: handles both Kyverno and CEL-based GeneratingPolicy. For GeneratingPolicy, counts all five status types (Pass,Fail,Warn,Error,Skip). Previously, onlyPassandFailwere tracked;Error,Skip, andWarnstatuses were silently dropped, causing CEL evaluation errors (e.g., when test resources omitmetadata.uidand a policy readsobject.metadata.uid) to produce all-zero output instead of surfacing the error .
Important:
addEngineResponsesis called only for legacy Kyverno policy responses . VAP responses are appended after this call and counted separately viaaddValidatingAdmissionResponse.
Output Formatting Pipeline#
After all policies are processed, the command selects one of four output modes :
--policy-report: callsprintReports→ComputePolicyReports, which groups results per policy and emitsClusterReport(cluster-scoped) orPolicyReport(namespaced) YAML/JSON objects.--generate-exceptions: callsprintExceptionsto emitPolicyExceptionresources for each violation.--table/-t: callsprintTable, which iterates allEngineResponseobjects and renders a colored table row per rule result.- Default (violations list): iterates responses inline, printing failed rules per resource with an
"audit warning"label when applicable. Error messages are printed for both mutate and generate policies .
In table mode, the --audit-warn flag causes RuleStatusFail results from audit-mode policies to render as warnings (color.ResultWarn()) instead of failures . The --detailed-results flag controls compactness of the table output .
ComputePolicyReportResult applies the same audit-warn downgrade at the report level: if the result is StatusFail, the policy action is Audit, and auditWarn=true, the result is changed to StatusWarn before being written into the report .
Exit Code Logic#
The exit function determines the process exit code from ResultCounts:
rc.Fail > 0→ exit 1 ("policy violations")rc.Error > 0→ exit 1 ("policy errors")rc.Warn > 0and--warn-exit-code N→ exit Nrc.Pass == 0and--warn-no-pass→ exit with warn code
Policies routed through AddValidatingPolicyResponse (ValidatingPolicy, DeletingPolicy, CleanupPolicy, ImageValidatingPolicy) do not benefit from the audit-warn Fail→Warn downgrade in result counting, so their failures always contribute to rc.Fail and will trigger exit 1 regardless of --audit-warn.