Skip to content

Commit 3d61c0e

Browse files
committed
fix: fix auto inject sidecar vars and update test
1 parent 03a4b78 commit 3d61c0e

2 files changed

Lines changed: 154 additions & 9 deletions

File tree

helm/fiftyone-teams-app/templates/delegated-operator-job-configmap.yaml

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,13 @@ data:
4545
{{- $mergedExtraContainers := $jobConfig.extraContainers | default $baseTpl.extraContainers }}
4646
{{- $mergedNativeSidecarContainers := $jobConfig.nativeSidecarContainers | default $baseTpl.nativeSidecarContainers }}
4747

48-
{{- /* telemetry-sidecar needs a shared emptyDir; values can't reliably keep it through fleet regenerators, so reconcile it here. */ -}}
49-
{{- $needsTelemetrySocket := false }}
48+
{{- $hasExecutorSidecar := false }}
5049
{{- range $sidecar := $mergedNativeSidecarContainers }}
51-
{{- range $vm := ($sidecar.volumeMounts | default list) }}
52-
{{- if eq $vm.name "telemetry-socket" }}{{- $needsTelemetrySocket = true }}{{- end }}
50+
{{- range $env := ($sidecar.env | default list) }}
51+
{{- if and (eq $env.name "EXECUTOR_SIDECAR") (eq (toString $env.value) "true") }}{{- $hasExecutorSidecar = true }}{{- end }}
5352
{{- end }}
5453
{{- end }}
55-
{{- if $needsTelemetrySocket }}
54+
{{- if $hasExecutorSidecar }}
5655
{{- $hasVolume := false }}
5756
{{- range $v := ($mergedVolumes | default list) }}
5857
{{- if eq $v.name "telemetry-socket" }}{{- $hasVolume = true }}{{- end }}
@@ -154,18 +153,26 @@ data:
154153
{{- end }}
155154
{{- with $mergedNativeSidecarContainers }}
156155
initContainers:
157-
{{- /* TARGET_CONTAINER tells the telemetry sidecar's log tailer which container to follow; the executor is hardcoded so we know the value. */ -}}
158156
{{- range $sidecar := . }}
157+
{{- $isExecutor := false }}
159158
{{- $hasTargetContainer := false }}
160159
{{- range $env := ($sidecar.env | default list) }}
161-
{{- if eq $env.name "TARGET_CONTAINER" }}
162-
{{- $hasTargetContainer = true }}
163-
{{- end }}
160+
{{- if eq $env.name "TARGET_CONTAINER" }}{{- $hasTargetContainer = true }}{{- end }}
161+
{{- if and (eq $env.name "EXECUTOR_SIDECAR") (eq (toString $env.value) "true") }}{{- $isExecutor = true }}{{- end }}
164162
{{- end }}
165163
{{- $rendered := deepCopy $sidecar }}
166164
{{- if not $hasTargetContainer }}
167165
{{- $_ := set $rendered "env" (prepend ($sidecar.env | default list) (dict "name" "TARGET_CONTAINER" "value" "executor")) }}
168166
{{- end }}
167+
{{- if $isExecutor }}
168+
{{- $hasSocketMount := false }}
169+
{{- range $vm := ($sidecar.volumeMounts | default list) }}
170+
{{- if eq $vm.name "telemetry-socket" }}{{- $hasSocketMount = true }}{{- end }}
171+
{{- end }}
172+
{{- if not $hasSocketMount }}
173+
{{- $_ := set $rendered "volumeMounts" (append ($sidecar.volumeMounts | default list) (dict "name" "telemetry-socket" "mountPath" "/tmp/telemetry")) }}
174+
{{- end }}
175+
{{- end }}
169176
{{- list $rendered | toYaml | nindent 12 }}
170177
{{- end }}
171178
{{- end }}

tests/unit/helm/delegated-operator-job-configmap_test.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)