Merge pull request #135560 from lalitc375/map-debug

Fix MAP failure on objects with duplicate list items
This commit is contained in:
Kubernetes Prow Robot
2025-12-03 16:14:20 -08:00
committed by GitHub
2 changed files with 102 additions and 1 deletions

View File

@@ -138,7 +138,7 @@ func ApplyStructuredMergeDiff(
return nil, fmt.Errorf("invalid ApplyConfiguration: %w", err)
}
liveObjTyped, err := typeConverter.ObjectToTyped(originalObject)
liveObjTyped, err := typeConverter.ObjectToTyped(originalObject, typed.AllowDuplicates)
if err != nil {
return nil, fmt.Errorf("failed to convert original object to typed object: %w", err)
}

View File

@@ -233,6 +233,107 @@ func TestApplyConfiguration(t *testing.T) {
object: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{Replicas: ptr.To[int32](1)}},
expectedErr: "must evaluate to Object but got Object.spec.metadata",
},
{
name: "apply configuration with duplicate env vars in original object",
expression: `Object{
spec: Object.spec{
replicas: 3
}
}`,
gvr: deploymentGVR,
object: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1),
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "nginx",
Env: []corev1.EnvVar{
{Name: "test", Value: "a"},
{Name: "test", Value: "b"},
},
}},
},
},
},
},
expectedResult: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](3),
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "nginx",
Env: []corev1.EnvVar{
{Name: "test", Value: "a"},
{Name: "test", Value: "b"},
},
}},
},
},
},
},
},
// This test verifies that modifying an existing environment variable works correctly,
// even if the original object contains duplicates.
// Because 'env' is defined with `listType=map` and `listMapKey=name` in the schema,
// Structured Merge Diff (SMD) treats 'name' as the unique key.
// When the patch updates the entry with name="test", SMD merges the changes.
// As a side effect of the merge process on a map-type list, duplicate entries for the
// same key in the original object are consolidated into a single entry in the result.
// This matches the behavior of Server-Side Apply (SSA) and kubectl apply.
{
name: "apply configuration modify existing env variable",
expression: `Object{
spec: Object.spec{
template: Object.spec.template{
spec: Object.spec.template.spec{
containers: [Object.spec.template.spec.containers{
name: "nginx",
env: [Object.spec.template.spec.containers.env{
name: "test",
value: "c"
}]
}]
}
}
}
}`,
gvr: deploymentGVR,
object: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1),
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "nginx",
Env: []corev1.EnvVar{
{Name: "test", Value: "a"},
{Name: "test", Value: "b"},
{Name: "foo", Value: "bar"},
},
}},
},
},
},
},
expectedResult: &appsv1.Deployment{
Spec: appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1),
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "nginx",
Env: []corev1.EnvVar{
{Name: "test", Value: "c"},
{Name: "foo", Value: "bar"},
},
}},
},
},
},
},
},
}
compiler, err := cel.NewCompositedCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))