Skip to content

Commit ea0378a

Browse files
committed
add unit test
1 parent 937120b commit ea0378a

File tree

3 files changed

+173
-9
lines changed

3 files changed

+173
-9
lines changed

pkg/controller/ps/controller_test.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,24 @@ import (
2828
gs "github.com/onsi/gomega/gstruct"
2929
appsv1 "k8s.io/api/apps/v1"
3030
corev1 "k8s.io/api/core/v1"
31+
policyv1 "k8s.io/api/policy/v1"
3132
storagev1 "k8s.io/api/storage/v1"
3233
k8serrors "k8s.io/apimachinery/pkg/api/errors"
3334
"k8s.io/apimachinery/pkg/api/resource"
3435
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3536
"k8s.io/apimachinery/pkg/labels"
3637
"k8s.io/apimachinery/pkg/types"
38+
"k8s.io/apimachinery/pkg/util/intstr"
3739
ctrl "sigs.k8s.io/controller-runtime"
3840
"sigs.k8s.io/controller-runtime/pkg/client"
3941

42+
apiv1alpha1 "github.com/percona/percona-server-mysql-operator/api/v1alpha1"
4043
psv1alpha1 "github.com/percona/percona-server-mysql-operator/api/v1alpha1"
44+
"github.com/percona/percona-server-mysql-operator/pkg/haproxy"
45+
"github.com/percona/percona-server-mysql-operator/pkg/innodbcluster"
4146
"github.com/percona/percona-server-mysql-operator/pkg/mysql"
4247
"github.com/percona/percona-server-mysql-operator/pkg/naming"
48+
"github.com/percona/percona-server-mysql-operator/pkg/orchestrator"
4349
)
4450

4551
var _ = Describe("Sidecars", Ordered, func() {
@@ -306,6 +312,162 @@ var _ = Describe("Unsafe configurations", Ordered, func() {
306312
})
307313
})
308314

