Support `oci://` URL Scheme Prefixes in K8s Image References
Feature Request: Support for oci:// URL Scheme Prefixes in K8s Image References
Use Case
I'm using Tilt to develop Istio WasmPlugins, which are custom modules that extend Istio's proxy functionality using an OCI image. In my ideal workflow, I can:
- Configure Tilt to build the image using
custom_build(https://docs.tilt.dev/api.html#api.custom_build). - Configure Tilt to replace the OCI image placeholder in the WasmPlugin manifest with the one generated by the
custom build using
k8s_kind(https://docs.tilt.dev/custom_resource.html). - As a result, whenever the
custom_builddeps are updated, Tilt will automatically build the Docker image, push it to the registry, then update the Tilt resources.
Tilt is very close to working, but there is one minor issue. The WasmPlugin wants the image name to be prefixed by oci:// so that Istio knows to pull from OCI (instead of, file:// or https://, etc). However, the k8s_kind behavior of Tilt sees this string and throws an error, because oci:// is invalid in its image syntax.
Example WasmPlugin manifest:
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: my-plugin
spec:
url: oci://registry.example.com/my-wasm-plugin:1.0
Over time, I expect other use cases to run into this problem. For example:
- Flux and ArgoCD support
oci://for helm charts. - A handful of volume CSI drivers support mounting images as volumes using the
oci://syntax.
Root Cause
Tilt's current parse model (using distribution/reference) expects image references to follow the Docker format (e.g., registry.example.com/image:tag) and doesn't support URL schemes.
Proposed Solutions
Option 1: Wrapper Approach
Create a wrapper around the reference parser that preserves URL schemes:
- Add a
SchemeReferencetype ininternal/container/container.gothat wraps the standard Docker reference and preserves the scheme - Modify
ParseNamedto detect and strip URL schemes likeoci://before passing to the reference parser - Add a custom
FamiliarStringfunction that reattaches the scheme when converting back to string - Update dependent functions to use this scheme-aware parsing
Code references:
Pros:
- Doesn't require forking or modifying vendor libraries
- Lightweight change contained within Tilt's codebase
- Could handle other URL schemes like
docker://similarly
Cons:
- Adds complexity to the parsing logic
Option 2: Direct Vendor Library Modification
Modify the distribution/reference library directly:
- Update the regex patterns in
regexp.goto accept URL schemes - Modify
ParseNormalizedNamedto handle the schemes
Pros:
- Cleaner approach that handles it at the source, without Tilt having to own this complexity.
Cons:
- Requires modifying vendor code which makes dependency management harder
- Upstream project may not want this change (Docker image references technically don't support URL schemes)
Option 3: Custom Locator for WasmPlugins
Create a specialized ImageLocator implementation for WasmPlugins:
- Create a new
WasmPluginImageLocatorininternal/k8s/locator.gothat specifically handlesoci://prefixes - Register it through the
k8s_kindAPI for Istio WasmPlugin resources - This locator would have custom extraction and injection logic for these specific resources
Code references:
- ImageLocator interface in internal/k8s/locator.go
- k8s_kind implementation in internal/tiltfile/k8s.go
Pros:
- Contained to just the specific resource type
- Doesn't modify general-purpose code
Cons:
- Less reusable for other URL schemes
- More complex API surface
Recommendation
I recommend Option 1 (wrapper approach) as I imagine Option 2 is a much larger lift, and parsing oci:// prefixes may not be consistent with the goals of the distribution/reference lib as a whole.
Assuming this is the direction we go in, I can throw together a PR.
Related Resources
If you just need to get unblocked, have you considered using the k8s_custom_deploy API? It lets you write a little shell script to do your own image injection and is pretty nice for more complex crds.
I guess I could be convinced that we could add more configuration to k8s_kind to allow this. Frankly, we've found k8s_kind is pretty difficult for people to use and reason about...feels like we're missing some more intuitive API...