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 cluster labels update conflict. #287

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

Conversation

morvencao
Copy link
Member

fix cluster labels update conflict:

E1122 13:49:38.188870       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-4/work-manager", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-4": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.423603       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-3/governance-policy-framework", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-3": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.438568       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-1/config-policy-controller", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-1": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.451226       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-3/config-policy-controller", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-3": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.460923       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-1/config-policy-controller", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-1": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.477055       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-1/governance-policy-framework", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-1": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.488734       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-3", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-3": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.503787       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-1/governance-policy-framework", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-1": the object has been modified; please apply your changes to the latest version and try again
E1122 13:49:45.511774       1 base_controller.go:270] "AddOnFeatureDiscoveryController" controller failed to sync "ocm-controlplane-1-mc-3", err: Operation cannot be fulfilled on managedclusters.cluster.open-cluster-management.io "ocm-controlplane-1-mc-3": the object has been modified; please apply your changes to the latest version and try again

Signed-off-by: morvencao [email protected]

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 22, 2022

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: morvencao
Once this PR has been reviewed and has the lgtm label, please assign qiujian16 for approval by writing /assign @qiujian16 in a comment. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

return nil
}

// otherwise, update cluster
_, err = c.clusterClient.ClusterV1().ManagedClusters().Update(ctx, cluster, metav1.UpdateOptions{})
oldData, err := json.Marshal(clusterv1.ManagedCluster{
Copy link
Member

Choose a reason for hiding this comment

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

maybe we could only build the patch like

patch := fmt.Sprintf("{\"metadata\": {\"finalizers\": %s}}", string(finalizerBytes))

Copy link
Member

Choose a reason for hiding this comment

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

and the unit tests need to be updated too

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

@morvencao
Copy link
Member Author

/hold

@morvencao morvencao force-pushed the br_fix_cluster_labels_update_confliction branch 2 times, most recently from 058c319 to af19cfd Compare November 22, 2022 16:08
// no work if the cluster labels have no change
if !modified {
return nil
}
Copy link
Member

Choose a reason for hiding this comment

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

How about keeping the modified check, after the modified check, we create patchBytes and apply the patch, thus we can avoid to path the same thing

Copy link
Member Author

Choose a reason for hiding this comment

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

added label equality check, if they are equal, no need to patch.

return nil
}
// patch the cluster labels
_, err = c.clusterClient.ClusterV1().ManagedClusters().Patch(ctx, cluster.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{}, "")
Copy link
Member

Choose a reason for hiding this comment

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

nit: we can omit the empty string "" at the end of Patch function

Copy link
Member Author

Choose a reason for hiding this comment

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

nice catch! done.

return nil
}
// patch the cluster labels
_, err = c.clusterClient.ClusterV1().ManagedClusters().Patch(ctx, cluster.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{}, "")
Copy link
Member

Choose a reason for hiding this comment

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

nit: we can omit the empty string "" at the end of Patch function

Copy link
Member Author

Choose a reason for hiding this comment

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

done.

resourcemerge.MergeMap(&modified, &cluster.Labels, addOnLabels)

