> ## Documentation Index
> Fetch the complete documentation index at: https://timoni.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Control the Apply Behavior

> Change how resources are applied with the action.timoni.sh annotations.

Timoni allows changing the default apply behaviour of Kubernetes resources
with the `action.timoni.sh` annotations.

## Annotations

| CUE                              | Generated YAML                      |
| -------------------------------- | ----------------------------------- |
| `timoniv1.Action.Force`          | `action.timoni.sh/force: enabled`   |
| `timoniv1.Action.OneOff`         | `action.timoni.sh/one-off: enabled` |
| `timoniv1.Action.Keep`           | `action.timoni.sh/prune: disabled`  |
| `timoniv1.Action.DisableWaiting` | `action.timoni.sh/wait: disabled`   |

### Force Apply

To recreate immutable resources such as Kubernetes Jobs,
these resources can be annotated with `action.timoni.sh/force: "enabled"`.

Example:

```cue theme={"system"}
package templates

import (
	batchv1 "k8s.io/api/batch/v1"
	timoniv1 "timoni.sh/core/v1alpha1"
)

#TestJob: batchv1.#Job & {
	#config:    #Config
	apiVersion: "batch/v1"
	kind:       "Job"
	metadata: timoniv1.#MetaComponent & {
		#Meta:      #config.metadata
		#Component: "test"
	}
	metadata: annotations: timoniv1.Action.Force
	spec: {...}
}

```

### One-Off Apply

To apply resources only if they don't exist on the cluster,
these resources can be annotated with `action.timoni.sh/one-off: "enabled"`.

Example:

```cue theme={"system"}
package templates

import (
	batchv1 "k8s.io/api/batch/v1"
	timoniv1 "timoni.sh/core/v1alpha1"
)

#InstallJob: batchv1.#Job & {
	#config:    #Config
	apiVersion: "batch/v1"
	kind:       "Job"
	metadata: timoniv1.#MetaComponent & {
		#Meta:      #config.metadata
		#Component: "install"
	}
	metadata: annotations: timoniv1.Action.OneOff
	spec: {...}
}

```

### Disable Pruning

To prevent Timoni's garbage collector from deleting certain
resources such as Kubernetes Persistent Volume Claims,
these resources can be annotated with `action.timoni.sh/prune: "disabled"`.

Example:

```cue theme={"system"}
package templates

import (
	corev1 "k8s.io/api/core/v1"
	timoniv1 "timoni.sh/core/v1alpha1"
)

#DatabasePVC: corev1.#PersistentVolumeClaim & {
	#config:    #Config
	apiVersion: "v1"
	kind:       "PersistentVolumeClaim"
	metadata: timoniv1.#MetaComponent & {
		#Meta:      #config.metadata
		#Component: "database"
	}
	metadata: annotations: timoniv1.Action.Keep
	spec: {...}
}

```

### Disable Waiting

To prevent Timoni's readiness check from waiting for certain
resources such as Kubernetes Persistent Volumes,
these resources can be annotated with `action.timoni.sh/wait: "disabled"`.

Example:

```cue theme={"system"}
package templates

import (
	corev1 "k8s.io/api/core/v1"
	timoniv1 "timoni.sh/core/v1alpha1"
)

#DatabasePV: corev1.#PersistentVolume & {
	#config:    #Config
	apiVersion: "v1"
	kind:       "PersistentVolume"
	metadata: timoniv1.#MetaComponent & {
		#Meta:      #config.metadata
		#Component: "database"
	}
	metadata: annotations: timoniv1.Action.DisableWaiting
	spec: {...}
}

```

### Waiting for Custom Resources

For custom resources, a readiness evaluation can be defined with [custom health checks](/cue/module/health-checks)
inside `timoni.cue` in module root.

Example:

```cue theme={"system"}
package main

import timoniv1 "timoni.sh/core/v1alpha1"

timoni: healthChecks: {
	"cert-manager.io": timoniv1.#HealthCheckForCondition & {
		group: "cert-manager.io"
	}
	"trust.cert-manager.io": timoniv1.#HealthCheckForCondition & {
		group:         "trust.cert-manager.io"
		conditionType: "Synced"
	}
}
```

The above definition tells Timoni to look for the `Ready=True` condition in
all kinds under the `cert-manager.io` group (`ClusterIssuer`, `Issuer`, `Certificate`) and
to look for `Synced=True` for the trust-manager kinds (`ClusterBundle`, `Bundle`).

## Taking Ownership of Existing Resources

When a module's resources already exist on the cluster, Timoni takes ownership
of them during the server-side apply. Objects created with `kubectl apply` or
`helm install` (both Helm v3 and Helm v4 releases) become managed by Timoni:
the field ownership is transferred from the `kubectl` and `helm` field managers
to `timoni` before the objects are applied, and the fields set with these tools
are replaced with the module's desired state.

When taking ownership, Timoni removes the following metadata from the objects:

* the `kubectl.kubernetes.io/last-applied-configuration` annotation
* the `meta.helm.sh/release-name` annotation
* the `meta.helm.sh/release-namespace` annotation

This allows migrating an app from Helm to Timoni by installing the module
instance over the existing Helm release, then deleting the Helm release
secrets without uninstalling the app.
