diff --git a/.cobra.yaml b/.cobra.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..781bc21df45db1f7d98acc65acecc2b5e674b467
--- /dev/null
+++ b/.cobra.yaml
@@ -0,0 +1,3 @@
+author: da/net research group <danet.fbi.h-da.de>
+year: 2021
+license: BSD
diff --git a/LICENSE b/LICENSE
index c73f25619885d45b7f7443839b91af6c1596b7a1..fd4861958aee4dcc8a061639bb5c13544437766a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,21 +1,19 @@
-BSD 3-Clause License
-
-Copyright (c) 2020, da/net
+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:
 
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
 
-* 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.
+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.
 
-* 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.
+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
diff --git a/api/proto/gosdnCLI.pb.go b/api/proto/gosdnCLI.pb.go
deleted file mode 100644
index e6b62456650a6a4ca00bb9def32281e9752180f1..0000000000000000000000000000000000000000
--- a/api/proto/gosdnCLI.pb.go
+++ /dev/null
@@ -1,1851 +0,0 @@
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.25.0-devel
-// 	protoc        v3.14.0
-// source: gosdnCLI.proto
-
-package gosdn
-
-import (
-	context "context"
-	grpc "google.golang.org/grpc"
-	codes "google.golang.org/grpc/codes"
-	status "google.golang.org/grpc/status"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	emptypb "google.golang.org/protobuf/types/known/emptypb"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// The request message containing the user's name.
-type HelloRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-}
-
-func (x *HelloRequest) Reset() {
-	*x = HelloRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *HelloRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*HelloRequest) ProtoMessage() {}
-
-func (x *HelloRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use HelloRequest.ProtoReflect.Descriptor instead.
-func (*HelloRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *HelloRequest) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-// The response message containing the greetings
-type HelloReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Message   string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
-	GoSDNInfo string `protobuf:"bytes,2,opt,name=goSDNInfo,proto3" json:"goSDNInfo,omitempty"`
-}
-
-func (x *HelloReply) Reset() {
-	*x = HelloReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[1]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *HelloReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*HelloReply) ProtoMessage() {}
-
-func (x *HelloReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[1]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use HelloReply.ProtoReflect.Descriptor instead.
-func (*HelloReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{1}
-}
-
-func (x *HelloReply) GetMessage() string {
-	if x != nil {
-		return x.Message
-	}
-	return ""
-}
-
-func (x *HelloReply) GetGoSDNInfo() string {
-	if x != nil {
-		return x.GoSDNInfo
-	}
-	return ""
-}
-
-// Request to shutdown goSDN
-type ShutdownRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-}
-
-func (x *ShutdownRequest) Reset() {
-	*x = ShutdownRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[2]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *ShutdownRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ShutdownRequest) ProtoMessage() {}
-
-func (x *ShutdownRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[2]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use ShutdownRequest.ProtoReflect.Descriptor instead.
-func (*ShutdownRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{2}
-}
-
-func (x *ShutdownRequest) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-// The response message containing some shutdown notes of goSDN
-type ShutdownReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
-}
-
-func (x *ShutdownReply) Reset() {
-	*x = ShutdownReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[3]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *ShutdownReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ShutdownReply) ProtoMessage() {}
-
-func (x *ShutdownReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[3]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use ShutdownReply.ProtoReflect.Descriptor instead.
-func (*ShutdownReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{3}
-}
-
-func (x *ShutdownReply) GetMessage() string {
-	if x != nil {
-		return x.Message
-	}
-	return ""
-}
-
-// Request with no meaning by now
-type TAPIRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-}
-
-func (x *TAPIRequest) Reset() {
-	*x = TAPIRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[4]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *TAPIRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*TAPIRequest) ProtoMessage() {}
-
-func (x *TAPIRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[4]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use TAPIRequest.ProtoReflect.Descriptor instead.
-func (*TAPIRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{4}
-}
-
-func (x *TAPIRequest) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-// The response message containing a string with no meaning by now
-type TAPIReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
-}
-
-func (x *TAPIReply) Reset() {
-	*x = TAPIReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[5]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *TAPIReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*TAPIReply) ProtoMessage() {}
-
-func (x *TAPIReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[5]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use TAPIReply.ProtoReflect.Descriptor instead.
-func (*TAPIReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{5}
-}
-
-func (x *TAPIReply) GetMessage() string {
-	if x != nil {
-		return x.Message
-	}
-	return ""
-}
-
-//
-type CreatePNDRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Name        string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
-	Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
-	Sbi         string `protobuf:"bytes,3,opt,name=sbi,proto3" json:"sbi,omitempty"`
-}
-
-func (x *CreatePNDRequest) Reset() {
-	*x = CreatePNDRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[6]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CreatePNDRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CreatePNDRequest) ProtoMessage() {}
-
-func (x *CreatePNDRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[6]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CreatePNDRequest.ProtoReflect.Descriptor instead.
-func (*CreatePNDRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{6}
-}
-
-func (x *CreatePNDRequest) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-func (x *CreatePNDRequest) GetDescription() string {
-	if x != nil {
-		return x.Description
-	}
-	return ""
-}
-
-func (x *CreatePNDRequest) GetSbi() string {
-	if x != nil {
-		return x.Sbi
-	}
-	return ""
-}
-
-type AllSBINamesReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	SbiNames []string `protobuf:"bytes,1,rep,name=sbiNames,proto3" json:"sbiNames,omitempty"`
-}
-
-func (x *AllSBINamesReply) Reset() {
-	*x = AllSBINamesReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[7]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AllSBINamesReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AllSBINamesReply) ProtoMessage() {}
-
-func (x *AllSBINamesReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[7]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AllSBINamesReply.ProtoReflect.Descriptor instead.
-func (*AllSBINamesReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{7}
-}
-
-func (x *AllSBINamesReply) GetSbiNames() []string {
-	if x != nil {
-		return x.SbiNames
-	}
-	return nil
-}
-
-//
-type CreatePNDReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
-}
-
-func (x *CreatePNDReply) Reset() {
-	*x = CreatePNDReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[8]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *CreatePNDReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CreatePNDReply) ProtoMessage() {}
-
-func (x *CreatePNDReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[8]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use CreatePNDReply.ProtoReflect.Descriptor instead.
-func (*CreatePNDReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{8}
-}
-
-func (x *CreatePNDReply) GetMessage() string {
-	if x != nil {
-		return x.Message
-	}
-	return ""
-}
-
-//
-type AllPNDsReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Pnds []*PND `protobuf:"bytes,1,rep,name=pnds,proto3" json:"pnds,omitempty"`
-}
-
-func (x *AllPNDsReply) Reset() {
-	*x = AllPNDsReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[9]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AllPNDsReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AllPNDsReply) ProtoMessage() {}
-
-func (x *AllPNDsReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[9]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AllPNDsReply.ProtoReflect.Descriptor instead.
-func (*AllPNDsReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{9}
-}
-
-func (x *AllPNDsReply) GetPnds() []*PND {
-	if x != nil {
-		return x.Pnds
-	}
-	return nil
-}
-
-type PND struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Uuid        string    `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
-	Name        string    `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
-	Description string    `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
-	Sbi         string    `protobuf:"bytes,4,opt,name=sbi,proto3" json:"sbi,omitempty"`
-	Devices     []*Device `protobuf:"bytes,5,rep,name=devices,proto3" json:"devices,omitempty"`
-}
-
-func (x *PND) Reset() {
-	*x = PND{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[10]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *PND) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*PND) ProtoMessage() {}
-
-func (x *PND) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[10]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use PND.ProtoReflect.Descriptor instead.
-func (*PND) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{10}
-}
-
-func (x *PND) GetUuid() string {
-	if x != nil {
-		return x.Uuid
-	}
-	return ""
-}
-
-func (x *PND) GetName() string {
-	if x != nil {
-		return x.Name
-	}
-	return ""
-}
-
-func (x *PND) GetDescription() string {
-	if x != nil {
-		return x.Description
-	}
-	return ""
-}
-
-func (x *PND) GetSbi() string {
-	if x != nil {
-		return x.Sbi
-	}
-	return ""
-}
-
-func (x *PND) GetDevices() []*Device {
-	if x != nil {
-		return x.Devices
-	}
-	return nil
-}
-
-type Device struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Uuid     string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"`
-	Address  string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
-	Username string `protobuf:"bytes,3,opt,name=username,proto3" json:"username,omitempty"`
-	Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
-}
-
-func (x *Device) Reset() {
-	*x = Device{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[11]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *Device) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Device) ProtoMessage() {}
-
-func (x *Device) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[11]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use Device.ProtoReflect.Descriptor instead.
-func (*Device) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{11}
-}
-
-func (x *Device) GetUuid() string {
-	if x != nil {
-		return x.Uuid
-	}
-	return ""
-}
-
-func (x *Device) GetAddress() string {
-	if x != nil {
-		return x.Address
-	}
-	return ""
-}
-
-func (x *Device) GetUsername() string {
-	if x != nil {
-		return x.Username
-	}
-	return ""
-}
-
-func (x *Device) GetPassword() string {
-	if x != nil {
-		return x.Password
-	}
-	return ""
-}
-
-type AddDeviceRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	UuidPND string  `protobuf:"bytes,1,opt,name=uuidPND,proto3" json:"uuidPND,omitempty"`
-	Device  *Device `protobuf:"bytes,2,opt,name=device,proto3" json:"device,omitempty"`
-}
-
-func (x *AddDeviceRequest) Reset() {
-	*x = AddDeviceRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[12]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AddDeviceRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AddDeviceRequest) ProtoMessage() {}
-
-func (x *AddDeviceRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[12]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AddDeviceRequest.ProtoReflect.Descriptor instead.
-func (*AddDeviceRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{12}
-}
-
-func (x *AddDeviceRequest) GetUuidPND() string {
-	if x != nil {
-		return x.UuidPND
-	}
-	return ""
-}
-
-func (x *AddDeviceRequest) GetDevice() *Device {
-	if x != nil {
-		return x.Device
-	}
-	return nil
-}
-
-type AddDeviceReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
-}
-
-func (x *AddDeviceReply) Reset() {
-	*x = AddDeviceReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[13]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *AddDeviceReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AddDeviceReply) ProtoMessage() {}
-
-func (x *AddDeviceReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[13]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use AddDeviceReply.ProtoReflect.Descriptor instead.
-func (*AddDeviceReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{13}
-}
-
-func (x *AddDeviceReply) GetMessage() string {
-	if x != nil {
-		return x.Message
-	}
-	return ""
-}
-
-type DeviceGetRequest struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	UuidPND    string `protobuf:"bytes,1,opt,name=uuidPND,proto3" json:"uuidPND,omitempty"`
-	UuidDevice string `protobuf:"bytes,2,opt,name=uuidDevice,proto3" json:"uuidDevice,omitempty"`
-	Path       string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
-}
-
-func (x *DeviceGetRequest) Reset() {
-	*x = DeviceGetRequest{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[14]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *DeviceGetRequest) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*DeviceGetRequest) ProtoMessage() {}
-
-func (x *DeviceGetRequest) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[14]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use DeviceGetRequest.ProtoReflect.Descriptor instead.
-func (*DeviceGetRequest) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{14}
-}
-
-func (x *DeviceGetRequest) GetUuidPND() string {
-	if x != nil {
-		return x.UuidPND
-	}
-	return ""
-}
-
-func (x *DeviceGetRequest) GetUuidDevice() string {
-	if x != nil {
-		return x.UuidDevice
-	}
-	return ""
-}
-
-func (x *DeviceGetRequest) GetPath() string {
-	if x != nil {
-		return x.Path
-	}
-	return ""
-}
-
-type DeviceGetReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
-}
-
-func (x *DeviceGetReply) Reset() {
-	*x = DeviceGetReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[15]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *DeviceGetReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*DeviceGetReply) ProtoMessage() {}
-
-func (x *DeviceGetReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[15]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use DeviceGetReply.ProtoReflect.Descriptor instead.
-func (*DeviceGetReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{15}
-}
-
-func (x *DeviceGetReply) GetMessage() string {
-	if x != nil {
-		return x.Message
-	}
-	return ""
-}
-
-// The response message containing a string with a goSDN log
-type LogReply struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	Log string `protobuf:"bytes,1,opt,name=log,proto3" json:"log,omitempty"`
-}
-
-func (x *LogReply) Reset() {
-	*x = LogReply{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_gosdnCLI_proto_msgTypes[16]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *LogReply) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*LogReply) ProtoMessage() {}
-
-func (x *LogReply) ProtoReflect() protoreflect.Message {
-	mi := &file_gosdnCLI_proto_msgTypes[16]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use LogReply.ProtoReflect.Descriptor instead.
-func (*LogReply) Descriptor() ([]byte, []int) {
-	return file_gosdnCLI_proto_rawDescGZIP(), []int{16}
-}
-
-func (x *LogReply) GetLog() string {
-	if x != nil {
-		return x.Log
-	}
-	return ""
-}
-
-var File_gosdnCLI_proto protoreflect.FileDescriptor
-
-var file_gosdnCLI_proto_rawDesc = []byte{
-	0x0a, 0x0e, 0x67, 0x6f, 0x73, 0x64, 0x6e, 0x43, 0x4c, 0x49, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x22, 0x22, 0x0a, 0x0c, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x44, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c,
-	0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x12, 0x1c, 0x0a, 0x09, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x02, 0x20,
-	0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x53, 0x44, 0x4e, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x25,
-	0x0a, 0x0f, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
-	0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x29, 0x0a, 0x0d, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77,
-	0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x22, 0x21, 0x0a, 0x0b, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
-	0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x22, 0x25, 0x0a, 0x09, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79,
-	0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x5a, 0x0a, 0x10, 0x43, 0x72,
-	0x65, 0x61, 0x74, 0x65, 0x50, 0x4e, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
-	0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
-	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x03, 0x73, 0x62, 0x69, 0x22, 0x2e, 0x0a, 0x10, 0x41, 0x6c, 0x6c, 0x53, 0x42, 0x49,
-	0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x62,
-	0x69, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x62,
-	0x69, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x2a, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
-	0x50, 0x4e, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61,
-	0x67, 0x65, 0x22, 0x2e, 0x0a, 0x0c, 0x41, 0x6c, 0x6c, 0x50, 0x4e, 0x44, 0x73, 0x52, 0x65, 0x70,
-	0x6c, 0x79, 0x12, 0x1e, 0x0a, 0x04, 0x70, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
-	0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x4e, 0x44, 0x52, 0x04, 0x70, 0x6e,
-	0x64, 0x73, 0x22, 0x8a, 0x01, 0x0a, 0x03, 0x50, 0x4e, 0x44, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75,
-	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x12,
-	0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
-	0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
-	0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
-	0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x62, 0x69, 0x18, 0x04, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x03, 0x73, 0x62, 0x69, 0x12, 0x27, 0x0a, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65,
-	0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
-	0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x07, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x22,
-	0x6e, 0x0a, 0x06, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69,
-	0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x18, 0x0a,
-	0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
-	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e,
-	0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18,
-	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22,
-	0x53, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75,
-	0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x18, 0x01,
-	0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x12, 0x25, 0x0a,
-	0x06, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x06, 0x64, 0x65,
-	0x76, 0x69, 0x63, 0x65, 0x22, 0x2a, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63,
-	0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
-	0x22, 0x60, 0x0a, 0x10, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71,
-	0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x75, 0x75, 0x69, 0x64, 0x50, 0x4e, 0x44, 0x12, 0x1e,
-	0x0a, 0x0a, 0x75, 0x75, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01,
-	0x28, 0x09, 0x52, 0x0a, 0x75, 0x75, 0x69, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12,
-	0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61,
-	0x74, 0x68, 0x22, 0x2a, 0x0a, 0x0e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52,
-	0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
-	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1c,
-	0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f,
-	0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x32, 0xb0, 0x05, 0x0a,
-	0x07, 0x47, 0x72, 0x70, 0x63, 0x43, 0x6c, 0x69, 0x12, 0x34, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48,
-	0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x6c,
-	0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3a,
-	0x0a, 0x08, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
-	0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x68, 0x75, 0x74, 0x64,
-	0x6f, 0x77, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x3e, 0x0a, 0x0f, 0x43, 0x72,
-	0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e,
-	0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
-	0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x6f,
-	0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x35, 0x0a, 0x0b, 0x54, 0x41,
-	0x50, 0x49, 0x47, 0x65, 0x74, 0x45, 0x64, 0x67, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22,
-	0x00, 0x12, 0x39, 0x0a, 0x0f, 0x54, 0x41, 0x50, 0x49, 0x47, 0x65, 0x74, 0x45, 0x64, 0x67, 0x65,
-	0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50,
-	0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x35, 0x0a, 0x0b,
-	0x54, 0x41, 0x50, 0x49, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x12, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
-	0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x41, 0x50, 0x49, 0x52, 0x65, 0x70, 0x6c,
-	0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x09, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x4e, 0x44,
-	0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50,
-	0x4e, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x4e, 0x44, 0x52, 0x65, 0x70, 0x6c, 0x79,
-	0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x50, 0x4e, 0x44, 0x73,
-	0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-	0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x2e, 0x41, 0x6c, 0x6c, 0x50, 0x4e, 0x44, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12,
-	0x43, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x53, 0x42, 0x49, 0x4e, 0x61, 0x6d, 0x65,
-	0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
-	0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x2e, 0x41, 0x6c, 0x6c, 0x53, 0x42, 0x49, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x70,
-	0x6c, 0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63,
-	0x65, 0x12, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76,
-	0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f,
-	0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c,
-	0x79, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x16, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x76,
-	0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x2e,
-	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52,
-	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44,
-	0x65, 0x76, 0x69, 0x63, 0x65, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42,
-	0x50, 0x0a, 0x1e, 0x64, 0x65, 0x2e, 0x68, 0x2d, 0x64, 0x61, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x67,
-	0x6f, 0x73, 0x64, 0x6e, 0x2e, 0x63, 0x6c, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63,
-	0x65, 0x42, 0x0c, 0x63, 0x6c, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x50,
-	0x01, 0x5a, 0x1e, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x66, 0x62, 0x69, 0x2e, 0x68, 0x2d,
-	0x64, 0x61, 0x2e, 0x64, 0x65, 0x2f, 0x63, 0x6f, 0x63, 0x73, 0x6e, 0x2f, 0x67, 0x6f, 0x73, 0x64,
-	0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_gosdnCLI_proto_rawDescOnce sync.Once
-	file_gosdnCLI_proto_rawDescData = file_gosdnCLI_proto_rawDesc
-)
-
-func file_gosdnCLI_proto_rawDescGZIP() []byte {
-	file_gosdnCLI_proto_rawDescOnce.Do(func() {
-		file_gosdnCLI_proto_rawDescData = protoimpl.X.CompressGZIP(file_gosdnCLI_proto_rawDescData)
-	})
-	return file_gosdnCLI_proto_rawDescData
-}
-
-var file_gosdnCLI_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
-var file_gosdnCLI_proto_goTypes = []interface{}{
-	(*HelloRequest)(nil),     // 0: proto.HelloRequest
-	(*HelloReply)(nil),       // 1: proto.HelloReply
-	(*ShutdownRequest)(nil),  // 2: proto.ShutdownRequest
-	(*ShutdownReply)(nil),    // 3: proto.ShutdownReply
-	(*TAPIRequest)(nil),      // 4: proto.TAPIRequest
-	(*TAPIReply)(nil),        // 5: proto.TAPIReply
-	(*CreatePNDRequest)(nil), // 6: proto.CreatePNDRequest
-	(*AllSBINamesReply)(nil), // 7: proto.AllSBINamesReply
-	(*CreatePNDReply)(nil),   // 8: proto.CreatePNDReply
-	(*AllPNDsReply)(nil),     // 9: proto.AllPNDsReply
-	(*PND)(nil),              // 10: proto.PND
-	(*Device)(nil),           // 11: proto.Device
-	(*AddDeviceRequest)(nil), // 12: proto.AddDeviceRequest
-	(*AddDeviceReply)(nil),   // 13: proto.AddDeviceReply
-	(*DeviceGetRequest)(nil), // 14: proto.DeviceGetRequest
-	(*DeviceGetReply)(nil),   // 15: proto.DeviceGetReply
-	(*LogReply)(nil),         // 16: proto.LogReply
-	(*emptypb.Empty)(nil),    // 17: google.protobuf.Empty
-}
-var file_gosdnCLI_proto_depIdxs = []int32{
-	10, // 0: proto.AllPNDsReply.pnds:type_name -> proto.PND
-	11, // 1: proto.PND.devices:type_name -> proto.Device
-	11, // 2: proto.AddDeviceRequest.device:type_name -> proto.Device
-	0,  // 3: proto.GrpcCli.SayHello:input_type -> proto.HelloRequest
-	2,  // 4: proto.GrpcCli.Shutdown:input_type -> proto.ShutdownRequest
-	17, // 5: proto.GrpcCli.CreateLogStream:input_type -> google.protobuf.Empty
-	4,  // 6: proto.GrpcCli.TAPIGetEdge:input_type -> proto.TAPIRequest
-	4,  // 7: proto.GrpcCli.TAPIGetEdgeNode:input_type -> proto.TAPIRequest
-	4,  // 8: proto.GrpcCli.TAPIGetLink:input_type -> proto.TAPIRequest
-	6,  // 9: proto.GrpcCli.CreatePND:input_type -> proto.CreatePNDRequest
-	17, // 10: proto.GrpcCli.GetAllPNDs:input_type -> google.protobuf.Empty
-	17, // 11: proto.GrpcCli.GetAllSBINames:input_type -> google.protobuf.Empty
-	12, // 12: proto.GrpcCli.AddDevice:input_type -> proto.AddDeviceRequest
-	14, // 13: proto.GrpcCli.HandleDeviceGetRequest:input_type -> proto.DeviceGetRequest
-	1,  // 14: proto.GrpcCli.SayHello:output_type -> proto.HelloReply
-	3,  // 15: proto.GrpcCli.Shutdown:output_type -> proto.ShutdownReply
-	16, // 16: proto.GrpcCli.CreateLogStream:output_type -> proto.LogReply
-	5,  // 17: proto.GrpcCli.TAPIGetEdge:output_type -> proto.TAPIReply
-	5,  // 18: proto.GrpcCli.TAPIGetEdgeNode:output_type -> proto.TAPIReply
-	5,  // 19: proto.GrpcCli.TAPIGetLink:output_type -> proto.TAPIReply
-	8,  // 20: proto.GrpcCli.CreatePND:output_type -> proto.CreatePNDReply
-	9,  // 21: proto.GrpcCli.GetAllPNDs:output_type -> proto.AllPNDsReply
-	7,  // 22: proto.GrpcCli.GetAllSBINames:output_type -> proto.AllSBINamesReply
-	13, // 23: proto.GrpcCli.AddDevice:output_type -> proto.AddDeviceReply
-	15, // 24: proto.GrpcCli.HandleDeviceGetRequest:output_type -> proto.DeviceGetReply
-	14, // [14:25] is the sub-list for method output_type
-	3,  // [3:14] is the sub-list for method input_type
-	3,  // [3:3] is the sub-list for extension type_name
-	3,  // [3:3] is the sub-list for extension extendee
-	0,  // [0:3] is the sub-list for field type_name
-}
-
-func init() { file_gosdnCLI_proto_init() }
-func file_gosdnCLI_proto_init() {
-	if File_gosdnCLI_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_gosdnCLI_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*HelloRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*HelloReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ShutdownRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*ShutdownReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*TAPIRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*TAPIReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CreatePNDRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AllSBINamesReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*CreatePNDReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AllPNDsReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*PND); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Device); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AddDeviceRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*AddDeviceReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DeviceGetRequest); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*DeviceGetReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_gosdnCLI_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*LogReply); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_gosdnCLI_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   17,
-			NumExtensions: 0,
-			NumServices:   1,
-		},
-		GoTypes:           file_gosdnCLI_proto_goTypes,
-		DependencyIndexes: file_gosdnCLI_proto_depIdxs,
-		MessageInfos:      file_gosdnCLI_proto_msgTypes,
-	}.Build()
-	File_gosdnCLI_proto = out.File
-	file_gosdnCLI_proto_rawDesc = nil
-	file_gosdnCLI_proto_goTypes = nil
-	file_gosdnCLI_proto_depIdxs = nil
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConnInterface
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion6
-
-// GrpcCliClient is the client API for GrpcCli service.
-//
-// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
-type GrpcCliClient interface {
-	// Sends a greeting
-	SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error)
-	// Shutdown goSDN
-	Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownReply, error)
-	// creates a stream to receive goSDN logs
-	CreateLogStream(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (GrpcCli_CreateLogStreamClient, error)
-	// By now solely TAPI specific calls can be issued from the grpc-cli
-	// TAPIGetEdge
-	TAPIGetEdge(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error)
-	//TAPIGetEdgeNode
-	TAPIGetEdgeNode(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error)
-	// TAPIGetLink
-	TAPIGetLink(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error)
-	// CreatePND
-	CreatePND(ctx context.Context, in *CreatePNDRequest, opts ...grpc.CallOption) (*CreatePNDReply, error)
-	// GetAllPNDs
-	GetAllPNDs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllPNDsReply, error)
-	// GetAllSBIs
-	GetAllSBINames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllSBINamesReply, error)
-	// AddDevice
-	AddDevice(ctx context.Context, in *AddDeviceRequest, opts ...grpc.CallOption) (*AddDeviceReply, error)
-	// HandleDeviceGetRequest
-	HandleDeviceGetRequest(ctx context.Context, in *DeviceGetRequest, opts ...grpc.CallOption) (*DeviceGetReply, error)
-}
-
-type grpcCliClient struct {
-	cc grpc.ClientConnInterface
-}
-
-func NewGrpcCliClient(cc grpc.ClientConnInterface) GrpcCliClient {
-	return &grpcCliClient{cc}
-}
-
-func (c *grpcCliClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) {
-	out := new(HelloReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/SayHello", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownReply, error) {
-	out := new(ShutdownReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/Shutdown", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) CreateLogStream(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (GrpcCli_CreateLogStreamClient, error) {
-	stream, err := c.cc.NewStream(ctx, &_GrpcCli_serviceDesc.Streams[0], "/proto.GrpcCli/CreateLogStream", opts...)
-	if err != nil {
-		return nil, err
-	}
-	x := &grpcCliCreateLogStreamClient{stream}
-	if err := x.ClientStream.SendMsg(in); err != nil {
-		return nil, err
-	}
-	if err := x.ClientStream.CloseSend(); err != nil {
-		return nil, err
-	}
-	return x, nil
-}
-
-type GrpcCli_CreateLogStreamClient interface {
-	Recv() (*LogReply, error)
-	grpc.ClientStream
-}
-
-type grpcCliCreateLogStreamClient struct {
-	grpc.ClientStream
-}
-
-func (x *grpcCliCreateLogStreamClient) Recv() (*LogReply, error) {
-	m := new(LogReply)
-	if err := x.ClientStream.RecvMsg(m); err != nil {
-		return nil, err
-	}
-	return m, nil
-}
-
-func (c *grpcCliClient) TAPIGetEdge(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error) {
-	out := new(TAPIReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/TAPIGetEdge", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) TAPIGetEdgeNode(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error) {
-	out := new(TAPIReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/TAPIGetEdgeNode", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) TAPIGetLink(ctx context.Context, in *TAPIRequest, opts ...grpc.CallOption) (*TAPIReply, error) {
-	out := new(TAPIReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/TAPIGetLink", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) CreatePND(ctx context.Context, in *CreatePNDRequest, opts ...grpc.CallOption) (*CreatePNDReply, error) {
-	out := new(CreatePNDReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/CreatePND", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) GetAllPNDs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllPNDsReply, error) {
-	out := new(AllPNDsReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/GetAllPNDs", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) GetAllSBINames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*AllSBINamesReply, error) {
-	out := new(AllSBINamesReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/GetAllSBINames", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) AddDevice(ctx context.Context, in *AddDeviceRequest, opts ...grpc.CallOption) (*AddDeviceReply, error) {
-	out := new(AddDeviceReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/AddDevice", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-func (c *grpcCliClient) HandleDeviceGetRequest(ctx context.Context, in *DeviceGetRequest, opts ...grpc.CallOption) (*DeviceGetReply, error) {
-	out := new(DeviceGetReply)
-	err := c.cc.Invoke(ctx, "/proto.GrpcCli/HandleDeviceGetRequest", in, out, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-// GrpcCliServer is the server API for GrpcCli service.
-type GrpcCliServer interface {
-	// Sends a greeting
-	SayHello(context.Context, *HelloRequest) (*HelloReply, error)
-	// Shutdown goSDN
-	Shutdown(context.Context, *ShutdownRequest) (*ShutdownReply, error)
-	// creates a stream to receive goSDN logs
-	CreateLogStream(*emptypb.Empty, GrpcCli_CreateLogStreamServer) error
-	// By now solely TAPI specific calls can be issued from the grpc-cli
-	// TAPIGetEdge
-	TAPIGetEdge(context.Context, *TAPIRequest) (*TAPIReply, error)
-	//TAPIGetEdgeNode
-	TAPIGetEdgeNode(context.Context, *TAPIRequest) (*TAPIReply, error)
-	// TAPIGetLink
-	TAPIGetLink(context.Context, *TAPIRequest) (*TAPIReply, error)
-	// CreatePND
-	CreatePND(context.Context, *CreatePNDRequest) (*CreatePNDReply, error)
-	// GetAllPNDs
-	GetAllPNDs(context.Context, *emptypb.Empty) (*AllPNDsReply, error)
-	// GetAllSBIs
-	GetAllSBINames(context.Context, *emptypb.Empty) (*AllSBINamesReply, error)
-	// AddDevice
-	AddDevice(context.Context, *AddDeviceRequest) (*AddDeviceReply, error)
-	// HandleDeviceGetRequest
-	HandleDeviceGetRequest(context.Context, *DeviceGetRequest) (*DeviceGetReply, error)
-}
-
-// UnimplementedGrpcCliServer can be embedded to have forward compatible implementations.
-type UnimplementedGrpcCliServer struct {
-}
-
-func (*UnimplementedGrpcCliServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
-}
-func (*UnimplementedGrpcCliServer) Shutdown(context.Context, *ShutdownRequest) (*ShutdownReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
-}
-func (*UnimplementedGrpcCliServer) CreateLogStream(*emptypb.Empty, GrpcCli_CreateLogStreamServer) error {
-	return status.Errorf(codes.Unimplemented, "method CreateLogStream not implemented")
-}
-func (*UnimplementedGrpcCliServer) TAPIGetEdge(context.Context, *TAPIRequest) (*TAPIReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method TAPIGetEdge not implemented")
-}
-func (*UnimplementedGrpcCliServer) TAPIGetEdgeNode(context.Context, *TAPIRequest) (*TAPIReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method TAPIGetEdgeNode not implemented")
-}
-func (*UnimplementedGrpcCliServer) TAPIGetLink(context.Context, *TAPIRequest) (*TAPIReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method TAPIGetLink not implemented")
-}
-func (*UnimplementedGrpcCliServer) CreatePND(context.Context, *CreatePNDRequest) (*CreatePNDReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method CreatePND not implemented")
-}
-func (*UnimplementedGrpcCliServer) GetAllPNDs(context.Context, *emptypb.Empty) (*AllPNDsReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method GetAllPNDs not implemented")
-}
-func (*UnimplementedGrpcCliServer) GetAllSBINames(context.Context, *emptypb.Empty) (*AllSBINamesReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method GetAllSBINames not implemented")
-}
-func (*UnimplementedGrpcCliServer) AddDevice(context.Context, *AddDeviceRequest) (*AddDeviceReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method AddDevice not implemented")
-}
-func (*UnimplementedGrpcCliServer) HandleDeviceGetRequest(context.Context, *DeviceGetRequest) (*DeviceGetReply, error) {
-	return nil, status.Errorf(codes.Unimplemented, "method HandleDeviceGetRequest not implemented")
-}
-
-func RegisterGrpcCliServer(s *grpc.Server, srv GrpcCliServer) {
-	s.RegisterService(&_GrpcCli_serviceDesc, srv)
-}
-
-func _GrpcCli_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(HelloRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).SayHello(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/SayHello",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).SayHello(ctx, req.(*HelloRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(ShutdownRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).Shutdown(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/Shutdown",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).Shutdown(ctx, req.(*ShutdownRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_CreateLogStream_Handler(srv interface{}, stream grpc.ServerStream) error {
-	m := new(emptypb.Empty)
-	if err := stream.RecvMsg(m); err != nil {
-		return err
-	}
-	return srv.(GrpcCliServer).CreateLogStream(m, &grpcCliCreateLogStreamServer{stream})
-}
-
-type GrpcCli_CreateLogStreamServer interface {
-	Send(*LogReply) error
-	grpc.ServerStream
-}
-
-type grpcCliCreateLogStreamServer struct {
-	grpc.ServerStream
-}
-
-func (x *grpcCliCreateLogStreamServer) Send(m *LogReply) error {
-	return x.ServerStream.SendMsg(m)
-}
-
-func _GrpcCli_TAPIGetEdge_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(TAPIRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).TAPIGetEdge(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/TAPIGetEdge",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).TAPIGetEdge(ctx, req.(*TAPIRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_TAPIGetEdgeNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(TAPIRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).TAPIGetEdgeNode(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/TAPIGetEdgeNode",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).TAPIGetEdgeNode(ctx, req.(*TAPIRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_TAPIGetLink_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(TAPIRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).TAPIGetLink(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/TAPIGetLink",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).TAPIGetLink(ctx, req.(*TAPIRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_CreatePND_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(CreatePNDRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).CreatePND(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/CreatePND",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).CreatePND(ctx, req.(*CreatePNDRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_GetAllPNDs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(emptypb.Empty)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).GetAllPNDs(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/GetAllPNDs",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).GetAllPNDs(ctx, req.(*emptypb.Empty))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_GetAllSBINames_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(emptypb.Empty)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).GetAllSBINames(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/GetAllSBINames",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).GetAllSBINames(ctx, req.(*emptypb.Empty))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_AddDevice_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(AddDeviceRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).AddDevice(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/AddDevice",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).AddDevice(ctx, req.(*AddDeviceRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-func _GrpcCli_HandleDeviceGetRequest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(DeviceGetRequest)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(GrpcCliServer).HandleDeviceGetRequest(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/proto.GrpcCli/HandleDeviceGetRequest",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(GrpcCliServer).HandleDeviceGetRequest(ctx, req.(*DeviceGetRequest))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-var _GrpcCli_serviceDesc = grpc.ServiceDesc{
-	ServiceName: "proto.GrpcCli",
-	HandlerType: (*GrpcCliServer)(nil),
-	Methods: []grpc.MethodDesc{
-		{
-			MethodName: "SayHello",
-			Handler:    _GrpcCli_SayHello_Handler,
-		},
-		{
-			MethodName: "Shutdown",
-			Handler:    _GrpcCli_Shutdown_Handler,
-		},
-		{
-			MethodName: "TAPIGetEdge",
-			Handler:    _GrpcCli_TAPIGetEdge_Handler,
-		},
-		{
-			MethodName: "TAPIGetEdgeNode",
-			Handler:    _GrpcCli_TAPIGetEdgeNode_Handler,
-		},
-		{
-			MethodName: "TAPIGetLink",
-			Handler:    _GrpcCli_TAPIGetLink_Handler,
-		},
-		{
-			MethodName: "CreatePND",
-			Handler:    _GrpcCli_CreatePND_Handler,
-		},
-		{
-			MethodName: "GetAllPNDs",
-			Handler:    _GrpcCli_GetAllPNDs_Handler,
-		},
-		{
-			MethodName: "GetAllSBINames",
-			Handler:    _GrpcCli_GetAllSBINames_Handler,
-		},
-		{
-			MethodName: "AddDevice",
-			Handler:    _GrpcCli_AddDevice_Handler,
-		},
-		{
-			MethodName: "HandleDeviceGetRequest",
-			Handler:    _GrpcCli_HandleDeviceGetRequest_Handler,
-		},
-	},
-	Streams: []grpc.StreamDesc{
-		{
-			StreamName:    "CreateLogStream",
-			Handler:       _GrpcCli_CreateLogStream_Handler,
-			ServerStreams: true,
-		},
-	},
-	Metadata: "gosdnCLI.proto",
-}
diff --git a/api/proto/gosdnCLI.proto b/api/proto/gosdnCLI.proto
deleted file mode 100644
index 355d8e7455f009d2b35e8bc34c079ce31466bbdd..0000000000000000000000000000000000000000
--- a/api/proto/gosdnCLI.proto
+++ /dev/null
@@ -1,125 +0,0 @@
-syntax = "proto3";
-import "google/protobuf/empty.proto";
-
-option go_package = "gitlab.fbi.h-da.de/cocsn/gosdn";
-
-package proto;
-
-// The greeting service definition.
-service GrpcCli {
-  // Sends a greeting
-  rpc SayHello (HelloRequest) returns (HelloReply) {}
-  // Shutdown goSDN
-  rpc Shutdown (ShutdownRequest) returns (ShutdownReply) {}
-  // creates a stream to receive goSDN logs
-  rpc CreateLogStream(google.protobuf.Empty) returns (stream LogReply) {}
-
-  // By now solely TAPI specific calls can be issued from the grpc-cli
-  // TAPIGetEdge
-  rpc TAPIGetEdge (TAPIRequest) returns (TAPIReply) {}
-  //TAPIGetEdgeNode
-  rpc TAPIGetEdgeNode (TAPIRequest) returns (TAPIReply) {}
-  // TAPIGetLink
-  rpc TAPIGetLink (TAPIRequest) returns (TAPIReply) {}
-  // CreatePND
-  rpc CreatePND (CreatePNDRequest) returns (CreatePNDReply) {}
-  // GetAllPNDs
-  rpc GetAllPNDs(google.protobuf.Empty) returns (AllPNDsReply) {}
-  // GetAllSBIs
-  rpc  GetAllSBINames(google.protobuf.Empty) returns (AllSBINamesReply) {}
-  // AddDevice
-  rpc AddDevice(AddDeviceRequest) returns (AddDeviceReply) {}
-  // HandleDeviceGetRequest
-  rpc HandleDeviceGetRequest(DeviceGetRequest) returns (DeviceGetReply) {}
-}
-
-// The request message containing the user's name.
-message HelloRequest {
-  string name = 1;
-}
-
-// The response message containing the greetings
-message HelloReply {
-  string message = 1;
-  string goSDNInfo = 2;
-}
-
-// Request to shutdown goSDN
-message ShutdownRequest {
-  string name = 1;
-}
-
-// The response message containing some shutdown notes of goSDN
-message ShutdownReply {
-  string message = 1;
-}
-
-// Request with no meaning by now
-message TAPIRequest {
-  string name = 1;
-}
-
-// The response message containing a string with no meaning by now
-message TAPIReply {
-  string message = 1;
-}
-
-//
-message CreatePNDRequest {
-    string name = 1;
-    string description = 2;
-    string sbi = 3;
-}
-
-message AllSBINamesReply {
-    repeated string sbiNames = 1;
-}
-
-//
-message CreatePNDReply {
-    string message = 1;
-}
-
-//
-message AllPNDsReply {
-    repeated PND pnds = 1;
-}
-
-message PND {
-    string uuid = 1;
-    string name = 2;
-    string description = 3;
-    string sbi = 4;
-    repeated Device devices = 5;
-}
-
-message Device {
- string uuid = 1;
- string address = 2;
- string username = 3;
- string password = 4;
-}
-
-message AddDeviceRequest {
-     string uuidPND = 1;
-     Device device = 2;
-}
-
-message AddDeviceReply {
-     string message = 1;
-}
-
-message DeviceGetRequest {
-    string uuidPND = 1;
-    string uuidDevice = 2;
-    string path = 3;
-}
-
-message DeviceGetReply {
-    string message = 1;
-}
-
-// The response message containing a string with a goSDN log
-message LogReply {
-  string log = 1;
-}
diff --git a/cmd/gnmi-capabilities/capabilities.go b/cli/capabilities.go
similarity index 69%
rename from cmd/gnmi-capabilities/capabilities.go
rename to cli/capabilities.go
index 54601b8a7ede5805a0d1a3ad633424020a8fc736..215380e3bde648388584b9ccdf042633c4bcf1ea 100644
--- a/cmd/gnmi-capabilities/capabilities.go
+++ b/cli/capabilities.go
@@ -1,4 +1,4 @@
-package main
+package cli
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
@@ -6,36 +6,37 @@ import (
 	"context"
 	"fmt"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
-	log "github.com/sirupsen/logrus"
 	"strings"
 )
 
-func main() {
-	cfg := &gnmi.Config{
-		Addr:     "[2003:e6:1722:fed0:0:242:ac11:5]:6030",
+func Capabilities() error {
+	cfg := gnmi.Config{
+		Addr:     "portainer.danet.fbi.h-da.de:6030",
 		Username: "admin",
 		Password: "arista",
 		Encoding: gpb.Encoding_JSON_IETF,
 	}
-	transport, err := nucleus.NewGnmiTransport(cfg)
+	opts := &nucleus.GnmiTransportOptions{Config: cfg}
+	transport, err := nucleus.NewGnmiTransport(opts)
 	if err != nil {
-		log.Error(err)
+		return err
 	}
 	resp, err := transport.Capabilities(context.Background())
 	if err != nil {
-		log.Error(err)
+		return err
 	}
 	modelData := resp.(*gpb.CapabilityResponse).SupportedModels
 	b := strings.Builder{}
 	for _, elem := range modelData {
 		_, err := b.WriteString(elem.Name)
 		if err != nil {
-			log.Error(err)
+			return err
 		}
 		_, err = b.WriteString("\n")
 		if err != nil {
-			log.Error(err)
+			return err
 		}
 	}
 	fmt.Println(b.String())
+	return nil
 }
diff --git a/cli/daemon.go b/cli/daemon.go
new file mode 100644
index 0000000000000000000000000000000000000000..50cac5ebae498c5f9289b5942a18f65db7429206
--- /dev/null
+++ b/cli/daemon.go
@@ -0,0 +1,20 @@
+package cli
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
+	log "github.com/sirupsen/logrus"
+	"os"
+)
+
+func Gosdn() error {
+	_, debug := os.LookupEnv("GOSDN_DEBUG")
+	if debug {
+		log.SetLevel(log.DebugLevel)
+	}
+
+	// Setup a channel to communicate if goSDN should shutdown.
+	IsRunningChannel := make(chan bool)
+
+	// hand off to cmd for further processing
+	return nucleus.StartAndRun(IsRunningChannel)
+}
diff --git a/cmd/gnmi/gnmi.go b/cli/get.go
similarity index 53%
rename from cmd/gnmi/gnmi.go
rename to cli/get.go
index da537bf1c4d5060dac54646566f3976b4eca820e..f5e1e061581c956c691f45313ae44f8d7e42b8e9 100644
--- a/cmd/gnmi/gnmi.go
+++ b/cli/get.go
@@ -1,4 +1,4 @@
-package main
+package cli
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
@@ -13,40 +13,30 @@ import (
   Bootstrapping of pnd, device and transport simplified not idiomatic
 */
 
-func main() {
-	log.SetLevel(log.DebugLevel)
+func Get() error {
 	sbi := &nucleus.OpenConfig{}
-	device := &nucleus.Device{
-		GoStruct: sbi.Schema().Root,
-		SBI:      sbi,
-		Config: nucleus.DeviceConfig{
-			Uuid: uuid.New(),
+	opts := &nucleus.GnmiTransportOptions{
+		Config: gnmi.Config{
+			Addr:     "portainer.danet.fbi.h-da.de:6030",
+			Username: "admin",
+			Password: "arista",
+			Encoding: gpb.Encoding_JSON_IETF,
 		},
+		SetNode: sbi.SetNode(),
+	}
+	device, err := nucleus.NewDevice(sbi, opts)
+	if err != nil {
+		return err
 	}
 	pnd, err := nucleus.NewPND("openconfig", "test description", uuid.New(), sbi)
 	if err != nil {
-		log.Fatal(err)
+		return err
 	}
 	if err := pnd.AddDevice(device); err != nil {
-		log.Fatal(err)
-	}
-
-	cfg := &gnmi.Config{
-		Addr:     "[2003:e6:1722:fed0:0:242:ac11:5]:6030",
-		Username: "admin",
-		Password: "arista",
-		Encoding: gpb.Encoding_JSON_IETF,
+		return err
 	}
-	transport, err := nucleus.NewGnmiTransport(cfg)
-	if err != nil {
-		log.Fatal(err)
-	}
-	transport.SetNode = sbi.SetNode()
-	transport.Unmarshal = sbi.Unmarshal()
 
-	device.Transport = transport
-
-	p := []string{"/interfaces"}
+	p := []string{"/interfaces/interface"}
 	errors := 0
 	for _, path := range p {
 		err := pnd.RequestAll(path)
@@ -58,6 +48,9 @@ func main() {
 	}
 
 	percentage := float64(errors) / float64(len(p)) * 100.0
-	log.Debugf("%v errors", errors)
-	log.Debugf("%v percent failed", percentage)
+	if errors != 0 {
+		log.Error("%v errors", errors)
+		log.Error("%v percent failed", percentage)
+	}
+	return nil
 }
diff --git a/cli/init.go b/cli/init.go
new file mode 100644
index 0000000000000000000000000000000000000000..c4c06a575e88d4b783d961c0c21afe1c03f342ee
--- /dev/null
+++ b/cli/init.go
@@ -0,0 +1,17 @@
+package cli
+
+import (
+	model "code.fbi.h-da.de/cocsn/yang-models/generated/arista"
+	"github.com/openconfig/ygot/ytypes"
+	log "github.com/sirupsen/logrus"
+)
+
+var schema *ytypes.Schema
+
+func init(){
+	var err error
+	schema, err = model.Schema()
+	if err != nil {
+		log.Fatal(err)
+	}
+}
\ No newline at end of file
diff --git a/cli/path_traversal.go b/cli/path_traversal.go
new file mode 100644
index 0000000000000000000000000000000000000000..06f2dbf3709cbcc99539fac03a299daad0bcab2d
--- /dev/null
+++ b/cli/path_traversal.go
@@ -0,0 +1,22 @@
+package cli
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/path"
+	log "github.com/sirupsen/logrus"
+)
+
+func PathTraversal() error {
+	log.SetLevel(log.DebugLevel)
+	paths, err := path.ParseSchema(schema, "device")
+	if err != nil {
+		return err
+	}
+
+	for _, v := range paths {
+		v.Print()
+	}
+
+	p := path.Strings(paths)
+	log.Debug(p)
+	return nil
+}
diff --git a/cli/set.go b/cli/set.go
new file mode 100644
index 0000000000000000000000000000000000000000..e818caeb7e4556931cbd807e23fe2f312577f3a9
--- /dev/null
+++ b/cli/set.go
@@ -0,0 +1,53 @@
+package cli
+
+import (
+	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
+	"context"
+	pb "google.golang.org/protobuf/proto"
+	"os"
+)
+
+func Set() error {
+	a := os.Getenv("GOSDN_TEST_ENDPOINT")
+	if a == "" {
+		a = "portainer.danet.fbi.h-da.de:6030"
+	}
+
+	opts := &nucleus.GnmiTransportOptions{
+		Config: gnmi.Config{
+			Addr:     a,
+			Username: "admin",
+			Password: "arista",
+		},
+	}
+	t, err := nucleus.NewGnmiTransport(opts)
+	if err != nil {
+		return err
+	}
+
+	reqs := []interface{}{
+		&gnmi.Operation{
+			Type:   "update",
+			Origin: "",
+			Target: "",
+			Path: []string{
+				"system",
+				"config",
+				"hostname",
+			},
+			Val: "ceos3000",
+		},
+	}
+
+	resp, err := t.Set(context.Background(), reqs...)
+	if err != nil {
+		return err
+	}
+
+	if err := proto.Write(resp.(pb.Message), "resp-set-system-config-hostname"); err != nil {
+		return err
+	}
+	return nil
+}
diff --git a/cmd/gnmi-telemetry/telemetry.go b/cli/subscribe.go
similarity index 65%
rename from cmd/gnmi-telemetry/telemetry.go
rename to cli/subscribe.go
index 70d858a2a239b77395b9693edee8abf95ee638be..e953c070efa054bc598af2ceacc9132ef0ccf354 100644
--- a/cmd/gnmi-telemetry/telemetry.go
+++ b/cli/subscribe.go
@@ -1,4 +1,4 @@
-package main
+package cli
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
@@ -14,34 +14,31 @@ import (
 	"time"
 )
 
-func main() {
+func Subscribe() error{
 	log.SetLevel(log.DebugLevel)
 	sbi := &nucleus.OpenConfig{}
 
-	device := nucleus.Device{
-		GoStruct: sbi.Schema().Root,
-		SBI:      sbi,
-		Config: nucleus.DeviceConfig{
-			Uuid: uuid.New(),
-		},
+	device, err := nucleus.NewDevice(sbi,
+		&nucleus.GnmiTransportOptions{
+			Config: gnmi.Config{
+				Addr:     "portainer.danet.fbi.h-da.de:6030",
+				Username: "admin",
+				Password: "arista",
+				Encoding: gpb.Encoding_JSON_IETF,
+			},
+			SetNode:  sbi.SetNode(),
+			RespChan: make(chan *gpb.SubscribeResponse),
+		})
+	if err != nil {
+		return err
 	}
 	pnd, err := nucleus.NewPND("openconfig", "a simple openconfig PND", uuid.New(), sbi)
 	if err != nil {
-		log.Fatal(err)
-	}
-	if err := pnd.AddDevice(&device); err != nil {
-		log.Fatal(err)
+		return err
 	}
-
-	cfg := &gnmi.Config{
-		Addr:     "[2003:e6:1722:fed0:0:242:ac11:5]:6030",
-		Username: "admin",
-		Password: "arista",
-		Encoding: gpb.Encoding_JSON_IETF,
+	if err := pnd.AddDevice(device); err != nil {
+		return err
 	}
-	transport, _ := nucleus.NewGnmiTransport(cfg)
-
-	device.Transport = transport
 
 	paths := []string{"/interfaces/interface/name"}
 
@@ -55,17 +52,18 @@ func main() {
 		HeartbeatInterval: uint64(time.Second.Nanoseconds()),
 		Paths:             gnmi.SplitPaths(paths),
 		Origin:            "",
-		Target:            device.Config.Address,
+		Target:            "portainer.danet.fbi.h-da.de:6030",
 	}
 	done := make(chan os.Signal, 1)
 	signal.Notify(done, syscall.SIGILL, syscall.SIGTERM)
 	ctx := context.WithValue(context.Background(), "opts", opts)
 	go func() {
-		if err := transport.Subscribe(ctx); err != nil {
+		if err := device.Transport.Subscribe(ctx); err != nil {
 			log.Fatal(err)
 		}
 	}()
 	fmt.Println("awaiting signal")
 	<-done
 	fmt.Println("exiting")
+	return nil
 }
diff --git a/cmd/gnmi-target/target.go b/cli/target.go
similarity index 93%
rename from cmd/gnmi-target/target.go
rename to cli/target.go
index e72ef7acb77d43cefb5770f79828f8cc6128cac0..0513487ac803622578bff56374759a19d3f0a656 100644
--- a/cmd/gnmi-target/target.go
+++ b/cli/target.go
@@ -1,4 +1,4 @@
-package main
+package cli
 
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/google/gnmi"
@@ -65,7 +65,7 @@ func (s *server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse,
 }
 */
 
-func main() {
+func Target() error {
 
 	// Google stuff from here
 	model := gnmi.NewModel(modeldata.ModelData,
@@ -79,7 +79,7 @@ func main() {
 	var configData []byte
 	s, err := newServer(model, configData)
 	if err != nil {
-		log.Fatalf("error in creating gnmi target: %v", err)
+		return err
 	}
 	pb.RegisterGNMIServer(g, s)
 	reflection.Register(g)
@@ -87,11 +87,12 @@ func main() {
 	log.Infof("starting to listen on %s", *bindAddr)
 	listen, err := net.Listen("tcp", *bindAddr)
 	if err != nil {
-		log.Fatalf("failed to listen: %v", err)
+		return err
 	}
 
 	log.Info("starting to serve")
 	if err := g.Serve(listen); err != nil {
-		log.Fatalf("failed to serve: %v", err)
+		return err
 	}
+	return nil
 }
diff --git a/cli/ygot.go b/cli/ygot.go
new file mode 100644
index 0000000000000000000000000000000000000000..e89e7cffe50675385994c25b609054df5b2c0037
--- /dev/null
+++ b/cli/ygot.go
@@ -0,0 +1,17 @@
+package cli
+
+import (
+	log "github.com/golang/glog"
+	"github.com/openconfig/ygot/util"
+)
+
+func LeafPaths() error {
+	for _,v := range schema.SchemaTree {
+		entry, err := util.FindLeafRefSchema(v, "/interface/")
+		if err != nil {
+			log.Error(err)
+		}
+		log.Info(entry)
+	}
+	return nil
+}
\ No newline at end of file
diff --git a/cmd/capabilities.go b/cmd/capabilities.go
new file mode 100644
index 0000000000000000000000000000000000000000..69f1bbb460acc11e2dd233ffefd7cad18aefe416
--- /dev/null
+++ b/cmd/capabilities.go
@@ -0,0 +1,55 @@
+/*
+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"
+)
+
+// capabilitiesCmd represents the capabilities command
+var capabilitiesCmd = &cobra.Command{
+	Use:   "capabilities",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.Capabilities()
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(capabilitiesCmd)
+}
diff --git a/cmd/get.go b/cmd/get.go
new file mode 100644
index 0000000000000000000000000000000000000000..2eecd66344539a486fe24562164bed88d8bebdcc
--- /dev/null
+++ b/cmd/get.go
@@ -0,0 +1,65 @@
+/*
+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"
+)
+
+// getCmd represents the get command
+var getCmd = &cobra.Command{
+	Use:   "get",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.Get()
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(getCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// getCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// getCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/gosdn/gosdn b/cmd/gosdn/gosdn
new file mode 100755
index 0000000000000000000000000000000000000000..645db8da274b5591f64db0ac267ff48df21c2714
Binary files /dev/null and b/cmd/gosdn/gosdn differ
diff --git a/cmd/gosdn/main.go b/cmd/gosdn/main.go
index 367250512af6318f1ad84ec85c139bfec28e1206..03815b4ec592e36599bf2d4bf92aa9f99f91e387 100644
--- a/cmd/gosdn/main.go
+++ b/cmd/gosdn/main.go
@@ -1,20 +1,37 @@
-package main
+/*
+Copyright © 2021 da/net research group <danet.fbi.h-da.de>
+All rights reserved.
 
-import (
-	"code.fbi.h-da.de/cocsn/gosdn/nucleus"
-	log "github.com/sirupsen/logrus"
-	"os"
-)
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
 
-func main() {
-	_, debug := os.LookupEnv("GOSDN_DEBUG")
-	if debug {
-		log.SetLevel(log.DebugLevel)
-	}
+1. Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
 
-	// Setup a channel to communicate if goSDN should shutdown.
-	IsRunningChannel := make(chan bool)
+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.
 
-	// hand off to cmd for further processing
-	nucleus.StartAndRun(IsRunningChannel)
+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 main
+
+import "code.fbi.h-da.de/cocsn/gosdn/cmd"
+
+func main() {
+  cmd.Execute()
 }
diff --git a/cmd/legacy.go b/cmd/legacy.go
new file mode 100644
index 0000000000000000000000000000000000000000..183857713ed710971882783733828e1cdecb7d5b
--- /dev/null
+++ b/cmd/legacy.go
@@ -0,0 +1,65 @@
+/*
+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"
+)
+
+// legacyCmd represents the legacy command
+var legacyCmd = &cobra.Command{
+	Use:   "legacy",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.PathTraversal()
+	},
+}
+
+func init() {
+	pathCmd.AddCommand(legacyCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// legacyCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// legacyCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/path-traversal/path_traversal.go b/cmd/path-traversal/path_traversal.go
deleted file mode 100644
index 4f951a53c5288738c5333e9cdab962a5f4ff005f..0000000000000000000000000000000000000000
--- a/cmd/path-traversal/path_traversal.go
+++ /dev/null
@@ -1,21 +0,0 @@
-package main
-
-import (
-	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
-	"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
-	log "github.com/sirupsen/logrus"
-)
-
-func main() {
-	log.SetLevel(log.DebugLevel)
-	schema, _ := openconfig.Schema()
-	paths := util.NewPaths()
-	paths.ParseSchema(schema, "device")
-
-	for _, v := range paths {
-		v.Print()
-	}
-
-	p := paths.StringBuilder()
-	log.Debug(p)
-}
diff --git a/cmd/path.go b/cmd/path.go
new file mode 100644
index 0000000000000000000000000000000000000000..713265798520f46a5afb98a3abf227338d7cdece
--- /dev/null
+++ b/cmd/path.go
@@ -0,0 +1,65 @@
+/*
+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 (
+	"errors"
+	"github.com/spf13/cobra"
+)
+
+// pathCmd represents the path command
+var pathCmd = &cobra.Command{
+	Use:   "path",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return errors.New("path needs either [ygot] or [legacy] command")
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(pathCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// pathCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// pathCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/pathgen.go b/cmd/pathgen.go
new file mode 100644
index 0000000000000000000000000000000000000000..60964b8d7e96c8c71de30498defe96ed02ed95a7
--- /dev/null
+++ b/cmd/pathgen.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"
+)
+
+// pathgenCmd represents the pathgen command
+var pathgenCmd = &cobra.Command{
+	Use:   "pathgen",
+	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("pathgen called")
+	},
+}
+
+func init() {
+	ygotCmd.AddCommand(pathgenCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// pathgenCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// pathgenCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/protomap.go b/cmd/protomap.go
new file mode 100644
index 0000000000000000000000000000000000000000..dc6e0df4bf0bed04f8b085dc3768b1e86423a578
--- /dev/null
+++ b/cmd/protomap.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"
+)
+
+// protomapCmd represents the protomap command
+var protomapCmd = &cobra.Command{
+	Use:   "protomap",
+	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("protomap called")
+	},
+}
+
+func init() {
+	ygotCmd.AddCommand(protomapCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// protomapCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// protomapCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/root.go b/cmd/root.go
new file mode 100644
index 0000000000000000000000000000000000000000..236c501e9215c131af2953d6caadd3e6f0843807
--- /dev/null
+++ b/cmd/root.go
@@ -0,0 +1,113 @@
+/*
+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"
+  "fmt"
+  "os"
+  "github.com/spf13/cobra"
+
+  homedir "github.com/mitchellh/go-homedir"
+  "github.com/spf13/viper"
+
+)
+
+
+var cfgFile string
+
+
+// rootCmd represents the base command when called without any subcommands
+var rootCmd = &cobra.Command{
+  Use:   "gosdn",
+  Short: "A brief description of your application",
+  Long: `A longer description that spans multiple lines and likely contains
+examples and usage of using your application. 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.`,
+  	RunE: func(cmd *cobra.Command, args []string) error {
+  	  return cli.Gosdn()
+    },
+}
+
+// Execute adds all child commands to the root command and sets flags appropriately.
+// This is called by main.main(). It only needs to happen once to the rootCmd.
+func Execute() {
+  if err := rootCmd.Execute(); err != nil {
+    fmt.Println(err)
+    os.Exit(1)
+  }
+}
+
+func init() {
+  cobra.OnInitialize(initConfig)
+
+  // Here you will define your flags and configuration settings.
+  // Cobra supports persistent flags, which, if defined here,
+  // will be global for your application.
+
+  rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.gosdn.yaml)")
+
+
+  // Cobra also supports local flags, which will only run
+  // when this action is called directly.
+  rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
+
+
+// initConfig reads in config file and ENV variables if set.
+func initConfig() {
+  if cfgFile != "" {
+    // Use config file from the flag.
+    viper.SetConfigFile(cfgFile)
+  } else {
+    // Find home directory.
+    home, err := homedir.Dir()
+    if err != nil {
+      fmt.Println(err)
+      os.Exit(1)
+    }
+
+    // Search config in home directory with name ".gosdn" (without extension).
+    viper.AddConfigPath(home)
+    viper.SetConfigName(".gosdn")
+  }
+
+  viper.AutomaticEnv() // read in environment variables that match
+
+  // If a config file is found, read it in.
+  if err := viper.ReadInConfig(); err == nil {
+    fmt.Println("Using config file:", viper.ConfigFileUsed())
+  }
+}
+
diff --git a/cmd/set.go b/cmd/set.go
new file mode 100644
index 0000000000000000000000000000000000000000..6631f08fb44efe3ed33f5eed16389183a569cf90
--- /dev/null
+++ b/cmd/set.go
@@ -0,0 +1,65 @@
+/*
+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"
+)
+
+// setCmd represents the set command
+var setCmd = &cobra.Command{
+	Use:   "set",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.Set()
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(setCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// setCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// setCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/subscribe.go b/cmd/subscribe.go
new file mode 100644
index 0000000000000000000000000000000000000000..c60671693ec6f580b2698ea1b5fa65a9aca16163
--- /dev/null
+++ b/cmd/subscribe.go
@@ -0,0 +1,65 @@
+/*
+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"
+)
+
+// subscribeCmd represents the subscribe command
+var subscribeCmd = &cobra.Command{
+	Use:   "subscribe",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.Subscribe()
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(subscribeCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// subscribeCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// subscribeCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/target.go b/cmd/target.go
new file mode 100644
index 0000000000000000000000000000000000000000..379ddcb7d770d39280aa7a043b2427a037186c7f
--- /dev/null
+++ b/cmd/target.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 (
+	"code.fbi.h-da.de/cocsn/gosdn/cli"
+
+	"github.com/spf13/cobra"
+)
+
+// targetCmd represents the target command
+var targetCmd = &cobra.Command{
+	Use:   "target",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.Target()
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(targetCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// targetCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// targetCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/util.go b/cmd/util.go
new file mode 100644
index 0000000000000000000000000000000000000000..432e5a54083af02a5477c3b591fcc1480d583d86
--- /dev/null
+++ b/cmd/util.go
@@ -0,0 +1,65 @@
+/*
+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"
+)
+
+// utilCmd represents the util command
+var utilCmd = &cobra.Command{
+	Use:   "util",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return cli.LeafPaths()
+	},
+}
+
+func init() {
+	ygotCmd.AddCommand(utilCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// utilCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// utilCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/cmd/ygot.go b/cmd/ygot.go
new file mode 100644
index 0000000000000000000000000000000000000000..d5298bd15d3844d05c964054b02ddcdf4eed4cc3
--- /dev/null
+++ b/cmd/ygot.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 (
+	"errors"
+
+	"github.com/spf13/cobra"
+)
+
+// ygotCmd represents the ygot command
+var ygotCmd = &cobra.Command{
+	Use:   "ygot",
+	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.`,
+	RunE: func(cmd *cobra.Command, args []string) error {
+		return errors.New("not implemented")
+	},
+}
+
+func init() {
+	rootCmd.AddCommand(ygotCmd)
+
+	// Here you will define your flags and configuration settings.
+
+	// Cobra supports Persistent Flags which will work for this command
+	// and all subcommands, e.g.:
+	// ygotCmd.PersistentFlags().String("foo", "", "A help for foo")
+
+	// Cobra supports local flags which will only run when this command
+	// is called directly, e.g.:
+	// ygotCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
+}
diff --git a/forks/goarista/gnmi/client.go b/forks/goarista/gnmi/client.go
index 33c3023b77760402803fef98bd8226c6917cb01e..f9ed05b53fcd4852b7f5fa4c61d40e25c3688532 100644
--- a/forks/goarista/gnmi/client.go
+++ b/forks/goarista/gnmi/client.go
@@ -9,7 +9,6 @@ import (
 	"crypto/tls"
 	"crypto/x509"
 	"errors"
-	"flag"
 	"fmt"
 	"math"
 	"net"
@@ -82,59 +81,6 @@ type SubscribeOptions struct {
 	Target            string
 }
 
-// ParseFlags reads arguments from stdin and returns a populated Config object and a list of
-// paths to subscribe to
-func ParseFlags() (*Config, []string) {
-	// flags
-	var (
-		addrsFlag = flag.String("addrs", "localhost:6030",
-			"Comma-separated list of addresses of OpenConfig gRPC servers. The address 'HOSTNAME' "+
-				"is replaced by the current hostname.")
-
-		caFileFlag = flag.String("cafile", "",
-			"Path to server TLS certificate file")
-
-		certFileFlag = flag.String("certfile", "",
-			"Path to ciena TLS certificate file")
-
-		keyFileFlag = flag.String("keyfile", "",
-			"Path to ciena TLS private key file")
-
-		passwordFlag = flag.String("password", "",
-			"Password to authenticate with")
-
-		usernameFlag = flag.String("username", "",
-			"Username to authenticate with")
-
-		tlsFlag = flag.Bool("tls", false,
-			"Enable TLS")
-
-		compressionFlag = flag.String("compression", "",
-			"Type of compression to use")
-
-		subscribeFlag = flag.String("subscribe", "",
-			"Comma-separated list of paths to subscribe to upon connecting to the server")
-
-		token = flag.String("token", "",
-			"Authentication token")
-	)
-	flag.Parse()
-	cfg := &Config{
-		Addr:        *addrsFlag,
-		CAFile:      *caFileFlag,
-		CertFile:    *certFileFlag,
-		KeyFile:     *keyFileFlag,
-		Password:    *passwordFlag,
-		Username:    *usernameFlag,
-		TLS:         *tlsFlag,
-		Compression: *compressionFlag,
-		Token:       *token,
-	}
-	subscriptions := strings.Split(*subscribeFlag, ",")
-	return cfg, subscriptions
-
-}
-
 // accessTokenCred implements credentials.PerRPCCredentials, the gRPC
 // interface for credentials that need to attach security information
 // to every RPC.
@@ -158,7 +104,7 @@ func (a *accessTokenCred) GetRequestMetadata(ctx context.Context,
 
 func (a *accessTokenCred) RequireTransportSecurity() bool { return true }
 
-// DialContext connects to a gnmi service and returns a ciena
+// DialContext connects to a gnmi service and returns a client
 func DialContext(ctx context.Context, cfg *Config) (pb.GNMIClient, error) {
 	opts := append([]grpc.DialOption(nil), cfg.DialOptions...)
 
diff --git a/go.mod b/go.mod
index 3bf6455f8bcaf316a36f60a071ed1fcffc3a04cd..a816066f9eb7c0960ae2db6f577903e529f16b7c 100644
--- a/go.mod
+++ b/go.mod
@@ -8,16 +8,17 @@ require (
 	github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a
 	github.com/go-openapi/runtime v0.19.22
 	github.com/go-openapi/strfmt v0.19.5
-	github.com/gojp/goreportcard v0.0.0-20210127091035-7a8a1ebca86e // indirect
 	github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
 	github.com/golang/protobuf v1.4.3
 	github.com/google/gnxi v0.0.0-20201221102247-c26672548161
 	github.com/google/uuid v1.1.2
+	github.com/mitchellh/go-homedir v1.1.0
 	github.com/neo4j/neo4j-go-driver v1.8.3
 	github.com/openconfig/gnmi v0.0.0-20200617225440-d2b4e6a45802
 	github.com/openconfig/goyang v0.2.3
 	github.com/openconfig/ygot v0.10.0
 	github.com/sirupsen/logrus v1.4.2
+	github.com/spf13/cobra v1.1.1
 	github.com/spf13/viper v1.7.1
 	github.com/stretchr/testify v1.6.1
 	github.com/tidwall/gjson v1.6.3
diff --git a/go.sum b/go.sum
index 59afc42905687a008a80ddf3b2ceaa58f7c0fe31..70db040bd062cdb899f48d595eeb96e3f317d264 100644
--- a/go.sum
+++ b/go.sum
@@ -15,11 +15,8 @@ code.fbi.h-da.de/cocsn/swagger/apis v0.0.0-20200924152423-61030cab7b88/go.mod h1
 code.fbi.h-da.de/cocsn/yang-models v0.0.4 h1:y/Ph5CaD2NJDPjoOuS59iKrMYf9bvpg2/hefC2RG6E4=
 code.fbi.h-da.de/cocsn/yang-models v0.0.4/go.mod h1:7MnNmAQ9o84BpUepcaV6RB1mBGCNyXVJcdbKUl6rK0g=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
-github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
 github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@@ -27,9 +24,7 @@ github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tN
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
-github.com/Shopify/sarama v1.26.1 h1:3jnfWKD7gVwbB1KSy/lE0szA9duPuSFLViK0o/d3DgA=
 github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU=
-github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
 github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
 github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -39,16 +34,12 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
 github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
 github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
 github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
-github.com/aristanetworks/fsnotify v1.4.2 h1:it2ydpY6k0aXB7qjb4vGhOYOL6YDC/sr8vhqwokFQwQ=
 github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
-github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3 h1:Bmjk+DjIi3tTAU0wxGaFbfjGUqlxxSXARq9A96Kgoos=
 github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
 github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a h1:R7ghEBfKIqu/SDpGHS9Nj1fWPxkvxh6Lv4Wq6eS95G4=
 github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a/go.mod h1:Q4lsGfepQE823ePrSNr2CjCz1oeeMECJ6k1yBVujrZg=
-github.com/aristanetworks/splunk-hec-go v0.3.3 h1:O7zlcm4ve7JvqTyEK3vSBh1LngLezraqcxv8Ya6tQFY=
 github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
@@ -56,41 +47,29 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l
 github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
 github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
-github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
 github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
-github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
-github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
-github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE=
-github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
-github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
-github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
-github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
 github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
@@ -99,13 +78,9 @@ github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
 github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
 github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
-github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
-github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
 github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
-github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
 github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
-github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
 github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
 github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -113,20 +88,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
 github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
 github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
-github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3BTYk=
 github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
-github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
 github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
-github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
-github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
-github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591 h1:0WWUDZ1oxq7NxVyGo8M3KI5jbkiwNAdZFFzAdC68up4=
-github.com/gdamore/tcell/v2 v2.0.1-0.20201017141208-acf90d56d591/go.mod h1:vSVL/GV5mCSlPC6thFP5kfOFdM9MGZcalipmpTxTgQA=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
@@ -230,8 +197,6 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V
 github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
-github.com/gojp/goreportcard v0.0.0-20210127091035-7a8a1ebca86e h1:dIosri706uqS1jZBZ3E+jroCHY3Q2cl9eiawwExScaw=
-github.com/gojp/goreportcard v0.0.0-20210127091035-7a8a1ebca86e/go.mod h1:19GXi0dz4yFthI9Q8VmbvIVKoLLyIe/fvPi2VreSGhk=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -249,11 +214,9 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU
 github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
 github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
 github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
 github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
 github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -265,7 +228,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
 github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo=
 github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -281,7 +243,6 @@ github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
 github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0=
 github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
@@ -302,7 +263,6 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX
 github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
 github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
 github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
 github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
 github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@@ -315,10 +275,9 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d h1:/WZQPMZNsjZ7IlCpsLGdQBINg5bxKQ1K1sh6awxLtkA=
 github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
-github.com/jcmturner/gofork v1.0.0 h1:J7uCkflzTEhUZ64xqKnkDxq3kzc96ajM1Gli5ktUem8=
 github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
 github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@@ -336,16 +295,13 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
 github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
-github.com/klauspost/compress v1.10.1 h1:a/QY0o9S6wCi0XhxaMX/QmusicNUqCqFugR6WKPOSoQ=
 github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
-github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs=
 github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
 github.com/klauspost/pgzip v1.2.4/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
 github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
-github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY=
 github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
@@ -353,9 +309,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxv
 github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
 github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
 github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -363,10 +317,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
-github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
-github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
-github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/magiconair/properties v1.8.4 h1:8KGKTcQQGm0Kv7vEbKFErAoAOFyyacLStRtQSeYtvkY=
 github.com/magiconair/properties v1.8.4/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
@@ -380,22 +330,18 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI
 github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
-github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/mholt/archiver/v3 v3.5.0/go.mod h1:qqTTPUK/HZPFgFQ/TJ3BzvTpF/dPtFVJXdQbCmeMxwc=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
 github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
 github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -426,11 +372,9 @@ github.com/openconfig/gnmi v0.0.0-20200508230933-d19cebf5e7be/go.mod h1:M/EcuapN
 github.com/openconfig/gnmi v0.0.0-20200617225440-d2b4e6a45802 h1:WXFwJlWOJINlwlyAZuNo4GdYZS6qPX36+rRUncLmN8Q=
 github.com/openconfig/gnmi v0.0.0-20200617225440-d2b4e6a45802/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A=
 github.com/openconfig/goyang v0.0.0-20200115183954-d0a48929f0ea/go.mod h1:dhXaV0JgHJzdrHi2l+w0fZrwArtXL7jEFoiqLEdmkvU=
-github.com/openconfig/goyang v0.2.2 h1:J8hlJk1GSHrcr9vVI7dTvsThsKihWcNXRjWOkjRK0Cw=
 github.com/openconfig/goyang v0.2.2/go.mod h1:vX61x01Q46AzbZUzG617vWqh/cB+aisc+RrNkXRd3W8=
 github.com/openconfig/goyang v0.2.3 h1:pYxQ+VG6KNS3N5zkQeLmIBtc3gRs6JHZOKMD2/knlv4=
 github.com/openconfig/goyang v0.2.3/go.mod h1:vX61x01Q46AzbZUzG617vWqh/cB+aisc+RrNkXRd3W8=
-github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696 h1:yHCGAHg2zMaW8olLrqEt3SAHGcEx2aJPEQWMRCyravY=
 github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
 github.com/openconfig/ygot v0.6.0/go.mod h1:o30svNf7O0xK+R35tlx95odkDmZWS9JyWWQSmIhqwAs=
 github.com/openconfig/ygot v0.9.0/go.mod h1:oCQNdXnv7dWc8scTDgoFkauv1wwplJn5HspHcjlxSAQ=
@@ -438,65 +382,47 @@ github.com/openconfig/ygot v0.10.0 h1:EmgwLXbFiCBmEUlSI4/1fPuRzgf4EsD0sThmAmRqbY
 github.com/openconfig/ygot v0.10.0/go.mod h1:oCQNdXnv7dWc8scTDgoFkauv1wwplJn5HspHcjlxSAQ=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3 h1:YtFkrqsMEj7YqpIhRteVxJxCeC3jJBieuLr0d4C4rSA=
 github.com/pborman/getopt v0.0.0-20190409184431-ee0cd42419d3/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
 github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 github.com/pelletier/go-toml v1.8.1 h1:1Nf83orprkJyknT6h7zbuEGUEjcyVlCxSUGTENmNCRM=
 github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
-github.com/pierrec/lz4 v2.4.1+incompatible h1:mFe7ttWaflA46Mhqh+jUfjp2qTbPYxLB2/OyBppH9dg=
 github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
 github.com/pierrec/lz4/v4 v4.0.3/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
 github.com/pierrec/lz4/v4 v4.1.1/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/prometheus/client_golang v0.9.0-pre1.0.20171201122222-661e31bf844d/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.4.1 h1:FFSuS004yOQEtDdTq+TAOLP5xUq63KqAFYyOi8zA+Y8=
 github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/common v0.0.0-20171117163051-2e54d0b93cba/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
-github.com/prometheus/procfs v0.0.0-20171221151313-8f918ac9ab4b/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
-github.com/prometheus/procfs v0.0.10 h1:QJQN3jYQhkamO4mhfUWqdDH2asK7ONOI9MTWjyAxNKM=
 github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
-github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
 github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
-github.com/rivo/tview v0.0.0-20201018122409-d551c850a743 h1:9BBjVJTRxuYBeCAv9DFH2hSzY0ujLx5sxMg5D3K/Xeg=
-github.com/rivo/tview v0.0.0-20201018122409-d551c850a743/go.mod h1:t7mcA3nlK9dxD1DMoz/DQRMWFMkGBUj6rJBM5VNfLFA=
-github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
-github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
@@ -506,7 +432,6 @@ github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
 github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
 github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@@ -514,27 +439,21 @@ github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIK
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
-github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.4.1 h1:asw9sl74539yqavKaglDM5hFpdJVK0Y5Dr/JOgQ89nQ=
 github.com/spf13/afero v1.4.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
-github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
-github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
+github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
 github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
-github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
-github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
 github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
 github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
@@ -550,9 +469,7 @@ github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU=
 github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
-github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI=
 github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
 github.com/tidwall/gjson v1.6.3 h1:aHoiiem0dr7GHkW001T1SMTJ7X5PvyekH5WX0whWGnI=
 github.com/tidwall/gjson v1.6.3/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0=
@@ -561,10 +478,8 @@ github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0
 github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
 github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
-github.com/tjfoc/gmsm v1.3.0 h1:i7c6Za/IlgBvnGxYpfD7L3TGuaS+v6oGcgq+J9/ecEA=
 github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
-github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
 github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
 github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
@@ -574,10 +489,7 @@ github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHM
 github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
 github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
-github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
-github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg=
 github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
-github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
 github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -592,7 +504,6 @@ go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@@ -607,7 +518,6 @@ golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -652,7 +562,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
 golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY=
 golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -664,7 +573,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -673,7 +581,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -687,8 +594,6 @@ golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -696,9 +601,6 @@ golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200926100807-9d91bd62050c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7 h1:XtNJkfEjb4zR3q20BBBcYUykVOEMgZeIUOpBPfNYgxg=
-golang.org/x/sys v0.0.0-20201017003518-b09fb700fbb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs=
 golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -707,13 +609,11 @@ golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fq
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -736,17 +636,14 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw
 golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628034336-212fb13d595e/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd h1:hHkvGJK23seRCflePJnVa9IMv8fsuavSCWKd11kDQFs=
 golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -769,7 +666,6 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98
 google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
 google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
 google.golang.org/genproto v0.0.0-20200519141106-08726f379972/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d h1:HV9Z9qMhQEsdlvxNFELgQ11RkMzO3CMkjEySjCtuLes=
 google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -780,7 +676,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
 google.golang.org/grpc v1.34.0 h1:raiipEjMOIC/TO2AvyTxP25XFdLxNIBwzDh3FM3XztI=
 google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
@@ -796,33 +691,24 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
 google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
-gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a h1:stTHdEoWg1pQ8riaP5ROrjS6zy6wewH/Q2iwnLCQUXY=
 gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
 gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
-gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
 gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
 gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=
 gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
-gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
 gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
-gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=
 gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
-gopkg.in/jcmturner/gokrb5.v7 v7.5.0 h1:a9tsXlIDD9SKxotJMK3niV7rPZAJeX2aD/0yg3qlIrg=
 gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
-gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
 gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
-gopkg.in/redis.v4 v4.2.4 h1:y3XbwQAiHwgNLUng56mgWYK39vsPqo8sT84XTEcxjr0=
 gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
diff --git a/mocks/GrpcCliClient.go b/mocks/GrpcCliClient.go
deleted file mode 100644
index f52bffb70d5518b1b140fd2b2436632b104a5f0a..0000000000000000000000000000000000000000
--- a/mocks/GrpcCliClient.go
+++ /dev/null
@@ -1,349 +0,0 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
-
-package mocks
-
-import (
-	context "context"
-
-	gosdn "code.fbi.h-da.de/cocsn/gosdn/api/proto"
-	emptypb "google.golang.org/protobuf/types/known/emptypb"
-
-	grpc "google.golang.org/grpc"
-
-	mock "github.com/stretchr/testify/mock"
-)
-
-// GrpcCliClient is an autogenerated mock type for the GrpcCliClient type
-type GrpcCliClient struct {
-	mock.Mock
-}
-
-// AddDevice provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) AddDevice(ctx context.Context, in *gosdn.AddDeviceRequest, opts ...grpc.CallOption) (*gosdn.AddDeviceReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.AddDeviceReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.AddDeviceRequest, ...grpc.CallOption) *gosdn.AddDeviceReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.AddDeviceReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.AddDeviceRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// CreateLogStream provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) CreateLogStream(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (gosdn.GrpcCli_CreateLogStreamClient, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 gosdn.GrpcCli_CreateLogStreamClient
-	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) gosdn.GrpcCli_CreateLogStreamClient); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(gosdn.GrpcCli_CreateLogStreamClient)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// CreatePND provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) CreatePND(ctx context.Context, in *gosdn.CreatePNDRequest, opts ...grpc.CallOption) (*gosdn.CreatePNDReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.CreatePNDReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.CreatePNDRequest, ...grpc.CallOption) *gosdn.CreatePNDReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.CreatePNDReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.CreatePNDRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// GetAllPNDs provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) GetAllPNDs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*gosdn.AllPNDsReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.AllPNDsReply
-	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) *gosdn.AllPNDsReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.AllPNDsReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// GetAllSBINames provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) GetAllSBINames(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*gosdn.AllSBINamesReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.AllSBINamesReply
-	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) *gosdn.AllSBINamesReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.AllSBINamesReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// HandleDeviceGetRequest provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) HandleDeviceGetRequest(ctx context.Context, in *gosdn.DeviceGetRequest, opts ...grpc.CallOption) (*gosdn.DeviceGetReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.DeviceGetReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.DeviceGetRequest, ...grpc.CallOption) *gosdn.DeviceGetReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.DeviceGetReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.DeviceGetRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// SayHello provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) SayHello(ctx context.Context, in *gosdn.HelloRequest, opts ...grpc.CallOption) (*gosdn.HelloReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.HelloReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.HelloRequest, ...grpc.CallOption) *gosdn.HelloReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.HelloReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.HelloRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// Shutdown provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) Shutdown(ctx context.Context, in *gosdn.ShutdownRequest, opts ...grpc.CallOption) (*gosdn.ShutdownReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.ShutdownReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.ShutdownRequest, ...grpc.CallOption) *gosdn.ShutdownReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.ShutdownReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.ShutdownRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// TAPIGetEdge provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) TAPIGetEdge(ctx context.Context, in *gosdn.TAPIRequest, opts ...grpc.CallOption) (*gosdn.TAPIReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.TAPIReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.TAPIRequest, ...grpc.CallOption) *gosdn.TAPIReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.TAPIReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.TAPIRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// TAPIGetEdgeNode provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) TAPIGetEdgeNode(ctx context.Context, in *gosdn.TAPIRequest, opts ...grpc.CallOption) (*gosdn.TAPIReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.TAPIReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.TAPIRequest, ...grpc.CallOption) *gosdn.TAPIReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.TAPIReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.TAPIRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// TAPIGetLink provides a mock function with given fields: ctx, in, opts
-func (_m *GrpcCliClient) TAPIGetLink(ctx context.Context, in *gosdn.TAPIRequest, opts ...grpc.CallOption) (*gosdn.TAPIReply, error) {
-	_va := make([]interface{}, len(opts))
-	for _i := range opts {
-		_va[_i] = opts[_i]
-	}
-	var _ca []interface{}
-	_ca = append(_ca, ctx, in)
-	_ca = append(_ca, _va...)
-	ret := _m.Called(_ca...)
-
-	var r0 *gosdn.TAPIReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.TAPIRequest, ...grpc.CallOption) *gosdn.TAPIReply); ok {
-		r0 = rf(ctx, in, opts...)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.TAPIReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.TAPIRequest, ...grpc.CallOption) error); ok {
-		r1 = rf(ctx, in, opts...)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
diff --git a/mocks/GrpcCliServer.go b/mocks/GrpcCliServer.go
deleted file mode 100644
index e7b36e9e24f5c42ad7b927157fb3b9d6a7856927..0000000000000000000000000000000000000000
--- a/mocks/GrpcCliServer.go
+++ /dev/null
@@ -1,261 +0,0 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
-
-package mocks
-
-import (
-	context "context"
-
-	gosdn "code.fbi.h-da.de/cocsn/gosdn/api/proto"
-	emptypb "google.golang.org/protobuf/types/known/emptypb"
-
-	mock "github.com/stretchr/testify/mock"
-)
-
-// GrpcCliServer is an autogenerated mock type for the GrpcCliServer type
-type GrpcCliServer struct {
-	mock.Mock
-}
-
-// AddDevice provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) AddDevice(_a0 context.Context, _a1 *gosdn.AddDeviceRequest) (*gosdn.AddDeviceReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.AddDeviceReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.AddDeviceRequest) *gosdn.AddDeviceReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.AddDeviceReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.AddDeviceRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// CreateLogStream provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) CreateLogStream(_a0 *emptypb.Empty, _a1 gosdn.GrpcCli_CreateLogStreamServer) error {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(*emptypb.Empty, gosdn.GrpcCli_CreateLogStreamServer) error); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// CreatePND provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) CreatePND(_a0 context.Context, _a1 *gosdn.CreatePNDRequest) (*gosdn.CreatePNDReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.CreatePNDReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.CreatePNDRequest) *gosdn.CreatePNDReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.CreatePNDReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.CreatePNDRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// GetAllPNDs provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) GetAllPNDs(_a0 context.Context, _a1 *emptypb.Empty) (*gosdn.AllPNDsReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.AllPNDsReply
-	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty) *gosdn.AllPNDsReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.AllPNDsReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// GetAllSBINames provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) GetAllSBINames(_a0 context.Context, _a1 *emptypb.Empty) (*gosdn.AllSBINamesReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.AllSBINamesReply
-	if rf, ok := ret.Get(0).(func(context.Context, *emptypb.Empty) *gosdn.AllSBINamesReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.AllSBINamesReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *emptypb.Empty) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// HandleDeviceGetRequest provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) HandleDeviceGetRequest(_a0 context.Context, _a1 *gosdn.DeviceGetRequest) (*gosdn.DeviceGetReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.DeviceGetReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.DeviceGetRequest) *gosdn.DeviceGetReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.DeviceGetReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.DeviceGetRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// SayHello provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) SayHello(_a0 context.Context, _a1 *gosdn.HelloRequest) (*gosdn.HelloReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.HelloReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.HelloRequest) *gosdn.HelloReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.HelloReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.HelloRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// Shutdown provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) Shutdown(_a0 context.Context, _a1 *gosdn.ShutdownRequest) (*gosdn.ShutdownReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.ShutdownReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.ShutdownRequest) *gosdn.ShutdownReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.ShutdownReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.ShutdownRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// TAPIGetEdge provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) TAPIGetEdge(_a0 context.Context, _a1 *gosdn.TAPIRequest) (*gosdn.TAPIReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.TAPIReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.TAPIRequest) *gosdn.TAPIReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.TAPIReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.TAPIRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// TAPIGetEdgeNode provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) TAPIGetEdgeNode(_a0 context.Context, _a1 *gosdn.TAPIRequest) (*gosdn.TAPIReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.TAPIReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.TAPIRequest) *gosdn.TAPIReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.TAPIReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.TAPIRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// TAPIGetLink provides a mock function with given fields: _a0, _a1
-func (_m *GrpcCliServer) TAPIGetLink(_a0 context.Context, _a1 *gosdn.TAPIRequest) (*gosdn.TAPIReply, error) {
-	ret := _m.Called(_a0, _a1)
-
-	var r0 *gosdn.TAPIReply
-	if rf, ok := ret.Get(0).(func(context.Context, *gosdn.TAPIRequest) *gosdn.TAPIReply); ok {
-		r0 = rf(_a0, _a1)
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.TAPIReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func(context.Context, *gosdn.TAPIRequest) error); ok {
-		r1 = rf(_a0, _a1)
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
diff --git a/mocks/GrpcCli_CreateLogStreamClient.go b/mocks/GrpcCli_CreateLogStreamClient.go
deleted file mode 100644
index 8e8c0cc1f5a445354decaa4c491e9faa8938c6b5..0000000000000000000000000000000000000000
--- a/mocks/GrpcCli_CreateLogStreamClient.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
-
-package mocks
-
-import (
-	context "context"
-
-	gosdn "code.fbi.h-da.de/cocsn/gosdn/api/proto"
-	metadata "google.golang.org/grpc/metadata"
-
-	mock "github.com/stretchr/testify/mock"
-)
-
-// GrpcCli_CreateLogStreamClient is an autogenerated mock type for the GrpcCli_CreateLogStreamClient type
-type GrpcCli_CreateLogStreamClient struct {
-	mock.Mock
-}
-
-// CloseSend provides a mock function with given fields:
-func (_m *GrpcCli_CreateLogStreamClient) CloseSend() error {
-	ret := _m.Called()
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func() error); ok {
-		r0 = rf()
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// Context provides a mock function with given fields:
-func (_m *GrpcCli_CreateLogStreamClient) Context() context.Context {
-	ret := _m.Called()
-
-	var r0 context.Context
-	if rf, ok := ret.Get(0).(func() context.Context); ok {
-		r0 = rf()
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(context.Context)
-		}
-	}
-
-	return r0
-}
-
-// Header provides a mock function with given fields:
-func (_m *GrpcCli_CreateLogStreamClient) Header() (metadata.MD, error) {
-	ret := _m.Called()
-
-	var r0 metadata.MD
-	if rf, ok := ret.Get(0).(func() metadata.MD); ok {
-		r0 = rf()
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(metadata.MD)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func() error); ok {
-		r1 = rf()
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// Recv provides a mock function with given fields:
-func (_m *GrpcCli_CreateLogStreamClient) Recv() (*gosdn.LogReply, error) {
-	ret := _m.Called()
-
-	var r0 *gosdn.LogReply
-	if rf, ok := ret.Get(0).(func() *gosdn.LogReply); ok {
-		r0 = rf()
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*gosdn.LogReply)
-		}
-	}
-
-	var r1 error
-	if rf, ok := ret.Get(1).(func() error); ok {
-		r1 = rf()
-	} else {
-		r1 = ret.Error(1)
-	}
-
-	return r0, r1
-}
-
-// RecvMsg provides a mock function with given fields: m
-func (_m *GrpcCli_CreateLogStreamClient) RecvMsg(m interface{}) error {
-	ret := _m.Called(m)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
-		r0 = rf(m)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// SendMsg provides a mock function with given fields: m
-func (_m *GrpcCli_CreateLogStreamClient) SendMsg(m interface{}) error {
-	ret := _m.Called(m)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
-		r0 = rf(m)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// Trailer provides a mock function with given fields:
-func (_m *GrpcCli_CreateLogStreamClient) Trailer() metadata.MD {
-	ret := _m.Called()
-
-	var r0 metadata.MD
-	if rf, ok := ret.Get(0).(func() metadata.MD); ok {
-		r0 = rf()
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(metadata.MD)
-		}
-	}
-
-	return r0
-}
diff --git a/mocks/GrpcCli_CreateLogStreamServer.go b/mocks/GrpcCli_CreateLogStreamServer.go
deleted file mode 100644
index 6141c33a47ffc2e7707b088e70f426f9f661824d..0000000000000000000000000000000000000000
--- a/mocks/GrpcCli_CreateLogStreamServer.go
+++ /dev/null
@@ -1,108 +0,0 @@
-// Code generated by mockery v2.6.0. DO NOT EDIT.
-
-package mocks
-
-import (
-	context "context"
-
-	gosdn "code.fbi.h-da.de/cocsn/gosdn/api/proto"
-	metadata "google.golang.org/grpc/metadata"
-
-	mock "github.com/stretchr/testify/mock"
-)
-
-// GrpcCli_CreateLogStreamServer is an autogenerated mock type for the GrpcCli_CreateLogStreamServer type
-type GrpcCli_CreateLogStreamServer struct {
-	mock.Mock
-}
-
-// Context provides a mock function with given fields:
-func (_m *GrpcCli_CreateLogStreamServer) Context() context.Context {
-	ret := _m.Called()
-
-	var r0 context.Context
-	if rf, ok := ret.Get(0).(func() context.Context); ok {
-		r0 = rf()
-	} else {
-		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(context.Context)
-		}
-	}
-
-	return r0
-}
-
-// RecvMsg provides a mock function with given fields: m
-func (_m *GrpcCli_CreateLogStreamServer) RecvMsg(m interface{}) error {
-	ret := _m.Called(m)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
-		r0 = rf(m)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// Send provides a mock function with given fields: _a0
-func (_m *GrpcCli_CreateLogStreamServer) Send(_a0 *gosdn.LogReply) error {
-	ret := _m.Called(_a0)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(*gosdn.LogReply) error); ok {
-		r0 = rf(_a0)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// SendHeader provides a mock function with given fields: _a0
-func (_m *GrpcCli_CreateLogStreamServer) SendHeader(_a0 metadata.MD) error {
-	ret := _m.Called(_a0)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
-		r0 = rf(_a0)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// SendMsg provides a mock function with given fields: m
-func (_m *GrpcCli_CreateLogStreamServer) SendMsg(m interface{}) error {
-	ret := _m.Called(m)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(interface{}) error); ok {
-		r0 = rf(m)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// SetHeader provides a mock function with given fields: _a0
-func (_m *GrpcCli_CreateLogStreamServer) SetHeader(_a0 metadata.MD) error {
-	ret := _m.Called(_a0)
-
-	var r0 error
-	if rf, ok := ret.Get(0).(func(metadata.MD) error); ok {
-		r0 = rf(_a0)
-	} else {
-		r0 = ret.Error(0)
-	}
-
-	return r0
-}
-
-// SetTrailer provides a mock function with given fields: _a0
-func (_m *GrpcCli_CreateLogStreamServer) SetTrailer(_a0 metadata.MD) {
-	_m.Called(_a0)
-}
diff --git a/mocks/Transport.go b/mocks/Transport.go
index c83ad194936477755ba1b78a0d20820c116eb957..6dc256acae1ee730623be6ab1fd5508f9f4ed9f5 100644
--- a/mocks/Transport.go
+++ b/mocks/Transport.go
@@ -45,6 +45,22 @@ func (_m *Transport) Get(ctx context.Context, params ...string) (interface{}, er
 	return r0, r1
 }
 
+// GetOptions provides a mock function with given fields:
+func (_m *Transport) GetOptions() interface{} {
+	ret := _m.Called()
+
+	var r0 interface{}
+	if rf, ok := ret.Get(0).(func() interface{}); ok {
+		r0 = rf()
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(interface{})
+		}
+	}
+
+	return r0
+}
+
 // ProcessResponse provides a mock function with given fields: resp, root, models
 func (_m *Transport) ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error {
 	ret := _m.Called(resp, root, models)
diff --git a/mocks/TransportOptions.go b/mocks/TransportOptions.go
new file mode 100644
index 0000000000000000000000000000000000000000..4893655f8a5bc0fef06e4898e116fc3df7171421
--- /dev/null
+++ b/mocks/TransportOptions.go
@@ -0,0 +1,57 @@
+// Code generated by mockery v2.6.0. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// TransportOptions is an autogenerated mock type for the TransportOptions type
+type TransportOptions struct {
+	mock.Mock
+}
+
+// GetAddress provides a mock function with given fields:
+func (_m *TransportOptions) GetAddress() string {
+	ret := _m.Called()
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func() string); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	return r0
+}
+
+// GetPassword provides a mock function with given fields:
+func (_m *TransportOptions) GetPassword() string {
+	ret := _m.Called()
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func() string); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	return r0
+}
+
+// GetUsername provides a mock function with given fields:
+func (_m *TransportOptions) GetUsername() string {
+	ret := _m.Called()
+
+	var r0 string
+	if rf, ok := ret.Get(0).(func() string); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Get(0).(string)
+	}
+
+	return r0
+}
+
+// IsTransportOption provides a mock function with given fields:
+func (_m *TransportOptions) IsTransportOption() {
+	_m.Called()
+}
diff --git a/nucleus/cli-handling.go b/nucleus/cli-handling.go
deleted file mode 100644
index cd1a42d4d0d0d655bdcb70ca6c50e3e0bb054327..0000000000000000000000000000000000000000
--- a/nucleus/cli-handling.go
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
-	This file contains the grpc cli server-side calls.
-    Functions here should call other functions in charge of the
-	particular task.
-*/
-
-package nucleus
-
-import (
-	"context"
-	"errors"
-	"io"
-	"net"
-	"os"
-	"sync"
-
-	"github.com/google/uuid"
-	"github.com/spf13/viper"
-
-	pb "code.fbi.h-da.de/cocsn/gosdn/api/proto"
-	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
-	gpb "github.com/openconfig/gnmi/proto/gnmi"
-	log "github.com/sirupsen/logrus"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/health"
-	healthpb "google.golang.org/grpc/health/grpc_health_v1"
-	"google.golang.org/protobuf/types/known/emptypb"
-)
-
-type logConnection struct {
-	stream pb.GrpcCli_CreateLogStreamServer
-	id     string
-	active bool
-	error  chan error
-}
-
-// server is used to implement the grcp cli server
-type server struct {
-	pb.UnimplementedGrpcCliServer
-	core           *Core
-	logConnections []*logConnection
-}
-
-var srv *server
-
-type buf []byte
-
-func (b *buf) Write(p []byte) (n int, err error) {
-
-	reply := pb.LogReply{Log: string(p)}
-	srv.BroadcastLog(&reply)
-	return len(p), nil
-}
-
-func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
-	log.Info("Received: ", in.GetName())
-	return &pb.HelloReply{Message: "Hello " + in.GetName(), GoSDNInfo: "goSDN in version: DEVELOP"}, nil
-}
-
-// CreateLogStream creates a continuous stream between client and server to send goSDN logs
-func (s *server) CreateLogStream(req *emptypb.Empty, stream pb.GrpcCli_CreateLogStreamServer) error {
-	conn := &logConnection{
-		stream: stream,
-		active: true,
-		error:  make(chan error),
-	}
-	s.logConnections = append(s.logConnections, conn)
-
-	return <-conn.error
-}
-
-func (s *server) BroadcastLog(log *pb.LogReply) {
-	wait := sync.WaitGroup{}
-	done := make(chan int)
-
-	for _, conn := range s.logConnections {
-		wait.Add(1)
-
-		go func(conn *logConnection) {
-			defer wait.Done()
-			if conn.active {
-				err := conn.stream.Send(log)
-
-				if err != nil {
-					conn.active = false
-					conn.error <- err
-				}
-			}
-		}(conn)
-	}
-
-	go func() {
-		//blocks until all send routines are finished
-		wait.Wait()
-		close(done)
-	}()
-
-	<-done
-}
-
-func (s *server) Shutdown(ctx context.Context, in *pb.ShutdownRequest) (*pb.ShutdownReply, error) {
-	log.Info("Shutdown Received: ", in.GetName())
-	s.core.IsRunning <- false
-	return &pb.ShutdownReply{Message: "Shutdown " + in.GetName()}, nil
-}
-
-func getCLIGoing(core *Core) {
-
-	var (
-		logConnections []*logConnection
-		logBuffer      buf
-		system         = ""
-	)
-
-	log.Info("Starting: GetCLIGoing")
-	// Boot-up the control interface for the cli
-	cliControlListener, err := net.Listen("tcp", viper.GetString("socket"))
-	if err != nil {
-		log.Fatal(err)
-	}
-
-	cliControlServer := grpc.NewServer()
-	healthCheck := health.NewServer()
-	srv = &server{core: core, logConnections: logConnections}
-
-	//TODO: move?
-	wrt := io.MultiWriter(os.Stdout, &logBuffer)
-	log.SetOutput(wrt)
-
-	healthpb.RegisterHealthServer(cliControlServer, healthCheck)
-	pb.RegisterGrpcCliServer(cliControlServer, srv)
-
-	healthCheck.SetServingStatus(system, healthpb.HealthCheckResponse_SERVING)
-
-	if err := cliControlServer.Serve(cliControlListener); err != nil {
-		log.Fatal(err)
-	}
-}
-
-// CreatePND creates a new PND and adds it to the principalNetworkDomain map of
-// the core
-func (s *server) CreatePND(ctx context.Context, in *pb.CreatePNDRequest) (*pb.CreatePNDReply, error) {
-	log.Info("Received: Create a PND with the name", in.GetName())
-	sbi, err := s.core.sbic.get(uuid.New())
-	if err != nil {
-		return nil, err
-	}
-	id := uuid.New()
-	pnd, err := NewPND(in.GetName(), in.GetDescription(), id, sbi.(SouthboundInterface))
-	if err != nil {
-		log.Error(err)
-		return &pb.CreatePNDReply{Message: err.Error()}, err
-	}
-	if err := s.core.pndc.add(pnd); err != nil {
-		return nil, err
-	}
-
-	return &pb.CreatePNDReply{Message: "Created new PND: " + id.String()}, nil
-}
-
-// deprecated
-// Subject to change, using discontinued full device access
-// GetAllPNDs is a request to get all currently registered PNDs and returns a slim
-// variant of PNDs and their respective devices
-func (s *server) GetAllPNDs(ctx context.Context, in *emptypb.Empty) (*pb.AllPNDsReply, error) {
-	log.Info("Received: Get all PNDs")
-	var pnds []*pb.PND
-	for _, uuidPND := range s.core.pndc.UUIDs() {
-		pnd, err := s.core.pndc.get(uuidPND)
-		if err != nil {
-			log.Error(err)
-			continue
-		}
-		var devices []*pb.Device
-		for uuidDevice, d := range pnd.(*pndImplementation).devices.store {
-			device, ok := d.(*Device)
-			if !ok {
-				log.Error(&ErrInvalidTypeAssertion{
-					v: d,
-					t: "Device",
-				})
-			}
-			tmpDevice := pb.Device{
-				Uuid:     uuidDevice.String(),
-				Address:  device.Config.Address,
-				Username: device.Config.Username,
-				Password: device.Config.Password}
-			devices = append(devices, &tmpDevice)
-		}
-		sbi, err := s.core.sbic.get(pnd.GetSBIs().(*sbiStore).UUIDs()[0])
-		if err != nil {
-			log.Error(err)
-			continue
-		}
-		tmpPND := pb.PND{
-			Uuid:        uuidPND.String(),
-			Name:        pnd.GetName(),
-			Description: pnd.GetDescription(),
-			Sbi:         sbi.SbiIdentifier(),
-			Devices:     devices,
-		}
-		pnds = append(pnds, &tmpPND)
-	}
-	return &pb.AllPNDsReply{Pnds: pnds}, nil
-}
-
-// GetAllSBINames returns all registered SBIs from core.
-func (s *server) GetAllSBINames(ctx context.Context, in *emptypb.Empty) (*pb.AllSBINamesReply, error) {
-	var sbiNames []string
-	for _, uuidDevice := range s.core.sbic.UUIDs() {
-		s, err := s.core.sbic.get(uuidDevice)
-		if err != nil {
-			log.Error(err)
-			continue
-		}
-		sbiNames = append(sbiNames, s.SbiIdentifier())
-	}
-	return &pb.AllSBINamesReply{SbiNames: sbiNames}, nil
-}
-
-// AddDevice adds a new Device to a specific PND
-// currently this is only working with gnmi transports
-func (s *server) AddDevice(ctx context.Context, in *pb.AddDeviceRequest) (*pb.AddDeviceReply, error) {
-	log.Info("Received: AddDevice")
-	uuidPND, err := uuid.Parse(in.UuidPND)
-	if err != nil {
-		return &pb.AddDeviceReply{Message: err.Error()}, err
-	}
-	pnd, err := s.core.pndc.get(uuidPND)
-	if err != nil {
-		log.Error(err)
-		return &pb.AddDeviceReply{Message: err.Error()}, err
-	}
-	// TODO: Add notion of default SBI to PND or solve differently
-	uuidSbi := pnd.GetSBIs().(*sbiStore).UUIDs()[0]
-	sbi, err := s.core.sbic.get(uuidSbi)
-	if err != nil {
-		log.Error(err)
-		return &pb.AddDeviceReply{Message: err.Error()}, err
-	}
-
-	//TODO: could the transport and the related config be created in device?
-	transport := &Gnmi{SetNode: sbi.SetNode()}
-	cfg := &gnmi.Config{
-		Addr:     in.Device.Address,
-		Username: in.Device.Username,
-		Password: in.Device.Password,
-		Encoding: gpb.Encoding_JSON_IETF,
-	}
-	transport.SetConfig(cfg)
-
-	newDevice := NewDevice(sbi, in.Device.Address, in.Device.Username,
-		in.Device.Password, transport)
-
-	err = pnd.AddDevice(newDevice)
-	if err != nil {
-		log.Error(err)
-		return &pb.AddDeviceReply{Message: err.Error()}, err
-	}
-
-	return &pb.AddDeviceReply{Message: "Added new Device: " + newDevice.Config.Uuid.String()}, err
-}
-
-// HandleDeviceGetRequest handles a GET request via pnd.Request()
-func (s *server) HandleDeviceGetRequest(ctx context.Context, in *pb.DeviceGetRequest) (*pb.DeviceGetReply, error) {
-	log.Info("Received: HandleDeviceGetRequest")
-	uuidPND, err := uuid.Parse(in.GetUuidPND())
-	if err != nil {
-		log.Info(err)
-		return &pb.DeviceGetReply{Message: err.Error()}, err
-	}
-	uuidDevice, err := uuid.Parse(in.GetUuidDevice())
-	if err != nil {
-		log.Info(err)
-		return &pb.DeviceGetReply{Message: err.Error()}, err
-	}
-	pnd, err := s.core.pndc.get(uuidPND)
-	if err != nil {
-		err := errors.New("Couldnt find PND: UUID is wrong")
-		log.Info(err)
-		return &pb.DeviceGetReply{Message: err.Error()}, err
-	}
-	//check if the device exists
-	if !pnd.ContainsDevice(uuidDevice) {
-		err := errors.New("Couldnt find device: UUID is wrong")
-		log.Info(err)
-		return &pb.DeviceGetReply{Message: err.Error()}, err
-	}
-
-	//GET request for the provided path
-	err = pnd.Request(uuidDevice, in.GetPath())
-	if err != nil {
-		log.Info(err)
-		return &pb.DeviceGetReply{Message: err.Error()}, err
-	}
-
-	d, err := pnd.MarshalDevice(uuidDevice)
-	if err != nil {
-		log.Info(err)
-		return &pb.DeviceGetReply{Message: err.Error()}, err
-	}
-
-	return &pb.DeviceGetReply{Message: d}, nil
-}
diff --git a/nucleus/cli-handling_test.go b/nucleus/cli-handling_test.go
deleted file mode 100644
index 522de1a0cfa12cea3ac919e23f5696865e7159f1..0000000000000000000000000000000000000000
--- a/nucleus/cli-handling_test.go
+++ /dev/null
@@ -1,377 +0,0 @@
-package nucleus
-
-import (
-	pb "code.fbi.h-da.de/cocsn/gosdn/api/proto"
-	"context"
-	"google.golang.org/protobuf/types/known/emptypb"
-	"reflect"
-	"testing"
-)
-
-func Test_buf_Write(t *testing.T) {
-	type args struct {
-		p []byte
-	}
-	tests := []struct {
-		name    string
-		b       buf
-		args    args
-		wantN   int
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			gotN, err := tt.b.Write(tt.args.p)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("Write() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if gotN != tt.wantN {
-				t.Errorf("Write() gotN = %v, want %v", gotN, tt.wantN)
-			}
-		})
-	}
-}
-
-func Test_getCLIGoing(t *testing.T) {
-	type args struct {
-		core *Core
-	}
-	tests := []struct {
-		name string
-		args args
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-		})
-	}
-}
-
-func Test_server_AddDevice(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *pb.AddDeviceRequest
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.AddDeviceReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.AddDevice(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("AddDevice() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_server_BroadcastLog(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		log *pb.LogReply
-	}
-	tests := []struct {
-		name   string
-		fields fields
-		args   args
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			_ = &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-		})
-	}
-}
-
-func Test_server_CreateLogStream(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		req    *emptypb.Empty
-		stream pb.GrpcCli_CreateLogStreamServer
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			if err := s.CreateLogStream(tt.args.req, tt.args.stream); (err != nil) != tt.wantErr {
-				t.Errorf("CreateLogStream() error = %v, wantErr %v", err, tt.wantErr)
-			}
-		})
-	}
-}
-
-func Test_server_CreatePND(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *pb.CreatePNDRequest
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.CreatePNDReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.CreatePND(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("CreatePND() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("CreatePND() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_server_GetAllPNDs(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *emptypb.Empty
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.AllPNDsReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.GetAllPNDs(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("GetAllPNDs() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("GetAllPNDs() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_server_GetAllSBINames(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *emptypb.Empty
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.AllSBINamesReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.GetAllSBINames(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("GetAllSBINames() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("GetAllSBINames() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_server_HandleDeviceGetRequest(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *pb.DeviceGetRequest
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.DeviceGetReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.HandleDeviceGetRequest(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("HandleDeviceGetRequest() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("HandleDeviceGetRequest() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_server_SayHello(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *pb.HelloRequest
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.HelloReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.SayHello(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("SayHello() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("SayHello() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
-func Test_server_Shutdown(t *testing.T) {
-	type fields struct {
-		UnimplementedGrpcCliServer pb.UnimplementedGrpcCliServer
-		core                       *Core
-		logConnections             []*logConnection
-	}
-	type args struct {
-		ctx context.Context
-		in  *pb.ShutdownRequest
-	}
-	tests := []struct {
-		name    string
-		fields  fields
-		args    args
-		want    *pb.ShutdownReply
-		wantErr bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			s := &server{
-				UnimplementedGrpcCliServer: tt.fields.UnimplementedGrpcCliServer,
-				core:                       tt.fields.core,
-				logConnections:             tt.fields.logConnections,
-			}
-			got, err := s.Shutdown(tt.args.ctx, tt.args.in)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("Shutdown() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("Shutdown() got = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
diff --git a/nucleus/device.go b/nucleus/device.go
index 24007fd301beb364f09ce09020314bcf020c8ae6..8d721e72eb03e0012d457a9a943a1ae08ddd5347 100644
--- a/nucleus/device.go
+++ b/nucleus/device.go
@@ -6,42 +6,41 @@ import (
 )
 
 type Device struct {
+	// Uuid represents the Devices UUID
+	Uuid uuid.UUID
+
 	// Device inherits properties of ygot.GoStruct
 	ygot.GoStruct
 
 	// SBI is the device's southbound interface implementation
 	SBI SouthboundInterface
 
-	// Config is the device's config. Under revision
-	Config DeviceConfig
-
 	// Transport is the device's Transport implementation
 	Transport Transport
 }
 
 //NewDevice creates a Device
-func NewDevice(sbi SouthboundInterface, addr, username, password string,
-	transport Transport) *Device {
+func NewDevice(sbi SouthboundInterface, opts TransportOptions) (*Device, error) {
+	var transport Transport
+	var err error
+	switch opts.(type) {
+	case *GnmiTransportOptions:
+		transport, err = NewGnmiTransport(opts.(*GnmiTransportOptions))
+		if err != nil {
+			return nil, err
+		}
+	default:
+		return nil, &ErrInvalidTransportOptions{opts}
+
+	}
 	return &Device{
-		GoStruct: sbi.Schema().Root,
-		SBI:      sbi,
-		Config: DeviceConfig{
-			Uuid:     uuid.New(),
-			Address:  addr,
-			Username: username,
-			Password: password,
-		},
+		Uuid:      uuid.New(),
+		GoStruct:  sbi.Schema().Root,
+		SBI:       sbi,
 		Transport: transport,
-	}
+	}, nil
 }
 
 func (d *Device) Id() uuid.UUID {
-	return d.Config.Uuid
-}
-
-type DeviceConfig struct {
-	Uuid     uuid.UUID
-	Address  string
-	Username string
-	Password string
+	return d.Uuid
 }
diff --git a/nucleus/device_test.go b/nucleus/device_test.go
index 443744d8c8c91ac46a8fade40c91967effd125f7..d6391e830b584836b8d5d6a8928d5320d05e2e36 100644
--- a/nucleus/device_test.go
+++ b/nucleus/device_test.go
@@ -1,6 +1,7 @@
 package nucleus
 
 import (
+	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
 	"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
 	"github.com/google/uuid"
 	"github.com/openconfig/ygot/ygot"
@@ -12,8 +13,8 @@ func TestDevice_Id(t *testing.T) {
 	type fields struct {
 		GoStruct  ygot.GoStruct
 		SBI       SouthboundInterface
-		Config    DeviceConfig
 		Transport Transport
+		Uuid      uuid.UUID
 	}
 	tests := []struct {
 		name   string
@@ -23,9 +24,7 @@ func TestDevice_Id(t *testing.T) {
 		{
 			name: "default",
 			fields: fields{
-				Config: DeviceConfig{
-					Uuid: did,
-				},
+				Uuid: did,
 			},
 			want: did,
 		},
@@ -35,8 +34,8 @@ func TestDevice_Id(t *testing.T) {
 			d := &Device{
 				GoStruct:  tt.fields.GoStruct,
 				SBI:       tt.fields.SBI,
-				Config:    tt.fields.Config,
 				Transport: tt.fields.Transport,
+				Uuid:      tt.fields.Uuid,
 			}
 			if got := d.Id(); !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("Id() = %v, want %v", got, tt.want)
@@ -48,45 +47,57 @@ func TestDevice_Id(t *testing.T) {
 func TestNewDevice(t *testing.T) {
 	sbi := &OpenConfig{}
 	type args struct {
-		sbi       SouthboundInterface
-		addr      string
-		username  string
-		password  string
-		transport Transport
+		sbi  SouthboundInterface
+		opts TransportOptions
 	}
 	tests := []struct {
-		name string
-		args args
-		want *Device
+		name    string
+		args    args
+		want    *Device
+		wantErr bool
 	}{
 		{
 			name: "default",
 			args: args{
-				sbi:       sbi,
-				addr:      "testdevice",
-				username:  "testuser",
-				password:  "testpassword",
-				transport: &Gnmi{},
+				sbi: sbi,
+				opts: &GnmiTransportOptions{
+					Config: gnmi.Config{
+						Addr:     "test:///",
+						Username: "test",
+						Password: "test",
+					},
+				},
 			},
 			want: &Device{
 				GoStruct: &openconfig.Device{},
 				SBI:      sbi,
-				Config: DeviceConfig{
-					Uuid:     uuid.UUID{},
-					Address:  "testdevice",
-					Username: "testuser",
-					Password: "testpassword",
+				Uuid:     uuid.New(),
+				Transport: &Gnmi{
+					Options: &GnmiTransportOptions{
+						Config: gnmi.Config{
+							Addr:     "test:///",
+							Username: "test",
+							Password: "test",
+						},
+					},
 				},
-				Transport: &Gnmi{},
 			},
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got := NewDevice(tt.args.sbi, tt.args.addr, tt.args.username, tt.args.password, tt.args.transport)
-			tt.want.Config.Uuid = got.Id()
+			got, err := NewDevice(tt.args.sbi, tt.args.opts)
+			if err != nil {
+				t.Error(err)
+			}
+			tt.want.Transport.(*Gnmi).client = got.Transport.(*Gnmi).client
+			tt.want.Uuid = got.Id()
+			if (err != nil) != tt.wantErr {
+				t.Errorf("NewDevice() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
 			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("NewDevice() = %v, want %v", got, tt.want)
+				t.Errorf("NewDevice() got = %v, want %v", got, tt.want)
 			}
 		})
 	}
diff --git a/nucleus/errors.go b/nucleus/errors.go
index 9656b7327acc584f7240fa09af334904e2f92d06..453dccf3b8b872085410f512e72906f08c2a96a5 100644
--- a/nucleus/errors.go
+++ b/nucleus/errors.go
@@ -1,6 +1,9 @@
 package nucleus
 
-import "fmt"
+import (
+	"fmt"
+	"reflect"
+)
 
 type ErrNilClient struct {
 }
@@ -55,4 +58,12 @@ type ErrInvalidParameters struct {
 
 func (e ErrInvalidParameters) Error() string {
 	return fmt.Sprintf("invalid parameters for %v: %v", e.f, e.r)
+}
+
+type ErrInvalidTransportOptions struct {
+	t interface{}
+}
+
+func (e ErrInvalidTransportOptions) Error() string {
+	return fmt.Sprintf("invalid transport options: %v", reflect.TypeOf(e.t))
 }
\ No newline at end of file
diff --git a/nucleus/gnmi_transport.go b/nucleus/gnmi_transport.go
index 1519721e2fa8d531a0f8ef42dbced5c276019a69..30af29f2320e673a0f013e5738fa00ff63cfdbe4 100644
--- a/nucleus/gnmi_transport.go
+++ b/nucleus/gnmi_transport.go
@@ -11,31 +11,35 @@ import (
 	"strings"
 )
 
-func NewGnmiTransport(config *gnmi.Config) (*Gnmi, error) {
-	c, err := gnmi.Dial(config)
+type Gnmi struct {
+	SetNode   func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
+	RespChan  chan *gpb.SubscribeResponse
+	Unmarshal func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error
+	Options   *GnmiTransportOptions
+	client    gpb.GNMIClient
+}
+
+func NewGnmiTransport(opts *GnmiTransportOptions) (*Gnmi, error) {
+	c, err := gnmi.Dial(&opts.Config)
 	if err != nil {
 		return nil, err
 	}
 	return &Gnmi{
-		config: config,
-		client: c,
+		SetNode:  opts.SetNode,
+		RespChan: opts.RespChan,
+		Options:  opts,
+		client:   c,
 	}, nil
 }
 
-type Gnmi struct {
-	SetNode   func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
-	Unmarshal func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error
-	RespChan  chan *gpb.SubscribeResponse
-	config    *gnmi.Config
-	client    gpb.GNMIClient
-}
-
-func (g *Gnmi) SetConfig(config *gnmi.Config) {
-	g.config = config
+//SetConfig sets the config of gnmi
+func (g *Gnmi) SetOptions(to TransportOptions) {
+	g.Options = to.(*GnmiTransportOptions)
 }
 
-func (g *Gnmi) GetConfig() *gnmi.Config {
-	return g.config
+//GetConfig returns the gnmi config
+func (g *Gnmi) GetOptions() interface{} {
+	return g.Options
 }
 
 // interface satisfaction for now
@@ -65,7 +69,7 @@ func (g *Gnmi) Set(ctx context.Context, params ...interface{}) (interface{}, err
 	// Invalid params cause unhealable error
 	ops := make([]*gnmi.Operation, 0)
 	exts := make([]*gnmi_ext.Extension, 0)
-	for _,p := range params{
+	for _, p := range params {
 		switch p.(type) {
 		case *gnmi.Operation:
 			ops = append(ops, p.(*gnmi.Operation))
@@ -136,8 +140,8 @@ func extraxtPathElements(path *gpb.Path) []string {
 
 // Capabilities calls GNMI capabilities
 func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) {
-	ctx = gnmi.NewContext(ctx, g.config)
-	ctx = context.WithValue(ctx, "config", g.config)
+	ctx = gnmi.NewContext(ctx, &g.Options.Config)
+	ctx = context.WithValue(ctx, "config", &g.Options.Config)
 	resp, err := g.client.Capabilities(ctx, &gpb.CapabilityRequest{})
 	if err != nil {
 		return nil, err
@@ -147,8 +151,8 @@ func (g *Gnmi) Capabilities(ctx context.Context) (interface{}, error) {
 
 // get calls GNMI get
 func (g *Gnmi) get(ctx context.Context, paths [][]string, origin string) (interface{}, error) {
-	ctx = gnmi.NewContext(ctx, g.config)
-	ctx = context.WithValue(ctx, "config", g.config)
+	ctx = gnmi.NewContext(ctx, &g.Options.Config)
+	ctx = context.WithValue(ctx, "config", &g.Options.Config)
 	req, err := gnmi.NewGetRequest(ctx, paths, origin)
 	if err != nil {
 		return nil, err
@@ -169,13 +173,13 @@ func (g *Gnmi) getWithRequest(ctx context.Context, req *gpb.GetRequest) (interfa
 // Set calls GNMI set
 func (g *Gnmi) set(ctx context.Context, setOps []*gnmi.Operation,
 	exts ...*gnmi_ext.Extension) (*gpb.SetResponse, error) {
-	ctx = gnmi.NewContext(ctx, g.config)
+	ctx = gnmi.NewContext(ctx, &g.Options.Config)
 	return gnmi.Set(ctx, g.client, setOps, exts...)
 }
 
 // Subscribe calls GNMI subscribe
 func (g *Gnmi) subscribe(ctx context.Context) error {
-	ctx = gnmi.NewContext(ctx, g.config)
+	ctx = gnmi.NewContext(ctx, &g.Options.Config)
 	opts := ctx.Value("opts").(*gnmi.SubscribeOptions)
 	go func() {
 		for {
@@ -194,3 +198,25 @@ func (g *Gnmi) subscribe(ctx context.Context) error {
 func (g *Gnmi) Close() error {
 	return nil
 }
+
+type GnmiTransportOptions struct {
+	// all needed gnmi transport parameters
+	gnmi.Config
+
+	SetNode func(schema *yang.Entry, root interface{}, path *gpb.Path,
+		val interface{}, opts ...ytypes.SetNodeOpt) error
+	Unmarshal func([]byte, []string, interface{}, ...ytypes.UnmarshalOpt) error
+	RespChan  chan *gpb.SubscribeResponse
+}
+
+func (gto *GnmiTransportOptions) GetAddress() string {
+	return gto.Addr
+}
+func (gto *GnmiTransportOptions) GetUsername() string {
+	return gto.Username
+}
+func (gto *GnmiTransportOptions) GetPassword() string {
+	return gto.Password
+}
+
+func (gto *GnmiTransportOptions) IsTransportOption() {}
diff --git a/nucleus/gnmi_transport_test.go b/nucleus/gnmi_transport_test.go
index d604ecc65016569dca780f17718a616dc783bd12..888a01a7b49f1274c87dfad854fc70b2cd1977a3 100644
--- a/nucleus/gnmi_transport_test.go
+++ b/nucleus/gnmi_transport_test.go
@@ -3,18 +3,18 @@ package nucleus
 import (
 	"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
 	"code.fbi.h-da.de/cocsn/gosdn/mocks"
-	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
 	"code.fbi.h-da.de/cocsn/gosdn/test"
 	"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
 	"context"
 	"errors"
 	log "github.com/golang/glog"
-	"github.com/golang/protobuf/proto"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	"github.com/openconfig/gnmi/proto/gnmi_ext"
 	"github.com/openconfig/goyang/pkg/yang"
 	"github.com/openconfig/ygot/ytypes"
 	"github.com/stretchr/testify/mock"
+	pb "google.golang.org/protobuf/proto"
 	"os"
 	"reflect"
 	"testing"
@@ -23,21 +23,22 @@ import (
 // TestMain bootstraps all tests. Humongous beast
 // TODO: Move somewhere more sensible
 func TestMain(m *testing.M) {
-	gnmiMessages = map[string]proto.Message{
-		"../test/cap-resp-arista-ceos":                  &gpb.CapabilityResponse{},
-		"../test/req-full-node":                         &gpb.GetRequest{},
-		"../test/req-full-node-arista-ceos":             &gpb.GetRequest{},
-		"../test/req-interfaces-arista-ceos":            &gpb.GetRequest{},
-		"../test/req-interfaces-interface-arista-ceos":  &gpb.GetRequest{},
-		"../test/req-interfaces-wildcard":               &gpb.GetRequest{},
-		"../test/resp-full-node":                        &gpb.GetResponse{},
-		"../test/resp-full-node-arista-ceos":            &gpb.GetResponse{},
-		"../test/resp-interfaces-arista-ceos":           &gpb.GetResponse{},
-		"../test/resp-interfaces-interface-arista-ceos": &gpb.GetResponse{},
-		"../test/resp-interfaces-wildcard":              &gpb.GetResponse{},
+	gnmiMessages = map[string]pb.Message{
+		"../test/proto/cap-resp-arista-ceos":                  &gpb.CapabilityResponse{},
+		"../test/proto/req-full-node":                         &gpb.GetRequest{},
+		"../test/proto/req-full-node-arista-ceos":             &gpb.GetRequest{},
+		"../test/proto/req-interfaces-arista-ceos":            &gpb.GetRequest{},
+		"../test/proto/req-interfaces-interface-arista-ceos":  &gpb.GetRequest{},
+		"../test/proto/req-interfaces-wildcard":               &gpb.GetRequest{},
+		"../test/proto/resp-full-node":                        &gpb.GetResponse{},
+		"../test/proto/resp-full-node-arista-ceos":            &gpb.GetResponse{},
+		"../test/proto/resp-interfaces-arista-ceos":           &gpb.GetResponse{},
+		"../test/proto/resp-interfaces-interface-arista-ceos": &gpb.GetResponse{},
+		"../test/proto/resp-interfaces-wildcard":              &gpb.GetResponse{},
+		"../test/proto/resp-set-system-config-hostname":       &gpb.SetResponse{},
 	}
 	for k, v := range gnmiMessages {
-		if err := util.Read(k, v); err != nil {
+		if err := proto.Read(k, v); err != nil {
 			log.Fatalf("error parsing %v: %v", k, err)
 		}
 	}
@@ -77,12 +78,25 @@ func mockTransport() Gnmi {
 	return Gnmi{
 		SetNode:  nil,
 		RespChan: make(chan *gpb.SubscribeResponse),
-		config:   gnmiConfig,
+		Options:  newGnmiTransportOptions(),
 		client:   &mocks.GNMIClient{},
 	}
 }
 
-var gnmiMessages map[string]proto.Message
+func newGnmiTransportOptions() *GnmiTransportOptions {
+	return &GnmiTransportOptions{
+		Config: gnmi.Config{
+			Username: "test",
+			Password: "test",
+			Addr:     "localhost:13371",
+			Encoding: gpb.Encoding_PROTO,
+		},
+		SetNode:  nil,
+		RespChan: make(chan *gpb.SubscribeResponse),
+	}
+}
+
+var gnmiMessages map[string]pb.Message
 var gnmiConfig *gnmi.Config
 var startGnmiTarget chan string
 var stopGnmiTarget chan bool
@@ -170,7 +184,6 @@ func TestGnmi_Close(t *testing.T) {
 			g := &Gnmi{
 				SetNode:  tt.fields.SetNode,
 				RespChan: tt.fields.RespChan,
-				config:   tt.fields.config,
 			}
 			if err := g.Close(); (err != nil) != tt.wantErr {
 				t.Errorf("Close() error = %v, wantErr %v", err, tt.wantErr)
@@ -249,7 +262,7 @@ func TestGnmi_Get(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			if tt.args.runEndpoint {
-				startGnmiTarget <- tt.fields.transport.config.Addr
+				startGnmiTarget <- tt.fields.transport.Options.Addr
 			}
 			got, err := tt.fields.transport.Get(context.Background(), tt.args.params...)
 			if (err != nil) != tt.wantErr {
@@ -266,31 +279,6 @@ func TestGnmi_Get(t *testing.T) {
 	}
 }
 
-func TestGnmi_GetConfig(t *testing.T) {
-	transport := mockTransport()
-	type fields struct {
-		transport *Gnmi
-	}
-	tests := []struct {
-		name   string
-		fields fields
-		want   *gnmi.Config
-	}{
-		{
-			name:   "default",
-			fields: fields{transport: &transport},
-			want:   gnmiConfig,
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			if got := tt.fields.transport.GetConfig(); !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("GetConfig() = %v, want %v", got, tt.want)
-			}
-		})
-	}
-}
-
 func TestGnmi_ProcessResponse(t *testing.T) {
 	type fields struct {
 		Sbi SouthboundInterface
@@ -309,7 +297,7 @@ func TestGnmi_ProcessResponse(t *testing.T) {
 			name:   "Interfaces Interface",
 			fields: fields{Sbi: &OpenConfig{}},
 			args: args{
-				path: "../test/resp-interfaces-interface-arista-ceos",
+				path: "../test/proto/resp-interfaces-interface-arista-ceos",
 				root: &openconfig.Device{},
 			},
 			wantErr: true,
@@ -318,7 +306,7 @@ func TestGnmi_ProcessResponse(t *testing.T) {
 			name:   "Interfaces Wildcard",
 			fields: fields{Sbi: &OpenConfig{}},
 			args: args{
-				path: "../test/resp-interfaces-wildcard",
+				path: "../test/proto/resp-interfaces-wildcard",
 				root: &openconfig.Device{},
 			},
 			wantErr: false,
@@ -327,7 +315,7 @@ func TestGnmi_ProcessResponse(t *testing.T) {
 			name:   "Root",
 			fields: fields{Sbi: &OpenConfig{}},
 			args: args{
-				path: "../test/resp-full-node-arista-ceos",
+				path: "../test/proto/resp-full-node-arista-ceos",
 				root: &openconfig.Device{},
 			},
 			wantErr: false,
@@ -388,47 +376,6 @@ func TestGnmi_Set(t *testing.T) {
 	}
 }
 
-func TestGnmi_SetConfig(t *testing.T) {
-	type fields struct {
-		SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
-		RespChan chan *gpb.SubscribeResponse
-		config   *gnmi.Config
-	}
-	type args struct {
-		config *gnmi.Config
-	}
-	tests := []struct {
-		name   string
-		fields fields
-		args   args
-	}{
-		{
-			name: "default",
-			fields: fields{
-				SetNode:  nil,
-				RespChan: nil,
-				config:   nil,
-			},
-			args: args{
-				config: &gnmi.Config{
-					Addr:     "test:///",
-					Password: "test",
-					Username: "test",
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			g := &Gnmi{}
-			g.SetConfig(tt.args.config)
-			if !reflect.DeepEqual(g.config, tt.args.config) {
-				t.Errorf("Type() = %v, want %v", g.config, tt.args.config)
-			}
-		})
-	}
-}
-
 func TestGnmi_Subscribe(t *testing.T) {
 	type fields struct {
 		SetNode  func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error
@@ -475,7 +422,6 @@ func TestGnmi_Type(t *testing.T) {
 			g := &Gnmi{
 				SetNode:  tt.fields.SetNode,
 				RespChan: tt.fields.RespChan,
-				config:   tt.fields.config,
 			}
 			if got := g.Type(); got != tt.want {
 				t.Errorf("Type() = %v, want %v", got, tt.want)
@@ -486,10 +432,10 @@ func TestGnmi_Type(t *testing.T) {
 
 func TestGnmi_getWithRequest(t *testing.T) {
 	transport := mockTransport()
-	reqFullNode := gnmiMessages["../test/req-full-node"].(*gpb.GetRequest)
-	reqInterfacesWildcard := gnmiMessages["../test/req-interfaces-wildcard"].(*gpb.GetRequest)
-	respFullNode := gnmiMessages["../test/resp-full-node"].(*gpb.GetResponse)
-	respInterfacesWildcard := gnmiMessages["../test/resp-interfaces-wildcard"].(*gpb.GetResponse)
+	reqFullNode := gnmiMessages["../test/proto/req-full-node"].(*gpb.GetRequest)
+	reqInterfacesWildcard := gnmiMessages["../test/proto/req-interfaces-wildcard"].(*gpb.GetRequest)
+	respFullNode := gnmiMessages["../test/proto/resp-full-node"].(*gpb.GetResponse)
+	respInterfacesWildcard := gnmiMessages["../test/proto/resp-interfaces-wildcard"].(*gpb.GetResponse)
 
 	transport.client.(*mocks.GNMIClient).
 		On("Get", mockContext, reqFullNode).
@@ -562,7 +508,7 @@ func TestGnmi_getWithRequest(t *testing.T) {
 
 func TestNewGnmiTransport(t *testing.T) {
 	type args struct {
-		config *gnmi.Config
+		opts *GnmiTransportOptions
 	}
 	tests := []struct {
 		name    string
@@ -572,38 +518,42 @@ func TestNewGnmiTransport(t *testing.T) {
 	}{
 		{
 			name: "default",
-			args: args{config: &gnmi.Config{
-				Username: "test",
-				Password: "test",
-				Addr:     "localhost:13371",
-				Encoding: gpb.Encoding_PROTO,
-			}},
-			want: &Gnmi{
-				config: &gnmi.Config{
+			args: args{opts: &GnmiTransportOptions{
+				Config: gnmi.Config{
 					Username: "test",
 					Password: "test",
 					Addr:     "localhost:13371",
 					Encoding: gpb.Encoding_PROTO,
 				},
+			}},
+			want: &Gnmi{
+				Options: &GnmiTransportOptions{
+					Config: gnmi.Config{
+						Username: "test",
+						Password: "test",
+						Addr:     "localhost:13371",
+						Encoding: gpb.Encoding_PROTO,
+					},
+				},
 				client: nil,
 			},
 			wantErr: false,
 		},
 		{
 			name:    "unsupported compression",
-			args:    args{config: &gnmi.Config{Compression: "brotli"}},
+			args:    args{opts: &GnmiTransportOptions{Config: gnmi.Config{Compression: "brotli"}}},
 			want:    nil,
 			wantErr: true,
 		},
 		{
 			name:    "certificate error no key file",
-			args:    args{config: &gnmi.Config{TLS: true, CertFile: "invalid", KeyFile: ""}},
+			args:    args{opts: &GnmiTransportOptions{Config: gnmi.Config{TLS: true, CertFile: "invalid", KeyFile: ""}}},
 			want:    nil,
 			wantErr: true,
 		},
 		{
 			name:    "certificate error no ca file",
-			args:    args{config: &gnmi.Config{TLS: true, CAFile: "invalid"}},
+			args:    args{opts: &GnmiTransportOptions{Config: gnmi.Config{TLS: true, CAFile: "invalid"}}},
 			want:    nil,
 			wantErr: true,
 		},
@@ -613,7 +563,7 @@ func TestNewGnmiTransport(t *testing.T) {
 			if tt.name == "default" {
 				startGnmiTarget <- gnmiConfig.Addr
 			}
-			got, err := NewGnmiTransport(tt.args.config)
+			got, err := NewGnmiTransport(tt.args.opts)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("NewGnmiTransport() error = %v, wantErr %v", err, tt.wantErr)
 				return
@@ -640,7 +590,7 @@ func TestGnmi_set(t *testing.T) {
 		Return(mockContext)
 
 	transport.client.(*mocks.GNMIClient).
-		On("Set", mockContext, mock.Anything,mock.Anything).
+		On("Set", mockContext, mock.Anything, mock.Anything).
 		Return(mockResponse, nil)
 
 	type fields struct {
@@ -666,9 +616,9 @@ func TestGnmi_set(t *testing.T) {
 				ctx: context.Background(),
 				setOps: []*gnmi.Operation{
 					{
-						Type:   "update",
-						Path:   []string{"interfaces", "interface", "name"},
-						Val:    "test0",
+						Type: "update",
+						Path: []string{"interfaces", "interface", "name"},
+						Val:  "test0",
 					},
 				},
 				exts: nil,
@@ -716,7 +666,6 @@ func TestGnmi_subscribe(t *testing.T) {
 				SetNode:   tt.fields.SetNode,
 				Unmarshal: tt.fields.Unmarshal,
 				RespChan:  tt.fields.RespChan,
-				config:    tt.fields.config,
 				client:    tt.fields.client,
 			}
 			if err := g.subscribe(tt.args.ctx); (err != nil) != tt.wantErr {
diff --git a/nucleus/integration_test.go b/nucleus/integration_test.go
index b8633c1c064025241fb48a388f431f2736173ac5..26e543bb1bb7b8e61d61c3b5b6179b7b28420128 100644
--- a/nucleus/integration_test.go
+++ b/nucleus/integration_test.go
@@ -6,12 +6,13 @@ import (
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
 	"os"
 	"reflect"
+	"sort"
 	"testing"
 	"time"
 )
 
 var address = "141.100.70.171:6030"
-var cfg *gnmi.Config
+var opt *GnmiTransportOptions
 
 func testSetupIntegration() {
 	a := os.Getenv("GOSDN_TEST_ENDPOINT")
@@ -19,11 +20,13 @@ func testSetupIntegration() {
 		address = a
 	}
 
-	cfg = &gnmi.Config{
-		Addr:     address,
-		Username: "admin",
-		Password: "arista",
-		Encoding: gpb.Encoding_JSON_IETF,
+	opt = &GnmiTransportOptions{
+		Config: gnmi.Config{
+			Addr:     address,
+			Username: "admin",
+			Password: "arista",
+			Encoding: gpb.Encoding_JSON_IETF,
+		},
 	}
 }
 
@@ -32,7 +35,7 @@ func TestGnmi_SetIntegration(t *testing.T) {
 		t.Skip("skipping integration test")
 	}
 	type fields struct {
-		config *gnmi.Config
+		opt *GnmiTransportOptions
 	}
 	type args struct {
 		ctx    context.Context
@@ -47,22 +50,24 @@ func TestGnmi_SetIntegration(t *testing.T) {
 	}{
 		{
 			name: "destination unreachable",
-			fields: fields{config: &gnmi.Config{
-				Addr: "203.0.113.10:6030",
+			fields: fields{opt: &GnmiTransportOptions{
+				Config: gnmi.Config{
+					Addr: "203.0.113.10:6030",
+				},
 			},
 			},
-			args:    args{
-				ctx: context.Background(),
+			args: args{
+				ctx:    context.Background(),
 				params: []interface{}{&gnmi.Operation{}},
 			},
 			want:    nil,
 			wantErr: true,
 		},
 		{
-			name:    "valid update",
-			fields:  fields{config: cfg},
-			args:    args{
-				ctx:    context.Background(),
+			name:   "valid update",
+			fields: fields{opt: opt},
+			args: args{
+				ctx: context.Background(),
 				params: []interface{}{
 					&gnmi.Operation{
 						Type:   "update",
@@ -77,22 +82,28 @@ func TestGnmi_SetIntegration(t *testing.T) {
 					},
 				},
 			},
-			want:    &gpb.SetResponse{},
+			want:    gnmiMessages["../test/proto/resp-set-system-config-hostname"],
 			wantErr: false,
 		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			g, err := NewGnmiTransport(cfg)
+			g, err := NewGnmiTransport(tt.fields.opt)
 			if err != nil {
-				t.Error(err)
+				t.Errorf("NewGnmiTransport() error = %v, wantErr %v", err, tt.wantErr)
+				return
 			}
 			got, err := g.Set(tt.args.ctx, tt.args.params...)
+			if tt.want != nil {
+				tt.want.(*gpb.SetResponse).Timestamp = got.(*gpb.SetResponse).Timestamp
+			}
 			if (err != nil) != tt.wantErr {
 				t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr)
 				return
 			}
-			if !reflect.DeepEqual(got, tt.want) {
+			if err != nil && tt.wantErr {
+				return
+			} else if !reflect.DeepEqual(got, tt.want) {
 				t.Errorf("Set() got = %v, want %v", got, tt.want)
 			}
 		})
@@ -103,7 +114,7 @@ func TestGnmi_GetIntegration(t *testing.T) {
 		t.Skip("skipping integration test")
 	}
 	t.Run("Test GNMI Get", func(t *testing.T) {
-		transport, err := NewGnmiTransport(cfg)
+		transport, err := NewGnmiTransport(opt)
 		if err != nil {
 			t.Error(err)
 		}
@@ -127,7 +138,7 @@ func TestGnmi_SubscribeIntegration(t *testing.T) {
 	}
 
 	t.Run("Test GNMI Subscribe", func(t *testing.T) {
-		transport, err := NewGnmiTransport(cfg)
+		transport, err := NewGnmiTransport(opt)
 		if err != nil {
 			t.Error(err)
 		}
@@ -164,7 +175,7 @@ func TestGnmi_CapabilitiesIntegration(t *testing.T) {
 		t.Skip("skipping integration test")
 	}
 	type fields struct {
-		config *gnmi.Config
+		opt *GnmiTransportOptions
 	}
 	type args struct {
 		ctx context.Context
@@ -178,29 +189,31 @@ func TestGnmi_CapabilitiesIntegration(t *testing.T) {
 	}{
 		{
 			name:    "supported models",
-			fields:  fields{config: cfg},
+			fields:  fields{opt: opt},
 			args:    args{ctx: context.Background()},
-			want:    gnmiMessages["../test/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedModels,
+			want:    gnmiMessages["../test/proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedModels,
 			wantErr: false,
 		},
 		{
 			name:    "supported encodings",
-			fields:  fields{config: cfg},
+			fields:  fields{opt: opt},
 			args:    args{ctx: context.Background()},
-			want:    gnmiMessages["../test/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedEncodings,
+			want:    gnmiMessages["../test/proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).SupportedEncodings,
 			wantErr: false,
 		},
 		{
 			name:    "gnmi version",
-			fields:  fields{config: cfg},
+			fields:  fields{opt: opt},
 			args:    args{ctx: context.Background()},
-			want:    gnmiMessages["../test/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).GNMIVersion,
+			want:    gnmiMessages["../test/proto/cap-resp-arista-ceos"].(*gpb.CapabilityResponse).GNMIVersion,
 			wantErr: false,
 		},
 		{
 			name: "destination unreachable",
-			fields: fields{config: &gnmi.Config{
-				Addr: "203.0.113.10:6030",
+			fields: fields{opt: &GnmiTransportOptions{
+				Config: gnmi.Config{
+					Addr: "203.0.113.10:6030",
+				},
 			},
 			},
 			args:    args{ctx: context.Background()},
@@ -210,7 +223,7 @@ func TestGnmi_CapabilitiesIntegration(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			g, err := NewGnmiTransport(tt.fields.config)
+			g, err := NewGnmiTransport(tt.fields.opt)
 			if err != nil {
 				t.Error(err)
 				return
@@ -226,6 +239,12 @@ func TestGnmi_CapabilitiesIntegration(t *testing.T) {
 				got = resp.(*gpb.CapabilityResponse).SupportedEncodings
 			case "supported models":
 				got = resp.(*gpb.CapabilityResponse).SupportedModels
+				sort.Slice(got.([]*gpb.ModelData), func(i, j int) bool {
+					return got.([]*gpb.ModelData)[i].Name < got.([]*gpb.ModelData)[j].Name
+				})
+				sort.Slice(tt.want.([]*gpb.ModelData), func(i, j int) bool {
+					return tt.want.([]*gpb.ModelData)[i].Name < tt.want.([]*gpb.ModelData)[j].Name
+				})
 			case "gnmi version":
 				got = resp.(*gpb.CapabilityResponse).GNMIVersion
 			default:
diff --git a/nucleus/nucleus-core.go b/nucleus/nucleus-core.go
index cb21c84458485f492800bdd382128122e94a50dd..99dcb95046e730d787ee3f7308279aa113aa0217 100644
--- a/nucleus/nucleus-core.go
+++ b/nucleus/nucleus-core.go
@@ -7,17 +7,16 @@ import (
 )
 
 //StartAndRun is used to start the core of the controller and any auxiliary services.
-func StartAndRun(IsRunningChannel chan bool) {
+func StartAndRun(IsRunningChannel chan bool) error {
 	log.Info("This is the network superintendent...")
 	log.Info("Starting my ducks")
 
 	// Initialize the Core
 	core := Core{}
 	if err := core.Initialize(IsRunningChannel); err != nil {
-		log.Fatal(err)
+		return err
 	}
 	// Start the GRCP CLI
-	go getCLIGoing(&core)
 	go core.Shutdown()
 
 	log.Info("and ready for take off")
diff --git a/nucleus/principalNetworkDomain_test.go b/nucleus/principalNetworkDomain_test.go
index 3f8e7f00212ef62769f2c6ac386cc12574fb6b24..cb5f3f5f78ec6e29ecbbfe9b186ebbf413ed91f0 100644
--- a/nucleus/principalNetworkDomain_test.go
+++ b/nucleus/principalNetworkDomain_test.go
@@ -36,14 +36,9 @@ func testSetupPnd() {
 
 func mockDevice() Device {
 	return Device{
-		GoStruct: nil,
-		SBI:      &OpenConfig{},
-		Config: DeviceConfig{
-			Uuid:     mdid,
-			Address:  "mock://localhost",
-			Username: "mock",
-			Password: "mock",
-		},
+		Uuid:      mdid,
+		GoStruct:  nil,
+		SBI:       &OpenConfig{},
 		Transport: &mocks.Transport{},
 	}
 }
@@ -124,7 +119,7 @@ func Test_destroy(t *testing.T) {
 
 func Test_pndImplementation_AddDevice(t *testing.T) {
 	type args struct {
-		device *Device
+		device interface{}
 	}
 	tests := []struct {
 		name    string
@@ -133,27 +128,51 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 	}{
 		{
 			name: "default",
-			args: args{device: &Device{
-				Config: DeviceConfig{
+			args: args{
+				device: &Device{
 					Uuid: did,
 				},
-			}},
+			},
 			wantErr: false,
 		},
+		{
+			name: "already exists",
+			args: args{
+				device: &Device{
+					Uuid: did,
+				},
+			},
+			wantErr: true,
+		},
+		{
+			name: "fails wrong type",
+			args: args{device: &pndImplementation{
+				id: did,
+			}},
+			wantErr: true,
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
-			if err := pnd.AddDevice(tt.args.device); (err != nil) != tt.wantErr {
-				t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
+			if tt.name == "already exists" {
+				pnd.devices.store[did] = &Device{Uuid: did}
 			}
-			_, ok := pnd.devices.store[did]
-			if !ok {
-				t.Errorf("AddDevice() Device %v not in device store %v",
-					tt.args.device, pnd.devices)
+			err := pnd.AddDevice(tt.args.device)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("AddDevice() error = %v, wantErr %v", err, tt.wantErr)
 			}
-			if err := pnd.devices.delete(did); err != nil {
-				t.Error(err)
+			if tt.name != "fails wrong type" {
+				if err == nil {
+					_, ok := pnd.devices.store[did]
+					if !ok {
+						t.Errorf("AddDevice() Device %v not in device store %v",
+							tt.args.device, pnd.devices)
+					}
+					if err := pnd.devices.delete(did); err != nil {
+						t.Error(err)
+					}
+				}
 			}
 		})
 	}
@@ -161,7 +180,7 @@ func Test_pndImplementation_AddDevice(t *testing.T) {
 
 func Test_pndImplementation_AddSbi(t *testing.T) {
 	type args struct {
-		sbi SouthboundInterface
+		sbi interface{}
 	}
 	tests := []struct {
 		name    string
@@ -177,20 +196,46 @@ func Test_pndImplementation_AddSbi(t *testing.T) {
 			},
 			wantErr: false,
 		},
+		{
+			name: "already exists",
+			args: args{
+				sbi: &OpenConfig{
+					id: defaultSbiId,
+				},
+			},
+			wantErr: true,
+		},
+		{
+			name: "fails wrong type",
+			args: args{
+				sbi: &pndImplementation{
+					id: defaultSbiId,
+				},
+			},
+			wantErr: true,
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
-			if err := pnd.AddSbi(tt.args.sbi); (err != nil) != tt.wantErr {
-				t.Errorf("AddSbi() error = %v, wantErr %v", err, tt.wantErr)
+			if tt.name == "already exists" {
+				pnd.sbic.store[defaultSbiId] = tt.args.sbi.(*OpenConfig)
 			}
-			_, ok := pnd.sbic.store[defaultSbiId]
-			if !ok {
-				t.Errorf("AddSbi() SBI %v not in device store %v",
-					tt.args.sbi, pnd.GetSBIs())
+			err := pnd.AddSbi(tt.args.sbi)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("AddSbi() error = %v, wantErr %v", err, tt.wantErr)
 			}
-			if err := pnd.sbic.delete(defaultSbiId); err != nil {
-				t.Error(err)
+			if tt.name != "fails wrong type" {
+				if err == nil {
+					_, ok := pnd.sbic.store[defaultSbiId]
+					if !ok {
+						t.Errorf("AddSbi() SBI %v not in device store %v",
+							tt.args.sbi, pnd.GetSBIs())
+					}
+					if err := pnd.sbic.delete(defaultSbiId); err != nil {
+						t.Error(err)
+					}
+				}
 			}
 		})
 	}
@@ -208,15 +253,15 @@ func Test_pndImplementation_ContainsDevice(t *testing.T) {
 	}{
 		{name: "default", args: args{
 			uuid:   did,
-			device: &Device{Config: DeviceConfig{Uuid: did}},
+			device: &Device{Uuid: did},
 		}, want: true},
 		{name: "fails", args: args{
 			uuid:   uuid.New(),
-			device: &Device{Config: DeviceConfig{Uuid: did}},
+			device: &Device{Uuid: did},
 		}, want: false},
 		{name: "fails empty", args: args{
 			uuid:   uuid.New(),
-			device: &Device{Config: DeviceConfig{Uuid: did}},
+			device: &Device{Uuid: did},
 		}, want: false},
 	}
 	for _, tt := range tests {
@@ -327,20 +372,20 @@ func Test_pndImplementation_MarshalDevice(t *testing.T) {
 		want    string
 		wantErr bool
 	}{
-		{name: "default", args: args{did}, want: "{\n\t\"Acl\": null,\n\t\"Bgp\": null,\n\t\"Components\": null,\n\t\"Interfaces\": null,\n\t\"LocalRoutes\": null,\n\t\"Messages\": null,\n\t\"NetworkInstances\": null,\n\t\"RoutingPolicy\": null,\n\t\"System\": null\n}", wantErr: false},
+		{
+			name:    "default",
+			args:    args{did},
+			want:    "{\n\t\"Acl\": null,\n\t\"Bgp\": null,\n\t\"Components\": null,\n\t\"Interfaces\": null,\n\t\"LocalRoutes\": null,\n\t\"Messages\": null,\n\t\"NetworkInstances\": null,\n\t\"RoutingPolicy\": null,\n\t\"System\": null\n}",
+			wantErr: false,
+		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
 			d := &Device{
-				GoStruct: &openconfig.Device{},
-				SBI:      nil,
-				Config: DeviceConfig{
-					Uuid:     tt.args.uuid,
-					Address:  "localhost",
-					Username: "test",
-					Password: "test",
-				},
+				Uuid:      tt.args.uuid,
+				GoStruct:  &openconfig.Device{},
+				SBI:       nil,
 				Transport: nil,
 			}
 			if err := pnd.addDevice(d); err != nil {
@@ -378,7 +423,7 @@ func Test_pndImplementation_RemoveDevice(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			pnd := newPnd()
 			if tt.name != "fails empty" {
-				d := &Device{Config: DeviceConfig{Uuid: did}}
+				d := &Device{Uuid: did}
 				if err := pnd.addDevice(d); err != nil {
 					t.Error(err)
 				}
diff --git a/nucleus/southbound_test.go b/nucleus/southbound_test.go
index 951f7979c30723e9b2ff281f30c69588529eea93..c4ebf28f299bb84d8f4ae6cfd14f1efaec7327d2 100644
--- a/nucleus/southbound_test.go
+++ b/nucleus/southbound_test.go
@@ -1,11 +1,10 @@
 package nucleus
 
 import (
-	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util"
+	"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
 	"code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
 	"github.com/google/uuid"
 	gpb "github.com/openconfig/gnmi/proto/gnmi"
-	"github.com/openconfig/ygot/ygot"
 	"github.com/openconfig/ygot/ytypes"
 	log "github.com/sirupsen/logrus"
 	"reflect"
@@ -137,14 +136,14 @@ func Test_unmarshal(t *testing.T) {
 			name: "fail",
 			args: args{
 				goStruct: &openconfig.Device{},
-				path:     "../test/resp-interfaces-interface-arista-ceos",
+				path:     "../test/proto/resp-interfaces-interface-arista-ceos",
 			},
 			wantErr: true,
 		},
 		{
 			name: "root w/opts",
 			args: args{
-				path:     "../test/resp-full-node-arista-ceos",
+				path:     "../test/proto/resp-full-node-arista-ceos",
 				goStruct: &openconfig.Device{},
 				opt:      []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}},
 			},
@@ -153,7 +152,7 @@ func Test_unmarshal(t *testing.T) {
 		{
 			name: "root w/o opts",
 			args: args{
-				path:     "../test/resp-full-node-arista-ceos",
+				path:     "../test/proto/resp-full-node-arista-ceos",
 				goStruct: &openconfig.Device{},
 				opt:      nil,
 			},
@@ -162,7 +161,7 @@ func Test_unmarshal(t *testing.T) {
 		{
 			name: "interfaces w/opts",
 			args: args{
-				path:     "../test/resp-interfaces-arista-ceos",
+				path:     "../test/proto/resp-interfaces-arista-ceos",
 				goStruct: &openconfig.Device{},
 				opt:      []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}},
 			},
@@ -171,7 +170,7 @@ func Test_unmarshal(t *testing.T) {
 		{
 			name: "interfaces w/o opts",
 			args: args{
-				path:     "../test/resp-interfaces-arista-ceos",
+				path:     "../test/proto/resp-interfaces-arista-ceos",
 				goStruct: &openconfig.Device{},
 				opt:      nil,
 			},
@@ -181,7 +180,7 @@ func Test_unmarshal(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			resp := &gpb.GetResponse{}
-			err := util.Read(tt.args.path, resp)
+			err := proto.Read(tt.args.path, resp)
 			if err != nil {
 				t.Error(err)
 			}
@@ -196,34 +195,3 @@ func Test_unmarshal(t *testing.T) {
 		})
 	}
 }
-
-func Test_iter(t *testing.T) {
-	type args struct {
-		a      ygot.GoStruct
-		fields []string
-	}
-	tests := []struct {
-		name      string
-		args      args
-		wantB     ygot.GoStruct
-		wantField string
-		wantErr   bool
-	}{
-		// TODO: Add test cases.
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			gotB, gotField, err := iter(tt.args.a, tt.args.fields)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("iter() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(gotB, tt.wantB) {
-				t.Errorf("iter() gotB = %v, want %v", gotB, tt.wantB)
-			}
-			if gotField != tt.wantField {
-				t.Errorf("iter() gotField = %v, want %v", gotField, tt.wantField)
-			}
-		})
-	}
-}
diff --git a/nucleus/store_test.go b/nucleus/store_test.go
index 012b47a4f1d32634a070ad6d2d695c60eb44d95f..defdaa58fa83bf01955cc18d361ce5c896162521 100644
--- a/nucleus/store_test.go
+++ b/nucleus/store_test.go
@@ -284,9 +284,7 @@ func Test_sbiStore_get(t *testing.T) {
 			fields: fields{
 				store: store{
 					did: &Device{
-						Config: DeviceConfig{
-							Uuid: did,
-						},
+						Uuid: did,
 					},
 				},
 			},
@@ -359,9 +357,7 @@ func Test_pndStore_get(t *testing.T) {
 			fields: fields{
 				store: store{
 					did: &Device{
-						Config: DeviceConfig{
-							Uuid: did,
-						},
+						Uuid: did,
 					},
 				},
 			},
@@ -404,12 +400,10 @@ func Test_deviceStore_get(t *testing.T) {
 			name: "exists",
 			fields: fields{
 				store: store{
-					defaultPndId: &Device{Config: DeviceConfig{Uuid: did}}}},
+					defaultPndId: &Device{Uuid: did}}},
 			args: args{id: defaultPndId},
 			want: &Device{
-				Config: DeviceConfig{
-					Uuid: did,
-				},
+				Uuid: did,
 			},
 			wantErr: false,
 		},
@@ -417,7 +411,7 @@ func Test_deviceStore_get(t *testing.T) {
 			name: "fails",
 			fields: fields{
 				store: store{
-					defaultPndId: &Device{Config: DeviceConfig{Uuid: did}}}},
+					defaultPndId: &Device{Uuid: did}}},
 			args:    args{id: iid},
 			wantErr: true,
 		},
diff --git a/nucleus/transport.go b/nucleus/transport.go
index 5724cf86e8dda13305bdc5780d8f13221df36973..cfab425227534cea87a8d1a139fec97c5e499e42 100644
--- a/nucleus/transport.go
+++ b/nucleus/transport.go
@@ -15,6 +15,7 @@ type Transport interface {
 	Set(ctx context.Context, params ...interface{}) (interface{}, error)
 	Subscribe(ctx context.Context, params ...string) error
 	Type() string
+	GetOptions() interface{}
 	ProcessResponse(resp interface{}, root interface{}, models *ytypes.Schema) error
 }
 
@@ -29,3 +30,10 @@ func (yc YANGConsumer) Consume(reader io.Reader, _ interface{}) error {
 	_, err := yc.Data.ReadFrom(reader)
 	return err
 }
+
+type TransportOptions interface {
+	GetAddress() string
+	GetUsername() string
+	GetPassword() string
+	IsTransportOption()
+}
diff --git a/nucleus/util/path_traversal.go b/nucleus/util/path/path_traversal.go
similarity index 50%
rename from nucleus/util/path_traversal.go
rename to nucleus/util/path/path_traversal.go
index cbcdd9bbc4d4768715e36cb7a5dd5f48a40934e3..c8951b0731e5579e973964f7e29a61bd1680989b 100644
--- a/nucleus/util/path_traversal.go
+++ b/nucleus/util/path/path_traversal.go
@@ -1,4 +1,4 @@
-package util
+package path
 
 import (
 	"fmt"
@@ -10,37 +10,48 @@ import (
 
 const DELIM = "/"
 
-type PathElement struct {
-	Children []*PathElement
+// PathElement represents a node in a path containing its name and possible child nodes
+type Element struct {
+	Children []*Element
 	Name     string
 }
 
-func (p *PathElement) Print() {
-	printPE(0, p)
+// Print prints the path element to stdout. It calls printElement recursively
+func (p *Element) Print() {
+	printElement(0, p)
 }
 
-func printPE(indent int, pe *PathElement) {
+func printElement(indent int, pe *Element) {
 	for i := 0; i < indent; i++ {
 		fmt.Print("    ")
 	}
 	fmt.Println(pe.Name)
 	if len(pe.Children) > 0 {
 		for _, p := range pe.Children {
-			printPE(indent+1, p)
+			printElement(indent+1, p)
 		}
 	}
 }
 
-func NewPaths() Paths {
-	return make(map[string]*PathElement)
+// ParseSchema takes a YANG schema and parses it into paths
+func ParseSchema(schema *ytypes.Schema, root string) (map[string]*Element, error) {
+	paths := make(map[string]*Element)
+	tree := schema.SchemaTree
+	for k, v := range tree {
+		if v.Parent != nil {
+			if v.Parent.Name == root {
+				path := processEntry(v)
+				paths[k] = path
+			}
+		}
+	}
+	return paths, nil
 }
 
-type Paths map[string]*PathElement
-
-func processEntry(e *yang.Entry) *PathElement {
+func processEntry(e *yang.Entry) *Element {
 	if e.Dir != nil {
-		elem := &PathElement{
-			Children: make([]*PathElement, len(e.Dir)),
+		elem := &Element{
+			Children: make([]*Element, len(e.Dir)),
 			Name:     e.Name,
 		}
 		i := 0
@@ -50,47 +61,36 @@ func processEntry(e *yang.Entry) *PathElement {
 		}
 		return elem
 	}
-	leaf := &PathElement{
+	leaf := &Element{
 		Name: e.Name,
 	}
 	return leaf
 }
 
-func (p Paths) ParseSchema(schema *ytypes.Schema, root string) error {
-	tree := schema.SchemaTree
-	for k, v := range tree {
-		if v.Parent != nil {
-			if v.Parent.Name == root {
-				path := processEntry(v)
-				p[k] = path
-			}
-		}
-	}
-	return nil
-}
-
-func (p Paths) StringBuilder() []string {
-	paths := make([]string, 0)
+// Strings constructs a slice containg all possible root to leaf paths.
+// Calls stringBuilder internally
+func Strings(paths map[string]*Element) []string {
+	p := make([]string, 0)
 	ch := make(chan string)
 	stop := make(chan bool)
 	val := make(chan []string)
 	go appendix(ch, stop, val)
-	for _, v := range p {
+	for _, v := range paths {
 		var b strings.Builder
 		stringBuilder(ch, &b, v)
 	}
 	stop <- true
-	paths = <-val
-	return paths
+	p = <-val
+	return p
 }
 
-func appendix(c chan string, stop chan bool, p chan []string) {
-	paths := make([]string, 0)
+func appendix(c chan string, stop chan bool, pathChan chan []string) {
+	p := make([]string, 0)
 	var sig bool
 	for {
 		select {
 		case path := <-c:
-			paths = append(paths, path)
+			p = append(p, path)
 			log.Debug(path)
 		case sig = <-stop:
 			log.Debugf("Signal received: %v", sig)
@@ -100,10 +100,10 @@ func appendix(c chan string, stop chan bool, p chan []string) {
 			break
 		}
 	}
-	p <- paths
+	pathChan <- p
 }
 
-func stringBuilder(ch chan string, b *strings.Builder, v *PathElement) {
+func stringBuilder(ch chan string, b *strings.Builder, v *Element) {
 	if b.Len() == 0 {
 		b.WriteString(DELIM)
 	}
@@ -111,9 +111,9 @@ func stringBuilder(ch chan string, b *strings.Builder, v *PathElement) {
 	if v.Children != nil {
 		b.WriteString(DELIM)
 		for _, c := range v.Children {
-			var b_cpy strings.Builder
-			b_cpy.WriteString(b.String())
-			stringBuilder(ch, &b_cpy, c)
+			var bCpy strings.Builder
+			bCpy.WriteString(b.String())
+			stringBuilder(ch, &bCpy, c)
 		}
 	} else {
 		log.Debug("leaf")
diff --git a/nucleus/util/path/path_traversal_test.go b/nucleus/util/path/path_traversal_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..2193eb4e494a1204d9c5c964efcb8498314eaf2f
--- /dev/null
+++ b/nucleus/util/path/path_traversal_test.go
@@ -0,0 +1,238 @@
+package path
+
+import (
+	model "code.fbi.h-da.de/cocsn/gosdn/test/yang"
+	"github.com/openconfig/goyang/pkg/yang"
+	"github.com/openconfig/ygot/ytypes"
+	log "github.com/sirupsen/logrus"
+	"os"
+	"reflect"
+	"testing"
+)
+
+var schema *ytypes.Schema
+
+func TestMain(m *testing.M) {
+	testSetupPath()
+	os.Exit(m.Run())
+}
+
+func testSetupPath() {
+	var err error
+	schema, err = model.Schema()
+	if err != nil {
+		log.Fatal(err)
+	}
+}
+
+func TestParseSchema(t *testing.T) {
+
+	type args struct {
+		schema *ytypes.Schema
+		root   string
+	}
+	tests := []struct {
+		name    string
+		args    args
+		want    map[string]*Element
+		wantErr bool
+	}{
+		{
+			name: "default",
+			args: args{
+				schema: schema,
+				root:   "device",
+			},
+			want: map[string]*Element{
+				"Test_Container1": {
+					Children: []*Element{
+						{
+							Children: []*Element{
+								{
+									Children: nil,
+									Name:     "leaf-list1",
+								},
+								{
+									Children: nil,
+									Name:     "leaf1",
+								},
+								{
+									Children: nil,
+									Name:     "leaf2",
+								},
+							},
+							Name: "list1",
+						},
+					},
+					Name: "container1",
+				},
+				"Test_Container2": {
+					Children: []*Element{
+						{
+							Children: []*Element{
+								{
+									Children: nil,
+									Name:     "leaf-list1",
+								},
+								{
+									Children: nil,
+									Name:     "leaf1",
+								},
+								{
+									Children: nil,
+									Name:     "leaf2",
+								},
+							},
+							Name: "list1",
+						},
+					},
+					Name: "container2",
+				},
+			},
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got, err := ParseSchema(tt.args.schema, tt.args.root)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("ParseSchema() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("ParseSchema() got = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestStrings(t *testing.T) {
+	type args struct {
+		paths map[string]*Element
+	}
+	tests := []struct {
+		name string
+		args args
+		want []string
+	}{
+		{
+			name: "default",
+			args: args{
+				paths: map[string]*Element{
+					"Test_Container1": {
+						Children: []*Element{
+							{
+								Children: []*Element{
+									{
+										Children: nil,
+										Name:     "leaf-list1",
+									},
+									{
+										Children: nil,
+										Name:     "leaf1",
+									},
+									{
+										Children: nil,
+										Name:     "leaf2",
+									},
+								},
+								Name: "list1",
+							},
+						},
+						Name: "container1",
+					},
+					"Test_Container2": {
+						Children: []*Element{
+							{
+								Children: []*Element{
+									{
+										Children: nil,
+										Name:     "leaf-list1",
+									},
+									{
+										Children: nil,
+										Name:     "leaf1",
+									},
+									{
+										Children: nil,
+										Name:     "leaf2",
+									},
+								},
+								Name: "list1",
+							},
+						},
+						Name: "container2",
+					},
+				},
+			},
+			want: []string{
+				"/container1/list1/leaf-list1",
+				"/container1/list1/leaf1",
+				"/container1/list1/leaf2",
+				"/container2/list1/leaf-list1",
+				"/container2/list1/leaf1",
+				"/container2/list1/leaf2",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := Strings(tt.args.paths); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Strings() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func Test_processEntry(t *testing.T) {
+	type args struct {
+		e *yang.Entry
+	}
+	tests := []struct {
+		name string
+		args args
+		want *Element
+	}{
+		{
+			name: "leaf",
+			args: args{e: schema.SchemaTree["Test_Container1_List1"].Dir["leaf1"]},
+			want: &Element{
+				Children: nil,
+				Name:     "leaf1",
+			},
+		},
+		{
+			name: "intermediate",
+			args: args{schema.SchemaTree["Test_Container1"]},
+			want: &Element{
+				Children: []*Element{
+					{
+						Children: []*Element{
+							{
+								Children: nil,
+								Name:     "leaf-list1",
+							},
+							{
+								Children: nil,
+								Name:     "leaf1",
+							},
+							{
+								Children: nil,
+								Name:     "leaf2",
+							},
+						},
+						Name: "list1",
+					},
+				},
+				Name: "container1",
+			},
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if got := processEntry(tt.args.e); !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("processEntry() = %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/nucleus/util/path_traversal_test.go b/nucleus/util/path_traversal_test.go
deleted file mode 100644
index c7d868219f5edd141ec2d256a5fc84542fa4471d..0000000000000000000000000000000000000000
--- a/nucleus/util/path_traversal_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package util
diff --git a/nucleus/util/message_tools.go b/nucleus/util/proto/message.go
similarity index 94%
rename from nucleus/util/message_tools.go
rename to nucleus/util/proto/message.go
index 30ba145ad3b4ee76bc5da4c48f0250afcd3f30fe..5057f1f0808f57e408d580f613ef8ab519500503 100644
--- a/nucleus/util/message_tools.go
+++ b/nucleus/util/proto/message.go
@@ -1,8 +1,8 @@
-package util
+package proto
 
 import (
 	"fmt"
-	"github.com/golang/protobuf/proto"
+	"google.golang.org/protobuf/proto"
 	"io/ioutil"
 )
 
@@ -30,7 +30,6 @@ func Read(filename string, message proto.Message) error {
 	if err != nil {
 		return fmt.Errorf("cannot read binary data from file: %w", err)
 	}
-
 	err = proto.Unmarshal(data, message)
 	if err != nil {
 		return fmt.Errorf("cannot unmarshal binary to proto message: %w", err)
diff --git a/nucleus/util/proto/message_test.go b/nucleus/util/proto/message_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..3f756d3aef8ad5c467a2572d793e374bb2802c30
--- /dev/null
+++ b/nucleus/util/proto/message_test.go
@@ -0,0 +1,130 @@
+package proto
+
+import (
+	gpb "github.com/openconfig/gnmi/proto/gnmi"
+	pb "google.golang.org/protobuf/proto"
+	"os"
+	"reflect"
+	"strings"
+	"testing"
+)
+
+func TestMain(m *testing.M) {
+	gnmiPaths = map[string]pb.Message{
+		"../../../test/proto/cap-resp-arista-ceos":                  &gpb.CapabilityResponse{},
+		"../../../test/proto/req-full-node":                         &gpb.GetRequest{},
+		"../../../test/proto/req-full-node-arista-ceos":             &gpb.GetRequest{},
+		"../../../test/proto/req-interfaces-arista-ceos":            &gpb.GetRequest{},
+		"../../../test/proto/req-interfaces-interface-arista-ceos":  &gpb.GetRequest{},
+		"../../../test/proto/req-interfaces-wildcard":               &gpb.GetRequest{},
+		"../../../test/proto/resp-full-node":                        &gpb.GetResponse{},
+		"../../../test/proto/resp-full-node-arista-ceos":            &gpb.GetResponse{},
+		"../../../test/proto/resp-interfaces-arista-ceos":           &gpb.GetResponse{},
+		"../../../test/proto/resp-interfaces-interface-arista-ceos": &gpb.GetResponse{},
+		"../../../test/proto/resp-interfaces-wildcard":              &gpb.GetResponse{},
+		"../../../test/proto/resp-set-system-config-hostname":       &gpb.SetResponse{},
+	}
+	os.Exit(m.Run())
+}
+
+var gnmiPaths map[string]pb.Message
+
+func TestRead(t *testing.T) {
+	type args struct {
+		filename string
+		message  pb.Message
+	}
+	type test struct {
+		name    string
+		args    args
+		want    reflect.Type
+		wantErr bool
+	}
+	var tests []test
+	for k, v := range gnmiPaths {
+		name := strings.Split(k, "/")[5]
+		tests = append(tests, test{
+			name: name,
+			args: args{
+				filename: k,
+				message:  v,
+			},
+			want:    reflect.TypeOf(v),
+			wantErr: false,
+		})
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Read(tt.args.filename, tt.args.message); (err != nil) != tt.wantErr {
+				t.Errorf("Read() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			got := reflect.TypeOf(tt.args.message)
+			if got != tt.want {
+				t.Errorf("Read() got Type %v, want Type %v", got, tt.want)
+			}
+		})
+	}
+}
+
+func TestWrite(t *testing.T) {
+	for k, v := range gnmiPaths {
+		if err := Read(k, v); err != nil {
+			t.Error(err)
+		}
+	}
+	type args struct {
+		message  pb.Message
+		filename string
+	}
+	type test struct {
+		name    string
+		args    args
+		want    pb.Message
+		wantErr bool
+	}
+	var tests []test
+	for k, v := range gnmiPaths {
+		name := strings.Split(k, "/")[5]
+		tests = append(tests, test{
+			name: name,
+			args: args{
+				message:  v,
+				filename: name + "_test",
+			},
+			want:    v,
+			wantErr: false,
+		})
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			if err := Write(tt.args.message, tt.args.filename); (err != nil) != tt.wantErr {
+				t.Errorf("Write() error = %v, wantErr %v", err, tt.wantErr)
+			}
+			var got pb.Message
+			switch tt.want.(type) {
+			case *gpb.GetResponse:
+				got = &gpb.GetResponse{}
+			case *gpb.GetRequest:
+				got = &gpb.GetRequest{}
+			case *gpb.SetResponse:
+				got = &gpb.SetResponse{}
+			case *gpb.SetRequest:
+				got = &gpb.SetRequest{}
+			case *gpb.CapabilityResponse:
+				got = &gpb.CapabilityResponse{}
+			default:
+				t.Error("no test case for message type")
+				return
+			}
+			err := Read(tt.args.filename, got)
+			if err != nil {
+				t.Error(err)
+			}
+			if reflect.DeepEqual(got, tt.want) {
+				t.Errorf("Write() got %v, want %v", got, tt.want)
+			}
+		})
+	}
+}
diff --git a/test/cap-resp-arista-ceos b/test/proto/cap-resp-arista-ceos
similarity index 100%
rename from test/cap-resp-arista-ceos
rename to test/proto/cap-resp-arista-ceos
diff --git a/test/req-full-node b/test/proto/req-full-node
similarity index 100%
rename from test/req-full-node
rename to test/proto/req-full-node
diff --git a/test/req-full-node-arista-ceos b/test/proto/req-full-node-arista-ceos
similarity index 100%
rename from test/req-full-node-arista-ceos
rename to test/proto/req-full-node-arista-ceos
diff --git a/test/req-interfaces-arista-ceos b/test/proto/req-interfaces-arista-ceos
similarity index 100%
rename from test/req-interfaces-arista-ceos
rename to test/proto/req-interfaces-arista-ceos
diff --git a/test/req-interfaces-interface-arista-ceos b/test/proto/req-interfaces-interface-arista-ceos
similarity index 100%
rename from test/req-interfaces-interface-arista-ceos
rename to test/proto/req-interfaces-interface-arista-ceos
diff --git a/test/req-interfaces-wildcard b/test/proto/req-interfaces-wildcard
similarity index 100%
rename from test/req-interfaces-wildcard
rename to test/proto/req-interfaces-wildcard
diff --git a/test/resp-full-node b/test/proto/resp-full-node
similarity index 100%
rename from test/resp-full-node
rename to test/proto/resp-full-node
diff --git a/test/resp-full-node-arista-ceos b/test/proto/resp-full-node-arista-ceos
similarity index 100%
rename from test/resp-full-node-arista-ceos
rename to test/proto/resp-full-node-arista-ceos
diff --git a/test/resp-interfaces-arista-ceos b/test/proto/resp-interfaces-arista-ceos
similarity index 100%
rename from test/resp-interfaces-arista-ceos
rename to test/proto/resp-interfaces-arista-ceos
diff --git a/test/resp-interfaces-interface-arista-ceos b/test/proto/resp-interfaces-interface-arista-ceos
similarity index 100%
rename from test/resp-interfaces-interface-arista-ceos
rename to test/proto/resp-interfaces-interface-arista-ceos
diff --git a/test/resp-interfaces-wildcard b/test/proto/resp-interfaces-wildcard
similarity index 100%
rename from test/resp-interfaces-wildcard
rename to test/proto/resp-interfaces-wildcard
diff --git a/test/proto/resp-set-system-config-hostname b/test/proto/resp-set-system-config-hostname
new file mode 100644
index 0000000000000000000000000000000000000000..c656ee5bb56b47d1e306627823c577d1b51d6988
--- /dev/null
+++ b/test/proto/resp-set-system-config-hostname
@@ -0,0 +1,8 @@
+>:
+system
+config
+hostname
+system
+config
+
+hostname  �����ȶ
\ No newline at end of file
diff --git a/test/yang/test-module.go b/test/yang/test-module.go
new file mode 100644
index 0000000000000000000000000000000000000000..6d962be48d2728bc24285a89b8251d1cd380d600
--- /dev/null
+++ b/test/yang/test-module.go
@@ -0,0 +1,3 @@
+package yang
+
+//go:generate go run $GOPATH/src/github.com/openconfig/ygot/generator/generator.go -output_file ./yang.go -package_name=yang -generate_fakeroot -fakeroot_name=device test.yang
diff --git a/test/yang/test.yang b/test/yang/test.yang
new file mode 100644
index 0000000000000000000000000000000000000000..35254174203402213cb12bf196fdc20c061c2e6d
--- /dev/null
+++ b/test/yang/test.yang
@@ -0,0 +1,66 @@
+module test {
+    yang-version 1.1;
+    namespace "urn:cocsn:params:xml:ns:yang:test";
+    prefix coc;
+
+    organization
+    "Darmstadt University of Applied Sciences";
+
+    description
+    "This YANG module is used to test YANG libs";
+
+    revision "2021-03-22" {
+    description
+        "Initial Revision";
+    }
+
+    container container1 {
+        list list1 {
+            key "leaf1";
+            leaf leaf1 {
+                config false;
+                type string;
+                mandatory "true";
+                description
+                "leaf1";
+            }
+            leaf-list leaf-list1 {
+                config true;
+                type string;
+                description
+                "leaf-list1";
+            }
+            leaf leaf2 {
+                config true;
+                type string;
+                description
+                "leaf2";
+            }
+        }
+    }
+
+    container container2 {
+        list list1 {
+            key "leaf1";
+            leaf leaf1 {
+                config false;
+                type string;
+                mandatory "true";
+                description
+                "leaf1";
+            }
+            leaf-list leaf-list1 {
+                config true;
+                type string;
+                description
+                "leaf-list1";
+            }
+            leaf leaf2 {
+                config true;
+                type string;
+                description
+                "leaf2";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/test/yang/yang.go b/test/yang/yang.go
new file mode 100644
index 0000000000000000000000000000000000000000..7801d549b1d569245936cbdddabf74d7bf215f4c
--- /dev/null
+++ b/test/yang/yang.go
@@ -0,0 +1,332 @@
+/*
+Package yang is a generated package which contains definitions
+of structs which represent a YANG schema. The generated schema can be
+compressed by a series of transformations (compression was false
+in this case).
+
+This package was generated by /Users/mk/go/pkg/mod/github.com/openconfig/ygot@v0.10.0/genutil/names.go
+using the following YANG input files:
+	- test.yang
+Imported modules were sourced from:
+*/
+package yang
+
+import (
+	"encoding/json"
+	"fmt"
+	"reflect"
+
+	"github.com/openconfig/goyang/pkg/yang"
+	"github.com/openconfig/ygot/ygot"
+	"github.com/openconfig/ygot/ytypes"
+)
+
+// Binary is a type that is used for fields that have a YANG type of
+// binary. It is used such that binary fields can be distinguished from
+// leaf-lists of uint8s (which are mapped to []uint8, equivalent to
+// []byte in reflection).
+type Binary []byte
+
+// YANGEmpty is a type that is used for fields that have a YANG type of
+// empty. It is used such that empty fields can be distinguished from boolean fields
+// in the generated code.
+type YANGEmpty bool
+
+var (
+	SchemaTree map[string]*yang.Entry
+)
+
+func init() {
+	var err error
+	if SchemaTree, err = UnzipSchema(); err != nil {
+		panic("schema error: " + err.Error())
+	}
+}
+
+// Schema returns the details of the generated schema.
+func Schema() (*ytypes.Schema, error) {
+	uzp, err := UnzipSchema()
+	if err != nil {
+		return nil, fmt.Errorf("cannot unzip schema, %v", err)
+	}
+
+	return &ytypes.Schema{
+		Root:       &Device{},
+		SchemaTree: uzp,
+		Unmarshal:  Unmarshal,
+	}, nil
+}
+
+// UnzipSchema unzips the zipped schema and returns a map of yang.Entry nodes,
+// keyed by the name of the struct that the yang.Entry describes the schema for.
+func UnzipSchema() (map[string]*yang.Entry, error) {
+	var schemaTree map[string]*yang.Entry
+	var err error
+	if schemaTree, err = ygot.GzipToSchema(ySchema); err != nil {
+		return nil, fmt.Errorf("could not unzip the schema; %v", err)
+	}
+	return schemaTree, nil
+}
+
+// Unmarshal unmarshals data, which must be RFC7951 JSON format, into
+// destStruct, which must be non-nil and the correct GoStruct type. It returns
+// an error if the destStruct is not found in the schema or the data cannot be
+// unmarshaled. The supplied options (opts) are used to control the behaviour
+// of the unmarshal function - for example, determining whether errors are
+// thrown for unknown fields in the input JSON.
+func Unmarshal(data []byte, destStruct ygot.GoStruct, opts ...ytypes.UnmarshalOpt) error {
+	tn := reflect.TypeOf(destStruct).Elem().Name()
+	schema, ok := SchemaTree[tn]
+	if !ok {
+		return fmt.Errorf("could not find schema for type %s", tn)
+	}
+	var jsonTree interface{}
+	if err := json.Unmarshal([]byte(data), &jsonTree); err != nil {
+		return err
+	}
+	return ytypes.Unmarshal(schema, destStruct, jsonTree, opts...)
+}
+
+// Device represents the /device YANG schema element.
+type Device struct {
+	Container1 *Test_Container1 `path:"container1" module:"test"`
+	Container2 *Test_Container2 `path:"container2" module:"test"`
+}
+
+// IsYANGGoStruct ensures that Device implements the yang.GoStruct
+// interface. This allows functions that need to handle this struct to
+// identify it as being generated by ygen.
+func (*Device) IsYANGGoStruct() {}
+
+// Validate validates s against the YANG schema corresponding to its type.
+func (t *Device) Validate(opts ...ygot.ValidationOption) error {
+	if err := ytypes.Validate(SchemaTree["Device"], t, opts...); err != nil {
+		return err
+	}
+	return nil
+}
+
+// ΛEnumTypeMap returns a map, keyed by YANG schema path, of the enumerated types
+// that are included in the generated code.
+func (t *Device) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTypes }
+
+// Test_Container1 represents the /test/container1 YANG schema element.
+type Test_Container1 struct {
+	List1 map[string]*Test_Container1_List1 `path:"list1" module:"test"`
+}
+
+// IsYANGGoStruct ensures that Test_Container1 implements the yang.GoStruct
+// interface. This allows functions that need to handle this struct to
+// identify it as being generated by ygen.
+func (*Test_Container1) IsYANGGoStruct() {}
+
+// NewList1 creates a new entry in the List1 list of the
+// Test_Container1 struct. The keys of the list are populated from the input
+// arguments.
+func (t *Test_Container1) NewList1(Leaf1 string) (*Test_Container1_List1, error) {
+
+	// Initialise the list within the receiver struct if it has not already been
+	// created.
+	if t.List1 == nil {
+		t.List1 = make(map[string]*Test_Container1_List1)
+	}
+
+	key := Leaf1
+
+	// Ensure that this key has not already been used in the
+	// list. Keyed YANG lists do not allow duplicate keys to
+	// be created.
+	if _, ok := t.List1[key]; ok {
+		return nil, fmt.Errorf("duplicate key %v for list List1", key)
+	}
+
+	t.List1[key] = &Test_Container1_List1{
+		Leaf1: &Leaf1,
+	}
+
+	return t.List1[key], nil
+}
+
+// Validate validates s against the YANG schema corresponding to its type.
+func (t *Test_Container1) Validate(opts ...ygot.ValidationOption) error {
+	if err := ytypes.Validate(SchemaTree["Test_Container1"], t, opts...); err != nil {
+		return err
+	}
+	return nil
+}
+
+// ΛEnumTypeMap returns a map, keyed by YANG schema path, of the enumerated types
+// that are included in the generated code.
+func (t *Test_Container1) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTypes }
+
+// Test_Container1_List1 represents the /test/container1/list1 YANG schema element.
+type Test_Container1_List1 struct {
+	LeafList1 []string `path:"leaf-list1" module:"test"`
+	Leaf1     *string  `path:"leaf1" module:"test"`
+	Leaf2     *string  `path:"leaf2" module:"test"`
+}
+
+// IsYANGGoStruct ensures that Test_Container1_List1 implements the yang.GoStruct
+// interface. This allows functions that need to handle this struct to
+// identify it as being generated by ygen.
+func (*Test_Container1_List1) IsYANGGoStruct() {}
+
+// ΛListKeyMap returns the keys of the Test_Container1_List1 struct, which is a YANG list entry.
+func (t *Test_Container1_List1) ΛListKeyMap() (map[string]interface{}, error) {
+	if t.Leaf1 == nil {
+		return nil, fmt.Errorf("nil value for key Leaf1")
+	}
+
+	return map[string]interface{}{
+		"leaf1": *t.Leaf1,
+	}, nil
+}
+
+// Validate validates s against the YANG schema corresponding to its type.
+func (t *Test_Container1_List1) Validate(opts ...ygot.ValidationOption) error {
+	if err := ytypes.Validate(SchemaTree["Test_Container1_List1"], t, opts...); err != nil {
+		return err
+	}
+	return nil
+}
+
+// ΛEnumTypeMap returns a map, keyed by YANG schema path, of the enumerated types
+// that are included in the generated code.
+func (t *Test_Container1_List1) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTypes }
+
+// Test_Container2 represents the /test/container2 YANG schema element.
+type Test_Container2 struct {
+	List1 map[string]*Test_Container2_List1 `path:"list1" module:"test"`
+}
+
+// IsYANGGoStruct ensures that Test_Container2 implements the yang.GoStruct
+// interface. This allows functions that need to handle this struct to
+// identify it as being generated by ygen.
+func (*Test_Container2) IsYANGGoStruct() {}
+
+// NewList1 creates a new entry in the List1 list of the
+// Test_Container2 struct. The keys of the list are populated from the input
+// arguments.
+func (t *Test_Container2) NewList1(Leaf1 string) (*Test_Container2_List1, error) {
+
+	// Initialise the list within the receiver struct if it has not already been
+	// created.
+	if t.List1 == nil {
+		t.List1 = make(map[string]*Test_Container2_List1)
+	}
+
+	key := Leaf1
+
+	// Ensure that this key has not already been used in the
+	// list. Keyed YANG lists do not allow duplicate keys to
+	// be created.
+	if _, ok := t.List1[key]; ok {
+		return nil, fmt.Errorf("duplicate key %v for list List1", key)
+	}
+
+	t.List1[key] = &Test_Container2_List1{
+		Leaf1: &Leaf1,
+	}
+
+	return t.List1[key], nil
+}
+
+// Validate validates s against the YANG schema corresponding to its type.
+func (t *Test_Container2) Validate(opts ...ygot.ValidationOption) error {
+	if err := ytypes.Validate(SchemaTree["Test_Container2"], t, opts...); err != nil {
+		return err
+	}
+	return nil
+}
+
+// ΛEnumTypeMap returns a map, keyed by YANG schema path, of the enumerated types
+// that are included in the generated code.
+func (t *Test_Container2) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTypes }
+
+// Test_Container2_List1 represents the /test/container2/list1 YANG schema element.
+type Test_Container2_List1 struct {
+	LeafList1 []string `path:"leaf-list1" module:"test"`
+	Leaf1     *string  `path:"leaf1" module:"test"`
+	Leaf2     *string  `path:"leaf2" module:"test"`
+}
+
+// IsYANGGoStruct ensures that Test_Container2_List1 implements the yang.GoStruct
+// interface. This allows functions that need to handle this struct to
+// identify it as being generated by ygen.
+func (*Test_Container2_List1) IsYANGGoStruct() {}
+
+// ΛListKeyMap returns the keys of the Test_Container2_List1 struct, which is a YANG list entry.
+func (t *Test_Container2_List1) ΛListKeyMap() (map[string]interface{}, error) {
+	if t.Leaf1 == nil {
+		return nil, fmt.Errorf("nil value for key Leaf1")
+	}
+
+	return map[string]interface{}{
+		"leaf1": *t.Leaf1,
+	}, nil
+}
+
+// Validate validates s against the YANG schema corresponding to its type.
+func (t *Test_Container2_List1) Validate(opts ...ygot.ValidationOption) error {
+	if err := ytypes.Validate(SchemaTree["Test_Container2_List1"], t, opts...); err != nil {
+		return err
+	}
+	return nil
+}
+
+// ΛEnumTypeMap returns a map, keyed by YANG schema path, of the enumerated types
+// that are included in the generated code.
+func (t *Test_Container2_List1) ΛEnumTypeMap() map[string][]reflect.Type { return ΛEnumTypes }
+
+var (
+	// ySchema is a byte slice contain a gzip compressed representation of the
+	// YANG schema from which the Go code was generated. When uncompressed the
+	// contents of the byte slice is a JSON document containing an object, keyed
+	// on the name of the generated struct, and containing the JSON marshalled
+	// contents of a goyang yang.Entry struct, which defines the schema for the
+	// fields within the struct.
+	ySchema = []byte{
+		0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x59, 0xdf, 0x6f, 0xda, 0x30,
+		0x10, 0x7e, 0xcf, 0x5f, 0x61, 0xf9, 0x99, 0x09, 0xe2, 0x41, 0xe9, 0xf2, 0xc6, 0xda, 0x4d, 0x93,
+		0xda, 0x6e, 0xd3, 0xd6, 0xf7, 0xca, 0x4a, 0x0e, 0x6a, 0x0d, 0x6c, 0x64, 0x3b, 0x5b, 0xa3, 0x89,
+		0xff, 0x7d, 0x22, 0xa1, 0xf9, 0x45, 0x12, 0xdb, 0x30, 0x69, 0x4c, 0xf2, 0x23, 0xf6, 0x5d, 0xee,
+		0xbb, 0xfb, 0xee, 0x72, 0xf9, 0xc4, 0xef, 0x00, 0x21, 0x84, 0xf0, 0x67, 0xba, 0x01, 0x1c, 0x21,
+		0x9c, 0xc0, 0x4f, 0x16, 0x03, 0x1e, 0x15, 0xa7, 0x77, 0x8c, 0x27, 0x38, 0x42, 0xe1, 0xe1, 0xe7,
+		0x8d, 0xe0, 0x4b, 0xb6, 0xc2, 0x11, 0x9a, 0x1c, 0x0e, 0x6e, 0x99, 0xc4, 0x11, 0x2a, 0x1e, 0x91,
+		0x1f, 0xc4, 0x82, 0x6b, 0xca, 0x38, 0xc8, 0xb0, 0x71, 0xde, 0x08, 0x51, 0xb3, 0x19, 0x35, 0x2d,
+		0x9a, 0xe1, 0xca, 0xe3, 0x76, 0xd8, 0xf2, 0xe2, 0xab, 0x84, 0x25, 0x7b, 0x39, 0x8a, 0xd4, 0x8a,
+		0x16, 0xb7, 0xc2, 0xe4, 0xd7, 0xdf, 0x45, 0x2a, 0x63, 0xe8, 0x74, 0x2d, 0xa0, 0x40, 0xf6, 0x4b,
+		0xc8, 0x3d, 0x1a, 0xbc, 0x2d, 0xa2, 0x8c, 0xba, 0x0d, 0x3f, 0x51, 0xb5, 0x90, 0xab, 0x74, 0x03,
+		0x5c, 0xe3, 0x08, 0x69, 0x99, 0x42, 0x8f, 0x61, 0xcd, 0x2a, 0x07, 0x75, 0x64, 0xb5, 0x6b, 0x9c,
+		0xec, 0x5a, 0xb9, 0xb6, 0x4b, 0x5d, 0x5e, 0xac, 0x99, 0xd2, 0x61, 0x7f, 0x22, 0xaf, 0x75, 0x28,
+		0xcc, 0x7a, 0xb0, 0x75, 0x17, 0xde, 0x48, 0x80, 0x0d, 0x11, 0x96, 0x84, 0xd8, 0x12, 0xe3, 0x4c,
+		0x90, 0x33, 0x51, 0xf6, 0x84, 0x75, 0x13, 0xd7, 0x43, 0xa0, 0x91, 0xc8, 0x8a, 0x50, 0xa0, 0xcb,
+		0x37, 0xc3, 0xac, 0x1e, 0xb3, 0x5b, 0xf9, 0x18, 0xb2, 0x3a, 0x50, 0x3d, 0x31, 0x98, 0x95, 0x94,
+		0x87, 0x06, 0x43, 0x0b, 0xea, 0x1d, 0x5b, 0xc0, 0xb5, 0x15, 0x4e, 0x6e, 0x89, 0x93, 0x5b, 0xc3,
+		0xbd, 0x45, 0x86, 0x5b, 0xc5, 0xd0, 0x32, 0x65, 0xb8, 0xc7, 0x6c, 0x0b, 0x6e, 0x95, 0x56, 0x5a,
+		0x32, 0xbe, 0xb2, 0x29, 0xf6, 0xeb, 0x2b, 0xe0, 0xfa, 0x2c, 0x84, 0xf7, 0x4c, 0xe9, 0x85, 0xd6,
+		0xd2, 0x0e, 0xe5, 0x03, 0xe3, 0x1f, 0xd6, 0xb0, 0x2f, 0xa0, 0x32, 0xb7, 0x64, 0xe1, 0x41, 0x5f,
+		0x6a, 0x1e, 0xe1, 0xf5, 0x74, 0x7a, 0x35, 0x9f, 0x4e, 0x27, 0xf3, 0xb7, 0xf3, 0xc9, 0xbb, 0xd9,
+		0x2c, 0xbc, 0x0a, 0x67, 0x16, 0x0f, 0xf9, 0x22, 0x13, 0x90, 0x90, 0xbc, 0xcf, 0x70, 0x84, 0x78,
+		0xba, 0x5e, 0x07, 0xa7, 0x31, 0x36, 0x50, 0x8b, 0x7c, 0x1e, 0x1d, 0xc7, 0xf7, 0xaf, 0x4f, 0x2e,
+		0xf1, 0x93, 0x7b, 0x31, 0x93, 0xfb, 0x40, 0x79, 0x42, 0xb5, 0x90, 0x99, 0xc5, 0x1b, 0xf5, 0x02,
+		0xa6, 0xfc, 0xe4, 0x9e, 0x27, 0x6e, 0x3d, 0x4f, 0xfc, 0xb6, 0xf2, 0xdb, 0xea, 0x9f, 0xf4, 0xb1,
+		0xd3, 0x27, 0xdb, 0x1d, 0x64, 0xa6, 0xb7, 0xb4, 0xdd, 0xe6, 0xb3, 0xdf, 0x78, 0x67, 0x6d, 0x3a,
+		0xbb, 0x0d, 0xd7, 0x97, 0xed, 0x82, 0x73, 0xa1, 0xa9, 0x66, 0x82, 0x0f, 0xe7, 0xa2, 0xe2, 0x67,
+		0xd8, 0xd0, 0x2d, 0xd5, 0xcf, 0xfb, 0xe2, 0x8c, 0x35, 0x28, 0x3d, 0xae, 0xb4, 0xdd, 0xd8, 0xf4,
+		0x35, 0xba, 0x67, 0x3b, 0x8d, 0x35, 0x3f, 0x70, 0xff, 0x08, 0x4a, 0x3f, 0xdd, 0x94, 0xee, 0x4f,
+		0xf7, 0xb9, 0x7b, 0x60, 0x47, 0xde, 0xb0, 0x74, 0x32, 0x24, 0x64, 0x48, 0xa4, 0x4b, 0x3d, 0x0e,
+		0x42, 0x6f, 0x82, 0xae, 0xa0, 0xd5, 0x60, 0x55, 0x1a, 0x98, 0x58, 0xe8, 0x64, 0xe2, 0x75, 0xb2,
+		0xd7, 0xc9, 0x5e, 0x27, 0x7b, 0x9d, 0xec, 0xbf, 0x3c, 0xbc, 0x4e, 0xf6, 0x3a, 0xd9, 0xeb, 0x64,
+		0xaf, 0x93, 0xbd, 0x4e, 0xf6, 0xdb, 0xca, 0x6f, 0x2b, 0xaf, 0x93, 0xff, 0x7b, 0x9d, 0x4c, 0xce,
+		0xd3, 0xc9, 0xe4, 0x62, 0x74, 0x32, 0x71, 0xd5, 0xc9, 0xa4, 0x57, 0x27, 0x07, 0x35, 0x70, 0x7d,
+		0xa0, 0x30, 0x53, 0x1f, 0xe9, 0x0f, 0xf8, 0x26, 0xc4, 0xf1, 0x70, 0xb7, 0x81, 0xe2, 0xfa, 0x55,
+		0x03, 0xd1, 0x6d, 0xf1, 0x6f, 0x77, 0x11, 0x30, 0xd8, 0xfd, 0x01, 0x00, 0x00, 0xff, 0xff, 0x01,
+		0x00, 0x00, 0xff, 0xff, 0x0c, 0xf4, 0xf2, 0x38, 0x0c, 0x1f, 0x00, 0x00,
+	}
+)
+
+// ΛEnumTypes is a map, keyed by a YANG schema path, of the enumerated types that
+// correspond with the leaf. The type is represented as a reflect.Type. The naming
+// of the map ensures that there are no clashes with valid YANG identifiers.
+var ΛEnumTypes = map[string][]reflect.Type{}