# HelmChart v2

This topic describes the Replicated HelmChart v2 custom resource.

## Overview

Each Helm chart `.tgz` archive in a release requires a unique HelmChart custom resource. The HelmChart custom resource provides the Replicated installer with the instructions needed to process and deploy the given Helm chart.

The HelmChart custom resource also generates a list of required images for the chart, which is necessary for the following use cases:
* Air gap installations with the Helm CLI or with a Replicated installer
* Online installations with a Replicated installer where the user will push images to a local image registry
* Online or air gap installations that use the [Security Center (Alpha)](/vendor/security-center-about) to scan and report on Helm chart images

## Example

The following is an example manifest file for the HelmChart v2 custom resource:

```yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  # chart identifies a matching chart from a .tgz
  chart:
    name: samplechart
    chartVersion: 3.1.7
  
  releaseName: samplechart-release-1

  exclude: "repl{{ ConfigOptionEquals `include_chart` `include_chart_no`}}"

  # weight determines the order that charts are applied, with lower weights first.
  weight: 42

  # helmUpgradeFlags specifies additional flags to pass to the `helm upgrade` command.
  helmUpgradeFlags:
    - --skip-crds
    - --no-hooks
    - --timeout
    - 1200s
    - --history-max=15

  # values are used in the customer environment as a pre-render step
  # these values are supplied to helm template
  values:
    postgresql:
      enabled: repl{{ ConfigOptionEquals `postgres_type` `embedded_postgres`}}

  optionalValues:
  - when: "repl{{ ConfigOptionEquals `postgres_type` `external_postgres`}}"
    recursiveMerge: false
    values:
      postgresql:
        postgresqlDatabase: "repl{{ if ConfigOptionEquals `postgres_type` `external_postgres`}}repl{{ ConfigOption `external_postgres_database`}}repl{{ end}}"
        postgresqlUsername: "repl{{ if ConfigOptionEquals `postgres_type` `external_postgres`}}repl{{ ConfigOption `external_postgres_username`}}repl{{ end}}"
        postgresqlHost: "repl{{ if ConfigOptionEquals `postgres_type` `external_postgres`}}repl{{ ConfigOption `external_postgres_host`}}repl{{ end}}"
        postgresqlPassword: "repl{{ if ConfigOptionEquals `postgres_type` `external_postgres`}}repl{{ ConfigOption `external_postgres_password`}}repl{{ end}}"
        postgresqlPort: "repl{{ if ConfigOptionEquals `postgres_type` `external_postgres`}}repl{{ ConfigOption `external_postgres_port`}}repl{{ end}}"

  # namespace allows for a chart to be installed in an alternate namespace to
  # the default
  namespace: samplechart-namespace

  # builder values render the chart with all images and manifests.
  # builder is used to create `.airgap` packages and to support end users
  # who use private registries
  builder:
    postgresql:
      enabled: true
```

## Properties

### chart

The `chart` key allows for a mapping between the data in this definition and the chart archive itself.
More than one `kind: HelmChart` can reference a single chart archive if you need different settings.

`chart` has the following properties:

| Property | Description |
| --- | --- |
| `chart.name` | The name of the chart. This value must exactly match the `name` field from a `Chart.yaml` in a `.tgz` chart archive that is also included in the release. If the names do not match, then the installation can error or fail. |
| `chart.chartVersion` | The version of the chart. This value must match the `version` field from a `Chart.yaml` in a `.tgz` chart archive that is also included in the release. |

#### Example

```yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  chart:
    name: samplechart
    chartVersion: 3.1.7
```

### releaseName

Specifies the release name to use when installing this instance of the Helm chart. Defaults to the chart name.

The release name must be unique across all charts deployed in the namespace. To deploy multiple instances of the same Helm chart in a release, add a separate HelmChart custom resource with a unique release name for each instance.

Must be a valid Helm release name that matches regex `^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$` and is no longer than 53 characters.

#### Example

```yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  releaseName: samplechart-release-1
```

### weight

