Skip to content

Commit a5b90e0

Browse files
committed
fix: limit number of resources in appset status (argoproj#24690)
Signed-off-by: Alexander Matyushentsev <[email protected]>
1 parent 531d96e commit a5b90e0

15 files changed

+157
-11
lines changed

applicationset/controllers/applicationset_controller.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ type ApplicationSetReconciler struct {
9191
GlobalPreservedAnnotations []string
9292
GlobalPreservedLabels []string
9393
Metrics *metrics.ApplicationsetMetrics
94+
MaxResourcesStatusCount int
9495
}
9596

9697
// +kubebuilder:rbac:groups=argoproj.io,resources=applicationsets,verbs=get;list;watch;create;update;patch;delete
@@ -1303,6 +1304,11 @@ func (r *ApplicationSetReconciler) updateResourcesStatus(ctx context.Context, lo
13031304
sort.Slice(statuses, func(i, j int) bool {
13041305
return statuses[i].Name < statuses[j].Name
13051306
})
1307+
1308+
if r.MaxResourcesStatusCount > 0 && len(statuses) > r.MaxResourcesStatusCount {
1309+
logCtx.Warnf("Truncating ApplicationSet %s resource status from %d to max allowed %d entries", appset.Name, len(statuses), r.MaxResourcesStatusCount)
1310+
statuses = statuses[:r.MaxResourcesStatusCount]
1311+
}
13061312
appset.Status.Resources = statuses
13071313
// DefaultRetry will retry 5 times with a backoff factor of 1, jitter of 0.1 and a duration of 10ms
13081314
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {

applicationset/controllers/applicationset_controller_test.go

Lines changed: 80 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6116,10 +6116,11 @@ func TestUpdateResourceStatus(t *testing.T) {
61166116
require.NoError(t, err)
61176117

61186118
for _, cc := range []struct {
6119-
name string
6120-
appSet v1alpha1.ApplicationSet
6121-
apps []v1alpha1.Application
6122-
expectedResources []v1alpha1.ResourceStatus
6119+
name string
6120+
appSet v1alpha1.ApplicationSet
6121+
apps []v1alpha1.Application
6122+
expectedResources []v1alpha1.ResourceStatus
6123+
maxResourcesStatusCount int
61236124
}{
61246125
{
61256126
name: "handles an empty application list",
@@ -6290,6 +6291,73 @@ func TestUpdateResourceStatus(t *testing.T) {
62906291
apps: []v1alpha1.Application{},
62916292
expectedResources: nil,
62926293
},
6294+
{
6295+
name: "truncates resources status list to",
6296+
appSet: v1alpha1.ApplicationSet{
6297+
ObjectMeta: metav1.ObjectMeta{
6298+
Name: "name",
6299+
Namespace: "argocd",
6300+
},
6301+
Status: v1alpha1.ApplicationSetStatus{
6302+
Resources: []v1alpha1.ResourceStatus{
6303+
{
6304+
Name: "app1",
6305+
Status: v1alpha1.SyncStatusCodeOutOfSync,
6306+
Health: &v1alpha1.HealthStatus{
6307+
Status: health.HealthStatusProgressing,
6308+
Message: "this is progressing",
6309+
},
6310+
},
6311+
{
6312+
Name: "app2",
6313+
Status: v1alpha1.SyncStatusCodeOutOfSync,
6314+
Health: &v1alpha1.HealthStatus{
6315+
Status: health.HealthStatusProgressing,
6316+
Message: "this is progressing",
6317+
},
6318+
},
6319+
},
6320+
},
6321+
},
6322+
apps: []v1alpha1.Application{
6323+
{
6324+
ObjectMeta: metav1.ObjectMeta{
6325+
Name: "app1",
6326+
},
6327+
Status: v1alpha1.ApplicationStatus{
6328+
Sync: v1alpha1.SyncStatus{
6329+
Status: v1alpha1.SyncStatusCodeSynced,
6330+
},
6331+
Health: v1alpha1.AppHealthStatus{
6332+
Status: health.HealthStatusHealthy,
6333+
},
6334+
},
6335+
},
6336+
{
6337+
ObjectMeta: metav1.ObjectMeta{
6338+
Name: "app2",
6339+
},
6340+
Status: v1alpha1.ApplicationStatus{
6341+
Sync: v1alpha1.SyncStatus{
6342+
Status: v1alpha1.SyncStatusCodeSynced,
6343+
},
6344+
Health: v1alpha1.AppHealthStatus{
6345+
Status: health.HealthStatusHealthy,
6346+
},
6347+
},
6348+
},
6349+
},
6350+
expectedResources: []v1alpha1.ResourceStatus{
6351+
{
6352+
Name: "app1",
6353+
Status: v1alpha1.SyncStatusCodeSynced,
6354+
Health: &v1alpha1.HealthStatus{
6355+
Status: health.HealthStatusHealthy,
6356+
},
6357+
},
6358+
},
6359+
maxResourcesStatusCount: 1,
6360+
},
62936361
} {
62946362
t.Run(cc.name, func(t *testing.T) {
62956363
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
@@ -6300,13 +6368,14 @@ func TestUpdateResourceStatus(t *testing.T) {
63006368
argodb := db.NewDB("argocd", settings.NewSettingsManager(t.Context(), kubeclientset, "argocd"), kubeclientset)
63016369

63026370
r := ApplicationSetReconciler{
6303-
Client: client,
6304-
Scheme: scheme,
6305-
Recorder: record.NewFakeRecorder(1),
6306-
Generators: map[string]generators.Generator{},
6307-
ArgoDB: argodb,
6308-
KubeClientset: kubeclientset,
6309-
Metrics: metrics,
6371+
Client: client,
6372+
Scheme: scheme,
6373+
Recorder: record.NewFakeRecorder(1),
6374+
Generators: map[string]generators.Generator{},
6375+
ArgoDB: argodb,
6376+
KubeClientset: kubeclientset,
6377+
Metrics: metrics,
6378+
MaxResourcesStatusCount: cc.maxResourcesStatusCount,
63106379
}
63116380

63126381
err := r.updateResourcesStatus(t.Context(), log.NewEntry(log.StandardLogger()), &cc.appSet, cc.apps)

cmd/argocd-applicationset-controller/commands/applicationset_controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func NewCommand() *cobra.Command {
7474
enableScmProviders bool
7575
webhookParallelism int
7676
tokenRefStrictMode bool
77+
maxResourcesStatusCount int
7778
)
7879
scheme := runtime.NewScheme()
7980
_ = clientgoscheme.AddToScheme(scheme)
@@ -225,6 +226,7 @@ func NewCommand() *cobra.Command {
225226
GlobalPreservedAnnotations: globalPreservedAnnotations,
226227
GlobalPreservedLabels: globalPreservedLabels,
227228
Metrics: &metrics,
229+
MaxResourcesStatusCount: maxResourcesStatusCount,
228230
}).SetupWithManager(mgr, enableProgressiveSyncs, maxConcurrentReconciliations); err != nil {
229231
log.Error(err, "unable to create controller", "controller", "ApplicationSet")
230232
os.Exit(1)
@@ -268,6 +270,7 @@ func NewCommand() *cobra.Command {
268270
command.Flags().StringSliceVar(&globalPreservedLabels, "preserved-labels", env.StringsFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS", []string{}, ","), "Sets global preserved field values for labels")
269271
command.Flags().IntVar(&webhookParallelism, "webhook-parallelism-limit", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_WEBHOOK_PARALLELISM_LIMIT", 50, 1, 1000), "Number of webhook requests processed concurrently")
270272
command.Flags().StringSliceVar(&metricsAplicationsetLabels, "metrics-applicationset-labels", []string{}, "List of Application labels that will be added to the argocd_applicationset_labels metric")
273+
command.Flags().IntVar(&maxResourcesStatusCount, "max-resources-status-count", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT", 0, 0, math.MaxInt), "Max number of resources stored in appset status.")
271274
return &command
272275
}
273276

docs/operator-manual/argocd-cmd-params-cm.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,8 @@ data:
284284
applicationsetcontroller.global.preserved.annotations: "acme.com/annotation1,acme.com/annotation2"
285285
# Comma delimited list of labels to preserve in generated applications
286286
applicationsetcontroller.global.preserved.labels: "acme.com/label1,acme.com/label2"
287+
# The maximum number of resources stored in the status of an ApplicationSet. This is a safeguard to prevent the status from growing too large.
288+
applicationsetcontroller.status.max.resources.count: "5000"
287289

288290
## Argo CD Notifications Controller Properties
289291
# Set the logging level. One of: debug|info|warn|error (default "info")

manifests/base/applicationset-controller/argocd-applicationset-controller-deployment.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ spec:
181181
name: argocd-cmd-params-cm
182182
key: applicationsetcontroller.requeue.after
183183
optional: true
184+
- name: ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT
185+
valueFrom:
186+
configMapKeyRef:
187+
name: argocd-cmd-params-cm
188+
key: applicationsetcontroller.status.max.resources.count
189+
optional: true
184190
volumeMounts:
185191
- mountPath: /app/config/ssh
186192
name: ssh-known-hosts

manifests/core-install-with-hydrator.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manifests/core-install.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manifests/ha/install-with-hydrator.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manifests/ha/install.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

manifests/ha/namespace-install-with-hydrator.yaml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)