Use structs for container validation test

This introduces no changes to unit tests other than to switch from
map-based to struct-based tables in TestValidateContainers and
TestValidateInitContainers in order to make diffs for later commits
easier to read.
This commit is contained in:
Lee Verberne 2022-07-26 06:31:35 +02:00
parent f88f76f444
commit 4a7fd2a614

View File

@ -7169,245 +7169,332 @@ func TestValidateContainers(t *testing.T) {
capabilities.SetForTests(capabilities.Capabilities{ capabilities.SetForTests(capabilities.Capabilities{
AllowPrivileged: false, AllowPrivileged: false,
}) })
errorCases := map[string][]core.Container{ errorCases := []struct {
"zero-length name": {{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, title string
"zero-length-image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, containers []core.Container
"name > 63 characters": {{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, }{
"name not a DNS label": {{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, {
"name not unique": { "zero-length name",
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, []core.Container{{Name: "", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
{Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
}, },
"zero-length image": {{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, {
"host port not unique": { "zero-length-image",
{Name: "abc", Image: "image", Ports: []core.ContainerPort{{ContainerPort: 80, HostPort: 80, Protocol: "TCP"}}, []core.Container{{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
{Name: "def", Image: "image", Ports: []core.ContainerPort{{ContainerPort: 81, HostPort: 80, Protocol: "TCP"}},
ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
}, },
"invalid env var name": { {
{Name: "abc", Image: "image", Env: []core.EnvVar{{Name: "ev!1"}}, ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, "name > 63 characters",
[]core.Container{{Name: strings.Repeat("a", 64), Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
}, },
"unknown volume name": { {
{Name: "abc", Image: "image", VolumeMounts: []core.VolumeMount{{Name: "anything", MountPath: "/foo"}}, "name not a DNS label",
ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}, []core.Container{{Name: "a.b.c", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
}, },
"invalid lifecycle, no exec command.": { {
{ "name not unique",
Name: "life-123", []core.Container{
Image: "image", {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
Lifecycle: &core.Lifecycle{ {Name: "abc", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
PreStop: &core.LifecycleHandler{
Exec: &core.ExecAction{},
},
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"invalid lifecycle, no http path.": { {
{ "zero-length image",
Name: "life-123", []core.Container{{Name: "abc", Image: "", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}},
Image: "image", },
Lifecycle: &core.Lifecycle{ {
PreStop: &core.LifecycleHandler{ "host port not unique",
HTTPGet: &core.HTTPGetAction{}, []core.Container{
}, {Name: "abc", Image: "image", Ports: []core.ContainerPort{{ContainerPort: 80, HostPort: 80, Protocol: "TCP"}},
}, ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
ImagePullPolicy: "IfNotPresent", {Name: "def", Image: "image", Ports: []core.ContainerPort{{ContainerPort: 81, HostPort: 80, Protocol: "TCP"}},
TerminationMessagePolicy: "File", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
}, },
}, },
"invalid lifecycle, no tcp socket port.": { {
{ "invalid env var name",
Name: "life-123", []core.Container{
Image: "image", {Name: "abc", Image: "image", Env: []core.EnvVar{{Name: "ev!1"}}, ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
Lifecycle: &core.Lifecycle{
PreStop: &core.LifecycleHandler{
TCPSocket: &core.TCPSocketAction{},
},
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"invalid lifecycle, zero tcp socket port.": { {
{ "unknown volume name",
Name: "life-123", []core.Container{
Image: "image", {Name: "abc", Image: "image", VolumeMounts: []core.VolumeMount{{Name: "anything", MountPath: "/foo"}},
Lifecycle: &core.Lifecycle{ ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"},
PreStop: &core.LifecycleHandler{ },
TCPSocket: &core.TCPSocketAction{ },
Port: intstr.FromInt(0), {
"invalid lifecycle, no exec command.",
[]core.Container{
{
Name: "life-123",
Image: "image",
Lifecycle: &core.Lifecycle{
PreStop: &core.LifecycleHandler{
Exec: &core.ExecAction{},
}, },
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"invalid lifecycle, no action.": { {
{ "invalid lifecycle, no http path.",
Name: "life-123", []core.Container{
Image: "image", {
Lifecycle: &core.Lifecycle{ Name: "life-123",
PreStop: &core.LifecycleHandler{}, Image: "image",
}, Lifecycle: &core.Lifecycle{
ImagePullPolicy: "IfNotPresent", PreStop: &core.LifecycleHandler{
TerminationMessagePolicy: "File", HTTPGet: &core.HTTPGetAction{},
}, },
},
"invalid readiness probe, terminationGracePeriodSeconds set.": {
{
Name: "life-123",
Image: "image",
ReadinessProbe: &core.Probe{
ProbeHandler: core.ProbeHandler{
TCPSocket: &core.TCPSocketAction{},
}, },
TerminationGracePeriodSeconds: utilpointer.Int64Ptr(10), ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"invalid liveness probe, no tcp socket port.": { {
{ "invalid lifecycle, no tcp socket port.",
Name: "life-123", []core.Container{
Image: "image", {
LivenessProbe: &core.Probe{ Name: "life-123",
ProbeHandler: core.ProbeHandler{ Image: "image",
TCPSocket: &core.TCPSocketAction{}, Lifecycle: &core.Lifecycle{
PreStop: &core.LifecycleHandler{
TCPSocket: &core.TCPSocketAction{},
},
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"invalid liveness probe, no action.": { {
{ "invalid lifecycle, zero tcp socket port.",
Name: "life-123", []core.Container{
Image: "image", {
LivenessProbe: &core.Probe{ Name: "life-123",
ProbeHandler: core.ProbeHandler{}, Image: "image",
}, Lifecycle: &core.Lifecycle{
ImagePullPolicy: "IfNotPresent", PreStop: &core.LifecycleHandler{
TerminationMessagePolicy: "File", TCPSocket: &core.TCPSocketAction{
}, Port: intstr.FromInt(0),
}, },
"invalid message termination policy": { },
{
Name: "life-123",
Image: "image",
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "Unknown",
},
},
"empty message termination policy": {
{
Name: "life-123",
Image: "image",
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "",
},
},
"privilege disabled": {
{Name: "abc", Image: "image", SecurityContext: fakeValidSecurityContext(true)},
},
"invalid compute resource": {
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: core.ResourceList{
"disk": resource.MustParse("10G"),
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"Resource CPU invalid": { {
{ "invalid lifecycle, no action.",
Name: "abc-123", []core.Container{
Image: "image", {
Resources: core.ResourceRequirements{ Name: "life-123",
Limits: getResourceLimits("-10", "0"), Image: "image",
}, Lifecycle: &core.Lifecycle{
ImagePullPolicy: "IfNotPresent", PreStop: &core.LifecycleHandler{},
TerminationMessagePolicy: "File",
},
},
"Resource Requests CPU invalid": {
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Requests: getResourceLimits("-10", "0"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
"Resource Memory invalid": {
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: getResourceLimits("0", "-10"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
"Request limit simple invalid": {
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: getResourceLimits("5", "3"),
Requests: getResourceLimits("6", "3"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
"Invalid storage limit request": {
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: core.ResourceList{
core.ResourceName("attachable-volumes-aws-ebs"): *resource.NewQuantity(10, resource.DecimalSI),
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"Request limit multiple invalid": { {
{ "invalid readiness probe, terminationGracePeriodSeconds set.",
Name: "abc-123", []core.Container{
Image: "image", {
Resources: core.ResourceRequirements{ Name: "life-123",
Limits: getResourceLimits("5", "3"), Image: "image",
Requests: getResourceLimits("6", "4"), ReadinessProbe: &core.Probe{
ProbeHandler: core.ProbeHandler{
TCPSocket: &core.TCPSocketAction{},
},
TerminationGracePeriodSeconds: utilpointer.Int64Ptr(10),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
"Invalid env from": { {
{ "invalid liveness probe, no tcp socket port.",
Name: "env-from-source", []core.Container{
Image: "image", {
ImagePullPolicy: "IfNotPresent", Name: "life-123",
TerminationMessagePolicy: "File", Image: "image",
EnvFrom: []core.EnvFromSource{ LivenessProbe: &core.Probe{
{ ProbeHandler: core.ProbeHandler{
ConfigMapRef: &core.ConfigMapEnvSource{ TCPSocket: &core.TCPSocketAction{},
LocalObjectReference: core.LocalObjectReference{ },
Name: "$%^&*#", },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"invalid liveness probe, no action.",
[]core.Container{
{
Name: "life-123",
Image: "image",
LivenessProbe: &core.Probe{
ProbeHandler: core.ProbeHandler{},
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"invalid message termination policy",
[]core.Container{
{
Name: "life-123",
Image: "image",
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "Unknown",
},
},
},
{
"empty message termination policy",
[]core.Container{
{
Name: "life-123",
Image: "image",
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "",
},
},
},
{
"privilege disabled",
[]core.Container{
{Name: "abc", Image: "image", SecurityContext: fakeValidSecurityContext(true)},
},
},
{
"invalid compute resource",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: core.ResourceList{
"disk": resource.MustParse("10G"),
},
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Resource CPU invalid",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: getResourceLimits("-10", "0"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Resource Requests CPU invalid",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Requests: getResourceLimits("-10", "0"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Resource Memory invalid",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: getResourceLimits("0", "-10"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Request limit simple invalid",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: getResourceLimits("5", "3"),
Requests: getResourceLimits("6", "3"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Invalid storage limit request",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: core.ResourceList{
core.ResourceName("attachable-volumes-aws-ebs"): *resource.NewQuantity(10, resource.DecimalSI),
},
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Request limit multiple invalid",
[]core.Container{
{
Name: "abc-123",
Image: "image",
Resources: core.ResourceRequirements{
Limits: getResourceLimits("5", "3"),
Requests: getResourceLimits("6", "4"),
},
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
},
},
},
{
"Invalid env from",
[]core.Container{
{
Name: "env-from-source",
Image: "image",
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
EnvFrom: []core.EnvFromSource{
{
ConfigMapRef: &core.ConfigMapEnvSource{
LocalObjectReference: core.LocalObjectReference{
Name: "$%^&*#",
},
}, },
}, },
}, },
@ -7415,9 +7502,9 @@ func TestValidateContainers(t *testing.T) {
}, },
}, },
} }
for k, v := range errorCases { for _, tc := range errorCases {
if errs := validateContainers(v, false, volumeDevices, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 { if errs := validateContainers(tc.containers, false, volumeDevices, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", tc.title)
} }
} }
} }
@ -7457,27 +7544,33 @@ func TestValidateInitContainers(t *testing.T) {
capabilities.SetForTests(capabilities.Capabilities{ capabilities.SetForTests(capabilities.Capabilities{
AllowPrivileged: false, AllowPrivileged: false,
}) })
errorCases := map[string][]core.Container{ errorCases := []struct {
"duplicate ports": { title string
{ initContainers []core.Container
Name: "abc", }{
Image: "image", {
Ports: []core.ContainerPort{ "duplicate ports",
{ []core.Container{
ContainerPort: 8080, HostPort: 8080, Protocol: "TCP", {
}, Name: "abc",
{ Image: "image",
ContainerPort: 8080, HostPort: 8080, Protocol: "TCP", Ports: []core.ContainerPort{
{
ContainerPort: 8080, HostPort: 8080, Protocol: "TCP",
},
{
ContainerPort: 8080, HostPort: 8080, Protocol: "TCP",
},
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
ImagePullPolicy: "IfNotPresent",
TerminationMessagePolicy: "File",
}, },
}, },
} }
for k, v := range errorCases { for _, tc := range errorCases {
if errs := validateContainers(v, true, volumeDevices, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 { if errs := validateContainers(tc.initContainers, true, volumeDevices, field.NewPath("field"), PodValidationOptions{}); len(errs) == 0 {
t.Errorf("expected failure for %s", k) t.Errorf("expected failure for %s", tc.title)
} }
} }
} }