193 lines
4.7 KiB
Go
193 lines
4.7 KiB
Go
/*
|
|
Copyright 2016 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 (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
apiv1 "k8s.io/api/core/v1"
|
|
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/kubernetes/pkg/kubelet/types"
|
|
|
|
pod_util "k8s.io/autoscaler/cluster-autoscaler/utils/pod"
|
|
. "k8s.io/autoscaler/cluster-autoscaler/utils/test"
|
|
)
|
|
|
|
func TestRequiredPodsForNode(t *testing.T) {
|
|
nodeName1 := "node1"
|
|
nodeName2 := "node2"
|
|
pod1 := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "default",
|
|
Name: "pod1",
|
|
SelfLink: "pod1",
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName1,
|
|
},
|
|
}
|
|
// Manifest pod.
|
|
pod2 := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod2",
|
|
Namespace: "kube-system",
|
|
SelfLink: "pod2",
|
|
Annotations: map[string]string{
|
|
types.ConfigMirrorAnnotationKey: "something",
|
|
},
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName1,
|
|
},
|
|
}
|
|
pod3 := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "pod2",
|
|
Namespace: "kube-system",
|
|
SelfLink: "pod2",
|
|
Annotations: map[string]string{
|
|
types.ConfigMirrorAnnotationKey: "something",
|
|
},
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName2,
|
|
},
|
|
}
|
|
|
|
podsForNodes := map[string][]*apiv1.Pod{nodeName1: {pod1, pod2}, nodeName2: {pod3}}
|
|
pods, err := getRequiredPodsForNode(nodeName1, podsForNodes)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, 1, len(pods))
|
|
assert.Equal(t, "pod2", pods[0].Name)
|
|
}
|
|
|
|
func Test_filterRequiredPodsForNode(t *testing.T) {
|
|
nodeName := "node1"
|
|
pod1 := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "default",
|
|
Name: "pod1",
|
|
SelfLink: "pod1",
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName,
|
|
},
|
|
}
|
|
// Manifest pod.
|
|
mirrorPod := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "mirrorPod",
|
|
Namespace: "kube-system",
|
|
SelfLink: "mirrorPod",
|
|
Annotations: map[string]string{
|
|
types.ConfigMirrorAnnotationKey: "something",
|
|
},
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName,
|
|
},
|
|
}
|
|
now := metav1.NewTime(time.Now())
|
|
podDeleted := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "default",
|
|
Name: "podDeleted",
|
|
SelfLink: "podDeleted",
|
|
Annotations: map[string]string{
|
|
types.ConfigMirrorAnnotationKey: "something",
|
|
},
|
|
DeletionTimestamp: &now,
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName,
|
|
},
|
|
}
|
|
|
|
podDaemonset := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "default",
|
|
Name: "podDaemonset",
|
|
SelfLink: "podDaemonset",
|
|
OwnerReferences: GenerateOwnerReferences("ds", "DaemonSet", "apps/v1", ""),
|
|
Annotations: map[string]string{
|
|
types.ConfigSourceAnnotationKey: types.FileSource,
|
|
},
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName,
|
|
},
|
|
}
|
|
|
|
podDaemonsetAnnotation := &apiv1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: "default",
|
|
Name: "podDaemonset2",
|
|
SelfLink: "podDaemonset2",
|
|
OwnerReferences: GenerateOwnerReferences("ds2", "CustomDaemonset", "crd/v1", ""),
|
|
Annotations: map[string]string{
|
|
pod_util.DaemonSetPodAnnotationKey: "true",
|
|
},
|
|
},
|
|
Spec: apiv1.PodSpec{
|
|
NodeName: nodeName,
|
|
},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
inputPods []*apiv1.Pod
|
|
want []*apiv1.Pod
|
|
}{
|
|
{
|
|
name: "nil input pod list",
|
|
inputPods: nil,
|
|
want: []*apiv1.Pod{},
|
|
},
|
|
{
|
|
name: "should return only mirrorPod",
|
|
inputPods: []*apiv1.Pod{pod1, mirrorPod},
|
|
want: []*apiv1.Pod{mirrorPod},
|
|
},
|
|
{
|
|
name: "should ignore podDeleted",
|
|
inputPods: []*apiv1.Pod{pod1, mirrorPod, podDeleted},
|
|
want: []*apiv1.Pod{mirrorPod},
|
|
},
|
|
{
|
|
name: "should return daemonset pod",
|
|
inputPods: []*apiv1.Pod{pod1, podDaemonset},
|
|
want: []*apiv1.Pod{podDaemonset},
|
|
},
|
|
{
|
|
name: "should return daemonset pods with",
|
|
inputPods: []*apiv1.Pod{pod1, podDaemonset, podDaemonsetAnnotation},
|
|
want: []*apiv1.Pod{podDaemonset, podDaemonsetAnnotation},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := filterRequiredPodsForNode(tt.inputPods); !apiequality.Semantic.DeepEqual(got, tt.want) {
|
|
t.Errorf("filterRequiredPodsForNode() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|