1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-26 05:14:13 +01:00

Merge pull request #149 from reetasingh/master

Adding golang ci lint support and Refactoring test by make it table driven
This commit is contained in:
Kubernetes Prow Robot
2019-06-04 07:25:11 -07:00
committed by GitHub
10 changed files with 137 additions and 49 deletions

15
.golangci.yml Normal file
View File

@@ -0,0 +1,15 @@
run:
deadline: 2m
linters:
disable-all: true
enable:
- gofmt
- gosimple
- gocyclo
- misspell
- govet
linters-settings:
goimports:
local-prefixes: github.com/kubernetes-incubator/descheduler

View File

@@ -1,7 +1,11 @@
sudo: false
language: go language: go
go: go:
- 1.9.1 - "1.10"
script: script:
- hack/verify-gofmt.sh - make lint
- make build - make build
- make test-unit - make test-unit

View File

@@ -22,6 +22,8 @@ LDFLAG_LOCATION=github.com/kubernetes-incubator/descheduler/cmd/descheduler/app
LDFLAGS=-ldflags "-X ${LDFLAG_LOCATION}.version=${VERSION} -X ${LDFLAG_LOCATION}.buildDate=${BUILD} -X ${LDFLAG_LOCATION}.gitCommit=${COMMIT}" LDFLAGS=-ldflags "-X ${LDFLAG_LOCATION}.version=${VERSION} -X ${LDFLAG_LOCATION}.buildDate=${BUILD} -X ${LDFLAG_LOCATION}.gitCommit=${COMMIT}"
GOLANGCI_VERSION := v1.15.0
HAS_GOLANGCI := $(shell which golangci-lint)
# IMAGE is the image name of descheduler # IMAGE is the image name of descheduler
# Should this be changed? # Should this be changed?
@@ -52,3 +54,8 @@ gen:
./hack/update-generated-conversions.sh ./hack/update-generated-conversions.sh
./hack/update-generated-deep-copies.sh ./hack/update-generated-deep-copies.sh
./hack/update-generated-defaulters.sh ./hack/update-generated-defaulters.sh
lint:
ifndef HAS_GOLANGCI
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin ${GOLANGCI_VERSION}
endif
golangci-lint run

View File

@@ -18,9 +18,10 @@ package app
import ( import (
"fmt" "fmt"
"github.com/spf13/cobra"
"runtime" "runtime"
"strings" "strings"
"github.com/spf13/cobra"
) )
var ( var (

View File

@@ -24,7 +24,7 @@ DESCHEDULER_ROOT=$(dirname "${BASH_SOURCE}")/..
GO_VERSION=($(go version)) GO_VERSION=($(go version))
if [[ -z $(echo "${GO_VERSION[2]}" | grep -E 'go1.2|go1.3|go1.4|go1.5|go1.6|go1.7|go1.8|go1.9|go1.10') ]]; then if [[ -z $(echo "${GO_VERSION[2]}" | grep -E 'go1.2|go1.3|go1.4|go1.5|go1.6|go1.7|go1.8|go1.9|go1.10') ]]; then
echo "Unknown go version '${GO_VERSION}', skipping gofmt." echo "Unknown go version '${GO_VERSION[2]}', skipping gofmt."
exit 1 exit 1
fi fi

View File

@@ -26,15 +26,39 @@ import (
) )
func TestEvictPod(t *testing.T) { func TestEvictPod(t *testing.T) {
n1 := test.BuildTestNode("node1", 1000, 2000, 9) node1 := test.BuildTestNode("node1", 1000, 2000, 9)
p1 := test.BuildTestPod("p1", 400, 0, n1.Name) pod1 := test.BuildTestPod("p1", 400, 0, "node1")
fakeClient := &fake.Clientset{} tests := []struct {
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) { description string
return true, &v1.PodList{Items: []v1.Pod{*p1}}, nil node *v1.Node
}) pod *v1.Pod
evicted, _ := EvictPod(fakeClient, p1, "v1", false) pods []v1.Pod
if !evicted { want bool
t.Errorf("Expected %v pod to be evicted", p1.Name) }{
{
description: "test pod eviction - pod present",
node: node1,
pod: pod1,
pods: []v1.Pod{*pod1},
want: true,
},
{
description: "test pod eviction - pod absent",
node: node1,
pod: pod1,
pods: []v1.Pod{*test.BuildTestPod("p2", 400, 0, "node1"), *test.BuildTestPod("p3", 450, 0, "node1")},
want: true,
},
} }
for _, test := range tests {
fakeClient := &fake.Clientset{}
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
return true, &v1.PodList{Items: test.pods}, nil
})
got, _ := EvictPod(fakeClient, test.pod, "v1", false)
if got != test.want {
t.Errorf("Test error for Desc: %s. Expected %v pod eviction to be %v, got %v", test.description, test.pod.Name, test.want, got)
}
}
} }

