1
16
17 package create
18
19 import (
20 "testing"
21
22 policyv1 "k8s.io/api/policy/v1"
23 apiequality "k8s.io/apimachinery/pkg/api/equality"
24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25 "k8s.io/apimachinery/pkg/util/intstr"
26 )
27
28 func TestCreatePdbValidation(t *testing.T) {
29 selectorOpts := "app=nginx"
30 podAmountNumber := "3"
31 podAmountPercent := "50%"
32
33 tests := map[string]struct {
34 options *PodDisruptionBudgetOpts
35 expected string
36 }{
37 "test-missing-name-param": {
38 options: &PodDisruptionBudgetOpts{
39 Selector: selectorOpts,
40 MinAvailable: podAmountNumber,
41 },
42 expected: "name must be specified",
43 },
44 "test-missing-selector-param": {
45 options: &PodDisruptionBudgetOpts{
46 Name: "my-pdb",
47 MinAvailable: podAmountNumber,
48 },
49 expected: "a selector must be specified",
50 },
51 "test-missing-max-unavailable-max-unavailable-param": {
52 options: &PodDisruptionBudgetOpts{
53 Name: "my-pdb",
54 Selector: selectorOpts,
55 },
56 expected: "one of min-available or max-unavailable must be specified",
57 },
58 "test-both-min-available-max-unavailable-param": {
59 options: &PodDisruptionBudgetOpts{
60 Name: "my-pdb",
61 Selector: selectorOpts,
62 MinAvailable: podAmountNumber,
63 MaxUnavailable: podAmountPercent,
64 },
65 expected: "min-available and max-unavailable cannot be both specified",
66 },
67 "test-invalid-min-available-format": {
68 options: &PodDisruptionBudgetOpts{
69 Name: "my-pdb",
70 Selector: selectorOpts,
71 MinAvailable: "10GB",
72 },
73 expected: "invalid format specified for min-available",
74 },
75 "test-invalid-max-unavailable-format": {
76 options: &PodDisruptionBudgetOpts{
77 Name: "my-pdb",
78 Selector: selectorOpts,
79 MaxUnavailable: "10GB",
80 },
81 expected: "invalid format specified for max-unavailable",
82 },
83 "test-valid-min-available-format": {
84 options: &PodDisruptionBudgetOpts{
85 Name: "my-pdb",
86 Selector: selectorOpts,
87 MaxUnavailable: podAmountNumber,
88 },
89 expected: "",
90 },
91 "test-valid-max-unavailable-format": {
92 options: &PodDisruptionBudgetOpts{
93 Name: "my-pdb",
94 Selector: selectorOpts,
95 MaxUnavailable: podAmountPercent,
96 },
97 expected: "",
98 },
99 }
100
101 for name, tc := range tests {
102 t.Run(name, func(t *testing.T) {
103
104 o := &PodDisruptionBudgetOpts{
105 Name: tc.options.Name,
106 Selector: tc.options.Selector,
107 MinAvailable: tc.options.MinAvailable,
108 MaxUnavailable: tc.options.MaxUnavailable,
109 }
110
111 err := o.Validate()
112 if err != nil && err.Error() != tc.expected {
113 t.Errorf("unexpected error: %v", err)
114 }
115 if tc.expected != "" && err == nil {
116 t.Errorf("expected error, got no error")
117 }
118 })
119 }
120 }
121
122 func TestCreatePdb(t *testing.T) {
123 selectorOpts := "app=nginx"
124 podAmountNumber := "3"
125 podAmountPercent := "50%"
126
127 selector, err := metav1.ParseToLabelSelector(selectorOpts)
128 if err != nil {
129 t.Errorf("unexpected error: %v", err)
130 }
131
132 minAvailableNumber := intstr.Parse(podAmountNumber)
133 minAvailablePercent := intstr.Parse(podAmountPercent)
134
135 maxUnavailableNumber := intstr.Parse(podAmountNumber)
136 maxUnavailablePercent := intstr.Parse(podAmountPercent)
137
138 tests := map[string]struct {
139 options *PodDisruptionBudgetOpts
140 expected *policyv1.PodDisruptionBudget
141 }{
142 "test-valid-min-available-pods-number": {
143 options: &PodDisruptionBudgetOpts{
144 Name: "my-pdb",
145 Selector: selectorOpts,
146 MinAvailable: podAmountNumber,
147 },
148 expected: &policyv1.PodDisruptionBudget{
149 TypeMeta: metav1.TypeMeta{
150 Kind: "PodDisruptionBudget",
151 APIVersion: "policy/v1",
152 },
153 ObjectMeta: metav1.ObjectMeta{
154 Name: "my-pdb",
155 },
156 Spec: policyv1.PodDisruptionBudgetSpec{
157 Selector: selector,
158 MinAvailable: &minAvailableNumber,
159 },
160 },
161 },
162 "test-valid-min-available-pods-percentage": {
163 options: &PodDisruptionBudgetOpts{
164 Name: "my-pdb",
165 Selector: selectorOpts,
166 MinAvailable: podAmountPercent,
167 },
168 expected: &policyv1.PodDisruptionBudget{
169 TypeMeta: metav1.TypeMeta{
170 Kind: "PodDisruptionBudget",
171 APIVersion: "policy/v1",
172 },
173 ObjectMeta: metav1.ObjectMeta{
174 Name: "my-pdb",
175 },
176 Spec: policyv1.PodDisruptionBudgetSpec{
177 Selector: selector,
178 MinAvailable: &minAvailablePercent,
179 },
180 },
181 },
182 "test-valid-max-unavailable-pods-number": {
183 options: &PodDisruptionBudgetOpts{
184 Name: "my-pdb",
185 Selector: selectorOpts,
186 MaxUnavailable: podAmountNumber,
187 },
188 expected: &policyv1.PodDisruptionBudget{
189 TypeMeta: metav1.TypeMeta{
190 Kind: "PodDisruptionBudget",
191 APIVersion: "policy/v1",
192 },
193 ObjectMeta: metav1.ObjectMeta{
194 Name: "my-pdb",
195 },
196 Spec: policyv1.PodDisruptionBudgetSpec{
197 Selector: selector,
198 MaxUnavailable: &maxUnavailableNumber,
199 },
200 },
201 },
202 "test-valid-max-unavailable-pods-percentage": {
203 options: &PodDisruptionBudgetOpts{
204 Name: "my-pdb",
205 Selector: selectorOpts,
206 MaxUnavailable: podAmountPercent,
207 },
208 expected: &policyv1.PodDisruptionBudget{
209 TypeMeta: metav1.TypeMeta{
210 Kind: "PodDisruptionBudget",
211 APIVersion: "policy/v1",
212 },
213 ObjectMeta: metav1.ObjectMeta{
214 Name: "my-pdb",
215 },
216 Spec: policyv1.PodDisruptionBudgetSpec{
217 Selector: selector,
218 MaxUnavailable: &maxUnavailablePercent,
219 },
220 },
221 },
222 }
223
224 for name, tc := range tests {
225 t.Run(name, func(t *testing.T) {
226
227 podDisruptionBudget, err := tc.options.createPodDisruptionBudgets()
228 if err != nil {
229 t.Errorf("unexpected error:\n%#v\n", err)
230 return
231 }
232 if !apiequality.Semantic.DeepEqual(podDisruptionBudget, tc.expected) {
233 t.Errorf("expected:\n%#v\ngot:\n%#v", tc.expected, podDisruptionBudget)
234 }
235 })
236 }
237 }
238
View as plain text