Skip to content

Commit f797d50

Browse files
authored
⚠️ update name validation patterns to match Kubernetes as close as possible (#1175)
* update name validation patterns to match Kubernetes as closely as possible Signed-off-by: everettraven <[email protected]> * remove duplicate channel name admission test Signed-off-by: everettraven <[email protected]> --------- Signed-off-by: everettraven <[email protected]>
1 parent a28d932 commit f797d50

File tree

3 files changed

+62
-38
lines changed

3 files changed

+62
-38
lines changed

api/v1alpha1/clusterextension_types.go

+25-17
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ type ClusterExtensionSpec struct {
6767
// applied to other Namespaces. This Namespace is expected to exist.
6868
//
6969
// installNamespace is required, immutable, and follows the DNS label standard
70-
// as defined in RFC 1123. This means that valid values:
70+
// as defined in [RFC 1123]. This means that valid values:
7171
// - Contain no more than 63 characters
7272
// - Contain only lowercase alphanumeric characters or '-'
7373
// - Start with an alphanumeric character
@@ -85,6 +85,8 @@ type ClusterExtensionSpec struct {
8585
// - thisisareallylongnamespacenamethatisgreaterthanthemaximumlength
8686
// - some.namespace
8787
//
88+
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
89+
//
8890
//+kubebuilder:validation:Pattern:=^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
8991
//+kubebuilder:validation:MaxLength:=63
9092
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="installNamespace is immutable"
@@ -140,11 +142,10 @@ type CatalogSource struct {
140142
// packageName is a reference to the name of the package to be installed
141143
// and is used to filter the content from catalogs.
142144
//
143-
// This field is required, immutable and follows the DNS label standard as defined in RFC
144-
// 1123, with a deviation in the maximum length being no more than 48
145-
// characters. This means that valid values:
146-
// - Contain no more than 48 characters
147-
// - Contain only lowercase alphanumeric characters or '-'
145+
// This field is required, immutable and follows the DNS subdomain name
146+
// standard as defined in [RFC 1123]. This means that valid entries:
147+
// - Contain no more than 253 characters
148+
// - Contain only lowercase alphanumeric characters, '-', or '.'
148149
// - Start with an alphanumeric character
149150
// - End with an alphanumeric character
150151
//
@@ -160,8 +161,10 @@ type CatalogSource struct {
160161
// - thisisareallylongpackagenamethatisgreaterthanthemaximumlength
161162
// - some.package
162163
//
163-
//+kubebuilder:validation:MaxLength:=48
164-
//+kubebuilder:validation:Pattern:=^[a-z0-9]+(-[a-z0-9]+)*$
164+
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
165+
//
166+
//+kubebuilder:validation:MaxLength:=253
167+
//+kubebuilder:validation:Pattern:=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
165168
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="packageName is immutable"
166169
PackageName string `json:"packageName"`
167170

@@ -259,10 +262,9 @@ type CatalogSource struct {
259262
//
260263
// When unspecified, upgrade edges across all channels will be used to identify valid automatic upgrade paths.
261264
//
262-
// This field follows the DNS subdomain name standard as defined in RFC
263-
// 1123, with a deviation in the maximum length being no more than 48
264-
// characters. This means that valid values:
265-
// - Contain no more than 48 characters
265+
// This field follows the DNS subdomain name standard as defined in [RFC
266+
// 1123]. This means that valid entries:
267+
// - Contain no more than 253 characters
266268
// - Contain only lowercase alphanumeric characters, '-', or '.'
267269
// - Start with an alphanumeric character
268270
// - End with an alphanumeric character
@@ -281,9 +283,13 @@ type CatalogSource struct {
281283
// - -some-channel
282284
// - some-channel-
283285
// - thisisareallylongchannelnamethatisgreaterthanthemaximumlength
286+
// - original_40
287+
// - --default-channel
288+
//
289+
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
284290
//
285-
//+kubebuilder:validation:MaxLength:=48
286-
//+kubebuilder:validation:Pattern:=^[a-z0-9]+([\.-][a-z0-9]+)*$
291+
//+kubebuilder:validation:MaxLength:=253
292+
//+kubebuilder:validation:Pattern:=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
287293
//+optional
288294
Channel string `json:"channel,omitempty"`
289295

@@ -329,8 +335,8 @@ type ServiceAccountReference struct {
329335
//
330336
// This ServiceAccount is expected to exist in the installNamespace.
331337
//
332-
// This field follows the DNS subdomain name standard as defined in RFC
333-
// 1123. This means that valid values:
338+
// This field follows the DNS subdomain name standard as defined in [RFC
339+
// 1123]. This means that valid values:
334340
// - Contain no more than 253 characters
335341
// - Contain only lowercase alphanumeric characters, '-', or '.'
336342
// - Start with an alphanumeric character
@@ -347,8 +353,10 @@ type ServiceAccountReference struct {
347353
// - -some-serviceaccount
348354
// - some-serviceaccount-
349355
//
356+
// [RFC 1123]: https://tools.ietf.org/html/rfc1123
357+
//
350358
//+kubebuilder:validation:MaxLength:=253
351-
//+kubebuilder:validation:Pattern:=^[a-z0-9]+([.|-][a-z0-9]+)*$
359+
//+kubebuilder:validation:Pattern:=^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
352360
//+kubebuilder:validation:XValidation:rule="self == oldSelf",message="name is immutable"
353361
Name string `json:"name"`
354362
}

config/base/crd/bases/olm.operatorframework.io_clusterextensions.yaml

+25-17
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ spec:
4747
applied to other Namespaces. This Namespace is expected to exist.
4848
4949
installNamespace is required, immutable, and follows the DNS label standard
50-
as defined in RFC 1123. This means that valid values:
50+
as defined in [RFC 1123]. This means that valid values:
5151
- Contain no more than 63 characters
5252
- Contain only lowercase alphanumeric characters or '-'
5353
- Start with an alphanumeric character
@@ -64,6 +64,8 @@ spec:
6464
- some-namespace-
6565
- thisisareallylongnamespacenamethatisgreaterthanthemaximumlength
6666
- some.namespace
67+
68+
[RFC 1123]: https://tools.ietf.org/html/rfc1123
6769
maxLength: 63
6870
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$
6971
type: string
@@ -133,8 +135,8 @@ spec:
133135
134136
This ServiceAccount is expected to exist in the installNamespace.
135137
136-
This field follows the DNS subdomain name standard as defined in RFC
137-
1123. This means that valid values:
138+
This field follows the DNS subdomain name standard as defined in [RFC
139+
1123]. This means that valid values:
138140
- Contain no more than 253 characters
139141
- Contain only lowercase alphanumeric characters, '-', or '.'
140142
- Start with an alphanumeric character
@@ -150,8 +152,10 @@ spec:
150152
Some examples of invalid values are:
151153
- -some-serviceaccount
152154
- some-serviceaccount-
155+
156+
[RFC 1123]: https://tools.ietf.org/html/rfc1123
153157
maxLength: 253
154-
pattern: ^[a-z0-9]+([.|-][a-z0-9]+)*$
158+
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
155159
type: string
156160
x-kubernetes-validations:
157161
- message: name is immutable
@@ -196,10 +200,9 @@ spec:
196200
197201
When unspecified, upgrade edges across all channels will be used to identify valid automatic upgrade paths.
198202
199-
This field follows the DNS subdomain name standard as defined in RFC
200-
1123, with a deviation in the maximum length being no more than 48
201-
characters. This means that valid values:
202-
- Contain no more than 48 characters
203+
This field follows the DNS subdomain name standard as defined in [RFC
204+
1123]. This means that valid entries:
205+
- Contain no more than 253 characters
203206
- Contain only lowercase alphanumeric characters, '-', or '.'
204207
- Start with an alphanumeric character
205208
- End with an alphanumeric character
@@ -218,19 +221,22 @@ spec:
218221
- -some-channel
219222
- some-channel-
220223
- thisisareallylongchannelnamethatisgreaterthanthemaximumlength
221-
maxLength: 48
222-
pattern: ^[a-z0-9]+([\.-][a-z0-9]+)*$
224+
- original_40
225+
- --default-channel
226+
227+
[RFC 1123]: https://tools.ietf.org/html/rfc1123
228+
maxLength: 253
229+
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
223230
type: string
224231
packageName:
225232
description: |-
226233
packageName is a reference to the name of the package to be installed
227234
and is used to filter the content from catalogs.
228235
229-
This field is required, immutable and follows the DNS label standard as defined in RFC
230-
1123, with a deviation in the maximum length being no more than 48
231-
characters. This means that valid values:
232-
- Contain no more than 48 characters
233-
- Contain only lowercase alphanumeric characters or '-'
236+
This field is required, immutable and follows the DNS subdomain name
237+
standard as defined in [RFC 1123]. This means that valid entries:
238+
- Contain no more than 253 characters
239+
- Contain only lowercase alphanumeric characters, '-', or '.'
234240
- Start with an alphanumeric character
235241
- End with an alphanumeric character
236242
@@ -245,8 +251,10 @@ spec:
245251
- some-package-
246252
- thisisareallylongpackagenamethatisgreaterthanthemaximumlength
247253
- some.package
248-
maxLength: 48
249-
pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
254+
255+
[RFC 1123]: https://tools.ietf.org/html/rfc1123
256+
maxLength: 253
257+
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
250258
type: string
251259
x-kubernetes-validations:
252260
- message: packageName is immutable

internal/controllers/clusterextension_admission_test.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func TestClusterExtensionSourceConfig(t *testing.T) {
7272
}
7373

7474
func TestClusterExtensionAdmissionPackageName(t *testing.T) {
75-
tooLongError := "spec.source.catalog.packageName: Too long: may not be longer than 48"
75+
tooLongError := "spec.source.catalog.packageName: Too long: may not be longer than 253"
7676
regexMismatchError := "spec.source.catalog.packageName in body should match"
7777

7878
testCases := []struct {
@@ -81,7 +81,7 @@ func TestClusterExtensionAdmissionPackageName(t *testing.T) {
8181
errMsg string
8282
}{
8383
{"no package name", "", regexMismatchError},
84-
{"long package name", "this-is-a-really-long-package-name-that-is-greater-than-48-characters", tooLongError},
84+
{"long package name", strings.Repeat("x", 254), tooLongError},
8585
{"leading digits with hypens", "0my-1package-9name", ""},
8686
{"trailing digits with hypens", "my0-package1-name9", ""},
8787
{"digits with hypens", "012-345-678-9", ""},
@@ -94,6 +94,10 @@ func TestClusterExtensionAdmissionPackageName(t *testing.T) {
9494
{"single hypen", "-", regexMismatchError},
9595
{"uppercase letters", "ABC-DEF-GHI-JKL", regexMismatchError},
9696
{"special characters", "my-$pecial-package-name", regexMismatchError},
97+
{"dot separated", "some.package", ""},
98+
{"underscore separated", "some_package", regexMismatchError},
99+
{"starts with dot", ".some.package", regexMismatchError},
100+
{"multiple sequential separators", "a.-b", regexMismatchError},
97101
}
98102

99103
t.Parallel()
@@ -123,6 +127,7 @@ func TestClusterExtensionAdmissionPackageName(t *testing.T) {
123127
})
124128
}
125129
}
130+
126131
func TestClusterExtensionAdmissionVersion(t *testing.T) {
127132
tooLongError := "spec.source.catalog.version: Too long: may not be longer than 64"
128133
regexMismatchError := "spec.source.catalog.version in body should match"
@@ -222,7 +227,7 @@ func TestClusterExtensionAdmissionVersion(t *testing.T) {
222227
}
223228

224229
func TestClusterExtensionAdmissionChannel(t *testing.T) {
225-
tooLongError := "spec.source.catalog.channel: Too long: may not be longer than 48"
230+
tooLongError := "spec.source.catalog.channel: Too long: may not be longer than 253"
226231
regexMismatchError := "spec.source.catalog.channel in body should match"
227232

228233
testCases := []struct {
@@ -234,7 +239,7 @@ func TestClusterExtensionAdmissionChannel(t *testing.T) {
234239
{"hypen-separated", "hyphenated-name", ""},
235240
{"dot-separated", "dotted.name", ""},
236241
{"includes version", "channel-has-version-1.0.1", ""},
237-
{"long channel name", "longname01234567890123456789012345678901234567890", tooLongError},
242+
{"long channel name", strings.Repeat("x", 254), tooLongError},
238243
{"spaces", "spaces spaces", regexMismatchError},
239244
{"capitalized", "Capitalized", regexMismatchError},
240245
{"camel case", "camelCase", regexMismatchError},
@@ -243,6 +248,8 @@ func TestClusterExtensionAdmissionChannel(t *testing.T) {
243248
{"ends with hyphen", "end-with-hyphen-", regexMismatchError},
244249
{"starts with period", ".start-with-period", regexMismatchError},
245250
{"ends with period", "end-with-period.", regexMismatchError},
251+
{"contains underscore", "some_thing", regexMismatchError},
252+
{"multiple sequential separators", "a.-b", regexMismatchError},
246253
}
247254

248255
t.Parallel()
@@ -350,6 +357,7 @@ func TestClusterExtensionAdmissionServiceAccount(t *testing.T) {
350357
{"ends with hyphen", "end-with-hyphen-", regexMismatchError},
351358
{"starts with period", ".start-with-period", regexMismatchError},
352359
{"ends with period", "end-with-period.", regexMismatchError},
360+
{"multiple sequential separators", "a.-b", regexMismatchError},
353361
}
354362

355363
t.Parallel()

0 commit comments

Comments
 (0)