View File

@@ -120,10 +120,7 @@ func IsReady(node *v1.Node) bool {
// IsNodeUschedulable checks if the node is unschedulable. This is helper function to check only in case of // IsNodeUschedulable checks if the node is unschedulable. This is helper function to check only in case of
// underutilized node so that they won't be accounted for. // underutilized node so that they won't be accounted for.
func IsNodeUschedulable(node *v1.Node) bool { func IsNodeUschedulable(node *v1.Node) bool {
if node.Spec.Unschedulable { return node.Spec.Unschedulable
return true
}
return false
} }
// PodFitsAnyNode checks if the given pod fits any of the given nodes, based on // PodFitsAnyNode checks if the given pod fits any of the given nodes, based on

View File

@@ -27,8 +27,8 @@ import (
core "k8s.io/client-go/testing" core "k8s.io/client-go/testing"
) )
//TODO:@ravisantoshgudimetla This could be made table driven.
func TestFindDuplicatePods(t *testing.T) { func TestFindDuplicatePods(t *testing.T) {
// first setup pods
node := test.BuildTestNode("n1", 2000, 3000, 10) node := test.BuildTestNode("n1", 2000, 3000, 10)
p1 := test.BuildTestPod("p1", 100, 0, node.Name) p1 := test.BuildTestPod("p1", 100, 0, node.Name)
p1.Namespace = "dev" p1.Namespace = "dev"
@@ -86,23 +86,65 @@ func TestFindDuplicatePods(t *testing.T) {
// A Critical Pod. // A Critical Pod.
p7.Annotations = test.GetCriticalPodAnnotation() p7.Annotations = test.GetCriticalPodAnnotation()
// Setup the fake client. tests := []struct {
fakeClient := &fake.Clientset{} description string
fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) { maxPodsToEvict int
return true, &v1.PodList{Items: []v1.Pod{*p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10}}, nil pods []v1.Pod
}) expectedEvictedPodCount int
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) { }{
return true, node, nil {
}) description: "Three pods in the default Namespace, bound to same ReplicaSet. 2 should get deleted",
maxPodsToEvict: 2,
pods: []v1.Pod{*p1, *p2, *p3},
expectedEvictedPodCount: 2,
},
{
description: "Three Pods in the test Namespace, bound to same ReplicaSet. 2 should be evicted",
maxPodsToEvict: 2,
pods: []v1.Pod{*p8, *p9, *p10},
expectedEvictedPodCount: 2,
},
{
description: "pods are part of daemonset and local storage - none should get deleted",
maxPodsToEvict: 2,
pods: []v1.Pod{*p4, *p5},
expectedEvictedPodCount: 0,
},
{
description: "pods are mirror pod and critical pod - none should get deleted",
maxPodsToEvict: 2,
pods: []v1.Pod{*p6, *p7},
expectedEvictedPodCount: 0,
},
{
description: "pods are part of replicaset, daemonset and local storage - all duplicate replicaset pods should get deleted",
maxPodsToEvict: 4,
pods: []v1.Pod{*p1, *p2, *p3, *p8, *p9, *p10, *p4, *p5},
expectedEvictedPodCount: 4,
},
{
description: "pods are part of replicaset, daemonset, local storage, mirror pod and critical pod - all duplicate replicaset pods should get deleted",
maxPodsToEvict: 5,
pods: []v1.Pod{*p1, *p2, *p3, *p8, *p9, *p10, *p4, *p5, *p6, *p7},
expectedEvictedPodCount: 4,
},
}
expectedEvictedPodCount := 4 for _, test := range tests {
npe := nodePodEvictedCount{}
npe[node] = 0
// Start evictions. npe := nodePodEvictedCount{}
podsEvicted := deleteDuplicatePods(fakeClient, "v1", []*v1.Node{node}, false, npe, 10, false) npe[node] = 0
if podsEvicted != expectedEvictedPodCount { fakeClient := &fake.Clientset{}
t.Error("Unexpected number of pods evicted.\nExpected:\t", expectedEvictedPodCount, "\nActual:\t\t", podsEvicted) fakeClient.Fake.AddReactor("list", "pods", func(action core.Action) (bool, runtime.Object, error) {
return true, &v1.PodList{Items: test.pods}, nil
})
fakeClient.Fake.AddReactor("get", "nodes", func(action core.Action) (bool, runtime.Object, error) {
return true, node, nil
})
podsEvicted := deleteDuplicatePods(fakeClient, "v1", []*v1.Node{node}, false, npe, test.maxPodsToEvict, false)
if podsEvicted != test.expectedEvictedPodCount {
t.Errorf("Test error for Desc: %s. Expected deleted pods count %v , got %v", test.description, test.expectedEvictedPodCount, podsEvicted)
}
} }
} }

