-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalidation.go-31fd924a4aad700e4886cc8170f0b4cfb8c8d9637d0dafd73ab75192f09386a0
153 lines (129 loc) · 5.21 KB
/
validation.go-31fd924a4aad700e4886cc8170f0b4cfb8c8d9637d0dafd73ab75192f09386a0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// PUBLISH-CODE
/*
Copyright 2014 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// This code is taken from github.com/apimachinery/pkg/util/validation/validation.go
// and modified
package validation
import (
"fmt"
"regexp"
"strings"
)
const qnameCharFmt = "[A-Za-z0-9]"
const qnameExtCharFmt = "[-A-Za-z0-9_.]"
const qualifiedNameFmt = "(" + qnameCharFmt + qnameExtCharFmt + "*)?" + qnameCharFmt
const qualifiedNameErrMsg = "must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character"
const qualifiedNameMaxLength = 63
var qualifiedNameRegexp = regexp.MustCompile("^" + qualifiedNameFmt + "$")
// IsQualifiedName tests whether the value passed is what Kubernetes calls a
// "qualified name". This is a format used in various places throughout the
// system. If the value is not valid, a list of error strings is returned.
// Otherwise an empty list (or nil) is returned.
func IsQualifiedName(value string) []string {
var errs []string
parts := strings.Split(value, "/")
var name string
switch len(parts) {
case 1:
name = parts[0]
case 2:
var prefix string
prefix, name = parts[0], parts[1]
if len(prefix) == 0 {
errs = append(errs, "prefix part "+emptyError())
} else if msgs := IsDNS1123Subdomain(prefix); len(msgs) != 0 {
errs = append(errs, prefixEach(msgs, "prefix part ")...)
}
default:
return append(errs, "a qualified name "+regexError(qualifiedNameErrMsg, qualifiedNameFmt, "MyName", "my.name", "123-abc")+
" with an optional DNS subdomain prefix and '/' (e.g. 'example.com/MyName')")
}
if len(name) == 0 {
errs = append(errs, "name part "+emptyError())
} else if len(name) > qualifiedNameMaxLength {
errs = append(errs, "name part "+maxLenError(qualifiedNameMaxLength))
}
if !qualifiedNameRegexp.MatchString(name) {
errs = append(errs, "name part "+regexError(qualifiedNameErrMsg, qualifiedNameFmt, "MyName", "my.name", "123-abc"))
}
return errs
}
const dns1123SubdomainFmt = dns1123LabelFmt + "(\\." + dns1123LabelFmt + ")*"
const dns1123SubdomainErrorMsg = "a lowercase RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character"
// DNS1123SubdomainMaxLength is a subdomain's max length in DNS (RFC 1123)
const DNS1123SubdomainMaxLength = 253
var dns1123SubdomainRegexp = regexp.MustCompile("^" + dns1123SubdomainFmt + "$")
const dns1123LabelFmt = "[a-z0-9]([-a-z0-9]*[a-z0-9])?"
// DNS1123LabelMaxLength is a label's max length in DNS (RFC 1123)
const DNS1123LabelMaxLength = 63
// IsDNS1123Subdomain tests for a string that conforms to the definition of a
// subdomain in DNS (RFC 1123).
func IsDNS1123Subdomain(value string) []string {
var errs []string
if len(value) > DNS1123SubdomainMaxLength {
errs = append(errs, maxLenError(DNS1123SubdomainMaxLength))
}
if !dns1123SubdomainRegexp.MatchString(value) {
errs = append(errs, regexError(dns1123SubdomainErrorMsg, dns1123SubdomainFmt, "example.com"))
}
return errs
}
const labelValueFmt = "(" + qualifiedNameFmt + ")?"
const labelValueErrMsg = "a valid label must be an empty string or consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character"
// LabelValueMaxLength is a label's max length
const LabelValueMaxLength = 63
var labelValueRegexp = regexp.MustCompile("^" + labelValueFmt + "$")
// IsValidLabelValue tests whether the value passed is a valid label value. If
// the value is not valid, a list of error strings is returned. Otherwise an
// empty list (or nil) is returned.
func IsValidLabelValue(value string) []string {
var errs []string
if len(value) > LabelValueMaxLength {
errs = append(errs, maxLenError(LabelValueMaxLength))
}
if !labelValueRegexp.MatchString(value) {
errs = append(errs, regexError(labelValueErrMsg, labelValueFmt, "MyValue", "my_value", "12345"))
}
return errs
}
func prefixEach(msgs []string, prefix string) []string {
for i := range msgs {
msgs[i] = prefix + msgs[i]
}
return msgs
}
// maxLenError returns a string explanation of a "string too long" validation
// failure.
func maxLenError(length int) string {
return fmt.Sprintf("must be no more than %d characters", length)
}
// regexError returns a string explanation of a regex validation failure.
func regexError(msg string, fmt string, examples ...string) string {
if len(examples) == 0 {
return msg + " (regex used for validation is '" + fmt + "')"
}
msg += " (e.g. "
for i := range examples {
if i > 0 {
msg += " or "
}
msg += "'" + examples[i] + "', "
}
msg += "regex used for validation is '" + fmt + "')"
return msg
}
// emptyError returns a string explanation of a "must not be empty" validation
// failure.
func emptyError() string {
return "must be non-empty"
}