Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): make deep copies of objects returned by informers (#22173) #22179

Merged
merged 22 commits into from
Mar 10, 2025

Conversation

rumstead
Copy link
Member

@rumstead rumstead commented Mar 4, 2025

closes #22173

Checklist:

  • Either (a) I've created an enhancement proposal and discussed it with the community, (b) this is a bug fix, or (c) this does not need to be in the release notes.
  • The title of the PR states what changed and the related issues number (used for the release note).
  • The title of the PR conforms to the Toolchain Guide
  • I've included "Closes [ISSUE #]" or "Fixes [ISSUE #]" in the description to automatically close the associated issue.
  • I've updated both the CLI and UI to expose my feature, or I plan to submit a second PR with them.
  • Does this PR require documentation updates?
  • I've updated documentation as required by this PR.
  • I have signed off all my commits as required by DCO
  • I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
  • My build is green (troubleshooting builds).
  • My new feature complies with the feature status guidelines.
  • I have added a brief description of why this PR is necessary and/or what this PR solves.
  • Optional. My organization is added to USERS.md.
  • Optional. For bug fixes, I've indicated what older releases this fix should be cherry-picked into (this may or may not happen depending on risk/complexity).

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
@rumstead rumstead requested a review from a team as a code owner March 4, 2025 21:27
Copy link

bunnyshell bot commented Mar 4, 2025

❗ Preview Environment delete from Bunnyshell failed

See: Environment Details | Pipeline Logs

Available commands (reply to this comment):

  • 🚀 /bns:deploy to redeploy the environment
  • /bns:delete to try again to remove the environment

@rumstead rumstead changed the title feat(server): make deep copies of objects returned by informers feat(server): make deep copies of objects returned by informers (#22173) Mar 4, 2025
@rumstead
Copy link
Member Author

rumstead commented Mar 4, 2025

Another way we could go about this is to wrap the informers. Maybe something like this:

package application

import (
	"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
	applisters "github.com/argoproj/argo-cd/v3/pkg/client/listers/application/v1alpha1"

	"k8s.io/apimachinery/pkg/labels"
)

// deepCopyApplicationLister wraps an ApplicationLister and returns deep copies of the applications.
type deepCopyApplicationLister struct {
	applisters.ApplicationLister
}

// List lists all Applications in the indexer and returns deep copies.
func (d *deepCopyApplicationLister) List(selector labels.Selector) ([]*v1alpha1.Application, error) {
	apps, err := d.ApplicationLister.List(selector)
	if err != nil {
		return nil, err
	}
	deepCopiedApps := make([]*v1alpha1.Application, len(apps))
	for i, app := range apps {
		deepCopiedApps[i] = app.DeepCopy()
	}
	return deepCopiedApps, nil
}

// Applications returns an object that can list and get Applications and returns deep copies.
func (d *deepCopyApplicationLister) Applications(namespace string) applisters.ApplicationNamespaceLister {
	return &deepCopyApplicationNamespaceLister{
		ApplicationNamespaceLister: d.ApplicationLister.Applications(namespace),
	}
}

// deepCopyApplicationNamespaceLister wraps an ApplicationNamespaceLister and returns deep copies of the applications.
type deepCopyApplicationNamespaceLister struct {
	applisters.ApplicationNamespaceLister
}

// List lists all Applications in the indexer for a given namespace and returns deep copies.
func (d *deepCopyApplicationNamespaceLister) List(selector labels.Selector) ([]*v1alpha1.Application, error) {
	apps, err := d.ApplicationNamespaceLister.List(selector)
	if err != nil {
		return nil, err
	}
	deepCopiedApps := make([]*v1alpha1.Application, len(apps))
	for i, app := range apps {
		deepCopiedApps[i] = app.DeepCopy()
	}
	return deepCopiedApps, nil
}

// Get retrieves the Application from the indexer for a given namespace and name and returns a deep copy.
func (d *deepCopyApplicationNamespaceLister) Get(name string) (*v1alpha1.Application, error) {
	app, err := d.ApplicationNamespaceLister.Get(name)
	if err != nil {
		return nil, err
	}
	return app.DeepCopy(), nil
}

@crenshaw-dev
Copy link
Member

I think I like the wrapping idea... seems better than sprinkling deep copies across the code base.

Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
@rumstead rumstead marked this pull request as draft March 5, 2025 14:23
rumstead added 11 commits March 5, 2025 10:42
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
@rumstead rumstead marked this pull request as ready for review March 5, 2025 21:04
@rumstead rumstead requested a review from gdsoumya March 5, 2025 21:10
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
@@ -888,7 +882,7 @@ func (s *Server) ListResourceEvents(ctx context.Context, q *application.Applicat
if err != nil {
return nil, fmt.Errorf("error listing resource events: %w", err)
}
return list, nil
return list.DeepCopy(), nil
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to wrap the kubernetes.Interface i think is too large of a task :-p. there are so too many methods.

Copy link

codecov bot commented Mar 5, 2025

Codecov Report

Attention: Patch coverage is 81.39535% with 16 lines in your changes missing coverage. Please review.

Please upload report for BASE (master@fbd7f29). Learn more about missing BASE report.
Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
server/application/deepinformer.go 81.25% 10 Missing and 5 partials ⚠️
server/application/application.go 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##             master   #22179   +/-   ##
=========================================
  Coverage          ?   55.84%           
=========================================
  Files             ?      343           
  Lines             ?    57290           
  Branches          ?        0           
=========================================
  Hits              ?    31996           
  Misses            ?    22650           
  Partials          ?     2644           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

rumstead added 3 commits March 6, 2025 10:09
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
Signed-off-by: rumstead <37445536+rumstead@users.noreply.github.com>
@@ -3350,3 +3351,106 @@ func Test_RevisionMetadata(t *testing.T) {
})
}
}

func Test_DeepCopyInformers(t *testing.T) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the "real" test. Ensuring the deep copy informers return an actual deep copy.

Copy link
Member

@gdsoumya gdsoumya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rumstead rumstead enabled auto-merge (squash) March 10, 2025 13:42
@rumstead rumstead merged commit e3bd569 into argoproj:master Mar 10, 2025
26 checks passed
@rumstead rumstead deleted the fix/appinformers-should-return-copy branch March 10, 2025 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Argo CD Server Informers returning non-readonly objects
3 participants