mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
346 lines
9.7 KiB
Go
346 lines
9.7 KiB
Go
package kclient
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang/mock/gomock"
|
|
"github.com/google/go-cmp/cmp"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
ktesting "k8s.io/client-go/testing"
|
|
)
|
|
|
|
func TestGetOnePodFromSelector(t *testing.T) {
|
|
fakePod := FakePodStatus(corev1.PodRunning, "nodejs")
|
|
fakePod.Labels["component"] = "nodejs"
|
|
|
|
fakePodWithDeletionTimeStamp := FakePodStatus(corev1.PodRunning, "nodejs")
|
|
fakePodWithDeletionTimeStamp.Labels["component"] = "nodejs"
|
|
currentTime := metav1.NewTime(time.Now())
|
|
fakePodWithDeletionTimeStamp.DeletionTimestamp = ¤tTime
|
|
|
|
type args struct {
|
|
selector string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
returnedPods *corev1.PodList
|
|
want *corev1.Pod
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "valid number of pods",
|
|
args: args{selector: fmt.Sprintf("component=%s", "nodejs")},
|
|
returnedPods: &corev1.PodList{
|
|
Items: []corev1.Pod{
|
|
*fakePod,
|
|
},
|
|
},
|
|
want: fakePod,
|
|
wantErr: false,
|
|
},
|
|
{
|
|
name: "zero pods",
|
|
args: args{selector: fmt.Sprintf("component=%s", "nodejs")},
|
|
returnedPods: &corev1.PodList{
|
|
Items: []corev1.Pod{},
|
|
},
|
|
want: &corev1.Pod{},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "mutiple pods",
|
|
args: args{selector: fmt.Sprintf("component=%s", "nodejs")},
|
|
returnedPods: &corev1.PodList{
|
|
Items: []corev1.Pod{
|
|
*fakePod,
|
|
*fakePod,
|
|
},
|
|
},
|
|
want: &corev1.Pod{},
|
|
wantErr: true,
|
|
},
|
|
{
|
|
name: "pod is in the deletion state",
|
|
args: args{selector: fmt.Sprintf("component=%s", "nodejs")},
|
|
returnedPods: &corev1.PodList{
|
|
Items: []corev1.Pod{
|
|
*fakePodWithDeletionTimeStamp,
|
|
},
|
|
},
|
|
want: &corev1.Pod{},
|
|
wantErr: true,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
fkclient, fkclientset := FakeNew()
|
|
|
|
fkclientset.Kubernetes.PrependReactor("list", "pods", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) {
|
|
if action.(ktesting.ListAction).GetListRestrictions().Labels.String() != fmt.Sprintf("component=%s", "nodejs") {
|
|
t.Errorf("list called with different selector want:%s, got:%s", fmt.Sprintf("component=%s", "nodejs"), action.(ktesting.ListAction).GetListRestrictions().Labels.String())
|
|
}
|
|
return true, tt.returnedPods, nil
|
|
})
|
|
|
|
got, err := fkclient.GetRunningPodFromSelector(tt.args.selector)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("GetOnePodFromSelector() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
} else if tt.wantErr && err != nil {
|
|
return
|
|
}
|
|
if diff := cmp.Diff(tt.want, got); diff != "" {
|
|
t.Errorf("Client.GetRunningPodFromSelector() mismatch (-want +got):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetPodUsingComponentName(t *testing.T) {
|
|
fakePod := FakePodStatus(corev1.PodRunning, "nodejs")
|
|
fakePod.Labels["component"] = "nodejs"
|
|
|
|
type args struct {
|
|
componentName string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want *corev1.Pod
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "list called with same component name",
|
|
args: args{
|
|
componentName: "nodejs",
|
|
},
|
|
want: fakePod,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
fkclient, fkclientset := FakeNew()
|
|
|
|
fkclientset.Kubernetes.PrependReactor("list", "pods", func(action ktesting.Action) (handled bool, ret runtime.Object, err error) {
|
|
if action.(ktesting.ListAction).GetListRestrictions().Labels.String() != fmt.Sprintf("component=%s", tt.args.componentName) {
|
|
t.Errorf("list called with different selector want:%s, got:%s", fmt.Sprintf("component=%s", tt.args.componentName), action.(ktesting.ListAction).GetListRestrictions().Labels.String())
|
|
}
|
|
return true, &corev1.PodList{
|
|
Items: []corev1.Pod{
|
|
*fakePod,
|
|
},
|
|
}, nil
|
|
})
|
|
|
|
got, err := fkclient.GetPodUsingComponentName(tt.args.componentName)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("GetPodUsingComponentName() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if diff := cmp.Diff(tt.want, got); diff != "" {
|
|
t.Errorf("Client.GetPodUsingComponentName() mismatch (-want +got):\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func generateOwnerReference(object unstructured.Unstructured) metav1.OwnerReference {
|
|
return metav1.OwnerReference{
|
|
APIVersion: object.GetAPIVersion(),
|
|
Kind: object.GetKind(),
|
|
Name: object.GetName(),
|
|
UID: object.GetUID(),
|
|
}
|
|
}
|
|
|
|
func Test_matchOwnerReferenceWithResources_PodsWithOwnerInResources(t *testing.T) {
|
|
type args struct {
|
|
resources func() []unstructured.Unstructured
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
want bool
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "Case 1: pod owned by a deployment",
|
|
args: args{
|
|
resources: func() []unstructured.Unstructured {
|
|
pod := fakePod("pod")
|
|
deployment := fakeDeployment("deployment")
|
|
deployOwnerRef := generateOwnerReference(deployment)
|
|
pod.SetOwnerReferences([]metav1.OwnerReference{deployOwnerRef})
|
|
return []unstructured.Unstructured{pod, deployment}
|
|
},
|
|
},
|
|
want: true,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
kubernetesClient := NewMockClientInterface(ctrl)
|
|
|
|
got, err := matchOwnerReferenceWithResources(
|
|
kubernetesClient,
|
|
tt.args.resources()[0].GetOwnerReferences()[0],
|
|
tt.args.resources(),
|
|
)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("matchOwnerReferenceWithResources() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("matchOwnerReferenceWithResources() got = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func fakePod(name string) unstructured.Unstructured {
|
|
return unstructured.Unstructured{Object: map[string]interface{}{
|
|
"apiVersion": "v1",
|
|
"kind": "Pod",
|
|
"metadata": map[string]interface{}{
|
|
"name": fmt.Sprintf("pod-%s", name),
|
|
"uid": fmt.Sprintf("pod-%s", name),
|
|
},
|
|
"spec": map[string]interface{}{
|
|
"containers": map[string]interface{}{
|
|
"name": fmt.Sprintf("%s-1", name),
|
|
"image": "image",
|
|
},
|
|
},
|
|
}}
|
|
}
|
|
|
|
func fakeDeployment(name string) unstructured.Unstructured {
|
|
return unstructured.Unstructured{
|
|
Object: map[string]interface{}{
|
|
"apiVersion": "apps/v1",
|
|
"kind": "Deployment",
|
|
"metadata": map[string]interface{}{
|
|
"name": fmt.Sprintf("deployment-%s", name),
|
|
"uid": fmt.Sprintf("deployment-%s", name),
|
|
},
|
|
"spec": map[string]interface{}{
|
|
"selector": map[string]interface{}{
|
|
"matchLabels": map[string]interface{}{
|
|
"app": "test",
|
|
},
|
|
},
|
|
"template": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
"labels": map[string]interface{}{
|
|
"app": "test",
|
|
},
|
|
},
|
|
"spec": fakePod(name),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func Test_matchOwnerReferenceWithResources_PodsWithNoOwnerInResources(t *testing.T) {
|
|
// pod and deployment that are not a part of args.resources
|
|
independentDeploy := fakeDeployment("independent-deploy")
|
|
independentPod := fakePod("independent-pod")
|
|
independentPod.SetOwnerReferences([]metav1.OwnerReference{generateOwnerReference(independentDeploy)})
|
|
|
|
type args struct {
|
|
resources func() []unstructured.Unstructured
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
args args
|
|
gvk *meta.RESTMapping
|
|
resource *unstructured.Unstructured
|
|
want bool
|
|
wantErr bool
|
|
}{
|
|
{
|
|
name: "Case 1: Pod not owned by anything in `resources` slice",
|
|
args: args{
|
|
resources: func() []unstructured.Unstructured {
|
|
pod := fakePod("pod")
|
|
deployment := fakeDeployment("deployment")
|
|
deployOwnerRef := generateOwnerReference(deployment)
|
|
pod.SetOwnerReferences([]metav1.OwnerReference{deployOwnerRef})
|
|
return []unstructured.Unstructured{pod, deployment}
|
|
},
|
|
},
|
|
gvk: &meta.RESTMapping{
|
|
Resource: schema.GroupVersionResource{
|
|
Group: "apps",
|
|
Version: "v1",
|
|
Resource: "deployments",
|
|
},
|
|
GroupVersionKind: schema.GroupVersionKind{
|
|
Group: "apps",
|
|
Version: "v1",
|
|
Kind: "Deployment",
|
|
},
|
|
},
|
|
resource: &unstructured.Unstructured{Object: map[string]interface{}{
|
|
"apiVersion": "apps/v1",
|
|
"kind": "Deployment",
|
|
"metadata": map[string]interface{}{
|
|
"namespace": independentDeploy.GetNamespace(),
|
|
"name": independentDeploy.GetName(),
|
|
"uid": independentDeploy.GetUID(),
|
|
},
|
|
"spec": map[string]interface{}{
|
|
"selector": map[string]interface{}{
|
|
"matchLabels": map[string]interface{}{
|
|
"app": "test",
|
|
},
|
|
},
|
|
"template": map[string]interface{}{
|
|
"metadata": map[string]interface{}{
|
|
"labels": map[string]interface{}{
|
|
"app": "test",
|
|
},
|
|
},
|
|
"spec": fakePod(independentDeploy.GetName()),
|
|
},
|
|
},
|
|
}},
|
|
want: false,
|
|
wantErr: false,
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ctrl := gomock.NewController(t)
|
|
kubernetesClient := NewMockClientInterface(ctrl)
|
|
kubernetesClient.EXPECT().GetRestMappingFromGVK(
|
|
schema.FromAPIVersionAndKind(independentDeploy.GetAPIVersion(), independentDeploy.GetKind())).Return(tt.gvk, nil).AnyTimes()
|
|
kubernetesClient.EXPECT().GetDynamicResource(tt.gvk.Resource, independentDeploy.GetName()).Return(tt.resource, nil).AnyTimes()
|
|
|
|
got, err := matchOwnerReferenceWithResources(kubernetesClient, independentPod.GetOwnerReferences()[0], tt.args.resources())
|
|
if (err != nil) != tt.wantErr {
|
|
t.Errorf("matchOwnerReferenceWithResources() error = %v, wantErr %v", err, tt.wantErr)
|
|
return
|
|
}
|
|
if got != tt.want {
|
|
t.Errorf("matchOwnerReferenceWithResources() got = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|