Skip to content
Open
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
171 changes: 171 additions & 0 deletions hips/hip-0027.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
---
hip: 0027
title: "Expose Previously Installed Chart Metadata During Template Rendering"
authors: [ "Andrew Shoell <[email protected]>" ]
created: "2025-11-12"
type: "feature"
status: "draft"
---

## Abstract

This HIP proposes exposing metadata from the currently deployed chart version during template rendering. Currently, Helm templates have access to `.Chart` for the chart being installed but no equivalent access to the currently deployed release. 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 a new `.DeployedChart` object available in all template contexts, populated with the deployed chart's metadata during `helm upgrade` and `helm rollback` operations. When no deployed release exists, `.DeployedChart` is nil, allowing safe checks with `{{ if .DeployedChart }}`. An optional `--disable-deployed-chart` flag provides opt-out capability.

## 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`

Alternatives considered and rejected:
- `.PreviousChart` - Ambiguous during rollbacks
- `.InstalledChart` - Confusing with current installation
- `.CurrentChart` - Ambiguous which is "current"
- `.Release.Deployed.Chart` - Unnecessarily nested

`.DeployedChart` unambiguously means "what is currently running in the cluster" and maintains consistency with Helm terminology.

### Always Available as Template Object

`.DeployedChart` is always present (though possibly nil) to ensure consistent template behavior, prevent undefined variable errors, and enable testing with `helm template`.

### Populated Only During Upgrades/Rollbacks

`.DeployedChart` contains chart metadata only during `helm upgrade` and `helm rollback` when a deployed release exists. It's nil for:
- `helm install` - No deployed release
- `helm template` / dry-runs - No cluster context
- When `--disable-deployed-chart` 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.

### Opt-Out Flag

The `--disable-deployed-chart` flag allows organizations to disable the feature for security or determinism requirements. A CLI flag was chosen over environment variables for explicitness and consistency with Helm's patterns.

### 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 Object: `.DeployedChart`

A top-level template object available in all contexts. Populated with deployed chart metadata during upgrade/rollback; nil otherwise.

**Metadata Structure:** Identical to `.Chart`, including `Name`, `Version`, `AppVersion`, and other [Chart.yaml fields](https://helm.sh/docs/topics/charts/#the-chartyaml-file).

**Usage Example:**
```yaml
{{- if .DeployedChart }}
{{- if and (semverCompare ">=2.0.0" .Chart.Version) (semverCompare "<2.0.0" .DeployedChart.Version) }}
# Migration logic for 1.x -> 2.x upgrade
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 }}
```

### Command-Line Flag

```bash
helm upgrade myrelease mychart --disable-deployed-chart
```

### Behavior Matrix

| Operation | `.DeployedChart` Value |
|-----------|------------------------|
| `helm install` | `nil` (no deployed release) |
| `helm upgrade` (new) | `nil` (no deployed release) |
| `helm upgrade` (existing) | Populated with deployed metadata |
| `helm rollback` | Populated with deployed metadata |
| `helm template` / dry-runs | `nil` (no cluster context) |
| With `--disable-deployed-chart` | `nil` (explicitly disabled) |

## Backwards Compatibility

Fully backwards compatible. The `.DeployedChart` object is purely additive—existing charts work unchanged. Go templates handle nil 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 `--disable-deployed-chart` flag provides opt-out for security-sensitive environments.

## How to Teach This

### Documentation Additions

1. **Template Objects Reference:** Add `.DeployedChart` to built-in objects with availability details
2. **Upgrade Guide:** "Implementing Version-Aware Upgrades" covering nil checks, version comparisons, and best practices
3. **Migration Examples:** Show replacement of post-renderers and pre-upgrade hooks with `.DeployedChart`
4. **Chart Linting:** Update `helm lint` to warn on `.DeployedChart` usage without nil 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`
2. Populate from release records during upgrade/rollback
3. Add `--disable-deployed-chart` flag
4. Include comprehensive unit and integration tests

## Rejected Ideas

- **Full Release Object:** Security/performance concerns; chart metadata sufficient
- **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 `.DeployedChart`:** Violates read-only template model; no clear use case

## 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/)