From c754102aac6de260e2b362b9204caa61dbfe9610 Mon Sep 17 00:00:00 2001
From: Manuel Kieweg <manuel.kieweg@h-da.de>
Date: Tue, 25 May 2021 17:58:57 +0200
Subject: [PATCH] basic tests for grpc client

---
 cli/grpc.go                             | 133 +++-
 cli/grpc_test.go                        | 807 ++++++++++++++++++++++++
 cli/http.go                             |  73 ---
 cmd/addPnd.go                           |  63 ++
 cmd/cliSet.go                           |  13 +-
 cmd/commit.go                           |   7 +-
 cmd/confirm.go                          |   7 +-
 cmd/getIds.go                           |  16 +-
 cmd/getPnd.go                           |  71 +++
 cmd/list.go                             |   6 +-
 cmd/pnd.go                              |  66 ++
 northbound/server/pnd.go                |  58 +-
 test/integration/cliIntegration_test.go | 104 ---
 test/integration/cmdIntegration_test.go |  74 +--
 14 files changed, 1234 insertions(+), 264 deletions(-)
 create mode 100644 cli/grpc_test.go
 delete mode 100644 cli/http.go
 create mode 100644 cmd/addPnd.go
 create mode 100644 cmd/getPnd.go
 create mode 100644 cmd/pnd.go

diff --git a/cli/grpc.go b/cli/grpc.go
index 098f09661..c91dd17dc 100644
--- a/cli/grpc.go
+++ b/cli/grpc.go
@@ -34,19 +34,13 @@ func Init(addr string) error {
 	return nil
 }
 
