Skip to content

Conversation

@PcInfamy
Copy link
Collaborator

@PcInfamy PcInfamy commented Dec 29, 2025

Testing/Validation

I wrote some test scripts to validate both an internal DB and an external DB with this chart.

Testing script output:
=== LibreNMS Chart Complete Test Suite ===

This script will test both internal and external database configurations.

Select test mode:
  1) Test with internal database (default, bundled MySQL)
  2) Test with external database (separate MySQL deployment)
  3) Test both configurations
  4) Cleanup cluster and exit

Enter choice [1-4]: 3

Running comprehensive test suite...

=== Phase 1: Testing Internal Database Configuration ===

=== LibreNMS Chart Testing Script ===

[0/7] Preparing kind cluster...
Cluster 'librenms-test' already exists, cleaning resources...
Switched to context "kind-librenms-test".
Uninstalling existing helm releases...
release "external-mysql" uninstalled
release "test-librenms-ext" uninstalled
Cleaning up remaining resources...
pod "test-librenms-ext-frontend-7b8c457d6d-ck289" deleted
pod "test-librenms-ext-poller-0" deleted
pod "test-librenms-ext-poller-1" deleted
service "kubernetes" deleted
persistentvolumeclaim "data-test-librenms-mysql-0" deleted
persistentvolumeclaim "redis-data-test-librenms-ext-redis-master-0" deleted
persistentvolumeclaim "redis-data-test-librenms-redis-master-0" deleted
Waiting for cleanup to complete...
✓ Cluster cleaned

[1/7] Updating chart dependencies...
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 2 charts
Downloading redis from repo https://charts.bitnami.com/bitnami
Pulled: registry-1.docker.io/bitnamicharts/redis:24.0.0
Digest: sha256:37c82701781aa30de0dfe548416481fd27216751fcecfee1a68e8244ee2b9a3a
Downloading mysql from repo https://charts.bitnami.com/bitnami
Pulled: registry-1.docker.io/bitnamicharts/mysql:14.0.3
Digest: sha256:2bbaf66e43dad7edce1eb563e19bcabd83eb8c8f79549505ad1c48e3a0cbfbba
Deleting outdated charts
✓ Dependencies updated

[2/7] Skipping default values lint (requires appkey)
✓ Skipped

[3/7] Linting chart with CI test values...
==> Linting ./charts/librenms
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, 0 chart(s) failed
✓ Lint passed (CI test values)

[4/7] Rendering templates with CI test values...
✓ Templates rendered successfully

[5/7] Checking for existing release...
No existing release found

[6/7] Installing chart...
NAME: test-librenms
LAST DEPLOYED: Mon Dec 29 15:31:37 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
✓ Chart installed successfully

[7/7] Waiting for pods to be ready...
pod/test-librenms-mysql-0 condition met
pod/test-librenms-poller-0 condition met
pod/test-librenms-poller-1 condition met
pod/test-librenms-redis-master-0 condition met
✓ Pods are ready

=== Deployment Status ===
NAME: test-librenms
LAST DEPLOYED: Mon Dec 29 15:31:37 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

=== Pod Status ===
NAME                           READY   STATUS    RESTARTS   AGE
test-librenms-mysql-0          1/1     Running   0          6m36s
test-librenms-poller-0         1/1     Running   0          6m36s
test-librenms-poller-1         1/1     Running   0          5m46s
test-librenms-redis-master-0   1/1     Running   0          6m36s

=== Services ===
NAME                           TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)    AGE
test-librenms-mysql            ClusterIP   10.96.93.17    <none>        3306/TCP   6m37s
test-librenms-mysql-headless   ClusterIP   None           <none>        3306/TCP   6m37s
test-librenms-redis-headless   ClusterIP   None           <none>        6379/TCP   6m37s
test-librenms-redis-master     ClusterIP   10.96.78.139   <none>        6379/TCP   6m37s

=== Testing Complete ===

Next steps:
  - Check logs: kubectl logs -n default <pod-name>
  - Access cluster: kubectl config use-context kind-librenms-test
  - Cleanup: ./cleanup-cluster.sh

