Preparation for release.

This commit is contained in:
2025-12-25 23:11:32 +00:00
parent 8adb52608f
commit 3e872dfdeb
28 changed files with 5905 additions and 201 deletions
+370
View File
@@ -248,3 +248,373 @@ metadata:
data:
config: "value"
```
## Transformation Rules
KubeMirror supports transformation rules that modify resources during mirroring. This enables environment-specific configurations, security hardening, and dynamic value generation.
### Transformation Examples
The repository includes comprehensive transformation examples in `transform-configmap.yaml` and `transform-secret.yaml`. These demonstrate:
1. **Static Value Transformation** - Replace values with constants
2. **Template-Based Transformation** - Generate dynamic values using Go templates
3. **Merge Transformation** - Add labels, annotations, or map entries
4. **Delete Transformation** - Remove sensitive or environment-specific fields
5. **Multi-Rule Transformations** - Combine multiple transformation types
### Quick Start with Transformations
```bash
# Apply transformation examples
kubectl apply -f examples/transform-configmap.yaml
kubectl apply -f examples/transform-secret.yaml
# Verify transformed ConfigMap
kubectl get configmap app-config-template -n namespace-2 -o yaml
# Check that the API_URL was transformed for namespace-2
kubectl get configmap app-config-template -n namespace-2 \
-o jsonpath='{.data.API_URL}'
# Expected: https://namespace-2.api.example.com
```
### Transformation Rule Types
#### 1. Value Rules (Static Replacement)
Replace a field with a static value:
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
- path: data.LOG_LEVEL
value: "error"
```
#### 2. Template Rules (Dynamic Generation)
Use Go templates with context variables:
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
- path: data.API_URL
template: "https://{{.TargetNamespace}}.api.example.com"
```
**Available template variables:**
- `.TargetNamespace` - Namespace where mirror is created
- `.SourceNamespace` - Original resource namespace
- `.SourceName` - Original resource name
- `.TargetName` - Mirror resource name
- `.Labels` - Map of source labels
- `.Annotations` - Map of source annotations
**Template functions:**
- `upper` - Convert to uppercase
- `lower` - Convert to lowercase
- `replace` - String replacement: `{{replace .TargetNamespace "-" "_"}}`
- `trimPrefix` - Remove prefix: `{{trimPrefix .TargetNamespace "namespace-"}}`
- `trimSuffix` - Remove suffix
- `hasPrefix` - Check for prefix
- `hasSuffix` - Check for suffix
- `default` - Provide fallback: `{{default "fallback" .OptionalField}}`
#### 3. Merge Rules (Add Entries)
Merge additional entries into maps (labels, annotations, data):
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
- path: metadata.labels
merge:
environment: "production"
managed-by: "kubemirror"
```
#### 4. Delete Rules (Remove Fields)
Remove sensitive or unnecessary fields:
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
- path: data.DEBUG_MODE
delete: true
- path: data.ADMIN_PASSWORD
delete: true
```
### Array Indexing
Transform specific elements in arrays using bracket notation `[index]`:
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
# Update first container's image
- path: spec.template.spec.containers[0].image
template: "registry.{{.TargetNamespace}}.example.com/app:v1"
# Update second environment variable
- path: spec.template.spec.containers[0].env[1].value
template: "postgres://{{.TargetNamespace}}-db.svc.cluster.local:5432"
# Update nested arrays (container → env vars → value)
- path: spec.template.spec.containers[0].env[2].value
value: "production"
# Update volume ConfigMap reference
- path: spec.template.spec.volumes[0].configMap.name
template: "{{.TargetNamespace}}-config"
```
**Common use cases for array indexing:**
- Container images: `spec.template.spec.containers[0].image`
- Environment variables: `spec.template.spec.containers[0].env[N].value`
- Volume mounts: `spec.template.spec.containers[0].volumeMounts[N].mountPath`
- Init containers: `spec.template.spec.initContainers[0].image`
- Volume references: `spec.template.spec.volumes[N].configMap.name`
- Resource limits: `spec.template.spec.containers[0].resources.limits.memory`
**Important notes:**
- Array indexes are zero-based (`[0]` is the first element)
- Index must be within array bounds or transformation will fail
- Use with strict mode to catch out-of-bounds errors
- See `transform-deployment.yaml` for comprehensive Deployment examples
### Namespace Patterns
Apply transformation rules conditionally based on target namespace patterns using glob-style matching.
#### Basic Pattern Matching
Limit a rule to specific namespaces using the `namespacePattern` field:
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
# Only apply to preprod namespaces
- path: data.GRAPHQL_HOST
value: "https://preprod.example.com/v1/graphql"
namespacePattern: "preprod-*"
# Only apply to production namespaces
- path: data.GRAPHQL_HOST
value: "https://api.example.com/v1/graphql"
namespacePattern: "prod-*"
```
#### Supported Pattern Syntax
- `*` - Matches zero or more characters
- `?` - Matches exactly one character
- No pattern or empty pattern - Matches all namespaces
**Examples:**
- `preprod-*` - Matches `preprod-api`, `preprod-worker`, `preprod-db`
- `*-staging` - Matches `app-staging`, `api-staging`
- `prod-*-v?` - Matches `prod-api-v1`, `prod-db-v2`
- `namespace-?` - Matches `namespace-1`, `namespace-2` (single digit only)
#### Pattern Matching Rules
1. **Rules without patterns** apply to **all namespaces**
2. **Rules with patterns** only apply when the pattern matches the target namespace
3. **Multiple rules with different patterns** can coexist - each is evaluated independently
4. **Pattern matching is case-sensitive**
#### Example: Environment-Specific Configuration
```yaml
annotations:
kubemirror.raczylo.com/transform: |
rules:
# Global rule - applies to all namespaces
- path: data.APP_NAME
value: "my-app"
# Preprod configuration
- path: data.LOG_LEVEL
value: "debug"
namespacePattern: "preprod-*"
- path: data.DATABASE_URL
template: "postgres://{{.TargetNamespace}}.db.preprod.example.com:5432"
namespacePattern: "preprod-*"
# Production configuration
- path: data.LOG_LEVEL
value: "error"
namespacePattern: "prod-*"
- path: data.DATABASE_URL
template: "postgres://{{.TargetNamespace}}.db.prod.example.com:5432"
namespacePattern: "prod-*"
```
In this example:
- `data.APP_NAME` is set in **all** mirrored namespaces
- `data.LOG_LEVEL` is `debug` in preprod namespaces, `error` in prod namespaces
- `data.DATABASE_URL` is environment-specific based on the namespace pattern
#### Combining Patterns with Templates
Namespace patterns work seamlessly with template rules:
```yaml
rules:
# Apply different API endpoints based on namespace
- path: data.API_ENDPOINT
template: "https://{{.TargetNamespace}}.api.preprod.com"
namespacePattern: "preprod-*"
- path: data.API_ENDPOINT
template: "https://{{.TargetNamespace}}.api.example.com"
namespacePattern: "prod-*"
```
#### Pattern Verification
```bash
# Verify preprod pattern matching
kubectl get configmap app-config-pattern -n preprod-api \
-o jsonpath='{.data.GRAPHQL_HOST}'
# Expected: https://preprod.example.com/v1/graphql
kubectl get configmap app-config-pattern -n prod-api \
-o jsonpath='{.data.GRAPHQL_HOST}'
# Expected: https://api.example.com/v1/graphql
# Verify multi-pattern configuration
kubectl get configmap app-config-multipattern -n namespace-2 \
-o jsonpath='{.data.ENVIRONMENT}'
# Expected: development
kubectl get configmap app-config-multipattern -n preprod-api \
-o jsonpath='{.data.ENVIRONMENT}'
# Expected: preproduction
```
### Strict Mode
By default, transformation errors are logged but don't block mirroring. Enable strict mode to fail mirroring on transformation errors:
```yaml
annotations:
kubemirror.raczylo.com/transform-strict: "true"
kubemirror.raczylo.com/transform: |
rules:
- path: data.CRITICAL_VALUE
value: "must-succeed"
```
### Transformation Verification
```bash
# Check static value transformation
kubectl get configmap app-config-static -n namespace-2 \
-o jsonpath='{.data.LOG_LEVEL}'
# Expected: error
# Check template transformation
kubectl get configmap app-config-template -n namespace-3 \
-o jsonpath='{.data.API_URL}'
# Expected: https://namespace-3.api.example.com
# Check merge transformation (labels should include new entries)
kubectl get configmap app-config-merge -n namespace-2 -o yaml | grep -A 5 labels
# Should include: environment: production, managed-by: kubemirror
# Check delete transformation (fields should be removed)
kubectl get configmap app-config-delete -n namespace-2 -o yaml | grep DEBUG_MODE
# Should return nothing (field deleted)
# Check Secret transformations
kubectl get secret database-credentials -n namespace-2 \
-o jsonpath='{.data.DB_HOST}' | base64 -d
# Expected: namespace-2.postgres.svc.cluster.local
```
### Common Transformation Patterns
#### Environment-Specific Configuration
```yaml
rules:
- path: data.LOG_LEVEL
template: |
{{- if hasPrefix .TargetNamespace "prod-" -}}
error
{{- else if hasPrefix .TargetNamespace "staging-" -}}
warn
{{- else -}}
debug
{{- end }}
```
#### Namespace-Based Service Discovery
```yaml
rules:
- path: data.DATABASE_HOST
template: "postgres.{{.TargetNamespace}}.svc.cluster.local"
- path: data.REDIS_HOST
template: "redis.{{.TargetNamespace}}.svc.cluster.local"
```
#### Security Hardening
```yaml
rules:
# Remove development credentials
- path: data.DEV_API_KEY
delete: true
# Set production encryption
- path: data.ENCRYPTION_STRENGTH
value: "AES-256"
# Add security labels
- path: metadata.labels
merge:
security-tier: "high"
encrypted: "true"
```
### Troubleshooting Transformations
```bash
# View transformation errors in controller logs
kubectl logs -n kubemirror-system -l app.kubernetes.io/name=kubemirror | grep -i transform
# Check if strict mode is blocking mirroring
kubectl get events --all-namespaces | grep -i "transformation.*failed"
# Verify transformation annotation is valid YAML
kubectl get configmap <name> -n <namespace> \
-o jsonpath='{.metadata.annotations.kubemirror\.raczylo\.com/transform}' | yq eval -
```
### Performance Considerations
- **Rule Limit**: Maximum 50 rules per resource (configurable)
- **Rule Size**: Maximum 10KB of YAML per resource (configurable)
- **Template Timeout**: 100ms per template execution (configurable)
- **Overhead**: <1ms average transformation time per mirror
### Security Notes
1. **Template Sandboxing**: Templates execute in a sandboxed environment with no file, network, or command access
2. **Timeout Protection**: Template execution is strictly time-limited to prevent DoS
3. **Size Limits**: Rules have size limits to prevent resource exhaustion
4. **No Code Execution**: Templates use predefined safe functions only