Skip to content

Commit c8217aa

Browse files
authored
fix: use prefixed AppProject name while handling resyncs (#666)
Signed-off-by: Chetan Banavikalmutt <[email protected]>
1 parent a510cea commit c8217aa

File tree

6 files changed

+505
-12
lines changed

6 files changed

+505
-12
lines changed

agent/inbound.go

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
package agent
1616

1717
import (
18+
"encoding/json"
1819
"fmt"
1920
"time"
2021

22+
"github.com/argoproj-labs/argocd-agent/internal/auth"
2123
"github.com/argoproj-labs/argocd-agent/internal/backend"
2224
"github.com/argoproj-labs/argocd-agent/internal/checkpoint"
2325
"github.com/argoproj-labs/argocd-agent/internal/event"
@@ -386,6 +388,13 @@ func (a *Agent) processIncomingResourceResyncEvent(ev *event.Event) error {
386388
}
387389

388390
resyncHandler := resync.NewRequestHandler(dynClient, sendQ, a.emitter, a.resources, logCtx, manager.ManagerRoleAgent, a.namespace)
391+
subject := &auth.AuthSubject{}
392+
err = json.Unmarshal([]byte(a.remote.ClientID()), subject)
393+
if err != nil {
394+
return fmt.Errorf("failed to extract agent name from client ID: %w", err)
395+
}
396+
397+
agentName := subject.ClientID
389398

390399
switch ev.Type() {
391400
case event.SyncedResourceList:
@@ -398,7 +407,7 @@ func (a *Agent) processIncomingResourceResyncEvent(ev *event.Event) error {
398407
return err
399408
}
400409

401-
return resyncHandler.ProcessSyncedResourceListRequest(a.remote.ClientID(), req)
410+
return resyncHandler.ProcessSyncedResourceListRequest(agentName, req)
402411
case event.ResponseSyncedResource:
403412
if a.mode != types.AgentModeManaged {
404413
return fmt.Errorf("agent can only handle SyncedResource request in the managed mode")
@@ -409,7 +418,7 @@ func (a *Agent) processIncomingResourceResyncEvent(ev *event.Event) error {
409418
return err
410419
}
411420

412-
return resyncHandler.ProcessIncomingSyncedResource(a.context, req, a.remote.ClientID())
421+
return resyncHandler.ProcessIncomingSyncedResource(a.context, req, agentName)
413422
case event.EventRequestUpdate:
414423
if a.mode != types.AgentModeAutonomous {
415424
return fmt.Errorf("agent can only handle RequestUpdate in the autonomous mode")
@@ -420,13 +429,23 @@ func (a *Agent) processIncomingResourceResyncEvent(ev *event.Event) error {
420429
return err
421430
}
422431

423-
return resyncHandler.ProcessRequestUpdateEvent(a.context, a.remote.ClientID(), incoming)
432+
// For autonomous agents, the principal stores AppProjects with a prefixed name (agent-name + "-" + project-name).
433+
// When the principal sends a RequestUpdate, it uses the prefixed name. We need to strip the prefix
434+
// before looking up the resource locally.
435+
if incoming.Kind == "AppProject" {
436+
prefix := agentName + "-"
437+
if len(incoming.Name) > len(prefix) && incoming.Name[:len(prefix)] == prefix {
438+
incoming.Name = incoming.Name[len(prefix):]
439+
}
440+
}
441+
442+
return resyncHandler.ProcessRequestUpdateEvent(a.context, agentName, incoming)
424443
case event.EventRequestResourceResync:
425444
if a.mode != types.AgentModeManaged {
426445
return fmt.Errorf("agent can only handle ResourceResync request in the managed mode")
427446
}
428447

429-
return resyncHandler.ProcessIncomingResourceResyncRequest(a.context, a.remote.ClientID())
448+
return resyncHandler.ProcessIncomingResourceResyncRequest(a.context, agentName)
430449
default:
431450
return fmt.Errorf("invalid type of resource resync: %s", ev.Type())
432451
}

agent/inbound_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package agent
1616

1717
import (
1818
"context"
19+
"encoding/json"
1920
"fmt"
2021
"testing"
2122

@@ -27,6 +28,7 @@ import (
2728
"k8s.io/apimachinery/pkg/runtime/schema"
2829
"k8s.io/client-go/rest"
2930

31+
"github.com/argoproj-labs/argocd-agent/internal/auth"
3032
backend_mocks "github.com/argoproj-labs/argocd-agent/internal/backend/mocks"
3133
"github.com/argoproj-labs/argocd-agent/internal/event"
3234
"github.com/argoproj-labs/argocd-agent/internal/manager"
@@ -1468,7 +1470,16 @@ func Test_processIncomingResourceResyncEvent(t *testing.T) {
14681470
a.namespace = "test"
14691471
a.context = context.Background()
14701472

1471-
err := a.queues.Create(a.remote.ClientID())
1473+
subject := &auth.AuthSubject{
1474+
ClientID: "test",
1475+
}
1476+
subjectJSON, err := json.Marshal(subject)
1477+
if err != nil {
1478+
t.Fatalf("Failed to marshal subject: %v", err)
1479+
}
1480+
a.remote.SetClientID(string(subjectJSON))
1481+
fmt.Println("a.remote.ClientID()", a.remote.ClientID())
1482+
err = a.queues.Create(a.remote.ClientID())
14721483
assert.Nil(t, err)
14731484
a.emitter = event.NewEventSource("test")
14741485

internal/resync/resync.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ func (r *RequestHandler) ProcessIncomingResourceResyncRequest(ctx context.Contex
156156
r.log.Errorf("failed to send request update for resource %s: %v", resource.Name, err)
157157
continue
158158
}
159+
r.log.WithField(logfields.Kind, resource.Kind).WithField(logfields.Name, resource.Name).Trace("Sent a request update event")
159160
}
160161

161162
return nil

principal/callbacks.go

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,14 +178,20 @@ func (s *Server) newAppProjectCallback(outbound *v1alpha1.AppProject) {
178178
"appproject_name": outbound.Name,
179179
})
180180

181-
s.resources.Add(outbound.Namespace, resources.NewResourceKeyFromAppProject(outbound))
182-
183181
// Check if this AppProject was created by an autonomous agent
184182
if isResourceFromAutonomousAgent(outbound) {
183+
// For autonomous agents, the agent name may be different from the namespace name.
184+
// SourceNamespaces[0] contains the exact agent name.
185+
if len(outbound.Spec.SourceNamespaces) > 0 {
186+
agentName := outbound.Spec.SourceNamespaces[0]
187+
s.resources.Add(agentName, resources.NewResourceKeyFromAppProject(outbound))
188+
}
185189
logCtx.Debugf("Discarding event, because the appProject is managed by an autonomous agent")
186190
return
187191
}
188192

193+
s.resources.Add(outbound.Namespace, resources.NewResourceKeyFromAppProject(outbound))
194+
189195
// Return early if no interested agent is connected
190196
if !s.queues.HasQueuePair(outbound.Namespace) {
191197
if err := s.queues.Create(outbound.Namespace); err != nil {
@@ -292,16 +298,19 @@ func (s *Server) deleteAppProjectCallback(outbound *v1alpha1.AppProject) {
292298
logCtx.Trace("Deleted appProject is recreated")
293299
return
294300
}
295-
}
296301

297-
s.resources.Remove(outbound.Namespace, resources.NewResourceKeyFromAppProject(outbound))
298-
299-
// Check if this AppProject was created by an autonomous agent by examining its name prefix
300-
if isResourceFromAutonomousAgent(outbound) {
302+
// For autonomous agents, the agent name may be different from the namespace name.
303+
// SourceNamespaces[0] contains the exact agent name.
304+
if len(outbound.Spec.SourceNamespaces) > 0 {
305+
agentName := outbound.Spec.SourceNamespaces[0]
306+
s.resources.Remove(agentName, resources.NewResourceKeyFromAppProject(outbound))
307+
}
301308
logCtx.Debugf("Discarding event, because the appProject is managed by an autonomous agent")
302309
return
303310
}
304311

312+
s.resources.Remove(outbound.Namespace, resources.NewResourceKeyFromAppProject(outbound))
313+
305314
if !s.queues.HasQueuePair(outbound.Namespace) {
306315
if err := s.queues.Create(outbound.Namespace); err != nil {
307316
logCtx.WithError(err).Error("failed to create a queue pair for an existing agent namespace")

principal/event.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,17 @@ func (s *Server) processIncomingResourceResyncEvent(ctx context.Context, agentNa
593593
return err
594594
}
595595

596+
// For autonomous agents, the agent sends RequestUpdate with the local AppProject name (e.g., "sample"),
597+
// but the principal stores it with a prefixed name (e.g., "agent-autonomous-sample").
598+
// We need to add the prefix before looking it up locally.
599+
if agentMode == types.AgentModeAutonomous && incoming.Kind == "AppProject" {
600+
prefixedName, err := agentPrefixedProjectName(incoming.Name, agentName)
601+
if err != nil {
602+
return fmt.Errorf("could not prefix project name: %w", err)
603+
}
604+
incoming.Name = prefixedName
605+
}
606+
596607
return resyncHandler.ProcessRequestUpdateEvent(ctx, agentName, incoming)
597608
case event.EventRequestResourceResync.String():
598609
if agentMode != types.AgentModeAutonomous {

0 commit comments

Comments
 (0)