diff --git a/.gitignore b/.gitignore index 01369e1cff..f04414d15b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ test/e2e/generated/bindata.go .vscode .DS_Store + +vendor/ diff --git a/pkg/control/sidecarcontrol/hash.go b/pkg/control/sidecarcontrol/hash.go index 85451dd1f7..be631500d5 100644 --- a/pkg/control/sidecarcontrol/hash.go +++ b/pkg/control/sidecarcontrol/hash.go @@ -43,6 +43,9 @@ func SidecarSetHashWithoutImage(sidecarSet *appsv1alpha1.SidecarSet) (string, er for i := range ss.Spec.Containers { ss.Spec.Containers[i].Image = "" } + for i := range ss.Spec.InitContainers { + ss.Spec.InitContainers[i].Image = "" + } encoded, err := encodeSidecarSet(ss) if err != nil { return "", err @@ -53,7 +56,17 @@ func SidecarSetHashWithoutImage(sidecarSet *appsv1alpha1.SidecarSet) (string, er func encodeSidecarSet(sidecarSet *appsv1alpha1.SidecarSet) (string, error) { // json.Marshal sorts the keys in a stable order in the encoding m := map[string]interface{}{"containers": sidecarSet.Spec.Containers} - //m["initContainers"] = sidecarSet.Spec.InitContainers + // when k8s 1.28, if initContainer restartPolicy = Always, indicates it is sidecar container, so the hash needs to contain it. + initContainer := make([]appsv1alpha1.SidecarContainer, 0) + for i := range sidecarSet.Spec.InitContainers { + container := &sidecarSet.Spec.InitContainers[i] + if IsSidecarContainer(container.Container) { + initContainer = append(initContainer, *container) + } + } + if len(initContainer) > 0 { + m["initContainers"] = sidecarSet.Spec.InitContainers + } data, err := json.Marshal(m) if err != nil { return "", err diff --git a/pkg/control/sidecarcontrol/hash_test.go b/pkg/control/sidecarcontrol/hash_test.go index 5549644461..6bf9c8f9e0 100644 --- a/pkg/control/sidecarcontrol/hash_test.go +++ b/pkg/control/sidecarcontrol/hash_test.go @@ -8,78 +8,210 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +var always = corev1.ContainerRestartPolicyAlways + func TestSidecarSetHash(t *testing.T) { - sidecarSet := &appsv1alpha1.SidecarSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-sidecar-set", + cases := []struct { + name string + getSidecarSet func() *appsv1alpha1.SidecarSet + expectHash string + }{ + { + name: "containers", + getSidecarSet: func() *appsv1alpha1.SidecarSet { + return &appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sidecar-set", + }, + Spec: appsv1alpha1.SidecarSetSpec{ + Containers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, + }, + } + }, + expectHash: "w26c4x8fz245642fdv499b464248f974xddx4x55z5dw55bc6x66464fxz77dc78", }, - Spec: appsv1alpha1.SidecarSetSpec{ - Containers: []appsv1alpha1.SidecarContainer{ - { - Container: corev1.Container{ - Name: "container1", - Image: "test-image", + { + name: "containers and initContainers", + getSidecarSet: func() *appsv1alpha1.SidecarSet { + return &appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sidecar-set", + }, + Spec: appsv1alpha1.SidecarSetSpec{ + Containers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, + InitContainers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, }, - }, + } }, + expectHash: "w26c4x8fz245642fdv499b464248f974xddx4x55z5dw55bc6x66464fxz77dc78", + }, + { + name: "containers and initContainers with restartPolicy=Always", + getSidecarSet: func() *appsv1alpha1.SidecarSet { + return &appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sidecar-set", + }, + Spec: appsv1alpha1.SidecarSetSpec{ + Containers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, + InitContainers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + RestartPolicy: &always, + }, + }, + }, + }, + } + }, + expectHash: "4xwx4d4844vd4v9x79wb4xbxf4xb29475cc4446v8cz2c2f2f5c5bw448vd42z8w", }, } - hash, err := SidecarSetHash(sidecarSet) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if hash == "" { - t.Fatalf("Expected non-empty hash") - } - - // Change sidecar set and expect different hash - sidecarSet.Spec.Containers[0].Image = "new-image" - newHash, err := SidecarSetHash(sidecarSet) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } + for _, cs := range cases { + t.Run(cs.name, func(t *testing.T) { + sidecarSet := cs.getSidecarSet() + hash1, err := SidecarSetHash(sidecarSet) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } else if hash1 == "" { + t.Fatalf("Expected non-empty hash") + } + if cs.expectHash != hash1 { + t.Fatalf("expect(%s), but get(%s)", cs.expectHash, hash1) + } - if newHash == hash { - t.Fatalf("Expected different hashes for different SidecarSets") + // Change sidecar set and expect different hash + sidecarSet.Spec.Containers[0].Image = "new-image" + newHash, err := SidecarSetHash(sidecarSet) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } else if newHash == hash1 { + t.Fatalf("Expected different hashes for different SidecarSets") + } + }) } } func TestSidecarSetHashWithoutImage(t *testing.T) { - sidecarSet := &appsv1alpha1.SidecarSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-sidecar-set", + cases := []struct { + name string + getSidecarSet func() *appsv1alpha1.SidecarSet + expectHash string + }{ + { + name: "containers and initContainers", + getSidecarSet: func() *appsv1alpha1.SidecarSet { + return &appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sidecar-set", + }, + Spec: appsv1alpha1.SidecarSetSpec{ + Containers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, + InitContainers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, + }, + } + }, + expectHash: "8wzddb4dvv9c6x8zdc77z4z75987424f457dfv6724ddw6zbdx467wz5x24fc759", }, - Spec: appsv1alpha1.SidecarSetSpec{ - Containers: []appsv1alpha1.SidecarContainer{ - { - Container: corev1.Container{ - Name: "container1", - Image: "test-image", + { + name: "containers and initContainers with restartPolicy=Always", + getSidecarSet: func() *appsv1alpha1.SidecarSet { + return &appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-sidecar-set", + }, + Spec: appsv1alpha1.SidecarSetSpec{ + Containers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + }, + }, + }, + InitContainers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "container1", + Image: "test-image", + RestartPolicy: &always, + }, + }, + }, }, - }, + } }, + expectHash: "5725fw8bwbx249bw57v5892c847dzf48bww9zb7c86xb95264fdz26654847b2c8", }, } - hash, err := SidecarSetHashWithoutImage(sidecarSet) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - - if hash == "" { - t.Fatalf("Expected non-empty hash") - } - - // Change sidecar set image and expect same hash - sidecarSet.Spec.Containers[0].Image = "new-image" - newHash, err := SidecarSetHashWithoutImage(sidecarSet) - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } + for _, cs := range cases { + t.Run(cs.name, func(t *testing.T) { + sidecarSet := cs.getSidecarSet() + hash1, err := SidecarSetHashWithoutImage(sidecarSet) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } else if hash1 == "" { + t.Fatalf("Expected non-empty hash") + } + if cs.expectHash != hash1 { + t.Fatalf("expect(%s), but get(%s)", cs.expectHash, hash1) + } - if newHash != hash { - t.Fatalf("Expected same hashes for SidecarSets with different images") + // Change sidecar set and expect different hash + sidecarSet.Spec.Containers[0].Image = "new-image" + sidecarSet.Spec.InitContainers[0].Image = "new-image" + newHash, err := SidecarSetHashWithoutImage(sidecarSet) + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } else if newHash != hash1 { + t.Fatalf("Expected same hashes for different SidecarSets") + } + }) } } diff --git a/pkg/control/sidecarcontrol/util.go b/pkg/control/sidecarcontrol/util.go index df1316cb3c..7b70d03d4b 100644 --- a/pkg/control/sidecarcontrol/util.go +++ b/pkg/control/sidecarcontrol/util.go @@ -246,6 +246,9 @@ func UpdatePodSidecarSetHash(pod *corev1.Pod, sidecarSet *appsv1alpha1.SidecarSe for _, sidecar := range sidecarSet.Spec.Containers { sidecarList.Insert(sidecar.Name) } + for _, sidecar := range sidecarSet.Spec.InitContainers { + sidecarList.Insert(sidecar.Name) + } sidecarSetHash[sidecarSet.Name] = SidecarSetUpgradeSpec{ UpdateTimestamp: metav1.Now(), @@ -564,3 +567,11 @@ func matchRegKey(key string, regs []*regexp.Regexp) bool { } return false } + +// IsSidecarContainer check whether initContainer is sidecar container in k8s 1.28. +func IsSidecarContainer(container corev1.Container) bool { + if container.RestartPolicy != nil && *container.RestartPolicy == corev1.ContainerRestartPolicyAlways { + return true + } + return false +} diff --git a/pkg/webhook/pod/mutating/sidecarset.go b/pkg/webhook/pod/mutating/sidecarset.go index 3399e7f544..194738c095 100644 --- a/pkg/webhook/pod/mutating/sidecarset.go +++ b/pkg/webhook/pod/mutating/sidecarset.go @@ -152,6 +152,7 @@ func (h *PodCreateHandler) sidecarsetMutatingPod(ctx context.Context, req admiss sort.SliceStable(sidecarInitContainers, func(i, j int) bool { return sidecarInitContainers[i].Name < sidecarInitContainers[j].Name }) + // TODO, implement PodInjectPolicy for initContainers for _, initContainer := range sidecarInitContainers { pod.Spec.InitContainers = append(pod.Spec.InitContainers, initContainer.Container) } @@ -368,11 +369,13 @@ func buildSidecars(isUpdated bool, pod *corev1.Pod, oldPod *corev1.Pod, matchedS } isInjecting := false + sidecarList := sets.NewString() //process initContainers //only when created pod, inject initContainer and pullSecrets if !isUpdated { for i := range sidecarSet.Spec.InitContainers { initContainer := &sidecarSet.Spec.InitContainers[i] + sidecarList.Insert(initContainer.Name) // volumeMounts that injected into sidecar container // when volumeMounts SubPathExpr contains expansions, then need copy container EnvVars(injectEnvs) injectedMounts, injectedEnvs := sidecarcontrol.GetInjectedVolumeMountsAndEnvs(control, initContainer, pod) @@ -393,13 +396,22 @@ func buildSidecars(isUpdated bool, pod *corev1.Pod, oldPod *corev1.Pod, matchedS // merged Env from sidecar.Env and transfer envs initContainer.Env = util.MergeEnvVar(initContainer.Env, transferEnvs) isInjecting = true - sidecarInitContainers = append(sidecarInitContainers, initContainer) + + // when sidecar container UpgradeStrategy is HotUpgrade + if sidecarcontrol.IsSidecarContainer(initContainer.Container) && sidecarcontrol.IsHotUpgradeContainer(initContainer) { + hotContainers, annotations := injectHotUpgradeContainers(hotUpgradeWorkInfo, initContainer) + sidecarInitContainers = append(sidecarInitContainers, hotContainers...) + for k, v := range annotations { + injectedAnnotations[k] = v + } + } else { + sidecarInitContainers = append(sidecarInitContainers, initContainer) + } } //process imagePullSecrets sidecarSecrets = append(sidecarSecrets, sidecarSet.Spec.ImagePullSecrets...) } - sidecarList := sets.NewString() //process containers for i := range sidecarSet.Spec.Containers { sidecarContainer := &sidecarSet.Spec.Containers[i] diff --git a/pkg/webhook/pod/mutating/sidecarset_test.go b/pkg/webhook/pod/mutating/sidecarset_test.go index d7011b1aaa..517c661180 100644 --- a/pkg/webhook/pod/mutating/sidecarset_test.go +++ b/pkg/webhook/pod/mutating/sidecarset_test.go @@ -22,6 +22,7 @@ import ( "fmt" "os" "path/filepath" + "reflect" "testing" "github.com/openkruise/kruise/apis" @@ -60,6 +61,8 @@ func TestMain(m *testing.M) { } var ( + always = corev1.ContainerRestartPolicyAlways + sidecarSet1 = &appsv1alpha1.SidecarSet{ ObjectMeta: metav1.ObjectMeta{ Name: "sidecarset1", @@ -113,6 +116,43 @@ var ( }, } + sidecarSetWithInitContainer = &appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + sidecarcontrol.SidecarSetHashAnnotation: "c4k2dbb95d", + }, + Name: "sidecarset", + Labels: map[string]string{}, + }, + Spec: appsv1alpha1.SidecarSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app": "suxing-test", + }, + }, + InitContainers: []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "dns-e", + Image: "dns-e-image:1.0", + VolumeMounts: []corev1.VolumeMount{ + {Name: "volume-1"}, + }, + }, + TransferEnv: []appsv1alpha1.TransferEnvVar{ + { + SourceContainerName: "nginx", + EnvName: "hello2", + }, + }, + }, + }, + Volumes: []corev1.Volume{ + {Name: "volume-1"}, + }, + }, + } + sidecarsetWithTransferEnv = &appsv1alpha1.SidecarSet{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ @@ -1108,6 +1148,113 @@ func TestMergeSidecarContainers(t *testing.T) { } } +func TestInjectInitContainer(t *testing.T) { + cases := []struct { + name string + getSidecarSets func() []*appsv1alpha1.SidecarSet + getPod func() *corev1.Pod + expectedPod func() *corev1.Pod + expectedInitContainerLen int + }{ + { + name: "inject initContainers-1", + getSidecarSets: func() []*appsv1alpha1.SidecarSet { + obj1 := sidecarSetWithInitContainer.DeepCopy() + obj1.Name = "sidecarset-1" + obj1.Annotations[sidecarcontrol.SidecarSetHashAnnotation] = "sidecarset-1-hash" + obj1.Annotations[sidecarcontrol.SidecarSetHashWithoutImageAnnotation] = "sidecarset-1-without-image-hash" + obj1.Spec.InitContainers[0].Name = "init-1" + obj1.Spec.InitContainers[0].RestartPolicy = &always + obj2 := sidecarSetWithInitContainer.DeepCopy() + obj2.Name = "sidecarset-2" + obj2.Annotations[sidecarcontrol.SidecarSetHashAnnotation] = "sidecarset-2-hash" + obj2.Annotations[sidecarcontrol.SidecarSetHashWithoutImageAnnotation] = "sidecarset-2-without-image-hash" + obj2.Spec.InitContainers[0].Name = "hot-init" + obj2.Spec.InitContainers[0].RestartPolicy = &always + obj2.Spec.InitContainers[0].UpgradeStrategy.UpgradeType = appsv1alpha1.SidecarContainerHotUpgrade + obj2.Spec.InitContainers[0].UpgradeStrategy.HotUpgradeEmptyImage = "empty:v1" + return []*appsv1alpha1.SidecarSet{obj1, obj2} + }, + getPod: func() *corev1.Pod { + obj := pod1.DeepCopy() + return obj + }, + expectedPod: func() *corev1.Pod { + obj := pod1.DeepCopy() + obj.Annotations = map[string]string{} + sidecarSetHash := make(map[string]sidecarcontrol.SidecarSetUpgradeSpec) + sidecarSetHashWithoutImage := make(map[string]sidecarcontrol.SidecarSetUpgradeSpec) + sidecarSetHash["sidecarset-1"] = sidecarcontrol.SidecarSetUpgradeSpec{ + UpdateTimestamp: metav1.Now(), + SidecarSetHash: "sidecarset-1-hash", + SidecarSetName: "sidecarset-1", + SidecarList: []string{"init-1"}, + } + sidecarSetHash["sidecarset-2"] = sidecarcontrol.SidecarSetUpgradeSpec{ + UpdateTimestamp: metav1.Now(), + SidecarSetHash: "sidecarset-2-hash", + SidecarSetName: "sidecarset-2", + SidecarList: []string{"hot-init"}, + } + sidecarSetHashWithoutImage["sidecarset-1"] = sidecarcontrol.SidecarSetUpgradeSpec{ + UpdateTimestamp: metav1.Now(), + SidecarSetHash: "sidecarset-1-without-image-hash", + SidecarSetName: "sidecarset-1", + SidecarList: []string{"init-1"}, + } + sidecarSetHashWithoutImage["sidecarset-2"] = sidecarcontrol.SidecarSetUpgradeSpec{ + UpdateTimestamp: metav1.Now(), + SidecarSetHash: "sidecarset-2-without-image-hash", + SidecarSetName: "sidecarset-2", + SidecarList: []string{"hot-init"}, + } + by, _ := json.Marshal(sidecarSetHash) + obj.Annotations[sidecarcontrol.SidecarSetHashAnnotation] = string(by) + by, _ = json.Marshal(sidecarSetHashWithoutImage) + obj.Annotations[sidecarcontrol.SidecarSetHashWithoutImageAnnotation] = string(by) + // store matched sidecarset list in pod annotations + obj.Annotations[sidecarcontrol.SidecarSetListAnnotation] = "sidecarset-1,sidecarset-2" + hotUpgradeWorkInfo := map[string]string{ + "hot-init": "hot-init-1", + } + by, _ = json.Marshal(hotUpgradeWorkInfo) + obj.Annotations[sidecarcontrol.SidecarSetWorkingHotUpgradeContainer] = string(by) + obj.Annotations[sidecarcontrol.GetPodSidecarSetVersionAnnotation("hot-init-1")] = "1" + obj.Annotations[sidecarcontrol.GetPodSidecarSetVersionAltAnnotation("hot-init-1")] = "0" + // "0" indicates sidecar container is hot upgrade empty container + obj.Annotations[sidecarcontrol.GetPodSidecarSetVersionAnnotation("hot-init-2")] = "0" + obj.Annotations[sidecarcontrol.GetPodSidecarSetVersionAltAnnotation("hot-init-2")] = "1" + obj.Spec.Volumes = append(obj.Spec.Volumes, corev1.Volume{Name: "volume-1"}) + return obj + }, + expectedInitContainerLen: 4, + }, + } + + for _, cs := range cases { + t.Run(cs.name, func(t *testing.T) { + decoder := admission.NewDecoder(scheme.Scheme) + ss := cs.getSidecarSets() + client := fake.NewClientBuilder().WithObjects(ss[0], ss[1]).WithIndex( + &appsv1alpha1.SidecarSet{}, fieldindex.IndexNameForSidecarSetNamespace, fieldindex.IndexSidecarSet, + ).Build() + pod := cs.getPod() + podHandler := &PodCreateHandler{Decoder: decoder, Client: client} + req := newAdmission(admissionv1.Create, runtime.RawExtension{}, runtime.RawExtension{}, "") + _, err := podHandler.sidecarsetMutatingPod(context.Background(), req, pod) + if err != nil { + t.Fatalf("inject sidecar into pod failed, err: %v", err) + } + if !reflect.DeepEqual(pod.Annotations, cs.expectedPod().Annotations) { + t.Fatalf("expect(%s), but get(%s)", util.DumpJSON(cs.expectedPod()), util.DumpJSON(pod)) + } + if len(pod.Spec.InitContainers) != cs.expectedInitContainerLen { + t.Fatalf("expect(%d), but get(%d)", cs.expectedInitContainerLen, len(pod.Spec.InitContainers)) + } + }) + } +} + func newAdmission(op admissionv1.Operation, object, oldObject runtime.RawExtension, subResource string) admission.Request { return admission.Request{ AdmissionRequest: newAdmissionRequest(op, object, oldObject, subResource), diff --git a/pkg/webhook/sidecarset/validating/sidecarset_create_update_handler.go b/pkg/webhook/sidecarset/validating/sidecarset_create_update_handler.go index 8b8c2d93c3..8dbf4dc5b9 100644 --- a/pkg/webhook/sidecarset/validating/sidecarset_create_update_handler.go +++ b/pkg/webhook/sidecarset/validating/sidecarset_create_update_handler.go @@ -112,6 +112,12 @@ func validateSidecarSetName(name string, prefix bool) (allErrs []string) { func (h *SidecarSetCreateUpdateHandler) validateSidecarSetSpec(obj *appsv1alpha1.SidecarSet, fldPath *field.Path) field.ErrorList { spec := &obj.Spec allErrs := field.ErrorList{} + // currently when initContainer restartPolicy = Always, kruise don't support in-place update + for _, c := range obj.Spec.InitContainers { + if sidecarcontrol.IsSidecarContainer(c.Container) && obj.Spec.UpdateStrategy.Type == appsv1alpha1.RollingUpdateSidecarSetStrategyType { + allErrs = append(allErrs, field.Required(fldPath.Child("updateStrategy"), "The initContainer in-place upgrade is not currently supported.")) + } + } //validate spec selector if spec.Selector == nil { diff --git a/pkg/webhook/sidecarset/validating/sidecarset_validating_test.go b/pkg/webhook/sidecarset/validating/sidecarset_validating_test.go index 04f7d09dca..ae99998192 100644 --- a/pkg/webhook/sidecarset/validating/sidecarset_validating_test.go +++ b/pkg/webhook/sidecarset/validating/sidecarset_validating_test.go @@ -47,6 +47,7 @@ var ( var ( testScheme *runtime.Scheme handler = &SidecarSetCreateUpdateHandler{} + always = corev1.ContainerRestartPolicyAlways ) func init() { @@ -499,6 +500,39 @@ func TestValidateSidecarSet(t *testing.T) { }, expectErrs: 1, }, + { + caseName: "The initContainer in-place upgrade is not currently supported.", + sidecarSet: appsv1alpha1.SidecarSet{ + ObjectMeta: metav1.ObjectMeta{Name: "test-sidecarset"}, + Spec: appsv1alpha1.SidecarSetSpec{ + Selector: &metav1.LabelSelector{ + MatchLabels: map[string]string{"a": "b"}, + }, + UpdateStrategy: appsv1alpha1.SidecarSetUpdateStrategy{ + Type: appsv1alpha1.RollingUpdateSidecarSetStrategyType, + }, + InitContainers: []appsv1alpha1.SidecarContainer{ + { + PodInjectPolicy: appsv1alpha1.BeforeAppContainerType, + ShareVolumePolicy: appsv1alpha1.ShareVolumePolicy{ + Type: appsv1alpha1.ShareVolumePolicyDisabled, + }, + UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{ + UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade, + }, + Container: corev1.Container{ + Name: "test-sidecar", + Image: "test-image", + ImagePullPolicy: corev1.PullIfNotPresent, + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + RestartPolicy: &always, + }, + }, + }, + }, + }, + expectErrs: 1, + }, } SidecarSetRevisions := []client.Object{ diff --git a/test/e2e/apps/sidecarset.go b/test/e2e/apps/sidecarset.go index 4aed6fff0f..1667cea830 100644 --- a/test/e2e/apps/sidecarset.go +++ b/test/e2e/apps/sidecarset.go @@ -565,6 +565,89 @@ var _ = SIGDescribe("SidecarSet", func() { } ginkgo.By("sidecarSet inject pod sidecar container transfer Envs with downward API by metadata.annotations done") }) + + // currently skip + // todo + /*framework.ConformanceIt("sidecarSet inject initContainer with restartPolicy=Always", func() { + always := corev1.ContainerRestartPolicyAlways + // create sidecarSet + sidecarSet := tester.NewBaseSidecarSet(ns) + sidecarSet.Spec.Containers = nil + sidecarSet.Spec.InitContainers = nil + obj1 := sidecarSet.DeepCopy() + obj1.Name = "sidecarset-1" + obj1.Spec.InitContainers = []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "init-1", + Command: []string{"/bin/sh", "-c", "sleep 1000000"}, + Image: "busybox:latest", + RestartPolicy: &always, + }, + }, + } + ginkgo.By("Creating SidecarSet failed") + _, err := kc.AppsV1alpha1().SidecarSets().Create(context.TODO(), obj1, metav1.CreateOptions{}) + gomega.Expect(err).To(gomega.HaveOccurred()) + obj1.Spec.UpdateStrategy.Type = appsv1alpha1.NotUpdateSidecarSetStrategyType + obj2 := sidecarSet.DeepCopy() + obj2.Spec.UpdateStrategy.Type = appsv1alpha1.NotUpdateSidecarSetStrategyType + obj2.Name = "sidecarset-2" + obj2.Spec.InitContainers = []appsv1alpha1.SidecarContainer{ + { + Container: corev1.Container{ + Name: "hot-init", + Image: "openkruise/hotupgrade-sample:sidecarv1", + RestartPolicy: &always, + Lifecycle: &corev1.Lifecycle{ + PostStart: &corev1.LifecycleHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"/bin/sh", "/migrate.sh"}, + }, + }, + }, + }, + UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{ + UpgradeType: appsv1alpha1.SidecarContainerHotUpgrade, + HotUpgradeEmptyImage: "openkruise/hotupgrade-sample:empty", + }, + }, + } + ginkgo.By("Creating SidecarSet success") + _, err = tester.CreateSidecarSet(obj1) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + _, err = tester.CreateSidecarSet(obj2) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + time.Sleep(time.Second) + + // create deployment + deploymentIn := tester.NewBaseDeployment(ns) + deploymentIn.Spec.Template.ObjectMeta.Annotations = map[string]string{ + "biz": "main", + } + deploymentIn.Spec.Template.Spec.Containers[0].Env = []corev1.EnvVar{ + { + Name: "POD_NAME", + Value: "bar", + }, + { + Name: "OD_NAME", + Value: "od_name", + }, + { + Name: "PROXY_IP", + Value: "127.0.0.1", + }, + } + ginkgo.By(fmt.Sprintf("Creating Deployment(%s/%s)", deploymentIn.Namespace, deploymentIn.Name)) + tester.CreateDeployment(deploymentIn) + // get pods + pods, err := tester.GetSelectorPods(deploymentIn.Namespace, deploymentIn.Spec.Selector) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + podIn := pods[0] + gomega.Expect(podIn.Spec.InitContainers).To(gomega.HaveLen(3)) + ginkgo.By("sidecarSet inject pod sidecar container transfer Envs with downward API by metadata.annotations done") + })*/ }) framework.KruiseDescribe("SidecarSet Upgrade functionality [SidecarSeUpgrade]", func() { @@ -773,6 +856,9 @@ var _ = SIGDescribe("SidecarSet", func() { for _, sidecar := range sidecarSetIn.Spec.Containers { origin.Insert(sidecar.Name) } + for _, sidecar := range sidecarSetIn.Spec.InitContainers { + origin.Insert(sidecar.Name) + } // SidecarSetHashAnnotation = "kruise.io/sidecarset-hash" upgradeSpec1 := sidecarcontrol.GetPodSidecarSetUpgradeSpecInAnnotations(sidecarSetIn.Name, sidecarcontrol.SidecarSetHashAnnotation, pod) gomega.Expect(upgradeSpec1.SidecarSetName).To(gomega.Equal(sidecarSetIn.Name)) @@ -819,6 +905,9 @@ var _ = SIGDescribe("SidecarSet", func() { for _, sidecar := range sidecarSetIn.Spec.Containers { origin.Insert(sidecar.Name) } + for _, sidecar := range sidecarSetIn.Spec.InitContainers { + origin.Insert(sidecar.Name) + } // SidecarSetHashAnnotation = "kruise.io/sidecarset-hash" upgradeSpec1 := sidecarcontrol.GetPodSidecarSetUpgradeSpecInAnnotations(sidecarSetIn.Name, sidecarcontrol.SidecarSetHashAnnotation, pod) gomega.Expect(upgradeSpec1.SidecarSetName).To(gomega.Equal(sidecarSetIn.Name)) diff --git a/test/e2e/framework/sidecarset_utils.go b/test/e2e/framework/sidecarset_utils.go index c8f3f0a6ef..2d81636f0f 100644 --- a/test/e2e/framework/sidecarset_utils.go +++ b/test/e2e/framework/sidecarset_utils.go @@ -130,7 +130,7 @@ func (s *SidecarSetTester) NewBaseDeployment(namespace string) *apps.Deployment Containers: []corev1.Container{ { Name: "main", - Image: imageutils.GetE2EImage(imageutils.BusyBox), + Image: "busybox:latest", Command: []string{"/bin/sh", "-c", "sleep 10000000"}, }, },