diff --git a/go.mod b/go.mod index 5871f579e0..2525e33aff 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/openshift/api v0.0.0-20220110171111-997c316db5e1 github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3 github.com/openshift/client-go v0.0.0-20211209144617-7385dd6338e3 - github.com/openshift/library-go v0.0.0-20220117173518-ca57b619b5d6 + github.com/openshift/library-go v0.0.0-20220119122101-7e1811fdb665 github.com/pkg/profile v1.5.0 // indirect github.com/prometheus-operator/prometheus-operator/pkg/client v0.45.0 github.com/prometheus/client_golang v1.11.0 diff --git a/go.sum b/go.sum index 6f536bbf03..240caf1a9a 100644 --- a/go.sum +++ b/go.sum @@ -535,8 +535,8 @@ github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3 h1:65 github.com/openshift/build-machinery-go v0.0.0-20211213093930-7e33a7eb4ce3/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/client-go v0.0.0-20211209144617-7385dd6338e3 h1:SG1aqwleU6bGD0X4mhkTNupjVnByMYYuW4XbnCPavQU= github.com/openshift/client-go v0.0.0-20211209144617-7385dd6338e3/go.mod h1:cwhyki5lqBmrT0m8Im+9I7PGFaraOzcYPtEz93RcsGY= -github.com/openshift/library-go v0.0.0-20220117173518-ca57b619b5d6 h1:HS6brMoum1oJyFriix+Ae3J2FfvK9u9TBqUu+JnG/pc= -github.com/openshift/library-go v0.0.0-20220117173518-ca57b619b5d6/go.mod h1:4UQ9snU1vg53fyTpHQw3vLPiAxI8ub5xrc+y8KPQQFs= +github.com/openshift/library-go v0.0.0-20220119122101-7e1811fdb665 h1:pzSrFYDV8k/41VreHttHb/OewcMNwk5pNKlmCxDD0bI= +github.com/openshift/library-go v0.0.0-20220119122101-7e1811fdb665/go.mod h1:4UQ9snU1vg53fyTpHQw3vLPiAxI8ub5xrc+y8KPQQFs= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= diff --git a/pkg/operator/starter.go b/pkg/operator/starter.go index 8fc26945f2..1fc831c974 100644 --- a/pkg/operator/starter.go +++ b/pkg/operator/starter.go @@ -229,10 +229,10 @@ func RunOperator(ctx context.Context, controllerContext *controllercmd.Controlle "openshift-kube-apiserver-operator", "cluster-kube-apiserver-operator", "6443", - func() (bool, error) { - isSNO, err := guard.IsSNOCheckFnc(configInformers.Config().V1().Infrastructures().Lister())() + func() (bool, bool, error) { + isSNO, precheckSucceeded, err := guard.IsSNOCheckFnc(configInformers.Config().V1().Infrastructures())() // create only when not a single node topology - return !isSNO, err + return !isSNO, precheckSucceeded, err }, ). WithOperandPodLabelSelector(labels.Set{"apiserver": "true"}.AsSelector()). diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/guard_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/guard_controller.go index 4ab81ee5eb..e38ba30f44 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/guard_controller.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controller/guard/guard_controller.go @@ -8,6 +8,7 @@ import ( "strconv" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -22,7 +23,7 @@ import ( "k8s.io/klog/v2" configv1 "github.com/openshift/api/config/v1" - configv1listers "github.com/openshift/client-go/config/listers/config/v1" + configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1" "github.com/openshift/library-go/pkg/controller/factory" "github.com/openshift/library-go/pkg/operator/events" "github.com/openshift/library-go/pkg/operator/resource/resourceapply" @@ -47,7 +48,7 @@ type GuardController struct { // installerPodImageFn returns the image name for the installer pod installerPodImageFn func() string - createConditionalFunc func() (bool, error) + createConditionalFunc func() (bool, bool, error) } func NewGuardController( @@ -62,7 +63,7 @@ func NewGuardController( podGetter corev1client.PodsGetter, pdbGetter policyclientv1.PodDisruptionBudgetsGetter, eventRecorder events.Recorder, - createConditionalFunc func() (bool, error), + createConditionalFunc func() (bool, bool, error), ) factory.Controller { c := &GuardController{ targetNamespace: targetNamespace, @@ -107,16 +108,30 @@ func nodeConditionFinder(status *corev1.NodeStatus, condType corev1.NodeConditio return nil } +func nodeHasUnschedulableTaint(node *corev1.Node) bool { + for _, taint := range node.Spec.Taints { + if taint.Effect == corev1.TaintEffectNoSchedule && taint.Key == corev1.TaintNodeUnschedulable { + return true + } + } + return false +} + func (c *GuardController) sync(ctx context.Context, syncCtx factory.SyncContext) error { klog.V(5).Info("Syncing guards") if c.createConditionalFunc == nil { - return fmt.Errorf("create conditional not set") + return fmt.Errorf("createConditionalFunc not set") } - shouldCreate, err := c.createConditionalFunc() + shouldCreate, precheckSucceeded, err := c.createConditionalFunc() if err != nil { - return fmt.Errorf("create conditional returns an error: %v", err) + return fmt.Errorf("createConditionalFunc returns an error: %v", err) + } + + if !precheckSucceeded { + klog.V(4).Infof("create conditional precheck did not succeed, skipping") + return nil } errs := []error{} @@ -181,25 +196,24 @@ func (c *GuardController) sync(ctx context.Context, syncCtx factory.SyncContext) pdb.Spec.MinAvailable = &minAvailable } - // List the pdb from the cache in case it exists and there's nothing to update - // so no Get request is executed. - pdbs, err := c.pdbLister.PodDisruptionBudgets(c.targetNamespace).List(labels.Everything()) - if err != nil { - klog.Errorf("Unable to list PodDisruptionBudgets: %v", err) - return err - } - - for _, pdbItem := range pdbs { - if pdbItem.Name == pdb.Name { - if pdbItem.Spec.MinAvailable != pdb.Spec.MinAvailable { - _, _, err = resourceapply.ApplyPodDisruptionBudget(ctx, c.pdbGetter, syncCtx.Recorder(), pdb) - if err != nil { - klog.Errorf("Unable to apply PodDisruptionBudget changes: %v", err) - return err - } + pdbObj, err := c.pdbLister.PodDisruptionBudgets(pdb.Namespace).Get(pdb.Name) + if err == nil { + if pdbObj.Spec.MinAvailable != pdb.Spec.MinAvailable { + _, _, err = resourceapply.ApplyPodDisruptionBudget(ctx, c.pdbGetter, syncCtx.Recorder(), pdb) + if err != nil { + klog.Errorf("Unable to apply PodDisruptionBudget changes: %v", err) + return fmt.Errorf("Unable to apply PodDisruptionBudget changes: %v", err) } - break } + } else if errors.IsNotFound(err) { + _, _, err = resourceapply.ApplyPodDisruptionBudget(ctx, c.pdbGetter, syncCtx.Recorder(), pdb) + if err != nil { + klog.Errorf("Unable to create PodDisruptionBudget: %v", err) + return fmt.Errorf("Unable to create PodDisruptionBudget: %v", err) + } + } else { + klog.Errorf("Unable to get PodDisruptionBudget: %v", err) + return err } operands := map[string]*corev1.Pod{} @@ -208,6 +222,12 @@ func (c *GuardController) sync(ctx context.Context, syncCtx factory.SyncContext) } for _, node := range nodes { + // Check whether the node is schedulable + if nodeHasUnschedulableTaint(node) { + klog.Infof("Node %v not schedulable, skipping reconciling the guard pod", node.Name) + continue + } + if _, exists := operands[node.Name]; !exists { // If the operand does not exist and the node is not ready, wait until the node becomes ready nodeReadyCondition := nodeConditionFinder(&node.Status, corev1.NodeReady) @@ -280,16 +300,24 @@ func (c *GuardController) sync(ctx context.Context, syncCtx factory.SyncContext) return utilerrors.NewAggregate(errs) } -func IsSNOCheckFnc(infraLister configv1listers.InfrastructureLister) func() (bool, error) { - return func() (bool, error) { - infraData, err := infraLister.Get("cluster") +// IsSNOCheckFnc creates a function that checks if the topology is SNO +// In case the err is nil, precheckSucceeded signifies whether the isSNO is valid. +// If precheckSucceeded is false, the isSNO return value does not reflect the cluster topology +// and defaults to the bool default value. +func IsSNOCheckFnc(infraInformer configv1informers.InfrastructureInformer) func() (isSNO, precheckSucceeded bool, err error) { + return func() (isSNO, precheckSucceeded bool, err error) { + if !infraInformer.Informer().HasSynced() { + // Do not return transient error + return false, false, nil + } + infraData, err := infraInformer.Lister().Get("cluster") if err != nil { - return false, fmt.Errorf("Unable to list infrastructures.config.openshift.io/cluster object, unable to determine topology mode") + return false, true, fmt.Errorf("Unable to list infrastructures.config.openshift.io/cluster object, unable to determine topology mode") } if infraData.Status.ControlPlaneTopology == "" { - return false, fmt.Errorf("ControlPlaneTopology was not set, unable to determine topology mode") + return false, true, fmt.Errorf("ControlPlaneTopology was not set, unable to determine topology mode") } - return infraData.Status.ControlPlaneTopology == configv1.SingleReplicaTopologyMode, nil + return infraData.Status.ControlPlaneTopology == configv1.SingleReplicaTopologyMode, true, nil } } diff --git a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go index 930ea816d9..f039f1e312 100644 --- a/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go +++ b/vendor/github.com/openshift/library-go/pkg/operator/staticpod/controllers.go @@ -68,7 +68,7 @@ type staticPodOperatorControllerBuilder struct { operatorName string operatorNamespace string readyzPort string - guardCreateConditionalFunc func() (bool, error) + guardCreateConditionalFunc func() (bool, bool, error) } func NewBuilder( @@ -99,7 +99,7 @@ type Builder interface { // the installer pod is created for a revision. WithCustomInstaller(command []string, installerPodMutationFunc installer.InstallerPodMutationFunc) Builder WithPruning(command []string, staticPodPrefix string) Builder - WithPodDisruptionBudgetGuard(operatorNamespace, operatorName, readyzPort string, createConditionalFunc func() (bool, error)) Builder + WithPodDisruptionBudgetGuard(operatorNamespace, operatorName, readyzPort string, createConditionalFunc func() (bool, bool, error)) Builder ToControllers() (manager.ControllerManager, error) } @@ -166,7 +166,7 @@ func (b *staticPodOperatorControllerBuilder) WithPruning(command []string, stati return b } -func (b *staticPodOperatorControllerBuilder) WithPodDisruptionBudgetGuard(operatorNamespace, operatorName, readyzPort string, createConditionalFunc func() (bool, error)) Builder { +func (b *staticPodOperatorControllerBuilder) WithPodDisruptionBudgetGuard(operatorNamespace, operatorName, readyzPort string, createConditionalFunc func() (bool, bool, error)) Builder { b.operatorNamespace = operatorNamespace b.operatorName = operatorName b.readyzPort = readyzPort diff --git a/vendor/modules.txt b/vendor/modules.txt index 4aa168fb77..46d2b258b0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -268,7 +268,7 @@ github.com/openshift/client-go/operatorcontrolplane/informers/externalversions/i github.com/openshift/client-go/operatorcontrolplane/informers/externalversions/operatorcontrolplane github.com/openshift/client-go/operatorcontrolplane/informers/externalversions/operatorcontrolplane/v1alpha1 github.com/openshift/client-go/operatorcontrolplane/listers/operatorcontrolplane/v1alpha1 -# github.com/openshift/library-go v0.0.0-20220117173518-ca57b619b5d6 +# github.com/openshift/library-go v0.0.0-20220119122101-7e1811fdb665 ## explicit; go 1.17 github.com/openshift/library-go/pkg/assets github.com/openshift/library-go/pkg/authorization/hardcodedauthorizer