Skip to content

Commit

Permalink
Validate control-plane quorum only on OpenShift
Browse files Browse the repository at this point in the history
Assert if cluster was installed on OpenShift, since only there a quorum PDB exists, otherwise we have nothing to assert
  • Loading branch information
razo7 committed Jan 17, 2024
1 parent 01c8263 commit 138830d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 3 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RUN export GO_VERSION=$(grep -E "go [[:digit:]]\.[[:digit:]][[:digit:]]" go.mod
# Copy the go source
COPY api/ api/
COPY controllers/ controllers/
COPY pkg/ pkg/
COPY hack/ hack/
COPY main.go main.go
COPY vendor/ vendor/
Expand Down
15 changes: 12 additions & 3 deletions api/v1beta1/nodemaintenance_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"

"github.com/medik8s/node-maintenance-operator/pkg/utils"
)

const (
Expand Down Expand Up @@ -163,7 +165,12 @@ func (v *NodeMaintenanceValidator) validateNoNodeMaintenanceExists(nodeName stri
}

func (v *NodeMaintenanceValidator) validateControlPlaneQuorum(nodeName string) error {
// check if the node is a control-plane node
if !utils.IsOpenshiftSupported {
// etcd quorum PDB is only installed in OpenShift
nodemaintenancelog.Info("Cluster does not have etcd quorum PDB, thus we can't asses control-plane quorum violation")
return nil
}
// check if the node is a control-plane node on OpenShift
node, err := getNode(nodeName, v.client)
if err != nil {
return fmt.Errorf("could not get node for master/control-plane quorum validation, please try again: %v", err)
Expand All @@ -174,11 +181,13 @@ func (v *NodeMaintenanceValidator) validateControlPlaneQuorum(nodeName string) e
// not a control-plane node, nothing to do
return nil
}
canDisrupt, err := etcd.IsEtcdDisruptionAllowed(context.Background(), v.client, nodemaintenancelog, node)
// The node is a control-plane node on OpenShift
// now we check if adding nm CR for this node will disrupt control-plane quorum
isDisruptionAllowed, err := etcd.IsEtcdDisruptionAllowed(context.Background(), v.client, nodemaintenancelog, node)
if err != nil {
return err
}
if !canDisrupt {
if !isDisruptionAllowed {
return fmt.Errorf(ErrorControlPlaneQuorumViolation, nodeName)
}
return nil
Expand Down
6 changes: 6 additions & 0 deletions api/v1beta1/nodemaintenance_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
policyv1 "k8s.io/api/policy/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/medik8s/node-maintenance-operator/pkg/utils"
)

var _ = Describe("NodeMaintenance Validation", func() {
Expand Down Expand Up @@ -91,6 +93,10 @@ var _ = Describe("NodeMaintenance Validation", func() {
node = getTestNode(existingNodeName, true)
err := k8sClient.Create(context.Background(), node)
Expect(err).ToNot(HaveOccurred())
// mock IsOpenshiftSupported value and set it true for the quorum violation check
orgValue := utils.IsOpenshiftSupported
utils.IsOpenshiftSupported = true
DeferCleanup(func() { utils.IsOpenshiftSupported = orgValue })
})

AfterEach(func() {
Expand Down
8 changes: 8 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (

nodemaintenancev1beta1 "github.com/medik8s/node-maintenance-operator/api/v1beta1"
"github.com/medik8s/node-maintenance-operator/controllers"
"github.com/medik8s/node-maintenance-operator/pkg/utils"
"github.com/medik8s/node-maintenance-operator/version"
//+kubebuilder:scaffold:imports
)
Expand Down Expand Up @@ -110,6 +111,13 @@ func main() {
setupLog.Error(err, "unable to set up lease Manager", "lease", "NodeMaintenance")
os.Exit(1)
}

if err := utils.ValidateIsOpenshift(mgr.GetConfig()); err != nil {
setupLog.Error(err, "failed to check if we run on Openshift")
os.Exit(1)
}
setupLog.Info("NMO was installed on Openshift cluster")


if err = (&controllers.NodeMaintenanceReconciler{
Client: cl,
Expand Down
33 changes: 33 additions & 0 deletions pkg/utils/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package utils

import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
)

// IsOpenshiftSupported will be set to true in case the operator was installed on OpenShift cluster
var IsOpenshiftSupported bool

// ValidateIsOpenshift returns true if the cluster has the openshift config group
func ValidateIsOpenshift(config *rest.Config) error {
dc, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil {
return err
}
apiGroups, err := dc.ServerGroups()
if err != nil {
return err
}

kind := schema.GroupVersionKind{Group: "config.openshift.io", Version: "v1", Kind: "ClusterVersion"}
for _, apiGroup := range apiGroups.Groups {
for _, supportedVersion := range apiGroup.Versions {
if supportedVersion.GroupVersion == kind.GroupVersion().String() {
IsOpenshiftSupported = true
return nil
}
}
}
return nil
}

0 comments on commit 138830d

Please sign in to comment.