Change:
Help review this, thanks.
Are you asking for better validation on pod creation? I'm not really sure what you mean when you say "tip".
Yes, I mean it's better validate the pod when create. The tip mean the validation info response from server and show by client.

Discussion:
import ( "encoding/json" "fmt" <ins> "math" </ins> "net" "os" "path"

var DNS952LabelErrorMsg string = fmt.Sprintf(`must be a DNS 952 label (at most %d characters, matching regex %s): e.g. "my-name"`, validation.DNS952LabelMaxLength, validation.DNS952LabelFmt) var pdPartitionErrorMsg string = InclusiveRangeErrorMsg(1, 255) var PortRangeErrorMsg string = InclusiveRangeErrorMsg(1, 65535) <ins> var IdRangeErrorMsg string = InclusiveRangeErrorMsg(0, math.MaxInt32) </ins> var PortNameErrorMsg string = fmt.Sprintf(`must be an IANA_SVC_NAME (at most 15 characters, matching regex %s, it must contain at least one letter [a-z], and hyphens cannot be adjacent to other hyphens): e.g. "http"`, validation.IdentifierNoHyphensBeginEndFmt) const totalAnnotationSizeLimitB int = 256 * (1 << 10) // 256 kB

if securityContext != nil { allErrs = append(allErrs, validateHostNetwork(securityContext.HostNetwork, spec.Containers, specPath.Child("containers"))...) <ins> if securityContext.FSGroup != nil && !validation.IsValidGroupId(*securityContext.FSGroup) { allErrs = append(allErrs, field.Invalid(fldPath.Child("fsGroup"), *(securityContext.FSGroup), IdRangeErrorMsg)) } if securityContext.RunAsUser != nil && !validation.IsValidUserId(*securityContext.RunAsUser) { allErrs = append(allErrs, field.Invalid(fldPath.Child("runAsUser"), *(securityContext.RunAsUser), IdRangeErrorMsg)) } for i, gid := range securityContext.SupplementalGroups { if !validation.IsValidGroupId(gid) { supplementalGroup := fmt.Sprintf(`supplementalGroups[%d]`, i) allErrs = append(allErrs, field.Invalid(fldPath.Child(supplementalGroup), gid, IdRangeErrorMsg)) } } </ins> } return allErrs

func TestValidatePodSpec(t *testing.T) { activeDeadlineSeconds := int64(30) <ins> minID := int64(0) maxID := int64(2147483647) </ins> successCases := []api.PodSpec{ { // Populate basic fields, leave defaults for most. Volumes:       []api.Volume{{Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}}},

RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, <ins> { // Populate RunAsUser SupplementalGroups FSGroup with minID 0 Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ SupplementalGroups: []int64{minID}, RunAsUser:          &minID, FSGroup:            &minID, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, { // Populate RunAsUser SupplementalGroups FSGroup with maxID 2147483647 Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ SupplementalGroups: []int64{maxID}, RunAsUser:          &maxID, FSGroup:            &maxID, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, </ins> { // Populate HostIPC. SecurityContext: &api.PodSecurityContext{ HostIPC: true,

} activeDeadlineSeconds = int64(0) <ins> minID = int64(-1) maxID = int64(2147483648) </ins> failureCases := map[string]api.PodSpec{ "bad volume": { Volumes:       []api.Volume{{}},

RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, <ins> "bad supplementalGroups large than math.MaxInt32": { Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ HostNetwork:        false, SupplementalGroups: []int64{maxID, 1234}, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, "bad supplementalGroups less than 0": { Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ HostNetwork:        false, SupplementalGroups: []int64{minID, 1234}, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, "bad runAsUser large than math.MaxInt32": { Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ HostNetwork: false, RunAsUser:   &maxID, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, "bad runAsUser less than 0": { Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ HostNetwork: false, RunAsUser:   &minID, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, "bad fsGroup large than math.MaxInt32": { Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ HostNetwork: false, FSGroup:     &maxID, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, "bad fsGroup less than 0": { Containers: []api.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent"}}, SecurityContext: &api.PodSecurityContext{ HostNetwork: false, FSGroup:     &minID, }, RestartPolicy: api.RestartPolicyAlways, DNSPolicy:     api.DNSClusterFirst, }, </ins> "bad-active-deadline-seconds": { Volumes: []api.Volume{ {Name: "vol", VolumeSource: api.VolumeSource{EmptyDir: &api.EmptyDirVolumeSource{}}},

package validation import ( <ins> "math" </ins> "net" "regexp" "strings"

return 0 < port && port < 65536 } <ins> // Now in libcontainer UID/GID limits is 0 ~ 1<<31 - 1 // TODO: once we have a type for UID/GID we should make these that type. const ( minUserID  = 0 maxUserID  = math.MaxInt32 minGroupID = 0 maxGroupID = math.MaxInt32 ) // IsValidGroupId tests that the argument is a valid gids. func IsValidGroupId(gid int64) bool { return minGroupID <= gid && gid <= maxGroupID } // IsValidUserId tests that the argument is a valid uids. func IsValidUserId(uid int64) bool { return minUserID <= uid && uid <= maxUserID } </ins> const doubleHyphensFmt string = ".*(--).*" var doubleHyphensRegexp = regexp.MustCompile("^" + doubleHyphensFmt + "$")

} } <ins> func TestIsValidGroupId(t *testing.T) { goodValues := []int64{0, 1, 1000, 65535, 2147483647} for _, val := range goodValues { if !IsValidGroupId(val) { t.Errorf("expected true for '%d'", val) } } badValues := []int64{-1, -1003, 2147483648, 4147483647} for _, val := range badValues { if IsValidGroupId(val) { t.Errorf("expected false for '%d'", val) } } } func TestIsValidUserId(t *testing.T) { goodValues := []int64{0, 1, 1000, 65535, 2147483647} for _, val := range goodValues { if !IsValidUserId(val) { t.Errorf("expected true for '%d'", val) } } badValues := []int64{-1, -1003, 2147483648, 4147483647} for _, val := range badValues { if IsValidUserId(val) { t.Errorf("expected false for '%d'", val) } } } </ins> func TestIsValidPortName(t *testing.T) { goodValues := []string{"telnet", "re-mail-ck", "pop3", "a", "a-1", "1-a", "a-1-b-2-c", "1-a-2-b-3"} for _, val := range goodValues {