@@ -23,6 +23,7 @@ import (
23
23
"k8s.io/apimachinery/pkg/api/errors"
24
24
"k8s.io/apimachinery/pkg/api/resource"
25
25
"k8s.io/apimachinery/pkg/util/intstr"
26
+ "k8s.io/apimachinery/pkg/util/validation/field"
26
27
"k8s.io/utils/ptr"
27
28
)
28
29
@@ -92,85 +93,6 @@ var _ = Describe("EtcdCluster Webhook", func() {
92
93
Expect (err ).To (Succeed ())
93
94
Expect (w ).To (BeEmpty ())
94
95
})
95
- It ("Should admit enabled empty PDB" , func () {
96
- etcdCluster := & EtcdCluster {
97
- Spec : EtcdClusterSpec {
98
- Replicas : ptr .To (int32 (1 )),
99
- PodDisruptionBudget : & EmbeddedPodDisruptionBudget {},
100
- },
101
- }
102
- w , err := etcdCluster .ValidateCreate ()
103
- Expect (err ).To (Succeed ())
104
- Expect (w ).To (BeEmpty ())
105
- })
106
- It ("Should reject if negative spec.podDisruptionBudget.minAvailable" , func () {
107
- etcdCluster := & EtcdCluster {
108
- Spec : EtcdClusterSpec {
109
- Replicas : ptr .To (int32 (1 )),
110
- PodDisruptionBudget : & EmbeddedPodDisruptionBudget {
111
- Spec : PodDisruptionBudgetSpec {
112
- MinAvailable : ptr .To (intstr .FromInt32 (int32 (- 1 ))),
113
- },
114
- },
115
- },
116
- }
117
- _ , err := etcdCluster .ValidateCreate ()
118
- if Expect (err ).To (HaveOccurred ()) {
119
- statusErr := err .(* errors.StatusError )
120
- Expect (statusErr .ErrStatus .Message ).To (ContainSubstring ("value cannot be less than zero" ))
121
- }
122
- })
123
- It ("Should reject if negative spec.podDisruptionBudget.maxUnavailable" , func () {
124
- etcdCluster := & EtcdCluster {
125
- Spec : EtcdClusterSpec {
126
- Replicas : ptr .To (int32 (1 )),
127
- PodDisruptionBudget : & EmbeddedPodDisruptionBudget {
128
- Spec : PodDisruptionBudgetSpec {
129
- MaxUnavailable : ptr .To (intstr .FromInt32 (int32 (- 1 ))),
130
- },
131
- },
132
- },
133
- }
134
- _ , err := etcdCluster .ValidateCreate ()
135
- if Expect (err ).To (HaveOccurred ()) {
136
- statusErr := err .(* errors.StatusError )
137
- Expect (statusErr .ErrStatus .Message ).To (ContainSubstring ("maxUnavailable: Invalid value: -1: value cannot be less than zero" ))
138
- }
139
- })
140
- It ("Should reject if min available field larger than replicas" , func () {
141
- etcdCluster := & EtcdCluster {
142
- Spec : EtcdClusterSpec {
143
- Replicas : ptr .To (int32 (1 )),
144
- PodDisruptionBudget : & EmbeddedPodDisruptionBudget {
145
- Spec : PodDisruptionBudgetSpec {
146
- MinAvailable : ptr .To (intstr .FromInt32 (int32 (2 ))),
147
- },
148
- },
149
- },
150
- }
151
- _ , err := etcdCluster .ValidateCreate ()
152
- if Expect (err ).To (HaveOccurred ()) {
153
- statusErr := err .(* errors.StatusError )
154
- Expect (statusErr .ErrStatus .Message ).To (ContainSubstring ("minAvailable: Invalid value: 2: value cannot be larger than number of replicas" ))
155
- }
156
- })
157
- It ("Should reject if max unavailable field larger than replicas" , func () {
158
- etcdCluster := & EtcdCluster {
159
- Spec : EtcdClusterSpec {
160
- Replicas : ptr .To (int32 (1 )),
161
- PodDisruptionBudget : & EmbeddedPodDisruptionBudget {
162
- Spec : PodDisruptionBudgetSpec {
163
- MaxUnavailable : ptr .To (intstr .FromInt32 (int32 (2 ))),
164
- },
165
- },
166
- },
167
- }
168
- _ , err := etcdCluster .ValidateCreate ()
169
- if Expect (err ).To (HaveOccurred ()) {
170
- statusErr := err .(* errors.StatusError )
171
- Expect (statusErr .ErrStatus .Message ).To (ContainSubstring ("maxUnavailable: Invalid value: 2: value cannot be larger than number of replicas" ))
172
- }
173
- })
174
96
})
175
97
176
98
Context ("When updating EtcdCluster under Validating Webhook" , func () {
@@ -211,4 +133,111 @@ var _ = Describe("EtcdCluster Webhook", func() {
211
133
Expect (err ).To (Succeed ())
212
134
})
213
135
})
136
+
137
+ Context ("Validate PDB" , func () {
138
+ etcdCluster := & EtcdCluster {
139
+ Spec : EtcdClusterSpec {
140
+ Replicas : ptr .To (int32 (3 )),
141
+ PodDisruptionBudget : & EmbeddedPodDisruptionBudget {},
142
+ },
143
+ }
144
+ It ("Should admit enabled empty PDB" , func () {
145
+ localCluster := etcdCluster .DeepCopy ()
146
+ w , err := localCluster .validatePdb ()
147
+ Expect (err ).To (BeNil ())
148
+ Expect (w ).To (BeEmpty ())
149
+ })
150
+ It ("Should reject if negative spec.podDisruptionBudget.minAvailable" , func () {
151
+ localCluster := etcdCluster .DeepCopy ()
152
+ localCluster .Spec .PodDisruptionBudget .Spec .MinAvailable = ptr .To (intstr .FromInt32 (int32 (- 1 )))
153
+ _ , err := localCluster .validatePdb ()
154
+ if Expect (err ).NotTo (BeNil ()) {
155
+ expectedFieldErr := field .Invalid (
156
+ field .NewPath ("spec" , "podDisruptionBudget" , "minAvailable" ),
157
+ - 1 ,
158
+ "value cannot be less than zero" ,
159
+ )
160
+ if Expect (err ).To (HaveLen (1 )) {
161
+ Expect (* (err [0 ])).To (Equal (* expectedFieldErr ))
162
+ }
163
+ }
164
+ })
165
+ It ("Should reject if negative spec.podDisruptionBudget.maxUnavailable" , func () {
166
+ localCluster := etcdCluster .DeepCopy ()
167
+ localCluster .Spec .PodDisruptionBudget .Spec .MaxUnavailable = ptr .To (intstr .FromInt32 (int32 (- 1 )))
168
+ _ , err := localCluster .validatePdb ()
169
+ if Expect (err ).NotTo (BeNil ()) {
170
+ expectedFieldErr := field .Invalid (
171
+ field .NewPath ("spec" , "podDisruptionBudget" , "maxUnavailable" ),
172
+ - 1 ,
173
+ "value cannot be less than zero" ,
174
+ )
175
+ if Expect (err ).To (HaveLen (1 )) {
176
+ Expect (* (err [0 ])).To (Equal (* expectedFieldErr ))
177
+ }
178
+ }
179
+ })
180
+ It ("Should reject if min available field larger than replicas" , func () {
181
+ localCluster := etcdCluster .DeepCopy ()
182
+ localCluster .Spec .Replicas = ptr .To (int32 (1 ))
183
+ localCluster .Spec .PodDisruptionBudget .Spec .MinAvailable = ptr .To (intstr .FromInt32 (int32 (2 )))
184
+ _ , err := localCluster .validatePdb ()
185
+ if Expect (err ).NotTo (BeNil ()) {
186
+ expectedFieldErr := field .Invalid (
187
+ field .NewPath ("spec" , "podDisruptionBudget" , "minAvailable" ),
188
+ 2 ,
189
+ "value cannot be larger than number of replicas" ,
190
+ )
191
+ if Expect (err ).To (HaveLen (1 )) {
192
+ Expect (* (err [0 ])).To (Equal (* expectedFieldErr ))
193
+ }
194
+ }
195
+ })
196
+ It ("Should reject if max unavailable field larger than replicas" , func () {
197
+ localCluster := etcdCluster .DeepCopy ()
198
+ localCluster .Spec .Replicas = ptr .To (int32 (1 ))
199
+ localCluster .Spec .PodDisruptionBudget .Spec .MaxUnavailable = ptr .To (intstr .FromInt32 (int32 (2 )))
200
+ _ , err := localCluster .validatePdb ()
201
+ if Expect (err ).NotTo (BeNil ()) {
202
+ expectedFieldErr := field .Invalid (
203
+ field .NewPath ("spec" , "podDisruptionBudget" , "maxUnavailable" ),
204
+ 2 ,
205
+ "value cannot be larger than number of replicas" ,
206
+ )
207
+ if Expect (err ).To (HaveLen (1 )) {
208
+ Expect (* (err [0 ])).To (Equal (* expectedFieldErr ))
209
+ }
210
+ }
211
+ })
212
+ It ("should accept correct percentage value for minAvailable" , func () {
213
+ localCluster := etcdCluster .DeepCopy ()
214
+ localCluster .Spec .Replicas = ptr .To (int32 (4 ))
215
+ localCluster .Spec .PodDisruptionBudget .Spec .MinAvailable = ptr .To (intstr .FromString ("50%" ))
216
+ warnings , err := localCluster .validatePdb ()
217
+ Expect (err ).To (BeNil ())
218
+ Expect (warnings ).To (ContainElement ("current number of spec.podDisruptionBudget.minAvailable can lead to loss of quorum" ))
219
+ })
220
+ It ("should accept correct percentage value for maxUnavailable" , func () {
221
+ localCluster := etcdCluster .DeepCopy ()
222
+ localCluster .Spec .PodDisruptionBudget .Spec .MaxUnavailable = ptr .To (intstr .FromString ("50%" ))
223
+ warnings , err := localCluster .validatePdb ()
224
+ Expect (err ).To (BeNil ())
225
+ Expect (warnings ).To (ContainElement ("current number of spec.podDisruptionBudget.maxUnavailable can lead to loss of quorum" ))
226
+ })
227
+ It ("Should reject incorrect value for maxUnavailable" , func () {
228
+ localCluster := etcdCluster .DeepCopy ()
229
+ localCluster .Spec .PodDisruptionBudget .Spec .MaxUnavailable = ptr .To (intstr .FromString ("50$" ))
230
+ _ , err := localCluster .validatePdb ()
231
+ if Expect (err ).NotTo (BeNil ()) {
232
+ expectedFieldErr := field .Invalid (
233
+ field .NewPath ("spec" , "podDisruptionBudget" , "maxUnavailable" ),
234
+ "50$" ,
235
+ "invalid percentage value" ,
236
+ )
237
+ if Expect (err ).To (HaveLen (1 )) {
238
+ Expect (* (err [0 ])).To (Equal (* expectedFieldErr ))
239
+ }
240
+ }
241
+ })
242
+ })
214
243
})
0 commit comments