This is an automated email from the ASF dual-hosted git repository.

zhonghongsheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/shardingsphere-on-cloud.git


The following commit(s) were added to refs/heads/main by this push:
     new e2a5864  feat: introduce new pitr subcommand delete (#461)
e2a5864 is described below

commit e2a586401673dccf0e6c6abe1e45627a352ed3d4
Author: liyao <[email protected]>
AuthorDate: Wed Nov 15 17:38:43 2023 +0800

    feat: introduce new pitr subcommand delete (#461)
    
    * feat: use common header in DELETE request
    
    * feat: add filename as backup metainfo
    
    * feat: add HideByName and DeleteByHidedName
    
    * feat: add delete backup record
    
    * chore: update local storage mock
    
    * chore: add test for delete
    
    * refactor: change func name delete to deleteRecord
    
    * refactor: optimize _execDelete
    
    * feat: add add delete status
    
    * chore: update delete func name
    
    * chore: add nolint for command definition
    
    * refactor: seperate common func validate
    
    * chore: adjust style according to lint
---
 pitr/cli/internal/cmd/common.go              |  47 +++++++
 pitr/cli/internal/cmd/delete.go              | 192 +++++++++++++++++++++++++++
 pitr/cli/internal/cmd/delete_test.go         | 116 ++++++++++++++++
 pitr/cli/internal/cmd/restore.go             |  17 +--
 pitr/cli/internal/pkg/local-storage.go       |  30 ++++-
 pitr/cli/internal/pkg/mocks/local-storage.go | 112 +++++++++-------
 pitr/cli/internal/pkg/model/ls_backup.go     |   1 +
 pitr/cli/pkg/httputils/req.go                |  10 +-
 8 files changed, 456 insertions(+), 69 deletions(-)

diff --git a/pitr/cli/internal/cmd/common.go b/pitr/cli/internal/cmd/common.go
new file mode 100644
index 0000000..0e80d5d
--- /dev/null
+++ b/pitr/cli/internal/cmd/common.go
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package cmd
+
+import (
+       "fmt"
+
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/model"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/xerr"
+)
+
+func validate(ls pkg.ILocalStorage, csn, recordID string) (*model.LsBackup, 
error) {
+       var (
+               bak *model.LsBackup
+               err error
+       )
+       if CSN != "" {
+               bak, err = ls.ReadByCSN(csn)
+               if err != nil {
+                       return bak, xerr.NewCliErr(fmt.Sprintf("read backup 
record by csn failed. err: %s", err))
+               }
+       }
+
+       if RecordID != "" {
+               bak, err = ls.ReadByID(recordID)
+               if err != nil {
+                       return bak, xerr.NewCliErr(fmt.Sprintf("read backup 
record by id failed. err: %s", err))
+               }
+       }
+       return bak, nil
+}
diff --git a/pitr/cli/internal/cmd/delete.go b/pitr/cli/internal/cmd/delete.go
new file mode 100644
index 0000000..6107097
--- /dev/null
+++ b/pitr/cli/internal/cmd/delete.go
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package cmd
+
+import (
+       "fmt"
+       "os"
+       "time"
+
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/model"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/xerr"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/pkg/logging"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/pkg/prettyoutput"
+       "github.com/jedib0t/go-pretty/v6/table"
+
+       "github.com/spf13/cobra"
+       "github.com/spf13/pflag"
+)
+
+//nolint:dupl
+var DeleteCmd = &cobra.Command{
+       Use:   "delete",
+       Short: "Delete a backup record",
+       Run: func(cmd *cobra.Command, args []string) {
+               cmd.Flags().VisitAll(func(flag *pflag.Flag) {
+                       fmt.Printf("Flag: %s Value: %s\n", flag.Name, 
flag.Value)
+               })
+
+               if CSN == "" && RecordID == "" {
+                       logging.Error("Please specify csn or record id")
+                       return
+               }
+
+               if CSN != "" && RecordID != "" {
+                       logging.Error("Please specify only one of csn and 
record id")
+                       return
+               }
+
+               if err := deleteRecord(); err != nil {
+                       logging.Error(err.Error())
+               }
+       },
+}
+
+//nolint:dupl
+func init() {
+       RootCmd.AddCommand(DeleteCmd)
+
+       DeleteCmd.Flags().StringVarP(&Host, "host", "H", "", "ss-proxy hostname 
or ip")
+       _ = DeleteCmd.MarkFlagRequired("host")
+       DeleteCmd.Flags().Uint16VarP(&Port, "port", "P", 0, "ss-proxy port")
+       _ = DeleteCmd.MarkFlagRequired("port")
+       DeleteCmd.Flags().StringVarP(&Username, "username", "u", "", "ss-proxy 
username")
+       _ = DeleteCmd.MarkFlagRequired("username")
+       DeleteCmd.Flags().StringVarP(&Password, "password", "p", "", "ss-proxy 
password")
+       _ = DeleteCmd.MarkFlagRequired("password")
+       DeleteCmd.Flags().StringVarP(&BackupPath, "dn-backup-path", "B", "", 
"openGauss data backup path")
+       _ = DeleteCmd.MarkFlagRequired("dn-backup-path")
+       DeleteCmd.Flags().Uint16VarP(&AgentPort, "agent-port", "a", 443, "agent 
server port")
+       _ = DeleteCmd.MarkFlagRequired("agent-port")
+
+       DeleteCmd.Flags().StringVarP(&CSN, "csn", "", "", "commit sequence 
number")
+       DeleteCmd.Flags().StringVarP(&RecordID, "id", "", "", "backup record 
id")
+}
+
+func deleteRecord() error {
+       // init local storage
+       ls, err := pkg.NewLocalStorage(pkg.DefaultRootDir())
+       if err != nil {
+               return xerr.NewCliErr(fmt.Sprintf("new local storage failed. 
err: %s", err.Error()))
+       }
+
+       // get backup record
+       var bak *model.LsBackup
+       bak, err = validate(ls, CSN, RecordID)
+       if err != nil {
+               return err
+       }
+
+       if bak == nil {
+               return xerr.NewCliErr(fmt.Sprintf("backup record not found. 
err: %s", err))
+       }
+
+       // check agent server status
+       logging.Info("Checking agent server status...")
+       if available := checkAgentServerStatus(bak); !available {
+               return xerr.NewCliErr("one or more agent server are not 
available.")
+       }
+
+       // mark the target backup record to be deleted
+       // meanwhile this record cannot be restored
+       if err := ls.HideByName(bak.Info.FileName); err != nil {
+               return xerr.NewCliErr("cannot mark backup record.")
+       }
+
+       // exec delete
+       logging.Info("Start delete backup data to openGauss...")
+       if err := _execDelete(bak); err != nil {
+               return xerr.NewCliErr(fmt.Sprintf("exec delete failed. err: 
%s", err))
+       }
+       logging.Info("Delete backup data success!")
+
+       // delete the backup record
+       if err := ls.DeleteByHidedName(bak.Info.FileName); err != nil {
+               return xerr.NewCliErr(fmt.Sprintf("exec delete backup record 
failed. err: %s", err))
+       }
+
+       logging.Info("Delete success!")
+       return nil
+}
+
+func _execDelete(lsBackup *model.LsBackup) error {
+       var (
+               dataNodeMap       = make(map[string]*model.DataNode)
+               totalNum          = len(lsBackup.SsBackup.StorageNodes)
+               resultCh          = make(chan *model.DeleteBackupResult, 
totalNum)
+               dnResult          = make([]*model.DeleteBackupResult, 0)
+               deleteFinalStatus = "Completed"
+       )
+       for _, dn := range lsBackup.DnList {
+               dataNodeMap[dn.IP] = dn
+       }
+
+       if totalNum == 0 {
+               logging.Info("No data node need to delete backup files")
+               return nil
+       }
+
+       pw := prettyoutput.NewPW(totalNum)
+       go pw.Render()
+
+       for _, storagenode := range lsBackup.SsBackup.StorageNodes {
+               sn := storagenode
+               if dn, ok := dataNodeMap[sn.IP]; !ok {
+                       logging.Warn(fmt.Sprintf("SKIPPED! data node %s:%d not 
found in backup info.", sn.IP, sn.Port))
+                       continue
+               } else {
+                       as := pkg.NewAgentServer(fmt.Sprintf("%s:%d", 
convertLocalhost(sn.IP), AgentPort))
+                       go doDelete(as, sn, dn, resultCh, pw)
+               }
+       }
+
+       time.Sleep(time.Millisecond * 100)
+
+       for pw.IsRenderInProgress() {
+               time.Sleep(time.Millisecond * 100)
+       }
+
+       close(resultCh)
+
+       for result := range resultCh {
+               dnResult = append(dnResult, result)
+               if result.Status != "Completed" {
+                       deleteFinalStatus = "Failed"
+               }
+       }
+
+       t := table.NewWriter()
+       t.SetOutputMirror(os.Stdout)
+       t.SetTitle("Delete Backup Files Result")
+       t.AppendHeader(table.Row{"#", "Node IP", "Node Port", "Result", 
"Message"})
+       t.SetColumnConfigs([]table.ColumnConfig{{Number: 5, WidthMax: 50}})
+
+       for i, result := range dnResult {
+               t.AppendRow([]interface{}{i + 1, result.IP, result.Port, 
result.Status, result.Msg})
+               t.AppendSeparator()
+       }
+
+       t.Render()
+
+       if deleteFinalStatus == "Failed" {
+               return xerr.NewCliErr("delete failed, please check the log for 
more details.")
+       }
+
+       return nil
+}
diff --git a/pitr/cli/internal/cmd/delete_test.go 
b/pitr/cli/internal/cmd/delete_test.go
new file mode 100644
index 0000000..194e617
--- /dev/null
+++ b/pitr/cli/internal/cmd/delete_test.go
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package cmd
+
+import (
+       "reflect"
+       "time"
+
+       "bou.ke/monkey"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg"
+       mock_pkg 
"github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/mocks"
+       "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/model"
+       "github.com/golang/mock/gomock"
+       . "github.com/onsi/ginkgo/v2"
+       . "github.com/onsi/gomega"
+)
+
+var _ = Describe("test delete", func() {
+       var (
+               proxy *mock_pkg.MockIShardingSphereProxy
+               ls    *mock_pkg.MockILocalStorage
+               as    *mock_pkg.MockIAgentServer
+               bak   = &model.LsBackup{
+                       Info: &model.BackupMetaInfo{
+                               ID:       "backup-id-1",
+                               FileName: "backup",
+                       },
+                       DnList: []*model.DataNode{
+                               {
+                                       IP: "127.0.0.1",
+                               },
+                       },
+                       SsBackup: &model.SsBackup{
+                               Status: "",
+                               ClusterInfo: &model.ClusterInfo{
+                                       MetaData: model.MetaData{
+                                               Databases: map[string]string{},
+                                               Props:     "",
+                                               Rules:     "",
+                                       },
+                                       SnapshotInfo: nil,
+                               },
+                               StorageNodes: []*model.StorageNode{
+                                       {
+                                               IP: "127.0.0.1",
+                                       },
+                               },
+                       },
+               }
+       )
+
+       BeforeEach(func() {
+               ctrl = gomock.NewController(GinkgoT())
+               proxy = mock_pkg.NewMockIShardingSphereProxy(ctrl)
+               as = mock_pkg.NewMockIAgentServer(ctrl)
+               ls = mock_pkg.NewMockILocalStorage(ctrl)
+               monkey.Patch(pkg.NewShardingSphereProxy, func(user, password, 
database, host string, port uint16) (pkg.IShardingSphereProxy, error) {
+                       return proxy, nil
+               })
+               monkey.Patch(pkg.NewLocalStorage, func(rootDir string) 
(pkg.ILocalStorage, error) {
+                       return ls, nil
+               })
+       })
+
+       AfterEach(func() {
+               ctrl.Finish()
+               monkey.UnpatchAll()
+       })
+
+       It("test exec delete main func", func() {
+               // patch ReadByID of mock ls
+               monkey.PatchInstanceMethod(reflect.TypeOf(ls), "ReadByID", 
func(_ *mock_pkg.MockILocalStorage, _ string) (*model.LsBackup, error) { return 
bak, nil })
+               monkey.Patch(pkg.NewAgentServer, func(_ string) 
pkg.IAgentServer { return as })
+
+               RecordID = "backup-id"
+               as.EXPECT().CheckStatus(gomock.Any()).Return(nil)
+               ls.EXPECT().HideByName(bak.Info.FileName).Return(nil)
+               as.EXPECT().DeleteBackup(gomock.Any()).Return(nil)
+               ls.EXPECT().DeleteByHidedName(bak.Info.FileName).Return(nil)
+
+               Expect(deleteRecord()).To(BeNil())
+       })
+
+       Context("test exec delete", func() {
+               It("should be success", func() {
+                       ctrl := gomock.NewController(GinkgoT())
+                       as := mock_pkg.NewMockIAgentServer(ctrl)
+                       monkey.Patch(pkg.NewAgentServer, func(_ string) 
pkg.IAgentServer {
+                               return as
+                       })
+                       defer func() {
+                               ctrl.Finish()
+                               monkey.UnpatchAll()
+                       }()
+                       as.EXPECT().DeleteBackup(gomock.Any()).Do(func(_ 
*model.DeleteBackupIn) {
+                               time.Sleep(3 * time.Second)
+                       }).Return(nil)
+                       Expect(_execDelete(bak)).To(BeNil())
+               })
+       })
+})
diff --git a/pitr/cli/internal/cmd/restore.go b/pitr/cli/internal/cmd/restore.go
index 92ca2a7..791a043 100644
--- a/pitr/cli/internal/cmd/restore.go
+++ b/pitr/cli/internal/cmd/restore.go
@@ -40,6 +40,7 @@ var (
        databaseNamesExist []string
 )
 
+//nolint:dupl
 var RestoreCmd = &cobra.Command{
        Use:   "restore",
        Short: "Restore a database cluster ",
@@ -64,6 +65,7 @@ var RestoreCmd = &cobra.Command{
        },
 }
 
+//nolint:dupl
 func init() {
        RootCmd.AddCommand(RestoreCmd)
 
@@ -97,18 +99,9 @@ func restore() error {
 
        // get backup record
        var bak *model.LsBackup
-       if CSN != "" {
-               bak, err = ls.ReadByCSN(CSN)
-               if err != nil {
-                       return xerr.NewCliErr(fmt.Sprintf("read backup record 
by csn failed. err: %s", err))
-               }
-       }
-
-       if RecordID != "" {
-               bak, err = ls.ReadByID(RecordID)
-               if err != nil {
-                       return xerr.NewCliErr(fmt.Sprintf("read backup record 
by id failed. err: %s", err))
-               }
+       bak, err = validate(ls, CSN, RecordID)
+       if err != nil {
+               return err
        }
        if bak == nil {
                return xerr.NewCliErr(fmt.Sprintf("backup record not found. 
err: %s", err))
diff --git a/pitr/cli/internal/pkg/local-storage.go 
b/pitr/cli/internal/pkg/local-storage.go
index ca00480..47693a2 100644
--- a/pitr/cli/internal/pkg/local-storage.go
+++ b/pitr/cli/internal/pkg/local-storage.go
@@ -44,6 +44,8 @@ type (
                ReadByID(id string) (*model.LsBackup, error)
                ReadByCSN(csn string) (*model.LsBackup, error)
                DeleteByName(name string) error
+               HideByName(name string) error
+               DeleteByHidedName(name string) error
        }
 
        Extension string
@@ -164,7 +166,7 @@ func (ls *localStorage) ReadAll() ([]*model.LsBackup, 
error) {
                if err := json.Unmarshal(file, b); err != nil {
                        return nil, xerr.NewCliErr(fmt.Sprintf("invalid 
contents[filePath=%s]. err: %s", path, err))
                }
-
+               b.Info.FileName = info.Name()
                backups = append(backups, b)
        }
        return backups, nil
@@ -214,10 +216,34 @@ func (ls *localStorage) GenFilename(extn Extension) 
string {
        }
 }
 
-func (ls *localStorage) DeleteByName(name string) error {
+type mode int
+
+const (
+       normal mode = iota
+       hided
+)
+
+func (ls *localStorage) deleteByName(name string, mode mode) error {
        path := fmt.Sprintf("%s/%s", ls.backupDir, name)
        if err := os.Remove(path); err != nil {
                return xerr.NewCliErr(fmt.Sprintf("delete file failed. err: 
%s", err))
        }
        return nil
 }
+
+func (ls *localStorage) DeleteByName(name string) error {
+       return ls.deleteByName(name, normal)
+}
+
+func (ls *localStorage) DeleteByHidedName(name string) error {
+       return ls.deleteByName(fmt.Sprintf(".%s", name), hided)
+}
+
+func (ls *localStorage) HideByName(name string) error {
+       path := fmt.Sprintf("%s/%s", ls.backupDir, name)
+       hided := fmt.Sprintf("%s/.%s", ls.backupDir, name)
+       if err := os.Rename(path, hided); err != nil {
+               return xerr.NewCliErr(fmt.Sprintf("hide file failed. err: %s", 
err))
+       }
+       return nil
+}
diff --git a/pitr/cli/internal/pkg/mocks/local-storage.go 
b/pitr/cli/internal/pkg/mocks/local-storage.go
index 9284834..5005197 100644
--- a/pitr/cli/internal/pkg/mocks/local-storage.go
+++ b/pitr/cli/internal/pkg/mocks/local-storage.go
@@ -1,72 +1,54 @@
-/*
-* Licensed to the Apache Software Foundation (ASF) under one or more
-* contributor license agreements.  See the NOTICE file distributed with
-* this work for additional information regarding copyright ownership.
-* The ASF licenses this file to You 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.
- */
-
 // Code generated by MockGen. DO NOT EDIT.
-// Source: local-storage.go
+// Source: internal/pkg/local-storage.go
 
 // Package mock_pkg is a generated GoMock package.
 package mock_pkg
 
 import (
-       reflect "reflect"
-
        pkg "github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg"
        model 
"github.com/apache/shardingsphere-on-cloud/pitr/cli/internal/pkg/model"
        gomock "github.com/golang/mock/gomock"
+       reflect "reflect"
 )
 
-// MockILocalStorage is a mock of ILocalStorage interface.
+// MockILocalStorage is a mock of ILocalStorage interface
 type MockILocalStorage struct {
        ctrl     *gomock.Controller
        recorder *MockILocalStorageMockRecorder
 }
 
-// MockILocalStorageMockRecorder is the mock recorder for MockILocalStorage.
+// MockILocalStorageMockRecorder is the mock recorder for MockILocalStorage
 type MockILocalStorageMockRecorder struct {
        mock *MockILocalStorage
 }
 
-// NewMockILocalStorage creates a new mock instance.
+// NewMockILocalStorage creates a new mock instance
 func NewMockILocalStorage(ctrl *gomock.Controller) *MockILocalStorage {
        mock := &MockILocalStorage{ctrl: ctrl}
        mock.recorder = &MockILocalStorageMockRecorder{mock}
        return mock
 }
 
-// EXPECT returns an object that allows the caller to indicate expected use.
+// EXPECT returns an object that allows the caller to indicate expected use
 func (m *MockILocalStorage) EXPECT() *MockILocalStorageMockRecorder {
        return m.recorder
 }
 
-// DeleteByName mocks base method.
-func (m *MockILocalStorage) DeleteByName(name string) error {
+// WriteByJSON mocks base method
+func (m *MockILocalStorage) WriteByJSON(name string, contents *model.LsBackup) 
error {
        m.ctrl.T.Helper()
-       ret := m.ctrl.Call(m, "DeleteByName", name)
+       ret := m.ctrl.Call(m, "WriteByJSON", name, contents)
        ret0, _ := ret[0].(error)
        return ret0
 }
 
-// DeleteByName indicates an expected call of DeleteByName.
-func (mr *MockILocalStorageMockRecorder) DeleteByName(name interface{}) 
*gomock.Call {
+// WriteByJSON indicates an expected call of WriteByJSON
+func (mr *MockILocalStorageMockRecorder) WriteByJSON(name, contents 
interface{}) *gomock.Call {
        mr.mock.ctrl.T.Helper()
-       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByName", 
reflect.TypeOf((*MockILocalStorage)(nil).DeleteByName), name)
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteByJSON", 
reflect.TypeOf((*MockILocalStorage)(nil).WriteByJSON), name, contents)
 }
 
-// GenFilename mocks base method.
+// GenFilename mocks base method
 func (m *MockILocalStorage) GenFilename(extn pkg.Extension) string {
        m.ctrl.T.Helper()
        ret := m.ctrl.Call(m, "GenFilename", extn)
@@ -74,13 +56,13 @@ func (m *MockILocalStorage) GenFilename(extn pkg.Extension) 
string {
        return ret0
 }
 
-// GenFilename indicates an expected call of GenFilename.
+// GenFilename indicates an expected call of GenFilename
 func (mr *MockILocalStorageMockRecorder) GenFilename(extn interface{}) 
*gomock.Call {
        mr.mock.ctrl.T.Helper()
        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenFilename", 
reflect.TypeOf((*MockILocalStorage)(nil).GenFilename), extn)
 }
 
-// ReadAll mocks base method.
+// ReadAll mocks base method
 func (m *MockILocalStorage) ReadAll() ([]*model.LsBackup, error) {
        m.ctrl.T.Helper()
        ret := m.ctrl.Call(m, "ReadAll")
@@ -89,13 +71,28 @@ func (m *MockILocalStorage) ReadAll() ([]*model.LsBackup, 
error) {
        return ret0, ret1
 }
 
-// ReadAll indicates an expected call of ReadAll.
+// ReadAll indicates an expected call of ReadAll
 func (mr *MockILocalStorageMockRecorder) ReadAll() *gomock.Call {
        mr.mock.ctrl.T.Helper()
        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadAll", 
reflect.TypeOf((*MockILocalStorage)(nil).ReadAll))
 }
 
-// ReadByCSN mocks base method.
+// ReadByID mocks base method
+func (m *MockILocalStorage) ReadByID(id string) (*model.LsBackup, error) {
+       m.ctrl.T.Helper()
+       ret := m.ctrl.Call(m, "ReadByID", id)
+       ret0, _ := ret[0].(*model.LsBackup)
+       ret1, _ := ret[1].(error)
+       return ret0, ret1
+}
+
+// ReadByID indicates an expected call of ReadByID
+func (mr *MockILocalStorageMockRecorder) ReadByID(id interface{}) *gomock.Call 
{
+       mr.mock.ctrl.T.Helper()
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadByID", 
reflect.TypeOf((*MockILocalStorage)(nil).ReadByID), id)
+}
+
+// ReadByCSN mocks base method
 func (m *MockILocalStorage) ReadByCSN(csn string) (*model.LsBackup, error) {
        m.ctrl.T.Helper()
        ret := m.ctrl.Call(m, "ReadByCSN", csn)
@@ -104,37 +101,50 @@ func (m *MockILocalStorage) ReadByCSN(csn string) 
(*model.LsBackup, error) {
        return ret0, ret1
 }
 
-// ReadByCSN indicates an expected call of ReadByCSN.
+// ReadByCSN indicates an expected call of ReadByCSN
 func (mr *MockILocalStorageMockRecorder) ReadByCSN(csn interface{}) 
*gomock.Call {
        mr.mock.ctrl.T.Helper()
        return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadByCSN", 
reflect.TypeOf((*MockILocalStorage)(nil).ReadByCSN), csn)
 }
 
-// ReadByID mocks base method.
-func (m *MockILocalStorage) ReadByID(id string) (*model.LsBackup, error) {
+// DeleteByName mocks base method
+func (m *MockILocalStorage) DeleteByName(name string) error {
        m.ctrl.T.Helper()
-       ret := m.ctrl.Call(m, "ReadByID", id)
-       ret0, _ := ret[0].(*model.LsBackup)
-       ret1, _ := ret[1].(error)
-       return ret0, ret1
+       ret := m.ctrl.Call(m, "DeleteByName", name)
+       ret0, _ := ret[0].(error)
+       return ret0
 }
 
-// ReadByID indicates an expected call of ReadByID.
-func (mr *MockILocalStorageMockRecorder) ReadByID(id interface{}) *gomock.Call 
{
+// DeleteByName indicates an expected call of DeleteByName
+func (mr *MockILocalStorageMockRecorder) DeleteByName(name interface{}) 
*gomock.Call {
        mr.mock.ctrl.T.Helper()
-       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadByID", 
reflect.TypeOf((*MockILocalStorage)(nil).ReadByID), id)
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteByName", 
reflect.TypeOf((*MockILocalStorage)(nil).DeleteByName), name)
 }
 
-// WriteByJSON mocks base method.
-func (m *MockILocalStorage) WriteByJSON(name string, contents *model.LsBackup) 
error {
+// HideByName mocks base method
+func (m *MockILocalStorage) HideByName(name string) error {
        m.ctrl.T.Helper()
-       ret := m.ctrl.Call(m, "WriteByJSON", name, contents)
+       ret := m.ctrl.Call(m, "HideByName", name)
        ret0, _ := ret[0].(error)
        return ret0
 }
 
-// WriteByJSON indicates an expected call of WriteByJSON.
-func (mr *MockILocalStorageMockRecorder) WriteByJSON(name, contents 
interface{}) *gomock.Call {
+// HideByName indicates an expected call of HideByName
+func (mr *MockILocalStorageMockRecorder) HideByName(name interface{}) 
*gomock.Call {
        mr.mock.ctrl.T.Helper()
-       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteByJSON", 
reflect.TypeOf((*MockILocalStorage)(nil).WriteByJSON), name, contents)
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HideByName", 
reflect.TypeOf((*MockILocalStorage)(nil).HideByName), name)
+}
+
+// DeleteByHidedName mocks base method
+func (m *MockILocalStorage) DeleteByHidedName(name string) error {
+       m.ctrl.T.Helper()
+       ret := m.ctrl.Call(m, "DeleteByHidedName", name)
+       ret0, _ := ret[0].(error)
+       return ret0
+}
+
+// DeleteByHidedName indicates an expected call of DeleteByHidedName
+func (mr *MockILocalStorageMockRecorder) DeleteByHidedName(name interface{}) 
*gomock.Call {
+       mr.mock.ctrl.T.Helper()
+       return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, 
"DeleteByHidedName", 
reflect.TypeOf((*MockILocalStorage)(nil).DeleteByHidedName), name)
 }
diff --git a/pitr/cli/internal/pkg/model/ls_backup.go 
b/pitr/cli/internal/pkg/model/ls_backup.go
index 8301a95..8b5a428 100644
--- a/pitr/cli/internal/pkg/model/ls_backup.go
+++ b/pitr/cli/internal/pkg/model/ls_backup.go
@@ -31,6 +31,7 @@ type (
                BackupMode DBBackupMode `json:"backup_mode"`
                StartTime  int64        `json:"start_time"` // Unix time
                EndTime    int64        `json:"end_time"`   // Unix time
+               FileName   string
        }
 
        DataNode struct {
diff --git a/pitr/cli/pkg/httputils/req.go b/pitr/cli/pkg/httputils/req.go
index 49138d8..c38a5ca 100644
--- a/pitr/cli/pkg/httputils/req.go
+++ b/pitr/cli/pkg/httputils/req.go
@@ -131,14 +131,16 @@ func (r *req) setReqHeader(req *http.Request) 
*http.Request {
                req.Header.Set(k, v)
        }
 
+       if req.Header.Get("x-request-id") == "" {
+               req.Header.Set("x-request-id", uuid.New().String())
+       }
+
        // set default header if method is post
-       if r.method == http.MethodPost {
+       if r.method == http.MethodPost || r.method == http.MethodDelete {
                if req.Header.Get("Content-Type") == "" {
                        req.Header.Set("Content-Type", "application/json")
                }
-               if req.Header.Get("x-request-id") == "" {
-                       req.Header.Set("x-request-id", uuid.New().String())
-               }
+
        }
        return req
 }

Reply via email to