Skip to content

Commit 3adb83c

Browse files
authored
fix(hydrator): refresh by annotation instead of work queue (#22016) (#22067)
Signed-off-by: Michael Crenshaw <[email protected]>
1 parent 63edc3e commit 3adb83c

File tree

7 files changed

+33
-10
lines changed

7 files changed

+33
-10
lines changed

controller/hydrator/hydrator.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type Dependencies interface {
2727
GetProcessableApps() (*appv1.ApplicationList, error)
2828
GetRepoObjs(app *appv1.Application, source appv1.ApplicationSource, revision string, project *appv1.AppProject) ([]*unstructured.Unstructured, *apiclient.ManifestResponse, error)
2929
GetWriteCredentials(ctx context.Context, repoURL string, project string) (*appv1.Repository, error)
30-
RequestAppRefresh(appName string)
30+
RequestAppRefresh(appName string, appNamespace string) error
3131
// TODO: only allow access to the hydrator status
3232
PersistAppHydratorStatus(orig *appv1.Application, newStatus *appv1.SourceHydratorStatus)
3333
AddHydrationQueueItem(key HydrationQueueKey)
@@ -156,7 +156,10 @@ func (h *Hydrator) ProcessHydrationQueueItem(hydrationKey HydrationQueueKey) (pr
156156
}
157157
h.dependencies.PersistAppHydratorStatus(origApp, &app.Status.SourceHydrator)
158158
// Request a refresh since we pushed a new commit.
159-
h.dependencies.RequestAppRefresh(app.QualifiedName())
159+
err := h.dependencies.RequestAppRefresh(app.Name, app.Namespace)
160+
if err != nil {
161+
logCtx.WithField("app", app.QualifiedName()).WithError(err).Error("Failed to request app refresh after hydration")
162+
}
160163
}
161164
return
162165
}

controller/hydrator_dependencies.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/argoproj/argo-cd/v2/controller/hydrator"
88
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
99
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
10+
argoutil "github.com/argoproj/argo-cd/v2/util/argo"
1011

1112
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1213
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -65,8 +66,17 @@ func (ctrl *ApplicationController) GetWriteCredentials(ctx context.Context, repo
6566
return ctrl.db.GetWriteRepository(ctx, repoURL, project)
6667
}
6768

68-
func (ctrl *ApplicationController) RequestAppRefresh(appName string) {
69-
ctrl.requestAppRefresh(appName, CompareWithLatest.Pointer(), nil)
69+
func (ctrl *ApplicationController) RequestAppRefresh(appName string, appNamespace string) error {
70+
// We request a refresh by setting the annotation instead of by adding it to the refresh queue, because there is no
71+
// guarantee that the hydrator is running on the same controller shard as is processing the application.
72+
73+
// This function is called for each app after a hydrate operation is completed so that the app controller can pick
74+
// up the newly-hydrated changes. So we set hydrate=false to avoid a hydrate loop.
75+
_, err := argoutil.RefreshApp(ctrl.applicationClientset.ArgoprojV1alpha1().Applications(appNamespace), appName, appv1.RefreshTypeNormal, false)
76+
if err != nil {
77+
return fmt.Errorf("failed to request app refresh: %w", err)
78+
}
79+
return nil
7080
}
7181

7282
func (ctrl *ApplicationController) PersistAppHydratorStatus(orig *appv1.Application, newStatus *appv1.SourceHydratorStatus) {

pkg/apis/application/v1alpha1/types.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,13 @@ const (
464464
RefreshTypeHard RefreshType = "hard"
465465
)
466466

467+
type HydrateType string
468+
469+
const (
470+
// HydrateTypeNormal is a normal hydration
471+
HydrateTypeNormal HydrateType = "normal"
472+
)
473+
467474
type RefTarget struct {
468475
Repo Repository `protobuf:"bytes,1,opt,name=repo"`
469476
TargetRevision string `protobuf:"bytes,2,opt,name=targetRevision"`
@@ -3026,7 +3033,7 @@ func (app *Application) IsHydrateRequested() bool {
30263033
if !ok {
30273034
return false
30283035
}
3029-
if typeStr == "normal" {
3036+
if typeStr == string(HydrateTypeNormal) {
30303037
return true
30313038
}
30323039
return false

server/application/application.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -748,7 +748,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
748748
})
749749
defer unsubscribe()
750750

751-
app, err := argoutil.RefreshApp(appIf, appName, refreshType)
751+
app, err := argoutil.RefreshApp(appIf, appName, refreshType, true)
752752
if err != nil {
753753
return nil, fmt.Errorf("error refreshing the app: %w", err)
754754
}

util/argo/argo.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,18 @@ func FilterByNameP(apps []*argoappv1.Application, name string) []*argoappv1.Appl
226226
}
227227

228228
// RefreshApp updates the refresh annotation of an application to coerce the controller to process it
229-
func RefreshApp(appIf v1alpha1.ApplicationInterface, name string, refreshType argoappv1.RefreshType) (*argoappv1.Application, error) {
229+
func RefreshApp(appIf v1alpha1.ApplicationInterface, name string, refreshType argoappv1.RefreshType, hydrate bool) (*argoappv1.Application, error) {
230230
metadata := map[string]interface{}{
231231
"metadata": map[string]interface{}{
232232
"annotations": map[string]string{
233233
argoappv1.AnnotationKeyRefresh: string(refreshType),
234-
argoappv1.AnnotationKeyHydrate: "normal",
235234
},
236235
},
237236
}
237+
if hydrate {
238+
metadata["metadata"].(map[string]interface{})["annotations"].(map[string]string)[argoappv1.AnnotationKeyHydrate] = string(argoappv1.HydrateTypeNormal)
239+
}
240+
238241
var err error
239242
patch, err := json.Marshal(metadata)
240243
if err != nil {

util/argo/argo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func TestRefreshApp(t *testing.T) {
4141
testApp.Namespace = "default"
4242
appClientset := appclientset.NewSimpleClientset(&testApp)
4343
appIf := appClientset.ArgoprojV1alpha1().Applications("default")
44-
_, err := RefreshApp(appIf, "test-app", argoappv1.RefreshTypeNormal)
44+
_, err := RefreshApp(appIf, "test-app", argoappv1.RefreshTypeNormal, true)
4545
require.NoError(t, err)
4646
// For some reason, the fake Application interface doesn't reflect the patch status after Patch(),
4747
// so can't verify it was set in unit tests.

util/webhook/webhook.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ func (a *ArgoCDWebhookHandler) HandleEvent(payload interface{}) {
311311
refreshPaths := path.GetAppRefreshPaths(&app)
312312
if path.AppFilesHaveChanged(refreshPaths, changedFiles) {
313313
namespacedAppInterface := a.appClientset.ArgoprojV1alpha1().Applications(app.ObjectMeta.Namespace)
314-
_, err = argo.RefreshApp(namespacedAppInterface, app.ObjectMeta.Name, v1alpha1.RefreshTypeNormal)
314+
_, err = argo.RefreshApp(namespacedAppInterface, app.ObjectMeta.Name, v1alpha1.RefreshTypeNormal, true)
315315
if err != nil {
316316
log.Warnf("Failed to refresh app '%s' for controller reprocessing: %v", app.ObjectMeta.Name, err)
317317
continue

0 commit comments

Comments
 (0)