-func GetIds(addr string) error {
+func GetIds(addr string) ([]*ppb.PrincipalNetworkDomain,error) {
 	ctx := context.Background()
 	resp, err := getAllCore(ctx, addr)
 	if err != nil {
-		return err
-	}
-	for i, pnd := range resp.Pnd {
-		log.Infof("PND %v: %v", i+1, pnd.Id)
-		for j, sbi := range pnd.Sbi {
-			log.Infof("\tSBI %v: %v", j+1, sbi.Id)
-		}
+		return nil, err
 	}
-	return nil
+	return resp.Pnd, nil
 }
 
 func getAllCore(ctx context.Context, addr string) (*pb.GetResponse, error) {
@@ -61,6 +55,99 @@ func getAllCore(ctx context.Context, addr string) (*pb.GetResponse, error) {
 	return coreClient.Get(ctx, req)
 }
 
+func AddPnd(addr, name, description, sbi string) error {
+	coreClient, err := nbi.CoreClient(addr, grpcWithInsecure)
+	if err != nil {
+		return err
+	}
+	ctx := context.Background()
+	req := &pb.SetRequest{
+		Timestamp: time.Now().UnixNano(),
+		Pnd:       []*pb.SetPnd{
+			{
+				Name:        name,
+				Description: description,
+				Sbi:         sbi,
+			},
+		},
+	}
+
+	resp, err := coreClient.Set(ctx, req)
+	if err != nil {
+		return err
+	}
+	log.Info(resp.Status.String())
+	return nil
+}
+
+func GetPnd(addr string, args ...string) (*pb.GetResponse, error) {
+	coreClient, err := nbi.CoreClient(addr, grpcWithInsecure)
+	if err != nil {
+		return nil,err
+	}
+	ctx := context.Background()
+	req := &pb.GetRequest{
+		Timestamp: time.Now().UnixNano(),
+		All:       false,
+		Pid:       args,
+	}
+	return coreClient.Get(ctx, req)
+}
+
+func GetChanges(addr, pnd string) (*ppb.GetResponse, error) {
+	ctx := context.Background()
+	client, err := nbi.PndClient(addr, grpcWithInsecure)
+	if err != nil {
+		return nil, err
+	}
+	req := &ppb.GetRequest{
+		Timestamp: time.Now().UnixNano(),
+		Request: &ppb.GetRequest_Change{
+			Change: &ppb.GetChange{
+				All: true,
+			},
+		},
+		Pid: pnd,
+	}
+	return client.Get(ctx, req)
+}
+
+func Commit(addr, pnd string, cuids ...string) (*ppb.SetResponse,error) {
+	changes := make([]*ppb.SetChange, len(cuids))
+	for i, arg := range cuids {
+		changes[i] = &ppb.SetChange{
+			Cuid: arg,
+			Op:   ppb.SetChange_COMMIT,
+		}
+	}
+	return commitConfirm(addr, pnd, changes)
+}
+
+func Confirm(addr, pnd string, cuids ...string) (*ppb.SetResponse,error) {
+	changes := make([]*ppb.SetChange, len(cuids))
+	for i, arg := range cuids {
+		changes[i] = &ppb.SetChange{
+			Cuid: arg,
+			Op:   ppb.SetChange_CONFIRM,
+		}
+	}
+	return commitConfirm(addr, pnd, changes)
+}
+
+func commitConfirm(addr, pnd string, changes []*ppb.SetChange) (*ppb.SetResponse,error) {
+	ctx := context.Background()
+	client, err := nbi.PndClient(addr, grpcWithInsecure)
+	if err != nil {
+		return nil, err
+	}
+	req := &ppb.SetRequest{
+		Timestamp: time.Now().UnixNano(),
+		Change:    changes,
+		Pid:       pnd,
+	}
+	return client.Set(ctx, req)
+}
+
 func AddDevice(addr, username, password, sbi, pnd, deviceAddress string) error {
 	pndClient, err := nbi.PndClient(addr, grpcWithInsecure)
 	if err != nil {
@@ -90,10 +177,10 @@ func AddDevice(addr, username, password, sbi, pnd, deviceAddress string) error {
 	return nil
 }
 
-func GetDevice(addr, pid, path string, did ...string) error {
+func GetDevice(addr, pid, path string, did ...string) (*ppb.GetResponse,error) {
 	pndClient, err := nbi.PndClient(addr, grpcWithInsecure)
 	if err != nil {
-		return err
+		return nil, err
 	}
 
 	var all bool
@@ -112,15 +199,10 @@ func GetDevice(addr, pid, path string, did ...string) error {
 		Pid: pid,
 	}
 	ctx := context.Background()
-	resp, err := pndClient.Get(ctx, req)
-	if err != nil {
-		return err
-	}
-	log.Info(resp.String())
-	return nil
+	return pndClient.Get(ctx, req)
 }
 
-func Update(addr, did, pid, path, value string) error {
+func Update(addr, did, pid, path, value string) (*ppb.SetResponse, error) {
 	req := &ppb.ChangeRequest{
 		Id:    did,
 		Path:  path,
@@ -130,7 +212,7 @@ func Update(addr, did, pid, path, value string) error {
 	return sendChangeRequest(addr, pid, req)
 }
 
-func Replace(addr, did, pid, path, value string) error {
+func Replace(addr, did, pid, path, value string) (*ppb.SetResponse, error) {
 	req := &ppb.ChangeRequest{
 		Id:    did,
 		Path:  path,
@@ -140,7 +222,7 @@ func Replace(addr, did, pid, path, value string) error {
 	return sendChangeRequest(addr, pid, req)
 }
 
-func Delete(addr, did, pid, path string) error {
+func Delete(addr, did, pid, path string) (*ppb.SetResponse, error) {
 	req := &ppb.ChangeRequest{
 		Id:    did,
 		Path:  path,
@@ -149,10 +231,10 @@ func Delete(addr, did, pid, path string) error {
 	return sendChangeRequest(addr, pid, req)
 }
 
-func sendChangeRequest(addr, pid string, req *ppb.ChangeRequest) error {
+func sendChangeRequest(addr, pid string, req *ppb.ChangeRequest) (*ppb.SetResponse, error) {
 	pndClient, err := nbi.PndClient(addr, grpcWithInsecure)
 	if err != nil {
-		return err
+		return nil, err
 	}
 	ctx := context.Background()
 	r := &ppb.SetRequest{
@@ -160,10 +242,5 @@ func sendChangeRequest(addr, pid string, req *ppb.ChangeRequest) error {
 		ChangeRequest: []*ppb.ChangeRequest{req},
 		Pid:           pid,
 	}
-	resp, err := pndClient.Set(ctx, r)
-	if err != nil {
-		return err
+	return pndClient.Set(ctx, r)
 	}
-	log.Info(resp.String())
-	return nil
-}
diff --git a/cli/grpc_test.go b/cli/grpc_test.go
new file mode 100644
index 000000000..9211ed97b
--- /dev/null
+++ b/cli/grpc_test.go
@@ -0,0 +1,807 @@
+package cli
+
+import (
+	pb "code.fbi.h-da.de/cocsn/api/go/gosdn/core"
+	ppb "code.fbi.h-da.de/cocsn/api/go/gosdn/pnd"
+	nbi "code.fbi.h-da.de/cocsn/gosdn/northbound/server"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
+	"context"
+	log "github.com/sirupsen/logrus"
+	"google.golang.org/grpc"
+	"k8s.io/apimachinery/pkg/util/rand"
+	"net"
+	"reflect"
+	"strconv"
+	"testing"
+	"time"
+)
+
+const unreachable = "203.0.113.10:6030"
+const testPath = "/system/config/hostname"
+const testUser = "admin"
+const testPassword = "admin"
+const testPid = "06aa4994-80f7-4751-99a4-6826b72d0057"
+const testCuid = "cf628f4b-393d-44a5-affb-949dfe5c3c27"
+const testDid = "1c37ff20-0169-44e0-bf37-b64787a979d5"
+
+func startGrpcServer() (*grpc.Server, string, error) {
+	port := rand.IntnRange(1025, 65536)
+	sock := "localhost:" + strconv.Itoa(port)
+	pndc := nucleus.NewPndStore()
+	lis, err := net.Listen("tcp", sock)
+	if err != nil {
+		return nil, "", err
+	}
+	grpcServer := grpc.NewServer()
+	northbound := nbi.NewNBI(pndc)
+	pb.RegisterCoreServer(grpcServer, northbound.Core)
+	ppb.RegisterPndServer(grpcServer, northbound.Pnd)
+	go func() {
+		log.Fatal(grpcServer.Serve(lis))
+	}()
+	return grpcServer, sock, nil
+}
+
+func TestAddDevice(t *testing.T) {
+	type args struct {
+		username      string
+		password      string
+		sbi           string
+		pnd           string
+		deviceAddress string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				username:      testUser,
+				password:      testPassword,
+				sbi:           "openconfig",
+				pnd:           testPid,
+				deviceAddress: "",
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+			if err := AddDevice(sock, tt.args.username, tt.args.password, tt.args.sbi, tt.args.pnd, tt.args.deviceAddress); (err != nil) != tt.wantErr {
+				t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestAddPnd(t *testing.T) {
+	type args struct {
+		name        string
+		description string
+		sbi         string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				name:        "test",
+				description: "test",
+				sbi:         "openconfig",
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+			if err := AddPnd(sock, tt.args.name, tt.args.description, tt.args.sbi); (err != nil) != tt.wantErr {
+				t.Errorf("AddPnd() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestCommit(t *testing.T) {
+	type args struct {
+		pnd   string
+		cuids []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    ppb.SetResponseStatus
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				pnd: testPid,
+				cuids: []string{
+					testCuid,
+				},
+			},
+			want:    ppb.SetResponse_OK,
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := Commit(sock, tt.args.pnd, tt.args.cuids...)
+			if err != nil {
+				if !tt.wantErr {
+					t.Errorf("Commit() error = %v, wantErr %v", err, tt.wantErr)
+				}
+				return
+			}
+			if !reflect.DeepEqual(got.Status, tt.want) {
+				t.Errorf("Commit() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestConfirm(t *testing.T) {
+	type args struct {
+		pnd   string
+		cuids []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    ppb.SetResponseStatus
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				pnd: testPid,
+				cuids: []string{
+					testCuid,
+				},
+			},
+			want:    ppb.SetResponse_OK,
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := Confirm(sock, tt.args.pnd, tt.args.cuids...)
+			if err != nil {
+				if !tt.wantErr {
+					t.Errorf("Confirm() error = %v, wantErr %v", err, tt.wantErr)
+				}
+				return
+			}
+			if !reflect.DeepEqual(got.Status, tt.want) {
+				t.Errorf("Confirm() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestDelete(t *testing.T) {
+	type args struct {
+		did  string
+		pid  string
+		path string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    ppb.SetResponseStatus
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				did:  "",
+				pid:  "",
+				path: "",
+			},
+			want:    ppb.SetResponse_OK,
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := Delete(sock, tt.args.did, tt.args.pid, tt.args.path)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Delete() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Delete() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetChanges(t *testing.T) {
+	type args struct {
+		pnd string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *ppb.GetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				pnd: testPid,
+			},
+			want: &ppb.GetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Pnd:       &ppb.PrincipalNetworkDomain{},
+				Ond:       nil,
+				Sbi:       nil,
+				Change:    nil,
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := GetChanges(sock, tt.args.pnd)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GetChanges() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetChanges() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetDevice(t *testing.T) {
+	type args struct {
+		pid  string
+		path string
+		did  []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *ppb.GetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				pid:  testPid,
+				path: testPath,
+				did:  []string{testDid},
+			},
+			want: &ppb.GetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Ond: []*ppb.OrchestratedNetworkingDevice{
+					{
+						Id:     testDid,
+						Name:   "testOnd",
+						Device: nil,
+						Sbi:    nil,
+					},
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := GetDevice(sock, tt.args.pid, tt.args.path, tt.args.did...)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GetDevice() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetDevice() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetIds(t *testing.T) {
+	tests := []struct {
+		name    string
+		want    []*ppb.PrincipalNetworkDomain
+		wantErr bool
+	}{
+		{
+			name: "default",
+			want: []*ppb.PrincipalNetworkDomain{
+				{
+					Id:          testPid,
+					Name:        "testPnd",
+					Description: "testPnd",
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := GetIds(sock)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GetIds() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetIds() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestGetPnd(t *testing.T) {
+	type args struct {
+		args []string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *pb.GetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{args: []string{testPid}},
+			want: &pb.GetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Pnd: []*ppb.PrincipalNetworkDomain{
+					{
+						Id:          testPid,
+						Name:        "testPnd",
+						Description: "testPnd",
+					},
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := GetPnd(sock, tt.args.args...)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("GetPnd() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("GetPnd() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestInit(t *testing.T) {
+	tests := []struct {
+		name    string
+		wantErr bool
+	}{
+		{
+			name:    "default",
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			if err := Init(sock); (err != nil) != tt.wantErr {
+				t.Errorf("Init() error = %v, wantErr %v", err, tt.wantErr)
+			}
+		})
+	}
+}
+
+func TestReplace(t *testing.T) {
+	type args struct {
+		did   string
+		pid   string
+		path  string
+		value string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *ppb.SetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				did:   testDid,
+				pid:   testPid,
+				path:  testPath,
+				value: "ceos3000",
+			},
+			want: &ppb.SetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Status:    ppb.SetResponse_OK,
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := Replace(sock, tt.args.did, tt.args.pid, tt.args.path, tt.args.value)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Replace() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Replace() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestUpdate(t *testing.T) {
+	type args struct {
+		did   string
+		pid   string
+		path  string
+		value string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *ppb.SetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				did:   testDid,
+				pid:   testPid,
+				path:  testPath,
+				value: "ceos3000",
+			},
+			want: &ppb.SetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Status:    ppb.SetResponse_OK,
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := Update(sock, tt.args.did, tt.args.pid, tt.args.path, tt.args.value)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("Update() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Update() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_commitConfirm(t *testing.T) {
+	type args struct {
+		pnd     string
+		changes []*ppb.SetChange
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *ppb.SetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				pnd: testPid,
+				changes: []*ppb.SetChange{
+					{
+						Cuid: testCuid,
+						Op:   ppb.SetChange_COMMIT,
+					},
+				},
+			},
+			want: &ppb.SetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Status:    ppb.SetResponse_OK,
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := commitConfirm(sock, tt.args.pnd, tt.args.changes)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("commitConfirm() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("commitConfirm() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_getAllCore(t *testing.T) {
+	tests := []struct {
+		name    string
+		want    *pb.GetResponse
+		wantErr bool
+	}{
+		{
+			name: "default",
+			want: &pb.GetResponse{
+				Timestamp: time.Now().UnixNano(),
+				Pnd: []*ppb.PrincipalNetworkDomain{
+					{
+						Id:          testPid,
+						Name:        "testPnd",
+						Description: "testPnd",
+					},
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			ctx := context.Background()
+			got, err := getAllCore(ctx, sock)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("getAllCore() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("getAllCore() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_sendChangeRequest(t *testing.T) {
+	type args struct {
+		pid string
+		req *ppb.ChangeRequest
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    *ppb.SetResponse
+		wantErr bool
+	}{
+		{
+			name: "update",
+			args: args{
+				pid: testPid,
+				req: &ppb.ChangeRequest{
+					Id:    testCuid,
+					Path:  testPath,
+					Value: "ceos3000",
+					ApiOp: ppb.ChangeRequest_UPDATE,
+				},
+			},
+			want:    nil,
+			wantErr: false,
+		},
+		{
+			name: "replace",
+			args: args{
+				pid: testPid,
+				req: &ppb.ChangeRequest{
+					Id:    testCuid,
+					Path:  testPath,
+					Value: "ceos3000",
+					ApiOp: ppb.ChangeRequest_REPLACE,
+				},
+			},
+			want:    nil,
+			wantErr: false,
+		},
+		{
+			name: "delete",
+			args: args{
+				pid: testPid,
+				req: &ppb.ChangeRequest{
+					Id:    testCuid,
+					Path:  testPath,
+					ApiOp: ppb.ChangeRequest_DELETE,
+				},
+			},
+			want:    nil,
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			server, sock, err := startGrpcServer()
+			if err != nil {
+				if !tt.wantErr {
+					t.Error("startGrpcServer() error = cannot start grpc server")
+				}
+				return
+			}
+			defer server.Stop()
+			if tt.name == "unreachable" {
+				sock = unreachable
+			}
+
+			got, err := sendChangeRequest(sock, tt.args.pid, tt.args.req)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("sendChangeRequest() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("sendChangeRequest() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/cli/http.go b/cli/http.go
deleted file mode 100644
index b7c3254b6..000000000
--- a/cli/http.go
+++ /dev/null
@@ -1,73 +0,0 @@
-package cli
-
-import (
-	"errors"
-	"fmt"
-	"io/ioutil"
-	"net/http"
-	"strings"
-
-	log "github.com/sirupsen/logrus"
-	"github.com/spf13/viper"
-)
-
-const apiRoot = "?"
-
-var builder *strings.Builder
-
-func init() {
-	builder = &strings.Builder{}
-}
-
-// HTTPGet sends sends requests from the CLI to the gosdn HTTP API and processes any response data
-func HTTPGet(apiEndpoint, f string, args ...string) error {
-	for _, p := range args {
-		builder.WriteString("&")
-		builder.WriteString(p)
-	}
-	resp, err := http.Get(apiEndpoint + apiRoot + "q=" + f + builder.String())
-	if err != nil {
-		log.Info(fmt.Sprintf("Err: %s", err))
-		return err
-	}
-	builder.Reset()
-	switch resp.StatusCode {
-	case http.StatusOK:
-		defer resp.Body.Close()
-		bytes, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			return err
-		}
-		switch f {
-		case "init":
-			pnd := string(bytes[9:45])
-			sbi := string(bytes[55:91])
-			viper.Set("CLI_PND", pnd)
-			viper.Set("CLI_SBI", sbi)
-			err := viper.WriteConfig()
-			if err != nil {
-				log.Error(err)
-			}
-		default:
-			fmt.Println(string(bytes))
-		}
-
-	case http.StatusCreated:
-		defer resp.Body.Close()
-		bytes, err := ioutil.ReadAll(resp.Body)
-		if err != nil {
-			return err
-		}
-		uuid := string(bytes[19:55])
-		viper.Set("LAST_DEVICE_UUID", uuid)
-		fmt.Println(string(bytes))
-
-	case http.StatusAccepted:
-	default:
-		log.WithFields(log.Fields{
-			"status code": resp.StatusCode,
-		}).Error("operation unsuccessful")
-		return errors.New(resp.Status)
-	}
-	return nil
-}
diff --git a/cmd/addPnd.go b/cmd/addPnd.go
new file mode 100644
index 000000000..e4e59c253
--- /dev/null
+++ b/cmd/addPnd.go
@@ -0,0 +1,63 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	"github.com/spf13/cobra"
+)
+
+// addCmd represents the add command
+var addCmd = &cobra.Command{
+	Use:   "add",
+	Short: "adds a new principal network domain to the controller",
+	Long: `A principal network domain is a main networking entity. This can be a
+campus building or site.
+
+A description must be passed as positional argument. A name and default SBI can be
+passed using flags`,
+	Args: cobra.ExactArgs(1),
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.AddPnd(apiEndpoint, pndName, args[0], pndDefaultSbi)
+	},
+}
+
+var pndName string
+var pndDefaultSbi string
+
+func init() {
+	pndCmd.AddCommand(addCmd)
+
+	addCmd.Flags().StringVar(&pndName, "name", "", "the name of the pnd")
+	addCmd.Flags().StringVar(&pndDefaultSbi, "sbi", "openconfig", "the default SBI of the pnd")
+
+}
diff --git a/cmd/cliSet.go b/cmd/cliSet.go
index e3f3a0743..118701920 100644
--- a/cmd/cliSet.go
+++ b/cmd/cliSet.go
@@ -46,15 +46,12 @@ only one value supported for now.
 
 Use "set replace" or "set delete" respectively`,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HTTPGet(
+		return cli.Update(
 			apiEndpoint,
-			"update",
-			"uuid="+uuid,
-			"cliSbi="+cliSbi,
-			"cliPnd="+cliPnd,
-			"path="+args[0],
-			"address="+address,
-			"value="+args[1],
+			uuid,
+			cliPnd,
+			args[0],
+			args[1],
 		)
 	},
 }
diff --git a/cmd/commit.go b/cmd/commit.go
index a6ccb3b10..8ad11bcae 100644
--- a/cmd/commit.go
+++ b/cmd/commit.go
@@ -43,11 +43,10 @@ var commitCmd = &cobra.Command{
 	Short: "Commit the given change for the active PND",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HTTPGet(
+		return cli.Commit(
 			apiEndpoint,
-			"change-commit",
-			"pnd="+cliPnd,
-			"cuid="+args[0],
+			cliPnd,
+			args[0],
 		)
 	},
 }
diff --git a/cmd/confirm.go b/cmd/confirm.go
index 59cda7698..9e719aee9 100644
--- a/cmd/confirm.go
+++ b/cmd/confirm.go
@@ -43,11 +43,10 @@ var confirmCmd = &cobra.Command{
 	Short: "Confirms the given change for the active PND",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HTTPGet(
+		return cli.Confirm(
 			apiEndpoint,
-			"change-confirm",
-			"pnd="+cliPnd,
-			"cuid="+args[0],
+			cliPnd,
+			args[0],
 		)
 	},
 }
diff --git a/cmd/getIds.go b/cmd/getIds.go
index 4aeebef79..b302f872a 100644
--- a/cmd/getIds.go
+++ b/cmd/getIds.go
@@ -33,6 +33,7 @@ package cmd
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	log "github.com/sirupsen/logrus"
 	"github.com/spf13/cobra"
 )
 
@@ -42,7 +43,20 @@ var getIdsCmd = &cobra.Command{
 	Short: "gets device IDs from the controller",
 	Long:  `Gets device IDs from the controller and lists them.`,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.GetIds(apiEndpoint)
+		resp, err := cli.GetIds(apiEndpoint)
+		if err != nil {
+			return err
+		}
+		for i, pnd := range resp {
+			log.Infof("PND %v: %v\n\tuuid: %v", i+1, pnd.Name, pnd.Id)
+			for j, ond := range pnd.Ond {
+				log.Infof("\tSBI %v: %v\n\tuuid: %v", j+1, ond.Name, ond.Id)
+			}
+			for k, sbi := range pnd.Sbi {
+				log.Infof("\tSBI %v: %v", k+1, sbi.Id)
+			}
+		}
+		return nil
 	},
 }
 
diff --git a/cmd/getPnd.go b/cmd/getPnd.go
new file mode 100644
index 000000000..c929efc35
--- /dev/null
+++ b/cmd/getPnd.go
@@ -0,0 +1,71 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package cmd
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+	log "github.com/sirupsen/logrus"
+	"github.com/spf13/cobra"
+)
+
+// getCmd represents the get command
+var getCmd = &cobra.Command{
+	Use:   "get",
+	Short: "get one or multiple pnds by uuid or name and print them to stdout",
+	Long: ``,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		resp, err := cli.GetPnd(apiEndpoint, args...)
+		if err != nil {
+			return err
+		}
+		for i, pnd := range resp {
+			log.Infof("PND %v: %v\n\tuuid: %v", i+1, pnd.Name, pnd.Id)
+			if verbose {
+				for j, ond := range pnd.Ond {
+					log.Infof("\tSBI %v: %v\n\tuuid: %v", j+1, ond.Name, ond.Id)
+				}
+				for k, sbi := range pnd.Sbi {
+					log.Infof("\tSBI %v: %v", k+1, sbi.Id)
+				}
+			}
+		}
+		return nil
+	},
+}
+
+var verbose bool
+
+func init() {
+	pndCmd.AddCommand(getCmd)
+
+	pndCmd.Flags().BoolVar(&verbose, "verbose", false, "show ond and sbi info")
+}
diff --git a/cmd/list.go b/cmd/list.go
index 198662268..c5163e7b9 100644
--- a/cmd/list.go
+++ b/cmd/list.go
@@ -42,11 +42,7 @@ var listCmd = &cobra.Command{
 	Short: "Lists all committed changes",
 	Long:  ``,
 	RunE: func(cmd *cobra.Command, args []string) error {
-		return cli.HTTPGet(
-			apiEndpoint,
-			"change-list",
-			"pnd="+cliPnd,
-		)
+		return cli.ListChanges(apiEndpoint, cliPnd)
 	},
 }
 
diff --git a/cmd/pnd.go b/cmd/pnd.go
new file mode 100644
index 000000000..4a3cdd32d
--- /dev/null
+++ b/cmd/pnd.go
@@ -0,0 +1,66 @@
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+*/
+package cmd
+
+import (
+	"fmt"
+
+	"github.com/spf13/cobra"
+)
+
+// pndCmd represents the pnd command
+var pndCmd = &cobra.Command{
+	Use:   "pnd",
+	Short: "A brief description of your command",
+	Long: `A longer description that spans multiple lines and likely contains examples
+and usage of using your command. For example:
+
+Cobra is a CLI library for Go that empowers applications.
+This application is a tool to generate the needed files
+to quickly create a Cobra application.`,
+	Run: func(cmd *cobra.Command, args []string) {
+		fmt.Println("pnd called")
+	},
+}
+
+func init() {
+	cliCmd.AddCommand(pndCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// pndCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// pndCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/northbound/server/pnd.go b/northbound/server/pnd.go
index e694a2c52..bcabcd07f 100644
--- a/northbound/server/pnd.go
+++ b/northbound/server/pnd.go
@@ -184,5 +184,61 @@ func fillChanges(pnd nucleus.PrincipalNetworkDomain) ([]*ppb.Change, error) {
 }
 
 func (p pnd) Set(ctx context.Context, request *ppb.SetRequest) (*ppb.SetResponse, error) {
-	panic("implement me")
+	pid, err := uuid.Parse(request.Pid)
+	if err != nil {
+		return nil, err
+	}
+	ondResp, err := handleSetOnd(pid, request.Ond)
+	if err != nil {
+		return nil, err
+	}
+	sbiResp, err := handleSetSbi(pid, request.Sbi)
+	if err != nil {
+		return nil, err
+	}
+	changeResp, err := handleSetChange(pid, request.Change)
+	if err != nil {
+		return nil, err
+	}
+	changeRequestResp, err := handleChangeRequest(pid, request.ChangeRequest)
+	if err != nil {
+		return nil, err
+	}
+	return &ppb.SetResponse{
+		Timestamp: time.Now().UnixNano(),
+		Status:    ppb.SetResponse_OK,
+		Responses: []*ppb.SetResponse{
+			ondResp,
+			sbiResp,
+			changeResp,
+			changeRequestResp,
+		},
+	}, nil
+}
+
+func handleSetOnd(pid uuid.UUID, req []*ppb.SetOnd) (*ppb.SetResponse, error) {
+	pndLock.Lock()
+	defer pndLock.Unlock()
+	pnd, err := pndc.Get(pid)
+	if err != nil {
+		return nil, err
+	}
+	for _,r := range req {
+		d, err := nucleus.NewDevice()
+		if err != nil {
+			return nil, err
+		}
+	}
+}
+
+func handleSetSbi(pid uuid.UUID, req []*ppb.SetSbi) (*ppb.SetResponse, error) {
+
+}
+
+func handleSetChange(pid uuid.UUID, change []*ppb.SetChange) (*ppb.SetResponse, error) {
+
+}
+
+func handleChangeRequest(pid uuid.UUID, req []*ppb.ChangeRequest) (*ppb.SetResponse, error) {
+
 }
diff --git a/test/integration/cliIntegration_test.go b/test/integration/cliIntegration_test.go
index dac342c5d..77e6efbd3 100644
--- a/test/integration/cliIntegration_test.go
+++ b/test/integration/cliIntegration_test.go
@@ -48,51 +48,6 @@ func TestCapabilities(t *testing.T) {
 	}
 }
 
-func TestGet(t *testing.T) {
-	if testing.Short() {
-		t.Skip("skipping integration test")
-	}
-	type args struct {
-		a    string
-		u    string
-		p    string
-		args []string
-	}
-	tests := []struct {
-		name    string
-		args    args
-		wantErr bool
-	}{
-		{
-			name: "default",
-			args: args{
-				a:    testAddress,
-				u:    testUsername,
-				p:    testPassword,
-				args: defaultPath,
-			},
-			wantErr: false,
-		},
-		{
-			name: "destination unreachable",
-			args: args{
-				a:    unreachable,
-				u:    testUsername,
-				p:    testPassword,
-				args: defaultPath,
-			},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if _, err := cli.Get(tt.args.a, tt.args.u, tt.args.p, tt.args.args...); (err != nil) != tt.wantErr {
-				t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
-			}
-		})
-	}
-}
-
 func TestHttpGet(t *testing.T) {
 	if testing.Short() {
 		t.Skip("skipping integration test")
@@ -134,62 +89,3 @@ func TestHttpGet(t *testing.T) {
 		})
 	}
 }
-
-func TestSet(t *testing.T) {
-	if testing.Short() {
-		t.Skip("skipping integration test")
-	}
-	type args struct {
-		a    string
-		u    string
-		p    string
-		typ  string
-		args []string
-	}
-	tests := []struct {
-		name    string
-		args    args
-		wantErr bool
-	}{
-		{
-			name: "default",
-			args: args{
-				a:    testAddress,
-				u:    testUsername,
-				p:    testPassword,
-				typ:  "update",
-				args: []string{"/system/config/hostname", "ceos3000"},
-			},
-			wantErr: false,
-		},
-		{
-			name: "destination unreachable",
-			args: args{
-				a:    unreachable,
-				u:    testUsername,
-				p:    testPassword,
-				typ:  "update",
-				args: []string{"/system/config/hostname", "ceos3000"},
-			},
-			wantErr: true,
-		},
-		{
-			name: "invalid path",
-			args: args{
-				a:    testAddress,
-				u:    testUsername,
-				p:    testPassword,
-				typ:  "update",
-				args: []string{"invalid/path", "ceos3000"},
-			},
-			wantErr: true,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if err := cli.Set(tt.args.a, tt.args.u, tt.args.p, tt.args.typ, tt.args.args...); (err != nil) != tt.wantErr {
-				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
-			}
-		})
-	}
-}
diff --git a/test/integration/cmdIntegration_test.go b/test/integration/cmdIntegration_test.go
index cfe01aad5..1a5d53802 100644
--- a/test/integration/cmdIntegration_test.go
+++ b/test/integration/cmdIntegration_test.go
@@ -16,12 +16,12 @@ import (
 )
 
 const unreachable = "203.0.113.10:6030"
+const testPath = "/system/config/hostname"
 
 var testAddress = "141.100.70.171:6030"
 var testAPIEndpoint = "http://gosdn-latest.apps.ocp.fbi.h-da.de/api"
 var testUsername = "admin"
 var testPassword = "arista"
-var defaultPath = []string{"/system/config/hostname"}
 var opt *nucleus.GnmiTransportOptions
 
 func TestMain(m *testing.M) {
@@ -102,7 +102,7 @@ func TestCmdIntegration(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			defer viper.Reset()
-			if err := cli.HTTPGet(testAPIEndpoint, "init"); (err != nil) != tt.wantErr {
+			if err := cli.Init(testAPIEndpoint); (err != nil) != tt.wantErr {
 				switch err.(type) {
 				case viper.ConfigFileNotFoundError:
 				default:
@@ -113,65 +113,67 @@ func TestCmdIntegration(t *testing.T) {
 			cliPnd := viper.GetString("CLI_PND")
 			cliSbi := viper.GetString("CLI_SBI")
 
-			if err := cli.HTTPGet(
+			if err := cli.AddDevice(
 				testAPIEndpoint,
-				"addDevice",
-				"address="+testAddress,
-				"password="+testPassword,
-				"username="+testUsername,
-				"sbi="+cliSbi,
-				"pnd="+cliPnd,
+				testUsername,
+				testPassword,
+				cliSbi,
+				cliPnd,
+				testAddress,
 			); (err != nil) != tt.wantErr {
 				t.Errorf("gosdn cli add-device error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
 			did := viper.GetString("LAST_DEVICE_UUID")
 
-			if err := cli.HTTPGet(
+			_, err := cli.GetDevice(
 				testAPIEndpoint,
-				"request",
-				"uuid="+did,
-				"sbi="+cliSbi,
-				"pnd="+cliPnd,
-				"path=/system/config/hostname",
-			); (err != nil) != tt.wantErr {
+				cliPnd,
+				testPath,
+				did,
+			)
+			if (err != nil) != tt.wantErr {
 				t.Errorf("gosdn cli request error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
 
-			if err := cli.HTTPGet(
+			_, err = cli.GetDevice(
 				testAPIEndpoint,
-				"getDevice",
-				"address="+testAddress,
-				"uuid="+did,
-				"sbi="+cliSbi,
-				"pnd="+cliPnd,
-			); (err != nil) != tt.wantErr {
+				cliPnd,
+				"",
+				did,
+			)
+			if (err != nil) != tt.wantErr {
 				t.Errorf("gosdn cli get-device error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
 
 			hostname := guuid.New().String()
-			if err := cli.HTTPGet(
+			_, err = cli.Update(
 				testAPIEndpoint,
-				"update",
-				"address="+testAddress,
-				"uuid="+did,
-				"sbi="+cliSbi,
-				"pnd="+cliPnd,
-				"path=/system/config/hostname",
-				"value="+hostname,
-			); (err != nil) != tt.wantErr {
+				did,
+				cliPnd,
+				testPath,
+				hostname,
+			)
+			if (err != nil) != tt.wantErr {
 				t.Errorf("gosdn cli set error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
 
-			resp, err := cli.Get(testAddress, testUsername, testPassword, "/system/config/hostname")
-			if (err != nil) != tt.wantErr {
-				t.Errorf("cli.Get() error = %v, wantErr %v", err, tt.wantErr)
+			resp, err := cli.GetDevice(testAddress, testUsername, testPassword, testPath)
+			if err != nil {
+				if  !tt.wantErr {
+					t.Errorf("cli.Get() error = %v, wantErr %v", err, tt.wantErr)
+				}
 				return
 			}
-			got := resp.Notification[0].Update[0].Val.GetStringVal()
+			var got string
+			if resp != nil {
+				got = resp.Ond[0].Name
+			} else {
+				t.Errorf("integration test failed got cannot be nil")
+			}
 			if got != hostname {
 				t.Errorf("integration test failed = got: %v, want: %v", got, hostname)
 			}
-- 
GitLab