@@ -3,6 +3,7 @@ package service
33import (
44 "context"
55 "encoding/json"
6+ "fmt"
67 "sync"
78
89 log "github.com/sirupsen/logrus"
@@ -16,8 +17,15 @@ import (
1617 appclientset "github.com/argoproj/argo-cd/v3/pkg/client/clientset/versioned"
1718)
1819
20+ const (
21+ CHANGE_REVISION_ANN = "mrp-controller.argoproj.io/change-revision"
22+ CHANGE_REVISIONS_ANN = "mrp-controller.argoproj.io/change-revisions"
23+ GIT_REVISION_ANN = "mrp-controller.argoproj.io/git-revision"
24+ GIT_REVISIONS_ANN = "mrp-controller.argoproj.io/git-revisions"
25+ )
26+
1927type ACRService interface {
20- ChangeRevision (ctx context.Context , application * application.Application ) error
28+ ChangeRevision (ctx context.Context , application * application.Application , useAnnotations bool ) error
2129}
2230
2331type acrService struct {
@@ -55,7 +63,7 @@ func getChangeRevision(app *application.Application) string {
5563 return ""
5664}
5765
58- func (c * acrService ) ChangeRevision (ctx context.Context , a * application.Application ) error {
66+ func (c * acrService ) ChangeRevision (ctx context.Context , a * application.Application , useAnnotations bool ) error {
5967 c .lock .Lock ()
6068 defer c .lock .Unlock ()
6169
@@ -73,36 +81,108 @@ func (c *acrService) ChangeRevision(ctx context.Context, a *application.Applicat
7381 return nil
7482 }
7583
76- revision , err := c .calculateRevision (ctx , app )
84+ currentRevision , previousRevision := c .getRevisions (ctx , a )
85+ if currentRevision == "" {
86+ c .logger .Infof ("Got empty current revision for application %s, is it an unsupported multisource or helm repo based application?" , app .Name )
87+ return nil
88+ }
89+ revision , err := c .calculateRevision (ctx , app , currentRevision , previousRevision )
7790 if err != nil {
7891 return err
7992 }
8093
94+ var revisions []string
8195 if revision == nil || * revision == "" {
8296 c .logger .Infof ("Revision for application %s is empty" , app .Name )
83- return nil
97+ } else {
98+ c .logger .Infof ("Change revision for application %s is %s" , app .Name , * revision )
99+ revisions = []string {* revision }
84100 }
85101
86- c .logger .Infof ("Change revision for application %s is %s" , app .Name , * revision )
87-
88102 app , err = c .applicationClientset .ArgoprojV1alpha1 ().Applications (app .Namespace ).Get (ctx , app .Name , metav1.GetOptions {})
89103 if err != nil {
90104 return err
91105 }
92106
93- revisions := [] string { * revision }
107+ patchMap := make ( map [ string ] any , 2 )
94108
95- if app .Status .OperationState != nil && app .Status .OperationState .Operation .Sync != nil {
96- c .logger .Infof ("Patch operation status for application %s" , app .Name )
97- return c .patchOperationSyncResultWithChangeRevision (ctx , app , revisions )
109+ if len (revisions ) > 0 {
110+ if app .Status .OperationState != nil && app .Status .OperationState .Operation .Sync != nil {
111+ c .logger .Infof ("Patch operation status for application %s" , app .Name )
112+ patchMap = c .patchOperationSyncResultWithChangeRevision (revisions )
113+ } else {
114+ c .logger .Infof ("Patch operation for application %s" , app .Name )
115+ patchMap = c .patchOperationWithChangeRevision (revisions )
116+ }
98117 }
118+ if useAnnotations {
119+ err = c .addAnnotationPatch (patchMap , app , * revision , revisions , currentRevision , []string {currentRevision })
120+ if err != nil {
121+ return err
122+ }
123+ }
124+ if len (patchMap ) > 0 {
125+ c .logger .Infof ("Patching resource: %v" , patchMap )
126+ patch , err := json .Marshal (patchMap )
127+ if err != nil {
128+ return err
129+ }
130+ _ , err = c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
131+ return err
132+ }
133+ c .logger .Infof ("No patch needed" )
134+ return nil
135+ }
99136
100- c .logger .Infof ("Patch operation for application %s" , app .Name )
101- return c .patchOperationWithChangeRevision (ctx , app , revisions )
137+ func addPatchIfNeeded (annotations map [string ]string , currentAnnotations map [string ]string , key string , val string ) {
138+ currentVal , ok := currentAnnotations [key ]
139+ if ! ok || currentVal != val {
140+ annotations [key ] = val
141+ }
102142}
103143
104- func (c * acrService ) calculateRevision (ctx context.Context , a * application.Application ) (* string , error ) {
105- currentRevision , previousRevision := c .getRevisions (ctx , a )
144+ func (c * acrService ) addAnnotationPatch (m map [string ]any ,
145+ a * application.Application ,
146+ changeRevision string ,
147+ changeRevisions []string ,
148+ gitRevision string ,
149+ gitRevisions []string ,
150+ ) error {
151+ c .logger .Infof ("annotating application '%s', changeRevision=%s, changeRevisions=%v, gitRevision=%s, gitRevisions=%v" , a .Name , changeRevision , changeRevisions , gitRevision , gitRevisions )
152+ annotations := map [string ]string {}
153+ currentAnnotations := a .Annotations
154+
155+ if changeRevision != "" {
156+ addPatchIfNeeded (annotations , currentAnnotations , CHANGE_REVISION_ANN , changeRevision )
157+ }
158+ if len (changeRevisions ) > 0 {
159+ changeRevisionsJSON , err := json .Marshal (changeRevisions )
160+ if err != nil {
161+ return fmt .Errorf ("failed to marshall changeRevisions %v: %w" , changeRevisions , err )
162+ }
163+ addPatchIfNeeded (annotations , currentAnnotations , CHANGE_REVISIONS_ANN , string (changeRevisionsJSON ))
164+ }
165+ if gitRevision != "" {
166+ addPatchIfNeeded (annotations , currentAnnotations , GIT_REVISION_ANN , gitRevision )
167+ }
168+ if len (gitRevisions ) > 0 {
169+ gitRevisionsJSON , err := json .Marshal (gitRevisions )
170+ if err != nil {
171+ return fmt .Errorf ("failed to marshall gitRevisions %v: %w" , gitRevisions , err )
172+ }
173+ addPatchIfNeeded (annotations , currentAnnotations , GIT_REVISIONS_ANN , string (gitRevisionsJSON ))
174+ }
175+
176+ if len (annotations ) == 0 {
177+ c .logger .Info ("no need to add annotations" )
178+ } else {
179+ c .logger .Infof ("added annotations to application %s patch: %v" , a .Name , annotations )
180+ m ["metadata" ] = map [string ]any {"annotations" : annotations }
181+ }
182+ return nil
183+ }
184+
185+ func (c * acrService ) calculateRevision (ctx context.Context , a * application.Application , currentRevision string , previousRevision string ) (* string , error ) {
106186 c .logger .Infof ("Calculate revision for application '%s', current revision '%s', previous revision '%s'" , a .Name , currentRevision , previousRevision )
107187 changeRevisionResult , err := c .applicationServiceClient .GetChangeRevision (ctx , & appclient.ChangeRevisionRequest {
108188 AppName : ptr .To (a .GetName ()),
@@ -116,33 +196,28 @@ func (c *acrService) calculateRevision(ctx context.Context, a *application.Appli
116196 return changeRevisionResult .Revision , nil
117197}
118198
119- func (c * acrService ) patchOperationWithChangeRevision (ctx context. Context , a * application. Application , revisions []string ) error {
199+ func (c * acrService ) patchOperationWithChangeRevision (revisions []string ) map [ string ] any {
120200 if len (revisions ) == 1 {
121- patch , _ := json . Marshal ( map [string ]any {
201+ return map [string ]any {
122202 "operation" : map [string ]any {
123203 "sync" : map [string ]any {
124204 "changeRevision" : revisions [0 ],
125205 },
126206 },
127- })
128- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
129- return err
207+ }
130208 }
131-
132- patch , _ := json .Marshal (map [string ]any {
209+ return map [string ]any {
133210 "operation" : map [string ]any {
134211 "sync" : map [string ]any {
135212 "changeRevisions" : revisions ,
136213 },
137214 },
138- })
139- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
140- return err
215+ }
141216}
142217
143- func (c * acrService ) patchOperationSyncResultWithChangeRevision (ctx context. Context , a * application. Application , revisions []string ) error {
218+ func (c * acrService ) patchOperationSyncResultWithChangeRevision (revisions []string ) map [ string ] any {
144219 if len (revisions ) == 1 {
145- patch , _ := json . Marshal ( map [string ]any {
220+ return map [string ]any {
146221 "status" : map [string ]any {
147222 "operationState" : map [string ]any {
148223 "operation" : map [string ]any {
@@ -152,12 +227,9 @@ func (c *acrService) patchOperationSyncResultWithChangeRevision(ctx context.Cont
152227 },
153228 },
154229 },
155- })
156- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
157- return err
230+ }
158231 }
159-
160- patch , _ := json .Marshal (map [string ]any {
232+ return map [string ]any {
161233 "status" : map [string ]any {
162234 "operationState" : map [string ]any {
163235 "operation" : map [string ]any {
@@ -167,9 +239,7 @@ func (c *acrService) patchOperationSyncResultWithChangeRevision(ctx context.Cont
167239 },
168240 },
169241 },
170- })
171- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
172- return err
242+ }
173243}
174244
175245func getCurrentRevisionFromOperation (a * application.Application ) string {
0 commit comments