Skip to content

Commit 0faf118

Browse files
authored
ClusterExtensionRevision .spec.revision must be positive (#2231)
Added the validation rules and the unit tests.
1 parent c6a2fed commit 0faf118

File tree

5 files changed

+69
-9
lines changed

5 files changed

+69
-9
lines changed

api/v1/clusterextensionrevision_types.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,12 @@ type ClusterExtensionRevisionSpec struct {
4949
// +kubebuilder:validation:Enum=Active;Paused;Archived
5050
// +kubebuilder:validation:XValidation:rule="oldSelf == 'Active' || oldSelf == 'Paused' || oldSelf == 'Archived' && oldSelf == self", message="can not un-archive"
5151
LifecycleState ClusterExtensionRevisionLifecycleState `json:"lifecycleState,omitempty"`
52-
// Revision number orders changes over time, must always be previous revision +1.
52+
// Revision is a sequence number representing a specific revision of the ClusterExtension instance.
53+
// Must be positive. Each ClusterExtensionRevision of the same parent ClusterExtension needs to have
54+
// a unique value assigned. It is immutable after creation. The new revision number must always be previous revision +1.
5355
//
5456
// +kubebuilder:validation:Required
57+
// +kubebuilder:validation:Minimum:=1
5558
// +kubebuilder:validation:XValidation:rule="self == oldSelf", message="revision is immutable"
5659
Revision int64 `json:"revision"`
5760
// Phases are groups of objects that will be applied at the same time.

api/v1/clusterextensionrevision_types_test.go

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) {
2929
},
3030
"phases may be initially empty": {
3131
spec: ClusterExtensionRevisionSpec{
32-
Phases: []ClusterExtensionRevisionPhase{},
32+
Revision: 1,
33+
Phases: []ClusterExtensionRevisionPhase{},
3334
},
3435
updateFunc: func(cer *ClusterExtensionRevision) {
3536
cer.Spec.Phases = []ClusterExtensionRevisionPhase{
@@ -42,7 +43,9 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) {
4243
allowed: true,
4344
},
4445
"phases may be initially unset": {
45-
spec: ClusterExtensionRevisionSpec{},
46+
spec: ClusterExtensionRevisionSpec{
47+
Revision: 1,
48+
},
4649
updateFunc: func(cer *ClusterExtensionRevision) {
4750
cer.Spec.Phases = []ClusterExtensionRevisionPhase{
4851
{
@@ -55,6 +58,7 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) {
5558
},
5659
"phases are immutable if not empty": {
5760
spec: ClusterExtensionRevisionSpec{
61+
Revision: 1,
5862
Phases: []ClusterExtensionRevisionPhase{
5963
{
6064
Name: "foo",
@@ -92,3 +96,47 @@ func TestClusterExtensionRevisionImmutability(t *testing.T) {
9296
})
9397
}
9498
}
99+
100+
func TestClusterExtensionRevisionValidity(t *testing.T) {
101+
c := newClient(t)
102+
ctx := context.Background()
103+
i := 0
104+
for name, tc := range map[string]struct {
105+
spec ClusterExtensionRevisionSpec
106+
valid bool
107+
}{
108+
"revision cannot be negative": {
109+
spec: ClusterExtensionRevisionSpec{
110+
Revision: -1,
111+
},
112+
valid: false,
113+
},
114+
"revision cannot be zero": {
115+
spec: ClusterExtensionRevisionSpec{},
116+
valid: false,
117+
},
118+
"revision must be positive": {
119+
spec: ClusterExtensionRevisionSpec{
120+
Revision: 1,
121+
},
122+
valid: true,
123+
},
124+
} {
125+
t.Run(name, func(t *testing.T) {
126+
cer := &ClusterExtensionRevision{
127+
ObjectMeta: metav1.ObjectMeta{
128+
Name: fmt.Sprintf("bar%d", i),
129+
},
130+
Spec: tc.spec,
131+
}
132+
i = i + 1
133+
err := c.Create(ctx, cer)
134+
if tc.valid && err != nil {
135+
t.Fatal("expected create to succeed, but got:", err)
136+
}
137+
if !tc.valid && !errors.IsInvalid(err) {
138+
t.Fatal("expected create to fail due to invalid payload, but got:", err)
139+
}
140+
})
141+
}
142+
}

helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensionrevisions.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,12 @@ spec:
122122
- message: previous is immutable
123123
rule: self == oldSelf
124124
revision:
125-
description: Revision number orders changes over time, must always
126-
be previous revision +1.
125+
description: |-
126+
Revision is a sequence number representing a specific revision of the ClusterExtension instance.
127+
Must be positive. Each ClusterExtensionRevision of the same parent ClusterExtension needs to have
128+
a unique value assigned. It is immutable after creation. The new revision number must always be previous revision +1.
127129
format: int64
130+
minimum: 1
128131
type: integer
129132
x-kubernetes-validations:
130133
- message: revision is immutable

manifests/experimental-e2e.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,9 +713,12 @@ spec:
713713
- message: previous is immutable
714714
rule: self == oldSelf
715715
revision:
716-
description: Revision number orders changes over time, must always
717-
be previous revision +1.
716+
description: |-
717+
Revision is a sequence number representing a specific revision of the ClusterExtension instance.
718+
Must be positive. Each ClusterExtensionRevision of the same parent ClusterExtension needs to have
719+
a unique value assigned. It is immutable after creation. The new revision number must always be previous revision +1.
718720
format: int64
721+
minimum: 1
719722
type: integer
720723
x-kubernetes-validations:
721724
- message: revision is immutable

manifests/experimental.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,12 @@ spec:
678678
- message: previous is immutable
679679
rule: self == oldSelf
680680
revision:
681-
description: Revision number orders changes over time, must always
682-
be previous revision +1.
681+
description: |-
682+
Revision is a sequence number representing a specific revision of the ClusterExtension instance.
683+
Must be positive. Each ClusterExtensionRevision of the same parent ClusterExtension needs to have
684+
a unique value assigned. It is immutable after creation. The new revision number must always be previous revision +1.
683685
format: int64
686+
minimum: 1
684687
type: integer
685688
x-kubernetes-validations:
686689
- message: revision is immutable

0 commit comments

Comments
 (0)