mirror of https://github.com/openkruise/kruise.git
1268 lines
35 KiB
Go
1268 lines
35 KiB
Go
/*
|
|
Copyright 2020 The Kruise 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 sidecarcontrol
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"reflect"
|
|
"testing"
|
|
|
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/util/sets"
|
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
|
|
|
appsv1alpha1 "github.com/openkruise/kruise/apis/apps/v1alpha1"
|
|
"github.com/openkruise/kruise/pkg/util"
|
|
"github.com/openkruise/kruise/pkg/util/configuration"
|
|
)
|
|
|
|
func init() {
|
|
sch = runtime.NewScheme()
|
|
utilruntime.Must(corev1.AddToScheme(sch))
|
|
}
|
|
|
|
var (
|
|
sch *runtime.Scheme
|
|
|
|
// image.Name -> image.Id
|
|
ImageIds = map[string]string{
|
|
"main:v1": "4120593193b4",
|
|
"cold-sidecar:v1": "docker-pullable://cold-sidecar@sha256:9ead06a1362e",
|
|
"cold-sidecar:v2": "docker-pullable://cold-sidecar@sha256:7223aa0f3a7a",
|
|
"hot-sidecar:v1": "docker-pullable://hot-sidecar@sha256:86618128c92e",
|
|
"hot-sidecar:v2": "docker-pullable://hot-sidecar@sha256:74abd85af1e9",
|
|
"hotupgrade:empty": "docker-pullable://hotupgrade@sha256:0e9daf5c02e7",
|
|
}
|
|
|
|
podDemo = &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{},
|
|
Name: "test-pod-1",
|
|
Namespace: "default",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
ResourceVersion: "495711227",
|
|
},
|
|
Spec: corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: "main",
|
|
Image: "main:v1",
|
|
},
|
|
{
|
|
Name: "cold-sidecar",
|
|
Image: "cold-sidecar:v1",
|
|
},
|
|
{
|
|
Name: "hot-sidecar-1",
|
|
Image: "hot-sidecar:v1",
|
|
},
|
|
{
|
|
Name: "hot-sidecar-2",
|
|
Image: "hotupgrade:empty",
|
|
},
|
|
},
|
|
},
|
|
Status: corev1.PodStatus{
|
|
Phase: corev1.PodRunning,
|
|
Conditions: []corev1.PodCondition{
|
|
{
|
|
Type: corev1.PodReady,
|
|
Status: corev1.ConditionTrue,
|
|
},
|
|
},
|
|
ContainerStatuses: []corev1.ContainerStatus{
|
|
{
|
|
Name: "main",
|
|
Image: "main:v1",
|
|
ImageID: ImageIds["main:v1"],
|
|
Ready: true,
|
|
},
|
|
{
|
|
Name: "cold-sidecar",
|
|
Image: "cold-sidecar:v1",
|
|
ImageID: ImageIds["cold-sidecar:v1"],
|
|
Ready: true,
|
|
},
|
|
{
|
|
Name: "hot-sidecar-1",
|
|
Image: "hot-sidecar:v1",
|
|
ImageID: ImageIds["hot-sidecar:v1"],
|
|
Ready: true,
|
|
},
|
|
{
|
|
Name: "hot-sidecar-2",
|
|
Image: "hotupgrade:empty",
|
|
ImageID: ImageIds["hotupgrade:empty"],
|
|
Ready: true,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
sidecarSetDemo = &appsv1alpha1.SidecarSet{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Generation: 123,
|
|
Annotations: map[string]string{
|
|
SidecarSetHashAnnotation: "bbb",
|
|
SidecarSetHashWithoutImageAnnotation: "without-image-aaa",
|
|
},
|
|
Name: "test-sidecarset",
|
|
Labels: map[string]string{
|
|
"app": "sidecar",
|
|
},
|
|
},
|
|
Spec: appsv1alpha1.SidecarSetSpec{
|
|
Containers: []appsv1alpha1.SidecarContainer{
|
|
{
|
|
Container: corev1.Container{
|
|
Name: "cold-sidecar",
|
|
Image: "cold-image:v1",
|
|
},
|
|
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
|
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
|
},
|
|
},
|
|
{
|
|
Container: corev1.Container{
|
|
Name: "hot-sidecar",
|
|
Image: "hot-image:v1",
|
|
},
|
|
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
|
UpgradeType: appsv1alpha1.SidecarContainerHotUpgrade,
|
|
HotUpgradeEmptyImage: "hotupgrade:empty",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
)
|
|
|
|
func TestIsSidecarContainerUpdateCompleted(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
getPod func() *corev1.Pod
|
|
upgradeSidecars func() (sets.String, sets.String)
|
|
expectedCompleted bool
|
|
}{
|
|
{
|
|
name: "only inject sidecar, not upgrade",
|
|
getPod: func() *corev1.Pod {
|
|
return podDemo.DeepCopy()
|
|
},
|
|
upgradeSidecars: func() (sets.String, sets.String) {
|
|
return sets.NewString(sidecarSetDemo.Name), sets.NewString("cold-sidecar", "hot-sidecar-1", "hot-sidecar-2")
|
|
},
|
|
expectedCompleted: true,
|
|
},
|
|
{
|
|
name: "upgrade cold sidecar, upgrade not completed",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
control := New(sidecarSetDemo.DeepCopy())
|
|
pod.Spec.Containers[1].Image = "cold-sidecar:v2"
|
|
UpdatePodSidecarSetHash(pod, control.GetSidecarset())
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"cold-sidecar"}, pod)
|
|
return pod
|
|
},
|
|
upgradeSidecars: func() (sets.String, sets.String) {
|
|
return sets.NewString(sidecarSetDemo.Name), sets.NewString("cold-sidecar", "hot-sidecar-1", "hot-sidecar-2")
|
|
},
|
|
expectedCompleted: false,
|
|
},
|
|
{
|
|
name: "upgrade cold sidecar, upgrade completed",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
control := New(sidecarSetDemo.DeepCopy())
|
|
pod.Spec.Containers[1].Image = "cold-sidecar:v2"
|
|
UpdatePodSidecarSetHash(pod, control.GetSidecarset())
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"cold-sidecar"}, pod)
|
|
pod.Status.ContainerStatuses[1].ImageID = ImageIds["cold-sidecar:v2"]
|
|
return pod
|
|
},
|
|
upgradeSidecars: func() (sets.String, sets.String) {
|
|
return sets.NewString(sidecarSetDemo.Name), sets.NewString("cold-sidecar", "hot-sidecar-1", "hot-sidecar-2")
|
|
},
|
|
expectedCompleted: true,
|
|
},
|
|
{
|
|
name: "upgrade hot sidecar, upgrade hot-sidecar-2 not completed",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
control := New(sidecarSetDemo.DeepCopy())
|
|
// upgrade cold sidecar completed
|
|
pod.Spec.Containers[1].Image = "cold-sidecar:v2"
|
|
UpdatePodSidecarSetHash(pod, control.GetSidecarset())
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"cold-sidecar"}, pod)
|
|
pod.Status.ContainerStatuses[1].ImageID = ImageIds["cold-sidecar:v2"]
|
|
// start upgrading hot sidecar
|
|
pod.Spec.Containers[3].Image = "hot-sidecar:v2"
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"hot-sidecar-2"}, pod)
|
|
return pod
|
|
},
|
|
upgradeSidecars: func() (sets.String, sets.String) {
|
|
return sets.NewString(sidecarSetDemo.Name), sets.NewString("cold-sidecar", "hot-sidecar-1", "hot-sidecar-2")
|
|
},
|
|
expectedCompleted: false,
|
|
},
|
|
{
|
|
name: "upgrade hot sidecar, upgrade hot-sidecar-1 not completed",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
control := New(sidecarSetDemo.DeepCopy())
|
|
// upgrade cold sidecar completed
|
|
pod.Spec.Containers[1].Image = "cold-sidecar:v2"
|
|
UpdatePodSidecarSetHash(pod, control.GetSidecarset())
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"cold-sidecar"}, pod)
|
|
pod.Status.ContainerStatuses[1].ImageID = ImageIds["cold-sidecar:v2"]
|
|
// start upgrading hot sidecar
|
|
pod.Spec.Containers[3].Image = "hot-sidecar:v2"
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"hot-sidecar-2"}, pod)
|
|
pod.Status.ContainerStatuses[3].ImageID = ImageIds["hot-sidecar:v2"]
|
|
pod.Spec.Containers[2].Image = "hotupgrade:empty"
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"hot-sidecar-1"}, pod)
|
|
return pod
|
|
},
|
|
upgradeSidecars: func() (sets.String, sets.String) {
|
|
return sets.NewString(sidecarSetDemo.Name), sets.NewString("cold-sidecar", "hot-sidecar-1", "hot-sidecar-2")
|
|
},
|
|
expectedCompleted: false,
|
|
},
|
|
{
|
|
name: "upgrade hot sidecar, upgrade hot-sidecar completed",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
control := New(sidecarSetDemo.DeepCopy())
|
|
// upgrade cold sidecar completed
|
|
pod.Spec.Containers[1].Image = "cold-sidecar:v2"
|
|
UpdatePodSidecarSetHash(pod, control.GetSidecarset())
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"cold-sidecar"}, pod)
|
|
pod.Status.ContainerStatuses[1].ImageID = ImageIds["cold-sidecar:v2"]
|
|
// start upgrading hot sidecar
|
|
pod.Spec.Containers[3].Image = "hot-sidecar:v2"
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"hot-sidecar-2"}, pod)
|
|
pod.Status.ContainerStatuses[3].ImageID = ImageIds["hot-sidecar:v2"]
|
|
pod.Spec.Containers[2].Image = "hotupgrade:empty"
|
|
control.UpdatePodAnnotationsInUpgrade([]string{"hot-sidecar-1"}, pod)
|
|
pod.Status.ContainerStatuses[2].ImageID = ImageIds["hotupgrade:empty"]
|
|
return pod
|
|
},
|
|
upgradeSidecars: func() (sets.String, sets.String) {
|
|
return sets.NewString(sidecarSetDemo.Name), sets.NewString("cold-sidecar", "hot-sidecar-1", "hot-sidecar-2")
|
|
},
|
|
expectedCompleted: true,
|
|
},
|
|
}
|
|
|
|
for _, cs := range cases {
|
|
t.Run(cs.name, func(t *testing.T) {
|
|
pod := cs.getPod()
|
|
sidecarSets, containers := cs.upgradeSidecars()
|
|
if IsSidecarContainerUpdateCompleted(pod, sidecarSets, containers) != cs.expectedCompleted {
|
|
t.Fatalf("IsSidecarContainerUpdateCompleted failed: %s", cs.name)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetPodSidecarSetRevision(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
getPod func() *corev1.Pod
|
|
//sidecarContainer -> sidecarSet.Revision
|
|
exceptRevision string
|
|
exceptWithoutImageRevision string
|
|
}{
|
|
{
|
|
name: "normal sidecarSet revision",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
pod.Annotations[SidecarSetHashAnnotation] = `{"test-sidecarset":{"hash":"aaa"}}`
|
|
pod.Annotations[SidecarSetHashWithoutImageAnnotation] = `{"test-sidecarset":{"hash":"without-image-aaa"}}`
|
|
return pod
|
|
},
|
|
exceptRevision: "aaa",
|
|
exceptWithoutImageRevision: "without-image-aaa",
|
|
},
|
|
{
|
|
name: "older sidecarSet revision",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
pod.Annotations[SidecarSetHashAnnotation] = `{"test-sidecarset": "aaa"}`
|
|
pod.Annotations[SidecarSetHashWithoutImageAnnotation] = `{"test-sidecarset": "without-image-aaa"}`
|
|
return pod
|
|
},
|
|
exceptRevision: "aaa",
|
|
exceptWithoutImageRevision: "without-image-aaa",
|
|
},
|
|
{
|
|
name: "failed sidecarSet revision",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
pod.Annotations[SidecarSetHashAnnotation] = "failed-sidecarset-hash"
|
|
pod.Annotations[SidecarSetHashWithoutImageAnnotation] = "failed-sidecarset-hash"
|
|
return pod
|
|
},
|
|
exceptRevision: "",
|
|
exceptWithoutImageRevision: "",
|
|
},
|
|
}
|
|
|
|
for _, cs := range cases {
|
|
t.Run(cs.name, func(t *testing.T) {
|
|
revision := GetPodSidecarSetRevision("test-sidecarset", cs.getPod())
|
|
if cs.exceptRevision != revision {
|
|
t.Fatalf("except sidecar container test-sidecarset revision %s, but get %s", cs.exceptRevision, revision)
|
|
}
|
|
withoutRevision := GetPodSidecarSetWithoutImageRevision("test-sidecarset", cs.getPod())
|
|
if cs.exceptWithoutImageRevision != withoutRevision {
|
|
t.Fatalf("except sidecar container test-sidecarset WithoutImageRevision %s, but get %s", cs.exceptWithoutImageRevision, withoutRevision)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdatePodSidecarSetHash(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
getPod func() *corev1.Pod
|
|
getSidecarSet func() *appsv1alpha1.SidecarSet
|
|
exceptRevision map[string]SidecarSetUpgradeSpec
|
|
exceptWithoutImageRevision map[string]SidecarSetUpgradeSpec
|
|
}{
|
|
{
|
|
name: "normal sidecarSet revision",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
pod.Annotations[SidecarSetHashAnnotation] = `{"test-sidecarset":{"hash":"aaa"}}`
|
|
pod.Annotations[SidecarSetHashWithoutImageAnnotation] = `{"test-sidecarset":{"hash":"without-image-aaa"}}`
|
|
return pod
|
|
},
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
return sidecarSetDemo.DeepCopy()
|
|
},
|
|
exceptRevision: map[string]SidecarSetUpgradeSpec{
|
|
"test-sidecarset": {
|
|
SidecarSetHash: "bbb",
|
|
},
|
|
},
|
|
exceptWithoutImageRevision: map[string]SidecarSetUpgradeSpec{
|
|
"test-sidecarset": {
|
|
SidecarSetHash: "without-image-aaa",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "older sidecarSet revision",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
pod.Annotations[SidecarSetHashAnnotation] = `{"test-sidecarset": "aaa"}`
|
|
pod.Annotations[SidecarSetHashWithoutImageAnnotation] = `{"test-sidecarset": "without-image-aaa"}`
|
|
return pod
|
|
},
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
return sidecarSetDemo.DeepCopy()
|
|
},
|
|
exceptRevision: map[string]SidecarSetUpgradeSpec{
|
|
"test-sidecarset": {
|
|
SidecarSetHash: "bbb",
|
|
},
|
|
},
|
|
exceptWithoutImageRevision: map[string]SidecarSetUpgradeSpec{
|
|
"test-sidecarset": {
|
|
SidecarSetHash: "without-image-aaa",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "failed sidecarSet revision",
|
|
getPod: func() *corev1.Pod {
|
|
pod := podDemo.DeepCopy()
|
|
pod.Annotations[SidecarSetHashAnnotation] = "failed-sidecarset-hash"
|
|
pod.Annotations[SidecarSetHashWithoutImageAnnotation] = "failed-sidecarset-hash"
|
|
return pod
|
|
},
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
return sidecarSetDemo.DeepCopy()
|
|
},
|
|
exceptRevision: map[string]SidecarSetUpgradeSpec{
|
|
"test-sidecarset": {
|
|
SidecarSetHash: "bbb",
|
|
},
|
|
},
|
|
exceptWithoutImageRevision: map[string]SidecarSetUpgradeSpec{},
|
|
},
|
|
}
|
|
|
|
for _, cs := range cases {
|
|
t.Run(cs.name, func(t *testing.T) {
|
|
podInput := cs.getPod()
|
|
sidecarSetInput := cs.getSidecarSet()
|
|
UpdatePodSidecarSetHash(podInput, sidecarSetInput)
|
|
// sidecarSet hash
|
|
sidecarSetHash := make(map[string]SidecarSetUpgradeSpec)
|
|
err := json.Unmarshal([]byte(podInput.Annotations[SidecarSetHashAnnotation]), &sidecarSetHash)
|
|
if err != nil {
|
|
t.Fatalf("parse pod sidecarSet hash failed: %s", err.Error())
|
|
}
|
|
for k, o := range sidecarSetHash {
|
|
eo := cs.exceptRevision[k]
|
|
if o.SidecarSetHash != eo.SidecarSetHash {
|
|
t.Fatalf("except sidecar container %s revision %s, but get revision %s", k, eo.SidecarSetHash, o.SidecarSetHash)
|
|
}
|
|
}
|
|
if len(cs.exceptWithoutImageRevision) == 0 {
|
|
return
|
|
}
|
|
// without image sidecarSet hash
|
|
sidecarSetHash = make(map[string]SidecarSetUpgradeSpec)
|
|
err = json.Unmarshal([]byte(podInput.Annotations[SidecarSetHashWithoutImageAnnotation]), &sidecarSetHash)
|
|
if err != nil {
|
|
t.Fatalf("parse pod sidecarSet hash failed: %s", err.Error())
|
|
}
|
|
for k, o := range sidecarSetHash {
|
|
eo := cs.exceptWithoutImageRevision[k]
|
|
if o.SidecarSetHash != eo.SidecarSetHash {
|
|
t.Fatalf("except sidecar container %s revision %s, but get revision %s", k, eo.SidecarSetHash, o.SidecarSetHash)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestConvertDownwardAPIFieldLabel(t *testing.T) {
|
|
testCases := []struct {
|
|
version string
|
|
label string
|
|
value string
|
|
expectedErr bool
|
|
expectedLabel string
|
|
expectedValue string
|
|
}{
|
|
{
|
|
version: "v2",
|
|
label: "metadata.name",
|
|
value: "test-pod",
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
version: "v1",
|
|
label: "invalid-label",
|
|
value: "value",
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
version: "v1",
|
|
label: "metadata.name",
|
|
value: "test-pod",
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
version: "v1",
|
|
label: "metadata.annotations",
|
|
value: "myAnnoValue",
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
version: "v1",
|
|
label: "metadata.labels",
|
|
value: "myLabelValue",
|
|
expectedErr: true,
|
|
},
|
|
{
|
|
version: "v1",
|
|
label: "metadata.annotations['myAnnoKey']",
|
|
value: "myAnnoValue",
|
|
expectedLabel: "metadata.annotations['myAnnoKey']",
|
|
expectedValue: "myAnnoValue",
|
|
},
|
|
{
|
|
version: "v1",
|
|
label: "metadata.labels['myLabelKey']",
|
|
value: "myLabelValue",
|
|
expectedLabel: "metadata.labels['myLabelKey']",
|
|
expectedValue: "myLabelValue",
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
label, value, err := ConvertDownwardAPIFieldLabel(tc.version, tc.label, tc.value)
|
|
if err != nil {
|
|
if tc.expectedErr {
|
|
continue
|
|
}
|
|
t.Errorf("ConvertDownwardAPIFieldLabel(%s, %s, %s) failed: %s",
|
|
tc.version, tc.label, tc.value, err)
|
|
}
|
|
if tc.expectedLabel != label || tc.expectedValue != value {
|
|
t.Errorf("ConvertDownwardAPIFieldLabel(%s, %s, %s) = (%s, %s, nil), expected (%s, %s, nil)",
|
|
tc.version, tc.label, tc.value, label, value, tc.expectedLabel, tc.expectedValue)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestExtractContainerNameFromFieldPath(t *testing.T) {
|
|
testCases := []struct {
|
|
fieldSelector *corev1.ObjectFieldSelector
|
|
pod *corev1.Pod
|
|
expectedErr bool
|
|
expectedName string
|
|
}{
|
|
{
|
|
fieldSelector: &corev1.ObjectFieldSelector{
|
|
APIVersion: "v1",
|
|
FieldPath: "metadata.labels['test-label']",
|
|
},
|
|
pod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod-label",
|
|
Labels: map[string]string{
|
|
"test-label": "test-pod-label",
|
|
},
|
|
}},
|
|
expectedName: "test-pod-label",
|
|
},
|
|
{
|
|
fieldSelector: &corev1.ObjectFieldSelector{
|
|
APIVersion: "v1",
|
|
FieldPath: "metadata.labels['test-label']",
|
|
},
|
|
pod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod-label",
|
|
}},
|
|
expectedName: "",
|
|
},
|
|
{
|
|
fieldSelector: &corev1.ObjectFieldSelector{
|
|
APIVersion: "v1",
|
|
FieldPath: "metadata.annotations['test-anno']",
|
|
},
|
|
pod: &corev1.Pod{ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod-anno",
|
|
Annotations: map[string]string{
|
|
"test-anno": "test-pod-anno",
|
|
},
|
|
}},
|
|
expectedName: "test-pod-anno",
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
containerName, err := ExtractContainerNameFromFieldPath(tc.fieldSelector, tc.pod)
|
|
if err != nil {
|
|
if tc.expectedErr {
|
|
continue
|
|
}
|
|
t.Errorf("ExtractContainerNameFromFieldPath(%s, %s) failed: %s",
|
|
tc.fieldSelector.FieldPath, tc.expectedName, err)
|
|
}
|
|
if tc.expectedName != containerName {
|
|
t.Errorf("ExtractContainerNameFromFieldPath (%s, %s), expected (%s)",
|
|
tc.fieldSelector.FieldPath, containerName, tc.expectedName)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetSidecarTransferEnvs(t *testing.T) {
|
|
testCases := []struct {
|
|
sidecarContainer *appsv1alpha1.SidecarContainer
|
|
pod *corev1.Pod
|
|
expectedEnvs []corev1.EnvVar
|
|
}{
|
|
{
|
|
sidecarContainer: &appsv1alpha1.SidecarContainer{
|
|
Container: corev1.Container{
|
|
Name: "cold-sidecar",
|
|
Image: "cold-image:v1",
|
|
},
|
|
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
|
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
|
},
|
|
TransferEnv: []appsv1alpha1.TransferEnvVar{
|
|
{
|
|
EnvName: "test-env",
|
|
SourceContainerName: "main",
|
|
},
|
|
},
|
|
},
|
|
pod: &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{},
|
|
Name: "test-pod-1",
|
|
Namespace: "default",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
ResourceVersion: "495711227",
|
|
},
|
|
Spec: corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: "main",
|
|
Image: "main:v1",
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "test-env",
|
|
Value: "test-value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedEnvs: []corev1.EnvVar{
|
|
{
|
|
Name: "test-env",
|
|
Value: "test-value",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
sidecarContainer: &appsv1alpha1.SidecarContainer{
|
|
Container: corev1.Container{
|
|
Name: "cold-sidecar",
|
|
Image: "cold-image:v1",
|
|
},
|
|
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
|
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
|
},
|
|
TransferEnv: []appsv1alpha1.TransferEnvVar{
|
|
{
|
|
EnvName: "test-env",
|
|
SourceContainerNameFrom: &appsv1alpha1.SourceContainerNameSource{
|
|
FieldRef: &corev1.ObjectFieldSelector{
|
|
APIVersion: "v1",
|
|
FieldPath: "metadata.labels['app']",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
pod: &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{},
|
|
Name: "test-pod-1",
|
|
Namespace: "default",
|
|
Labels: map[string]string{"app": "main"},
|
|
ResourceVersion: "495711227",
|
|
},
|
|
Spec: corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: "main",
|
|
Image: "main:v1",
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "test-env",
|
|
Value: "test-value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedEnvs: []corev1.EnvVar{
|
|
{
|
|
Name: "test-env",
|
|
Value: "test-value",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
sidecarContainer: &appsv1alpha1.SidecarContainer{
|
|
Container: corev1.Container{
|
|
Name: "cold-sidecar",
|
|
Image: "cold-image:v1",
|
|
},
|
|
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
|
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
|
},
|
|
TransferEnv: []appsv1alpha1.TransferEnvVar{
|
|
{
|
|
EnvName: "test-env",
|
|
SourceContainerNameFrom: &appsv1alpha1.SourceContainerNameSource{
|
|
FieldRef: &corev1.ObjectFieldSelector{
|
|
APIVersion: "v1",
|
|
FieldPath: "metadata.annotations['app']",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
pod: &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{"app": "main"},
|
|
Name: "test-pod-1",
|
|
Namespace: "default",
|
|
Labels: map[string]string{"app": "main"},
|
|
ResourceVersion: "495711227",
|
|
},
|
|
Spec: corev1.PodSpec{
|
|
Containers: []corev1.Container{
|
|
{
|
|
Name: "main",
|
|
Image: "main:v1",
|
|
Env: []corev1.EnvVar{
|
|
{
|
|
Name: "test-env",
|
|
Value: "test-value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedEnvs: []corev1.EnvVar{
|
|
{
|
|
Name: "test-env",
|
|
Value: "test-value",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range testCases {
|
|
injectedEnvs := GetSidecarTransferEnvs(tc.sidecarContainer, tc.pod)
|
|
if len(injectedEnvs) != len(tc.expectedEnvs) {
|
|
t.Errorf("GetSidecarTransferEnv failed, expected envs %s, got %s",
|
|
tc.expectedEnvs, injectedEnvs)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPatchPodMetadata(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
getPod func() *corev1.Pod
|
|
patches func() []appsv1alpha1.SidecarSetPatchPodMetadata
|
|
expectAnnotations map[string]string
|
|
expectErr bool
|
|
skip bool
|
|
}{
|
|
{
|
|
name: "add pod annotation",
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{}
|
|
return demo
|
|
},
|
|
patches: func() []appsv1alpha1.SidecarSetPatchPodMetadata {
|
|
patch := []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
PatchPolicy: appsv1alpha1.SidecarSetRetainPatchPolicy,
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
{
|
|
PatchPolicy: appsv1alpha1.SidecarSetOverwritePatchPolicy,
|
|
Annotations: map[string]string{
|
|
"key2": "value2",
|
|
},
|
|
},
|
|
}
|
|
return patch
|
|
},
|
|
expectAnnotations: map[string]string{
|
|
"key1": "value1",
|
|
"key2": "value2",
|
|
},
|
|
skip: false,
|
|
expectErr: false,
|
|
},
|
|
{
|
|
name: "add pod annotation, exist",
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
"key1": "old",
|
|
"key2": "old",
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
patches: func() []appsv1alpha1.SidecarSetPatchPodMetadata {
|
|
patch := []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
PatchPolicy: appsv1alpha1.SidecarSetRetainPatchPolicy,
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
{
|
|
PatchPolicy: appsv1alpha1.SidecarSetOverwritePatchPolicy,
|
|
Annotations: map[string]string{
|
|
"key2": "value2",
|
|
},
|
|
},
|
|
}
|
|
return patch
|
|
},
|
|
expectAnnotations: map[string]string{
|
|
"key1": "old",
|
|
"key2": "value2",
|
|
},
|
|
skip: false,
|
|
expectErr: false,
|
|
},
|
|
{
|
|
name: "json merge pod annotation",
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
"key1": `{"log-agent":1}`,
|
|
"key2": `{"log-agent":1}`,
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
patches: func() []appsv1alpha1.SidecarSetPatchPodMetadata {
|
|
patch := []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
PatchPolicy: appsv1alpha1.SidecarSetMergePatchJsonPatchPolicy,
|
|
Annotations: map[string]string{
|
|
"key1": `{"log-agent":1}`,
|
|
"key2": `{"envoy":2}`,
|
|
"key3": `{"probe":5}`,
|
|
},
|
|
},
|
|
}
|
|
return patch
|
|
},
|
|
expectAnnotations: map[string]string{
|
|
"key1": `{"log-agent":1}`,
|
|
"key2": `{"envoy":2,"log-agent":1}`,
|
|
"key3": `{"probe":5}`,
|
|
},
|
|
skip: false,
|
|
expectErr: false,
|
|
},
|
|
{
|
|
name: "json merge pod annotation, skip",
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Annotations: map[string]string{
|
|
"key1": `{"log-agent":1}`,
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
patches: func() []appsv1alpha1.SidecarSetPatchPodMetadata {
|
|
patch := []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
PatchPolicy: appsv1alpha1.SidecarSetMergePatchJsonPatchPolicy,
|
|
Annotations: map[string]string{
|
|
"key1": `{"log-agent":1}`,
|
|
},
|
|
},
|
|
}
|
|
return patch
|
|
},
|
|
expectAnnotations: map[string]string{
|
|
"key1": `{"log-agent":1}`,
|
|
},
|
|
skip: true,
|
|
expectErr: false,
|
|
},
|
|
}
|
|
|
|
for _, cs := range cases {
|
|
t.Run(cs.name, func(t *testing.T) {
|
|
pod := cs.getPod()
|
|
skip, err := PatchPodMetadata(&pod.ObjectMeta, cs.patches())
|
|
if cs.expectErr && err == nil {
|
|
t.Fatalf("PatchPodMetadata failed")
|
|
} else if !cs.expectErr && err != nil {
|
|
t.Fatalf("PatchPodMetadata failed: %v", err)
|
|
} else if skip != cs.skip {
|
|
t.Fatalf("expect %v, but get %v", cs.skip, skip)
|
|
} else if !reflect.DeepEqual(cs.expectAnnotations, pod.Annotations) {
|
|
t.Fatalf("expect %v, but get %v", cs.expectAnnotations, pod.Annotations)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestValidateSidecarSetPatchMetadataWhitelist(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
getSidecarSet func() *appsv1alpha1.SidecarSet
|
|
getKruiseCM func() *corev1.ConfigMap
|
|
expectErr bool
|
|
}{
|
|
{
|
|
name: "validate sidecarSet no patch Metadata",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := sidecarSetDemo.DeepCopy()
|
|
return demo
|
|
},
|
|
getKruiseCM: func() *corev1.ConfigMap {
|
|
return nil
|
|
},
|
|
expectErr: false,
|
|
},
|
|
{
|
|
name: "validate sidecarSet whitelist failed-1",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := sidecarSetDemo.DeepCopy()
|
|
demo.Spec.PatchPodMetadata = []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getKruiseCM: func() *corev1.ConfigMap {
|
|
return nil
|
|
},
|
|
expectErr: true,
|
|
},
|
|
{
|
|
name: "validate sidecarSet whitelist success-1",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := sidecarSetDemo.DeepCopy()
|
|
demo.Spec.PatchPodMetadata = []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getKruiseCM: func() *corev1.ConfigMap {
|
|
demo := &corev1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: configuration.KruiseConfigurationName,
|
|
Namespace: util.GetKruiseNamespace(),
|
|
},
|
|
Data: map[string]string{
|
|
configuration.SidecarSetPatchPodMetadataWhiteListKey: `{"rules":[{"allowedAnnotationKeyExprs":["key.*"]}]}`,
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
expectErr: false,
|
|
},
|
|
{
|
|
name: "validate sidecarSet whitelist failed-2",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := sidecarSetDemo.DeepCopy()
|
|
demo.Spec.PatchPodMetadata = []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getKruiseCM: func() *corev1.ConfigMap {
|
|
demo := &corev1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: configuration.KruiseConfigurationName,
|
|
Namespace: util.GetKruiseNamespace(),
|
|
},
|
|
Data: map[string]string{
|
|
configuration.SidecarSetPatchPodMetadataWhiteListKey: `{"rules":[{"allowedAnnotationKeyExprs":["key2"]}]}`,
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
expectErr: true,
|
|
},
|
|
{
|
|
name: "validate sidecarSet whitelist failed-3",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := sidecarSetDemo.DeepCopy()
|
|
demo.Spec.PatchPodMetadata = []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getKruiseCM: func() *corev1.ConfigMap {
|
|
demo := &corev1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: configuration.KruiseConfigurationName,
|
|
Namespace: util.GetKruiseNamespace(),
|
|
},
|
|
Data: map[string]string{
|
|
configuration.SidecarSetPatchPodMetadataWhiteListKey: `{"rules":[{"allowedAnnotationKeyExprs":["key.*"],"selector":{"matchLabels":{"app":"other"}}}]}`,
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
expectErr: true,
|
|
},
|
|
{
|
|
name: "validate sidecarSet whitelist success-2",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := sidecarSetDemo.DeepCopy()
|
|
demo.Spec.PatchPodMetadata = []appsv1alpha1.SidecarSetPatchPodMetadata{
|
|
{
|
|
Annotations: map[string]string{
|
|
"key1": "value1",
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getKruiseCM: func() *corev1.ConfigMap {
|
|
demo := &corev1.ConfigMap{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: configuration.KruiseConfigurationName,
|
|
Namespace: util.GetKruiseNamespace(),
|
|
},
|
|
Data: map[string]string{
|
|
configuration.SidecarSetPatchPodMetadataWhiteListKey: `{"rules":[{"allowedAnnotationKeyExprs":["key.*"],"selector":{"matchLabels":{"app":"sidecar"}}}]}`,
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
expectErr: false,
|
|
},
|
|
}
|
|
|
|
for _, cs := range cases {
|
|
t.Run(cs.name, func(t *testing.T) {
|
|
fakeClient := fake.NewClientBuilder().WithScheme(sch).Build()
|
|
if cs.getKruiseCM() != nil {
|
|
fakeClient.Create(context.TODO(), cs.getKruiseCM())
|
|
}
|
|
err := ValidateSidecarSetPatchMetadataWhitelist(fakeClient, cs.getSidecarSet())
|
|
if cs.expectErr && err == nil {
|
|
t.Fatalf("ValidateSidecarSetPatchMetadataWhitelist failed")
|
|
} else if !cs.expectErr && err != nil {
|
|
t.Fatalf("ValidateSidecarSetPatchMetadataWhitelist failed: %s", err.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPodMatchedSidecarSet(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
getSidecarSet func() *appsv1alpha1.SidecarSet
|
|
getPod func() *corev1.Pod
|
|
getNs func() []*corev1.Namespace
|
|
expect bool
|
|
}{
|
|
{
|
|
name: "test1",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := &appsv1alpha1.SidecarSet{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "sidecarset-test"},
|
|
Spec: appsv1alpha1.SidecarSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "nginx"},
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
Namespace: "app1",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getNs: func() []*corev1.Namespace {
|
|
return nil
|
|
},
|
|
expect: true,
|
|
},
|
|
{
|
|
name: "test2",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := &appsv1alpha1.SidecarSet{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "sidecarset-test"},
|
|
Spec: appsv1alpha1.SidecarSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "nginx"},
|
|
},
|
|
Namespace: "app1",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
Namespace: "app1",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getNs: func() []*corev1.Namespace {
|
|
return nil
|
|
},
|
|
expect: true,
|
|
},
|
|
{
|
|
name: "test3",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := &appsv1alpha1.SidecarSet{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "sidecarset-test"},
|
|
Spec: appsv1alpha1.SidecarSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "nginx"},
|
|
},
|
|
Namespace: "app2",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
Namespace: "app1",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getNs: func() []*corev1.Namespace {
|
|
return nil
|
|
},
|
|
expect: false,
|
|
},
|
|
{
|
|
name: "test4",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := &appsv1alpha1.SidecarSet{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "sidecarset-test"},
|
|
Spec: appsv1alpha1.SidecarSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "nginx"},
|
|
},
|
|
NamespaceSelector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "app1"},
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
Namespace: "app1",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getNs: func() []*corev1.Namespace {
|
|
demo := []*corev1.Namespace{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app1",
|
|
Labels: map[string]string{"app": "app1"},
|
|
},
|
|
},
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app2",
|
|
Labels: map[string]string{"app": "app2"},
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
expect: true,
|
|
},
|
|
{
|
|
name: "test5",
|
|
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
|
demo := &appsv1alpha1.SidecarSet{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "sidecarset-test"},
|
|
Spec: appsv1alpha1.SidecarSetSpec{
|
|
Selector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "nginx"},
|
|
},
|
|
NamespaceSelector: &metav1.LabelSelector{
|
|
MatchLabels: map[string]string{"app": "app2"},
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getPod: func() *corev1.Pod {
|
|
demo := &corev1.Pod{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "test-pod",
|
|
Labels: map[string]string{"app": "nginx"},
|
|
Namespace: "app1",
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
getNs: func() []*corev1.Namespace {
|
|
demo := []*corev1.Namespace{
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app1",
|
|
Labels: map[string]string{"app": "app1"},
|
|
},
|
|
},
|
|
{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "app2",
|
|
Labels: map[string]string{"app": "app2"},
|
|
},
|
|
},
|
|
}
|
|
return demo
|
|
},
|
|
expect: false,
|
|
},
|
|
}
|
|
|
|
for _, cs := range cases {
|
|
t.Run(cs.name, func(t *testing.T) {
|
|
fakeClient := fake.NewClientBuilder().WithScheme(sch).Build()
|
|
for _, ns := range cs.getNs() {
|
|
_ = fakeClient.Create(context.TODO(), ns)
|
|
}
|
|
matched, err := PodMatchedSidecarSet(fakeClient, cs.getPod(), cs.getSidecarSet())
|
|
if err != nil {
|
|
t.Fatalf("PodMatchedSidecarSet failed: %s", err.Error())
|
|
}
|
|
if cs.expect != matched {
|
|
t.Fatalf("expect(%v), but get(%v)", cs.expect, matched)
|
|
}
|
|
})
|
|
}
|
|
}
|