Skip to content

Commit 2a3c692

Browse files
authored
fix: Make change of tracking method work at runtime (#9820)
* fix: Make change of tracking method work at runtime Signed-off-by: jannfis <jann@mistrust.net> * GetAppName() will figure tracking label or annotation on its own Signed-off-by: jannfis <jann@mistrust.net> * Correct test comments and add another test Signed-off-by: jannfis <jann@mistrust.net> * Add a read lock before getting cache settings Signed-off-by: jannfis <jann@mistrust.net>
1 parent f34687b commit 2a3c692

File tree

7 files changed

+219
-4
lines changed

7 files changed

+219
-4
lines changed

controller/cache/cache.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ func NewLiveStateCache(
176176
type cacheSettings struct {
177177
clusterSettings clustercache.Settings
178178
appInstanceLabelKey string
179+
trackingMethod appv1.TrackingMethod
179180
}
180181

181182
type liveStateCache struct {
@@ -210,7 +211,7 @@ func (c *liveStateCache) loadCacheSettings() (*cacheSettings, error) {
210211
ResourceHealthOverride: lua.ResourceHealthOverrides(resourceOverrides),
211212
ResourcesFilter: resourcesFilter,
212213
}
213-
return &cacheSettings{clusterSettings, appInstanceLabelKey}, nil
214+
return &cacheSettings{clusterSettings, appInstanceLabelKey, argo.GetTrackingMethod(c.settingsMgr)}, nil
214215
}
215216

216217
func asResourceNode(r *clustercache.Resource) appv1.ResourceNode {
@@ -388,7 +389,6 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
388389
return nil, fmt.Errorf("controller is configured to ignore cluster %s", cluster.Server)
389390
}
390391

391-
trackingMethod := argo.GetTrackingMethod(c.settingsMgr)
392392
clusterCacheOpts := []clustercache.UpdateSettingsFunc{
393393
clustercache.SetListSemaphore(semaphore.NewWeighted(clusterCacheListSemaphoreSize)),
394394
clustercache.SetListPageSize(clusterCacheListPageSize),
@@ -401,9 +401,12 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
401401
clustercache.SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (interface{}, bool) {
402402
res := &ResourceInfo{}
403403
populateNodeInfo(un, res)
404+
c.lock.RLock()
405+
cacheSettings := c.cacheSettings
406+
c.lock.RUnlock()
404407
res.Health, _ = health.GetResourceHealth(un, cacheSettings.clusterSettings.ResourceHealthOverride)
405408

406-
appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, trackingMethod)
409+
appName := c.resourceTracking.GetAppName(un, cacheSettings.appInstanceLabelKey, cacheSettings.trackingMethod)
407410
if isRoot && appName != "" {
408411
res.AppName = appName
409412
}

test/e2e/app_management_test.go

+187
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
projectFixture "github.com/argoproj/argo-cd/v2/test/e2e/fixture/project"
3939
repoFixture "github.com/argoproj/argo-cd/v2/test/e2e/fixture/repos"
4040
"github.com/argoproj/argo-cd/v2/test/e2e/testdata"
41+
"github.com/argoproj/argo-cd/v2/util/argo"
4142
. "github.com/argoproj/argo-cd/v2/util/argo"
4243
. "github.com/argoproj/argo-cd/v2/util/errors"
4344
"github.com/argoproj/argo-cd/v2/util/io"
@@ -2063,3 +2064,189 @@ func TestDisableManifestGeneration(t *testing.T) {
20632064
assert.Equal(t, app.Status.SourceType, ApplicationSourceTypeDirectory)
20642065
})
20652066
}
2067+
2068+
func TestSwitchTrackingMethod(t *testing.T) {
2069+
ctx := Given(t)
2070+
2071+
ctx.
2072+
SetTrackingMethod(string(argo.TrackingMethodAnnotation)).
2073+
Path("deployment").
2074+
When().
2075+
CreateApp().
2076+
Sync().
2077+
Refresh(RefreshTypeNormal).
2078+
Then().
2079+
Expect(OperationPhaseIs(OperationSucceeded)).
2080+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2081+
Expect(HealthIs(health.HealthStatusHealthy)).
2082+
When().
2083+
And(func() {
2084+
// Add resource with tracking annotation. This should put the
2085+
// application OutOfSync.
2086+
FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{
2087+
ObjectMeta: metav1.ObjectMeta{
2088+
Name: "other-configmap",
2089+
Annotations: map[string]string{
2090+
common.AnnotationKeyAppInstance: fmt.Sprintf("%s:/ConfigMap:%s/other-configmap", Name(), DeploymentNamespace()),
2091+
},
2092+
},
2093+
}, metav1.CreateOptions{}))
2094+
}).
2095+
Then().
2096+
Expect(OperationPhaseIs(OperationSucceeded)).
2097+
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
2098+
Expect(HealthIs(health.HealthStatusHealthy)).
2099+
When().
2100+
And(func() {
2101+
// Delete resource to bring application back in sync
2102+
FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "other-configmap", metav1.DeleteOptions{}))
2103+
}).
2104+
Then().
2105+
Expect(OperationPhaseIs(OperationSucceeded)).
2106+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2107+
Expect(HealthIs(health.HealthStatusHealthy)).
2108+
When().
2109+
SetTrackingMethod(string(argo.TrackingMethodLabel)).
2110+
Sync().
2111+
Then().
2112+
Expect(OperationPhaseIs(OperationSucceeded)).
2113+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2114+
Expect(HealthIs(health.HealthStatusHealthy)).
2115+
When().
2116+
And(func() {
2117+
// Add a resource with a tracking annotation. This should not
2118+
// affect the application, because we now use the tracking method
2119+
// "label".
2120+
FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{
2121+
ObjectMeta: metav1.ObjectMeta{
2122+
Name: "other-configmap",
2123+
Annotations: map[string]string{
2124+
common.AnnotationKeyAppInstance: fmt.Sprintf("%s:/ConfigMap:%s/other-configmap", Name(), DeploymentNamespace()),
2125+
},
2126+
},
2127+
}, metav1.CreateOptions{}))
2128+
}).
2129+
Then().
2130+
Expect(OperationPhaseIs(OperationSucceeded)).
2131+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2132+
Expect(HealthIs(health.HealthStatusHealthy)).
2133+
When().
2134+
And(func() {
2135+
// Add a resource with the tracking label. The app should become
2136+
// OutOfSync.
2137+
FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{
2138+
ObjectMeta: metav1.ObjectMeta{
2139+
Name: "extra-configmap",
2140+
Labels: map[string]string{
2141+
common.LabelKeyAppInstance: Name(),
2142+
},
2143+
},
2144+
}, metav1.CreateOptions{}))
2145+
}).
2146+
Then().
2147+
Expect(OperationPhaseIs(OperationSucceeded)).
2148+
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
2149+
Expect(HealthIs(health.HealthStatusHealthy)).
2150+
When().
2151+
And(func() {
2152+
// Delete resource to bring application back in sync
2153+
FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "extra-configmap", metav1.DeleteOptions{}))
2154+
}).
2155+
Then().
2156+
Expect(OperationPhaseIs(OperationSucceeded)).
2157+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2158+
Expect(HealthIs(health.HealthStatusHealthy))
2159+
}
2160+
2161+
func TestSwitchTrackingLabel(t *testing.T) {
2162+
ctx := Given(t)
2163+
2164+
ctx.
2165+
Path("deployment").
2166+
When().
2167+
CreateApp().
2168+
Sync().
2169+
Refresh(RefreshTypeNormal).
2170+
Then().
2171+
Expect(OperationPhaseIs(OperationSucceeded)).
2172+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2173+
Expect(HealthIs(health.HealthStatusHealthy)).
2174+
When().
2175+
And(func() {
2176+
// Add extra resource that carries the default tracking label
2177+
// We expect the app to go out of sync.
2178+
FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{
2179+
ObjectMeta: metav1.ObjectMeta{
2180+
Name: "other-configmap",
2181+
Labels: map[string]string{
2182+
common.LabelKeyAppInstance: Name(),
2183+
},
2184+
},
2185+
}, metav1.CreateOptions{}))
2186+
}).
2187+
Then().
2188+
Expect(OperationPhaseIs(OperationSucceeded)).
2189+
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
2190+
Expect(HealthIs(health.HealthStatusHealthy)).
2191+
When().
2192+
And(func() {
2193+
// Delete resource to bring application back in sync
2194+
FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "other-configmap", metav1.DeleteOptions{}))
2195+
}).
2196+
Then().
2197+
Expect(OperationPhaseIs(OperationSucceeded)).
2198+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2199+
Expect(HealthIs(health.HealthStatusHealthy)).
2200+
When().
2201+
// Change tracking label
2202+
SetTrackingLabel("argocd.tracking").
2203+
Sync().
2204+
Then().
2205+
Expect(OperationPhaseIs(OperationSucceeded)).
2206+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2207+
Expect(HealthIs(health.HealthStatusHealthy)).
2208+
When().
2209+
And(func() {
2210+
// Create resource with the new tracking label, the application
2211+
// is expected to go out of sync
2212+
FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{
2213+
ObjectMeta: metav1.ObjectMeta{
2214+
Name: "other-configmap",
2215+
Labels: map[string]string{
2216+
"argocd.tracking": Name(),
2217+
},
2218+
},
2219+
}, metav1.CreateOptions{}))
2220+
}).
2221+
Then().
2222+
Expect(OperationPhaseIs(OperationSucceeded)).
2223+
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
2224+
Expect(HealthIs(health.HealthStatusHealthy)).
2225+
When().
2226+
And(func() {
2227+
// Delete resource to bring application back in sync
2228+
FailOnErr(nil, KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Delete(context.Background(), "other-configmap", metav1.DeleteOptions{}))
2229+
}).
2230+
Then().
2231+
Expect(OperationPhaseIs(OperationSucceeded)).
2232+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2233+
Expect(HealthIs(health.HealthStatusHealthy)).
2234+
When().
2235+
And(func() {
2236+
// Add extra resource that carries the default tracking label
2237+
// We expect the app to stay in sync, because the configured
2238+
// label is different.
2239+
FailOnErr(KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Create(context.Background(), &v1.ConfigMap{
2240+
ObjectMeta: metav1.ObjectMeta{
2241+
Name: "other-configmap",
2242+
Labels: map[string]string{
2243+
common.LabelKeyAppInstance: Name(),
2244+
},
2245+
},
2246+
}, metav1.CreateOptions{}))
2247+
}).
2248+
Then().
2249+
Expect(OperationPhaseIs(OperationSucceeded)).
2250+
Expect(SyncStatusIs(SyncStatusCodeSynced)).
2251+
Expect(HealthIs(health.HealthStatusHealthy))
2252+
}