// no work if the cluster labels have no change
if !modified {
Copy link
Member

Choose a reason for hiding this comment

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

How about keeping the modified check, after the modified check, we create patchBytes and apply the patch, thus we can avoid to path the same thing

Copy link
Member Author

Choose a reason for hiding this comment

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

added label equality check, if they are equal, no need to patch.

@morvencao morvencao force-pushed the br_fix_cluster_labels_update_confliction branch 4 times, most recently from 1ed4b3c to 3c8be77 Compare November 23, 2022 03:22
@morvencao
Copy link
Member Author

is the integration test failure relevant?

@morvencao
Copy link
Member Author

/hold cancel

@skeeey
Copy link
Member

skeeey commented Nov 23, 2022

it seems not, restart the test to have a try

@morvencao morvencao force-pushed the br_fix_cluster_labels_update_confliction branch from 3c8be77 to 004c7cb Compare November 23, 2022 06:08
@morvencao morvencao force-pushed the br_fix_cluster_labels_update_confliction branch 2 times, most recently from 9c6ee0c to a49c139 Compare November 23, 2022 07:30
@morvencao morvencao force-pushed the br_fix_cluster_labels_update_confliction branch from a49c139 to 54a22eb Compare November 23, 2022 08:37
addOn, err := c.addOnLister.ManagedClusterAddOns(clusterName).Get(addOnName)
switch {
case errors.IsNotFound(err):
// addon is deleted
key := fmt.Sprintf("%s%s-", addOnFeaturePrefix, addOnName)
labels[key] = ""
key := fmt.Sprintf("%s%s", addOnFeaturePrefix, addOnName)
Copy link
Member

Choose a reason for hiding this comment

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

nit I think you can build key apriori instead of in each case

Copy link
Member Author

Choose a reason for hiding this comment

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

done

key := fmt.Sprintf("%s%s-", addOnFeaturePrefix, addOnName)
labels[key] = ""
key := fmt.Sprintf("%s%s", addOnFeaturePrefix, addOnName)
delete(labels, key)
Copy link
Member

Choose a reason for hiding this comment

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

should this be labels[key] = nil?

Copy link
Member Author

@morvencao morvencao Nov 23, 2022

Choose a reason for hiding this comment

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

it will not work since labels are known type(map[string]string), set value to nil, it will complain;

pkg/hub/addon/discovery_controller.go:144:17: cannot use nil as string value in assignment
pkg/hub/addon/discovery_controller.go:148:17: cannot use nil as string value in assignment
pkg/hub/addon/discovery_controller.go:219:23: cannot use nil as string value in assignment
pkg/hub/addon/discovery_controller.go:234:23: cannot use nil as string value in assignment

key := fmt.Sprintf("%s%s-", addOnFeaturePrefix, addOnName)
labels[key] = ""
key := fmt.Sprintf("%s%s", addOnFeaturePrefix, addOnName)
delete(labels, key)
Copy link
Member

Choose a reason for hiding this comment

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

should this be labels[key] = nil?

newTaints = nil
}
// build cluster taints patch
patchBytes, err := json.Marshal(map[string]interface{}{
Copy link
Member

Choose a reason for hiding this comment

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

it is better to add uid/resourceversion is precond.

Copy link
Member Author

Choose a reason for hiding this comment

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

added uid/resourceversion as precond

@@ -110,48 +112,68 @@ func (c *addOnFeatureDiscoveryController) sync(ctx context.Context, syncCtx fact
func (c *addOnFeatureDiscoveryController) syncAddOn(ctx context.Context, clusterName, addOnName string) error {
klog.V(4).Infof("Reconciling addOn %q", addOnName)

labels := map[string]string{}
Copy link
Member

Choose a reason for hiding this comment

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

I do not remember why we need syncAddOn, seems to me syncCluster is sufficient...

Copy link
Member Author

Choose a reason for hiding this comment

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

From integration testing, the syncAddOn is covered, so it is still being used?

// addon is deleting
if !addOn.DeletionTimestamp.IsZero() {
delete(addOnLabels, key)
Copy link
Member

Choose a reason for hiding this comment

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

set to nil if the key exists

if _, ok := addOnLabels[key]; !ok {
addOnLabels[fmt.Sprintf("%s-", key)] = ""
if _, ok := newAddonLabels[key]; !ok {
delete(addOnLabels, key)
Copy link
Member

Choose a reason for hiding this comment

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

set to nil if the key exists

Signed-off-by: morvencao <[email protected]>
@morvencao morvencao force-pushed the br_fix_cluster_labels_update_confliction branch from d42d27e to 5dbc6af Compare November 23, 2022 10:42
@morvencao
Copy link
Member Author

morvencao commented Nov 25, 2022

@qiujian16 Another look? all comments addressed except the one set to nil for label key, because labels is known type(map[string]string), set value to nil, it will complain:

pkg/hub/addon/discovery_controller.go:144:17: cannot use nil as string value in assignment
pkg/hub/addon/discovery_controller.go:148:17: cannot use nil as string value in assignment
pkg/hub/addon/discovery_controller.go:219:23: cannot use nil as string value in assignment
pkg/hub/addon/discovery_controller.go:234:23: cannot use nil as string value in assignment

@qiujian16
Copy link
Member

you cannot set nil in map[string]string, but you can do it in map[string]interface{}. The patch you generate should be based on a map[string]interface{}.

@morvencao
Copy link
Member Author

morvencao commented Nov 26, 2022

Any benefit to use map[string]interface{} instead of map[string]string?
In labels update case, the labels field is known type, and the JSON encoding can also generate patch bytes based on map[string]string type. We can convert map[string]string to map[string]interface{}, but that will also make it more complicated, especially we need to check whether labels are actually updated before launch patch request.
I tried to use map[string]interface{}, it is more complicated and the UT cases are also need to updated accordingly.

@qiujian16
Copy link
Member

you can delete a key with map[string]interface{}

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.

4 participants