needRefreshAppStatus answers if application status needs to be refreshed. Returns true if application never been compared, has changed or comparison result has expired. Additionally, it returns whether full refresh was requested or not. If full refresh is requested then target and live state should
(app *appv1.Application, statusRefreshTimeout, statusHardRefreshTimeout time.Duration)
| 2014 | // Additionally, it returns whether full refresh was requested or not. |
| 2015 | // If full refresh is requested then target and live state should be reconciled, else only live state tree should be updated. |
| 2016 | func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application, statusRefreshTimeout, statusHardRefreshTimeout time.Duration) (bool, appv1.RefreshType, CompareWith) { |
| 2017 | logCtx := log.WithFields(applog.GetAppLogFields(app)) |
| 2018 | var reason string |
| 2019 | compareWith := CompareWithLatest |
| 2020 | refreshType := appv1.RefreshTypeNormal |
| 2021 | |
| 2022 | softExpired := app.Status.ReconciledAt == nil || app.Status.ReconciledAt.Add(statusRefreshTimeout).Before(time.Now().UTC()) |
| 2023 | hardExpired := (app.Status.ReconciledAt == nil || app.Status.ReconciledAt.Add(statusHardRefreshTimeout).Before(time.Now().UTC())) && statusHardRefreshTimeout.Seconds() != 0 |
| 2024 | |
| 2025 | if requestedType, ok := app.IsRefreshRequested(); ok { |
| 2026 | compareWith = CompareWithLatestForceResolve |
| 2027 | // user requested app refresh. |
| 2028 | refreshType = requestedType |
| 2029 | reason = fmt.Sprintf("%s refresh requested", refreshType) |
| 2030 | } else { |
| 2031 | if !currentSourceEqualsSyncedSource(app) { |
| 2032 | reason = "spec.source differs" |
| 2033 | compareWith = CompareWithLatestForceResolve |
| 2034 | if app.Spec.HasMultipleSources() { |
| 2035 | reason = "at least one of the spec.sources differs" |
| 2036 | } |
| 2037 | } else if hardExpired || softExpired { |
| 2038 | // The commented line below mysteriously crashes if app.Status.ReconciledAt is nil |
| 2039 | // reason = fmt.Sprintf("comparison expired. reconciledAt: %v, expiry: %v", app.Status.ReconciledAt, statusRefreshTimeout) |
| 2040 | // TODO: find existing Golang bug or create a new one |
| 2041 | reconciledAtStr := "never" |
| 2042 | if app.Status.ReconciledAt != nil { |
| 2043 | reconciledAtStr = app.Status.ReconciledAt.String() |
| 2044 | } |
| 2045 | reason = fmt.Sprintf("comparison expired, requesting refresh. reconciledAt: %v, expiry: %v", reconciledAtStr, statusRefreshTimeout) |
| 2046 | if hardExpired { |
| 2047 | reason = fmt.Sprintf("comparison expired, requesting hard refresh. reconciledAt: %v, expiry: %v", reconciledAtStr, statusHardRefreshTimeout) |
| 2048 | refreshType = appv1.RefreshTypeHard |
| 2049 | } |
| 2050 | } else if !reflect.DeepEqual(app.Spec.Destination, app.Status.Sync.ComparedTo.Destination) { |
| 2051 | reason = "spec.destination differs" |
| 2052 | } else if app.HasChangedManagedNamespaceMetadata() { |
| 2053 | reason = "spec.syncPolicy.managedNamespaceMetadata differs" |
| 2054 | } else if !app.Spec.IgnoreDifferences.Equals(app.Status.Sync.ComparedTo.IgnoreDifferences) { |
| 2055 | reason = "spec.ignoreDifferences differs" |
| 2056 | } else if requested, level := ctrl.isRefreshRequested(app.QualifiedName()); requested { |
| 2057 | compareWith = level |
| 2058 | reason = "controller refresh requested" |
| 2059 | } |
| 2060 | } |
| 2061 | |
| 2062 | if reason != "" { |
| 2063 | logCtx.Infof("Refreshing app status (%s), level (%d)", reason, compareWith) |
| 2064 | return true, refreshType, compareWith |
| 2065 | } |
| 2066 | return false, refreshType, compareWith |
| 2067 | } |
| 2068 | |
| 2069 | func (ctrl *ApplicationController) refreshAppConditions(app *appv1.Application) (*appv1.AppProject, bool) { |
| 2070 | errorConditions := make([]appv1.ApplicationCondition, 0) |