Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 58 additions & 23 deletions hips/hip-9999.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,16 @@ This HIP builds upon [H4HIP: Wasm plugin system](./hip-0026.md) to define how ch

## Motivation

While the main plugin system HIP enables users to extend Helm's functionality, chart authors ([Application Distributors](https://github.com/helm/community/blob/main/user-profiles.md#2-application-distributor)) need a way to specify which plugins their charts require. This allows charts to use alternative render engines, download protocols, and other plugin-based functionality while ensuring users have the necessary plugins installed.
While the main plugin system HIP enables users to extend Helm's functionality, chart authors ([Application Distributors](https://github.com/helm/community/blob/main/user-profiles.md#2-application-distributor)) need a way to specify which plugins their charts require. This allows charts to use alternative render engines, download protocols, and other plugin-based functionality while ensuring users have the necessary plugins installed. Enabling much greater control of a chart's operations and flexibility of operation.

The salient difference is that Helm CLI/SDK plugins are controled by the Helm user. Chart defined plugins are defined by the Chart author.

Enabling Helm charts to be extensible aims to enable Chart authors

TODO: System that "just works" / UX
TODO: Out-of-scope: Operator model: Helm plans to remain a low-level tool
TODO: Plugin maintainence model (artifact hub, Helm maintained "official", communinity mantained)
TODO: "existing functionality" -> go plugins

## Specification

Expand All @@ -26,14 +35,17 @@ Support for Chart-defined plugins will be added starting in Chart API v3. `Chart
For the initial release of the new plugin system, chart authors will be able to define custom plugins for the following categories:

- **`getter/v1`** - Download protocols for subcharts beyond HTTP/S and OCI (e.g., S3, Git)
- **`render/v1`** - Manifest rendering using alternative engines beyond gotemplate (e.g., Pkl, Cue, Kustomize)
- **`render/v1`** - Manifest rendering using alternative engines beyond gotemplate (e.g., Pkl, Cue, Kustomize, YamlScript, etc)
- **`values/v1`** - Manage (expand, rewrite, validate) chart rendering values

After the initial plugin system release, the intention is to make it easy to continue adding new chart-defined plugin types to extend additional categories of non-default chart behavior as this becomes desirable. Some examples may be:

- **Values schema validation** (for validating the chart's `values.yaml` file using something other than JSON Schema)
- **Dependency resolution** (for using a different subchart dependency resolver than the one currently used by Helm)
- **Values schema management** - expanding, rewriting, validating chart's `values.yaml` file using something other than Helm's inbuilt JSON Schema and subchart values export support
- **Dependency resolution** - determining and ordering dependencies
- Values schema validation (for validating the chart's `values.yaml` file using something other than JSON Schema)
- Dependency resolution (for using a different subchart dependency resolver than the one currently used by Helm)

To plan for forward compatibility, a `minimumHelmVersion` field may be added to allow future plugins to specify the minimum version of Helm that must be used for the chart (or since this is the version of Helm that introduced the new plugin, perhaps this can be auto-detected).
To plan for forward compatibility, a `minimumHelmVersion` field may be added to Charts to allow future plugins to specify the minimum version of Helm that must be used for the chart (or since this is the version of Helm that introduced the new plugin, perhaps this can be auto-detected).

### Chart.yaml Plugin Syntax

Expand All @@ -46,7 +58,26 @@ The `plugins` key is defined as a **list** (not a map). This is critical for `re

Example `Chart.yaml` for Charts v3:

`Chart.yaml` plugins will be defined via a `plugins:` key containing a list of plguins. Enabling ordering of plugin operations. e.g. Chaining chart yaml renderers.

TODO: Do we want to group plugin types? e.g.

```yaml
render/v1:
- name: pkl
repository: oci://ghcr.io/pkl-community/helm-pkl
version: 0.1.0
- name: kustomize
repository: oci://ghcr.io/helm-kustomize
version: 0.1.0
getter/v1:
- name: s3
repository: oci://ghcr.io/hypnoglow/helm-s3
version: 0.16.3
```

```yaml
---
apiVersion: v3
name: my-chart
version: 1.0.0
Expand All @@ -61,12 +92,6 @@ plugins:
type: getter/v1
repository: oci://ghcr.io/hypnoglow/helm-s3
version: 0.16.3

# Renamed from "dependencies" in v2
subcharts:
- name: postgresql
version: 12.x.x
repository: https://charts.bitnami.com/bitnami
```

