diff --git a/.gitignore b/.gitignore index be19042..47726a0 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,6 @@ .idea/ junit/ +nohup.out +.DS_Store +.vscode diff --git a/.license/README.md b/.license/README.md index de881ea..417a1eb 100644 --- a/.license/README.md +++ b/.license/README.md @@ -3,7 +3,7 @@ This folder contains the copyright templates for source files of NSM project. Below is an example of valid copyright header for `.go` files: ``` -// Copyright (c) 2020 Doc.ai and/or its affiliates. +// Copyright (c) 2020 Pragmagic Inc. and/or its affiliates. // // Copyright (c) 2020 Cisco and/or its affiliates. // @@ -24,7 +24,7 @@ Below is an example of valid copyright header for `.go` files: Note you can use your company name instead of `Cisco and/or its affiliates`. Also, source code files can have multi copyright holders, for example: ``` -// Copyright (c) 2020 Doc.ai and/or its affiliates. +// Copyright (c) 2020 Pragmagic Inc. and/or its affiliates. // // Copyright (c) 2020 Cisco and/or its affiliates. // diff --git a/Dockerfile b/Dockerfile index 1a3d3ad..c3fd83b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,4 +19,8 @@ CMD dlv -l :40000 --headless=true --api-version=2 test -test.v ./... FROM alpine as runtime COPY --from=build /bin/app /bin/app + +# Expose port for REST server +EXPOSE 3001 + CMD /bin/app \ No newline at end of file diff --git a/README.md b/README.md index 80fa61b..57f0fc3 100644 --- a/README.md +++ b/README.md @@ -1,75 +1,31 @@ -# Build +# Network Service Mesh Dashboard Backend -## Build cmd binary locally +NSM dashboard backend part provides graphical model data for [the UI part](https://github.com/networkservicemesh/cmd-dashboard-ui) through the REST API -You can build the locally by executing +Written in [Go](https://go.dev/) -```bash -go build ./... -``` +The entire NSM dashboard deployment info see [here](https://github.com/networkservicemesh/deployments-k8s/tree/main/examples/observability/dashboard) -## Build Docker container +## Dev/debug -You can build the docker container by running: +### To run dashboard backend in the cluster: -```bash -docker build . -``` +1. `git clone git@github.com:networkservicemesh/deployments-k8s.git` +2. `cd deployments-k8s/examples/observability/dashboard` +3. Edit `dashboard-pod.yaml` and remove the `dashboard-ui` container +4. `kubectl apply -f dashboard-pod.yaml` +5. `kubectl apply -f dashboard-backend-service.yaml` +6. `kubectl port-forward -n nsm-system service/dashboard-backend 3001:3001` +7. Check `http://localhost:3001/nodes` in the browser -# Testing +### To run dashboard backend with a custom container ([Docker](https://docs.docker.com/engine/install/) have to be installed) in the cluster: -## Testing Docker container - -Testing is run via a Docker container. To run testing run: - -```bash -docker run --privileged --rm $(docker build -q --target test .) -``` - -# Debugging - -## Debugging the tests -If you wish to debug the test code itself, that can be acheived by running: - -```bash -docker run --privileged --rm -p 40000:40000 $(docker build -q --target debug .) -``` - -This will result in the tests running under dlv. Connecting your debugger to localhost:40000 will allow you to debug. - -```bash --p 40000:40000 -``` -forwards port 40000 in the container to localhost:40000 where you can attach with your debugger. - -```bash ---target debug -``` - -Runs the debug target, which is just like the test target, but starts tests with dlv listening on port 40000 inside the container. - -## Debugging the cmd - -When you run 'cmd' you will see an early line of output that tells you: - -```Setting env variable DLV_LISTEN_FORWARDER to a valid dlv '--listen' value will cause the dlv debugger to execute this binary and listen as directed.``` - -If you follow those instructions when running the Docker container: -```bash -docker run --privileged -e DLV_LISTEN_FORWARDER=:50000 -p 50000:50000 --rm $(docker build -q --target test .) -``` - -```-e DLV_LISTEN_FORWARDER=:50000``` tells docker to set the environment variable DLV_LISTEN_FORWARDER to :50000 telling -dlv to listen on port 50000. - -```-p 50000:50000``` tells docker to forward port 50000 in the container to port 50000 in the host. From there, you can -just connect dlv using your favorite IDE and debug cmd. - -## Debugging the tests and the cmd - -```bash -docker run --privileged -e DLV_LISTEN_FORWARDER=:50000 -p 40000:40000 -p 50000:50000 --rm $(docker build -q --target debug .) -``` - -Please note, the tests **start** the cmd, so until you connect to port 40000 with your debugger and walk the tests -through to the point of running cmd, you will not be able to attach a debugger on port 50000 to the cmd. \ No newline at end of file +1. `git clone git@github.com:networkservicemesh/cmd-dashboard-backend.git` +2. `cd cmd-dashboard-backend` +3. Make the necessary code changes +4. Create a [Dockerhub](https://hub.docker.com/) repository +5. `docker build -t your-dh-namespace/dh-repo-name .` +6. `docker push your-dh-namespace/dh-repo-name` +7. `cd deployments-k8s/examples/observability/dashboard` +8. Edit `dashboard-pod.yaml` and set your Dockerhub image address for the `dashboard-backend` container +9. Execute the steps 3-7 from the previous section diff --git a/go.mod b/go.mod index 75a5330..2014a86 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,75 @@ -module github.com/networkservicemesh/cmd-template +module github.com/networkservicemesh/cmd-dashboard-backend go 1.20 + +require ( + github.com/antonfisher/nested-logrus-formatter v1.3.1 + github.com/edwarnicke/genericsync v0.0.0-20220910010113-61a344f9bc29 + github.com/gin-gonic/gin v1.9.1 + github.com/networkservicemesh/api v1.11.0 + github.com/networkservicemesh/sdk v1.11.0 + github.com/sirupsen/logrus v1.9.0 + github.com/spiffe/go-spiffe/v2 v2.0.0 + google.golang.org/grpc v1.59.0 +) + +require ( + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bytedance/sonic v1.10.2 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect + github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.16.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.6 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.1.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + github.com/zeebo/errs v1.2.2 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 // indirect + go.opentelemetry.io/otel v1.19.0-rc.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0-rc.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0-rc.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0-rc.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0-rc.1 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.42.0-rc.1 // indirect + go.opentelemetry.io/otel/metric v1.19.0-rc.1 // indirect + go.opentelemetry.io/otel/sdk v1.19.0-rc.1 // indirect + go.opentelemetry.io/otel/sdk/metric v1.19.0-rc.1 // indirect + go.opentelemetry.io/otel/trace v1.19.0-rc.1 // indirect + go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + golang.org/x/arch v0.6.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum index e69de29..a1163d2 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,266 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antonfisher/nested-logrus-formatter v1.3.1 h1:NFJIr+pzwv5QLHTPyKz9UMEoHck02Q9L0FP13b/xSbQ= +github.com/antonfisher/nested-logrus-formatter v1.3.1/go.mod h1:6WTfyWFkBc9+zyBaKIqRrg/KwMqBbodBjgbHjDz7zjA= +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/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= +github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= +github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= +github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= +github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= +github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +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/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +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/edwarnicke/genericsync v0.0.0-20220910010113-61a344f9bc29 h1:4/2wgileNvQB4HfJbq7u4FFLKIfc38a6P0S/51ZGgX8= +github.com/edwarnicke/genericsync v0.0.0-20220910010113-61a344f9bc29/go.mod h1:3m+ZfVq+z0pTLW798jmqnifMsalrVLIKmfXaMFvqSuc= +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= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= +github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +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/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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= +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.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= +github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/networkservicemesh/api v1.11.0 h1:9Hbanw+Eet3D/BF2jE75Nfhsmz0r9aStBiHEeyXXc50= +github.com/networkservicemesh/api v1.11.0/go.mod h1:DO7D13Y4x/A8tQ2cQyUWa9o5wi7XHUB8+vITWRKreCc= +github.com/networkservicemesh/sdk v1.11.0 h1:RUoMfq1/yBjWHeikEbcPGIcK7L23yim8sapBk51g4QA= +github.com/networkservicemesh/sdk v1.11.0/go.mod h1:kskx6RdU+taL14uTk/BMq7cDDPEy2s7O/ekcGxfWmBk= +github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= +github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spiffe/go-spiffe/v2 v2.0.0 h1:y6N7BZAxgaFZYELyrIdxSMm2e2tWpzgQewUts9h1hfM= +github.com/spiffe/go-spiffe/v2 v2.0.0/go.mod h1:TEfgrEcyFhuSuvqohJt6IxENUNeHfndWCCV1EX7UaVk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g= +github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0 h1:ZOLJc06r4CB42laIXg/7udr0pbZyuAihN10A/XuiQRY= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.42.0/go.mod h1:5z+/ZWJQKXa9YT34fQNx5K8Hd1EoIhvtUygUQPqEOgQ= +go.opentelemetry.io/otel v1.19.0-rc.1 h1:9nKcb4AOpKFjcIWQgebt1k75VYn2ZQMvgXD+/n28OLo= +go.opentelemetry.io/otel v1.19.0-rc.1/go.mod h1:+JfHvVWJ0QCKM+TFO3gpReowE8GaFEx2Ry9calmSibE= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0-rc.1 h1:m86dgj8YG+6KfM9wrSfMMTPi822rqfLGyQ1DD257zaU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0-rc.1/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0-rc.1 h1:mgQPqQKUP0IyfrmXCdMbqAH1xsBAHVzolbJkzgAqxlc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0-rc.1/go.mod h1:FMR+HUsfMXreSeo2juctBZN0rizwEc/c1vw7q2LY2lk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0-rc.1 h1:8ZG2TARAaJWqm1YN2QH86h1xX4EPCA4ldZtc4N4YWgg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0-rc.1/go.mod h1:jykghzDqP7m7cPJHTLdKpzYO1LSLZJM78TIhTdcWM8s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0-rc.1 h1:oy1QPbh9KiTlBicC8xXMPoMu6sxnsyPl1mdXBUrg3QY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0-rc.1/go.mod h1:MX98pqy1OH9RFoOhcK7MWP0me/bMs5m/8BLxg2Sg8oY= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0-rc.1 h1:V92ofeZM5yESfTQtNVpjEG+cDI8rp+3dmVE4OjVzcc8= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0-rc.1/go.mod h1:EtVcwPt5W/MC6fZfzya4A5iE9bRz8ysu0FRrNL8+SN0= +go.opentelemetry.io/otel/metric v1.19.0-rc.1 h1:LqJlejNazmpXWlOrgYUc1xj0pZ5cqkLoDaP4hlPQR00= +go.opentelemetry.io/otel/metric v1.19.0-rc.1/go.mod h1:xzyh2gMwfLsu30VybtOXISwzy7ohXDkPiG+YFPfcROc= +go.opentelemetry.io/otel/sdk v1.19.0-rc.1 h1:dD5Y9QMAktJ0gIlZjv+fmRAyVGm5v76spKJ63Ev22WQ= +go.opentelemetry.io/otel/sdk v1.19.0-rc.1/go.mod h1:e3KNe2cNBxQH2lL5sX9p7yi/GLKZ/QZDGyoJVNvYx7A= +go.opentelemetry.io/otel/sdk/metric v1.19.0-rc.1 h1:RbGxgZUjffRVPLjX/H695ri/noDOeFtzaP6uINNFJjA= +go.opentelemetry.io/otel/sdk/metric v1.19.0-rc.1/go.mod h1:J+jlmTpSn8aR86SQSlTkhGRKCN9ktrTDRzGgcaxDKzw= +go.opentelemetry.io/otel/trace v1.19.0-rc.1 h1:VvCcp07aHaPAS3I0UwONZiY4mglW2LHXRKNazj3B0w4= +go.opentelemetry.io/otel/trace v1.19.0-rc.1/go.mod h1:UttzyZK+fFPfslCglhDGMadPXgSNaQAqLPSh2ahBA34= +go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc= +golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200806141610-86f49bd18e98/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20231030173426-d783a09b4405 h1:I6WNifs6pF9tNdSob2W24JtyxIYjzFB9qDlpUC76q+U= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d h1:DoPTO70H+bcDXcd39vOqb2viZxgqeBeSGtZ55yZU4/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17 h1:Jyp0Hsi0bmHXG6k9eATXoYtjd6e2UzZ1SCn/wIupY14= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +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.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc/examples v0.0.0-20201130180447-c456688b1860/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/square/go-jose.v2 v2.4.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/main.go b/main.go index 82418ab..78a17d3 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,7 @@ -// Copyright (c) 2021 Doc.ai and/or its affiliates. -// // Copyright (c) 2023 Cisco and/or its affiliates. // +// Copyright (c) 2023 Pragmagic Inc. and/or its affiliates. +// // SPDX-License-Identifier: Apache-2.0 // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,5 +18,204 @@ package main +import ( + "context" + "crypto/tls" + "net/http" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "github.com/networkservicemesh/api/pkg/api/networkservice" + "github.com/networkservicemesh/api/pkg/api/registry" + + nested "github.com/antonfisher/nested-logrus-formatter" + "github.com/gin-gonic/gin" + "github.com/sirupsen/logrus" + "github.com/spiffe/go-spiffe/v2/spiffetls/tlsconfig" + "github.com/spiffe/go-spiffe/v2/svid/x509svid" + "github.com/spiffe/go-spiffe/v2/workloadapi" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" + + "github.com/networkservicemesh/sdk/pkg/tools/log" + "github.com/networkservicemesh/sdk/pkg/tools/log/logruslogger" + "github.com/networkservicemesh/sdk/pkg/tools/spiffejwt" + "github.com/networkservicemesh/sdk/pkg/tools/token" + "github.com/networkservicemesh/sdk/pkg/tools/tracing" +) + func main() { + ctx, cancel := signal.NotifyContext( + context.Background(), + os.Interrupt, + syscall.SIGHUP, + syscall.SIGTERM, + syscall.SIGQUIT, + ) + defer cancel() + + // Setup logger + log.EnableTracing(true) + logrus.SetFormatter(&nested.Formatter{}) + ctx = log.WithLog(ctx, logruslogger.New(ctx, map[string]interface{}{"cmd": os.Args[:1]})) + logger := log.FromContext(ctx) + + // Setup Spire + source, err := workloadapi.NewX509Source(ctx) + if err != nil { + logger.Fatalf("Error getting x509 source: %v", err.Error()) + } + var svid *x509svid.SVID + svid, err = source.GetX509SVID() + if err != nil { + logger.Fatalf("Error getting x509 svid: %v", err.Error()) + } + logger.Infof("sVID: %q", svid.ID) + + tlsClientConfig := tlsconfig.MTLSClientConfig(source, source, tlsconfig.AuthorizeAny()) + tlsClientConfig.MinVersion = tls.VersionTLS12 + + // Configure and run REST API server + configureAndRunRESTServer() + + // Create gRPC dial options + dialOptions := append(tracing.WithTracingDial(), + grpc.WithDefaultCallOptions( + grpc.WaitForReady(true), + grpc.PerRPCCredentials(token.NewPerRPCCredentials(spiffejwt.TokenGeneratorFunc(source, time.Duration(10)*time.Minute))), + ), + grpc.WithTransportCredentials(credentials.NewTLS(tlsClientConfig)), + ) + + // Monitor Connections + for ; ctx.Err() == nil; time.Sleep(time.Millisecond * 100) { + var nseChannel = getNseChannel(ctx, logger, dialOptions) + + for ctx.Err() == nil { + select { + case <-ctx.Done(): + return + case nse, ok := <-nseChannel: + if !ok { + break + } + + nsmgrAddr := strings.Join(strings.Split(strings.TrimPrefix(nse.GetNetworkServiceEndpoint().Url, "tcp://["), "]:"), ":") + + if _, exists := nsmgrs.Load(nsmgrAddr); !exists { + nsmgrs.Store(nsmgrAddr, true) + logger.Infof("Extracted NSMGR addr: %q", nsmgrAddr) + + // Start a goroutine for each nsmgr + go func() { + nsmgrConn, err := grpc.Dial(nsmgrAddr, dialOptions...) + if err != nil { + logger.Errorf("Failed dial to NSMgr %q: %v", nsmgrAddr, err.Error()) + return + } + + clientConnections := networkservice.NewMonitorConnectionClient(nsmgrConn) + + stream, err := clientConnections.MonitorConnections(ctx, &networkservice.MonitorScopeSelector{}) + if err != nil { + logger.Errorf("Error from MonitorConnectionClient: %v", err.Error()) + return + } + + for ctx.Err() == nil { + event, err := stream.Recv() + if err != nil { + logger.Errorf("Error from %q nsmgr monitorConnection stream: %v", nsmgrAddr, err.Error()) + time.Sleep(time.Millisecond * 500) + cleanupManager(logger, nsmgrAddr) + break + } + updateConnections(logger, nsmgrAddr, event) + } + }() + } + } + } + } +} + +func getNseChannel(ctx context.Context, logger log.Logger, dialOptions []grpc.DialOption) <-chan *registry.NetworkServiceEndpointResponse { + registryAddr := os.Getenv("NSM_REGISTRY_URL") + + if registryAddr == "" { + registryAddr = "registry:5002" + } + + conn, err := grpc.Dial(registryAddr, dialOptions...) + if err != nil { + logger.Errorf("Failed dial to Registry: %v", err.Error()) + } + + clientNse := registry.NewNetworkServiceEndpointRegistryClient(conn) + + streamNse, err := clientNse.Find(ctx, ®istry.NetworkServiceEndpointQuery{ + Watch: true, + NetworkServiceEndpoint: ®istry.NetworkServiceEndpoint{ + NetworkServiceNames: []string{"forwarder"}, + }, + }) + if err != nil { + logger.Errorf("Failed to perform Find NSE request: %v", err) + } + + return registry.ReadNetworkServiceEndpointChannel(streamNse) +} + +func updateConnections(logger log.Logger, nsmgrAddr string, event *networkservice.ConnectionEvent) { + for _, connection := range event.Connections { + connectionID := generateConnectionID(connection) + logger.Infof("Handling %q event on %q nsmgr connection: %q", event.Type.String(), nsmgrAddr, connectionID) + switch { + case event.Type == networkservice.ConnectionEventType_DELETE: + connections.Delete(connectionID) + removeManagerConnection(nsmgrAddr, connectionID) + default: // INITIAL_STATE_TRANSFER and UPDATE event types + connections.Store(connectionID, connection) + addManagerConnection(nsmgrAddr, connectionID) + } + } + parceConnectionsToGraphicalModel() +} + +func cleanupManager(logger log.Logger, nsmgrAddr string) { + mgrConnections, _ := managerConnections.Load(nsmgrAddr) + mgrConnections.Range(func(connectionID string, _ bool) bool { + logger.Infof("Removing %q nsmgr connection: %q", nsmgrAddr, connectionID) + connections.Delete(connectionID) + return true + }) + managerConnections.Delete(nsmgrAddr) + nsmgrs.Delete(nsmgrAddr) + parceConnectionsToGraphicalModel() +} + +func configureAndRunRESTServer() { + gin.SetMode(gin.ReleaseMode) + r := gin.Default() + + r.Use(func(c *gin.Context) { + c.Writer.Header().Set("Access-Control-Allow-Origin", "http://localhost:3000") + c.Next() + }) + + r.GET("/nodes", func(c *gin.Context) { + c.IndentedJSON(http.StatusOK, storageData.Nodes) + }) + r.GET("/edges", func(c *gin.Context) { + c.IndentedJSON(http.StatusOK, storageData.Edges) + }) + + go func() { + if err := r.Run(":3001"); err != nil { + panic("Failed to run REST server: " + err.Error()) + } + }() } diff --git a/model.go b/model.go new file mode 100644 index 0000000..2140a2d --- /dev/null +++ b/model.go @@ -0,0 +1,72 @@ +// Copyright (c) 2023 Cisco and/or its affiliates. +// +// Copyright (c) 2023 Pragmagic Inc. and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +// Node is a graphical model entity +type Node struct { + Data struct { + ID string `json:"id"` + Type NodeType `json:"type"` + Label string `json:"label"` + Parent string `json:"parent,omitempty"` + CustomData map[string]interface{} `json:"customData,omitempty"` + } `json:"data"` +} + +// Edge is a graphical model connection +type Edge struct { + Data struct { + ID string `json:"id"` + Type EdgeType `json:"type"` + Label string `json:"label,omitempty"` + Source string `json:"source"` + Target string `json:"target"` + Healthy bool `json:"healthy,omitempty"` + CustomData map[string]interface{} `json:"customData,omitempty"` + } `json:"data"` +} + +// NodeType is a Node entity type +type NodeType string + +const ( + clusterNT NodeType = "cluster" + interfaceNT NodeType = "interface" + clientNT NodeType = "client" + forwarderNT NodeType = "forwarder" + managerNT NodeType = "manager" + endpointNT NodeType = "endpoint" + serviceNT NodeType = "service" + // registryNT NodeType = "registry" +) + +// EdgeType is a connection type +type EdgeType string + +const ( + interfaceConnection EdgeType = "interfaceConnection" + interfaceCrossConnection EdgeType = "interfaceCrossConnection" + // serviceRequest EdgeType = "serviceRequest" + // registryRequest EdgeType = "registryRequest" +) + +const ( + clientInterface string = "client_interface" + serverInterface string = "server_interface" +) diff --git a/model_utils.go b/model_utils.go new file mode 100644 index 0000000..8f2e3a4 --- /dev/null +++ b/model_utils.go @@ -0,0 +1,258 @@ +// Copyright (c) 2023 Cisco and/or its affiliates. +// +// Copyright (c) 2023 Pragmagic Inc. and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "strings" + + "github.com/edwarnicke/genericsync" + + "github.com/networkservicemesh/api/pkg/api/networkservice" +) + +func updateStorage(nodes []Node, edges []Edge) { + storageData.Nodes = nodes + storageData.Edges = edges +} + +func addManagerConnection(mgr, conn string) { + if _, ok := managerConnections.Load(mgr); !ok { + managerConnections.Store(mgr, new(genericsync.Map[string, bool])) + } + conns, _ := managerConnections.Load(mgr) + conns.Store(conn, true) + managerConnections.Store(mgr, conns) +} + +func removeManagerConnection(mgr, conn string) { + if conns, ok := managerConnections.Load(mgr); ok { + conns.Delete(conn) + if isMapEmpty(conns) { + managerConnections.Delete(mgr) + } + } +} + +func parceConnectionsToGraphicalModel() { + nodeMap := make(map[string]Node) + var edges []Edge + + // Add local cluster node + var clusterLocal Node + if !isConnectionMapEmpty(&connections) { + clusterLocal = makeLocalCluster(nodeMap) + } + + connections.Range(func(connectionID string, conn *networkservice.Connection) bool { + healthy := conn.GetState() != networkservice.State_DOWN + + // Add Network Service Node + ns := makeNetworkService(nodeMap, conn.GetNetworkService(), clusterLocal.Data.ID) + + // Create all path segment nodes, interfaces and interface connections + pathSegments := conn.GetPath().GetPathSegments() + var previousInterfaceID string + for _, segment := range pathSegments { + segmentType := getPathSegmentType(segment.GetName()) + + // Add segment node + node := makeSegmentNode(nodeMap, segment.GetName(), clusterLocal.Data.ID, ns.Data.ID, segmentType) + + switch { + case segmentType == clientNT: + interfID := fmt.Sprintf("int-c--%s--%s", connectionID, node.Data.ID) + nodeMap[interfID] = makeInterface(interfID, node.Data.ID, getInterfaceLabelFromMetrics(segment, clientInterface)) + previousInterfaceID = interfID + case segmentType == endpointNT: + interfID := fmt.Sprintf("int-s--%s--%s", connectionID, node.Data.ID) + nodeMap[interfID] = makeInterface(interfID, node.Data.ID, getInterfaceLabelFromMetrics(segment, serverInterface)) + edges = addEdge(edges, previousInterfaceID, interfID, interfaceConnection, healthy) + case segmentType == forwarderNT: + interfCID := fmt.Sprintf("int-c--%s--%s", connectionID, node.Data.ID) + nodeMap[interfCID] = makeInterface(interfCID, node.Data.ID, getInterfaceLabelFromMetrics(segment, clientInterface)) + edges = addEdge(edges, previousInterfaceID, interfCID, interfaceConnection, healthy) + interfEID := fmt.Sprintf("int-s--%s--%s", connectionID, node.Data.ID) + nodeMap[interfEID] = makeInterface(interfEID, node.Data.ID, getInterfaceLabelFromMetrics(segment, serverInterface)) + edges = addEdge(edges, interfCID, interfEID, interfaceCrossConnection, healthy) + previousInterfaceID = interfEID + // TODO Aggregate statistics for the Overview page + } + } + return true + }) + + edges = addInternalNSEInterfaceConnections(edges, nodeMap) + + updateStorage(mapToArray(nodeMap), edges) +} + +func addInternalNSEInterfaceConnections(edges []Edge, nodeMap map[string]Node) []Edge { + var endpoints []Node + for _, node := range nodeMap { + if node.Data.Type == endpointNT { + endpoints = append(endpoints, node) + } + } + for _, nse := range endpoints { + var interfaces []Node + for _, node := range nodeMap { + if node.Data.Parent == nse.Data.ID { + interfaces = append(interfaces, node) + } + } + if len(interfaces) > 1 { + for i := 0; i < len(interfaces)-1; i++ { + for j := i + 1; j < len(interfaces)-1; j++ { + edges = addEdge(edges, interfaces[i].Data.ID, interfaces[j].Data.ID, interfaceCrossConnection, true) + } + } + } + } + return edges +} + +func makeLocalCluster(nodeMap map[string]Node) Node { + clusterLocal := Node{} + clusterLocalName := "cluster-local" + clusterLocal.Data.ID = clusterLocalName + clusterLocal.Data.Type = clusterNT + clusterLocal.Data.Label = clusterLocalName + nodeMap[clusterLocal.Data.ID] = clusterLocal + return clusterLocal +} + +func makeNetworkService(nodeMap map[string]Node, id, parentID string) Node { + ns := Node{} + ns.Data.ID = id + if !duplicateNodeExists(nodeMap, ns.Data.ID) { + ns.Data.Type = serviceNT + ns.Data.Label = id + ns.Data.Parent = parentID + nodeMap[ns.Data.ID] = ns + } + return ns +} + +func makeSegmentNode(nodeMap map[string]Node, id, parentID, nsID string, segmentType NodeType) Node { + node := Node{} + node.Data.ID = id + if !duplicateNodeExists(nodeMap, node.Data.ID) { + node.Data.Type = segmentType + node.Data.Parent = parentID + if node.Data.Type == endpointNT { + node.Data.CustomData = make(map[string]interface{}) + node.Data.CustomData["networkService"] = nsID + } + node.Data.Label = id + nodeMap[node.Data.ID] = node + } + return node +} + +func makeInterface(id, parentID, label string) Node { + interf := Node{} + interf.Data.ID = id + interf.Data.Type = interfaceNT + interf.Data.Parent = parentID + interf.Data.Label = label + return interf +} + +func addEdge(edges []Edge, sourceID, targetID string, edgeType EdgeType, healthy bool) []Edge { + edge := Edge{} + edge.Data.ID = fmt.Sprintf("conn--%s--%s", sourceID, targetID) + edge.Data.Type = edgeType + edge.Data.Source = sourceID + edge.Data.Target = targetID + edge.Data.Healthy = healthy + return append(edges, edge) +} + +func getInterfaceLabelFromMetrics(segment *networkservice.PathSegment, interfaceType string) string { + metrics := segment.GetMetrics() + if metrics != nil && metrics[interfaceType] != "" { + return metrics[interfaceType] + } + return "unknown" +} + +func duplicateNodeExists(nodeMap map[string]Node, id string) bool { + if _, exists := nodeMap[id]; exists { + return true + } + return false +} + +func mapToArray(nodeMap map[string]Node) []Node { + nodes := make([]Node, 0, len(nodeMap)) + for _, node := range nodeMap { + nodes = append(nodes, node) + } + return nodes +} + +func getPathSegmentType(name string) NodeType { + switch { + case strings.HasPrefix(name, "nsmgr-"): + return managerNT + case strings.HasPrefix(name, "forwarder-") || strings.HasPrefix(name, "fwd-"): + return forwarderNT + case strings.HasPrefix(name, "nse-"): + return endpointNT + default: + return clientNT + } +} + +func generateConnectionID(connection *networkservice.Connection) string { + ids := "" + for _, segment := range connection.GetPath().GetPathSegments() { + ids += segment.GetId() + } + return generateHash(ids) +} + +func generateHash(input string) string { + hasher := sha256.New() + hasher.Write([]byte(input)) + hashBytes := hasher.Sum(nil) + hash := hex.EncodeToString(hashBytes) + return hash +} + +func isMapEmpty[K string, V any](m *genericsync.Map[K, V]) bool { + isEmpty := true + m.Range(func(k K, v V) bool { + isEmpty = false + return false + }) + return isEmpty +} + +func isConnectionMapEmpty[K string, V *networkservice.Connection](m *genericsync.Map[K, V]) bool { + isEmpty := true + m.Range(func(k K, v V) bool { + isEmpty = false + return false + }) + return isEmpty +} diff --git a/storage.go b/storage.go new file mode 100644 index 0000000..706ca3f --- /dev/null +++ b/storage.go @@ -0,0 +1,36 @@ +// Copyright (c) 2023 Cisco and/or its affiliates. +// +// Copyright (c) 2023 Pragmagic Inc. and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/edwarnicke/genericsync" + + "github.com/networkservicemesh/api/pkg/api/networkservice" +) + +// StorageData is a current graphical model state +type StorageData struct { + Nodes []Node + Edges []Edge +} + +var storageData StorageData +var connections genericsync.Map[string, *networkservice.Connection] +var managerConnections genericsync.Map[string, *genericsync.Map[string, bool]] +var nsmgrs genericsync.Map[string, bool]