mirror of
https://github.com/lukaszraczylo/kubemirror.git
synced 2026-06-05 22:43:51 +00:00
Preparation for release.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -7,6 +7,9 @@ resources:
|
||||
- source-secret.yaml
|
||||
- source-configmap.yaml
|
||||
- traefik-middleware.yaml
|
||||
- transform-configmap.yaml
|
||||
- transform-secret.yaml
|
||||
- transform-deployment.yaml
|
||||
|
||||
commonLabels:
|
||||
managed-by: kustomize
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
# Transformation Examples for KubeMirror
|
||||
# These examples demonstrate the transformation rules feature
|
||||
|
||||
---
|
||||
# Example 1: Static Value Transformation
|
||||
# Changes LOG_LEVEL to "error" in all mirrors
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-static
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
- path: data.LOG_LEVEL
|
||||
value: "error"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "static-value-transform"
|
||||
data:
|
||||
LOG_LEVEL: "debug"
|
||||
APP_NAME: "my-app"
|
||||
|
||||
---
|
||||
# Example 2: Template-Based Transformation
|
||||
# Creates namespace-specific API URLs
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-template
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3,namespace-4"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
- path: data.API_URL
|
||||
template: "https://{{.TargetNamespace}}.api.example.com"
|
||||
- path: data.NAMESPACE_UPPER
|
||||
template: "{{upper .TargetNamespace}}"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "template-transform"
|
||||
data:
|
||||
API_URL: "https://default.api.example.com"
|
||||
NAMESPACE_UPPER: "DEFAULT"
|
||||
|
||||
---
|
||||
# Example 3: Merge Transformation
|
||||
# Adds environment-specific labels to mirrored ConfigMaps
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-merge
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
- path: metadata.labels
|
||||
merge:
|
||||
environment: "production"
|
||||
managed-by: "kubemirror"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
app: "myapp"
|
||||
example: "merge-transform"
|
||||
data:
|
||||
config: "value"
|
||||
|
||||
---
|
||||
# Example 4: Delete Transformation
|
||||
# Removes sensitive debug fields from mirrors
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-delete
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
- path: data.DEBUG_MODE
|
||||
delete: true
|
||||
- path: data.INTERNAL_API_KEY
|
||||
delete: true
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "delete-transform"
|
||||
data:
|
||||
DEBUG_MODE: "true"
|
||||
INTERNAL_API_KEY: "secret-key"
|
||||
PUBLIC_CONFIG: "safe-value"
|
||||
|
||||
---
|
||||
# Example 5: Multi-Rule Complex Transformation
|
||||
# Combines value, template, merge, and delete operations
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-complex
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3,namespace-4"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Set log level to error in production mirrors
|
||||
- path: data.LOG_LEVEL
|
||||
value: "error"
|
||||
|
||||
# Create namespace-specific database URL
|
||||
- path: data.DATABASE_URL
|
||||
template: "postgres://{{.TargetNamespace}}.db.svc.cluster.local:5432/app"
|
||||
|
||||
# Create namespace-specific cache prefix
|
||||
- path: data.CACHE_PREFIX
|
||||
template: "{{replace .TargetNamespace \"-\" \"_\"}}"
|
||||
|
||||
# Add environment labels
|
||||
- path: metadata.labels
|
||||
merge:
|
||||
environment: "production"
|
||||
tier: "backend"
|
||||
|
||||
# Remove debug configurations
|
||||
- path: data.DEBUG_MODE
|
||||
delete: true
|
||||
|
||||
# Remove development API keys
|
||||
- path: data.DEV_API_KEY
|
||||
delete: true
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
app: "complex-app"
|
||||
example: "multi-rule-transform"
|
||||
data:
|
||||
LOG_LEVEL: "debug"
|
||||
DATABASE_URL: "postgres://localhost:5432/app"
|
||||
CACHE_PREFIX: "dev"
|
||||
DEBUG_MODE: "true"
|
||||
DEV_API_KEY: "dev-key-12345"
|
||||
APP_NAME: "my-app"
|
||||
|
||||
---
|
||||
# Example 6: Template Functions Showcase
|
||||
# Demonstrates all available template functions
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-functions
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# String manipulation
|
||||
- path: data.UPPER_NAMESPACE
|
||||
template: "{{upper .TargetNamespace}}"
|
||||
|
||||
- path: data.LOWER_NAMESPACE
|
||||
template: "{{lower .TargetNamespace}}"
|
||||
|
||||
- path: data.TRIMMED_PREFIX
|
||||
template: "{{trimPrefix .TargetNamespace \"namespace-\"}}"
|
||||
|
||||
- path: data.REPLACED_DASH
|
||||
template: "{{replace .TargetNamespace \"-\" \"_\"}}"
|
||||
|
||||
# Default value for missing field
|
||||
- path: data.WITH_DEFAULT
|
||||
template: "{{default \"fallback-value\" .OptionalField}}"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "template-functions"
|
||||
data:
|
||||
placeholder: "will-be-replaced"
|
||||
|
||||
---
|
||||
# Example 7: Strict Mode Transformation
|
||||
# Transformation errors will block mirroring
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-strict
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2"
|
||||
kubemirror.raczylo.com/transform-strict: "true"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
- path: data.CRITICAL_VALUE
|
||||
value: "must-succeed"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "strict-mode"
|
||||
data:
|
||||
CRITICAL_VALUE: "default"
|
||||
|
||||
---
|
||||
# Example 8: Namespace Pattern - Environment-Specific Configuration
|
||||
# Apply different GraphQL hosts based on namespace patterns
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-pattern
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "preprod-api,preprod-worker,prod-api,staging-api"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Preprod environments get preprod GraphQL endpoint
|
||||
- path: data.GRAPHQL_HOST
|
||||
value: "https://preprod.example.com/v1/graphql"
|
||||
namespacePattern: "preprod-*"
|
||||
|
||||
# Production environments get production endpoint
|
||||
- path: data.GRAPHQL_HOST
|
||||
value: "https://api.example.com/v1/graphql"
|
||||
namespacePattern: "prod-*"
|
||||
|
||||
# Staging environments get staging endpoint
|
||||
- path: data.GRAPHQL_HOST
|
||||
value: "https://staging.example.com/v1/graphql"
|
||||
namespacePattern: "*-staging"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "namespace-pattern"
|
||||
data:
|
||||
GRAPHQL_HOST: "https://default.example.com/v1/graphql"
|
||||
APP_NAME: "my-app"
|
||||
|
||||
---
|
||||
# Example 9: Namespace Pattern with Templates
|
||||
# Combine patterns with template-based transformations
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-pattern-template
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "preprod-api,preprod-worker,prod-api,prod-worker"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Preprod: low log level
|
||||
- path: data.LOG_LEVEL
|
||||
value: "debug"
|
||||
namespacePattern: "preprod-*"
|
||||
|
||||
# Production: high log level
|
||||
- path: data.LOG_LEVEL
|
||||
value: "error"
|
||||
namespacePattern: "prod-*"
|
||||
|
||||
# All preprod: namespace-specific database URL
|
||||
- path: data.DATABASE_URL
|
||||
template: "postgres://{{.TargetNamespace}}.db.preprod.example.com:5432/mydb"
|
||||
namespacePattern: "preprod-*"
|
||||
|
||||
# All prod: namespace-specific database URL
|
||||
- path: data.DATABASE_URL
|
||||
template: "postgres://{{.TargetNamespace}}.db.prod.example.com:5432/mydb"
|
||||
namespacePattern: "prod-*"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "pattern-with-template"
|
||||
data:
|
||||
LOG_LEVEL: "info"
|
||||
DATABASE_URL: "postgres://localhost:5432/mydb"
|
||||
|
||||
---
|
||||
# Example 10: Complex Multi-Pattern Rules
|
||||
# Multiple patterns with different transformations
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: app-config-multipattern
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3,preprod-api,prod-api"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Global rule (no pattern) - applies to ALL namespaces
|
||||
- path: data.APP_NAME
|
||||
value: "universal-app"
|
||||
|
||||
# Only for numbered namespaces (namespace-2, namespace-3)
|
||||
- path: data.ENVIRONMENT
|
||||
value: "development"
|
||||
namespacePattern: "namespace-?"
|
||||
|
||||
# Only for preprod environments
|
||||
- path: data.ENVIRONMENT
|
||||
value: "preproduction"
|
||||
namespacePattern: "preprod-*"
|
||||
|
||||
# Only for production environments
|
||||
- path: data.ENVIRONMENT
|
||||
value: "production"
|
||||
namespacePattern: "prod-*"
|
||||
|
||||
# Add security label only to production
|
||||
- path: metadata.labels
|
||||
merge:
|
||||
security-tier: "high"
|
||||
compliance: "required"
|
||||
namespacePattern: "prod-*"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "multi-pattern"
|
||||
data:
|
||||
APP_NAME: "default-app"
|
||||
ENVIRONMENT: "unknown"
|
||||
@@ -0,0 +1,249 @@
|
||||
# Array Indexing Transformation Examples for KubeMirror
|
||||
# Demonstrates transformation rules on Kubernetes Deployments with containers, env vars, etc.
|
||||
|
||||
---
|
||||
# Example 1: Transform Container Image with Namespace-Specific Registry
|
||||
# Changes the image for the first container to use a namespace-specific registry
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: web-app
|
||||
namespace: namespace-1
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
app: web-app
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Update container image to use namespace-specific registry
|
||||
- path: spec.template.spec.containers[0].image
|
||||
template: "registry.{{.TargetNamespace}}.example.com/web-app:v1.0.0"
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: web-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: web-app
|
||||
spec:
|
||||
containers:
|
||||
- name: web
|
||||
image: web-app:latest
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
|
||||
---
|
||||
# Example 2: Transform Environment Variables
|
||||
# Changes specific environment variables in containers
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: api-service
|
||||
namespace: namespace-1
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3,namespace-4"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Set LOG_LEVEL env var to error for production
|
||||
- path: spec.template.spec.containers[0].env[0].value
|
||||
value: "error"
|
||||
|
||||
# Set DATABASE_URL to namespace-specific database
|
||||
- path: spec.template.spec.containers[0].env[1].value
|
||||
template: "postgres://{{.TargetNamespace}}-db.postgres.svc.cluster.local:5432/api"
|
||||
|
||||
# Set API_KEY_PREFIX with namespace identifier
|
||||
- path: spec.template.spec.containers[0].env[2].value
|
||||
template: "{{upper (replace .TargetNamespace \"-\" \"_\")}}"
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: api-service
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: api-service
|
||||
spec:
|
||||
containers:
|
||||
- name: api
|
||||
image: api-service:v2.0.0
|
||||
env:
|
||||
- name: LOG_LEVEL
|
||||
value: "debug"
|
||||
- name: DATABASE_URL
|
||||
value: "postgres://localhost:5432/api"
|
||||
- name: API_KEY_PREFIX
|
||||
value: "DEV"
|
||||
- name: SERVICE_NAME
|
||||
value: "api-service"
|
||||
|
||||
---
|
||||
# Example 3: Transform Multiple Containers
|
||||
# Handles deployments with multiple containers (app + sidecar)
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: app-with-sidecar
|
||||
namespace: namespace-1
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Main application container - update image
|
||||
- path: spec.template.spec.containers[0].image
|
||||
template: "{{.TargetNamespace}}.registry.example.com/app:v1"
|
||||
|
||||
# Main application container - set environment
|
||||
- path: spec.template.spec.containers[0].env[0].value
|
||||
template: "{{.TargetNamespace}}"
|
||||
|
||||
# Sidecar container - update image
|
||||
- path: spec.template.spec.containers[1].image
|
||||
value: "logging-sidecar:stable"
|
||||
|
||||
# Sidecar container - configure log destination
|
||||
- path: spec.template.spec.containers[1].env[0].value
|
||||
template: "https://logs.{{.TargetNamespace}}.example.com/ingest"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: app-with-sidecar
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: app-with-sidecar
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: app:latest
|
||||
env:
|
||||
- name: ENVIRONMENT
|
||||
value: "development"
|
||||
- name: log-collector
|
||||
image: logging-sidecar:latest
|
||||
env:
|
||||
- name: LOG_ENDPOINT
|
||||
value: "https://logs.dev.example.com/ingest"
|
||||
|
||||
---
|
||||
# Example 4: Transform Volume Mounts and ConfigMap References
|
||||
# Updates volume configurations for namespace-specific resources
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: config-consumer
|
||||
namespace: namespace-1
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Update ConfigMap name reference in volume
|
||||
- path: spec.template.spec.volumes[0].configMap.name
|
||||
template: "{{.TargetNamespace}}-config"
|
||||
|
||||
# Update Secret name reference in volume
|
||||
- path: spec.template.spec.volumes[1].secret.secretName
|
||||
template: "{{.TargetNamespace}}-credentials"
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: config-consumer
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: config-consumer
|
||||
spec:
|
||||
containers:
|
||||
- name: app
|
||||
image: app:v1
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /etc/config
|
||||
- name: secret-volume
|
||||
mountPath: /etc/secrets
|
||||
volumes:
|
||||
- name: config-volume
|
||||
configMap:
|
||||
name: app-config
|
||||
- name: secret-volume
|
||||
secret:
|
||||
secretName: app-credentials
|
||||
|
||||
---
|
||||
# Example 5: Complex Nested Array Transformations
|
||||
# Demonstrates deeply nested path access in complex structures
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: complex-app
|
||||
namespace: namespace-1
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Container image
|
||||
- path: spec.template.spec.containers[0].image
|
||||
template: "{{.TargetNamespace}}.registry.io/app:v1"
|
||||
|
||||
# Nested env var value (REDIS_HOST)
|
||||
- path: spec.template.spec.containers[0].env[1].value
|
||||
template: "redis.{{.TargetNamespace}}.svc.cluster.local"
|
||||
|
||||
# Resource limits
|
||||
- path: spec.template.spec.containers[0].resources.limits.memory
|
||||
value: "2Gi"
|
||||
|
||||
# Init container image
|
||||
- path: spec.template.spec.initContainers[0].image
|
||||
value: "init-db:stable"
|
||||
|
||||
# Init container env var
|
||||
- path: spec.template.spec.initContainers[0].env[0].value
|
||||
template: "{{.TargetNamespace}}-database"
|
||||
spec:
|
||||
replicas: 2
|
||||
selector:
|
||||
matchLabels:
|
||||
app: complex-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: complex-app
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-db
|
||||
image: init-db:latest
|
||||
env:
|
||||
- name: DB_NAME
|
||||
value: "default-database"
|
||||
containers:
|
||||
- name: app
|
||||
image: app:dev
|
||||
env:
|
||||
- name: APP_NAME
|
||||
value: "complex-app"
|
||||
- name: REDIS_HOST
|
||||
value: "localhost"
|
||||
resources:
|
||||
limits:
|
||||
memory: "1Gi"
|
||||
cpu: "1000m"
|
||||
@@ -0,0 +1,142 @@
|
||||
# Secret Transformation Examples for KubeMirror
|
||||
# Demonstrates transformation rules applied to Kubernetes Secrets
|
||||
|
||||
---
|
||||
# Example 1: Environment-Specific Database Credentials
|
||||
# Creates namespace-specific database connection strings
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: database-credentials
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Create namespace-specific database host
|
||||
- path: data.DB_HOST
|
||||
template: "{{.TargetNamespace}}.postgres.svc.cluster.local"
|
||||
|
||||
# Create namespace-specific database name
|
||||
- path: data.DB_NAME
|
||||
template: "app_{{replace .TargetNamespace \"-\" \"_\"}}"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "secret-template-transform"
|
||||
type: Opaque
|
||||
stringData:
|
||||
DB_HOST: "localhost"
|
||||
DB_NAME: "app_dev"
|
||||
DB_USER: "appuser"
|
||||
DB_PASSWORD: "defaultpass"
|
||||
|
||||
---
|
||||
# Example 2: Remove Admin Credentials from Non-Admin Namespaces
|
||||
# Deletes sensitive admin fields when mirroring to production
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: app-credentials
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Remove admin credentials
|
||||
- path: data.ADMIN_USERNAME
|
||||
delete: true
|
||||
|
||||
- path: data.ADMIN_PASSWORD
|
||||
delete: true
|
||||
|
||||
- path: data.ROOT_TOKEN
|
||||
delete: true
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "secret-delete-transform"
|
||||
type: Opaque
|
||||
stringData:
|
||||
APP_KEY: "app-key-12345"
|
||||
ADMIN_USERNAME: "admin"
|
||||
ADMIN_PASSWORD: "super-secret"
|
||||
ROOT_TOKEN: "root-token-xyz"
|
||||
|
||||
---
|
||||
# Example 3: API Key with Namespace-Specific Prefixes
|
||||
# Adds namespace identification to API keys
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: api-keys
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3,namespace-4"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Add namespace prefix to API key for tracking
|
||||
- path: data.API_KEY_PREFIX
|
||||
template: "{{upper (replace .TargetNamespace \"-\" \"_\")}}"
|
||||
|
||||
# Set environment-specific API endpoint
|
||||
- path: data.API_ENDPOINT
|
||||
template: "https://api.{{.TargetNamespace}}.example.com/v1"
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
example: "secret-api-transform"
|
||||
type: Opaque
|
||||
stringData:
|
||||
API_KEY_PREFIX: "DEV"
|
||||
API_KEY: "sk-1234567890"
|
||||
API_ENDPOINT: "https://api.dev.example.com/v1"
|
||||
|
||||
---
|
||||
# Example 4: Complex Multi-Rule Secret Transformation
|
||||
# Combines multiple transformation types for comprehensive secret management
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: app-secrets-complex
|
||||
namespace: namespace-1
|
||||
annotations:
|
||||
kubemirror.raczylo.com/sync: "true"
|
||||
kubemirror.raczylo.com/target-namespaces: "namespace-2,namespace-3"
|
||||
kubemirror.raczylo.com/transform: |
|
||||
rules:
|
||||
# Set production-grade encryption key
|
||||
- path: data.ENCRYPTION_STRENGTH
|
||||
value: "AES-256"
|
||||
|
||||
# Create namespace-specific service URLs
|
||||
- path: data.SERVICE_URL
|
||||
template: "https://{{.TargetNamespace}}.services.example.com"
|
||||
|
||||
# Create namespace-based Redis host
|
||||
- path: data.REDIS_HOST
|
||||
template: "redis.{{.TargetNamespace}}.svc.cluster.local"
|
||||
|
||||
# Set cache key prefix based on namespace
|
||||
- path: data.CACHE_PREFIX
|
||||
template: "{{replace .TargetNamespace \"-\" \":\"}}:"
|
||||
|
||||
# Remove development-only secrets
|
||||
- path: data.DEV_OAUTH_SECRET
|
||||
delete: true
|
||||
|
||||
- path: data.LOCAL_SIGNING_KEY
|
||||
delete: true
|
||||
labels:
|
||||
kubemirror.raczylo.com/enabled: "true"
|
||||
app: "complex-app"
|
||||
example: "secret-complex-transform"
|
||||
type: Opaque
|
||||
stringData:
|
||||
ENCRYPTION_STRENGTH: "AES-128"
|
||||
SERVICE_URL: "https://localhost:8080"
|
||||
REDIS_HOST: "localhost"
|
||||
CACHE_PREFIX: "dev:"
|
||||
APP_SECRET: "secret-12345"
|
||||
DEV_OAUTH_SECRET: "dev-oauth-xyz"
|
||||
LOCAL_SIGNING_KEY: "local-key-abc"
|
||||
Reference in New Issue
Block a user