Specifies the installation order of the Helm charts in the release. Charts are installed by weight in ascending order with lower weights first. Also determines the uninstall order, where charts are uninstalled by weight in descending order with higher weights first. **Supported values:** Positive or negative integers. **Default:** `0`

For installations with the Helm CLI, the Replicated Enterprise Portal uses the `weight` property to order the list of charts in the installation and update instructions. For more information, see [View Install and Update Instructions](/vendor/enterprise-portal-use#view-install-and-update-instructions) in _Access and Use the Enterprise Portal_.

#### Example

```yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  weight: 42
```

### helmUpgradeFlags

Specifies additional flags to pass to the `helm upgrade` command.
The Replicated installer runs `helm upgrade` for _all_ deployments, not just upgrades, by specifying the `--install` flag.

The Replicated installer passes these flags in addition to the flags it passes by default.
The values specified in this field take precedence if the installer already passes the same flag.

Template functions can parse the `helmUpgradeFlags` attribute. For more information, see [About Replicated template functions](/reference/template-functions-about).

For non-boolean flags that require an additional argument, such as `--timeout 1200s`, you must use an equal sign (`=`) or specify the additional argument separately in the array.

#### Example

```yaml
helmUpgradeFlags:
  - --timeout
  - 1200s
  - --history-max=15
```

### exclude

When the installer processes your release, it excludes any Helm chart if the output of the `exclude` field is `true`.

Template functions can parse the `exclude` attribute. See [About Replicated template functions](template-functions-about).

#### Example

```yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  exclude: '{{repl ConfigOptionEquals "postgres_type" "external_postgres" }}'
```

### values

Use the `values` key to set or delete existing values in the Helm chart `values.yaml` file. Any values that you include in the `values` key must match values in the Helm chart `values.yaml`. For example, `spec.values.images.pullSecret` in the HelmChart custom resource matches `images.pullSecret` in the Helm chart `values.yaml`.

During installation or upgrade with KOTS, KOTS merges `values` with the Helm chart `values.yaml` in the chart archive. Only include values in the `values` key that you want to set or delete.

#### Examples

##### Set static values

```yaml
# Helm chart values.yaml
replicatedOnlyValue:
  enabled: false
```
```yaml
# HelmChart custom resource

apiVersion: kots.io/v1beta2
kind: HelmChart
spec:
  values:
    replicatedOnlyValue:
      enabled: true
```

##### Set values with Replicated Config template functions

Using Replicated template functions in the [Config](/reference/template-functions-config-context) context allows you to set Helm values based on user-supplied values from the Admin Console configuration page.

The following Helm chart `values.yaml` file contains `postgresql.enabled`, which is set to `false`: 

```yaml
# Helm chart values.yaml
postgresql:
  enabled: false
```
The following HelmChart custom resource contains a mapping to `postgresql.enabled` in its `values` key:

```yaml
# HelmChart custom resource

apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  values:
    postgresql:
      enabled: repl{{ ConfigOptionEquals `postgres_type` `embedded_postgres`}}
```

The `values.postgresql.enabled` field in the HelmChart custom resource above uses the Replicated [ConfigOptionEquals](/reference/template-functions-config-context#configoptionequals) template function to evaluate the user's selection for a `postgres_type` configuration option.

During installation or upgrade, the template function is rendered to true or false based on the user's selction. Then, the Replicated installer sets the matching `postgresql.enabled` value in the Helm chart `values.yaml` file accordingly.

##### Set values with Replicated License template functions

Using Replicated template functions in the [License](/reference/template-functions-license-context) context allows you to set Helm values based on the unique license file used for installation or upgrade.

For example, the following HelmChart custom resource uses the Replicated [LiencseFieldValue](/reference/template-functions-license-context#licensefieldvalue) template function to evaluate if the license has the boolean `newFeatureEntitlement` field set to `true`:

```yaml
# HelmChart custom resource

apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  values:
    newFeature:
      enabled: repl{{ LicenseFieldValue "newFeatureEntitlement" }}
```

During installation or upgrade, the LicenseFieldValue template function is rendered based on the user's license. Then, the Replicated installer sets the matching `newFeature.enabled` value in the Helm chart `values.yaml` file accordingly.

##### Delete a default value key

A common use case for deleting default value keys is when you include a community Helm chart as a dependency. Because you cannot control how the community chart is built and structured, you might want to change some of the default behavior. For more information about using a `null` value to delete a key, see [Deleting a Default Key](https://helm.sh/docs/chart_template_guide/values_files/#deleting-a-default-key) in the Helm documentation.

```yaml
# HelmChart custom resource

apiVersion: kots.io/v1beta2
kind: HelmChart
spec:
  values:
    exampleKey: "null"
```

### optionalValues

Use the `optionalValues` key to set values in the Helm chart `values.yaml` file when a conditional statement evaluates to true. For example, a customer including an optional application component might need Helm chart values related to that component.

`optionalValues` includes the following properties:

| Property | Description |
| --- | --- |
| `optionalValues.when` | Defines a conditional statement that must evaluate to true for the Helm chart to apply the values in `optionalValues.values`. The Replicated installer defers evaluation of the conditional in `optionalValues.when` until render time in the customer environment. |
| `optionalValues.recursiveMerge` | The `optionalValues.recursiveMerge` boolean defines how the Replicated installer merges `values` and `optionalValues`. When `optionalValues.recursiveMerge` is false, the top level keys in `optionalValues` override the top level keys in `values`. When `optionalValues.recursiveMerge` is true, the installer includes all keys from `values` and `optionalValues`. In the case of a conflict where there is a matching key in `optionalValues` and `values`, the Replicated installer uses the value of the key from `optionalValues`. By default, `optionalValues.recursiveMerge` is false. For an example, see [Recursive merge](#recursive-merge) on this page.|
| `optionalValues.values` | Array of key value pairs to set in the Helm chart when the specified condition is true. Supports static values and Replicated template functions. |

#### Examples

##### Set optional values with Replicated template functions

```yaml
# HelmChart custom resource

apiVersion: kots.io/v1beta2
kind: HelmChart
spec:
  optionalValues:
    - when: "repl{{ ConfigOptionEquals `mariadb_type` `external`}}"
      recursiveMerge: false
      values:
        externalDatabase:
          host: "repl{{ ConfigOption `external_db_host`}}"
          user: "repl{{ ConfigOption `external_db_user`}}"
          password: "repl{{ ConfigOption `external_db_password`}}"
          database: "repl{{ ConfigOption `external_db_database`}}"
          port: "repl{{ ConfigOption `external_ db_port`}}"
```

During installation, the Replicated installer renders the template functions and sets the `externalDatabase` values in the HelmChart `values.yaml` file _only_ when the user selects the `external` option for `mariadb_type`.

##### Recursive merge

The following HelmChart custom resource has both `values` and `optionalValues`:

```yaml
# HelmChart custom resource
apiVersion: kots.io/v1beta2
kind: HelmChart
spec:
  values:
    favorite:
      drink:
        hot: tea
        cold: soda
      dessert: ice cream
      day: saturday
  optionalValues:
    - when: '{{repl ConfigOptionEquals "example_config_option" "1" }}'
      recursiveMerge: false
      values:
        example_config_option:
          enabled: true
        favorite:
          drink:
            cold: lemonade
```

The associated Helm chart `values.yaml` file defines these key value pairs:

```yaml
# Helm chart values.yaml
favorite:
  drink:
    hot: coffee
    cold: soda
  dessert: pie
```
The associated Helm chart has the following `templates/configmap.yaml` file:

```yaml
# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
data:
  favorite_day: {{ .Values.favorite.day }}
  favorite_dessert: {{ .Values.favorite.dessert }}
  favorite_drink_cold: {{ .Values.favorite.drink.cold }}
  favorite_drink_hot: {{ .Values.favorite.drink.hot }}
```

When `recursiveMerge` is `false`, the ConfigMap for the deployed application includes the following key value pairs:

```yaml
# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
data:
  favorite_day: null
  favorite_dessert: pie
  favorite_drink_cold: lemonade
  favorite_drink_hot: coffee
```
When `recursiveMerge` is `true`, the ConfigMap for the deployed application includes the following key value pairs:

```yaml
# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
data:
  favorite_day: saturday
  favorite_dessert: ice cream
  favorite_drink_cold: lemonade
  favorite_drink_hot: tea
```

### namespace

The `namespace` key specifies an alternative namespace to install the Helm chart. By default, for Embedded Cluster v2 and KOTS existing cluster installations, KOTS installs the Helm chart in the same namespace as the Admin Console. For Embedded Cluster v3 installations, Embedded Cluster installs the chart in a `<chart-name>` namespace by default.

Template functions can parse the `namespace` attribute. For more information about template functions, see [About Replicated template functions](/reference/template-functions-about).

If you specify a namespace in the HelmChart `namespace` field, you must also include the same namespace in the [additionalNamespaces](custom-resource-application#additionalnamespaces) field of the Application custom resource.

### builder

The `builder` key contains the minimum Helm values required so that the output of `helm template` exposes all container images needed to install the chart in an air-gapped environment.

The Replicated Vendor Portal uses the Helm values in the `builder` key to run `helm template` on the chart. It then parses the output to generate a list of required images. 

The Vendor Portal then uses this list of images to do the following:
* Create the Helm CLI air gap installation instructions that are automatically made available to customers in the [Enterprise Portal](/vendor/enterprise-portal-about) or Download Portal. 
* Build the `.airgap` bundle for a release to support air gap installations with a Replicated installer (Embedded Cluster, KOTS, kURL).
* Determine which images to scan and report on in the [Security Center (Alpha)](/vendor/security-center-about).

You must configure the `builder` key to support the following installation types:

* Air gap installations with a Replicated installer (Embedded Cluster, KOTS, kURL)
* Air gap installations with the Helm CLI
* Online installations with KOTS or kURL where the user will push images to their own local image registry

#### Requirements

The `builder` key has the following requirements and recommendations:
* Replicated recommends that you include only the minimum Helm values in the `builder` key required to template the Helm chart with the correct image tags.
* Use only static, or _hardcoded_, values in the `builder` key. You can't use template functions in the `builder` key because values in the `builder` key are not rendered in a customer environment.
* Any `required` Helm values that need to be set to render the chart templates must have a value in the `builder` key. For more information about the Helm `required` function, see [Using the 'required' function](https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-required-function) in the Helm documentation.
* Specify `kubeVersion` in the root Helm chart. The Vendor Portal renders Helm charts with the minimum Kubernetes minor version that satisfies the `kubeVersion` in the root Helm chart. For example, if the chart specifies `kubeVersion: >=1.24.1`, then it's rendered with Kubernetes 1.25.0. If this fails or if a `kubeVersion` is not specified in the root Helm chart, then the Vendor Portal attempts to render the chart with each supported minor version of Kubernetes up to the latest version.

#### Example

Many applications include or exclude images based on a given condition.

For example, a Helm chart might include a conditional PostgreSQL Deployment, as shown in the following Helm template:

```yaml
{{- if .Values.postgresql.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  labels:
    app: postgresql
spec:
  selector:
    matchLabels:
      app: postgresql
  template:
    metadata:
      labels:
        app: postgresql
    spec:
      containers:
      - name: postgresql
        image: "postgres:10.17"
        ports:
        - name: postgresql
          containerPort: 80
# ...
{{- end }}
```

To include the `postgresql` image in the air gap bundle, add `postgresql.enabled` to the `builder` key of the HelmChart custom resource and set it to `true`:

```yaml
apiVersion: kots.io/v1beta2
kind: HelmChart
metadata:
  name: samplechart
spec:
  chart:
    name: samplechart
    chartVersion: 3.1.7
  values:
    postgresql:
      enabled: repl{{ ConfigOptionEquals "postgres_type" "embedded_postgres"}}
  builder:
    postgresql:
      enabled: true
```