Skip to content

Ship chainsaw binary + wire deployment-phase runner (#660 PR 2) #1220

Description

@mchmarny

Summary

Ship the chainsaw binary in the deployment validator image and wire the
Chainsaw runner into aicr validate --phase deployment so the
hydrated ComponentRef.HealthCheckAsserts content from #660 PR 1
actually executes. Codify timeouts, parallelism, and Job envelope margin
as named constants. Restrict registry-declared assert content to a
read-only allowlist.

Depends on #660 PR 1 (hydration mechanism).

Scope

Validator image + library

  • Ship the chainsaw binary in the deployment validator image:
    • Reuse the version and per-platform checksums already pinned in
      .settings.yaml (chainsaw: 'v0.2.14' and chainsaw_checksums); do
      not introduce a second pin in Dockerfile or goreleaser config.
    • Use multi-stage COPY --from=... from an upstream chainsaw release
      artifact into the existing gcr.io/distroless/static-debian12:nonroot
      base (replace the base only if signing/scan coverage requires it).
    • The exec.LookPath / /usr/local/bin/chainsaw fallback in
      validators/chainsaw/binary.go:41-47 must find the binary at runtime.
  • Bump the kyverno/chainsaw Go library in go.mod in lockstep with
    the image binary; raw-K8s-YAML (library path) and Chainsaw Test format
    (binary path) dispatch in validators/chainsaw/runner.go:132-143 must
    stay aligned.

Runtime semantics

  • Per-component Chainsaw execution timeout: defaults.ChainsawAssertTimeout.
  • Outer envelope: the enclosing expected-resources validator catalog
    timeout (and therefore Job activeDeadlineSeconds) must exceed
    defaults.ChainsawAssertTimeout by a named-constant margin
    (defaults.JobEnvelopeMargin, ≥ 60s) so Chainsaw has headroom for
    process termination, temp-dir cleanup, and log flushing before the
    Job SIGKILLs the container.
  • Bounded parallelism across components: defaults.ChainsawMaxParallel.
  • Dispatch: raw K8s resource YAML via the chainsaw Go library
    (checks.Check); apiVersion: chainsaw.kyverno.io/v1alpha1 kind: Test via the binary (per the package comment at
    validators/chainsaw/runner.go:15-20).

Gate relaxation + CLI output

  • Drop the && len(ref.ExpectedResources) == 0 clause in
    validators/deployment/expected_resources.go:86 so both
    ExpectedResources and HealthCheckAsserts paths run per component
    during the transition. The current gate is mutually exclusive and
    silently skips Chainsaw whenever ExpectedResources are present.
  • Dedupe/annotate CLI output: when both paths report the same resource
    as healthy, collapse into a single line; when they disagree, report
    both with source tags ([expectedResources] / [chainsaw]).

Read-only allowlist

  • Reject any registry-declared assert content that uses a Chainsaw
    operation other than assert / error (deny script, wait,
    catch, apply, create, delete, patch, update, command,
    ...). This bounds the cluster-admin posture documented in
    pkg/validator/job/rbac.go:41-67. Lint-time enforcement lands in
    PR 5; PR 2 enforces at runtime so the contract is binding before
    backfill ([EPIC] Reuse Chainsaw health checks in aicr validate --phase deployment #660 PR 3) lands.

Migration of GPU deep checks from #611

  • Migrate clusterPolicyReady and skyhookReady from
    validators/deployment/expected_resources.go into the corresponding
    component's Chainsaw health-check YAML, so deployment validation is
    driven by registry-declared content for those two components.
  • draKubeletPluginReady: keep in Go for now. The chart's full
    DaemonSet name is release-derived (-kubelet-plugin suffix), and
    expressing the same check in static Chainsaw YAML requires a chart-shape
    label that may not yet be available. Document this exception in the PR
    body; do not encode a release-derived full name (would violate
    deployer-neutrality). PR 3 / PR 4 can revisit if a usable label exists.

Acceptance Criteria

  • aicr validate --phase deployment executes Chainsaw asserts declared
    via healthCheck.assertFile for every enabled component in the recipe
    that has one.
  • Validator image ships a pinned chainsaw binary whose version and
    per-platform checksums come from .settings.yaml; no duplicate pin.
  • kyverno/chainsaw Go library bumped in lockstep.
  • Job activeDeadlineSeconds exceeds defaults.ChainsawAssertTimeout
    by defaults.JobEnvelopeMargin (≥ 60s).
  • validators/deployment/expected_resources.go:86 gate is relaxed;
    both paths run; CLI output dedupes / source-tags.
  • Non-allowlisted Chainsaw operations are rejected at runtime with
    ErrCodeInvalidRequest.
  • clusterPolicyReady and skyhookReady are expressed in
    registry-declared Chainsaw YAML; draKubeletPluginReady documented
    as an exception.

Risks

  • Image size / pull latency from adding chainsaw binary — measure.
  • Distroless base may not satisfy chainsaw's runtime needs — fallback
    base must be reconsidered if signing/scan coverage breaks.
  • Chainsaw Go library bump may pull in transitive deps — diff CI.

Related

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions