github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/sync_upgrade_policy_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package configuration
    21  
    22  import (
    23  	. "github.com/onsi/ginkgo/v2"
    24  	. "github.com/onsi/gomega"
    25  
    26  	"github.com/golang/mock/gomock"
    27  	corev1 "k8s.io/api/core/v1"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/runtime"
    30  
    31  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    32  	cfgproto "github.com/1aal/kubeblocks/pkg/configuration/proto"
    33  	mock_proto "github.com/1aal/kubeblocks/pkg/configuration/proto/mocks"
    34  	testutil "github.com/1aal/kubeblocks/pkg/testutil/k8s"
    35  )
    36  
    37  var operatorSyncPolicy = &syncPolicy{}
    38  
    39  var _ = Describe("Reconfigure OperatorSyncPolicy", func() {
    40  
    41  	var (
    42  		k8sMockClient     *testutil.K8sClientMockHelper
    43  		reconfigureClient *mock_proto.MockReconfigureClient
    44  	)
    45  
    46  	BeforeEach(func() {
    47  		k8sMockClient = testutil.NewK8sMockClient()
    48  		reconfigureClient = mock_proto.NewMockReconfigureClient(k8sMockClient.Controller())
    49  	})
    50  
    51  	AfterEach(func() {
    52  		k8sMockClient.Finish()
    53  	})
    54  
    55  	Context("sync reconfigure policy test", func() {
    56  		It("Should success without error", func() {
    57  			By("check policy name")
    58  			Expect(operatorSyncPolicy.GetPolicyName()).Should(BeEquivalentTo("operatorSyncUpdate"))
    59  
    60  			By("prepare reconfigure policy params")
    61  			mockParam := newMockReconfigureParams("operatorSyncPolicy", k8sMockClient.Client(),
    62  				withGRPCClient(func(addr string) (cfgproto.ReconfigureClient, error) {
    63  					return reconfigureClient, nil
    64  				}),
    65  				withMockStatefulSet(3, nil),
    66  				withConfigSpec("for_test", map[string]string{"a": "c b e f"}),
    67  				withConfigConstraintSpec(&appsv1alpha1.FormatterConfig{Format: appsv1alpha1.RedisCfg}),
    68  				withConfigPatch(map[string]string{
    69  					"a": "c b e f",
    70  				}),
    71  				withClusterComponent(3),
    72  				withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{
    73  					ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{
    74  						Name:       "for_test",
    75  						VolumeName: "test_volume",
    76  					},
    77  				}}))
    78  
    79  			By("mock client get pod caller")
    80  			k8sMockClient.MockListMethod(testutil.WithListReturned(
    81  				testutil.WithConstructListSequenceResult([][]runtime.Object{
    82  					fromPodObjectList(newMockPodsWithStatefulSet(&mockParam.ComponentUnits[0], 3,
    83  						withReadyPod(0, 1))),
    84  					fromPodObjectList(newMockPodsWithStatefulSet(&mockParam.ComponentUnits[0], 3,
    85  						withReadyPod(0, 3))),
    86  				}),
    87  				testutil.WithAnyTimes()))
    88  
    89  			By("mock client patch caller")
    90  			// mock client update caller
    91  			k8sMockClient.MockPatchMethod(testutil.WithSucceed(testutil.WithMinTimes(3)))
    92  
    93  			By("mock remote online update caller")
    94  			reconfigureClient.EXPECT().OnlineUpgradeParams(gomock.Any(), gomock.Any()).Return(
    95  				&cfgproto.OnlineUpgradeParamsResponse{}, nil).
    96  				MinTimes(3)
    97  
    98  			status, err := operatorSyncPolicy.Upgrade(mockParam)
    99  			Expect(err).Should(Succeed())
   100  			Expect(status.Status).Should(BeEquivalentTo(ESRetry))
   101  			Expect(status.SucceedCount).Should(BeEquivalentTo(1))
   102  			Expect(status.ExpectedCount).Should(BeEquivalentTo(3))
   103  
   104  			status, err = operatorSyncPolicy.Upgrade(mockParam)
   105  			Expect(err).Should(Succeed())
   106  			Expect(status.Status).Should(BeEquivalentTo(ESNone))
   107  			Expect(status.SucceedCount).Should(BeEquivalentTo(3))
   108  			Expect(status.ExpectedCount).Should(BeEquivalentTo(3))
   109  		})
   110  	})
   111  
   112  	Context("sync reconfigure policy with selector test", func() {
   113  		It("Should success without error", func() {
   114  			By("check policy name")
   115  			Expect(operatorSyncPolicy.GetPolicyName()).Should(BeEquivalentTo("operatorSyncUpdate"))
   116  
   117  			By("prepare reconfigure policy params")
   118  			mockParam := newMockReconfigureParams("operatorSyncPolicy", k8sMockClient.Client(),
   119  				withGRPCClient(func(addr string) (cfgproto.ReconfigureClient, error) {
   120  					return reconfigureClient, nil
   121  				}),
   122  				withMockStatefulSet(3, nil),
   123  				withConfigSpec("for_test", map[string]string{"a": "c b e f"}),
   124  				withConfigConstraintSpec(&appsv1alpha1.FormatterConfig{Format: appsv1alpha1.RedisCfg}),
   125  				withConfigPatch(map[string]string{
   126  					"a": "c b e f",
   127  				}),
   128  				withClusterComponent(3),
   129  				withCDComponent(appsv1alpha1.Consensus, []appsv1alpha1.ComponentConfigSpec{{
   130  					ComponentTemplateSpec: appsv1alpha1.ComponentTemplateSpec{
   131  						Name:       "for_test",
   132  						VolumeName: "test_volume",
   133  					},
   134  				}}))
   135  
   136  			// add selector
   137  			mockParam.ConfigConstraint.Selector = &metav1.LabelSelector{
   138  				MatchLabels: map[string]string{
   139  					"primary": "true",
   140  				},
   141  			}
   142  
   143  			By("mock client get pod caller")
   144  			k8sMockClient.MockListMethod(testutil.WithListReturned(
   145  				testutil.WithConstructListReturnedResult(
   146  					fromPodObjectList(newMockPodsWithStatefulSet(&mockParam.ComponentUnits[0], 3,
   147  						withReadyPod(0, 1), func(pod *corev1.Pod, index int) {
   148  							if index == 0 {
   149  								if pod.Labels == nil {
   150  									pod.Labels = make(map[string]string)
   151  								}
   152  								pod.Labels["primary"] = "true"
   153  							}
   154  						}))),
   155  				testutil.WithAnyTimes()))
   156  
   157  			By("mock client patch caller")
   158  			// mock client update caller
   159  			k8sMockClient.MockPatchMethod(testutil.WithSucceed(testutil.WithTimes(1)))
   160  
   161  			By("mock remote online update caller")
   162  			reconfigureClient.EXPECT().OnlineUpgradeParams(gomock.Any(), gomock.Any()).Return(
   163  				&cfgproto.OnlineUpgradeParamsResponse{}, nil).
   164  				Times(1)
   165  
   166  			status, err := operatorSyncPolicy.Upgrade(mockParam)
   167  			Expect(err).Should(Succeed())
   168  			Expect(status.Status).Should(BeEquivalentTo(ESNone))
   169  			Expect(status.SucceedCount).Should(BeEquivalentTo(1))
   170  			Expect(status.ExpectedCount).Should(BeEquivalentTo(1))
   171  		})
   172  	})
   173  
   174  })