Implement SDL CLI 'remove' -command 68/7068/3
authorTimo Tietavainen <timo.tietavainen@nokia.com>
Mon, 15 Nov 2021 19:33:15 +0000 (21:33 +0200)
committerTimo Tietavainen <timo.tietavainen@nokia.com>
Wed, 17 Nov 2021 07:22:26 +0000 (09:22 +0200)
Implement a new 'remove' -command for 'sdlcli' -tool. With this
command single or many keys under given namespace can be removed
from SDL DB. Command syntax is:
  sdlcli remove <namespace> <key> [<key2>... <keyN>] [flags]
For the time being only -h and --help flags are supported with the
'remove' -command.

Issue-Id: RIC-113

Signed-off-by: Timo Tietavainen <timo.tietavainen@nokia.com>
Change-Id: I4b68689ae9ec388372298f0445f714a5bdb23f3b

internal/cli/cli_private_fn_test.go
internal/cli/remove.go [new file with mode: 0644]
internal/cli/remove_test.go [new file with mode: 0644]
internal/cli/types.go
internal/mocks/db_mocks_private_testing.go

index 95bc579..2dacf4d 100644 (file)
 package cli
 
 var (
-       NewRootCmd        = newRootCmd
-       NewHealthCheckCmd = newHealthCheckCmd
-       NewKeysCmdForTest = newKeysCmd
-       NewGetCmdForTest  = newGetCmd
-       NewSetCmdForTest  = newSetCmd
+       NewRootCmd          = newRootCmd
+       NewHealthCheckCmd   = newHealthCheckCmd
+       NewKeysCmdForTest   = newKeysCmd
+       NewGetCmdForTest    = newGetCmd
+       NewSetCmdForTest    = newSetCmd
+       NewRemoveCmdForTest = newRemoveCmd
 )
