Trait
A Trait represents a cross-cutting concern that can be attached to components to add additional capabilities like persistent storage, observability, security policies, or service mesh integration. Traits modify or extend the resources generated by ComponentTypes without requiring changes to the ComponentType itself.
API Version
openchoreo.dev/v1alpha1
Resource Definition
Metadata
Traits are namespace-scoped resources typically created in an Organization's namespace to be available for components in that organization.
apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: <trait-name>
namespace: <org-namespace> # Organization namespace
Spec Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
schema | TraitSchema | No | - | Configurable parameters for this trait |
creates | [TraitCreate] | No | [] | New Kubernetes resources to create |
patches | [TraitPatch] | No | [] | Modifications to existing ComponentType resources |
TraitSchema
Defines the configurable parameters that developers can set when attaching this trait to a component.
| Field | Type | Required | Default | Description |
|----------------|--------|----------|------------------------------------------------------------|
| types | object | No | - | Reusable type definitions referenced in parameters |
| parameters | object | No | - | Developer-facing configuration options |
| envOverrides | object | No | - | Parameters that can be overridden per environment |
Parameter Schema Syntax
Uses the same inline schema syntax as ComponentType:
fieldName: "type | default=value | required=true | enum=val1,val2"
Example:
schema:
parameters:
volumeName: "string | required=true"
mountPath: "string | required=true"
containerName: "string | default=app"
envOverrides:
size: "string | default=10Gi"
storageClass: "string | default=standard"
TraitCreate
Defines a new Kubernetes resource to be created when the trait is applied.
| Field | Type | Required | Description |
|---|---|---|---|
template | object | Yes | Kubernetes resource template with CEL expressions |
CEL expressions in trait templates have access to:
metadata.*- Component metadatatrait.*- Trait parameters and instance nameparameters.*- Component parametersenvironment.*- Environment information
TraitPatch
Defines modifications to existing resources generated by the ComponentType.
| Field | Type | Required | Description |
|---|---|---|---|
forEach | string | No | CEL expression for iterating over a list |
var | string | No | Variable name for forEach iterations (required if forEach set) |
target | PatchTarget | Yes | Specifies which resource to patch |
operations | [JSONPatchOperation] | Yes | List of JSONPatch operations to apply |
PatchTarget
Specifies which Kubernetes resource to modify.
| Field | Type | Required | Description |
|---|---|---|---|
group | string | No | API group (empty for core resources) |
version | string | Yes | API version (e.g., "v1", "v1beta1") |
kind | string | Yes | Resource type (e.g., "Deployment", "StatefulSet") |
where | string | No | CEL expression to filter which resources to patch |
JSONPatchOperation
Defines a modification using JSONPatch format (RFC 6902) with OpenChoreo extensions.
| Field | Type | Required | Description |
|---|---|---|---|
op | string | Yes | Operation: add, replace, remove, mergeShallow |
path | string | Yes | JSON Pointer to the field (RFC 6901) |
value | any | No | Value to set (not used for remove) |
Supported Operations
- add: Add a new field or array element
- replace: Replace an existing field value
- remove: Delete a field
- mergeShallow: OpenChoreo extension for overlaying map keys
Path Syntax
Supports array filters for targeting specific elements:
/spec/containers/[?(@.name=='app')]/volumeMounts/-
Examples
Persistent Volume Trait
apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: persistent-volume
namespace: default
spec:
schema:
parameters:
volumeName: "string | required=true"
mountPath: "string | required=true"
containerName: "string | default=app"
envOverrides:
size: "string | default=10Gi"
storageClass: "string | default=standard"
creates:
- template:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ${metadata.name}-${trait.instanceName}
namespace: ${metadata.namespace}
spec:
accessModes:
- ReadWriteOnce
storageClassName: ${trait.parameters.storageClass}
resources:
requests:
storage: ${trait.parameters.size}
patches:
- target:
group: apps
version: v1
kind: Deployment
operations:
- op: add
path: /spec/template/spec/containers/[?(@.name=='${trait.parameters.containerName}')]/volumeMounts/-
value:
name: ${trait.parameters.volumeName}
mountPath: ${trait.parameters.mountPath}
- op: add
path: /spec/template/spec/volumes/-
value:
name: ${trait.parameters.volumeName}
persistentVolumeClaim:
claimName: ${metadata.name}-${trait.instanceName}
Sidecar Container Trait
apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: logging-sidecar
namespace: default
spec:
schema:
parameters:
logPath: "string | default=/var/log/app"
sidecarImage: "string | default=fluent/fluent-bit:latest"
patches:
- target:
group: apps
version: v1
kind: Deployment
operations:
- op: add
path: /spec/template/spec/containers/-
value:
name: log-collector
image: ${trait.parameters.sidecarImage}
volumeMounts:
- name: logs
mountPath: ${trait.parameters.logPath}
- op: add
path: /spec/template/spec/volumes/-
value:
name: logs
emptyDir: {}
Resource Limits Trait
apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: resource-limits
namespace: default
spec:
schema:
envOverrides:
cpuLimit: "string | default=1000m"
memoryLimit: "string | default=512Mi"
patches:
- target:
group: apps
version: v1
kind: Deployment
operations:
- op: mergeShallow
path: /spec/template/spec/containers/[?(@.name=='main')]/resources
value:
limits:
cpu: ${trait.parameters.cpuLimit}
memory: ${trait.parameters.memoryLimit}
Multi-Container Trait with forEach
apiVersion: openchoreo.dev/v1alpha1
kind: Trait
metadata:
name: multi-volume
namespace: default
spec:
schema:
parameters:
mounts: "array<object> | required=true"
patches:
- target:
group: apps
version: v1
kind: Deployment
forEach: ${trait.parameters.mounts}
var: mount
operations:
- op: add
path: /spec/template/spec/volumes/-
value:
name: ${mount.name}
emptyDir: {}
- op: add
path: /spec/template/spec/containers/[?(@.name=='app')]/volumeMounts/-
value:
name: ${mount.name}
mountPath: ${mount.path}
Usage
Developers attach traits to components in the Component specification:
apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-service
spec:
componentType: deployment/service
traits:
- name: persistent-volume
instanceName: data-storage
parameters:
volumeName: data
mountPath: /var/data
containerName: app
envOverrides:
size: 20Gi
storageClass: fast-ssd
Platform engineers can also override trait parameters in ComponentDeployment:
apiVersion: openchoreo.dev/v1alpha1
kind: ComponentDeployment
metadata:
name: my-service-production
spec:
componentName: my-service
environment: production
traitOverrides:
- instanceName: data-storage
parameters:
size: 100Gi
storageClass: production-ssd
Best Practices
- Single Responsibility: Each trait should address one cross-cutting concern
- Naming: Use descriptive names that indicate the capability being added
- Parameters: Provide sensible defaults for all non-required parameters
- Target Specificity: Use
whereclauses when needed to avoid unintended modifications - Testing: Test traits with different ComponentTypes to ensure compatibility
- Documentation: Document which ComponentTypes a trait is designed to work with
- Idempotency: Ensure traits can be safely applied multiple times
Trait vs ComponentType
| Aspect | ComponentType | Trait |
|---|---|---|
| Purpose | Defines core deployment pattern | Adds cross-cutting concerns |
| Scope | One per component | Multiple can be attached to one component |
| Resources | Creates primary workload resources | Creates supplementary resources or patches existing ones |
| Modification | Determines base resource structure | Modifies or extends ComponentType resources |
| Examples | Service, WebApp, ScheduledTask | Persistent Storage, Logging, Security |
Related Resources
- ComponentType - Defines the base deployment pattern
- Component - Attaches traits to components
- ComponentDeployment - Can override trait parameters per environment