<p dir="auto">In reviewing <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="40556112" data-permission-text="Title is private" data-url="https://github.com/kubernetes/kubernetes/issues/951" data-hovercard-type="pull_request" data-hovercard-url="/kubernetes/kubernetes/pull/951/hovercard" href="https://github.com/kubernetes/kubernetes/pull/951">#951</a>, it came to my attention that we have no validation or formal spec on what character restrictions we impose on label keys and values.  This is bad if we plan to support a more formal complex selector grammar which may require escaping rules.  We need to define a valid schema and enforce it via validation on object persistence.</p>
<p dir="auto">Clients today are restricted by the set of valid keys allowed in JSON or YAML for use as their label keys depending on the input format they use.</p>
<p dir="auto">According to JSON spec:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string. A string is very much like a C or Java string."><pre class="notranslate"><code class="notranslate">A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string. A string is very much like a C or Java string.
</code></pre></div>
<p dir="auto">This means, it's ok today to have labels keys in our input JSON like the following:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="{
  &quot;fu=&quot;:&quot;=bar&quot;
  &quot;fu==bar&quot;:&quot;something&quot;
  &quot;fu  == :: ?? != bar&quot;: &quot;seriously??&quot;
}"><pre class="notranslate"><code class="notranslate">{
  "fu=":"=bar"
  "fu==bar":"something"
  "fu  == :: ?? != bar": "seriously??"
}
</code></pre></div>
<p dir="auto">This makes supporting a label selector grammar ridiculously hard.  For example, a label selector of "foo==bar" is undefined because we have no rational way to parse that.  Even "foo=bar" today is broken by what we accept as input.</p>
<p dir="auto">I think k8s should require all label keys to match our dns952 regex.  This means all label keys are lower-case and single word terms.</p>
<p dir="auto">With this model, we can reliably look to support more complex label selector functions because we know where to stop parsing on left-hand operand, pluse we can support nicer unary operators or functions:</p>
<ul dir="auto">
<li>exists(foo)</li>
<li>foo=bar</li>
</ul>
<p dir="auto">The order that conversion functions are added to the scheme depends on the package initialization order in Go.  The name of a conversion function is used in other generated functions (for performance), but because the order of packages is not guaranteed stable any change in build order can result in conversions being generated in different orders.</p>
<p dir="auto">The reason we have duplicate conversions is extensions/v1beta1 and v1 for Pods (of which most of the sub objects are identical).  We need to ensure that there is a predictable order for the public conversion name - because conversions overwrite each other in the scheme, the generator doesn't have access to all conversions, only the most recent.</p>
<p dir="auto">Debugging info: Go 1.4</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ hack/update-generated-conversions.sh 2&gt;&amp;1 | grep -E 'conversion_generated.go|Generating'
Generating for version v1beta3
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6825 (0x3f499c)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4982 (0x5176d2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:91 (0x966cb3)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:103 (0x964541)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0x954796)
Generating for version v1
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6825 (0x3f499c)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4982 (0x5176d2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:91 (0x966cb3)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:103 (0x964541)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0x954796)"><pre class="notranslate"><code class="notranslate">$ hack/update-generated-conversions.sh 2&gt;&amp;1 | grep -E 'conversion_generated.go|Generating'
Generating for version v1beta3
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6825 (0x3f499c)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4982 (0x5176d2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:91 (0x966cb3)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:103 (0x964541)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0x954796)
Generating for version v1
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6825 (0x3f499c)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4982 (0x5176d2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:91 (0x966cb3)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:103 (0x964541)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0x954796)
</code></pre></div>
<p dir="auto">Go 1.5</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ hack/update-generated-conversions.sh 2&gt;&amp;1 | grep -E 'conversion_generated.go|Generating'
Generating for version v1beta3
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6564 (0x46e6df)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0xa07cd4)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:100 (0xa15fa2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4786 (0x5ba394)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:86 (0xa18b8b)
Generating for version v1
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6564 (0x46e6df)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0xa07cd4)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:100 (0xa15fa2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4786 (0x5ba394)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:86 (0xa18b8b)"><pre class="notranslate"><code class="notranslate">$ hack/update-generated-conversions.sh 2&gt;&amp;1 | grep -E 'conversion_generated.go|Generating'
Generating for version v1beta3
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6564 (0x46e6df)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0xa07cd4)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:100 (0xa15fa2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4786 (0x5ba394)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:86 (0xa18b8b)
Generating for version v1
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/api/v1/conversion_generated.go:6564 (0x46e6df)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/authorization/v1beta1/conversion_generated.go:24 (0xa07cd4)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1/conversion_generated.go:100 (0xa15fa2)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/extensions/v1beta1/conversion_generated.go:4786 (0x5ba394)
/Users/clayton/projects/go/src/github.com/openshift/origin/Godeps/_workspace/src/k8s.io/kubernetes/pkg/apis/metrics/v1alpha1/conversion_generated.go:86 (0xa18b8b)
</code></pre></div>
<p dir="auto">Need to figure out how to enforce an order.</p>