Port Forwarding:
Starting port-forward to LibreNMS frontend on http://localhost:8000
Press Ctrl+C to stop port-forwarding and exit

Forwarding from 127.0.0.1:8000 -> 8000
Forwarding from [::1]:8000 -> 8000
Handling connection for 8000
Handling connection for 8000
Handling connection for 8000
Handling connection for 8000
Handling connection for 8000
Handling connection for 8000
^C
Cluster remains running. Access it with:
  kubectl config use-context kind-librenms-test

✓ Internal database test completed

Press Enter to continue to external database test, or Ctrl+C to stop...


=== Phase 2: Testing External Database Configuration ===

=== LibreNMS Chart External Database Testing Script ===

[0/10] Preparing kind cluster...
Cluster 'librenms-test' already exists, using it...
Switched to context "kind-librenms-test".
✓ Using existing cluster

[1/10] Adding Bitnami Helm repository...
"bitnami" already exists with the same configuration, skipping
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
✓ Helm repositories updated

[2/10] Deploying external MySQL database...
Installing MySQL as external database...
NAME: external-mysql
LAST DEPLOYED: Mon Dec 29 15:40:24 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 14.0.3
APP VERSION: 9.4.0

⚠ WARNING: Since August 28th, 2025, only a limited subset of images/charts are available for free.
    Subscribe to Bitnami Secure Images to receive continued support and security updates.
    More info at https://bitnami.com and https://github.com/bitnami/containers/issues/83267

** Please be patient while the chart is being deployed **

Tip:

  Watch the deployment status using the command: kubectl get pods -w --namespace default

Services:

  echo Primary: external-mysql.default.svc.cluster.local:3306

Execute the following to get the administrator credentials:

  echo Username: root
  MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default external-mysql -o jsonpath="{.data.mysql-root-password}" | base64 -d)

To connect to your database:

  1. Run a pod that you can use as a client:

      kubectl run external-mysql-client --rm --tty -i --restart='Never' --image  docker.io/bitnamilegacy/mysql:9.4.0-debian-12-r1 --namespace default --env MYSQL_ROOT_PASSWORD=$MYSQL_ROOT_PASSWORD --command -- bash

  2. To connect to primary service (read/write):

      mysql -h external-mysql.default.svc.cluster.local -uroot -p"$MYSQL_ROOT_PASSWORD"






WARNING: There are "resources" sections in the chart not set. Using "resourcesPreset" is not recommended for production. For production installations, please set the following values according to your workload needs:
  - primary.resources
  - secondary.resources
+info https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/

⚠ SECURITY WARNING: Original containers have been substituted. This Helm chart was designed, tested, and validated on multiple platforms using a specific set of Bitnami and Tanzu Application Catalog containers. Substituting other containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.

Substituted images detected:
  - docker.io/bitnamilegacy/mysql:9.4.0-debian-12-r1

⚠ WARNING: Original containers have been substituted for unrecognized ones. Deploying this chart with non-standard containers is likely to cause degraded security and performance, broken chart features, and missing environment variables.

Unrecognized images:
  - docker.io/bitnamilegacy/mysql:9.4.0-debian-12-r1
✓ External MySQL deployed

[3/10] Creating database secret...
secret "librenms-mysql-external" deleted
secret/librenms-mysql-external created
✓ Database secret created

[4/10] Updating chart dependencies...
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 2 charts
Downloading redis from repo https://charts.bitnami.com/bitnami
Pulled: registry-1.docker.io/bitnamicharts/redis:24.0.0
Digest: sha256:37c82701781aa30de0dfe548416481fd27216751fcecfee1a68e8244ee2b9a3a
Downloading mysql from repo https://charts.bitnami.com/bitnami
Pulled: registry-1.docker.io/bitnamicharts/mysql:14.0.3
Digest: sha256:2bbaf66e43dad7edce1eb563e19bcabd83eb8c8f79549505ad1c48e3a0cbfbba
Deleting outdated charts
✓ Dependencies updated

[5/10] Linting chart with external database configuration...
==> Linting ./charts/librenms
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, 0 chart(s) failed
✓ Lint passed (external DB)

