@@ -28,6 +28,7 @@ import (
28
28
"github.com/argoproj-labs/argocd-agent/pkg/types"
29
29
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
30
30
"github.com/sirupsen/logrus"
31
+ corev1 "k8s.io/api/core/v1"
31
32
apierrors "k8s.io/apimachinery/pkg/api/errors"
32
33
"k8s.io/client-go/dynamic"
33
34
)
@@ -57,6 +58,8 @@ func (a *Agent) processIncomingEvent(ev *event.Event) error {
57
58
err = a .processIncomingApplication (ev )
58
59
case event .TargetAppProject :
59
60
err = a .processIncomingAppProject (ev )
61
+ case event .TargetRepository :
62
+ err = a .processIncomingRepository (ev )
60
63
case event .TargetResource :
61
64
err = a .processIncomingResourceRequest (ev )
62
65
case event .TargetResourceResync :
@@ -264,6 +267,88 @@ func (a *Agent) processIncomingAppProject(ev *event.Event) error {
264
267
return err
265
268
}
266
269
270
+ func (a * Agent ) processIncomingRepository (ev * event.Event ) error {
271
+ logCtx := log ().WithFields (logrus.Fields {
272
+ "method" : "processIncomingEvents" ,
273
+ })
274
+
275
+ incomingRepo , err := ev .Repository ()
276
+ if err != nil {
277
+ return err
278
+ }
279
+
280
+ var exists , sourceUIDMatch bool
281
+
282
+ // Source UID annotation is not present for repos on the autonomous agent since it is the source of truth.
283
+ if a .mode == types .AgentModeManaged {
284
+ exists , sourceUIDMatch , err = a .repoManager .CompareSourceUID (a .context , incomingRepo )
285
+ if err != nil {
286
+ return fmt .Errorf ("failed to compare the source UID of app: %w" , err )
287
+ }
288
+ }
289
+
290
+ switch ev .Type () {
291
+ case event .Create :
292
+ if exists {
293
+ if sourceUIDMatch {
294
+ logCtx .Debug ("Received a Create event for an existing repository. Updating the existing repository" )
295
+ _ , err := a .updateRepository (incomingRepo )
296
+ if err != nil {
297
+ return fmt .Errorf ("could not update the existing repository: %w" , err )
298
+ }
299
+ return nil
300
+ } else {
301
+ logCtx .Debug ("Repository already exists with a different source UID. Deleting the existing repository" )
302
+ if err := a .deleteRepository (incomingRepo ); err != nil {
303
+ return fmt .Errorf ("could not delete existing repository prior to creation: %w" , err )
304
+ }
305
+ }
306
+ }
307
+
308
+ _ , err = a .createRepository (incomingRepo )
309
+ if err != nil {
310
+ logCtx .Errorf ("Error creating repository: %v" , err )
311
+ }
312
+
313
+ case event .SpecUpdate :
314
+ if ! exists {
315
+ logCtx .Debug ("Received an Update event for a repository that doesn't exist. Creating the incoming repository" )
316
+ if _ , err := a .createRepository (incomingRepo ); err != nil {
317
+ return fmt .Errorf ("could not create incoming repository: %w" , err )
318
+ }
319
+ return nil
320
+ }
321
+
322
+ if ! sourceUIDMatch {
323
+ logCtx .Debug ("Source UID mismatch between the incoming repository and existing repository. Deleting the existing repository" )
324
+ if err := a .deleteRepository (incomingRepo ); err != nil {
325
+ return fmt .Errorf ("could not delete existing repository prior to creation: %w" , err )
326
+ }
327
+
328
+ logCtx .Debug ("Creating the incoming repository after deleting the existing repository" )
329
+ if _ , err := a .createRepository (incomingRepo ); err != nil {
330
+ return fmt .Errorf ("could not create incoming repository after deleting existing repository: %w" , err )
331
+ }
332
+ return nil
333
+ }
334
+
335
+ _ , err = a .updateRepository (incomingRepo )
336
+ if err != nil {
337
+ logCtx .Errorf ("Error updating repository: %v" , err )
338
+ }
339
+
340
+ case event .Delete :
341
+ err = a .deleteRepository (incomingRepo )
342
+ if err != nil {
343
+ logCtx .Errorf ("Error deleting repository: %v" , err )
344
+ }
345
+ default :
346
+ logCtx .Warnf ("Received an unknown event: %s. Protocol mismatch?" , ev .Type ())
347
+ }
348
+
349
+ return err
350
+ }
351
+
267
352
// processIncomingResourceResyncEvent handles all the resync events that are
268
353
// exchanged with the agent/principal restarts
269
354
func (a * Agent ) processIncomingResourceResyncEvent (ev * event.Event ) error {
@@ -457,7 +542,7 @@ func (a *Agent) deleteApplication(app *v1alpha1.Application) error {
457
542
return err
458
543
}
459
544
460
- if a .mode == types .AgentModeManaged && err == nil {
545
+ if a .mode == types .AgentModeManaged {
461
546
appCache .DeleteApplicationSpec (app .UID , logCtx )
462
547
}
463
548
@@ -562,3 +647,98 @@ func (a *Agent) deleteAppProject(project *v1alpha1.AppProject) error {
562
647
}
563
648
return nil
564
649
}
650
+
651
+ // createRepository creates a Repository upon an event in the agent's work queue.
652
+ func (a * Agent ) createRepository (incoming * corev1.Secret ) (* corev1.Secret , error ) {
653
+ logCtx := log ().WithFields (logrus.Fields {
654
+ "method" : "CreateRepository" ,
655
+ "repo" : incoming .Name ,
656
+ })
657
+
658
+ // In modes other than "managed", we don't process new repository events
659
+ // that are incoming.
660
+ if a .mode .IsAutonomous () {
661
+ logCtx .Info ("Discarding this event, because agent is not in managed mode" )
662
+ return nil , event .NewEventDiscardedErr ("cannot create repository: agent is not in managed mode" )
663
+ }
664
+
665
+ // If we receive a new Repository event for a Repository we already manage, it usually
666
+ // means that we're out-of-sync from the control plane.
667
+ if a .repoManager .IsManaged (incoming .Name ) {
668
+ logCtx .Trace ("Repository is already managed on this agent. Updating the existing Repository" )
669
+ return a .updateRepository (incoming )
670
+ }
671
+
672
+ logCtx .Infof ("Creating a new repository on behalf of an incoming event" )
673
+
674
+ if incoming .Annotations == nil {
675
+ incoming .Annotations = make (map [string ]string )
676
+ }
677
+
678
+ // Get rid of some fields that we do not want to have on the repository as we start fresh.
679
+ delete (incoming .Annotations , "kubectl.kubernetes.io/last-applied-configuration" )
680
+
681
+ created , err := a .repoManager .Create (a .context , incoming )
682
+ if apierrors .IsAlreadyExists (err ) {
683
+ logCtx .Debug ("repository already exists" )
684
+ return created , nil
685
+ }
686
+
687
+ return created , err
688
+ }
689
+
690
+ func (a * Agent ) updateRepository (incoming * corev1.Secret ) (* corev1.Secret , error ) {
691
+ incoming .SetNamespace (a .namespace )
692
+ logCtx := log ().WithFields (logrus.Fields {
693
+ "method" : "UpdateRepository" ,
694
+ "repo" : incoming .Name ,
695
+ "resourceVersion" : incoming .ResourceVersion ,
696
+ })
697
+
698
+ if ! a .repoManager .IsManaged (incoming .Name ) {
699
+ logCtx .Trace ("Repository is not managed on this agent. Creating the new Repository" )
700
+ return a .createRepository (incoming )
701
+ }
702
+
703
+ if a .repoManager .IsChangeIgnored (incoming .Name , incoming .ResourceVersion ) {
704
+ logCtx .Tracef ("Discarding this event, because agent has seen this version %s already" , incoming .ResourceVersion )
705
+ return nil , event .NewEventDiscardedErr ("the version %s has already been seen by this agent" , incoming .ResourceVersion )
706
+ } else {
707
+ logCtx .Tracef ("New resource version: %s" , incoming .ResourceVersion )
708
+ }
709
+
710
+ logCtx .Infof ("Updating repository" )
711
+
712
+ return a .repoManager .UpdateManagedRepository (a .context , incoming )
713
+ }
714
+
715
+ func (a * Agent ) deleteRepository (repo * corev1.Secret ) error {
716
+ repo .SetNamespace (a .namespace )
717
+ logCtx := log ().WithFields (logrus.Fields {
718
+ "method" : "DeleteRepository" ,
719
+ "repo" : repo .Name ,
720
+ })
721
+
722
+ if ! a .repoManager .IsManaged (repo .Name ) {
723
+ return fmt .Errorf ("repository %s is not managed" , repo .Name )
724
+ }
725
+
726
+ logCtx .Infof ("Deleting repository" )
727
+
728
+ deletionPropagation := backend .DeletePropagationBackground
729
+ err := a .repoManager .Delete (a .context , repo .Name , repo .Namespace , & deletionPropagation )
730
+ if err != nil {
731
+ if apierrors .IsNotFound (err ) {
732
+ logCtx .Debug ("repository is not found, perhaps it is already deleted" )
733
+ return nil
734
+ }
735
+ return err
736
+ }
737
+
738
+ err = a .repoManager .Unmanage (repo .Name )
739
+ if err != nil {
740
+ log ().Warnf ("Could not unmanage repository %s: %v" , repo .Name , err )
741
+ }
742
+
743
+ return nil
744
+ }
0 commit comments