315+
var _ = Describe("PodDisruptionBudget", Ordered, func() {
316+
ctx := context.Background()
317+
318+
crName := "pdb"
319+
ns := crName
320+
crNamespacedName := types.NamespacedName{Name: crName, Namespace: ns}
321+
322+
namespace := &corev1.Namespace{
323+
ObjectMeta: metav1.ObjectMeta{
324+
Name: crName,
325+
Namespace: ns,
326+
},
327+
}
328+
329+
var r *PerconaServerMySQLReconciler
330+
331+
BeforeAll(func() {
332+
By("Creating the Namespace to perform the tests")
333+
err := k8sClient.Create(ctx, namespace)
334+
Expect(err).To(Not(HaveOccurred()))
335+
})
336+
337+
AfterAll(func() {
338+
By("Deleting the Namespace to perform the tests")
339+
_ = k8sClient.Delete(ctx, namespace)
340+
})
341+
342+
Context("Check default cluster", Ordered, func() {
343+
cr, err := readDefaultCR(crName, ns)
344+
It("should prepare reconciler", func() {
345+
r = reconciler()
346+
Expect(err).To(Succeed())
347+
cliCmd, err := getFakeClient(cr, innodbcluster.ClusterStatusOK, []innodbcluster.MemberState{
348+
innodbcluster.MemberStateOnline,
349+
innodbcluster.MemberStateOnline,
350+
innodbcluster.MemberStateOnline,
351+
}, false, true)
352+
Expect(err).To(Succeed())
353+
r.ClientCmd = cliCmd
354+
const operatorPass = "test"
355+
secret := &corev1.Secret{
356+
ObjectMeta: metav1.ObjectMeta{
357+
Name: cr.InternalSecretName(),
358+
Namespace: cr.Namespace,
359+
},
360+
Data: map[string][]byte{
361+
string(apiv1alpha1.UserOperator): []byte(operatorPass),
362+
},
363+
}
364+
Expect(k8sClient.Create(ctx, secret)).Should(Succeed())
365+
})
366+
367+
It("should create cr.yaml", func() {
368+
cr.Spec.MySQL.ClusterType = psv1alpha1.ClusterTypeAsync
369+
cr.Spec.Unsafe.Orchestrator = true
370+
cr.Spec.Unsafe.Proxy = true
371+
cr.Spec.MySQL.PodDisruptionBudget = &psv1alpha1.PodDisruptionBudgetSpec{
372+
MaxUnavailable: &intstr.IntOrString{
373+
Type: intstr.Int,
374+
IntVal: 20,
375+
},
376+
}
377+
cr.Spec.Proxy.Router.Enabled = false
378+
cr.Spec.Proxy.HAProxy.Enabled = true
379+
cr.Spec.Proxy.HAProxy.PodDisruptionBudget = &psv1alpha1.PodDisruptionBudgetSpec{
380+
MinAvailable: &intstr.IntOrString{
381+
Type: intstr.Int,
382+
IntVal: 12,
383+
},
384+
}
385+
cr.Spec.Orchestrator.Enabled = true
386+
cr.Spec.Orchestrator.PodDisruptionBudget = &psv1alpha1.PodDisruptionBudgetSpec{
387+
MaxUnavailable: &intstr.IntOrString{
388+
Type: intstr.Int,
389+
IntVal: 11,
390+
},
391+
}
392+
Expect(k8sClient.Create(ctx, cr)).Should(Succeed())
393+
})
394+
395+
It("should create MySQL pods", func() {
396+
for _, pod := range makeFakeReadyPods(cr, 3, "mysql") {
397+
status := pod.(*corev1.Pod).Status
398+
Expect(k8sClient.Create(ctx, pod)).Should(Succeed())
399+
p := new(corev1.Pod)
400+
Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(pod), p)).Should(Succeed())
401+
p.Status = status
402+
Expect(k8sClient.Status().Update(ctx, p)).Should(Succeed())
403+
}
404+
})
405+
406+
When("HAProxy is enabled", Ordered, func() {
407+
It("should reconcile", func() {
408+
_, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: crNamespacedName})
409+
Expect(err).NotTo(HaveOccurred())
410+
})
411+
It("should check PodDisruptionBudget for MySQL", func() {
412+
pdb := &policyv1.PodDisruptionBudget{
413+
ObjectMeta: metav1.ObjectMeta{
414+
Name: cr.Name + "-mysql",
415+
Namespace: cr.Namespace,
416+
},
417+
}
418+
419+
Eventually(func() bool {
420+
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(pdb), pdb)
421+
return err == nil
422+
}, time.Second*15, time.Millisecond*250).Should(BeTrue())
423+
424+
Expect(pdb.Labels).To(Equal(mysql.MatchLabels(cr)))
425+
Expect(pdb.Spec.Selector.MatchLabels).To(Equal(mysql.MatchLabels(cr)))
426+
427+
Expect(pdb.Spec.MaxUnavailable.IntVal).To(Equal(int32(20)))
428+
})
429+
430+
It("should check PodDisruptionBudget for HAProxy", func() {
431+
pdb := &policyv1.PodDisruptionBudget{
432+
ObjectMeta: metav1.ObjectMeta{
433+
Name: cr.Name + "-haproxy",
434+
Namespace: cr.Namespace,
435+
},
436+
}
437+
438+
Eventually(func() bool {
439+
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(pdb), pdb)
440+
return err == nil
441+
}, time.Second*15, time.Millisecond*250).Should(BeTrue())
442+
443+
Expect(pdb.Labels).To(Equal(haproxy.MatchLabels(cr)))
444+
Expect(pdb.Spec.Selector.MatchLabels).To(Equal(haproxy.MatchLabels(cr)))
445+
446+
Expect(pdb.Spec.MinAvailable.IntVal).To(Equal(int32(12)))
447+
})
448+
449+
It("should check PodDisruptionBudget for Orchestrator", func() {
450+
pdb := &policyv1.PodDisruptionBudget{
451+
ObjectMeta: metav1.ObjectMeta{
452+
Name: cr.Name + "-orchestrator",
453+
Namespace: cr.Namespace,
454+
},
455+
}
456+
457+
Eventually(func() bool {
458+
err := k8sClient.Get(ctx, client.ObjectKeyFromObject(pdb), pdb)
459+
return err == nil
460+
}, time.Second*15, time.Millisecond*250).Should(BeTrue())
461+
462+
Expect(pdb.Labels).To(Equal(orchestrator.MatchLabels(cr)))
463+
Expect(pdb.Spec.Selector.MatchLabels).To(Equal(orchestrator.MatchLabels(cr)))
464+
465+
Expect(pdb.Spec.MaxUnavailable.IntVal).To(Equal(int32(11)))
466+
})
467+
})
468+
})
469+
})
470+
309471
var _ = Describe("Reconcile HAProxy when async cluster type", Ordered, func() {
310472
ctx := context.Background()
311473

pkg/controller/ps/status_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,7 @@ func TestReconcileStatusHAProxyGR(t *testing.T) {
641641
t.Run(tt.name, func(t *testing.T) {
642642
cr := tt.cr.DeepCopy()
643643
cb := fake.NewClientBuilder().WithScheme(scheme).WithObjects(cr).WithStatusSubresource(cr).WithObjects(tt.objects...).WithStatusSubresource(tt.objects...)
644-
cliCmd, err := getFakeClient(cr, tt.innodbClusterState, tt.mysqlMemberStates, tt.noMetadataDB)
644+
cliCmd, err := getFakeClient(cr, tt.innodbClusterState, tt.mysqlMemberStates, tt.noMetadataDB, false)
645645
if err != nil {
646646
t.Fatal(err)
647647
}
@@ -910,7 +910,7 @@ func TestReconcileStatusRouterGR(t *testing.T) {
910910
t.Run(tt.name, func(t *testing.T) {
911911
cr := tt.cr.DeepCopy()
912912
cb := fake.NewClientBuilder().WithScheme(scheme).WithObjects(cr).WithStatusSubresource(cr).WithObjects(tt.objects...).WithStatusSubresource(tt.objects...)
913-
cliCmd, err := getFakeClient(cr, tt.innodbClusterState, tt.mysqlMemberStates, tt.noMetadataDB)
913+
cliCmd, err := getFakeClient(cr, tt.innodbClusterState, tt.mysqlMemberStates, tt.noMetadataDB, false)
914914
if err != nil {
915915
t.Fatal(err)
916916
}
@@ -1016,8 +1016,9 @@ func TestReconcileErrorStatus(t *testing.T) {
10161016
}
10171017

10181018
type fakeClient struct {
1019-
scripts []fakeClientScript
1020-
execCount int
1019+
scripts []fakeClientScript
1020+
execCount int
1021+
disableCheck bool
10211022
}
10221023

10231024
// Exec increments the internal counter `execCount`.
@@ -1029,7 +1030,7 @@ func (c *fakeClient) Exec(_ context.Context, _ *corev1.Pod, _ string, command []
10291030
if c.execCount >= len(c.scripts) {
10301031
return errors.Errorf("unexpected exec call")
10311032
}
1032-
if !reflect.DeepEqual(c.scripts[c.execCount].cmd, command) {
1033+
if !reflect.DeepEqual(c.scripts[c.execCount].cmd, command) && !c.disableCheck {
10331034
return errors.Errorf("expected command: %v; got %v", c.scripts[c.execCount].cmd, command)
10341035
}
10351036
var in []byte
@@ -1040,7 +1041,7 @@ func (c *fakeClient) Exec(_ context.Context, _ *corev1.Pod, _ string, command []
10401041
return err
10411042
}
10421043
}
1043-
if !reflect.DeepEqual(in, c.scripts[c.execCount].stdin) {
1044+
if !reflect.DeepEqual(in, c.scripts[c.execCount].stdin) && !c.disableCheck {
10441045
return errors.Errorf("expected stdin: %v; got %v", c.scripts[c.execCount].stdin, in)
10451046
}
10461047
_, err = stdout.Write(c.scripts[c.execCount].stdout)
@@ -1080,7 +1081,7 @@ func getFakeClient(
10801081
cr *apiv1alpha1.PerconaServerMySQL,
10811082
innodbClusterStatus innodbcluster.ClusterStatus,
10821083
mysqlMemberStates []innodbcluster.MemberState,
1083-
noMetadataDB bool,
1084+
noMetadataDB bool, disableCheck bool,
10841085
) (clientcmd.Client, error) {
10851086
queryScript := func(query string, out any) fakeClientScript {
10861087
buf := new(bytes.Buffer)
@@ -1174,7 +1175,8 @@ func getFakeClient(
11741175
})
11751176

11761177
return &fakeClient{
1177-
scripts: scripts,
1178+
scripts: scripts,
1179+
disableCheck: disableCheck,
11781180
}, nil
11791181
}
11801182

pkg/k8s/pdb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
func podDisruptionBudget(cr *apiv1alpha1.PerconaServerMySQL, spec *apiv1alpha1.PodDisruptionBudgetSpec, labels map[string]string) *policyv1.PodDisruptionBudget {
1212
return &policyv1.PodDisruptionBudget{
1313
ObjectMeta: metav1.ObjectMeta{
14-
Name: cr.Name + "-" + labels[naming.LabelComponent],
14+
Name: cr.Name + "-" + labels[naming.LabelName],
1515
Namespace: cr.Namespace,
1616
Labels: labels,
1717
},

0 commit comments

Comments
 (0)