View File

@@ -106,10 +106,10 @@ func TestRemovePodsViolatingNodeAffinity(t *testing.T) {
}, },
}, },
expectedEvictedPodCount: 0, expectedEvictedPodCount: 0,
pods: addPodsToNode(nodeWithoutLabels), pods: addPodsToNode(nodeWithoutLabels),
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels}, nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0}, npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
maxPodsToEvict: 0, maxPodsToEvict: 0,
}, },
{ {
description: "Invalid strategy type, should not evict any pods", description: "Invalid strategy type, should not evict any pods",
@@ -122,19 +122,19 @@ func TestRemovePodsViolatingNodeAffinity(t *testing.T) {
}, },
}, },
expectedEvictedPodCount: 0, expectedEvictedPodCount: 0,
pods: addPodsToNode(nodeWithoutLabels), pods: addPodsToNode(nodeWithoutLabels),
nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels}, nodes: []*v1.Node{nodeWithoutLabels, nodeWithLabels},
npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0}, npe: nodePodEvictedCount{nodeWithoutLabels: 0, nodeWithLabels: 0},
maxPodsToEvict: 0, maxPodsToEvict: 0,
}, },
{ {
description: "Pod is correctly scheduled on node, no eviction expected", description: "Pod is correctly scheduled on node, no eviction expected",
strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy, strategy: requiredDuringSchedulingIgnoredDuringExecutionStrategy,
expectedEvictedPodCount: 0, expectedEvictedPodCount: 0,
pods: addPodsToNode(nodeWithLabels), pods: addPodsToNode(nodeWithLabels),
nodes: []*v1.Node{nodeWithLabels}, nodes: []*v1.Node{nodeWithLabels},
npe: nodePodEvictedCount{nodeWithLabels: 0}, npe: nodePodEvictedCount{nodeWithLabels: 0},
maxPodsToEvict: 0, maxPodsToEvict: 0,
}, },
{ {
description: "Pod is scheduled on node without matching labels, another schedulable node available, should be evicted", description: "Pod is scheduled on node without matching labels, another schedulable node available, should be evicted",

View File

@@ -115,8 +115,6 @@ func startEndToEndForLowNodeUtilization(clientset clientset.Interface) {
nodePodCount := strategies.InitializeNodePodCount(nodes) nodePodCount := strategies.InitializeNodePodCount(nodes)
strategies.LowNodeUtilization(ds, lowNodeUtilizationStrategy, evictionPolicyGroupVersion, nodes, nodePodCount) strategies.LowNodeUtilization(ds, lowNodeUtilizationStrategy, evictionPolicyGroupVersion, nodes, nodePodCount)
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
return
} }
func TestE2E(t *testing.T) { func TestE2E(t *testing.T) {