[6/10] Rendering templates with external database...
Verifying external DB configuration...
  ✓ DB_HOST configured correctly
  ✓ DB_PORT configured correctly
  ✓ DB_USERNAME configured correctly
  ✓ DB_DATABASE configured correctly
  ✓ External secret reference configured correctly
✓ Templates rendered successfully

[7/10] Checking for existing release...
No existing release found

[8/10] Installing chart with external database...
NAME: test-librenms-ext
LAST DEPLOYED: Mon Dec 29 15:41:32 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
✓ Chart installed successfully with external database

[9/10] Verifying external database connection...
Checking if LibreNMS can connect to external MySQL...
Testing database connection from pod: test-librenms-ext-frontend-7b8c457d6d-xkjlm
  Checking environment variables...
Defaulted container "librenms" out of: librenms, init (init)
DB_USERNAME=librenms
DB_HOST=external-mysql.default.svc.cluster.local
DB_PORT=3306
DB_DATABASE=librenms
✓ Database connection verified

[10/10] Waiting for pods to be ready...
pod/test-librenms-ext-frontend-7b8c457d6d-xkjlm condition met
pod/test-librenms-ext-poller-0 condition met
pod/test-librenms-ext-poller-1 condition met
pod/test-librenms-ext-rrdcached-78b589d457-fqdvg condition met
✓ Pods are ready

=== Deployment Status ===
NAME: test-librenms-ext
LAST DEPLOYED: Mon Dec 29 15:41:32 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

=== Pod Status ===
NAME                                           READY   STATUS    RESTARTS   AGE
external-mysql-0                               1/1     Running   0          7m13s
test-librenms-ext-frontend-7b8c457d6d-xkjlm    1/1     Running   0          6m4s
test-librenms-ext-poller-0                     1/1     Running   0          6m4s
test-librenms-ext-poller-1                     1/1     Running   0          5m23s
test-librenms-ext-redis-master-0               1/1     Running   0          6m4s
test-librenms-ext-rrdcached-78b589d457-fqdvg   1/1     Running   0          6m4s
test-librenms-frontend-746c4df755-5zrqk        1/1     Running   0          15m
test-librenms-mysql-0                          1/1     Running   0          15m
test-librenms-poller-0                         1/1     Running   0          15m
test-librenms-poller-1                         1/1     Running   0          15m
test-librenms-redis-master-0                   1/1     Running   0          15m
test-librenms-rrdcached-786d4c8446-kwmp8       1/1     Running   0          15m

=== Services ===
NAME                                   TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)     AGE
external-mysql                         ClusterIP   10.96.176.112   <none>        3306/TCP    7m13s
external-mysql-headless                ClusterIP   None            <none>        3306/TCP    7m13s
kubernetes                             ClusterIP   10.96.0.1       <none>        443/TCP     16m
test-librenms                          ClusterIP   10.96.203.34    <none>        8000/TCP    15m
test-librenms-ext                      ClusterIP   10.96.136.24    <none>        8000/TCP    6m4s
test-librenms-ext-redis-headless       ClusterIP   None            <none>        6379/TCP    6m4s
test-librenms-ext-redis-master         ClusterIP   10.96.204.181   <none>        6379/TCP    6m4s
test-librenms-ext-rrdcached            ClusterIP   10.96.39.94     <none>        42217/TCP   6m4s
test-librenms-ext-rrdcached-headless   ClusterIP   None            <none>        42217/TCP   6m4s
test-librenms-mysql                    ClusterIP   10.96.93.17     <none>        3306/TCP    15m
test-librenms-mysql-headless           ClusterIP   None            <none>        3306/TCP    15m
test-librenms-redis-headless           ClusterIP   None            <none>        6379/TCP    15m
test-librenms-redis-master             ClusterIP   10.96.78.139    <none>        6379/TCP    15m
test-librenms-rrdcached                ClusterIP   10.96.24.51     <none>        42217/TCP   15m
test-librenms-rrdcached-headless       ClusterIP   None            <none>        42217/TCP   15m

=== External Database ===
MySQL Release: external-mysql
MySQL Service: external-mysql.default.svc.cluster.local:3306
Database: librenms
Username: librenms
Password: librenms123 (from secret: librenms-mysql-external)

=== Testing Complete ===

External Database Testing Completed Successfully!

Next steps:
  - Check logs: kubectl logs -n default <pod-name>
  - Access cluster: kubectl config use-context kind-librenms-test
  - Verify MySQL: kubectl exec -it external-mysql-0 -- mysql -ulibrenms -plibrenms123 librenms
  - Cleanup: ./cleanup-cluster.sh

Port Forwarding:
Starting port-forward to LibreNMS frontend on http://localhost:8001
Press Ctrl+C to stop port-forwarding and exit

Forwarding from 127.0.0.1:8001 -> 8000
Forwarding from [::1]:8001 -> 8000
Handling connection for 8001
Handling connection for 8001
Handling connection for 8001
Handling connection for 8001
Handling connection for 8001
Handling connection for 8001
^C
Cluster remains running. Access it with:
  kubectl config use-context kind-librenms-test

=== All Tests Completed Successfully ===

Add support for external MySQL/MariaDB databases with the following changes:
- Add database.mode setting to switch between internal and external modes
- Add database.external section with host, port, name, user, password, timeout
- Support existingSecret for secure credential management
- Add JSON schema validation for database configuration

This allows users to use existing database instances instead of the bundled MySQL.
Add 7 new helper functions to abstract database configuration:
- librenms.dbHost: Returns database hostname (strips port if included)
- librenms.dbPort: Returns database port (extracts from host string if needed)
- librenms.dbName: Returns database name
- librenms.dbUser: Returns database username
- librenms.dbTimeout: Returns connection timeout with default
- librenms.dbPasswordEnv: Renders password from literal or secret
- librenms.validateExternalDB: Validates required external DB parameters

Helpers support both internal (bundled MySQL) and external database modes.
Replace hardcoded MySQL values with helper function calls:
- DB_HOST: Now rendered without port for proper mariadb client usage
- DB_PORT: Added as separate environment variable
- DB_USERNAME: Uses dbUser helper
- DB_DATABASE: Uses dbName helper

This ensures database configuration is correctly injected regardless of
internal or external database mode.
Update deployment, cron, and poller StatefulSet templates:
- Use dbPasswordEnv helper for secure password injection
- Fix poller readiness probe to use separate host/port parameters
- Ensure all workloads properly reference configmap for DB settings

These changes enable external database connectivity across all LibreNMS
components while maintaining backward compatibility with internal mode.
@PcInfamy PcInfamy self-assigned this Dec 29, 2025
@PcInfamy PcInfamy requested a review from jacobw December 29, 2025 21:58
@PcInfamy PcInfamy marked this pull request as ready for review December 29, 2025 21:58
Add extensive documentation to README template covering:
- Internal vs external database mode selection
- External database configuration examples
- Flexible connection string formats (host:port or separate port)
- Kubernetes secret integration for credentials
- Database pre-requisites and requirements
- Example kubectl commands for secret creation

Documentation is clear and production-ready.
Regenerate README.md from updated template using helm-docs.
Includes comprehensive external database configuration guide
with examples, prerequisites, and best practices.
@PcInfamy PcInfamy force-pushed the external-db-support branch from 2ec2f32 to f0c6d69 Compare December 29, 2025 22:14
Copy link
Collaborator

@jacobw jacobw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great PR! Couple of small comments.

Comment on lines +38 to +39
# -- Database configuration for LibreNMS
database:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider merging the existing mysql section so all database configuration was under on e section, possibly as external and internal?

Comment on lines +85 to +88
{{- if contains ":" $host -}}
{{- $host | splitList ":" | first -}}
{{- else -}}
{{- $host -}}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values description didn't say you could define host:port. Was it your intention to support both formats? This sounds maybe unnecessary given you'd only really set this once.

Copy link
Collaborator

@jacobw jacobw Jan 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I see you adding this in the README, but not in the values.yaml comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants