From b1a112f96c05625c62402d3fb942c167fd349727 Mon Sep 17 00:00:00 2001 From: Petr Lebedev Date: Tue, 21 Oct 2025 16:08:44 +0300 Subject: [PATCH] fix(redisproxy): support classic ArgoCD applications without agent prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The redisproxy implementation strictly required all Redis keys to start with an agent name prefix in the format 'agentName_'. This worked for agent-managed applications but broke for classic ArgoCD applications (using token authentication) which generate Redis keys without any prefix. When a key without the prefix arrived at redisproxy, the extractAgentNameFromRedisCommandKey function would fail with 'unexpected lack of "_" namespace/name separator' error, causing PUB/SUB connections to drop and resource requests for classic applications to fail completely. ## Solution Modified extractAgentNameFromRedisCommandKey function to gracefully handle Redis keys without the agent prefix by: 1. Detecting keys without underscore separator in the namespace field 2. Returning empty string (instead of error) for non-agent-prefixed keys 3. This allows these keys to be routed to the principal Redis instead of failing The routing logic in handleConnectionMessageLoop already supports this via the 'if agentName != ""' check, which will forward local keys to principal Redis. ## Changes Made ### principal/redisproxy/redisproxy.go - Modified extractAgentNameFromRedisCommandKey() function - Changed error case for missing underscore to return empty string with debug log - Updated comments to clarify behavior for classic vs agent-managed applications ### principal/redisproxy/redisproxy_test.go - Updated test cases to reflect new behavior - Changed 'errorExpected: true' to 'errorExpected: false' for classic app keys - Updated test descriptions to clarify that keys without prefix are classic apps ## Testing ✅ All existing tests pass (21 tests in redisproxy package) ✅ Code compiles without errors ✅ Multi-platform Docker image builds successfully (linux/amd64 and linux/arm64) ## Impact - ✅ Agent-managed applications continue to work as before - ✅ Classic ArgoCD applications now work correctly - ✅ Mixed environments with both types of applications are now supported - ✅ No breaking changes to existing functionality ## Example Routing - Agent-managed key: 'app|managed-resources|agent-managed_my-app|1.8.3' → Routed to agent via gRPC - Classic app key: 'app|managed-resources|my-app|1.8.3' → Routed to principal Redis (control plane) Signed-off-by: Petr Lebedev --- .gitignore | 1 + principal/redisproxy/redisproxy.go | 7 ++++--- principal/redisproxy/redisproxy_test.go | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index ab795b26..98f67bf4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ vendor/ build/ __pycache__ site/ +local*.sh diff --git a/principal/redisproxy/redisproxy.go b/principal/redisproxy/redisproxy.go index c4fd74e8..adfd7821 100644 --- a/principal/redisproxy/redisproxy.go +++ b/principal/redisproxy/redisproxy.go @@ -814,10 +814,11 @@ func extractAgentNameFromRedisCommandKey(redisKey string, logCtx *logrus.Entry) namespaceAndName := splitByPipe[2] // It is not possible to create a namespace name containing a '_' value, so this is a correct delimiter + // If the namespace/name doesn't contain '_', it's a classic (non-agent-managed) application + // and should be forwarded to principal redis if !strings.Contains(namespaceAndName, "_") { - errMsg := fmt.Sprintf("unexpected lack of '_' namespace/name separate: '%s'", redisKey) - logCtx.Error(errMsg) - return "", fmt.Errorf("%s", errMsg) + logCtx.Debugf("Redis key without agent prefix detected: '%s'. Routing to principal redis.", redisKey) + return "", nil } // namespace is the agent name diff --git a/principal/redisproxy/redisproxy_test.go b/principal/redisproxy/redisproxy_test.go index 77edb7e9..a32dea86 100644 --- a/principal/redisproxy/redisproxy_test.go +++ b/principal/redisproxy/redisproxy_test.go @@ -51,16 +51,16 @@ func Test_extractAgentNameFromRedisCommandKey(t *testing.T) { errorExpected: false, }, { - name: "'app|managed-resources' with only namespace", + name: "'app|managed-resources' with only namespace (classic app without agent prefix)", key: "app|managed-resources|my-app|1.8.3", value: "", - errorExpected: true, + errorExpected: false, }, { - name: "'app|resources-tree' with only namespace", + name: "'app|resources-tree' with only namespace (classic app without agent prefix)", key: "app|resources-tree|my-app|1.8.3.gz", value: "", - errorExpected: true, + errorExpected: false, }, { name: "'app|resources-tree' with unexpected field format",