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

Resolve "Nil pointer dereference in integration test"

parent b533a19a
Branches
Tags
9 merge requests!246Develop,!245Develop into Master,!244Master into develop2 into master,!219Draft: Testing,!214Test pipelines,!195DO NOT MERGE 2,!194DO NOT MERGE! just for testing,!162Resolve "Nil pointer dereference in integration test",!138Develop
Showing with 171 additions and 449 deletions
package integration
package api
import (
"fmt"
"os"
"testing"
tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport"
"code.fbi.h-da.de/cocsn/gosdn/api"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/util/proto"
"fmt"
guuid "github.com/google/uuid"
gpb "github.com/openconfig/gnmi/proto/gnmi"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
pb "google.golang.org/protobuf/proto"
"os"
"testing"
)
const unreachable = "203.0.113.10:6030"
......@@ -20,10 +20,11 @@ const testPath = "/system/config/hostname"
var testIP = "141.100.70.171"
var testPort = "6030"
var testAddress = testIP + ":" + testPort
var testAPIEndpoint = "http://gosdn-latest.apps.ocp.fbi.h-da.de/api"
var testAPIEndpoint = "gosdn-latest.apps.ocp.fbi.h-da.de"
var testUsername = "admin"
var testPassword = "arista"
var opt *tpb.TransportOption
var gnmiMessages map[string]pb.Message
func TestMain(m *testing.M) {
testSetupIntegration()
......@@ -31,6 +32,11 @@ func TestMain(m *testing.M) {
}
func testSetupIntegration() {
viper.SetConfigFile(".k8s.toml")
if err := viper.ReadInConfig(); err != nil {
log.Error(err)
}
if os.Getenv("GOSDN_LOG") == "nolog" {
log.SetLevel(log.PanicLevel)
}
......@@ -91,7 +97,9 @@ func testSetupIntegration() {
}
}
func TestCmdIntegration(t *testing.T) {
func TestApiIntegration(t *testing.T) {
// TDOO: Remove once openshift grpc support is available
t.Skip("skipped due to openshift limitations")
if testing.Short() {
t.Skip("skipping integration test")
}
......@@ -107,7 +115,7 @@ func TestCmdIntegration(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer viper.Reset()
if err := api.Init(testAPIEndpoint); (err != nil) != tt.wantErr {
if err := Init(testAPIEndpoint); (err != nil) != tt.wantErr {
switch err.(type) {
case viper.ConfigFileNotFoundError:
default:
......@@ -118,7 +126,7 @@ func TestCmdIntegration(t *testing.T) {
cliPnd := viper.GetString("CLI_PND")
cliSbi := viper.GetString("CLI_SBI")
if _, err := api.AddDevice(
if _, err := AddDevice(
testAPIEndpoint,
testUsername,
testPassword,
......@@ -132,7 +140,7 @@ func TestCmdIntegration(t *testing.T) {
}
did := viper.GetString("LAST_DEVICE_UUID")
_, err := api.GetDevice(
_, err := GetDevice(
testAPIEndpoint,
cliPnd,
testPath,
......@@ -143,7 +151,7 @@ func TestCmdIntegration(t *testing.T) {
return
}
_, err = api.GetDevice(
_, err = GetDevice(
testAPIEndpoint,
cliPnd,
"",
......@@ -155,7 +163,7 @@ func TestCmdIntegration(t *testing.T) {
}
hostname := guuid.New().String()
_, err = api.Update(
_, err = Update(
testAPIEndpoint,
did,
cliPnd,
......@@ -167,10 +175,10 @@ func TestCmdIntegration(t *testing.T) {
return
}
resp, err := api.GetDevice(testAddress, testUsername, testPassword, testPath)
resp, err := GetDevice(testAddress, testUsername, testPassword, testPath)
if err != nil {
if !tt.wantErr {
t.Errorf("api.Get() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
}
return
}
......
package api
import (
"context"
"fmt"
"strings"
spb "code.fbi.h-da.de/cocsn/api/go/gosdn/southbound"
tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport"
"code.fbi.h-da.de/cocsn/gosdn/nucleus"
gpb "github.com/openconfig/gnmi/proto/gnmi"
)
// Capabilities sends a gNMI Capabilities request to the specified target
// and prints the supported models to stdout
func Capabilities(a, u, p string) error {
opts := &tpb.TransportOption{
Address: a,
Username: u,
Password: p,
}
transport, err := nucleus.NewGnmiTransport(opts, nucleus.NewSBI(spb.Type_OPENCONFIG))
if err != nil {
return err
}
resp, err := transport.Capabilities(context.Background())
if err != nil {
return err
}
modelData := resp.(*gpb.CapabilityResponse).SupportedModels
b := strings.Builder{}
for _, elem := range modelData {
_, err := b.WriteString(elem.Name)
if err != nil {
return err
}
_, err = b.WriteString("\n")
if err != nil {
return err
}
}
fmt.Println(b.String())
return nil
}
......@@ -8,10 +8,9 @@ require (
code.fbi.h-da.de/cocsn/yang-models v0.0.7
github.com/google/uuid v1.2.0
github.com/openconfig/gnmi v0.0.0-20210527163611-d3a3e30199da
github.com/openconfig/goyang v0.2.4
github.com/openconfig/ygot v0.10.11
github.com/sirupsen/logrus v1.8.1
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.7.0
google.golang.org/grpc v1.37.0
google.golang.org/protobuf v1.26.0
)
......@@ -171,7 +171,6 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
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=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/gnxi v0.0.0-20210423111716-4b504ef806a7 h1:cJ62uhbZcclaYm9gq4JNyazqSY7bUEggwZdw0nHTT7o=
github.com/google/gnxi v0.0.0-20210423111716-4b504ef806a7/go.mod h1:dPTuHPVOqxZ2yGKPjymiMt1vrZa8KHXWKX+Lx1z5d88=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
......
package api
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
tpb "code.fbi.h-da.de/cocsn/api/go/gosdn/transport"
"code.fbi.h-da.de/cocsn/gosdn/nucleus/types"
"code.fbi.h-da.de/cocsn/gosdn/forks/goarista/gnmi"
"code.fbi.h-da.de/cocsn/gosdn/nucleus"
log "github.com/sirupsen/logrus"
)
// Subscribe starts a gNMI subscriber requersting the specified paths on the target and
// logs the response to stdout. Only 'stream' mode with 'sample' operation supported.
func Subscribe(address, username, password, deviceName string, sample, heartbeat int64, args ...string) error {
sbi := &nucleus.OpenConfig{}
tOpts := &tpb.TransportOption{
Address: address,
Username: username,
Password: password,
Tls: false,
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{
Compression: "",
GrpcDialOptions: nil,
Token: "",
Encoding: 0,
},
},
}
device, err := nucleus.NewDevice(deviceName, tOpts, sbi)
if err != nil {
return err
}
opts := &gnmi.SubscribeOptions{
UpdatesOnly: false,
Prefix: "",
Mode: "stream",
StreamMode: "sample",
SampleInterval: uint64(sample * time.Second.Nanoseconds()),
SuppressRedundant: false,
HeartbeatInterval: uint64(heartbeat * time.Second.Nanoseconds()),
Paths: gnmi.SplitPaths(args),
Origin: "",
Target: address,
}
done := make(chan os.Signal, 1)
signal.Notify(done, syscall.SIGILL, syscall.SIGTERM)
ctx := context.WithValue(context.Background(), types.CtxKeyOpts, opts) //nolint
go func() {
if err := device.Transport().Subscribe(ctx); err != nil {
log.Fatal(err)
}
}()
fmt.Println("awaiting signal")
<-done
fmt.Println("exiting")
return nil
}
package api
import (
"context"
"net"
"reflect"
"code.fbi.h-da.de/cocsn/gosdn/forks/google/gnmi"
oc "code.fbi.h-da.de/cocsn/yang-models/generated/openconfig"
pb "github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/goyang/pkg/yang"
"github.com/openconfig/ygot/util"
"github.com/openconfig/ygot/ygot"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
type server struct {
*gnmi.Server
}
func callback(newConfig ygot.ValidatedGoStruct) error {
// Apply the config to your device and return nil if success. return error if fails.
//
// Do something ...
return nil
}
func newServer(model *gnmi.Model, config []byte) (*server, error) {
s, err := gnmi.NewServer(model, config, callback)
if err != nil {
return nil, err
}
return &server{Server: s}, nil
}
// Get overrides the Get func of gnmi.Target to provide user auth.
func (s *server) Get(ctx context.Context, req *pb.GetRequest) (*pb.GetResponse, error) {
return s.Server.Get(ctx, req)
}
// Set overrides the Set func of gnmi.Target to provide user auth.
/*
func (s *server) Set(ctx context.Context, req *pb.SetRequest) (*pb.SetResponse, error) {
msg, ok := credentials.AuthorizeUser(ctx)
if !ok {
log.Infof("denied a Set request: %v", msg)
return nil, status.Error(codes.PermissionDenied, msg)
}
log.Infof("allowed a Set request: %v", msg)
return s.Server.Set(ctx, req)
}
*/
// Target starts a gNMI target listening on the specified port.
func Target(bindAddr string) error {
entries := make([]*yang.Entry, 0)
for _, e := range oc.SchemaTree {
entries = append(entries, e)
}
modelData, err := util.FindModelData(entries)
if err != nil {
return err
}
// Google stuff from here
model := gnmi.NewModel(
modelData,
reflect.TypeOf((*oc.Device)(nil)),
oc.SchemaTree["Device"],
oc.Unmarshal,
oc.ΛEnum)
g := grpc.NewServer()
var configData []byte
s, err := newServer(model, configData)
if err != nil {
return err
}
pb.RegisterGNMIServer(g, s)
reflection.Register(g)
log.Infof("starting to listen on %s", bindAddr)
listen, err := net.Listen("tcp", bindAddr)
if err != nil {
return err
}
log.Info("starting to serve")
if err := g.Serve(listen); err != nil {
return err
}
return nil
}
......@@ -3,12 +3,13 @@ package main
import (
"context"
"os"
"strconv"
nucleus "code.fbi.h-da.de/cocsn/gosdn/nucleus/errors"
log "github.com/sirupsen/logrus"
"github.com/spf13/viper"
appv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
netv1 "k8s.io/api/networking/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
......@@ -16,6 +17,16 @@ import (
"k8s.io/client-go/tools/clientcmd"
)
// GRPC defines the grpc port used by the deployment
const GRPC = 55055
// HTTP defines the http port used by the deployment
const HTTP = 8080
var service *corev1.Service
var deployment *appv1.Deployment
var config *corev1.ConfigMap
func main() {
log.SetFormatter(&log.JSONFormatter{})
kubeconfig, err := clientcmd.BuildConfigFromFlags("https://api.ocp.fbi.h-da.de:6443", "")
......@@ -37,15 +48,6 @@ func main() {
tag = os.Getenv("CI_COMMIT_SHA")
}
switch os.Getenv("CI_NIGHTLY") {
case "mainline":
tag = "nightly"
case "develop":
tag = "nightly-develop"
default:
tag = os.Getenv("CI_COMMIT_SHA")
}
switch os.Getenv("K8S_OP") {
case "create":
if err := create(clientset, tag); err != nil {
......@@ -55,27 +57,56 @@ func main() {
if err := remove(clientset, tag); err != nil {
log.Fatal(err)
}
case "getenv":
if err := getenv(clientset, tag); err != nil {
log.Fatal(err)
}
default:
log.Fatal("invalid option")
}
}
func getenv(clientset *kubernetes.Clientset, tag string) error {
env := "gosdn-" + tag
opts := metav1.GetOptions{}
ctx := context.Background()
service, err := clientset.CoreV1().Services("cocsn").Get(ctx, env, opts)
if err != nil {
return err
}
var ip string
for _, ingress := range service.Status.LoadBalancer.Ingress {
ip = ingress.IP
}
var port string
for _, p := range service.Spec.Ports {
if p.Name == "grpc" {
port = strconv.Itoa(int(p.NodePort))
}
}
log.WithFields(log.Fields{
"ip": ip,
"port": port,
}).Info(env)
viper.Set("GOSDN_TEST_API_ENDPOINT", ip+":"+port)
return viper.SafeWriteConfigAs(".k8s.toml")
}
// nolint
func create(clientset *kubernetes.Clientset, tag string) error {
env := "gosdn-" + tag
service := createService(env)
ingress := createIngress(env)
config := createConfigMap(env)
deployment := createDeployment(env, tag)
deployment = createDeployment(env, tag)
opts := metav1.CreateOptions{}
ctx := context.Background()
_, err := clientset.CoreV1().Services("cocsn").Create(ctx, service, opts)
_, err := clientset.AppsV1().Deployments("cocsn").Create(ctx, deployment, opts)
if err != nil {
switch err.(type) {
case *errors.StatusError:
if err.(*errors.StatusError).ErrStatus.Code == 409 {
if err := update(clientset, service, env); err != nil {
return err
if err := update(clientset, deployment, env); err != nil {
log.Error(err)
}
} else {
log.Error(err)
......@@ -84,25 +115,14 @@ func create(clientset *kubernetes.Clientset, tag string) error {
log.Error(err)
}
} else {
log.Printf("service %v created", service.Name)
log.Printf("deployment %v created", deployment.Name)
}
_, err = clientset.NetworkingV1beta1().Ingresses("cocsn").Create(ctx, ingress, opts)
deployment, err = clientset.AppsV1().Deployments("cocsn").Get(ctx, env, metav1.GetOptions{})
if err != nil {
switch err.(type) {
case *errors.StatusError:
if err.(*errors.StatusError).ErrStatus.Code == 409 {
if err := update(clientset, ingress, env); err != nil {
log.Error(err)
}
} else {
log.Error(err)
}
default:
log.Error(err)
}
} else {
log.Printf("ingress %v created", ingress.Name)
log.Error(err)
}
config = createConfigMap(env)
_, err = clientset.CoreV1().ConfigMaps("cocsn").Create(ctx, config, opts)
if err != nil {
switch err.(type) {
......@@ -120,13 +140,15 @@ func create(clientset *kubernetes.Clientset, tag string) error {
} else {
log.Printf("configMap %v created", config.Name)
}
_, err = clientset.AppsV1().Deployments("cocsn").Create(ctx, deployment, opts)
service = createService(env)
_, err = clientset.CoreV1().Services("cocsn").Create(ctx, service, opts)
if err != nil {
switch err.(type) {
case *errors.StatusError:
if err.(*errors.StatusError).ErrStatus.Code == 409 {
if err := update(clientset, deployment, env); err != nil {
log.Error(err)
if err := update(clientset, service, env); err != nil {
return err
}
} else {
log.Error(err)
......@@ -135,7 +157,7 @@ func create(clientset *kubernetes.Clientset, tag string) error {
log.Error(err)
}
} else {
log.Printf("deployment %v created", deployment.Name)
log.Printf("service %v created", service.Name)
}
return nil
}
......@@ -157,18 +179,6 @@ func update(clientset *kubernetes.Clientset, resource metav1.Common, env string)
return err
}
log.Printf("service %v updated", service.Name)
case *netv1.Ingress:
ingress := resource
i, err := clientset.NetworkingV1beta1().Ingresses("cocsn").Get(ctx, env, getOpts)
if err != nil {
return err
}
i.DeepCopyInto(ingress)
_, err = clientset.NetworkingV1beta1().Ingresses("cocsn").Update(ctx, ingress, opts)
if err != nil {
return err
}
log.Printf("ingress %v updated", ingress.Name)
case *corev1.ConfigMap:
config := resource
c, err := clientset.CoreV1().ConfigMaps("cocsn").Get(ctx, env+"-config", getOpts)
......@@ -221,12 +231,6 @@ func remove(clientset *kubernetes.Clientset, tag string) error {
} else {
log.Printf("deployment %v deleted", env)
}
err = clientset.NetworkingV1beta1().Ingresses("cocsn").Delete(ctx, env, opts)
if err != nil {
log.Error(err)
} else {
log.Printf("ingress %v deleted", env)
}
return err
}
......@@ -240,23 +244,33 @@ func createService(environment string) *corev1.Service {
Name: environment,
Namespace: "cocsn",
Labels: map[string]string{"run": environment},
Annotations: map[string]string{
"metallb.universe.tf/address-pool": "hdanet",
},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: "v1",
Kind: "Deployment",
Name: environment,
UID: deployment.GetUID(),
},
},
},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{
{
Name: "http",
Port: 8080,
TargetPort: intstr.IntOrString{IntVal: 8080},
Port: HTTP,
TargetPort: intstr.IntOrString{IntVal: HTTP},
},
{
Name: "grpc",
Port: 55055,
TargetPort: intstr.IntOrString{IntVal: 55055},
Port: GRPC,
TargetPort: intstr.IntOrString{IntVal: GRPC},
},
},
Selector: map[string]string{"run": environment},
Type: "NodePort",
ExternalName: environment + ".apps.ocp.fbi.h-da.de",
Selector: map[string]string{"run": environment},
Type: "LoadBalancer",
},
}
}
......@@ -301,11 +315,11 @@ func createDeployment(environment, hash string) *appv1.Deployment {
Ports: []corev1.ContainerPort{
{
Name: "grpc",
ContainerPort: 55055,
ContainerPort: GRPC,
},
{
Name: "http",
ContainerPort: 8080,
ContainerPort: HTTP,
},
},
VolumeMounts: []corev1.VolumeMount{
......@@ -318,7 +332,7 @@ func createDeployment(environment, hash string) *appv1.Deployment {
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/livez",
Port: intstr.IntOrString{IntVal: 8080},
Port: intstr.IntOrString{IntVal: HTTP},
},
},
InitialDelaySeconds: 5,
......@@ -328,7 +342,7 @@ func createDeployment(environment, hash string) *appv1.Deployment {
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/readyz",
Port: intstr.IntOrString{IntVal: 8080},
Port: intstr.IntOrString{IntVal: HTTP},
},
},
InitialDelaySeconds: 10,
......@@ -358,41 +372,15 @@ func createConfigMap(env string) *corev1.ConfigMap {
},
ObjectMeta: metav1.ObjectMeta{
Name: env + "-config",
},
Data: map[string]string{"gosdn.toml": "#empty"},
}
}
func createIngress(env string) *netv1.Ingress {
return &netv1.Ingress{
TypeMeta: metav1.TypeMeta{
Kind: "Ingress",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: env,
Namespace: "cocsn",
},
Spec: netv1.IngressSpec{
Rules: []netv1.IngressRule{
OwnerReferences: []metav1.OwnerReference{
{
Host: env + ".apps.ocp.fbi.h-da.de",
IngressRuleValue: netv1.IngressRuleValue{
HTTP: &netv1.HTTPIngressRuleValue{
Paths: []netv1.HTTPIngressPath{
{
Path: "/api",
Backend: netv1.IngressBackend{
ServiceName: env,
ServicePort: intstr.IntOrString{IntVal: 8080},
},
},
},
},
},
APIVersion: "v1",
Kind: "Deployment",
Name: env,
UID: deployment.GetUID(),
},
},
},
Status: netv1.IngressStatus{},
Data: map[string]string{"gosdn.toml": "#empty"},
}
}
services:
- docker:19.03.12-dind
- name: docker:19.03.12-dind
command: ["--registry-mirror", "http://141.100.70.170:6000"]
variables:
DOCKER_TLS_CERTDIR: "/certs"
......@@ -14,6 +15,7 @@ variables:
tags:
- dind
script:
- docker info
- >
docker build \
--build-arg GITLAB_USER=$GO_MODULES_USER \
......
......@@ -17,7 +17,6 @@ build:k8s-bot:
image:
name: bitnami/kubectl:latest
entrypoint: [""]
before_script:
- echo "override global before script"
variables:
......
......@@ -27,7 +27,7 @@ linters:
enable:
- gofmt
- goimports
- golint
- revive
- gocyclo
- govet
issues:
......
integration-test:
.integration-test: &integration-test
image: golang:1.16
stage: integration-test
needs:
- job: "apply"
- job: "deploy:integration-test"
variables:
GOSDN_LOG: "nolog"
GOSDN_TEST_API_ENDPOINT: http://gosdn-$CI_COMMIT_SHA.apps.ocp.fbi.h-da.de/api
GOSDN_TEST_API_ENDPOINT: gosdn-$CI_COMMIT_SHA.apps.ocp.fbi.h-da.de
GOSDN_TEST_ENDPOINT_IP: 141.100.70.171
GOSDN_CHANGE_TIMEOUT: "100ms"
rules:
......@@ -20,10 +21,38 @@ integration-test:
allow_failure: true
when: delayed
start_in: 2 minutes
integration-test:nucleus:
<<: *integration-test
script:
- cd ./test/integration
- go test -race -v -run TestGnmi_SetIntegration
- go test -race -v -run TestGnmi_GetIntegration
- go test -race -v -run TestGnmi_SubscribeIntegration
- go test -race -v -run TestGnmi_CapabilitiesIntegration
integration-test:cmd:
<<: *integration-test
variables:
K8S_OP: "getenv"
needs:
- job: "build:merge-request"
- job: "apply"
- job: "deploy:integration-test"
- job: "build:k8s-bot"
artifacts: true
script:
- cd ./test/integration
- ./../../build/cd/k8s-bot
- go test -race -v -run TestCmdIntegration
integration-test:cli:
<<: *integration-test
script:
- ./build/ci/generate_port.sh $CI_PIPELINE_ID >> port
- export GOSDN_TEST_ENDPOINT_PORT=$(cat port)
- go test -race ./test/integration -v -coverprofile=coverage.out
- cd ./api
- go test -race -v -run TestApiIntegration
.test: &test
image: golang:1.16
......@@ -49,4 +78,4 @@ unit-test:
controller-test:
script:
- go test -race -v -run TestRun
<<: *test
\ No newline at end of file
<<: *test
......@@ -71,6 +71,7 @@ func startGrpcServer() error {
if err != nil {
return err
}
log.Infof("listening to %v", lis.Addr())
c.grpcServer = grpc.NewServer()
c.nbi = nbi.NewNBI(c.pndc)
pb.RegisterCoreServer(c.grpcServer, c.nbi.Core)
......
......@@ -4,7 +4,6 @@ go 1.16
require (
code.fbi.h-da.de/cocsn/api/go v0.0.0-20210609143151-4dabee5ab99a
code.fbi.h-da.de/cocsn/gosdn/api v0.0.0-20210610093733-cbc69d7e537d
code.fbi.h-da.de/cocsn/yang-models v0.0.7
github.com/aristanetworks/goarista v0.0.0-20201120222254-94a892eb0c6a
github.com/docker/docker v20.10.6+incompatible
......
......@@ -21,12 +21,8 @@ cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIA
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
code.fbi.h-da.de/cocsn/api/go v0.0.0-20210609120033-1ef56612bd26/go.mod h1:2+rnE92IyXLbiy3/92EM7JrtsY5tXPAKX90QmsT2+m0=
code.fbi.h-da.de/cocsn/api/go v0.0.0-20210609143151-4dabee5ab99a h1:C2tdh2A4RckZJXUymtF2ec8hE8mTkhn7EQJShv+i/Jk=
code.fbi.h-da.de/cocsn/api/go v0.0.0-20210609143151-4dabee5ab99a/go.mod h1:2+rnE92IyXLbiy3/92EM7JrtsY5tXPAKX90QmsT2+m0=
code.fbi.h-da.de/cocsn/gosdn v0.0.3-0.20210609130706-9cca50b3d195/go.mod h1:EK0GUnwNB+qMMjSJxGzLpfDw+KsUHS2LZkdzshldm4Q=
code.fbi.h-da.de/cocsn/gosdn/api v0.0.0-20210610093733-cbc69d7e537d h1:olcB+ojVhToetF73X1waLRaTG7oZpdFvZ2yUIAKiiI8=
code.fbi.h-da.de/cocsn/gosdn/api v0.0.0-20210610093733-cbc69d7e537d/go.mod h1:rn/FEXBauGQyFOIS2NhGd0EzF29Ibds0xt34Oo5wTgk=
code.fbi.h-da.de/cocsn/yang-models v0.0.7 h1:3TOo8J+EdAJKeq4o3aaNWZRhjSwguIS8wciW1U9PkSk=
code.fbi.h-da.de/cocsn/yang-models v0.0.7/go.mod h1:M+2HinfhTT8nA8qvn2cpWNlOtuiizTNDWA3yfy72K/g=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
......@@ -237,11 +233,11 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
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/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
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/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
......@@ -317,22 +313,18 @@ github.com/neo4j/neo4j-go-driver v1.8.3/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcL
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg=
github.com/onsi/ginkgo v1.12.1 h1:mFwc4LvZ0xpSvDZ3E+k8Yte0hLOMxXUlP+yXtJqkYfQ=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.10.3 h1:gph6h/qe9GSUw1NhH1gp+qb+h8rXD8Cy60Z32Qw3ELA=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
github.com/openconfig/gnmi v0.0.0-20200414194230-1597cc0f2600/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A=
github.com/openconfig/gnmi v0.0.0-20200508230933-d19cebf5e7be/go.mod h1:M/EcuapNQgvzxo1DDXHK4tx3QpYM/uG4l591v33jG2A=
......@@ -533,7 +525,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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
......@@ -570,7 +561,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
......@@ -725,6 +715,7 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8
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/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
......
......@@ -6,9 +6,7 @@ import (
)
func Test_httpApi(t *testing.T) {
if testing.Short() {
t.Skip("this test is executed separately")
}
tests := []struct {
name string
request string
......
......@@ -41,24 +41,29 @@ type Gnmi struct {
config *gnmi.Config
}
// NewGnmiTransport takes a struct of GnmiTransportOptions and returns a Gnmi
// newGnmiTransport takes a struct of GnmiTransportOptions and returns a Gnmi
// transport based on the values of it.
func NewGnmiTransport(opts *tpb.TransportOption, sbi southbound.SouthboundInterface) (*Gnmi, error) {
// Do not call directly. Use NewTransport() instead.
func newGnmiTransport(opts *tpb.TransportOption, sbi southbound.SouthboundInterface) (*Gnmi, error) {
if opts == nil || sbi == nil {
return nil, &errors.ErrInvalidParameters{}
} else if opts.TransportOption == nil {
return nil, &errors.ErrInvalidParameters{}
}
gnmiConfig := &gnmi.Config{
Addr: opts.Address,
Password: opts.Password,
Username: opts.Username,
TLS: opts.Tls,
Compression: opts.GetGnmiTransportOption().Compression,
Compression: opts.GetGnmiTransportOption().GetCompression(),
}
c, err := gnmi.Dial(gnmiConfig)
if err != nil {
return nil, err
}
log.WithFields(log.Fields{
"target": opts.Address,
"tls": opts.Tls,
"encoding": opts.GetGnmiTransportOption().Encoding,
"target": opts.Address,
"tls": opts.Tls,
}).Info("building new gNMI transport")
return &Gnmi{
SetNode: sbi.SetNode(),
......@@ -230,10 +235,7 @@ func (g *Gnmi) ProcessResponse(resp interface{}, root interface{}, s *ytypes.Sch
val, ok := update.Val.Value.(*gpb.TypedValue_JsonIetfVal)
if ok {
opts := []ytypes.UnmarshalOpt{&ytypes.IgnoreExtraFields{}}
if err := g.Unmarshal(val.JsonIetfVal, pathutils.ToStrings(fullPath), root, opts...); err != nil {
return err
}
return nil
return g.Unmarshal(val.JsonIetfVal, pathutils.ToStrings(fullPath), root, opts...)
}
// TODO(mk): Evaluate hardcoded model key
schema := models["Device"]
......
......@@ -431,8 +431,6 @@ func TestGnmi_getWithRequest(t *testing.T) {
}
func TestNewGnmiTransport(t *testing.T) {
// TODO: revise test
t.Skip("deep equal for gnmi.Config broken")
type args struct {
opts *tpb.TransportOption
}
......@@ -442,35 +440,6 @@ func TestNewGnmiTransport(t *testing.T) {
want *Gnmi
wantErr bool
}{
{
name: "default",
args: args{
opts: &tpb.TransportOption{
Address: "localhost:13371",
Username: "test",
Password: "test",
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{},
},
}},
want: &Gnmi{
Options: &tpb.TransportOption{
Address: "localhost:13371",
Username: "test",
Password: "test",
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{},
},
},
client: nil,
config: &gnmi.Config{
Addr: "localhost:13371",
Password: "test",
Username: "test",
},
},
wantErr: false,
},
{
name: "unsupported compression",
args: args{
......@@ -483,34 +452,6 @@ func TestNewGnmiTransport(t *testing.T) {
want: nil,
wantErr: true,
},
{
name: "certificate error no key file",
args: args{
opts: &tpb.TransportOption{
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{
GrpcDialOptions: map[string]string{
"cert-file": "invalid",
},
},
}}},
want: nil,
wantErr: true,
},
{
name: "certificate error no ca file",
args: args{
opts: &tpb.TransportOption{
TransportOption: &tpb.TransportOption_GnmiTransportOption{
GnmiTransportOption: &tpb.GnmiTransportOption{
GrpcDialOptions: map[string]string{
"ca-file": "invalid",
},
},
}}},
want: nil,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
......@@ -518,7 +459,7 @@ func TestNewGnmiTransport(t *testing.T) {
startGnmiTarget <- gnmiConfig.Addr
}
got, err := NewGnmiTransport(tt.args.opts, NewSBI(spb.Type_OPENCONFIG))
got, err := newGnmiTransport(tt.args.opts, NewSBI(spb.Type_OPENCONFIG))
if (err != nil) != tt.wantErr {
t.Errorf("NewGnmiTransport() error = %v, wantErr %v", err, tt.wantErr)
return
......@@ -530,7 +471,7 @@ func TestNewGnmiTransport(t *testing.T) {
tt.want.RespChan = got.RespChan
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewGnmiTransport() got = %v, want %v", got, tt.want)
t.Errorf("NewGnmiTransport() got = %#v, want %#v", got, tt.want)
}
if tt.name == "default" {
stopGnmiTarget <- true
......
......@@ -57,10 +57,7 @@ func (oc *OpenConfig) Schema() *ytypes.Schema {
// Needed for type assertion.
func (oc *OpenConfig) SetNode() func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
return func(schema *yang.Entry, root interface{}, path *gpb.Path, val interface{}, opts ...ytypes.SetNodeOpt) error {
if err := ytypes.SetNode(schema, root.(*openconfig.Device), path, val, opts...); err != nil {
return err
}
return nil
return ytypes.SetNode(schema, root.(*openconfig.Device), path, val, opts...)
}
}
......
......@@ -68,7 +68,9 @@ func (s genericStore) Add(item store.Storable) error {
}
// Get takes a Storable's UUID and returns the Storable. If the requested
// Storable does not exist an error is returned.
// Storable does not exist an error is returned. Get is only type safe for
// this Storable interface. For type safe get operations on specialised stores
// use GetDevice, GetPND, GetSBI, or GetChange respectively.
func (s genericStore) Get(id uuid.UUID) (store.Storable, error) {
if !s.Exists(id) {
return nil, &errors.ErrNotFound{ID: id}
......
......@@ -272,18 +272,6 @@ func Test_sbiStore_get(t *testing.T) {
args: args{id: defaultSbiID},
wantErr: true,
},
{
name: "fails wrong type",
fields: fields{
genericStore: genericStore{
did: &CommonDevice{
UUID: did,
},
},
},
args: args{id: did},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
......@@ -345,18 +333,6 @@ func Test_pndStore_get(t *testing.T) {
args: args{id: defaultPndID},
wantErr: true,
},
{
name: "fails wrong type",
fields: fields{
genericStore: genericStore{
did: &CommonDevice{
UUID: did,
},
},
},
args: args{id: did},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment