Skip to content

Commit

Permalink
Manage OSSM operator subscription manually to ensure a compatible ver…
Browse files Browse the repository at this point in the history
…sion is installed

Istio and the Gateway API CRDs need to be in sync to work. The CRDs are
baked into a particular openshift release, so this change updates the
ingress operator to install a compatible version with the CRDs it
already installs.
  • Loading branch information
rfredette committed Jul 29, 2024
1 parent defe53f commit 1e5e244
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 1 deletion.
1 change: 1 addition & 0 deletions manifests/00-cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ rules:
- operators.coreos.com
resources:
- subscriptions
- installplans
verbs:
- '*'

Expand Down
20 changes: 20 additions & 0 deletions pkg/operator/controller/gatewayclass/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

logf "github.com/openshift/cluster-ingress-operator/pkg/log"
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"

"k8s.io/client-go/tools/record"

Expand Down Expand Up @@ -61,6 +62,22 @@ func NewUnmanaged(mgr manager.Manager, config Config) (controller.Controller, er
if err := c.Watch(source.Kind(operatorCache, &gatewayapiv1beta1.GatewayClass{}), &handler.EnqueueRequestForObject{}, isOurGatewayClass, predicate.Not(isIstioGatewayClass)); err != nil {
return nil, err
}
isOurInstallPlan := predicate.NewPredicateFuncs(func(o client.Object) bool {
installPlan := o.(*operatorsv1alpha1.InstallPlan)
for _, csv := range installPlan.Spec.ClusterServiceVersionNames {
if csv == serviceMeshOperatorDesiredVersion {
return true
}
}
return false
})
isInstallPlanApproved := predicate.NewPredicateFuncs(func(o client.Object) bool {
installPlan := o.(*operatorsv1alpha1.InstallPlan)
return installPlan.Spec.Approved
})
if err := c.Watch(source.Kind(operatorCache, &operatorsv1alpha1.InstallPlan{}), &handler.EnqueueRequestForObject{}, isOurInstallPlan, predicate.Not(isInstallPlanApproved)); err != nil {
return nil, err
}
return c, nil
}

Expand Down Expand Up @@ -97,6 +114,9 @@ func (r *reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
if _, _, err := r.ensureServiceMeshOperatorSubscription(ctx); err != nil {
errs = append(errs, err)
}
if _, _, err := r.ensureServiceMeshOperatorInstallPlan(ctx); err != nil {
errs = append(errs, err)
}
if _, _, err := r.ensureServiceMeshControlPlane(ctx, &gatewayclass); err != nil {
errs = append(errs, err)
}
Expand Down
46 changes: 45 additions & 1 deletion pkg/operator/controller/gatewayclass/subscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"sigs.k8s.io/controller-runtime/pkg/client"

operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"

Expand All @@ -16,6 +17,11 @@ import (
"k8s.io/apimachinery/pkg/types"
)

var (
serviceMeshOperatorDesiredVersion = "servicemeshoperator.v2.5.0"
serviceMeshOperatorNamespace = "openshift-operators"
)

// ensureServiceMeshOperatorSubscription attempts to ensure that a subscription
// for servicemeshoperator is present and returns a Boolean indicating whether
// it exists, the subscription if it exists, and an error value.
Expand Down Expand Up @@ -56,10 +62,11 @@ func desiredSubscription(name types.NamespacedName) (*operatorsv1alpha1.Subscrip
},
Spec: &operatorsv1alpha1.SubscriptionSpec{
Channel: "stable",
InstallPlanApproval: operatorsv1alpha1.ApprovalAutomatic,
InstallPlanApproval: operatorsv1alpha1.ApprovalManual,
Package: "servicemeshoperator",
CatalogSource: "redhat-operators",
CatalogSourceNamespace: "openshift-marketplace",
StartingCSV: serviceMeshOperatorDesiredVersion,
},
}
return &subscription, nil
Expand Down Expand Up @@ -115,3 +122,40 @@ func subscriptionChanged(current, expected *operatorsv1alpha1.Subscription) (boo

return true, updated
}

// ensureServiceMeshOperatorInstallPlan attempts to ensure that the install plan for the appropriate OSSM operator
// version is approved.
func (r *reconciler) ensureServiceMeshOperatorInstallPlan(ctx context.Context) (bool, *operatorsv1alpha1.InstallPlan, error) {
currentInstallPlan, err := r.getCurrentInstallPlan(ctx)
if err != nil {
return false, nil, err
} else if currentInstallPlan == nil {
return false, nil, nil
}
if !currentInstallPlan.Spec.Approved {
currentInstallPlan.Spec.Approved = true
if err := r.client.Update(ctx, currentInstallPlan); err != nil {
return false, nil, fmt.Errorf("Failed to update %s/%s: %w", currentInstallPlan.Namespace, currentInstallPlan.Name, err)
}
return true, currentInstallPlan, nil
}
return false, currentInstallPlan, nil
}

func (r *reconciler) getCurrentInstallPlan(ctx context.Context) (*operatorsv1alpha1.InstallPlan, error) {
InstallPlans := &operatorsv1alpha1.InstallPlanList{}
if err := r.client.List(ctx, InstallPlans, client.InNamespace(serviceMeshOperatorNamespace)); err != nil {
return nil, err
}
if InstallPlans == nil || len(InstallPlans.Items) == 0 {
return nil, nil
}
for _, InstallPlan := range InstallPlans.Items {
for _, CSVName := range InstallPlan.Spec.ClusterServiceVersionNames {
if CSVName == serviceMeshOperatorDesiredVersion {
return &InstallPlan, nil
}
}
}
return nil, fmt.Errorf("No InstallPlan with cluster service version %s found", serviceMeshOperatorDesiredVersion)
}

0 comments on commit 1e5e244

Please sign in to comment.