Skip to content

Commit 5c56a34

Browse files
authored
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 acff4bc commit 5c56a34

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

internal/apiserver/labelservice/labelimpl.go

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717

1818
import (
1919
"context"
20-
"errors"
20+
"fmt"
2121
"strings"
2222

2323
"github.com/crunchydata/postgres-operator/internal/apiserver"
@@ -53,7 +53,7 @@ func Label(request *msgs.LabelRequest, ns, pgouser string) msgs.LabelResponse {
5353
labelsMap, err = validateLabel(request.LabelCmdLabel)
5454
if err != nil {
5555
resp.Status.Code = msgs.Error
56-
resp.Status.Msg = "labels not formatted correctly"
56+
resp.Status.Msg = err.Error()
5757
return resp
5858
}
5959

@@ -181,29 +181,57 @@ func addLabels(items []crv1.Pgcluster, DryRun bool, LabelCmdLabel string, newLab
181181
}
182182
}
183183

184+
// validateLabel validates if the input is a valid Kubernetes label
185+
//
186+
// A label is composed of a key and value.
187+
//
188+
// The key can either be a name or have an optional prefix that i
189+
// terminated by a "/", e.g. "prefix/name"
190+
//
191+
// The name must be a valid DNS 1123 value
192+
// THe prefix must be a valid DNS 1123 subdomain
193+
//
194+
// The value can be validated by machinery provided by Kubenretes
195+
//
196+
// Ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
184197
func validateLabel(LabelCmdLabel string) (map[string]string, error) {
185-
var err error
186-
labelMap := make(map[string]string)
187-
userValues := strings.Split(LabelCmdLabel, ",")
188-
for _, v := range userValues {
198+
labelMap := map[string]string{}
199+
200+
for _, v := range strings.Split(LabelCmdLabel, ",") {
189201
pair := strings.Split(v, "=")
190202
if len(pair) != 2 {
191-
log.Error("label format incorrect, requires name=value")
192-
return labelMap, errors.New("label format incorrect, requires name=value")
203+
return labelMap, fmt.Errorf("label format incorrect, requires key=value")
193204
}
194205

195-
errs := validation.IsDNS1035Label(pair[0])
196-
if len(errs) > 0 {
197-
return labelMap, errors.New("label format incorrect, requires name=value " + errs[0])
206+
// first handle the key
207+
keyParts := strings.Split(pair[0], "/")
208+
209+
switch len(keyParts) {
210+
default:
211+
return labelMap, fmt.Errorf("invalid key for " + v)
212+
case 2:
213+
if errs := validation.IsDNS1123Subdomain(keyParts[0]); len(errs) > 0 {
214+
return labelMap, fmt.Errorf("invalid key for %s: %s", v, strings.Join(errs, ","))
215+
}
216+
217+
if errs := validation.IsDNS1123Label(keyParts[1]); len(errs) > 0 {
218+
return labelMap, fmt.Errorf("invalid key for %s: %s", v, strings.Join(errs, ","))
219+
}
220+
case 1:
221+
if errs := validation.IsDNS1123Label(keyParts[0]); len(errs) > 0 {
222+
return labelMap, fmt.Errorf("invalid key for %s: %s", v, strings.Join(errs, ","))
223+
}
198224
}
199-
errs = validation.IsDNS1035Label(pair[1])
200-
if len(errs) > 0 {
201-
return labelMap, errors.New("label format incorrect, requires name=value " + errs[0])
225+
226+
// handle the value
227+
if errs := validation.IsValidLabelValue(pair[1]); len(errs) > 0 {
228+
return labelMap, fmt.Errorf("invalid value for %s: %s", v, strings.Join(errs, ","))
202229
}
203230

204231
labelMap[pair[0]] = pair[1]
205232
}
206-
return labelMap, err
233+
234+
return labelMap, nil
207235
}
208236

209237
// DeleteLabel ...

0 commit comments

Comments
 (0)