@@ -657,3 +657,141 @@ func (s *doK8sConfigMapTemplateTest) loadTestFile(filename, chartVersion string)
657657 result = strings .TrimSpace (result )
658658 return strings .TrimSpace (result )
659659}
660+
661+ func (s * doK8sConfigMapTemplateTest ) TestNativeSidecarTelemetryAutoInject () {
662+ testCases := []struct {
663+ name string
664+ values map [string ]string
665+ expected func (subT gruntworkTesting.TestingT , job batchv1.Job )
666+ }{
667+ {
668+ "AutoInjectsTelemetrySocketWiringWhenSidecarHasExecutorEnv" ,
669+ map [string ]string {
670+ "delegatedOperatorJobTemplates.jobs.testJob.unused" : "nil" ,
671+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].name" : "telemetry-sidecar" ,
672+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].image" : "telemetry-sidecar:latest" ,
673+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].restartPolicy" : "Always" ,
674+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].env[0].name" : "EXECUTOR_SIDECAR" ,
675+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].env[0].value" : "true" ,
676+ },
677+ func (subT gruntworkTesting.TestingT , job batchv1.Job ) {
678+ podSpec := job .Spec .Template .Spec
679+
680+ s .Require ().NotNil (podSpec .ShareProcessNamespace , "shareProcessNamespace must be set when nativeSidecarContainers present" )
681+ s .True (* podSpec .ShareProcessNamespace , "shareProcessNamespace must be true" )
682+
683+ s .Require ().Len (podSpec .InitContainers , 1 , "Should be one initContainer (the sidecar)" )
684+ sidecar := podSpec .InitContainers [0 ]
685+ s .True (envContains (sidecar .Env , "TARGET_CONTAINER" , "executor" ), "Sidecar must have auto-injected TARGET_CONTAINER=executor" )
686+ s .True (volumeMountContains (sidecar .VolumeMounts , "telemetry-socket" , "/tmp/telemetry" ), "Sidecar must have auto-injected telemetry-socket volumeMount" )
687+
688+ executor := findContainer (podSpec .Containers , "executor" )
689+ s .Require ().NotNil (executor , "executor container must exist" )
690+ s .True (volumeMountContains (executor .VolumeMounts , "telemetry-socket" , "/tmp/telemetry" ), "Executor must have auto-injected telemetry-socket volumeMount" )
691+
692+ s .True (volumeContains (podSpec .Volumes , "telemetry-socket" ), "Pod must have auto-injected telemetry-socket emptyDir volume" )
693+ },
694+ },
695+ {
696+ "PreservesExplicitTargetContainerOverride" ,
697+ map [string ]string {
698+ "delegatedOperatorJobTemplates.jobs.testJob.unused" : "nil" ,
699+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].name" : "telemetry-sidecar" ,
700+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].image" : "telemetry-sidecar:latest" ,
701+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].restartPolicy" : "Always" ,
702+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].env[0].name" : "EXECUTOR_SIDECAR" ,
703+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].env[0].value" : "true" ,
704+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].env[1].name" : "TARGET_CONTAINER" ,
705+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].env[1].value" : "custom-executor" ,
706+ },
707+ func (subT gruntworkTesting.TestingT , job batchv1.Job ) {
708+ sidecar := job .Spec .Template .Spec .InitContainers [0 ]
709+ s .True (envContains (sidecar .Env , "TARGET_CONTAINER" , "custom-executor" ), "User-set TARGET_CONTAINER must win" )
710+ s .False (envContains (sidecar .Env , "TARGET_CONTAINER" , "executor" ), "Auto-inject must not also append TARGET_CONTAINER=executor" )
711+ },
712+ },
713+ {
714+ "DoesNotInjectTelemetryWiringForNonExecutorSidecar" ,
715+ map [string ]string {
716+ "delegatedOperatorJobTemplates.jobs.testJob.unused" : "nil" ,
717+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].name" : "istio-proxy" ,
718+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].image" : "istio-proxy:latest" ,
719+ "delegatedOperatorJobTemplates.template.nativeSidecarContainers[0].restartPolicy" : "Always" ,
720+ },
721+ func (subT gruntworkTesting.TestingT , job batchv1.Job ) {
722+ podSpec := job .Spec .Template .Spec
723+ s .False (volumeContains (podSpec .Volumes , "telemetry-socket" ), "Non-executor sidecar must not auto-inject telemetry-socket volume" )
724+ sidecar := podSpec .InitContainers [0 ]
725+ s .False (volumeMountContains (sidecar .VolumeMounts , "telemetry-socket" , "/tmp/telemetry" ), "Non-executor sidecar must not auto-inject volumeMount" )
726+ executor := findContainer (podSpec .Containers , "executor" )
727+ s .Require ().NotNil (executor )
728+ s .False (volumeMountContains (executor .VolumeMounts , "telemetry-socket" , "/tmp/telemetry" ), "Executor must not get telemetry-socket mount when no executor sidecar" )
729+ },
730+ },
731+ }
732+
733+ for _ , testCase := range testCases {
734+ testCase := testCase
735+ s .Run (testCase .name , func () {
736+ subT := s .T ()
737+ subT .Parallel ()
738+
739+ options := & helm.Options {SetValues : testCase .values }
740+ output := helm .RenderTemplate (subT , options , s .chartPath , s .releaseName , s .templates )
741+
742+ var configMap corev1.ConfigMap
743+ helm .UnmarshalK8SYaml (subT , output , & configMap )
744+
745+ s .Require ().NotEmpty (configMap .Data ["testJob.yaml" ], "testJob.yaml should be rendered in configmap data" )
746+
747+ jinjaArgs := map [string ]interface {}{
748+ "_id" : strings .ToLower (random .UniqueId ()),
749+ "_command" : "fiftyone" ,
750+ "_args" : []string {"delegated" , "launch" },
751+ }
752+ actualJobYaml , err := convertJinjaToYAML (configMap .Data ["testJob.yaml" ], jinjaArgs )
753+ s .NoError (err )
754+
755+ var job batchv1.Job
756+ helm .UnmarshalK8SYaml (subT , actualJobYaml , & job )
757+
758+ testCase .expected (subT , job )
759+ })
760+ }
761+ }
762+
763+ func envContains (envs []corev1.EnvVar , name , value string ) bool {
764+ for _ , e := range envs {
765+ if e .Name == name && e .Value == value {
766+ return true
767+ }
768+ }
769+ return false
770+ }
771+
772+ func volumeMountContains (vms []corev1.VolumeMount , name , mountPath string ) bool {
773+ for _ , vm := range vms {
774+ if vm .Name == name && vm .MountPath == mountPath {
775+ return true
776+ }
777+ }
778+ return false
779+ }
780+
781+ func volumeContains (vols []corev1.Volume , name string ) bool {
782+ for _ , v := range vols {
783+ if v .Name == name {
784+ return true
785+ }
786+ }
787+ return false
788+ }
789+
790+ func findContainer (containers []corev1.Container , name string ) * corev1.Container {
791+ for i , c := range containers {
792+ if c .Name == name {
793+ return & containers [i ]
794+ }
795+ }
796+ return nil
797+ }
0 commit comments