Skip to content
Snippets Groups Projects
Commit c754102a authored by Manuel Kieweg's avatar Manuel Kieweg
Browse files

basic tests for grpc client

parent 94504d80
No related branches found
No related tags found
1 merge request!155Northbound Interface
Pipeline #71958 failed
......@@ -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
}
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)
}
})
}
}
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
}
/*
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")
}
......@@ -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],
)
},
}
......
......@@ -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],
)
},
}
......
......@@ -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],
)
},
}
......
......@@ -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
},
}
......
/*
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")
}
......@@ -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)
},
}
......
/*
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")
}
......@@ -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) {
}
......@@ -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)
}
})
}
}
......@@ -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)
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment