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

fix: do not allow user to pick the same resource twice #1098

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

ryanzhang-oss
Copy link
Contributor

@ryanzhang-oss ryanzhang-oss commented Mar 25, 2025

Description of your changes

  1. Add the check in the resource selector to block duplication
  2. Add a few e2e that is missing from previous PR

I have:

  • Run make reviewable to ensure this PR is ready for review.

How has this code been tested

Special notes for your reviewer

@ryanzhang-oss ryanzhang-oss marked this pull request as draft March 25, 2025 23:50
@ryanzhang-oss ryanzhang-oss force-pushed the fix-duplicate-resource-select branch from 172c13a to 25efa7c Compare March 26, 2025 20:21
@ryanzhang-oss ryanzhang-oss requested a review from Copilot March 27, 2025 17:29
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR prevents users from selecting the same resource more than once by detecting duplicates and returning an error, and updates related tests to verify the behavior.

  • Introduces duplicate resource detection logic in the resource selector to error out on repeated selections.
  • Updates e2e tests and resource override tests to reflect the requirement of unique resource selections.
  • Adjusts error handling in the controller to requeue after a delay when a duplicate is detected.

Reviewed Changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/e2e/placement_selecting_resources_test.go Adds a focused test case to verify that duplicate resource selection produces the expected status update.
test/e2e/placement_ro_test.go Adjusts test messages and injects Placement references for resource override scenarios.
test/e2e/actuals_test.go Improves error messaging by including cluster name details.
pkg/controllers/clusterresourceplacement/resource_selector_test.go Updates tests to work with unstructured objects and maintain order for resource selection.
pkg/controllers/clusterresourceplacement/resource_selector.go Implements duplicate detection in resource selection and refines resource sorting logic.
pkg/controllers/clusterresourceplacement/controller.go Modifies error handling to requeue updates after a duplicate resource error is encountered.
Files not reviewed (1)
  • Makefile: Language not supported
Comments suppressed due to low confidence (2)

pkg/controllers/clusterresourceplacement/resource_selector.go:105

  • [nitpick] Enhance the duplicate resource error message to include details such as the resource's name and kind to improve debuggability for users.
