Skip to content

Commit

Permalink
Allow running the SSP Operator on plain kubernetes
Browse files Browse the repository at this point in the history
SSP can't run on a plain kubernetes, because it requires the
`Infrastructure` kind to be present on the cluster.

When deploying KubeVirt with HCO using OLM on plain kubernetes,
the deployment is never completed because SSP operator never becomes
ready. More details and full description of the issue can be found here:
kubevirt/hyperconverged-cluster-operator#2129

This commit disables the reconcilers and all the watches, in case the
`Infrastructure` is not found on the cluster, instead of killing the
process.

That way, the SSP operator
is runing and responding to the health and ready checks, but does
nothing else. The result is that SSP is still not working on plain
kubernetest, but the OLM deployment is successfully completed.

Signed-off-by: Nahshon Unna-Tsameret <nunnatsa@redhat.com>
  • Loading branch information
nunnatsa committed Nov 8, 2022
1 parent d2e8d82 commit 1760a88
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 42 deletions.
1 change: 1 addition & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ rules:
- apiGroups:
- config.openshift.io
resources:
- clusterversions
- infrastructures
verbs:
- get
Expand Down
94 changes: 53 additions & 41 deletions controllers/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package controllers
import (
"context"
"fmt"
"github.com/go-logr/logr"
"path/filepath"

"kubevirt.io/ssp-operator/internal/common"
Expand Down Expand Up @@ -36,64 +37,75 @@ func CreateAndStartReconciler(ctx context.Context, mgr controllerruntime.Manager
node_labeller.New(),
}

var requiredCrds []string
for i := range sspOperands {
requiredCrds = append(requiredCrds, sspOperands[i].RequiredCrds()...)
}

mgrCtx, cancel := context.WithCancel(ctx)
defer cancel()
mgrCtx = logr.NewContext(mgrCtx, mgr.GetLogger())

crdWatch := crd_watch.New(requiredCrds...)
// Cleanly stops the manager and exit. The pod will be restarted.
crdWatch.AllCrdsAddedHandler = cancel
crdWatch.SomeCrdRemovedHandler = cancel

err = crdWatch.Init(mgrCtx, mgr.GetAPIReader())
runningOnOpenShift, err := common.RunningOnOpenshift(ctx, mgr.GetAPIReader())
if err != nil {
return err
}

if missingCrds := crdWatch.MissingCrds(); len(missingCrds) > 0 {
mgr.GetLogger().Error(nil, "Some required crds are missing. The operator will not create any new resources.",
"missingCrds", missingCrds,
)
}
if runningOnOpenShift {
var requiredCrds []string
for i := range sspOperands {
requiredCrds = append(requiredCrds, sspOperands[i].RequiredCrds()...)
}

err = mgr.Add(crdWatch)
if err != nil {
return err
}
crdWatch := crd_watch.New(requiredCrds...)
// Cleanly stops the manager and exit. The pod will be restarted.
crdWatch.AllCrdsAddedHandler = cancel
crdWatch.SomeCrdRemovedHandler = cancel

infrastructureTopology, err := common.GetInfrastructureTopology(mgrCtx, mgr.GetAPIReader())
if err != nil {
return fmt.Errorf("failed to get infrastructure topology: %w", err)
}
err = crdWatch.Init(mgrCtx, mgr.GetAPIReader())
if err != nil {
return err
}

serviceController, err := CreateServiceController(mgrCtx, mgr)
if err != nil {
return fmt.Errorf("failed to create service controller: %w", err)
}
if missingCrds := crdWatch.MissingCrds(); len(missingCrds) > 0 {
mgr.GetLogger().Error(nil, "Some required crds are missing. The operator will not create any new resources.",
"missingCrds", missingCrds,
)
}

err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error {
err := serviceController.Start(ctx, mgr)
infrastructureTopology, err := common.GetInfrastructureTopology(mgrCtx, mgr.GetAPIReader())
if err != nil {
return fmt.Errorf("error starting serviceController: %w", err)
return err
}

mgr.GetLogger().Info("Services Controller started")
err = mgr.Add(crdWatch)
if err != nil {
return err
}

return nil
}))
if err != nil {
return fmt.Errorf("error adding service controller: %w", err)
}
serviceController, err := CreateServiceController(mgrCtx, mgr)
if err != nil {
return fmt.Errorf("failed to create service controller: %w", err)
}

reconciler := NewSspReconciler(mgr.GetClient(), mgr.GetAPIReader(), infrastructureTopology, sspOperands, crdWatch)
err = mgr.Add(manager.RunnableFunc(func(ctx context.Context) error {
err := serviceController.Start(ctx, mgr)
if err != nil {
return fmt.Errorf("error starting serviceController: %w", err)
}

err = reconciler.setupController(mgr)
if err != nil {
return err
mgr.GetLogger().Info("Services Controller started")

return nil
}))
if err != nil {
return fmt.Errorf("error adding service controller: %w", err)
}

reconciler := NewSspReconciler(mgr.GetClient(), mgr.GetAPIReader(), infrastructureTopology, sspOperands, crdWatch)

err = reconciler.setupController(mgr)
if err != nil {
return err
}

} else { // if !runningOnOpenShift
mgr.GetLogger().Info("SSP operator is running in inactive mode. The operator will not react to any event.")
}

mgr.GetLogger().Info("starting manager")
Expand Down
2 changes: 1 addition & 1 deletion controllers/ssp_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ var _ reconcile.Reconciler = &sspReconciler{}
// +kubebuilder:rbac:groups=ssp.kubevirt.io,resources=ssps,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ssp.kubevirt.io,resources=ssps/status,verbs=get;update;patch
// +kubebuilder:rbac:groups=ssp.kubevirt.io,resources=ssps/finalizers,verbs=update
// +kubebuilder:rbac:groups=config.openshift.io,resources=infrastructures,verbs=get;list;watch
// +kubebuilder:rbac:groups=config.openshift.io,resources=infrastructures;clusterversions,verbs=get;list;watch
// +kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=list
// +kubebuilder:rbac:groups=ssp.kubevirt.io,resources=kubevirtcommontemplatesbundles,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=ssp.kubevirt.io,resources=kubevirtmetricsaggregations,verbs=get;list;watch;create;update;patch;delete
Expand Down
20 changes: 20 additions & 0 deletions internal/common/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (

"github.com/go-logr/logr"
osconfv1 "github.com/openshift/api/config/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)
Expand All @@ -33,6 +36,23 @@ func GetOperatorVersion() string {
return EnvOrDefault(OperatorVersionKey, defaultOperatorVersion)
}

func RunningOnOpenshift(ctx context.Context, cl client.Reader) (bool, error) {
clusterVersion := &osconfv1.ClusterVersion{
ObjectMeta: metav1.ObjectMeta{
Name: "version",
},
}
if err := cl.Get(ctx, client.ObjectKeyFromObject(clusterVersion), clusterVersion); err != nil {
if meta.IsNoMatchError(err) || apierrors.IsNotFound(err) {
// Not on OpenShift
return false, nil
} else {
return false, err
}
}
return true, nil
}

func GetInfrastructureTopology(ctx context.Context, c client.Reader) (osconfv1.TopologyMode, error) {
infraConfig := &osconfv1.Infrastructure{}
if err := c.Get(ctx, types.NamespacedName{Name: "cluster"}, infraConfig); err != nil {
Expand Down

0 comments on commit 1760a88

Please sign in to comment.