diff --git a/internal/cli/remove.go b/internal/cli/remove.go
new file mode 100644 (file)
index 0000000..35fef03
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+   Copyright (c) 2021 AT&T Intellectual Property.
+   Copyright (c) 2018-2021 Nokia.
+
+   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.
+*/
+
+/*
+ * This source code is part of the near-RT RIC (RAN Intelligent Controller)
+ * platform project (RICP).
+ */
+
+package cli
+
+import (
+       "bytes"
+       "gerrit.o-ran-sc.org/r/ric-plt/sdlgo"
+       "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/sdlgoredis"
+       "github.com/spf13/cobra"
+       "os"
+)
+
+const removeLongHelp = "Remove key(s) under given namespace from SDL DB.\n" +
+       "Multiple keys to remove can be given in a single command,\n" +
+       "each key is separated from the one next to it by a space."
+
+func init() {
+       rootCmd.AddCommand(newRemoveCmd(func() ISyncStorage {
+               return sdlgo.NewSyncStorage()
+       }))
+}
+
+func newRemoveCmd(sdlCreateCb SyncStorageCreateCb) *cobra.Command {
+       cmd := &cobra.Command{
+               Use:   "remove <namespace> <key> [<key2>... <keyN>]",
+               Short: "Remove key(s) under given namespace from SDL DB",
+               Long:  removeLongHelp,
+               Args:  cobra.MinimumNArgs(2),
+               RunE: func(cmd *cobra.Command, args []string) error {
+                       var buf bytes.Buffer
+                       sdlgoredis.SetDbLogger(&buf)
+                       err := runRemove(sdlCreateCb, args)
+                       if err != nil {
+                               cmd.PrintErrf("%s\n", buf.String())
+                       }
+                       return err
+               },
+       }
+       cmd.SetOut(os.Stdout)
+       return cmd
+}
+
+func runRemove(sdlCreateCb SyncStorageCreateCb, args []string) error {
+       sdl := sdlCreateCb()
+       if err := sdl.Remove(args[0], args[1:]); err != nil {
+               return err
+       }
+       return nil
+}
diff --git a/internal/cli/remove_test.go b/internal/cli/remove_test.go
new file mode 100644 (file)
index 0000000..180499d
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+   Copyright (c) 2021 AT&T Intellectual Property.
+   Copyright (c) 2018-2021 Nokia.
+
+   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.
+*/
+
+/*
+ * This source code is part of the near-RT RIC (RAN Intelligent Controller)
+ * platform project (RICP).
+ */
+
+package cli_test
+
+import (
+       "bytes"
+       "fmt"
+       "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/cli"
+       "gerrit.o-ran-sc.org/r/ric-plt/sdlgo/internal/mocks"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+var removeMocks *RemoveMocks
+
+type RemoveMocks struct {
+       sdlIface *mocks.MockSdlApi
+       ns       string
+       keys     []string
+       ret      error
+}
+
+func setupRemoveCliMock(ns string, keys []string, ret error) {
+       removeMocks = new(RemoveMocks)
+       removeMocks.ns = ns
+       removeMocks.keys = keys
+       removeMocks.ret = ret
+}
+
+func newMockSdlRemoveApi() cli.ISyncStorage {
+       removeMocks.sdlIface = new(mocks.MockSdlApi)
+       removeMocks.sdlIface.On("Remove", removeMocks.ns, removeMocks.keys).Return(removeMocks.ret)
+       return removeMocks.sdlIface
+}
+
+func runRemoveCli() (string, string, error) {
+       bufStdout := new(bytes.Buffer)
+       bufStderr := new(bytes.Buffer)
+       cmd := cli.NewRemoveCmdForTest(newMockSdlRemoveApi)
+       cmd.SetOut(bufStdout)
+       cmd.SetErr(bufStderr)
+       args := []string{removeMocks.ns}
+       args = append(args, removeMocks.keys...)
+       cmd.SetArgs(args)
+       err := cmd.Execute()
+
+       return bufStdout.String(), bufStderr.String(), err
+}
+
+func TestCliRemoveCanShowHelp(t *testing.T) {
+       var expOkErr error
+       expHelp := "Usage:\n  " + "remove <namespace> <key> [<key2>... <keyN>] [flags]"
+       expFlagErr := fmt.Errorf("unknown flag: --some-unknown-flag")
+       expArgCntLtErr := fmt.Errorf("requires at least 2 arg(s), only received 1")
+       tests := []struct {
+               args      []string
+               expErr    error
+               expOutput string
+       }{
+               {args: []string{"-h"}, expErr: expOkErr, expOutput: expHelp},
+               {args: []string{"--help"}, expErr: expOkErr, expOutput: expHelp},
+               {args: []string{"--some-unknown-flag"}, expErr: expFlagErr, expOutput: expHelp},
+               {args: []string{"some-ns"}, expErr: expArgCntLtErr, expOutput: expHelp},
+       }
+
+       for _, test := range tests {
+               buf := new(bytes.Buffer)
+               cmd := cli.NewRemoveCmdForTest(newMockSdlRemoveApi)
+               cmd.SetOut(buf)
+               cmd.SetArgs(test.args)
+
+               err := cmd.Execute()
+
+               stdout := buf.String()
+               assert.Equal(t, test.expErr, err)
+               assert.Contains(t, stdout, test.expOutput)
+       }
+}
+
+func TestCliRemoveCommandWithOneKeySuccess(t *testing.T) {
+       setupRemoveCliMock("some-ns", []string{"some-key"}, nil)
+
+       stdout, stderr, err := runRemoveCli()
+
+       assert.Nil(t, err)
+       assert.Equal(t, "", stdout)
+       assert.Equal(t, "", stderr)
+       removeMocks.sdlIface.AssertExpectations(t)
+}
+
+func TestCliRemoveCommandWithMultipleKeysSuccess(t *testing.T) {
+       setupRemoveCliMock("some-ns", []string{"some-key-1", "some-key-1", "some-key-3"}, nil)
+
+       stdout, stderr, err := runRemoveCli()
+
+       assert.Nil(t, err)
+       assert.Equal(t, "", stdout)
+       assert.Equal(t, "", stderr)
+       removeMocks.sdlIface.AssertExpectations(t)
+}
+
+func TestCliRemoveCommandFailure(t *testing.T) {
+       expErr := fmt.Errorf("some-error")
+       setupRemoveCliMock("some-ns", []string{"some-key"}, expErr)
+
+       _, stderr, err := runRemoveCli()
+
+       assert.Equal(t, expErr, err)
+       assert.Contains(t, stderr, expErr.Error())
+       removeMocks.sdlIface.AssertExpectations(t)
+}
index 448515c..dbe410b 100644 (file)
@@ -43,6 +43,7 @@ type DbCreateCb func() *Database
 type ISyncStorage interface {
        ListKeys(ns string, pattern string) ([]string, error)
        Set(ns string, pairs ...interface{}) error
+       Remove(ns string, keys []string) error
 }
 
 //SyncStorageCreateCb callback function type to create a new SyncStorageInterface
index 45fbb78..06927cb 100644 (file)
@@ -54,3 +54,8 @@ func (m *MockSdlApi) Set(ns string, pairs ...interface{}) error {
        a := m.Called(ns, pairs)
        return a.Error(0)
 }
+
+func (m *MockSdlApi) Remove(ns string, keys []string) error {
+       a := m.Called(ns, keys)
+       return a.Error(0)
+}