blob: 08d0c6e7ea736349083e9c4a382db4be644a0fd7 [file] [log] [blame]
Serge Bazanski1f789542024-05-22 14:01:50 +02001package node
2
3import (
4 "fmt"
5 "regexp"
6)
7
8var (
9 reLabelFirstLast = regexp.MustCompile(`^[a-zA-Z0-9]$`)
10 reLabelBody = regexp.MustCompile(`^[a-zA-Z0-9\-._]*$`)
11
12 // ErrLabelEmpty is returned by ValidateLabel if the label key/value is not at
13 // least one character long.
14 ErrLabelEmpty = fmt.Errorf("empty")
15 // ErrLabelTooLong is returned by ValidateLabel if the label key/value is more
16 // than 63 characters long.
17 ErrLabelTooLong = fmt.Errorf("too long")
18 // ErrLabelInvalidFirstCharacter is returned by ValidateLabel if the label
19 // key/value contains an invalid character on the first position.
20 ErrLabelInvalidFirstCharacter = fmt.Errorf("first character not a letter or number")
21 // ErrLabelInvalidLastCharacter is returned by ValidateLabel if the label
22 // key/value contains an invalid character on the last position.
23 ErrLabelInvalidLastCharacter = fmt.Errorf("last character not a letter or number")
24 // ErrLabelInvalidCharacter is returned by ValidateLabel if the label key/value
25 // contains an invalid character.
26 ErrLabelInvalidCharacter = fmt.Errorf("invalid character")
27)
28
29const (
30 // MaxLabelsPerNode is the absolute maximum of labels that can be attached to a
31 // node.
32 MaxLabelsPerNode = 128
33)
34
35// ValidateLabel ensures that a given node label key/value component is valid:
36//
37// 1. 1 to 63 characters long (inclusive);
38// 2. Characters are all ASCII a-z A-Z 0-9 '_', '-' or '.';
39// 3. The first character is ASCII a-z A-Z or 0-9.
40// 4. The last character is ASCII a-z A-Z or 0-9.
41//
42// If it's valid, nil is returned. Otherwise, one of ErrLabelEmpty,
43// ErrLabelTooLong, ErrLabelInvalidFirstCharacter or ErrLabelInvalidCharacter is
44// returned.
45func ValidateLabel(v string) error {
46 if len(v) == 0 {
47 return ErrLabelEmpty
48 }
49 if len(v) > 63 {
50 return ErrLabelTooLong
51 }
52 if !reLabelFirstLast.MatchString(string(v[0])) {
53 return ErrLabelInvalidFirstCharacter
54 }
55 if !reLabelFirstLast.MatchString(string(v[len(v)-1])) {
56 return ErrLabelInvalidLastCharacter
57 }
58 // Body characters are a superset of the first/last characters, and we've already
59 // checked those so we can check the entire string here.
60 if !reLabelBody.MatchString(v) {
61 return ErrLabelInvalidCharacter
62 }
63 return nil
64}