mirror of https://github.com/k3s-io/k3s
Add namespacing for label keys
parent
d5a6a54391
commit
c857dc1196
|
@ -107,12 +107,21 @@ type ObjectMeta struct {
|
||||||
CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"`
|
CreationTimestamp util.Time `json:"creationTimestamp,omitempty" yaml:"creationTimestamp,omitempty"`
|
||||||
|
|
||||||
// Labels are key value pairs that may be used to scope and select individual resources.
|
// Labels are key value pairs that may be used to scope and select individual resources.
|
||||||
|
// Label keys are of the form:
|
||||||
|
// label-key ::= prefixed-name | name
|
||||||
|
// prefixed-name ::= prefix '/' name
|
||||||
|
// prefix ::= DNS_SUBDOMAIN
|
||||||
|
// name ::= DNS_LABEL
|
||||||
|
// The prefix is optional. If the prefix is not specified, the key is assumed to be private
|
||||||
|
// to the user. Other system components that wish to use labels must specify a prefix. The
|
||||||
|
// "kubernetes.io/" prefix is reserved for use by kubernetes components.
|
||||||
// TODO: replace map[string]string with labels.LabelSet type
|
// TODO: replace map[string]string with labels.LabelSet type
|
||||||
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"`
|
||||||
|
|
||||||
// Annotations are unstructured key value data stored with a resource that may be set by
|
// Annotations are unstructured key value data stored with a resource that may be set by
|
||||||
// external tooling. They are not queryable and should be preserved when modifying
|
// external tooling. They are not queryable and should be preserved when modifying
|
||||||
// objects.
|
// objects. Annotation keys have the same formatting restrictions as Label keys. See the
|
||||||
|
// comments on Labels for details.
|
||||||
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
Annotations map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -385,8 +385,20 @@ func ValidatePodSpec(spec *api.PodSpec) errs.ValidationErrorList {
|
||||||
func validateLabels(labels map[string]string, field string) errs.ValidationErrorList {
|
func validateLabels(labels map[string]string, field string) errs.ValidationErrorList {
|
||||||
allErrs := errs.ValidationErrorList{}
|
allErrs := errs.ValidationErrorList{}
|
||||||
for k := range labels {
|
for k := range labels {
|
||||||
if !util.IsDNS952Label(k) {
|
var n, ns string
|
||||||
allErrs = append(allErrs, errs.NewFieldNotSupported(field, k))
|
parts := strings.Split(k, "/")
|
||||||
|
switch len(parts) {
|
||||||
|
case 1:
|
||||||
|
n = parts[0]
|
||||||
|
case 2:
|
||||||
|
ns = parts[0]
|
||||||
|
n = parts[1]
|
||||||
|
default:
|
||||||
|
allErrs = append(allErrs, errs.NewFieldInvalid(field, k, ""))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (ns != "" && !util.IsDNSSubdomain(ns)) || !util.IsDNS952Label(n) {
|
||||||
|
allErrs = append(allErrs, errs.NewFieldInvalid(field, k, ""))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
|
|
|
@ -35,6 +35,39 @@ func expectPrefix(t *testing.T, prefix string, errs errors.ValidationErrorList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateLabels(t *testing.T) {
|
||||||
|
successCases := []map[string]string{
|
||||||
|
{"simple": "bar"},
|
||||||
|
{"now-with-dashes": "bar"},
|
||||||
|
{"simple/simple": "bar"},
|
||||||
|
{"now-with-dashes/simple": "bar"},
|
||||||
|
{"now-with-dashes/now-with-dashes": "bar"},
|
||||||
|
{"now.with.dots/simple": "bar"},
|
||||||
|
{"now-with.dashes-and.dots/simple": "bar"},
|
||||||
|
}
|
||||||
|
for i := range successCases {
|
||||||
|
errs := validateLabels(successCases[i], "field")
|
||||||
|
if len(errs) != 0 {
|
||||||
|
t.Errorf("case[%d] expected success, got %#v", i, errs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
errorCases := []map[string]string{
|
||||||
|
{"123cantbeginwithnumber": "bar"}, //invalid
|
||||||
|
{"NoUppercase123": "bar"}, //invalid
|
||||||
|
{"nospecialchars^=@": "bar"}, //invalid
|
||||||
|
{"cantendwithadash-": "bar"}, //invalid
|
||||||
|
{"rfc952-mustbe24charactersorless": "bar"}, //invalid
|
||||||
|
{"only/one/slash": "bar"},
|
||||||
|
}
|
||||||
|
for i := range errorCases {
|
||||||
|
errs := validateLabels(errorCases[i], "field")
|
||||||
|
if len(errs) != 1 {
|
||||||
|
t.Errorf("case[%d] expected failure", i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateVolumes(t *testing.T) {
|
func TestValidateVolumes(t *testing.T) {
|
||||||
successCase := []api.Volume{
|
successCase := []api.Volume{
|
||||||
{Name: "abc"},
|
{Name: "abc"},
|
||||||
|
|
Loading…
Reference in New Issue