if _, exist := resourceMap[ri]; exist {

pkg/controllers/clusterresourceplacement/resource_selector_test.go:924

  • [nitpick] Consider adding a dedicated unit test case for gatherSelectedResource to verify that the function returns an error when duplicate resources are provided.
tests := map[string]struct {

@ryanzhang-oss ryanzhang-oss force-pushed the fix-duplicate-resource-select branch from 90ee8bc to 12d903b Compare March 28, 2025 21:17
@ryanzhang-oss ryanzhang-oss force-pushed the fix-duplicate-resource-select branch from 12d903b to e6d2395 Compare March 28, 2025 21:34
@ryanzhang-oss ryanzhang-oss marked this pull request as ready for review March 28, 2025 21:34
@ryanzhang-oss ryanzhang-oss requested a review from Copilot March 28, 2025 23:40
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR prevents users from selecting the same resource more than once by detecting duplicates in the resource selectors and updating the CRP status accordingly. Key changes include:

  • Adding an end-to-end test to verify that duplicated resource selection is rejected.
  • Updating tests in resourceOverride flows to include the Placement reference and improve error messages.
  • Refactoring resource selection logic to return unstructured objects and check for duplicate resource identifiers.

Reviewed Changes

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/e2e/placement_selecting_resources_test.go Adds a new e2e test case for duplicated resource selection, expecting an invalid CRP status.
test/e2e/placement_ro_test.go Updates tests by adding Placement refs and revising test descriptions for clarity in resourceOverride scenarios.
test/e2e/actuals_test.go Improves error message details by including the member cluster name when a namespace is not removed.
pkg/controllers/clusterresourceplacement/resource_selector_test.go Modifies tests to use unstructured objects instead of runtime.Object for consistency.
pkg/controllers/clusterresourceplacement/resource_selector.go Refactors resource gathering to enforce uniqueness and sorts resources with simplified code.
pkg/controllers/clusterresourceplacement/controller.go Adjusts the error handling by requeuing after a fixed delay to allow user correction.
Files not reviewed (1)
  • Makefile: Language not supported

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Co-authored-by: Copilot <[email protected]>
@Azure Azure deleted a comment from kaito-pr-agent bot Mar 29, 2025
Copy link

Title

fix: do not allow user to pick the same resource twice


User description

Description of your changes

Fixes #

I have:

  • Run make reviewable to ensure this PR is ready for review.

How has this code been tested

Special notes for your reviewer


PR Type

Enhancement


Description

  • Added validation to prevent users from selecting the same resource twice in ClusterResourcePlacement.

  • Updated test cases to include scenarios where resources are selected multiple times.

  • Enhanced error handling to return a specific error when duplicate resources are detected.

  • Modified the sorting logic to ensure stability across reconcile loops.


Changes walkthrough 📝

Relevant files
Bug fix
3 files
controller.go
Handle duplicate resource selection                                           
+2/-1     
resource_selector.go
Validate resource selection uniqueness                                     
+26/-11 
actuals_test.go
Improve error message for work namespace removal                 
+1/-1     
Tests
3 files
resource_selector_test.go
Add test cases for duplicate resource selection                   
+24/-24 
placement_ro_test.go
Add test cases for resourceOverride with multiple overrides
+230/-3 
placement_selecting_resources_test.go
Add test case for picking N resources with duplicates       
+65/-0   
Formatting
1 files
Makefile
Bump staticcheck version                                                                 
+1/-1     

Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    **🎫 Ticket compliance analysis **

     Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 PR contains tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Potential Bug

    The new code adds a delay of 5 minutes before requeuing, which might not be necessary.

    // no need to retry faster, the user needs to fix the resource selectors
    return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil
    Potential Bug

    The new test cases for handling duplicate resources should include assertions to verify the expected behavior.

    	It("should remove controller finalizers from CRP", func() {
    		finalizerRemovedActual := allFinalizersExceptForCustomDeletionBlockerRemovedFromCRPActual(crpName)
    		Eventually(finalizerRemovedActual, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to remove controller finalizers from CRP %s", crpName)
    	})
    })
    
    var _ = Describe("When creating a pickN ClusterResourcePlacement with duplicated resources", Ordered, func() {
    	crpName := fmt.Sprintf(crpNameTemplate, GinkgoParallelProcess())
    	var existingNS corev1.Namespace
    	BeforeAll(func() {
    		By("creating work resources on hub cluster")
    		createWorkResources()
    		existingNS = appNamespace()
    		By("Create a crp that selects the same resource twice")
    		crp := &placementv1beta1.ClusterResourcePlacement{
    			ObjectMeta: metav1.ObjectMeta{
    				Name: crpName,
    				// Add a custom finalizer; this would allow us to better observe
    				// the behavior of the controllers.
    				Finalizers: []string{customDeletionBlockerFinalizer},
    			},
    			Spec: placementv1beta1.ClusterResourcePlacementSpec{
    				ResourceSelectors: []placementv1beta1.ClusterResourceSelector{
    					{
    						Group:   corev1.GroupName,
    						Version: "v1",
    						Kind:    "Namespace",
    						Name:    existingNS.Name,
    					},
    					{
    						Group:   corev1.GroupName,
    						Version: "v1",
    						Kind:    "Namespace",
    						Name:    existingNS.Name,
    					},
    				},
    			},
    		}
    		By(fmt.Sprintf("creating placement %s", crpName))
    		Expect(hubClient.Create(ctx, crp)).To(Succeed(), "Failed to create CRP %s", crpName)
    	})
    
    	AfterAll(func() {
    		By(fmt.Sprintf("garbage all things related to placement %s", crpName))
    		ensureCRPAndRelatedResourcesDeleted(crpName, allMemberClusters)
    	})
    
    	It("should update CRP status as expected", func() {
    		Eventually(func() error {
    			crp := &placementv1beta1.ClusterResourcePlacement{}
    			if err := hubClient.Get(ctx, types.NamespacedName{Name: crpName}, crp); err != nil {
    				return err
    			}
    			wantStatus := placementv1beta1.ClusterResourcePlacementStatus{
    				Conditions: []metav1.Condition{
    					{
    						Status:             metav1.ConditionFalse,
    						Type:               string(placementv1beta1.ClusterResourcePlacementScheduledConditionType),
    						Reason:             clusterresourceplacement.InvalidResourceSelectorsReason,
    						ObservedGeneration: 1,
    					},
    				},
    			}
    			if diff := cmp.Diff(crp.Status, wantStatus, crpStatusCmpOptions...); diff != "" {
    				return fmt.Errorf("CRP status diff (-got, +want): %s", diff)
    			}
    			return nil
    		}, eventuallyDuration, eventuallyInterval).Should(Succeed(), "Failed to update CRP %s status as expected", crpName)
    	})
    })

    Copy link
    Contributor

    @jwtty jwtty left a comment

    Choose a reason for hiding this comment

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

    lgtm

    @@ -177,7 +177,8 @@ func (r *Reconciler) handleUpdate(ctx context.Context, crp *fleetv1beta1.Cluster
    klog.ErrorS(updateErr, "Failed to update the status", "clusterResourcePlacement", crpKObj)
    return ctrl.Result{}, controller.NewUpdateIgnoreConflictError(updateErr)
    }
    return ctrl.Result{}, err
    // no need to retry faster, the user needs to fix the resource selectors
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    there could be some api server errors returned from selectResourcesForPlacement func. Should we keep the existing backoff?

    }
    if _, exist := resourceMap[ri]; exist {
    err = fmt.Errorf("found duplicate resource %+v", ri)
    klog.ErrorS(err, "user selected one resource more than once", "resource", ri, "placement", placement)
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    Suggested change
    klog.ErrorS(err, "user selected one resource more than once", "resource", ri, "placement", placement)
    klog.ErrorS(err, "User selected one resource more than once", "resource", ri, "placement", placement)

    @@ -201,6 +201,9 @@ var _ = Context("creating resourceOverride with multiple jsonPatchOverrides to o
    Namespace: roNamespace,
    },
    Spec: placementv1alpha1.ResourceOverrideSpec{
    Placement: &placementv1alpha1.PlacementRef{
    Name: crpName, // assigned CRP name
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    it may work as expected to test the override without configuring the CRP.

    },
    Spec: placementv1beta1.ClusterResourcePlacementSpec{
    ResourceSelectors: []placementv1beta1.ClusterResourceSelector{
    {
    Copy link
    Contributor

    Choose a reason for hiding this comment

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

    should we block this case via the validation webhook?

    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.

    None yet

    4 participants