@@ -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,96 @@ 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+ revision , err := c .calculateRevision (ctx , app , currentRevision , previousRevision )
7786 if err != nil {
7887 return err
7988 }
8089
90+ var revisions []string
8191 if revision == nil || * revision == "" {
8292 c .logger .Infof ("Revision for application %s is empty" , app .Name )
83- return nil
93+ } else {
94+ c .logger .Infof ("Change revision for application %s is %s" , app .Name , * revision )
95+ revisions = []string {* revision }
8496 }
8597
86- c .logger .Infof ("Change revision for application %s is %s" , app .Name , * revision )
87-
8898 app , err = c .applicationClientset .ArgoprojV1alpha1 ().Applications (app .Namespace ).Get (ctx , app .Name , metav1.GetOptions {})
8999 if err != nil {
90100 return err
91101 }
92102
93- revisions := [] string { * revision }
103+ patchMap := make ( map [ string ] any , 2 )
94104
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 )
105+ if len (revisions ) > 0 {
106+ if app .Status .OperationState != nil && app .Status .OperationState .Operation .Sync != nil {
107+ c .logger .Infof ("Patch operation status for application %s" , app .Name )
108+ patchMap = c .patchOperationSyncResultWithChangeRevision (ctx , app , revisions )
109+ } else {
110+ c .logger .Infof ("Patch operation for application %s" , app .Name )
111+ patchMap = c .patchOperationWithChangeRevision (ctx , app , revisions )
112+ }
113+ }
114+ if useAnnotations {
115+ err = c .addAnnotationPatch (patchMap , app , * revision , revisions , currentRevision , []string {currentRevision })
116+ if err != nil {
117+ return err
118+ }
98119 }
120+ if len (patchMap ) > 0 {
121+ c .logger .Infof ("patching resource: %v" , patchMap )
122+ patch , err := json .Marshal (patchMap )
123+ if err != nil {
124+ return err
125+ }
126+ _ , err = c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
127+ return err
128+ } else {
129+ c .logger .Infof ("no patch needed" )
130+ return nil
131+ }
132+ }
99133
100- c .logger .Infof ("Patch operation for application %s" , app .Name )
101- return c .patchOperationWithChangeRevision (ctx , app , revisions )
134+ func addPatchIfNeeded (annotations map [string ]string , currentAnnotations map [string ]string , key string , val string ) {
135+ currentVal , ok := currentAnnotations [key ]
136+ if ! ok || currentVal != val {
137+ annotations [key ] = val
138+ }
102139}
103140
104- func (c * acrService ) calculateRevision (ctx context.Context , a * application.Application ) (* string , error ) {
105- currentRevision , previousRevision := c .getRevisions (ctx , a )
141+ func (c * acrService ) addAnnotationPatch (m map [string ]any ,
142+ a * application.Application ,
143+ changeRevision string ,
144+ changeRevisions []string ,
145+ gitRevision string ,
146+ gitRevisions []string ) error {
147+ c .logger .Infof ("annotating application '%s', changeRevision=%s, changeRevisions=%v, gitRevision=%s, gitRevisions=%v" , a .Name , changeRevision , changeRevisions , gitRevision , gitRevisions )
148+ annotations := map [string ]string {}
149+ currentAnnotations := a .Annotations
150+
151+ changeRevisionsJson , err := json .Marshal (changeRevisions )
152+ if err != nil {
153+ return fmt .Errorf ("Failed to marshall changeRevisions %v: %v" , changeRevisions , err )
154+ }
155+ gitRevisionsJson , err := json .Marshal (gitRevisions )
156+ if err != nil {
157+ return fmt .Errorf ("Failed to marshall gitRevisions %v: %v" , gitRevisions , err )
158+ }
159+
160+ addPatchIfNeeded (annotations , currentAnnotations , CHANGE_REVISION_ANN , changeRevision )
161+ addPatchIfNeeded (annotations , currentAnnotations , CHANGE_REVISIONS_ANN , string (changeRevisionsJson ))
162+ addPatchIfNeeded (annotations , currentAnnotations , GIT_REVISION_ANN , gitRevision )
163+ addPatchIfNeeded (annotations , currentAnnotations , GIT_REVISIONS_ANN , string (gitRevisionsJson ))
164+
165+ if len (annotations ) == 0 {
166+ c .logger .Info ("no need to add annotations" )
167+ }
168+ c .logger .Infof ("added annotations to application %s patch: %v" , a .Name , annotations )
169+ m ["metadata" ] = map [string ]any {"annotations" : annotations }
170+ return nil
171+ }
172+
173+ func (c * acrService ) calculateRevision (ctx context.Context , a * application.Application , currentRevision string , previousRevision string ) (* string , error ) {
106174 c .logger .Infof ("Calculate revision for application '%s', current revision '%s', previous revision '%s'" , a .Name , currentRevision , previousRevision )
107175 changeRevisionResult , err := c .applicationServiceClient .GetChangeRevision (ctx , & appclient.ChangeRevisionRequest {
108176 AppName : ptr .To (a .GetName ()),
@@ -116,33 +184,28 @@ func (c *acrService) calculateRevision(ctx context.Context, a *application.Appli
116184 return changeRevisionResult .Revision , nil
117185}
118186
119- func (c * acrService ) patchOperationWithChangeRevision (ctx context.Context , a * application.Application , revisions []string ) error {
187+ func (c * acrService ) patchOperationWithChangeRevision (ctx context.Context , a * application.Application , revisions []string ) map [ string ] any {
120188 if len (revisions ) == 1 {
121- patch , _ := json . Marshal ( map [string ]any {
189+ return map [string ]any {
122190 "operation" : map [string ]any {
123191 "sync" : map [string ]any {
124192 "changeRevision" : revisions [0 ],
125193 },
126194 },
127- })
128- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
129- return err
195+ }
130196 }
131-
132- patch , _ := json .Marshal (map [string ]any {
197+ return map [string ]any {
133198 "operation" : map [string ]any {
134199 "sync" : map [string ]any {
135200 "changeRevisions" : revisions ,
136201 },
137202 },
138- })
139- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
140- return err
203+ }
141204}
142205
143- func (c * acrService ) patchOperationSyncResultWithChangeRevision (ctx context.Context , a * application.Application , revisions []string ) error {
206+ func (c * acrService ) patchOperationSyncResultWithChangeRevision (ctx context.Context , a * application.Application , revisions []string ) map [ string ] any {
144207 if len (revisions ) == 1 {
145- patch , _ := json . Marshal ( map [string ]any {
208+ return map [string ]any {
146209 "status" : map [string ]any {
147210 "operationState" : map [string ]any {
148211 "operation" : map [string ]any {
@@ -152,12 +215,9 @@ func (c *acrService) patchOperationSyncResultWithChangeRevision(ctx context.Cont
152215 },
153216 },
154217 },
155- })
156- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
157- return err
218+ }
158219 }
159-
160- patch , _ := json .Marshal (map [string ]any {
220+ return map [string ]any {
161221 "status" : map [string ]any {
162222 "operationState" : map [string ]any {
163223 "operation" : map [string ]any {
@@ -167,9 +227,7 @@ func (c *acrService) patchOperationSyncResultWithChangeRevision(ctx context.Cont
167227 },
168228 },
169229 },
170- })
171- _ , err := c .applicationClientset .ArgoprojV1alpha1 ().Applications (a .Namespace ).Patch (ctx , a .Name , types .MergePatchType , patch , metav1.PatchOptions {})
172- return err
230+ }
173231}
174232
175233func getCurrentRevisionFromOperation (a * application.Application ) string {
0 commit comments