Skip to content
GitHub stars

Datasource Configuration ​

LynqHub polls your database at a configured interval, reads active rows, and reconciles the corresponding LynqNode CRs. This page covers connecting to MySQL, mapping columns to template variables, and handling common schema shapes.

Supported Datasources ​

DatasourceStatusSince
MySQLStablev1.0
PostgreSQLPlannedv1.2
CustomContribute—

MySQL Connection ​

yaml
apiVersion: operator.lynq.sh/v1
kind: LynqHub
metadata:
  name: my-hub
  namespace: lynq-system
spec:
  source:
    type: mysql
    mysql:
      host: mysql.default.svc.cluster.local
      port: 3306
      username: node_reader
      passwordRef:
        name: mysql-credentials
        key: password
      database: nodes
      table: node_configs
    syncInterval: 1m
FieldDescriptionDefault
hostMySQL hostname or IP—
portMySQL port3306
usernameDatabase user (use read-only)—
passwordRefSecret containing the password—
databaseDatabase name—
tableTable or view name—
syncIntervalPoll frequency (30s, 1m, 5m)30s

Kubernetes Secret:

yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysql-credentials
  namespace: lynq-system
type: Opaque
stringData:
  password: your-password-here

Column Mappings ​

Required ​

Every LynqHub needs exactly two required mappings:

yaml
valueMappings:
  uid: node_id       # unique node identifier
  activate: is_active  # activation flag

uid — Unique string identifier per row. Used in resource naming and labels.

activate — Controls whether a row is provisioned. Accepted truthy values: 1, true, TRUE, True, yes, YES, Yes. Everything else (including NULL) is treated as inactive.

Extra Mappings ​

Any additional columns can be mapped to template variables:

yaml
extraValueMappings:
  planId: subscription_plan   # column → template variable
  region: deployment_region
  maxUsers: max_user_count

These become available in all templates as {{ .planId }}, {{ .region }}, etc.

Schema Examples ​

Simple table ​

sql
CREATE TABLE node_configs (
    node_id         VARCHAR(255) PRIMARY KEY,
    is_active       TINYINT(1)  DEFAULT 0,
    subscription_plan VARCHAR(50),
    deployment_region VARCHAR(50)
);
yaml
valueMappings:
  uid: node_id
  activate: is_active
extraValueMappings:
  planId: subscription_plan
  region: deployment_region

TINYINT activate column ​

MySQL TINYINT(1) returns the string "1" or "0" when queried — both are valid activate values.

sql
CREATE TABLE nodes (
    id      VARCHAR(255) PRIMARY KEY,
    enabled TINYINT(1) DEFAULT 0
);
yaml
valueMappings:
  uid: id
  activate: enabled  # "1" = active, "0" = inactive

Status string (requires a VIEW) ​

If your activate column holds strings like "active" / "inactive", those aren't directly valid. Create a MySQL VIEW to transform them:

sql
CREATE VIEW node_configs AS
SELECT
    id           AS node_id,
    CASE status
        WHEN 'active' THEN '1'
        ELSE '0'
    END          AS is_active,
    plan         AS subscription_plan
FROM nodes;

Then point the hub at the view name instead of the raw table. See Datasource Views for more VIEW patterns.

Best Practices ​

Use a read-only database user. Lynq only needs SELECT on the target table/view.

sql
CREATE USER 'node_reader'@'%' IDENTIFIED BY 'secure_password';
GRANT SELECT ON nodes.node_configs TO 'node_reader'@'%';
FLUSH PRIVILEGES;

Use a VIEW to isolate sensitive columns. Grant SELECT only on the view, not the underlying table.

Index the activate column for faster filtering at scale:

sql
CREATE INDEX idx_active ON nodes(is_active);

Set syncInterval based on scale:

yaml
syncInterval: 30s  # development
syncInterval: 1m   # production (recommended)
syncInterval: 5m   # large deployments (1000+ nodes)

Troubleshooting ​

Nodes not created — check activate values:

sql
SELECT node_id, is_active FROM node_configs
WHERE is_active NOT IN ('0', '1', 'true', 'false', 'yes', 'no', 'TRUE', 'FALSE');
-- Any rows here have invalid activate values

Check operator logs for sync errors:

bash
kubectl logs -n lynq-system -l control-plane=controller-manager | grep -i "hub\|sync\|query"

Connection errors — test from inside the cluster:

bash
kubectl run mysql-test --rm -it --image=mysql:8 -- \
  mysql -h mysql.default.svc.cluster.local -u node_reader -p

Verify the Secret:

bash
kubectl get secret mysql-credentials -n lynq-system -o jsonpath='{.data.password}' | base64 -d

Caveats ​

hostOrUrl mapping is deprecated (since v1.1.11, removed in v1.3.0). If your hub currently uses it:

yaml
# Deprecated
valueMappings:
  hostOrUrl: node_url

# Migrate to:
extraValueMappings:
  nodeUrl: node_url
# Then use {{ .nodeUrl | toHost }} in templates instead of {{ .host }}

See Also ​