@@ -16,8 +16,13 @@ limitations under the License.
1616*/
1717
1818import (
19+ << << << < HEAD
1920 "encoding/json"
2021 "errors"
22+ == == == =
23+ "context"
24+ "fmt"
25+ >> >> >> > 5 c56a341d ... Update label validation to match Kubernetes rules
2126 "strings"
2227
2328 "github.com/crunchydata/postgres-operator/internal/apiserver"
@@ -54,7 +59,7 @@ func Label(request *msgs.LabelRequest, ns, pgouser string) msgs.LabelResponse {
5459 labelsMap , err = validateLabel (request .LabelCmdLabel , ns )
5560 if err != nil {
5661 resp .Status .Code = msgs .Error
57- resp .Status .Msg = "labels not formatted correctly"
62+ resp .Status .Msg = err . Error ()
5863 return resp
5964 }
6065
@@ -250,29 +255,57 @@ func PatchPgcluster(newLabels map[string]string, oldCRD crv1.Pgcluster, ns strin
250255
251256}
252257
253- func validateLabel (LabelCmdLabel , ns string ) (map [string ]string , error ) {
254- var err error
255- labelMap := make (map [string ]string )
256- userValues := strings .Split (LabelCmdLabel , "," )
257- for _ , v := range userValues {
258+ // validateLabel validates if the input is a valid Kubernetes label
259+ //
260+ // A label is composed of a key and value.
261+ //
262+ // The key can either be a name or have an optional prefix that i
263+ // terminated by a "/", e.g. "prefix/name"
264+ //
265+ // The name must be a valid DNS 1123 value
266+ // THe prefix must be a valid DNS 1123 subdomain
267+ //
268+ // The value can be validated by machinery provided by Kubenretes
269+ //
270+ // Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
271+ func validateLabel (LabelCmdLabel string ) (map [string ]string , error ) {
272+ labelMap := map [string ]string {}
273+
274+ for _ , v := range strings .Split (LabelCmdLabel , "," ) {
258275 pair := strings .Split (v , "=" )
259276 if len (pair ) != 2 {
260- log .Error ("label format incorrect, requires name=value" )
261- return labelMap , errors .New ("label format incorrect, requires name=value" )
277+ return labelMap , fmt .Errorf ("label format incorrect, requires key=value" )
262278 }
263279
264- errs := validation .IsDNS1035Label (pair [0 ])
265- if len (errs ) > 0 {
266- return labelMap , errors .New ("label format incorrect, requires name=value " + errs [0 ])
280+ // first handle the key
281+ keyParts := strings .Split (pair [0 ], "/" )
282+
283+ switch len (keyParts ) {
284+ default :
285+ return labelMap , fmt .Errorf ("invalid key for " + v )
286+ case 2 :
287+ if errs := validation .IsDNS1123Subdomain (keyParts [0 ]); len (errs ) > 0 {
288+ return labelMap , fmt .Errorf ("invalid key for %s: %s" , v , strings .Join (errs , "," ))
289+ }
290+
291+ if errs := validation .IsDNS1123Label (keyParts [1 ]); len (errs ) > 0 {
292+ return labelMap , fmt .Errorf ("invalid key for %s: %s" , v , strings .Join (errs , "," ))
293+ }
294+ case 1 :
295+ if errs := validation .IsDNS1123Label (keyParts [0 ]); len (errs ) > 0 {
296+ return labelMap , fmt .Errorf ("invalid key for %s: %s" , v , strings .Join (errs , "," ))
297+ }
267298 }
268- errs = validation .IsDNS1035Label (pair [1 ])
269- if len (errs ) > 0 {
270- return labelMap , errors .New ("label format incorrect, requires name=value " + errs [0 ])
299+
300+ // handle the value
301+ if errs := validation .IsValidLabelValue (pair [1 ]); len (errs ) > 0 {
302+ return labelMap , fmt .Errorf ("invalid value for %s: %s" , v , strings .Join (errs , "," ))
271303 }
272304
273305 labelMap [pair [0 ]] = pair [1 ]
274306 }
275- return labelMap , err
307+
308+ return labelMap , nil
276309}
277310
278311// DeleteLabel ...
0 commit comments