Feature Description
Make the activate column in valueMappings optional instead of required. When not specified, all rows should be treated as active by default.
Current Behavior
Currently, the activate field is required in valueMappings:
apiVersion: operator.lynq.sh/v1
kind: LynqHub
metadata:
name: mysql-prod
spec:
valueMappings:
uid: node_id
activate: is_active # ❌ Required - must specify
Problems:
- Unnecessary complexity: For many use cases, all rows should always be active
- Database schema overhead: Forces users to add an activation column even when not needed
- Migration burden: Existing databases must be modified to add activation columns
Proposed Behavior
Make activate optional with smart defaults:
# Option 1: Explicit activate column (current behavior, still supported)
spec:
valueMappings:
uid: node_id
activate: is_active # ✅ Optional - explicit control
# Option 2: No activate column (new behavior)
spec:
valueMappings:
uid: node_id
# activate not specified - all rows treated as active ✅
Logic
When activate is specified:
- Query and evaluate the column value
- Only include rows where
activate is truthy (true, "true", 1, "1", etc.)
- Existing behavior unchanged
When activate is NOT specified:
- Treat all returned rows as active
- No filtering based on activation status
- New default-active behavior
Use Cases
Use Case 1: Simple Multi-Tenant Setup
# All tenants are always active - no need for activation column
apiVersion: operator.lynq.sh/v1
kind: LynqHub
metadata:
name: tenants-hub
spec:
source:
type: mysql
mysql:
query: "SELECT tenant_id FROM tenants" # No is_active column needed
valueMappings:
uid: tenant_id
# No activate field - all tenants always active
Use Case 2: Dev/Test Environments
# Development environment - all test instances always on
apiVersion: operator.lynq.sh/v1
kind: LynqHub
metadata:
name: dev-instances
spec:
valueMappings:
uid: instance_id
# No activation control needed in dev
Use Case 3: Gradual Migration (Backward Compatible)
# Existing production setup - keep activation logic
apiVersion: operator.lynq.sh/v1
kind: LynqHub
metadata:
name: prod-tenants
spec:
valueMappings:
uid: tenant_id
activate: is_active # Still works exactly as before
Implementation Details
Validation Changes
Location: api/v1/lynqhub_webhook.go
// Current validation (strict)
func (r *LynqHub) validateValueMappings() error {
if r.Spec.ValueMappings.UID == "" {
return fmt.Errorf("valueMappings.uid is required")
}
if r.Spec.ValueMappings.Activate == "" { // ❌ Remove this check
return fmt.Errorf("valueMappings.activate is required")
}
return nil
}
// Proposed validation (relaxed)
func (r *LynqHub) validateValueMappings() error {
if r.Spec.ValueMappings.UID == "" {
return fmt.Errorf("valueMappings.uid is required")
}
// ✅ activate is now optional - no validation error if missing
return nil
}
Controller Changes
Location: internal/controller/lynqhub_controller.go
// Current behavior (requires activate column)
func (r *LynqHubReconciler) filterActiveRows(rows []Row, activateCol string) []Row {
var active []Row
for _, row := range rows {
if isActiveTruthy(row[activateCol]) { // ❌ Fails if activateCol is empty
active = append(active, row)
}
}
return active
}
// Proposed behavior (activate column optional)
func (r *LynqHubReconciler) filterActiveRows(rows []Row, activateCol string) []Row {
// ✅ If no activate column specified, all rows are active
if activateCol == "" {
return rows // All rows treated as active
}
// Existing logic when activate column is specified
var active []Row
for _, row := range rows {
if isActiveTruthy(row[activateCol]) {
active = append(active, row)
}
}
return active
}
Template Variable Changes
Location: internal/template/engine.go
// Current behavior (activate always present)
func BuildVariables(uid, activate string, extraMappings map[string]string) Variables {
vars := Variables{
"uid": uid,
"activate": activate, // ❌ May be empty string if not mapped
}
// ...
}
// Proposed behavior (activate defaults to "true" if not mapped)
func BuildVariables(uid, activate string, extraMappings map[string]string) Variables {
vars := Variables{
"uid": uid,
}
// ✅ Only add activate variable if it was explicitly mapped
if activate != "" {
vars["activate"] = activate
} else {
vars["activate"] = "true" // Default to active if not specified
}
// ...
}
Backward Compatibility
This change is 100% backward compatible:
| Scenario |
Current Behavior |
New Behavior |
Compatible? |
activate specified, column exists |
Rows filtered by column value |
Same |
✅ Yes |
activate specified, column missing |
Query error |
Query error (same) |
✅ Yes |
activate not specified |
Validation error |
All rows treated as active |
✅ Yes (new feature) |
Migration path:
- Existing LynqHub CRs with
activate mapping → No changes needed, works as-is
- New LynqHub CRs without
activate mapping → Automatically treats all rows as active
Benefits
✅ Simpler setup: No need for activation columns in simple use cases
✅ Backward compatible: Existing configurations unchanged
✅ Database flexibility: Works with existing tables without schema modifications
✅ Reduced boilerplate: Less YAML to write for common scenarios
✅ Clearer intent: Explicit activation column = "I need control", no column = "always on"
Edge Cases
- Empty activate column value: Treated as inactive (existing behavior preserved)
- Activate column with NULL values: Treated as inactive (existing behavior preserved)
- Mixed setup: Some hubs use activate, some don't - both work independently ✅
- Template variable
.activate: Always available, defaults to "true" when not mapped
Implementation Checklist
Additional Context
Related to:
- Original requirement tracking: All rows must have activation control
- User feedback: Many use cases don't need activation logic
Common patterns this enables:
- Static tenant lists (always active)
- Development/staging environments (no activation needed)
- Migration from external systems (gradual activation adoption)
- Read-only datasources (can't add activation columns)
Priority: Medium (quality-of-life improvement, not critical)
Estimated Effort: Small-Medium (2-3 days for full implementation + tests + docs)
Compatible Versions: v1.2.0 and later (requires minor version bump for new behavior)
Breaking Changes: None - fully backward compatible
Are you willing to contribute this feature?
Feature Description
Make the
activatecolumn invalueMappingsoptional instead of required. When not specified, all rows should be treated as active by default.Current Behavior
Currently, the
activatefield is required invalueMappings:Problems:
Proposed Behavior
Make
activateoptional with smart defaults:Logic
When
activateis specified:activateis truthy (true,"true",1,"1", etc.)When
activateis NOT specified:Use Cases
Use Case 1: Simple Multi-Tenant Setup
Use Case 2: Dev/Test Environments
Use Case 3: Gradual Migration (Backward Compatible)
Implementation Details
Validation Changes
Location:
api/v1/lynqhub_webhook.goController Changes
Location:
internal/controller/lynqhub_controller.goTemplate Variable Changes
Location:
internal/template/engine.goBackward Compatibility
This change is 100% backward compatible:
activatespecified, column existsactivatespecified, column missingactivatenot specifiedMigration path:
activatemapping → No changes needed, works as-isactivatemapping → Automatically treats all rows as activeBenefits
✅ Simpler setup: No need for activation columns in simple use cases
✅ Backward compatible: Existing configurations unchanged
✅ Database flexibility: Works with existing tables without schema modifications
✅ Reduced boilerplate: Less YAML to write for common scenarios
✅ Clearer intent: Explicit activation column = "I need control", no column = "always on"
Edge Cases
.activate: Always available, defaults to"true"when not mappedImplementation Checklist
api/v1/lynqhub_webhook.go:activatefieldinternal/controller/lynqhub_controller.go:filterActiveRows()to handle emptyactivateColinternal/template/engine.go:activatevariable when not mappeddocs/datasource.md: Document optionalactivatefielddocs/configuration.md: Add examples of both patternsdocs/templates.md: Document.activatevariable behaviorconfig/samples/:activate(all-active pattern)activate(selective activation)Additional Context
Related to:
Common patterns this enables:
Priority: Medium (quality-of-life improvement, not critical)
Estimated Effort: Small-Medium (2-3 days for full implementation + tests + docs)
Compatible Versions: v1.2.0 and later (requires minor version bump for new behavior)
Breaking Changes: None - fully backward compatible
Are you willing to contribute this feature?