Implement SDL CLI 'set' -command 35/7035/6
authorTimo Tietavainen <timo.tietavainen@nokia.com>
Thu, 11 Nov 2021 13:51:39 +0000 (15:51 +0200)
committerTimo Tietavainen <timo.tietavainen@nokia.com>
Mon, 15 Nov 2021 14:52:51 +0000 (16:52 +0200)
Implement a new set -command to 'sdlcli' -tool. With this command one
string key-value pair can be set to SDL DB under given namespace.
Command syntax is:
  sdlcli set <namespace> <key> <value> [flags]
For the time being only -h and --help flags are supported with the
set -command.

Issue-Id: RIC-113

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

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

index 78c6102..95bc579 100644 (file)
@@ -27,4 +27,5 @@ var (
        NewHealthCheckCmd = newHealthCheckCmd
        NewKeysCmdForTest = newKeysCmd
        NewGetCmdForTest  = newGetCmd
+       NewSetCmdForTest  = newSetCmd
 )
diff --git a/internal/cli/set.go b/internal/cli/set.go
new file mode 100644 (file)
index 0000000..03f6872
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+   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"
+)
+
+func init() {
+       rootCmd.AddCommand(newSetCmd(func() ISyncStorage {
+               return sdlgo.NewSyncStorage()
+       }))
+}
+
+func newSetCmd(sdlCreateCb SyncStorageCreateCb) *cobra.Command {
+       cmd := &cobra.Command{
+               Use:   "set <namespace> <key> <value>",
+               Short: "Set a key-value pair to SDL DB under given namespace",
+               Long:  `Set a key-value pair to SDL DB under given namespace`,
+               Args:  cobra.ExactArgs(3),
+               RunE: func(cmd *cobra.Command, args []string) error {
+                       var buf bytes.Buffer
+                       sdlgoredis.SetDbLogger(&buf)
+                       err := runSet(sdlCreateCb, args)
+                       if err != nil {
+                               cmd.PrintErrf("%s\n", buf.String())
+                       }
+                       return err
+               },
+       }
+       cmd.SetOut(os.Stdout)
+       return cmd
+}
+
+func runSet(sdlCreateCb SyncStorageCreateCb, args []string) error {
+       sdl := sdlCreateCb()
+       if err := sdl.Set(args[0], args[1], args[2]); err != nil {
+               return err
+       }
+       return nil
+}
diff --git a/internal/cli/set_test.go b/internal/cli/set_test.go
new file mode 100644 (file)
index 0000000..36fc057
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+   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 setMocks *SetMocks
+
+type SetMocks struct {
+       sdlIface *mocks.MockSdlApi
+       ns       string
+       key      string
+       value    string
+       ret      error
+}
+
+func setupSetCliMock(ns, key, value string, ret error) {
+       setMocks = new(SetMocks)
+       setMocks.ns = ns
+       setMocks.key = key
+       setMocks.value = value
+       setMocks.ret = ret
+}
+
+func newMockSdlSetApi() cli.ISyncStorage {
+       setMocks.sdlIface = new(mocks.MockSdlApi)
+       setMocks.sdlIface.On("Set", setMocks.ns, []interface{}{setMocks.key, setMocks.value}).Return(setMocks.ret)
+       return setMocks.sdlIface
+}
+
+func runSetCli() (string, string, error) {
+       bufStdout := new(bytes.Buffer)
+       bufStderr := new(bytes.Buffer)
+       cmd := cli.NewSetCmdForTest(newMockSdlSetApi)
+       cmd.SetOut(bufStdout)
+       cmd.SetErr(bufStderr)
+       cmd.SetArgs([]string{setMocks.ns, setMocks.key, setMocks.value})
+       err := cmd.Execute()
+
+       return bufStdout.String(), bufStderr.String(), err
+}
+
+func TestCliSetCanShowHelp(t *testing.T) {
+       var expOkErr error
+       expHelp := "Usage:\n  " + "set <namespace> <key> <value> [flags]"
+       expFlagErr := fmt.Errorf("unknown flag: --some-unknown-flag")
+       expArgCntLtErr := fmt.Errorf("accepts 3 arg(s), received 2")
+       expArgCntGtErr := fmt.Errorf("accepts 3 arg(s), received 4")
+       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", "some-key"}, expErr: expArgCntLtErr, expOutput: expHelp},
+               {args: []string{"some-ns", "some-key", "some-value", "some-extra"}, expErr: expArgCntGtErr, expOutput: expHelp},
+       }
+
+       for _, test := range tests {
+               buf := new(bytes.Buffer)
+               cmd := cli.NewSetCmdForTest(newMockSdlSetApi)
+               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 TestCliSetCommandSuccess(t *testing.T) {
+       setupSetCliMock("some-ns", "some-key", "some-value", nil)
+
+       stdout, stderr, err := runSetCli()
+
+       assert.Nil(t, err)
+       assert.Equal(t, "", stdout)
+       assert.Equal(t, "", stderr)
+       setMocks.sdlIface.AssertExpectations(t)
+}
+
+func TestCliSetCommandFailure(t *testing.T) {
+       expErr := fmt.Errorf("some-error")
+       setupSetCliMock("some-ns", "some-key", "some-value", expErr)
+
+       _, stderr, err := runSetCli()
+
+       assert.Equal(t, expErr, err)
+       assert.Contains(t, stderr, expErr.Error())
+       setMocks.sdlIface.AssertExpectations(t)
+}
index 5321f0c..448515c 100644 (file)
@@ -42,6 +42,7 @@ type DbCreateCb func() *Database
 //iSyncStorage is an interface towards SDL SyncStorage API
 type ISyncStorage interface {
        ListKeys(ns string, pattern string) ([]string, error)
+       Set(ns string, pairs ...interface{}) error
 }
 
 //SyncStorageCreateCb callback function type to create a new SyncStorageInterface
index f6d0791..45fbb78 100644 (file)
@@ -49,3 +49,8 @@ func (m *MockSdlApi) ListKeys(ns string, pattern string) ([]string, error) {
        a := m.Called(ns, pattern)
        return a.Get(0).([]string), a.Error(1)
 }
+
+func (m *MockSdlApi) Set(ns string, pairs ...interface{}) error {
+       a := m.Called(ns, pairs)
+       return a.Error(0)
+}