diff --git a/pkg/juicefs/mount/builder/common.go b/pkg/juicefs/mount/builder/common.go index b86cca160c..8bb1654a1d 100644 --- a/pkg/juicefs/mount/builder/common.go +++ b/pkg/juicefs/mount/builder/common.go @@ -34,7 +34,6 @@ import ( const ( JfsDirName = "jfs-dir" - JfsRootDirName = "jfs-root-dir" UpdateDBDirName = "updatedb" UpdateDBCfgFile = "/etc/updatedb.conf" ) @@ -112,6 +111,11 @@ func (r *BaseBuilder) genCommonJuicePod(cnGen func() corev1.Container) *corev1.P {Name: "metrics", ContainerPort: r.genMetricsPort()}, } } + if initContainer := r.genInitContainer(cnGen); initContainer != nil { + // initContainer should have the same volumeMounts as mount container + initContainer.VolumeMounts = pod.Spec.Containers[0].VolumeMounts + pod.Spec.InitContainers = []corev1.Container{*initContainer} + } return pod } @@ -146,6 +150,71 @@ func (r *BaseBuilder) genMountCommand() string { return util.QuoteForShell(cmd) } +// genInitContainer: generate init container +func (r *BaseBuilder) genInitContainer(cnGen func() corev1.Container) *corev1.Container { + if r.jfsSetting.SubPath == "" { + // do not need initContainer if no subpath + return nil + } + container := cnGen() + container.Name = "jfs-init" + + initCmds := []string{ + r.genInitCommand(), + } + // create subpath if readonly mount or in webhook mode + if util.ContainsString(r.jfsSetting.Options, "read-only") || util.ContainsString(r.jfsSetting.Options, "ro") || config.Webhook { + // generate mount command + initCmds = append(initCmds, + r.getJobCommand(), + fmt.Sprintf("if [ ! -d /mnt/jfs/%s ]; then mkdir -m 777 /mnt/jfs/%s; fi;", r.jfsSetting.SubPath, r.jfsSetting.SubPath), + "umount /mnt/jfs", + ) + // set quota in webhook mode + if config.Webhook && r.capacity > 0 { + quotaPath := r.jfsSetting.SubPath + var subdir string + for _, o := range r.jfsSetting.Options { + pair := strings.Split(o, "=") + if len(pair) != 2 { + continue + } + if pair[0] == "subdir" { + subdir = path.Join("/", pair[1]) + } + } + var setQuotaCmd string + targetPath := path.Join(subdir, quotaPath) + capacity := strconv.FormatInt(r.capacity, 10) + if r.jfsSetting.IsCe { + // juicefs quota; if [ $? -eq 0 ]; then juicefs quota set ${metaurl} --path ${path} --capacity ${capacity}; fi + cmdArgs := []string{ + config.CeCliPath, "quota; if [ $? -eq 0 ]; then", + config.CeCliPath, + "quota", "set", "${metaurl}", + "--path", targetPath, + "--capacity", capacity, + "; fi", + } + setQuotaCmd = strings.Join(cmdArgs, " ") + } else { + cmdArgs := []string{ + config.CliPath, "quota; if [ $? -eq 0 ]; then", + config.CliPath, + "quota", "set", r.jfsSetting.Name, + "--path", targetPath, + "--capacity", capacity, + "; fi", + } + setQuotaCmd = strings.Join(cmdArgs, " ") + } + initCmds = append(initCmds, setQuotaCmd) + } + } + container.Command = []string{"sh", "-c", strings.Join(initCmds, "\n")} + return &container +} + // genInitCommand generates init command func (r *BaseBuilder) genInitCommand() string { formatCmd := r.jfsSetting.FormatCmd @@ -156,57 +225,6 @@ func (r *BaseBuilder) genInitCommand() string { } initCmds := []string{formatCmd} - // create subpath if readonly mount or in webhook mode - if r.jfsSetting.SubPath != "" { - if util.ContainsString(r.jfsSetting.Options, "read-only") || util.ContainsString(r.jfsSetting.Options, "ro") || config.Webhook { - // generate mount command - initCmds = append(initCmds, - r.getJobCommand(), - fmt.Sprintf("if [ ! -d /mnt/jfs/%s ]; then mkdir -m 777 /mnt/jfs/%s; fi;", r.jfsSetting.SubPath, r.jfsSetting.SubPath), - "umount /mnt/jfs", - ) - // set quota in webhook mode - if config.Webhook && r.capacity > 0 { - quotaPath := r.jfsSetting.SubPath - var subdir string - for _, o := range r.jfsSetting.Options { - pair := strings.Split(o, "=") - if len(pair) != 2 { - continue - } - if pair[0] == "subdir" { - subdir = path.Join("/", pair[1]) - } - } - var setQuotaCmd string - targetPath := path.Join(subdir, quotaPath) - capacity := strconv.FormatInt(r.capacity, 10) - if r.jfsSetting.IsCe { - // juicefs quota; if [ $? -eq 0 ]; then juicefs quota set ${metaurl} --path ${path} --capacity ${capacity}; fi - cmdArgs := []string{ - config.CeCliPath, "quota; if [ $? -eq 0 ]; then", - config.CeCliPath, - "quota", "set", "${metaurl}", - "--path", targetPath, - "--capacity", capacity, - "; fi", - } - setQuotaCmd = strings.Join(cmdArgs, " ") - } else { - cmdArgs := []string{ - config.CliPath, "quota; if [ $? -eq 0 ]; then", - config.CliPath, - "quota", "set", r.jfsSetting.Name, - "--path", targetPath, - "--capacity", capacity, - "; fi", - } - setQuotaCmd = strings.Join(cmdArgs, " ") - } - initCmds = append(initCmds, setQuotaCmd) - } - } - } return strings.Join(initCmds, "\n") } diff --git a/pkg/juicefs/mount/builder/job.go b/pkg/juicefs/mount/builder/job.go index f6a9f469b9..60d6b6dd62 100644 --- a/pkg/juicefs/mount/builder/job.go +++ b/pkg/juicefs/mount/builder/job.go @@ -19,6 +19,7 @@ package builder import ( "crypto/sha256" "fmt" + "strings" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" @@ -48,7 +49,10 @@ func (r *JobBuilder) NewJobForCreateVolume() *batchv1.Job { jobName := GenJobNameByVolumeId(r.jfsSetting.VolumeId) + "-createvol" job := r.newJob(jobName) jobCmd := r.getCreateVolumeCmd() - job.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", jobCmd} + initCmd := r.genInitCommand() + cmd := strings.Join([]string{initCmd, jobCmd}, "\n") + job.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", cmd} + klog.Infof("create volume job cmd: %s", jobCmd) return job } @@ -57,7 +61,9 @@ func (r *JobBuilder) NewJobForDeleteVolume() *batchv1.Job { jobName := GenJobNameByVolumeId(r.jfsSetting.VolumeId) + "-delvol" job := r.newJob(jobName) jobCmd := r.getDeleteVolumeCmd() - job.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", jobCmd} + initCmd := r.genInitCommand() + cmd := strings.Join([]string{initCmd, jobCmd}, "\n") + job.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", cmd} klog.Infof("delete volume job cmd: %s", jobCmd) return job } diff --git a/pkg/juicefs/mount/builder/pod.go b/pkg/juicefs/mount/builder/pod.go index b367059d41..747a1a7852 100644 --- a/pkg/juicefs/mount/builder/pod.go +++ b/pkg/juicefs/mount/builder/pod.go @@ -19,6 +19,7 @@ package builder import ( "fmt" "path/filepath" + "strings" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,8 +44,13 @@ func NewPodBuilder(setting *config.JfsSetting, capacity int64) *PodBuilder { func (r *PodBuilder) NewMountPod(podName string) *corev1.Pod { pod := r.genCommonJuicePod(r.genCommonContainer) - cmd := r.genMountCommand() pod.Name = podName + mountCmd := r.genMountCommand() + cmd := mountCmd + initCmd := r.genInitCommand() + if initCmd != "" { + cmd = strings.Join([]string{initCmd, mountCmd}, "\n") + } pod.Spec.Containers[0].Command = []string{"sh", "-c", cmd} pod.Spec.Containers[0].Env = []corev1.EnvVar{{ Name: "JFS_FOREGROUND", @@ -56,14 +62,6 @@ func (r *PodBuilder) NewMountPod(podName string) *corev1.Pod { pod.Spec.Volumes = append(pod.Spec.Volumes, volumes...) pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, volumeMounts...) - // generate initContainer - if r.jfsSetting.FormatCmd != "" { - initVolumeMounts := r.genInitVolumes() - initContainer := r.genInitContainer() - initContainer.VolumeMounts = append(initContainer.VolumeMounts, initVolumeMounts...) - pod.Spec.InitContainers = []corev1.Container{initContainer} - } - // add cache-dir hostpath & PVC volume cacheVolumes, cacheVolumeMounts := r.genCacheDirVolumes() pod.Spec.Volumes = append(pod.Spec.Volumes, cacheVolumes...) @@ -74,6 +72,9 @@ func (r *PodBuilder) NewMountPod(podName string) *corev1.Pod { pod.Spec.Volumes = append(pod.Spec.Volumes, mountVolumes...) pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, mountVolumeMounts...) + if len(pod.Spec.InitContainers) != 0 { + pod.Spec.InitContainers[0].VolumeMounts = append(pod.Spec.InitContainers[0].VolumeMounts, mountVolumeMounts...) + } return pod } @@ -169,35 +170,9 @@ func (r *PodBuilder) genHostPathVolumes() (volumes []corev1.Volume, volumeMounts return } -// genInitContainer: generate init container -func (r *PodBuilder) genInitContainer() corev1.Container { - rootUser := int64(0) - isPrivileged := true - secretName := r.jfsSetting.SecretName - container := corev1.Container{ - Name: "jfs-format", - Image: r.jfsSetting.Attr.Image, - SecurityContext: &corev1.SecurityContext{ - Privileged: &isPrivileged, - RunAsUser: &rootUser, - }, - } - - initCmd := r.genInitCommand() - container.Command = []string{"sh", "-c", initCmd} - - container.EnvFrom = append(container.EnvFrom, corev1.EnvFromSource{ - SecretRef: &corev1.SecretEnvSource{LocalObjectReference: corev1.LocalObjectReference{ - Name: secretName, - }}, - }) - return container -} - // genPodVolumes: generate volumes for mount pod // 1. jfs dir: mount point used to propagate the mount point in the mount container to host // 2. update db dir: mount updatedb.conf from host to mount pod -// 3. jfs config dir: mount jfs config dir as emptyDir to deliver config file to mount container func (r *PodBuilder) genPodVolumes() ([]corev1.Volume, []corev1.VolumeMount) { dir := corev1.HostPathDirectoryOrCreate file := corev1.HostPathFileOrCreate @@ -233,39 +208,9 @@ func (r *PodBuilder) genPodVolumes() ([]corev1.Volume, []corev1.VolumeMount) { }) } - if r.jfsSetting.FormatCmd != "" { - // initContainer will generate xx.conf to share with mount container - volumes = append(volumes, corev1.Volume{ - Name: JfsRootDirName, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }) - volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: JfsRootDirName, - MountPath: "/root/.juicefs", - }) - } - return volumes, volumeMounts } -// genInitVolumes: generate volumes for initContainer in mount pod -// jfs config dir: mount jfs config dir as emptyDir to deliver config file to initContainer -func (r *PodBuilder) genInitVolumes() []corev1.VolumeMount { - volumeMounts := []corev1.VolumeMount{} - - if r.jfsSetting.FormatCmd != "" { - // initContainer will generate xx.conf to share with mount container - volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: JfsRootDirName, - MountPath: "/root/.juicefs", - }) - } - - return volumeMounts -} - // genCleanCachePod: generate pod to clean cache in host func (r *PodBuilder) genCleanCachePod() *corev1.Pod { volumeMountPrefix := "/var/jfsCache" diff --git a/pkg/juicefs/mount/builder/pod_test.go b/pkg/juicefs/mount/builder/pod_test.go index ce9e66e89c..320995cc4b 100644 --- a/pkg/juicefs/mount/builder/pod_test.go +++ b/pkg/juicefs/mount/builder/pod_test.go @@ -174,9 +174,6 @@ func Test_getCacheDirVolumes(t *testing.T) { volumeMounts := []corev1.VolumeMount{{ Name: JfsDirName, MountPath: config.PodMountBase, - }, { - Name: JfsRootDirName, - MountPath: "/root/.juicefs", }} volumes := []corev1.Volume{{ @@ -184,20 +181,14 @@ func Test_getCacheDirVolumes(t *testing.T) { VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{ Path: config.MountPointPath, Type: &dir, - }}}, { - Name: JfsRootDirName, - VolumeSource: corev1.VolumeSource{HostPath: &corev1.HostPathVolumeSource{ - Path: config.JFSConfigPath, - Type: &dir, - }}, - }} + }}}} s, _ := config.ParseSetting(map[string]string{"name": "test"}, nil, optionWithoutCacheDir, true) r.jfsSetting = s cacheVolumes, cacheVolumeMounts := r.genCacheDirVolumes() volumes = append(volumes, cacheVolumes...) volumeMounts = append(volumeMounts, cacheVolumeMounts...) - if len(volumes) != 3 || len(volumeMounts) != 3 { + if len(volumes) != 2 || len(volumeMounts) != 2 { t.Error("getCacheDirVolumes can't work properly") } @@ -206,7 +197,7 @@ func Test_getCacheDirVolumes(t *testing.T) { cacheVolumes, cacheVolumeMounts = r.genCacheDirVolumes() volumes = append(volumes, cacheVolumes...) volumeMounts = append(volumeMounts, cacheVolumeMounts...) - if len(volumes) != 4 || len(volumeMounts) != 4 { + if len(volumes) != 3 || len(volumeMounts) != 3 { t.Error("getCacheDirVolumes can't work properly") } @@ -215,7 +206,7 @@ func Test_getCacheDirVolumes(t *testing.T) { cacheVolumes, cacheVolumeMounts = r.genCacheDirVolumes() volumes = append(volumes, cacheVolumes...) volumeMounts = append(volumeMounts, cacheVolumeMounts...) - if len(volumes) != 6 || len(volumeMounts) != 6 { + if len(volumes) != 5 || len(volumeMounts) != 5 { t.Error("getCacheDirVolumes can't work properly") } @@ -224,7 +215,7 @@ func Test_getCacheDirVolumes(t *testing.T) { cacheVolumes, cacheVolumeMounts = r.genCacheDirVolumes() volumes = append(volumes, cacheVolumes...) volumeMounts = append(volumeMounts, cacheVolumeMounts...) - if len(volumes) != 7 || len(volumeMounts) != 7 { + if len(volumes) != 6 || len(volumeMounts) != 6 { t.Error("getCacheDirVolumes can't work properly") } } diff --git a/pkg/juicefs/mount/builder/vci-serverless.go b/pkg/juicefs/mount/builder/vci-serverless.go index 9b560a11b0..dabcc89f30 100644 --- a/pkg/juicefs/mount/builder/vci-serverless.go +++ b/pkg/juicefs/mount/builder/vci-serverless.go @@ -57,7 +57,6 @@ func NewVCIBuilder(setting *config.JfsSetting, capacity int64, app corev1.Pod, p // 1. no hostpath // 2. without privileged container // 3. no propagationBidirectional -// 3. no initContainer // 4. with env JFS_NO_UMOUNT=1 // 5. annotations for VCI func (r *VCIBuilder) NewMountSidecar() *corev1.Pod { @@ -70,6 +69,18 @@ func (r *VCIBuilder) NewMountSidecar() *corev1.Pod { "mountPath" : "%s" }]`, r.jfsSetting.MountPath), } + if len(pod.Spec.InitContainers) != 0 { + pod.Annotations = map[string]string{ + VCIPropagationConfig: VCIPropagationConfigValue, + VCIPropagation: fmt.Sprintf(`[{ + "container": "jfs-mount", + "mountPath" : "%s" + }, { + "container": "jfs-init", + "mountPath" : "/mnt/jfs" + }]`, r.jfsSetting.MountPath), + } + } pod.Spec.Containers[0].Lifecycle.PostStart = &corev1.Handler{ Exec: &corev1.ExecAction{Command: []string{"bash", "-c", diff --git a/pkg/util/util.go b/pkg/util/util.go index 0615508262..078627bc7a 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -275,7 +275,9 @@ func GetReferenceKey(target string) string { // ParseMntPath return mntPath, volumeId (/jfs/volumeId, volumeId err) func ParseMntPath(cmd string) (string, string, error) { - args := strings.Fields(cmd) + cmds := strings.Split(cmd, "\n") + mountCmd := cmds[len(cmds)-1] + args := strings.Fields(mountCmd) if len(args) < 3 || !strings.HasPrefix(args[2], config.PodMountBase) { return "", "", fmt.Errorf("err cmd:%s", cmd) } diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index bc9abac60e..c8b30377d3 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -158,28 +158,46 @@ func TestParseMntPath(t *testing.T) { }{ { name: "get sourcePath from pod cmd success", + args: args{cmd: "/usr/local/bin/juicefs format --storage=s3 --bucket=http://juicefs-bucket.minio.default.svc.cluster.local:9000 --access-key=minioadmin --secret-key=${secretkey} ${metaurl} ce-secret\n/bin/mount.juicefs redis://127.0.0.1/6379 /jfs/pvc-xxx"}, + want: "/jfs/pvc-xxx", + want1: "pvc-xxx", + wantErr: false, + }, + { + name: "without init cmd", args: args{cmd: "/bin/mount.juicefs redis://127.0.0.1/6379 /jfs/pvc-xxx"}, want: "/jfs/pvc-xxx", want1: "pvc-xxx", wantErr: false, }, + { + name: "with create subpath", + args: args{cmd: "/usr/local/bin/juicefs format --storage=s3 --bucket=http://juicefs-bucket.minio.default.svc.cluster.local:9000 --access-key=minioadmin --secret-key=${secretkey} ${metaurl} ce-secret\n" + + "/bin/mount.juicefs ${metaurl} /mnt/jfs -o buffer-size=300,cache-size=100,enable-xattr\n" + + "if [ ! -d /mnt/jfs/pvc-fb2ec20c-474f-4804-9504-966da4af9b73 ]; then mkdir -m 777 /mnt/jfs/pvc-fb2ec20c-474f-4804-9504-966da4af9b73; fi;\n" + + "umount /mnt/jfs\n" + + "/bin/mount.juicefs redis://127.0.0.1/6379 /jfs/pvc-xxx"}, + want: "/jfs/pvc-xxx", + want1: "pvc-xxx", + wantErr: false, + }, { name: "err-pod cmd args <3", - args: args{cmd: "/bin/mount.juicefs redis://127.0.0.1/6379"}, + args: args{cmd: "/usr/local/bin/juicefs format --storage=s3 --bucket=http://juicefs-bucket.minio.default.svc.cluster.local:9000 --access-key=minioadmin --secret-key=${secretkey} ${metaurl} ce-secret\n/bin/mount.juicefs redis://127.0.0.1/6379"}, want: "", want1: "", wantErr: true, }, { name: "err-cmd sourcePath no MountBase prefix", - args: args{cmd: "/bin/mount.juicefs redis://127.0.0.1/6379 /err-jfs/pvc-xxx"}, + args: args{cmd: "/usr/local/bin/juicefs format --storage=s3 --bucket=http://juicefs-bucket.minio.default.svc.cluster.local:9000 --access-key=minioadmin --secret-key=${secretkey} ${metaurl} ce-secret\n/bin/mount.juicefs redis://127.0.0.1/6379 /err-jfs/pvc-xxx"}, want: "", want1: "", wantErr: true, }, { name: "err-cmd sourcePath length err", - args: args{cmd: "/bin/mount.juicefs redis://127.0.0.1/6379 /jfs"}, + args: args{cmd: "/usr/local/bin/juicefs format --storage=s3 --bucket=http://juicefs-bucket.minio.default.svc.cluster.local:9000 --access-key=minioadmin --secret-key=${secretkey} ${metaurl} ce-secret\n/bin/mount.juicefs redis://127.0.0.1/6379 /jfs"}, want: "", want1: "", wantErr: true, diff --git a/pkg/webhook/handler/mutate/sidecar.go b/pkg/webhook/handler/mutate/sidecar.go index 0e0f844ced..e7429ef82a 100644 --- a/pkg/webhook/handler/mutate/sidecar.go +++ b/pkg/webhook/handler/mutate/sidecar.go @@ -124,10 +124,6 @@ func (s *SidecarMutate) mutate(ctx context.Context, pod *corev1.Pod, pair util.P s.injectAnnotation(out, mountPod.Annotations) // inject container s.injectContainer(out, mountPod.Spec.Containers[0]) - if len(mountPod.Spec.InitContainers) > 0 { - // inject initContainer - s.injectInitContainer(out, mountPod.Spec.InitContainers[0]) - } return } @@ -146,16 +142,9 @@ func (s *SidecarMutate) Deduplicate(pod, mountPod *corev1.Pod, index int) { return } - // deduplicate initContainer name - for _, c := range pod.Spec.InitContainers { - if c.Name == mountPod.Spec.InitContainers[0].Name { - mountPod.Spec.InitContainers[0].Name = fmt.Sprintf("%s-%d", c.Name, index) - } - } - // deduplicate volume name for i, mv := range mountPod.Spec.Volumes { - if mv.Name == builder.UpdateDBDirName || mv.Name == builder.JfsDirName || mv.Name == builder.JfsRootDirName { + if mv.Name == builder.UpdateDBDirName || mv.Name == builder.JfsDirName { continue } mountIndex := 0 @@ -215,10 +204,6 @@ func (s *SidecarMutate) injectContainer(pod *corev1.Pod, container corev1.Contai pod.Spec.Containers = append([]corev1.Container{container}, pod.Spec.Containers...) } -func (s *SidecarMutate) injectInitContainer(pod *corev1.Pod, container corev1.Container) { - pod.Spec.InitContainers = append([]corev1.Container{container}, pod.Spec.InitContainers...) -} - func (s *SidecarMutate) injectVolume(pod *corev1.Pod, build builder.SidecarInterface, volumes []corev1.Volume, mountPath string, pair util.PVPair) { mountedVolume := []corev1.Volume{} podVolumes := make(map[string]bool) @@ -226,7 +211,7 @@ func (s *SidecarMutate) injectVolume(pod *corev1.Pod, build builder.SidecarInter podVolumes[volume.Name] = true } for _, v := range volumes { - if v.Name == builder.UpdateDBDirName || v.Name == builder.JfsDirName || v.Name == builder.JfsRootDirName { + if v.Name == builder.UpdateDBDirName || v.Name == builder.JfsDirName { if _, ok := podVolumes[v.Name]; ok { continue } diff --git a/pkg/webhook/handler/mutate/sidecar_test.go b/pkg/webhook/handler/mutate/sidecar_test.go index 8c6dc0281b..f3fbeeac02 100644 --- a/pkg/webhook/handler/mutate/sidecar_test.go +++ b/pkg/webhook/handler/mutate/sidecar_test.go @@ -190,39 +190,6 @@ func TestSidecarMutate_injectVolume(t *testing.T) { } } -func TestSidecarMutate_injectInitContainer(t *testing.T) { - type args struct { - pod *corev1.Pod - container corev1.Container - } - tests := []struct { - name string - args args - wantInitContainerLen int - }{ - { - name: "test inject init container", - args: args{ - pod: &corev1.Pod{}, - container: corev1.Container{ - Name: "format", - Image: "juicedata/mount:latest", - }, - }, - wantInitContainerLen: 1, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - s := &SidecarMutate{} - s.injectInitContainer(tt.args.pod, tt.args.container) - if len(tt.args.pod.Spec.InitContainers) != tt.wantInitContainerLen { - t.Errorf("injectInitContainer() = %v, want %v", tt.args.pod.Spec.InitContainers, tt.wantInitContainerLen) - } - }) - } -} - func TestSidecarMutate_injectContainer(t *testing.T) { type args struct { pod *corev1.Pod