test/e2e/fixture/app/actions.go

+10
Original file line numberDiff line numberDiff line change
@@ -341,3 +341,13 @@ func (a *Actions) verifyAction() {
341341
a.Then().Expect(Success(""))
342342
}
343343
}
344+
345+
func (a *Actions) SetTrackingMethod(trackingMethod string) *Actions {
346+
fixture.SetTrackingMethod(trackingMethod)
347+
return a
348+
}
349+
350+
func (a *Actions) SetTrackingLabel(trackingLabel string) *Actions {
351+
fixture.SetTrackingLabel(trackingLabel)
352+
return a
353+
}

test/e2e/fixture/app/context.go

+5
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,8 @@ func (c *Context) HelmSkipCrds() *Context {
308308
c.helmSkipCrds = true
309309
return c
310310
}
311+
312+
func (c *Context) SetTrackingMethod(trackingMethod string) *Context {
313+
fixture.SetTrackingMethod(trackingMethod)
314+
return c
315+
}

test/e2e/fixture/fixture.go

+7
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,13 @@ func SetTrackingMethod(trackingMethod string) {
357357
})
358358
}
359359

360+
func SetTrackingLabel(trackingLabel string) {
361+
updateSettingConfigMap(func(cm *corev1.ConfigMap) error {
362+
cm.Data["application.instanceLabelKey"] = trackingLabel
363+
return nil
364+
})
365+
}
366+
360367
func SetResourceOverridesSplitKeys(overrides map[string]v1alpha1.ResourceOverride) {
361368
updateSettingConfigMap(func(cm *corev1.ConfigMap) error {
362369
for k, v := range overrides {

util/argo/resource_tracking.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func NewResourceTracking() ResourceTracking {
5454
// GetTrackingMethod retrieve tracking method from settings
5555
func GetTrackingMethod(settingsMgr *settings.SettingsManager) v1alpha1.TrackingMethod {
5656
tm, err := settingsMgr.GetTrackingMethod()
57-
if err != nil {
57+
if err != nil || tm == "" {
5858
return TrackingMethodLabel
5959
}
6060
return v1alpha1.TrackingMethod(tm)

util/settings/settings.go

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ type ArgoCDSettings struct {
9999
ServerRBACLogEnforceEnable bool `json:"serverRBACLogEnforceEnable"`
100100
// ExecEnabled indicates whether the UI exec feature is enabled
101101
ExecEnabled bool `json:"execEnabled"`
102+
// TrackingMethod defines the resource tracking method to be used
103+
TrackingMethod string `json:"application.resourceTrackingMethod,omitempty"`
102104
}
103105

104106
type GoogleAnalytics struct {
@@ -1271,6 +1273,7 @@ func updateSettingsFromConfigMap(settings *ArgoCDSettings, argoCDCM *apiv1.Confi
12711273
}
12721274
settings.InClusterEnabled = argoCDCM.Data[inClusterEnabledKey] != "false"
12731275
settings.ExecEnabled = argoCDCM.Data[execEnabledKey] == "true"
1276+
settings.TrackingMethod = argoCDCM.Data[settingsResourceTrackingMethodKey]
12741277
}
12751278

12761279
// validateExternalURL ensures the external URL that is set on the configmap is valid

0 commit comments

Comments
 (0)