diff --git a/pkg/controller/inference/playground_controller.go b/pkg/controller/inference/playground_controller.go index aa8b493c..793480a0 100644 --- a/pkg/controller/inference/playground_controller.go +++ b/pkg/controller/inference/playground_controller.go @@ -264,7 +264,7 @@ func buildTemplate(models []*coreapi.OpenModel, playground *inferenceapi.Playgro // envs envs := parser.Envs() if playground.Spec.BackendRuntimeConfig != nil { - envs = append(envs, playground.Spec.BackendRuntimeConfig.Envs...) + envs = util.MergeEnvs(envs, playground.Spec.BackendRuntimeConfig.Envs) } // args diff --git a/pkg/util/util.go b/pkg/util/util.go index bf651a59..9688ce6f 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -38,6 +38,27 @@ func MergeResources(toMerge corev1.ResourceList, toBeMerged corev1.ResourceList) return toMerge } +// MergeEnvs merges two env var list and ensures that entries in BackendRuntimeConfig.Env take precedence. +// This function takes two slices of corev1.EnvVar: 'base' and 'overrides'. It returns a new slice of corev1.EnvVar +// where the 'overrides' values overwrite any duplicate names in 'base'. +func MergeEnvs(base []corev1.EnvVar, overrides []corev1.EnvVar) []corev1.EnvVar { + envMap := make(map[string]corev1.EnvVar) + + for _, env := range base { + envMap[env.Name] = env + } + + for _, env := range overrides { + envMap[env.Name] = env + } + + result := make([]corev1.EnvVar, 0, len(envMap)) + for _, env := range envMap { + result = append(result, env) + } + return result +} + // MergeKVs will merge kvs in toBeMerged to toMerge. // If kvs exist in toMerge, they will be replaced. func MergeKVs(toMerge map[string]string, toBeMerged map[string]string) map[string]string { diff --git a/pkg/util/util_test.go b/pkg/util/util_test.go index 9db27ea2..25a3db05 100644 --- a/pkg/util/util_test.go +++ b/pkg/util/util_test.go @@ -71,6 +71,101 @@ func TestMergeResources(t *testing.T) { } } +func TestMergeEnvs(t *testing.T) { + testCases := []struct { + name string + base []corev1.EnvVar + overrides []corev1.EnvVar + want []corev1.EnvVar + }{ + { + name: "overrides should overwrite base", + base: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "value2"}, + }, + overrides: []corev1.EnvVar{ + {Name: "VAR2", Value: "new_value2"}, + {Name: "VAR3", Value: "value3"}, + }, + want: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "new_value2"}, + {Name: "VAR3", Value: "value3"}, + }, + }, + { + name: "base has exclusive keys", + base: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + }, + overrides: []corev1.EnvVar{ + {Name: "VAR2", Value: "value2"}, + }, + want: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "value2"}, + }, + }, + { + name: "base is empty", + base: []corev1.EnvVar{}, + overrides: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "value2"}, + }, + want: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "value2"}, + }, + }, + { + name: "overrides is empty", + base: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "value2"}, + }, + overrides: []corev1.EnvVar{}, + want: []corev1.EnvVar{ + {Name: "VAR1", Value: "value1"}, + {Name: "VAR2", Value: "value2"}, + }, + }, + { + name: "both base and overrides are empty", + base: []corev1.EnvVar{}, + overrides: []corev1.EnvVar{}, + want: []corev1.EnvVar{}, + }, + { + name: "both base and overrides are nil", + base: nil, + overrides: nil, + want: []corev1.EnvVar{}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := MergeEnvs(tc.base, tc.overrides) + + gotMap := make(map[string]string) + for _, env := range got { + gotMap[env.Name] = env.Value + } + + wantMap := make(map[string]string) + for _, env := range tc.want { + wantMap[env.Name] = env.Value + } + + if diff := cmp.Diff(gotMap, wantMap); diff != "" { + t.Fatalf("unexpected envs: %s", diff) + } + }) + } +} + func TestMergeKVs(t *testing.T) { testCases := []struct { name string