-
Notifications
You must be signed in to change notification settings - Fork 206
docs: adding expose depoyed chart hip #421
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d263887
8867321
f613f22
78d4fe8
f88e9b9
4c65745
b48d8f5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,199 @@ | ||
| --- | ||
| hip: 0027 | ||
| title: "Expose Previously Installed Chart Metadata During Template Rendering" | ||
| authors: ["Andrew Shoell <mrlunchbox777@gmail.com>"] | ||
| created: "2025-11-12" | ||
| type: "feature" | ||
| status: "draft" | ||
| --- | ||
|
|
||
| ## Abstract | ||
|
|
||
| This HIP proposes exposing metadata from currently deployed chart versions during template rendering. Currently, Helm templates have access to `.Chart` for the chart being installed but no equivalent access to deployed releases. This forces chart authors to use complex workarounds like post-renderers, pre-upgrade hooks, or manual values conventions to implement version-aware upgrade logic. | ||
|
|
||
| The proposal introduces `.DeployedChart` (singular, latest deployed) and `.DeployedCharts` (array, multiple versions) objects available in all template contexts, populated during `helm upgrade` and `helm rollback` operations. The `--deployed-depth` flag controls how many deployed versions to retrieve (default: 1), with `--deployed-depth 0` disabling the feature. | ||
|
|
||
| ## Motivation | ||
|
|
||
| ### Current Limitations | ||
|
|
||
| Helm provides comprehensive chart metadata through `.Chart` but offers no native way to access deployed release metadata during template evaluation. Chart developers must resort to problematic workarounds: | ||
|
|
||
| **Post-Renderers:** External tools that query the cluster, parse manifests, and make version-aware modifications. This moves upgrade logic outside the chart, requires additional tooling, and breaks Helm's self-contained design. | ||
|
|
||
| **Pre-Upgrade Hooks:** Store version metadata in ConfigMaps via hooks, creating ordering dependencies and potential failure points. | ||
|
|
||
| **Manual Values:** Require users to specify previous versions in values files—error-prone and defeats Helm's release tracking. | ||
|
|
||
| ### Real-World Impact | ||
|
|
||
| This limitation prevents or complicates legitimate use cases: | ||
|
|
||
| - **Breaking Changes:** No clean migration path for renamed resources or changed structures | ||
| - **Conditional Resources:** Cannot create migration Jobs based on version deltas | ||
| - **Smart Defaults:** Cannot distinguish fresh installs from upgrades for intelligent defaults | ||
| - **Advanced Deployments:** Blue-green and similar strategies require external orchestration | ||
|
|
||
| Post-rendering solutions violate Helm's design philosophy that template rendering should be deterministic and self-contained. Making deployed chart metadata available at template time keeps upgrade logic in the chart itself, maintaining Helm's portability, testability, and transparency. | ||
|
|
||
| ## Rationale | ||
|
|
||
| ### Naming: `.DeployedChart` and `.DeployedCharts` | ||
|
|
||
| `.DeployedChart` (singular) provides ergonomic access to the most recent deployed version. `.DeployedCharts` (array) provides access to historical deployed versions in reverse chronological order (index 0 is most recent). `.DeployedChart` is syntactic sugar for `.DeployedCharts[0]`. | ||
|
|
||
| Alternatives considered and rejected: | ||
|
|
||
| - `.PreviousChart` - Ambiguous during rollbacks | ||
| - `.InstalledChart` - Confusing with current installation | ||
| - `.CurrentChart` - Ambiguous which is "current" | ||
| - `.Release.Deployed.Chart` - Unnecessarily nested | ||
|
|
||
| ### Always Available as Template Objects | ||
|
|
||
| `.DeployedChart` (nil or chart metadata) and `.DeployedCharts` (empty array or populated) are always present to ensure consistent template behavior, prevent undefined variable errors, and enable testing with `helm template`. | ||
|
|
||
| ### Populated Only During Upgrades/Rollbacks | ||
|
|
||
| `.DeployedChart`/`.DeployedCharts` contain chart metadata only during `helm upgrade` and `helm rollback` when deployed releases exist. During rollback, they reflect the currently deployed version (being rolled back _from_). They're nil/empty for: | ||
|
|
||
| - `helm install` - No deployed release | ||
| - `helm template` / dry-runs - No cluster context | ||
| - When `--deployed-depth 0` is used | ||
|
|
||
| ### Chart Metadata Only | ||
|
|
||
| This proposal exposes only Chart.yaml metadata (same structure as `.Chart`), not values, manifests, or release metadata. This maintains security (values may contain secrets), performance (manifests can be large), and simplicity while solving 90% of use cases. Future HIPs could extend this if needed. | ||
|
|
||
| ### Depth Control Flag | ||
|
|
||
| The `--deployed-depth` flag controls how many deployed chart versions to retrieve (default: 1). Setting `--deployed-depth 0` disables the feature for security or determinism requirements. Higher depths may impact performance and should only be used for specific multi-version migration scenarios. | ||
|
|
||
| ### Design Decisions | ||
|
|
||
| - **Different Chart Names:** Still populates `.DeployedChart` even if chart names differ—templates can detect and handle this | ||
| - **Helm's Record:** Reflects Helm's stored release record, not actual cluster state (use `lookup()` for that) | ||
| - **Dry-Run/Template:** Always nil to maintain cluster-agnostic, deterministic behavior | ||
|
|
||
| ## Specification | ||
|
|
||
| ### New Template Objects | ||
|
|
||
| **`.DeployedChart`**: Singular object containing the most recent deployed chart metadata (nil if none exists). Syntactic sugar for `.DeployedCharts[0]`. | ||
|
|
||
| **`.DeployedCharts`**: Array of deployed chart metadata objects in reverse chronological order (most recent first). Empty array if no deployed releases exist. | ||
|
|
||
| **Metadata Structure:** Each chart object is identical to `.Chart`, including `Name`, `Version`, `AppVersion`, and other [Chart.yaml fields](https://helm.sh/docs/topics/charts/#the-chartyaml-file). | ||
|
|
||
| **Usage Examples:** | ||
|
|
||
| ```yaml | ||
| # Simple case: check latest deployed version | ||
| {{- if .DeployedChart }} | ||
| {{- if and (semverCompare ">=2.0.0" .Chart.Version) (semverCompare "<2.0.0" .DeployedChart.Version) }} | ||
| apiVersion: batch/v1 | ||
| kind: Job | ||
| metadata: | ||
| name: {{ include "mychart.fullname" . }}-migration | ||
| annotations: | ||
| "helm.sh/hook": pre-upgrade | ||
| spec: | ||
| template: | ||
| spec: | ||
| containers: | ||
| - name: migrate | ||
| image: myapp/migrator:{{ .Chart.AppVersion }} | ||
| command: ["migrate", "v1-to-v2"] | ||
| {{- end }} | ||
| {{- end }} | ||
|
|
||
| # Multi-version migration: handle complex upgrade paths | ||
| {{- if gt (len .DeployedCharts) 0 }} | ||
| {{- range .DeployedCharts }} | ||
| {{- if semverCompare "<1.5.0" .Version }} | ||
| # Run migration for versions before 1.5.0 | ||
| {{- end }} | ||
| {{- end }} | ||
| {{- end }} | ||
| ``` | ||
|
|
||
| ### Command-Line Flag | ||
|
|
||
| ```bash | ||
| # Default: retrieve latest deployed chart | ||
| helm upgrade myrelease mychart | ||
|
|
||
| # Retrieve last 3 deployed versions | ||
| helm upgrade myrelease mychart --deployed-depth 3 | ||
|
|
||
| # Disable feature | ||
| helm upgrade myrelease mychart --deployed-depth 0 | ||
| ``` | ||
|
|
||
| ### Behavior Matrix | ||
|
|
||
| | Operation | `.DeployedChart` / `.DeployedCharts` | | ||
| | -------------------------- | --------------------------------------------------------------- | | ||
| | `helm install` | `nil` / `[]` (no deployed release) | | ||
| | `helm upgrade` (new) | `nil` / `[]` (no deployed release) | | ||
| | `helm upgrade` (existing) | Populated with deployed metadata (most recent first) | | ||
| | `helm rollback` | Populated with currently deployed version (rolling back _from_) | | ||
| | `helm template` / dry-runs | `nil` / `[]` (no cluster context) | | ||
| | `--deployed-depth 0` | `nil` / `[]` (explicitly disabled) | | ||
| | `--deployed-depth N` | Up to N most recent deployed versions | | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| Fully backwards compatible. The `.DeployedChart` and `.DeployedCharts` objects are purely additive—existing charts work unchanged. Go templates handle nil and empty arrays safely; the recommended `{{ if .DeployedChart }}` pattern works in all scenarios. | ||
|
|
||
| ## Security Implications | ||
|
|
||
| **Not Exposed:** Previous values (may contain secrets) or previous manifest (may contain sensitive data). Only Chart.yaml metadata is exposed. | ||
|
|
||
| **Considerations:** Chart authors should not store sensitive data in Chart.yaml. The `--deployed-depth 0` flag provides opt-out for security-sensitive environments. Higher depth values increase data exposure; use the minimum required. | ||
|
|
||
| ## How to Teach This | ||
|
|
||
| ### Documentation Additions | ||
|
|
||
| 1. **Template Objects Reference:** Add `.DeployedChart` and `.DeployedCharts` to built-in objects with availability details | ||
| 2. **Upgrade Guide:** "Implementing Version-Aware Upgrades" covering nil/empty checks, version comparisons, and best practices | ||
| 3. **Migration Examples:** Show replacement of post-renderers and pre-upgrade hooks | ||
| 4. **Performance Note:** Document that `--deployed-depth` should be kept minimal; default of 1 is recommended | ||
| 5. **Chart Linting:** Update `helm lint` to warn on usage without nil/empty checks | ||
|
|
||
| ### Key Example Pattern | ||
|
|
||
| ```yaml | ||
| {{- if and .DeployedChart (semverCompare "<3.0.0" .DeployedChart.Version) }} | ||
| # Handle breaking change from versions < 3.0.0 | ||
| {{- end }} | ||
| ``` | ||
|
|
||
| ## Reference Implementation | ||
|
|
||
| A future pull request will: | ||
|
|
||
| 1. Extend template rendering context to include `.DeployedChart` and `.DeployedCharts` | ||
| 2. Populate from release records during upgrade/rollback (reverse chronological order) | ||
| 3. Add `--deployed-depth` flag (default: 1) | ||
| 4. Implement `.DeployedChart` as alias to `.DeployedCharts[0]` | ||
| 5. Include comprehensive unit and integration tests covering depth behavior | ||
|
|
||
| ## Rejected Ideas | ||
|
|
||
| - **Full Release Object:** Security/performance concerns; chart metadata sufficient | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. my main thought is, would you not also want to expose the values of Some thoughts about this: What about adding "History" key to the existing .Release built-in: This could be a filtered version of the Release object that's currently stored in helm release secrets by default. Agree that the full release object could cause performance issues. perhaps this could be mitigated by:
Not yet sure what security concerns adding the Release object would add that other built-ins don't already have (eg, .Values, .Files, etc). But good to consider here. |
||
| - **Only Version Strings:** Inconsistent with `.Chart`; prevents access to other metadata | ||
| - **Environment Variable Control:** Less explicit than CLI flag | ||
| - **Cluster Query During `helm template`:** Violates cluster-agnostic design principle | ||
| - **Mutable Objects:** Violates read-only template model; no clear use case | ||
| - **Separate `--disable-deployed-chart` Flag:** Unified `--deployed-depth` with 0 value is cleaner | ||
| - **Unlimited History:** Performance implications; requiring explicit depth prevents accidental overhead | ||
|
|
||
| ## References | ||
|
|
||
| - [Helm Built-in Objects](https://helm.sh/docs/chart_template_guide/builtin_objects/) | ||
| - [Helm Chart.yaml](https://helm.sh/docs/topics/charts/#the-chartyaml-file) | ||
| - [Go Templates](https://pkg.go.dev/text/template) | ||
| - [Semantic Versioning](https://semver.org/) | ||
| - [Example of current workaround](https://github.com/helm/community/pull/421#issuecomment-3662769874) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be "9999", see https://github.com/helm/community/blob/main/hips/hip-0001.md