diff options
| author | KubeEdge Bot <48982446+kubeedge-bot@users.noreply.github.com> | 2023-07-22 18:09:47 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-22 18:09:47 +0800 |
| commit | 87d48a0b0f4895a3781b1132f95f68916cd24b01 (patch) | |
| tree | 907234cacae751d15b4fad9ba382dc5ac808aaa8 /edge | |
| parent | Merge pull request #4578 from Shelley-BaoYue/container-terminated-when-edgeco... (diff) | |
| parent | fix delete sts po (diff) | |
| download | kubeedge-87d48a0b0f4895a3781b1132f95f68916cd24b01.tar.gz | |
Merge pull request #4631 from Shelley-BaoYue/fix-sts
fix delete statefulset pod error
Diffstat (limited to 'edge')
| -rw-r--r-- | edge/mocks/beego/fake_sqlresult.go | 68 | ||||
| -rw-r--r-- | edge/pkg/metamanager/dao/meta.go | 12 | ||||
| -rw-r--r-- | edge/pkg/metamanager/dao/meta_test.go | 48 | ||||
| -rw-r--r-- | edge/pkg/metamanager/process.go | 82 | ||||
| -rw-r--r-- | edge/pkg/metamanager/process_test.go | 79 |
5 files changed, 228 insertions, 61 deletions
diff --git a/edge/mocks/beego/fake_sqlresult.go b/edge/mocks/beego/fake_sqlresult.go new file mode 100644 index 000000000..a07a1d6e7 --- /dev/null +++ b/edge/mocks/beego/fake_sqlresult.go @@ -0,0 +1,68 @@ +/* +Copyright 2023 The KubeEdge Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Source: database/sql/sql.go (interfaces: Result) + +Package beego is a generated GoMock package. +*/ + +package beego + +import ( + "reflect" + + "github.com/golang/mock/gomock" +) + +// MockSQLResult is a mock of SQL Result +type MockSQLResult struct { + ctrl *gomock.Controller + recorder *MockSQLResultMockRecorder +} + +// MockSQLResultMockRecorder is the mock recorder for MockSQLResult +type MockSQLResultMockRecorder struct { + mock *MockSQLResult +} + +// NewMockDriverRes creates a new mock instance +func NewMockDriverRes(ctrl *gomock.Controller) *MockSQLResult { + mock := &MockSQLResult{ctrl: ctrl} + mock.recorder = &MockSQLResultMockRecorder{mock: mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockSQLResult) EXPECT() *MockSQLResultMockRecorder { + return m.recorder +} + +// RowsAffected indicates an expected call of RowsAffected +func (mr *MockSQLResultMockRecorder) RowsAffected() *gomock.Call { + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RowsAffected", reflect.TypeOf((*MockSQLResult)(nil).RowsAffected)) +} + +// LastInsertId mocks base LastInsertId method +func (m *MockSQLResult) LastInsertId() (int64, error) { + return 1, nil +} + +// RowsAffected mocks base RowsAffected method +func (m *MockSQLResult) RowsAffected() (int64, error) { + ret := m.ctrl.Call(m, "RowsAffected") + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} diff --git a/edge/pkg/metamanager/dao/meta.go b/edge/pkg/metamanager/dao/meta.go index 07eb720c7..09a6179a0 100644 --- a/edge/pkg/metamanager/dao/meta.go +++ b/edge/pkg/metamanager/dao/meta.go @@ -1,6 +1,7 @@ package dao import ( + "fmt" "strings" "k8s.io/klog/v2" @@ -47,6 +48,17 @@ func DeleteMetaByKey(key string) error { return err } +// DeleteMetaByKeyAndPodUID delete meta by key and podUID +func DeleteMetaByKeyAndPodUID(key, podUID string) (int64, error) { + sqlStr := fmt.Sprintf("DELETE FROM meta WHERE key = '%s' and value LIKE '%%%s%%'", key, podUID) + res, err := dbm.DBAccess.Raw(sqlStr).Exec() + if err != nil { + klog.Errorf("delete pod by key %s and podUID %s failed, err: %v", key, podUID, err) + return 0, err + } + return res.RowsAffected() +} + // UpdateMeta update meta func UpdateMeta(meta *Meta) error { num, err := dbm.DBAccess.Update(meta) // will update all field diff --git a/edge/pkg/metamanager/dao/meta_test.go b/edge/pkg/metamanager/dao/meta_test.go index fed201e91..323e90d04 100644 --- a/edge/pkg/metamanager/dao/meta_test.go +++ b/edge/pkg/metamanager/dao/meta_test.go @@ -129,6 +129,54 @@ func TestDeleteMetaByKey(t *testing.T) { } } +// TestDeleteMetaByKeyAndPodUID is function to test DeleteMetaByKeyAndPodUID +func TestDeleteMetaByKeyAndPodUID(t *testing.T) { + //Initialize Global Variables (Mocks) + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + ormerMock := beego.NewMockOrmer(mockCtrl) + dbm.DBAccess = ormerMock + rawSeterMock := beego.NewMockRawSeter(mockCtrl) + deleteRes := beego.NewMockDriverRes(mockCtrl) + deleteRes.EXPECT().RowsAffected().Return(int64(1), nil).Times(1) + + cases := []struct { + // name is name of the testcase + name string + // deleteReturnRes is first return of mock interface rawSeterMock's Exec function + deleteReturnRes sql.Result + // deleteReturnErr is second return of mock interface rawSeterMock's Exec function which is also expected error + deleteReturnErr error + // deleteReturnRaw is the return of mock interface ormerMock's Raw function + deleteReturnRaw orm.RawSeter + }{{ + // Success Case + name: "SuccessCase", + deleteReturnRes: deleteRes, + deleteReturnErr: nil, + deleteReturnRaw: rawSeterMock, + }, { + // Failure Case + name: "FailureCase", + deleteReturnRes: nil, + deleteReturnErr: errFailedDBOperation, + deleteReturnRaw: rawSeterMock, + }, + } + + // run the test cases + for _, test := range cases { + t.Run(test.name, func(t *testing.T) { + rawSeterMock.EXPECT().Exec().Return(test.deleteReturnRes, test.deleteReturnErr).Times(1) + ormerMock.EXPECT().Raw(gomock.Any(), gomock.Any()).Return(test.deleteReturnRaw).Times(1) + _, err := DeleteMetaByKeyAndPodUID("test", "testUID") + if test.deleteReturnErr != err { + t.Errorf("Delete Meta By Key Case failed : wanted %v and got %v", test.deleteReturnErr, err) + } + }) + } +} + // TestUpdateMeta is function to test UpdateMeta func TestUpdateMeta(t *testing.T) { //Initialize Global Variables (Mocks) diff --git a/edge/pkg/metamanager/process.go b/edge/pkg/metamanager/process.go index e9aed6d36..50884c65b 100644 --- a/edge/pkg/metamanager/process.go +++ b/edge/pkg/metamanager/process.go @@ -147,6 +147,38 @@ func (m *metaManager) handleMessage(message *model.Message) error { return nil } +func processDeletePodDB(message model.Message) error { + var msgPod corev1.Pod + msgContent, err := message.GetContentData() + if err != nil { + return err + } + + err = json.Unmarshal(msgContent, &msgPod) + if err != nil { + return err + } + + num, err := dao.DeleteMetaByKeyAndPodUID(message.GetResource(), string(msgPod.UID)) + if err != nil { + return err + } + if num == 0 { + klog.V(2).Infof("don't need to delete pod DB") + return nil + } + + podPatchKey := strings.Replace(message.GetResource(), + constants.ResourceSep+model.ResourceTypePod+constants.ResourceSep, + constants.ResourceSep+model.ResourceTypePodPatch+constants.ResourceSep, 1) + err = dao.DeleteMetaByKey(podPatchKey) + if err != nil { + return err + } + + return nil +} + func (m *metaManager) processInsert(message model.Message) { imitator.DefaultV2Client.Inject(message) @@ -267,56 +299,6 @@ func (m *metaManager) processDelete(message model.Message) { sendToCloud(resp) } -func processDeletePodDB(message model.Message) error { - podDBList, err := dao.QueryMeta("key", message.GetResource()) - if err != nil { - return err - } - - podList := *podDBList - if len(podList) == 0 { - klog.Infof("no pod with key %s key in DB", message.GetResource()) - return nil - } - - var podDB corev1.Pod - err = json.Unmarshal([]byte(podList[0]), &podDB) - if err != nil { - return err - } - - var msgPod corev1.Pod - msgContent, err := message.GetContentData() - if err != nil { - return err - } - - err = json.Unmarshal(msgContent, &msgPod) - if err != nil { - return err - } - - if podDB.UID != msgPod.UID { - klog.Warning("pod UID is not equal to pod stored in DB, don't need to delete pod DB") - return nil - } - - err = dao.DeleteMetaByKey(message.GetResource()) - if err != nil { - return err - } - - podPatchKey := strings.Replace(message.GetResource(), - constants.ResourceSep+model.ResourceTypePod+constants.ResourceSep, - constants.ResourceSep+model.ResourceTypePodPatch+constants.ResourceSep, 1) - err = dao.DeleteMetaByKey(podPatchKey) - if err != nil { - return err - } - - return nil -} - func (m *metaManager) processQuery(message model.Message) { resKey, resType, resID := parseResource(&message) var metas *[]string diff --git a/edge/pkg/metamanager/process_test.go b/edge/pkg/metamanager/process_test.go index 2bdaf1eea..d3d60f8a1 100644 --- a/edge/pkg/metamanager/process_test.go +++ b/edge/pkg/metamanager/process_test.go @@ -26,6 +26,7 @@ import ( coordinationv1 "k8s.io/api/coordination/v1" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/uuid" "github.com/kubeedge/beehive/pkg/common" "github.com/kubeedge/beehive/pkg/core" @@ -492,6 +493,8 @@ func TestProcessDelete(t *testing.T) { defer mockCtrl.Finish() ormerMock := beego.NewMockOrmer(mockCtrl) querySetterMock := beego.NewMockQuerySeter(mockCtrl) + rawSetterMock := beego.NewMockRawSeter(mockCtrl) + deleteRes := beego.NewMockDriverRes(mockCtrl) dbm.DBAccess = ormerMock meta := newMetaManager(true) core.Register(meta) @@ -528,6 +531,23 @@ func TestProcessDelete(t *testing.T) { } }) + // SuccessWhenUIDNotEqual + msgPod := v1.Pod{} + msgPod.Name = "testPod" + msgPod.UID = uuid.NewUUID() + deleteRes.EXPECT().RowsAffected().Return(int64(0), nil).Times(1) + rawSetterMock.EXPECT().Exec().Return(deleteRes, nil).Times(1) + ormerMock.EXPECT().Raw(gomock.Any(), gomock.Any()).Return(rawSetterMock).Times(1) + msg = model.NewMessage("").BuildRouter(ModuleNameEdgeHub, GroupResource, "test/"+model.ResourceTypePod, model.DeleteOperation).FillBody(msgPod) + meta.processDelete(*msg) + message, _ = beehiveContext.Receive(ModuleNameEdgeHub) + t.Run("SuccessWhenUIDNotEqual", func(t *testing.T) { + want := OK + if message.GetContent() != want { + t.Errorf("Wrong message received : Wanted %v and Got %v", want, message.GetContent()) + } + }) + //Success Case querySetterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(querySetterMock).Times(1) querySetterMock.EXPECT().Delete().Return(int64(1), nil).Times(1) @@ -548,6 +568,7 @@ func TestProcessDelete(t *testing.T) { t.Errorf("Wrong message received : Wanted %v and Got %v", want, message.GetContent()) } }) + // Success Case pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -571,20 +592,56 @@ func TestProcessDelete(t *testing.T) { t.Errorf("Wrong message received : Wanted %v and Got %v", constants.MessageSuccessfulContent, message.GetContent()) } }) +} - fakeDao := new([]dao.Meta) - fakeDaoArray := make([]dao.Meta, 1) - fakeDaoArray[0] = dao.Meta{Key: "Test", Value: string(podBytes)} - fakeDao = &fakeDaoArray - querySetterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(querySetterMock).Times(3) - querySetterMock.EXPECT().All(gomock.Any()).SetArg(0, *fakeDao).Return(int64(1), nil).Times(1) - querySetterMock.EXPECT().Delete().Return(int64(1), nil).Times(2) - ormerMock.EXPECT().QueryTable(gomock.Any()).Return(querySetterMock).Times(3) +func TestProcessDelete_SuccessDeletePodToEdged(t *testing.T) { + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + ormerMock := beego.NewMockOrmer(mockCtrl) + querySetterMock := beego.NewMockQuerySeter(mockCtrl) + rawSetterMock := beego.NewMockRawSeter(mockCtrl) + deleteRes := beego.NewMockDriverRes(mockCtrl) + dbm.DBAccess = ormerMock + meta := newMetaManager(true) + core.Register(meta) + + add := &common.ModuleInfo{ + ModuleName: meta.Name(), + ModuleType: common.MsgCtxTypeChannel, + } + beehiveContext.AddModule(add) + beehiveContext.AddModuleGroup(meta.Name(), meta.Group()) + edgeHub := &common.ModuleInfo{ + ModuleName: ModuleNameEdgeHub, + ModuleType: common.MsgCtxTypeChannel, + } + beehiveContext.AddModule(edgeHub) + beehiveContext.AddModuleGroup(ModuleNameEdgeHub, modules.HubGroup) + edged := &common.ModuleInfo{ + ModuleName: ModuleNameEdged, + ModuleType: common.MsgCtxTypeChannel, + } + beehiveContext.AddModule(edged) - resource = fmt.Sprintf("test/%s/nginx", model.ResourceTypePod) - msg = model.NewMessage("").BuildRouter(ModuleNameController, modules.MetaGroup, resource, model.DeleteOperation).FillBody(podBytes) + deleteRes.EXPECT().RowsAffected().Return(int64(1), nil).Times(1) + rawSetterMock.EXPECT().Exec().Return(deleteRes, nil).Times(1) + ormerMock.EXPECT().Raw(gomock.Any(), gomock.Any()).Return(rawSetterMock).Times(1) + querySetterMock.EXPECT().Filter(gomock.Any(), gomock.Any()).Return(querySetterMock).Times(1) + querySetterMock.EXPECT().Delete().Return(int64(1), nil).Times(1) + ormerMock.EXPECT().QueryTable(gomock.Any()).Return(querySetterMock).Times(1) + + pod := &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "nginx", + Namespace: "test", + UID: "1234567890", + }, + } + podBytes, _ := json.Marshal(pod) + resource := fmt.Sprintf("test/%s/nginx", model.ResourceTypePod) + msg := model.NewMessage("").BuildRouter(ModuleNameController, modules.MetaGroup, resource, model.DeleteOperation).FillBody(podBytes) meta.processDelete(*msg) - message, _ = beehiveContext.Receive(ModuleNameEdged) + message, _ := beehiveContext.Receive(ModuleNameEdged) t.Run("SuccessDeletePodToEdged", func(t *testing.T) { want := ModuleNameController if message.GetSource() != want { |
