Skip to content

Commit

Permalink
Merge pull request #61 from razo7/taint-ut
Browse files Browse the repository at this point in the history
Validate utils Package and Taint Functionality
  • Loading branch information
openshift-merge-robot authored Jul 6, 2023
2 parents 50ea936 + 3ee5066 commit a50d9f6
Show file tree
Hide file tree
Showing 12 changed files with 446 additions and 35 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ test: test-no-verify verify-unchanged ## Generate and format code, run tests, ge
# --require-suite: If set, Ginkgo fails if there are ginkgo tests in a directory but no invocation of RunSpecs.
# --vv: If set, emits with maximal verbosity - includes skipped and pending tests.
test-no-verify: manifests generate go-verify fmt vet fix-imports envtest ginkgo # Generate and format code, and run tests
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(ENVTEST_DIR)/$(ENVTEST_VERSION) -p path)" $(GINKGO) -r --keep-going --require-suite --vv -coverprofile cover.out ./controllers
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(ENVTEST_DIR)/$(ENVTEST_VERSION) -p path)" \
$(GINKGO) -r --keep-going --require-suite --vv -coverprofile cover.out ./controllers/... ./pkg/...

.PHONY: bundle-run
export BUNDLE_RUN_NAMESPACE ?= openshift-operators
Expand Down
34 changes: 3 additions & 31 deletions controllers/fenceagentsremediation_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,28 +90,10 @@ var _ = Describe("FAR Controller", func() {
})
})
})

