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:
15
.golangci.yml
Normal file
15
.golangci.yml
Normal 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
|
||||||
12
.travis.yml
12
.travis.yml
@@ -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
|
||||||
|
|||||||
7
Makefile
7
Makefile
@@ -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
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
Reference in New Issue
Block a user