Skip to content

Commit

Permalink
add feature gate controller to HCCO
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Hunt <[email protected]>
  • Loading branch information
haircommander committed Dec 2, 2024
1 parent 9e7cce0 commit b74e50a
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 12 deletions.
24 changes: 12 additions & 12 deletions control-plane-operator/hostedclusterconfigoperator/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/configmetrics"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/controllers/cmca"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/controllers/drainer"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/controllers/featuregate"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/controllers/hcpstatus"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/controllers/inplaceupgrader"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/controllers/machine"
Expand All @@ -36,14 +37,12 @@ import (
"github.com/openshift/hypershift/support/releaseinfo"
"github.com/openshift/hypershift/support/upsert"
"github.com/openshift/hypershift/support/util"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/spf13/cobra"
"go.uber.org/zap/zapcore"

"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/cluster"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
)
Expand All @@ -58,14 +57,15 @@ func NewCommand() *cobra.Command {
}

var controllerFuncs = map[string]operator.ControllerSetupFunc{
"controller-manager-ca": cmca.Setup,
resources.ControllerName: resources.Setup,
"inplaceupgrader": inplaceupgrader.Setup,
"node": node.Setup,
nodecount.ControllerName: nodecount.Setup,
"machine": machine.Setup,
"drainer": drainer.Setup,
hcpstatus.ControllerName: hcpstatus.Setup,
"controller-manager-ca": cmca.Setup,
resources.ControllerName: resources.Setup,
"inplaceupgrader": inplaceupgrader.Setup,
"node": node.Setup,
nodecount.ControllerName: nodecount.Setup,
featuregate.ControllerName: featuregate.Setup,
"machine": machine.Setup,
"drainer": drainer.Setup,
hcpstatus.ControllerName: hcpstatus.Setup,
}

type HostedClusterConfigOperator struct {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package featuregate

import (
"context"
"fmt"

"github.com/blang/semver/v4"
hypershiftv1beta1 "github.com/openshift/hypershift/api/hypershift/v1beta1"
"github.com/openshift/hypershift/support/util"
nodelib "github.com/openshift/library-go/pkg/apiserver/node"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

hypershiftv1beta1applyconfigurations "github.com/openshift/hypershift/client/applyconfiguration/hypershift/v1beta1"
hypershiftclient "github.com/openshift/hypershift/client/clientset/clientset"
)

type minimumKubeletVersionReconciler struct {
hcpName, hcpNamespace string
client hypershiftclient.Interface
lister client.Client

guestClusterClient client.Client
}

func (r *minimumKubeletVersionReconciler) Reconcile(ctx context.Context, _ reconcile.Request) (reconcile.Result, error) {
log := ctrl.LoggerFrom(ctx)
log.Info("Reconciling")

var hcp hypershiftv1beta1.HostedControlPlane
if err := r.lister.Get(ctx, client.ObjectKey{
Namespace: r.hcpNamespace,
Name: r.hcpName,
}, &hcp); err != nil {
return reconcile.Result{}, err
}
if isPaused, duration := util.IsReconciliationPaused(log, hcp.Spec.PausedUntil); isPaused {
log.Info("Reconciliation paused", "pausedUntil", *hcp.Spec.PausedUntil)
return ctrl.Result{
RequeueAfter: duration,
}, nil
}
if hcp.ObjectMeta.DeletionTimestamp != nil {
return reconcile.Result{}, nil
}

nodes := &corev1.NodeList{}
if err := r.guestClusterClient.List(ctx, nodes); err != nil {
return ctrl.Result{}, fmt.Errorf("failed to get Nodes: %w", err)
}

currentOldestKubelet := getOldestKubeletVersion(nodes.Items)
if currentOldestKubelet == nil {
// no valid nodes, leave the field unset
return reconcile.Result{}, nil
}

cfg := hypershiftv1beta1applyconfigurations.HostedControlPlane(r.hcpName, r.hcpNamespace)
cfg.Status = hypershiftv1beta1applyconfigurations.HostedControlPlaneStatus().WithOldestKubeletVersion(currentOldestKubelet.String())
_, err := r.client.HypershiftV1beta1().HostedControlPlanes(r.hcpNamespace).ApplyStatus(ctx, cfg, metav1.ApplyOptions{FieldManager: ControllerName})
return reconcile.Result{}, err
}

func getOldestKubeletVersion(nodes []corev1.Node) *semver.Version {
var oldestVersion *semver.Version
for _, node := range nodes {
vStr := node.Status.NodeInfo.KubeletVersion
v, err := nodelib.ParseKubeletVersion(vStr)
if err != nil {
continue
}
if oldestVersion == nil || v.LT(*oldestVersion) {
oldestVersion = v
}
}
return oldestVersion
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package featuregate

import (
"context"
"time"

hypershiftclient "github.com/openshift/hypershift/client/clientset/clientset"
"github.com/openshift/hypershift/control-plane-operator/hostedclusterconfigoperator/operator"
featuregate "github.com/openshift/hypershift/hypershift-operator/featuregate"
corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

const ControllerName = "featuregate"

func Setup(ctx context.Context, opts *operator.HostedClusterConfigOperatorConfig) error {
if !featuregate.Gates.Enabled(featuregate.MinimumKubeletVersion) {
return nil
}

hypershiftClient, err := hypershiftclient.NewForConfig(opts.CPCluster.GetConfig())
if err != nil {
return err
}

return ctrl.NewControllerManagedBy(opts.Manager).
Named(ControllerName).
For(&corev1.Node{}).
WithOptions(controller.Options{
RateLimiter: workqueue.NewTypedItemExponentialFailureRateLimiter[reconcile.Request](1*time.Second, 10*time.Second),
}).Complete(&minimumKubeletVersionReconciler{
hcpName: opts.HCPName,
hcpNamespace: opts.Namespace,
client: hypershiftClient,
lister: opts.CPCluster.GetClient(),
guestClusterClient: opts.Manager.GetClient(),
})
}

0 comments on commit b74e50a

Please sign in to comment.