Unverified Commit 8f3188d3 authored by hhzhang16's avatar hhzhang16 Committed by GitHub
Browse files

feat: add missing overrides (#7017)


Signed-off-by: default avatarHannah Zhang <hannahz@nvidia.com>
parent 175d9196
...@@ -64,6 +64,7 @@ const ( ...@@ -64,6 +64,7 @@ const (
KubeAnnotationDeploymentStrategy = "nvidia.com/deployment-strategy" KubeAnnotationDeploymentStrategy = "nvidia.com/deployment-strategy"
KubeAnnotationDeploymentRollingUpdateMaxSurge = "nvidia.com/deployment-rolling-update-max-surge" KubeAnnotationDeploymentRollingUpdateMaxSurge = "nvidia.com/deployment-rolling-update-max-surge"
KubeAnnotationDeploymentRollingUpdateMaxUnavailable = "nvidia.com/deployment-rolling-update-max-unavailable" KubeAnnotationDeploymentRollingUpdateMaxUnavailable = "nvidia.com/deployment-rolling-update-max-unavailable"
SchedulerNameVolcano = "volcano"
) )
// DynamoComponentDeploymentReconciler reconciles a DynamoComponentDeployment object // DynamoComponentDeploymentReconciler reconciles a DynamoComponentDeployment object
...@@ -561,7 +562,7 @@ func (r *DynamoComponentDeploymentReconciler) generateLeaderPodTemplateSpec(ctx ...@@ -561,7 +562,7 @@ func (r *DynamoComponentDeploymentReconciler) generateLeaderPodTemplateSpec(ctx
} }
leaderPodTemplateSpec.ObjectMeta.Annotations["scheduling.k8s.io/group-name"] = kubeName leaderPodTemplateSpec.ObjectMeta.Annotations["scheduling.k8s.io/group-name"] = kubeName
leaderPodTemplateSpec.Spec.SchedulerName = "volcano" leaderPodTemplateSpec.Spec.SchedulerName = SchedulerNameVolcano
err = checkMainContainer(&leaderPodTemplateSpec.Spec) err = checkMainContainer(&leaderPodTemplateSpec.Spec)
...@@ -614,7 +615,7 @@ func (r *DynamoComponentDeploymentReconciler) generateWorkerPodTemplateSpec(ctx ...@@ -614,7 +615,7 @@ func (r *DynamoComponentDeploymentReconciler) generateWorkerPodTemplateSpec(ctx
workerPodTemplateSpec.ObjectMeta.Labels["instance-id"] = fmt.Sprintf("%d", instanceID) workerPodTemplateSpec.ObjectMeta.Labels["instance-id"] = fmt.Sprintf("%d", instanceID)
delete(workerPodTemplateSpec.ObjectMeta.Labels, commonconsts.KubeLabelDynamoSelector) delete(workerPodTemplateSpec.ObjectMeta.Labels, commonconsts.KubeLabelDynamoSelector)
workerPodTemplateSpec.Spec.SchedulerName = "volcano" workerPodTemplateSpec.Spec.SchedulerName = SchedulerNameVolcano
if workerPodTemplateSpec.ObjectMeta.Annotations == nil { if workerPodTemplateSpec.ObjectMeta.Annotations == nil {
workerPodTemplateSpec.ObjectMeta.Annotations = make(map[string]string) workerPodTemplateSpec.ObjectMeta.Annotations = make(map[string]string)
......
...@@ -154,6 +154,21 @@ func applyPodSpecOverrides(spec *corev1.PodSpec, overrides *corev1.PodSpec) { ...@@ -154,6 +154,21 @@ func applyPodSpecOverrides(spec *corev1.PodSpec, overrides *corev1.PodSpec) {
if overrides.DNSConfig != nil { if overrides.DNSConfig != nil {
spec.DNSConfig = overrides.DNSConfig spec.DNSConfig = overrides.DNSConfig
} }
if overrides.SecurityContext != nil {
if spec.SecurityContext == nil {
spec.SecurityContext = &corev1.PodSecurityContext{}
}
mergePodSecurityContext(spec.SecurityContext, overrides.SecurityContext)
}
if overrides.TerminationGracePeriodSeconds != nil {
spec.TerminationGracePeriodSeconds = overrides.TerminationGracePeriodSeconds
}
if len(overrides.TopologySpreadConstraints) > 0 {
spec.TopologySpreadConstraints = overrides.TopologySpreadConstraints
}
if overrides.AutomountServiceAccountToken != nil {
spec.AutomountServiceAccountToken = overrides.AutomountServiceAccountToken
}
spec.Volumes = mergeNamedSlice(spec.Volumes, overrides.Volumes, func(v corev1.Volume) string { return v.Name }) spec.Volumes = mergeNamedSlice(spec.Volumes, overrides.Volumes, func(v corev1.Volume) string { return v.Name })
spec.InitContainers = mergeNamedSlice(spec.InitContainers, overrides.InitContainers, func(c corev1.Container) string { return c.Name }) spec.InitContainers = mergeNamedSlice(spec.InitContainers, overrides.InitContainers, func(c corev1.Container) string { return c.Name })
...@@ -184,6 +199,44 @@ func applyContainerOverrides(container *corev1.Container, overrides *corev1.Cont ...@@ -184,6 +199,44 @@ func applyContainerOverrides(container *corev1.Container, overrides *corev1.Cont
} }
} }
// mergePodSecurityContext copies non-nil fields from src into dst, preserving
// any controller-enforced defaults already present on dst.
func mergePodSecurityContext(dst, src *corev1.PodSecurityContext) {
if src.RunAsNonRoot != nil {
dst.RunAsNonRoot = src.RunAsNonRoot
}
if src.RunAsUser != nil {
dst.RunAsUser = src.RunAsUser
}
if src.RunAsGroup != nil {
dst.RunAsGroup = src.RunAsGroup
}
if src.FSGroup != nil {
dst.FSGroup = src.FSGroup
}
if src.SupplementalGroups != nil {
dst.SupplementalGroups = src.SupplementalGroups
}
if src.Sysctls != nil {
dst.Sysctls = src.Sysctls
}
if src.FSGroupChangePolicy != nil {
dst.FSGroupChangePolicy = src.FSGroupChangePolicy
}
if src.SeccompProfile != nil {
dst.SeccompProfile = src.SeccompProfile
}
if src.AppArmorProfile != nil {
dst.AppArmorProfile = src.AppArmorProfile
}
if src.SELinuxOptions != nil {
dst.SELinuxOptions = src.SELinuxOptions
}
if src.WindowsOptions != nil {
dst.WindowsOptions = src.WindowsOptions
}
}
// mergeNamedSlice merges two slices of named items. Items from overrides with // mergeNamedSlice merges two slices of named items. Items from overrides with
// the same name as a base item replace the base entry; new names are appended. // the same name as a base item replace the base entry; new names are appended.
// Preserves ordering of base items. // Preserves ordering of base items.
......
...@@ -352,6 +352,55 @@ func TestApplyProfilingJobOverrides_DNSConfigAndPolicy(t *testing.T) { ...@@ -352,6 +352,55 @@ func TestApplyProfilingJobOverrides_DNSConfigAndPolicy(t *testing.T) {
} }
} }
func TestApplyProfilingJobOverrides_TerminationGracePeriodSeconds(t *testing.T) {
job := baseJob()
applyProfilingJobOverrides(job, &batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
TerminationGracePeriodSeconds: ptr.To[int64](120),
},
},
})
if job.Spec.Template.Spec.TerminationGracePeriodSeconds == nil || *job.Spec.Template.Spec.TerminationGracePeriodSeconds != 120 {
t.Errorf("expected TerminationGracePeriodSeconds=120, got %v", job.Spec.Template.Spec.TerminationGracePeriodSeconds)
}
}
func TestApplyProfilingJobOverrides_TopologySpreadConstraints(t *testing.T) {
job := baseJob()
tsc := []corev1.TopologySpreadConstraint{
{
MaxSkew: 1,
TopologyKey: "kubernetes.io/hostname",
WhenUnsatisfiable: corev1.DoNotSchedule,
},
}
applyProfilingJobOverrides(job, &batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
TopologySpreadConstraints: tsc,
},
},
})
if len(job.Spec.Template.Spec.TopologySpreadConstraints) != 1 {
t.Error("topologySpreadConstraints not applied")
}
}
func TestApplyProfilingJobOverrides_AutomountServiceAccountToken(t *testing.T) {
job := baseJob()
applyProfilingJobOverrides(job, &batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
AutomountServiceAccountToken: ptr.To(false),
},
},
})
if job.Spec.Template.Spec.AutomountServiceAccountToken == nil || *job.Spec.Template.Spec.AutomountServiceAccountToken != false {
t.Error("expected AutomountServiceAccountToken=false")
}
}
func TestApplyProfilingJobOverrides_VolumesDedup(t *testing.T) { func TestApplyProfilingJobOverrides_VolumesDedup(t *testing.T) {
job := baseJob() job := baseJob()
applyProfilingJobOverrides(job, &batchv1.JobSpec{ applyProfilingJobOverrides(job, &batchv1.JobSpec{
...@@ -566,6 +615,42 @@ func TestApplyProfilingJobOverrides_ContainerSecurityContext(t *testing.T) { ...@@ -566,6 +615,42 @@ func TestApplyProfilingJobOverrides_ContainerSecurityContext(t *testing.T) {
} }
} }
func TestApplyProfilingJobOverrides_PodSecurityContext(t *testing.T) {
job := baseJob()
// Seed a default pod-level security context (mimics what the controller sets).
job.Spec.Template.Spec.SecurityContext = &corev1.PodSecurityContext{
RunAsNonRoot: ptr.To(true),
RunAsUser: ptr.To[int64](1000),
RunAsGroup: ptr.To[int64](1000),
FSGroup: ptr.To[int64](1000),
}
override := &corev1.PodSecurityContext{
RunAsNonRoot: ptr.To(false),
}
applyProfilingJobOverrides(job, &batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
SecurityContext: override,
},
},
})
got := job.Spec.Template.Spec.SecurityContext
if got == nil {
t.Fatal("pod securityContext is nil after override")
}
// User override wins: RunAsNonRoot should be false.
if got.RunAsNonRoot == nil || *got.RunAsNonRoot != false {
t.Errorf("expected RunAsNonRoot=false, got %v", got.RunAsNonRoot)
}
// Controller defaults preserved for fields not specified in the override.
if got.RunAsUser == nil || *got.RunAsUser != 1000 {
t.Errorf("expected RunAsUser=1000 (controller default preserved), got %v", got.RunAsUser)
}
if got.FSGroup == nil || *got.FSGroup != 1000 {
t.Errorf("expected FSGroup=1000 (controller default preserved), got %v", got.FSGroup)
}
}
func TestApplyProfilingJobOverrides_CommandAndArgsPreserved(t *testing.T) { func TestApplyProfilingJobOverrides_CommandAndArgsPreserved(t *testing.T) {
job := baseJob() job := baseJob()
applyProfilingJobOverrides(job, &batchv1.JobSpec{ applyProfilingJobOverrides(job, &batchv1.JobSpec{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment