mirror of
https://github.com/lukaszraczylo/kubemirror.git
synced 2026-06-10 23:09:14 +00:00
184 lines
4.9 KiB
Markdown
184 lines
4.9 KiB
Markdown
# Transformation Rules Design
|
|
|
|
## Overview
|
|
|
|
Transformation rules allow users to modify resources during mirroring. Rules are specified in the `kubemirror.raczylo.com/transform` annotation as YAML.
|
|
|
|
## Annotation Format
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: app-config
|
|
annotations:
|
|
kubemirror.raczylo.com/sync: "true"
|
|
kubemirror.raczylo.com/target-namespaces: "prod-*"
|
|
kubemirror.raczylo.com/transform: |
|
|
rules:
|
|
- path: data.LOG_LEVEL
|
|
value: "error"
|
|
- path: data.API_URL
|
|
template: "https://{{.TargetNamespace}}.api.example.com"
|
|
- path: metadata.labels
|
|
merge:
|
|
environment: "production"
|
|
managed-by: "kubemirror"
|
|
- path: data.DEBUG_MODE
|
|
delete: true
|
|
```
|
|
|
|
## Rule Types
|
|
|
|
### 1. Static Value (`value`)
|
|
Set a field to a static value, replacing existing content.
|
|
|
|
```yaml
|
|
- path: data.LOG_LEVEL
|
|
value: "error"
|
|
```
|
|
|
|
### 2. Template Value (`template`)
|
|
Use Go templates with context variables.
|
|
|
|
**Available template variables:**
|
|
- `.TargetNamespace` - Target namespace name
|
|
- `.SourceNamespace` - Source namespace name
|
|
- `.SourceName` - Source resource name
|
|
- `.TargetName` - Target resource name (usually same as source)
|
|
- `.Labels` - Map of source labels
|
|
- `.Annotations` - Map of source annotations
|
|
|
|
```yaml
|
|
- path: data.API_URL
|
|
template: "https://{{.TargetNamespace}}.api.example.com"
|
|
|
|
- path: metadata.annotations.namespace-specific
|
|
template: "Mirrored from {{.SourceNamespace}}/{{.SourceName}}"
|
|
```
|
|
|
|
### 3. Map Merge (`merge`)
|
|
Merge additional key-value pairs into an existing map. If the map doesn't exist, it's created.
|
|
|
|
```yaml
|
|
- path: metadata.labels
|
|
merge:
|
|
environment: "production"
|
|
tier: "frontend"
|
|
```
|
|
|
|
### 4. Field Deletion (`delete`)
|
|
Remove a field from the resource.
|
|
|
|
```yaml
|
|
- path: data.DEBUG_MODE
|
|
delete: true
|
|
|
|
- path: metadata.annotations.internal-only
|
|
delete: true
|
|
```
|
|
|
|
## Path Syntax
|
|
|
|
Paths use dot notation to traverse the resource structure:
|
|
- `data.KEY` - Data field in ConfigMap/Secret
|
|
- `metadata.labels.LABEL_KEY` - Specific label
|
|
- `metadata.annotations.ANNOTATION_KEY` - Specific annotation
|
|
- `spec.replicas` - Spec field
|
|
- `spec.template.spec.containers[0].image` - Array indexing
|
|
|
|
## Template Functions
|
|
|
|
Custom template functions available:
|
|
|
|
- `{{ upper .TargetNamespace }}` - Uppercase
|
|
- `{{ lower .TargetNamespace }}` - Lowercase
|
|
- `{{ replace .TargetNamespace "-" "_" }}` - String replacement
|
|
- `{{ trimPrefix .TargetNamespace "prod-" }}` - Remove prefix
|
|
- `{{ trimSuffix .TargetNamespace "-app" }}` - Remove suffix
|
|
- `{{ default "fallback" .Labels.optional }}` - Default value
|
|
|
|
## Security Considerations
|
|
|
|
1. **Template Sandboxing**: Templates are executed in a sandboxed environment
|
|
2. **Path Validation**: Paths must be valid JSONPath expressions
|
|
3. **No External Access**: Templates cannot access files, network, or execute commands
|
|
4. **Resource Limits**: Maximum template execution time: 100ms
|
|
5. **Size Limits**: Maximum transformation rule size: 10KB
|
|
|
|
## Examples
|
|
|
|
### Environment-Specific Configuration
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: app-config
|
|
namespace: default
|
|
annotations:
|
|
kubemirror.raczylo.com/sync: "true"
|
|
kubemirror.raczylo.com/target-namespaces: "dev-*,staging-*,prod-*"
|
|
kubemirror.raczylo.com/transform: |
|
|
rules:
|
|
# Set log level based on namespace prefix
|
|
- path: data.LOG_LEVEL
|
|
template: |
|
|
{{- if hasPrefix .TargetNamespace "prod-" -}}
|
|
error
|
|
{{- else if hasPrefix .TargetNamespace "staging-" -}}
|
|
warn
|
|
{{- else -}}
|
|
debug
|
|
{{- end }}
|
|
|
|
# Namespace-specific API URL
|
|
- path: data.API_URL
|
|
template: "https://{{.TargetNamespace}}.api.example.com"
|
|
|
|
# Add environment label
|
|
- path: metadata.labels
|
|
merge:
|
|
environment: "{{ trimPrefix .TargetNamespace (regexFind `^[^-]+` .TargetNamespace) }}"
|
|
```
|
|
|
|
### Secret with Dynamic Values
|
|
|
|
```yaml
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: database-config
|
|
annotations:
|
|
kubemirror.raczylo.com/sync: "true"
|
|
kubemirror.raczylo.com/target-namespaces: "app-*"
|
|
kubemirror.raczylo.com/transform: |
|
|
rules:
|
|
# Database host varies by namespace
|
|
- path: data.DB_HOST
|
|
template: "{{ .TargetNamespace }}.postgres.svc.cluster.local"
|
|
|
|
# Remove admin password in non-admin namespaces
|
|
- path: data.ADMIN_PASSWORD
|
|
delete: true
|
|
```
|
|
|
|
## Error Handling
|
|
|
|
Transformation errors are non-fatal by default:
|
|
- Invalid path: Log warning, skip transformation
|
|
- Template error: Log warning, skip transformation
|
|
- Type mismatch: Log warning, skip transformation
|
|
|
|
To make errors fatal (block mirroring):
|
|
```yaml
|
|
kubemirror.raczylo.com/transform-strict: "true"
|
|
```
|
|
|
|
## Performance
|
|
|
|
- Rules are parsed once and cached
|
|
- Template compilation is cached
|
|
- Average overhead: <1ms per mirror creation
|
|
- Maximum rules per resource: 50
|