Skip to content

Commit 8bce29c

Browse files
committed
Update Version regex to support ranges
Fixes #345 Add positive and negative test cases. Signed-off-by: Todd Short <[email protected]>
1 parent 2114da6 commit 8bce29c

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

api/v1alpha1/operator_types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type OperatorSpec struct {
2929
PackageName string `json:"packageName"`
3030

3131
//+kubebuilder:validation:MaxLength:=64
32-
//+kubebuilder:validation:Pattern=^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$
32+
//+kubebuilder:validation:Pattern=`^(\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\^)\s*(v?(0|[1-9]\d*|[x|X|\*])(\.(0|[1-9]\d*|x|X|\*]))?(\.(0|[1-9]\d*|x|X|\*))?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?)\s*)((?:\s+|,\s*|\s*\|\|\s*)(=||!=|>|<|>=|=>|<=|=<|~|~>|\^)\s*(v?(0|[1-9]\d*|x|X|\*])(\.(0|[1-9]\d*|x|X|\*))?(\.(0|[1-9]\d*|x|X|\*]))?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?)\s*)*$`
3333
//+kubebuilder:Optional
3434
// Version is an optional semver constraint on the package version. If not specified, the latest version available of the package will be installed.
3535
// If specified, the specific version of the package will be installed so long as it is available in any of the content sources available.

config/crd/bases/operators.operatorframework.io_operators.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ spec:
5151
sources available. Examples: 1.2.3, 1.0.0-alpha, 1.0.0-rc.1 \n For
5252
more information on semver, please see https://semver.org/"
5353
maxLength: 64
54-
pattern: ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$
54+
pattern: ^(\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\^)\s*(v?(0|[1-9]\d*|[x|X|\*])(\.(0|[1-9]\d*|x|X|\*]))?(\.(0|[1-9]\d*|x|X|\*))?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?)\s*)((?:\s+|,\s*|\s*\|\|\s*)(=||!=|>|<|>=|=>|<=|=<|~|~>|\^)\s*(v?(0|[1-9]\d*|x|X|\*])(\.(0|[1-9]\d*|x|X|\*))?(\.(0|[1-9]\d*|x|X|\*]))?(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?)\s*)*$
5555
type: string
5656
required:
5757
- packageName

internal/controllers/admission_test.go

+57-1
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ var _ = Describe("Operator Spec Validations", func() {
6161
"1.2.3-pre+bad_metadata",
6262
"1.2.-3",
6363
".1.2.3",
64+
"<<1.2.3",
65+
">>1.2.3",
66+
">~1.2.3",
67+
"==1.2.3",
68+
"=!1.2.3",
69+
"1.Y",
70+
">1.2.3 && <2.3.4",
71+
">1.2.3;<2.3.4",
72+
"1.2.3 - 2.3.4",
6473
}
6574
for _, invalidSemver := range invalidSemvers {
6675
err := cl.Create(ctx, operator(operatorsv1alpha1.OperatorSpec{
@@ -69,7 +78,54 @@ var _ = Describe("Operator Spec Validations", func() {
6978
}))
7079

7180
Expect(err).To(HaveOccurred(), "expected error for invalid semver %q", invalidSemver)
72-
Expect(err.Error()).To(ContainSubstring("spec.version in body should match '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-(0|[1-9]\\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+([0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*))?$'"))
81+
// Don't need to include the whole regex, this should be enough to match the MasterMinds regex
82+
Expect(err.Error()).To(ContainSubstring("spec.version in body should match '^(\\s*(=||!=|>|<|>=|=>|<=|=<|~|~>|\\^)"))
83+
}
84+
})
85+
It("should pass if a valid semver range given", func() {
86+
validSemvers := []string{
87+
">=1.2.3",
88+
"=>1.2.3",
89+
">= 1.2.3",
90+
">=v1.2.3",
91+
">= v1.2.3",
92+
"<=1.2.3",
93+
"=<1.2.3",
94+
"=1.2.3",
95+
"!=1.2.3",
96+
"<1.2.3",
97+
">1.2.3",
98+
"~1.2.2",
99+
"~>1.2.3",
100+
"^1.2.3",
101+
"1.2.3",
102+
"v1.2.3",
103+
"1.x",
104+
"1.X",
105+
"1.*",
106+
"1.2.x",
107+
"1.2.X",
108+
"1.2.*",
109+
">=1.2.3 <2.3.4",
110+
">=1.2.3,<2.3.4",
111+
">=1.2.3, <2.3.4",
112+
"<1.2.3||>2.3.4",
113+
"<1.2.3|| >2.3.4",
114+
"<1.2.3 ||>2.3.4",
115+
"<1.2.3 || >2.3.4",
116+
">1.0.0,<1.2.3 || >2.1.0",
117+
"<1.2.3-abc >2.3.4-def",
118+
"<1.2.3-abc+def >2.3.4-ghi+jkl",
119+
}
120+
for _, validSemver := range validSemvers {
121+
op := operator(operatorsv1alpha1.OperatorSpec{
122+
PackageName: "package",
123+
Version: validSemver,
124+
})
125+
err := cl.Create(ctx, op)
126+
Expect(err).NotTo(HaveOccurred(), "expected success for semver range '%q': %w", validSemver, err)
127+
err = cl.Delete(ctx, op)
128+
Expect(err).NotTo(HaveOccurred(), "unexpected error deleting valid semver '%q': %w", validSemver, err)
73129
}
74130
})
75131
It("should fail if an invalid channel name is given", func() {

0 commit comments

Comments
 (0)