Skip to content

Commit 7afc54c

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 b15c31d commit 7afc54c

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"
@@ -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

Comments
 (0)