Skip to content

Commit d8a482d

Browse files
jkatzJonathan S. Katz
authored andcommitted
Update label validation to match Kubernetes rules
The validation rules for certain kinds of keys are now covered, and values are properly validated against what Kubernetes expects. Issue: [ch10197] Issue: #2215
1 parent 93798e4 commit d8a482d

File tree

1 file changed

+48
-15
lines changed

1 file changed

+48
-15
lines changed

internal/apiserver/labelservice/labelimpl.go

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ limitations under the License.
1616
*/
1717

1818
import (
19+
<<<<<<< HEAD
1920
"encoding/json"
2021
"errors"
22+
=======
23+
"context"
24+
"fmt"
25+
>>>>>>> 5c56a341d... 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

Comments
 (0)