55 "encoding/json"
66 "errors"
77 "fmt"
8+ "os"
89 "reflect"
910 "strings"
1011 goSync "sync"
@@ -73,7 +74,7 @@ type managedResource struct {
7374type AppStateManager interface {
7475 CompareAppState (app * v1alpha1.Application , project * v1alpha1.AppProject , revisions []string , sources []v1alpha1.ApplicationSource , noCache bool , noRevisionCache bool , localObjects []string , hasMultipleSources bool ) (* comparisonResult , error )
7576 SyncAppState (app * v1alpha1.Application , state * v1alpha1.OperationState )
76- GetRepoObjs (app * v1alpha1.Application , sources []v1alpha1.ApplicationSource , appLabelKey string , revisions []string , noCache , noRevisionCache , verifySignature bool , proj * v1alpha1.AppProject ) ([]* unstructured.Unstructured , []* apiclient.ManifestResponse , error )
77+ GetRepoObjs (app * v1alpha1.Application , sources []v1alpha1.ApplicationSource , appLabelKey string , revisions []string , noCache , noRevisionCache , verifySignature bool , proj * v1alpha1.AppProject ) ([]* unstructured.Unstructured , []* apiclient.ManifestResponse , map [ string ] bool , error )
7778}
7879
7980// comparisonResult holds the state of an application after the reconciliation
@@ -126,51 +127,51 @@ type appStateManager struct {
126127// task to the repo-server. It returns the list of generated manifests as unstructured
127128// objects. It also returns the full response from all calls to the repo server as the
128129// second argument.
129- func (m * appStateManager ) GetRepoObjs (app * v1alpha1.Application , sources []v1alpha1.ApplicationSource , appLabelKey string , revisions []string , noCache , noRevisionCache , verifySignature bool , proj * v1alpha1.AppProject ) ([]* unstructured.Unstructured , []* apiclient.ManifestResponse , error ) {
130+ func (m * appStateManager ) GetRepoObjs (app * v1alpha1.Application , sources []v1alpha1.ApplicationSource , appLabelKey string , revisions []string , noCache , noRevisionCache , verifySignature bool , proj * v1alpha1.AppProject ) ([]* unstructured.Unstructured , []* apiclient.ManifestResponse , map [ string ] bool , error ) {
130131 ts := stats .NewTimingStats ()
131132 helmRepos , err := m .db .ListHelmRepositories (context .Background ())
132133 if err != nil {
133- return nil , nil , fmt .Errorf ("failed to list Helm repositories: %w" , err )
134+ return nil , nil , nil , fmt .Errorf ("failed to list Helm repositories: %w" , err )
134135 }
135136 permittedHelmRepos , err := argo .GetPermittedRepos (proj , helmRepos )
136137 if err != nil {
137- return nil , nil , fmt .Errorf ("failed to get permitted Helm repositories for project %q: %w" , proj .Name , err )
138+ return nil , nil , nil , fmt .Errorf ("failed to get permitted Helm repositories for project %q: %w" , proj .Name , err )
138139 }
139140
140141 ts .AddCheckpoint ("repo_ms" )
141142 helmRepositoryCredentials , err := m .db .GetAllHelmRepositoryCredentials (context .Background ())
142143 if err != nil {
143- return nil , nil , fmt .Errorf ("failed to get Helm credentials: %w" , err )
144+ return nil , nil , nil , fmt .Errorf ("failed to get Helm credentials: %w" , err )
144145 }
145146 permittedHelmCredentials , err := argo .GetPermittedReposCredentials (proj , helmRepositoryCredentials )
146147 if err != nil {
147- return nil , nil , fmt .Errorf ("failed to get permitted Helm credentials for project %q: %w" , proj .Name , err )
148+ return nil , nil , nil , fmt .Errorf ("failed to get permitted Helm credentials for project %q: %w" , proj .Name , err )
148149 }
149150
150151 enabledSourceTypes , err := m .settingsMgr .GetEnabledSourceTypes ()
151152 if err != nil {
152- return nil , nil , fmt .Errorf ("failed to get enabled source types: %w" , err )
153+ return nil , nil , nil , fmt .Errorf ("failed to get enabled source types: %w" , err )
153154 }
154155 ts .AddCheckpoint ("plugins_ms" )
155156
156157 kustomizeSettings , err := m .settingsMgr .GetKustomizeSettings ()
157158 if err != nil {
158- return nil , nil , fmt .Errorf ("failed to get Kustomize settings: %w" , err )
159+ return nil , nil , nil , fmt .Errorf ("failed to get Kustomize settings: %w" , err )
159160 }
160161
161162 helmOptions , err := m .settingsMgr .GetHelmSettings ()
162163 if err != nil {
163- return nil , nil , fmt .Errorf ("failed to get Helm settings: %w" , err )
164+ return nil , nil , nil , fmt .Errorf ("failed to get Helm settings: %w" , err )
164165 }
165166
166167 ts .AddCheckpoint ("build_options_ms" )
167168 serverVersion , apiResources , err := m .liveStateCache .GetVersionsInfo (app .Spec .Destination .Server )
168169 if err != nil {
169- return nil , nil , fmt .Errorf ("failed to get cluster version for cluster %q: %w" , app .Spec .Destination .Server , err )
170+ return nil , nil , nil , fmt .Errorf ("failed to get cluster version for cluster %q: %w" , app .Spec .Destination .Server , err )
170171 }
171172 conn , repoClient , err := m .repoClientset .NewRepoServerClient ()
172173 if err != nil {
173- return nil , nil , fmt .Errorf ("failed to connect to repo server: %w" , err )
174+ return nil , nil , nil , fmt .Errorf ("failed to connect to repo server: %w" , err )
174175 }
175176 defer io .Close (conn )
176177
@@ -180,21 +181,23 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
180181 // Store the map of all sources having ref field into a map for applications with sources field
181182 refSources , err := argo .GetRefSources (context .Background (), app .Spec , m .db )
182183 if err != nil {
183- return nil , nil , fmt .Errorf ("failed to get ref sources: %v" , err )
184+ return nil , nil , nil , fmt .Errorf ("failed to get ref sources: %v" , err )
184185 }
185186
187+ manifestsChanges := make (map [string ]bool )
188+
186189 for i , source := range sources {
187190 if len (revisions ) < len (sources ) || revisions [i ] == "" {
188191 revisions [i ] = source .TargetRevision
189192 }
190193 ts .AddCheckpoint ("helm_ms" )
191194 repo , err := m .db .GetRepository (context .Background (), source .RepoURL )
192195 if err != nil {
193- return nil , nil , fmt .Errorf ("failed to get repo %q: %w" , source .RepoURL , err )
196+ return nil , nil , nil , fmt .Errorf ("failed to get repo %q: %w" , source .RepoURL , err )
194197 }
195198 kustomizeOptions , err := kustomizeSettings .GetOptions (source , m .settingsMgr .GetKustomizeSetNamespaceEnabled ())
196199 if err != nil {
197- return nil , nil , fmt .Errorf ("failed to get Kustomize options for source %d of %d: %w" , i + 1 , len (sources ), err )
200+ return nil , nil , nil , fmt .Errorf ("failed to get Kustomize options for source %d of %d: %w" , i + 1 , len (sources ), err )
198201 }
199202
200203 syncedRevision := app .Status .Sync .Revision
@@ -209,7 +212,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
209212 val , ok := app .Annotations [v1alpha1 .AnnotationKeyManifestGeneratePaths ]
210213 if ! source .IsHelm () && syncedRevision != "" && ok && val != "" {
211214 // Validate the manifest-generate-path annotation to avoid generating manifests if it has not changed.
212- _ , err = repoClient .UpdateRevisionForPaths (context .Background (), & apiclient.UpdateRevisionForPathsRequest {
215+ updateRevisionResponse , err : = repoClient .UpdateRevisionForPaths (context .Background (), & apiclient.UpdateRevisionForPathsRequest {
213216 Repo : repo ,
214217 Revision : revisions [i ],
215218 SyncedRevision : syncedRevision ,
@@ -224,8 +227,13 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
224227 RefSources : refSources ,
225228 HasMultipleSources : app .Spec .HasMultipleSources (),
226229 })
230+
231+ // not need to change, if we already found at least one cached revision that has no changes
232+ if updateRevisionResponse != nil && os .Getenv ("PERSIST_CHANGE_REVISIONS" ) == "1" {
233+ manifestsChanges [syncedRevision ] = updateRevisionResponse .Changes
234+ }
227235 if err != nil {
228- return nil , nil , fmt .Errorf ("failed to compare revisions for source %d of %d: %w" , i + 1 , len (sources ), err )
236+ return nil , nil , nil , fmt .Errorf ("failed to compare revisions for source %d of %d: %w" , i + 1 , len (sources ), err )
229237 }
230238 }
231239
@@ -256,13 +264,13 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
256264 ApplicationMetadata : & app .ObjectMeta ,
257265 })
258266 if err != nil {
259- return nil , nil , fmt .Errorf ("failed to generate manifest for source %d of %d: %w" , i + 1 , len (sources ), err )
267+ return nil , nil , nil , fmt .Errorf ("failed to generate manifest for source %d of %d: %w" , i + 1 , len (sources ), err )
260268 }
261269
262270 targetObj , err := unmarshalManifests (manifestInfo .GetCompiledManifests ())
263271
264272 if err != nil {
265- return nil , nil , fmt .Errorf ("failed to unmarshal manifests for source %d of %d: %w" , i + 1 , len (sources ), err )
273+ return nil , nil , nil , fmt .Errorf ("failed to unmarshal manifests for source %d of %d: %w" , i + 1 , len (sources ), err )
266274 }
267275 targetObjs = append (targetObjs , targetObj ... )
268276
@@ -276,7 +284,7 @@ func (m *appStateManager) GetRepoObjs(app *v1alpha1.Application, sources []v1alp
276284 }
277285 logCtx = logCtx .WithField ("time_ms" , time .Since (ts .StartTime ).Milliseconds ())
278286 logCtx .Info ("GetRepoObjs stats" )
279- return targetObjs , manifestInfos , nil
287+ return targetObjs , manifestInfos , manifestsChanges , nil
280288}
281289
282290func unmarshalManifests (manifests []string ) ([]* unstructured.Unstructured , error ) {
@@ -444,6 +452,8 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
444452 var manifestInfos []* apiclient.ManifestResponse
445453 targetNsExists := false
446454
455+ var manifestChanged map [string ]bool
456+
447457 if len (localManifests ) == 0 {
448458 // If the length of revisions is not same as the length of sources,
449459 // we take the revisions from the sources directly for all the sources.
@@ -454,7 +464,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
454464 }
455465 }
456466
457- targetObjs , manifestInfos , err = m .GetRepoObjs (app , sources , appLabelKey , revisions , noCache , noRevisionCache , verifySignature , project )
467+ targetObjs , manifestInfos , manifestChanged , err = m .GetRepoObjs (app , sources , appLabelKey , revisions , noCache , noRevisionCache , verifySignature , project )
458468 if err != nil {
459469 targetObjs = make ([]* unstructured.Unstructured , 0 )
460470 msg := fmt .Sprintf ("Failed to load target state: %s" , err .Error ())
@@ -828,8 +838,9 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
828838 Sources : sources ,
829839 IgnoreDifferences : app .Spec .IgnoreDifferences ,
830840 },
831- Status : syncCode ,
832- Revisions : manifestRevisions ,
841+ Status : syncCode ,
842+ Revisions : manifestRevisions ,
843+ ManifestsChanged : manifestChanged ,
833844 }
834845 } else {
835846 syncStatus = v1alpha1.SyncStatus {
@@ -838,8 +849,9 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
838849 Source : app .Spec .GetSource (),
839850 IgnoreDifferences : app .Spec .IgnoreDifferences ,
840851 },
841- Status : syncCode ,
842- Revision : revision ,
852+ Status : syncCode ,
853+ Revision : revision ,
854+ ManifestsChanged : manifestChanged ,
843855 }
844856 }
845857
0 commit comments