Context("IsNodeNameValid", func() {
BeforeEach(func() {
node = getNode(node01)
DeferCleanup(k8sClient.Delete, context.Background(), node)
Expect(k8sClient.Create(context.Background(), node)).To(Succeed())
})
When("FAR CR's name doesn't match to an existing node name", func() {
It("should fail", func() {
Expect(utils.IsNodeNameValid(k8sClient, dummyNode)).To(BeFalse())
})
})
When("FAR's name does match to an existing node name", func() {
It("should succeed", func() {
Expect(utils.IsNodeNameValid(k8sClient, node01)).To(BeTrue())
})
})
})
})
Context("Reconcile", func() {
farNamespacedName := client.ObjectKey{Name: node01, Namespace: defaultNamespace}
nodeKey := client.ObjectKey{Name: node01}
farNamespacedName := client.ObjectKey{Name: node01, Namespace: defaultNamespace}
farNoExecuteTaint := utils.CreateFARNoExecuteTaint()
//Scenarios
BeforeEach(func() {
Expand All @@ -132,7 +114,7 @@ var _ = Describe("FAR Controller", func() {

When("creating valid FAR CR", func() {
BeforeEach(func() {
node = getNode(node01)
node = utils.GetNode("", node01)
})
It("should have finalizer and taint", func() {
By("Searching for remediation taint")
Expand All @@ -150,7 +132,7 @@ var _ = Describe("FAR Controller", func() {
})
When("creating invalid FAR CR Name", func() {
BeforeEach(func() {
node = getNode(node01)
node = utils.GetNode("", node01)
underTestFAR = getFenceAgentsRemediation(dummyNode, fenceAgentIPMI, testShareParam, testNodeParam)
})
It("should not have a finalizer nor taint", func() {
Expand Down Expand Up @@ -183,16 +165,6 @@ func getFenceAgentsRemediation(nodeName string, agent string, sharedparameters m
}
}

// used for making new node object for test and have a unique resourceVersion
// getNode returns a node object with the name nodeName
func getNode(nodeName string) *corev1.Node {
return &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
},
}
}

// buildFarPod builds a dummy pod with FAR label and namespace
func buildFarPod() *corev1.Pod {
fenceAgentsPod := &corev1.Pod{}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.20

require (
github.com/go-logr/logr v1.2.4
github.com/medik8s/common v1.2.0
github.com/onsi/ginkgo/v2 v2.11.0
github.com/onsi/gomega v1.27.8
github.com/openshift/api v0.0.0-20230621174358-ea40115b9fa6
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/medik8s/common v1.2.0 h1:xgQOijD3rEn+PfCd4lJuV3WFdt5QA6SIaqF01rRp2as=
github.com/medik8s/common v1.2.0/go.mod h1:ZT/3hfMXJLmZEcqmxRWB5LGC8Wl+qKGGQ4zM8hOE7PY=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand Down
31 changes: 29 additions & 2 deletions pkg/utils/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package utils
import (
"context"

medik8sLabels "github.com/medik8s/common/pkg/labels"

corev1 "k8s.io/api/core/v1"
apiErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const WorkerLabelName = "node-role.kubernetes.io/worker"

// getNodeWithName returns a node with a name nodeName, or an error if it can't be found
func getNodeWithName(r client.Reader, nodeName string) (*corev1.Node, error) {
node := &corev1.Node{}
Expand All @@ -33,3 +34,29 @@ func IsNodeNameValid(r client.Reader, nodeName string) (bool, error) {
}
return true, nil
}

// GetNode returns a node object with the name nodeName based on the nodeType input
// used for making new node object for test and have a unique resourceVersion
func GetNode(nodeRole, nodeName string) *corev1.Node {
if nodeRole == "control-plane" {
return &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
},
Spec: corev1.NodeSpec{
Taints: []corev1.Taint{
{
Key: medik8sLabels.ControlPlaneRole,
Effect: corev1.TaintEffectNoExecute,
},
},
},
}
} else {
return &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: nodeName,
},
}
}
}
36 changes: 36 additions & 0 deletions pkg/utils/nodes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package utils

import (
"context"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

corev1 "k8s.io/api/core/v1"
)

const (
dummyNode = "dummy-node"
node01 = "worker-0"
)

var _ = Describe("Utils-nodes", func() {
var node *corev1.Node
Context("FAR CR and Node Names Validity test", func() {
BeforeEach(func() {
node = GetNode("", node01)
Expect(k8sClient.Create(context.Background(), node)).To(Succeed())
DeferCleanup(k8sClient.Delete, context.Background(), node)
})
When("FAR CR's name doesn't match to an existing node name", func() {
It("should fail", func() {
Expect(IsNodeNameValid(k8sClient, dummyNode)).To(BeFalse())
})
})
When("FAR's name does match to an existing node name", func() {
It("should succeed", func() {
Expect(IsNodeNameValid(k8sClient, node01)).To(BeTrue())
})
})
})
})
99 changes: 99 additions & 0 deletions pkg/utils/suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package utils

import (
"context"
"os"
"path/filepath"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"go.uber.org/zap/zapcore"

"k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"

"github.com/medik8s/fence-agents-remediation/api/v1alpha1"
)

// These tests use Ginkgo (BDD-style Go testing framework). Refer to
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.

const defaultNamespace = "default"

var k8sClient client.Client
var k8sManager manager.Manager
var testEnv *envtest.Environment
var ctx context.Context
var cancel context.CancelFunc

func TestUtils(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Utils Suite")
}

var _ = BeforeSuite(func() {
opts := zap.Options{
Development: true,
TimeEncoder: zapcore.RFC3339NanoTimeEncoder,
}
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseFlagOptions(&opts)))

By("bootstrapping test environment")
testEnv = &envtest.Environment{
CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")},
ErrorIfCRDPathMissing: true,
}

cfg, err := testEnv.Start()
Expect(err).NotTo(HaveOccurred())
Expect(cfg).NotTo(BeNil())

err = v1alpha1.AddToScheme(scheme.Scheme)
Expect(err).NotTo(HaveOccurred())

//+kubebuilder:scaffold:scheme

k8sManager, err = ctrl.NewManager(cfg, ctrl.Options{Scheme: scheme.Scheme})
Expect(err).NotTo(HaveOccurred())

k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
Expect(err).NotTo(HaveOccurred())
Expect(k8sClient).NotTo(BeNil())

os.Setenv("DEPLOYMENT_NAMESPACE", defaultNamespace)

go func() {
// https://github.com/kubernetes-sigs/controller-runtime/issues/1571
ctx, cancel = context.WithCancel(ctrl.SetupSignalHandler())
err := k8sManager.Start(ctx)
Expect(err).NotTo(HaveOccurred())
}()
})

var _ = AfterSuite(func() {
By("tearing down the test environment")
cancel()
err := testEnv.Stop()
Expect(err).NotTo(HaveOccurred())
})
58 changes: 58 additions & 0 deletions pkg/utils/taint_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package utils

import (
"context"

medik8sLabels "github.com/medik8s/common/pkg/labels"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const node0 = "worker-0"

var _ = Describe("Utils-taint", func() {
nodeKey := client.ObjectKey{Name: node0}
controlPlaneRoleTaint := getControlPlaneRoleTaint()
farNoExecuteTaint := CreateFARNoExecuteTaint()
Context("Taint functioninality test", func() {
// Check functionaility with control-plane node which already has a taint
BeforeEach(func() {
node := GetNode("control-plane", node0)
Expect(k8sClient.Create(context.Background(), node)).To(Succeed())
DeferCleanup(k8sClient.Delete, context.Background(), node)
})
When("Control-plane node only has 1 the control-plane-role taint", func() {
It("should add and delete medik8s NoSchedule taint and keep other existing taints", func() {
By("having one control-plane-role taint")
taintedNode := &corev1.Node{}
Expect(k8sClient.Get(context.Background(), nodeKey, taintedNode)).To(Succeed())
// control-plane-role taint already exist by GetNode
By("adding medik8s NoSchedule taint")
Expect(AppendTaint(k8sClient, node0)).To(Succeed())
Expect(k8sClient.Get(context.Background(), nodeKey, taintedNode)).To(Succeed())
Expect(TaintExists(taintedNode.Spec.Taints, &controlPlaneRoleTaint)).To(BeTrue())
Expect(TaintExists(taintedNode.Spec.Taints, &farNoExecuteTaint)).To(BeTrue())
By("removing medik8s NoSchedule taint")
// We want to see that RemoveTaint only remove the taint it receives
Expect(RemoveTaint(k8sClient, node0)).To(Succeed())
Expect(k8sClient.Get(context.Background(), nodeKey, taintedNode)).To(Succeed())
Expect(TaintExists(taintedNode.Spec.Taints, &controlPlaneRoleTaint)).To(BeTrue())
Expect(TaintExists(taintedNode.Spec.Taints, &farNoExecuteTaint)).To(BeFalse())

// there is a not-ready taint now as well, so there will be 2 taints... skip count tests
// Expect(len(taintedNode.Spec.Taints)).To(Equal(1))
})
})
})
})

// getControlPlaneRoleTaint returns a control-plane-role taint
func getControlPlaneRoleTaint() corev1.Taint {
return corev1.Taint{
Key: medik8sLabels.ControlPlaneRole,
Effect: corev1.TaintEffectNoExecute,
}
}
3 changes: 2 additions & 1 deletion test/e2e/far_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"time"

medik8sLabels "github.com/medik8s/common/pkg/labels"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

Expand Down Expand Up @@ -64,7 +65,7 @@ var _ = Describe("FAR E2e", func() {
BeforeEach(func() {
nodes := &corev1.NodeList{}
selector := labels.NewSelector()
requirement, _ := labels.NewRequirement(utils.WorkerLabelName, selection.Exists, []string{})
requirement, _ := labels.NewRequirement(medik8sLabels.WorkerRole, selection.Exists, []string{})
selector = selector.Add(*requirement)
Expect(k8sClient.List(context.Background(), nodes, &client.ListOptions{LabelSelector: selector})).ToNot(HaveOccurred())
if len(nodes.Items) < 1 {
Expand Down
Loading

0 comments on commit a50d9f6

Please sign in to comment.