226 lines
6.4 KiB
Go
226 lines
6.4 KiB
Go
/*
|
|
Copyright 2020 The Kubernetes Authors.
|
|
|
|
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 simulator
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
. "k8s.io/autoscaler/cluster-autoscaler/utils/test"
|
|
|
|
apiv1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/labels"
|
|
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
var snapshots = map[string]func() ClusterSnapshot{
|
|
"basic": func() ClusterSnapshot { return NewBasicClusterSnapshot() },
|
|
"delta": func() ClusterSnapshot { return NewDeltaClusterSnapshot() },
|
|
}
|
|
|
|
func nodeNames(nodes []*apiv1.Node) []string {
|
|
names := make([]string, len(nodes), len(nodes))
|
|
for i, node := range nodes {
|
|
names[i] = node.Name
|
|
}
|
|
return names
|
|
}
|
|
|
|
func nodeInfoNames(nodeInfos []*schedulernodeinfo.NodeInfo) []string {
|
|
names := make([]string, len(nodeInfos), len(nodeInfos))
|
|
for i, node := range nodeInfos {
|
|
names[i] = node.Node().Name
|
|
}
|
|
return names
|
|
}
|
|
|
|
func nodeInfoPods(nodeInfos []*schedulernodeinfo.NodeInfo) []*apiv1.Pod {
|
|
pods := []*apiv1.Pod{}
|
|
for _, node := range nodeInfos {
|
|
pods = append(pods, node.Pods()...)
|
|
}
|
|
return pods
|
|
}
|
|
|
|
func TestForkAddNode(t *testing.T) {
|
|
nodeCount := 3
|
|
|
|
nodes := createTestNodes(nodeCount)
|
|
extraNodes := createTestNodesWithPrefix("tmp", 2)
|
|
|
|
for name, snapshotFactory := range snapshots {
|
|
t.Run(fmt.Sprintf("%s: fork should not affect base data: adding nodes", name),
|
|
func(t *testing.T) {
|
|
clusterSnapshot := snapshotFactory()
|
|
err := clusterSnapshot.AddNodes(nodes)
|
|
assert.NoError(t, err)
|
|
|
|
err = clusterSnapshot.Fork()
|
|
assert.NoError(t, err)
|
|
|
|
for _, node := range extraNodes {
|
|
err = clusterSnapshot.AddNode(node)
|
|
assert.NoError(t, err)
|
|
}
|
|
forkNodes, err := clusterSnapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, append(nodeNames(nodes), nodeNames(extraNodes)...), nodeInfoNames(forkNodes))
|
|
|
|
err = clusterSnapshot.Revert()
|
|
assert.NoError(t, err)
|
|
|
|
baseNodes, err := clusterSnapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(baseNodes))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestForkAddPods(t *testing.T) {
|
|
nodeCount := 3
|
|
podCount := 90
|
|
|
|
nodes := createTestNodes(nodeCount)
|
|
pods := createTestPods(podCount)
|
|
assignPodsToNodes(pods, nodes)
|
|
|
|
for name, snapshotFactory := range snapshots {
|
|
t.Run(fmt.Sprintf("%s: fork should not affect base data: adding pods", name),
|
|
func(t *testing.T) {
|
|
clusterSnapshot := snapshotFactory()
|
|
err := clusterSnapshot.AddNodes(nodes)
|
|
assert.NoError(t, err)
|
|
|
|
err = clusterSnapshot.Fork()
|
|
assert.NoError(t, err)
|
|
|
|
for _, pod := range pods {
|
|
err = clusterSnapshot.AddPod(pod, pod.Spec.NodeName)
|
|
assert.NoError(t, err)
|
|
}
|
|
forkPods, err := clusterSnapshot.Pods().List(labels.Everything())
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, pods, forkPods)
|
|
forkNodes, err := clusterSnapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(forkNodes))
|
|
|
|
err = clusterSnapshot.Revert()
|
|
assert.NoError(t, err)
|
|
|
|
basePods, err := clusterSnapshot.Pods().List(labels.Everything())
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 0, len(basePods))
|
|
baseNodes, err := clusterSnapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(baseNodes))
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestForkRemovePods(t *testing.T) {
|
|
nodeCount := 3
|
|
podCount := 90
|
|
deletedPodCount := 10
|
|
|
|
nodes := createTestNodes(nodeCount)
|
|
pods := createTestPods(podCount)
|
|
assignPodsToNodes(pods, nodes)
|
|
|
|
for name, snapshotFactory := range snapshots {
|
|
t.Run(fmt.Sprintf("%s: fork should not affect base data: removing pods", name),
|
|
func(t *testing.T) {
|
|
clusterSnapshot := snapshotFactory()
|
|
err := clusterSnapshot.AddNodes(nodes)
|
|
assert.NoError(t, err)
|
|
|
|
for _, pod := range pods {
|
|
err = clusterSnapshot.AddPod(pod, pod.Spec.NodeName)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
err = clusterSnapshot.Fork()
|
|
assert.NoError(t, err)
|
|
|
|
for _, pod := range pods[:deletedPodCount] {
|
|
err = clusterSnapshot.RemovePod(pod.Namespace, pod.Name, pod.Spec.NodeName)
|
|
assert.NoError(t, err)
|
|
}
|
|
|
|
forkPods, err := clusterSnapshot.Pods().List(labels.Everything())
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, pods[deletedPodCount:], forkPods)
|
|
forkNodes, err := clusterSnapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(forkNodes))
|
|
assert.ElementsMatch(t, pods[deletedPodCount:], nodeInfoPods(forkNodes))
|
|
|
|
err = clusterSnapshot.Revert()
|
|
assert.NoError(t, err)
|
|
|
|
basePods, err := clusterSnapshot.Pods().List(labels.Everything())
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, pods, basePods)
|
|
baseNodes, err := clusterSnapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, nodeNames(nodes), nodeInfoNames(baseNodes))
|
|
assert.ElementsMatch(t, pods, nodeInfoPods(baseNodes))
|
|
})
|
|
}
|
|
}
|
|
|
|
func extractNodes(nodeInfos []*schedulernodeinfo.NodeInfo) []*apiv1.Node {
|
|
nodes := []*apiv1.Node{}
|
|
for _, ni := range nodeInfos {
|
|
nodes = append(nodes, ni.Node())
|
|
}
|
|
return nodes
|
|
}
|
|
|
|
func TestReAddNode(t *testing.T) {
|
|
for name, snapshotFactory := range snapshots {
|
|
t.Run(fmt.Sprintf("%s: re-add node", name),
|
|
func(t *testing.T) {
|
|
snapshot := snapshotFactory()
|
|
|
|
node := BuildTestNode("node", 10, 100)
|
|
err := snapshot.AddNode(node)
|
|
assert.NoError(t, err)
|
|
|
|
err = snapshot.Fork()
|
|
assert.NoError(t, err)
|
|
|
|
err = snapshot.RemoveNode("node")
|
|
assert.NoError(t, err)
|
|
|
|
err = snapshot.AddNode(node)
|
|
assert.NoError(t, err)
|
|
|
|
forkNodes, err := snapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, []*apiv1.Node{node}, extractNodes(forkNodes))
|
|
|
|
err = snapshot.Commit()
|
|
committedNodes, err := snapshot.NodeInfos().List()
|
|
assert.NoError(t, err)
|
|
assert.ElementsMatch(t, []*apiv1.Node{node}, extractNodes(committedNodes))
|
|
})
|
|
}
|
|
}
|