Skip to content

Conversation

@JustinKuli
Copy link
Member

Mainly

The optional `config` field in a Subscription, and the optional
`targetNamespaces` and `selector` fields in an OperatorGroup often need
to exactly match what the user has specified, rather than being merged
with what might already be there. That is, when they are specified, it
is usually better to treat them with `mustonlyhave` semantics.

Previously, if a user adjusted the `targetNamespaces` to change it from
one namespace to another (maybe they had a typo originally), the
existing list and the new list would be merged, and the operator would
likely not deploy as intended. Similarly, if a user had a nodeSelector
in their `config`, adjustments would often result in a selector that did
not match any nodes.

Now, when one of those specific fields is set, it is handled better.
When the field is not set, the existing configuration is still used.

For https://issues.redhat.com/browse/ACM-22555

It seems like this was a typo in the original implementation - the
controller correctly updates the resource to match the "merged" version,
but was then using the "desired" version of the resource (which only
specifies what parts the user was interested in, and does not reflect
the full live state) when updating the status of the policy.

The updated section in `musthaveOpGroup` now more closely matches the
analogous section in `musthaveSubscription`.

Signed-off-by: Justin Kulikauskas <[email protected]>
unstructured.SetNestedMap(existing.Object, desiredConfig, "spec", "config")
} else if eq, _ := deeplyEquivalent(desiredConfig, existingConfig, true); !eq {
forceUpdate = true
unstructured.SetNestedMap(existing.Object, desiredConfig, "spec", "config")
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess you will update this? return value

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah the linter complained 😅

The error should be impossible because the earlier check verified that .spec.config was a Map.

}
}

func (r *OperatorPolicyReconciler) mergeOpGroups(
Copy link
Contributor

Choose a reason for hiding this comment

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

Are you going to add unit tests for MergeOgGroups and MergeSubscriptions?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wasn't planning to, do you think it's necessary?

func (r *OperatorPolicyReconciler) mergeObjects(
ctx context.Context,
desired map[string]interface{},
desired map[string]any,
Copy link
Contributor

Choose a reason for hiding this comment

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

curious interface any are same from doc said.. why did you change?

Copy link
Member Author

Choose a reason for hiding this comment

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

Just my editor complaining about it.


//nolint:dogsled
_, errMsg, updateNeeded, _, _ := handleKeys(desiredObj, existing, existingObjectCopy, complianceType, "")
_, errMsg, updateNeeded, _, _ := handleKeys(desiredObj, existing, existingObjectCopy, policyv1.MustHave, "")
Copy link
Contributor

@yiraeChristineKim yiraeChristineKim Nov 21, 2025

Choose a reason for hiding this comment

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

At first, the user added a OperatorGroup to Operatorpolicy. Later, they changed their mind and wanted to use the default OperatorGroup instead. So they deleted the OperatorGroup from the operator policy and set mutUserOnlyHave.
In this case, will the OperatorGroup be removed and a new one created?

Copy link
Member Author

Choose a reason for hiding this comment

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

OperatorPolicy can not be set to mustonlyhave: https://github.com/open-cluster-management-io/config-policy-controller/blob/main/api/v1beta1/operatorpolicy_types.go#L156

Also, OperatorPolicy will try to never create a second OperatorGroup in a namespace: https://github.com/open-cluster-management-io/config-policy-controller/blob/main/controllers/operatorpolicy_controller.go#L1138 which might answer part of your question.

But generally if a user declared an OperatorGroup with specific configurations, and then wanted to revert to a more normal one, they would need to edit the policy to specify what they wanted in the group. If that part of the policy is just removed, it will just consider the existing OperatorGroup acceptable.

}

// when specified, manually handle targetNamespaces as if it's "mustonlyhave"
if len(desired.Spec.TargetNamespaces) > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

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

If users want to delete targetNamespace can user use mustOnlyHave?

Copy link
Member Author

Choose a reason for hiding this comment

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

If they initially set targetNamespaces, but then wanted to remove it from the OperatorGroup, I think they would need to use a ConfigurationPolicy (or manually apply the change on the cluster)

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh one more thing If users changed the TargetNamespaces then what happen to old targetnamespace. Do we remove resources in previous targetnamespace?

The optional `config` field in a Subscription, and the optional
`targetNamespaces` and `selector` fields in an OperatorGroup often need
to exactly match what the user has specified, rather than being merged
with what might already be there. That is, when they are specified, it
is usually better to treat them with `mustonlyhave` semantics.

Previously, if a user adjusted the `targetNamespaces` to change it from
one namespace to another (maybe they had a typo originally), the
existing list and the new list would be merged, and the operator would
likely not deploy as intended. Similarly, if a user had a nodeSelector
in their `config`, adjustments would often result in a selector that did
not match any nodes.

Now, when one of those specific fields is set, it is handled better.
When the field is not set, the existing configuration is still used.

Refs:
 - https://issues.redhat.com/browse/ACM-22555

Signed-off-by: Justin Kulikauskas <[email protected]>
@JustinKuli JustinKuli force-pushed the 22555-operatorpolicy-advanced-fields branch from 0144f8b to a378f03 Compare November 21, 2025 20:18
@openshift-ci
Copy link

openshift-ci bot commented Nov 26, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JustinKuli, yiraeChristineKim

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

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [JustinKuli,yiraeChristineKim]

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

@yiraeChristineKim
Copy link
Contributor

/hold

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants