# Advanced Features

- [Resource Tracking with Kubedog](#resource-tracking-with-kubedog)
- [Import Configuration Parameters into Helmfile](#import-configuration-parameters-into-helmfile)
- [Deploy Kustomization with Helmfile](#deploy-kustomizations-with-helmfile)
- [Adhoc Kustomization of Helm Charts](#adhoc-kustomization-of-helm-charts)
- [Adding dependencies without forking the chart](#adding-dependencies-without-forking-the-chart)

## Resource Tracking with Kubedog

Helmfile can use [kubedog](https://github.com/werf/kubedog) for advanced resource tracking instead of Helm's built-in `--wait` flag. This provides more detailed feedback and control over deployment progress.

### Basic Usage

Enable kubedog tracking in your `helmfile.yaml`:

```yaml
releases:
  - name: myapp
    chart: ./charts/myapp
    trackMode: kubedog
    trackTimeout: 300  # seconds
    trackLogs: true
```

Or use command-line flags:

```bash
helmfile apply --track-mode kubedog --track-timeout 300 --track-logs
```

### Configuration Options

- **`trackMode`**: Set to `kubedog` to enable kubedog tracking, or `helm-legacy` to use Helm v4's legacy wait mode (default: `helm`)
- **`trackTimeout`**: Timeout in seconds for tracking resources (default: 300)
- **`trackLogs`**: Enable real-time log streaming from tracked resources

### Track Modes

Helmfile supports three track modes:

- **`helm`** (default): Uses Helm's built-in `--wait` flag for resource tracking
- **`helm-legacy`**: Uses Helm v4's `--wait=legacy` flag. This is useful when migrating from Helm v3 to Helm v4 and you have charts that may have compatibility issues with the new watcher-based wait mechanism (e.g., charts with `livenessProbe` but no `startupProbe`). Note: This mode only works with Helm v4; with Helm v3 it falls back to regular `--wait`.
- **`kubedog`**: Uses kubedog for advanced resource tracking with detailed feedback

### Resource Filtering

Control which resources to track using whitelist/blacklist:

```yaml
releases:
  - name: myapp
    chart: ./charts/myapp
    trackMode: kubedog
    # Track only specific resource kinds
    trackKinds:
      - Deployment
      - StatefulSet
    # Skip certain resource kinds
    skipKinds:
      - ConfigMap
      - Secret
```

### Specific Resource Tracking

Track only specific resources by name and namespace:

```yaml
releases:
  - name: myapp
    chart: ./charts/myapp
    trackMode: kubedog
    trackResources:
      - kind: Deployment
        name: myapp-deployment
        namespace: default
      - kind: Job
        name: myapp-job
```

### Priority Rules

Resource filtering follows this priority (highest to lowest):

1. **`trackResources`**: Whitelist specific resources (takes highest priority)
2. **`skipKinds`**: Blacklist resource kinds
3. **`trackKinds`**: Whitelist resource kinds

### Benefits

- **Real-time feedback**: See deployment progress with detailed status updates
- **Log streaming**: View container logs during deployment
- **Fine-grained control**: Track only the resources you care about
- **Better debugging**: Immediate visibility into deployment issues

### Helm v4 Legacy Wait Mode

When using Helm v4 with charts that have broken `livenessProbe` configurations without `startupProbe`, the default `--wait=watcher` mode may fail. Helm v4 introduces `--wait=legacy` which uses the simpler polling mechanism compatible with Helm v3's behavior.

To use this mode, set `trackMode: helm-legacy`:

```yaml
releases:
  - name: myapp
    chart: ./charts/myapp
    trackMode: helm-legacy
```

Or via command-line:

```bash
helmfile apply --track-mode helm-legacy
```

### Compatibility

- **`helm`**: Default mode, uses Helm's built-in `--wait` flag
- **`helm-legacy`**: Uses Helm v4's `--wait=legacy` flag (only available in Helm v4)
- **`kubedog`**: Uses kubedog library for advanced resource tracking
- Kubedog tracking is compatible with Helm 3.x and 4.x
- Kubedog is a compiled dependency and is only used when `trackMode: kubedog` is set
- Works with charts that deploy supported workload kinds (currently `Deployment`, `StatefulSet`, `DaemonSet`, `Job`, and `Canary`); other resource kinds are created by Helm/Helmfile as usual but are ignored by the kubedog tracker

### Advanced Kubedog Settings

```yaml
releases:
  - name: myapp
    chart: ./charts/myapp
    trackMode: kubedog
    trackTimeout: 600
    trackLogs: true
    kubedogQPS: 5.0
    kubedogBurst: 10
```

- **`kubedogQPS`**: QPS (queries per second) for the kubedog kubernetes client (default: uses cluster defaults)
- **`kubedogBurst`**: Burst for the kubedog kubernetes client (default: uses cluster defaults)

## Import Configuration Parameters into Helmfile

Helmfile integrates [vals]() to import configuration parameters from following backends:

- AWS SSM Parameter Store
- AWS SecretsManager
- Vault
- SOPS

See [Vals "Supported Backends"](https://github.com/helmfile/vals#supported-backends) for the full list of available backends.

This feature was implemented in https://github.com/roboll/helmfile/pull/906.
If you're curious about how it's designed and how it works, please review the pull request.

## Deploy Kustomizations with Helmfile

You can deploy [kustomize](https://github.com/kubernetes-sigs/kustomize) "kustomization"s with Helmfile.

Most Kustomize operations are usually done with `kustomize edit` and can be done declaratively via Helm `values.yaml` files.

Under the hood, Helmfile transforms the kustomization into a local chart in a temporary directory so that it can be `helm upgrade --install`ed.

The transformation is done by generating (1)a temporary kustomization from various options and (2)temporary chart from the temporary kustomization.

An example pseudo code for the transformation logic can be written as:

```console
$ TMPCHART=/tmp/sometmpdir
$ mkdir -p ${TMPCHART}/templates
$ somehow_generate_chart_yaml ${TMPCHART}/Chart.yaml

$ TMPKUSTOMIZATION=/tmp/sometmpdir2
$ somehow_generate_temp_kustomization_yaml ${TMPKUSTOMIZATION}/kustomization.yaml
$ kustomize build ${TMPKUSTOMIZATION}/kustomization.yaml > ${TMPCHART}/templates/all.yaml
```

Let's say you have a `helmfile.yaml` that looks like the below:

```yaml
releases:
- name: myapp
  chart: mykustomization
  values:
  - values.yaml
```

Helmfile firstly generates a temporary `kustomization.yaml` that looks like:

```yaml
bases:
- $(ABS_PATH_TO_HELMFILE_YAML}/mykustomization
```

Followed by the below steps:

- Running `kustomize edit set image $IMAGE` for every `$IMAGE` generated from your values.yaml
- Running `kustomize edit set nameprefix $NAMEPREFIX` with the nameprefix specified in your values.yaml
- Running `kustomize edit set namesuffix $NAMESUFFIX` with the namesuffix specified in your values.yaml
- Running `kustomize edit set namespace $NS` with the namespace specified in your values.yaml

A `values.yaml` file for kustomization would look like the below:

```yaml
images:
# kustomize edit set image mysql=eu.gcr.io/my-project/mysql@canary
- name: mysql
  newName: eu.gcr.io/my-project/mysql
  newTag: canary
# kustomize edit set image myapp=my-registry/my-app@sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
- name: myapp
  digest: sha256:24a0c4b4a4c0eb97a1aabb8e29f18e917d05abfe1b7a7c07857230879ce7d3d3
  newName: my-registry/my-app

# kustomize edit set nameprefix foo-
namePrefix: foo-

# kustomize edit set namesuffix -bar
nameSuffix: -bar

# kustomize edit set namespace myapp
namespace: myapp
```

At this point, Helmfile can generate a complete kustomization from the base kustomization you specified in `releases[].chart` of your helmfile.yaml and `values.yaml`,
which can be included in the temporary chart.

After all, Helmfile just installs the temporary chart like standard charts, which allows you to manage everything with Helmfile regardless of each app is declared using a Helm chart or a kustomization.

Please also see [test/advanced/helmfile.yaml](https://github.com/helmfile/helmfile/tree/master/test/advanced/helmfile.yaml) for an example of kustomization support and more.

## Adhoc Kustomization of Helm charts

With Helmfile's integration with Kustomize, not only deploying Kustomization as a Helm chart, you can kustomize charts before installation.

.. Hint:: The following fields can also specify files, in the same manner as
   the `values` field.

Currently, Helmfile allows you to set the following fields for kustomizing the chart:

- [`releases[].strategicMergePatches`](#strategicmergepatches)
- `releases[].jsonPatches`
- [`releases[].transformers`](#transformers)

### `strategicMergePatches`

You can add/update any Kubernetes resource field rendered from a Helm chart by specifying `releases[].strategicMergePatches`:

```
repositories:
- name: incubator
  url: https://charts.helm.sh/incubator

releases:
- name: raw1
  chart: incubator/raw
  values:
  - resources:
    - apiVersion: v1
      kind: ConfigMap
      metadata:
        name: raw1
        namespace: default
      data:
        foo: FOO
  strategicMergePatches:
    - apiVersion: v1
      kind: ConfigMap
      metadata:
        name: raw1
        namespace: default
      data:
        bar: BAR
```

Running `helmfile template` on the above example results in a ConfigMap called `raw` whose `data` is:

```yaml
foo: FOO
bar: BAR
```

Please note that the second `data` field `bar` is coming from the strategic-merge patch defined in the above helmfile.yaml.

There's also `releases[].jsonPatches` that works similarly to `strategicMergePatches` but has additional capability to remove fields.

Please also see [test/advanced/helmfile.yaml](https://github.com/helmfile/helmfile/tree/master/test/advanced/helmfile.yaml) for an example of patching support and more.

### `transformers`

You can set `transformers` to apply [Kustomize's transformers](https://github.com/kubernetes-sigs/kustomize/blob/master/examples/configureBuiltinPlugin.md#configuring-the-builtin-plugins-instead).

Each item can be a path to a YAML or Go template file, or an embedded transformer declaration as a YAML hash.

It's often used to add common labels and annotations to your resources.

In the below example, we add common annotations and labels every resource rendered from the `aws-load-balancer-controller` chart:

```yaml
releases:
- name: "aws-load-balancer-controller"
  namespace: "kube-system"
  forceNamespace: "kube-system"
  chart: "center/aws/aws-load-balancer-controller"
  transformers:
  - apiVersion: builtin
    kind: AnnotationsTransformer
    metadata:
      name: notImportantHere
    annotations:
      area: 51
      greeting: take me to your leader
    fieldSpecs:
    - path: metadata/annotations
      create: true
  - apiVersion: builtin
    kind: LabelTransformer
    metadata:
      name: notImportantHere
    labels:
      foo: bar
    fieldSpecs:
    - path: metadata/labels
      create: true
```

As explained earlier, `transformers` can be not only a list of embedded transformers, but also YAML or Go template files, or a mix of those three kinds.

```yaml
transformers:
# Embedded transformer
- apiVersion: builtin
  kind: AnnotationsTransformer
  metadata:
    name: notImportantHere
  annotations:
    area: 51
    greeting: take me to your leader
  fieldSpecs:
  - path: metadata/annotations
    create: true
# YAML file
- path/to/transformer.yaml
# Go template
# The same set of template parameters as release values files templates is available.
- path/to/transformer.yaml.gotmpl
```

Please see https://github.com/kubernetes-sigs/kustomize/blob/master/examples/configureBuiltinPlugin.md#configuring-the-builtin-plugins-instead for more information on how to declare transformers.

## Adding dependencies without forking the chart

With Helmfile, you can add chart dependencies to a Helm chart without forking it.

An example `helmfile.yaml` that adds a `stable/envoy` dependency to the release `foo` looks like the below:

```yaml
repositories:
- name: stable
  url: https://charts.helm.sh/stable

releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: stable/envoy
    version: 1.5
```

When Helmfile encounters `releases[].dependencies`, it creates another temporary chart from `./path/to/foo` and adds the following `dependencies` to the `Chart.yaml`, so that you don't need to fork the chart.

```yaml
dependencies:
- name: envoy
  repo: https://charts.helm.sh/stable
  condition: envoy.enabled
```

A Helm chart can have two or more dependencies for the same chart with different `alias`es. To give your dependency an `alias`, define it like you would do in a standard `Chart.yaml`:

```yaml
repositories:
- name: stable
  url: https://charts.helm.sh/stable

releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: stable/envoy
    version: 1.5
    alias: bar
  - chart: stable/envoy
    version: 1.5
    alias: baz
```

which will tweaks the temporary chart's `Chart.yaml` to have:


```yaml
dependencies:
- alias: bar
  name: envoy
  repo: https://charts.helm.sh/stable
  condition: bar.enabled
- alias: baz
  name: envoy
  repo: https://charts.helm.sh/stable
  condition: baz.enabled
```

Please see #649 for more context around this feature.

After the support for adhoc dependency to local chart (#1765),
you can even write local file paths relative to `helmfile.yaml` in `chart`:

```yaml
releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: ./path/to/bar
```

Internally, Helmfile creates another temporary chart from the local chart `./path/to/foo`, and modifies the chart's `Chart.yaml` dependencies to look like:

```yaml
dependencies:
- alias: bar
  name: bar
  repo: file:///abs/path/to/bar
  condition: bar.enabled
```

Please read https://github.com/roboll/helmfile/issues/1762#issuecomment-816341251 for more details.

### OCI chart dependencies

With Helmfile version v0.146.0 or later, you can add OCI chart to chart dependencies.

An example `helmfile.yaml` that adds a OCI chart dependency to the release `foo` looks like the below:

```yaml
releases:
- name: foo
  chart: ./path/to/foo
  dependencies:
  - chart: oci://my-oci-registry/helm-repo/envoy
    version: 1.5
```

## Lockfile per environment

In some cases it can be handy for CI/CD pipelines to be able to roll out updates gradually for environments, such as staging and production while using the same
set of charts. This can be achieved by using `lockFilePath` in combination with environments, such as:

```yaml
environments:
  staging:
  production

---
lockFilePath: .helmfile.{{ .Environment.Name}}.lock

releases:
- name: myapp
  chart: charts/myapp
```
