API Reference
Complete API reference for Lynq CRDs.
LynqHub
Defines external data source and sync configuration.
Resource metadata
- Kind:
LynqHub - API Version:
operator.lynq.sh/v1
Spec
apiVersion: operator.lynq.sh/v1
kind: LynqHub
metadata:
name: my-hub
spec:
# Data source configuration
source:
type: mysql # mysql (postgresql planned for v1.2)
mysql:
host: string # Database host (required)
port: int # Database port (default: 3306)
username: string # Database username (required)
passwordRef: # Password secret reference (required)
name: string # Secret name
key: string # Secret key
database: string # Database name (required)
table: string # Table name (required)
syncInterval: duration # Sync interval (required, e.g., "1m")
# Required column mappings
valueMappings:
uid: string # Node ID column (required)
hostOrUrl: string # Node URL column (required)
activate: string # Activation flag column (required)
# Optional column mappings
extraValueMappings:
key: value # Additional column mappings (optional)Status
status:
observedGeneration: int64 # Last observed generation
referencingTemplates: int32 # Number of templates referencing this hub
desired: int32 # Desired LynqNode CRs (templates × rows)
ready: int32 # Ready LynqNode CRs
failed: int32 # Failed LynqNode CRs
conditions: # Status conditions
- type: Ready
status: "True"
reason: SyncSucceeded
message: "Successfully synced N nodes"
lastTransitionTime: timestampLynqForm
Defines resource blueprint for nodes.
Resource metadata
- Kind:
LynqForm - API Version:
operator.lynq.sh/v1
Spec
apiVersion: operator.lynq.sh/v1
kind: LynqForm
metadata:
name: my-template
spec:
hubId: string # LynqHub name (required)
# Resource arrays
serviceAccounts: []TResource
deployments: []TResource
statefulSets: []TResource
daemonSets: []TResource
services: []TResource
configMaps: []TResource
secrets: []TResource
persistentVolumeClaims: []TResource
jobs: []TResource
cronJobs: []TResource
ingresses: []TResource
podDisruptionBudgets: []TResource # PodDisruptionBudget resources
networkPolicies: []TResource # NetworkPolicy resources
horizontalPodAutoscalers: []TResource # HorizontalPodAutoscaler resources
manifests: []TResource # Raw unstructured resourcesTResource Structure
id: string # Unique resource ID (required)
nameTemplate: string # Go template for resource name (required)
labelsTemplate: # Template-enabled labels (optional)
key: value
annotationsTemplate: # Template-enabled annotations (optional)
key: value
dependIds: []string # Dependency IDs (optional)
creationPolicy: string # Once | WhenNeeded (default: WhenNeeded)
deletionPolicy: string # Delete | Retain (default: Delete)
conflictPolicy: string # Stuck | Force (default: Stuck)
patchStrategy: string # apply | merge | replace (default: apply)
waitForReady: bool # Wait for resource ready (default: true)
timeoutSeconds: int32 # Readiness timeout (default: 300, max: 3600)
spec: object # Kubernetes resource spec (required)Status
status:
observedGeneration: int64
validationErrors: []string # Template validation errors
totalNodes: int32 # Total nodes using this template
readyNodes: int32 # Ready nodes
conditions:
- type: Valid
status: "True"
reason: ValidationSucceededLynqNode
Represents a single node instance.
Resource metadata
- Kind:
LynqNode - API Version:
operator.lynq.sh/v1
Managed resource
LynqNode objects are typically managed by the operator and rarely created manually.
Spec
apiVersion: operator.lynq.sh/v1
kind: LynqNode
metadata:
name: acme-prod-template
annotations:
# Template variables (set by Hub controller)
lynq.sh/uid: "acme-corp"
lynq.sh/host: "acme.example.com"
lynq.sh/hostOrUrl: "https://acme.example.com"
lynq.sh/activate: "true"
# Extra variables from extraValueMappings
lynq.sh/planId: "enterprise"
spec:
hubId: string # Registry name
templateRef: string # Template name
# Rendered resources (already evaluated)
deployments: []TResource
# ... (same structure as LynqForm)Status
status:
observedGeneration: int64
desiredResources: int32 # Total resources
readyResources: int32 # Ready resources
failedResources: int32 # Failed resources
appliedResources: []string # Tracked resource keys for orphan detection
# Format: "kind/namespace/name@id"
# Example: ["Deployment/default/app@deploy-1", "Service/default/app@svc-1"]
conditions:
- type: Ready
status: "True"
reason: Reconciled
message: "Successfully reconciled all resources"
lastTransitionTime: timestamp
- type: Progressing
status: "False"
reason: ReconcileComplete
- type: Conflicted
status: "False"
reason: NoConflicts
- type: Degraded
status: "False"
reason: Healthy
message: "All resources are healthy"Condition Types
Ready Condition
Indicates whether the node is fully reconciled and all resources are ready.
Status Values:
True: All resources successfully reconciled and readyFalse: Not all resources are ready or some have failed
Possible Reasons (when status=False):
ResourcesFailedAndConflicted: Both failed and conflicted resources exist (highest priority)ResourcesConflicted: One or more resources in conflict stateResourcesFailed: One or more resources failed during reconciliationNotAllResourcesReady: Resources exist but haven't reached ready state yet
New in v1.1.4
The Ready condition now provides granular reasons to help quickly identify the root cause of failures. Conflict-related reasons are prioritized for better visibility.
Progressing Condition
Indicates whether reconciliation is currently in progress.
Status Values:
True: Reconciliation is actively applying changesFalse: Reconciliation completed
Degraded Condition
New in v1.1.4
The Degraded condition provides visibility into node health issues separate from the Ready condition.
Indicates when a node is not functioning optimally, even if reconciliation has completed.
Status Values:
True: Node has health issuesFalse: Node is healthy
Possible Reasons (when status=True):
ResourceFailuresAndConflicts: Node has both failed and conflicted resourcesResourceFailures: Node has failed resourcesResourceConflicts: Node has conflicted resourcesResourcesNotReady: Not all resources have reached ready state (new in v1.1.4)
Conflicted Condition
Indicates whether any resources have ownership conflicts.
Status Values:
True: One or more resources are in conflictFalse: No conflicts detected
## Field Types
### Duration
String with unit suffix:
- `s`: seconds
- `m`: minutes
- `h`: hours
Examples: `30s`, `1m`, `2h`
### CreationPolicy
- `Once`: Create once, never update
- `WhenNeeded`: Create and update as needed (default)
### DeletionPolicy
- `Delete`: Delete resource on LynqNode deletion (default) - uses ownerReference for automatic cleanup
- `Retain`: Keep resource on deletion - uses label-based tracking only (NO ownerReference set at creation)
### ConflictPolicy
- `Stuck`: Stop on ownership conflict (default)
- `Force`: Take ownership forcefully
### PatchStrategy
- `apply`: Server-Side Apply (default)
- `merge`: Strategic Merge Patch
- `replace`: Full replacement
## Annotations
### Node Annotations (auto-generated)
```yaml
# Template variables
lynq.sh/uid: string
lynq.sh/host: string
lynq.sh/hostOrUrl: string
lynq.sh/activate: string
# Extra variables from extraValueMappings
lynq.sh/<key>: value
# CreationPolicy tracking
lynq.sh/created-once: "true"Resource Tracking Labels
Label-based tracking is used instead of ownerReferences for:
- Cross-namespace resources (ownerReferences don't work across namespaces)
- Namespace resources (cannot have ownerReferences)
- DeletionPolicy=Retain resources (to prevent automatic garbage collection)
# Tracking labels (set at resource creation)
lynq.sh/node: node-name
lynq.sh/node-namespace: node-namespace
# Orphan label (added when resource becomes orphaned - for selector queries)
lynq.sh/orphaned: "true"Orphan Markers:
When resources are retained (not deleted) due to DeletionPolicy=Retain, the operator adds:
- Label
orphaned: "true"- For easy filtering with label selectors - Annotation
orphaned-at- RFC3339 timestamp when the resource became orphaned - Annotation
orphaned-reason- Reason for becoming orphaned:RemovedFromTemplate: Resource was removed from LynqFormLynqNodeDeleted: LynqNode CR was deleted
Why split label/annotation?
- Label: Simple value for selector queries (Kubernetes label values must be RFC 1123 compliant)
- Annotations: Detailed metadata like timestamps (no value restrictions)
Orphan Marker Lifecycle:
- Resource removed from template → Orphan markers added (label + annotations)
- Resource re-added to template → Orphan markers automatically removed during apply
- No manual cleanup needed → Operator manages the full lifecycle
This enables safe template evolution: you can freely add/remove resources from templates, and previously orphaned resources will be cleanly re-adopted if you add them back.
Finding orphaned resources:
# Find all orphaned resources
kubectl get all -A -l lynq.sh/orphaned=true
# Find orphaned resources by reason (using annotation)
kubectl get all -A -l lynq.sh/orphaned=true -o jsonpath='{range .items[?(@.metadata.annotations.k8s-lynq\.org/orphaned-reason=="RemovedFromTemplate")]}{.kind}/{.metadata.name}{"\n"}{end}'
# Find orphaned resources from a specific node (label still available)
kubectl get all -A -l lynq.sh/orphaned=true,lynq.sh/lynqnode=my-nodeResource Annotations
DeletionPolicy Annotation:
The operator automatically adds a deletion-policy annotation to all created resources:
metadata:
annotations:
lynq.sh/deletion-policy: "Retain" # or "Delete"Purpose:
- Critical for orphan cleanup: When resources are removed from templates, they no longer exist in the template spec
- The annotation is the only source of truth for determining the correct cleanup behavior
- Without this annotation, all orphaned resources would default to
Deletepolicy
Behavior:
- Set automatically during resource creation by
renderResourcefunction - Read during orphan cleanup in
deleteOrphanedResourcefunction - Falls back to
Deleteif annotation is missing (defensive default)
Example query:
# Find all Retain resources
kubectl get all -A -o jsonpath='{range .items[?(@.metadata.annotations.k8s-lynq\.org/deletion-policy=="Retain")]}{.kind}/{.metadata.name}{"\n"}{end}'Examples
See Templates Guide and Quick Start Guide for complete examples.
Validation Rules
LynqHub
spec.valueMappingsmust include:uid,hostOrUrl,activatespec.source.syncIntervalmust match pattern:^\d+(s|m|h)$spec.source.mysql.hostrequired whentype=mysql
LynqForm
spec.hubIdmust reference existing LynqHub- Each
TResource.idmust be unique within template dependIdsmust not form cycles- Templates must be valid Go templates
LynqNode
- Typically validated by operator, not manually created
- All referenced resources must exist
See Also
- Template Guide - Template syntax and functions
- Policies Guide - Policy options
- Dependencies Guide - Resource ordering
