@@ -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"
@@ -55,7 +60,7 @@ func Label(request *msgs.LabelRequest, ns, pgouser string) msgs.LabelResponse {
5560 labelsMap , err = validateLabel (request .LabelCmdLabel , ns )
5661 if err != nil {
5762 resp .Status .Code = msgs .Error
58- resp .Status .Msg = "labels not formatted correctly"
63+ resp .Status .Msg = err . Error ()
5964 return resp
6065 }
6166
@@ -259,29 +264,57 @@ func PatchPgcluster(newLabels map[string]string, oldCRD crv1.Pgcluster, ns strin
259264
260265}
261266
262- func validateLabel (LabelCmdLabel , ns string ) (map [string ]string , error ) {
263- var err error
264- labelMap := make (map [string ]string )
265- userValues := strings .Split (LabelCmdLabel , "," )
266- for _ , v := range userValues {
267+ // validateLabel validates if the input is a valid Kubernetes label
268+ //
269+ // A label is composed of a key and value.
270+ //
271+ // The key can either be a name or have an optional prefix that i
272+ // terminated by a "/", e.g. "prefix/name"
273+ //
274+ // The name must be a valid DNS 1123 value
275+ // THe prefix must be a valid DNS 1123 subdomain
276+ //
277+ // The value can be validated by machinery provided by Kubenretes
278+ //
279+ // Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
280+ func validateLabel (LabelCmdLabel string ) (map [string ]string , error ) {
281+ labelMap := map [string ]string {}
282+
283+ for _ , v := range strings .Split (LabelCmdLabel , "," ) {
267284 pair := strings .Split (v , "=" )
268285 if len (pair ) != 2 {
269- log .Error ("label format incorrect, requires name=value" )
270- return labelMap , errors .New ("label format incorrect, requires name=value" )
286+ return labelMap , fmt .Errorf ("label format incorrect, requires key=value" )
271287 }
272288
273- errs := validation .IsDNS1035Label (pair [0 ])
274- if len (errs ) > 0 {
275- return labelMap , errors .New ("label format incorrect, requires name=value " + errs [0 ])
289+ // first handle the key
290+ keyParts := strings .Split (pair [0 ], "/" )
291+
292+ switch len (keyParts ) {
293+ default :
294+ return labelMap , fmt .Errorf ("invalid key for " + v )
295+ case 2 :
296+ if errs := validation .IsDNS1123Subdomain (keyParts [0 ]); len (errs ) > 0 {
297+ return labelMap , fmt .Errorf ("invalid key for %s: %s" , v , strings .Join (errs , "," ))
298+ }
299+
300+ if errs := validation .IsDNS1123Label (keyParts [1 ]); len (errs ) > 0 {
301+ return labelMap , fmt .Errorf ("invalid key for %s: %s" , v , strings .Join (errs , "," ))
302+ }
303+ case 1 :
304+ if errs := validation .IsDNS1123Label (keyParts [0 ]); len (errs ) > 0 {
305+ return labelMap , fmt .Errorf ("invalid key for %s: %s" , v , strings .Join (errs , "," ))
306+ }
276307 }
277- errs = validation .IsDNS1035Label (pair [1 ])
278- if len (errs ) > 0 {
279- return labelMap , errors .New ("label format incorrect, requires name=value " + errs [0 ])
308+
309+ // handle the value
310+ if errs := validation .IsValidLabelValue (pair [1 ]); len (errs ) > 0 {
311+ return labelMap , fmt .Errorf ("invalid value for %s: %s" , v , strings .Join (errs , "," ))
280312 }
281313
282314 labelMap [pair [0 ]] = pair [1 ]
283315 }
284- return labelMap , err
316+
317+ return labelMap , nil
285318}
286319
287320// DeleteLabel ...
0 commit comments