fix(tiller): ImageRef works in raw dict positions #6

Merged
arrdem merged 1 commit from arrdem/imageref-yaml-representer into trunk 2026-04-24 06:54:52 +00:00
Contributor

Summary

Make ImageRef usable anywhere in a manifest — including user-composed dicts like extra_containers=[{"image": some_ref}] — not just as the image= kwarg on builder functions.

Two commits, one story

  1. tiller.render YAML representer for ImageRef. ImageRef auto-unwraps from OpaquePythonObject at the Starlark→Python boundary, so it reaches yaml.dump as a raw dataclass. Without a representer PyYAML emits !!python/object:tiller.types.ImageRef, which is invalid k8s YAML. Register _imageref_representer that emits str(imageref).

  2. _parse_registry accepts str | ImageRef. inject_pull_secrets runs BEFORE render, so commit 1 alone wasn't enough — the transform sees the raw ImageRef inside container["image"] and errors with 'ImageRef' object has no attribute 'split'. Coerce to str at entry; ImageRef.__str__ yields the canonical form the existing parsing already handles.

Motivation

A downstream flowmetal Tillerfile wanted extra_containers=[_chaos_sidecar(...)] with an ImageRef-typed chaos_image. It was forced to type the input as a plain str to dodge commit 1's YAML bug, which threw away tag/digest semantics. Both halves of this PR together restore "ImageRef just works everywhere."

Test plan

tests/test_render.py:

  • test_imageref_in_image_kwarg — baseline.
  • test_imageref_in_extra_container — defect case + explicit !!python/object absence assertion.
  • test_imageref_digest — digest form.

tests/test_transforms.py:

  • test_imageref_in_extra_containerinject_pull_secrets picks the right registry from a sidecar ImageRef.
  • test_imageref_with_digest — same with a digest.

244 tests pass in the full suite (up from 242).

### Summary Make `ImageRef` usable anywhere in a manifest — including user-composed dicts like `extra_containers=[{"image": some_ref}]` — not just as the `image=` kwarg on builder functions. ### Two commits, one story 1. **`tiller.render` YAML representer for ImageRef.** ImageRef auto-unwraps from `OpaquePythonObject` at the Starlark→Python boundary, so it reaches `yaml.dump` as a raw dataclass. Without a representer PyYAML emits `!!python/object:tiller.types.ImageRef`, which is invalid k8s YAML. Register `_imageref_representer` that emits `str(imageref)`. 2. **`_parse_registry` accepts `str | ImageRef`.** `inject_pull_secrets` runs BEFORE render, so commit 1 alone wasn't enough — the transform sees the raw ImageRef inside `container["image"]` and errors with `'ImageRef' object has no attribute 'split'`. Coerce to str at entry; `ImageRef.__str__` yields the canonical form the existing parsing already handles. ### Motivation A downstream flowmetal Tillerfile wanted `extra_containers=[_chaos_sidecar(...)]` with an `ImageRef`-typed `chaos_image`. It was forced to type the input as a plain `str` to dodge commit 1's YAML bug, which threw away tag/digest semantics. Both halves of this PR together restore "ImageRef just works everywhere." ### Test plan `tests/test_render.py`: - `test_imageref_in_image_kwarg` — baseline. - `test_imageref_in_extra_container` — defect case + explicit `!!python/object` absence assertion. - `test_imageref_digest` — digest form. `tests/test_transforms.py`: - `test_imageref_in_extra_container` — `inject_pull_secrets` picks the right registry from a sidecar ImageRef. - `test_imageref_with_digest` — same with a digest. 244 tests pass in the full suite (up from 242).
Companion to the render-pipeline ImageRef representer. Before
that representer landed, the only way an image value appeared in
the manifest was as a string (builders called `str(image)` at
their `image=` kwarg). Now that users can put an ImageRef in a
raw dict position like `extra_containers=[{"image": some_ref}]`,
the `inject_pull_secrets` transform — which reads container
image values to pick an appropriate pull secret per registry —
sees raw ImageRef instances and errors with
`'ImageRef' object has no attribute 'split'`.

`_parse_registry` now coerces to str at entry (ImageRef's
`__str__` yields the canonical `repo:tag` or `repo@digest` form,
which the existing parsing handles correctly).

Two new tests in tests/test_transforms.py:
- inject_pull_secrets with an ImageRef (tag form) in a sidecar
  container injects the matching pull secret.
- Same with an ImageRef (digest form).
arrdem merged commit 4c84730608 into trunk 2026-04-24 06:54:52 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
arrdem/source!6
No description provided.