### Render/v1 Plugin Specification
Expand Down Expand Up @@ -115,7 +140,7 @@ All `render/v1` plugins receive the same Helm built-in objects via JSON serializ
- `Subcharts` - Metadata about subchart dependencies
- `Files` - Non-template files accessible to the chart
- `Capabilities` - Information about the Kubernetes cluster
- `Template` - Template-specific information (name, base path)
- `SourceFiles` - Template-specific information (name, base path)

Plugins return rendered Kubernetes manifests as a map of `filename -> content`.

Expand Down Expand Up @@ -179,6 +204,7 @@ Plugins are referenced by OCI URL in `Chart.yaml` (not packaged within charts).
**Plugin versioning:** The content cache supports multiple versions of the same plugin, allowing different charts to depend on different plugin versions without conflicts.

### Plugin Storage: Installed vs Cached
### Chart plugins vs. user (CLI/SDK) plugins

Plugins exist in two distinct storage models:

Expand All @@ -193,6 +219,7 @@ Plugins exist in two distinct storage models:
| -------------------------- | ------------------------------------------ | ------------------------------------- |
| Global install destination | `$PLUGINS_DIR/<name>/` | Final location for installed plugins |
| Chart-defined cache | `$HELM_CACHE_HOME/content/{digest}.plugin` | Content-addressable cache (transient) |
Chart plugins are not visible to the CLI/SDK plugin registry and cannot be managed via `helm plugin install/uninstall`. They are only loaded and used when a chart explicitly specifies them in `Chart.yaml`.

**Important distinction:** Chart-defined plugins are **cached**, not **managed**. The content cache is transient storage that can be cleared at any time (`rm -rf $HELM_CACHE_HOME/content/`) without breaking workflows - plugins will simply be re-fetched on next use. This is analogous to chart caching: users don't "manage" cached charts, they manage chart dependencies via `Chart.yaml` and `Chart.lock`.

Expand Down Expand Up @@ -390,25 +417,32 @@ Some environments run with read-only filesystems. The SDK should support:

#### SDK API Requirements

To support these use cases, the SDK must abstract plugin loading:
To support these use cases, the SDK provides the `PluginRenderer` with configurable options:

```go
// SDK users can customize caching behavior
type RenderOptions struct {
// CompilationCache allows custom Wasm compilation cache
type PluginRenderer struct {
// ContentCachePath is the path to the content cache directory.
// Plugins are loaded from cached archives using their digest from Chart.lock.
// Set to "" to disable disk-based loading (use with PreloadedPlugins).
ContentCachePath string

// CompilationCache allows custom Wasm compilation cache.
// Default: disk-based at $HELM_CACHE_HOME/wazero-build/
// For non-writable filesystems, use wazero.NewCompilationCache() for in-memory.
CompilationCache wazero.CompilationCache

// ContentCache allows custom plugin tarball cache
// Default: disk-based at $HELM_CACHE_HOME/content/
ContentCache downloader.Cache

// PreloadedPlugins allows passing pre-compiled plugins
// Useful for non-writable filesystems or pre-warmed caches
PreloadedPlugins map[string]wazero.CompiledModule
// PreloadedPlugins allows passing pre-loaded plugin archives as raw bytes.
// Map keys are the plugin digest (matching Chart.lock).
// Useful for non-writable filesystems where plugins are embedded at build time.
PreloadedPlugins map[string][]byte
}
```

**For non-writable filesystems**, SDK users must:

1. Set `ContentCachePath` to `""` (empty string) to disable disk access
2. Provide `PreloadedPlugins` with embedded plugin archives keyed by digest

#### Native Go Plugin Runtime (SDK Only)

For SDK users who want to bypass Wasm entirely, a separate HIP proposes a `go/v1` runtime that allows registering native Go implementations for plugin types. This is SDK-only (CLI always uses Wasm for sandboxing) and covered in a dedicated HIP.
Expand Down Expand Up @@ -454,6 +488,7 @@ This redirects plugin downloads to an internal mirror, following the same patter
- Organizations already have registry mirroring infrastructure

**Decision:** Prioritize registries.conf implementation before moving chart-defined plugins out of experimental. A dedicated `helm plugin download` command is not planned (see Rejected Ideas).
**Decision needed:** Implement `helm pull --download-plugins`, wait for registries.conf, or both?

## Rejected ideas

Expand Down