Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unit tests for daemon package #273

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api/v1/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (e NetFilterType) String() string {
}
}

func InitNicIDMap(client *kubernetes.Clientset, namespace string) error {
func InitNicIDMap(client kubernetes.Interface, namespace string) error {
cm, err := client.CoreV1().ConfigMaps(namespace).Get(
context.Background(),
SupportedNicIDConfigmap,
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 24 additions & 16 deletions pkg/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"math/rand"
"os"
"os/exec"
"path"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -67,9 +68,9 @@ type Daemon struct {

client snclientset.Interface
// kubeClient allows interaction with Kubernetes, including the node we are running on.
kubeClient *kubernetes.Clientset
kubeClient kubernetes.Interface

mcClient *mcclientset.Clientset
mcClient mcclientset.Interface

nodeState *sriovnetworkv1.SriovNetworkNodeState

Expand Down Expand Up @@ -115,6 +116,9 @@ const (

var namespace = os.Getenv("NAMESPACE")

// used by test to mock interactions with filesystem
var filesystemRoot string = ""

// writer implements io.Writer interface as a pass-through for glog.
type writer struct {
logFunc func(args ...interface{})
Expand All @@ -129,8 +133,8 @@ func (w writer) Write(p []byte) (n int, err error) {
func New(
nodeName string,
client snclientset.Interface,
kubeClient *kubernetes.Clientset,
mcClient *mcclientset.Clientset,
kubeClient kubernetes.Interface,
mcClient mcclientset.Interface,
exitCh chan<- error,
stopCh <-chan struct{},
syncCh <-chan struct{},
Expand Down Expand Up @@ -275,11 +279,13 @@ func (dn *Daemon) Run(stopCh <-chan struct{}, exitCh <-chan error) error {
case <-stopCh:
glog.V(0).Info("Run(): stop daemon")
return nil
case err := <-exitCh:
case err, more := <-exitCh:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to boolean here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because when closing exitCh (and it's actually the only use of it, no one is writing in it), err.Error() produces a "nil pointer dereference"

glog.Warningf("Got an error: %v", err)
dn.refreshCh <- Message{
syncStatus: syncStatusFailed,
lastSyncError: err.Error(),
if more {
dn.refreshCh <- Message{
syncStatus: syncStatusFailed,
lastSyncError: err.Error(),
}
}
return err
case <-time.After(30 * time.Second):
Expand Down Expand Up @@ -310,11 +316,12 @@ func (dn *Daemon) enqueueNodeState(obj interface{}) {
func (dn *Daemon) processNextWorkItem() bool {
glog.V(2).Infof("worker queue size: %d", dn.workqueue.Len())
obj, shutdown := dn.workqueue.Get()
glog.V(2).Infof("get item: %d", obj.(int64))
if shutdown {
return false
}

glog.V(2).Infof("get item: %d", obj.(int64))

// We wrap this block in a func so we can defer c.workqueue.Done.
err := func(obj interface{}) error {
// We call Done here so the workqueue knows we have finished
Expand All @@ -330,7 +337,7 @@ func (dn *Daemon) processNextWorkItem() bool {
return nil
}

err := dn.nodeStateSyncHandler(key)
err := dn.nodeStateSyncHandler()
if err != nil {
// Ereport error message, and put the item back to work queue for retry.
dn.refreshCh <- Message{
Expand Down Expand Up @@ -397,9 +404,8 @@ func (dn *Daemon) operatorConfigChangeHandler(old, new interface{}) {
}
}

func (dn *Daemon) nodeStateSyncHandler(generation int64) error {
func (dn *Daemon) nodeStateSyncHandler() error {
var err error
glog.V(0).Infof("nodeStateSyncHandler(): new generation is %d", generation)
// Get the latest NodeState
var latestState *sriovnetworkv1.SriovNetworkNodeState
latestState, err = dn.client.SriovnetworkV1().SriovNetworkNodeStates(namespace).Get(context.Background(), dn.name, metav1.GetOptions{})
Expand All @@ -408,6 +414,8 @@ func (dn *Daemon) nodeStateSyncHandler(generation int64) error {
return err
}
latest := latestState.GetGeneration()
glog.V(0).Infof("nodeStateSyncHandler(): new generation is %d", latest)

if dn.nodeState.GetGeneration() == latest {
glog.V(0).Infof("nodeStateSyncHandler(): Interface not changed")
if latestState.Status.LastSyncError != "" ||
Expand Down Expand Up @@ -934,7 +942,7 @@ func tryEnableRdma() (bool, error) {
glog.V(2).Infof("tryEnableRdma()")
var stdout, stderr bytes.Buffer

cmd := exec.Command("/bin/bash", rdmaScriptsPath)
cmd := exec.Command("/bin/bash", path.Join(filesystemRoot, rdmaScriptsPath))
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
Expand All @@ -959,7 +967,7 @@ func tryEnableRdma() (bool, error) {
func tryCreateSwitchdevUdevRule(nodeState *sriovnetworkv1.SriovNetworkNodeState) error {
glog.V(2).Infof("tryCreateSwitchdevUdevRule()")
var newContent string
filePath := "/host/etc/udev/rules.d/20-switchdev.rules"
filePath := path.Join(filesystemRoot, "/host/etc/udev/rules.d/20-switchdev.rules")

for _, ifaceStatus := range nodeState.Status.Interfaces {
if ifaceStatus.EswitchMode == sriovnetworkv1.ESwithModeSwitchDev {
Expand Down Expand Up @@ -995,7 +1003,7 @@ func tryCreateSwitchdevUdevRule(nodeState *sriovnetworkv1.SriovNetworkNodeState)
}

var stdout, stderr bytes.Buffer
cmd := exec.Command("/bin/bash", udevScriptsPath)
cmd := exec.Command("/bin/bash", path.Join(filesystemRoot, udevScriptsPath))
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
Expand All @@ -1016,7 +1024,7 @@ func tryCreateSwitchdevUdevRule(nodeState *sriovnetworkv1.SriovNetworkNodeState)

func tryCreateNMUdevRule() error {
glog.V(2).Infof("tryCreateNMUdevRule()")
dirPath := "/host/etc/udev/rules.d/"
dirPath := path.Join(filesystemRoot, "/host/etc/udev/rules.d/")
filePath := dirPath + "10-nm-unmanaged.rules"

newContent := fmt.Sprintf("ACTION==\"add|change|move\", ATTRS{device}==\"%s\", ENV{NM_UNMANAGED}=\"1\"\n", strings.Join(sriovnetworkv1.GetSupportedVfIds(), "|"))
Expand Down
Loading