@@ -17,7 +17,7 @@ limitations under the License.
1717
1818import (
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/
184197func 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