Skip to content

Commit

Permalink
Use Patch() instead of Update() for updating the status of network.op…
Browse files Browse the repository at this point in the history
…erator

As we don't enable status subresource in the CRD
networks.operator.openshift.io. We used to use the Update() func
to update the status of network.operator. It might mistakenly
override some content in the spec. Using Patch() to ensure
that the status_manager only updates the status field.

Signed-off-by: Peng Liu <pliu@redhat.com>
  • Loading branch information
pliurh committed Apr 16, 2024
1 parent 395a36a commit e2e7a0c
Showing 1 changed file with 25 additions and 19 deletions.
44 changes: 25 additions & 19 deletions pkg/controller/statusmanager/status_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package statusmanager

import (
"context"
"encoding/json"
"fmt"
"log"
"os"
Expand Down Expand Up @@ -316,16 +317,21 @@ func (status *StatusManager) writeHypershiftStatus(operStatus *operv1.NetworkSta
// Set updates the operator and clusteroperator statuses with the provided conditions.
func (status *StatusManager) set(reachedAvailableLevel bool, conditions ...operv1.OperatorCondition) {
var operStatus *operv1.NetworkStatus
oc := &operv1.Network{ObjectMeta: metav1.ObjectMeta{Name: names.OPERATOR_CONFIG}}

// Set status on the network.operator object
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
oc := &operv1.Network{ObjectMeta: metav1.ObjectMeta{Name: names.OPERATOR_CONFIG}}
err := status.client.ClientFor("").CRClient().Get(context.TODO(), types.NamespacedName{Name: names.OPERATOR_CONFIG}, oc)
if err != nil {
// Should never happen outside of unit tests
return err
}

return nil
})
if err != nil {
// Should never happen outside of unit tests
log.Printf("Failed to get operator: %v", err)
} else {
oldStatus := oc.Status.DeepCopy()

oc.Status.Version = os.Getenv("RELEASE_VERSION")
Expand Down Expand Up @@ -378,24 +384,24 @@ func (status *StatusManager) set(reachedAvailableLevel bool, conditions ...operv

operStatus = &oc.Status

if equality.Semantic.DeepEqual(&oc.Status, oldStatus) {
return nil
}

buf, err := yaml.Marshal(oc.Status.Conditions)
if err != nil {
buf = []byte(fmt.Sprintf("(failed to convert to YAML: %s)", err))
}

if err := status.client.ClientFor("").CRClient().Update(context.TODO(), oc); err != nil {
return err
if !equality.Semantic.DeepEqual(&oc.Status, oldStatus) {
type st struct {
Status operv1.NetworkStatus `json:"status"`
}
// make sure we only update the status field
patchData, err := json.Marshal(&st{
Status: oc.Status,
})
if err != nil {
log.Printf("failed to create patch: %v", err)
} else {
// Use server-side apply
if err := status.client.ClientFor("").CRClient().Patch(context.TODO(), oc, crclient.RawPatch(types.ApplyPatchType, patchData),
crclient.ForceOwnership, crclient.FieldOwner("cluster-network-operator/statusmanager")); err != nil {
log.Printf("Failed to set operator status: %v", err)
}
}
}
log.Printf("Network operator config updated with conditions:\n%s", buf)

return nil
})
if err != nil {
log.Printf("Failed to set operator status: %v", err)
}

// Set status conditions on the network clusteroperator object.
Expand Down

0 comments on commit e2e7a0c

Please sign in to comment.