From ddb0bc9c3d57e92bb7b4b220d9f513360676103a Mon Sep 17 00:00:00 2001 From: Benjamin Reed Date: Fri, 21 Nov 2025 11:43:06 -0500 Subject: [PATCH 1/3] feat(redis): add support for specifying username --- diode-server/cmd/ingester/main.go | 8 ++++++-- diode-server/cmd/reconciler/main.go | 16 ++++++++++++---- diode-server/ingester/config.go | 1 + diode-server/reconciler/config.go | 1 + diode-server/reconciler/server.go | 8 ++++++-- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/diode-server/cmd/ingester/main.go b/diode-server/cmd/ingester/main.go index 0817482d..b4672039 100644 --- a/diode-server/cmd/ingester/main.go +++ b/diode-server/cmd/ingester/main.go @@ -68,12 +68,16 @@ func main() { os.Exit(1) } - redisStreamClient := redis.NewClient(&redis.Options{ + redisOptions := redis.Options{ Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort), Password: cfg.RedisPassword, DB: cfg.RedisStreamDB, TLSConfig: redisTLSConfig, - }) + } + if cfg.RedisUsername != "" { + redisOptions.Username = cfg.RedisUsername + } + redisStreamClient := redis.NewClient(&redisOptions) if _, err := redisStreamClient.Ping(ctx).Result(); err != nil { s.Logger().Error("failed to connect to redis stream", "redisStream", redisStreamClient.String(), "error", err) diff --git a/diode-server/cmd/reconciler/main.go b/diode-server/cmd/reconciler/main.go index 109d8dbd..1cd3ce49 100644 --- a/diode-server/cmd/reconciler/main.go +++ b/diode-server/cmd/reconciler/main.go @@ -84,12 +84,16 @@ func main() { os.Exit(1) } - redisClient := redis.NewClient(&redis.Options{ + redisOptions := redis.Options{ Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort), Password: cfg.RedisPassword, DB: cfg.RedisDB, TLSConfig: redisTLSConfig, - }) + } + if cfg.RedisUsername != "" { + redisOptions.Username = cfg.RedisUsername + } + redisClient := redis.NewClient(&redisOptions) if _, err := redisClient.Ping(ctx).Result(); err != nil { s.Logger().Error("failed to connect to redis", "redis", redisClient.String(), "error", err) @@ -97,12 +101,16 @@ func main() { os.Exit(1) } - redisStreamClient := redis.NewClient(&redis.Options{ + redisStreamOptions := redis.Options{ Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort), Password: cfg.RedisPassword, DB: cfg.RedisStreamDB, TLSConfig: redisTLSConfig, - }) + } + if cfg.RedisUsername != "" { + redisStreamOptions.Username = cfg.RedisUsername + } + redisStreamClient := redis.NewClient(&redisStreamOptions) if _, err := redisStreamClient.Ping(ctx).Result(); err != nil { s.Logger().Error("failed to connect to redis stream", "redisStream", redisStreamClient.String(), "error", err) diff --git a/diode-server/ingester/config.go b/diode-server/ingester/config.go index ef716e00..403cbbd3 100644 --- a/diode-server/ingester/config.go +++ b/diode-server/ingester/config.go @@ -10,6 +10,7 @@ type Config struct { GRPCPort int `envconfig:"GRPC_PORT" default:"8081"` RedisHost string `envconfig:"REDIS_HOST" default:"127.0.0.1"` RedisPort string `envconfig:"REDIS_PORT" default:"6379"` + RedisUsername string `envconfig:"REDIS_USERNAME" default:""` RedisPassword string `envconfig:"REDIS_PASSWORD" required:"true"` RedisStreamDB int `envconfig:"REDIS_STREAM_DB" default:"1"` diff --git a/diode-server/reconciler/config.go b/diode-server/reconciler/config.go index 6ddd8c35..541e5eb3 100644 --- a/diode-server/reconciler/config.go +++ b/diode-server/reconciler/config.go @@ -10,6 +10,7 @@ type Config struct { GRPCPort int `envconfig:"GRPC_PORT" default:"8081"` RedisHost string `envconfig:"REDIS_HOST" default:"127.0.0.1"` RedisPort string `envconfig:"REDIS_PORT" default:"6379"` + RedisUsername string `envconfig:"REDIS_USERNAME" default:""` RedisPassword string `envconfig:"REDIS_PASSWORD" required:"true"` RedisDB int `envconfig:"REDIS_DB" default:"0"` RedisStreamDB int `envconfig:"REDIS_STREAM_DB" default:"1"` diff --git a/diode-server/reconciler/server.go b/diode-server/reconciler/server.go index d9437ba3..279624cf 100644 --- a/diode-server/reconciler/server.go +++ b/diode-server/reconciler/server.go @@ -37,12 +37,16 @@ func NewServer(ctx context.Context, logger *slog.Logger, repository Repository, return nil, fmt.Errorf("failed to create TLS config for Redis: %v", err) } - redisClient := redis.NewClient(&redis.Options{ + redisOptions := redis.Options{ Addr: fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort), Password: cfg.RedisPassword, DB: cfg.RedisDB, TLSConfig: redisTLSConfig, - }) + } + if cfg.RedisUsername != "" { + redisOptions.Username = cfg.RedisUsername + } + redisClient := redis.NewClient(&redisOptions) if _, err := redisClient.Ping(ctx).Result(); err != nil { return nil, fmt.Errorf("failed connection to %s: %v", redisClient.String(), err) From 068b37153ffe2434dca53a5bbba176100ae598da Mon Sep 17 00:00:00 2001 From: Benjamin Reed Date: Fri, 21 Nov 2025 16:13:23 -0500 Subject: [PATCH 2/3] feat: update diode chart to support external redis username --- charts/diode/templates/_helpers.tpl | 13 +++++++++++++ .../diode/templates/diode-ingester-configmap.yaml | 1 + .../diode/templates/diode-reconciler-configmap.yaml | 1 + charts/diode/values.yaml | 2 ++ diode-server/docker/docker-compose.yaml | 2 ++ diode-server/docker/sample.env | 1 + diode-server/ingester/component_test.go | 2 ++ diode-server/reconciler/reconciler_test.go | 2 ++ 8 files changed, 24 insertions(+) diff --git a/charts/diode/templates/_helpers.tpl b/charts/diode/templates/_helpers.tpl index e1237f61..ff2c8d6a 100644 --- a/charts/diode/templates/_helpers.tpl +++ b/charts/diode/templates/_helpers.tpl @@ -291,6 +291,19 @@ Create the port of the Redis database {{- end }} {{- end }} +{{/* +Create the username of the Redis database +*/}} +{{- define "diode.redis.username" -}} +{{- if .Values.redis.enabled -}} +{{- printf "" }} +{{- else if and .Values.externalRedis (hasKey .Values.externalRedis "username") -}} +{{- .Values.externalRedis.username }} +{{- else -}} +{{- fail "externalRedis.username must be defined when redis.enabled is false" }} +{{- end }} +{{- end }} + {{/* Create the database name for PostgreSQL */}} diff --git a/charts/diode/templates/diode-ingester-configmap.yaml b/charts/diode/templates/diode-ingester-configmap.yaml index be13a5d9..77e9e92d 100644 --- a/charts/diode/templates/diode-ingester-configmap.yaml +++ b/charts/diode/templates/diode-ingester-configmap.yaml @@ -17,6 +17,7 @@ data: SENTRY_DSN: {{ $config.sentryDsn | quote }} REDIS_HOST: {{ include "diode.redis.hostname" . | quote }} REDIS_PORT: {{ include "diode.redis.port" . | quote }} + REDIS_USERNAME: {{ include "diode.redis.username" . | quote }} {{- if and .Values.externalRedis.tls .Values.externalRedis.tls.enabled }} REDIS_TLS_ENABLED: "true" REDIS_TLS_SKIP_VERIFY: {{ .Values.externalRedis.tls.skipVerify | default false | quote }} diff --git a/charts/diode/templates/diode-reconciler-configmap.yaml b/charts/diode/templates/diode-reconciler-configmap.yaml index fe911392..c6661453 100644 --- a/charts/diode/templates/diode-reconciler-configmap.yaml +++ b/charts/diode/templates/diode-reconciler-configmap.yaml @@ -17,6 +17,7 @@ data: SENTRY_DSN: {{ $config.sentryDsn | quote }} REDIS_HOST: {{ include "diode.redis.hostname" . | quote }} REDIS_PORT: {{ include "diode.redis.port" . | quote }} + REDIS_USERNAME: {{ include "diode.redis.username" . | quote }} REDIS_DB: {{ $config.redisDb | default "0" | quote }} REDIS_STREAM_DB: {{ $config.redisStreamDb | default "1" | quote }} {{- if and .Values.externalRedis.tls .Values.externalRedis.tls.enabled }} diff --git a/charts/diode/values.yaml b/charts/diode/values.yaml index 222268ca..1ed44424 100644 --- a/charts/diode/values.yaml +++ b/charts/diode/values.yaml @@ -57,6 +57,8 @@ externalRedis: hostname: localhost # -- port port: 6379 + # -- username (optional, Redis 6+) + username: "" tls: # -- enable TLS enabled: false diff --git a/diode-server/docker/docker-compose.yaml b/diode-server/docker/docker-compose.yaml index bd14df81..62d4a280 100644 --- a/diode-server/docker/docker-compose.yaml +++ b/diode-server/docker/docker-compose.yaml @@ -23,6 +23,7 @@ services: - REDIS_PASSWORD=${REDIS_PASSWORD} - REDIS_HOST=${REDIS_HOST} - REDIS_PORT=${REDIS_PORT} + - REDIS_USERNAME="" - SENTRY_DSN=${SENTRY_DSN} - TELEMETRY_METRICS_EXPORTER=${TELEMETRY_METRICS_EXPORTER} - TELEMETRY_TRACES_EXPORTER=${TELEMETRY_TRACES_EXPORTER} @@ -40,6 +41,7 @@ services: - REDIS_PASSWORD=${REDIS_PASSWORD} - REDIS_HOST=${REDIS_HOST} - REDIS_PORT=${REDIS_PORT} + - REDIS_USERNAME="" - NETBOX_DIODE_PLUGIN_API_BASE_URL=${NETBOX_DIODE_PLUGIN_API_BASE_URL} - NETBOX_DIODE_PLUGIN_SKIP_TLS_VERIFY=${NETBOX_DIODE_PLUGIN_SKIP_TLS_VERIFY} - LOGGING_LEVEL=${LOGGING_LEVEL} diff --git a/diode-server/docker/sample.env b/diode-server/docker/sample.env index 022d3f41..890436e3 100644 --- a/diode-server/docker/sample.env +++ b/diode-server/docker/sample.env @@ -2,6 +2,7 @@ DIODE_NGINX_PORT=8080 REDIS_PASSWORD= REDIS_HOST=redis REDIS_PORT=6378 +REDIS_USERNAME="" NETBOX_DIODE_PLUGIN_API_BASE_URL=/api/plugins/diode NETBOX_DIODE_PLUGIN_SKIP_TLS_VERIFY=false LOGGING_LEVEL=DEBUG diff --git a/diode-server/ingester/component_test.go b/diode-server/ingester/component_test.go index d1005ca9..3cdc4963 100644 --- a/diode-server/ingester/component_test.go +++ b/diode-server/ingester/component_test.go @@ -45,6 +45,7 @@ func setupEnv(redisAddr string) { _ = os.Setenv("GRPC_PORT", grpcPort) _ = os.Setenv("REDIS_HOST", host) _ = os.Setenv("REDIS_PORT", port) + _ = os.Setenv("REDIS_USERNAME", "") _ = os.Setenv("REDIS_PASSWORD", "") _ = os.Setenv("REDIS_DB", "0") _ = os.Setenv("REDIS_STREAM_DB", "1") @@ -59,6 +60,7 @@ func teardownEnv() { _ = os.Unsetenv("GRPC_PORT") _ = os.Unsetenv("REDIS_HOST") _ = os.Unsetenv("REDIS_PORT") + _ = os.Unsetenv("REDIS_USERNAME") _ = os.Unsetenv("REDIS_PASSWORD") _ = os.Unsetenv("REDIS_DB") _ = os.Unsetenv("REDIS_STREAM_DB") diff --git a/diode-server/reconciler/reconciler_test.go b/diode-server/reconciler/reconciler_test.go index 9d73f84c..dd8576c5 100644 --- a/diode-server/reconciler/reconciler_test.go +++ b/diode-server/reconciler/reconciler_test.go @@ -26,6 +26,7 @@ func setupEnv(redisAddr string) { _ = os.Setenv("GRPC_PORT", grpcPort) _ = os.Setenv("REDIS_HOST", host) _ = os.Setenv("REDIS_PORT", port) + _ = os.Setenv("REDIS_USERNAME", "") _ = os.Setenv("REDIS_PASSWORD", "") _ = os.Setenv("REDIS_DB", "0") _ = os.Setenv("REDIS_STREAM_DB", "1") @@ -49,6 +50,7 @@ func teardownEnv() { _ = os.Unsetenv("GRPC_PORT") _ = os.Unsetenv("REDIS_HOST") _ = os.Unsetenv("REDIS_PORT") + _ = os.Unsetenv("REDIS_USERNAME") _ = os.Unsetenv("REDIS_PASSWORD") _ = os.Unsetenv("REDIS_DB") _ = os.Unsetenv("REDIS_STREAM_DB") From ab5dc3ee134c4be20deb0d8cdfa095d824eb64ce Mon Sep 17 00:00:00 2001 From: Benjamin Reed Date: Fri, 21 Nov 2025 16:14:33 -0500 Subject: [PATCH 3/3] chore: update chart version and regen README --- charts/diode/Chart.yaml | 2 +- charts/diode/README.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/charts/diode/Chart.yaml b/charts/diode/Chart.yaml index 5246f168..46962ad5 100644 --- a/charts/diode/Chart.yaml +++ b/charts/diode/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: diode description: A Helm chart for Diode type: application -version: "1.9.1" +version: "1.10.0" appVersion: "1.5.0" home: https://github.com/netboxlabs/diode sources: diff --git a/charts/diode/README.md b/charts/diode/README.md index 40575ec2..12c9eff7 100644 --- a/charts/diode/README.md +++ b/charts/diode/README.md @@ -2,7 +2,7 @@ A Helm chart for Diode -![Version: 1.9.1](https://img.shields.io/badge/Version-1.9.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.5.0](https://img.shields.io/badge/AppVersion-1.5.0-informational?style=flat-square) +![Version: 1.10.0](https://img.shields.io/badge/Version-1.10.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.5.0](https://img.shields.io/badge/AppVersion-1.5.0-informational?style=flat-square) ## Prerequisites @@ -319,6 +319,7 @@ helm show values diode/diode | externalRedis.tls.clientKeyPath | string | `""` | path to client private key for mutual TLS | | externalRedis.tls.enabled | bool | `false` | enable TLS | | externalRedis.tls.skipVerify | bool | `false` | skip TLS verify | +| externalRedis.username | string | `""` | username (optional, Redis 6+) | | global.commonAnnotations | object | `{}` | common annotations for all resources | | global.commonLabels | object | `{}` | common labels for all resources | | global.diode | object | `{"busybox":{"image":"busybox:latest","imagePullPolicy":"IfNotPresent"},"hydra":{"waitForPostgres":true},"ingester":{"waitForRedis":true},"reconciler":{"waitForPostgres":true,"waitForRedis":true}}` | diode global configuration |