Skip to content

Commit

Permalink
controllers: auto update operator subscription channel name
Browse files Browse the repository at this point in the history
- Provider operator sends it's version as a response to heartbeat and
client operator should try to match that version
- We update the channel name of the subscription for client operator to
initiates it's own upgrade

Signed-off-by: Leela Venkaiah G <[email protected]>
  • Loading branch information
leelavg committed Dec 19, 2023
1 parent c2ef3f7 commit 93bcc91
Showing 1 changed file with 79 additions and 1 deletion.
80 changes: 79 additions & 1 deletion controllers/storageclient_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"strings"
"time"

"github.com/blang/semver/v4"
"github.com/red-hat-storage/ocs-client-operator/api/v1alpha1"
"github.com/red-hat-storage/ocs-client-operator/pkg/utils"
"github.com/red-hat-storage/ocs-client-operator/version"
Expand Down Expand Up @@ -64,7 +65,8 @@ const (
storageClientNamespaceLabel = "ocs.openshift.io/storageclient.namespace"
storageClientFinalizer = "storageclient.ocs.openshift.io"

csvPrefix = "ocs-client-operator"
csvPrefix = "ocs-client-operator"
storageClientSubPkg = csvPrefix
)

// StorageClientReconciler reconciles a StorageClient object
Expand Down Expand Up @@ -211,6 +213,10 @@ func (s *StorageClientReconciler) reconcilePhases(instance *v1alpha1.StorageClie
return res, err
}

if err := s.reconcileSubscriptionChannel(instance); err != nil {
return reconcile.Result{}, err
}

return reconcile.Result{}, nil
}

Expand Down Expand Up @@ -513,6 +519,78 @@ func (s *StorageClientReconciler) reconcileClientStatusReporterJob(instance *v1a
return reconcile.Result{}, nil
}

func (s *StorageClientReconciler) reconcileSubscriptionChannel(instance *v1alpha1.StorageClient) error {
oprVersion, err := semver.Make(instance.Spec.OperatorVersion)
if err != nil {
return fmt.Errorf("Failed to parse OperatorVersion: %v", err)
}

var pltVersion string
clusterVersion := &configv1.ClusterVersion{}
clusterVersion.Name = "version"
if err = s.Client.Get(s.ctx, types.NamespacedName{Name: clusterVersion.Name}, clusterVersion); err != nil {
return fmt.Errorf("Failed to get clusterVersion: %v", err)
} else {

Check failure on line 533 in controllers/storageclient_controller.go

View workflow job for this annotation

GitHub Actions / golangci-lint (1.20)

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)

Check failure on line 533 in controllers/storageclient_controller.go

View workflow job for this annotation

GitHub Actions / golangci-lint (1.21)

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
item := utils.Find(clusterVersion.Status.History, func(record *configv1.UpdateHistory) bool {
return record.State == configv1.CompletedUpdate
})
if item != nil {
pltVersion = item.Version
}
}
if pltVersion == "" {
return errors.New("Unable to find platform version with completed update")
}
clsVersion, err := semver.Make(pltVersion)
if err != nil {
return fmt.Errorf("Failed to parse PlatformVersion: %v", err)
}

if clsVersion.Major <= oprVersion.Major && clsVersion.Minor <= oprVersion.Minor {
// not specifically an error, provider operator wants client operator to be at a specific version
// however we can choose not to depending on our current condition and just stay inside support
// matrix
s.Log.Info("Not changing channel name as operator version may become unsupported to the platform version")
return nil
}

subList := &opv1a1.SubscriptionList{}
if err := s.Client.List(s.ctx, subList, client.InNamespace(s.OperatorNamespace)); err != nil {
return fmt.Errorf("Failed to list Subscriptions: %v", err)
}
sub := utils.Find(subList.Items, func(sub *opv1a1.Subscription) bool {
return sub.Spec.Package == storageClientSubPkg
})
if sub == nil {
// highly unlikely and if not found a programmatic error might have occured

Check failure on line 565 in controllers/storageclient_controller.go

View workflow job for this annotation

GitHub Actions / codespell

occured ==> occurred
return fmt.Errorf("Unable to find subscription with package name %q", storageClientSubPkg)
}

// TODO(lgangava): have details in the configmap that's generatable during build time
channel := fmt.Sprintf("stable-%d.%d", oprVersion.Major, oprVersion.Minor)

if sub.Spec.Channel != channel {
channelPatch := []struct {
Op string `json:"Op"`
Path string `json:"Path"`
Value interface{} `json:"Value"`
}{
{
Op: "replace",
Path: "/spec/channel",
Value: channel,
},
}
jsonPatch, _ := json.Marshal(channelPatch)
patch := client.RawPatch(types.JSONPatchType, jsonPatch)
if err := s.Client.Patch(s.ctx, sub, patch); err != nil {
return fmt.Errorf("Unable to patch subscription channel name to %q: %v", channel, err)
}
}

return nil
}

func (s *StorageClientReconciler) setOperatorCondition(instance *v1alpha1.StorageClient) error {
if !instance.GetDeletionTimestamp().IsZero() && instance.Spec.OperatorVersion == version.Version {
return s.OperatorCondition.Set(s.ctx, metav1.ConditionFalse,
Expand Down

0 comments on commit 93bcc91

Please sign in to comment.