From ab7a1683f2a60f9d365bc810fdfddc245a0f59ab Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Thu, 1 Feb 2024 12:59:23 +0100 Subject: [PATCH 01/31] Upgrade dependencies Submodule: github.com/googleapis/googleapis fd52f71f4842399b922ba14b3ff0205b669cdedf Direct: github.com/google/uuid v1.6.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 github.com/nats-io/nats.go v1.32.0 github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2 github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 go.opentelemetry.io/otel v1.22.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 go.opentelemetry.io/otel/metric v1.22.0 go.opentelemetry.io/otel/sdk v1.22.0 go.opentelemetry.io/otel/trace v1.22.0 golang.org/x/exp v0.0.0-20240119083558-1b970713d09a google.golang.org/api v0.161.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe google.golang.org/grpc v1.61.0 Indirect: cloud.google.com/go/compute v1.23.4 github.com/bufbuild/protocompile v0.8.0 github.com/jhump/protoreflect v1.15.6 github.com/klauspost/compress v1.17.5 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 go.opentelemetry.io/proto/otlp v1.1.0 google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe --- dependency/googleapis | 2 +- go.mod | 52 ++++++++++---------- go.sum | 112 ++++++++++++++++++++---------------------- 3 files changed, 81 insertions(+), 85 deletions(-) diff --git a/dependency/googleapis b/dependency/googleapis index 29fdc0036..fd52f71f4 160000 --- a/dependency/googleapis +++ b/dependency/googleapis @@ -1 +1 @@ -Subproject commit 29fdc0036ce62452d188c5a246aa4664ef9cc4a3 +Subproject commit fd52f71f4842399b922ba14b3ff0205b669cdedf diff --git a/go.mod b/go.mod index a6ea7a963..7ccf6d7d0 100644 --- a/go.mod +++ b/go.mod @@ -13,23 +13,23 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.0 github.com/golang/snappy v0.0.4 github.com/google/go-querystring v1.1.0 - github.com/google/uuid v1.5.0 + github.com/google/uuid v1.6.0 github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 - github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 github.com/hashicorp/go-multierror v1.1.1 github.com/jessevdk/go-flags v1.5.0 github.com/json-iterator/go v1.1.12 github.com/jtacoma/uritemplates v1.0.0 github.com/karrick/tparse/v2 v2.8.2 github.com/lestrrat-go/jwx/v2 v2.0.19 - github.com/nats-io/nats.go v1.31.0 + github.com/nats-io/nats.go v1.32.0 github.com/panjf2000/ants/v2 v2.9.0 - github.com/pion/dtls/v2 v2.2.8-0.20240102042511-9ffd96c827fe + github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.2.5-0.20240112105119-e165727b7d41 - github.com/plgd-dev/go-coap/v3 v3.3.1 + github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2 + github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 github.com/sirupsen/logrus v1.9.3 @@ -39,35 +39,35 @@ require ( github.com/ugorji/go/codec v1.2.12 github.com/vincent-petithory/dataurl v1.0.0 go.mongodb.org/mongo-driver v1.13.1 - go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.46.1 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 - go.opentelemetry.io/otel v1.21.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 - go.opentelemetry.io/otel/metric v1.21.0 - go.opentelemetry.io/otel/sdk v1.21.0 - go.opentelemetry.io/otel/trace v1.21.0 + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 + go.opentelemetry.io/otel v1.22.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 + go.opentelemetry.io/otel/metric v1.22.0 + go.opentelemetry.io/otel/sdk v1.22.0 + go.opentelemetry.io/otel/trace v1.22.0 go.uber.org/atomic v1.11.0 go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e + golang.org/x/exp v0.0.0-20240119083558-1b970713d09a golang.org/x/net v0.20.0 golang.org/x/oauth2 v0.16.0 golang.org/x/sync v0.6.0 - google.golang.org/api v0.156.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 - google.golang.org/grpc v1.60.1 + google.golang.org/api v0.161.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe + google.golang.org/grpc v1.61.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute v1.23.4 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/sprig v2.15.0+incompatible // indirect github.com/aokoli/goutils v1.0.1 // indirect - github.com/bufbuild/protocompile v0.7.1 // indirect + github.com/bufbuild/protocompile v0.8.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -87,8 +87,8 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/huandu/xstrings v1.0.0 // indirect github.com/imdario/mergo v0.3.4 // indirect - github.com/jhump/protoreflect v1.15.4 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/jhump/protoreflect v1.15.6 // indirect + github.com/klauspost/compress v1.17.5 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.4 // indirect @@ -113,15 +113,15 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 // indirect - go.opentelemetry.io/proto/otlp v1.0.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/sys v0.16.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 // indirect + google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) diff --git a/go.sum b/go.sum index 3a6e81a7e..c1f0bc4da 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= 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= @@ -16,8 +16,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYE github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bufbuild/protocompile v0.7.1 h1:Kd8fb6EshOHXNNRtYAmLAwy/PotlyFoN0iMbuwGNh0M= -github.com/bufbuild/protocompile v0.7.1/go.mod h1:+Etjg4guZoAqzVk2czwEQP12yaxLJ8DxuqCJ9qHdH94= +github.com/bufbuild/protocompile v0.8.0 h1:9Kp1q6OkS9L4nM3FYbr8vlJnEwtbpDPQlQOVXfR+78s= +github.com/bufbuild/protocompile v0.8.0/go.mod h1:+Etjg4guZoAqzVk2czwEQP12yaxLJ8DxuqCJ9qHdH94= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= 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= @@ -25,7 +25,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA 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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= 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= @@ -123,8 +123,8 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= @@ -139,8 +139,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDa github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -159,8 +159,8 @@ github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSl github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= -github.com/jhump/protoreflect v1.15.4 h1:mrwJhfQGGljwvR/jPEocli8KA6G9afbQpH8NY2wORcI= -github.com/jhump/protoreflect v1.15.4/go.mod h1:2B+zwrnMY3TTIqEK01OG/d3pyUycQBfDf+bx8fE2DNg= +github.com/jhump/protoreflect v1.15.6 h1:WMYJbw2Wo+KOWwZFvgY0jMoVHM6i4XIvRs2RcBj5VmI= +github.com/jhump/protoreflect v1.15.6/go.mod h1:jCHoyYQIJnaabEYnbGwyo9hUqfyUMTbJw/tAut5t97E= 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/jtacoma/uritemplates v1.0.0 h1:xwx5sBF7pPAb0Uj8lDC1Q/aBPpOFyQza7OC705ZlLCo= @@ -174,8 +174,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= +github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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= @@ -212,8 +212,8 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 h1:28i1IjGcx8AofiB4N3q5Yls55VEaitzuEPkFJEVgGkA= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= -github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= -github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0= +github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -225,8 +225,8 @@ github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnl github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pion/dtls/v2 v2.0.1-0.20200503085337-8e86b3a7d585/go.mod h1:/GahSOC8ZY/+17zkaGJIG4OUkSGAcZu/N/g3roBOCkM= github.com/pion/dtls/v2 v2.0.10-0.20210502094952-3dc563b9aede/go.mod h1:86wv5dgx2J/z871nUR+5fTTY9tISLUlo+C5Gm86r1Hs= -github.com/pion/dtls/v2 v2.2.8-0.20240102042511-9ffd96c827fe h1:irKb6v72GiA86l+Tp0UZjSZqiOj8LwFxBDvzkhmoO/w= -github.com/pion/dtls/v2 v2.2.8-0.20240102042511-9ffd96c827fe/go.mod h1:eWsePf7yhHNQGu6UKU6xs2XMUYpHX2uqqvyZhNB6ooA= +github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 h1:r7K+oQUYubeA0am08kTAvd2wT2D8PZggs/CpMGp0nkM= +github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8/go.mod h1:/gft3czh67pwl4nM1BBUvF7eTy72uGkObJXOYfxRDbA= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= @@ -238,12 +238,12 @@ github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.2.5-0.20240112105119-e165727b7d41 h1:1oTDtgAjVkeOX63MzvdiB/kx2RS1UYOtQMs6ywNejvA= -github.com/plgd-dev/device/v2 v2.2.5-0.20240112105119-e165727b7d41/go.mod h1:US5p507VILktZa6Ep77gTEqwY8F+IbVUmtbt5aTtdlI= +github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2 h1:JmrEO6lBnrbBEF5+zK4rzWyzi7sbBoWqcf1yb9YTrxo= +github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2/go.mod h1:Ih+RlLSenRpRSVbd07VBEbOVNwlOkefkBnoJra6L+bU= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= -github.com/plgd-dev/go-coap/v3 v3.3.1 h1:oxVnn5MAOEWImoGgoG5S0grTXQXqhNu5gQqW7zMPu40= -github.com/plgd-dev/go-coap/v3 v3.3.1/go.mod h1:r3KbxxpBgOPmC0fh6y0yUrDvJh3LdCrhD2zdRr0L1j4= +github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f h1:pVQdfS93HKSqHMNIH4JJcz2lUl/mgoZ6FOjQQDcTPMM= +github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f/go.mod h1:Pac6EsvakCrwCaZGk7YkbecVLnDYRauEt4ULvYRw5Dk= github.com/plgd-dev/kit v0.0.0-20200819113605-d5fcf3e94f63/go.mod h1:Yl9zisyXfPdtP9hTWlJqjJYXmgU/jtSDKttz9/CeD90= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 h1:TC1HJ/UbyflJFPvaOdGmNZ5TeFGex1/dyr9urNGLy7M= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSGQjdi8eInxwFCs0tSApuEM1o0qNck+sJYp4M= @@ -318,26 +318,26 @@ go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/ go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.46.1 h1:C6OqX3inTcc1vUX2BL7Au7cQO20/0fCI02XdInR8m5Y= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.46.1/go.mod h1:M9ZtzJcGI4ejexSjUP69JmhbzAe93mu2xUBH3QBUtLM= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0 h1:cl5P5/GIfFh4t6xyruOgJP5QiA1pw4fYYdv6nc6CBWw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.21.0/go.mod h1:zgBdWWAu7oEEMC06MMKc5NLbA/1YDXV1sMpSqEeLQLg= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8= -go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= -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.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0 h1:1ahNAu2+hiHJOXd9J8hQ1zSGxEYHy7sn1ozpL50YWZY= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0/go.mod h1:VEW8hmKJJZg+c3lfqHhxqa0BYg2PEUyNRehU5D2yBDw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= +go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= +go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -368,13 +368,11 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e h1:723BNChdd0c2Wk6WOE320qGBiPtYx0F0Bbm1kriShfE= -golang.org/x/exp v0.0.0-20240110193028-0dcbfd608b1e/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= +golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= 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= @@ -409,7 +407,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -446,7 +443,6 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -454,7 +450,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -488,8 +484,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.156.0 h1:yloYcGbBtVYjLKQe4enCunxvwn3s2w/XPrrhVf6MsvQ= -google.golang.org/api v0.156.0/go.mod h1:bUSmn4KFO0Q+69zo9CNIDp4Psi6BqM0np0CbzKRSiSY= +google.golang.org/api v0.161.0 h1:oYzk/bs26WN10AV7iU7MVJVXBH8oCPS2hHyBiEeFoSU= +google.golang.org/api v0.161.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -499,12 +495,12 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= -google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1 h1:OPXtXn7fNMaXwO3JvOmF1QyTc00jsSFFz1vXXBOdCDo= -google.golang.org/genproto/googleapis/api v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:B5xPO//w8qmBDjGReYLpR6UJPnkldGkCSMoH/2vxJeg= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 h1:gphdwh0npgs8elJ4T6J+DQJHPVF7RsuJHCfwztUb4J4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= 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= @@ -512,8 +508,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From b689d68e23159e4af088d4b2ddabf0f6bdc0435a Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Thu, 1 Feb 2024 16:33:49 +0100 Subject: [PATCH 02/31] Upgrade depedencies github.com/go-co-op/gocron: v1 -> v2 --- .../service/cleanDatabase_test.go | 2 + certificate-authority/service/config.go | 24 ++- certificate-authority/service/config_test.go | 203 ++++++++++++++++++ certificate-authority/service/service.go | 26 +-- certificate-authority/service/service_test.go | 38 ---- go.mod | 3 +- go.sum | 16 +- 7 files changed, 238 insertions(+), 74 deletions(-) create mode 100644 certificate-authority/service/config_test.go delete mode 100644 certificate-authority/service/service_test.go diff --git a/certificate-authority/service/cleanDatabase_test.go b/certificate-authority/service/cleanDatabase_test.go index 529c983cd..acdb91ad5 100644 --- a/certificate-authority/service/cleanDatabase_test.go +++ b/certificate-authority/service/cleanDatabase_test.go @@ -3,6 +3,7 @@ package service_test import ( "context" "errors" + "fmt" "io" "testing" "time" @@ -26,6 +27,7 @@ func TestCertificateAuthorityServerCleanUpSigningRecords(t *testing.T) { cfg := test.MakeConfig(t) cfg.Clients.Storage.ExtendCronParserBySeconds = true cfg.Clients.Storage.CleanUpRecords = "*/1 * * * * *" + fmt.Printf("%v\n\n", test.MakeConfig(t)) shutDown := testService.SetUpServices(context.Background(), t, testService.SetUpServicesCertificateAuthority|testService.SetUpServicesOAuth, testService.WithCAConfig(cfg)) defer shutDown() diff --git a/certificate-authority/service/config.go b/certificate-authority/service/config.go index a9583fe47..8e9f2f5d1 100644 --- a/certificate-authority/service/config.go +++ b/certificate-authority/service/config.go @@ -5,7 +5,7 @@ import ( "net" "time" - gocron "github.com/go-co-op/gocron" + "github.com/go-co-op/gocron/v2" "github.com/google/uuid" grpcService "github.com/plgd-dev/hub/v2/certificate-authority/service/grpc" storeConfig "github.com/plgd-dev/hub/v2/certificate-authority/store/config" @@ -89,20 +89,22 @@ func (c *StorageConfig) Validate() error { if c.CleanUpRecords == "" { return nil } - s := gocron.NewScheduler(time.Local) - if c.ExtendCronParserBySeconds { - s = s.CronWithSeconds(c.CleanUpRecords) - } else { - s = s.Cron(c.CleanUpRecords) + s, err := gocron.NewScheduler(gocron.WithLocation(time.Local)) + if err != nil { + return fmt.Errorf("cannot create cron job: %w", err) } - _, err := s.Do(func() { - // do nothing - }) + defer func() { + if errS := s.Shutdown(); errS != nil { + log.Errorf("failed to shutdown cron job: %w", errS) + } + }() + _, err = s.NewJob(gocron.CronJob(c.CleanUpRecords, c.ExtendCronParserBySeconds), + gocron.NewTask(func() { + // do nothing + })) if err != nil { return fmt.Errorf("cleanUpRecords('%v') - %w", c.CleanUpRecords, err) } - s.Clear() - s.Stop() return nil } diff --git a/certificate-authority/service/config_test.go b/certificate-authority/service/config_test.go new file mode 100644 index 000000000..58427612d --- /dev/null +++ b/certificate-authority/service/config_test.go @@ -0,0 +1,203 @@ +// ************************************************************************ +// Copyright (C) 2022 plgd.dev, s.r.o. +// +// 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 service_test + +import ( + "testing" + + "github.com/plgd-dev/hub/v2/certificate-authority/service" + "github.com/plgd-dev/hub/v2/certificate-authority/test" + "github.com/stretchr/testify/require" +) + +func TestConfigValidate(t *testing.T) { + type args struct { + cfg service.Config + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.Clients.Storage.ExtendCronParserBySeconds = true + c.Clients.Storage.CleanUpRecords = "*/1 * * * * *" + return c + }(), + }, + }, + { + name: "invalid log config", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.Log.Level = 42 + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid grpc api config", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.APIs.GRPC.Addr = "invalid" + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid http api config", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.APIs.HTTP.Addr = "invalid" + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid signer config", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.Signer.CAPool = 42 + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid clients storage config", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.Clients.Storage.CleanUpRecords = "invalid" + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid clients telemetry config", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.Clients.OpenTelemetryCollector.GRPC.Enabled = true + c.Clients.OpenTelemetryCollector.GRPC.Connection.Addr = "" + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid hubID", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.HubID = "invalid" + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid signer", + args: args{ + cfg: func() service.Config { + c := test.MakeConfig(t) + c.Signer.CertFile = "invalid" + return c + }(), + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.args.cfg.Validate() + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} + +func TestStorageConfigValidate(t *testing.T) { + type args struct { + cfg service.StorageConfig + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "valid - disabled", + args: args{ + cfg: func() service.StorageConfig { + c := test.MakeStorageConfig() + c.CleanUpRecords = "" + return c + }(), + }, + }, + { + name: "invalid", + args: args{ + cfg: func() service.StorageConfig { + c := test.MakeStorageConfig() + c.CleanUpRecords = "invalid" + return c + }(), + }, + wantErr: true, + }, + { + name: "invalid db", + args: args{ + cfg: func() service.StorageConfig { + c := test.MakeStorageConfig() + c.Embedded.Use = "invalid" + return c + }(), + }, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := tt.args.cfg.Validate() + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/certificate-authority/service/service.go b/certificate-authority/service/service.go index 5312aa732..8aae3617d 100644 --- a/certificate-authority/service/service.go +++ b/certificate-authority/service/service.go @@ -6,7 +6,7 @@ import ( "fmt" "time" - gocron "github.com/go-co-op/gocron" + "github.com/go-co-op/gocron/v2" grpcService "github.com/plgd-dev/hub/v2/certificate-authority/service/grpc" httpService "github.com/plgd-dev/hub/v2/certificate-authority/service/http" "github.com/plgd-dev/hub/v2/certificate-authority/store" @@ -59,26 +59,28 @@ func newStore(ctx context.Context, config StorageConfig, fileWatcher *fsnotify.W if config.CleanUpRecords == "" { return db, fl.ToFunction(), nil } - s := gocron.NewScheduler(time.Local) - if config.ExtendCronParserBySeconds { - s = s.CronWithSeconds(config.CleanUpRecords) - } else { - s = s.Cron(config.CleanUpRecords) + s, err := gocron.NewScheduler(gocron.WithLocation(time.Local)) + if err != nil { + fl.Execute() + return nil, nil, fmt.Errorf("cannot create cron job: %w", err) } - _, err = s.Do(func() { + + _, err = s.NewJob(gocron.CronJob(config.CleanUpRecords, config.ExtendCronParserBySeconds), gocron.NewTask(func() { _, errDel := db.DeleteNonDeviceExpiredRecords(ctx, time.Now()) if errDel != nil && !errors.Is(errDel, store.ErrNotSupported) { log.Errorf("failed to delete expired signing records: %w", errDel) } - }) + })) if err != nil { fl.Execute() return nil, nil, fmt.Errorf("cannot create cron job: %w", err) } - fl.AddFunc(s.Clear) - fl.AddFunc(s.Stop) - s.StartAsync() - + fl.AddFunc(func() { + if errS := s.Shutdown(); errS != nil { + log.Errorf("failed to shutdown cron job: %w", errS) + } + }) + s.Start() return db, fl.ToFunction(), nil } diff --git a/certificate-authority/service/service_test.go b/certificate-authority/service/service_test.go deleted file mode 100644 index 47f7b6d81..000000000 --- a/certificate-authority/service/service_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// ************************************************************************ -// Copyright (C) 2022 plgd.dev, s.r.o. -// -// 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 service_test - -import ( - "context" - "fmt" - "testing" - - "github.com/plgd-dev/hub/v2/certificate-authority/test" - testService "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/require" -) - -func TestServiceServe(t *testing.T) { - fmt.Printf("%v\n\n", test.MakeConfig(t)) - - shutDown := testService.SetUpServices(context.Background(), t, testService.SetUpServicesCertificateAuthority|testService.SetUpServicesOAuth) - defer shutDown() - - cfg := test.MakeConfig(t) - cfg.Clients.Storage.CleanUpRecords = "/2 * * * *" - require.Error(t, cfg.Validate()) -} diff --git a/go.mod b/go.mod index 7ccf6d7d0..5add27db3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/fullstorydev/grpchan v1.1.1 github.com/fxamacker/cbor/v2 v2.5.0 - github.com/go-co-op/gocron v1.37.0 + github.com/go-co-op/gocron/v2 v2.2.2 github.com/gocql/gocql v1.6.0 github.com/golang-jwt/jwt/v5 v5.2.0 github.com/golang/snappy v0.0.4 @@ -88,6 +88,7 @@ require ( github.com/huandu/xstrings v1.0.0 // indirect github.com/imdario/mergo v0.3.4 // indirect github.com/jhump/protoreflect v1.15.6 // indirect + github.com/jonboulle/clockwork v0.4.0 // indirect github.com/klauspost/compress v1.17.5 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect diff --git a/go.sum b/go.sum index c1f0bc4da..489184b8c 100644 --- a/go.sum +++ b/go.sum @@ -26,7 +26,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= -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= @@ -57,8 +56,8 @@ github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= -github.com/go-co-op/gocron v1.37.0 h1:ZYDJGtQ4OMhTLKOKMIch+/CY70Brbb1dGdooLEhh7b0= -github.com/go-co-op/gocron v1.37.0/go.mod h1:3L/n6BkO7ABj+TrfSVXLRzsP26zmikL4ISkLQ0O8iNY= +github.com/go-co-op/gocron/v2 v2.2.2 h1:XgQIiocDrdSX/B2AICR0FWk4ZeyJzeK5LVmLRoou3F0= +github.com/go-co-op/gocron/v2 v2.2.2/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -122,7 +121,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= @@ -161,6 +159,8 @@ github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7 github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= github.com/jhump/protoreflect v1.15.6 h1:WMYJbw2Wo+KOWwZFvgY0jMoVHM6i4XIvRs2RcBj5VmI= github.com/jhump/protoreflect v1.15.6/go.mod h1:jCHoyYQIJnaabEYnbGwyo9hUqfyUMTbJw/tAut5t97E= +github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= +github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= 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/jtacoma/uritemplates v1.0.0 h1:xwx5sBF7pPAb0Uj8lDC1Q/aBPpOFyQza7OC705ZlLCo= @@ -179,13 +179,10 @@ github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6K github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= @@ -235,7 +232,6 @@ github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZ github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2 h1:JmrEO6lBnrbBEF5+zK4rzWyzi7sbBoWqcf1yb9YTrxo= @@ -257,8 +253,6 @@ github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3 github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= @@ -341,7 +335,6 @@ go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7e go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= @@ -529,7 +522,6 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= From 4c4861a4bc483ba4080a1d448063da392eff4026 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 23 Jan 2024 16:52:16 +0100 Subject: [PATCH 03/31] Add support for testing of a bridged device --- .vscode/settings.json | 10 +- .../service/subscribeToDevice_test.go | 4 +- .../service/devicesStatusUpdater_test.go | 17 +- .../observation/deviceObserver_test.go | 12 +- go.mod | 2 +- go.sum | 4 +- .../service/getResourceFromDevice_test.go | 3 +- test/cloud-server/Dockerfile | 9 + test/cloud-server/run.sh | 324 ++++++++++-------- test/device/bridge/device.go | 71 ++++ test/device/device.go | 157 +++++++++ test/device/ocf/device.go | 129 +++++++ .../service/deleteResource_test.go | 7 +- test/iotivity-lite/service/offboard_test.go | 63 ++-- test/iotivity-lite/service/republish_test.go | 6 +- test/{sdkclient.go => sdk/client.go} | 13 +- test/test.go | 293 ++++++---------- 17 files changed, 726 insertions(+), 398 deletions(-) create mode 100644 test/device/bridge/device.go create mode 100644 test/device/device.go create mode 100644 test/device/ocf/device.go rename test/{sdkclient.go => sdk/client.go} (95%) diff --git a/.vscode/settings.json b/.vscode/settings.json index 1eb846981..b9dead665 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,14 +27,16 @@ "TEST_MEMORY_COAP_GATEWAY_EXPECTED_RSS_IN_MB": "1000", "TEST_MEMORY_COAP_GATEWAY_RESOURCE_DATA_SIZE": "200", "TEST_COAP_GATEWAY_LOG_LEVEL": "info", - "TEST_COAP_GATEWAY_LOG_DUMP_BODY": "false", + "TEST_COAP_GATEWAY_LOG_DUMP_BODY": "false", "TEST_RESOURCE_AGGREGATE_LOG_LEVEL": "info", - "TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY": "false", + "TEST_RESOURCE_AGGREGATE_LOG_DUMP_BODY": "false", "TEST_GRPC_GATEWAY_LOG_LEVEL": "info", - "TEST_GRPC_GATEWAY_LOG_DUMP_BODY": "false", + "TEST_GRPC_GATEWAY_LOG_DUMP_BODY": "false", "TEST_IDENTITY_STORE_LOG_LEVEL": "info", - "TEST_IDENTITY_STORE_LOG_DUMP_BODY": "false", + "TEST_IDENTITY_STORE_LOG_DUMP_BODY": "false", "TEST_DATABASE": "mongoDB", + // "TEST_DEVICE_NAME": "bridged-device", + // "TEST_DEVICE_TYPE": "bridged", // "GODEBUG": "scavtrace=1", // "TEST_COAP_GATEWAY_UDP_ENABLED": "true", // "GOMAXPROCS": 1, diff --git a/cloud2cloud-gateway/service/subscribeToDevice_test.go b/cloud2cloud-gateway/service/subscribeToDevice_test.go index 45e4bfd6e..8540c2887 100644 --- a/cloud2cloud-gateway/service/subscribeToDevice_test.go +++ b/cloud2cloud-gateway/service/subscribeToDevice_test.go @@ -66,7 +66,7 @@ func TestRequestHandlerSubscribeToDevicePublishedOnly(t *testing.T) { subID := subscriber.Subscribe(ctx, t, token, deviceID, "", c2cEvents.EventTypes{c2cEvents.EventType_ResourcesPublished}) ev := <-dataChan - publishedResources := test.ResourceLinksToResources(deviceID, test.TestDevsimResources) + publishedResources := test.ResourceLinksToResources(deviceID, test.GetAllBackendResourceLinks()) assert.Equal(t, c2cEvents.EventType_ResourcesPublished, ev.GetHeader().EventType) links := ev.GetData().(schema.ResourceLinks) resources := testSubscribeToDeviceDecodeResources(links) @@ -118,7 +118,7 @@ func TestRequestHandlerSubscribeToDevice(t *testing.T) { require.Len(t, events, 2) for _, ev := range events { if ev.GetHeader().EventType == c2cEvents.EventType_ResourcesPublished { - publishedResources := test.ResourceLinksToResources(deviceID, test.TestDevsimResources) + publishedResources := test.ResourceLinksToResources(deviceID, test.GetAllBackendResourceLinks()) links := ev.GetData().(schema.ResourceLinks) resources := testSubscribeToDeviceDecodeResources(links) test.CheckProtobufs(t, publishedResources, resources, test.RequireToCheckFunc(require.Equal)) diff --git a/coap-gateway/service/devicesStatusUpdater_test.go b/coap-gateway/service/devicesStatusUpdater_test.go index 4948dcc90..3caf0391e 100644 --- a/coap-gateway/service/devicesStatusUpdater_test.go +++ b/coap-gateway/service/devicesStatusUpdater_test.go @@ -1,5 +1,5 @@ -//go:build test -// +build test +//go:build test || device_integration +// +build test device_integration package service_test @@ -18,6 +18,7 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/commands" test "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" + "github.com/plgd-dev/hub/v2/test/device" oauthService "github.com/plgd-dev/hub/v2/test/oauth-server/service" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" @@ -27,7 +28,7 @@ import ( "google.golang.org/grpc/credentials" ) -func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, deviceID string, oauthCfg oauthService.Config, coapCfg coapService.Config) (*pb.Device, time.Time /*startOnboard*/, time.Duration /*delta*/) { +func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device.Device, oauthCfg oauthService.Config, coapCfg coapService.Config) (*pb.Device, time.Time /*startOnboard*/, time.Duration /*delta*/) { tearDown := service.SetUp(ctx, t, service.WithOAuthConfig(oauthCfg), service.WithCOAPGWConfig(coapCfg)) defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) @@ -42,7 +43,7 @@ func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, deviceID strin c := pb.NewGrpcGatewayClient(conn) startOnboard := time.Now() - _, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) + shutdownDevSim := test.OnboardDevice(ctx, t, c, device, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, device.GetDefaultResources()) defer shutdownDevSim() deltaOnboard := time.Since(startOnboard) / 2 @@ -67,7 +68,7 @@ func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, deviceID strin } func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasNoExpiration(t *testing.T) { - deviceID := test.MustFindDeviceByName(test.TestDeviceName) + d := test.MustFindTestDevice() ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) defer cancel() @@ -75,13 +76,13 @@ func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasNoExpiration(t *test oauthCfg.OAuthSigner.Clients.Find(config.OAUTH_MANAGER_CLIENT_ID).AccessTokenLifetime = 0 coapCfg := coapgwTest.MakeConfig(t) - device, _, _ := onboardDeviceAndGetDevice(ctx, t, deviceID, oauthCfg, coapCfg) + device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg) assert.Equal(t, commands.Connection_ONLINE, device.Metadata.Connection.Status) } func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasExpiration(t *testing.T) { - deviceID := test.MustFindDeviceByName(test.TestDeviceName) + d := test.MustFindTestDevice() ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) defer cancel() @@ -90,7 +91,7 @@ func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasExpiration(t *testin oauthCfg.OAuthSigner.Clients.Find(config.OAUTH_MANAGER_CLIENT_ID).AccessTokenLifetime = accessTokenLifetime coapCfg := coapgwTest.MakeConfig(t) - device, _, _ := onboardDeviceAndGetDevice(ctx, t, deviceID, oauthCfg, coapCfg) + device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg) assert.Equal(t, commands.Connection_ONLINE, device.Metadata.Connection.Status) } diff --git a/coap-gateway/service/observation/deviceObserver_test.go b/coap-gateway/service/observation/deviceObserver_test.go index 31f4d9342..90f5d300d 100644 --- a/coap-gateway/service/observation/deviceObserver_test.go +++ b/coap-gateway/service/observation/deviceObserver_test.go @@ -198,19 +198,19 @@ func TestDeviceObserverRegisterForPublishedResources(t *testing.T) { require.Equal(t, observation.ObservationType_PerResource, obs.GetObservationType()) res, err := obs.GetResources() require.NoError(t, err) - pbTest.CmpResourceIds(t, test.ResourceLinksToResourceIds(deviceID, test.TestDevsimResources), res) + pbTest.CmpResourceIds(t, test.ResourceLinksToResourceIds(deviceID, test.GetAllBackendResourceLinks()), res) } expectedObserved := strings.MakeSet() for _, resID := range test.ResourceLinksToResourceIds(deviceID, test.FilterResourceLink(func(rl schema.ResourceLink) bool { return rl.Policy.BitMask.Has(schema.Observable) - }, test.TestDevsimResources)) { + }, test.GetAllBackendResourceLinks())) { expectedObserved.Add(resID.ToString()) } expectedRetrieved := strings.MakeSet() for _, resID := range test.ResourceLinksToResourceIds(deviceID, test.FilterResourceLink(func(rl schema.ResourceLink) bool { return !rl.Policy.BitMask.Has(schema.Observable) - }, test.TestDevsimResources)) { + }, test.GetAllBackendResourceLinks())) { expectedRetrieved.Add(resID.ToString()) } runTestDeviceObserverRegister(ctx, t, deviceID, expectedObserved, expectedRetrieved, validateData, nil, nil, false) @@ -230,19 +230,19 @@ func TestDeviceObserverRegisterForPublishedResourcesWithAlreadyPublishedResource require.Equal(t, observation.ObservationType_PerResource, obs.GetObservationType()) res, err := obs.GetResources() require.NoError(t, err) - pbTest.CmpResourceIds(t, test.ResourceLinksToResourceIds(deviceID, test.TestDevsimResources), res) + pbTest.CmpResourceIds(t, test.ResourceLinksToResourceIds(deviceID, test.GetAllBackendResourceLinks()), res) } expectedObserved := strings.MakeSet() for _, resID := range test.ResourceLinksToResourceIds(deviceID, test.FilterResourceLink(func(rl schema.ResourceLink) bool { return rl.Policy.BitMask.Has(schema.Observable) - }, test.TestDevsimResources)) { + }, test.GetAllBackendResourceLinks())) { expectedObserved.Add(resID.ToString()) } expectedRetrieved := strings.MakeSet() for _, resID := range test.ResourceLinksToResourceIds(deviceID, test.FilterResourceLink(func(rl schema.ResourceLink) bool { return !rl.Policy.BitMask.Has(schema.Observable) - }, test.TestDevsimResources)) { + }, test.GetAllBackendResourceLinks())) { expectedRetrieved.Add(resID.ToString()) } runTestDeviceObserverRegister(ctx, t, deviceID, expectedObserved, expectedRetrieved, validateData, testPreregisterVirtualDevice, testValidateResourceLinks, false) diff --git a/go.mod b/go.mod index 5add27db3..e5bca5a6d 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/panjf2000/ants/v2 v2.9.0 github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2 + github.com/plgd-dev/device/v2 v2.2.5-0.20240203174619-48d29f285e4f github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 diff --git a/go.sum b/go.sum index 489184b8c..3611611c6 100644 --- a/go.sum +++ b/go.sum @@ -234,8 +234,8 @@ github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9 github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2 h1:JmrEO6lBnrbBEF5+zK4rzWyzi7sbBoWqcf1yb9YTrxo= -github.com/plgd-dev/device/v2 v2.2.5-0.20240201132112-e22e783189d2/go.mod h1:Ih+RlLSenRpRSVbd07VBEbOVNwlOkefkBnoJra6L+bU= +github.com/plgd-dev/device/v2 v2.2.5-0.20240203174619-48d29f285e4f h1:fnjdDr3zDDCDw7KwCzDHtBTplV7vImLW88BJ6L1IcHk= +github.com/plgd-dev/device/v2 v2.2.5-0.20240203174619-48d29f285e4f/go.mod h1:bNW1Z70fOwogtFdc73ICv4kaQCtSHnFVpMbJaaG6Rtc= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f h1:pVQdfS93HKSqHMNIH4JJcz2lUl/mgoZ6FOjQQDcTPMM= diff --git a/grpc-gateway/service/getResourceFromDevice_test.go b/grpc-gateway/service/getResourceFromDevice_test.go index 27afd55df..6fe91fd56 100644 --- a/grpc-gateway/service/getResourceFromDevice_test.go +++ b/grpc-gateway/service/getResourceFromDevice_test.go @@ -24,6 +24,7 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" + "github.com/plgd-dev/hub/v2/test/sdk" "github.com/plgd-dev/hub/v2/test/service" "github.com/stretchr/testify/require" "google.golang.org/grpc" @@ -174,7 +175,7 @@ func TestRequestHandlerGetResourceFromDevice(t *testing.T) { } func validateETags(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, deviceID, href string) { - sdkClient, err := test.NewSDKClient() + sdkClient, err := sdk.NewClient() require.NoError(t, err) defer func() { diff --git a/test/cloud-server/Dockerfile b/test/cloud-server/Dockerfile index fa37f1da6..7c41522f6 100644 --- a/test/cloud-server/Dockerfile +++ b/test/cloud-server/Dockerfile @@ -18,6 +18,12 @@ ARG tool=cert-tool WORKDIR $root_directory/tools/$tool RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/cert-tool +#coap-gateway +#the "device_integration" tag should ensure that only integration tests with a device simulator are compiled +ARG service=coap-gateway +WORKDIR $root_directory/$service/service +RUN go test -p 1 -c -tags=device_integration -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/coap-gateway.test + #grpc-gateway ARG service=grpc-gateway WORKDIR $root_directory/$service/service @@ -60,6 +66,7 @@ RUN echo "deb [ arch=$(dpkg --print-architecture) ] https://repo.mongodb.org/apt RUN apt update && \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mongodb-org mongodb-org-server COPY --from=build /go/bin/cert-tool /usr/local/bin/cert-tool +COPY --from=build /go/bin/coap-gateway.test /usr/local/bin/coap-gateway.test COPY --from=build /go/bin/grpc-gateway.test /usr/local/bin/grpc-gateway.test COPY --from=build /go/bin/test-iotivity-lite.test /usr/local/bin/test-iotivity-lite.test COPY --from=build /go/bin/nats-server /usr/local/bin/nats-server @@ -68,6 +75,8 @@ COPY test/cloud-server/run.sh /usr/local/bin/run.sh # global ENV FQDN="localhost" +ENV PREPARE_ENV="true" +ENV RUN="true" # global - certificates generated by cert-tool ENV CERT_TOOL_SIGN_ALG=ECDSA-SHA256 diff --git a/test/cloud-server/run.sh b/test/cloud-server/run.sh index ad49eb459..a11d74811 100755 --- a/test/cloud-server/run.sh +++ b/test/cloud-server/run.sh @@ -6,119 +6,91 @@ umask 0000 # Configure services export PATH="/usr/local/bin:$PATH" -export COAP_GATEWAY_CLOUD_ID="adebc667-1f2b-41e3-bf5c-6d6eabc68cc6" +if [ -z "${COAP_GATEWAY_CLOUD_ID}" ]; then + COAP_GATEWAY_CLOUD_ID="adebc667-1f2b-41e3-bf5c-6d6eabc68cc6" +fi -export CERTIFICATES_PATH="/data/certs" -export OAUTH_KEYS_PATH="/data/oauth/keys" -export OAUTH_SECRETS_PATH="/data/oauth/secrets" -export LOGS_PATH="/data/log" -export MONGO_PATH="/data/db" +CERTIFICATES_PATH="/data/certs" +LOGS_PATH="/data/log" +MONGO_PATH="/data/db" -export INTERNAL_CERT_DIR_PATH="$CERTIFICATES_PATH/internal" -export GRPC_INTERNAL_CERT_NAME="endpoint.crt" -export GRPC_INTERNAL_CERT_KEY_NAME="endpoint.key" +INTERNAL_CERT_DIR_PATH="$CERTIFICATES_PATH/internal" +GRPC_INTERNAL_CERT_NAME="endpoint.crt" +GRPC_INTERNAL_CERT_KEY_NAME="endpoint.key" -export EXTERNAL_CERT_DIR_PATH="$CERTIFICATES_PATH/external" -export COAP_GATEWAY_FILE_CERT_NAME="coap-gateway.crt" -export COAP_GATEWAY_FILE_CERT_KEY_NAME="coap-gateway.key" +EXTERNAL_CERT_DIR_PATH="$CERTIFICATES_PATH/external" +COAP_GATEWAY_FILE_CERT_NAME="coap-gateway.crt" +COAP_GATEWAY_FILE_CERT_KEY_NAME="coap-gateway.key" # ROOT CERTS -export CA_POOL_DIR="$CERTIFICATES_PATH" -export CA_POOL_NAME_PREFIX="root_ca" -export CA_POOL_CERT_PATH="$CA_POOL_DIR/$CA_POOL_NAME_PREFIX.crt" -export CA_POOL_CERT_KEY_PATH="$CA_POOL_DIR/$CA_POOL_NAME_PREFIX.key" +CA_POOL_DIR="$CERTIFICATES_PATH" +CA_POOL_NAME_PREFIX="root_ca" +CA_POOL_CERT_PATH="$CA_POOL_DIR/$CA_POOL_NAME_PREFIX.crt" +CA_POOL_CERT_KEY_PATH="$CA_POOL_DIR/$CA_POOL_NAME_PREFIX.key" # DIAL CERTS -export DIAL_FILE_CA_POOL="$CA_POOL_CERT_PATH" -export DIAL_FILE_CERT_DIR_PATH="$INTERNAL_CERT_DIR_PATH" -export DIAL_FILE_CERT_NAME="$GRPC_INTERNAL_CERT_NAME" -export DIAL_FILE_CERT_KEY_NAME="$GRPC_INTERNAL_CERT_KEY_NAME" - -#LISTEN CERTS -export LISTEN_FILE_CA_POOL="$CA_POOL_CERT_PATH" -export LISTEN_FILE_CERT_DIR_PATH="$INTERNAL_CERT_DIR_PATH" -export LISTEN_FILE_CERT_NAME="$GRPC_INTERNAL_CERT_NAME" -export LISTEN_FILE_CERT_KEY_NAME="$GRPC_INTERNAL_CERT_KEY_NAME" - -#SECRETS -export SECRETS_DIRECTORY=/data/secrets - -#OAUTH-SEVER KEYS -export OAUTH_ID_TOKEN_KEY_PATH=${OAUTH_KEYS_PATH}/id-token.pem -export OAUTH_ACCESS_TOKEN_KEY_PATH=${OAUTH_KEYS_PATH}/access-token.pem - -export OAUTH_DEVICE_SECRET_PATH=${OAUTH_SECRETS_PATH}/device.secret - -#ENDPOINTS -export MONGODB_HOST="localhost:$MONGO_PORT" -export MONGODB_URI="mongodb://$MONGODB_HOST" -export NATS_HOST="localhost:$NATS_PORT" -export NATS_URL="nats://${NATS_HOST}" - -# needed by grpc-gateway.test -export TEST_COAP_GW_CERT_FILE="${EXTERNAL_CERT_DIR_PATH}/${COAP_GATEWAY_FILE_CERT_NAME}" -export TEST_COAP_GW_KEY_FILE="${EXTERNAL_CERT_DIR_PATH}/${COAP_GATEWAY_FILE_CERT_KEY_NAME}" -export TEST_ROOT_CA_CERT="${CA_POOL_CERT_PATH}" -export TEST_ROOT_CA_KEY="${CA_POOL_CERT_KEY_PATH}" -export TEST_CLOUD_SID="${COAP_GATEWAY_CLOUD_ID}" -export TEST_OAUTH_SERVER_ID_TOKEN_PRIVATE_KEY="${OAUTH_ID_TOKEN_KEY_PATH}" -export TEST_OAUTH_SERVER_ACCESS_TOKEN_PRIVATE_KEY="${OAUTH_ACCESS_TOKEN_KEY_PATH}" -export TEST_COAP_GATEWAY_UDP_ENABLED="${COAP_GATEWAY_UDP_ENABLED}" - -mkdir -p ${OAUTH_SECRETS_PATH} -if [ -z "${OAUTH_CLIENT_SECRET}" ] -then - export OAUTH_CLIENT_SECRET="secret" -fi -echo -n ${OAUTH_CLIENT_SECRET} > ${OAUTH_DEVICE_SECRET_PATH} +DIAL_FILE_CERT_DIR_PATH="$INTERNAL_CERT_DIR_PATH" +DIAL_FILE_CERT_NAME="$GRPC_INTERNAL_CERT_NAME" +DIAL_FILE_CERT_KEY_NAME="$GRPC_INTERNAL_CERT_KEY_NAME" -mkdir -p $CA_POOL_DIR -mkdir -p $INTERNAL_CERT_DIR_PATH -mkdir -p $EXTERNAL_CERT_DIR_PATH -mkdir -p ${SECRETS_DIRECTORY} -ln -s ${SECRETS_DIRECTORY} /secrets - -export CA_POOL=$CA_POOL_CERT_PATH -export CERT_FILE=$DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME -export KEY_FILE=$DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME +# OAUTH-SEVER KEYS +OAUTH_KEYS_PATH="/data/oauth/keys" +OAUTH_ID_TOKEN_KEY_PATH=${OAUTH_KEYS_PATH}/id-token.pem +OAUTH_ACCESS_TOKEN_KEY_PATH=${OAUTH_KEYS_PATH}/access-token.pem CERT_TOOL_SIGN_ALG=${CERT_TOOL_SIGN_ALG:-ECDSA-SHA256} CERT_TOOL_ELLIPTIC_CURVE=${CERT_TOOL_ELLIPTIC_CURVE:-P256} -fqdnSAN="--cert.san.domain=$FQDN" -if ip route get $FQDN 2>/dev/null >/dev/null; then - fqdnSAN="--cert.san.ip=$FQDN" -fi -echo "generating CA cert" -cert-tool --cmd.generateRootCA --outCert=$CA_POOL_CERT_PATH --outKey=$CA_POOL_CERT_KEY_PATH --cert.subject.cn="Root CA" \ - --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} -echo "generating GRPC internal cert" -cert-tool --cmd.generateCertificate --outCert=$DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME \ - --outKey=$DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME --cert.subject.cn="localhost" --cert.san.domain="localhost" \ - --cert.san.ip="0.0.0.0" --cert.san.ip="127.0.0.1" $fqdnSAN --signerCert=$CA_POOL_CERT_PATH --signerKey=$CA_POOL_CERT_KEY_PATH \ - --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} -echo "generating COAP-GW cert" -cert-tool --cmd.generateIdentityCertificate=$COAP_GATEWAY_CLOUD_ID --outCert=$EXTERNAL_CERT_DIR_PATH/$COAP_GATEWAY_FILE_CERT_NAME \ - --outKey=$EXTERNAL_CERT_DIR_PATH/$COAP_GATEWAY_FILE_CERT_KEY_NAME --cert.san.domain=$COAP_GATEWAY_FQDN \ - --signerCert=$CA_POOL_CERT_PATH --signerKey=$CA_POOL_CERT_KEY_PATH --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} \ - --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} -echo "generating NGINX cert" -cert-tool --cmd.generateCertificate --outCert=$EXTERNAL_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME \ - --outKey=$EXTERNAL_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME --cert.subject.cn="localhost" --cert.san.domain="localhost" \ - --cert.san.ip="0.0.0.0" --cert.san.ip="127.0.0.1" $fqdnSAN --signerCert=$CA_POOL_CERT_PATH --signerKey=$CA_POOL_CERT_KEY_PATH \ - --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} - -mkdir -p ${OAUTH_KEYS_PATH} -openssl genrsa -out ${OAUTH_ID_TOKEN_KEY_PATH} 4096 -openssl ecparam -name prime256v1 -genkey -noout -out ${OAUTH_ACCESS_TOKEN_KEY_PATH} - -mkdir -p $MONGO_PATH -mkdir -p $CERTIFICATES_PATH -mkdir -p $LOGS_PATH - -# nats -echo "starting nats-server" -cat > /data/nats.config < ${OAUTH_DEVICE_SECRET_PATH} + + mkdir -p $CERTIFICATES_PATH + mkdir -p $CA_POOL_DIR + mkdir -p $INTERNAL_CERT_DIR_PATH + mkdir -p $EXTERNAL_CERT_DIR_PATH + + fqdnSAN="--cert.san.domain=$FQDN" + if ip route get $FQDN 2>/dev/null >/dev/null; then + fqdnSAN="--cert.san.ip=$FQDN" + fi + echo "generating CA cert" + cert-tool --cmd.generateRootCA --outCert=$CA_POOL_CERT_PATH --outKey=$CA_POOL_CERT_KEY_PATH --cert.subject.cn="Root CA" \ + --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} + echo "generating GRPC internal cert" + cert-tool --cmd.generateCertificate --outCert=$DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME \ + --outKey=$DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME --cert.subject.cn="localhost" --cert.san.domain="localhost" \ + --cert.san.ip="0.0.0.0" --cert.san.ip="127.0.0.1" $fqdnSAN --signerCert=$CA_POOL_CERT_PATH --signerKey=$CA_POOL_CERT_KEY_PATH \ + --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} + echo "generating COAP-GW cert" + cert-tool --cmd.generateIdentityCertificate=$COAP_GATEWAY_CLOUD_ID --outCert=$EXTERNAL_CERT_DIR_PATH/$COAP_GATEWAY_FILE_CERT_NAME \ + --outKey=$EXTERNAL_CERT_DIR_PATH/$COAP_GATEWAY_FILE_CERT_KEY_NAME --cert.san.domain=$COAP_GATEWAY_FQDN \ + --signerCert=$CA_POOL_CERT_PATH --signerKey=$CA_POOL_CERT_KEY_PATH --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} \ + --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} + echo "generating NGINX cert" + cert-tool --cmd.generateCertificate --outCert=$EXTERNAL_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME \ + --outKey=$EXTERNAL_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME --cert.subject.cn="localhost" --cert.san.domain="localhost" \ + --cert.san.ip="0.0.0.0" --cert.san.ip="127.0.0.1" $fqdnSAN --signerCert=$CA_POOL_CERT_PATH --signerKey=$CA_POOL_CERT_KEY_PATH \ + --cert.signatureAlgorithm=${CERT_TOOL_SIGN_ALG} --cert.ellipticCurve=${CERT_TOOL_ELLIPTIC_CURVE} + + mkdir -p ${OAUTH_KEYS_PATH} + openssl genrsa -out ${OAUTH_ID_TOKEN_KEY_PATH} 4096 + openssl ecparam -name prime256v1 -genkey -noout -out ${OAUTH_ACCESS_TOKEN_KEY_PATH} + + # nats + cat > /data/nats.config <$LOGS_PATH/nats-server.log 2>&1 & -status=$? -nats_server_pid=$! -if [ $status -ne 0 ]; then - echo "Failed to start nats-server: $status" - sync - cat $LOGS_PATH/nats-server.log - exit $status + # mongo + mkdir -p $MONGO_PATH + cat $DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME > $DIAL_FILE_CERT_DIR_PATH/mongo.key + cat $DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME >> $DIAL_FILE_CERT_DIR_PATH/mongo.key fi -# waiting for nats. Without wait, sometimes auth service didn't connect. -i=0 -while true; do - i=$((i+1)) - if nc -z localhost $NATS_PORT; then - break +if [ "${RUN}" == "true" ]; then + # nats + export NATS_HOST="localhost:$NATS_PORT" + export NATS_URL="nats://${NATS_HOST}" + + echo "starting nats-server" + nats-server -c /data/nats.config >$LOGS_PATH/nats-server.log 2>&1 & + status=$? + nats_server_pid=$! + if [ $status -ne 0 ]; then + echo "Failed to start nats-server: $status" + sync + cat $LOGS_PATH/nats-server.log + exit $status + fi + + # waiting for nats. Without wait, sometimes auth service didn't connect. + i=0 + while true; do + i=$((i+1)) + if nc -z localhost $NATS_PORT; then + break + fi + echo "Try to reconnect to nats(${NATS_HOST}) $i" + sleep 1 + done + + # mongo + export MONGODB_HOST="localhost:$MONGO_PORT" + export MONGODB_URI="mongodb://$MONGODB_HOST" + + echo "starting mongod" + mongod --setParameter maxNumActiveUserIndexBuilds=64 --port $MONGO_PORT --dbpath $MONGO_PATH \ + --sslMode requireSSL --sslCAFile $CA_POOL_CERT_PATH --sslPEMKeyFile $DIAL_FILE_CERT_DIR_PATH/mongo.key \ + >$LOGS_PATH/mongod.log 2>&1 & + status=$? + mongo_pid=$! + if [ $status -ne 0 ]; then + echo "Failed to start mongod: $status" + sync + cat $LOGS_PATH/mongod.log + exit $status fi - echo "Try to reconnect to nats(${NATS_HOST}) $i" - sleep 1 -done - -# mongo -echo "starting mongod" -cat $DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_NAME > $DIAL_FILE_CERT_DIR_PATH/mongo.key -cat $DIAL_FILE_CERT_DIR_PATH/$DIAL_FILE_CERT_KEY_NAME >> $DIAL_FILE_CERT_DIR_PATH/mongo.key -mongod --setParameter maxNumActiveUserIndexBuilds=64 --port $MONGO_PORT --dbpath $MONGO_PATH --sslMode requireSSL --sslCAFile $CA_POOL_CERT_PATH --sslPEMKeyFile $DIAL_FILE_CERT_DIR_PATH/mongo.key >$LOGS_PATH/mongod.log 2>&1 & -status=$? -mongo_pid=$! -if [ $status -ne 0 ]; then - echo "Failed to start mongod: $status" - sync - cat $LOGS_PATH/mongod.log - exit $status -fi -# waiting for mongo DB. Without wait, sometimes auth service didn't connect. -i=0 -while true; do - i=$((i+1)) - if openssl s_client -connect ${MONGODB_HOST} -cert ${INTERNAL_CERT_DIR_PATH}/${DIAL_FILE_CERT_NAME} -key ${INTERNAL_CERT_DIR_PATH}/${DIAL_FILE_CERT_KEY_NAME} <<< "Q" 2>/dev/null > /dev/null; then - break + # waiting for mongo DB. Without wait, sometimes auth service didn't connect. + i=0 + while [ $i -lt 60 ]; do + i=$((i+1)) + + if [ $i -eq 60 ]; then + echo "Failed to start mongod: timeout" + sync + cat $LOGS_PATH/mongod.log + exit 1 + fi + + if openssl s_client -connect ${MONGODB_HOST} -cert ${INTERNAL_CERT_DIR_PATH}/${DIAL_FILE_CERT_NAME} \ + -key ${INTERNAL_CERT_DIR_PATH}/${DIAL_FILE_CERT_KEY_NAME} <<< "Q" 2>/dev/null > /dev/null; then + break + fi + echo "Try to reconnect to mongodb(${MONGODB_HOST}) $i" + sleep 1 + done + + # needed by coap-gateway.test and grpc-gateway.test + ## LISTEN CERTS + export LISTEN_FILE_CA_POOL="$CA_POOL_CERT_PATH" + export LISTEN_FILE_CERT_DIR_PATH="$INTERNAL_CERT_DIR_PATH" + export LISTEN_FILE_CERT_NAME="$GRPC_INTERNAL_CERT_NAME" + export LISTEN_FILE_CERT_KEY_NAME="$GRPC_INTERNAL_CERT_KEY_NAME" + ## OTHER + export TEST_COAP_GW_CERT_FILE="${EXTERNAL_CERT_DIR_PATH}/${COAP_GATEWAY_FILE_CERT_NAME}" + export TEST_COAP_GW_KEY_FILE="${EXTERNAL_CERT_DIR_PATH}/${COAP_GATEWAY_FILE_CERT_KEY_NAME}" + export TEST_ROOT_CA_CERT="${CA_POOL_CERT_PATH}" + export TEST_ROOT_CA_KEY="${CA_POOL_CERT_KEY_PATH}" + export TEST_CLOUD_SID="${COAP_GATEWAY_CLOUD_ID}" + export TEST_OAUTH_SERVER_ID_TOKEN_PRIVATE_KEY="${OAUTH_ID_TOKEN_KEY_PATH}" + export TEST_OAUTH_SERVER_ACCESS_TOKEN_PRIVATE_KEY="${OAUTH_ACCESS_TOKEN_KEY_PATH}" + export TEST_COAP_GATEWAY_UDP_ENABLED="${COAP_GATEWAY_UDP_ENABLED}" + + if [ "${COAP_GATEWAY_TEST_DISABLED}" != "1" ]; then + opts=() + if [ -n "${COAP_GATEWAY_TEST_RUN}" ]; then + opts+=("-test.run" "${COAP_GATEWAY_TEST_RUN}") + fi + echo "starting coap-gateway test" + coap-gateway.test -test.v -test.timeout 600s -test.parallel 1 ${opts[@]} fi - echo "Try to reconnect to mongodb(${MONGODB_HOST}) $i" - sleep 1 -done -echo "starting grpc-gateway test" -grpc-gateway.test -test.v -test.timeout 600s -test.parallel 1 + if [ "${GRPC_GATEWAY_TEST_DISABLED}" != "1" ]; then + opts=() + if [ -n "${GRPC_GATEWAY_TEST_RUN}" ]; then + opts+=("-test.run" "${GRPC_GATEWAY_TEST_RUN}") + fi + echo "starting grpc-gateway test" + grpc-gateway.test -test.v -test.timeout 600s -test.parallel 1 ${opts[@]} + fi -echo "starting test/iotivity-lite test" -test-iotivity-lite.test -test.v -test.timeout 600s -test.parallel 1 + if [ "${IOTIVITY_LITE_TEST_DISABLED}" != "1" ]; then + opts=() + if [ -n "${IOTIVITY_LITE_TEST_RUN}" ]; then + opts+=("-test.run" "${IOTIVITY_LITE_TEST_RUN}") + fi + echo "starting test/iotivity-lite test" + test-iotivity-lite.test -test.v -test.timeout 600s -test.parallel 1 ${opts[@]} + fi +fi diff --git a/test/device/bridge/device.go b/test/device/bridge/device.go new file mode 100644 index 000000000..46e9f2967 --- /dev/null +++ b/test/device/bridge/device.go @@ -0,0 +1,71 @@ +/**************************************************************************** + * + * Copyright (c) 2024 plgd.dev s.r.o. + * + * 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 bridge + +import ( + "time" + + "github.com/plgd-dev/device/v2/schema" + schemaDevice "github.com/plgd-dev/device/v2/schema/device" + "github.com/plgd-dev/device/v2/schema/interfaces" + "github.com/plgd-dev/device/v2/schema/maintenance" + "github.com/plgd-dev/hub/v2/test/device" + "github.com/plgd-dev/hub/v2/test/sdk" +) + +var TestResources = []schema.ResourceLink{ + { + Href: schemaDevice.ResourceURI, + ResourceTypes: []string{"oic.d.virtual", schemaDevice.ResourceType}, + Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_R}, + Policy: &schema.Policy{ + BitMask: 1, + }, + }, + { + Href: maintenance.ResourceURI, + ResourceTypes: []string{maintenance.ResourceType}, + Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_RW}, + Policy: &schema.Policy{ + BitMask: 1, + }, + }, +} + +type Device struct { + device.BaseDevice +} + +func NewDevice(id, name string) *Device { + return &Device{ + BaseDevice: device.MakeBaseDevice(id, name), + } +} + +func (d *Device) GetSDKClientOptions() []sdk.Option { + return []sdk.Option{sdk.WithUseDeviceIDInQuery(true)} +} + +func (d *Device) GetRetryInterval(int) time.Duration { + return time.Second * 10 +} + +func (d *Device) GetDefaultResources() schema.ResourceLinks { + return TestResources +} diff --git a/test/device/device.go b/test/device/device.go new file mode 100644 index 000000000..28ccb9933 --- /dev/null +++ b/test/device/device.go @@ -0,0 +1,157 @@ +/**************************************************************************** + * + * Copyright (c) 2024 plgd.dev s.r.o. + * + * 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 device + +import ( + "context" + "errors" + "fmt" + "log" + "sync/atomic" + "time" + + "github.com/plgd-dev/device/v2/client/core" + deviceCoap "github.com/plgd-dev/device/v2/pkg/net/coap" + "github.com/plgd-dev/device/v2/schema" + "github.com/plgd-dev/device/v2/schema/device" + "github.com/plgd-dev/hub/v2/test/sdk" +) + +type Device interface { + // GetID returns device ID + GetID() string + + // SetID sets device ID + SetID(id string) + + // GetName returns device name + GetName() string + + // GetRetryInterval returns retry interval of the device before retrying provisioning + GetRetryInterval(attempt int) time.Duration + + // GetDefaultResources returns default device resources + GetDefaultResources() schema.ResourceLinks + + // GetSDKClientOptions returns options for the SDK client used with this device + GetSDKClientOptions() []sdk.Option +} + +type BaseDevice struct { + id string + name string +} + +func MakeBaseDevice(id, name string) BaseDevice { + return BaseDevice{ + id: id, + name: name, + } +} + +func (bd *BaseDevice) GetID() string { + return bd.id +} + +func (bd *BaseDevice) SetID(id string) { + bd.id = id +} + +func (bd *BaseDevice) GetName() string { + return bd.name +} + +func (bd *BaseDevice) GetSDKClientOptions() []sdk.Option { + return nil +} + +type Type int + +const ( + OCF Type = iota + Bridged +) + +func FindDeviceByName(ctx context.Context, name string, getResourceOpts func(*core.Device) deviceCoap.OptionFunc) (deviceID string, _ error) { + client := core.NewClient() + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + h := findDeviceIDByNameHandler{ + name: name, + cancel: cancel, + getResourceOptions: getResourceOpts, + } + + err := client.GetDevicesByMulticast(ctx, core.DefaultDiscoveryConfiguration(), &h) + if err != nil { + return "", fmt.Errorf("could not find the device named %s: %w", name, err) + } + id, ok := h.id.Load().(string) + if !ok || id == "" { + return "", fmt.Errorf("could not find the device named %s: not found", name) + } + return id, nil +} + +type findDeviceIDByNameHandler struct { + id atomic.Value + name string + cancel context.CancelFunc + getResourceOptions func(*core.Device) deviceCoap.OptionFunc +} + +func (h *findDeviceIDByNameHandler) Handle(ctx context.Context, dev *core.Device) { + defer func() { + if errC := dev.Close(ctx); errC != nil { + h.Error(errC) + } + }() + deviceLinks, err := dev.GetResourceLinks(ctx, dev.GetEndpoints()) + if err != nil { + h.Error(err) + return + } + l, ok := deviceLinks.GetResourceLink(device.ResourceURI) + if !ok { + return + } + var d device.Device + var getResourceOpts []deviceCoap.OptionFunc + if h.getResourceOptions != nil { + getResourceOpts = append(getResourceOpts, h.getResourceOptions(dev)) + } + err = dev.GetResource(ctx, l, &d, getResourceOpts...) + if err != nil { + h.Error(err) + return + } + if d.Name == h.name { + h.id.Store(d.ID) + h.cancel() + } +} + +func (h *findDeviceIDByNameHandler) Error(err error) { + if errors.Is(err, context.Canceled) { + return + } + log.Printf("find device ID by name handler error: %v", err.Error()) +} diff --git a/test/device/ocf/device.go b/test/device/ocf/device.go new file mode 100644 index 000000000..495377798 --- /dev/null +++ b/test/device/ocf/device.go @@ -0,0 +1,129 @@ +/**************************************************************************** + * + * Copyright (c) 2024 plgd.dev s.r.o. + * + * 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 ocf + +import ( + "math" + "time" + + "github.com/plgd-dev/device/v2/schema" + "github.com/plgd-dev/device/v2/schema/collection" + "github.com/plgd-dev/device/v2/schema/configuration" + schemaDevice "github.com/plgd-dev/device/v2/schema/device" + "github.com/plgd-dev/device/v2/schema/interfaces" + "github.com/plgd-dev/device/v2/schema/maintenance" + "github.com/plgd-dev/device/v2/schema/platform" + "github.com/plgd-dev/device/v2/schema/plgdtime" + "github.com/plgd-dev/device/v2/schema/softwareupdate" + "github.com/plgd-dev/device/v2/test/resource/types" + "github.com/plgd-dev/hub/v2/test/device" +) + +var TestResources = []schema.ResourceLink{ + { + Href: platform.ResourceURI, + ResourceTypes: []string{platform.ResourceType}, + Interfaces: []string{interfaces.OC_IF_R, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, + + { + Href: schemaDevice.ResourceURI, + ResourceTypes: []string{types.DEVICE_CLOUD, schemaDevice.ResourceType}, + Interfaces: []string{interfaces.OC_IF_R, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, + + { + Href: configuration.ResourceURI, + ResourceTypes: []string{configuration.ResourceType}, + Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, + + { + Href: "/light/1", + ResourceTypes: []string{types.CORE_LIGHT}, + Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, + + { + Href: "/switches", + ResourceTypes: []string{collection.ResourceType}, + Interfaces: []string{interfaces.OC_IF_LL, interfaces.OC_IF_CREATE, interfaces.OC_IF_B, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, + + { + Href: maintenance.ResourceURI, + ResourceTypes: []string{maintenance.ResourceType}, + Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 1, + }, + }, + + { + Href: plgdtime.ResourceURI, + ResourceTypes: []string{plgdtime.ResourceType}, + Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, + + { + Href: softwareupdate.ResourceURI, + ResourceTypes: []string{softwareupdate.ResourceType}, + Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, + Policy: &schema.Policy{ + BitMask: 3, + }, + }, +} + +type Device struct { + device.BaseDevice +} + +func NewDevice(id, name string) *Device { + return &Device{ + BaseDevice: device.MakeBaseDevice(id, name), + } +} + +func (d *Device) GetRetryInterval(attempt int) time.Duration { + /* [2s, 4s, 8s, 16s, 32s, 64s] */ + return time.Duration(math.Exp2(float64(attempt))) * time.Second +} + +func (d *Device) GetDefaultResources() schema.ResourceLinks { + return TestResources +} diff --git a/test/iotivity-lite/service/deleteResource_test.go b/test/iotivity-lite/service/deleteResource_test.go index 090083ac6..7433a1145 100644 --- a/test/iotivity-lite/service/deleteResource_test.go +++ b/test/iotivity-lite/service/deleteResource_test.go @@ -20,6 +20,7 @@ import ( "github.com/plgd-dev/hub/v2/test/config" iotService "github.com/plgd-dev/hub/v2/test/iotivity-lite/service" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" + "github.com/plgd-dev/hub/v2/test/sdk" "github.com/plgd-dev/hub/v2/test/service" "github.com/stretchr/testify/require" "golang.org/x/exp/maps" @@ -173,13 +174,13 @@ func TestBatchDeleteResources(t *testing.T) { // TODO: copy services initialization from the real coap-gw to the mock coap-gw, // for now we must force TCP when mock coap-gw is used // _, _ = test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - _, _ = test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + _, shutdown := test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) require.True(t, bh.WaitForFirstSignIn(time.Second*20)) t.Cleanup(func() { - test.DisownDevice(t, deviceID) + shutdown() }) - devClient, err := test.NewSDKClient() + devClient, err := sdk.NewClient() require.NoError(t, err) defer func() { _ = devClient.Close(ctx) diff --git a/test/iotivity-lite/service/offboard_test.go b/test/iotivity-lite/service/offboard_test.go index 6aec76563..5b5c02d4e 100644 --- a/test/iotivity-lite/service/offboard_test.go +++ b/test/iotivity-lite/service/offboard_test.go @@ -30,7 +30,7 @@ import ( // signed in -> deregister by sending DELETE request func TestOffboard(t *testing.T) { - deviceID := test.MustFindDeviceByName(test.TestDeviceName) + d := test.MustFindTestDevice() deadline := time.Now().Add(time.Minute) ctx, cancel := context.WithDeadline(context.Background(), deadline) @@ -75,14 +75,14 @@ func TestOffboard(t *testing.T) { // TODO: copy services initialization from the real coap-gw to the mock coap-gw, // for now we must force TCP when mock coap-gw is used - // _, _ = test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - _, _ = test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + // shutdown := test.OnboardDevice(ctx, t, c, d, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) + shutdown := test.OnboardDevice(ctx, t, c, d, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) require.True(t, ch.WaitForFirstSignIn(time.Second*20)) t.Cleanup(func() { - test.DisownDevice(t, deviceID) + shutdown() }) - test.OffBoardDevSim(ctx, t, deviceID) + test.OffboardDevice(ctx, t, d) require.True(t, ch.WaitForFirstSignOff(time.Second*20)) } @@ -183,7 +183,7 @@ func (sh *switchableHandler) RefreshToken(req coapgwService.CoapRefreshTokenReq) // not signed in, with permanent and short access-token -> deregister by sending DELETE request with access token func TestOffboardWithoutSignIn(t *testing.T) { - deviceID := test.MustFindDeviceByName(test.TestDeviceName) + d := test.MustFindTestDevice() deadline := time.Now().Add(time.Minute) ctx, cancel := context.WithDeadline(context.Background(), deadline) @@ -206,19 +206,8 @@ func TestOffboardWithoutSignIn(t *testing.T) { log.Debugf("%+v", h.CallCounter.Data) signInCount, ok := h.CallCounter.Data[iotService.SignInKey] require.True(t, ok) - // sometimes the first sign-in attempt fails, so we allow 2 attempts - /* - === RUN TestOffboardWithoutSignIn - offboard_test.go:205: - Error Trace: /src/github.com/plgd-dev/hub/test/iotivity-lite/service/offboard_test.go:205 - /src/github.com/plgd-dev/hub/test/coap-gateway/test/test.go:59 - /src/github.com/plgd-dev/hub/test/iotivity-lite/service/offboard_test.go:236 - Error: Not equal: - expected: 1 - actual : 2 - Test: TestOffboardWithoutSignIn - */ - require.True(t, signInCount >= 1 || signInCount <= 2) + // depending on the timing of the test, the sign-in may be called once or twice + require.True(t, signInCount >= 1 && signInCount <= 2) _, ok = h.CallCounter.Data[iotService.RefreshTokenKey] require.False(t, ok) signOffCount, ok := h.CallCounter.Data[iotService.SignOffKey] @@ -240,22 +229,22 @@ func TestOffboardWithoutSignIn(t *testing.T) { }() c := pb.NewGrpcGatewayClient(conn) - // deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + // shutdown := test.OnboardDevSim(ctx, t, c, d, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) + shutdown := test.OnboardDevice(ctx, t, c, d, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) t.Cleanup(func() { - test.DisownDevice(t, deviceID) + shutdown() }) require.True(t, sh.WaitForFirstSignIn(time.Second*20)) // first retry after failure is after 2 seconds, so hopefully it doesn't trigger, if this test // behaves flakily then we will have to update simulator to have a configurable retry sh.failSignIn.Store(false) - // wait for sign-in to be called again - time.Sleep(time.Second * 3) - test.OffBoardDevSim(ctx, t, deviceID) + time.Sleep(d.GetRetryInterval(1) + time.Second) + test.OffboardDevice(ctx, t, d) require.True(t, sh.WaitForFirstSignOff(time.Second*20)) } // not signed in, with permanent but long access-token -> try to sign in and then deregister without access token +// OCF device specific behavior func TestOffboardWithSignIn(t *testing.T) { deviceID := test.MustFindDeviceByName(test.TestDeviceName) @@ -303,10 +292,10 @@ func TestOffboardWithSignIn(t *testing.T) { }() c := pb.NewGrpcGatewayClient(conn) - // deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + // deviceID, shutdown := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) + deviceID, shutdown := test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) t.Cleanup(func() { - test.DisownDevice(t, deviceID) + shutdown() }) require.True(t, sh.WaitForFirstSignIn(time.Second*20)) @@ -320,6 +309,7 @@ func TestOffboardWithSignIn(t *testing.T) { } // not signed up, with refresh token -> try to login and then deregister without access token +// OCF device specific behavior func TestOffboardWithSignInByRefreshToken(t *testing.T) { deviceID := test.MustFindDeviceByName(test.TestDeviceName) @@ -369,9 +359,9 @@ func TestOffboardWithSignInByRefreshToken(t *testing.T) { // register device first time // deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + deviceID, shutdown := test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) t.Cleanup(func() { - test.DisownDevice(t, deviceID) + shutdown() }) require.True(t, sh.WaitForFirstSignIn(time.Second*20)) @@ -398,7 +388,7 @@ func TestOffboardWithSignInByRefreshToken(t *testing.T) { // Multiple offboard attempts should be ignored func TestOffboardWithRepeat(t *testing.T) { - deviceID := test.MustFindDeviceByName(test.TestDeviceName) + d := test.MustFindTestDevice() deadline := time.Now().Add(time.Minute) ctx, cancel := context.WithDeadline(context.Background(), deadline) @@ -439,17 +429,17 @@ func TestOffboardWithRepeat(t *testing.T) { c := pb.NewGrpcGatewayClient(conn) // deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - deviceID, _ = test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + shutdown := test.OnboardDevice(ctx, t, c, d, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) t.Cleanup(func() { - test.DisownDevice(t, deviceID) + shutdown() }) require.True(t, sh.WaitForFirstSignIn(time.Second*20)) time.Sleep(time.Second) - test.OffBoardDevSim(ctx, t, deviceID) - test.OffBoardDevSim(ctx, t, deviceID) - test.OffBoardDevSim(ctx, t, deviceID) + test.OffboardDevice(ctx, t, d) + test.OffboardDevice(ctx, t, d) + test.OffboardDevice(ctx, t, d) require.True(t, sh.WaitForFirstSignOff(time.Second*20)) // first SignOff should timeout after 10 secs, we wait 10 additional seconds for the other @@ -458,6 +448,7 @@ func TestOffboardWithRepeat(t *testing.T) { } // Onboarding should interrupt an ongoing offboarding +// OCF device specific behavior func TestOffboardInterrupt(t *testing.T) { deviceID := test.MustFindDeviceByName(test.TestDeviceName) diff --git a/test/iotivity-lite/service/republish_test.go b/test/iotivity-lite/service/republish_test.go index 70d7f0bec..8d4c17e8f 100644 --- a/test/iotivity-lite/service/republish_test.go +++ b/test/iotivity-lite/service/republish_test.go @@ -23,7 +23,7 @@ import ( ) func TestRepublishAfterRefresh(t *testing.T) { - deviceID := test.MustFindDeviceByName(test.TestDeviceName) + d := test.MustFindTestDevice() atLifetime := time.Second * 20 deadline := time.Now().Add(time.Minute) @@ -65,8 +65,8 @@ func TestRepublishAfterRefresh(t *testing.T) { }() c := pb.NewGrpcGatewayClient(conn) - // _, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) - _, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) + // shutdownDevSim := test.OnboardDevice(ctx, t, c, d, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) + shutdownDevSim := test.OnboardDevice(ctx, t, c, d, string(schema.TCPSecureScheme)+"://"+config.COAP_GW_HOST, nil) defer shutdownDevSim() for { diff --git a/test/sdkclient.go b/test/sdk/client.go similarity index 95% rename from test/sdkclient.go rename to test/sdk/client.go index 9343e9c4d..28a4b719b 100644 --- a/test/sdkclient.go +++ b/test/sdk/client.go @@ -1,4 +1,4 @@ -package test +package sdk import ( "context" @@ -55,6 +55,8 @@ type sdkConfig struct { // TODO: replace by notBefore and notAfter validFrom string // RFC3339, or relative time such as now-1m validFor string // string parsable by time.ParseDuration + + useDeviceIDInQuery bool } // Option interface used for setting optional sdkConfig properties. @@ -92,6 +94,12 @@ func WithValidity(validFrom, validFor string) Option { }) } +func WithUseDeviceIDInQuery(useDeviceIDInQuery bool) Option { + return optionFunc(func(cfg *sdkConfig) { + cfg.useDeviceIDInQuery = useDeviceIDInQuery + }) +} + func getSDKConfig(opts ...Option) (*sdkConfig, error) { c := &sdkConfig{ id: CertIdentity, @@ -116,7 +124,7 @@ func getSDKConfig(opts ...Option) (*sdkConfig, error) { return c, nil } -func NewSDKClient(opts ...Option) (*client.Client, error) { +func NewClient(opts ...Option) (*client.Client, error) { c, err := getSDKConfig(opts...) if err != nil { return nil, err @@ -172,6 +180,7 @@ func NewSDKClient(opts ...Option) (*client.Client, error) { cfg := client.Config{ DisablePeerTCPSignalMessageCSMs: true, DeviceOwnershipSDK: devCfg, + UseDeviceIDInQuery: c.useDeviceIDInQuery, } client, err := client.NewClientFromConfig(&cfg, &testSetupSecureClient{ diff --git a/test/test.go b/test/test.go index 83b370bb5..4860f32fb 100644 --- a/test/test.go +++ b/test/test.go @@ -2,9 +2,7 @@ package test import ( "context" - "errors" "fmt" - "log" "net" "os" "os/exec" @@ -15,12 +13,12 @@ import ( deviceClient "github.com/plgd-dev/device/v2/client" "github.com/plgd-dev/device/v2/client/core" + deviceCoap "github.com/plgd-dev/device/v2/pkg/net/coap" "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/acl" "github.com/plgd-dev/device/v2/schema/cloud" - "github.com/plgd-dev/device/v2/schema/collection" "github.com/plgd-dev/device/v2/schema/configuration" - "github.com/plgd-dev/device/v2/schema/device" + schemaDevice "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/device/v2/schema/maintenance" "github.com/plgd-dev/device/v2/schema/platform" @@ -37,12 +35,15 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/events" "github.com/plgd-dev/hub/v2/test/config" + "github.com/plgd-dev/hub/v2/test/device" + "github.com/plgd-dev/hub/v2/test/device/bridge" + "github.com/plgd-dev/hub/v2/test/device/ocf" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" + "github.com/plgd-dev/hub/v2/test/sdk" "github.com/plgd-dev/kit/v2/codec/json" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ugorji/go/codec" - "go.uber.org/atomic" ) type ResourceLinkRepresentation struct { @@ -65,8 +66,8 @@ func (d *ResourceLinkRepresentation) UnmarshalJSON(data []byte) error { err := json.Decode(data, &r) return r, err }, - device.ResourceURI: func(data []byte) (interface{}, error) { - var r device.Device + schemaDevice.ResourceURI: func(data []byte) (interface{}, error) { + var r schemaDevice.Device err := json.Decode(data, &r) r.ProtocolIndependentID = "" return r, err @@ -144,9 +145,7 @@ var ( TestDeviceNameWithOicResObservable string TestDeviceModelNumber = "CS-0" TestDeviceSoftwareVersion = "1.0.1-rc1" - - TestDevsimResources []schema.ResourceLink - TestDevsimBackendResources []schema.ResourceLink + TestDeviceType device.Type testIovityLiteVersion *sync.Map[string, uint32] ) @@ -190,93 +189,27 @@ type CollectionLinkRepresentation struct { type CollectionLinkRepresentations []CollectionLinkRepresentation func init() { - TestDeviceName = "devsim-" + MustGetHostname() + if name := os.Getenv("TEST_DEVICE_NAME"); name != "" { + TestDeviceName = name + } else { + TestDeviceName = "devsim-" + MustGetHostname() + } TestDeviceNameWithOicResObservable = "devsim-resobs-" + MustGetHostname() - - // when adding new resource, add also representation to GetAllBackendResourceRepresentations func - TestDevsimResources = []schema.ResourceLink{ - { - Href: platform.ResourceURI, - ResourceTypes: []string{platform.ResourceType}, - Interfaces: []string{interfaces.OC_IF_R, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, - - { - Href: device.ResourceURI, - ResourceTypes: []string{types.DEVICE_CLOUD, device.ResourceType}, - Interfaces: []string{interfaces.OC_IF_R, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, - - { - Href: configuration.ResourceURI, - ResourceTypes: []string{configuration.ResourceType}, - Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, - - { - Href: TestResourceLightInstanceHref("1"), - ResourceTypes: []string{types.CORE_LIGHT}, - Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, - - { - Href: TestResourceSwitchesHref, - ResourceTypes: []string{collection.ResourceType}, - Interfaces: []string{interfaces.OC_IF_LL, interfaces.OC_IF_CREATE, interfaces.OC_IF_B, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, - - { - Href: maintenance.ResourceURI, - ResourceTypes: []string{maintenance.ResourceType}, - Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 1, - }, - }, - - { - Href: plgdtime.ResourceURI, - ResourceTypes: []string{plgdtime.ResourceType}, - Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, - - { - Href: softwareupdate.ResourceURI, - ResourceTypes: []string{softwareupdate.ResourceType}, - Interfaces: []string{interfaces.OC_IF_RW, interfaces.OC_IF_BASELINE}, - Policy: &schema.Policy{ - BitMask: 3, - }, - }, + if dtype := os.Getenv("TEST_DEVICE_TYPE"); dtype == "bridged" { + TestDeviceType = device.Bridged + } else { + TestDeviceType = device.OCF } testIovityLiteVersion = sync.NewMap[string, uint32]() } -func GetDeviceResourceRepresentation(deviceID, deviceName string) device.Device { - return device.Device{ +func GetDeviceResourceRepresentation(deviceID, deviceName string) schemaDevice.Device { + return schemaDevice.Device{ ID: deviceID, Interfaces: []string{interfaces.OC_IF_R, interfaces.OC_IF_BASELINE}, Name: deviceName, - ResourceTypes: []string{types.DEVICE_CLOUD, device.ResourceType}, + ResourceTypes: []string{types.DEVICE_CLOUD, schemaDevice.ResourceType}, DataModelVersion: "ocf.res.1.3.0", SpecificationVersion: "ocf.2.0.5", ModelNumber: TestDeviceModelNumber, @@ -314,7 +247,7 @@ func GetAllBackendResourceRepresentations(t *testing.T, deviceID, deviceName str }, }, { - Href: "/" + commands.NewResourceID(deviceID, device.ResourceURI).ToString(), + Href: "/" + commands.NewResourceID(deviceID, schemaDevice.ResourceURI).ToString(), Representation: dev, }, { @@ -461,25 +394,32 @@ func AddDeviceSwitchResources(ctx context.Context, t *testing.T, deviceID string return links } -func setAccessForCloud(ctx context.Context, t *testing.T, c *deviceClient.Client, deviceID string) { - cloudSID := config.HubID() - require.NotEmpty(t, cloudSID) - +func setAccessForCloud(ctx context.Context, c *deviceClient.Client, deviceID, cloudSID string) error { d, links, err := c.GetDevice(ctx, deviceID) - require.NoError(t, err) - + if err != nil { + return err + } defer func() { - errC := d.Close(ctx) - require.NoError(t, errC) + _ = d.Close(ctx) }() + + // skip setting of ACLs for insecure devices + if !d.IsSecured() { + return nil + } + p, err := d.Provision(ctx, links) - require.NoError(t, err) + if err != nil { + return err + } defer func() { _ = p.Close(ctx) }() link, err := core.GetResourceLink(links, acl.ResourceURI) - require.NoError(t, err) + if err != nil { + return err + } confResources := acl.AllResources for _, href := range links.GetResourceHrefs(maintenance.ResourceType) { confResources = append(confResources, acl.Resource{ @@ -507,37 +447,56 @@ func setAccessForCloud(ctx context.Context, t *testing.T, c *deviceClient.Client }, } - err = p.UpdateResource(ctx, link, setAcl, nil) + return p.UpdateResource(ctx, link, setAcl, nil) +} + +func disownDevice(t *testing.T, d device.Device) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*8) + defer cancel() + client, err := sdk.NewClient(d.GetSDKClientOptions()...) require.NoError(t, err) + defer func() { + _ = client.Close(ctx) + }() + err = client.DisownDevice(ctx, d.GetID()) + require.NoError(t, err) + time.Sleep(time.Second * 2) } -func OnboardDevSimForClient(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, clientID, deviceID, hubEndpoint string, expectedResources []schema.ResourceLink) (string, func()) { +func OnboardDevice(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, d device.Device, hubEndpoint string, expectedResources []schema.ResourceLink) func() { + return OnboardDeviceForClient(ctx, t, c, d, config.OAUTH_MANAGER_CLIENT_ID, hubEndpoint, expectedResources) +} + +func OnboardDeviceForClient(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, d device.Device, clientID, hubEndpoint string, expectedResources []schema.ResourceLink) func() { cloudSID := config.HubID() require.NotEmpty(t, cloudSID) - devClient, err := NewSDKClient() + devClient, err := sdk.NewClient(d.GetSDKClientOptions()...) require.NoError(t, err) defer func() { _ = devClient.Close(ctx) }() - deviceID, err = devClient.OwnDevice(ctx, deviceID, deviceClient.WithOTM(deviceClient.OTMType_JustWorks)) + + deviceID, err := devClient.OwnDevice(ctx, d.GetID(), deviceClient.WithOTM(deviceClient.OTMType_JustWorks)) require.NoError(t, err) + d.SetID(deviceID) - setAccessForCloud(ctx, t, devClient, deviceID) + err = setAccessForCloud(ctx, devClient, d.GetID(), cloudSID) + require.NoError(t, err) - code := oauthTest.GetAuthorizationCode(t, config.OAUTH_SERVER_HOST, clientID, deviceID, "") + code := oauthTest.GetAuthorizationCode(t, config.OAUTH_SERVER_HOST, clientID, d.GetID(), "") onboard := func() { var cloudRes cloud.Configuration - err = devClient.GetResource(ctx, deviceID, cloud.ResourceURI, &cloudRes) + err = devClient.GetResource(ctx, d.GetID(), cloud.ResourceURI, &cloudRes) require.NoError(t, err) if cloudRes.ProvisioningStatus != cloud.ProvisioningStatus_UNINITIALIZED { // device cloud is configured so we need to remove it first - err = devClient.OffboardDevice(ctx, deviceID) + err = devClient.OffboardDevice(ctx, d.GetID()) require.NoError(t, err) } - err = devClient.OnboardDevice(ctx, deviceID, config.DEVICE_PROVIDER, hubEndpoint, code, cloudSID) + err = devClient.OnboardDevice(ctx, d.GetID(), config.DEVICE_PROVIDER, hubEndpoint, code, cloudSID) require.NoError(t, err) } if len(expectedResources) > 0 { @@ -565,44 +524,40 @@ func OnboardDevSimForClient(ctx context.Context, t *testing.T, c pb.GrpcGatewayC } CheckProtobufs(t, expectedEvent, ev, RequireToCheckFunc(require.Equal)) onboard() - WaitForDevice(t, subClient, deviceID, ev.GetSubscriptionId(), ev.GetCorrelationId(), expectedResources) + WaitForDevice(t, subClient, d.GetID(), ev.GetSubscriptionId(), ev.GetCorrelationId(), expectedResources) err = subClient.CloseSend() require.NoError(t, err) } else { onboard() } - return deviceID, func() { - DisownDevice(t, deviceID) + return func() { + disownDevice(t, d) } } +func OnboardDevSimForClient(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, clientID, deviceID, hubEndpoint string, expectedResources []schema.ResourceLink) (string, func()) { + d := ocf.NewDevice(deviceID, TestDeviceName) + cleanup := OnboardDeviceForClient(ctx, t, c, d, clientID, hubEndpoint, expectedResources) + return d.GetID(), cleanup +} + func OnboardDevSim(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, deviceID, hubEndpoint string, expectedResources []schema.ResourceLink) (string, func()) { return OnboardDevSimForClient(ctx, t, c, config.OAUTH_MANAGER_CLIENT_ID, deviceID, hubEndpoint, expectedResources) } -func OffBoardDevSim(ctx context.Context, t *testing.T, deviceID string) { - devClient, err := NewSDKClient() +func OffboardDevice(ctx context.Context, t *testing.T, d device.Device) { + devClient, err := sdk.NewClient(d.GetSDKClientOptions()...) require.NoError(t, err) defer func() { _ = devClient.Close(ctx) }() - - err = devClient.OffboardDevice(ctx, deviceID) + err = devClient.OffboardDevice(ctx, d.GetID()) require.NoError(t, err) } -func DisownDevice(t *testing.T, deviceID string) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*8) - defer cancel() - client, err := NewSDKClient() - require.NoError(t, err) - defer func() { - _ = client.Close(ctx) - }() - err = client.DisownDevice(ctx, deviceID) - require.NoError(t, err) - time.Sleep(time.Second * 2) +func OffBoardDevSim(ctx context.Context, t *testing.T, deviceID string) { + OffboardDevice(ctx, t, ocf.NewDevice(deviceID, TestDeviceName)) } func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, deviceID, subID, correlationID string, expectedResources []schema.ResourceLink) { @@ -822,7 +777,7 @@ func MustFindDeviceByName(name string) (deviceID string) { for i := 0; i < 3; i++ { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - deviceID, err = FindDeviceByName(ctx, name) + deviceID, err = device.FindDeviceByName(ctx, name, nil) if err == nil { return deviceID } @@ -830,70 +785,37 @@ func MustFindDeviceByName(name string) (deviceID string) { panic(err) } -type findDeviceIDByNameHandler struct { - id atomic.Value - name string - cancel context.CancelFunc -} - -func (h *findDeviceIDByNameHandler) Handle(ctx context.Context, dev *core.Device) { - defer func() { - if errC := dev.Close(ctx); errC != nil { - h.Error(errC) +func MustFindTestDevice() device.Device { + var getResourceOpts func(*core.Device) deviceCoap.OptionFunc + if TestDeviceType == device.Bridged { + getResourceOpts = func(d *core.Device) deviceCoap.OptionFunc { + return deviceCoap.WithQuery("di=" + d.DeviceID()) } - }() - deviceLinks, err := dev.GetResourceLinks(ctx, dev.GetEndpoints()) - if err != nil { - h.Error(err) - return - } - l, ok := deviceLinks.GetResourceLink(device.ResourceURI) - if !ok { - return - } - var d device.Device - err = dev.GetResource(ctx, l, &d) - if err != nil { - h.Error(err) - return } - if d.Name == h.name { - h.id.Store(d.ID) - h.cancel() - } -} -func (h *findDeviceIDByNameHandler) Error(err error) { - if errors.Is(err, context.Canceled) { - return - } - log.Printf("find device ID by name handler error: %v", err.Error()) -} - -func FindDeviceByName(ctx context.Context, name string) (deviceID string, _ error) { - client := core.NewClient() - - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - h := findDeviceIDByNameHandler{ - name: name, - cancel: cancel, + var deviceID string + var err error + for i := 0; i < 3; i++ { + ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) + defer cancel() + deviceID, err = device.FindDeviceByName(ctx, TestDeviceName, getResourceOpts) + if err == nil { + break + } } - err := client.GetDevicesByMulticast(ctx, core.DefaultDiscoveryConfiguration(), &h) if err != nil { - return "", fmt.Errorf("could not find the device named %s: %w", name, err) + panic(err) } - id, ok := h.id.Load().(string) - if !ok || id == "" { - return "", fmt.Errorf("could not find the device named %s: not found", name) + + if TestDeviceType == device.Bridged { + return bridge.NewDevice(deviceID, TestDeviceName) } - return id, nil + return ocf.NewDevice(deviceID, TestDeviceName) } func IsDiscoveryResourceBatchObservable(ctx context.Context, t *testing.T, deviceID string) bool { - devClient, err := NewSDKClient() + devClient, err := sdk.NewClient() require.NoError(t, err) defer func() { _ = devClient.Close(ctx) @@ -913,15 +835,16 @@ func IsDiscoveryResourceBatchObservable(ctx context.Context, t *testing.T, devic return false } -func GetResource(ctx context.Context, deviceID, resourceURI, resourceType string, resp interface{}) error { - devClient, err := NewSDKClient() +func GetResource(ctx context.Context, deviceID, resourceURI, resourceType string, resp interface{}, opts ...deviceClient.GetOption) error { + devClient, err := sdk.NewClient() defer func() { _ = devClient.Close(ctx) }() if err != nil { return err } - err = devClient.GetResource(ctx, deviceID, resourceURI, resp, deviceClient.WithResourceTypes(resourceType)) + opts = append(opts, deviceClient.WithResourceTypes(resourceType)) + err = devClient.GetResource(ctx, deviceID, resourceURI, resp, opts...) if err != nil { return err } @@ -944,7 +867,7 @@ func GetIotivityLiteVersion(t *testing.T, deviceID string) uint32 { func DeviceIsBatchObservable(ctx context.Context, t *testing.T, deviceID string) bool { var links schema.ResourceLinks - err := GetResource(ctx, deviceID, resources.ResourceURI, resources.ResourceType, &links) + err := GetResource(ctx, deviceID, resources.ResourceURI, resources.ResourceType, &links, deviceClient.WithQuery("di="+deviceID)) require.NoError(t, err) require.Equal(t, 1, len(links)) return links[0].Policy.BitMask.Has(schema.Observable) && @@ -952,7 +875,7 @@ func DeviceIsBatchObservable(ctx context.Context, t *testing.T, deviceID string) } func GetAllBackendResourceLinks() schema.ResourceLinks { - return append(TestDevsimResources, TestDevsimBackendResources...) + return ocf.TestResources } func ProtobufToInterface(t *testing.T, val interface{}) interface{} { From c22519a39ca6223416de2540558ea4b45b45c1fe Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Fri, 9 Feb 2024 12:49:28 +0000 Subject: [PATCH 04/31] Charts: Upgrade dependencies nats 0.19.14 -> 1.1.8 mongodb 13.4.3 -> 13.18.3 --- .github/workflows/build-publish.yaml | 3 - .golangci.yml | 4 - charts/plgd-hub/Chart.lock | 8 +- charts/plgd-hub/Chart.yaml | 4 +- charts/plgd-hub/README.md | 46 ++- .../templates/certs/internal/nats-crt.yaml | 6 +- charts/plgd-hub/values.yaml | 31 +- tools/nats-server-config-reloader/Dockerfile | 19 - tools/nats-server-config-reloader/main.go | 119 ------ .../pkg/natsreloader/natsreloader.go | 355 ------------------ .../natsreloadertest/natsreloader_test.go | 125 ------ 11 files changed, 55 insertions(+), 665 deletions(-) delete mode 100644 tools/nats-server-config-reloader/Dockerfile delete mode 100644 tools/nats-server-config-reloader/main.go delete mode 100644 tools/nats-server-config-reloader/pkg/natsreloader/natsreloader.go delete mode 100644 tools/nats-server-config-reloader/pkg/natsreloader/natsreloadertest/natsreloader_test.go diff --git a/.github/workflows/build-publish.yaml b/.github/workflows/build-publish.yaml index 342d30cfd..df982ef88 100644 --- a/.github/workflows/build-publish.yaml +++ b/.github/workflows/build-publish.yaml @@ -109,9 +109,6 @@ jobs: - name: cert-tool directory: tools/cert-tool file: tools/cert-tool/Dockerfile - - name: nats-server-config-reloader - directory: tools/nats-server-config-reloader - file: tools/nats-server-config-reloader/Dockerfile uses: ./.github/workflows/build-publish-cfg.yaml with: name: ${{ matrix.name }} diff --git a/.golangci.yml b/.golangci.yml index 6373304e8..b0a433957 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -123,10 +123,6 @@ issues: - gocognit - gocyclo - gosec - - path: tools/nats-server-config-reloader/pkg/natsreloader/natsreloader.go - text: "G404:" - linters: - - gosec - path: pkg/time/delay.go text: "G404:" linters: diff --git a/charts/plgd-hub/Chart.lock b/charts/plgd-hub/Chart.lock index 63f6c64c9..5600a23bd 100644 --- a/charts/plgd-hub/Chart.lock +++ b/charts/plgd-hub/Chart.lock @@ -1,12 +1,12 @@ dependencies: - name: nats repository: https://nats-io.github.io/k8s/helm/charts/ - version: 0.19.14 + version: 1.1.8 - name: mongodb repository: https://charts.bitnami.com/bitnami - version: 13.4.3 + version: 13.18.3 - name: scylla repository: https://scylla-operator-charts.storage.googleapis.com/stable version: v1.10.0 -digest: sha256:19d6a1d0ed96e796922eeeb3d1e4920f1aea3774af332a5f8704b190a5e428fe -generated: "2023-11-03T15:24:42.261277287Z" +digest: sha256:093ffd05d3af7fbac3b5cb209351ebd25456c15eb79bfa81aa1525e139dbdec4 +generated: "2024-02-09T12:45:01.826312981Z" diff --git a/charts/plgd-hub/Chart.yaml b/charts/plgd-hub/Chart.yaml index 9dab65931..5c070c040 100644 --- a/charts/plgd-hub/Chart.yaml +++ b/charts/plgd-hub/Chart.yaml @@ -11,11 +11,11 @@ appVersion: vnext dependencies: - name: "nats" - version: "0.19.14" + version: "1.1.8" repository: "https://nats-io.github.io/k8s/helm/charts/" condition: nats.enabled - name: "mongodb" - version: "13.4.3" + version: "13.18.3" repository: "https://charts.bitnami.com/bitnami" condition: mongodb.enabled - name: "scylla" diff --git a/charts/plgd-hub/README.md b/charts/plgd-hub/README.md index 9f2c56415..6ffe125fd 100644 --- a/charts/plgd-hub/README.md +++ b/charts/plgd-hub/README.md @@ -45,8 +45,8 @@ global: | Repository | Name | Version | |------------|------|---------| -| https://charts.bitnami.com/bitnami | mongodb | 13.4.3 | -| https://nats-io.github.io/k8s/helm/charts/ | nats | 0.19.14 | +| https://charts.bitnami.com/bitnami | mongodb | 13.18.3 | +| https://nats-io.github.io/k8s/helm/charts/ | nats | 1.1.8 | | https://scylla-operator-charts.storage.googleapis.com/stable | scylla | 1.10.0 | ## Values @@ -70,11 +70,15 @@ global: | certificateauthority.clients.storage.cqlDB.keyspace.replication.class | string | `"SimpleStrategy"` | | | certificateauthority.clients.storage.cqlDB.keyspace.replication.replication_factor | int | `1` | | | certificateauthority.clients.storage.cqlDB.numConnections | int | `16` | | +| certificateauthority.clients.storage.cqlDB.port | int | `9142` | | +| certificateauthority.clients.storage.cqlDB.reconnectionPolicy.constant.interval | string | `"3s"` | | +| certificateauthority.clients.storage.cqlDB.reconnectionPolicy.constant.maxRetries | int | `3` | | | certificateauthority.clients.storage.cqlDB.table | string | `"signedCertificateRecords"` | | | certificateauthority.clients.storage.cqlDB.tls.caPool | string | `nil` | | | certificateauthority.clients.storage.cqlDB.tls.certFile | string | `nil` | | | certificateauthority.clients.storage.cqlDB.tls.keyFile | string | `nil` | | | certificateauthority.clients.storage.cqlDB.tls.useSystemCAPool | bool | `false` | | +| certificateauthority.clients.storage.cqlDB.useHostnameResolution | bool | `true` | Resolve IP address to hostname before validate certificate. If false, the TLS validator will use ip/hostname advertised by the Cassandra node. | | certificateauthority.clients.storage.mongoDB.bulkWrite.documentLimit | int | `1000` | The maximum number of documents to cache before an immediate write. | | certificateauthority.clients.storage.mongoDB.bulkWrite.throttleTime | string | `"500ms"` | The amount of time to wait until a record is written to mongodb. Any records collected during the throttle time will also be written. A throttle time of zero writes immediately. If recordLimit is reached, all records are written immediately | | certificateauthority.clients.storage.mongoDB.bulkWrite.timeout | string | `"1m0s"` | A time limit for write bulk to mongodb. A Timeout of zero means no timeout. | @@ -295,7 +299,7 @@ global: | extraAuthorizationCAPool.mountPath | string | `"/certs/extra"` | Mount path for custom auth ca pool | | extraAuthorizationCAPool.name | string | `"authorization-ca-pool"` | Name of secret for storing custom auth ca pool | | extraDeploy | string | `nil` | Extra deploy. Resolved as template | -| global | object | `{"audience":"","authority":null,"authorizationCAPool":null,"defaultCommandTimeToLive":"10s","deviceIdClaim":null,"domain":null,"enableWildCartCert":true,"hubId":null,"oauth":{"device":[],"web":{"clientID":null,"scopes":["openid"]}},"openTelemetryExporter":{"address":null,"enabled":false,"keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"ownerClaim":"sub"}` | Global config variables | +| global | object | `{"audience":"","authority":null,"authorizationCAPool":null,"defaultCommandTimeToLive":"10s","deviceIdClaim":null,"domain":null,"enableWildCartCert":true,"hubId":null,"oauth":{"device":[],"web":{"clientID":null,"scopes":["openid"]}},"openTelemetryExporter":{"address":null,"enabled":false,"keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"ownerClaim":"sub","useDatabase":"mongoDB"}` | Global config variables | | global.audience | string | `""` | OAuth audience | | global.authority | string | `nil` | OAuth authority | | global.authorizationCAPool | string | `nil` | Custom CA certificate for authorization endpoint in PEM format | @@ -311,6 +315,7 @@ global: | global.openTelemetryExporter.keepAlive | object | `{"permitWithoutStream":true,"time":"10s","timeout":"20s"}` | Expoter keep alive configuration | | global.openTelemetryExporter.tls | object | `{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}` | Expoter TLS configuration | | global.ownerClaim | string | `"sub"` | OAuth owner Claim | +| global.useDatabase | string | `"mongoDB"` | Use database. Supported values: "mongoDB", "cqlDB" | | grpcgateway.affinity | object | `{}` | Affinity definition | | grpcgateway.apis | object | `{"grpc":{"address":null,"authorization":{"audience":"","authority":"","http":{"idleConnTimeout":"30s","maxConnsPerHost":32,"maxIdleConns":16,"maxIdleConnsPerHost":16,"timeout":"10s","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":true}}},"enforcementPolicy":{"minTime":"5s","permitWithoutStream":true},"keepAlive":{"maxConnectionAge":"0s","maxConnectionAgeGrace":"0s","maxConnectionIdle":"0s","time":"2h","timeout":"20s"},"ownerCacheExpiration":"1m","recvMsgSize":4194304,"sendMsgSize":4194304,"subscriptionBufferSize":1000,"tls":{"caPool":null,"certFile":null,"clientCertificateRequired":false,"keyFile":null}}}` | For complete grpc-gateway service configuration see [plgd/grpc-gateway](https://github.com/plgd-dev/hub/tree/main/grpc-gateway) | | grpcgateway.clients | object | `{"certificateAuthority":{"grpc":{"address":"","keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}}},"eventBus":{"goPoolSize":16,"nats":{"pendingLimits":{"bytesLimit":"67108864","msgLimit":524288},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"url":null}},"identityStore":{"grpc":{"address":"","keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}}},"resourceAggregate":{"grpc":{"address":"","keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}}},"resourceDirectory":{"grpc":{"address":"","keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}}}}` | For complete grpc-gateway service configuration see [plgd/grpc-gateway](https://github.com/plgd-dev/hub/tree/main/grpc-gateway) | @@ -430,11 +435,12 @@ global: | httpgateway.service.targetPort | string | `"http"` | Target port | | httpgateway.service.type | string | `"ClusterIP"` | | | httpgateway.tolerations | object | `{}` | Toleration definition | -| httpgateway.ui | object | `{"directory":"/usr/local/var/www","enabled":true,"theme":"","webConfiguration":{"deviceOAuthClient":{"audience":null,"clientID":null,"providerName":null,"scopes":[]},"httpGatewayAddress":"","webOAuthClient":{"audience":"","clientID":"","scopes":[]}}}` | For complete http-gateway service configuration see [plgd/http-gateway](https://github.com/plgd-dev/hub/tree/main/http-gateway) | +| httpgateway.ui | object | `{"directory":"/usr/local/var/www","enabled":true,"theme":"","webConfiguration":{"deviceOAuthClient":{"audience":null,"clientID":null,"providerName":null,"scopes":[]},"deviceProvisioningService":"","httpGatewayAddress":"","visibility":{"mainSidebar":{"apiTokens":false,"certificates":true,"chatRoom":true,"configuration":true,"dashboard":false,"deviceFirmwareUpdate":false,"deviceLogs":false,"deviceProvisioning":true,"devices":true,"docs":true,"integrations":false,"pendingCommands":true,"remoteClients":true,"schemaHub":false}},"webOAuthClient":{"audience":"","clientID":"","scopes":[]}}}` | For complete http-gateway service configuration see [plgd/http-gateway](https://github.com/plgd-dev/hub/tree/main/http-gateway) | | httpgateway.uiDomain | string | `nil` | Domain for UI Default: {{ global.domain }} | | identitystore.affinity | object | `{}` | Affinity definition | | identitystore.apis | object | `{"grpc":{"address":null,"authorization":{"audience":null,"authority":null,"http":{"idleConnTimeout":"30s","maxConnsPerHost":32,"maxIdleConns":16,"maxIdleConnsPerHost":16,"timeout":"10s","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":true}},"ownerClaim":null},"enforcementPolicy":{"minTime":"5s","permitWithoutStream":true},"keepAlive":{"maxConnectionAge":"0s","maxConnectionAgeGrace":"0s","maxConnectionIdle":"0s","time":"2h","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"clientCertificateRequired":true,"keyFile":null}}}` | For complete identity service configuration see [plgd/identity](https://github.com/plgd-dev/hub/tree/main/identity) | -| identitystore.clients | object | `{"eventBus":{"nats":{"flusherTimeout":"30s","jetstream":false,"tls":{"useSystemCAPool":false},"url":""}},"storage":{"cqlDB":{"connectTimeout":"10s","hosts":[],"keyspace":{"create":true,"name":"plgdhub","replication":{"class":"SimpleStrategy","replication_factor":1}},"numConnections":16,"table":"deviceOwners","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"mongoDB":{"database":"ownersDevices","maxConnIdleTime":"4m0s","maxPoolSize":16,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"uri":null},"use":"mongoDB"}}` | For complete identity service configuration see [plgd/authorization](https://github.com/plgd-dev/hub/tree/main/identity) | +| identitystore.clients | object | `{"eventBus":{"nats":{"flusherTimeout":"30s","jetstream":false,"tls":{"useSystemCAPool":false},"url":""}},"storage":{"cqlDB":{"connectTimeout":"10s","hosts":[],"keyspace":{"create":true,"name":"plgdhub","replication":{"class":"SimpleStrategy","replication_factor":1}},"numConnections":16,"port":9142,"reconnectionPolicy":{"constant":{"interval":"3s","maxRetries":3}},"table":"deviceOwners","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"useHostnameResolution":true},"mongoDB":{"database":"ownersDevices","maxConnIdleTime":"4m0s","maxPoolSize":16,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"uri":null},"use":"mongoDB"}}` | For complete identity service configuration see [plgd/authorization](https://github.com/plgd-dev/hub/tree/main/identity) | +| identitystore.clients.storage.cqlDB.useHostnameResolution | bool | `true` | Resolve IP address to hostname before validate certificate. If false, the TLS validator will use ip/hostname advertised by the Cassandra node. | | identitystore.config | object | `{"fileName":"service.yaml","mountPath":"/config","volume":"config"}` | yaml configuration | | identitystore.config.fileName | string | `"service.yaml"` | File name | | identitystore.config.mountPath | string | `"/config"` | Service configuration mount path | @@ -553,8 +559,8 @@ global: | mockoauthserver.service.targetPort | string | `"http"` | Target port | | mockoauthserver.service.type | string | `"ClusterIP"` | | | mockoauthserver.tolerations | object | `{}` | Toleration definition | -| mongodb | object | `{"arbiter":{"enabled":false},"architecture":"replicaset","auth":{"enabled":false},"customLivenessProbe":{"exec":{"command":["/bin/bash","-c","/certs/livenessProbe.sh"]},"failureThreshold":6,"initialDelaySeconds":30,"periodSeconds":20,"successThreshold":1,"timeoutSeconds":10},"customReadinessProbe":{"exec":{"command":["bash","-ec","TLS_OPTIONS='--tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem'\n/certs/mongo $TLS_OPTIONS --eval 'db.hello().isWritablePrimary || db.hello().secondary' | grep -q 'true'\n"]},"failureThreshold":6,"initialDelaySeconds":10,"periodSeconds":20,"successThreshold":1,"timeoutSeconds":10},"enabled":true,"extraEnvVars":[{"name":"MONGODB_EXTRA_FLAGS","value":"--tlsMode=requireTLS --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem"},{"name":"MONGODB_CLIENT_EXTRA_FLAGS","value":"--tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem"}],"extraVolumeMounts":[{"mountPath":"/certs","name":"mongodb-crt"},{"mountPath":"/certs-original","name":"mongodb-cm-crt"}],"extraVolumes":[{"emptyDir":{},"name":"mongodb-crt"},{"name":"mongodb-cm-crt","secret":{"secretName":"mongodb-cm-crt"}}],"fullnameOverride":"mongodb","image":{"debug":true,"net":{"port":27017}},"initContainers":[{"command":["sh","-c","/bin/bash <<'EOF'\n#!/bin/bash\ncp /opt/bitnami/mongodb/bin/mongo /certs/mongo\necho '\nINIT=0\nwhile [[ $# -gt 0 ]]; do\n case $1 in\n --init)\n INIT=1\n shift\n ;;\n esac\ndone\n\nCERT_CRT=/certs-original/tls.crt\nCERT_SHA256=/certs/cert.sha256.$(sha256sum -z ${CERT_CRT} | cut -d \" \" -f 1)\nCA=/certs-original/ca.crt\nCA_SHA256=/certs/ca.sha256.$(sha256sum -z ${CA} | cut -d \" \" -f 1)\nROTATE_CERTIFICATES=0\nif [ ! -f ${CERT_SHA256} ]; then\n rm -f /certs/cert.sha256.*\n cat ${CERT_CRT} > /certs/cert.pem\n cat /certs-original/tls.key >> /certs/cert.pem\n touch ${CERT_SHA256}\n ROTATE_CERTIFICATES=1\nfi\n\nif [ ! -f ${CA_SHA256} ]; then\n rm -f /certs/ca.sha256.*\n cp ${CA} /certs/ca.pem\n touch ${CA_SHA256}\n ROTATE_CERTIFICATES=1\nfi\n\nif [ \"${INIT}\" == \"1\" ]; then\n exit 0\nfi\n\nif [ \"${ROTATE_CERTIFICATES}\" == \"1\" ]; then\n echo \"Rotating certificates\"\n /certs/mongo --tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem --eval db.adminCommand\\(\"{rotateCertificates: 1, message: \\\"Rotating certificates\\\"}\"\\)\nelse\n echo \"Ping database\"\n /certs/mongo --tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem --eval db.adminCommand\\(\\\"ping\\\"\\)\nfi\n' > /certs/livenessProbe.sh\nchmod u+x /certs/livenessProbe.sh\n/certs/livenessProbe.sh --init\nEOF\n"],"image":"docker.io/bitnami/mongodb:5.0.10-debian-11-r3","imagePullPolicy":"IfNotPresent","name":"mongo-binary","volumeMounts":[{"mountPath":"/certs","name":"mongodb-crt"},{"mountPath":"/certs-original","name":"mongodb-cm-crt"}]}],"livenessProbe":{"enabled":false},"persistence":{"enabled":true},"readinessProbe":{"enabled":false},"replicaCount":3,"replicaSetName":"rs0","tls":{"enabled":false}}` | External mongodb-replica dependency setup | -| nats | object | `{"cluster":{"enabled":false,"noAdvertise":false},"enabled":true,"leafnodes":{"enabled":false,"noAdvertise":false},"nats":{"tls":{"ca":"ca.crt","cert":"tls.crt","key":"tls.key","secret":{"name":"nats-service-crt"},"verify":true}},"natsbox":{"enabled":false},"reloader":{"image":"ghcr.io/plgd-dev/hub/nats-server-config-reloader:vnext","pullPolicy":"Always"}}` | External nats dependency setup | +| mongodb | object | `{"arbiter":{"enabled":false},"architecture":"replicaset","auth":{"enabled":false},"customLivenessProbe":{"exec":{"command":["/bin/bash","-c","/certs/livenessProbe.sh"]},"failureThreshold":6,"initialDelaySeconds":30,"periodSeconds":20,"successThreshold":1,"timeoutSeconds":10},"customReadinessProbe":{"exec":{"command":["bash","-ec","TLS_OPTIONS='--tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem'\n/certs/mongo $TLS_OPTIONS --eval 'db.hello().isWritablePrimary || db.hello().secondary' | grep -q 'true'\n"]},"failureThreshold":6,"initialDelaySeconds":10,"periodSeconds":20,"successThreshold":1,"timeoutSeconds":10},"enabled":true,"extraEnvVars":[{"name":"MONGODB_EXTRA_FLAGS","value":"--tlsMode=requireTLS --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem"},{"name":"MONGODB_CLIENT_EXTRA_FLAGS","value":"--tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem"}],"extraVolumeMounts":[{"mountPath":"/certs","name":"mongodb-crt"},{"mountPath":"/certs-original","name":"mongodb-cm-crt"}],"extraVolumes":[{"emptyDir":{},"name":"mongodb-crt"},{"name":"mongodb-cm-crt","secret":{"secretName":"mongodb-cm-crt"}}],"fullnameOverride":"mongodb","image":{"debug":true},"initContainers":[{"command":["sh","-c","/bin/bash <<'EOF'\n#!/bin/bash\ncp /opt/bitnami/mongodb/bin/mongo /certs/mongo\necho '\nINIT=0\nwhile [[ $# -gt 0 ]]; do\n case $1 in\n --init)\n INIT=1\n shift\n ;;\n esac\ndone\n\nCERT_CRT=/certs-original/tls.crt\nCERT_SHA256=/certs/cert.sha256.$(sha256sum -z ${CERT_CRT} | cut -d \" \" -f 1)\nCA=/certs-original/ca.crt\nCA_SHA256=/certs/ca.sha256.$(sha256sum -z ${CA} | cut -d \" \" -f 1)\nROTATE_CERTIFICATES=0\nif [ ! -f ${CERT_SHA256} ]; then\n rm -f /certs/cert.sha256.*\n cat ${CERT_CRT} > /certs/cert.pem\n cat /certs-original/tls.key >> /certs/cert.pem\n touch ${CERT_SHA256}\n ROTATE_CERTIFICATES=1\nfi\n\nif [ ! -f ${CA_SHA256} ]; then\n rm -f /certs/ca.sha256.*\n cp ${CA} /certs/ca.pem\n touch ${CA_SHA256}\n ROTATE_CERTIFICATES=1\nfi\n\nif [ \"${INIT}\" == \"1\" ]; then\n exit 0\nfi\n\nif [ \"${ROTATE_CERTIFICATES}\" == \"1\" ]; then\n echo \"Rotating certificates\"\n /certs/mongo --tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem --eval db.adminCommand\\(\"{rotateCertificates: 1, message: \\\"Rotating certificates\\\"}\"\\)\nelse\n echo \"Ping database\"\n /certs/mongo --tls --tlsCertificateKeyFile=/certs/cert.pem --tlsCAFile=/certs/ca.pem --eval db.adminCommand\\(\\\"ping\\\"\\)\nfi\n' > /certs/livenessProbe.sh\nchmod u+x /certs/livenessProbe.sh\n/certs/livenessProbe.sh --init\nEOF\n"],"image":"docker.io/bitnami/mongodb:5.0.10-debian-11-r3","imagePullPolicy":"IfNotPresent","name":"mongo-binary","volumeMounts":[{"mountPath":"/certs","name":"mongodb-crt"},{"mountPath":"/certs-original","name":"mongodb-cm-crt"}]}],"livenessProbe":{"enabled":false},"persistence":{"enabled":true},"readinessProbe":{"enabled":false},"replicaCount":3,"replicaSetName":"rs0","tls":{"enabled":false}}` | External mongodb-replica dependency setup | +| nats | object | `{"config":{"nats":{"tls":{"enabled":true,"merge":{"verify":true},"secretName":"nats-service-crt"}}},"enabled":true,"monitor":{"enabled":false},"natsBox":{"enabled":false},"tlsCA":{"enabled":true,"secretName":"nats-service-crt"}}` | External nats dependency setup | | resourceaggregate.affinity | object | `{}` | Affinity definition | | resourceaggregate.apis.grpc.address | string | `nil` | | | resourceaggregate.apis.grpc.authorization.audience | string | `nil` | | @@ -583,7 +589,8 @@ global: | resourceaggregate.apis.grpc.tls.certFile | string | `nil` | | | resourceaggregate.apis.grpc.tls.clientCertificateRequired | bool | `true` | | | resourceaggregate.apis.grpc.tls.keyFile | string | `nil` | | -| resourceaggregate.clients | object | `{"eventBus":{"nats":{"flusherTimeout":"30s","jetstream":false,"pendingLimits":{"bytesLimit":"67108864","msgLimit":524288},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"url":null}},"eventStore":{"cqlDB":{"connectTimeout":"10s","hosts":[],"keyspace":{"create":true,"name":"plgdhub","replication":{"class":"SimpleStrategy","replication_factor":1}},"numConnections":16,"table":"events","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"defaultCommandTimeToLive":null,"mongoDB":{"batchSize":128,"database":"eventStore","maxConnIdleTime":"4m0s","maxPoolSize":16,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"uri":null},"occMaxRetry":8,"use":"mongoDB"},"identityStore":{"grpc":{"address":null,"keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}}}}` | For complete resource-aggregate service configuration see [plgd/resource-aggregate](https://github.com/plgd-dev/hub/tree/main/resource-aggregate) | +| resourceaggregate.clients | object | `{"eventBus":{"nats":{"flusherTimeout":"30s","jetstream":false,"pendingLimits":{"bytesLimit":"67108864","msgLimit":524288},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"url":null}},"eventStore":{"cqlDB":{"connectTimeout":"10s","hosts":[],"keyspace":{"create":true,"name":"plgdhub","replication":{"class":"SimpleStrategy","replication_factor":1}},"numConnections":16,"port":9142,"reconnectionPolicy":{"constant":{"interval":"3s","maxRetries":3}},"table":"events","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"useHostnameResolution":true},"defaultCommandTimeToLive":null,"mongoDB":{"batchSize":128,"database":"eventStore","maxConnIdleTime":"4m0s","maxPoolSize":16,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"uri":null},"occMaxRetry":8,"use":"mongoDB"},"identityStore":{"grpc":{"address":null,"keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}}}}` | For complete resource-aggregate service configuration see [plgd/resource-aggregate](https://github.com/plgd-dev/hub/tree/main/resource-aggregate) | +| resourceaggregate.clients.eventStore.cqlDB.useHostnameResolution | bool | `true` | Resolve IP address to hostname before validate certificate. If false, the TLS validator will use ip/hostname advertised by the Cassandra node. | | resourceaggregate.config | object | `{"fileName":"service.yaml","mountPath":"/config","volume":"config"}` | Service configuration | | resourceaggregate.config.fileName | string | `"service.yaml"` | Service configuration file name | | resourceaggregate.config.mountPath | string | `"/config"` | Configuration mount path | @@ -636,7 +643,8 @@ global: | resourceaggregate.tolerations | object | `{}` | Toleration definition | | resourcedirectory.affinity | object | `{}` | Affinity definition | | resourcedirectory.apis | object | `{"grpc":{"address":null,"authorization":{"audience":null,"authority":null,"http":{"idleConnTimeout":"30s","maxConnsPerHost":32,"maxIdleConns":16,"maxIdleConnsPerHost":16,"timeout":"10s","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":true}},"ownerClaim":null},"enforcementPolicy":{"minTime":"5s","permitWithoutStream":true},"keepAlive":{"maxConnectionAge":"0s","maxConnectionAgeGrace":"0s","maxConnectionIdle":"0s","time":"2h","timeout":"20s"},"ownerCacheExpiration":"1m","recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"clientCertificateRequired":true,"keyFile":null}}}` | For complete resource-directory service configuration see [plgd/resource-directory](https://github.com/plgd-dev/hub/tree/main/resource-directory) | -| resourcedirectory.clients | object | `{"eventBus":{"goPoolSize":16,"nats":{"pendingLimits":{"bytesLimit":"67108864","msgLimit":"524288"},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"url":""}},"eventStore":{"cacheExpiration":"20m","cqlDB":{"connectTimeout":"10s","hosts":[],"keyspace":{"create":true,"name":"plgdhub","replication":{"class":"SimpleStrategy","replication_factor":1}},"numConnections":16,"table":"events","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"mongoDB":{"batchSize":128,"database":"eventStore","maxConnIdleTime":"4m0s","maxPoolSize":16,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"uri":""},"use":"mongoDB"},"identityStore":{"cacheExpiration":"1m","grpc":{"address":"","keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"oauth":{"audience":"","clientID":null,"clientSecret":null,"http":{"idleConnTimeout":"30s","maxConnsPerHost":32,"maxIdleConns":16,"maxIdleConnsPerHost":16,"timeout":"10s","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"scopes":[],"tokenURL":"","verifyServiceTokenFrequency":"10s"},"ownerClaim":null,"pullFrequency":"15s"}}` | For complete resource-directory service configuration see [plgd/resource-directory](https://github.com/plgd-dev/hub/tree/main/resource-directory) | +| resourcedirectory.clients | object | `{"eventBus":{"goPoolSize":16,"nats":{"pendingLimits":{"bytesLimit":"67108864","msgLimit":"524288"},"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"url":""}},"eventStore":{"cacheExpiration":"20m","cqlDB":{"connectTimeout":"10s","hosts":[],"keyspace":{"create":true,"name":"plgdhub","replication":{"class":"SimpleStrategy","replication_factor":1}},"numConnections":16,"port":9142,"reconnectionPolicy":{"constant":{"interval":"3s","maxRetries":3}},"table":"events","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"useHostnameResolution":true},"mongoDB":{"batchSize":128,"database":"eventStore","maxConnIdleTime":"4m0s","maxPoolSize":16,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false},"uri":""},"use":"mongoDB"},"identityStore":{"cacheExpiration":"1m","grpc":{"address":"","keepAlive":{"permitWithoutStream":true,"time":"10s","timeout":"20s"},"recvMsgSize":4194304,"sendMsgSize":4194304,"tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"oauth":{"audience":"","clientID":null,"clientSecret":null,"http":{"idleConnTimeout":"30s","maxConnsPerHost":32,"maxIdleConns":16,"maxIdleConnsPerHost":16,"timeout":"10s","tls":{"caPool":null,"certFile":null,"keyFile":null,"useSystemCAPool":false}},"scopes":[],"tokenURL":"","verifyServiceTokenFrequency":"10s"},"ownerClaim":null,"pullFrequency":"15s"}}` | For complete resource-directory service configuration see [plgd/resource-directory](https://github.com/plgd-dev/hub/tree/main/resource-directory) | +| resourcedirectory.clients.eventStore.cqlDB.useHostnameResolution | bool | `true` | Resolve IP address to hostname before validate certificate. If false, the TLS validator will use ip/hostname advertised by the Cassandra node. | | resourcedirectory.config | object | `{"fileName":"service.yaml","mountPath":"/config","volume":"config"}` | Service configuration | | resourcedirectory.config.fileName | string | `"service.yaml"` | Service configuration file | | resourcedirectory.config.mountPath | string | `"/config"` | Configuration mount path | @@ -687,9 +695,23 @@ global: | resourcedirectory.service.targetPort | string | `"grpc"` | Target port | | resourcedirectory.service.type | string | `"ClusterIP"` | resource-directory service type | | resourcedirectory.tolerations | object | `{}` | Toleration definition | -| scylla.datacenter | string | `"dc1"` | | -| scylla.enabled | bool | `false` | | +| scylla.datacenter | string | `"dc-1"` | | +| scylla.enabled | bool | `false` | Enable scylla service. Required scylla operator: https://github.com/scylladb/scylla-operator/blob/master/docs/source/generic.md#deploy-scylla-operator | +| scylla.racks[0].members | int | `3` | | +| scylla.racks[0].name | string | `"dc-1a"` | | +| scylla.racks[0].resources.limits.cpu | int | `1` | | +| scylla.racks[0].resources.limits.memory | string | `"4Gi"` | | +| scylla.racks[0].resources.requests.cpu | int | `1` | | +| scylla.racks[0].resources.requests.memory | string | `"4Gi"` | | +| scylla.racks[0].scyllaConfig | string | `"scylla-cfg"` | | +| scylla.racks[0].storage.capacity | string | `"10Gi"` | | +| scylla.racks[0].volumeMounts[0].mountPath | string | `"/certs"` | | +| scylla.racks[0].volumeMounts[0].name | string | `"scylla-certs-volume"` | | +| scylla.racks[0].volumes[0].name | string | `"scylla-certs-volume"` | | +| scylla.racks[0].volumes[0].secret.secretName | string | `"scylla-dc-1a-crt"` | | +| scylla.scyllaImage.tag | string | `"5.2.9"` | | +| scylla.sysctls[0] | string | `"fs.aio-max-nr=2097152"` | | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.11.3](https://github.com/norwoodj/helm-docs/releases/v1.11.3) +Autogenerated from chart metadata using [helm-docs v1.12.0](https://github.com/norwoodj/helm-docs/releases/v1.12.0) diff --git a/charts/plgd-hub/templates/certs/internal/nats-crt.yaml b/charts/plgd-hub/templates/certs/internal/nats-crt.yaml index d425bcb18..a800f32de 100644 --- a/charts/plgd-hub/templates/certs/internal/nats-crt.yaml +++ b/charts/plgd-hub/templates/certs/internal/nats-crt.yaml @@ -1,14 +1,14 @@ -{{- if and .Values.nats.enabled .Values.certmanager.enabled }} +{{- if and .Values.nats.enabled .Values.certmanager.enabled .Values.nats.config.nats.tls.enabled }} {{- $natsServiceName := printf "%s-nats" ( include "nats.fullname" . ) }} apiVersion: cert-manager.io/v1 kind: Certificate metadata: - name: {{ .Values.nats.nats.tls.secret.name }} + name: {{ .Values.nats.config.nats.tls.secretName }} namespace: {{ .Release.Namespace }} labels: {{- include "plgd-hub.labels" . | nindent 4 }} spec: - secretName: {{ .Values.nats.nats.tls.secret.name }} + secretName: {{ .Values.nats.config.nats.tls.secretName }} privateKey: algorithm: {{ .Values.certmanager.internal.cert.key.algorithm | default .Values.certmanager.default.cert.key.algorithm }} size: {{ .Values.certmanager.internal.cert.key.size | default .Values.certmanager.default.cert.key.size }} diff --git a/charts/plgd-hub/values.yaml b/charts/plgd-hub/values.yaml index 4d9a252f0..811daff00 100644 --- a/charts/plgd-hub/values.yaml +++ b/charts/plgd-hub/values.yaml @@ -56,25 +56,20 @@ extraDeploy: # -- External nats dependency setup nats: enabled: true - nats: - tls: - secret: - name: nats-service-crt - ca: ca.crt - cert: tls.crt - key: tls.key - verify: true - cluster: - enabled: false - noAdvertise: false - leafnodes: + tlsCA: + enabled: true + secretName: nats-service-crt + config: + nats: + tls: + enabled: true + secretName: nats-service-crt + merge: + verify: true + natsBox: enabled: false - noAdvertise: false - natsbox: + monitor: enabled: false - reloader: - image: ghcr.io/plgd-dev/hub/nats-server-config-reloader:vnext - pullPolicy: Always # -- External mongodb-replica dependency setup @@ -92,8 +87,6 @@ mongodb: enabled: false image: debug: true - net: - port: 27017 tls: enabled: false extraEnvVars: diff --git a/tools/nats-server-config-reloader/Dockerfile b/tools/nats-server-config-reloader/Dockerfile deleted file mode 100644 index 20aaf5bfd..000000000 --- a/tools/nats-server-config-reloader/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM golang:1.20.13-alpine AS build -RUN apk add --no-cache curl git build-base -WORKDIR $GOPATH/src/github.com/plgd-dev/hub -COPY go.mod go.sum ./ -RUN go mod download -COPY . . -RUN go mod vendor -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) -RUN ( cd ./vendor/golang.org/x/oauth2 && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/golang_org_x_oauth2_propagate_error.patch ) -WORKDIR $GOPATH/src/github.com/plgd-dev/hub/tools/nats-server-config-reloader -RUN CGO_ENABLED=0 go build -mod=vendor -o /go/bin/nats-server-config-reloader . - -FROM alpine:3.19 AS security-provider -RUN apk add -U --no-cache ca-certificates - -FROM scratch AS service -COPY --from=security-provider /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ -COPY --from=build /go/bin/nats-server-config-reloader /usr/local/bin/nats-server-config-reloader -ENTRYPOINT [ /usr/local/bin/nats-server-config-reloader ] \ No newline at end of file diff --git a/tools/nats-server-config-reloader/main.go b/tools/nats-server-config-reloader/main.go deleted file mode 100644 index 8eba9a121..000000000 --- a/tools/nats-server-config-reloader/main.go +++ /dev/null @@ -1,119 +0,0 @@ -package main - -import ( - "context" - "errors" - "flag" - "fmt" - "log" - "os" - "os/signal" - "strings" - "syscall" - - "github.com/plgd-dev/hub/v2/tools/nats-server-config-reloader/pkg/natsreloader" -) - -var ( - BuildTime = "build-time-not-set" - GitInfo = "gitinfo-not-set" - Version = "version-not-set" -) - -const errorFmt = natsreloader.ErrorFmt - -// StringSet is a wrapper for []string to allow using it with the flags package. -type StringSet []string - -func (s *StringSet) String() string { - return strings.Join([]string(*s), ", ") -} - -// Set appends the value provided to the list of strings. -func (s *StringSet) Set(val string) error { - *s = append(*s, val) - return nil -} - -func main() { - fs := flag.NewFlagSet("nats-server-config-reloader", flag.ExitOnError) - flag.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage: nats-server-config-reloader [options...]\n\n") - fs.PrintDefaults() - fmt.Fprintf(os.Stderr, "\n") - } - - // Help and version - var ( - showHelp bool - showVersion bool - fileSet StringSet - customSignal int - ) - - nconfig := &natsreloader.Config{} - fs.BoolVar(&showHelp, "h", false, "Show help") - fs.BoolVar(&showHelp, "help", false, "Show help") - fs.BoolVar(&showVersion, "v", false, "Show version") - fs.BoolVar(&showVersion, "version", false, "Show version") - - fs.StringVar(&nconfig.PidFile, "P", "/var/run/nats/gnatsd.pid", "NATS Server Pid File") - fs.StringVar(&nconfig.PidFile, "pid", "/var/run/nats/gnatsd.pid", "NATS Server Pid File") - fs.Var(&fileSet, "c", "NATS Server Config File (may be repeated to specify more than one)") - fs.Var(&fileSet, "config", "NATS Server Config File (may be repeated to specify more than one)") - fs.IntVar(&nconfig.MaxRetries, "max-retries", 5, "Max attempts to trigger reload") - fs.IntVar(&nconfig.RetryWaitSecs, "retry-wait-secs", 2, "Time to back off when reloading fails before retrying") - fs.IntVar(&customSignal, "signal", 1, "Signal to send to the NATS Server process (default SIGHUP 1)") - - err := fs.Parse(os.Args[1:]) - if err != nil { - fmt.Fprintf(os.Stderr, errorFmt, err) - os.Exit(1) - } - - nconfig.ConfigFiles = fileSet - if len(fileSet) == 0 { - nconfig.ConfigFiles = []string{"/etc/nats-config/gnatsd.conf"} - } - nconfig.Signal = syscall.Signal(customSignal) - - switch { - case showHelp: - flag.Usage() - os.Exit(0) - case showVersion: - fmt.Fprintf(os.Stderr, "NATS Server Config Reloader v%s (%s, %s)\n", Version, GitInfo, BuildTime) - os.Exit(0) - } - r, err := natsreloader.NewReloader(nconfig) - if err != nil { - fmt.Fprintf(os.Stderr, errorFmt, err) - os.Exit(1) - } - - // Signal handling. - go func() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) - - for sig := range c { - log.Printf("Trapped \"%v\" signal\n", sig) - switch sig { - case syscall.SIGINT: - log.Println("Exiting...") - os.Exit(0) - return - case syscall.SIGTERM: - _ = r.Stop() - return - } - } - }() - - log.Printf("Starting NATS Server Reloader v%s\n", Version) - err = r.Run(context.Background()) - if err != nil && !errors.Is(err, context.Canceled) { - fmt.Fprintf(os.Stderr, errorFmt, err.Error()) - os.Exit(1) - } -} diff --git a/tools/nats-server-config-reloader/pkg/natsreloader/natsreloader.go b/tools/nats-server-config-reloader/pkg/natsreloader/natsreloader.go deleted file mode 100644 index 51c4c60bd..000000000 --- a/tools/nats-server-config-reloader/pkg/natsreloader/natsreloader.go +++ /dev/null @@ -1,355 +0,0 @@ -package natsreloader - -import ( - "bytes" - "context" - "crypto/sha256" - "fmt" - "io" - "log" - "math/rand" - "os" - "path/filepath" - "sort" - "strconv" - "time" - - "github.com/fsnotify/fsnotify" -) - -const ErrorFmt = "Error: %s\n" - -// Config represents the configuration of the reloader. -type Config struct { - PidFile string - ConfigFiles []string - MaxRetries int - RetryWaitSecs int - Signal os.Signal -} - -// Reloader monitors the state from a single server config file -// and sends signal on updates. -type Reloader struct { - *Config - - // proc represents the NATS Server process which will - // be signaled. - proc *os.Process - - // pid is the last known PID from the NATS Server. - pid int - - // quit shutsdown the reloader. - quit func() -} - -func (r *Reloader) waitForProcess() error { - var proc *os.Process - var pid int - attempts := 0 - - startTime := time.Now() - for { - pidfile, err := os.ReadFile(r.PidFile) - if err != nil { - goto WaitAndRetry - } - - pid, err = strconv.Atoi(string(pidfile)) - if err != nil { - goto WaitAndRetry - } - - proc, err = os.FindProcess(pid) - if err != nil { - goto WaitAndRetry - } - break - - WaitAndRetry: - log.Printf(ErrorFmt, err) - attempts++ - if attempts > r.MaxRetries { - return fmt.Errorf("too many errors attempting to find server process") - } - time.Sleep(time.Duration(r.RetryWaitSecs) * time.Second) - } - - if attempts > 0 { - log.Printf("found pid from pidfile %q after %v failed attempts (%v time after start)", - r.PidFile, attempts, time.Since(startTime)) - } - - r.pid = pid - r.proc = proc - return nil -} - -func removeDuplicateStrings(s []string) []string { - if len(s) < 1 { - return s - } - - sort.Strings(s) - prev := 1 - for curr := 1; curr < len(s); curr++ { - if s[curr-1] != s[curr] { - s[prev] = s[curr] - prev++ - } - } - - return s[:prev] -} - -func calcDigest(filePath string) ([]byte, error) { - h := sha256.New() - f, err := os.Open(filePath) - if err != nil { - return nil, err - } - defer func() { - _ = f.Close() - }() - if _, err := io.Copy(h, f); err != nil { - return nil, err - } - return h.Sum(nil), nil -} - -func handleEvent(event fsnotify.Event, lastConfigAppliedCache map[string][]byte, updatedFiles, deletedFiles []string) ([]string, []string) { - if event.Op&fsnotify.Remove == fsnotify.Remove { - // We don't get a Remove event for the directory itself, so - // we need to detect that separately. - return updatedFiles, append(deletedFiles, event.Name) - } - _, err := os.Stat(event.Name) - if err != nil { - // Beware that this means that we won't reconfigure if a file - // is permanently removed. We want to support transient - // disappearance, waiting for the new content, and have not set - // up any sort of longer-term timers to detect permanent - // deletion. - // If you really need this, then switch a file to be empty - // before removing if afterwards. - return updatedFiles, deletedFiles - } - - if len(updatedFiles) > 0 { - return updatedFiles, deletedFiles - } - digest, err := calcDigest(event.Name) - if err != nil { - log.Printf(ErrorFmt, err) - return updatedFiles, deletedFiles - } - - lastConfigHash, ok := lastConfigAppliedCache[event.Name] - if ok && bytes.Equal(lastConfigHash, digest) { - return updatedFiles, deletedFiles - } - - log.Printf("changed config; file=%q existing=%v total-files=%d", - event.Name, ok, len(lastConfigAppliedCache)) - lastConfigAppliedCache[event.Name] = digest - return append(updatedFiles, event.Name), deletedFiles -} - -// handleEvents handles all events in the queue. It returns the updated and deleted files and can contain duplicates. -func handleEvents(configWatcher *fsnotify.Watcher, event fsnotify.Event, lastConfigAppliedCache map[string][]byte) ([]string, []string) { - updatedFiles, deletedFiles := handleEvent(event, lastConfigAppliedCache, make([]string, 0, 16), make([]string, 0, 16)) - for { - select { - case event := <-configWatcher.Events: - updatedFiles, deletedFiles = handleEvent(event, lastConfigAppliedCache, updatedFiles, deletedFiles) - default: - return updatedFiles, deletedFiles - } - } -} - -func handleDeletedFiles(deletedFiles []string, configWatcher *fsnotify.Watcher, lastConfigAppliedCache map[string][]byte) ([]string, []string) { - log.Printf("Ticker is running with deletedFiles %v", deletedFiles) - newDeletedFiles := make([]string, 0, len(deletedFiles)) - updated := make([]string, 0, len(deletedFiles)) - for _, f := range deletedFiles { - if err := configWatcher.Add(f); err != nil { - newDeletedFiles = append(newDeletedFiles, f) - } else { - updated, _ = handleEvent(fsnotify.Event{Name: f, Op: fsnotify.Create}, lastConfigAppliedCache, updated, nil) - } - } - return removeDuplicateStrings(updated), newDeletedFiles -} - -func (r *Reloader) init() (*fsnotify.Watcher, map[string][]byte, error) { - err := r.waitForProcess() - if err != nil { - return nil, nil, err - } - - configWatcher, err := fsnotify.NewWatcher() - if err != nil { - return nil, nil, err - } - - // Follow configuration updates in the directory where - // the config file is located and trigger reload when - // it is either recreated or written into. - for i := range r.ConfigFiles { - // Ensure our paths are canonical - r.ConfigFiles[i], _ = filepath.Abs(r.ConfigFiles[i]) - } - r.ConfigFiles = removeDuplicateStrings(r.ConfigFiles) - // Follow configuration file updates and trigger reload when - // it is either recreated or written into. - for i := range r.ConfigFiles { - // Watch files individually for https://github.com/kubernetes/kubernetes/issues/112677 - if err := configWatcher.Add(r.ConfigFiles[i]); err != nil { - _ = configWatcher.Close() - return nil, nil, err - } - log.Printf("watching file: %v", r.ConfigFiles[i]) - } - - // lastConfigAppliedCache is the last config update - // applied by us - lastConfigAppliedCache := make(map[string][]byte) - - // Preload config hashes, so we know their digests - // up front and avoid potentially reloading when unnecessary. - for _, configFile := range r.ConfigFiles { - digest, err := calcDigest(configFile) - if err != nil { - _ = configWatcher.Close() - return nil, nil, err - } - lastConfigAppliedCache[configFile] = digest - } - - // If the two pids don't match then os.FindProcess() has done something - // rather hinkier than we expect, but log them both just in case on some - // future platform there's a weird namespace issue, as a difference will - // help with debugging. - log.Printf("Live, ready to kick pid %v (live, from %v spec) based on any of %v files", - r.proc.Pid, r.pid, len(lastConfigAppliedCache)) - - if len(lastConfigAppliedCache) == 0 { - log.Printf("Error: no watched config files cached; input spec was: %#v", - r.ConfigFiles) - } - return configWatcher, lastConfigAppliedCache, nil -} - -func (r *Reloader) reload(updatedFiles []string) error { - attempts := 0 - for { - log.Printf("Sending signal '%s' to server to reload configuration due to: %s", r.Signal.String(), updatedFiles) - err := r.proc.Signal(r.Signal) - if err == nil { - return nil - } - log.Printf("Error during reload: %s\n", err) - if attempts > r.MaxRetries { - return fmt.Errorf("too many errors (%v) attempting to signal server to reload: %w", attempts, err) - } - delay := retryJitter(time.Duration(r.RetryWaitSecs) * time.Second) - log.Printf("Wait and retrying after some time [%v] ...", delay) - time.Sleep(delay) - attempts++ - } -} - -// Run starts the main loop. -func (r *Reloader) Run(ctx context.Context) error { - ctx, cancel := context.WithCancel(ctx) - r.quit = func() { - cancel() - } - - configWatcher, lastConfigAppliedCache, err := r.init() - if err != nil { - return err - } - defer func() { - _ = configWatcher.Close() - }() - - // We use a ticker to re-add deleted files to the watcher - t := time.NewTicker(time.Second) - t.Stop() - defer t.Stop() - var tickerRunning bool - var deletedFiles []string - var updatedFiles []string - - for { - select { - case <-ctx.Done(): - return nil - case <-t.C: - updatedFiles, deletedFiles = handleDeletedFiles(deletedFiles, configWatcher, lastConfigAppliedCache) - if len(deletedFiles) == 0 { - // No more deleted files, stop the ticker - t.Stop() - tickerRunning = false - } - if len(updatedFiles) > 0 { - // Send signal to reload the config - log.Printf("Updated files: %v", updatedFiles) - break - } - continue - // Check if the process is still alive - case event := <-configWatcher.Events: - updated, deleted := handleEvents(configWatcher, event, lastConfigAppliedCache) - updatedFiles = removeDuplicateStrings(updated) - deletedFiles = removeDuplicateStrings(append(deletedFiles, deleted...)) - if !tickerRunning { - // Start the ticker to re-add deleted files - t.Reset(time.Second) - tickerRunning = true - } - if len(updatedFiles) > 0 { - // Send signal to reload the config - log.Printf("Updated files: %v", updatedFiles) - break - } - continue - case err := <-configWatcher.Errors: - log.Printf(ErrorFmt, err) - continue - } - // Configuration was updated, try to do reload for a few times - // otherwise give up and wait for next event. - err := r.reload(updatedFiles) - if err != nil { - return err - } - updatedFiles = nil - } -} - -// Stop shutsdown the process. -func (r *Reloader) Stop() error { - log.Println("Shutting down...") - r.quit() - return nil -} - -// NewReloader returns a configured NATS server reloader. -func NewReloader(config *Config) (*Reloader, error) { - return &Reloader{ - Config: config, - }, nil -} - -// retryJitter helps avoid trying things at synchronized times, thus improving -// resiliency in aggregate. -func retryJitter(base time.Duration) time.Duration { - b := float64(base) - // 10% +/- - offset := rand.Float64()*0.2 - 0.1 - return time.Duration(b + offset) -} diff --git a/tools/nats-server-config-reloader/pkg/natsreloader/natsreloadertest/natsreloader_test.go b/tools/nats-server-config-reloader/pkg/natsreloader/natsreloadertest/natsreloader_test.go deleted file mode 100644 index d25772ffc..000000000 --- a/tools/nats-server-config-reloader/pkg/natsreloader/natsreloadertest/natsreloader_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package natsreloadertest - -import ( - "context" - "errors" - "fmt" - "os" - "os/signal" - "sync" - "syscall" - "testing" - "time" - - "github.com/plgd-dev/hub/v2/tools/nats-server-config-reloader/pkg/natsreloader" -) - -var ( - configContents = `port = 2222` - newConfigContents = `port = 2222 -someOtherThing = "bar" -` -) - -func TestReloader(t *testing.T) { - // Setup a pidfile that points to us - pid := os.Getpid() - pidfile, err := os.CreateTemp(os.TempDir(), "nats-pid-") - if err != nil { - t.Fatal(err) - } - - p := fmt.Sprintf("%d", pid) - if _, err := pidfile.WriteString(p); err != nil { - t.Fatal(err) - } - defer os.Remove(pidfile.Name()) - - // Create tempfile with contents, then update it - nconfig := &natsreloader.Config{ - PidFile: pidfile.Name(), - ConfigFiles: []string{}, - Signal: syscall.SIGHUP, - } - - var configFiles []*os.File - for i := 0; i < 2; i++ { - configFile, err := os.CreateTemp(os.TempDir(), "nats-conf-") - if err != nil { - t.Fatal(err) - } - defer os.Remove(configFile.Name()) - - if _, err := configFile.WriteString(configContents); err != nil { - t.Fatal(err) - } - configFiles = append(configFiles, configFile) - nconfig.ConfigFiles = append(nconfig.ConfigFiles, configFile.Name()) - } - - r, err := natsreloader.NewReloader(nconfig) - if err != nil { - t.Fatal(err) - } - - signals := 0 - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - var sigsMu sync.Mutex - - // Signal handling. - go func() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGHUP) - - // Success when receiving the first signal - for range c { - sigsMu.Lock() - signals++ - sigsMu.Unlock() - } - }() - - go func() { - // This is terrible, but we need this thread to wait until r.Run(ctx) has finished starting up - // before we start mucking with the file. - // There isn't any other good way to synchronize on this happening. - time.Sleep(100 * time.Millisecond) - for _, configfile := range configFiles { - for i := 0; i < 5; i++ { - // Append some more stuff to the config - if _, err := configfile.WriteAt([]byte(newConfigContents), 0); err != nil { - return - } - time.Sleep(10 * time.Millisecond) - } - } - - // Create some random file in the same directory, shouldn't trigger an - // additional server signal. - configFile, err := os.CreateTemp(os.TempDir(), "foo") - if err != nil { - t.Log(err) - return - } - defer os.Remove(configFile.Name()) - time.Sleep(100 * time.Millisecond) - - cancel() - }() - - err = r.Run(ctx) - if err != nil && !errors.Is(err, context.Canceled) { - t.Fatal(err) - } - // We should have gotten only one signal for each configuration file - sigsMu.Lock() - got := signals - sigsMu.Unlock() - expected := len(configFiles) - if got != expected { - t.Fatalf("Wrong number of signals received. Expected: %v, got: %v", expected, got) - } -} From b20c02ad4e6101783d681ae99b6574e93a468025 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Fri, 16 Feb 2024 10:47:05 +0000 Subject: [PATCH 05/31] fix linter (mainly revive) --- certificate-authority/store/mongodb/store.go | 4 +-- .../service/deviceSubscriptionHandlers.go | 2 +- .../service/requestHandler.go | 2 +- cloud2cloud-connector/store/mongodb/store.go | 4 +-- cloud2cloud-gateway/service/httpApi.go | 2 +- .../service/subscriptionManager.go | 2 +- cloud2cloud-gateway/store/mongodb/store.go | 4 +-- coap-gateway/service/auth.go | 4 +-- coap-gateway/service/log.go | 2 +- .../service/observation/observation_test.go | 2 +- http-gateway/serverMux/router.go | 2 +- http-gateway/service/subscribeToEvents.go | 2 +- identity-store/client/ownerCache.go | 1 - identity-store/client/ownerCache_test.go | 2 +- pkg/cqldb/cqldb.go | 4 +-- pkg/fsnotify/fsnotify_test.go | 2 +- pkg/log/log.go | 2 +- pkg/net/coap/service/service_test.go | 8 +++--- pkg/net/grpc/server/makeDefaultOptions.go | 4 +-- pkg/net/http/interceptor.go | 2 +- pkg/net/http/loggingMiddleware.go | 2 +- pkg/security/jwt/claims_test.go | 2 +- pkg/security/jwt/scopeClaims_test.go | 2 +- .../cqrs/aggregate/aggregate.go | 2 +- .../cqrs/eventstore/mongodb/eventstore.go | 2 +- .../cqrs/eventstore/projection.go | 2 +- .../cqrs/projection/projection.go | 6 ++--- .../cqrs/projection/projection_test.go | 14 +++++----- resource-aggregate/service/aggregate.go | 10 +++---- resource-aggregate/service/service.go | 2 +- .../service/updateDeviceMetadata.go | 2 +- .../service/updateServiceHeartbeat.go | 4 +-- resource-directory/service/grpcApi.go | 2 +- test/http/request.go | 2 +- .../service/deleteResource_test.go | 2 +- test/iotivity-lite/service/offboard_test.go | 14 +++++----- test/iotivity-lite/service/republish_test.go | 2 +- test/oauth-server/test/test.go | 2 +- test/pb/event.go | 26 +++++++++---------- test/security/jwk.go | 2 +- test/virtual-device/cmd/main.go | 2 +- 41 files changed, 78 insertions(+), 83 deletions(-) diff --git a/certificate-authority/store/mongodb/store.go b/certificate-authority/store/mongodb/store.go index f1c1bb5b5..90b0115cf 100644 --- a/certificate-authority/store/mongodb/store.go +++ b/certificate-authority/store/mongodb/store.go @@ -49,9 +49,7 @@ func New(ctx context.Context, cfg *Config, fileWatcher *fsnotify.Watcher, logger certManager.Close() return nil, err } - s.SetOnClear(func(c context.Context) error { - return s.clearDatabases(ctx) - }) + s.SetOnClear(s.clearDatabases) s.AddCloseFunc(certManager.Close) return &s, nil } diff --git a/cloud2cloud-connector/service/deviceSubscriptionHandlers.go b/cloud2cloud-connector/service/deviceSubscriptionHandlers.go index 2f9b0276d..02521db54 100644 --- a/cloud2cloud-connector/service/deviceSubscriptionHandlers.go +++ b/cloud2cloud-connector/service/deviceSubscriptionHandlers.go @@ -115,7 +115,7 @@ func (c *DevicesSubscription) Add(ctx context.Context, deviceID string, linkedAc return retrieveResource(ctx, c.tracerProvider, c.raClient, val, linkedAccount, linkedCloud) }, onError: func(err error) { - log.Errorf("device %v subscription(ResourceUpdatePending, ResourceRetrievePending) was closed", deviceID) + log.Errorf("device %v subscription(ResourceUpdatePending, ResourceRetrievePending) was closed: %w", deviceID, err) c.data.Delete(getKey(linkedAccount.UserID, deviceID)) }, }) diff --git a/cloud2cloud-connector/service/requestHandler.go b/cloud2cloud-connector/service/requestHandler.go index f8bfa780d..265cfe217 100644 --- a/cloud2cloud-connector/service/requestHandler.go +++ b/cloud2cloud-connector/service/requestHandler.go @@ -82,7 +82,7 @@ func NewHTTP(requestHandler *RequestHandler, authInterceptor kitNetHttp.Intercep r := router.NewRouter() r.StrictSlash(true) r.Use(kitNetHttp.CreateLoggingMiddleware(kitNetHttp.WithLogger(logger))) - r.Use(kitNetHttp.CreateAuthMiddleware(authInterceptor, func(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) { + r.Use(kitNetHttp.CreateAuthMiddleware(authInterceptor, func(_ context.Context, w http.ResponseWriter, r *http.Request, err error) { logAndWriteErrorResponse(fmt.Errorf("cannot process request on %v: %w", r.RequestURI, err), http.StatusUnauthorized, w) })) diff --git a/cloud2cloud-connector/store/mongodb/store.go b/cloud2cloud-connector/store/mongodb/store.go index eccf4c4b5..205661dd7 100644 --- a/cloud2cloud-connector/store/mongodb/store.go +++ b/cloud2cloud-connector/store/mongodb/store.go @@ -19,9 +19,7 @@ func NewStore(ctx context.Context, cfg pkgMongo.Config, tls *tls.Config, tracerP return nil, err } s := Store{m} - s.SetOnClear(func(c context.Context) error { - return s.clearDatabases(ctx) - }) + s.SetOnClear(s.clearDatabases) return &s, nil } diff --git a/cloud2cloud-gateway/service/httpApi.go b/cloud2cloud-gateway/service/httpApi.go index 968f254c0..b8df6758f 100644 --- a/cloud2cloud-gateway/service/httpApi.go +++ b/cloud2cloud-gateway/service/httpApi.go @@ -172,7 +172,7 @@ func NewHTTP(requestHandler *RequestHandler, authInterceptor kitNetHttp.Intercep r := router.NewRouter() r.StrictSlash(true) r.Use(kitNetHttp.CreateLoggingMiddleware(kitNetHttp.WithLogger(logger))) - r.Use(kitNetHttp.CreateAuthMiddleware(authInterceptor, func(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) { + r.Use(kitNetHttp.CreateAuthMiddleware(authInterceptor, func(_ context.Context, w http.ResponseWriter, r *http.Request, err error) { logAndWriteErrorResponse(fmt.Errorf("cannot process request on %v: %w", r.RequestURI, err), http.StatusUnauthorized, w) })) diff --git a/cloud2cloud-gateway/service/subscriptionManager.go b/cloud2cloud-gateway/service/subscriptionManager.go index eac5d2795..d73ecc85e 100644 --- a/cloud2cloud-gateway/service/subscriptionManager.go +++ b/cloud2cloud-gateway/service/subscriptionManager.go @@ -108,7 +108,7 @@ func (s *SubscriptionManager) Load(id string) (store.Subscription, bool) { } func cancelSubscription(ctx context.Context, emitEvent emitEventFunc, sub store.Subscription) error { - _, err := emitEvent(ctx, events.EventType_SubscriptionCanceled, sub, func(ctx context.Context) (uint64, error) { + _, err := emitEvent(ctx, events.EventType_SubscriptionCanceled, sub, func(_ context.Context) (uint64, error) { return sub.SequenceNumber, nil }, nil) return err diff --git a/cloud2cloud-gateway/store/mongodb/store.go b/cloud2cloud-gateway/store/mongodb/store.go index 6628c2429..fb5249f59 100644 --- a/cloud2cloud-gateway/store/mongodb/store.go +++ b/cloud2cloud-gateway/store/mongodb/store.go @@ -22,8 +22,8 @@ func NewStore(ctx context.Context, cfg pkgMongo.Config, tls *tls.Config, tracerP if err != nil { return nil, err } - s.SetOnClear(func(c context.Context) error { - return s.DropCollection(ctx, subscriptionsCName) + s.SetOnClear(func(clearCtx context.Context) error { + return s.DropCollection(clearCtx, subscriptionsCName) }) return &Store{s}, nil } diff --git a/coap-gateway/service/auth.go b/coap-gateway/service/auth.go index 407beea6e..6b47c9b82 100644 --- a/coap-gateway/service/auth.go +++ b/coap-gateway/service/auth.go @@ -20,7 +20,7 @@ import ( type Interceptor = func(ctx context.Context, code codes.Code, path string) (context.Context, error) func newAuthInterceptor() Interceptor { - return func(ctx context.Context, code codes.Code, path string) (context.Context, error) { + return func(ctx context.Context, _ codes.Code, path string) (context.Context, error) { switch path { case uri.RefreshToken, uri.SignUp, uri.SignIn, plgdtime.ResourceURI: return ctx, nil @@ -130,7 +130,7 @@ func MakeGetConfigForClient(tlsCfg *tls.Config, identityPropertiesRequired bool) MinVersion: tlsCfg.MinVersion, ClientAuth: tlsCfg.ClientAuth, ClientCAs: tlsCfg.ClientCAs, - VerifyPeerCertificate: func(rawCerts [][]byte, chains [][]*x509.Certificate) error { + VerifyPeerCertificate: func(_ [][]byte, chains [][]*x509.Certificate) error { var errors *multierror.Error for _, chain := range chains { err := verifyChain(chain, tlsCfg.ClientCAs, identityPropertiesRequired) diff --git a/coap-gateway/service/log.go b/coap-gateway/service/log.go index 15e74d9b4..9b55c1a14 100644 --- a/coap-gateway/service/log.go +++ b/coap-gateway/service/log.go @@ -15,7 +15,7 @@ import ( const logNotificationKey = "notification" -var toNil = func(args ...interface{}) { +var toNil = func(...interface{}) { // Do nothing because we don't want to log anything } diff --git a/coap-gateway/service/observation/observation_test.go b/coap-gateway/service/observation/observation_test.go index 0e9b4c4a5..2ac26b572 100644 --- a/coap-gateway/service/observation/observation_test.go +++ b/coap-gateway/service/observation/observation_test.go @@ -51,7 +51,7 @@ func TestIsResourceObservableWithInterface(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) handlerFuture, setHandler := future.New() - makeHandler := func(service *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(_ *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { cfg := coapgwTestService.ServiceHandlerConfig{} for _, o := range opts { o.Apply(&cfg) diff --git a/http-gateway/serverMux/router.go b/http-gateway/serverMux/router.go index bd716a3e0..9c0d85a9c 100644 --- a/http-gateway/serverMux/router.go +++ b/http-gateway/serverMux/router.go @@ -14,7 +14,7 @@ import ( func NewRouter(queryCaseInsensitive map[string]string, authInterceptor kitHttp.Interceptor, opts ...kitHttp.LogOpt) *router.Router { r := router.NewRouter() r.Use(kitHttp.CreateLoggingMiddleware(opts...)) - r.Use(kitHttp.CreateAuthMiddleware(authInterceptor, func(ctx context.Context, w http.ResponseWriter, r *http.Request, err error) { + r.Use(kitHttp.CreateAuthMiddleware(authInterceptor, func(_ context.Context, w http.ResponseWriter, r *http.Request, err error) { WriteError(w, grpc.ForwardErrorf(codes.Unauthenticated, "cannot access to %v: %w", r.RequestURI, err)) })) r.Use(kitHttp.CreateMakeQueryCaseInsensitiveMiddleware(queryCaseInsensitive, opts...)) diff --git a/http-gateway/service/subscribeToEvents.go b/http-gateway/service/subscribeToEvents.go index 3f4edb6f7..9cfe1588b 100644 --- a/http-gateway/service/subscribeToEvents.go +++ b/http-gateway/service/subscribeToEvents.go @@ -28,7 +28,7 @@ func modifyResourceIdFilter(data []byte) []byte { resourceIdFilter := gjson.Get(string(data), "createSubscription.resourceIdFilter") newData := string(data) // append resourceIdFilter to httpResourceIdFilter - resourceIdFilter.ForEach(func(key, value gjson.Result) bool { + resourceIdFilter.ForEach(func(_, value gjson.Result) bool { newData, _ = sjson.Set(newData, "createSubscription.httpResourceIdFilter.-1", value.Str) return true }) diff --git a/identity-store/client/ownerCache.go b/identity-store/client/ownerCache.go index 7b440afbe..0b6235093 100644 --- a/identity-store/client/ownerCache.go +++ b/identity-store/client/ownerCache.go @@ -252,7 +252,6 @@ func (c *OwnerCache) Update(ctx context.Context) (added []string, removed []stri added, removed, err = s.syncDevicesLocked(ctx, owner, c) return err }) - if err != nil { return nil, nil, err } diff --git a/identity-store/client/ownerCache_test.go b/identity-store/client/ownerCache_test.go index 63e2e37f5..a50ed3694 100644 --- a/identity-store/client/ownerCache_test.go +++ b/identity-store/client/ownerCache_test.go @@ -59,7 +59,7 @@ func TestOwnerCacheSubscribe(t *testing.T) { CertFile: cfg.APIs.GRPC.TLS.CertFile, KeyFile: cfg.APIs.GRPC.TLS.KeyFile, }, - }, fileWatcher, log.Get(), noop.NewTracerProvider(), grpc.WithPerRPCCredentials(kitNetGrpc.NewOAuthAccess(func(ctx context.Context) (*oauth2.Token, error) { + }, fileWatcher, log.Get(), noop.NewTracerProvider(), grpc.WithPerRPCCredentials(kitNetGrpc.NewOAuthAccess(func(context.Context) (*oauth2.Token, error) { return &oauth2.Token{ AccessToken: token, TokenType: "Bearer", diff --git a/pkg/cqldb/cqldb.go b/pkg/cqldb/cqldb.go index 49af196da..b47ab61be 100644 --- a/pkg/cqldb/cqldb.go +++ b/pkg/cqldb/cqldb.go @@ -130,9 +130,9 @@ func New(ctx context.Context, cfg Config, tls *tls.Config, logger log.Logger, _ logger: logger, } - s.onClear = func(c context.Context) error { + s.onClear = func(clearCtx context.Context) error { // default clear function drops the whole database - return s.DropKeyspace(ctx) + return s.DropKeyspace(clearCtx) } return s, nil } diff --git a/pkg/fsnotify/fsnotify_test.go b/pkg/fsnotify/fsnotify_test.go index e2503805b..f5a9f703a 100644 --- a/pkg/fsnotify/fsnotify_test.go +++ b/pkg/fsnotify/fsnotify_test.go @@ -25,7 +25,7 @@ func TestWatcher(t *testing.T) { err = w.Add("/tmp") require.NoError(t, err) - onEventHandler := func(event Event) {} + onEventHandler := func(Event) {} w.AddOnEventHandler(&onEventHandler) w.RemoveOnEventHandler(&onEventHandler) diff --git a/pkg/log/log.go b/pkg/log/log.go index 40d0182cc..c4aaee370 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -293,7 +293,7 @@ var getLogFuncMap = map[zapcore.Level]func(l *WrapSuggarLogger) func(args ...int FatalLevel: func(l *WrapSuggarLogger) func(args ...interface{}) { return l.Fatal }, } -var emptyLogFunc = func(args ...interface{}) { +var emptyLogFunc = func(...interface{}) { // do nothing } diff --git a/pkg/net/coap/service/service_test.go b/pkg/net/coap/service/service_test.go index 5cfdafbb2..8d46952f6 100644 --- a/pkg/net/coap/service/service_test.go +++ b/pkg/net/coap/service/service_test.go @@ -60,8 +60,8 @@ func TestNew(t *testing.T) { }, options: []func(*Options){ WithMessagePool(pool.New(uint32(1024), 1024)), - WithOnNewConnection(func(conn mux.Conn) {}), - WithOnInactivityConnection(func(conn mux.Conn) {}), + WithOnNewConnection(func(mux.Conn) {}), + WithOnInactivityConnection(func(mux.Conn) {}), WithOverrideTLS(func(cfg *tls.Config) *tls.Config { return cfg }), }, }, @@ -87,8 +87,8 @@ func TestNew(t *testing.T) { }, options: []func(*Options){ WithMessagePool(pool.New(uint32(1024), 1024)), - WithOnNewConnection(func(conn mux.Conn) {}), - WithOnInactivityConnection(func(conn mux.Conn) {}), + WithOnNewConnection(func(mux.Conn) {}), + WithOnInactivityConnection(func(mux.Conn) {}), WithOverrideTLS(func(cfg *tls.Config) *tls.Config { return cfg }), }, }, diff --git a/pkg/net/grpc/server/makeDefaultOptions.go b/pkg/net/grpc/server/makeDefaultOptions.go index 667b94934..868ac95d2 100644 --- a/pkg/net/grpc/server/makeDefaultOptions.go +++ b/pkg/net/grpc/server/makeDefaultOptions.go @@ -251,7 +251,7 @@ func MakeDefaultOptions(auth pkgGrpc.AuthInterceptors, logger log.Logger, tracer }, } unaryInterceptors := []grpc.UnaryServerInterceptor{ - func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { + func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { setGrpcRequest(ctx, req) return handler(ctx, req) }, @@ -298,7 +298,7 @@ func WithWhiteListedMethods(method ...string) Option { } func NewAuth(validator pkgGrpc.Validator, opts ...Option) pkgGrpc.AuthInterceptors { - interceptor := pkgGrpc.ValidateJWTWithValidator(validator, func(ctx context.Context, method string) jwt.ClaimsValidator { + interceptor := pkgGrpc.ValidateJWTWithValidator(validator, func(context.Context, string) jwt.ClaimsValidator { return pkgJwt.NewScopeClaims() }) var cfg config diff --git a/pkg/net/http/interceptor.go b/pkg/net/http/interceptor.go index 37125b0b5..41b27d629 100644 --- a/pkg/net/http/interceptor.go +++ b/pkg/net/http/interceptor.go @@ -46,7 +46,7 @@ func (c DeniedClaims) Validate() error { } func MakeClaimsFunc(methods map[string][]AuthArgs) ClaimsFunc { - return func(ctx context.Context, method, uri string) jwt.ClaimsValidator { + return func(_ context.Context, method, uri string) jwt.ClaimsValidator { args, ok := methods[method] if !ok { return &DeniedClaims{Err: fmt.Errorf("inaccessible method: %v", method)} diff --git a/pkg/net/http/loggingMiddleware.go b/pkg/net/http/loggingMiddleware.go index a6a5761ef..862e51cff 100644 --- a/pkg/net/http/loggingMiddleware.go +++ b/pkg/net/http/loggingMiddleware.go @@ -70,7 +70,7 @@ func (w *statusWriter) Flush() { } } -var toNil = func(args ...interface{}) { +var toNil = func(...interface{}) { // Do nothing because we don't want to log anything } diff --git a/pkg/security/jwt/claims_test.go b/pkg/security/jwt/claims_test.go index db045c83a..0d6fc2175 100644 --- a/pkg/security/jwt/claims_test.go +++ b/pkg/security/jwt/claims_test.go @@ -467,7 +467,7 @@ func TestParseToken(t *testing.T) { func checkClaims(t *testing.T, tokenClaims jwt.Claims, expError error) { token := config.CreateJwtToken(t, tokenClaims) - _, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) { + _, err := jwt.Parse(token, func(*jwt.Token) (interface{}, error) { return jwt.VerificationKeySet{ Keys: []jwt.VerificationKey{ []uint8(config.JWTSecret), diff --git a/pkg/security/jwt/scopeClaims_test.go b/pkg/security/jwt/scopeClaims_test.go index 2912cc08d..f41adef4d 100644 --- a/pkg/security/jwt/scopeClaims_test.go +++ b/pkg/security/jwt/scopeClaims_test.go @@ -61,7 +61,7 @@ func TestScopeClaimsInvalidScope(t *testing.T) { func checkScopedClaims(t *testing.T, tokenClaims jwt.Claims, expError error) { token := config.CreateJwtToken(t, tokenClaims) - _, err := jwt.ParseWithClaims(token, &pkgJwt.ScopeClaims{}, func(t *jwt.Token) (interface{}, error) { + _, err := jwt.ParseWithClaims(token, &pkgJwt.ScopeClaims{}, func(*jwt.Token) (interface{}, error) { return jwt.VerificationKeySet{ Keys: []jwt.VerificationKey{ []uint8(config.JWTSecret), diff --git a/resource-aggregate/cqrs/aggregate/aggregate.go b/resource-aggregate/cqrs/aggregate/aggregate.go index 3e73e7699..4e1d71b75 100644 --- a/resource-aggregate/cqrs/aggregate/aggregate.go +++ b/resource-aggregate/cqrs/aggregate/aggregate.go @@ -137,7 +137,7 @@ func HandleRetry(ctx context.Context, retryFunc RetryFunc) error { func NewAggregateModel(ctx context.Context, groupID, aggregateID string, store eventstore.EventStore, logDebugfFunc eventstore.LogDebugfFunc, model AggregateModel) (*AggregateModelWrapper, error) { amodel := &AggregateModelWrapper{model: model} - ep := eventstore.NewProjection(store, func(ctx context.Context, groupID, aggregateID string) (eventstore.Model, error) { return amodel, nil }, logDebugfFunc) + ep := eventstore.NewProjection(store, func(_ context.Context, _, _ string) (eventstore.Model, error) { return amodel, nil }, logDebugfFunc) err := ep.Project(ctx, []eventstore.SnapshotQuery{ { GroupID: groupID, diff --git a/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go b/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go index 78d5e8247..c3a481b4a 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go @@ -168,7 +168,7 @@ func newEventStoreWithClient(ctx context.Context, store *pkgMongo.Store, dbPrefi } if logDebugfFunc == nil { - logDebugfFunc = func(fmt string, args ...interface{}) { + logDebugfFunc = func(string, ...interface{}) { // no-op if not set } } diff --git a/resource-aggregate/cqrs/eventstore/projection.go b/resource-aggregate/cqrs/eventstore/projection.go index 5f7d8ed58..cdec3e572 100644 --- a/resource-aggregate/cqrs/eventstore/projection.go +++ b/resource-aggregate/cqrs/eventstore/projection.go @@ -71,7 +71,7 @@ type Projection struct { // NewProjection projection over eventstore. func NewProjection(store EventStore, factoryModel FactoryModelFunc, logDebugfFunc LogDebugfFunc) *Projection { if logDebugfFunc == nil { - logDebugfFunc = func(fmt string, args ...interface{}) {} + logDebugfFunc = func(string, ...interface{}) {} } return &Projection{ store: store, diff --git a/resource-aggregate/cqrs/projection/projection.go b/resource-aggregate/cqrs/projection/projection.go index a888d820d..b55e53df3 100644 --- a/resource-aggregate/cqrs/projection/projection.go +++ b/resource-aggregate/cqrs/projection/projection.go @@ -24,7 +24,7 @@ type Projection struct { // NewProjection creates new resource projection. func NewProjection(ctx context.Context, name string, store eventstore.EventStore, subscriber eventbus.Subscriber, factoryModel eventstore.FactoryModelFunc) (*Projection, error) { - cqrsProjection, err := newProjection(ctx, store, name, subscriber, factoryModel, func(template string, args ...interface{}) {}) + cqrsProjection, err := newProjection(ctx, store, name, subscriber, factoryModel, func(string, ...interface{}) {}) if err != nil { return nil, fmt.Errorf("cannot create Projection: %w", err) } @@ -52,7 +52,7 @@ func (p *Projection) Register(ctx context.Context, deviceID string) (created boo }, func() interface{} { return kitSync.NewRefCounter(&deviceProjection{ deviceID: deviceID, - }, func(ctx context.Context, data interface{}) error { + }, func(_ context.Context, data interface{}) error { d := data.(*deviceProjection) d.released = true return nil @@ -151,7 +151,7 @@ func (p *Projection) ForceUpdate(ctx context.Context, resourceID *commands.Resou func (p *Projection) release(v *kitSync.RefCounter) error { data := v.Data().(*deviceProjection) deviceID := data.deviceID - p.refCountMap.ReplaceWithFunc(deviceID, func(oldValue interface{}, oldLoaded bool) (newValue interface{}, doDelete bool) { + p.refCountMap.ReplaceWithFunc(deviceID, func(oldValue interface{}, _ bool) (newValue interface{}, doDelete bool) { o := oldValue.(*kitSync.RefCounter) d := o.Data().(*deviceProjection) if err := o.Release(context.Background()); err != nil { diff --git a/resource-aggregate/cqrs/projection/projection_test.go b/resource-aggregate/cqrs/projection/projection_test.go index 97ec0ffab..ef8890ee1 100644 --- a/resource-aggregate/cqrs/projection/projection_test.go +++ b/resource-aggregate/cqrs/projection/projection_test.go @@ -185,7 +185,7 @@ func TestResourceProjectionTestLoadParallelModels(t *testing.T) { "test", eventstore, nil, - func(ctx context.Context, groupID, aggregateID string) (cqrsEventStore.Model, error) { + func(_ context.Context, _, _ string) (cqrsEventStore.Model, error) { return events.NewResourceLinksSnapshotTaken(), nil }, ) @@ -201,7 +201,7 @@ func TestResourceProjectionTestLoadParallelModels(t *testing.T) { go func(v int) { defer wg.Done() n := time.Now() - p.cqrsProjection.Models(nil, func(m cqrsEventStore.Model) (wantNext bool) { return true }) + p.cqrsProjection.Models(nil, func(cqrsEventStore.Model) (wantNext bool) { return true }) diff := -1 * time.Until(n) t.Logf("%v models time %v\n", v, diff) }(i) @@ -248,7 +248,7 @@ func TestResourceProjection_Register(t *testing.T) { "test", eventstore, nil, - func(ctx context.Context, groupID, aggregateID string) (cqrsEventStore.Model, error) { + func(_ context.Context, _, _ string) (cqrsEventStore.Model, error) { return events.NewResourceLinksSnapshotTaken(), nil }, ) @@ -315,7 +315,7 @@ func TestResourceProjection_Unregister(t *testing.T) { "test", eventstore, nil, - func(ctx context.Context, groupID, aggregateID string) (cqrsEventStore.Model, error) { + func(_ context.Context, _, _ string) (cqrsEventStore.Model, error) { return events.NewResourceLinksSnapshotTaken(), nil }, ) @@ -454,7 +454,7 @@ func TestResourceLinksProjection_Models(t *testing.T) { "test", eventstore, nil, - func(ctx context.Context, groupID, aggregateID string) (cqrsEventStore.Model, error) { + func(_ context.Context, _, _ string) (cqrsEventStore.Model, error) { return events.NewResourceLinksSnapshotTaken(), nil }, ) @@ -722,7 +722,7 @@ func TestResourceStateProjection_Models(t *testing.T) { "test", eventstore, nil, - func(ctx context.Context, groupID, aggregateID string) (cqrsEventStore.Model, error) { + func(_ context.Context, _, _ string) (cqrsEventStore.Model, error) { return events.NewResourceStateSnapshotTaken(), nil }, ) @@ -785,7 +785,7 @@ func TestResourceProjection_ForceUpdate(t *testing.T) { "test", eventstore, nil, - func(ctx context.Context, groupID, aggregateID string) (cqrsEventStore.Model, error) { + func(_ context.Context, _, _ string) (cqrsEventStore.Model, error) { return events.NewResourceStateSnapshotTaken(), nil }, ) diff --git a/resource-aggregate/service/aggregate.go b/resource-aggregate/service/aggregate.go index 63722234a..832879bf8 100644 --- a/resource-aggregate/service/aggregate.go +++ b/resource-aggregate/service/aggregate.go @@ -22,25 +22,25 @@ type Aggregate struct { } func NewResourceStateFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + return func(context.Context) (cqrsAggregate.AggregateModel, error) { return events.NewResourceStateSnapshotTakenForCommand(userID, owner, hubID), nil } } func NewResourceLinksFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + return func(context.Context) (cqrsAggregate.AggregateModel, error) { return events.NewResourceLinksSnapshotTakenForCommand(userID, owner, hubID), nil } } func NewDeviceMetadataFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + return func(context.Context) (cqrsAggregate.AggregateModel, error) { return events.NewDeviceMetadataSnapshotTakenForCommand(userID, owner, hubID), nil } } func NewServicesMetadataFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + return func(context.Context) (cqrsAggregate.AggregateModel, error) { return events.NewServiceMetadataSnapshotTakenForCommand(userID, owner, hubID), nil } } @@ -55,7 +55,7 @@ func NewAggregate(resourceID *commands.ResourceId, store eventstore.EventStore, retry, store, factoryModel, - func(template string, args ...interface{}) { + func(string, ...interface{}) { // TODO: add debug log }) if err != nil { diff --git a/resource-aggregate/service/service.go b/resource-aggregate/service/service.go index 059ae09f1..bd96873e4 100644 --- a/resource-aggregate/service/service.go +++ b/resource-aggregate/service/service.go @@ -164,7 +164,7 @@ func NewService(ctx context.Context, config Config, fileWatcher *fsnotify.Watche serviceHeartbeat := NewServiceHeartbeat(config, eventStore, publisher, logger) grpcServer.AddCloseFunc(serviceHeartbeat.Close) - requestHandler := NewRequestHandler(config, eventStore, publisher, func(getCtx context.Context, owner string, deviceIDs []string) ([]string, error) { + requestHandler := NewRequestHandler(config, eventStore, publisher, func(getCtx context.Context, _ string, deviceIDs []string) ([]string, error) { getAllDevices := len(deviceIDs) == 0 if !getAllDevices { return ownerCache.GetSelectedDevices(getCtx, deviceIDs) diff --git a/resource-aggregate/service/updateDeviceMetadata.go b/resource-aggregate/service/updateDeviceMetadata.go index 9df379bc6..04428df06 100644 --- a/resource-aggregate/service/updateDeviceMetadata.go +++ b/resource-aggregate/service/updateDeviceMetadata.go @@ -70,7 +70,7 @@ func (r RequestHandler) updateDeviceMetadata(ctx context.Context, request *comma resID := commands.NewResourceID(request.GetDeviceId(), commands.StatusHref) var latestSnapshot *events.DeviceMetadataSnapshotTakenForCommand - deviceMetadataFactoryModel := func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + deviceMetadataFactoryModel := func(context.Context) (cqrsAggregate.AggregateModel, error) { latestSnapshot = events.NewDeviceMetadataSnapshotTakenForCommand(userID, owner, r.config.HubID) return latestSnapshot, nil } diff --git a/resource-aggregate/service/updateServiceHeartbeat.go b/resource-aggregate/service/updateServiceHeartbeat.go index 84ee82dc0..9084c8ead 100644 --- a/resource-aggregate/service/updateServiceHeartbeat.go +++ b/resource-aggregate/service/updateServiceHeartbeat.go @@ -197,7 +197,7 @@ func (s *ServiceHeartbeat) updateServiceMetadata(aggregate *Aggregate, r UpdateS func (s *ServiceHeartbeat) processRequest(r UpdateServiceMetadataReqResp) time.Time { resID := commands.NewResourceID(s.config.HubID, commands.ServicesResourceHref) var snapshot *events.ServiceMetadataSnapshotTakenForCommand - newServicesMetadataFactoryModelFunc := func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + newServicesMetadataFactoryModelFunc := func(context.Context) (cqrsAggregate.AggregateModel, error) { snapshot = events.NewServiceMetadataSnapshotTakenForCommand(ServiceUserID, ServiceUserID, s.config.HubID) return snapshot, nil } @@ -372,7 +372,7 @@ func (s *ServiceHeartbeat) updateDeviceToExpired(ctx context.Context, serviceID, resID := commands.NewResourceID(deviceID, commands.StatusHref) var latestSnapshot *events.DeviceMetadataSnapshotTakenForCommand - deviceMetadataFactoryModel := func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { + deviceMetadataFactoryModel := func(context.Context) (cqrsAggregate.AggregateModel, error) { latestSnapshot = events.NewDeviceMetadataSnapshotTakenForCommand(userID, "", s.config.HubID) return latestSnapshot, nil } diff --git a/resource-directory/service/grpcApi.go b/resource-directory/service/grpcApi.go index ca473238c..14a9765d4 100644 --- a/resource-directory/service/grpcApi.go +++ b/resource-directory/service/grpcApi.go @@ -195,7 +195,7 @@ func NewRequestHandler( } func NewEventStoreModelFactory() func(context.Context, string, string) (eventstore.Model, error) { - return func(ctx context.Context, deviceID, resourceID string) (eventstore.Model, error) { + return func(_ context.Context, deviceID, resourceID string) (eventstore.Model, error) { switch resourceID { case commands.MakeLinksResourceUUID(deviceID).String(): return NewResourceLinksProjection(deviceID), nil diff --git a/test/http/request.go b/test/http/request.go index 96f6ef4da..600475108 100644 --- a/test/http/request.go +++ b/test/http/request.go @@ -143,7 +143,7 @@ func DoHTTPRequest(t *testing.T, req *http.Request) *http.Response { } func ReadHTTPResponse(t *testing.T, w io.Reader, contentType string, data interface{}) { - readFrom := func(w io.Reader, v interface{}) error { + readFrom := func(_ io.Reader, _ interface{}) error { return fmt.Errorf("not supported") } switch contentType { diff --git a/test/iotivity-lite/service/deleteResource_test.go b/test/iotivity-lite/service/deleteResource_test.go index 7433a1145..fd096fb15 100644 --- a/test/iotivity-lite/service/deleteResource_test.go +++ b/test/iotivity-lite/service/deleteResource_test.go @@ -143,7 +143,7 @@ func TestBatchDeleteResources(t *testing.T) { }, func(unpublished map[int64]struct{}) bool { return len(unpublished) == numSwitches }) - getHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + getHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return bh } diff --git a/test/iotivity-lite/service/offboard_test.go b/test/iotivity-lite/service/offboard_test.go index 5b5c02d4e..06ba674c4 100644 --- a/test/iotivity-lite/service/offboard_test.go +++ b/test/iotivity-lite/service/offboard_test.go @@ -41,7 +41,7 @@ func TestOffboard(t *testing.T) { defer tearDown() ch := iotService.NewCoapHandlerWithCounter(0) - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return ch } @@ -195,7 +195,7 @@ func TestOffboardWithoutSignIn(t *testing.T) { sh := NewSwitchableHandler(-1) sh.failSignIn.Store(true) - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return sh } @@ -259,7 +259,7 @@ func TestOffboardWithSignIn(t *testing.T) { sh := NewSwitchableHandler(-1) sh.failSignIn.Store(true) sh.SetAccessToken(strings.Repeat("this-access-token-is-so-long-that-its-size-is-longer-than-the-allowed-request-header-size", 5)) - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return sh } @@ -324,7 +324,7 @@ func TestOffboardWithSignInByRefreshToken(t *testing.T) { sh := NewSwitchableHandler(20) sh.failSignIn.Store(true) sh.SetAccessToken(strings.Repeat("this-access-token-is-so-long-that-its-size-is-longer-than-the-allowed-request-header-size", 5)) - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return sh } @@ -344,7 +344,7 @@ func TestOffboardWithSignInByRefreshToken(t *testing.T) { assert.Equal(t, 1, signOffCount) } - coapShutdown := coapgwTest.SetUp(t, makeHandler, func(handler coapgwTestService.ServiceHandler) {}) + coapShutdown := coapgwTest.SetUp(t, makeHandler, func(coapgwTestService.ServiceHandler) {}) ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) @@ -400,7 +400,7 @@ func TestOffboardWithRepeat(t *testing.T) { sh := NewSwitchableHandler(-1) sh.blockSignOff() - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return sh } @@ -467,7 +467,7 @@ func TestOffboardInterrupt(t *testing.T) { // off-boarding will try login by refresh token, but block the sending of response blockRefreshCh := sh.blockRefresh() - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return sh } diff --git a/test/iotivity-lite/service/republish_test.go b/test/iotivity-lite/service/republish_test.go index 8d4c17e8f..404e4a365 100644 --- a/test/iotivity-lite/service/republish_test.go +++ b/test/iotivity-lite/service/republish_test.go @@ -34,7 +34,7 @@ func TestRepublishAfterRefresh(t *testing.T) { tearDown := service.SetUpServices(ctx, t, services) defer tearDown() - makeHandler := func(s *coapgwTestService.Service, opts ...coapgwTestService.Option) coapgwTestService.ServiceHandler { + makeHandler := func(*coapgwTestService.Service, ...coapgwTestService.Option) coapgwTestService.ServiceHandler { return iotService.NewCoapHandlerWithCounter(int64(atLifetime.Seconds())) } validateHandler := func(handler coapgwTestService.ServiceHandler) { diff --git a/test/oauth-server/test/test.go b/test/oauth-server/test/test.go index 2f6871671..e91be0e8c 100644 --- a/test/oauth-server/test/test.go +++ b/test/oauth-server/test/test.go @@ -197,7 +197,7 @@ func HTTPDo(t require.TestingT, req *http.Request, followRedirect bool) *http.Re Transport: trans, } if !followRedirect { - c.CheckRedirect = func(req *http.Request, via []*http.Request) error { + c.CheckRedirect = func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse } } diff --git a/test/pb/event.go b/test/pb/event.go index d56d53812..4a16cfef0 100644 --- a/test/pb/event.go +++ b/test/pb/event.go @@ -180,10 +180,10 @@ var cleanupEventFn = map[string]func(ev *pb.Event){ getTypeName(&pb.Event_ResourceChanged{}): func(ev *pb.Event) { CleanUpResourceChanged(ev.GetResourceChanged(), false) }, - getTypeName(&pb.Event_OperationProcessed_{}): func(ev *pb.Event) { + getTypeName(&pb.Event_OperationProcessed_{}): func(*pb.Event) { // nothing to do }, - getTypeName(&pb.Event_SubscriptionCanceled_{}): func(ev *pb.Event) { + getTypeName(&pb.Event_SubscriptionCanceled_{}): func(*pb.Event) { // nothing to do }, getTypeName(&pb.Event_ResourceUpdatePending{}): func(ev *pb.Event) { @@ -283,34 +283,34 @@ var compareEventFn = map[string]func(t *testing.T, e, g *pb.Event, cmpInterface getTypeName(&pb.Event_ResourceChanged{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { CmpResourceChanged(t, e.GetResourceChanged(), g.GetResourceChanged(), cmpInterface) }, - getTypeName(&pb.Event_ResourceUpdatePending{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceUpdatePending{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceUpdatePending(t, e.GetResourceUpdatePending(), g.GetResourceUpdatePending()) }, - getTypeName(&pb.Event_ResourceUpdated{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceUpdated{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceUpdated(t, e.GetResourceUpdated(), g.GetResourceUpdated()) }, - getTypeName(&pb.Event_ResourceRetrievePending{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceRetrievePending{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceRetrievePending(t, e.GetResourceRetrievePending(), g.GetResourceRetrievePending()) }, - getTypeName(&pb.Event_ResourceRetrieved{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceRetrieved{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceRetrieved(t, e.GetResourceRetrieved(), g.GetResourceRetrieved()) }, - getTypeName(&pb.Event_ResourceDeletePending{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceDeletePending{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceDeletePending(t, e.GetResourceDeletePending(), g.GetResourceDeletePending()) }, - getTypeName(&pb.Event_ResourceDeleted{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceDeleted{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceDeleted(t, e.GetResourceDeleted(), g.GetResourceDeleted()) }, - getTypeName(&pb.Event_ResourceCreatePending{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceCreatePending{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceCreatePending(t, e.GetResourceCreatePending(), g.GetResourceCreatePending()) }, - getTypeName(&pb.Event_ResourceCreated{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_ResourceCreated{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpResourceCreated(t, e.GetResourceCreated(), g.GetResourceCreated()) }, - getTypeName(&pb.Event_DeviceMetadataUpdatePending{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_DeviceMetadataUpdatePending{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpDeviceMetadataUpdatePending(t, e.GetDeviceMetadataUpdatePending(), g.GetDeviceMetadataUpdatePending()) }, - getTypeName(&pb.Event_DeviceMetadataUpdated{}): func(t *testing.T, e, g *pb.Event, cmpInterface string) { //nolint:unparam + getTypeName(&pb.Event_DeviceMetadataUpdated{}): func(t *testing.T, e, g *pb.Event, _ string) { CmpDeviceMetadataUpdated(t, e.GetDeviceMetadataUpdated(), g.GetDeviceMetadataUpdated()) }, } @@ -319,7 +319,7 @@ func CmpEvent(t *testing.T, expected, got *pb.Event, cmpInterface string) { require.Equal(t, GetEventType(expected), GetEventType(got)) cmp, ok := compareEventFn[GetEventType(expected)] if !ok { - cmp = func(t *testing.T, e, g *pb.Event, cmpInterface string) { + cmp = func(t *testing.T, e, g *pb.Event, _ string) { CleanUpEvent(t, e) CleanUpEvent(t, g) test.CheckProtobufs(t, e, g, test.RequireToCheckFunc(require.Equal)) diff --git a/test/security/jwk.go b/test/security/jwk.go index d90d2563c..f373d487b 100644 --- a/test/security/jwk.go +++ b/test/security/jwk.go @@ -70,7 +70,7 @@ func NewTestJwks(t *testing.T) JWKServer { require.NoError(t, err) mux := http.NewServeMux() - mux.HandleFunc(jwksUri, func(w http.ResponseWriter, r *http.Request) { + mux.HandleFunc(jwksUri, func(w http.ResponseWriter, _ *http.Request) { if _, err := io.WriteString(w, string(jwks)); err != nil { log.Debugf("failed to write jwks: %v", err) } diff --git a/test/virtual-device/cmd/main.go b/test/virtual-device/cmd/main.go index d1fe26855..bf485ad61 100644 --- a/test/virtual-device/cmd/main.go +++ b/test/virtual-device/cmd/main.go @@ -73,7 +73,7 @@ func generateIdentityCert(deviceID string, signerCert []*x509.Certificate, signe } func makeVerifyCertificate(signerCert []*x509.Certificate) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { - return func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { + return func(rawCerts [][]byte, _ [][]*x509.Certificate) error { if len(rawCerts) == 0 { return fmt.Errorf("empty certificates chain") } From 74ddc41ca7c3ac3d4e6aa6bec6861c6013efd2c1 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Thu, 29 Feb 2024 20:18:19 +0000 Subject: [PATCH 06/31] coap-gateway/resource-aggregate: add device local endpoints support Obtain the local endpoints of a device within a Local Area Network (LAN) that is situated behind a Network Address Translation (NAT) firewall from the hub. --- .../service/getDevices_test.go | 1 + coap-gateway/service/devicesStatusUpdater.go | 9 +- coap-gateway/service/log.go | 4 + .../service/observation/deviceObserver.go | 3 +- .../service/observation/observation.go | 42 -- .../service/observation/observation_test.go | 3 +- coap-gateway/service/session.go | 29 ++ coap-gateway/service/signIn.go | 1 + coap-gateway/uri/uri.go | 6 +- grpc-gateway/client/getDevice_test.go | 1 + grpc-gateway/client/getDevices_test.go | 1 + grpc-gateway/pb/service.swagger.json | 7 + http-gateway/swagger.yaml | 12 +- .../DevicesDetailsPage/DevicesDetailsPage.tsx | 1 + .../Detail/DevicesDetailsPage/Tabs/Tab1.tsx | 31 +- .../DevicesDetailsPage/Tabs/Tab1.types.ts | 1 + .../src/containers/Devices/Devices.i18n.ts | 4 + .../src/containers/Devices/Devices.types.ts | 1 + pkg/log/logKeys.go | 1 + pkg/net/coap/getResourceLinks.go | 84 ++++ pkg/net/coap/getResourceLinks_test.go | 244 +++++++++++ resource-aggregate/commands/commands.pb.go | 390 +++++++++--------- .../cqrs/aggregate/aggregateParallel_test.go | 2 +- .../events/deviceMetadataSnapshotTaken.go | 5 + .../deviceMetadataSnapshotTaken_test.go | 28 +- .../events/deviceMetadataUpdated.go | 2 + resource-aggregate/pb/commands.proto | 1 + resource-directory/service/getDevices_test.go | 1 + test/pb/device.go | 2 + test/test.go | 5 + test/virtual-device/virtualDevice.go | 9 +- 31 files changed, 671 insertions(+), 260 deletions(-) delete mode 100644 coap-gateway/service/observation/observation.go create mode 100644 pkg/net/coap/getResourceLinks.go create mode 100644 pkg/net/coap/getResourceLinks_test.go diff --git a/cloud2cloud-connector/service/getDevices_test.go b/cloud2cloud-connector/service/getDevices_test.go index 1f57dcfcc..c2cd276e7 100644 --- a/cloud2cloud-connector/service/getDevices_test.go +++ b/cloud2cloud-connector/service/getDevices_test.go @@ -99,6 +99,7 @@ func testRequestHandlerGetDevices(t *testing.T, events store.Events) { if dev.GetMetadata().GetConnection() != nil { dev.GetMetadata().GetConnection().Id = "" dev.GetMetadata().GetConnection().ConnectedAt = 0 + dev.GetMetadata().GetConnection().LocalEndpoints = nil } if dev.GetMetadata().GetTwinSynchronization() != nil { dev.GetMetadata().GetTwinSynchronization().CommandMetadata = nil diff --git a/coap-gateway/service/devicesStatusUpdater.go b/coap-gateway/service/devicesStatusUpdater.go index 6077ab19f..e5f1875ce 100644 --- a/coap-gateway/service/devicesStatusUpdater.go +++ b/coap-gateway/service/devicesStatusUpdater.go @@ -40,10 +40,11 @@ func (u *devicesStatusUpdater) updateOnlineStatus(ctx context.Context, client *s DeviceId: authCtx.GetDeviceID(), Update: &commands.UpdateDeviceMetadataRequest_Connection{ Connection: &commands.Connection{ - Status: commands.Connection_ONLINE, - ConnectedAt: pkgTime.UnixNano(connectedAt), - Protocol: client.GetApplicationProtocol(), - ServiceId: u.serviceInstanceID.String(), + Status: commands.Connection_ONLINE, + ConnectedAt: pkgTime.UnixNano(connectedAt), + Protocol: client.GetApplicationProtocol(), + ServiceId: u.serviceInstanceID.String(), + LocalEndpoints: client.getLocalEndpoints(), }, }, CommandMetadata: &commands.CommandMetadata{ diff --git a/coap-gateway/service/log.go b/coap-gateway/service/log.go index 9b55c1a14..172e8a10a 100644 --- a/coap-gateway/service/log.go +++ b/coap-gateway/service/log.go @@ -96,6 +96,10 @@ func (c *session) getLogger() log.Logger { if deviceID != "" { logger = logger.With(log.DeviceIDKey, deviceID) } + localEndpoints := c.getLocalEndpoints() + if len(localEndpoints) > 0 { + logger = logger.With(log.LocalEndpointsKey, localEndpoints) + } select { case <-c.coapConn.Done(): logger = logger.With("closedConnection", true) diff --git a/coap-gateway/service/observation/deviceObserver.go b/coap-gateway/service/observation/deviceObserver.go index 8eed989cd..5a7073b2f 100644 --- a/coap-gateway/service/observation/deviceObserver.go +++ b/coap-gateway/service/observation/deviceObserver.go @@ -15,6 +15,7 @@ import ( "github.com/plgd-dev/hub/v2/coap-gateway/resource" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" "github.com/plgd-dev/hub/v2/pkg/log" + "github.com/plgd-dev/hub/v2/pkg/net/coap" pkgStrings "github.com/plgd-dev/hub/v2/pkg/strings" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" pbRD "github.com/plgd-dev/hub/v2/resource-directory/pb" @@ -165,7 +166,7 @@ func WithMaxETagsCountInRequest(v uint32) MaxETagsCountInRequestOpt { } func prepareSetupDeviceObserver(ctx context.Context, deviceID string, coapConn ClientConn, rdClient GrpcGatewayClient, raClient ResourceAggregateClient, cfg DeviceObserverConfig) (DeviceObserverConfig, []*commands.Resource, error) { - links, sequence, err := GetResourceLinks(ctx, coapConn, resources.ResourceURI) + links, sequence, err := coap.GetResourceLinksWithLinkInterface(ctx, coapConn, resources.ResourceURI) switch { case err == nil: if cfg.ObservationType == ObservationType_Detect { diff --git a/coap-gateway/service/observation/observation.go b/coap-gateway/service/observation/observation.go deleted file mode 100644 index 6d8caf9b1..000000000 --- a/coap-gateway/service/observation/observation.go +++ /dev/null @@ -1,42 +0,0 @@ -package observation - -import ( - "context" - "fmt" - - "github.com/plgd-dev/device/v2/schema" - "github.com/plgd-dev/device/v2/schema/interfaces" - coapMessage "github.com/plgd-dev/go-coap/v3/message" - "github.com/plgd-dev/go-coap/v3/message/codes" - "github.com/plgd-dev/hub/v2/coap-gateway/uri" - "github.com/plgd-dev/kit/v2/codec/cbor" -) - -// Query resource links from the given resource with the interface oic.if.ll. -func GetResourceLinks(ctx context.Context, coapConn ClientConn, href string) (schema.ResourceLinks, uint64, error) { - msg, err := coapConn.Get(ctx, href, coapMessage.Option{ - ID: coapMessage.URIQuery, - Value: []byte(uri.InterfaceQueryKeyPrefix + interfaces.OC_IF_LL), - }) - if err != nil { - return schema.ResourceLinks{}, 0, err - } - defer coapConn.ReleaseMessage(msg) - - if msg.Code() != codes.Content { - return schema.ResourceLinks{}, 0, fmt.Errorf("invalid response code %v", msg.Code()) - } - - data := msg.Body() - if data == nil { - return schema.ResourceLinks{}, 0, fmt.Errorf("empty response") - } - - var links schema.ResourceLinks - err = cbor.ReadFrom(msg.Body(), &links) - if err != nil { - return schema.ResourceLinks{}, 0, err - } - - return links, msg.Sequence(), nil -} diff --git a/coap-gateway/service/observation/observation_test.go b/coap-gateway/service/observation/observation_test.go index 2ac26b572..2136fceca 100644 --- a/coap-gateway/service/observation/observation_test.go +++ b/coap-gateway/service/observation/observation_test.go @@ -11,6 +11,7 @@ import ( coapgwService "github.com/plgd-dev/hub/v2/coap-gateway/service" "github.com/plgd-dev/hub/v2/coap-gateway/service/observation" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" + "github.com/plgd-dev/hub/v2/pkg/net/coap" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/pkg/sync/task/future" "github.com/plgd-dev/hub/v2/test" @@ -116,7 +117,7 @@ func TestIsResourceObservableWithInterface(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - links, _, err := observation.GetResourceLinks(ctx, handler.coapConn, tt.args.href) + links, _, err := coap.GetResourceLinksWithLinkInterface(ctx, handler.coapConn, tt.args.href) if tt.wantErr { require.Error(t, err) return diff --git a/coap-gateway/service/session.go b/coap-gateway/service/session.go index 8943cc59c..9cc80e294 100644 --- a/coap-gateway/service/session.go +++ b/coap-gateway/service/session.go @@ -9,6 +9,7 @@ import ( "math" "net" "sync" + "sync/atomic" "time" "github.com/pion/dtls/v2" @@ -25,6 +26,7 @@ import ( "github.com/plgd-dev/hub/v2/grpc-gateway/pb" idEvents "github.com/plgd-dev/hub/v2/identity-store/events" "github.com/plgd-dev/hub/v2/pkg/log" + "github.com/plgd-dev/hub/v2/pkg/net/coap" coapService "github.com/plgd-dev/hub/v2/pkg/net/coap/service" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/pkg/opentelemetry/otelcoap" @@ -105,6 +107,7 @@ type session struct { exchangeCache *ExchangeCache refreshCache *RefreshCache tlsDeviceID string + localEndpoints atomic.Pointer[[]string] private struct { // guarded by mutex mutex sync.Mutex authCtx *authorizationContext @@ -516,6 +519,32 @@ func (c *session) batchNotifyContentChanged(ctx context.Context, deviceID string return err } +func (c *session) resolveLocalEndpoints() { + v := []string{} + if !c.localEndpoints.CompareAndSwap(nil, &v) { + return + } + + localEndpoints, err := coap.GetEndpointsFromDeviceResource(c.Context(), c) + if err != nil { + c.getLogger().Warnf("cannot get local endpoints: %v", err) + c.localEndpoints.Store(nil) + return + } + c.localEndpoints.Store(&localEndpoints) +} + +func (c *session) getLocalEndpoints() []string { + v := c.localEndpoints.Load() + if v == nil { + return nil + } + if len(*v) == 0 { + return nil + } + return *v +} + func (c *session) notifyContentChanged(deviceID, href string, batch bool, notification *pool.Message) error { if !c.blockSignOff.TryAcquire(1) { c.getLogger().Debugf("cannot notify resource /%v%v content changed: signOff processing", deviceID, href) diff --git a/coap-gateway/service/signIn.go b/coap-gateway/service/signIn.go index d50380bb4..6e0bef9b3 100644 --- a/coap-gateway/service/signIn.go +++ b/coap-gateway/service/signIn.go @@ -153,6 +153,7 @@ func (c *session) updateBySignInData(ctx context.Context, upd updateType, device } if upd == updateTypeNew { + c.resolveLocalEndpoints() resp, err := c.server.devicesStatusUpdater.UpdateOnlineStatus(ctx, c) if err != nil { return nil, fmt.Errorf("cannot update cloud device status: %w", err) diff --git a/coap-gateway/uri/uri.go b/coap-gateway/uri/uri.go index 34e82e1f0..b198e124d 100644 --- a/coap-gateway/uri/uri.go +++ b/coap-gateway/uri/uri.go @@ -15,6 +15,8 @@ const ( ResourceDiscovery = Base + "/res" ResourceRoute = ApiV1 + "/devices" - InterfaceQueryKey = "if" - InterfaceQueryKeyPrefix = InterfaceQueryKey + "=" + InterfaceQueryKey = "if" + InterfaceQueryKeyPrefix = InterfaceQueryKey + "=" + ResourceTypeQueryKey = "rt" + ResourceTypeQueryKeyPrefix = ResourceTypeQueryKey + "=" ) diff --git a/grpc-gateway/client/getDevice_test.go b/grpc-gateway/client/getDevice_test.go index d47cbc4b1..f7c806819 100644 --- a/grpc-gateway/client/getDevice_test.go +++ b/grpc-gateway/client/getDevice_test.go @@ -117,6 +117,7 @@ func TestClient_GetDevice(t *testing.T) { got.Device.ProtocolIndependentId = "" got.Device.Metadata.Connection.Id = "" got.Device.Metadata.Connection.ConnectedAt = 0 + got.Device.Metadata.Connection.LocalEndpoints = nil got.Device.Metadata.Connection.ServiceId = "" got.Device.Metadata.TwinSynchronization.SyncingAt = 0 got.Device.Metadata.TwinSynchronization.InSyncAt = 0 diff --git a/grpc-gateway/client/getDevices_test.go b/grpc-gateway/client/getDevices_test.go index 289cd9c65..828b3917c 100644 --- a/grpc-gateway/client/getDevices_test.go +++ b/grpc-gateway/client/getDevices_test.go @@ -21,6 +21,7 @@ func sortDevices(s map[string]*client.DeviceDetails) map[string]*client.DeviceDe x.Device.ProtocolIndependentId = "" x.Device.Metadata.Connection.Id = "" x.Device.Metadata.Connection.ConnectedAt = 0 + x.Device.Metadata.Connection.LocalEndpoints = nil x.Device.Metadata.Connection.ServiceId = "" x.Device.Metadata.TwinSynchronization.SyncingAt = 0 x.Device.Metadata.TwinSynchronization.InSyncAt = 0 diff --git a/grpc-gateway/pb/service.swagger.json b/grpc-gateway/pb/service.swagger.json index f42b11cca..826952e78 100644 --- a/grpc-gateway/pb/service.swagger.json +++ b/grpc-gateway/pb/service.swagger.json @@ -1393,6 +1393,13 @@ "serviceId": { "type": "string", "description": "The service.ID, which identify the device being served, must be set when the status is ONLINE. However, during an OFFLINE event, they will be sed to empty values." + }, + "localEndpoints": { + "type": "array", + "items": { + "type": "string" + }, + "description": "The last local endpoints of the device, and it is set when the status is ONLINE." } } }, diff --git a/http-gateway/swagger.yaml b/http-gateway/swagger.yaml index fd7cdc5a2..c43d8b28a 100644 --- a/http-gateway/swagger.yaml +++ b/http-gateway/swagger.yaml @@ -961,6 +961,14 @@ components: type: string format: int64 description: "Unix timestamp in nanoseconds." + serviceId: + type: string + description: "The service.ID, which identify the device being served, must be set when the status is ONLINE. However, during an OFFLINE event, they will be sed to empty values." + localEndpoints: + type: array + description: "The last local endpoints of the device, and it is set when the status is ONLINE." + items: + type: string twinSynchronization: $ref: "#/components/schemas/TwinSynchronization" twinEnabled: @@ -1636,14 +1644,14 @@ components: title: "Visibility" deviceProvisioningService: type: string - title": "Address to device provisioning service HTTP API in format https://host:port" + title: "Address to device provisioning service HTTP API in format https://host:port" UIVisibility: type: object description: | true - show, false - hide properties: mainSidebar: - $ref: "#/definitions/UIVisibilityMainSidebar" + $ref: "#/components/schemas/UIVisibilityMainSidebar" title: "Main sidebar visibility" parameters: deviceId: diff --git a/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/DevicesDetailsPage.tsx b/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/DevicesDetailsPage.tsx index 222cc871c..4bcc0a468 100644 --- a/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/DevicesDetailsPage.tsx +++ b/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/DevicesDetailsPage.tsx @@ -236,6 +236,7 @@ const DevicesDetailsPage: FC = (props) => { softwareUpdateData={softwareUpdateData?.result?.data?.content} twinSyncLoading={twinSyncLoading} types={data?.types} + endpoints={data?.metadata?.connection?.localEndpoints} /> ), }, diff --git a/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.tsx b/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.tsx index 508d0db23..69c45b69b 100644 --- a/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.tsx +++ b/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.tsx @@ -21,8 +21,19 @@ import DateFormat from '@/containers/PendingCommands/DateFormat' import testId from '@/testId' const Tab1: FC = (props) => { - const { isTwinEnabled, setTwinSynchronization, twinSyncLoading, deviceId, types, deviceName, model, pendingCommandsData, firmware, softwareUpdateData } = - props + const { + isTwinEnabled, + setTwinSynchronization, + twinSyncLoading, + deviceId, + types, + deviceName, + model, + pendingCommandsData, + firmware, + softwareUpdateData, + endpoints, + } = props const { formatMessage: _ } = useIntl() const resourceRegistrationObservationWSKey = getResourceRegistrationNotificationKey(deviceId) @@ -156,6 +167,22 @@ const Tab1: FC = (props) => { ), }, { attribute: _(t.status), value: pendingCommandsData ? `${pendingCommandsData.length} pending commands` : '-' }, + { + attribute: _(t.endpoints), + value: endpoints ? ( + + {endpoints?.map?.((endpoint: string) => {endpoint})} + + ) : ( +
-
+ ), + }, ]} /> diff --git a/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.types.ts b/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.types.ts index a82229bcb..fd020f3ae 100644 --- a/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.types.ts +++ b/http-gateway/web/src/containers/Devices/Detail/DevicesDetailsPage/Tabs/Tab1.types.ts @@ -20,4 +20,5 @@ export type Props = { purl: string // url with query parameters to update server signed: string // "vendor" } + endpoints?: string[] } diff --git a/http-gateway/web/src/containers/Devices/Devices.i18n.ts b/http-gateway/web/src/containers/Devices/Devices.i18n.ts index f4481918c..b4f4ea3be 100644 --- a/http-gateway/web/src/containers/Devices/Devices.i18n.ts +++ b/http-gateway/web/src/containers/Devices/Devices.i18n.ts @@ -565,4 +565,8 @@ export const messages = defineMessages({ id: 'devices.dps', defaultMessage: 'DPS', }, + endpoints: { + id: 'devices.endpoints', + defaultMessage: 'Endpoints', + }, }) diff --git a/http-gateway/web/src/containers/Devices/Devices.types.ts b/http-gateway/web/src/containers/Devices/Devices.types.ts index aabc69bf6..2621b8bad 100644 --- a/http-gateway/web/src/containers/Devices/Devices.types.ts +++ b/http-gateway/web/src/containers/Devices/Devices.types.ts @@ -26,6 +26,7 @@ export type DeviceDataType = { } connection?: { status?: string + localEndpoints?: string[] } twinEnabled?: boolean } diff --git a/pkg/log/logKeys.go b/pkg/log/logKeys.go index aa6335560..0ffe57c60 100644 --- a/pkg/log/logKeys.go +++ b/pkg/log/logKeys.go @@ -29,6 +29,7 @@ var ( MessageKey = "message" SubjectsKey = "subjects" CertManagerKey = "certManager" + LocalEndpointsKey = "localEndpoints" ) func DurationToMilliseconds(duration time.Duration) float32 { diff --git a/pkg/net/coap/getResourceLinks.go b/pkg/net/coap/getResourceLinks.go new file mode 100644 index 000000000..3e1dfa7fe --- /dev/null +++ b/pkg/net/coap/getResourceLinks.go @@ -0,0 +1,84 @@ +package coap + +import ( + "context" + "fmt" + "net" + + "github.com/plgd-dev/device/v2/schema" + "github.com/plgd-dev/device/v2/schema/device" + "github.com/plgd-dev/device/v2/schema/interfaces" + "github.com/plgd-dev/device/v2/schema/resources" + "github.com/plgd-dev/go-coap/v3/message" + "github.com/plgd-dev/go-coap/v3/message/codes" + "github.com/plgd-dev/go-coap/v3/message/pool" + "github.com/plgd-dev/hub/v2/coap-gateway/uri" + "github.com/plgd-dev/kit/v2/codec/cbor" +) + +type ClientConn = interface { + Get(ctx context.Context, path string, opts ...message.Option) (*pool.Message, error) + ReleaseMessage(m *pool.Message) + RemoteAddr() net.Addr +} + +// GetResourceLinks queries the resource links from the given resource. +func GetResourceLinks(ctx context.Context, coapConn ClientConn, href string, opts ...message.Option) (schema.ResourceLinks, uint64, error) { + msg, err := coapConn.Get(ctx, href, opts...) + if err != nil { + return schema.ResourceLinks{}, 0, err + } + defer coapConn.ReleaseMessage(msg) + + if msg.Code() != codes.Content { + return schema.ResourceLinks{}, 0, fmt.Errorf("invalid response code %v", msg.Code()) + } + + data := msg.Body() + if data == nil { + return schema.ResourceLinks{}, 0, fmt.Errorf("empty response") + } + + var links schema.ResourceLinks + err = cbor.ReadFrom(msg.Body(), &links) + if err != nil { + return schema.ResourceLinks{}, 0, err + } + + return links, msg.Sequence(), nil +} + +// GetResourceLinksWithLinkInterface query resource links from the given resource with the interface oic.if.ll. +func GetResourceLinksWithLinkInterface(ctx context.Context, coapConn ClientConn, href string) (schema.ResourceLinks, uint64, error) { + return GetResourceLinks(ctx, coapConn, href, message.Option{ + ID: message.URIQuery, + Value: []byte(uri.InterfaceQueryKeyPrefix + interfaces.OC_IF_LL), + }) +} + +// GetEndpointsFromResourceType retrieves the endpoints associated with a specific resource type. +func GetEndpointsFromResourceType(ctx context.Context, coapConn ClientConn, resourceType string) ([]string, error) { + links, _, err := GetResourceLinks(ctx, coapConn, resources.ResourceURI, message.Option{ + ID: message.URIQuery, + Value: []byte(uri.InterfaceQueryKeyPrefix + interfaces.OC_IF_LL), + }, message.Option{ + ID: message.URIQuery, + Value: []byte(uri.ResourceTypeQueryKeyPrefix + resourceType), + }) + if err != nil { + return nil, err + } + if len(links) == 0 { + return nil, fmt.Errorf("no local endpoints found") + } + endpoints := make([]string, 0, 8) + for _, ep := range links[0].Endpoints { + endpoints = append(endpoints, ep.URI) + } + return endpoints, nil +} + +// GetEndpointsFromDeviceResource retrieves the endpoints from the device resource. +func GetEndpointsFromDeviceResource(ctx context.Context, coapConn ClientConn) ([]string, error) { + return GetEndpointsFromResourceType(ctx, coapConn, device.ResourceType) +} diff --git a/pkg/net/coap/getResourceLinks_test.go b/pkg/net/coap/getResourceLinks_test.go new file mode 100644 index 000000000..9b951b49a --- /dev/null +++ b/pkg/net/coap/getResourceLinks_test.go @@ -0,0 +1,244 @@ +package coap_test + +import ( + "bytes" + "context" + "net" + "strings" + "testing" + + "github.com/plgd-dev/device/v2/schema" + "github.com/plgd-dev/device/v2/schema/device" + "github.com/plgd-dev/device/v2/schema/resources" + "github.com/plgd-dev/go-coap/v3/message" + "github.com/plgd-dev/go-coap/v3/message/codes" + "github.com/plgd-dev/go-coap/v3/message/pool" + "github.com/plgd-dev/hub/v2/coap-gateway/uri" + "github.com/plgd-dev/hub/v2/pkg/net/coap" + "github.com/plgd-dev/hub/v2/test" + "github.com/stretchr/testify/require" +) + +type testCoapConn struct { + devID string + links schema.ResourceLinks + t *testing.T +} + +func (t *testCoapConn) Get(ctx context.Context, path string, opts ...message.Option) (*pool.Message, error) { + var rtFilter []string + for _, opt := range opts { + if opt.ID == message.URIQuery { + vals := strings.SplitN(string(opt.Value), "=", 2) + if len(vals) != 2 { + continue + } + if vals[0] == uri.ResourceTypeQueryKey { + rtFilter = append(rtFilter, vals[1]) + } + } + } + resp := pool.NewMessage(ctx) + switch path { + case device.ResourceURI: + resp.SetCode(codes.Content) + resp.SetContentFormat(message.AppOcfCbor) + resp.SetBody(bytes.NewReader(test.EncodeToCbor(t.t, device.Device{ + ID: t.devID, + }))) + return resp, nil + case resources.ResourceURI: + links := t.links + if len(rtFilter) > 0 { + links = links.GetResourceLinks(rtFilter...) + } + if len(links) == 0 { + resp.SetCode(codes.BadRequest) + return resp, nil + } + resp.SetCode(codes.Content) + resp.SetContentFormat(message.AppOcfCbor) + resp.SetBody(bytes.NewReader(test.EncodeToCbor(t.t, links))) + return resp, nil + } + resp.SetCode(codes.NotFound) + return resp, nil +} + +func (t *testCoapConn) ReleaseMessage(*pool.Message) { +} + +func (t *testCoapConn) RemoteAddr() net.Addr { + return &net.TCPAddr{} +} + +func TestGetEndpointsFromDeviceResource(t *testing.T) { + type args struct { + ctx context.Context + coapConn coap.ClientConn + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "valid", + args: args{ + ctx: context.Background(), + coapConn: &testCoapConn{ + t: t, + devID: "dev1", + links: schema.ResourceLinks{ + { + DeviceID: "00000000-0000-0000-0000-000000000001", + Href: device.ResourceURI, + ResourceTypes: []string{device.ResourceType}, + Endpoints: []schema.Endpoint{ + { + URI: "coap://localhost:5683", + }, + { + URI: "coaps://localhost:5684", + }, + }, + }, + }, + }, + }, + want: []string{"coap://localhost:5683", "coaps://localhost:5684"}, + }, + { + name: "rt not found", + args: args{ + ctx: context.Background(), + coapConn: &testCoapConn{ + t: t, + devID: "dev1", + links: schema.ResourceLinks{ + { + DeviceID: "00000000-0000-0000-0000-000000000001", + Href: resources.ResourceURI, + ResourceTypes: []string{resources.ResourceType}, + Endpoints: []schema.Endpoint{ + { + URI: "coap://localhost:5683", + }, + { + URI: "coaps://localhost:5684", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := coap.GetEndpointsFromDeviceResource(tt.args.ctx, tt.args.coapConn) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} + +func TestGetResourceLinksWithLinkInterface(t *testing.T) { + type args struct { + ctx context.Context + coapConn coap.ClientConn + href string + } + tests := []struct { + name string + args args + want schema.ResourceLinks + wantErr bool + }{ + { + name: "valid", + args: args{ + ctx: context.Background(), + href: resources.ResourceURI, + coapConn: &testCoapConn{ + t: t, + devID: "dev1", + links: schema.ResourceLinks{ + { + DeviceID: "00000000-0000-0000-0000-000000000001", + Href: device.ResourceURI, + ResourceTypes: []string{device.ResourceType}, + Endpoints: []schema.Endpoint{ + { + URI: "coap://localhost:5683", + }, + { + URI: "coaps://localhost:5684", + }, + }, + }, + }, + }, + }, + want: schema.ResourceLinks{ + { + DeviceID: "00000000-0000-0000-0000-000000000001", + Href: device.ResourceURI, + ResourceTypes: []string{device.ResourceType}, + Endpoints: []schema.Endpoint{ + { + URI: "coap://localhost:5683", + }, + { + URI: "coaps://localhost:5684", + }, + }, + }, + }, + }, + { + name: "rt not found", + args: args{ + ctx: context.Background(), + href: device.ResourceURI, + coapConn: &testCoapConn{ + t: t, + devID: "dev1", + links: schema.ResourceLinks{ + { + DeviceID: "00000000-0000-0000-0000-000000000001", + Href: resources.ResourceURI, + ResourceTypes: []string{resources.ResourceType}, + Endpoints: []schema.Endpoint{ + { + URI: "coap://localhost:5683", + }, + { + URI: "coaps://localhost:5684", + }, + }, + }, + }, + }, + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, _, err := coap.GetResourceLinksWithLinkInterface(tt.args.ctx, tt.args.coapConn, tt.args.href) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/resource-aggregate/commands/commands.pb.go b/resource-aggregate/commands/commands.pb.go index 9bd65d903..9b7f22483 100644 --- a/resource-aggregate/commands/commands.pb.go +++ b/resource-aggregate/commands/commands.pb.go @@ -1783,11 +1783,12 @@ type Connection struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status Connection_Status `protobuf:"varint,1,opt,name=status,proto3,enum=resourceaggregate.pb.Connection_Status" json:"status,omitempty"` - Id string `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"` // when status is ONLINE, this field contains the connection id. To update state offline, this field must be same as the one in the previous message. - ConnectedAt int64 `protobuf:"varint,4,opt,name=connected_at,json=connectedAt,proto3" json:"connected_at,omitempty"` // timestamp when the device was connected - Protocol Connection_Protocol `protobuf:"varint,5,opt,name=protocol,proto3,enum=resourceaggregate.pb.Connection_Protocol" json:"protocol,omitempty"` // application protocol. It need to be set when the status is ONLINE. - ServiceId string `protobuf:"bytes,6,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` // The service.ID, which identify the device being served, must be set when the status is ONLINE. However, during an OFFLINE event, they will be sed to empty values. + Status Connection_Status `protobuf:"varint,1,opt,name=status,proto3,enum=resourceaggregate.pb.Connection_Status" json:"status,omitempty"` + Id string `protobuf:"bytes,3,opt,name=id,proto3" json:"id,omitempty"` // when status is ONLINE, this field contains the connection id. To update state offline, this field must be same as the one in the previous message. + ConnectedAt int64 `protobuf:"varint,4,opt,name=connected_at,json=connectedAt,proto3" json:"connected_at,omitempty"` // timestamp when the device was connected + Protocol Connection_Protocol `protobuf:"varint,5,opt,name=protocol,proto3,enum=resourceaggregate.pb.Connection_Protocol" json:"protocol,omitempty"` // application protocol. It need to be set when the status is ONLINE. + ServiceId string `protobuf:"bytes,6,opt,name=service_id,json=serviceId,proto3" json:"service_id,omitempty"` // The service.ID, which identify the device being served, must be set when the status is ONLINE. However, during an OFFLINE event, they will be sed to empty values. + LocalEndpoints []string `protobuf:"bytes,7,rep,name=local_endpoints,json=localEndpoints,proto3" json:"local_endpoints,omitempty"` // The last local endpoints of the device, and it is set when the status is ONLINE. } func (x *Connection) Reset() { @@ -1857,6 +1858,13 @@ func (x *Connection) GetServiceId() string { return "" } +func (x *Connection) GetLocalEndpoints() []string { + if x != nil { + return x.LocalEndpoints + } + return nil +} + type TwinSynchronization struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3154,7 +3162,7 @@ var file_resource_aggregate_pb_commands_proto_rawDesc = []byte{ 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xf7, 0x02, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xa0, 0x03, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, @@ -3169,194 +3177,196 @@ var file_resource_aggregate_pb_commands_proto_rawDesc = []byte{ 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 0x22, 0x21, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x4f, - 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, - 0x4e, 0x45, 0x10, 0x01, 0x22, 0x52, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, - 0x04, 0x43, 0x4f, 0x41, 0x50, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4f, 0x41, 0x50, 0x53, - 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x4f, 0x41, 0x50, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x03, - 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x41, 0x50, 0x53, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x04, 0x12, - 0x07, 0x0a, 0x03, 0x43, 0x32, 0x43, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x12, - 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, - 0x69, 0x6c, 0x22, 0xe7, 0x02, 0x0a, 0x13, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x05, 0x73, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x41, 0x74, - 0x12, 0x1c, 0x0a, 0x0a, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x74, 0x12, 0x50, - 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x38, 0x0a, 0x18, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, - 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x16, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x22, 0x40, 0x0a, 0x05, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x53, 0x59, - 0x4e, 0x43, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, - 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, - 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5e, 0x0a, 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x21, 0x0a, 0x06, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, + 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x22, 0x52, 0x0a, + 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, + 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x41, 0x50, 0x10, 0x01, + 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4f, 0x41, 0x50, 0x53, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, + 0x4f, 0x41, 0x50, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x41, + 0x50, 0x53, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x32, 0x43, 0x10, + 0x05, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x12, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0xe7, 0x02, 0x0a, 0x13, + 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x13, 0x74, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, - 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, - 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, - 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, - 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x08, 0x0a, - 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xab, 0x01, - 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, - 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, - 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, - 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xe6, 0x02, 0x0a, 0x22, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, - 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0c, - 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, - 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, + 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, + 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x12, 0x1c, 0x0a, 0x0a, 0x69, 0x6e, 0x5f, + 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, + 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x18, 0x66, 0x6f, 0x72, + 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, + 0x6e, 0x41, 0x74, 0x22, 0x40, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, + 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x00, 0x12, 0x0c, 0x0a, + 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, + 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x5f, 0x53, + 0x59, 0x4e, 0x43, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, + 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5e, 0x0a, + 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4a, 0x04, - 0x08, 0x04, 0x10, 0x05, 0x22, 0x6e, 0x0a, 0x23, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, - 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x22, 0xe7, 0x01, 0x0a, 0x1c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x91, - 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, - 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x23, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x98, 0x01, - 0x0a, 0x24, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, - 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x35, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x22, - 0x7f, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x13, 0x74, 0x77, 0x69, 0x6e, 0x53, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, + 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, + 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, + 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, + 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, + 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x22, 0x8d, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, - 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, - 0x6c, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, - 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x22, 0x70, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x46, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x48, 0x00, 0x52, 0x09, 0x68, - 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x22, 0x53, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x13, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x56, 0x61, 0x6c, - 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, - 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x73, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xab, 0x01, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x22, 0xe6, 0x02, 0x0a, 0x22, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, + 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, + 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, + 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, + 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x6e, 0x0a, + 0x23, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, + 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xe7, 0x01, + 0x0a, 0x1c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, + 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x91, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x6e, 0x63, + 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, + 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x23, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x98, 0x01, 0x0a, 0x24, 0x43, 0x61, 0x6e, 0x63, 0x65, + 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x22, 0x35, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x22, 0x7f, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, + 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, + 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x8d, 0x01, 0x0a, 0x10, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, + 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, + 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, + 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x22, 0x70, 0x0a, 0x1c, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x09, 0x68, 0x65, 0x61, + 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, + 0x62, 0x65, 0x61, 0x74, 0x48, 0x00, 0x52, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, + 0x74, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x53, 0x0a, 0x1d, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, + 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, + 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x68, 0x65, 0x61, + 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, + 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, + 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go b/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go index d1388b868..d309c1343 100644 --- a/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go +++ b/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go @@ -82,7 +82,7 @@ func TestParallelRequest(t *testing.T) { href := "/test/resource/1" newAggregate := func(deviceID, href string) *aggregate.Aggregate { - a, err := aggregate.NewAggregate(deviceID, commands.NewResourceID(deviceID, href).ToUUID().String(), aggregate.NewDefaultRetryFunc(64), store, func(context.Context) (aggregate.AggregateModel, error) { + a, err := aggregate.NewAggregate(deviceID, commands.NewResourceID(deviceID, href).ToUUID().String(), aggregate.NewDefaultRetryFunc(128), store, func(context.Context) (aggregate.AggregateModel, error) { ev := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") ev.ResourceId = commands.NewResourceID(deviceID, href) return ev, nil diff --git a/resource-aggregate/events/deviceMetadataSnapshotTaken.go b/resource-aggregate/events/deviceMetadataSnapshotTaken.go index e213803da..d4756de78 100644 --- a/resource-aggregate/events/deviceMetadataSnapshotTaken.go +++ b/resource-aggregate/events/deviceMetadataSnapshotTaken.go @@ -356,6 +356,11 @@ func (d *DeviceMetadataSnapshotTaken) updateDeviceConnection(ctx context.Context req.GetConnection().ConnectedAt = lastConnectedAt } + // keep local endpoints from the previous event + if len(req.GetConnection().GetLocalEndpoints()) == 0 { + req.GetConnection().LocalEndpoints = d.GetDeviceMetadataUpdated().GetConnection().GetLocalEndpoints() + } + getTwinSynchronization := d.getTwinSynchronizationForDisconnectedDevice if req.GetConnection().IsOnline() { getTwinSynchronization = d.getTwinSynchronizationForConnectedDevice diff --git a/resource-aggregate/events/deviceMetadataSnapshotTaken_test.go b/resource-aggregate/events/deviceMetadataSnapshotTaken_test.go index 444e765fe..eb7189ce4 100644 --- a/resource-aggregate/events/deviceMetadataSnapshotTaken_test.go +++ b/resource-aggregate/events/deviceMetadataSnapshotTaken_test.go @@ -16,13 +16,16 @@ import ( "google.golang.org/protobuf/proto" ) +var localEndpoints = []string{"coap://localhost:5683"} + var testEventDeviceMetadataSnapshotTaken events.DeviceMetadataSnapshotTaken = events.DeviceMetadataSnapshotTaken{ DeviceId: dev1, DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ DeviceId: dev1, Connection: &commands.Connection{ - Status: commands.Connection_ONLINE, - Id: "con1", + Status: commands.Connection_ONLINE, + Id: "con1", + LocalEndpoints: localEndpoints, }, TwinEnabled: true, AuditContext: &commands.AuditContext{ @@ -170,9 +173,10 @@ func TestDeviceMetadataSnapshotTakenHandleCommand(t *testing.T) { CorrelationId: correlationID, Update: &commands.UpdateDeviceMetadataRequest_Connection{ Connection: &commands.Connection{ - Status: commands.Connection_ONLINE, - ConnectedAt: connectedAt, - Protocol: commands.Connection_COAPS, + Status: commands.Connection_ONLINE, + ConnectedAt: connectedAt, + Protocol: commands.Connection_COAPS, + LocalEndpoints: localEndpoints, }, }, }, @@ -181,9 +185,10 @@ func TestDeviceMetadataSnapshotTakenHandleCommand(t *testing.T) { pb.ToEvent(&events.DeviceMetadataUpdated{ DeviceId: deviceID, Connection: &commands.Connection{ - Status: commands.Connection_ONLINE, - ConnectedAt: connectedAt, - Protocol: commands.Connection_COAPS, + Status: commands.Connection_ONLINE, + ConnectedAt: connectedAt, + Protocol: commands.Connection_COAPS, + LocalEndpoints: localEndpoints, }, TwinEnabled: true, TwinSynchronization: &commands.TwinSynchronization{}, @@ -230,9 +235,10 @@ func TestDeviceMetadataSnapshotTakenHandleCommand(t *testing.T) { pb.ToEvent(&events.DeviceMetadataUpdated{ DeviceId: deviceID, Connection: &commands.Connection{ - Status: commands.Connection_OFFLINE, - ConnectedAt: connectedAt, - Protocol: commands.Connection_COAPS, + Status: commands.Connection_OFFLINE, + ConnectedAt: connectedAt, + Protocol: commands.Connection_COAPS, + LocalEndpoints: localEndpoints, }, TwinEnabled: true, TwinSynchronization: &commands.TwinSynchronization{}, diff --git a/resource-aggregate/events/deviceMetadataUpdated.go b/resource-aggregate/events/deviceMetadataUpdated.go index 86c56fd19..07085dcdd 100644 --- a/resource-aggregate/events/deviceMetadataUpdated.go +++ b/resource-aggregate/events/deviceMetadataUpdated.go @@ -6,6 +6,7 @@ import ( pkgTime "github.com/plgd-dev/hub/v2/pkg/time" commands "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" + "golang.org/x/exp/slices" "google.golang.org/protobuf/proto" ) @@ -74,6 +75,7 @@ func (d *DeviceMetadataUpdated) Equal(upd *DeviceMetadataUpdated) bool { return d.GetConnection().GetStatus() == upd.GetConnection().GetStatus() && d.GetConnection().GetId() == upd.GetConnection().GetId() && d.GetConnection().GetProtocol() == upd.GetConnection().GetProtocol() && + slices.Equal(d.GetConnection().GetLocalEndpoints(), upd.GetConnection().GetLocalEndpoints()) && d.GetCanceled() == upd.GetCanceled() && d.GetTwinEnabled() == upd.GetTwinEnabled() && d.GetAuditContext().GetUserId() == upd.GetAuditContext().GetUserId() && diff --git a/resource-aggregate/pb/commands.proto b/resource-aggregate/pb/commands.proto index dcac3dd94..ed8163b1b 100644 --- a/resource-aggregate/pb/commands.proto +++ b/resource-aggregate/pb/commands.proto @@ -443,6 +443,7 @@ message Connection { } Protocol protocol = 5; // application protocol. It need to be set when the status is ONLINE. string service_id = 6; // The service.ID, which identify the device being served, must be set when the status is ONLINE. However, during an OFFLINE event, they will be sed to empty values. + repeated string local_endpoints = 7; // The last local endpoints of the device, and it is set when the status is ONLINE. } //******************************************************************************************************************************************************* // Update Device Metadata - Twin Synchronization State diff --git a/resource-directory/service/getDevices_test.go b/resource-directory/service/getDevices_test.go index c3ec3b128..c07fa1645 100644 --- a/resource-directory/service/getDevices_test.go +++ b/resource-directory/service/getDevices_test.go @@ -166,6 +166,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { dev.ProtocolIndependentId = "" dev.Metadata.Connection.Id = "" dev.Metadata.Connection.ConnectedAt = 0 + dev.Metadata.Connection.LocalEndpoints = nil dev.Metadata.Connection.ServiceId = "" dev.Metadata.TwinSynchronization.SyncingAt = 0 dev.Metadata.TwinSynchronization.InSyncAt = 0 diff --git a/test/pb/device.go b/test/pb/device.go index a5c8b641c..b94a06927 100644 --- a/test/pb/device.go +++ b/test/pb/device.go @@ -18,6 +18,7 @@ func CmpDeviceValues(t *testing.T, expected, got []*pbGrpc.Device) { dev.ProtocolIndependentId = "" dev.Metadata.Connection.Id = "" dev.Metadata.Connection.ConnectedAt = 0 + dev.Metadata.Connection.LocalEndpoints = nil dev.Metadata.Connection.ServiceId = "" if dev.Metadata.TwinSynchronization != nil { dev.Metadata.TwinSynchronization.SyncingAt = 0 @@ -61,6 +62,7 @@ func CleanUpDeviceMetadataUpdated(e *events.DeviceMetadataUpdated, resetCorrelat } e.GetConnection().Id = "" e.GetConnection().ConnectedAt = 0 + e.GetConnection().LocalEndpoints = nil } if e.GetTwinSynchronization() != nil { e.GetTwinSynchronization().CommandMetadata = nil diff --git a/test/test.go b/test/test.go index 4860f32fb..e84a2769e 100644 --- a/test/test.go +++ b/test/test.go @@ -592,6 +592,11 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, val.DeviceMetadataUpdated.GetConnection().ConnectedAt = 0 require.NotEmpty(t, val.DeviceMetadataUpdated.GetConnection().GetServiceId()) val.DeviceMetadataUpdated.GetConnection().ServiceId = "" + if !config.COAP_GATEWAY_UDP_ENABLED { + // TODO: fix bug in iotivity-lite, for DTLS it is not fill endpoints + require.NotEmpty(t, val.DeviceMetadataUpdated.GetConnection().GetLocalEndpoints()) + } + val.DeviceMetadataUpdated.GetConnection().LocalEndpoints = nil } if val.DeviceMetadataUpdated.GetTwinSynchronization() != nil { val.DeviceMetadataUpdated.GetTwinSynchronization().CommandMetadata = nil diff --git a/test/virtual-device/virtualDevice.go b/test/virtual-device/virtualDevice.go index bbbfaf423..ce2948774 100644 --- a/test/virtual-device/virtualDevice.go +++ b/test/virtual-device/virtualDevice.go @@ -80,10 +80,11 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin CorrelationId: uuid.NewString(), Update: &commands.UpdateDeviceMetadataRequest_Connection{ Connection: &commands.Connection{ - Status: commands.Connection_ONLINE, - ConnectedAt: time.Now().UnixNano(), - Protocol: protocol, - ServiceId: "a0000000-0000-0000-0000-000000000099", + Status: commands.Connection_ONLINE, + ConnectedAt: time.Now().UnixNano(), + Protocol: protocol, + ServiceId: "a0000000-0000-0000-0000-000000000099", + LocalEndpoints: []string{"coaps+tcp://localhost:5684"}, }, }, TimeToLive: time.Now().Add(time.Hour).UnixNano(), From 18e99fd2eab72acc131b9bc628320fa89db85e31 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Sat, 2 Mar 2024 12:36:49 +0100 Subject: [PATCH 07/31] Update measureMemory.yml --- .github/workflows/measureMemory.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/measureMemory.yml b/.github/workflows/measureMemory.yml index 201e0604b..f011846ef 100644 --- a/.github/workflows/measureMemory.yml +++ b/.github/workflows/measureMemory.yml @@ -288,7 +288,7 @@ jobs: - name: Resolve database id: db run: | - if [ "${{ github.event_name != 'workflow_dispatch' || inputs.cql }}" == "true" ]; then + if [ "${{ github.event_name == 'workflow_dispatch' && inputs.cql }}" == "true" ]; then echo "name=cqldb" >> $GITHUB_OUTPUT else echo "name=mongodb" >> $GITHUB_OUTPUT From db43d184b6e34be75f4df62832e17973ad225343 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Mon, 4 Mar 2024 08:09:46 +0000 Subject: [PATCH 08/31] coap-gateway: report local endpoints only once through logs --- coap-gateway/service/log.go | 4 ---- coap-gateway/service/session.go | 24 +++--------------------- coap-gateway/service/signIn.go | 1 - 3 files changed, 3 insertions(+), 26 deletions(-) diff --git a/coap-gateway/service/log.go b/coap-gateway/service/log.go index 172e8a10a..9b55c1a14 100644 --- a/coap-gateway/service/log.go +++ b/coap-gateway/service/log.go @@ -96,10 +96,6 @@ func (c *session) getLogger() log.Logger { if deviceID != "" { logger = logger.With(log.DeviceIDKey, deviceID) } - localEndpoints := c.getLocalEndpoints() - if len(localEndpoints) > 0 { - logger = logger.With(log.LocalEndpointsKey, localEndpoints) - } select { case <-c.coapConn.Done(): logger = logger.With("closedConnection", true) diff --git a/coap-gateway/service/session.go b/coap-gateway/service/session.go index 9cc80e294..3fca51dde 100644 --- a/coap-gateway/service/session.go +++ b/coap-gateway/service/session.go @@ -9,7 +9,6 @@ import ( "math" "net" "sync" - "sync/atomic" "time" "github.com/pion/dtls/v2" @@ -107,7 +106,6 @@ type session struct { exchangeCache *ExchangeCache refreshCache *RefreshCache tlsDeviceID string - localEndpoints atomic.Pointer[[]string] private struct { // guarded by mutex mutex sync.Mutex authCtx *authorizationContext @@ -519,30 +517,14 @@ func (c *session) batchNotifyContentChanged(ctx context.Context, deviceID string return err } -func (c *session) resolveLocalEndpoints() { - v := []string{} - if !c.localEndpoints.CompareAndSwap(nil, &v) { - return - } - +func (c *session) getLocalEndpoints() []string { localEndpoints, err := coap.GetEndpointsFromDeviceResource(c.Context(), c) if err != nil { c.getLogger().Warnf("cannot get local endpoints: %v", err) - c.localEndpoints.Store(nil) - return - } - c.localEndpoints.Store(&localEndpoints) -} - -func (c *session) getLocalEndpoints() []string { - v := c.localEndpoints.Load() - if v == nil { - return nil - } - if len(*v) == 0 { return nil } - return *v + c.getLogger().With(log.LocalEndpointsKey, localEndpoints).Debugf("local endpoints retrieval successful.") + return localEndpoints } func (c *session) notifyContentChanged(deviceID, href string, batch bool, notification *pool.Message) error { diff --git a/coap-gateway/service/signIn.go b/coap-gateway/service/signIn.go index 6e0bef9b3..d50380bb4 100644 --- a/coap-gateway/service/signIn.go +++ b/coap-gateway/service/signIn.go @@ -153,7 +153,6 @@ func (c *session) updateBySignInData(ctx context.Context, upd updateType, device } if upd == updateTypeNew { - c.resolveLocalEndpoints() resp, err := c.server.devicesStatusUpdater.UpdateOnlineStatus(ctx, c) if err != nil { return nil, fmt.Errorf("cannot update cloud device status: %w", err) From 4546c6eb4d2040d07d244ba39ea894cb3c92e0b5 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Mon, 4 Mar 2024 11:29:04 +0000 Subject: [PATCH 09/31] certificate-authority: Enable the deletion of multiple signing records --- .../store/mongodb/signingRecords.go | 2 +- .../store/mongodb/signingRecords_test.go | 87 +++++++++++-------- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/certificate-authority/store/mongodb/signingRecords.go b/certificate-authority/store/mongodb/signingRecords.go index 124339e91..00a73514d 100644 --- a/certificate-authority/store/mongodb/signingRecords.go +++ b/certificate-authority/store/mongodb/signingRecords.go @@ -91,7 +91,7 @@ func (s *Store) DeleteSigningRecords(ctx context.Context, owner string, query *s IdFilter: query.GetIdFilter(), DeviceIdFilter: query.GetDeviceIdFilter(), } - res, err := s.Collection(signingRecordsCol).DeleteOne(ctx, toSigningRecordsQueryFilter(owner, &q)) + res, err := s.Collection(signingRecordsCol).DeleteMany(ctx, toSigningRecordsQueryFilter(owner, &q)) if err != nil { return -1, multierror.Append(ErrCannotRemoveSigningRecord, err) } diff --git a/certificate-authority/store/mongodb/signingRecords_test.go b/certificate-authority/store/mongodb/signingRecords_test.go index ff8e81549..fc9ebc7d6 100644 --- a/certificate-authority/store/mongodb/signingRecords_test.go +++ b/certificate-authority/store/mongodb/signingRecords_test.go @@ -103,11 +103,28 @@ func TestStoreUpdateSigningRecord(t *testing.T) { } } -func TestStoreDeleteSigningRecord(t *testing.T) { - const id1 = "9d017fad-2961-4fcc-94a9-1e1291a88ffc" - deviceID1 := hubTest.GenerateDeviceIDbyIdx(1) - const id2 = "9d017fad-2961-4fcc-94a9-1e1291a88ffd" - deviceID2 := hubTest.GenerateDeviceIDbyIdx(2) +func TestStoreDeleteSigningRecords(t *testing.T) { + records := []struct { + id string + deviceID string + }{ + { + id: "9d017fad-2961-4fcc-94a9-1e1291a88ffc", + deviceID: hubTest.GenerateDeviceIDbyIdx(1), + }, + { + id: "9d017fad-2961-4fcc-94a9-1e1291a88ffd", + deviceID: hubTest.GenerateDeviceIDbyIdx(2), + }, + { + id: "9d017fad-2961-4fcc-94a9-1e1291a88ffe", + deviceID: hubTest.GenerateDeviceIDbyIdx(3), + }, + { + id: "9d017fad-2961-4fcc-94a9-1e1291a88fff", + deviceID: hubTest.GenerateDeviceIDbyIdx(4), + }, + } const owner = "owner" type args struct { owner string @@ -134,7 +151,7 @@ func TestStoreDeleteSigningRecord(t *testing.T) { args: args{ owner: "owner1", query: &store.DeleteSigningRecordsQuery{ - IdFilter: []string{id1}, + IdFilter: []string{records[0].id}, }, }, want: 0, @@ -144,7 +161,7 @@ func TestStoreDeleteSigningRecord(t *testing.T) { args: args{ owner: owner, query: &store.DeleteSigningRecordsQuery{ - DeviceIdFilter: []string{deviceID1}, + DeviceIdFilter: []string{records[0].deviceID}, }, }, want: 1, @@ -154,11 +171,21 @@ func TestStoreDeleteSigningRecord(t *testing.T) { args: args{ owner: owner, query: &store.DeleteSigningRecordsQuery{ - IdFilter: []string{id2}, + IdFilter: []string{records[1].id}, }, }, want: 1, }, + { + name: "multiple ids", + args: args{ + owner: owner, + query: &store.DeleteSigningRecordsQuery{ + IdFilter: []string{records[2].id, records[3].id}, + }, + }, + want: 2, + }, { name: "valid - empty", args: args{ @@ -173,34 +200,22 @@ func TestStoreDeleteSigningRecord(t *testing.T) { defer cleanUpStore() ctx := context.Background() - err := s.CreateSigningRecord(ctx, &store.SigningRecord{ - Id: id1, - Owner: owner, - CommonName: "commonName", - PublicKey: "publicKey", - DeviceId: deviceID1, - CreationDate: constDate().UnixNano(), - Credential: &pb.CredentialStatus{ - CertificatePem: "certificate", - Date: constDate().UnixNano(), - ValidUntilDate: constDate().UnixNano(), - }, - }) - require.NoError(t, err) - err = s.CreateSigningRecord(ctx, &store.SigningRecord{ - Id: id2, - Owner: owner, - CommonName: "commonName", - PublicKey: "publicKey", - DeviceId: deviceID2, - CreationDate: constDate().UnixNano(), - Credential: &pb.CredentialStatus{ - CertificatePem: "certificate", - Date: constDate().UnixNano(), - ValidUntilDate: constDate().UnixNano(), - }, - }) - require.NoError(t, err) + for _, r := range records { + err := s.CreateSigningRecord(ctx, &store.SigningRecord{ + Id: r.id, + Owner: owner, + CommonName: "commonName", + PublicKey: "publicKey", + DeviceId: r.deviceID, + CreationDate: constDate().UnixNano(), + Credential: &pb.CredentialStatus{ + CertificatePem: "certificate", + Date: constDate().UnixNano(), + ValidUntilDate: constDate().UnixNano(), + }, + }) + require.NoError(t, err) + } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From 991e941dfef100a9b551e27493f073e7b761b89b Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Mon, 4 Mar 2024 16:47:30 +0100 Subject: [PATCH 10/31] Do not check endpoints for bridged device in tests --- resource-aggregate/service/aggregate.go | 4 ++-- test/test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/resource-aggregate/service/aggregate.go b/resource-aggregate/service/aggregate.go index 832879bf8..0ed337c31 100644 --- a/resource-aggregate/service/aggregate.go +++ b/resource-aggregate/service/aggregate.go @@ -276,9 +276,9 @@ func (a *Aggregate) cleanUpToSnapshot(ctx context.Context, events []eventstore.E err := a.eventstore.RemoveUpToVersion(ctx, []eventstore.VersionQuery{{GroupID: event.GroupID(), AggregateID: event.AggregateID(), Version: event.Version()}}) if err != nil && !errors.Is(err, eventstore.ErrNotSupported) { if ru, ok := event.(interface{ GetResourceId() *commands.ResourceId }); ok { - log.Info("unable to remove events up to snapshot with version('%v') for resource('%v')", event.Version(), ru.GetResourceId()) + log.Infof("unable to remove events up to snapshot with version('%v') for resource('%v')", event.Version(), ru.GetResourceId()) } else { - log.Info("unable to remove events up to snapshot(%v) with version('%v') of deviceId('%v')", event.EventType(), event.Version(), event.GroupID()) + log.Infof("unable to remove events up to snapshot(%v) with version('%v') of deviceId('%v')", event.EventType(), event.Version(), event.GroupID()) } } } diff --git a/test/test.go b/test/test.go index e84a2769e..44c54f357 100644 --- a/test/test.go +++ b/test/test.go @@ -592,7 +592,7 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, val.DeviceMetadataUpdated.GetConnection().ConnectedAt = 0 require.NotEmpty(t, val.DeviceMetadataUpdated.GetConnection().GetServiceId()) val.DeviceMetadataUpdated.GetConnection().ServiceId = "" - if !config.COAP_GATEWAY_UDP_ENABLED { + if TestDeviceType != device.Bridged && !config.COAP_GATEWAY_UDP_ENABLED { // TODO: fix bug in iotivity-lite, for DTLS it is not fill endpoints require.NotEmpty(t, val.DeviceMetadataUpdated.GetConnection().GetLocalEndpoints()) } From 3683d60231c66a529050a4e35c334bd3ce6fdb53 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 1 Mar 2024 13:24:37 +0100 Subject: [PATCH 11/31] Update GitHub actions golangci/golangci-lint-action: v3 -> v4 --- .github/workflows/golangci-lint.yml | 2 +- .golangci.yml | 13 ++++++++----- go.mod | 5 +++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 9c80297ec..313bb1dae 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -30,7 +30,7 @@ jobs: - run: go version - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v4 with: version: latest args: --timeout=5m diff --git a/.golangci.yml b/.golangci.yml index b0a433957..4d9f826ca 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,13 +5,13 @@ run: skip-dirs-use-default: false linters-settings: - gocyclo: - min-complexity: 15 - govet: - # check-shadowing: true - check-shadowing: false exhaustive: default-signifies-exhaustive: true + gocyclo: + min-complexity: 15 + gomoddirectives: + replace-allow-list: + - github.com/pion/dtls/v2 gomodguard: blocked: modules: @@ -21,6 +21,9 @@ linters-settings: gosec: excludes: - G402 + govet: + # check-shadowing: true + check-shadowing: false stylecheck: go: "1.20" checks: ["all", "-ST1003"] diff --git a/go.mod b/go.mod index e5bca5a6d..83d803b12 100644 --- a/go.mod +++ b/go.mod @@ -126,5 +126,6 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect ) -// note: github.com/pion/dtls/v2/pkg/net package is not yet available in release branches -exclude github.com/pion/dtls/v2 v2.2.9 +// note: github.com/pion/dtls/v2/pkg/net package is not yet available in release branches, +// so we force to the use of the pinned master branch +replace github.com/pion/dtls/v2 => github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 From 6ef1951a7464e5b0b1de293c9635fa5fec179243 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 1 Mar 2024 13:28:43 +0100 Subject: [PATCH 12/31] Update docker images golang: 1.20.13-alpine -> 1.20.14-alpine --- bundle/Dockerfile | 2 +- http-gateway/Dockerfile | 2 +- test/cloud-server/Dockerfile | 2 +- tools/cert-tool/Dockerfile | 2 +- tools/docker/Dockerfile.in | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bundle/Dockerfile b/bundle/Dockerfile index 981ae6c2e..f04a6c0c3 100644 --- a/bundle/Dockerfile +++ b/bundle/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.13-alpine AS build +FROM golang:1.20.14-alpine AS build RUN apk add --no-cache curl git build-base WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ diff --git a/http-gateway/Dockerfile b/http-gateway/Dockerfile index ede92cf49..283d4168d 100644 --- a/http-gateway/Dockerfile +++ b/http-gateway/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.13-alpine AS build +FROM golang:1.20.14-alpine AS build ARG VERSION ARG COMMIT_DATE ARG SHORT_COMMIT diff --git a/test/cloud-server/Dockerfile b/test/cloud-server/Dockerfile index 7c41522f6..d787646f5 100644 --- a/test/cloud-server/Dockerfile +++ b/test/cloud-server/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.13-alpine AS build +FROM golang:1.20.14-alpine AS build ARG VERSION ARG COMMIT_DATE ARG SHORT_COMMIT diff --git a/tools/cert-tool/Dockerfile b/tools/cert-tool/Dockerfile index 18eb73a6a..dbce19b87 100644 --- a/tools/cert-tool/Dockerfile +++ b/tools/cert-tool/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.13-alpine AS build +FROM golang:1.20.14-alpine AS build ARG DIRECTORY ARG NAME ARG VERSION diff --git a/tools/docker/Dockerfile.in b/tools/docker/Dockerfile.in index c120f554e..d88d76351 100644 --- a/tools/docker/Dockerfile.in +++ b/tools/docker/Dockerfile.in @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.13-alpine AS build +FROM golang:1.20.14-alpine AS build ARG VERSION ARG COMMIT_DATE ARG SHORT_COMMIT From 542247ee9e8688b6f079a847cf3659126ae5a916 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 1 Mar 2024 13:29:56 +0100 Subject: [PATCH 13/31] Update hub-test docker image golang: 1.20.13 -> 1.20.14 --- Dockerfile.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile.test b/Dockerfile.test index 9b4d1596d..dbe9f1f8e 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -5,7 +5,7 @@ RUN apt-get update \ # apt: ca-certificates git make sudo RUN git clone https://github.com/udhos/update-golang.git \ && cd update-golang \ - && sudo RELEASE=1.20.13 ./update-golang.sh \ + && sudo RELEASE=1.20.14 ./update-golang.sh \ && ln -s /usr/local/go/bin/go /usr/bin/go WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ From a4dbf262c9ff430c688f9b487fbc40e47cae0817 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 1 Mar 2024 15:46:30 +0100 Subject: [PATCH 14/31] Fix Docker issues reported by SonarCloud --- Dockerfile.test | 8 +++-- bundle/Dockerfile | 70 +++++++++++++++++++++++++++--------- http-gateway/Dockerfile | 14 +++++--- http-gateway/Dockerfile.www | 6 ++-- test/cloud-server/Dockerfile | 13 ++++--- tools/cert-tool/Dockerfile | 10 ++++-- tools/docker/Dockerfile.in | 14 +++++--- 7 files changed, 98 insertions(+), 37 deletions(-) diff --git a/Dockerfile.test b/Dockerfile.test index dbe9f1f8e..6de8e49e3 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -1,6 +1,7 @@ FROM ubuntu:22.04 AS hub-test RUN apt-get update \ && DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends build-essential ca-certificates curl git make patch sudo \ + && apt-get clean \ && curl -sSL https://get.docker.com/ | sh # apt: ca-certificates git make sudo RUN git clone https://github.com/udhos/update-golang.git \ @@ -15,9 +16,12 @@ COPY . . WORKDIR $GOPATH/src/github.com/plgd-dev/hub/tools/cert-tool RUN go build -o /usr/bin/cert-tool -WORKDIR $GOPATH/src/github.com/plgd-dev/hub +WORKDIR /usr/local/go # apt: patch -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch" ) + + +WORKDIR $GOPATH/src/github.com/plgd-dev/hub # RUN go mod tidy diff --git a/bundle/Dockerfile b/bundle/Dockerfile index f04a6c0c3..8ca905053 100644 --- a/bundle/Dockerfile +++ b/bundle/Dockerfile @@ -5,7 +5,10 @@ WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ RUN go mod download COPY . . -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) +WORKDIR /usr/local/go +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch" ) +WORKDIR $GOPATH/src/github.com/plgd-dev/hub + ARG root_directory=$GOPATH/src/github.com/plgd-dev/hub ARG COMMIT_DATE @@ -17,57 +20,90 @@ ARG RELEASE_URL #coap-gateway ARG service=coap-gateway WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #grpc-gateway ARG service=grpc-gateway WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #http-gateway ARG service=http-gateway WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #resource-directory ARG service=resource-directory WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #resource-aggregate ARG service=resource-aggregate WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #identity-store ARG service=identity-store WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #certificate-authority ARG service=certificate-authority WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #oauth-server ARG service=oauth-server WORKDIR $root_directory/test/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #cloud2cloud-gateway ARG service=cloud2cloud-gateway WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #cloud2cloud-connector ARG service=cloud2cloud-connector WORKDIR $root_directory/$service -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$service ./cmd/service +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$service" \ + ./cmd/service #cert-tool ARG tool=cert-tool WORKDIR $root_directory/tools/$tool -RUN go build -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/$tool ./ +RUN go build \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o "/go/bin/$tool" \ + ./ #nats WORKDIR $root_directory @@ -90,18 +126,20 @@ RUN unzip ./nats.zip -d ./nats RUN cp ./nats/*/nats /go/bin/nats FROM ubuntu:22.04 AS service -RUN apt update # iproute2 -> ip utility in run.sh # netcat -> nc utility in run.sh # nginx -> nginx server in run.sh # openssl -> openssl utility in run.sh -RUN apt-get install -y --no-install-recommends ca-certificates gnupg iproute2 netcat nginx openssl wget curl sudo coreutils +RUN apt update \ + && apt-get install -y --no-install-recommends ca-certificates gnupg iproute2 netcat nginx openssl wget curl sudo coreutils \ + && apt-get clean # yq utility in run.sh RUN wget https://github.com/mikefarah/yq/releases/download/v4.6.3/yq_linux_$(dpkg --print-architecture) -O /usr/bin/yq && chmod +x /usr/bin/yq RUN wget -qO - https://pgp.mongodb.com/server-6.0.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb-6.0.gpg RUN echo "deb [ arch=$(dpkg --print-architecture) ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mongodb-org mongodb-org-server +RUN apt update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mongodb-org mongodb-org-server \ + && apt-get clean COPY --from=build /go/bin/coap-gateway /usr/local/bin/coap-gateway COPY --from=build /go/src/github.com/plgd-dev/hub/coap-gateway/config.yaml /configs/coap-gateway.yaml diff --git a/http-gateway/Dockerfile b/http-gateway/Dockerfile index 283d4168d..452259cf4 100644 --- a/http-gateway/Dockerfile +++ b/http-gateway/Dockerfile @@ -11,10 +11,16 @@ COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go mod vendor -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) -RUN ( cd ./vendor/golang.org/x/oauth2 && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/golang_org_x_oauth2_propagate_error.patch ) +WORKDIR /usr/local/go +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch" ) +WORKDIR $GOPATH/src/github.com/plgd-dev/hub/vendor/golang.org/x/oauth2 +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/golang_org_x_oauth2_propagate_error.patch" ) WORKDIR $GOPATH/src/github.com/plgd-dev/hub/http-gateway -RUN CGO_ENABLED=0 go build -mod=vendor -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/http-gateway ./cmd/service +RUN CGO_ENABLED=0 go build \ + -mod=vendor \ + -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o /go/bin/http-gateway \ + ./cmd/service FROM alpine:3.19 AS security-provider RUN apk add -U --no-cache ca-certificates @@ -27,4 +33,4 @@ COPY --from=security-provider /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY http-gateway/web/build /usr/local/var/www COPY --from=build /go/bin/http-gateway /usr/local/bin/http-gateway USER nonroot -ENTRYPOINT [ "/usr/local/bin/http-gateway" ] \ No newline at end of file +ENTRYPOINT [ "/usr/local/bin/http-gateway" ] diff --git a/http-gateway/Dockerfile.www b/http-gateway/Dockerfile.www index 9c97348fa..8cfa637bb 100644 --- a/http-gateway/Dockerfile.www +++ b/http-gateway/Dockerfile.www @@ -1,11 +1,11 @@ # syntax=docker/dockerfile:1 FROM node:18 AS build-web COPY http-gateway/web /web -RUN cd /web && \ - npm config set fetch-retries 3 && \ +WORKDIR /web +RUN npm config set fetch-retries 3 && \ npm config set fetch-retry-mintimeout 600000 && \ npm config set fetch-retry-maxtimeout 1200000 && \ npm config set fetch-timeout 1800000 && \ npm install --ignore-scripts && \ npm run :generate:theme && \ - npm run build \ No newline at end of file + npm run build diff --git a/test/cloud-server/Dockerfile b/test/cloud-server/Dockerfile index d787646f5..ca78855ee 100644 --- a/test/cloud-server/Dockerfile +++ b/test/cloud-server/Dockerfile @@ -10,7 +10,8 @@ WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ RUN go mod download COPY . . -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) +WORKDIR /usr/local/go +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch" ) ARG root_directory=$GOPATH/src/github.com/plgd-dev/hub #cert-tool @@ -55,16 +56,18 @@ RUN unzip ./nats.zip -d ./nats RUN cp ./nats/*/nats /go/bin/nats FROM ubuntu:22.04 AS service -RUN apt update # iproute2 -> ip utility in run.sh # netcat -> nc utility in run.sh # nginx -> nginx server in run.sh # openssl -> openssl utility in run.sh -RUN apt-get install -y --no-install-recommends ca-certificates gnupg iproute2 netcat nginx openssl wget +RUN apt update \ + && apt-get install -y --no-install-recommends ca-certificates gnupg iproute2 netcat nginx openssl wget \ + && apt-get clean RUN wget -qO - https://pgp.mongodb.com/server-6.0.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/mongodb-6.0.gpg RUN echo "deb [ arch=$(dpkg --print-architecture) ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-6.0.list -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mongodb-org mongodb-org-server +RUN apt update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends mongodb-org mongodb-org-server \ + && apt-get clean COPY --from=build /go/bin/cert-tool /usr/local/bin/cert-tool COPY --from=build /go/bin/coap-gateway.test /usr/local/bin/coap-gateway.test COPY --from=build /go/bin/grpc-gateway.test /usr/local/bin/grpc-gateway.test diff --git a/tools/cert-tool/Dockerfile b/tools/cert-tool/Dockerfile index dbce19b87..370f7d98b 100644 --- a/tools/cert-tool/Dockerfile +++ b/tools/cert-tool/Dockerfile @@ -11,9 +11,13 @@ WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ RUN go mod download COPY . . -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) +WORKDIR /usr/local/go +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch" ) WORKDIR $GOPATH/src/github.com/plgd-dev/hub/tools/cert-tool -RUN CGO_ENABLED=0 go build -ldflags "-X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/cert-tool ./ +RUN CGO_ENABLED=0 go build \ + -ldflags "-X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o /go/bin/cert-tool \ + ./ FROM alpine:3.19 AS security-provider RUN addgroup -S nonroot \ @@ -23,4 +27,4 @@ FROM scratch AS service COPY --from=security-provider /etc/passwd /etc/passwd COPY --from=build /go/bin/cert-tool /usr/local/bin/cert-tool USER nonroot -ENTRYPOINT [ "/usr/local/bin/cert-tool" ] \ No newline at end of file +ENTRYPOINT [ "/usr/local/bin/cert-tool" ] diff --git a/tools/docker/Dockerfile.in b/tools/docker/Dockerfile.in index d88d76351..50782a0a8 100644 --- a/tools/docker/Dockerfile.in +++ b/tools/docker/Dockerfile.in @@ -11,10 +11,16 @@ COPY go.mod go.sum ./ RUN go mod download COPY . . RUN go mod vendor -RUN ( cd /usr/local/go && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch ) -RUN ( cd ./vendor/golang.org/x/oauth2 && patch -p1 < $GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/golang_org_x_oauth2_propagate_error.patch ) +WORKDIR /usr/local/go +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shrink_tls_conn.patch" ) +WORKDIR $GOPATH/src/github.com/plgd-dev/hub/vendor/golang.org/x/oauth2 +RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/golang_org_x_oauth2_propagate_error.patch" ) WORKDIR $GOPATH/src/github.com/plgd-dev/hub/@DIRECTORY@ -RUN CGO_ENABLED=0 go build -mod=vendor -ldflags "-X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" -o /go/bin/@NAME@ ./cmd/service +RUN CGO_ENABLED=0 go build \ + -mod=vendor \ + -ldflags "-X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ + -o /go/bin/@NAME@ \ + ./cmd/service FROM alpine:3.19 AS security-provider RUN apk add -U --no-cache ca-certificates @@ -26,4 +32,4 @@ COPY --from=security-provider /etc/passwd /etc/passwd COPY --from=security-provider /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=build /go/bin/@NAME@ /usr/local/bin/@NAME@ USER nonroot -ENTRYPOINT [ "/usr/local/bin/@NAME@" ] \ No newline at end of file +ENTRYPOINT [ "/usr/local/bin/@NAME@" ] From c66a897a69fa349ca630f022fd0285061666f172 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 5 Mar 2024 09:04:25 +0100 Subject: [PATCH 15/31] Upgrade dependencies Submodule: github.com/googleapis/googleapis abe813038ee35695ddf10675fb3690f06c8f9cd4 Direct: github.com/fxamacker/cbor/v2 v2.6.0 github.com/go-co-op/gocron/v2 v2.2.4 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/lestrrat-go/jwx/v2 v2.0.20 github.com/nats-io/nats.go v1.33.1 github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba github.com/stretchr/testify v1.9.0 github.com/tidwall/gjson v1.17.1 go.mongodb.org/mongo-driver v1.14.0 go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 go.opentelemetry.io/otel v1.24.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 go.opentelemetry.io/otel/metric v1.24.0 go.opentelemetry.io/otel/sdk v1.24.0 go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 golang.org/x/net v0.22.0 golang.org/x/oauth2 v0.18.0 google.golang.org/api v0.168.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 google.golang.org/grpc v1.62.0 Indirect: cloud.google.com/go/compute v1.25.0 github.com/envoyproxy/protoc-gen-validate v1.0.4 github.com/googleapis/gax-go/v2 v2.12.2 github.com/klauspost/compress v1.17.7 go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 golang.org/x/crypto v0.21.0 golang.org/x/sys v0.18.0 google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 --- dependency/googleapis | 2 +- go.mod | 67 ++++++++++--------- go.sum | 146 +++++++++++++++++++----------------------- 3 files changed, 100 insertions(+), 115 deletions(-) diff --git a/dependency/googleapis b/dependency/googleapis index fd52f71f4..abe813038 160000 --- a/dependency/googleapis +++ b/dependency/googleapis @@ -1 +1 @@ -Subproject commit fd52f71f4842399b922ba14b3ff0205b669cdedf +Subproject commit abe813038ee35695ddf10675fb3690f06c8f9cd4 diff --git a/go.mod b/go.mod index 83d803b12..24cdeaee0 100644 --- a/go.mod +++ b/go.mod @@ -7,10 +7,10 @@ require ( github.com/felixge/httpsnoop v1.0.4 github.com/fsnotify/fsnotify v1.7.0 github.com/fullstorydev/grpchan v1.1.1 - github.com/fxamacker/cbor/v2 v2.5.0 - github.com/go-co-op/gocron/v2 v2.2.2 + github.com/fxamacker/cbor/v2 v2.6.0 + github.com/go-co-op/gocron/v2 v2.2.4 github.com/gocql/gocql v1.6.0 - github.com/golang-jwt/jwt/v5 v5.2.0 + github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/snappy v0.0.4 github.com/google/go-querystring v1.1.0 github.com/google/uuid v1.6.0 @@ -23,46 +23,46 @@ require ( github.com/json-iterator/go v1.1.12 github.com/jtacoma/uritemplates v1.0.0 github.com/karrick/tparse/v2 v2.8.2 - github.com/lestrrat-go/jwx/v2 v2.0.19 - github.com/nats-io/nats.go v1.32.0 + github.com/lestrrat-go/jwx/v2 v2.0.20 + github.com/nats-io/nats.go v1.33.1 github.com/panjf2000/ants/v2 v2.9.0 github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.2.5-0.20240203174619-48d29f285e4f - github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f + github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c + github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.8.4 - github.com/tidwall/gjson v1.17.0 + github.com/stretchr/testify v1.9.0 + github.com/tidwall/gjson v1.17.1 github.com/tidwall/sjson v1.2.5 github.com/ugorji/go/codec v1.2.12 github.com/vincent-petithory/dataurl v1.0.0 - go.mongodb.org/mongo-driver v1.13.1 - go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0 - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 - go.opentelemetry.io/otel v1.22.0 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 - go.opentelemetry.io/otel/metric v1.22.0 - go.opentelemetry.io/otel/sdk v1.22.0 - go.opentelemetry.io/otel/trace v1.22.0 + go.mongodb.org/mongo-driver v1.14.0 + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/atomic v1.11.0 - go.uber.org/zap v1.26.0 - golang.org/x/exp v0.0.0-20240119083558-1b970713d09a - golang.org/x/net v0.20.0 - golang.org/x/oauth2 v0.16.0 + go.uber.org/zap v1.27.0 + golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 + golang.org/x/net v0.22.0 + golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.6.0 - google.golang.org/api v0.161.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe - google.golang.org/grpc v1.61.0 + google.golang.org/api v0.168.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 + google.golang.org/grpc v1.62.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - cloud.google.com/go/compute v1.23.4 // indirect + cloud.google.com/go/compute v1.25.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/sprig v2.15.0+incompatible // indirect @@ -72,7 +72,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/dsnet/golib/memfile v1.0.0 // indirect - github.com/envoyproxy/protoc-gen-validate v1.0.2 // indirect + github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/goccy/go-json v0.10.2 // indirect @@ -81,7 +81,7 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -89,7 +89,7 @@ require ( github.com/imdario/mergo v0.3.4 // indirect github.com/jhump/protoreflect v1.15.6 // indirect github.com/jonboulle/clockwork v0.4.0 // indirect - github.com/klauspost/compress v1.17.5 // indirect + github.com/klauspost/compress v1.17.7 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.4 // indirect @@ -114,15 +114,14 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) diff --git a/go.sum b/go.sum index 3611611c6..7b36ca297 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.23.4 h1:EBT9Nw4q3zyE7G45Wvv3MzolIrCJEuHys5muLY0wvAw= -cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= +cloud.google.com/go/compute v1.25.0 h1:H1/4SqSUhjPFE7L5ddzHOfY2bCAvjwNRZPNl6Ni5oYU= +cloud.google.com/go/compute v1.25.0/go.mod h1:GR7F0ZPZH8EhChlMo9FkLd7eUTwEymjqQagxzilIxIE= 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= @@ -25,7 +25,6 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA 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-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20231109132714-523115ebc101 h1:7To3pQ+pZo0i3dsWEbinPNFs5gPSBOsJtx3wTT94VBY= 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= @@ -41,8 +40,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 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/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/favadi/protoc-go-inject-tag v1.4.0 h1:K3KXxbgRw5WT4f43LbglARGz/8jVsDOS7uMjG4oNvXY= github.com/favadi/protoc-go-inject-tag v1.4.0/go.mod h1:AZ+PK+QDKUOLlBRG0rYiKkUX5Hw7+7GTFzlU99GFSbQ= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -53,11 +52,11 @@ github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyT github.com/fullstorydev/grpchan v1.1.1 h1:heQqIJlAv5Cnks9a70GRL2EJke6QQoUB25VGR6TZQas= github.com/fullstorydev/grpchan v1.1.1/go.mod h1:f4HpiV8V6htfY/K44GWV1ESQzHBTq7DinhzqQ95lpgc= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE= -github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= +github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= +github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= -github.com/go-co-op/gocron/v2 v2.2.2 h1:XgQIiocDrdSX/B2AICR0FWk4ZeyJzeK5LVmLRoou3F0= -github.com/go-co-op/gocron/v2 v2.2.2/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= +github.com/go-co-op/gocron/v2 v2.2.4 h1:fL6a8/U+BJQ9UbaeqKxua8wY02w4ftKZsxPzLSNOCKk= +github.com/go-co-op/gocron/v2 v2.2.4/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -79,8 +78,8 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= +github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= @@ -101,7 +100,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 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/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -125,8 +123,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= @@ -173,9 +171,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPquI5E= -github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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= @@ -193,8 +190,8 @@ github.com/lestrrat-go/iter v0.0.0-20200422075355-fc1769541911/go.mod h1:zIdgO1m github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= github.com/lestrrat-go/jwx v1.0.2/go.mod h1:TPF17WiSFegZo+c20fdpw49QD+/7n4/IsGvEmCSWwT0= -github.com/lestrrat-go/jwx/v2 v2.0.19 h1:ekv1qEZE6BVct89QA+pRF6+4pCpfVrOnEJnTnT4RXoY= -github.com/lestrrat-go/jwx/v2 v2.0.19/go.mod h1:l3im3coce1lL2cDeAjqmaR+Awx+X8Ih+2k8BuHNJ4CU= +github.com/lestrrat-go/jwx/v2 v2.0.20 h1:sAgXuWS/t8ykxS9Bi2Qtn5Qhpakw1wrcjxChudjolCc= +github.com/lestrrat-go/jwx/v2 v2.0.20/go.mod h1:UlCSmKqw+agm5BsOBfEAbTvKsEApaGNqHAEUTv5PJC4= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/pdebug v0.0.0-20200204225717-4d6bd78da58d/go.mod h1:B06CSso/AWxiPejj+fheUINGeBKeeEZNt8w+EoU7+L8= @@ -204,13 +201,12 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w 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/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 h1:28i1IjGcx8AofiB4N3q5Yls55VEaitzuEPkFJEVgGkA= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= -github.com/nats-io/nats.go v1.32.0 h1:Bx9BZS+aXYlxW08k8Gd3yR2s73pV5XSoAQUyp1Kwvp0= -github.com/nats-io/nats.go v1.32.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nats.go v1.33.1 h1:8TxLZZ/seeEfR97qV0/Bl939tpDnt2Z2fK3HkPypj70= +github.com/nats-io/nats.go v1.33.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -220,26 +216,20 @@ github.com/panjf2000/ants/v2 v2.4.3/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OI github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pion/dtls/v2 v2.0.1-0.20200503085337-8e86b3a7d585/go.mod h1:/GahSOC8ZY/+17zkaGJIG4OUkSGAcZu/N/g3roBOCkM= -github.com/pion/dtls/v2 v2.0.10-0.20210502094952-3dc563b9aede/go.mod h1:86wv5dgx2J/z871nUR+5fTTY9tISLUlo+C5Gm86r1Hs= github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 h1:r7K+oQUYubeA0am08kTAvd2wT2D8PZggs/CpMGp0nkM= github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8/go.mod h1:/gft3czh67pwl4nM1BBUvF7eTy72uGkObJXOYfxRDbA= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport v0.10.0/go.mod h1:BnHnUipd0rZQyTVB2SBGojFHT9CBt5C5TcsJSQGkvSE= -github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= -github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A= github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= -github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.2.5-0.20240203174619-48d29f285e4f h1:fnjdDr3zDDCDw7KwCzDHtBTplV7vImLW88BJ6L1IcHk= -github.com/plgd-dev/device/v2 v2.2.5-0.20240203174619-48d29f285e4f/go.mod h1:bNW1Z70fOwogtFdc73ICv4kaQCtSHnFVpMbJaaG6Rtc= +github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c h1:d6CMhw6Lx/fJpeZrbnbeHULtbfRfPLDprMWmKP/YxnA= +github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c/go.mod h1:4hzgXvOY/u2+EvQDehDCe77UKuhD+9SouLiPKEFexes= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= -github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f h1:pVQdfS93HKSqHMNIH4JJcz2lUl/mgoZ6FOjQQDcTPMM= -github.com/plgd-dev/go-coap/v3 v3.3.2-0.20240201130556-f8d6fade418f/go.mod h1:Pac6EsvakCrwCaZGk7YkbecVLnDYRauEt4ULvYRw5Dk= +github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba h1:bDpB1PPdUzgaTdcPr4jMdbb78ODxvG9CE7lSOQngL9Y= +github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba/go.mod h1:rUgy/k2SX0esIM7JT01euQALT5YrYkROwxMSwfiIzhw= github.com/plgd-dev/kit v0.0.0-20200819113605-d5fcf3e94f63/go.mod h1:Yl9zisyXfPdtP9hTWlJqjJYXmgU/jtSDKttz9/CeD90= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 h1:TC1HJ/UbyflJFPvaOdGmNZ5TeFGex1/dyr9urNGLy7M= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSGQjdi8eInxwFCs0tSApuEM1o0qNck+sJYp4M= @@ -273,11 +263,12 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM= -github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U= +github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -302,34 +293,33 @@ github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk= -go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= +go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= +go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0 h1:1ahNAu2+hiHJOXd9J8hQ1zSGxEYHy7sn1ozpL50YWZY= -go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.47.0/go.mod h1:VEW8hmKJJZg+c3lfqHhxqa0BYg2PEUyNRehU5D2yBDw= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0 h1:UNQQKPfTDe1J81ViolILjTKPr9WetKW6uei2hFgJmFs= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.47.0/go.mod h1:r9vWsPS/3AQItv3OSlEJ/E4mbrhUbbw18meOjArPtKQ= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 h1:sv9kVfal0MK0wBMCOGr+HeJm9v803BkJxGrk2au7j08= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0/go.mod h1:SK2UL73Zy1quvRPonmOmRDiWk1KBV3LyIeeIxcEApWw= -go.opentelemetry.io/otel v1.22.0 h1:xS7Ku+7yTFvDfDraDIJVpw7XPyuHlB9MCiqqX5mcJ6Y= -go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ= -go.opentelemetry.io/otel/metric v1.22.0 h1:lypMQnGyJYeuYPhOM/bgjbFM6WE44W1/T45er4d8Hhg= -go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= -go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= -go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= -go.opentelemetry.io/otel/trace v1.22.0 h1:Hg6pPujv0XG9QaVbGOBVHunyuLcCC3jN7WEhPx83XD0= -go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 h1:qF3LdpkD3Kbaw0Smsh+SVcJI/mtYGz9ZdCmu0YF2Lo4= +go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0/go.mod h1:eqNF9g7W06ubrU7jk6M6UW9OTrcSPZvVY10cw9DUJ7c= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -348,24 +338,23 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= -golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= 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= @@ -391,21 +380,19 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210502030024-e5908800b52b/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= +golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= 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= @@ -436,8 +423,9 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -477,8 +465,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.161.0 h1:oYzk/bs26WN10AV7iU7MVJVXBH8oCPS2hHyBiEeFoSU= -google.golang.org/api v0.161.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.168.0 h1:MBRe+Ki4mMN93jhDDbpuRLjRddooArz4FeSObvUMmjY= +google.golang.org/api v0.168.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -488,12 +476,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg= -google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe h1:0poefMBYvYbs7g5UkjS6HcxBPaTRAmznle9jnxYoAI8= -google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe h1:bQnxqljG/wqi4NTXu2+DJ3n7APcEA882QZ1JvhQAq9o= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ= +google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 h1:IR+hp6ypxjH24bkMfEJ0yHR21+gwPWdV+/IBrPQyn3k= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= 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= @@ -501,8 +487,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From a63ccdde24fe148426cd94fb0bad76b17eb6699e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:44:09 +0000 Subject: [PATCH 16/31] Update Helm release nats to v1.1.9 Generated by renovateBot --- charts/plgd-hub/Chart.lock | 6 +++--- charts/plgd-hub/Chart.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/charts/plgd-hub/Chart.lock b/charts/plgd-hub/Chart.lock index 5600a23bd..aac7c15ab 100644 --- a/charts/plgd-hub/Chart.lock +++ b/charts/plgd-hub/Chart.lock @@ -1,12 +1,12 @@ dependencies: - name: nats repository: https://nats-io.github.io/k8s/helm/charts/ - version: 1.1.8 + version: 1.1.9 - name: mongodb repository: https://charts.bitnami.com/bitnami version: 13.18.3 - name: scylla repository: https://scylla-operator-charts.storage.googleapis.com/stable version: v1.10.0 -digest: sha256:093ffd05d3af7fbac3b5cb209351ebd25456c15eb79bfa81aa1525e139dbdec4 -generated: "2024-02-09T12:45:01.826312981Z" +digest: sha256:3ed14035e169597cbd91e8521414c8bbae13879d27bda6726ce45b1e74572050 +generated: "2024-03-05T10:43:45.524423289Z" diff --git a/charts/plgd-hub/Chart.yaml b/charts/plgd-hub/Chart.yaml index 5c070c040..91c970029 100644 --- a/charts/plgd-hub/Chart.yaml +++ b/charts/plgd-hub/Chart.yaml @@ -11,7 +11,7 @@ appVersion: vnext dependencies: - name: "nats" - version: "1.1.8" + version: "1.1.9" repository: "https://nats-io.github.io/k8s/helm/charts/" condition: nats.enabled - name: "mongodb" From 1ea02660fd274f4ba293763ed752a5a18b265920 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Fri, 8 Mar 2024 19:03:48 +0100 Subject: [PATCH 17/31] Upgrade dependencies Direct: github.com/go-co-op/gocron/v2 v2.2.5 github.com/lestrrat-go/jwx/v2 v2.0.21 google.golang.org/api v0.169.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 google.golang.org/grpc v1.62.1 google.golang.org/protobuf v1.33.0 Indirect: github.com/bufbuild/protocompile v0.9.0 github.com/golang/protobuf v1.5.4 github.com/lestrrat-go/httprc v1.0.5 google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7 --- go.mod | 20 ++++++++++---------- go.sum | 40 ++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/go.mod b/go.mod index 24cdeaee0..da40ff847 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/fullstorydev/grpchan v1.1.1 github.com/fxamacker/cbor/v2 v2.6.0 - github.com/go-co-op/gocron/v2 v2.2.4 + github.com/go-co-op/gocron/v2 v2.2.5 github.com/gocql/gocql v1.6.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/snappy v0.0.4 @@ -23,7 +23,7 @@ require ( github.com/json-iterator/go v1.1.12 github.com/jtacoma/uritemplates v1.0.0 github.com/karrick/tparse/v2 v2.8.2 - github.com/lestrrat-go/jwx/v2 v2.0.20 + github.com/lestrrat-go/jwx/v2 v2.0.21 github.com/nats-io/nats.go v1.33.1 github.com/panjf2000/ants/v2 v2.9.0 github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 @@ -53,11 +53,11 @@ require ( golang.org/x/net v0.22.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.6.0 - google.golang.org/api v0.168.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 - google.golang.org/grpc v1.62.0 + google.golang.org/api v0.169.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 + google.golang.org/grpc v1.62.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.32.0 + google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 ) @@ -67,7 +67,7 @@ require ( github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/sprig v2.15.0+incompatible // indirect github.com/aokoli/goutils v1.0.1 // indirect - github.com/bufbuild/protocompile v0.8.0 // indirect + github.com/bufbuild/protocompile v0.9.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect @@ -78,7 +78,7 @@ require ( github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.2 // indirect @@ -92,7 +92,7 @@ require ( github.com/klauspost/compress v1.17.7 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect - github.com/lestrrat-go/httprc v1.0.4 // indirect + github.com/lestrrat-go/httprc v1.0.5 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/option v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -121,7 +121,7 @@ require ( golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) diff --git a/go.sum b/go.sum index 7b36ca297..d0575bf89 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYE github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bufbuild/protocompile v0.8.0 h1:9Kp1q6OkS9L4nM3FYbr8vlJnEwtbpDPQlQOVXfR+78s= -github.com/bufbuild/protocompile v0.8.0/go.mod h1:+Etjg4guZoAqzVk2czwEQP12yaxLJ8DxuqCJ9qHdH94= +github.com/bufbuild/protocompile v0.9.0 h1:DI8qLG5PEO0Mu1Oj51YFPqtx6I3qYXUAhJVJ/IzAVl0= +github.com/bufbuild/protocompile v0.9.0/go.mod h1:s89m1O8CqSYpyE/YaSGtg1r1YFMF5nLTwh4vlj6O444= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= 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= @@ -55,8 +55,8 @@ github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= -github.com/go-co-op/gocron/v2 v2.2.4 h1:fL6a8/U+BJQ9UbaeqKxua8wY02w4ftKZsxPzLSNOCKk= -github.com/go-co-op/gocron/v2 v2.2.4/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= +github.com/go-co-op/gocron/v2 v2.2.5 h1:AGyUDXmSmqnclltaMVrLCtl3viJMY3TcpWdU4dbi/mE= +github.com/go-co-op/gocron/v2 v2.2.5/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -98,8 +98,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -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/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -184,14 +184,14 @@ github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= -github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJGdI8= -github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= +github.com/lestrrat-go/httprc v1.0.5 h1:bsTfiH8xaKOJPrg1R+E3iE/AWZr/x0Phj9PBTG/OLUk= +github.com/lestrrat-go/httprc v1.0.5/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= github.com/lestrrat-go/iter v0.0.0-20200422075355-fc1769541911/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc= github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= github.com/lestrrat-go/jwx v1.0.2/go.mod h1:TPF17WiSFegZo+c20fdpw49QD+/7n4/IsGvEmCSWwT0= -github.com/lestrrat-go/jwx/v2 v2.0.20 h1:sAgXuWS/t8ykxS9Bi2Qtn5Qhpakw1wrcjxChudjolCc= -github.com/lestrrat-go/jwx/v2 v2.0.20/go.mod h1:UlCSmKqw+agm5BsOBfEAbTvKsEApaGNqHAEUTv5PJC4= +github.com/lestrrat-go/jwx/v2 v2.0.21 h1:jAPKupy4uHgrHFEdjVjNkUgoBKtVDgrQPB/h55FHrR0= +github.com/lestrrat-go/jwx/v2 v2.0.21/go.mod h1:09mLW8zto6bWL9GbwnqAli+ArLf+5M33QLQPDggkUWM= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lestrrat-go/pdebug v0.0.0-20200204225717-4d6bd78da58d/go.mod h1:B06CSso/AWxiPejj+fheUINGeBKeeEZNt8w+EoU7+L8= @@ -465,8 +465,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.168.0 h1:MBRe+Ki4mMN93jhDDbpuRLjRddooArz4FeSObvUMmjY= -google.golang.org/api v0.168.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= +google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -476,10 +476,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8 h1:8eadJkXbwDEMNwcB5O0s5Y5eCfyuCLdvaiOIaGTrWmQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240304212257-790db918fca8/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8 h1:IR+hp6ypxjH24bkMfEJ0yHR21+gwPWdV+/IBrPQyn3k= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240304212257-790db918fca8/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7 h1:bITUotW/BD35GhBwrwGexWa8/P5CKHXACICrmuFJBa8= +google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 h1:em/y72n4XlYRtayY/cVj6pnVzHa//BDA1BdoO+z9mdE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= 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= @@ -487,8 +487,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= -google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= +google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -502,8 +502,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= From 5a5b13d0f34ab97bcd24267580e8670131817748 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Thu, 21 Mar 2024 20:45:47 +0000 Subject: [PATCH 18/31] http-gateway: Allow requesting device resources with escaped characters --- http-gateway/service/requestHandler.go | 29 +++-- pkg/strings/unescape.go | 147 +++++++++++++++++++++++++ pkg/strings/unescape_internal_test.go | 84 ++++++++++++++ 3 files changed, 250 insertions(+), 10 deletions(-) create mode 100644 pkg/strings/unescape.go create mode 100644 pkg/strings/unescape_internal_test.go diff --git a/http-gateway/service/requestHandler.go b/http-gateway/service/requestHandler.go index e74cc7364..6bca657e8 100644 --- a/http-gateway/service/requestHandler.go +++ b/http-gateway/service/requestHandler.go @@ -16,6 +16,7 @@ import ( "github.com/plgd-dev/hub/v2/http-gateway/uri" "github.com/plgd-dev/hub/v2/pkg/log" kitHttp "github.com/plgd-dev/hub/v2/pkg/net/http" + pkgStrings "github.com/plgd-dev/hub/v2/pkg/strings" ) // RequestHandler for handling incoming request @@ -38,22 +39,30 @@ func matchPrefixAndSplitURIPath(requestURI, prefix string) []string { return strings.Split(p, "/") } +func unescapeString(s string) string { + newS, err := pkgStrings.Unescape(s, pkgStrings.UnescapingModeAllCharacters, false) + if err != nil { + return s + } + return newS +} + func resourcePendingCommandsMatcher(r *http.Request, rm *mux.RouteMatch) bool { paths := matchPrefixAndSplitURIPath(r.RequestURI, uri.Devices) if len(paths) > 3 && paths[1] == uri.ResourcesPathKey && strings.Contains(paths[len(paths)-1], uri.PendingCommandsPathKey) { if rm.Vars == nil { rm.Vars = make(map[string]string) } - rm.Vars[uri.DeviceIDKey] = paths[0] - rm.Vars[uri.ResourceHrefKey] = strings.Split("/"+strings.Join(paths[2:len(paths)-1], "/"), "?")[0] + rm.Vars[uri.DeviceIDKey] = unescapeString(paths[0]) + rm.Vars[uri.ResourceHrefKey] = unescapeString(strings.Split("/"+strings.Join(paths[2:len(paths)-1], "/"), "?")[0]) return true } if len(paths) > 4 && paths[1] == uri.ResourcesPathKey && strings.Contains(paths[len(paths)-2], uri.PendingCommandsPathKey) { if rm.Vars == nil { rm.Vars = make(map[string]string) } - rm.Vars[uri.DeviceIDKey] = paths[0] - rm.Vars[uri.ResourceHrefKey] = "/" + strings.Join(paths[2:len(paths)-2], "/") + rm.Vars[uri.DeviceIDKey] = unescapeString(paths[0]) + rm.Vars[uri.ResourceHrefKey] = unescapeString("/" + strings.Join(paths[2:len(paths)-2], "/")) rm.Vars[uri.CorrelationIDKey] = strings.Split(paths[len(paths)-1], "?")[0] return true } @@ -68,8 +77,8 @@ func resourceMatcher(r *http.Request, rm *mux.RouteMatch) bool { if rm.Vars == nil { rm.Vars = make(map[string]string) } - rm.Vars[uri.DeviceIDKey] = paths[0] - rm.Vars[uri.ResourceHrefKey] = strings.Split("/"+strings.Join(paths[2:], "/"), "?")[0] + rm.Vars[uri.DeviceIDKey] = unescapeString(paths[0]) + rm.Vars[uri.ResourceHrefKey] = unescapeString(strings.Split("/"+strings.Join(paths[2:], "/"), "?")[0]) return true } return false @@ -81,8 +90,8 @@ func resourceLinksMatcher(r *http.Request, rm *mux.RouteMatch) bool { if rm.Vars == nil { rm.Vars = make(map[string]string) } - rm.Vars[uri.DeviceIDKey] = paths[0] - rm.Vars[uri.ResourceHrefKey] = strings.Split("/"+strings.Join(paths[2:], "/"), "?")[0] + rm.Vars[uri.DeviceIDKey] = unescapeString(paths[0]) + rm.Vars[uri.ResourceHrefKey] = unescapeString(strings.Split("/"+strings.Join(paths[2:], "/"), "?")[0]) return true } return false @@ -98,8 +107,8 @@ func resourceEventsMatcher(r *http.Request, rm *mux.RouteMatch) bool { if rm.Vars == nil { rm.Vars = make(map[string]string) } - rm.Vars[uri.DeviceIDKey] = paths[0] - rm.Vars[uri.ResourceHrefKey] = "/" + strings.Join(paths[2:len(paths)-1], "/") + rm.Vars[uri.DeviceIDKey] = unescapeString(paths[0]) + rm.Vars[uri.ResourceHrefKey] = unescapeString("/" + strings.Join(paths[2:len(paths)-1], "/")) return true } return false diff --git a/pkg/strings/unescape.go b/pkg/strings/unescape.go new file mode 100644 index 000000000..5e879347d --- /dev/null +++ b/pkg/strings/unescape.go @@ -0,0 +1,147 @@ +package strings + +import ( + "strconv" + "strings" +) + +type MalformedSequenceError string + +func (e MalformedSequenceError) Error() string { + return "malformed path escape " + strconv.Quote(string(e)) +} + +// UnescapingMode defines the behavior of ServeMux when unescaping path parameters. +type UnescapingMode int + +const ( + // UnescapingModeAllExceptReserved unescapes all path parameters except RFC 6570 + // reserved characters. + UnescapingModeAllExceptReserved UnescapingMode = 1 + + // UnescapingModeAllExceptSlash unescapes URL path parameters except path + // separators, which will be left as "%2F". + UnescapingModeAllExceptSlash UnescapingMode = 2 + + // UnescapingModeAllCharacters unescapes all URL path parameters. + UnescapingModeAllCharacters UnescapingMode = 3 +) + +/* + * The following code is adopted and modified from Go's standard library + * and carries the attached license. + * + * Copyright 2009 The Go Authors. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + */ + +// isHex returns whether or not the given byte is a valid hex character +func isHex(c byte) bool { + switch { + case '0' <= c && c <= '9': + return true + case 'a' <= c && c <= 'f': + return true + case 'A' <= c && c <= 'F': + return true + } + return false +} + +func isRFC6570Reserved(c byte) bool { + switch c { + case '!', '#', '$', '&', '\'', '(', ')', '*', + '+', ',', '/', ':', ';', '=', '?', '@', '[', ']': + return true + default: + return false + } +} + +// unHex converts a hex point to the bit representation +func unHex(c byte) byte { + switch { + case '0' <= c && c <= '9': + return c - '0' + case 'a' <= c && c <= 'f': + return c - 'a' + 10 + case 'A' <= c && c <= 'F': + return c - 'A' + 10 + } + return 0 +} + +// shouldUnescapeWithMode returns true if the character is escapable with the +// given mode +func shouldUnescapeWithMode(c byte, mode UnescapingMode) bool { + switch mode { + case UnescapingModeAllExceptReserved: + if isRFC6570Reserved(c) { + return false + } + case UnescapingModeAllExceptSlash: + if c == '/' { + return false + } + case UnescapingModeAllCharacters: + return true + } + return true +} + +// checkWellFormed checks if the given string is well-formed +func checkWellFormed(s string) (bool, error) { + n := 0 + for i := 0; i < len(s); { + if s[i] != '%' { + i++ + continue + } + n++ + if i+2 >= len(s) || !isHex(s[i+1]) || !isHex(s[i+2]) { + s = s[i:] + if len(s) > 3 { + s = s[:3] + } + return false, MalformedSequenceError(s) + } + i += 3 + } + return n != 0, nil +} + +// Unescape unescapes a path string using the provided mode +func Unescape(s string, mode UnescapingMode, multisegment bool) (string, error) { + if !multisegment { + mode = UnescapingModeAllCharacters + } + + // Count %, check that they're well-formed. + needEscape, err := checkWellFormed(s) + if err != nil { + return "", err + } + if !needEscape { + return s, nil + } + + var t strings.Builder + t.Grow(len(s)) + for i := 0; i < len(s); i++ { + switch s[i] { + case '%': + c := unHex(s[i+1])<<4 | unHex(s[i+2]) + if shouldUnescapeWithMode(c, mode) { + t.WriteByte(c) + i += 2 + continue + } + fallthrough + default: + t.WriteByte(s[i]) + } + } + + return t.String(), nil +} diff --git a/pkg/strings/unescape_internal_test.go b/pkg/strings/unescape_internal_test.go new file mode 100644 index 000000000..b3b4c093d --- /dev/null +++ b/pkg/strings/unescape_internal_test.go @@ -0,0 +1,84 @@ +package strings_test + +import ( + "testing" + + "github.com/plgd-dev/hub/v2/pkg/strings" + "github.com/stretchr/testify/require" +) + +func TestUnescape(t *testing.T) { + tbl := []struct { + name string + input string + mode strings.UnescapingMode + multisegment bool + expected string + expectedErr error + }{ + { + name: "No escaping required", + input: "hello world", + mode: strings.UnescapingModeAllCharacters, + multisegment: true, + expected: "hello world", + expectedErr: nil, + }, + { + name: "Single character escaping", + input: "/%20", + mode: strings.UnescapingModeAllCharacters, + multisegment: true, + expected: "/ ", + expectedErr: nil, + }, + { + name: "Multiple character escaping", + input: "hello%20world", + mode: strings.UnescapingModeAllCharacters, + multisegment: true, + expected: "hello world", + expectedErr: nil, + }, + { + name: "Invalid escape sequence", + input: "%2", + mode: strings.UnescapingModeAllCharacters, + multisegment: true, + expected: "", + expectedErr: strings.MalformedSequenceError("%2"), + }, + { + name: "Escaping except slash with multisegment=false", + input: "/%2F%23%20", + mode: strings.UnescapingModeAllExceptSlash, + multisegment: true, + expected: "/%2F# ", + expectedErr: nil, + }, + { + name: "Escaping except reserved with multisegment=true", + input: "/%2F%23%20", + mode: strings.UnescapingModeAllExceptReserved, + multisegment: true, + expected: "/%2F%23 ", + expectedErr: nil, + }, + { + name: "Escaping all characters with multisegment=true", + input: "/%2F%23%20", + mode: strings.UnescapingModeAllCharacters, + multisegment: true, + expected: "//# ", + expectedErr: nil, + }, + } + + for _, test := range tbl { + t.Run(test.name, func(t *testing.T) { + result, err := strings.Unescape(test.input, test.mode, test.multisegment) + require.Equal(t, test.expected, result) + require.Equal(t, test.expectedErr, err) + }) + } +} From 93ac0eba3bf893acae97c2f176ee3f864bbb5565 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Tue, 26 Mar 2024 08:54:52 +0000 Subject: [PATCH 19/31] coap-gateway: Fixing device status to offline when the access token expires --- .../service/devicesStatusUpdater_test.go | 44 ++++++++++++++----- coap-gateway/service/signIn.go | 6 ++- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/coap-gateway/service/devicesStatusUpdater_test.go b/coap-gateway/service/devicesStatusUpdater_test.go index 3caf0391e..ba2690cb0 100644 --- a/coap-gateway/service/devicesStatusUpdater_test.go +++ b/coap-gateway/service/devicesStatusUpdater_test.go @@ -21,16 +21,16 @@ import ( "github.com/plgd-dev/hub/v2/test/device" oauthService "github.com/plgd-dev/hub/v2/test/oauth-server/service" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" - "github.com/plgd-dev/hub/v2/test/service" + testService "github.com/plgd-dev/hub/v2/test/service" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) -func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device.Device, oauthCfg oauthService.Config, coapCfg coapService.Config) (*pb.Device, time.Time /*startOnboard*/, time.Duration /*delta*/) { - tearDown := service.SetUp(ctx, t, service.WithOAuthConfig(oauthCfg), service.WithCOAPGWConfig(coapCfg)) - defer tearDown() +func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device.Device, oauthCfg oauthService.Config, coapCfg coapService.Config, wait time.Duration) (*pb.Device, time.Time /*startOnboard*/, time.Duration /*delta*/) { + oauthShutdown := oauthTest.New(t, oauthCfg) + servicesTeardown := testService.SetUpServices(context.Background(), t, testService.SetUpServicesCertificateAuthority|testService.SetUpServicesId|testService.SetUpServicesResourceAggregate|testService.SetUpServicesResourceDirectory|testService.SetUpServicesCoapGateway|testService.SetUpServicesGrpcGateway, testService.WithCOAPGWConfig(coapCfg)) ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ @@ -44,11 +44,16 @@ func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device. startOnboard := time.Now() shutdownDevSim := test.OnboardDevice(ctx, t, c, device, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, device.GetDefaultResources()) - defer shutdownDevSim() deltaOnboard := time.Since(startOnboard) / 2 + // stop oauth server to don't allow refresh token during sleep + oauthShutdown() + // for update resource-directory cache - time.Sleep(time.Second) + time.Sleep(wait) + oauthShutdown = oauthTest.New(t, oauthCfg) + ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) + defer oauthShutdown() client, err := c.GetDevices(ctx, &pb.GetDevicesRequest{}) require.NoError(t, err) @@ -64,10 +69,12 @@ func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device. devices = append(devices, dev) } require.Len(t, devices, 1) + shutdownDevSim() + servicesTeardown() return devices[0], startOnboard, deltaOnboard } -func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasNoExpiration(t *testing.T) { +func TestDevicesStatusAccessTokenHasNoExpiration(t *testing.T) { d := test.MustFindTestDevice() ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) defer cancel() @@ -76,12 +83,12 @@ func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasNoExpiration(t *test oauthCfg.OAuthSigner.Clients.Find(config.OAUTH_MANAGER_CLIENT_ID).AccessTokenLifetime = 0 coapCfg := coapgwTest.MakeConfig(t) - device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg) + device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg, time.Second) assert.Equal(t, commands.Connection_ONLINE, device.Metadata.Connection.Status) } -func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasExpiration(t *testing.T) { +func TestDevicesStatusAccessTokenHasExpiration(t *testing.T) { d := test.MustFindTestDevice() ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) defer cancel() @@ -90,8 +97,25 @@ func TestDevicesStatusUpdaterDisabledAndDeviceAccessTokenHasExpiration(t *testin accessTokenLifetime := time.Second * 10 oauthCfg.OAuthSigner.Clients.Find(config.OAUTH_MANAGER_CLIENT_ID).AccessTokenLifetime = accessTokenLifetime coapCfg := coapgwTest.MakeConfig(t) + coapCfg.APIs.COAP.OwnerCacheExpiration = time.Second - device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg) + device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg, time.Second) assert.Equal(t, commands.Connection_ONLINE, device.Metadata.Connection.Status) } + +func TestDevicesStatusAccessTokenHasExpirationAndTokenWillExpire(t *testing.T) { + d := test.MustFindTestDevice() + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + + oauthCfg := oauthTest.MakeConfig(t) + accessTokenLifetime := time.Second * 10 + oauthCfg.OAuthSigner.Clients.Find(config.OAUTH_MANAGER_CLIENT_ID).AccessTokenLifetime = accessTokenLifetime + coapCfg := coapgwTest.MakeConfig(t) + coapCfg.APIs.COAP.OwnerCacheExpiration = time.Second + + device, _, _ := onboardDeviceAndGetDevice(ctx, t, d, oauthCfg, coapCfg, accessTokenLifetime) + + assert.Equal(t, commands.Connection_OFFLINE, device.Metadata.Connection.Status) +} diff --git a/coap-gateway/service/signIn.go b/coap-gateway/service/signIn.go index d50380bb4..06ea77033 100644 --- a/coap-gateway/service/signIn.go +++ b/coap-gateway/service/signIn.go @@ -229,7 +229,11 @@ func getSignInDataFromClaims(ctx context.Context, client *session, signIn CoapSi expTime, _ := jwtClaims.GetExpirationTime() validUntil := time.Time{} if expTime != nil { - validUntil = expTime.Time + if time.Until(expTime.Time) < 2*client.server.config.APIs.COAP.OwnerCacheExpiration { + return "", time.Time{}, fmt.Errorf("access token will expire (%v) in less time than the interval for checking expiration (%v)", expTime.Time, 2*client.server.config.APIs.COAP.OwnerCacheExpiration) + } + // set expiration time before token expiration to allow sign off device. + validUntil = expTime.Time.Add(-2 * client.server.config.APIs.COAP.OwnerCacheExpiration) } return deviceID, validUntil, nil From eebd73c404d90231e97adde25a86d50926a0aad4 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Wed, 27 Mar 2024 13:55:52 +0000 Subject: [PATCH 20/31] coap-gateway: Allows unpublishing multiple resources in a single query --- coap-gateway/service/resourceDirectory.go | 8 ++- .../resourceDirectory_internal_test.go | 71 +++++++++++++++++++ 2 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 coap-gateway/service/resourceDirectory_internal_test.go diff --git a/coap-gateway/service/resourceDirectory.go b/coap-gateway/service/resourceDirectory.go index 3d4b26971..a2b165ca3 100644 --- a/coap-gateway/service/resourceDirectory.go +++ b/coap-gateway/service/resourceDirectory.go @@ -193,11 +193,13 @@ func parseUnpublishQueryString(queries []string) (deviceID string, instanceIDs [ if err != nil { return "", nil, fmt.Errorf("cannot parse unpublish query: %w", err) } - if di := values.Get("di"); di != "" { + for _, di := range values["di"] { + if deviceID != "" { + return "", nil, fmt.Errorf("unable to parse unpublish query: duplicate in parameter di(%v), previously di(%v)", di, deviceID) + } deviceID = di } - - if ins := values.Get("ins"); ins != "" { + for _, ins := range values["ins"] { i, err := strconv.Atoi(ins) if err != nil { return "", nil, fmt.Errorf("cannot convert %v to number", ins) diff --git a/coap-gateway/service/resourceDirectory_internal_test.go b/coap-gateway/service/resourceDirectory_internal_test.go new file mode 100644 index 000000000..5cf9ef032 --- /dev/null +++ b/coap-gateway/service/resourceDirectory_internal_test.go @@ -0,0 +1,71 @@ +//go:build test +// +build test + +package service + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseUnpublishQueryString(t *testing.T) { + tests := []struct { + name string + queries []string + expectedID string + expectedIns []int64 + wantErr bool + }{ + { + name: "ValidQueries", + queries: []string{"di=device1", "ins=1", "ins=2"}, + expectedID: "device1", + expectedIns: []int64{1, 2}, + }, + { + name: "MultipleInsInOneQuery", + queries: []string{"di=device1&ins=1&ins=2"}, + expectedID: "device1", + expectedIns: []int64{1, 2}, + }, + { + name: "InvalidIns", + queries: []string{"di=device1", "ins=abc"}, + wantErr: true, + }, + { + name: "One of the queries is invalid", + queries: []string{"di=device1", "ins=1", "invalid_query"}, + expectedID: "device1", + expectedIns: []int64{1}, + }, + { + name: "MultipleDeviceIDs", + queries: []string{"di=device1&di=device2"}, + wantErr: true, + }, + { + name: "DeviceIDandInsAreNotSet", + queries: []string{"invalidQuery=123"}, + wantErr: true, + }, + { + name: "EmptyQueries", + queries: []string{}, + wantErr: true, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + deviceID, instanceIDs, err := parseUnpublishQueryString(test.queries) + if test.wantErr { + require.Error(t, err) + return + } + require.Equal(t, test.expectedID, deviceID) + require.Equal(t, test.expectedIns, instanceIDs) + }) + } +} From 72721a993bbddbb08975c8490a3205d039a39a98 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 2 Apr 2024 15:11:36 +0200 Subject: [PATCH 21/31] Update GitHub actions Chizkiyahu/delete-untagged-ghcr-action: v3 -> v4 --- .github/actions/cleanup-stale/action.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/cleanup-stale/action.yaml b/.github/actions/cleanup-stale/action.yaml index 5df2e9b24..a82536d73 100644 --- a/.github/actions/cleanup-stale/action.yaml +++ b/.github/actions/cleanup-stale/action.yaml @@ -44,7 +44,7 @@ runs: password: ${{ inputs.token }} - name: Delete untagged images with no dependency - uses: Chizkiyahu/delete-untagged-ghcr-action@v3 + uses: Chizkiyahu/delete-untagged-ghcr-action@v4 with: repository: ${{ github.repository }} repository_owner: ${{ github.repository_owner }} From a63b34a779919713e10252f6d1e12b89771b3acc Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Tue, 2 Apr 2024 17:40:37 +0200 Subject: [PATCH 22/31] Update golangci-lint configuration and fix issues --- .golangci.yml | 81 +++++--- bundle/client/grpc/main.go | 2 +- bundle/client/ob/main.go | 3 +- certificate-authority/pb/signingRecords.go | 13 +- .../service/cleanDatabase_test.go | 14 +- certificate-authority/service/config.go | 2 +- .../service/grpc/infoData.go | 3 +- .../service/grpc/signCertificate.go | 3 +- .../service/grpc/signIdentityCertificate.go | 3 +- certificate-authority/service/grpc/signer.go | 54 +++--- certificate-authority/service/service.go | 6 +- .../store/cqldb/signingRecords.go | 4 +- .../store/cqldb/signingRecords_test.go | 7 +- .../store/mongodb/signingRecords_test.go | 15 +- cloud2cloud-connector/events/event.go | 5 +- .../service/addLinkedAccount.go | 9 +- .../service/deviceSubscriptionHandlers.go | 7 +- .../service/oauthCallback.go | 3 +- cloud2cloud-connector/service/service.go | 4 +- cloud2cloud-connector/service/store.go | 6 +- .../service/subscriptions.go | 12 +- .../service/taskProcessor.go | 4 +- .../service/updateResource.go | 8 +- .../store/mongodb/linkedAccounts.go | 16 +- .../store/mongodb/linkedAccounts_test.go | 25 ++- .../store/mongodb/linkedClouds.go | 18 +- .../store/mongodb/linkedClouds_test.go | 19 +- cloud2cloud-gateway/service/retrieveDevice.go | 4 +- .../service/retrieveResource.go | 3 +- .../service/retrieveResourceSubscription.go | 3 +- .../service/subscribeToDevices_test.go | 45 +++-- .../service/subscriptionManager.go | 7 +- cloud2cloud-gateway/service/subscriptions.go | 4 +- cloud2cloud-gateway/store/mongodb/store.go | 3 +- .../store/mongodb/subscription.go | 26 +-- cloud2cloud-gateway/test/events.go | 11 +- coap-gateway/coapconv/coapconv.go | 6 +- coap-gateway/service/auth.go | 21 ++- coap-gateway/service/clientObserveHandler.go | 17 +- coap-gateway/service/clientObserver.go | 12 +- coap-gateway/service/clientRetrieveHandler.go | 2 +- .../service/clientRetrieveHandler_test.go | 2 +- coap-gateway/service/config.go | 3 +- coap-gateway/service/exchangeCache.go | 4 +- coap-gateway/service/mem_test.go | 7 +- coap-gateway/service/message/response_test.go | 3 +- .../service/observation/deviceObserver.go | 20 +- .../observation/deviceObserver_test.go | 10 +- .../service/observation/resourcesObserver.go | 21 +-- coap-gateway/service/refreshCache.go | 6 +- coap-gateway/service/refreshToken.go | 8 +- coap-gateway/service/resourceDirectory.go | 8 +- coap-gateway/service/service.go | 9 +- coap-gateway/service/session.go | 8 +- coap-gateway/service/signIn.go | 9 +- coap-gateway/service/signIn_test.go | 5 +- coap-gateway/service/signOff.go | 11 +- coap-gateway/service/signUp.go | 13 +- coap-gateway/service/utils_test.go | 3 +- grpc-gateway/client/client.go | 3 +- grpc-gateway/client/client_test.go | 3 - grpc-gateway/client/createResource_test.go | 6 +- grpc-gateway/client/deleteResource_test.go | 13 +- grpc-gateway/client/deviceSubscriptions.go | 32 ++-- .../client/deviceSubscriptions_test.go | 29 ++- grpc-gateway/client/devicesSubscription.go | 6 +- grpc-gateway/client/generalMessageCodec.go | 3 +- grpc-gateway/client/getDevice_test.go | 7 +- grpc-gateway/client/getDevices_test.go | 7 +- grpc-gateway/client/getResource_test.go | 7 +- grpc-gateway/client/maintenance_test.go | 5 +- grpc-gateway/client/observeDeviceResources.go | 2 +- .../client/observeDeviceResources_test.go | 3 +- grpc-gateway/client/observeDevices_test.go | 10 +- grpc-gateway/client/observeResource_test.go | 10 +- grpc-gateway/client/resourceSubscription.go | 6 +- grpc-gateway/client/updateResource_test.go | 13 +- grpc-gateway/pb/getResources.go | 4 +- grpc-gateway/pb/hubConfiguration.go | 33 ++-- grpc-gateway/pb/hubConfiguration_test.go | 4 +- .../service/cancelPendingCommands_test.go | 2 +- .../cancelPendingMetadataUpdates_test.go | 2 +- grpc-gateway/service/getEvents_test.go | 2 +- .../service/getResourceFromDevice_test.go | 6 +- .../service/subscribeToEvents_test.go | 39 ++-- .../service/updateDeviceMetadata_test.go | 35 ++-- grpc-gateway/service/updateResource_test.go | 19 +- grpc-gateway/subscription/subscription.go | 20 +- .../subscription/subscription_test.go | 4 +- .../subscription/subscriptionsCache.go | 10 +- .../service/cancelPendingCommands_test.go | 4 +- .../cancelPendingMetadataUpdate_test.go | 2 +- .../cancelPendingMetadataUpdates_test.go | 2 +- http-gateway/service/deleteDevice.go | 19 +- http-gateway/service/getDevice.go | 16 +- .../service/getDevicePendingCommands_test.go | 30 +-- http-gateway/service/getHubConfiguration.go | 2 +- .../service/getPendingCommands_test.go | 30 +-- .../service/getPendingMetadataUpdates_test.go | 30 +-- .../getResourcePendingCommands_test.go | 30 +-- http-gateway/service/getResource_test.go | 2 +- .../service/getWebConfiguration_test.go | 2 +- http-gateway/service/service.go | 6 +- .../service/subscribeToEvents_test.go | 26 +-- .../service/updateDeviceMetadata_test.go | 8 +- http-gateway/test/http.go | 6 +- http-gateway/test/unmarshalProto.go | 2 +- identity-store/client/ownerCache.go | 6 +- identity-store/client/ownerCache_test.go | 2 +- identity-store/persistence/cqldb/persist.go | 2 +- .../persistence/cqldb/persist_test.go | 35 ++-- identity-store/persistence/mongodb/persist.go | 2 +- identity-store/service/getDevices_test.go | 10 +- identity-store/service/service_test.go | 3 +- pkg/config/database/config.go | 5 +- pkg/log/log_test.go | 36 ++-- pkg/net/coap/getResourceLinks.go | 5 +- pkg/net/coap/service/config.go | 3 +- pkg/net/coap/service/service_test.go | 28 +-- pkg/net/grpc/error_test.go | 2 +- pkg/net/http/convertError_test.go | 5 +- pkg/net/http/loggingMiddleware.go | 3 +- pkg/net/http/service/config.go | 11 +- .../certManager/client/certManager.go | 3 +- .../certManager/general/certManager.go | 3 +- .../certManager/general/certManager_test.go | 6 +- .../certManager/server/certManager.go | 3 +- .../certificateSigner/certificateSigner.go | 8 +- pkg/security/jwt/claims_test.go | 3 +- pkg/security/jwt/jwk.go | 7 +- pkg/security/jwt/validator_test.go | 42 ++--- pkg/security/oauth2/plgd_clientCrendetials.go | 6 +- pkg/security/x509/load.go | 5 +- pkg/security/x509/verify.go | 6 +- pkg/service/service.go | 4 +- pkg/strings/slice_test.go | 10 +- pkg/strings/sortedSlice_test.go | 6 +- pkg/sync/task/future/future_test.go | 4 +- pkg/sync/task/queue/queue.go | 6 +- pkg/yaml/yaml_test.go | 2 +- resource-aggregate/commands/utils.go | 19 +- .../cqrs/aggregate/aggregate.go | 6 +- .../cqrs/aggregate/test/aggregate.go | 2 +- .../eventbus/goroutinePoolHandler_test.go | 10 +- .../eventbus/nats/publisher/publisher_test.go | 47 +++-- .../nats/subscriber/reconnect_test.go | 4 +- .../eventbus/nats/subscriber/subscriber.go | 3 +- .../nats/subscriber/subscriber_test.go | 7 +- .../cqrs/eventstore/cqldb/delete.go | 4 +- .../cqrs/eventstore/cqldb/delete_test.go | 2 +- .../cqrs/eventstore/cqldb/eventstore.go | 4 +- .../eventstore/cqldb/getLatestDeviceETags.go | 3 +- .../cqldb/getLatestDeviceETags_test.go | 2 +- .../cqrs/eventstore/cqldb/load.go | 3 +- .../cqldb/loadDeviceMetadataByServiceIDs.go | 3 +- .../loadDeviceMetadataByServiceIDs_test.go | 2 +- .../cqrs/eventstore/cqldb/save.go | 9 +- resource-aggregate/cqrs/eventstore/event.go | 3 +- .../cqrs/eventstore/eventstore.go | 4 +- .../mongodb/acceptance_testing_events_test.go | 3 +- .../acceptance_testing_eventstore_test.go | 3 +- .../mongodb/acceptance_testing_test.go | 6 +- .../cqrs/eventstore/mongodb/delete.go | 4 +- .../cqrs/eventstore/mongodb/delete_test.go | 2 +- .../cqrs/eventstore/mongodb/eventstore.go | 2 +- .../eventstore/mongodb/eventstore_test.go | 2 +- .../mongodb/getLatestDeviceETags.go | 4 +- .../mongodb/getLatestDeviceETags_test.go | 2 +- .../cqrs/eventstore/mongodb/getevents.go | 4 +- .../cqrs/eventstore/mongodb/getevents_test.go | 2 +- .../cqrs/eventstore/mongodb/load.go | 4 +- .../mongodb/loadDeviceMetadataByServiceIDs.go | 2 +- .../loadDeviceMetadataByServiceIDs_test.go | 2 +- .../eventstore/mongodb/maintenance_test.go | 4 +- .../cqrs/eventstore/projection.go | 2 +- .../eventstore/test/acceptance_testing.go | 2 +- .../cqrs/eventstore/test/events.go | 3 +- .../cqrs/eventstore/test/eventstore.go | 3 +- .../cqrs/projection/projection.go | 2 +- .../cqrs/projection/projectionInternal.go | 2 +- .../projection/projectionInternal_test.go | 17 +- .../cqrs/projection/projection_test.go | 32 ++-- resource-aggregate/cqrs/utils/utils_test.go | 9 +- .../events/deviceMetadataSnapshotTaken.go | 12 +- .../events/deviceMetadataUpdated_test.go | 30 +-- .../events/resourceLinksSnapshotTaken.go | 4 +- .../events/resourceLinksSnapshotTaken_test.go | 14 +- .../events/resourceStateSnapshotTaken.go | 176 ++++++++++-------- .../events/resourceStateSnapshotTaken_test.go | 12 +- .../events/serviceMetadataSnapshotTaken.go | 5 +- .../events/serviceMetadataUpdated.go | 5 +- resource-aggregate/events/utils.go | 18 +- resource-aggregate/events/utils_test.go | 5 +- resource-aggregate/service/aggregate_test.go | 155 ++++++++------- .../cancelDeviceMetadataUpdates_test.go | 12 +- .../service/cancelResourceCommands_test.go | 4 +- .../confirmDeviceMetadataUpdate_test.go | 8 +- resource-aggregate/service/grpcApi_test.go | 78 ++++---- .../service/updateDeviceMetadata_test.go | 10 +- .../service/updateServiceHeartbeat.go | 5 +- .../service/updateServiceHeartbeat_test.go | 13 +- resource-directory/service/deviceDirectory.go | 3 +- .../service/getPendingCommands_test.go | 30 +-- .../service/resourceDirectory_test.go | 3 +- .../service/resourceShadow_test.go | 5 +- .../coap-gateway/service/resourceDirectory.go | 5 +- test/coap-gateway/service/service.go | 3 +- test/http/request.go | 7 +- test/iotivity-lite/service/offboard_test.go | 25 ++- test/iotivity-lite/service/republish_test.go | 4 +- test/oauth-server/service/getJWKs_test.go | 2 +- test/oauth-server/service/loadKeys.go | 6 +- test/oauth-server/service/token.go | 5 +- test/oauth-server/service/token_test.go | 12 +- test/pb/pendingCommand.go | 30 +-- test/sdk/client.go | 11 +- test/test.go | 15 +- test/virtual-device/cmd/main.go | 15 +- 218 files changed, 1272 insertions(+), 1234 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 4d9f826ca..e9ae1112c 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,9 +1,3 @@ -run: - skip-dirs: - - dependency - - http-gateway/grpc-websocket-proxy - skip-dirs-use-default: false - linters-settings: exhaustive: default-signifies-exhaustive: true @@ -22,38 +16,39 @@ linters-settings: excludes: - G402 govet: - # check-shadowing: true - check-shadowing: false + enable: + - nilness + - shadow stylecheck: - go: "1.20" checks: ["all", "-ST1003"] + testifylint: + disable: + - go-require linters: enable: + - asasalint # Check for pass []any as any in variadic func(...any) - asciicheck # Simple linter to check that your code does not contain non-ASCII identifiers - bidichk # Checks for dangerous unicode character sequences - # - bodyclose # checks whether HTTP response body is closed successfully - # - contextcheck # check the function whether use a non-inherited context + - bodyclose # Checks whether HTTP response body is closed successfully + # - copyloopvar # Detects places where loop variables are copied - decorder # check declaration order and count of types, constants, variables and functions - # - depguard # Go linter that checks if package imports are in a list of acceptable packages - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - # - dupl # Tool for code clone detection + - dupl # Tool for code clone detection - durationcheck # check for two durations multiplied together - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. - errorlint # errorlint is a linter for that can be used to find code that will cause problems with the error wrapping scheme introduced in Go 1.13. - # - exhaustive # check exhaustiveness of enum switch statements + - execinquery # Execinquery is a linter about query string checker in Query function which reads your Go src files and warning it finds. - exportloopref # checks for pointers to enclosing loop variables - # - forbidigo # Forbids identifiers # - forcetypeassert # finds forced type assertions - gci # Gci control golang package import order and make it always deterministic. - # - gochecknoglobals # Checks that no globals are present in Go code - # - gochecknoinits # Checks that no init functions are present in Go code - # - gocognit # Computes and checks the cognitive complexity of functions + - gocheckcompilerdirectives # Checks that go compiler directive comments (//go:) are valid. + - gocognit # Computes and checks the cognitive complexity of functions - goconst # Finds repeated strings that could be replaced by a constant - gocritic # The most opinionated Go source code linter - # - gocyclo # Computes and checks the cyclomatic complexity of functions + - gocyclo # Computes and checks the cyclomatic complexity of functions # - godox # Tool for detection of FIXME, TODO and other comment keywords # - goerr113 # Golang linter to check the errors handling expressions - gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification @@ -64,49 +59,73 @@ linters: - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems + - gosmopolitan # Report certain i18n/l10n anti-patterns in your Go codebase - gosimple # Linter for Go source code that specializes in simplifying a code - govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - - grouper # An analyzer to analyze expression groups. + - grouper # An analyzer to analyze expression groups - importas # Enforces consistent import aliases - ineffassign # Detects when assignments to existing variables are not used + # - intrange # Intrange is a linter to find places where for loops could make use of an integer range + - loggercheck # Checks key value pairs for common logger libraries (kitlog,klog,logr,zap). + - mirror # Reports wrong mirror patterns of bytes/strings usage - misspell # Finds commonly misspelled English words in comments - - nakedret # Finds naked returns in functions greater than a specified function length - nilerr # Finds the code that returns nil even if it checks that the error is not nil. # - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. # - noctx # noctx finds sending http request without context.Context - nolintlint # Reports ill-formed or insufficient nolint directives - # - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test + - nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL + - perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. - predeclared # find code that shadows one of Go's predeclared identifiers + # - protogetter # Reports direct reads from proto message fields when getters should be used. - revive # golint replacement, finds style mistakes + - reassign # Checks that package variables are not reassigned + - sloglint # Ensure consistent code style when using log/slog + # - spancheck # Checks for mistakes with OpenTelemetry/Census spans - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - stylecheck # Stylecheck is a replacement for golint - # - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 - # - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes + - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + - testifylint # Checks usage of github.com/stretchr/testify. + - tparallel # tparallel detects inappropriate usage of t.Parallel() method in your Go test codes - typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - unconvert # Remove unnecessary type conversions - unparam # Reports unused function parameters - unused # Checks Go code for unused constants, variables, functions and types - # - wastedassign # wastedassign finds wasted assignment statements + - usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library. + - wastedassign # wastedassign finds wasted assignment statements - whitespace # Tool for detection of leading and trailing whitespace disable: - containedctx # containedctx is a linter that detects struct contained context.Context field + - contextcheck # check the function whether use a non-inherited context - cyclop # checks function and package cyclomatic complexity + - depguard # Go linter that checks if package imports are in a list of acceptable packages + - exhaustive # Check exhaustiveness of enum switch statements - exhaustivestruct # Checks if all struct's fields are initialized + - exhaustruct # Checks if all structure fields are initialized. + - forbidigo # Forbids identifiers - funlen # Tool for detection of long functions + - gochecknoglobals # Checks that no globals are present in Go code + - gochecknoinits # Checks that no init functions are present in Go code - godot # Check if comments end in a period - gomnd # An analyzer to detect magic numbers. - ifshort # Checks that your code uses short syntax for if-statements whenever possible + - inamedparam # Reports interfaces with unnamed method parameters. + - interfacebloat # A linter that checks the number of methods inside an interface - ireturn # Accept Interfaces, Return Concrete Types - lll # Reports long lines - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted + - nakedret # Finds naked returns in functions greater than a specified function length - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity + - nonamedreturns # Reports all named returns + - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - prealloc # Finds slice declarations that could potentially be preallocated - promlinter # Check Prometheus metrics naming via promlint - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. + - structcheck # Finds unused struct fields + - tagalign # Check that struct tags are well aligned. - tagliatelle # Checks the struct tags. - testpackage # linter that makes you use a separate _test package - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers @@ -115,6 +134,9 @@ linters: - wsl # Whitespace Linter - Forces you to use empty lines! issues: + exclude-dirs: + - dependency + - http-gateway/grpc-websocket-proxy exclude-rules: - path: _test.go linters: @@ -137,5 +159,14 @@ issues: text: "SA1019:" linters: - staticcheck + - path: coap-gateway/service/session.go + linters: + - dupl + - path: grpc-gateway/client/subscription.go + linters: + - dupl + - path: resource-aggregate/events/resourceLinks.*.go|resource-aggregate/client/sync.*.go|resource-aggregate/service/grpcApi.go|resource-aggregate/events/resource.*.go + linters: + - dupl # Fix found issues (if it's supported by the linter). # fix: true diff --git a/bundle/client/grpc/main.go b/bundle/client/grpc/main.go index ae9372d13..3e17d02cd 100644 --- a/bundle/client/grpc/main.go +++ b/bundle/client/grpc/main.go @@ -63,7 +63,7 @@ func getServiceToken(authAddr string, tls *tls.Config) (string, error) { } token := body["access_token"] if token == "" { - return "", fmt.Errorf("token not found in body") + return "", errors.New("token not found in body") } return token, nil } diff --git a/bundle/client/ob/main.go b/bundle/client/ob/main.go index 024d91d45..1d0970a5a 100644 --- a/bundle/client/ob/main.go +++ b/bundle/client/ob/main.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "crypto/tls" + "errors" "flag" "fmt" "log" @@ -66,7 +67,7 @@ func getServiceToken(authAddr string) (string, error) { } token := body["access_token"] if token == "" { - return "", fmt.Errorf("token not found in body") + return "", errors.New("token not found in body") } return token, nil } diff --git a/certificate-authority/pb/signingRecords.go b/certificate-authority/pb/signingRecords.go index 6fa3654d2..b6eccf5cf 100644 --- a/certificate-authority/pb/signingRecords.go +++ b/certificate-authority/pb/signingRecords.go @@ -1,6 +1,7 @@ package pb import ( + "errors" "fmt" "sort" @@ -26,7 +27,7 @@ func (signingRecord *SigningRecord) Unmarshal(b []byte) error { func (signingRecord *SigningRecord) Validate() error { if signingRecord.GetId() == "" { - return fmt.Errorf("empty signing record ID") + return errors.New("empty signing record ID") } if _, err := uuid.Parse(signingRecord.GetId()); err != nil { return fmt.Errorf("invalid signing record ID(%v): %w", signingRecord.GetId(), err) @@ -37,19 +38,19 @@ func (signingRecord *SigningRecord) Validate() error { } } if signingRecord.GetCommonName() == "" { - return fmt.Errorf("empty signing record commonName") + return errors.New("empty signing record commonName") } if signingRecord.GetOwner() == "" { - return fmt.Errorf("empty signing record owner") + return errors.New("empty signing record owner") } if signingRecord.GetCredential() != nil && signingRecord.GetCredential().GetDate() == 0 { - return fmt.Errorf("empty signing credential date") + return errors.New("empty signing credential date") } if signingRecord.GetCredential() != nil && signingRecord.GetCredential().GetValidUntilDate() == 0 { - return fmt.Errorf("empty signing record credential expiration date") + return errors.New("empty signing record credential expiration date") } if signingRecord.GetCredential() != nil && signingRecord.GetCredential().GetCertificatePem() == "" { - return fmt.Errorf("empty signing record credential certificate") + return errors.New("empty signing record credential certificate") } return nil } diff --git a/certificate-authority/service/cleanDatabase_test.go b/certificate-authority/service/cleanDatabase_test.go index acdb91ad5..29ba16dbb 100644 --- a/certificate-authority/service/cleanDatabase_test.go +++ b/certificate-authority/service/cleanDatabase_test.go @@ -78,23 +78,25 @@ func TestCertificateAuthorityServerCleanUpSigningRecords(t *testing.T) { require.NoError(t, err) var got pb.SigningRecords for { - r, err := client.Recv() - if errors.Is(err, io.EOF) { + r, errR := client.Recv() + if errors.Is(errR, io.EOF) { break } + require.NoError(t, errR) got = append(got, r) } - require.Equal(t, 1, len(got)) + require.Len(t, got, 1) time.Sleep(4 * time.Second) client, err = grpcClient.GetSigningRecords(ctx, &pb.GetSigningRecordsRequest{}) require.NoError(t, err) got = nil for { - r, err := client.Recv() - if errors.Is(err, io.EOF) { + r, errR := client.Recv() + if errors.Is(errR, io.EOF) { break } + require.NoError(t, errR) got = append(got, r) } - require.Equal(t, 0, len(got)) + require.Empty(t, got) } diff --git a/certificate-authority/service/config.go b/certificate-authority/service/config.go index 8e9f2f5d1..7a0852e2c 100644 --- a/certificate-authority/service/config.go +++ b/certificate-authority/service/config.go @@ -89,7 +89,7 @@ func (c *StorageConfig) Validate() error { if c.CleanUpRecords == "" { return nil } - s, err := gocron.NewScheduler(gocron.WithLocation(time.Local)) + s, err := gocron.NewScheduler(gocron.WithLocation(time.Local)) //nolint:gosmopolitan if err != nil { return fmt.Errorf("cannot create cron job: %w", err) } diff --git a/certificate-authority/service/grpc/infoData.go b/certificate-authority/service/grpc/infoData.go index e3cd974d0..b8dc2b5d2 100644 --- a/certificate-authority/service/grpc/infoData.go +++ b/certificate-authority/service/grpc/infoData.go @@ -3,6 +3,7 @@ package grpc import ( "crypto/x509" "encoding/pem" + "errors" "fmt" "regexp" ) @@ -25,7 +26,7 @@ func (d infoData) String() string { func getInfoData(csr []byte) (infoData, error) { csrBlock, _ := pem.Decode(csr) if csrBlock == nil { - return infoData{}, fmt.Errorf("pem not found") + return infoData{}, errors.New("pem not found") } certificateRequest, err := x509.ParseCertificateRequest(csrBlock.Bytes) diff --git a/certificate-authority/service/grpc/signCertificate.go b/certificate-authority/service/grpc/signCertificate.go index 350187284..45252f07c 100644 --- a/certificate-authority/service/grpc/signCertificate.go +++ b/certificate-authority/service/grpc/signCertificate.go @@ -3,6 +3,7 @@ package grpc import ( "context" "crypto/x509" + "errors" "fmt" "regexp" "time" @@ -104,7 +105,7 @@ func (s *CertificateAuthorityServer) SignCertificate(ctx context.Context, req *p } signer := s.GetSigner() if signer == nil { - return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, fmt.Errorf("signer is empty"))) + return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("signer is empty"))) } cert, signingRecord, err := signer.Sign(ctx, req.GetCertificateSigningRequest()) if err != nil { diff --git a/certificate-authority/service/grpc/signIdentityCertificate.go b/certificate-authority/service/grpc/signIdentityCertificate.go index ccde56cd8..be765018d 100644 --- a/certificate-authority/service/grpc/signIdentityCertificate.go +++ b/certificate-authority/service/grpc/signIdentityCertificate.go @@ -3,6 +3,7 @@ package grpc import ( "context" "crypto/x509/pkix" + "errors" "fmt" "github.com/plgd-dev/hub/v2/certificate-authority/pb" @@ -45,7 +46,7 @@ func (s *CertificateAuthorityServer) SignIdentityCertificate(ctx context.Context } signer := s.GetSigner() if signer == nil { - return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, fmt.Errorf("signer is empty"))) + return nil, logger.LogAndReturnError(status.Errorf(codes.InvalidArgument, fmtError, errors.New("signer is empty"))) } cert, signingRecord, err := signer.SignIdentityCSR(ctx, req.GetCertificateSigningRequest()) if err != nil { diff --git a/certificate-authority/service/grpc/signer.go b/certificate-authority/service/grpc/signer.go index d4f014afc..0b4866e0a 100644 --- a/certificate-authority/service/grpc/signer.go +++ b/certificate-authority/service/grpc/signer.go @@ -6,7 +6,6 @@ import ( "crypto/ecdsa" "crypto/x509" "errors" - "fmt" "time" "github.com/karrick/tparse/v2" @@ -26,7 +25,7 @@ type Signer struct { func checkCertificatePrivateKey(cert []*x509.Certificate, priv *ecdsa.PrivateKey) error { if len(cert) == 0 { - return fmt.Errorf("at least one certificate need to be set") + return errors.New("at least one certificate need to be set") } x509Cert := cert[0] switch pub := x509Cert.PublicKey.(type) { @@ -57,7 +56,7 @@ func NewSigner(ownerClaim string, hubID string, signerConfig SignerConfig) (*Sig if err != nil { return nil, err } - if err := checkCertificatePrivateKey(certificate, privateKey); err != nil { + if err = checkCertificatePrivateKey(certificate, privateKey); err != nil { return nil, err } if len(certificate) == 1 && pkgX509.IsRootCA(certificate[0]) { @@ -76,13 +75,13 @@ func NewSigner(ownerClaim string, hubID string, signerConfig SignerConfig) (*Sig certificateAuthorities := make([]*x509.Certificate, 0, len(signerConfig.caPoolArray)*4) for _, caFile := range signerConfig.caPoolArray { - data, err := caFile.Read() - if err != nil { - return nil, err + data, errR := caFile.Read() + if errR != nil { + return nil, errR } - certs, err := pkgX509.ParseX509(data) - if err != nil { - return nil, err + certs, errR := pkgX509.ParseX509(data) + if errR != nil { + return nil, errR } certificateAuthorities = append(certificateAuthorities, certs...) } @@ -108,21 +107,26 @@ func NewSigner(ownerClaim string, hubID string, signerConfig SignerConfig) (*Sig }, nil } +func (s *Signer) prepareSigningRecord(ctx context.Context, template *x509.Certificate) (*pb.SigningRecord, error) { + subject, err := overrideSubject(ctx, template.Subject, s.ownerClaim, s.hubID, "") + if err != nil { + return nil, err + } + template.Subject = subject + owner, err := ownerToUUID(ctx, s.ownerClaim) + if err != nil { + return nil, err + } + return toSigningRecord(owner, template) +} + func (s *Signer) Sign(ctx context.Context, csr []byte) ([]byte, *pb.SigningRecord, error) { notBefore := s.validFrom() notAfter := notBefore.Add(s.validFor) var signingRecord *pb.SigningRecord signer := certificateSigner.New(s.certificate, s.privateKey, certificateSigner.WithNotBefore(notBefore), certificateSigner.WithNotAfter(notAfter), certificateSigner.WithOverrideCertTemplate(func(template *x509.Certificate) error { - subject, err := overrideSubject(ctx, template.Subject, s.ownerClaim, s.hubID, "") - if err != nil { - return err - } - template.Subject = subject - owner, err := ownerToUUID(ctx, s.ownerClaim) - if err != nil { - return err - } - signingRecord, err = toSigningRecord(owner, template) + var err error + signingRecord, err = s.prepareSigningRecord(ctx, template) return err })) crt, err := signer.Sign(ctx, csr) @@ -134,16 +138,8 @@ func (s *Signer) SignIdentityCSR(ctx context.Context, csr []byte) ([]byte, *pb.S notAfter := notBefore.Add(s.validFor) var signingRecord *pb.SigningRecord signer := certificateSigner.NewIdentityCertificateSigner(s.certificate, s.privateKey, certificateSigner.WithNotBefore(notBefore), certificateSigner.WithNotAfter(notAfter), certificateSigner.WithOverrideCertTemplate(func(template *x509.Certificate) error { - subject, err := overrideSubject(ctx, template.Subject, s.ownerClaim, s.hubID, "uuid:") - if err != nil { - return err - } - template.Subject = subject - owner, err := ownerToUUID(ctx, s.ownerClaim) - if err != nil { - return err - } - signingRecord, err = toSigningRecord(owner, template) + var err error + signingRecord, err = s.prepareSigningRecord(ctx, template) return err })) cert, err := signer.Sign(ctx, csr) diff --git a/certificate-authority/service/service.go b/certificate-authority/service/service.go index 8aae3617d..c4c240c5c 100644 --- a/certificate-authority/service/service.go +++ b/certificate-authority/service/service.go @@ -52,14 +52,14 @@ func newStore(ctx context.Context, config StorageConfig, fileWatcher *fsnotify.W return nil, nil, err } fl.AddFunc(func() { - if err := db.Close(ctx); err != nil { - log.Errorf("failed to close mongodb store: %w", err) + if errC := db.Close(ctx); errC != nil { + log.Errorf("failed to close mongodb store: %w", errC) } }) if config.CleanUpRecords == "" { return db, fl.ToFunction(), nil } - s, err := gocron.NewScheduler(gocron.WithLocation(time.Local)) + s, err := gocron.NewScheduler(gocron.WithLocation(time.Local)) //nolint:gosmopolitan if err != nil { fl.Execute() return nil, nil, fmt.Errorf("cannot create cron job: %w", err) diff --git a/certificate-authority/store/cqldb/signingRecords.go b/certificate-authority/store/cqldb/signingRecords.go index 5ae8e3629..76739b95e 100644 --- a/certificate-authority/store/cqldb/signingRecords.go +++ b/certificate-authority/store/cqldb/signingRecords.go @@ -81,7 +81,7 @@ func (s *Store) CreateSigningRecord(ctx context.Context, signingRecord *store.Si return err } if !applied { - return fmt.Errorf("cannot insert signing record: already exists") + return errors.New("cannot insert signing record: already exists") } return nil } @@ -251,7 +251,7 @@ func (s *Store) deviceIDFilterToPrimaryKeys(ctx context.Context, owner string, d func (s *Store) ownerFilterToPrimaryKeys(ctx context.Context, owner string) (primaryKeysValues, error) { if owner == "" { - return nil, fmt.Errorf("invalid owner") + return nil, errors.New("invalid owner") } var b strings.Builder diff --git a/certificate-authority/store/cqldb/signingRecords_test.go b/certificate-authority/store/cqldb/signingRecords_test.go index 918252230..075b1da6d 100644 --- a/certificate-authority/store/cqldb/signingRecords_test.go +++ b/certificate-authority/store/cqldb/signingRecords_test.go @@ -12,7 +12,6 @@ import ( "github.com/plgd-dev/hub/v2/certificate-authority/store" "github.com/plgd-dev/hub/v2/certificate-authority/test" hubTest "github.com/plgd-dev/hub/v2/test" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -355,7 +354,7 @@ func TestStoreDeleteExpiredRecords(t *testing.T) { var h1 testSigningRecordHandler err = s.LoadSigningRecords(ctx, "owner", nil, h1.Handle) require.NoError(t, err) - require.Len(t, h1.lcs, 0) + require.Empty(t, h1.lcs) } type testSigningRecordHandler struct { @@ -520,10 +519,10 @@ func TestStoreLoadSigningRecords(t *testing.T) { var h testSigningRecordHandler err := s.LoadSigningRecords(ctx, "owner", tt.args.query, h.Handle) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.NoError(t, err) + require.NoError(t, err) require.Len(t, h.lcs, len(tt.want)) h.lcs.Sort() tt.want.Sort() diff --git a/certificate-authority/store/mongodb/signingRecords_test.go b/certificate-authority/store/mongodb/signingRecords_test.go index fc9ebc7d6..8dde1808c 100644 --- a/certificate-authority/store/mongodb/signingRecords_test.go +++ b/certificate-authority/store/mongodb/signingRecords_test.go @@ -11,7 +11,6 @@ import ( "github.com/plgd-dev/hub/v2/certificate-authority/store" "github.com/plgd-dev/hub/v2/certificate-authority/test" hubTest "github.com/plgd-dev/hub/v2/test" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -93,9 +92,9 @@ func TestStoreUpdateSigningRecord(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := s.UpdateSigningRecord(ctx, tt.args.sub) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } err = s.FlushBulkWriter() require.NoError(t, err) @@ -221,10 +220,10 @@ func TestStoreDeleteSigningRecords(t *testing.T) { t.Run(tt.name, func(t *testing.T) { n, err := s.DeleteSigningRecords(ctx, tt.args.owner, tt.args.query) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) - assert.Equal(t, tt.want, n) + require.NoError(t, err) + require.Equal(t, tt.want, n) } }) } @@ -283,8 +282,8 @@ func TestStoreDeleteExpiredRecords(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := s.DeleteNonDeviceExpiredRecords(ctx, tt.args.now) - assert.NoError(t, err) - assert.Equal(t, tt.want, got) + require.NoError(t, err) + require.Equal(t, tt.want, got) }) } } diff --git a/cloud2cloud-connector/events/event.go b/cloud2cloud-connector/events/event.go index 0d5379041..e8cccab97 100644 --- a/cloud2cloud-connector/events/event.go +++ b/cloud2cloud-connector/events/event.go @@ -4,6 +4,7 @@ import ( "crypto/hmac" "crypto/sha256" "encoding/hex" + "errors" "fmt" "net/http" "strconv" @@ -51,7 +52,7 @@ func invalidKey(key string) string { } func invalidKeyError(key string) error { - return fmt.Errorf(invalidKey(key)) + return errors.New(invalidKey(key)) } func invalidKeyValueError(key string, value interface{}, err error) error { @@ -120,7 +121,7 @@ func ParseEventHeader(r *http.Request) (h EventHeader, _ error) { if r.Method == "POST" && v != "" { acceptEncoding = strings.Split(v, ",") if len(acceptEncoding) != 1 { - return h, invalidKeyValueError(AcceptEncodingKey, acceptEncoding, fmt.Errorf("more than 1")) + return h, invalidKeyValueError(AcceptEncodingKey, acceptEncoding, errors.New("more than 1")) } } diff --git a/cloud2cloud-connector/service/addLinkedAccount.go b/cloud2cloud-connector/service/addLinkedAccount.go index 83b0ae089..a79e0ffdb 100644 --- a/cloud2cloud-connector/service/addLinkedAccount.go +++ b/cloud2cloud-connector/service/addLinkedAccount.go @@ -4,6 +4,7 @@ import ( "context" "crypto/rand" "encoding/base64" + "errors" "fmt" "net/http" "time" @@ -28,7 +29,7 @@ func (h *LinkedCloudHandler) Handle(ctx context.Context, iter store.LinkedCloudI h.linkedCloud = s return iter.Err() } - return fmt.Errorf("not found") + return errors.New("not found") } func generateRandomString(n int) (string, error) { @@ -42,14 +43,14 @@ func generateRandomString(n int) (string, error) { func (rh *RequestHandler) handleOAuth(w http.ResponseWriter, r *http.Request, linkedAccount store.LinkedAccount, linkedCloud store.LinkedCloud) (int, error) { t, err := generateRandomString(32) if err != nil { - return http.StatusInternalServerError, fmt.Errorf("cannot generate token") + return http.StatusInternalServerError, errors.New("cannot generate token") } _, loaded := rh.provisionCache.LoadOrStore(t, cache.NewElement(ProvisionCacheData{ linkedAccount: linkedAccount, linkedCloud: linkedCloud, }, time.Now().Add(CacheExpiration), nil)) if loaded { - return http.StatusInternalServerError, fmt.Errorf("cannot store key - collision") + return http.StatusInternalServerError, errors.New("cannot store key - collision") } if !linkedAccount.Data.HasOrigin() { @@ -86,7 +87,7 @@ func (rh *RequestHandler) addLinkedAccount(w http.ResponseWriter, r *http.Reques UserID: userID, } if linkedAccount.LinkedCloudID == "" { - return http.StatusBadRequest, fmt.Errorf("invalid cloud_id") + return http.StatusBadRequest, errors.New("invalid cloud_id") } return rh.handleOAuth(w, r, linkedAccount, linkedCloud) } diff --git a/cloud2cloud-connector/service/deviceSubscriptionHandlers.go b/cloud2cloud-connector/service/deviceSubscriptionHandlers.go index 02521db54..25a700ea7 100644 --- a/cloud2cloud-connector/service/deviceSubscriptionHandlers.go +++ b/cloud2cloud-connector/service/deviceSubscriptionHandlers.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "sync/atomic" "time" @@ -41,15 +42,15 @@ func (h deviceSubscriptionHandlers) RetrieveResource(ctx context.Context, event } func (h deviceSubscriptionHandlers) DeleteResource(context.Context, *raEvents.ResourceDeletePending) error { - return fmt.Errorf(NOT_SUPPORTED_ERR) + return errors.New(NOT_SUPPORTED_ERR) } func (h deviceSubscriptionHandlers) CreateResource(context.Context, *raEvents.ResourceCreatePending) error { - return fmt.Errorf(NOT_SUPPORTED_ERR) + return errors.New(NOT_SUPPORTED_ERR) } func (h deviceSubscriptionHandlers) UpdateDeviceMetadata(context.Context, *raEvents.DeviceMetadataUpdatePending) error { - return fmt.Errorf(NOT_SUPPORTED_ERR) + return errors.New(NOT_SUPPORTED_ERR) } func (h deviceSubscriptionHandlers) OnDeviceSubscriberReconnectError(err error) { diff --git a/cloud2cloud-connector/service/oauthCallback.go b/cloud2cloud-connector/service/oauthCallback.go index d4522cd84..890a365bb 100644 --- a/cloud2cloud-connector/service/oauthCallback.go +++ b/cloud2cloud-connector/service/oauthCallback.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "net/http" @@ -43,7 +44,7 @@ func (rh *RequestHandler) oAuthCallback(w http.ResponseWriter, r *http.Request) cacheData := rh.provisionCache.Load(state) if cacheData == nil { - return http.StatusBadRequest, fmt.Errorf("invalid/expired OAuth state") + return http.StatusBadRequest, errors.New("invalid/expired OAuth state") } rh.provisionCache.Delete(state) data := cacheData.Data() diff --git a/cloud2cloud-connector/service/service.go b/cloud2cloud-connector/service/service.go index 2a2a53b94..5f4b786cc 100644 --- a/cloud2cloud-connector/service/service.go +++ b/cloud2cloud-connector/service/service.go @@ -125,8 +125,8 @@ func newStore(ctx context.Context, config pkgMongo.Config, fileWatcher *fsnotify return nil, nil, fmt.Errorf("cannot create mongodb subscription store: %w", err) } fl.AddFunc(func() { - if err := db.Close(ctx); err != nil { - log.Errorf("failed to close subscription store: %w", err) + if errC := db.Close(ctx); errC != nil { + log.Errorf("failed to close subscription store: %w", errC) } }) diff --git a/cloud2cloud-connector/service/store.go b/cloud2cloud-connector/service/store.go index 481469fc5..a7cf41bdc 100644 --- a/cloud2cloud-connector/service/store.go +++ b/cloud2cloud-connector/service/store.go @@ -2,7 +2,7 @@ package service import ( "context" - "fmt" + "errors" "github.com/plgd-dev/hub/v2/cloud2cloud-connector/store" "github.com/plgd-dev/hub/v2/pkg/log" @@ -128,7 +128,7 @@ func (s *Store) PullOutSubscription(subscripionID string) (SubscriptionData, boo func (s *Store) PullOutCloud(ctx context.Context, cloudID string) (*CloudData, error) { cloud, ok := s.cache.PullOutCloud(cloudID) if !ok { - return cloud, fmt.Errorf("not found") + return cloud, errors.New("not found") } return cloud, s.db.RemoveLinkedCloud(ctx, cloudID) } @@ -136,7 +136,7 @@ func (s *Store) PullOutCloud(ctx context.Context, cloudID string) (*CloudData, e func (s *Store) PullOutLinkedAccount(ctx context.Context, cloudID, linkedAccountID string) (*LinkedAccountData, error) { cloud, ok := s.cache.PullOutLinkedAccount(cloudID, linkedAccountID) if !ok { - return cloud, fmt.Errorf("not found") + return cloud, errors.New("not found") } return cloud, s.db.RemoveLinkedAccount(ctx, linkedAccountID) } diff --git a/cloud2cloud-connector/service/subscriptions.go b/cloud2cloud-connector/service/subscriptions.go index 7ae4ebaeb..d95a30792 100644 --- a/cloud2cloud-connector/service/subscriptions.go +++ b/cloud2cloud-connector/service/subscriptions.go @@ -107,13 +107,13 @@ func subscribe(ctx context.Context, tracerProvider trace.TracerProvider, href, c go func() { defer func() { - if err := w.Close(); err != nil { - log.Errorf("failed to close write pipe: %v", err) + if errC := w.Close(); errC != nil { + log.Errorf("failed to close write pipe: %w", errC) } }() - err := json.WriteTo(w, reqBody) - if err != nil { - log.Errorf("cannot encode %+v to json: %w", reqBody, err) + errW := json.WriteTo(w, reqBody) + if errW != nil { + log.Errorf("cannot encode %+v to json: %w", reqBody, errW) } }() httpResp, err := client.Do(req) @@ -212,7 +212,7 @@ func (s *SubscriptionManager) handleEvent(ctx context.Context, header events.Eve ctx = kitNetGrpc.CtxWithToken(ctx, subData.linkedAccount.Data.Origin().AccessToken.String()) if header.EventType == events.EventType_SubscriptionCanceled { - err := s.handleCancelEvent(header) + err = s.handleCancelEvent(header) if err != nil { return http.StatusGone, fmt.Errorf("cannot cancel subscription: %w", err) } diff --git a/cloud2cloud-connector/service/taskProcessor.go b/cloud2cloud-connector/service/taskProcessor.go index f38d018a0..497f284bb 100644 --- a/cloud2cloud-connector/service/taskProcessor.go +++ b/cloud2cloud-connector/service/taskProcessor.go @@ -150,9 +150,9 @@ func (h *TaskProcessor) Run(ctx context.Context, subscriptionManager *Subscripti for process { select { case e := <-h.tasksChan: - ctx, cancel := context.WithTimeout(ctx, h.timeout) + runctx, cancel := context.WithTimeout(ctx, h.timeout) defer cancel() - err := h.runTask(ctx, e, subscriptionManager) + err := h.runTask(runctx, e, subscriptionManager) if err != nil { log.Errorf("cannot process task %+v: %w", e, err) } diff --git a/cloud2cloud-connector/service/updateResource.go b/cloud2cloud-connector/service/updateResource.go index f00edaf23..fb53a7e78 100644 --- a/cloud2cloud-connector/service/updateResource.go +++ b/cloud2cloud-connector/service/updateResource.go @@ -40,12 +40,12 @@ func updateDeviceResource(ctx context.Context, tracerProvider trace.TracerProvid go func() { defer func() { if errC := w.Close(); errC != nil { - log.Errorf("failed to close write pipe: %v", errC) + log.Errorf("failed to close write pipe: %w", errC) } }() - _, err := w.Write(content) - if err != nil { - log.Errorf("cannot update content of device %v resource %v: %w", deviceID, href, err) + _, errW := w.Write(content) + if errW != nil { + log.Errorf("cannot update content of device %v resource %v: %w", deviceID, href, errW) } }() httpResp, err := client.Do(req) diff --git a/cloud2cloud-connector/store/mongodb/linkedAccounts.go b/cloud2cloud-connector/store/mongodb/linkedAccounts.go index 77eb611fd..55414965c 100644 --- a/cloud2cloud-connector/store/mongodb/linkedAccounts.go +++ b/cloud2cloud-connector/store/mongodb/linkedAccounts.go @@ -14,21 +14,21 @@ const resLinkedAccountCName = "linkedAccounts" func validateLinkedAccount(sub store.LinkedAccount) error { if sub.ID == "" { - return fmt.Errorf("invalid ID") + return errors.New("invalid ID") } if sub.UserID == "" { - return fmt.Errorf("invalid UserID") + return errors.New("invalid UserID") } if sub.LinkedCloudID == "" { - return fmt.Errorf("invalid LinkedCloudID") + return errors.New("invalid LinkedCloudID") } origin := sub.Data.Origin() if origin.AccessToken == "" && origin.RefreshToken == "" { - return fmt.Errorf("invalid Data.OriginCloud.AccessToken and Data.OriginCloud.RefreshToken") + return errors.New("invalid Data.OriginCloud.AccessToken and Data.OriginCloud.RefreshToken") } target := sub.Data.Target() if target.AccessToken == "" && target.RefreshToken == "" { - return fmt.Errorf("invalid Data.TargetCloud.AccessToken and Data.TargetCloud.RefreshToken") + return errors.New("invalid Data.TargetCloud.AccessToken and Data.TargetCloud.RefreshToken") } return nil } @@ -59,21 +59,21 @@ func (s *Store) UpdateLinkedAccount(ctx context.Context, sub store.LinkedAccount return fmt.Errorf("cannot update linked account: %w", err) } if res.MatchedCount == 0 { - return fmt.Errorf("cannot update linked account: not found") + return errors.New("cannot update linked account: not found") } return nil } func (s *Store) RemoveLinkedAccount(ctx context.Context, linkedAccountID string) error { if linkedAccountID == "" { - return fmt.Errorf("cannot remove linked account: invalid linkedAccountID") + return errors.New("cannot remove linked account: invalid linkedAccountID") } res, err := s.Collection(resLinkedAccountCName).DeleteOne(ctx, bson.M{"_id": linkedAccountID}) if err != nil { return fmt.Errorf("cannot remove linked account: %w", err) } if res.DeletedCount == 0 { - return fmt.Errorf("cannot remove linked account: not found") + return errors.New("cannot remove linked account: not found") } return nil } diff --git a/cloud2cloud-connector/store/mongodb/linkedAccounts_test.go b/cloud2cloud-connector/store/mongodb/linkedAccounts_test.go index bcfd24f20..0bb3ed8e6 100644 --- a/cloud2cloud-connector/store/mongodb/linkedAccounts_test.go +++ b/cloud2cloud-connector/store/mongodb/linkedAccounts_test.go @@ -7,7 +7,6 @@ import ( "github.com/plgd-dev/hub/v2/cloud2cloud-connector/store" "github.com/plgd-dev/hub/v2/cloud2cloud-connector/test" "github.com/plgd-dev/hub/v2/pkg/security/oauth2" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -45,10 +44,10 @@ func TestStoreInsertLinkedAccount(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := s.InsertLinkedAccount(ctx, tt.args.sub) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) + require.Error(t, err) + return } + require.NoError(t, err) }) } } @@ -107,10 +106,10 @@ func TestStoreUpdateLinkedAccount(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := s.UpdateLinkedAccount(ctx, tt.args.sub) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) + require.Error(t, err) + return } + require.NoError(t, err) }) } } @@ -159,10 +158,10 @@ func TestStoreRemoveLinkedAccount(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := s.RemoveLinkedAccount(ctx, tt.args.linkedAccountID) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.NoError(t, err) + require.NoError(t, err) }) } } @@ -241,11 +240,11 @@ func TestStoreLoadLinkedAccounts(t *testing.T) { var h testLinkedAccountHandler err := s.LoadLinkedAccounts(ctx, tt.args.query, &h) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tt.want, h.accs) + require.Error(t, err) + return } + require.NoError(t, err) + require.Equal(t, tt.want, h.accs) }) } } diff --git a/cloud2cloud-connector/store/mongodb/linkedClouds.go b/cloud2cloud-connector/store/mongodb/linkedClouds.go index 48af42c9f..857249014 100644 --- a/cloud2cloud-connector/store/mongodb/linkedClouds.go +++ b/cloud2cloud-connector/store/mongodb/linkedClouds.go @@ -14,22 +14,22 @@ const resLinkedCloudCName = "LinkedCloud" func validateLinkedCloud(sub store.LinkedCloud) error { if sub.ID == "" { - return fmt.Errorf("cannot save linked cloud: invalid Id") + return errors.New("cannot save linked cloud: invalid Id") } if sub.Endpoint.URL == "" { - return fmt.Errorf("cannot save linked cloud: invalid URL") + return errors.New("cannot save linked cloud: invalid URL") } if sub.OAuth.ClientID == "" { - return fmt.Errorf("cannot save linked cloud: invalid ClientId") + return errors.New("cannot save linked cloud: invalid ClientId") } if sub.OAuth.ClientSecret == "" { - return fmt.Errorf("cannot save linked cloud: invalid ClientSecret") + return errors.New("cannot save linked cloud: invalid ClientSecret") } if sub.OAuth.AuthURL == "" { - return fmt.Errorf("cannot save linked cloud: invalid AuthUrl") + return errors.New("cannot save linked cloud: invalid AuthUrl") } if sub.OAuth.TokenURL == "" { - return fmt.Errorf("cannot save linked cloud: invalid TokenUrl") + return errors.New("cannot save linked cloud: invalid TokenUrl") } return nil } @@ -46,7 +46,7 @@ func (s *Store) UpdateLinkedCloud(ctx context.Context, sub store.LinkedCloud) er return fmt.Errorf("cannot save linked cloud: %w", err) } if res.MatchedCount == 0 { - return fmt.Errorf("cannot update linked cloud: not found") + return errors.New("cannot update linked cloud: not found") } return nil } @@ -67,7 +67,7 @@ func (s *Store) InsertLinkedCloud(ctx context.Context, sub store.LinkedCloud) er func (s *Store) RemoveLinkedCloud(ctx context.Context, linkedCloudID string) error { if linkedCloudID == "" { - return fmt.Errorf("cannot remove linked cloud: invalid LinkedCloudId") + return errors.New("cannot remove linked cloud: invalid LinkedCloudId") } res, err := s.Collection(resLinkedCloudCName).DeleteOne(ctx, bson.M{"_id": linkedCloudID}) @@ -75,7 +75,7 @@ func (s *Store) RemoveLinkedCloud(ctx context.Context, linkedCloudID string) err return fmt.Errorf("cannot remove linked cloud: %w", err) } if res.DeletedCount == 0 { - return fmt.Errorf("cannot remove linked cloud: not found") + return errors.New("cannot remove linked cloud: not found") } return nil } diff --git a/cloud2cloud-connector/store/mongodb/linkedClouds_test.go b/cloud2cloud-connector/store/mongodb/linkedClouds_test.go index a983ae00d..b1b68867a 100644 --- a/cloud2cloud-connector/store/mongodb/linkedClouds_test.go +++ b/cloud2cloud-connector/store/mongodb/linkedClouds_test.go @@ -7,7 +7,6 @@ import ( "github.com/plgd-dev/hub/v2/cloud2cloud-connector/store" "github.com/plgd-dev/hub/v2/cloud2cloud-connector/test" "github.com/plgd-dev/hub/v2/pkg/security/oauth2/oauth" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -85,10 +84,10 @@ func TestStoreUpdateLinkedCloud(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := s.UpdateLinkedCloud(ctx, tt.args.sub) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) + require.Error(t, err) + return } + require.NoError(t, err) }) } } @@ -142,10 +141,10 @@ func TestStoreRemoveLinkedCloud(t *testing.T) { t.Run(tt.name, func(t *testing.T) { err := s.RemoveLinkedCloud(ctx, tt.args.LinkedCloudID) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) + require.Error(t, err) + return } + require.NoError(t, err) }) } } @@ -242,11 +241,11 @@ func TestStoreLoadLinkedClouds(t *testing.T) { var h testLinkedCloudHandler err := s.LoadLinkedClouds(ctx, tt.args.query, &h) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } - assert.NoError(t, err) - assert.Equal(t, tt.want, h.lcs) + require.NoError(t, err) + require.Equal(t, tt.want, h.lcs) }) } } diff --git a/cloud2cloud-gateway/service/retrieveDevice.go b/cloud2cloud-gateway/service/retrieveDevice.go index fd972a7e7..4aa7cc798 100644 --- a/cloud2cloud-gateway/service/retrieveDevice.go +++ b/cloud2cloud-gateway/service/retrieveDevice.go @@ -65,7 +65,7 @@ func (rh *RequestHandler) GetResourceLinks(ctx context.Context, deviceIdFilter [ } } if len(resourceLinks) == 0 { - return nil, fmt.Errorf("cannot get resource links: not found") + return nil, errors.New("cannot get resource links: not found") } return resourceLinks, nil } @@ -216,7 +216,7 @@ func (rh *RequestHandler) RetrieveDeviceWithContentQuery(ctx context.Context, w case ContentQueryAllValue: return rh.RetrieveDeviceWithRepresentations(ctx, w, routeVars[deviceIDKey], encoder) } - return http.StatusBadRequest, fmt.Errorf("invalid content query parameter") + return http.StatusBadRequest, errors.New("invalid content query parameter") } func (rh *RequestHandler) RetrieveDevice(w http.ResponseWriter, r *http.Request) { diff --git a/cloud2cloud-gateway/service/retrieveResource.go b/cloud2cloud-gateway/service/retrieveResource.go index a9f99d3b9..1dd61b911 100644 --- a/cloud2cloud-gateway/service/retrieveResource.go +++ b/cloud2cloud-gateway/service/retrieveResource.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "net/http" "strings" @@ -48,7 +49,7 @@ func (rh *RequestHandler) RetrieveResourceWithContentQuery(ctx context.Context, } return code, err } - return http.StatusBadRequest, fmt.Errorf("invalid content query parameter") + return http.StatusBadRequest, errors.New("invalid content query parameter") } func (rh *RequestHandler) RetrieveResource(w http.ResponseWriter, r *http.Request) { diff --git a/cloud2cloud-gateway/service/retrieveResourceSubscription.go b/cloud2cloud-gateway/service/retrieveResourceSubscription.go index 738f408bd..b61d7766f 100644 --- a/cloud2cloud-gateway/service/retrieveResourceSubscription.go +++ b/cloud2cloud-gateway/service/retrieveResourceSubscription.go @@ -1,6 +1,7 @@ package service import ( + "errors" "fmt" "net/http" @@ -15,7 +16,7 @@ func (rh *RequestHandler) retrieveSubscription(w http.ResponseWriter, r *http.Re sub, ok := rh.subMgr.Load(subscriptionID) if !ok { - return http.StatusNotFound, fmt.Errorf("not found") + return http.StatusNotFound, errors.New("not found") } if href != "" && sub.Href != href { diff --git a/cloud2cloud-gateway/service/subscribeToDevices_test.go b/cloud2cloud-gateway/service/subscribeToDevices_test.go index 4b6fed496..8bbb23755 100644 --- a/cloud2cloud-gateway/service/subscribeToDevices_test.go +++ b/cloud2cloud-gateway/service/subscribeToDevices_test.go @@ -25,7 +25,6 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" "github.com/plgd-dev/kit/v2/codec/json" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -77,21 +76,21 @@ func TestRequestHandlerSubscribeToDevices(t *testing.T) { r := router.NewRouter() r.StrictSlash(true) r.HandleFunc(eventsURI, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h, err := events.ParseEventHeader(r) - assert.NoError(t, err) + h, err2 := events.ParseEventHeader(r) + require.NoError(t, err2) defer func() { _ = r.Body.Close() }() - assert.Equal(t, wantEventType, h.EventType) - buf, err := io.ReadAll(r.Body) - assert.NoError(t, err) + require.Equal(t, wantEventType, h.EventType) + buf, err2 := io.ReadAll(r.Body) + require.NoError(t, err2) var v interface{} - err = json.Decode(buf, &v) - assert.NoError(t, err) - assert.Equal(t, v, wantEventContent) + err2 = json.Decode(buf, &v) + require.NoError(t, err2) + require.Equal(t, wantEventContent, v) w.WriteHeader(http.StatusOK) - err = eventsServer.Close() - assert.NoError(t, err) + err2 = eventsServer.Close() + require.NoError(t, err2) })).Methods("POST") _ = http.Serve(eventsServer, r) }() @@ -109,7 +108,7 @@ func TestRequestHandlerSubscribeToDevices(t *testing.T) { require.NoError(t, err) req := testHttp.NewHTTPRequest(http.MethodPost, uri, bytes.NewBuffer(data)).AuthToken(token).Accept(accept).Build(ctx, t) resp := testHttp.DoHTTPRequest(t, req) - assert.Equal(t, wantCode, resp.StatusCode) + require.Equal(t, wantCode, resp.StatusCode) defer func() { _ = resp.Body.Close() }() @@ -170,21 +169,21 @@ func TestRequestHandlerSubscribeToDevicesOffline(t *testing.T) { r := router.NewRouter() r.StrictSlash(true) r.HandleFunc(eventsURI, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - h, err := events.ParseEventHeader(r) - assert.NoError(t, err) + h, err2 := events.ParseEventHeader(r) + require.NoError(t, err2) defer func() { _ = r.Body.Close() }() - assert.Equal(t, wantEventType, h.EventType) - buf, err := io.ReadAll(r.Body) - assert.NoError(t, err) + require.Equal(t, wantEventType, h.EventType) + buf, err2 := io.ReadAll(r.Body) + require.NoError(t, err2) var v interface{} - err = json.Decode(buf, &v) - assert.NoError(t, err) - assert.Equal(t, v, wantEventContent) + err2 = json.Decode(buf, &v) + require.NoError(t, err2) + require.Equal(t, wantEventContent, v) w.WriteHeader(http.StatusOK) - err = eventsServer.Close() - assert.NoError(t, err) + err2 = eventsServer.Close() + require.NoError(t, err2) })).Methods("POST") _ = http.Serve(eventsServer, r) }() @@ -202,7 +201,7 @@ func TestRequestHandlerSubscribeToDevicesOffline(t *testing.T) { require.NoError(t, err) req := testHttp.NewHTTPRequest(http.MethodPost, uri, bytes.NewBuffer(data)).AuthToken(oauthTest.GetDefaultAccessToken(t)).Accept(accept).Build(ctx, t) resp := testHttp.DoHTTPRequest(t, req) - assert.Equal(t, wantCode, resp.StatusCode) + require.Equal(t, wantCode, resp.StatusCode) defer func() { _ = resp.Body.Close() }() diff --git a/cloud2cloud-gateway/service/subscriptionManager.go b/cloud2cloud-gateway/service/subscriptionManager.go index d73ecc85e..0cd36bac1 100644 --- a/cloud2cloud-gateway/service/subscriptionManager.go +++ b/cloud2cloud-gateway/service/subscriptionManager.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "sync" "time" @@ -73,12 +74,12 @@ func (s *SubscriptionManager) storeToSubs(sub store.Subscription) { func (s *SubscriptionManager) Connect(id string) error { subRaw, ok := s.subscriptions.Load(id) if !ok { - return fmt.Errorf("not found") + return errors.New("not found") } sub := subRaw.(*SubscriptionData) if sub.sub != nil { if !ok { - return fmt.Errorf("already connected") + return errors.New("already connected") } } ctx := s.ctx @@ -117,7 +118,7 @@ func cancelSubscription(ctx context.Context, emitEvent emitEventFunc, sub store. func (s *SubscriptionManager) PullOut(ctx context.Context, id, href string) (store.Subscription, error) { subDataRaw, ok := s.subscriptions.PullOut(id) if !ok { - return store.Subscription{}, fmt.Errorf("not found") + return store.Subscription{}, errors.New("not found") } subData := subDataRaw.(*SubscriptionData) if href != "" && subData.data.Href != href { diff --git a/cloud2cloud-gateway/service/subscriptions.go b/cloud2cloud-gateway/service/subscriptions.go index 0d1605a11..4e917a343 100644 --- a/cloud2cloud-gateway/service/subscriptions.go +++ b/cloud2cloud-gateway/service/subscriptions.go @@ -221,7 +221,7 @@ func (s *SubscriptionData) createDevicesSubscription(ctx context.Context, emitEv } for _, e := range eventTypes { - _, err := emitEvent(ctx, e, s.Data(), s.IncrementSequenceNumber, makeDevicesRepresentation([]string{})) + _, err = emitEvent(ctx, e, s.Data(), s.IncrementSequenceNumber, makeDevicesRepresentation([]string{})) if err != nil { return nil, createSubDevicesError(err) } @@ -339,7 +339,7 @@ func (s *SubscriptionData) createDeviceSubscription(ctx context.Context, emitEve func (s *SubscriptionData) Connect(ctx context.Context, emitEvent emitEventFunc, deleteSub func(ctx context.Context, subID, href string) (store.Subscription, error)) error { if s.Subscription() != nil { - return fmt.Errorf("is already connected") + return errors.New("is already connected") } h := closeEventHandler{ ctx: ctx, diff --git a/cloud2cloud-gateway/store/mongodb/store.go b/cloud2cloud-gateway/store/mongodb/store.go index fb5249f59..f7b80bf01 100644 --- a/cloud2cloud-gateway/store/mongodb/store.go +++ b/cloud2cloud-gateway/store/mongodb/store.go @@ -3,6 +3,7 @@ package mongodb import ( "context" "crypto/tls" + "errors" "fmt" pkgMongo "github.com/plgd-dev/hub/v2/pkg/mongodb" @@ -30,7 +31,7 @@ func NewStore(ctx context.Context, cfg pkgMongo.Config, tls *tls.Config, tracerP func incrementSubscriptionSequenceNumber(ctx context.Context, col *mongo.Collection, subscriptionID string) (uint64, error) { if subscriptionID == "" { - return 0, fmt.Errorf("cannot increment sequence number: invalid subscriptionID") + return 0, errors.New("cannot increment sequence number: invalid subscriptionID") } var res bson.M diff --git a/cloud2cloud-gateway/store/mongodb/subscription.go b/cloud2cloud-gateway/store/mongodb/subscription.go index 2d8513960..8649063ca 100644 --- a/cloud2cloud-gateway/store/mongodb/subscription.go +++ b/cloud2cloud-gateway/store/mongodb/subscription.go @@ -75,49 +75,49 @@ func makeDBSub(sub store.Subscription) DBSub { func validateDevicesSubscription(sub store.Subscription) error { if sub.DeviceID != "" { - return fmt.Errorf("invalid DeviceID for devices subscription type") + return errors.New("invalid DeviceID for devices subscription type") } if sub.Href != "" { - return fmt.Errorf("invalid Href for devices subscription type") + return errors.New("invalid Href for devices subscription type") } return nil } func validateDeviceSubscription(sub store.Subscription) error { if sub.DeviceID == "" { - return fmt.Errorf("invalid DeviceID for device subscription type") + return errors.New("invalid DeviceID for device subscription type") } if sub.Href != "" { - return fmt.Errorf("invalid Href for device subscription type") + return errors.New("invalid Href for device subscription type") } return nil } func validateResourceSubscription(sub store.Subscription) error { if sub.DeviceID == "" { - return fmt.Errorf("invalid DeviceID for resource subscription type") + return errors.New("invalid DeviceID for resource subscription type") } if sub.Href == "" { - return fmt.Errorf("invalid Href for resource subscription type") + return errors.New("invalid Href for resource subscription type") } return nil } func validateSubscription(sub store.Subscription) error { if sub.ID == "" { - return fmt.Errorf("invalid ID") + return errors.New("invalid ID") } if len(sub.EventTypes) == 0 { - return fmt.Errorf("invalid EventTypes") + return errors.New("invalid EventTypes") } if sub.URL == "" { - return fmt.Errorf("invalid URL") + return errors.New("invalid URL") } if sub.SigningSecret == "" { - return fmt.Errorf("invalid SigningSecret") + return errors.New("invalid SigningSecret") } if sub.AccessToken == "" { - return fmt.Errorf("invalid AccessToken") + return errors.New("invalid AccessToken") } switch sub.Type { @@ -156,7 +156,7 @@ func (s *Store) IncrementSubscriptionSequenceNumber(ctx context.Context, subscri func (s *Store) SetInitialized(ctx context.Context, subscriptionID string) error { col := s.Collection(subscriptionsCName) if subscriptionID == "" { - return fmt.Errorf("cannot set initialized: invalid subscriptionId") + return errors.New("cannot set initialized: invalid subscriptionId") } opts := &options.UpdateOptions{} @@ -193,7 +193,7 @@ func (s *Store) LoadSubscriptions(ctx context.Context, query store.SubscriptionQ case query.Type == "" && query.DeviceID == "" && query.Href == "": iter, err = col.Find(ctx, bson.M{}) case query.Type == "": - return fmt.Errorf("invalid Type") + return errors.New("invalid Type") case query.DeviceID != "" && query.Href != "": q := bson.M{ typeKey: query.Type, diff --git a/cloud2cloud-gateway/test/events.go b/cloud2cloud-gateway/test/events.go index c59398a91..e30b3fe52 100644 --- a/cloud2cloud-gateway/test/events.go +++ b/cloud2cloud-gateway/test/events.go @@ -17,7 +17,6 @@ import ( "github.com/plgd-dev/hub/v2/pkg/security/certManager/server" "github.com/plgd-dev/hub/v2/test/config" "github.com/plgd-dev/kit/v2/codec/json" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -64,7 +63,7 @@ func DecodeEvent(t *testing.T, etype events.EventType, data []byte) interface{} case events.EventType_ResourcesUnpublished: var links schema.ResourceLinks err := json.Decode(data, &links) - assert.NoError(t, err) + require.NoError(t, err) return links case events.EventType_ResourceChanged: var colContent []map[interface{}]interface{} @@ -74,7 +73,7 @@ func DecodeEvent(t *testing.T, etype events.EventType, data []byte) interface{} } var content map[interface{}]interface{} err = json.Decode(data, &content) - assert.NoError(t, err) + require.NoError(t, err) return content case events.EventType_DevicesRegistered: fallthrough @@ -85,7 +84,7 @@ func DecodeEvent(t *testing.T, etype events.EventType, data []byte) interface{} case events.EventType_DevicesOffline: var devices []map[string]string err := json.Decode(data, &devices) - assert.NoError(t, err) + require.NoError(t, err) return devices } @@ -134,12 +133,12 @@ func (s *EventsServer) Run(t *testing.T) EventChan { r.StrictSlash(true) r.HandleFunc(s.uri, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h, err := events.ParseEventHeader(r) - assert.NoError(t, err) + require.NoError(t, err) defer func() { _ = r.Body.Close() }() buf, err := io.ReadAll(r.Body) - assert.NoError(t, err) + require.NoError(t, err) data := DecodeEvent(t, h.EventType, buf) dataChan <- Event{ diff --git a/coap-gateway/coapconv/coapconv.go b/coap-gateway/coapconv/coapconv.go index a00296795..e6975e0e5 100644 --- a/coap-gateway/coapconv/coapconv.go +++ b/coap-gateway/coapconv/coapconv.go @@ -110,7 +110,7 @@ func newCoapResourceCreateOrUpdateRequest(ctx context.Context, messagePool *pool return nil, fmt.Errorf("invalid content type for request: %w", err) } if content == nil { - return nil, fmt.Errorf("invalid content for request") + return nil, errors.New("invalid content for request") } token, err := message.GetToken() if err != nil { @@ -416,8 +416,8 @@ func NewUpdateResourceRequest(resourceID *commands.ResourceId, req *mux.Message, return &commands.UpdateResourceRequest{ ResourceId: resourceID, Content: &commands.Content{ - Data: content.Data, - ContentType: content.ContentType, + Data: content.GetData(), + ContentType: content.GetContentType(), }, ResourceInterface: resourceInterface, CommandMetadata: metadata, diff --git a/coap-gateway/service/auth.go b/coap-gateway/service/auth.go index 6b47c9b82..72003e5b5 100644 --- a/coap-gateway/service/auth.go +++ b/coap-gateway/service/auth.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "fmt" "time" @@ -27,7 +28,7 @@ func newAuthInterceptor() Interceptor { } e := ctx.Value(&authCtxKey) if e == nil { - return ctx, fmt.Errorf("invalid authorization context") + return ctx, errors.New("invalid authorization context") } authCtx := e.(*authorizationContext) err := authCtx.IsValid() @@ -60,7 +61,7 @@ func (s *Service) verifyDeviceID(tlsDeviceID string, claim pkgJwt.Claims) (strin return jwtDeviceID, nil } if tlsDeviceID == "" { - return "", fmt.Errorf("certificate of device doesn't contain device id") + return "", errors.New("certificate of device doesn't contain device id") } if s.config.APIs.COAP.Authorization.DeviceIDClaim != "" && jwtDeviceID != tlsDeviceID { return "", fmt.Errorf("access token issued to the device ('%v') used by the different device ('%v')", jwtDeviceID, tlsDeviceID) @@ -81,7 +82,7 @@ func (s *Service) VerifyAndResolveDeviceID(tlsDeviceID, paramDeviceID string, cl func verifyChain(chain []*x509.Certificate, capool *x509.CertPool, identityPropertiesRequired bool) error { if len(chain) == 0 { - return fmt.Errorf("certificate chain is empty") + return errors.New("certificate chain is empty") } certificate := chain[0] intermediateCAPool := x509.NewCertPool() @@ -109,10 +110,10 @@ func verifyChain(chain []*x509.Certificate, capool *x509.CertPool, identityPrope } } if !ekuHasClient { - return fmt.Errorf("the extended key usage field in the device certificate does not contain client authentication") + return errors.New("the extended key usage field in the device certificate does not contain client authentication") } if !ekuHasServer { - return fmt.Errorf("the extended key usage field in the device certificate does not contain server authentication") + return errors.New("the extended key usage field in the device certificate does not contain server authentication") } if !identityPropertiesRequired { return nil @@ -131,17 +132,17 @@ func MakeGetConfigForClient(tlsCfg *tls.Config, identityPropertiesRequired bool) ClientAuth: tlsCfg.ClientAuth, ClientCAs: tlsCfg.ClientCAs, VerifyPeerCertificate: func(_ [][]byte, chains [][]*x509.Certificate) error { - var errors *multierror.Error + var errs *multierror.Error for _, chain := range chains { err := verifyChain(chain, tlsCfg.ClientCAs, identityPropertiesRequired) if err == nil { return nil } - errors = multierror.Append(errors, err) + errs = multierror.Append(errs, err) } - err := fmt.Errorf("empty chains") - if errors.ErrorOrNil() != nil { - err = errors + err := errors.New("empty chains") + if errs.ErrorOrNil() != nil { + err = errs } return pkgX509.NewError(chains, err) }, diff --git a/coap-gateway/service/clientObserveHandler.go b/coap-gateway/service/clientObserveHandler.go index 2221886d5..16e9705b7 100644 --- a/coap-gateway/service/clientObserveHandler.go +++ b/coap-gateway/service/clientObserveHandler.go @@ -178,18 +178,15 @@ func (s *resourceSubscription) Init(ctx context.Context) error { var d *events.ResourceChanged for { - resource, err := client.Recv() - if errors.Is(err, io.EOF) { + resource, errR := client.Recv() + if errors.Is(errR, io.EOF) { break } - if err != nil { - return err + if errR != nil { + return errR } d = resource.Data } - if err != nil { - return err - } authCtx, err := s.client.GetAuthorizationContext() if err != nil { return err @@ -254,7 +251,7 @@ func startResourceObservation(req *mux.Message, client *session, authCtx *author return nil, statusErrorf(coapconv.GrpcErr2CoapCode(err, coapconv.Retrieve), "%w", getStartObserveResourceErr(deviceID, href, err)) } if !ok { - return nil, statusErrorf(coapCodes.Unauthorized, "%w", getStartObserveResourceErr(deviceID, href, fmt.Errorf("unauthorized access"))) + return nil, statusErrorf(coapCodes.Unauthorized, "%w", getStartObserveResourceErr(deviceID, href, errors.New("unauthorized access"))) } token := req.Token().String() sub := newResourceSubscription(req, client, authCtx, deviceID, href) @@ -294,7 +291,7 @@ func stopResourceObservation(req *mux.Message, client *session, deviceID, href s return nil, statusErrorf(coapCodes.BadRequest, "%w", getStopObserveResourceErr(deviceID, href, err)) } if !canceled { - return nil, statusErrorf(coapCodes.BadRequest, "%w", getStopObserveResourceErr(deviceID, href, fmt.Errorf("subscription not found"))) + return nil, statusErrorf(coapCodes.BadRequest, "%w", getStopObserveResourceErr(deviceID, href, errors.New("subscription not found"))) } return CreateResourceContentToObserver(client, nil, 1, req.Token()) } @@ -306,7 +303,7 @@ func clientResetObservationHandler(req *mux.Message, client *session) (*pool.Mes return nil, statusErrorf(coapCodes.BadRequest, "%w", fmt.Errorf("cannot reset resource observation: %w", err)) } if !canceled { - return nil, statusErrorf(coapCodes.BadRequest, "%w", fmt.Errorf("cannot reset resource observation: not found")) + return nil, statusErrorf(coapCodes.BadRequest, "%w", errors.New("cannot reset resource observation: not found")) } // reset does not send response return nil, nil diff --git a/coap-gateway/service/clientObserver.go b/coap-gateway/service/clientObserver.go index 07df6b2d9..61a141d9a 100644 --- a/coap-gateway/service/clientObserver.go +++ b/coap-gateway/service/clientObserver.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "github.com/plgd-dev/hub/v2/coap-gateway/service/observation" @@ -30,7 +31,7 @@ func (c *session) getDeviceObserver(ctx context.Context) (*observation.DeviceObs } deviceObserver, ok := v.(*observation.DeviceObserver) if !ok { - return nil, false, getError(fmt.Errorf("invalid future value")) + return nil, false, getError(errors.New("invalid future value")) } return deviceObserver, true, nil } @@ -59,8 +60,7 @@ func (c *session) replaceDeviceObserverWithDeviceTwin(ctx context.Context, twinE observationType = obs.GetObservationType() } if deviceID == "" { - err := fmt.Errorf("cannot replace device observer: invalid device id") - return false, err + return false, errors.New("cannot replace device observer: invalid device id") } twinEnabled = twinEnabled || twinForceSynchronization if !twinForceSynchronization && prevTwinEnabled == twinEnabled { @@ -68,8 +68,8 @@ func (c *session) replaceDeviceObserverWithDeviceTwin(ctx context.Context, twinE } deviceObserverFuture, setDeviceObserver := future.New() oldDeviceObserver := c.replaceDeviceObserver(deviceObserverFuture) - if err := cleanDeviceObserver(ctx, oldDeviceObserver); err != nil { - c.Errorf("failed to close replaced device observer: %w", err) + if errD := cleanDeviceObserver(ctx, oldDeviceObserver); errD != nil { + c.Errorf("failed to close replaced device observer: %w", errD) } deviceObserver, err := observation.NewDeviceObserver(c.Context(), deviceID, c, c, c, @@ -98,7 +98,7 @@ func toDeviceObserver(ctx context.Context, devObsFut *future.Future) (*observati } deviceObserver, ok := v.(*observation.DeviceObserver) if !ok { - return nil, fmt.Errorf("invalid future value") + return nil, errors.New("invalid future value") } return deviceObserver, nil } diff --git a/coap-gateway/service/clientRetrieveHandler.go b/coap-gateway/service/clientRetrieveHandler.go index 99b72f21a..353f1b194 100644 --- a/coap-gateway/service/clientRetrieveHandler.go +++ b/coap-gateway/service/clientRetrieveHandler.go @@ -98,7 +98,7 @@ func clientRetrieveFromResourceTwinHandler(ctx context.Context, client *session, return resourceValue.GetData().Content, coapCodes.Content, nil } } - return nil, coapCodes.NotFound, fmt.Errorf("not found") + return nil, coapCodes.NotFound, errors.New("not found") } func clientRetrieveFromDeviceHandler(req *mux.Message, client *session, deviceID, href string) (*commands.Content, coapCodes.Code, error) { diff --git a/coap-gateway/service/clientRetrieveHandler_test.go b/coap-gateway/service/clientRetrieveHandler_test.go index 1484fed73..150d85fae 100644 --- a/coap-gateway/service/clientRetrieveHandler_test.go +++ b/coap-gateway/service/clientRetrieveHandler_test.go @@ -106,7 +106,7 @@ func TestClientRetrieveHandler(t *testing.T) { req.SetOptionString(message.URIQuery, tt.args.query) } resp, err := co.Do(req) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, tt.wantsCode.String(), resp.Code().String()) }) } diff --git a/coap-gateway/service/config.go b/coap-gateway/service/config.go index e49aa1e61..2f488fa65 100644 --- a/coap-gateway/service/config.go +++ b/coap-gateway/service/config.go @@ -1,6 +1,7 @@ package service import ( + "errors" "fmt" "time" @@ -174,7 +175,7 @@ func (c *COAPConfigMarshalerUnmarshaler) Validate() error { return err } if !c.InjectedCOAPConfig.TLSConfig.IdentityPropertiesRequired && c.Authorization.DeviceIDClaim != "" { - return fmt.Errorf("tls.identityPropertiesRequired('%v') - %w", c.InjectedCOAPConfig.TLSConfig.IdentityPropertiesRequired, fmt.Errorf("combination with authorization.deviceIDClaim is not supported")) + return fmt.Errorf("tls.identityPropertiesRequired('%v') - %w", c.InjectedCOAPConfig.TLSConfig.IdentityPropertiesRequired, errors.New("combination with authorization.deviceIDClaim is not supported")) } return nil } diff --git a/coap-gateway/service/exchangeCache.go b/coap-gateway/service/exchangeCache.go index d0d758e39..b798d44b8 100644 --- a/coap-gateway/service/exchangeCache.go +++ b/coap-gateway/service/exchangeCache.go @@ -2,7 +2,7 @@ package service import ( "context" - "fmt" + "errors" "sync" "github.com/plgd-dev/hub/v2/pkg/security/oauth2" @@ -40,7 +40,7 @@ func (e *ExchangeCache) getFutureToken(authorizationCode string) (*future.Future // Execute Exchange or returned cached value. func (e *ExchangeCache) Execute(ctx context.Context, provider *oauth2.PlgdProvider, authorizationCode string) (*oauth2.Token, error) { if authorizationCode == "" { - return nil, fmt.Errorf("invalid authorization code") + return nil, errors.New("invalid authorization code") } f, set := e.getFutureToken(authorizationCode) diff --git a/coap-gateway/service/mem_test.go b/coap-gateway/service/mem_test.go index 200c84728..4795e6203 100644 --- a/coap-gateway/service/mem_test.go +++ b/coap-gateway/service/mem_test.go @@ -6,6 +6,7 @@ package service_test import ( "context" "crypto/tls" + "errors" "fmt" "os" "os/exec" @@ -221,7 +222,7 @@ func testDevices(t *testing.T, numDevices, numResources, expRSSInMB int, resourc err = cmdService.Start() require.NoError(t, err) } else { - require.NoError(t, fmt.Errorf("service process is dead - canceling test")) + require.NoError(t, errors.New("service process is dead - canceling test")) } } t.Logf("waiting for service to start: %v, serviceRSS %v\n", time.Since(now), bToMb(serviceRSS)) @@ -250,8 +251,8 @@ func testDevices(t *testing.T, numDevices, numResources, expRSSInMB int, resourc }() coapShutdown := func() { - err := s.Close() - require.NoError(t, err) + errC := s.Close() + require.NoError(t, errC) wg.Wait() } defer coapShutdown() diff --git a/coap-gateway/service/message/response_test.go b/coap-gateway/service/message/response_test.go index c78868e94..7c8ab93d1 100644 --- a/coap-gateway/service/message/response_test.go +++ b/coap-gateway/service/message/response_test.go @@ -2,6 +2,7 @@ package message import ( "context" + "errors" "fmt" "net/http" "testing" @@ -72,7 +73,7 @@ func TestIsTempError(t *testing.T) { }, { name: "any error as temporary", - args: args{err: fmt.Errorf("any error")}, + args: args{err: errors.New("any error")}, want: true, }, { diff --git a/coap-gateway/service/observation/deviceObserver.go b/coap-gateway/service/observation/deviceObserver.go index 5a7073b2f..baaf63218 100644 --- a/coap-gateway/service/observation/deviceObserver.go +++ b/coap-gateway/service/observation/deviceObserver.go @@ -255,8 +255,8 @@ func NewDeviceObserver(ctx context.Context, deviceID string, coapConn ClientConn if cfg.ObservationType == ObservationType_PerDevice { etags := getETags(ctx, deviceID, rdClient, cfg) - resourcesObserver, err := createDiscoveryResourceObserver(ctx, deviceID, coapConn, callbacks, etags, cfg.Logger) - if err == nil { + resourcesObserver, errC := createDiscoveryResourceObserver(ctx, deviceID, coapConn, callbacks, etags, cfg.Logger) + if errC == nil { return &DeviceObserver{ deviceID: deviceID, observationType: ObservationType_PerDevice, @@ -267,15 +267,15 @@ func NewDeviceObserver(ctx context.Context, deviceID string, coapConn ClientConn raClient: raClient, }, nil } - cfg.Logger.Debugf("NewDeviceObserver: failed to create /oic/res observation for device(%v): %v", deviceID, err) + cfg.Logger.Debugf("NewDeviceObserver: failed to create /oic/res observation for device(%v): %v", deviceID, errC) } if cfg.RequireBatchObserveEnabled { return nil, createError(fmt.Errorf("device(%v) doesn't support batch observe, which is required by configuration", deviceID)) } - resourcesObserver, err := createPublishedResourcesObserver(ctx, deviceID, coapConn, callbacks, published, cfg.Logger) - if err != nil { - return nil, createError(err) + resourcesObserver, errC := createPublishedResourcesObserver(ctx, deviceID, coapConn, callbacks, published, cfg.Logger) + if errC != nil { + return nil, createError(errC) } return &DeviceObserver{ deviceID: deviceID, @@ -289,12 +289,12 @@ func NewDeviceObserver(ctx context.Context, deviceID string, coapConn ClientConn } func emptyDeviceIDError() error { - return fmt.Errorf("empty deviceID") + return errors.New("empty deviceID") } func IsDiscoveryResourceObservable(links schema.ResourceLinks) (bool, error) { if len(links) == 0 { - return false, fmt.Errorf("no links") + return false, errors.New("no links") } resourceHref := resources.ResourceURI observeInterface := interfaces.OC_IF_B @@ -328,7 +328,7 @@ func loadTwinEnabled(ctx context.Context, rdClient GrpcGatewayClient, deviceID s return fmt.Errorf("cannot get device(%v) metadata: %w", deviceID, err) } if deviceID == "" { - return false, metadataError(fmt.Errorf("invalid deviceID")) + return false, metadataError(errors.New("invalid deviceID")) } deviceMetadataClient, err := rdClient.GetDevicesMetadata(ctx, &pb.GetDevicesMetadataRequest{ DeviceIdFilter: []string{deviceID}, @@ -413,7 +413,7 @@ func (d *DeviceObserver) GetResources() ([]*commands.ResourceId, error) { return nil, nil } if d.resourcesObserver == nil { - return nil, getResourcesError(fmt.Errorf("resources observer is nil")) + return nil, getResourcesError(errors.New("resources observer is nil")) } return d.resourcesObserver.getResources(), nil } diff --git a/coap-gateway/service/observation/deviceObserver_test.go b/coap-gateway/service/observation/deviceObserver_test.go index 90f5d300d..bf25e3e2d 100644 --- a/coap-gateway/service/observation/deviceObserver_test.go +++ b/coap-gateway/service/observation/deviceObserver_test.go @@ -121,13 +121,13 @@ func (h *observerHandler) SignIn(req coapgwService.CoapSignInReq) (coapgwService err = h.service.Submit(func() { if prevDeviceObserver != nil { - v, err := prevDeviceObserver.Get(h.ctx) - require.NoError(h.t, err) + v, errD := prevDeviceObserver.Get(h.ctx) + require.NoError(h.t, errD) obs := v.(*observation.DeviceObserver) obs.Clean(h.ctx) } - deviceObserver, err := h.deviceObserverFactory.makeDeviceObserver(h.ctx, h.coapConn, h.OnObserveResource, h.OnGetResourceContent, h.UpdateTwinSynchronizationStatus, observation.WithRequireBatchObserveEnabled(h.requireBatchObserveEnabled)) - require.NoError(h.t, err) + deviceObserver, errD := h.deviceObserverFactory.makeDeviceObserver(h.ctx, h.coapConn, h.OnObserveResource, h.OnGetResourceContent, h.UpdateTwinSynchronizationStatus, observation.WithRequireBatchObserveEnabled(h.requireBatchObserveEnabled)) + require.NoError(h.t, errD) setDeviceObserver(deviceObserver, nil) }) require.NoError(h.t, err) @@ -298,7 +298,7 @@ func testPreregisterVirtualDevice(ctx context.Context, t *testing.T, deviceID st ev, err := client.Recv() require.NoError(t, err) require.NotEmpty(t, ev.GetOperationProcessed()) - require.Equal(t, ev.GetOperationProcessed().GetErrorStatus().GetCode(), pb.Event_OperationProcessed_ErrorStatus_OK) + require.Equal(t, pb.Event_OperationProcessed_ErrorStatus_OK, ev.GetOperationProcessed().GetErrorStatus().GetCode()) virtualdevice.CreateDevice(ctx, t, "name-"+deviceID, deviceID, numResources, test.StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME), isClient, raClient) resources := virtualdevice.CreateDeviceResourceLinks(deviceID, numResources) links := make([]schema.ResourceLink, 0, len(resources)) diff --git a/coap-gateway/service/observation/resourcesObserver.go b/coap-gateway/service/observation/resourcesObserver.go index ffe438afe..0ea55ea89 100644 --- a/coap-gateway/service/observation/resourcesObserver.go +++ b/coap-gateway/service/observation/resourcesObserver.go @@ -2,6 +2,7 @@ package observation import ( "context" + "errors" "fmt" "sync" "time" @@ -68,13 +69,13 @@ func newResourcesObserver(deviceID string, coapConn ClientConn, callbacks Resour fatalCannotCreate(emptyDeviceIDError()) } if coapConn == nil { - fatalCannotCreate(fmt.Errorf("invalid coap-gateway connection")) + fatalCannotCreate(errors.New("invalid coap-gateway connection")) } if callbacks.OnObserveResource == nil { - fatalCannotCreate(fmt.Errorf("invalid onObserveResource callback")) + fatalCannotCreate(errors.New("invalid onObserveResource callback")) } if callbacks.OnGetResourceContent == nil { - fatalCannotCreate(fmt.Errorf("invalid onGetResourceContent callback")) + fatalCannotCreate(errors.New("invalid onGetResourceContent callback")) } return &resourcesObserver{ deviceID: deviceID, @@ -124,15 +125,13 @@ func (o *resourcesObserver) setSynchronizedAtResource(href string) bool { o.private.lock.Lock() defer o.private.lock.Unlock() i := o.private.resources.search(href) - synced := false if i < len(o.private.resources) && o.private.resources[i].Equals(href) { - synced = o.private.resources[i].synced.CompareAndSwap(false, true) + if !o.private.resources[i].synced.CompareAndSwap(false, true) { + return false + } } else { return false } - if !synced { - return false - } if o.isSynchronizedLocked() { return true } @@ -213,7 +212,7 @@ func (o *resourcesObserver) observeResource(ctx context.Context, obsRes *observe return nil, cannotObserveResourceError(o.deviceID, obsRes.Href(), err) } if obs.Canceled() { - return nil, cannotObserveResourceError(o.deviceID, obsRes.Href(), fmt.Errorf("resource not observable")) + return nil, cannotObserveResourceError(o.deviceID, obsRes.Href(), errors.New("resource not observable")) } return obs, nil } @@ -373,8 +372,8 @@ func (o *resourcesObserver) CleanObservedResources(ctx context.Context) { } func (o *resourcesObserver) cleanObservedResourcesLocked(ctx context.Context) { - observedResources := o.popObservedResourcesLocked() - for _, obs := range observedResources { + ors := o.popObservedResourcesLocked() + for _, obs := range ors { if v := obs.PopObservation(); v != nil { if err := v.Cancel(ctx); err != nil { o.logger.Errorf("cannot cancel resource('/%v%v') observation: %w", o.deviceID, obs.Href(), err) diff --git a/coap-gateway/service/refreshCache.go b/coap-gateway/service/refreshCache.go index 338554213..39531da0e 100644 --- a/coap-gateway/service/refreshCache.go +++ b/coap-gateway/service/refreshCache.go @@ -2,7 +2,7 @@ package service import ( "context" - "fmt" + "errors" "sync" "github.com/plgd-dev/hub/v2/pkg/log" @@ -66,7 +66,7 @@ func refresh(ctx context.Context, providers map[string]*oauth2.PlgdProvider, que return nil, err } - return nil, fmt.Errorf("invalid token") + return nil, errors.New("invalid token") } func (r *RefreshCache) getFutureToken(refreshToken string) (*future.Future, future.SetFunc) { @@ -83,7 +83,7 @@ func (r *RefreshCache) getFutureToken(refreshToken string) (*future.Future, futu func (r *RefreshCache) Execute(ctx context.Context, providers map[string]*oauth2.PlgdProvider, queue *queue.Queue, refreshToken string, logger log.Logger) (*oauth2.Token, error) { if refreshToken == "" { - return nil, fmt.Errorf("invalid refreshToken") + return nil, errors.New("invalid refreshToken") } f, set := r.getFutureToken(refreshToken) diff --git a/coap-gateway/service/refreshToken.go b/coap-gateway/service/refreshToken.go index a818c795b..df1347b21 100644 --- a/coap-gateway/service/refreshToken.go +++ b/coap-gateway/service/refreshToken.go @@ -117,7 +117,7 @@ func getRefreshTokenDataFromClaims(ctx context.Context, client *session, accessT owner = req.UserID } if owner == "" { - return "", "", fmt.Errorf("cannot determine owner") + return "", "", errors.New("cannot determine owner") } return deviceID, owner, nil } @@ -149,7 +149,7 @@ func refreshTokenPostHandler(req *mux.Message, client *session) (*pool.Message, } if token.RefreshToken == "" { - return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, refreshToken.DeviceID, fmt.Errorf("refresh didn't return a refresh token"))) + return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, refreshToken.DeviceID, errors.New("refresh didn't return a refresh token"))) } deviceID, owner, err := getRefreshTokenDataFromClaims(req.Context(), client, token.AccessToken.String(), refreshToken) @@ -163,12 +163,12 @@ func refreshTokenPostHandler(req *mux.Message, client *session) (*pool.Message, return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, deviceID, fmt.Errorf("cannot check owning: %w", err))) } if !ok { - return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, deviceID, fmt.Errorf("device is not registered"))) + return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, deviceID, errors.New("device is not registered"))) } expire, ok := ValidUntil(token.Expiry) if !ok { - return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, deviceID, fmt.Errorf("expired access token"))) + return nil, statusErrorf(coapCodes.Unauthorized, "%w", fmt.Errorf(fmtErr, deviceID, errors.New("expired access token"))) } validUntil := pkgTime.Unix(0, expire) diff --git a/coap-gateway/service/resourceDirectory.go b/coap-gateway/service/resourceDirectory.go index a2b165ca3..61c6a8dcb 100644 --- a/coap-gateway/service/resourceDirectory.go +++ b/coap-gateway/service/resourceDirectory.go @@ -146,7 +146,7 @@ func observeResources(ctx context.Context, client *session, w wkRd, sequenceNumb return } if !ok { - x.client.Errorf("%w", x.observeError(x.w.DeviceID, fmt.Errorf("cannot get device observer"))) + x.client.Errorf("%w", x.observeError(x.w.DeviceID, errors.New("cannot get device observer"))) return } if errObs := obs.AddPublishedResources(x.ctx, x.publishedResources); errObs != nil { @@ -170,8 +170,8 @@ func resourceDirectoryPublishHandler(req *mux.Message, client *session) (*pool.M return nil, statusErrorf(coapCodes.BadRequest, "%w", err) } - if errCode, err := observeResources(req.Context(), client, w, req.Sequence()); err != nil { - return nil, statusErrorf(errCode, "%w", err) + if errCode, errO := observeResources(req.Context(), client, w, req.Sequence()); errO != nil { + return nil, statusErrorf(errCode, "%w", errO) } accept := coapconv.GetAccept(req.Options()) @@ -209,7 +209,7 @@ func parseUnpublishQueryString(queries []string) (deviceID string, instanceIDs [ } if deviceID == "" { - return "", nil, fmt.Errorf("deviceID not found") + return "", nil, errors.New("deviceID not found") } return diff --git a/coap-gateway/service/service.go b/coap-gateway/service/service.go index 4ce87f54e..7aa1a6247 100644 --- a/coap-gateway/service/service.go +++ b/coap-gateway/service/service.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "fmt" "net" "os" @@ -291,7 +292,7 @@ func New(ctx context.Context, config Config, fileWatcher *fsnotify.Watcher, logg if firstProvider == nil { nats.Close() - return nil, fmt.Errorf("device providers are empty") + return nil, errors.New("device providers are empty") } keyCache := jwt.NewKeyCache(firstProvider.OpenID.JWKSURL, firstProvider.HTTP()) @@ -357,7 +358,7 @@ func onUnprocessedRequestError(code coapCodes.Code) error { if code == coapCodes.Content { errMsg = "notification from client was dropped" } - return fmt.Errorf(errMsg) + return errors.New(errMsg) } func wantToCloseClientOnError(req *mux.Message) bool { @@ -391,7 +392,7 @@ func (s *Service) processCommandTask(req *mux.Message, client *session, span tra }() } default: - err := onUnprocessedRequestError(req.Code()) + err = onUnprocessedRequestError(req.Code()) client.logRequestResponse(req, nil, err) span.RecordError(err) span.SetStatus(otelCodes.Error, err.Error()) @@ -449,7 +450,7 @@ func executeCommand(s mux.ResponseWriter, req *mux.Message, server *Service, fnc if !ok { client = newSession(server, s.Conn(), "", time.Time{}) if req.Code() == coapCodes.Empty { - client.logRequestResponse(req, nil, fmt.Errorf("cannot handle command: client not found")) + client.logRequestResponse(req, nil, errors.New("cannot handle command: client not found")) client.Close() return } diff --git a/coap-gateway/service/session.go b/coap-gateway/service/session.go index 3fca51dde..6a8899d20 100644 --- a/coap-gateway/service/session.go +++ b/coap-gateway/service/session.go @@ -82,13 +82,13 @@ func (a *authorizationContext) GetJWTClaims() pkgJwt.Claims { func (a *authorizationContext) IsValid() error { if a == nil { - return fmt.Errorf("invalid authorization context") + return errors.New("invalid authorization context") } if a.AccessToken == "" { - return fmt.Errorf("invalid access token") + return errors.New("invalid access token") } if !a.Expire.IsZero() && time.Now().UnixNano() > a.Expire.UnixNano() { - return fmt.Errorf("token is expired") + return errors.New("token is expired") } return nil } @@ -837,7 +837,7 @@ func (c *session) unpublishResourceLinks(ctx context.Context, hrefs []string, in return resp.UnpublishedHrefs } if !ok { - logUnpublishError(fmt.Errorf("device observer not found")) + logUnpublishError(errors.New("device observer not found")) return resp.UnpublishedHrefs } observer.RemovePublishedResources(ctx, resp.UnpublishedHrefs) diff --git a/coap-gateway/service/signIn.go b/coap-gateway/service/signIn.go index 06ea77033..f49bf5d60 100644 --- a/coap-gateway/service/signIn.go +++ b/coap-gateway/service/signIn.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "time" @@ -33,13 +34,13 @@ type CoapSignInResp struct { // Check that all required request fields are set func (request CoapSignInReq) checkOAuthRequest() error { if request.DeviceID == "" { - return fmt.Errorf("invalid device id") + return errors.New("invalid device id") } if request.UserID == "" { - return fmt.Errorf("invalid user id") + return errors.New("invalid user id") } if request.AccessToken == "" { - return fmt.Errorf("invalid access token") + return errors.New("invalid access token") } return nil } @@ -217,7 +218,7 @@ func getSignInDataFromClaims(ctx context.Context, client *session, signIn CoapSi return "", time.Time{}, err } - if err := jwtClaims.ValidateOwnerClaim(client.server.config.APIs.COAP.Authorization.OwnerClaim, signIn.UserID); err != nil { + if err = jwtClaims.ValidateOwnerClaim(client.server.config.APIs.COAP.Authorization.OwnerClaim, signIn.UserID); err != nil { return "", time.Time{}, err } diff --git a/coap-gateway/service/signIn_test.go b/coap-gateway/service/signIn_test.go index bdc02be8d..ea3c67858 100644 --- a/coap-gateway/service/signIn_test.go +++ b/coap-gateway/service/signIn_test.go @@ -7,7 +7,6 @@ import ( "context" "crypto/tls" "errors" - "fmt" "strings" "testing" "time" @@ -159,7 +158,7 @@ func TestDontCreateObservationAfterRefreshTokenAndSignIn(t *testing.T) { observedPath[path] = struct{}{} h(w, r) } else { - require.NoError(t, fmt.Errorf("cannot observe the same resource twice")) + require.NoError(t, errors.New("cannot observe the same resource twice")) } }) if co == nil { @@ -320,6 +319,6 @@ func TestCertificateExpiration(t *testing.T) { // connection was closed by certificate expiration return case <-time.After(2 * duration): - require.NoError(t, fmt.Errorf("timeout")) + require.NoError(t, errors.New("timeout")) } } diff --git a/coap-gateway/service/signOff.go b/coap-gateway/service/signOff.go index b4f6409e8..7145b8512 100644 --- a/coap-gateway/service/signOff.go +++ b/coap-gateway/service/signOff.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "math" "net/url" @@ -74,13 +75,13 @@ func (s signOffData) updateSignOffDataFromAuthContext(client *session) signOffDa func (s signOffData) validateSignOffData() error { if s.deviceID == "" { - return fmt.Errorf("invalid device id") + return errors.New("invalid device id") } if s.userID == "" { - return fmt.Errorf("invalid user id") + return errors.New("invalid user id") } if s.accessToken == "" { - return fmt.Errorf("invalid access token") + return errors.New("invalid access token") } return nil } @@ -91,7 +92,7 @@ func getSignOffDataFromClaims(ctx context.Context, client *session, sod signOffD return "", err } - if err := jwtClaims.ValidateOwnerClaim(client.server.config.APIs.COAP.Authorization.OwnerClaim, sod.userID); err != nil { + if err = jwtClaims.ValidateOwnerClaim(client.server.config.APIs.COAP.Authorization.OwnerClaim, sod.userID); err != nil { return "", err } @@ -125,7 +126,7 @@ func signOffHandler(req *mux.Message, client *session) (*pool.Message, error) { err = client.blockSignOff.Acquire(ctx, math.MaxInt64) if err != nil { - return nil, statusErrorf(coapCodes.ServiceUnavailable, errFmtSignOff, fmt.Errorf("cannot acquire sign off lock: some commands are in progress")) + return nil, statusErrorf(coapCodes.ServiceUnavailable, errFmtSignOff, errors.New("cannot acquire sign off lock: some commands are in progress")) } defer client.blockSignOff.Release(math.MaxInt64) diff --git a/coap-gateway/service/signUp.go b/coap-gateway/service/signUp.go index d2a2c205f..a6c49f8f7 100644 --- a/coap-gateway/service/signUp.go +++ b/coap-gateway/service/signUp.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "github.com/plgd-dev/go-coap/v3/message" @@ -34,10 +35,10 @@ type CoapSignUpResponse struct { // Check that all required request fields are set func (request CoapSignUpRequest) checkOAuthRequest() error { if request.DeviceID == "" { - return fmt.Errorf("invalid device id") + return errors.New("invalid device id") } if request.AuthorizationCode == "" { - return fmt.Errorf("invalid authorization code") + return errors.New("invalid authorization code") } return nil } @@ -81,7 +82,7 @@ func getSignUpToken(ctx context.Context, client *session, signUp CoapSignUpReque return nil, statusErrorf(coapCodes.ServiceUnavailable, errFmtSignUP, err) } if token.RefreshToken == "" { - return nil, statusErrorf(coapCodes.Unauthorized, errFmtSignUP, fmt.Errorf("exchange didn't return a refresh token")) + return nil, statusErrorf(coapCodes.Unauthorized, errFmtSignUP, errors.New("exchange didn't return a refresh token")) } return token, nil } @@ -97,7 +98,7 @@ func getSignUpDataFromClaims(ctx context.Context, client *session, accessToken s return "", "", err } if owner == "" { - return "", "", fmt.Errorf("cannot determine owner") + return "", "", errors.New("cannot determine owner") } deviceID, err := client.server.VerifyAndResolveDeviceID(client.tlsDeviceID, signUp.DeviceID, claim) @@ -129,7 +130,7 @@ func signUpPostHandler(req *mux.Message, client *session) (*pool.Message, error) validUntil, ok := ValidUntil(token.Expiry) if !ok { - return nil, statusErrorf(coapCodes.Unauthorized, errFmtSignUP, fmt.Errorf("expired access token")) + return nil, statusErrorf(coapCodes.Unauthorized, errFmtSignUP, errors.New("expired access token")) } deviceID, owner, err := getSignUpDataFromClaims(req.Context(), client, token.AccessToken.String(), signUp) @@ -139,7 +140,7 @@ func signUpPostHandler(req *mux.Message, client *session) (*pool.Message, error) setDeviceIDToTracerSpan(req.Context(), deviceID) ctx := kitNetGrpc.CtxWithToken(req.Context(), token.AccessToken.String()) - if _, err := client.server.isClient.AddDevice(ctx, &pb.AddDeviceRequest{ + if _, err = client.server.isClient.AddDevice(ctx, &pb.AddDeviceRequest{ DeviceId: deviceID, }); err != nil { return nil, statusErrorf(coapconv.GrpcErr2CoapCode(err, coapconv.Update), errFmtSignUP, err) diff --git a/coap-gateway/service/utils_test.go b/coap-gateway/service/utils_test.go index 8aab65d32..eb7aad785 100644 --- a/coap-gateway/service/utils_test.go +++ b/coap-gateway/service/utils_test.go @@ -13,7 +13,6 @@ import ( "crypto/x509" "encoding/pem" "errors" - "fmt" "io" "os" "reflect" @@ -435,7 +434,7 @@ func testCoapDialWithHandler(t *testing.T, deviceID string, withTLS, identityCer InsecureSkipVerify: true, VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { if len(rawCerts) == 0 { - return fmt.Errorf("empty certificates chain") + return errors.New("empty certificates chain") } intermediateCAPool := x509.NewCertPool() certs := make([]*x509.Certificate, 0, len(rawCerts)) diff --git a/grpc-gateway/client/client.go b/grpc-gateway/client/client.go index d4959d88f..491410b68 100644 --- a/grpc-gateway/client/client.go +++ b/grpc-gateway/client/client.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "fmt" "sync" "time" @@ -44,7 +45,7 @@ func New(client pb.GrpcGatewayClient) *Client { // NewFromConfig constructs a new client client. For every call there is expected jwt token for grpc stored in context. func NewFromConfig(cfg *Config, tlsCfg *tls.Config) (*Client, error) { if cfg == nil || cfg.GatewayAddress == "" { - return nil, fmt.Errorf("missing client client config") + return nil, errors.New("missing client client config") } keepAlive := keepalive.ClientParameters{ diff --git a/grpc-gateway/client/client_test.go b/grpc-gateway/client/client_test.go index b487e5c38..94555f8c9 100644 --- a/grpc-gateway/client/client_test.go +++ b/grpc-gateway/client/client_test.go @@ -111,9 +111,6 @@ func (h *gatewayHandler) GetResources(_ *pb.GetResourcesRequest, srv pb.GrpcGate if err != nil { return err } - if err != nil { - return err - } return nil } diff --git a/grpc-gateway/client/createResource_test.go b/grpc-gateway/client/createResource_test.go index 28c4b0c97..aad482a4c 100644 --- a/grpc-gateway/client/createResource_test.go +++ b/grpc-gateway/client/createResource_test.go @@ -70,17 +70,17 @@ func TestClient_CreateResource(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() var got interface{} - err := c.CreateResource(ctx, tt.args.deviceID, tt.args.href, tt.args.data, &got) + err := c.CreateResource(runctx, tt.args.deviceID, tt.args.href, tt.args.data, &got) if tt.wantErr { require.Error(t, err) var grpcStatus interface { diff --git a/grpc-gateway/client/deleteResource_test.go b/grpc-gateway/client/deleteResource_test.go index 501bb2d65..9dbc20918 100644 --- a/grpc-gateway/client/deleteResource_test.go +++ b/grpc-gateway/client/deleteResource_test.go @@ -15,7 +15,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -87,7 +86,7 @@ func TestClientDeleteResource(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdownDevsim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevsim() @@ -95,10 +94,10 @@ func TestClientDeleteResource(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() var got interface{} - err := c.DeleteResource(ctx, tt.args.deviceID, tt.args.href, &got) + err := c.DeleteResource(runctx, tt.args.deviceID, tt.args.href, &got) if tt.wantErr { require.Error(t, err) return @@ -176,7 +175,7 @@ func TestClientBatchDeleteResource(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdown := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdown() @@ -184,10 +183,10 @@ func TestClientBatchDeleteResource(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() var got test.CollectionLinkRepresentations - err := c.DeleteResource(ctx, tt.args.deviceID, tt.args.href, &got, client.WithInterface(interfaces.OC_IF_B)) + err := c.DeleteResource(runctx, tt.args.deviceID, tt.args.href, &got, client.WithInterface(interfaces.OC_IF_B)) if tt.wantErr { require.Error(t, err) require.Equal(t, tt.wantErrCode, status.Convert(err).Code()) diff --git a/grpc-gateway/client/deviceSubscriptions.go b/grpc-gateway/client/deviceSubscriptions.go index 6ce78045e..e1579ae94 100644 --- a/grpc-gateway/client/deviceSubscriptions.go +++ b/grpc-gateway/client/deviceSubscriptions.go @@ -114,7 +114,7 @@ func (s *DeviceSubscriptions) doOp(ctx context.Context, req *pb.SubscribeToEvent return nil, fmt.Errorf("unexpected event %+v", ev) } if op.GetErrorStatus().GetCode() != pb.Event_OperationProcessed_ErrorStatus_OK { - return nil, fmt.Errorf(op.GetErrorStatus().GetMessage()) + return nil, errors.New(op.GetErrorStatus().GetMessage()) } return ev, nil } @@ -146,70 +146,70 @@ type deviceSub struct { func (s *deviceSub) HandleResourcePublished(ctx context.Context, val *events.ResourceLinksPublished) error { if s.ResourcePublishedHandler == nil { - return fmt.Errorf("ResourcePublishedHandler in not supported") + return errors.New("ResourcePublishedHandler in not supported") } return s.ResourcePublishedHandler.HandleResourcePublished(ctx, val) } func (s *deviceSub) HandleResourceUnpublished(ctx context.Context, val *events.ResourceLinksUnpublished) error { if s.ResourceUnpublishedHandler == nil { - return fmt.Errorf("ResourceUnpublishedHandler in not supported") + return errors.New("ResourceUnpublishedHandler in not supported") } return s.ResourceUnpublishedHandler.HandleResourceUnpublished(ctx, val) } func (s *deviceSub) HandleResourceUpdatePending(ctx context.Context, val *events.ResourceUpdatePending) error { if s.ResourceUpdatePendingHandler == nil { - return fmt.Errorf("ResourceUpdatePendingHandler in not supported") + return errors.New("ResourceUpdatePendingHandler in not supported") } return s.ResourceUpdatePendingHandler.HandleResourceUpdatePending(ctx, val) } func (s *deviceSub) HandleResourceUpdated(ctx context.Context, val *events.ResourceUpdated) error { if s.ResourceUpdatedHandler == nil { - return fmt.Errorf("ResourceUpdatedHandler in not supported") + return errors.New("ResourceUpdatedHandler in not supported") } return s.ResourceUpdatedHandler.HandleResourceUpdated(ctx, val) } func (s *deviceSub) HandleResourceRetrievePending(ctx context.Context, val *events.ResourceRetrievePending) error { if s.ResourceRetrievePendingHandler == nil { - return fmt.Errorf("ResourceRetrievePendingHandler in not supported") + return errors.New("ResourceRetrievePendingHandler in not supported") } return s.ResourceRetrievePendingHandler.HandleResourceRetrievePending(ctx, val) } func (s *deviceSub) HandleResourceRetrieved(ctx context.Context, val *events.ResourceRetrieved) error { if s.ResourceRetrievedHandler == nil { - return fmt.Errorf("ResourceRetrievedHandler in not supported") + return errors.New("ResourceRetrievedHandler in not supported") } return s.ResourceRetrievedHandler.HandleResourceRetrieved(ctx, val) } func (s *deviceSub) HandleResourceDeletePending(ctx context.Context, val *events.ResourceDeletePending) error { if s.ResourceDeletePendingHandler == nil { - return fmt.Errorf("ResourceDeletePendingHandler in not supported") + return errors.New("ResourceDeletePendingHandler in not supported") } return s.ResourceDeletePendingHandler.HandleResourceDeletePending(ctx, val) } func (s *deviceSub) HandleResourceDeleted(ctx context.Context, val *events.ResourceDeleted) error { if s.ResourceDeletedHandler == nil { - return fmt.Errorf("ResourceDeletedHandler in not supported") + return errors.New("ResourceDeletedHandler in not supported") } return s.ResourceDeletedHandler.HandleResourceDeleted(ctx, val) } func (s *deviceSub) HandleResourceCreatePending(ctx context.Context, val *events.ResourceCreatePending) error { if s.ResourceCreatePendingHandler == nil { - return fmt.Errorf("ResourceCreatePendingHandler in not supported") + return errors.New("ResourceCreatePendingHandler in not supported") } return s.ResourceCreatePendingHandler.HandleResourceCreatePending(ctx, val) } func (s *deviceSub) HandleResourceCreated(ctx context.Context, val *events.ResourceCreated) error { if s.ResourceCreatedHandler == nil { - return fmt.Errorf("ResourceCreatedHandler in not supported") + return errors.New("ResourceCreatedHandler in not supported") } return s.ResourceCreatedHandler.HandleResourceCreated(ctx, val) } @@ -229,7 +229,7 @@ func (s *Subcription) Cancel(ctx context.Context) error { func getSubscribeTypeAndHandler(closeErrorHandler SubscriptionHandler, handle interface{}) ([]pb.SubscribeToEvents_CreateSubscription_Event, *deviceSub, error) { if closeErrorHandler == nil { - return nil, nil, fmt.Errorf("invalid closeErrorHandler") + return nil, nil, errors.New("invalid closeErrorHandler") } var resourcePublishedHandler ResourcePublishedHandler var resourceUnpublishedHandler ResourceUnpublishedHandler @@ -285,7 +285,7 @@ func getSubscribeTypeAndHandler(closeErrorHandler SubscriptionHandler, handle in } if len(filterEvents) == 0 { - return nil, nil, fmt.Errorf("invalid handler - supported handlers: ResourcePublishedHandler, ResourceUnpublishedHandler, ResourceUpdatePendingHandler, ResourceUpdatedHandler, ResourceRetrievePendingHandler, ResourceRetrievedHandler, ResourceDeletePendingHandler, ResourceDeletedHandler, ResourceCreatePendingHandler, ResourceCreatedHandler") + return nil, nil, errors.New("invalid handler - supported handlers: ResourcePublishedHandler, ResourceUnpublishedHandler, ResourceUpdatePendingHandler, ResourceUpdatedHandler, ResourceRetrievePendingHandler, ResourceRetrievedHandler, ResourceDeletePendingHandler, ResourceDeletedHandler, ResourceCreatePendingHandler, ResourceCreatedHandler") } return filterEvents, &deviceSub{ @@ -306,7 +306,7 @@ func getSubscribeTypeAndHandler(closeErrorHandler SubscriptionHandler, handle in func (s *DeviceSubscriptions) Subscribe(ctx context.Context, deviceID string, closeErrorHandler SubscriptionHandler, handle interface{}) (*Subcription, error) { token, err := uuid.NewRandom() if err != nil { - return nil, fmt.Errorf("cannot generate token for subscribe") + return nil, errors.New("cannot generate token for subscribe") } filterEvents, eh, err := getSubscribeTypeAndHandler(closeErrorHandler, handle) @@ -336,7 +336,7 @@ func (s *DeviceSubscriptions) Subscribe(ctx context.Context, deviceID string, cl } cancelToken, err := uuid.NewRandom() if err != nil { - return fmt.Errorf("cannot generate token for cancellation") + return errors.New("cannot generate token for cancellation") } _, err = s.doOp(ctx, &pb.SubscribeToEvents{ Action: &pb.SubscribeToEvents_CancelSubscription_{ @@ -437,7 +437,7 @@ func (s *DeviceSubscriptions) handleSubscriptionCanceled(e *pb.Event) (processed ha.OnClose() return true } - ha.Error(fmt.Errorf(reason)) + ha.Error(errors.New(reason)) return true } diff --git a/grpc-gateway/client/deviceSubscriptions_test.go b/grpc-gateway/client/deviceSubscriptions_test.go index def1d9155..7750a7621 100644 --- a/grpc-gateway/client/deviceSubscriptions_test.go +++ b/grpc-gateway/client/deviceSubscriptions_test.go @@ -23,7 +23,6 @@ import ( pbTest "github.com/plgd-dev/hub/v2/test/pb" "github.com/plgd-dev/hub/v2/test/service" "github.com/plgd-dev/kit/v2/codec/cbor" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" ) @@ -85,8 +84,8 @@ func TestObserveDeviceResourcesRetrieve(t *testing.T) { c := NewTestClient(t) defer func() { - err := c.Close() - assert.NoError(t, err) + errC := c.Close() + require.NoError(t, errC) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() @@ -95,8 +94,8 @@ func TestObserveDeviceResourcesRetrieve(t *testing.T) { sub, err := c.NewDeviceSubscription(ctx, deviceID, h) require.NoError(t, err) defer func() { - wait, err := sub.Cancel() - require.NoError(t, err) + wait, errC := sub.Cancel() + require.NoError(t, errC) wait() }() @@ -180,8 +179,8 @@ func TestObserveDeviceResourcesUpdate(t *testing.T) { c := NewTestClient(t) defer func() { - err := c.Close() - assert.NoError(t, err) + errC := c.Close() + require.NoError(t, errC) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() @@ -193,8 +192,8 @@ func TestObserveDeviceResourcesUpdate(t *testing.T) { sub, err := c.NewDeviceSubscription(ctx, deviceID, h) require.NoError(t, err) defer func() { - wait, err := sub.Cancel() - require.NoError(t, err) + wait, errC := sub.Cancel() + require.NoError(t, errC) wait() }() @@ -208,8 +207,8 @@ func TestObserveDeviceResourcesUpdate(t *testing.T) { v := map[string]interface{}{ "value": true, } - d, err := cbor.Encode(v) - require.NoError(t, err) + d, errEnc := cbor.Encode(v) + require.NoError(t, errEnc) return d }(), }, @@ -308,8 +307,8 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { c := NewTestClient(t) defer func() { - err := c.Close() - assert.NoError(t, err) + errC := c.Close() + require.NoError(t, errC) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() @@ -318,8 +317,8 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { sub, err := c.NewDeviceSubscription(ctx, deviceID, h) require.NoError(t, err) defer func() { - wait, err := sub.Cancel() - require.NoError(t, err) + wait, errC := sub.Cancel() + require.NoError(t, errC) wait() }() diff --git a/grpc-gateway/client/devicesSubscription.go b/grpc-gateway/client/devicesSubscription.go index 5106cab38..2a02cfdec 100644 --- a/grpc-gateway/client/devicesSubscription.go +++ b/grpc-gateway/client/devicesSubscription.go @@ -69,7 +69,7 @@ func NewDevicesSubscription(ctx context.Context, closeErrorHandler SubscriptionH } if deviceMetadataUpdatedHandler == nil && deviceRegisteredHandler == nil && deviceUnregisteredHandler == nil { - return nil, fmt.Errorf("invalid handler - it's supports: DeviceMetadataUpdatedHandler, DeviceRegisteredHandler, DeviceUnregisteredHandler") + return nil, errors.New("invalid handler - it's supports: DeviceMetadataUpdatedHandler, DeviceRegisteredHandler, DeviceUnregisteredHandler") } client, err := New(gwClient).SubscribeToEventsWithCurrentState(ctx, time.Minute) if err != nil { @@ -95,7 +95,7 @@ func NewDevicesSubscription(ctx context.Context, closeErrorHandler SubscriptionH return nil, fmt.Errorf("unexpected event %+v", ev) } if op.GetErrorStatus().GetCode() != pb.Event_OperationProcessed_ErrorStatus_OK { - return nil, fmt.Errorf(op.GetErrorStatus().GetMessage()) + return nil, errors.New(op.GetErrorStatus().GetMessage()) } var wg sync.WaitGroup @@ -169,7 +169,7 @@ func (s *DevicesSubscription) handleCancel(cancel *pb.Event_SubscriptionCanceled s.closeErrorHandler.OnClose() return } - s.closeErrorHandler.Error(fmt.Errorf(reason)) + s.closeErrorHandler.Error(errors.New(reason)) } func (s *DevicesSubscription) runRecv() { diff --git a/grpc-gateway/client/generalMessageCodec.go b/grpc-gateway/client/generalMessageCodec.go index 3d32eda06..d83db6c64 100644 --- a/grpc-gateway/client/generalMessageCodec.go +++ b/grpc-gateway/client/generalMessageCodec.go @@ -1,6 +1,7 @@ package client import ( + "errors" "fmt" "io" @@ -55,7 +56,7 @@ func (GeneralMessageCodec) Decode(m *pool.Message, v interface{}) error { } if m.Body() == nil { - return fmt.Errorf("unexpected empty body") + return errors.New("unexpected empty body") } if err := decoder(m.Body(), v); err != nil { diff --git a/grpc-gateway/client/getDevice_test.go b/grpc-gateway/client/getDevice_test.go index f7c806819..525d5f517 100644 --- a/grpc-gateway/client/getDevice_test.go +++ b/grpc-gateway/client/getDevice_test.go @@ -16,7 +16,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -96,7 +95,7 @@ func TestClient_GetDevice(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) @@ -104,9 +103,9 @@ func TestClient_GetDevice(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - got, err := c.GetDevice(ctx, tt.args.deviceID) + got, err := c.GetDevice(runctx, tt.args.deviceID) if tt.wantErr { require.Error(t, err) return diff --git a/grpc-gateway/client/getDevices_test.go b/grpc-gateway/client/getDevices_test.go index 828b3917c..e92774ab1 100644 --- a/grpc-gateway/client/getDevices_test.go +++ b/grpc-gateway/client/getDevices_test.go @@ -11,7 +11,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -73,7 +72,7 @@ func TestClient_GetDevices(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) @@ -81,9 +80,9 @@ func TestClient_GetDevices(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - got, err := c.GetDevices(ctx, tt.args.opts...) + got, err := c.GetDevices(runctx, tt.args.opts...) if tt.wantErr { require.Error(t, err) return diff --git a/grpc-gateway/client/getResource_test.go b/grpc-gateway/client/getResource_test.go index b72f10e88..6131789f8 100644 --- a/grpc-gateway/client/getResource_test.go +++ b/grpc-gateway/client/getResource_test.go @@ -13,7 +13,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -104,7 +103,7 @@ func TestClientGetResource(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) @@ -112,10 +111,10 @@ func TestClientGetResource(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() var got interface{} - err := c.GetResource(ctx, tt.args.deviceID, tt.args.href, &got, tt.args.opts...) + err := c.GetResource(runctx, tt.args.deviceID, tt.args.href, &got, tt.args.opts...) if tt.wantErr { require.Error(t, err) return diff --git a/grpc-gateway/client/maintenance_test.go b/grpc-gateway/client/maintenance_test.go index 6404029a3..7256a3b0e 100644 --- a/grpc-gateway/client/maintenance_test.go +++ b/grpc-gateway/client/maintenance_test.go @@ -10,7 +10,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -54,7 +53,7 @@ func TestClientFactoryReset(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, _ = test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) @@ -108,7 +107,7 @@ func TestClientReboot(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() _, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) diff --git a/grpc-gateway/client/observeDeviceResources.go b/grpc-gateway/client/observeDeviceResources.go index 8bca2b728..8ea852174 100644 --- a/grpc-gateway/client/observeDeviceResources.go +++ b/grpc-gateway/client/observeDeviceResources.go @@ -46,7 +46,7 @@ func (c *Client) ObserveDeviceResources(ctx context.Context, deviceID string, ha sub, err := c.NewDeviceSubscription(ctx, deviceID, &deviceResourcesObservation{ h: handler, removeSubscription: func() { - if _, err := c.stopObservingDeviceResources(ID.String()); err != nil { + if _, err = c.stopObservingDeviceResources(ID.String()); err != nil { handler.Error(fmt.Errorf("failed to stop device('%v') resources observation: %w", ID.String(), err)) } }, diff --git a/grpc-gateway/client/observeDeviceResources_test.go b/grpc-gateway/client/observeDeviceResources_test.go index bdf19df89..9a05ff6a8 100644 --- a/grpc-gateway/client/observeDeviceResources_test.go +++ b/grpc-gateway/client/observeDeviceResources_test.go @@ -13,7 +13,6 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -28,7 +27,7 @@ func TestObserveDeviceResourcesPublish(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() diff --git a/grpc-gateway/client/observeDevices_test.go b/grpc-gateway/client/observeDevices_test.go index df9943bb0..6f32642a2 100644 --- a/grpc-gateway/client/observeDevices_test.go +++ b/grpc-gateway/client/observeDevices_test.go @@ -2,6 +2,7 @@ package client_test import ( "context" + "errors" "fmt" "testing" @@ -11,7 +12,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -26,7 +26,7 @@ func TestObserveDevices(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) @@ -43,7 +43,7 @@ func TestObserveDevices(t *testing.T) { select { case res = <-h.res: case <-ctx.Done(): - require.NoError(t, fmt.Errorf("timeout")) + require.NoError(t, errors.New("timeout")) } require.Equal(t, client.DevicesObservationEvent{ DeviceIDs: []string{deviceID}, @@ -53,7 +53,7 @@ func TestObserveDevices(t *testing.T) { select { case res = <-h.res: case <-ctx.Done(): - require.NoError(t, fmt.Errorf("timeout")) + require.NoError(t, errors.New("timeout")) } require.Equal(t, client.DevicesObservationEvent{ DeviceIDs: []string{deviceID}, @@ -64,7 +64,7 @@ func TestObserveDevices(t *testing.T) { select { case res = <-h.res: case <-ctx.Done(): - require.NoError(t, fmt.Errorf("timeout")) + require.NoError(t, errors.New("timeout")) } require.True(t, res.Event == client.DevicesObservationEvent_OFFLINE || res.Event == client.DevicesObservationEvent_UNREGISTERED) require.Equal(t, client.DevicesObservationEvent{ diff --git a/grpc-gateway/client/observeResource_test.go b/grpc-gateway/client/observeResource_test.go index a95e56221..cdeaca197 100644 --- a/grpc-gateway/client/observeResource_test.go +++ b/grpc-gateway/client/observeResource_test.go @@ -27,8 +27,8 @@ func TestObservingResource(t *testing.T) { c := NewTestClient(t) defer func() { - err := c.Close() - assert.NoError(t, err) + errC := c.Close() + require.NoError(t, errC) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() @@ -37,8 +37,8 @@ func TestObservingResource(t *testing.T) { id, err := c.ObserveResource(ctx, deviceID, configuration.ResourceURI, h) require.NoError(t, err) defer func() { - err := c.StopObservingResource(id) - require.NoError(t, err) + errS := c.StopObservingResource(id) + require.NoError(t, errS) }() name := "observe simulator" @@ -56,7 +56,7 @@ func TestObservingResource(t *testing.T) { require.Equal(t, name, d.Name) err = c.UpdateResource(ctx, deviceID, configuration.ResourceURI, map[string]interface{}{"n": test.TestDeviceName}, nil) - assert.NoError(t, err) + require.NoError(t, err) } func makeTestObservationHandler() *testObservationHandler { diff --git a/grpc-gateway/client/resourceSubscription.go b/grpc-gateway/client/resourceSubscription.go index 85e11bd56..abe5f9cc5 100644 --- a/grpc-gateway/client/resourceSubscription.go +++ b/grpc-gateway/client/resourceSubscription.go @@ -54,7 +54,7 @@ func NewResourceSubscription(ctx context.Context, resourceID *commands.ResourceI } if resourceContentChangedHandler == nil { - return nil, fmt.Errorf("invalid handler - it's supports: ResourceContentChangedHandler") + return nil, errors.New("invalid handler - it's supports: ResourceContentChangedHandler") } client, err := New(gwClient).SubscribeToEventsWithCurrentState(ctx, time.Minute) if err != nil { @@ -85,7 +85,7 @@ func NewResourceSubscription(ctx context.Context, resourceID *commands.ResourceI return nil, fmt.Errorf("unexpected event %+v", ev) } if op.GetErrorStatus().GetCode() != pb.Event_OperationProcessed_ErrorStatus_OK { - return nil, fmt.Errorf(op.GetErrorStatus().GetMessage()) + return nil, errors.New(op.GetErrorStatus().GetMessage()) } var wg sync.WaitGroup @@ -141,7 +141,7 @@ func (s *ResourceSubscription) handleCancel(cancel *pb.Event_SubscriptionCancele s.closeErrorHandler.OnClose() return } - s.closeErrorHandler.Error(fmt.Errorf(reason)) + s.closeErrorHandler.Error(errors.New(reason)) } func (s *ResourceSubscription) runRecv() { diff --git a/grpc-gateway/client/updateResource_test.go b/grpc-gateway/client/updateResource_test.go index b9161dd7a..f77e1e8f9 100644 --- a/grpc-gateway/client/updateResource_test.go +++ b/grpc-gateway/client/updateResource_test.go @@ -13,7 +13,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -97,18 +96,18 @@ func TestClientUpdateResource(t *testing.T) { c := NewTestClient(t) defer func() { - err := c.Close() - assert.NoError(t, err) + errC := c.Close() + require.NoError(t, errC) }() _, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + runctx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() var got interface{} - err := c.UpdateResource(ctx, tt.args.deviceID, tt.args.href, tt.args.data, &got, tt.args.opts...) + err := c.UpdateResource(runctx, tt.args.deviceID, tt.args.href, tt.args.data, &got, tt.args.opts...) if tt.wantErr { require.Error(t, err) return @@ -135,7 +134,7 @@ func TestUpdateConfigurationName(t *testing.T) { c := NewTestClient(t) defer func() { err := c.Close() - assert.NoError(t, err) + require.NoError(t, err) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c.GrpcGatewayClient(), deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) defer shutdownDevSim() @@ -145,7 +144,7 @@ func TestUpdateConfigurationName(t *testing.T) { for _, link := range test.GetAllBackendResourceLinks() { var got interface{} err := c.GetResource(ctx, devID, link.Href, &got) - assert.NoError(t, err) + require.NoError(t, err) resourceData[link.Href] = got } return resourceData diff --git a/grpc-gateway/pb/getResources.go b/grpc-gateway/pb/getResources.go index 7596ab70f..78869173c 100644 --- a/grpc-gateway/pb/getResources.go +++ b/grpc-gateway/pb/getResources.go @@ -2,7 +2,7 @@ package pb import ( "encoding/base64" - "fmt" + "errors" "net/url" "strings" @@ -16,7 +16,7 @@ func parseQuery(m url.Values, query string) (err error) { var key string key, query, _ = strings.Cut(query, "&") if strings.Contains(key, ";") { - err = fmt.Errorf("invalid semicolon separator in query") + err = errors.New("invalid semicolon separator in query") continue } if key == "" { diff --git a/grpc-gateway/pb/hubConfiguration.go b/grpc-gateway/pb/hubConfiguration.go index b2ecf7036..b53fbf4ab 100644 --- a/grpc-gateway/pb/hubConfiguration.go +++ b/grpc-gateway/pb/hubConfiguration.go @@ -1,18 +1,22 @@ package pb +func copyScopes(scopes []string) []string { + if len(scopes) == 0 { + return nil + } + sc := make([]string, len(scopes)) + copy(sc, scopes) + return sc +} + func (r *WebOAuthClient) Clone() *WebOAuthClient { if r == nil { return nil } - var scopes []string - if len(r.Scopes) > 0 { - scopes = make([]string, len(r.Scopes)) - copy(scopes, r.Scopes) - } return &WebOAuthClient{ - ClientId: r.ClientId, - Audience: r.Audience, - Scopes: scopes, + ClientId: r.GetClientId(), + Audience: r.GetAudience(), + Scopes: copyScopes(r.GetScopes()), } } @@ -20,15 +24,10 @@ func (r *DeviceOAuthClient) Clone() *DeviceOAuthClient { if r == nil { return nil } - var scopes []string - if len(r.Scopes) > 0 { - scopes = make([]string, len(r.Scopes)) - copy(scopes, r.Scopes) - } return &DeviceOAuthClient{ - ProviderName: r.ProviderName, - ClientId: r.ClientId, - Audience: r.Audience, - Scopes: scopes, + ProviderName: r.GetProviderName(), + ClientId: r.GetClientId(), + Audience: r.GetAudience(), + Scopes: copyScopes(r.GetScopes()), } } diff --git a/grpc-gateway/pb/hubConfiguration_test.go b/grpc-gateway/pb/hubConfiguration_test.go index 0f430f4a9..0287be823 100644 --- a/grpc-gateway/pb/hubConfiguration_test.go +++ b/grpc-gateway/pb/hubConfiguration_test.go @@ -14,7 +14,7 @@ func TestDeviceOAuthClient_Clone(t *testing.T) { } b := a.Clone() require.Equal(t, &a, b) - require.NotEqual(t, fmt.Sprintf("%p", &a.Scopes), fmt.Sprintf("%p", b.Scopes)) + require.NotEqual(t, fmt.Sprintf("%p", &a.Scopes), fmt.Sprintf("%p", b.GetScopes())) } func TestWebOAuthClient_Clone(t *testing.T) { @@ -24,5 +24,5 @@ func TestWebOAuthClient_Clone(t *testing.T) { } b := a.Clone() require.Equal(t, &a, b) - require.NotEqual(t, fmt.Sprintf("%p", &a.Scopes), fmt.Sprintf("%p", b.Scopes)) + require.NotEqual(t, fmt.Sprintf("%p", &a.Scopes), fmt.Sprintf("%p", b.GetScopes())) } diff --git a/grpc-gateway/service/cancelPendingCommands_test.go b/grpc-gateway/service/cancelPendingCommands_test.go index e1be47df2..8b98a010c 100644 --- a/grpc-gateway/service/cancelPendingCommands_test.go +++ b/grpc-gateway/service/cancelPendingCommands_test.go @@ -19,7 +19,7 @@ func TestRequestHandlerCancelPendingCommands(t *testing.T) { client, resourcePendings, _, shutdown := pbTest.InitPendingEvents(ctx, t) defer shutdown() - require.Equal(t, len(resourcePendings), 4) + require.Len(t, resourcePendings, 4) type args struct { req *pb.CancelPendingCommandsRequest diff --git a/grpc-gateway/service/cancelPendingMetadataUpdates_test.go b/grpc-gateway/service/cancelPendingMetadataUpdates_test.go index 26f776eac..c7b8446d8 100644 --- a/grpc-gateway/service/cancelPendingMetadataUpdates_test.go +++ b/grpc-gateway/service/cancelPendingMetadataUpdates_test.go @@ -19,7 +19,7 @@ func TestRequestHandlerCancelPendingMetadataUpdates(t *testing.T) { client, _, devicePendings, shutdown := pbTest.InitPendingEvents(ctx, t) defer shutdown() - require.Equal(t, len(devicePendings), 2) + require.Len(t, devicePendings, 2) type args struct { req *pb.CancelPendingMetadataUpdatesRequest diff --git a/grpc-gateway/service/getEvents_test.go b/grpc-gateway/service/getEvents_test.go index bdbb443a1..3209b14c1 100644 --- a/grpc-gateway/service/getEvents_test.go +++ b/grpc-gateway/service/getEvents_test.go @@ -63,7 +63,7 @@ func TestRequestHandlerGetEvents(t *testing.T) { defer shutdownDevSim() events := getAllEvents(ctx, t, c) - require.True(t, len(events) > 0) + require.NotEmpty(t, events) type args struct { req *pb.GetEventsRequest diff --git a/grpc-gateway/service/getResourceFromDevice_test.go b/grpc-gateway/service/getResourceFromDevice_test.go index 6fe91fd56..e5243fca1 100644 --- a/grpc-gateway/service/getResourceFromDevice_test.go +++ b/grpc-gateway/service/getResourceFromDevice_test.go @@ -179,8 +179,8 @@ func validateETags(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, de require.NoError(t, err) defer func() { - err := sdkClient.Close(context.Background()) - require.NoError(t, err) + errC := sdkClient.Close(context.Background()) + require.NoError(t, errC) }() // get resource from device via SDK @@ -201,7 +201,7 @@ func validateETags(ctx context.Context, t *testing.T, c pb.GrpcGatewayClient, de Etag: [][]byte{cfg2.GetData().GetEtag()}, }) require.NoError(t, err) - require.Equal(t, checkTag.GetData().GetStatus(), commands.Status_NOT_MODIFIED) + require.Equal(t, commands.Status_NOT_MODIFIED, checkTag.GetData().GetStatus()) require.Empty(t, checkTag.GetData().GetContent().GetData()) require.Empty(t, checkTag.GetData().GetContent().GetContentType()) require.Equal(t, int32(-1), checkTag.GetData().GetContent().GetCoapContentFormat()) diff --git a/grpc-gateway/service/subscribeToEvents_test.go b/grpc-gateway/service/subscribeToEvents_test.go index 8af9dc33b..4ea25baf1 100644 --- a/grpc-gateway/service/subscribeToEvents_test.go +++ b/grpc-gateway/service/subscribeToEvents_test.go @@ -35,7 +35,6 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" serviceTest "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/grpc" @@ -201,7 +200,7 @@ func TestRequestHandlerSubscribeToEvents(t *testing.T) { require.NoError(t, err) defer func() { errC := client.CloseSend() - assert.NoError(t, errC) + require.NoError(t, errC) }() var wg sync.WaitGroup wg.Add(1) @@ -209,11 +208,11 @@ func TestRequestHandlerSubscribeToEvents(t *testing.T) { defer wg.Done() var events []*pb.Event for range tt.want { - ev, err := client.Recv() - if errors.Is(err, io.EOF) { + ev, errR := client.Recv() + if errors.Is(errR, io.EOF) { break } - require.NoError(t, err) + require.NoError(t, errR) events = append(events, ev) } pbTest.CmpEvents(t, tt.want, events) @@ -663,9 +662,9 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { secureGWShutdown() createFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -675,27 +674,27 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { }, TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errC) } createFn(time.Millisecond * 500) // for test expired event createFn(0) retrieveFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, platform.ResourceURI), TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn(time.Millisecond * 500) // for test expired event retrieveFn(0) updateFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -705,32 +704,32 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { }, TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errU) } updateFn(time.Millisecond * 500) // for test expired event updateFn(0) deleteFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn(time.Millisecond * 500) // for test expired event deleteFn(0) updateDeviceMetadataFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(updateCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadataFn(time.Millisecond * 500) // for test expired event updateDeviceMetadataFn(0) // for test expired event diff --git a/grpc-gateway/service/updateDeviceMetadata_test.go b/grpc-gateway/service/updateDeviceMetadata_test.go index b9f3a26a3..d30978aaf 100644 --- a/grpc-gateway/service/updateDeviceMetadata_test.go +++ b/grpc-gateway/service/updateDeviceMetadata_test.go @@ -3,7 +3,7 @@ package service_test import ( "context" "crypto/tls" - "fmt" + "errors" "testing" "time" @@ -25,7 +25,6 @@ import ( "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -107,7 +106,7 @@ func (f *deviceMetadataUpdatedFilter) WaitForEvent(t time.Duration, correlationI return &ev, nil } case <-time.After(time.Until(deadline)): - return nil, fmt.Errorf("timeout") + return nil, errors.New("timeout") } } } @@ -157,10 +156,10 @@ func TestRequestHandlerUpdateDeviceMetadataTwinEnabled(t *testing.T) { obsDeviceMetadataUpdated, err := s.Subscribe(ctx, uuid.New().String(), utils.GetDeviceMetadataEventSubject("*", deviceID, (&events.DeviceMetadataUpdated{}).EventType()), deviceMetadataUpdatedFilter) require.NoError(t, err) defer func() { - err := obs.Close() - assert.NoError(t, err) - err = obsDeviceMetadataUpdated.Close() - assert.NoError(t, err) + errC := obs.Close() + require.NoError(t, errC) + errC = obsDeviceMetadataUpdated.Close() + require.NoError(t, errC) }() _, err = c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ @@ -176,12 +175,12 @@ func TestRequestHandlerUpdateDeviceMetadataTwinEnabled(t *testing.T) { }) require.NoError(t, err) require.False(t, ev.GetData().GetTwinEnabled()) - require.Equal(t, ev.GetData().GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.Equal(t, commands.TwinSynchronization_DISABLED, ev.GetData().GetTwinSynchronization().GetState()) deviceMetadataUpdated, err := deviceMetadataUpdatedFilter.WaitForEvent(time.Second, ev.GetData().GetAuditContext().GetCorrelationId()) require.NoError(t, err) require.False(t, deviceMetadataUpdated.GetTwinEnabled()) - require.Equal(t, deviceMetadataUpdated.GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.Equal(t, commands.TwinSynchronization_DISABLED, deviceMetadataUpdated.GetTwinSynchronization().GetState()) _, err = c.UpdateResource(ctx, &pb.UpdateResourceRequest{ ResourceInterface: interfaces.OC_IF_BASELINE, @@ -215,12 +214,12 @@ func TestRequestHandlerUpdateDeviceMetadataTwinEnabled(t *testing.T) { }) require.NoError(t, err) require.True(t, ev.GetData().GetTwinEnabled()) - require.NotEqual(t, ev.GetData().GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.NotEqual(t, commands.TwinSynchronization_DISABLED, ev.GetData().GetTwinSynchronization().GetState()) deviceMetadataUpdated, err = deviceMetadataUpdatedFilter.WaitForEvent(time.Second, ev.GetData().GetAuditContext().GetCorrelationId()) require.NoError(t, err) require.True(t, deviceMetadataUpdated.GetTwinEnabled()) - require.NotEqual(t, deviceMetadataUpdated.GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.NotEqual(t, commands.TwinSynchronization_DISABLED, deviceMetadataUpdated.GetTwinSynchronization().GetState()) for { deviceMetadataUpdated, err = deviceMetadataUpdatedFilter.WaitForEvent(time.Second, "") @@ -319,10 +318,10 @@ func TestRequestHandlerUpdateDeviceMetadataTwinForceSynchronization(t *testing.T obsDeviceMetadataUpdated, err := s.Subscribe(ctx, uuid.New().String(), utils.GetDeviceMetadataEventSubject("*", deviceID, (&events.DeviceMetadataUpdated{}).EventType()), deviceMetadataUpdatedFilter) require.NoError(t, err) defer func() { - err := obs.Close() - assert.NoError(t, err) - err = obsDeviceMetadataUpdated.Close() - assert.NoError(t, err) + errC := obs.Close() + require.NoError(t, errC) + errC = obsDeviceMetadataUpdated.Close() + require.NoError(t, errC) }() ev, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ @@ -336,7 +335,7 @@ func TestRequestHandlerUpdateDeviceMetadataTwinForceSynchronization(t *testing.T deviceMetadataUpdated, err := deviceMetadataUpdatedFilter.WaitForEvent(time.Second, ev.GetData().GetAuditContext().GetCorrelationId()) require.NoError(t, err) require.False(t, deviceMetadataUpdated.GetTwinEnabled()) - require.Equal(t, deviceMetadataUpdated.GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.Equal(t, commands.TwinSynchronization_DISABLED, deviceMetadataUpdated.GetTwinSynchronization().GetState()) require.Equal(t, int64(0), ev.GetData().GetTwinSynchronization().GetForceSynchronizationAt()) evResourceChanged := waitForResourceChanged(v, plgdtime.ResourceURI) @@ -355,7 +354,7 @@ func TestRequestHandlerUpdateDeviceMetadataTwinForceSynchronization(t *testing.T deviceMetadataUpdated, err = deviceMetadataUpdatedFilter.WaitForEvent(time.Second, ev.GetData().GetAuditContext().GetCorrelationId()) require.NoError(t, err) require.True(t, deviceMetadataUpdated.GetTwinEnabled()) - require.NotEqual(t, deviceMetadataUpdated.GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.NotEqual(t, commands.TwinSynchronization_DISABLED, deviceMetadataUpdated.GetTwinSynchronization().GetState()) require.Greater(t, ev.GetData().GetTwinSynchronization().GetForceSynchronizationAt(), checkTwin) checkTwin = ev.GetData().GetTwinSynchronization().GetForceSynchronizationAt() @@ -412,7 +411,7 @@ func TestRequestHandlerUpdateDeviceMetadataTwinForceSynchronization(t *testing.T deviceMetadataUpdated, err = deviceMetadataUpdatedFilter.WaitForEvent(time.Second, ev.GetData().GetAuditContext().GetCorrelationId()) require.NoError(t, err) require.True(t, deviceMetadataUpdated.GetTwinEnabled()) - require.NotEqual(t, deviceMetadataUpdated.GetTwinSynchronization().GetState(), commands.TwinSynchronization_DISABLED) + require.NotEqual(t, commands.TwinSynchronization_DISABLED, deviceMetadataUpdated.GetTwinSynchronization().GetState()) require.Greater(t, ev.GetData().GetTwinSynchronization().GetForceSynchronizationAt(), checkTwin) checkTwin = ev.GetData().GetTwinSynchronization().GetForceSynchronizationAt() diff --git a/grpc-gateway/service/updateResource_test.go b/grpc-gateway/service/updateResource_test.go index e8e4cf1dc..0b0480fce 100644 --- a/grpc-gateway/service/updateResource_test.go +++ b/grpc-gateway/service/updateResource_test.go @@ -25,7 +25,6 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -244,7 +243,7 @@ func TestRequestHandlerGetAfterUpdateResource(t *testing.T) { client, err := c.GetResources(ctx, &pb.GetResourcesRequest{ DeviceIdFilter: []string{devID}, }) - assert.NoError(t, err) + require.NoError(t, err) for { value, err := client.Recv() if errors.Is(err, io.EOF) { @@ -307,13 +306,13 @@ func TestRequestHandlerRunMultipleUpdateResource(t *testing.T) { func() { t.Logf("TestRequestHandlerMultipleUpdateResource:run %v\n", i) lightHref := test.TestResourceLightInstanceHref("1") - ctx, cancel := context.WithTimeout(ctx, time.Second*3) + subCtx, cancel := context.WithTimeout(ctx, time.Second*3) defer cancel() - subClient, err := c.SubscribeToEvents(ctx) + subClient, err := c.SubscribeToEvents(subCtx) require.NoError(t, err) defer func() { - err = subClient.CloseSend() - require.NoError(t, err) + errC := subClient.CloseSend() + require.NoError(t, errC) }() err = subClient.Send(&pb.SubscribeToEvents{Action: &pb.SubscribeToEvents_CreateSubscription_{ @@ -329,9 +328,9 @@ func TestRequestHandlerRunMultipleUpdateResource(t *testing.T) { require.NoError(t, err) ev, err := subClient.Recv() require.NoError(t, err) - require.Equal(t, ev.GetOperationProcessed().GetErrorStatus().GetCode(), pb.Event_OperationProcessed_ErrorStatus_OK) + require.Equal(t, pb.Event_OperationProcessed_ErrorStatus_OK, ev.GetOperationProcessed().GetErrorStatus().GetCode()) for j := 1; j >= 0; j-- { - _, err = c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, err = c.UpdateResource(subCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, lightHref), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -393,10 +392,10 @@ func TestRequestHandlerRunMultipleParallelUpdateResource(t *testing.T) { go func() { defer wg.Done() lightHref := test.TestResourceLightInstanceHref("1") - ctx, cancel := context.WithTimeout(ctx, timeout) + updateCtx, cancel := context.WithTimeout(ctx, timeout) defer cancel() for j := 1; j >= 0; j-- { - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, err := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, lightHref), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), diff --git a/grpc-gateway/subscription/subscription.go b/grpc-gateway/subscription/subscription.go index b86be8524..a830f3f22 100644 --- a/grpc-gateway/subscription/subscription.go +++ b/grpc-gateway/subscription/subscription.go @@ -1,6 +1,7 @@ package subscription import ( + "errors" "fmt" "github.com/google/uuid" @@ -129,13 +130,8 @@ func (s *Sub) Init(owner string, subCache *SubscriptionsCache) error { return nil } -func (s *Sub) isFilteredEvent(e *pb.Event, eventType FilterBitmask) (bool, error) { - if e == nil { - return false, fmt.Errorf("invalid event") - } - if !IsFilteredBit(s.filter, eventType) { - return false, nil - } +//nolint:gocyclo +func (s *Sub) isFilteredEventByType(e *pb.Event) (bool, error) { switch ev := e.GetType().(type) { case *pb.Event_DeviceRegistered_: return true, nil @@ -173,6 +169,16 @@ func (s *Sub) isFilteredEvent(e *pb.Event, eventType FilterBitmask) (bool, error return false, fmt.Errorf("unknown event type('%T')", e.GetType()) } +func (s *Sub) isFilteredEvent(e *pb.Event, eventType FilterBitmask) (bool, error) { + if e == nil { + return false, errors.New("invalid event") + } + if !IsFilteredBit(s.filter, eventType) { + return false, nil + } + return s.isFilteredEventByType(e) +} + func (s *Sub) ProcessEvent(e *pb.Event, eventType FilterBitmask) error { ok, err := s.isFilteredEvent(e, eventType) if err != nil { diff --git a/grpc-gateway/subscription/subscription_test.go b/grpc-gateway/subscription/subscription_test.go index 371360bbc..ac4a50619 100644 --- a/grpc-gateway/subscription/subscription_test.go +++ b/grpc-gateway/subscription/subscription_test.go @@ -217,8 +217,8 @@ func TestRequestHandlerSubscribeToEvents(t *testing.T) { err = s.Init(owner, subCache) require.NoError(t, err) defer func() { - err := s.Close() - require.NoError(t, err) + errC := s.Close() + require.NoError(t, errC) }() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, rdc, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) diff --git a/grpc-gateway/subscription/subscriptionsCache.go b/grpc-gateway/subscription/subscriptionsCache.go index d0fb8c673..997fbd6f3 100644 --- a/grpc-gateway/subscription/subscriptionsCache.go +++ b/grpc-gateway/subscription/subscriptionsCache.go @@ -391,13 +391,13 @@ func (c *SubscriptionsCache) Subscribe(subject string, onEvent SendEventWithType closeFunc = c.makeCloseFunc(subject, handlerID) } if s.subscription == nil { - err := s.subscribeLocked(subject, c.conn.Subscribe, func(msg *nats.Msg) { - if err := s.handleEvent(msg); err != nil { - c.errFunc(err) + errS := s.subscribeLocked(subject, c.conn.Subscribe, func(msg *nats.Msg) { + if errH := s.handleEvent(msg); errH != nil { + c.errFunc(errH) } }) - if err != nil { - return err + if errS != nil { + return errS } } return nil diff --git a/http-gateway/service/cancelPendingCommands_test.go b/http-gateway/service/cancelPendingCommands_test.go index 887e20bb9..362e955f3 100644 --- a/http-gateway/service/cancelPendingCommands_test.go +++ b/http-gateway/service/cancelPendingCommands_test.go @@ -32,7 +32,7 @@ func TestRequestHandlerCancelPendingCommands(t *testing.T) { _, resourcePendings, _, shutdown := pbTest.InitPendingEvents(ctx, t) defer shutdown() - require.Equal(t, len(resourcePendings), 4) + require.Len(t, resourcePendings, 4) type args struct { deviceID string @@ -109,7 +109,7 @@ func TestRequestHandlerCancelResourceCommand(t *testing.T) { _, resourcePendings, _, shutdown := pbTest.InitPendingEvents(ctx, t) defer shutdown() - require.Equal(t, len(resourcePendings), 4) + require.Len(t, resourcePendings, 4) type args struct { deviceID string diff --git a/http-gateway/service/cancelPendingMetadataUpdate_test.go b/http-gateway/service/cancelPendingMetadataUpdate_test.go index 7caf37295..945ede80c 100644 --- a/http-gateway/service/cancelPendingMetadataUpdate_test.go +++ b/http-gateway/service/cancelPendingMetadataUpdate_test.go @@ -22,7 +22,7 @@ func TestRequestHandlerCancelDeviceMetadataUpdate(t *testing.T) { _, _, devicePendings, shutdown := pbTest.InitPendingEvents(ctx, t) defer shutdown() - require.Equal(t, len(devicePendings), 2) + require.Len(t, devicePendings, 2) type args struct { deviceID string diff --git a/http-gateway/service/cancelPendingMetadataUpdates_test.go b/http-gateway/service/cancelPendingMetadataUpdates_test.go index 4e997c275..f21bf3f13 100644 --- a/http-gateway/service/cancelPendingMetadataUpdates_test.go +++ b/http-gateway/service/cancelPendingMetadataUpdates_test.go @@ -22,7 +22,7 @@ func TestRequestHandlerCancelPendingMetadataUpdates(t *testing.T) { _, _, devicePendings, shutdown := pbTest.InitPendingEvents(ctx, t) defer shutdown() - require.Equal(t, len(devicePendings), 2) + require.Len(t, devicePendings, 2) type args struct { deviceID string diff --git a/http-gateway/service/deleteDevice.go b/http-gateway/service/deleteDevice.go index 48b71c444..61748966e 100644 --- a/http-gateway/service/deleteDevice.go +++ b/http-gateway/service/deleteDevice.go @@ -2,35 +2,18 @@ package service import ( "net/http" - "net/http/httptest" - "github.com/google/go-querystring/query" - "github.com/gorilla/mux" "github.com/plgd-dev/hub/v2/http-gateway/serverMux" - "github.com/plgd-dev/hub/v2/http-gateway/uri" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "google.golang.org/grpc/codes" ) func (requestHandler *RequestHandler) deleteDevice(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - deviceID := vars[uri.DeviceIDKey] - type Options struct { - DeviceIDFilter []string `url:"deviceIdFilter"` - } - opt := Options{ - DeviceIDFilter: []string{deviceID}, - } - v, err := query.Values(opt) + deviceID, rec, err := requestHandler.serveDevicesRequest(r) if err != nil { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot delete device('%v'): %v", deviceID, err)) return } - r.URL.Path = uri.Devices - r.URL.RawQuery = v.Encode() - rec := httptest.NewRecorder() - requestHandler.mux.ServeHTTP(rec, r) - toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot delete device('%v'): %v", deviceID, err)) }, streamResponseKey) diff --git a/http-gateway/service/getDevice.go b/http-gateway/service/getDevice.go index 0cf9e3985..d9119ed00 100644 --- a/http-gateway/service/getDevice.go +++ b/http-gateway/service/getDevice.go @@ -25,7 +25,8 @@ func isNotModifiedResponse(result interface{}) bool { } data, ok := m["data"] if ok { - tmp, ok := data.(map[string]interface{}) + var tmp map[string]interface{} + tmp, ok = data.(map[string]interface{}) if !ok { return false } @@ -104,7 +105,7 @@ func toSimpleResponse(w http.ResponseWriter, rec *httptest.ResponseRecorder, wri writeSimpleResponse(w, rec, result, writeError) } -func (requestHandler *RequestHandler) getDevice(w http.ResponseWriter, r *http.Request) { +func (requestHandler *RequestHandler) serveDevicesRequest(r *http.Request) (string, *httptest.ResponseRecorder, error) { vars := mux.Vars(r) deviceID := vars[uri.DeviceIDKey] type Options struct { @@ -115,14 +116,21 @@ func (requestHandler *RequestHandler) getDevice(w http.ResponseWriter, r *http.R } v, err := query.Values(opt) if err != nil { - serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get device('%v'): %v", deviceID, err)) - return + return deviceID, nil, err } r.URL.Path = uri.Devices r.URL.RawQuery = v.Encode() rec := httptest.NewRecorder() requestHandler.mux.ServeHTTP(rec, r) + return deviceID, rec, nil +} +func (requestHandler *RequestHandler) getDevice(w http.ResponseWriter, r *http.Request) { + deviceID, rec, err := requestHandler.serveDevicesRequest(r) + if err != nil { + serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get device('%v'): %v", deviceID, err)) + return + } toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get device('%v'): %v", deviceID, err)) }, streamResponseKey) diff --git a/http-gateway/service/getDevicePendingCommands_test.go b/http-gateway/service/getDevicePendingCommands_test.go index 1f6d5281e..8bdef9aff 100644 --- a/http-gateway/service/getDevicePendingCommands_test.go +++ b/http-gateway/service/getDevicePendingCommands_test.go @@ -246,9 +246,9 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { secureGWShutdown() createFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -257,22 +257,22 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errC) } createFn() retrieveFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, platform.ResourceURI), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn() updateFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -281,26 +281,26 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errU) } updateFn() deleteFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn() updateDeviceMetadataFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(updateCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadataFn() diff --git a/http-gateway/service/getHubConfiguration.go b/http-gateway/service/getHubConfiguration.go index f63659c77..4bfb2e90f 100644 --- a/http-gateway/service/getHubConfiguration.go +++ b/http-gateway/service/getHubConfiguration.go @@ -78,7 +78,7 @@ func (requestHandler *RequestHandler) getHubConfiguration(w http.ResponseWriter, m := serverMux.NewJsonpbMarshaler() w.Header().Set(contentTypeHeaderKey, uri.ApplicationProtoJsonContentType) w.WriteHeader(http.StatusOK) - if err := m.NewEncoder(w).Encode(resp); err != nil { + if err = m.NewEncoder(w).Encode(resp); err != nil { log.Errorf("failed to write response: %v", err) } return diff --git a/http-gateway/service/getPendingCommands_test.go b/http-gateway/service/getPendingCommands_test.go index 9813962c4..ed07951f0 100644 --- a/http-gateway/service/getPendingCommands_test.go +++ b/http-gateway/service/getPendingCommands_test.go @@ -293,9 +293,9 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { secureGWShutdown() createFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -304,22 +304,22 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errC) } createFn() retrieveFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, platform.ResourceURI), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn() updateFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -328,26 +328,26 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errU) } updateFn() deleteFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn() updateDeviceMetadataFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(updateCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadataFn() diff --git a/http-gateway/service/getPendingMetadataUpdates_test.go b/http-gateway/service/getPendingMetadataUpdates_test.go index 263a3d1ea..33eef6ebb 100644 --- a/http-gateway/service/getPendingMetadataUpdates_test.go +++ b/http-gateway/service/getPendingMetadataUpdates_test.go @@ -108,9 +108,9 @@ func TestRequestHandlerGetPendingMetadataUpdates(t *testing.T) { secureGWShutdown() createFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -119,22 +119,22 @@ func TestRequestHandlerGetPendingMetadataUpdates(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errC) } createFn() retrieveFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, platform.ResourceURI), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn() updateFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -143,26 +143,26 @@ func TestRequestHandlerGetPendingMetadataUpdates(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errU) } updateFn() deleteFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn() updateDeviceMetadataFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(updateCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadataFn() diff --git a/http-gateway/service/getResourcePendingCommands_test.go b/http-gateway/service/getResourcePendingCommands_test.go index b06eb5d70..161cdffc1 100644 --- a/http-gateway/service/getResourcePendingCommands_test.go +++ b/http-gateway/service/getResourcePendingCommands_test.go @@ -161,9 +161,9 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { secureGWShutdown() createFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -172,22 +172,22 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errC) } createFn() retrieveFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, platform.ResourceURI), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn() updateFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -196,26 +196,26 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { }), }, }) - require.Error(t, err) + require.Error(t, errU) } updateFn() deleteFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn() updateDeviceMetadataFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(deleteCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadataFn() diff --git a/http-gateway/service/getResource_test.go b/http-gateway/service/getResource_test.go index 7512db5f1..242e14092 100644 --- a/http-gateway/service/getResource_test.go +++ b/http-gateway/service/getResource_test.go @@ -206,7 +206,7 @@ func TestRequestHandlerGetResource(t *testing.T) { values = append(values, value.GetData()) } if tt.wantCode != http.StatusOK { - require.Len(t, values, 0) + require.Empty(t, values) return } require.Len(t, values, 1) diff --git a/http-gateway/service/getWebConfiguration_test.go b/http-gateway/service/getWebConfiguration_test.go index c65d35e9f..2bf1019bf 100644 --- a/http-gateway/service/getWebConfiguration_test.go +++ b/http-gateway/service/getWebConfiguration_test.go @@ -159,7 +159,7 @@ func TestRequestHandlerGetWebDirectory(t *testing.T) { want, err := os.ReadFile(tt.wantFile) require.NoError(t, err) - require.Equal(t, got, want) + require.Equal(t, want, got) }) } } diff --git a/http-gateway/service/service.go b/http-gateway/service/service.go index 47d9344b8..b18d9ffee 100644 --- a/http-gateway/service/service.go +++ b/http-gateway/service/service.go @@ -79,9 +79,9 @@ func New(ctx context.Context, config Config, fileWatcher *fsnotify.Watcher, logg return nil, fmt.Errorf("cannot connect to grpc-gateway: %w", err) } s.AddCloseFunc(func() { - err := grpcConn.Close() - if err != nil { - logger.Errorf("error occurs during close connection to grpc-gateway: %v", err) + errC := grpcConn.Close() + if errC != nil { + logger.Errorf("error occurs during close connection to grpc-gateway: %v", errC) } }) grpcClient := pb.NewGrpcGatewayClient(grpcConn.GRPC()) diff --git a/http-gateway/service/subscribeToEvents_test.go b/http-gateway/service/subscribeToEvents_test.go index 7d9600db2..db3118b19 100644 --- a/http-gateway/service/subscribeToEvents_test.go +++ b/http-gateway/service/subscribeToEvents_test.go @@ -160,30 +160,30 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource send := func(req *pb.SubscribeToEvents) error { marshaler := runtime.JSONPb{} - data, err := marshaler.Marshal(req) - require.NoError(t, err) + data, errM := marshaler.Marshal(req) + require.NoError(t, errM) return wsConn.WriteMessage(websocket.TextMessage, data) } sendBackwardResourceIDFilter := func(req *pb.SubscribeToEvents, resourceIDFilter []string) error { marshaler := runtime.JSONPb{} - data, err := marshaler.Marshal(req) - require.NoError(t, err) + data, errM := marshaler.Marshal(req) + require.NoError(t, errM) - newData, err := sjson.Delete(string(data), "createSubscription.resourceIdFilter") - require.NoError(t, err) - newData, err = sjson.Set(newData, "createSubscription.resourceIdFilter", resourceIDFilter) - require.NoError(t, err) + newData, errM := sjson.Delete(string(data), "createSubscription.resourceIdFilter") + require.NoError(t, errM) + newData, errM = sjson.Set(newData, "createSubscription.resourceIdFilter", resourceIDFilter) + require.NoError(t, errM) return wsConn.WriteMessage(websocket.TextMessage, []byte(newData)) } recv := func() (*pb.Event, error) { - _, reader, err := wsConn.NextReader() - if err != nil { - return nil, err + _, reader, errM := wsConn.NextReader() + if errM != nil { + return nil, errM } var event pb.Event - err = httpgwTest.Unmarshal(http.StatusOK, reader, &event) - return &event, err + errM = httpgwTest.Unmarshal(http.StatusOK, reader, &event) + return &event, errM } createResourceSub := &pb.SubscribeToEvents{ CorrelationId: "testToken", diff --git a/http-gateway/service/updateDeviceMetadata_test.go b/http-gateway/service/updateDeviceMetadata_test.go index 9566dad49..aa4123696 100644 --- a/http-gateway/service/updateDeviceMetadata_test.go +++ b/http-gateway/service/updateDeviceMetadata_test.go @@ -163,8 +163,8 @@ func TestRequestHandlerUpdateDeviceMetadata(t *testing.T) { }() updateDeviceTwinSynchronization := func(in *pb.UpdateDeviceMetadataRequest) error { - data, err := protojson.Marshal(in) - require.NoError(t, err) + data, errM := protojson.Marshal(in) + require.NoError(t, errM) rb := httpgwTest.NewRequest(http.MethodPut, uri.DeviceMetadata, bytes.NewReader(data)).AuthToken(token).DeviceId(deviceID) resp := httpgwTest.HTTPDo(t, rb.Build()) @@ -173,8 +173,8 @@ func TestRequestHandlerUpdateDeviceMetadata(t *testing.T) { }(resp) var got pb.UpdateDeviceMetadataResponse - err = httpgwTest.Unmarshal(resp.StatusCode, resp.Body, &got) - return err + errM = httpgwTest.Unmarshal(resp.StatusCode, resp.Body, &got) + return errM } err = updateDeviceTwinSynchronization(&pb.UpdateDeviceMetadataRequest{ diff --git a/http-gateway/test/http.go b/http-gateway/test/http.go index 8164c3055..466a248a0 100644 --- a/http-gateway/test/http.go +++ b/http-gateway/test/http.go @@ -55,7 +55,7 @@ func (c *RequestBuilder) DeviceId(deviceID string) *RequestBuilder { } func (c *RequestBuilder) Twin(v bool) *RequestBuilder { - c.AddQuery(uri.TwinQueryKey, fmt.Sprintf("%v", v)) + c.AddQuery(uri.TwinQueryKey, strconv.FormatBool(v)) return c } @@ -63,7 +63,7 @@ func (c *RequestBuilder) Timestamp(v time.Time) *RequestBuilder { if v.IsZero() { return c } - c.AddQuery(uri.TimestampFilterQueryKey, fmt.Sprintf("%v", v.UnixNano())) + c.AddQuery(uri.TimestampFilterQueryKey, strconv.FormatInt(v.UnixNano(), 10)) return c } @@ -102,7 +102,7 @@ func (c *RequestBuilder) ResourceHref(resourceHref string) *RequestBuilder { } func (c *RequestBuilder) AuthToken(token string) *RequestBuilder { - c.header["Authorization"] = fmt.Sprintf("bearer %s", token) + c.header["Authorization"] = "bearer " + token return c } diff --git a/http-gateway/test/unmarshalProto.go b/http-gateway/test/unmarshalProto.go index 44e7a49a9..0d4318661 100644 --- a/http-gateway/test/unmarshalProto.go +++ b/http-gateway/test/unmarshalProto.go @@ -51,7 +51,7 @@ func Unmarshal(code int, input io.Reader, v protoreflect.ProtoMessage) error { u := protojson.UnmarshalOptions{ DiscardUnknown: true, } - err := u.Unmarshal(data, v) + err = u.Unmarshal(data, v) if err != nil { return err } diff --git a/identity-store/client/ownerCache.go b/identity-store/client/ownerCache.go index 0b6235093..634b1337c 100644 --- a/identity-store/client/ownerCache.go +++ b/identity-store/client/ownerCache.go @@ -222,13 +222,13 @@ func (c *OwnerCache) Subscribe(owner string, onEvent func(e *events.Event)) (fun closeFunc = c.makeCloseFunc(owner, handlerID) } if s.subscription == nil { - err := s.subscribeLocked(owner, c.conn.Subscribe, func(msg *nats.Msg) { + errS := s.subscribeLocked(owner, c.conn.Subscribe, func(msg *nats.Msg) { if errH := s.Handle(msg); errH != nil { c.errFunc(errH) } }) - if err != nil { - return err + if errS != nil { + return errS } } return nil diff --git a/identity-store/client/ownerCache_test.go b/identity-store/client/ownerCache_test.go index a50ed3694..1da485754 100644 --- a/identity-store/client/ownerCache_test.go +++ b/identity-store/client/ownerCache_test.go @@ -127,7 +127,7 @@ func TestOwnerCacheSubscribe(t *testing.T) { time.Sleep(time.Millisecond * 100) for _, d := range devices[:2] { - _, err := c.AddDevice(ctx, &pb.AddDeviceRequest{DeviceId: d}) + _, err = c.AddDevice(ctx, &pb.AddDeviceRequest{DeviceId: d}) require.NoError(t, err) } time.Sleep(time.Millisecond * 100) diff --git a/identity-store/persistence/cqldb/persist.go b/identity-store/persistence/cqldb/persist.go index abc2f97b3..c4875c8e2 100644 --- a/identity-store/persistence/cqldb/persist.go +++ b/identity-store/persistence/cqldb/persist.go @@ -137,7 +137,7 @@ func (i *iterator) Close() { func (p *PersistenceTx) Persist(d *persistence.AuthorizedDevice) error { if d == nil { - return fmt.Errorf("cannot persist nil device") + return errors.New("cannot persist nil device") } if p.err != nil { return p.err diff --git a/identity-store/persistence/cqldb/persist_test.go b/identity-store/persistence/cqldb/persist_test.go index 713d10712..4aefa1071 100644 --- a/identity-store/persistence/cqldb/persist_test.go +++ b/identity-store/persistence/cqldb/persist_test.go @@ -11,7 +11,6 @@ import ( "github.com/plgd-dev/hub/v2/pkg/log" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" ) @@ -28,7 +27,7 @@ func newTestPersistence(t *testing.T) *cqldb.Store { Embedded: cfg, Table: "testDeviceOwnership", }, fileWatcher, log.Get(), noop.NewTracerProvider()) - assert.NoError(t, err) + require.NoError(t, err) p.AddCloseFunc(func() { errC := fileWatcher.Close() @@ -98,12 +97,12 @@ func TestPersistenceTxRetrieve(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, ok, err := tx.Retrieve(tt.deviceID, tt.owner) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tt.want, got) - assert.Equal(t, tt.wantOk, ok) + require.Error(t, err) + return } + require.NoError(t, err) + require.Equal(t, tt.want, got) + require.Equal(t, tt.wantOk, ok) }) } } @@ -158,12 +157,12 @@ func TestPersistenceTxRetrieveByDevice(t *testing.T) { t.Run(tt.name, func(t *testing.T) { got, ok, err := tx.RetrieveByDevice(tt.deviceID) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) - assert.Equal(t, tt.want, got) - assert.Equal(t, tt.wantOk, ok) + require.Error(t, err) + return } + require.NoError(t, err) + require.Equal(t, tt.want, got) + require.Equal(t, tt.wantOk, ok) }) } } @@ -221,8 +220,8 @@ func TestPersistenceTxRetrieveByOwner(t *testing.T) { iter := tx.RetrieveByOwner(tt.owner) defer iter.Close() func() { - err := iter.Err() - require.NoError(t, err) + errC := iter.Err() + require.NoError(t, errC) }() var retrievedDevices []*persistence.AuthorizedDevice @@ -235,7 +234,7 @@ func TestPersistenceTxRetrieveByOwner(t *testing.T) { retrievedDevices = append(retrievedDevices, &device) } - assert.Equal(t, tt.devices, retrievedDevices) + require.Equal(t, tt.devices, retrievedDevices) }) } } @@ -322,10 +321,10 @@ func TestPersistenceTxPersist(t *testing.T) { } err = tx.Persist(tt.device) if tt.wantErr { - assert.Error(t, err) - } else { - assert.NoError(t, err) + require.Error(t, err) + return } + require.NoError(t, err) }) } } diff --git a/identity-store/persistence/mongodb/persist.go b/identity-store/persistence/mongodb/persist.go index b968151e0..893562f6c 100644 --- a/identity-store/persistence/mongodb/persist.go +++ b/identity-store/persistence/mongodb/persist.go @@ -211,7 +211,7 @@ func (p *PersistenceTx) Delete(deviceID, userID string) error { return err } if res.DeletedCount == 0 { - return fmt.Errorf("not found") + return errors.New("not found") } if err := p.tx.CommitTransaction(p.ctx); err != nil { return fmt.Errorf("cannot commit transaction: %w", err) diff --git a/identity-store/service/getDevices_test.go b/identity-store/service/getDevices_test.go index 928fd73c5..31506a12c 100644 --- a/identity-store/service/getDevices_test.go +++ b/identity-store/service/getDevices_test.go @@ -9,7 +9,6 @@ import ( kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" ) @@ -27,13 +26,13 @@ func TestUserDevicesList(t *testing.T) { }() persistDevice(t, s.service.persistence, newTestDevice()) err := s.service.GetDevices(newGetDevicesRequest(), srv) - assert.NoError(t, err) + require.NoError(t, err) r := map[string]*pb.Device{ testDeviceID: { DeviceId: testDeviceID, }, } - assert.Equal(t, r, srv.resourceValues) + require.Equal(t, r, srv.resourceValues) } func TestListingMoreDevices(t *testing.T) { @@ -53,8 +52,7 @@ func TestListingMoreDevices(t *testing.T) { persistDevice(t, s.service.persistence, d) err := s.service.GetDevices(newGetDevicesRequest(), srv) - assert := assert.New(t) - assert.NoError(err) + require.NoError(t, err) r := map[string]*pb.Device{ testDeviceID: { DeviceId: testDeviceID, @@ -63,7 +61,7 @@ func TestListingMoreDevices(t *testing.T) { DeviceId: d.DeviceID, }, } - assert.Equal(r, srv.resourceValues) + require.Equal(t, r, srv.resourceValues) } func newGetDevicesRequest() *pb.GetDevicesRequest { diff --git a/identity-store/service/service_test.go b/identity-store/service/service_test.go index 78d96afff..fdd330898 100644 --- a/identity-store/service/service_test.go +++ b/identity-store/service/service_test.go @@ -15,7 +15,6 @@ import ( natsTest "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventbus/nats/test" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" ) @@ -113,5 +112,5 @@ func persistDevice(t *testing.T, p Persistence, d *persistence.AuthorizedDevice) tx := p.NewTransaction(context.Background()) defer tx.Close() err := tx.Persist(d) - assert.Nil(t, err) + require.NoError(t, err) } diff --git a/pkg/config/database/config.go b/pkg/config/database/config.go index c0eb846bb..f1ecaa699 100644 --- a/pkg/config/database/config.go +++ b/pkg/config/database/config.go @@ -1,6 +1,7 @@ package database import ( + "errors" "fmt" "reflect" "strings" @@ -31,7 +32,7 @@ func (c *Config[MongoConfig, CQLDBConfig]) Validate() error { switch c.Use.ToLower() { case MongoDB.ToLower(): if reflect.ValueOf(c.MongoDB).Kind() == reflect.Ptr && reflect.ValueOf(c.MongoDB).IsNil() { - return fmt.Errorf("mongoDB - is empty") + return errors.New("mongoDB - is empty") } if err := c.MongoDB.Validate(); err != nil { return fmt.Errorf("mongoDB.%w", err) @@ -39,7 +40,7 @@ func (c *Config[MongoConfig, CQLDBConfig]) Validate() error { c.Use = "mongoDB" case CqlDB.ToLower(): if reflect.ValueOf(c.CqlDB).Kind() == reflect.Ptr && reflect.ValueOf(c.CqlDB).IsNil() { - return fmt.Errorf("cqlDB - is empty") + return errors.New("cqlDB - is empty") } if err := c.CqlDB.Validate(); err != nil { return fmt.Errorf("cqlDB.%w", err) diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index ced4caf0d..0a453ef96 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -3,12 +3,12 @@ package log import ( "crypto/x509" "crypto/x509/pkix" - "fmt" + "errors" "testing" "time" pkgX509 "github.com/plgd-dev/hub/v2/pkg/security/x509" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNew(t *testing.T) { @@ -17,34 +17,34 @@ func TestNew(t *testing.T) { config := MakeDefaultConfig() Setup(config) - assert.NotPanics(t, func() { Debug(testStr) }) - assert.NotPanics(t, func() { Info(testStr) }) - assert.NotPanics(t, func() { + require.NotPanics(t, func() { Debug(testStr) }) + require.NotPanics(t, func() { Info(testStr) }) + require.NotPanics(t, func() { Info(testStr, pkgX509.NewError([][]*x509.Certificate{{&x509.Certificate{ Subject: pkix.Name{ CommonName: "certName", }, - }}}, fmt.Errorf(" x509"))) + }}}, errors.New(" x509"))) }) - assert.NotPanics(t, func() { Warn(testStr) }) - assert.NotPanics(t, func() { Error(testStr) }) + require.NotPanics(t, func() { Warn(testStr) }) + require.NotPanics(t, func() { Error(testStr) }) - assert.NotPanics(t, func() { Debugf(testStr) }) - assert.NotPanics(t, func() { Infof(testStr) }) - assert.NotPanics(t, func() { Warnf(testStr) }) - assert.NotPanics(t, func() { Errorf(testStr) }) + require.NotPanics(t, func() { Debugf(testStr) }) + require.NotPanics(t, func() { Infof(testStr) }) + require.NotPanics(t, func() { Warnf(testStr) }) + require.NotPanics(t, func() { Errorf(testStr) }) timesStr := []string{"rfc3339nano", "rfc3339", "iso8601", "millis", "nanos", ""} for _, str := range timesStr { var v TimeEncoderWrapper - assert.NoError(t, v.UnmarshalText([]byte(str))) + require.NoError(t, v.UnmarshalText([]byte(str))) text, err := v.MarshalText() - assert.NoError(t, err) - assert.Equal(t, str, string(text)) + require.NoError(t, err) + require.Equal(t, str, string(text)) } - assert.Equal(t, float32(1000), DurationToMilliseconds(time.Second)) - assert.Error(t, LogAndReturnError(fmt.Errorf(testStr))) + require.InEpsilon(t, float32(1000), DurationToMilliseconds(time.Second), 0.1) + require.Error(t, LogAndReturnError(errors.New(testStr))) cfg := MakeDefaultConfig() - assert.NoError(t, cfg.Validate()) + require.NoError(t, cfg.Validate()) } diff --git a/pkg/net/coap/getResourceLinks.go b/pkg/net/coap/getResourceLinks.go index 3e1dfa7fe..770a8bb63 100644 --- a/pkg/net/coap/getResourceLinks.go +++ b/pkg/net/coap/getResourceLinks.go @@ -2,6 +2,7 @@ package coap import ( "context" + "errors" "fmt" "net" @@ -36,7 +37,7 @@ func GetResourceLinks(ctx context.Context, coapConn ClientConn, href string, opt data := msg.Body() if data == nil { - return schema.ResourceLinks{}, 0, fmt.Errorf("empty response") + return schema.ResourceLinks{}, 0, errors.New("empty response") } var links schema.ResourceLinks @@ -69,7 +70,7 @@ func GetEndpointsFromResourceType(ctx context.Context, coapConn ClientConn, reso return nil, err } if len(links) == 0 { - return nil, fmt.Errorf("no local endpoints found") + return nil, errors.New("no local endpoints found") } endpoints := make([]string, 0, 8) for _, ep := range links[0].Endpoints { diff --git a/pkg/net/coap/service/config.go b/pkg/net/coap/service/config.go index 59eeee3ac..eeae3dfd4 100644 --- a/pkg/net/coap/service/config.go +++ b/pkg/net/coap/service/config.go @@ -1,6 +1,7 @@ package service import ( + "errors" "fmt" "strings" "time" @@ -48,7 +49,7 @@ func (c *Config) validateKeepAliveAndInactivityMonitor() error { } } if c.KeepAlive == nil && c.InactivityMonitor == nil { - return fmt.Errorf("keepAlive or inactivityMonitor must be set") + return errors.New("keepAlive or inactivityMonitor must be set") } return nil } diff --git a/pkg/net/coap/service/service_test.go b/pkg/net/coap/service/service_test.go index 8d46952f6..f48269fd5 100644 --- a/pkg/net/coap/service/service_test.go +++ b/pkg/net/coap/service/service_test.go @@ -107,8 +107,8 @@ func TestNew(t *testing.T) { } require.NoError(t, err) go func() { - err := got.Serve() - require.NoError(t, err) + errS := got.Serve() + require.NoError(t, errS) }() err = got.Close() require.NoError(t, err) @@ -152,8 +152,8 @@ func TestOnClientInactivityTCP(t *testing.T) { })) require.NoError(t, err) go func() { - err := got.Serve() - require.NoError(t, err) + errS := got.Serve() + require.NoError(t, errS) }() time.Sleep(time.Second * 3) @@ -217,8 +217,8 @@ func TestOnClientInactivityUDP(t *testing.T) { })) require.NoError(t, err) go func() { - err := got.Serve() - require.NoError(t, err) + errS := got.Serve() + require.NoError(t, errS) }() time.Sleep(time.Second * 3) @@ -278,8 +278,8 @@ func TestOnClientInactivityCustomTCP(t *testing.T) { closeChan := make(chan struct{}, 2) got, err := New(ctx, cfg, router, fileWatcher, logger, WithOnInactivityConnection(func(conn mux.Conn) { numInactiveClients.Inc() - err := conn.Close() - require.NoError(t, err) + errC := conn.Close() + require.NoError(t, errC) }), WithOnNewConnection(func(conn mux.Conn) { conn.AddOnClose(func() { closeChan <- struct{}{} @@ -287,8 +287,8 @@ func TestOnClientInactivityCustomTCP(t *testing.T) { })) require.NoError(t, err) go func() { - err := got.Serve() - require.NoError(t, err) + errS := got.Serve() + require.NoError(t, errS) }() time.Sleep(time.Second * 3) @@ -349,8 +349,8 @@ func TestOnClientInactivityCustomUDP(t *testing.T) { closeChan := make(chan struct{}, 2) got, err := New(ctx, cfg, router, fileWatcher, logger, WithOnInactivityConnection(func(conn mux.Conn) { numInactiveClients.Inc() - err := conn.Close() - require.NoError(t, err) + errC := conn.Close() + require.NoError(t, errC) }), WithOnNewConnection(func(conn mux.Conn) { conn.AddOnClose(func() { closeChan <- struct{}{} @@ -358,8 +358,8 @@ func TestOnClientInactivityCustomUDP(t *testing.T) { })) require.NoError(t, err) go func() { - err := got.Serve() - require.NoError(t, err) + errS := got.Serve() + require.NoError(t, errS) }() time.Sleep(time.Second * 3) diff --git a/pkg/net/grpc/error_test.go b/pkg/net/grpc/error_test.go index 50cbfc77c..8366fd3c1 100644 --- a/pkg/net/grpc/error_test.go +++ b/pkg/net/grpc/error_test.go @@ -97,7 +97,7 @@ func TestForwardErrorf(t *testing.T) { s, ok := status.FromError(err) require.True(t, ok) assert.Equal(t, tt.wantCode, s.Code()) - test.CheckProtobufs(t, tt.wantDetails, s.Details(), test.AssertToCheckFunc(assert.Equal)) + test.CheckProtobufs(t, tt.wantDetails, s.Details(), test.RequireToCheckFunc(require.Equal)) assert.Equal(t, tt.wantMessage, s.Message()) }) } diff --git a/pkg/net/http/convertError_test.go b/pkg/net/http/convertError_test.go index b1194c801..10c6a9fea 100644 --- a/pkg/net/http/convertError_test.go +++ b/pkg/net/http/convertError_test.go @@ -2,6 +2,7 @@ package http import ( "context" + "errors" "fmt" "net/http" "testing" @@ -42,11 +43,11 @@ func TestErrToStatus(t *testing.T) { { name: "coap", args: args{ - err: coapStatus.Error(forbidden, fmt.Errorf("coap error")), + err: coapStatus.Error(forbidden, errors.New("coap error")), }, want: http.StatusForbidden, }, - {name: "grpc", args: args{err: fmt.Errorf("unknown error")}, want: http.StatusInternalServerError}, + {name: "grpc", args: args{err: errors.New("unknown error")}, want: http.StatusInternalServerError}, {name: "sdkError", args: args{err: SdkError{errorCode: codes.PermissionDenied}}, want: http.StatusForbidden}, } for _, tt := range tests { diff --git a/pkg/net/http/loggingMiddleware.go b/pkg/net/http/loggingMiddleware.go index 862e51cff..19c592514 100644 --- a/pkg/net/http/loggingMiddleware.go +++ b/pkg/net/http/loggingMiddleware.go @@ -2,6 +2,7 @@ package http import ( "bufio" + "errors" "fmt" "net" "net/http" @@ -58,7 +59,7 @@ func (w *statusWriter) Write(b []byte) (int, error) { func (w *statusWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { writer, ok := w.ResponseWriter.(http.Hijacker) if !ok { - return nil, nil, fmt.Errorf("not supported by the underlying writer") + return nil, nil, errors.New("not supported by the underlying writer") } return writer.Hijack() } diff --git a/pkg/net/http/service/config.go b/pkg/net/http/service/config.go index 76af609f4..cdde59691 100644 --- a/pkg/net/http/service/config.go +++ b/pkg/net/http/service/config.go @@ -1,6 +1,7 @@ package http import ( + "errors" "fmt" "github.com/plgd-dev/hub/v2/pkg/config" @@ -32,19 +33,19 @@ func (c *Config) Validate() error { return fmt.Errorf("HTTPConnection.%w", err) } if c.TraceProvider == nil { - return fmt.Errorf("traceProvider is required") + return errors.New("traceProvider is required") } if c.AuthRules == nil { - return fmt.Errorf("authRules is required") + return errors.New("authRules is required") } if c.FileWatcher == nil { - return fmt.Errorf("fileWatcher is required") + return errors.New("fileWatcher is required") } if c.Logger == nil { - return fmt.Errorf("logger is required") + return errors.New("logger is required") } if c.ServiceName == "" { - return fmt.Errorf("serviceName is required") + return errors.New("serviceName is required") } return nil diff --git a/pkg/security/certManager/client/certManager.go b/pkg/security/certManager/client/certManager.go index 8e550ee30..2ca175623 100644 --- a/pkg/security/certManager/client/certManager.go +++ b/pkg/security/certManager/client/certManager.go @@ -2,6 +2,7 @@ package client import ( "crypto/tls" + "errors" "fmt" "github.com/plgd-dev/hub/v2/pkg/config/property/urischeme" @@ -42,7 +43,7 @@ func (c *Config) Validate() error { func (c *Config) CAPoolArray() ([]urischeme.URIScheme, error) { if !c.validated { - return nil, fmt.Errorf("call Validate() first") + return nil, errors.New("call Validate() first") } return c.caPoolArray, nil } diff --git a/pkg/security/certManager/general/certManager.go b/pkg/security/certManager/general/certManager.go index b249ffab4..637e63358 100644 --- a/pkg/security/certManager/general/certManager.go +++ b/pkg/security/certManager/general/certManager.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "crypto/tls" "crypto/x509" + "errors" "fmt" "strings" "sync" @@ -191,7 +192,7 @@ func (a *CertManager) getTLSKeyPair() (*tls.Certificate, error) { } } if a.private.tlsKeyPair == nil { - return nil, fmt.Errorf("certificate is not loaded") + return nil, errors.New("certificate is not loaded") } return a.private.tlsKeyPair, nil diff --git a/pkg/security/certManager/general/certManager_test.go b/pkg/security/certManager/general/certManager_test.go index 433501cbd..3101e880b 100644 --- a/pkg/security/certManager/general/certManager_test.go +++ b/pkg/security/certManager/general/certManager_test.go @@ -178,18 +178,18 @@ func TestCertManagerWithExpiredCA(t *testing.T) { defer mng.Close() pool := mng.GetCertificateAuthorities() require.NotNil(t, pool) - require.Equal(t, 1, len(pool.Subjects())) //nolint:staticcheck + require.Len(t, pool.Subjects(), 1) //nolint:staticcheck time.Sleep(time.Second * 2) pool = mng.GetCertificateAuthorities() require.NotNil(t, pool) - require.Equal(t, 0, len(pool.Subjects())) //nolint:staticcheck + require.Empty(t, pool.Subjects()) //nolint:staticcheck caPem, _ = getCA(t, time.Now(), time.Second*100) err = os.WriteFile(caFile.Name(), caPem, os.FileMode(os.O_RDWR)) require.NoError(t, err) time.Sleep(time.Second * 1) pool = mng.GetCertificateAuthorities() require.NotNil(t, pool) - require.Equal(t, 1, len(pool.Subjects())) //nolint:staticcheck + require.Len(t, pool.Subjects(), 1) //nolint:staticcheck } // Check when cert expires diff --git a/pkg/security/certManager/server/certManager.go b/pkg/security/certManager/server/certManager.go index dd3a3fbb6..953d35cbb 100644 --- a/pkg/security/certManager/server/certManager.go +++ b/pkg/security/certManager/server/certManager.go @@ -2,6 +2,7 @@ package server import ( "crypto/tls" + "errors" "fmt" "github.com/plgd-dev/hub/v2/pkg/config/property/urischeme" @@ -43,7 +44,7 @@ func (c *Config) Validate() error { func (c *Config) CAPoolArray() ([]urischeme.URIScheme, error) { if !c.validated { - return nil, fmt.Errorf("call Validate() first") + return nil, errors.New("call Validate() first") } return c.caPoolArray, nil } diff --git a/pkg/security/certificateSigner/certificateSigner.go b/pkg/security/certificateSigner/certificateSigner.go index 2620e5e83..707588448 100644 --- a/pkg/security/certificateSigner/certificateSigner.go +++ b/pkg/security/certificateSigner/certificateSigner.go @@ -6,7 +6,7 @@ import ( "crypto/rand" "crypto/x509" "encoding/pem" - "fmt" + "errors" "math/big" "time" @@ -58,11 +58,11 @@ func New(caCert []*x509.Certificate, caKey crypto.PrivateKey, opts ...Opt) *Cert func (s *CertificateSigner) Sign(_ context.Context, csr []byte) ([]byte, error) { if len(s.caCert) == 0 { - return nil, fmt.Errorf("cannot sign with empty signer CA certificates") + return nil, errors.New("cannot sign with empty signer CA certificates") } csrBlock, _ := pem.Decode(csr) if csrBlock == nil { - return nil, fmt.Errorf("pem not found") + return nil, errors.New("pem not found") } certificateRequest, err := x509.ParseCertificateRequest(csrBlock.Bytes) @@ -106,7 +106,7 @@ func (s *CertificateSigner) Sign(_ context.Context, csr []byte) ([]byte, error) ExtraExtensions: certificateRequest.Extensions, } if s.cfg.OverrideCertTemplate != nil { - if err := s.cfg.OverrideCertTemplate(&template); err != nil { + if err = s.cfg.OverrideCertTemplate(&template); err != nil { return nil, err } } diff --git a/pkg/security/jwt/claims_test.go b/pkg/security/jwt/claims_test.go index 0d6fc2175..17398991a 100644 --- a/pkg/security/jwt/claims_test.go +++ b/pkg/security/jwt/claims_test.go @@ -132,7 +132,7 @@ func TestAudienceOfOne(t *testing.T) { c[pkgJwt.ClaimAudience] = "test" aud, err := c.GetAudience() require.NoError(t, err) - require.Equal(t, []string(aud), []string{c[pkgJwt.ClaimAudience].(string)}) + require.Equal(t, []string{c[pkgJwt.ClaimAudience].(string)}, []string(aud)) } func TestAudienceOfTwo(t *testing.T) { @@ -482,7 +482,6 @@ func checkClaims(t *testing.T, tokenClaims jwt.Claims, expError error) { } func TestValidate(t *testing.T) { - now := time.Now() expiredTime := now.Add(-time.Hour) futureTime := now.Add(time.Hour) diff --git a/pkg/security/jwt/jwk.go b/pkg/security/jwt/jwk.go index d7a87eb16..054c6a390 100644 --- a/pkg/security/jwt/jwk.go +++ b/pkg/security/jwt/jwk.go @@ -2,6 +2,7 @@ package jwt import ( "context" + "errors" "fmt" "net/http" "sync" @@ -53,21 +54,21 @@ func (c *KeyCache) GetKey(token *jwt.Token) (interface{}, error) { func (c *KeyCache) LookupKey(token *jwt.Token) (jwk.Key, error) { id, ok := token.Header["kid"].(string) if !ok { - return nil, fmt.Errorf("missing key id in token") + return nil, errors.New("missing key id in token") } c.m.Lock() defer c.m.Unlock() if c.keys == nil { - return nil, fmt.Errorf("empty JWK cache") + return nil, errors.New("empty JWK cache") } if key, ok := c.keys.LookupKeyID(id); ok { if key.Algorithm().String() == token.Method.Alg() { return key, nil } } - return nil, fmt.Errorf("could not find JWK") + return nil, errors.New("could not find JWK") } func (c *KeyCache) FetchKeys() error { diff --git a/pkg/security/jwt/validator_test.go b/pkg/security/jwt/validator_test.go index 59ca74c91..baef741e4 100644 --- a/pkg/security/jwt/validator_test.go +++ b/pkg/security/jwt/validator_test.go @@ -67,36 +67,36 @@ func TestClaims(t *testing.T) { require.ErrorIs(t, err, jwt.ErrTokenExpired) clientID, err := c.GetClientID() - assert.NoError(t, err) - assert.Equal(t, "test.client.id", clientID) + require.NoError(t, err) + require.Equal(t, "test.client.id", clientID) email, err := c.GetEmail() - assert.NoError(t, err) - assert.Equal(t, "user@example.com", email) + require.NoError(t, err) + require.Equal(t, "user@example.com", email) scope, err := c.GetScope() - assert.Contains(t, scope, "test.scope") - assert.NoError(t, err) + require.Contains(t, scope, "test.scope") + require.NoError(t, err) audience, err := c.GetAudience() - assert.NoError(t, err) - assert.Contains(t, audience, "http://identity-server:3001/resources") - assert.Contains(t, audience, "test.resource") + require.NoError(t, err) + require.Contains(t, audience, "http://identity-server:3001/resources") + require.Contains(t, audience, "test.resource") exp, err := c.GetExpirationTime() - assert.NoError(t, err) - assert.Equal(t, 2019, exp.Year()) + require.NoError(t, err) + require.Equal(t, 2019, exp.Year()) id, err := c.GetID() - assert.NoError(t, err) - assert.Empty(t, id) + require.NoError(t, err) + require.Empty(t, id) iat, err := c.GetIssuedAt() - assert.NoError(t, err) - assert.Nil(t, iat) + require.NoError(t, err) + require.Nil(t, iat) iss, err := c.GetIssuer() - assert.NoError(t, err) - assert.Equal(t, iss, "http://identity-server:3001") + require.NoError(t, err) + require.Equal(t, "http://identity-server:3001", iss) nbf, err := c.GetNotBefore() - assert.NoError(t, err) - assert.Equal(t, 2019, nbf.Year()) + require.NoError(t, err) + require.Equal(t, 2019, nbf.Year()) sub, err := c.GetSubject() - assert.NoError(t, err) - assert.Equal(t, "1b87effa-34e2-4a44-82c6-6e0ab80209ff", sub) + require.NoError(t, err) + require.Equal(t, "1b87effa-34e2-4a44-82c6-6e0ab80209ff", sub) } func TestParser(t *testing.T) { diff --git a/pkg/security/oauth2/plgd_clientCrendetials.go b/pkg/security/oauth2/plgd_clientCrendetials.go index 2df542aa2..5a18a7df3 100644 --- a/pkg/security/oauth2/plgd_clientCrendetials.go +++ b/pkg/security/oauth2/plgd_clientCrendetials.go @@ -42,9 +42,9 @@ func (p *ClientCredentialsPlgdProvider) Exchange(ctx context.Context, authorizat m := pkgJwt.Claims(claims) c := p.Config.ToDefaultClientCredentials() if p.deviceIDClaim != "" { - deviceID, err := m.GetDeviceID(p.deviceIDClaim) - if err != nil { - return nil, fmt.Errorf("cannot get deviceIDClaim: %w", err) + deviceID, errG := m.GetDeviceID(p.deviceIDClaim) + if errG != nil { + return nil, fmt.Errorf("cannot get deviceIDClaim: %w", errG) } if deviceID == "" { return nil, fmt.Errorf("deviceIDClaim('%v') is not set in token", p.deviceIDClaim) diff --git a/pkg/security/x509/load.go b/pkg/security/x509/load.go index bd5bf03bd..c76dc905c 100644 --- a/pkg/security/x509/load.go +++ b/pkg/security/x509/load.go @@ -5,7 +5,6 @@ import ( "crypto/x509" "encoding/pem" "errors" - "fmt" "os" ) @@ -25,7 +24,7 @@ func ParseX509(pemBlock []byte) ([]*x509.Certificate, error) { for { certDERBlock, tmp := pem.Decode(data) if certDERBlock == nil { - return nil, fmt.Errorf("cannot decode pem block") + return nil, errors.New("cannot decode pem block") } certs, err := x509.ParseCertificates(certDERBlock.Bytes) if err != nil { @@ -44,7 +43,7 @@ func ParseX509(pemBlock []byte) ([]*x509.Certificate, error) { func ParsePrivateKey(pemBlock []byte) (*ecdsa.PrivateKey, error) { certDERBlock, _ := pem.Decode(pemBlock) if certDERBlock == nil { - return nil, fmt.Errorf("cannot decode pem block") + return nil, errors.New("cannot decode pem block") } if key, err := x509.ParsePKCS8PrivateKey(certDERBlock.Bytes); err == nil { diff --git a/pkg/security/x509/verify.go b/pkg/security/x509/verify.go index c1aaf0f29..218866e8d 100644 --- a/pkg/security/x509/verify.go +++ b/pkg/security/x509/verify.go @@ -3,7 +3,7 @@ package x509 import ( "bytes" "crypto/x509" - "fmt" + "errors" ) func IsRootCA(cert *x509.Certificate) bool { @@ -29,10 +29,10 @@ func setCAPools(roots *x509.CertPool, intermediates *x509.CertPool, certs []*x50 // Verify verifies certificate against certificate authorities. func Verify(certificates []*x509.Certificate, certificateAuthorities []*x509.Certificate, useSystemRoots bool, opts x509.VerifyOptions) ([][]*x509.Certificate, error) { if len(certificates) == 0 { - return nil, fmt.Errorf("at least one certificate need to be set") + return nil, errors.New("at least one certificate need to be set") } if len(certificateAuthorities) == 0 { - return nil, fmt.Errorf("at least one certificate authority need to be set") + return nil, errors.New("at least one certificate authority need to be set") } intermediateCA := x509.NewCertPool() rootCA := x509.NewCertPool() diff --git a/pkg/service/service.go b/pkg/service/service.go index cb9f5c17c..3d58cbb64 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -1,7 +1,7 @@ package service import ( - "fmt" + "errors" "os" "os/signal" "sync" @@ -40,7 +40,7 @@ func (s *Service) Add(services ...APIService) { func (s *Service) Serve() error { if !s.serving.CompareAndSwap(false, true) { - return fmt.Errorf("already serving") + return errors.New("already serving") } defer close(s.done) var wg sync.WaitGroup diff --git a/pkg/strings/slice_test.go b/pkg/strings/slice_test.go index cc5ce265f..6fee31e9f 100644 --- a/pkg/strings/slice_test.go +++ b/pkg/strings/slice_test.go @@ -65,7 +65,7 @@ func TestIntersection(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := Intersection(tt.args.s1, tt.args.s2) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } @@ -121,8 +121,8 @@ func TestSplit(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotTrue, gotFalse := Split(tt.args.s, tt.args.f) - require.Equal(t, gotTrue, tt.wantTrue) - require.Equal(t, gotFalse, tt.wantFalse) + require.Equal(t, tt.wantTrue, gotTrue) + require.Equal(t, tt.wantFalse, gotFalse) }) } } @@ -168,7 +168,7 @@ func TestUnique(t *testing.T) { got := Unique(tt.args.s) sort.Strings(got) sort.Strings(tt.want) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } @@ -211,7 +211,7 @@ func TestContains(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := Contains(tt.args.slice, tt.args.s) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } diff --git a/pkg/strings/sortedSlice_test.go b/pkg/strings/sortedSlice_test.go index b7e192593..823a9f19b 100644 --- a/pkg/strings/sortedSlice_test.go +++ b/pkg/strings/sortedSlice_test.go @@ -335,7 +335,7 @@ func TestSortedSlice_Intersection(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := tt.slice.Intersection(tt.args.second) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } @@ -392,7 +392,7 @@ func TestSortedSlice_Equal(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := tt.slice.Equal(tt.args.second) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } @@ -473,7 +473,7 @@ func TestSortedSlice_IsSuperslice(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := tt.slice.IsSuperslice(tt.args.s) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } diff --git a/pkg/sync/task/future/future_test.go b/pkg/sync/task/future/future_test.go index adce8e2e1..af1f13525 100644 --- a/pkg/sync/task/future/future_test.go +++ b/pkg/sync/task/future/future_test.go @@ -2,7 +2,7 @@ package future import ( "context" - "fmt" + "errors" "sync" "testing" "time" @@ -29,7 +29,7 @@ func TestFutureReadyAfterError(t *testing.T) { fut, set := New() require.False(t, fut.Ready()) - set(nil, fmt.Errorf("test error")) + set(nil, errors.New("test error")) require.True(t, fut.Ready()) val, err := fut.Get(context.Background()) diff --git a/pkg/sync/task/queue/queue.go b/pkg/sync/task/queue/queue.go index 29a9bdfcf..da64612e9 100644 --- a/pkg/sync/task/queue/queue.go +++ b/pkg/sync/task/queue/queue.go @@ -2,7 +2,7 @@ package queue import ( "container/list" - "fmt" + "errors" "sync" "github.com/panjf2000/ants/v2" @@ -21,7 +21,7 @@ type Queue struct { // New creates task queue which is processed by goroutines. func New(cfg Config) (*Queue, error) { if cfg.Size <= 0 { - return nil, fmt.Errorf("invalid value of Size") + return nil, errors.New("invalid value of Size") } p, err := ants.NewPool(cfg.GoPoolSize, ants.WithPreAlloc(true), ants.WithExpiryDuration(cfg.MaxIdleTime), ants.WithNonblocking(true)) if err != nil { @@ -38,7 +38,7 @@ func (q *Queue) appendQueue(tasks []func()) error { q.mutex.Lock() defer q.mutex.Unlock() if q.queue.Len()+len(tasks) > q.limit { - return fmt.Errorf("reached limit of max processed jobs") + return errors.New("reached limit of max processed jobs") } for _, t := range tasks { q.queue.PushBack(t) diff --git a/pkg/yaml/yaml_test.go b/pkg/yaml/yaml_test.go index 68a0833a0..f2eb5b74f 100644 --- a/pkg/yaml/yaml_test.go +++ b/pkg/yaml/yaml_test.go @@ -131,7 +131,7 @@ func TestMergeYamlNodes(t *testing.T) { // merge the nodes got, err := MergeYamlNodes(tt.args.node1, tt.args.node2) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) diff --git a/resource-aggregate/commands/utils.go b/resource-aggregate/commands/utils.go index 33ed82e69..b0b973438 100644 --- a/resource-aggregate/commands/utils.go +++ b/resource-aggregate/commands/utils.go @@ -18,20 +18,20 @@ const ( // ToUUID converts resource href and device id to unique resource ID func (r *ResourceId) ToUUID() uuid.UUID { - if len(r.Href) == 0 { + if len(r.GetHref()) == 0 { return uuid.Nil } - return uuid.NewSHA1(uuid.NameSpaceURL, []byte(r.DeviceId+r.Href)) + return uuid.NewSHA1(uuid.NameSpaceURL, []byte(r.GetDeviceId()+r.GetHref())) } // ToUUID converts resource href and device id to unique resource ID func (r *Resource) ToUUID() uuid.UUID { - return uuid.NewSHA1(uuid.NameSpaceURL, []byte(r.DeviceId+r.Href)) + return uuid.NewSHA1(uuid.NameSpaceURL, []byte(r.GetDeviceId()+r.GetHref())) } // GetResourceID converts resource href and device id to resource id struct func (r *Resource) GetResourceID() *ResourceId { - return &ResourceId{DeviceId: r.DeviceId, Href: r.Href} + return &ResourceId{DeviceId: r.GetDeviceId(), Href: r.GetHref()} } func MakeLinksResourceUUID(deviceID string) uuid.UUID { @@ -138,24 +138,25 @@ func (r *ResourceId) Equal(r1 *ResourceId) bool { if r == nil || r1 == nil { return false } - return r.DeviceId == r1.DeviceId && r.Href == r1.Href + return r.GetDeviceId() == r1.GetDeviceId() && r.GetHref() == r1.GetHref() } func (r *ResourceId) ToString() string { if r == nil { return "" } - if r.DeviceId == "" { + deviceID := r.GetDeviceId() + if deviceID == "" { return "" } - if r.Href == "" { + href := r.GetHref() + if href == "" { return "" } - href := r.Href if href[0] != '/' { href = "/" + href } - return r.DeviceId + href + return deviceID + href } func ResourceIdFromString(v string) *ResourceId { diff --git a/resource-aggregate/cqrs/aggregate/aggregate.go b/resource-aggregate/cqrs/aggregate/aggregate.go index 4e1d71b75..d7aabadcb 100644 --- a/resource-aggregate/cqrs/aggregate/aggregate.go +++ b/resource-aggregate/cqrs/aggregate/aggregate.go @@ -29,7 +29,7 @@ func NewDefaultRetryFunc(limit int) RetryFunc { counter := new(int) return func() (time.Time, error) { if *counter >= limit { - return time.Time{}, fmt.Errorf("retry reach limit") + return time.Time{}, errors.New("retry reach limit") } *counter++ return time.Now().Add(time.Millisecond * 10), nil @@ -130,7 +130,7 @@ func HandleRetry(ctx context.Context, retryFunc RetryFunc) error { select { case <-time.After(time.Until(when)): case <-ctx.Done(): - return fmt.Errorf("retry canceled") + return errors.New("retry canceled") } return nil } @@ -169,7 +169,7 @@ func (a *Aggregate) HandleCommandWithAggregateModelWrapper(ctx context.Context, } snapshot, ok := amodel.TakeSnapshot(newVersion + uint64(len(newEvents)-1)) if !ok { - return nil, false, fmt.Errorf("cannot take snapshot") + return nil, false, errors.New("cannot take snapshot") } // save all events except last one, because last one will be replaced by snapshot saveEvents := make([]eventstore.Event, 0, len(newEvents)) diff --git a/resource-aggregate/cqrs/aggregate/test/aggregate.go b/resource-aggregate/cqrs/aggregate/test/aggregate.go index 54b714aba..57d960a5e 100644 --- a/resource-aggregate/cqrs/aggregate/test/aggregate.go +++ b/resource-aggregate/cqrs/aggregate/test/aggregate.go @@ -109,7 +109,7 @@ func (e *Snapshot) HandleCommand(_ context.Context, cmd Command, newVersion uint return []eventstore.Event{&Published{DeviceId: req.DeviceId, Href: req.Href, EventVersion: newVersion}}, nil case *Unpublish: if !e.IsPublished { - return nil, fmt.Errorf("not allowed to unpublish twice in tests") + return nil, errors.New("not allowed to unpublish twice in tests") } e.IsPublished = false return []eventstore.Event{&Unpublished{DeviceId: req.DeviceId, Href: req.Href, EventVersion: newVersion}}, nil diff --git a/resource-aggregate/cqrs/eventbus/goroutinePoolHandler_test.go b/resource-aggregate/cqrs/eventbus/goroutinePoolHandler_test.go index 9212bd802..6d81ccad1 100644 --- a/resource-aggregate/cqrs/eventbus/goroutinePoolHandler_test.go +++ b/resource-aggregate/cqrs/eventbus/goroutinePoolHandler_test.go @@ -3,11 +3,11 @@ package eventbus import ( "context" "errors" - "fmt" "testing" "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type mockEventHandler struct { @@ -241,19 +241,19 @@ func TestGoroutinePoolHandler_Handle(t *testing.T) { eh, func(err error) { if wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) err := ep.Handle(tt.args.ctx, tt.args.iter) - assert.NoError(t, err) + require.NoError(t, err) select { case <-eh.processed: assert.Equal(t, tt.want, eh.events) case <-time.After(time.Millisecond * 100): if !tt.wantTimeout { - assert.NoError(t, fmt.Errorf("timeout")) + require.Fail(t, "timeout") } } }) diff --git a/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go b/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go index 312f30b67..162818451 100644 --- a/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go +++ b/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "testing" "time" @@ -44,7 +43,7 @@ func TestPublisher(t *testing.T) { FlusherTimeout: time.Second * 30, }, }, fileWatcher, logger, publisher.WithMarshaler(json.Marshal)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, publisher) defer func() { publisher.Close() @@ -55,7 +54,7 @@ func TestPublisher(t *testing.T) { logger, subscriber.WithGoPool(func(f func()) error { go f(); return nil }), subscriber.WithUnmarshaler(json.Unmarshal)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, subscriber) defer func() { subscriber.Close() @@ -114,7 +113,7 @@ func TestPublisherJetStream(t *testing.T) { logger, subscriber.WithGoPool(func(f func()) error { go f(); return nil }), subscriber.WithUnmarshaler(json.Unmarshal)) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, subscriber) defer func() { subscriber.Close() @@ -207,7 +206,7 @@ func (eh *mockEventHandler) waitForEvent(timeout time.Duration) (mockEvent, erro case e := <-eh.newEvent: return e, nil case <-time.After(timeout): - return mockEvent{}, fmt.Errorf("timeout") + return mockEvent{}, errors.New("timeout") } } @@ -218,7 +217,7 @@ func testWaitForAnyEvent(timeout time.Duration, eh1 *mockEventHandler, eh2 *mock case e := <-eh2.newEvent: return e, nil case <-time.After(timeout): - return mockEvent{}, fmt.Errorf("timeout") + return mockEvent{}, errors.New("timeout") } } @@ -226,7 +225,7 @@ func testNewSubscription(ctx context.Context, t *testing.T, subscriber eventbus. t.Log("Subscribe to testNewSubscription") m := newMockEventHandler() ob, err := subscriber.Subscribe(ctx, subscriptionID, topics, m) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, ob) if ob == nil { return nil, nil @@ -306,11 +305,11 @@ func acceptanceTest(ctx context.Context, t *testing.T, timeout time.Duration, wa }, } - assert.Equal(t, 2, len(topics)) + require.Len(t, topics, 2) t.Log("Without subscription") err := publisher.Publish(ctx, topics[0:1], aggregateID1Path.GroupID, aggregateID1Path.AggregateID, eventsToPublish[0]) - assert.NoError(t, err) + require.NoError(t, err) time.Sleep(waitForSubscription) // Add handlers and observers. @@ -319,66 +318,66 @@ func acceptanceTest(ctx context.Context, t *testing.T, timeout time.Duration, wa time.Sleep(waitForSubscription) err = publisher.Publish(ctx, topics[0:1], aggregateID1Path.GroupID, aggregateID1Path.AggregateID, eventsToPublish[1]) - assert.NoError(t, err) + require.NoError(t, err) event0, err := m0.waitForEvent(timeout) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, eventsToPublish[1], event0) err = ob0.Close() - assert.NoError(t, err) + require.NoError(t, err) t.Log("Subscribe more observers") m1, ob1 := testNewSubscription(ctx, t, subscriber, "sub-1", topics[1:2]) defer func() { err = ob1.Close() - assert.NoError(t, err) + require.NoError(t, err) }() m2, ob2 := testNewSubscription(ctx, t, subscriber, "sub-2", topics[1:2]) defer func() { err = ob2.Close() - assert.NoError(t, err) + require.NoError(t, err) }() m3, ob3 := testNewSubscription(ctx, t, subscriber, "sub-shared", topics[0:1]) defer func() { err = ob3.Close() - assert.NoError(t, err) + require.NoError(t, err) }() m4, ob4 := testNewSubscription(ctx, t, subscriber, "sub-shared", topics[0:1]) defer func() { err = ob4.Close() - assert.NoError(t, err) + require.NoError(t, err) }() time.Sleep(waitForSubscription) err = publisher.Publish(ctx, topics, aggregateID1Path.GroupID, aggregateID1Path.AggregateID, eventsToPublish[2]) - assert.NoError(t, err) + require.NoError(t, err) event1, err := m1.waitForEvent(timeout) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, eventsToPublish[2], event1) event2, err := m2.waitForEvent(timeout) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, eventsToPublish[2], event2) event3, err := testWaitForAnyEvent(timeout, m3, m4) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, eventsToPublish[2], event3) topic := "test.new_topic_" + uuid.Must(uuid.NewRandom()).String() topics = append(topics, topic) err = ob4.SetTopics(ctx, topics) time.Sleep(waitForSubscription) - assert.NoError(t, err) + require.NoError(t, err) err = publisher.Publish(ctx, []string{topic}, aggregateID1Path.GroupID, aggregateID1Path.AggregateID, eventsToPublish[3]) - assert.NoError(t, err) + require.NoError(t, err) event4, err := m4.waitForEvent(timeout) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, eventsToPublish[3], event4) err = ob4.SetTopics(ctx, nil) - assert.NoError(t, err) + require.NoError(t, err) } diff --git a/resource-aggregate/cqrs/eventbus/nats/subscriber/reconnect_test.go b/resource-aggregate/cqrs/eventbus/nats/subscriber/reconnect_test.go index 57702f655..b5ec6891d 100644 --- a/resource-aggregate/cqrs/eventbus/nats/subscriber/reconnect_test.go +++ b/resource-aggregate/cqrs/eventbus/nats/subscriber/reconnect_test.go @@ -3,7 +3,7 @@ package subscriber_test import ( "context" "encoding/json" - "fmt" + "errors" "testing" "time" @@ -95,7 +95,7 @@ func TestSubscriberReconnect(t *testing.T) { select { case <-ch: case <-ctx.Done(): - require.NoError(t, fmt.Errorf("Timeout")) + require.NoError(t, errors.New("Timeout")) } naClient1, pub1, err := natsTest.NewClientAndPublisher(config.MakePublisherConfig(), fileWatcher, logger, publisher.WithMarshaler(json.Marshal)) require.NoError(t, err) diff --git a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go index a7a49434a..0556a828b 100644 --- a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go +++ b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go @@ -3,6 +3,7 @@ package subscriber import ( "context" "encoding/json" + "errors" "fmt" "sync" "time" @@ -146,7 +147,7 @@ func New(conn *nats.Conn, pendingLimits natsClient.PendingLimitsConfig, logger l } if cfg.dataUnmarshaler == nil { - return nil, fmt.Errorf("invalid eventUnmarshaler") + return nil, errors.New("invalid eventUnmarshaler") } s := &Subscriber{ diff --git a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go index 4eb45c9ae..bad00781b 100644 --- a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go +++ b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "testing" "time" @@ -141,7 +140,7 @@ func (eh *mockEventHandler) waitForEvent(timeout time.Duration) (mockEvent, erro case e := <-eh.newEvent: return e, nil case <-time.After(timeout): - return mockEvent{}, fmt.Errorf("timeout") + return mockEvent{}, errors.New("timeout") } } @@ -152,7 +151,7 @@ func testWaitForAnyEvent(timeout time.Duration, eh1 *mockEventHandler, eh2 *mock case e := <-eh2.newEvent: return e, nil case <-time.After(timeout): - return mockEvent{}, fmt.Errorf("timeout") + return mockEvent{}, errors.New("timeout") } } @@ -243,7 +242,7 @@ func acceptanceTest(ctx context.Context, t *testing.T, timeout time.Duration, pu }, } - require.Equal(t, 2, len(publishTopics)) + require.Len(t, publishTopics, 2) t.Log("Without subscription") err := publisher.Publish(ctx, publishTopics[0:1], aggregateID1Path.GroupID, aggregateID1Path.AggregateID, eventsToPublish[0]) diff --git a/resource-aggregate/cqrs/eventstore/cqldb/delete.go b/resource-aggregate/cqrs/eventstore/cqldb/delete.go index 0a82de4d3..a5240ba60 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/delete.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/delete.go @@ -2,7 +2,7 @@ package cqldb import ( "context" - "fmt" + "errors" "strings" "github.com/plgd-dev/hub/v2/pkg/cqldb" @@ -30,7 +30,7 @@ func getDeviceIDFilter(queries []eventstore.DeleteQuery) string { func (s *EventStore) Delete(ctx context.Context, queries []eventstore.DeleteQuery) error { deviceIDFilter := getDeviceIDFilter(queries) if len(deviceIDFilter) == 0 { - return fmt.Errorf("failed to delete documents: invalid query") + return errors.New("failed to delete documents: invalid query") } return s.client.Session().Query("delete from " + s.Table() + " " + cqldb.WhereClause + " " + deviceIDKey + " in (" + deviceIDFilter + ");").WithContext(ctx).Exec() diff --git a/resource-aggregate/cqrs/eventstore/cqldb/delete_test.go b/resource-aggregate/cqrs/eventstore/cqldb/delete_test.go index 51c512505..27158b12b 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/delete_test.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/delete_test.go @@ -61,7 +61,7 @@ func TestEventStore_Delete(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go b/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go index 5e5565a72..2796a4fc0 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go @@ -138,11 +138,11 @@ func encodeToBlob(data []byte) string { func getLatestEventsSnapshot(events []eventstore.Event, marshaler MarshalerFunc) (eventstore.Event, []byte, error) { if len(events) == 0 { - return nil, nil, fmt.Errorf("empty events") + return nil, nil, errors.New("empty events") } lastEvent := events[len(events)-1] if !lastEvent.IsSnapshot() { - return nil, nil, fmt.Errorf("the last event must be a snapshot") + return nil, nil, errors.New("the last event must be a snapshot") } // Marshal event data if there is any. snapshot, err := marshaler(lastEvent) diff --git a/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags.go b/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags.go index 147203c83..b3f052fcb 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags.go @@ -3,7 +3,6 @@ package cqldb import ( "context" "errors" - "fmt" "sort" "strings" @@ -40,7 +39,7 @@ func (a etagTimestamps) toETags(limit int) [][]byte { // Get latest ETags for device resources from event store for batch observing func (s *EventStore) GetLatestDeviceETags(ctx context.Context, deviceID string, limit uint32) ([][]byte, error) { if deviceID == "" { - return nil, fmt.Errorf("deviceID is invalid") + return nil, errors.New("deviceID is invalid") } var q strings.Builder q.WriteString(cqldb.SelectCommand) diff --git a/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags_test.go b/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags_test.go index 3147f11e1..b390d6355 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags_test.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/getLatestDeviceETags_test.go @@ -23,7 +23,7 @@ func TestGetLatestDeviceETAG(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/cqldb/load.go b/resource-aggregate/cqrs/eventstore/cqldb/load.go index 05172685b..d0d1b57d9 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/load.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/load.go @@ -3,6 +3,7 @@ package cqldb import ( "context" "fmt" + "strconv" "strings" "github.com/gocql/gocql" @@ -166,7 +167,7 @@ func snapshotQueriesToFilter(deviceID string, queries []eventstore.SnapshotQuery } filter.WriteString(timestampKey) filter.WriteString(">=") - filter.WriteString(fmt.Sprintf("%v", timestamp)) + filter.WriteString(strconv.FormatInt(timestamp, 10)) filter.WriteString(" ALLOW FILTERING") } return filter.String() diff --git a/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs.go b/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs.go index 4319e4ec3..efb8c78f0 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strconv" "strings" "github.com/gocql/gocql" @@ -19,7 +20,7 @@ func (s *EventStore) LoadDeviceMetadataByServiceIDs(ctx context.Context, service return nil, status.Errorf(codes.InvalidArgument, "invalid serviceIDs") } serviceIDs = pkgStrings.Unique(serviceIDs) - q := cqldb.SelectCommand + " " + deviceIDKey + "," + serviceIDKey + " " + cqldb.FromClause + " " + s.Table() + " " + cqldb.WhereClause + " " + serviceIDKey + " in (" + strings.Join(serviceIDs, ",") + ") LIMIT " + fmt.Sprintf("%v", limit) + ";" + q := cqldb.SelectCommand + " " + deviceIDKey + "," + serviceIDKey + " " + cqldb.FromClause + " " + s.Table() + " " + cqldb.WhereClause + " " + serviceIDKey + " in (" + strings.Join(serviceIDs, ",") + ") LIMIT " + strconv.FormatInt(limit, 10) + ";" iter := s.client.Session().Query(q).WithContext(ctx).Iter() if iter == nil { return nil, errors.New("cannot create iterator") diff --git a/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs_test.go b/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs_test.go index dc08689c5..e6f1af5c3 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs_test.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/loadDeviceMetadataByServiceIDs_test.go @@ -23,7 +23,7 @@ func TestLoadDeviceMetadataByServiceIDs(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/cqldb/save.go b/resource-aggregate/cqrs/eventstore/cqldb/save.go index 64742c06e..24684855f 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/save.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/save.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "strconv" "strings" "github.com/gocql/gocql" @@ -54,8 +55,8 @@ func eventToKeyValues(event eventstore.Event, insert bool, data []byte) keyValue kvs = append(kvs, keyValue{Key: idKey, Val: event.AggregateID()}) kvs = append(kvs, keyValue{Key: eventTypeKey, Val: "'" + event.EventType() + "'"}) } - kvs = append(kvs, keyValue{Key: versionKey, Val: fmt.Sprintf("%v", event.Version())}) - kvs = append(kvs, keyValue{Key: timestampKey, Val: fmt.Sprintf("%v", event.Timestamp().UnixNano())}) + kvs = append(kvs, keyValue{Key: versionKey, Val: strconv.FormatUint(event.Version(), 10)}) + kvs = append(kvs, keyValue{Key: timestampKey, Val: strconv.FormatInt(event.Timestamp().UnixNano(), 10)}) kvs = append(kvs, keyValue{Key: snapshotKey, Val: encodeToBlob(data)}) serviceID, ok := event.ServiceID() if ok { @@ -69,7 +70,7 @@ func eventToKeyValues(event eventstore.Event, insert bool, data []byte) keyValue etagData := event.ETag() if etagData != nil { kvs = append(kvs, keyValue{Key: etagKey, Val: encodeToBlob(etagData.ETag)}) - kvs = append(kvs, keyValue{Key: etagTimestampKey, Val: fmt.Sprintf("%v", etagData.Timestamp)}) + kvs = append(kvs, keyValue{Key: etagTimestampKey, Val: strconv.FormatInt(etagData.Timestamp, 10)}) } else { kvs = append(kvs, keyValue{Key: etagKey, Val: "null"}) kvs = append(kvs, keyValue{Key: etagTimestampKey, Val: "0"}) @@ -88,7 +89,7 @@ func (s *EventStore) saveEvent(ctx context.Context, events []eventstore.Event) ( return eventstore.Fail, err } setters := eventsToCQLSetValue(lastEvent, snapshotBinary) - q := "update " + s.client.Keyspace() + "." + s.config.Table + " set " + setters + " " + cqldb.WhereClause + " " + deviceIDKey + "=" + lastEvent.GroupID() + " and " + idKey + "=" + lastEvent.AggregateID() + " if " + versionKey + "=" + fmt.Sprintf("%v", events[0].Version()-1) + ";" + q := "update " + s.client.Keyspace() + "." + s.config.Table + " set " + setters + " " + cqldb.WhereClause + " " + deviceIDKey + "=" + lastEvent.GroupID() + " and " + idKey + "=" + lastEvent.AggregateID() + " if " + versionKey + "=" + strconv.FormatUint(events[0].Version()-1, 10) + ";" ok, err := s.client.Session().Query(q).WithContext(ctx).ScanCAS(nil) if err != nil { return eventstore.Fail, fmt.Errorf("cannot update snapshot event('%v'): %w", events, err) diff --git a/resource-aggregate/cqrs/eventstore/event.go b/resource-aggregate/cqrs/eventstore/event.go index 68d4d3e18..47e8d5789 100644 --- a/resource-aggregate/cqrs/eventstore/event.go +++ b/resource-aggregate/cqrs/eventstore/event.go @@ -2,6 +2,7 @@ package eventstore import ( "context" + "errors" "fmt" "time" @@ -153,7 +154,7 @@ func validateFirstEvent(event Event) error { } if event.Timestamp().IsZero() { - return fmt.Errorf("invalid zero events[0].Timestamp") + return errors.New("invalid zero events[0].Timestamp") } return nil diff --git a/resource-aggregate/cqrs/eventstore/eventstore.go b/resource-aggregate/cqrs/eventstore/eventstore.go index a67bd9c31..6925728de 100644 --- a/resource-aggregate/cqrs/eventstore/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/eventstore.go @@ -2,7 +2,7 @@ package eventstore import ( "context" - "fmt" + "errors" ) // VersionQuery used to load events from version. @@ -69,4 +69,4 @@ type EventStore interface { } // ErrNotSupported is returned when the operation is not supported. -var ErrNotSupported = fmt.Errorf("not supported") +var ErrNotSupported = errors.New("not supported") diff --git a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go index 4c62467b8..e76aef4e4 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go @@ -3,7 +3,6 @@ package mongodb_test import ( "context" "errors" - "fmt" "reflect" "sort" "sync" @@ -20,7 +19,7 @@ var ( UserId: "userId", } - errCannotUnmarshalEvent = fmt.Errorf("cannot unmarshal event") + errCannotUnmarshalEvent = errors.New("cannot unmarshal event") ) func MakeResourceLinksPublishedEvent(resources []*commands.Resource, deviceID string, eventMetadata *events.EventMetadata) eventstore.EventUnmarshaler { diff --git a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_eventstore_test.go b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_eventstore_test.go index 90bebaac3..8135ac720 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_eventstore_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_eventstore_test.go @@ -3,7 +3,6 @@ package mongodb_test import ( "context" "errors" - "fmt" "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" ) @@ -132,7 +131,7 @@ func (s *MockEventStore) LoadFromSnapshot(ctx context.Context, queries []eventst ret = append(ret, q) } if len(ret) == 0 { - return fmt.Errorf("cannot load events: not found") + return errors.New("cannot load events: not found") } return s.LoadFromVersion(ctx, ret, eventHandler) diff --git a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_test.go b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_test.go index e228170d8..229540a5c 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_test.go @@ -298,7 +298,7 @@ func AcceptanceTest(ctx context.Context, t *testing.T, store eventstore.EventSto eh1 := NewMockEventHandler() err = store.LoadFromSnapshot(ctx, []eventstore.SnapshotQuery{{GroupID: "notExist"}}, eh1) require.NoError(t, err) - require.Equal(t, 0, len(eh1.events)) + require.Empty(t, eh1.events) t.Log("load events") eh2 := NewMockEventHandler() @@ -392,7 +392,7 @@ func AcceptanceTest(ctx context.Context, t *testing.T, store eventstore.EventSto }, }, eh8) require.NoError(t, err) - require.Equal(t, 0, len(eh8.events[aggregateID1Path.GroupID][aggregateID1Path.AggregateID])) + require.Empty(t, eh8.events[aggregateID1Path.GroupID][aggregateID1Path.AggregateID]) t.Log("load events up to version without version specified") eh9 := NewMockEventHandler() @@ -403,7 +403,7 @@ func AcceptanceTest(ctx context.Context, t *testing.T, store eventstore.EventSto }, }, eh9) require.NoError(t, err) - require.Equal(t, 0, len(eh9.events[aggregateID1Path.GroupID][aggregateID1Path.AggregateID])) + require.Empty(t, eh9.events[aggregateID1Path.GroupID][aggregateID1Path.AggregateID]) t.Log("test projection all") model := NewMockEventHandler() diff --git a/resource-aggregate/cqrs/eventstore/mongodb/delete.go b/resource-aggregate/cqrs/eventstore/mongodb/delete.go index cb73ab476..80bf60d53 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/delete.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/delete.go @@ -2,7 +2,7 @@ package mongodb import ( "context" - "fmt" + "errors" "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" "github.com/plgd-dev/kit/v2/strings" @@ -29,7 +29,7 @@ func getDeviceIDFilter(queries []eventstore.DeleteQuery) bson.A { func (s *EventStore) Delete(ctx context.Context, queries []eventstore.DeleteQuery) error { deviceIDFilter := getDeviceIDFilter(queries) if len(deviceIDFilter) == 0 { - return fmt.Errorf("failed to delete documents: invalid query") + return errors.New("failed to delete documents: invalid query") } col := s.client().Database(s.DBName()).Collection(getEventCollectionName()) diff --git a/resource-aggregate/cqrs/eventstore/mongodb/delete_test.go b/resource-aggregate/cqrs/eventstore/mongodb/delete_test.go index 5aa075fa6..259c65511 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/delete_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/delete_test.go @@ -62,7 +62,7 @@ func TestEventStoreDelete(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go b/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go index c3a481b4a..32823d387 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go @@ -252,7 +252,7 @@ func getDocID(event eventstore.Event) string { } func getLatestSnapshotVersion(events []eventstore.Event) (uint64, error) { - err := fmt.Errorf("not found") + err := errors.New("not found") var latestSnapshotVersion uint64 for _, e := range events { if e.IsSnapshot() { diff --git a/resource-aggregate/cqrs/eventstore/mongodb/eventstore_test.go b/resource-aggregate/cqrs/eventstore/mongodb/eventstore_test.go index c556233be..2409bc29b 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/eventstore_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/eventstore_test.go @@ -44,7 +44,7 @@ func TestEventStore(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags.go b/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags.go index decf83cb7..d8f3bcf98 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags.go @@ -36,7 +36,7 @@ func decodeETag(cur *mongo.Cursor) ([]byte, error) { return nil, fmt.Errorf("cannot convert etag %T to primitive.Binary", etagRaw) } if len(etag.Data) == 0 { - return nil, fmt.Errorf("etag is empty") + return nil, errors.New("etag is empty") } return etag.Data, nil } @@ -49,7 +49,7 @@ func (s *EventStore) GetLatestDeviceETags(ctx context.Context, deviceID string, s.LogDebugfFunc("mongodb.Evenstore.GetLatestETag takes %v", time.Since(t)) }() if deviceID == "" { - return nil, fmt.Errorf("deviceID is invalid") + return nil, errors.New("deviceID is invalid") } filter := bson.D{ bson.E{Key: groupIDKey, Value: deviceID}, diff --git a/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags_test.go b/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags_test.go index 3847cf617..6cb6ed468 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/getLatestDeviceETags_test.go @@ -23,7 +23,7 @@ func TestGetLatestDeviceETAG(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/mongodb/getevents.go b/resource-aggregate/cqrs/eventstore/mongodb/getevents.go index 777ea40d1..1eadae300 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/getevents.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/getevents.go @@ -2,7 +2,7 @@ package mongodb import ( "context" - "fmt" + "errors" "time" "github.com/hashicorp/go-multierror" @@ -163,7 +163,7 @@ func (s *EventStore) GetEvents(ctx context.Context, queries []eventstore.GetEven s.LogDebugfFunc("mongodb.Evenstore.GetEvents takes %v", time.Since(t)) }() if len(queries) == 0 { - return fmt.Errorf("not supported") + return errors.New("not supported") } eventFilter := GetNormalizedGetEventsFilter(queries) diff --git a/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go b/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go index d826e2cd6..ba9d3f940 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go @@ -309,7 +309,7 @@ func Test_getNormalizedGetEventsFilter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := mongodb.GetNormalizedGetEventsFilter(tt.args.queries) - require.Equal(t, got, tt.want) + require.Equal(t, tt.want, got) }) } } diff --git a/resource-aggregate/cqrs/eventstore/mongodb/load.go b/resource-aggregate/cqrs/eventstore/mongodb/load.go index 15a341678..2ec7428f7 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/load.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/load.go @@ -52,7 +52,7 @@ func (i *iterator) parseDocument() bool { return false } if len(i.events) == 0 { - i.err = fmt.Errorf("invalid data, no events found") + i.err = errors.New("invalid data, no events found") return false } i.groupID, ok = doc[groupIDKey].(string) @@ -339,7 +339,7 @@ func (s *EventStore) LoadFromSnapshot(ctx context.Context, queries []eventstore. s.LogDebugfFunc("mongodb.Evenstore.LoadFromSnapshot takes %v", time.Since(t)) }() if len(queries) == 0 { - return fmt.Errorf("not supported") + return errors.New("not supported") } normalizeQuery := make(map[string][]eventstore.SnapshotQuery) diff --git a/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs.go b/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs.go index 331b0811d..03a613c25 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs.go @@ -20,7 +20,7 @@ func (s *EventStore) LoadDeviceMetadataByServiceIDs(ctx context.Context, service s.LogDebugfFunc("mongodb.Evenstore.LoadDocMetadataFromByServiceIDs takes %v", time.Since(t)) }() if len(serviceIDs) == 0 { - return nil, fmt.Errorf("not supported") + return nil, errors.New("not supported") } serviceIDs = strings.Unique(serviceIDs) diff --git a/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs_test.go b/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs_test.go index 2cda0511d..cf865b675 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/loadDeviceMetadataByServiceIDs_test.go @@ -23,7 +23,7 @@ func TestLoadDeviceMetadataByServiceIDs(t *testing.T) { ctx := context.Background() store, err := NewTestEventStore(ctx, fileWatcher, logger) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") diff --git a/resource-aggregate/cqrs/eventstore/mongodb/maintenance_test.go b/resource-aggregate/cqrs/eventstore/mongodb/maintenance_test.go index 8acf362f3..7aa5ea00d 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/maintenance_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/maintenance_test.go @@ -75,7 +75,7 @@ func TestMaintenance(t *testing.T) { mongodb.WithMarshaler(bson.Marshal), mongodb.WithUnmarshaler(bson.Unmarshal), ) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, store) defer func() { t.Log("clearing db") @@ -161,5 +161,5 @@ func TestMaintenance(t *testing.T) { eh3 := newMockRecordHandler() err = store.Query(ctx, 777, eh3) require.NoError(t, err) - require.Equal(t, 0, len(eh3.tasks)) + require.Empty(t, eh3.tasks) } diff --git a/resource-aggregate/cqrs/eventstore/projection.go b/resource-aggregate/cqrs/eventstore/projection.go index cdec3e572..345a8ff01 100644 --- a/resource-aggregate/cqrs/eventstore/projection.go +++ b/resource-aggregate/cqrs/eventstore/projection.go @@ -97,7 +97,7 @@ func (i *iterator) RewindToNextAggregateEvent(ctx context.Context) EventUnmarsha if nextAggregateEvent != nil { return nextAggregateEvent } - if snapshot == nil && nextAggregateEvent == nil { + if snapshot == nil { return nil } } diff --git a/resource-aggregate/cqrs/eventstore/test/acceptance_testing.go b/resource-aggregate/cqrs/eventstore/test/acceptance_testing.go index 072764543..ddc1fdafe 100644 --- a/resource-aggregate/cqrs/eventstore/test/acceptance_testing.go +++ b/resource-aggregate/cqrs/eventstore/test/acceptance_testing.go @@ -287,7 +287,7 @@ func AcceptanceTest(ctx context.Context, t *testing.T, store eventstore.EventSto eh1 := NewMockEventHandler() err = store.LoadFromSnapshot(ctx, []eventstore.SnapshotQuery{{GroupID: uuid.Nil.String()}}, eh1) require.NoError(t, err) - require.Equal(t, 0, len(eh1.events)) + require.Empty(t, eh1.events) t.Log("load events") eh2 := NewMockEventHandler() diff --git a/resource-aggregate/cqrs/eventstore/test/events.go b/resource-aggregate/cqrs/eventstore/test/events.go index 126df9e2f..086c4d48d 100644 --- a/resource-aggregate/cqrs/eventstore/test/events.go +++ b/resource-aggregate/cqrs/eventstore/test/events.go @@ -3,7 +3,6 @@ package test import ( "context" "errors" - "fmt" "reflect" "sort" "sync" @@ -20,7 +19,7 @@ var ( UserId: "userId", } - errCannotUnmarshalEvent = fmt.Errorf("cannot unmarshal event") + errCannotUnmarshalEvent = errors.New("cannot unmarshal event") ) func MakeResourceLinksPublishedEvent(resources []*commands.Resource, deviceID string, eventMetadata *events.EventMetadata) eventstore.EventUnmarshaler { diff --git a/resource-aggregate/cqrs/eventstore/test/eventstore.go b/resource-aggregate/cqrs/eventstore/test/eventstore.go index 3148c449b..54dcc707a 100644 --- a/resource-aggregate/cqrs/eventstore/test/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/test/eventstore.go @@ -3,7 +3,6 @@ package test import ( "context" "errors" - "fmt" "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" ) @@ -132,7 +131,7 @@ func (s *MockEventStore) LoadFromSnapshot(ctx context.Context, queries []eventst ret = append(ret, q) } if len(ret) == 0 { - return fmt.Errorf("cannot load events: not found") + return errors.New("cannot load events: not found") } return s.LoadFromVersion(ctx, ret, eventHandler) diff --git a/resource-aggregate/cqrs/projection/projection.go b/resource-aggregate/cqrs/projection/projection.go index b55e53df3..e1ce3361b 100644 --- a/resource-aggregate/cqrs/projection/projection.go +++ b/resource-aggregate/cqrs/projection/projection.go @@ -75,7 +75,7 @@ func (p *Projection) Register(ctx context.Context, deviceID string) (created boo return errors.ErrorOrNil() } if updateSubscriber { - err := p.cqrsProjection.SubscribeTo(topics) + err = p.cqrsProjection.SubscribeTo(topics) if err != nil { return false, releaseAndReturnError(deviceID, err) } diff --git a/resource-aggregate/cqrs/projection/projectionInternal.go b/resource-aggregate/cqrs/projection/projectionInternal.go index f6b928521..3e981af6e 100644 --- a/resource-aggregate/cqrs/projection/projectionInternal.go +++ b/resource-aggregate/cqrs/projection/projectionInternal.go @@ -69,7 +69,7 @@ func (p *projection) SubscribeTo(topics []string) error { } if p.observer == nil { if p.subscriber == nil { - return fmt.Errorf("projection doesn't support subscribe to topics") + return errors.New("projection doesn't support subscribe to topics") } observer, err := p.subscriber.Subscribe(p.ctx, p.subscriptionID, topics, p) if err != nil { diff --git a/resource-aggregate/cqrs/projection/projectionInternal_test.go b/resource-aggregate/cqrs/projection/projectionInternal_test.go index cc0350bcc..c4aa32152 100644 --- a/resource-aggregate/cqrs/projection/projectionInternal_test.go +++ b/resource-aggregate/cqrs/projection/projectionInternal_test.go @@ -21,7 +21,6 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/events" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" ) @@ -59,7 +58,7 @@ func TestProjection(t *testing.T) { naPubClient, publisher, err := natsTest.NewClientAndPublisher(config.MakePublisherConfig(), fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) - assert.NotNil(t, publisher) + require.NotNil(t, publisher) defer func() { publisher.Close() naPubClient.Close() @@ -74,8 +73,8 @@ func TestProjection(t *testing.T) { subscriber.WithGoPool(pool.Submit), subscriber.WithUnmarshaler(utils.Unmarshal), ) - assert.NoError(t, err) - assert.NotNil(t, subscriber) + require.NoError(t, err) + require.NotNil(t, subscriber) defer func() { subscriber.Close() naSubClient.Close() @@ -168,7 +167,7 @@ func TestProjection(t *testing.T) { models = append(models, m) return true }) - require.Equal(t, 1, len(models)) + require.Len(t, models, 1) err = projection.Project(ctx, []eventstore.SnapshotQuery{{ GroupID: res2.DeviceId, @@ -180,7 +179,7 @@ func TestProjection(t *testing.T) { models = append(models, m) return true }) - require.Equal(t, 2, len(models)) + require.Len(t, models, 2) err = projection.SubscribeTo(topics) require.NoError(t, err) @@ -208,7 +207,7 @@ func TestProjection(t *testing.T) { models = append(models, m) return true }) - require.Equal(t, 3, len(models)) + require.Len(t, models, 3) err = projection.SubscribeTo(topics[0:1]) require.NoError(t, err) @@ -229,7 +228,7 @@ func TestProjection(t *testing.T) { models = append(models, m) return true }) - require.Equal(t, 2, len(models)) + require.Len(t, models, 2) projection.lock.Unlock() err = projection.SubscribeTo(nil) @@ -253,6 +252,6 @@ func TestProjection(t *testing.T) { models = append(models, m) return true }) - require.Equal(t, 2, len(models)) + require.Len(t, models, 2) projection.lock.Unlock() } diff --git a/resource-aggregate/cqrs/projection/projection_test.go b/resource-aggregate/cqrs/projection/projection_test.go index ef8890ee1..071896d7c 100644 --- a/resource-aggregate/cqrs/projection/projection_test.go +++ b/resource-aggregate/cqrs/projection/projection_test.go @@ -252,7 +252,7 @@ func TestResourceProjection_Register(t *testing.T) { return events.NewResourceLinksSnapshotTaken(), nil }, ) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -263,9 +263,9 @@ func TestResourceProjection_Register(t *testing.T) { assert.False(t, gotLoaded) } if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -319,19 +319,19 @@ func TestResourceProjection_Unregister(t *testing.T) { return events.NewResourceLinksSnapshotTaken(), nil }, ) - assert.NoError(t, err) + require.NoError(t, err) _, err = p.Register(ctx, d1res1.DeviceId) - assert.NoError(t, err) + require.NoError(t, err) _, err = p.Register(ctx, d1res1.DeviceId) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := p.Unregister(tt.args.deviceID) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } @@ -458,12 +458,12 @@ func TestResourceLinksProjection_Models(t *testing.T) { return events.NewResourceLinksSnapshotTaken(), nil }, ) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err = p.Register(ctx, tt.args.deviceID) - assert.NoError(t, err) + require.NoError(t, err) got := []cqrsEventStore.Model{} p.Models(func(m cqrsEventStore.Model) (wantNext bool) { got = append(got, m) @@ -726,12 +726,12 @@ func TestResourceStateProjection_Models(t *testing.T) { return events.NewResourceStateSnapshotTaken(), nil }, ) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { _, err = p.Register(ctx, tt.args.resourceID.GetDeviceId()) - assert.NoError(t, err) + require.NoError(t, err) got := []cqrsEventStore.Model{} p.Models(func(m cqrsEventStore.Model) (wantNext bool) { got = append(got, m) @@ -789,16 +789,16 @@ func TestResourceProjection_ForceUpdate(t *testing.T) { return events.NewResourceStateSnapshotTaken(), nil }, ) - assert.NoError(t, err) + require.NoError(t, err) _, err = p.Register(ctx, d1res1.DeviceId) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := p.ForceUpdate(ctx, tt.args.resourceID) if tt.wantErr { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } }) } diff --git a/resource-aggregate/cqrs/utils/utils_test.go b/resource-aggregate/cqrs/utils/utils_test.go index 2c91ac99b..b4afa5b9b 100644 --- a/resource-aggregate/cqrs/utils/utils_test.go +++ b/resource-aggregate/cqrs/utils/utils_test.go @@ -7,6 +7,7 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/utils" "github.com/plgd-dev/hub/v2/resource-aggregate/events" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestDummyForCoverage(t *testing.T) { @@ -34,17 +35,17 @@ func TestProtobufMarshaler(t *testing.T) { req := events.ResourceChanged{} out, err := utils.Marshal(&req) - assert.NoError(t, err) + require.NoError(t, err) assert.NotEmpty(t, out) a := struct{}{} _, err = utils.Marshal(a) - assert.Error(t, err) + require.Error(t, err) resp := events.ResourceChanged{} err = utils.Unmarshal(out, &resp) - assert.NoError(t, err) + require.NoError(t, err) err = utils.Unmarshal(out, a) - assert.Error(t, err) + require.Error(t, err) } diff --git a/resource-aggregate/events/deviceMetadataSnapshotTaken.go b/resource-aggregate/events/deviceMetadataSnapshotTaken.go index d4756de78..4c1fca6a8 100644 --- a/resource-aggregate/events/deviceMetadataSnapshotTaken.go +++ b/resource-aggregate/events/deviceMetadataSnapshotTaken.go @@ -74,7 +74,8 @@ func (d *DeviceMetadataSnapshotTaken) CheckInitialized() bool { func (d *DeviceMetadataSnapshotTaken) HandleDeviceMetadataUpdated(_ context.Context, upd *DeviceMetadataUpdated, confirm bool) (bool, error) { index := -1 - for i, event := range d.GetUpdatePendings() { + updatePendings := d.GetUpdatePendings() + for i, event := range updatePendings { if event.GetAuditContext().GetCorrelationId() == upd.GetAuditContext().GetCorrelationId() { index = i break @@ -84,9 +85,10 @@ func (d *DeviceMetadataSnapshotTaken) HandleDeviceMetadataUpdated(_ context.Cont return false, status.Errorf(codes.InvalidArgument, "cannot find twin synchronization update pending event with correlationId('%v')", upd.GetAuditContext().GetCorrelationId()) } if index >= 0 { - d.UpdatePendings = append(d.UpdatePendings[:index], d.UpdatePendings[index+1:]...) + updatePendings = append(updatePendings[:index], updatePendings[index+1:]...) + d.UpdatePendings = updatePendings } - if d.DeviceMetadataUpdated.Equal(upd) { + if d.GetDeviceMetadataUpdated().Equal(upd) { return false, nil } @@ -321,9 +323,9 @@ func (d *DeviceMetadataSnapshotTaken) getTwinSynchronizationForConnectedDevice(r func (d *DeviceMetadataSnapshotTaken) getTwinSynchronizationForDisconnectedDevice(req *commands.UpdateDeviceMetadataRequest) (*commands.TwinSynchronization, error) { twinSynchronization := d.prepareTwinSynchronization() - if d.DeviceMetadataUpdated.GetConnection().IsOnline() && !req.GetConnection().IsOnline() && d.DeviceMetadataUpdated.GetConnection().GetId() != req.GetConnection().GetId() { + if d.GetDeviceMetadataUpdated().GetConnection().IsOnline() && !req.GetConnection().IsOnline() && d.GetDeviceMetadataUpdated().GetConnection().GetId() != req.GetConnection().GetId() { // if previous status was online and new status is offline, the connectionId must be the same - return nil, status.Errorf(codes.InvalidArgument, "cannot update connection status online(id='%v') to offline(id='%v'): connectionId mismatch", d.DeviceMetadataUpdated.GetConnection().GetId(), req.GetConnection().GetId()) + return nil, status.Errorf(codes.InvalidArgument, "cannot update connection status online(id='%v') to offline(id='%v'): connectionId mismatch", d.GetDeviceMetadataUpdated().GetConnection().GetId(), req.GetConnection().GetId()) } if d.GetDeviceMetadataUpdated().GetTwinEnabled() { twinSynchronization.State = commands.TwinSynchronization_OUT_OF_SYNC diff --git a/resource-aggregate/events/deviceMetadataUpdated_test.go b/resource-aggregate/events/deviceMetadataUpdated_test.go index c5af85f82..c5f0a394c 100644 --- a/resource-aggregate/events/deviceMetadataUpdated_test.go +++ b/resource-aggregate/events/deviceMetadataUpdated_test.go @@ -48,9 +48,9 @@ func TestDeviceMetadataUpdated_Equal(t *testing.T) { { name: "Identity", fields: fields{ - Connection: upd.Connection, - TwinEnabled: upd.TwinEnabled, - AuditContext: upd.AuditContext, + Connection: upd.GetConnection(), + TwinEnabled: upd.GetTwinEnabled(), + AuditContext: upd.GetAuditContext(), }, args: args{upd}, want: true, @@ -61,8 +61,8 @@ func TestDeviceMetadataUpdated_Equal(t *testing.T) { Connection: &commands.Connection{ Status: commands.Connection_OFFLINE, }, - TwinEnabled: upd.TwinEnabled, - AuditContext: upd.AuditContext, + TwinEnabled: upd.GetTwinEnabled(), + AuditContext: upd.GetAuditContext(), }, args: args{upd}, want: false, @@ -70,9 +70,9 @@ func TestDeviceMetadataUpdated_Equal(t *testing.T) { { name: "Changed TwinSynchronization", fields: fields{ - Connection: upd.Connection, + Connection: upd.GetConnection(), TwinEnabled: false, - AuditContext: upd.AuditContext, + AuditContext: upd.GetAuditContext(), }, args: args{upd}, want: false, @@ -80,11 +80,11 @@ func TestDeviceMetadataUpdated_Equal(t *testing.T) { { name: "Changed AuditContext.UserId", fields: fields{ - Connection: upd.Connection, - TwinEnabled: upd.TwinEnabled, + Connection: upd.GetConnection(), + TwinEnabled: upd.GetTwinEnabled(), AuditContext: &commands.AuditContext{ - UserId: upd.AuditContext.UserId + "0", - CorrelationId: upd.AuditContext.CorrelationId, + UserId: upd.GetAuditContext().GetUserId() + "0", + CorrelationId: upd.GetAuditContext().GetCorrelationId(), }, }, args: args{upd}, @@ -93,11 +93,11 @@ func TestDeviceMetadataUpdated_Equal(t *testing.T) { { name: "Changed AuditContext.CorrelationId", fields: fields{ - Connection: upd.Connection, - TwinEnabled: upd.TwinEnabled, + Connection: upd.GetConnection(), + TwinEnabled: upd.GetTwinEnabled(), AuditContext: &commands.AuditContext{ - UserId: upd.AuditContext.UserId, - CorrelationId: upd.AuditContext.CorrelationId + "0", + UserId: upd.GetAuditContext().GetUserId(), + CorrelationId: upd.GetAuditContext().GetCorrelationId() + "0", }, }, args: args{upd}, diff --git a/resource-aggregate/events/resourceLinksSnapshotTaken.go b/resource-aggregate/events/resourceLinksSnapshotTaken.go index a4a46c59b..897f0d641 100644 --- a/resource-aggregate/events/resourceLinksSnapshotTaken.go +++ b/resource-aggregate/events/resourceLinksSnapshotTaken.go @@ -89,7 +89,7 @@ func (e *ResourceLinksSnapshotTaken) GetNewPublishedLinks(pub *ResourceLinksPubl published := make([]*commands.Resource, 0, len(pub.GetResources())) for _, resPub := range pub.GetResources() { - resSnap, ok := e.Resources[resPub.Href] + resSnap, ok := e.GetResources()[resPub.GetHref()] if !ok || !EqualResource(resPub, resSnap) { published = append(published, resPub) } @@ -226,7 +226,7 @@ func (e *ResourceLinksSnapshotTakenForCommand) HandleCommand(ctx context.Context if newVersion == 0 { return nil, status.Errorf(codes.NotFound, errInvalidVersion) } - if req.CommandMetadata == nil { + if req.GetCommandMetadata() == nil { return nil, status.Errorf(codes.InvalidArgument, errInvalidCommandMetadata) } diff --git a/resource-aggregate/events/resourceLinksSnapshotTaken_test.go b/resource-aggregate/events/resourceLinksSnapshotTaken_test.go index 749eb4353..e049d4ad7 100644 --- a/resource-aggregate/events/resourceLinksSnapshotTaken_test.go +++ b/resource-aggregate/events/resourceLinksSnapshotTaken_test.go @@ -30,8 +30,8 @@ func TestResourceLinksSnapshotTakenGetNewPublishedLinks(t *testing.T) { } res1Upd := commands.Resource{ - Href: res.Href, - DeviceId: res.Href + "-upd", + Href: res.GetHref(), + DeviceId: res.GetHref() + "-upd", } tests := []struct { @@ -66,7 +66,7 @@ func TestResourceLinksSnapshotTakenGetNewPublishedLinks(t *testing.T) { name: "Identical", fields: fields{ Resources: map[string]*commands.Resource{ - res.Href: &res, + res.GetHref(): &res, }, }, args: args{ @@ -92,7 +92,7 @@ func TestResourceLinksSnapshotTakenGetNewPublishedLinks(t *testing.T) { name: "New published resource (2)", fields: fields{ Resources: map[string]*commands.Resource{ - res.Href: &res, + res.GetHref(): &res, }, }, args: args{ @@ -106,8 +106,8 @@ func TestResourceLinksSnapshotTakenGetNewPublishedLinks(t *testing.T) { name: "Updated resource", fields: fields{ Resources: map[string]*commands.Resource{ - res.Href: &res, - resHref.Href: &resHref, + res.GetHref(): &res, + resHref.GetHref(): &resHref, }, }, args: args{ @@ -369,7 +369,7 @@ func TestResourceLinksSnapshotTakenHandleEventResourceLinksUnpublished(t *testin Hrefs: tt.args.hrefs, }) if len(tt.want) == 0 { - require.Len(t, got, 0) + require.Empty(t, got) return } sort.Strings(tt.want) diff --git a/resource-aggregate/events/resourceStateSnapshotTaken.go b/resource-aggregate/events/resourceStateSnapshotTaken.go index 14996d6a1..05881fad4 100644 --- a/resource-aggregate/events/resourceStateSnapshotTaken.go +++ b/resource-aggregate/events/resourceStateSnapshotTaken.go @@ -212,7 +212,8 @@ func RemoveIndex(s []int, index int) []int { func (e *ResourceStateSnapshotTaken) handleEventResourceCreated(created *ResourceCreated) error { index := -1 - for i, event := range e.GetResourceCreatePendings() { + resourceCreatePendings := e.GetResourceCreatePendings() + for i, event := range resourceCreatePendings { if event.GetAuditContext().GetCorrelationId() == created.GetAuditContext().GetCorrelationId() { index = i break @@ -223,14 +224,16 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceCreated(created *Resourc } e.ResourceId = created.GetResourceId() e.EventMetadata = created.GetEventMetadata() - e.ResourceCreatePendings = append(e.ResourceCreatePendings[:index], e.ResourceCreatePendings[index+1:]...) + resourceCreatePendings = append(resourceCreatePendings[:index], resourceCreatePendings[index+1:]...) + e.ResourceCreatePendings = resourceCreatePendings e.AuditContext = created.GetAuditContext() return nil } func (e *ResourceStateSnapshotTaken) handleEventResourceUpdated(updated *ResourceUpdated) error { index := -1 - for i, event := range e.GetResourceUpdatePendings() { + resourceUpdatePendings := e.GetResourceUpdatePendings() + for i, event := range resourceUpdatePendings { if event.GetAuditContext().GetCorrelationId() == updated.GetAuditContext().GetCorrelationId() { index = i break @@ -241,14 +244,16 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceUpdated(updated *Resourc } e.ResourceId = updated.GetResourceId() e.EventMetadata = updated.GetEventMetadata() - e.ResourceUpdatePendings = append(e.ResourceUpdatePendings[:index], e.ResourceUpdatePendings[index+1:]...) + resourceUpdatePendings = append(resourceUpdatePendings[:index], resourceUpdatePendings[index+1:]...) + e.ResourceUpdatePendings = resourceUpdatePendings e.AuditContext = updated.GetAuditContext() return nil } func (e *ResourceStateSnapshotTaken) handleEventResourceRetrieved(retrieved *ResourceRetrieved) error { index := -1 - for i, event := range e.GetResourceRetrievePendings() { + resourceRetrievePendings := e.GetResourceRetrievePendings() + for i, event := range resourceRetrievePendings { if event.GetAuditContext().GetCorrelationId() == retrieved.GetAuditContext().GetCorrelationId() { index = i break @@ -259,7 +264,8 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceRetrieved(retrieved *Res } e.ResourceId = retrieved.GetResourceId() e.EventMetadata = retrieved.GetEventMetadata() - e.ResourceRetrievePendings = append(e.ResourceRetrievePendings[:index], e.ResourceRetrievePendings[index+1:]...) + resourceRetrievePendings = append(resourceRetrievePendings[:index], resourceRetrievePendings[index+1:]...) + e.ResourceRetrievePendings = resourceRetrievePendings e.AuditContext = retrieved.GetAuditContext() return nil } @@ -294,7 +300,8 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceDeleted(deleted *Resourc e.ResourceUpdatePendings = nil } else { index := -1 - for i, event := range e.GetResourceDeletePendings() { + resourceDeletePendings := e.GetResourceDeletePendings() + for i, event := range resourceDeletePendings { if event.GetAuditContext().GetCorrelationId() == deleted.GetAuditContext().GetCorrelationId() { index = i break @@ -303,7 +310,8 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceDeleted(deleted *Resourc if index < 0 { return status.Errorf(codes.InvalidArgument, "cannot find resource delete pending event with correlationId('%v')", deleted.GetAuditContext().GetCorrelationId()) } - e.ResourceDeletePendings = append(e.ResourceDeletePendings[:index], e.ResourceDeletePendings[index+1:]...) + resourceDeletePendings = append(resourceDeletePendings[:index], resourceDeletePendings[index+1:]...) + e.ResourceDeletePendings = resourceDeletePendings } e.ResourceId = deleted.GetResourceId() e.EventMetadata = deleted.GetEventMetadata() @@ -315,76 +323,84 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceStateSnapshotTaken(snaps e.CopyData(snapshot) } +//nolint:gocyclo +func (e *ResourceStateSnapshotTaken) handleByEvent(eu eventstore.EventUnmarshaler) error { + if eu.EventType() == "" { + return status.Errorf(codes.Internal, "cannot determine type of event") + } + switch eu.EventType() { + case (&ResourceStateSnapshotTaken{}).EventType(): + var s ResourceStateSnapshotTaken + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + e.handleEventResourceStateSnapshotTaken(&s) + case (&ResourceUpdatePending{}).EventType(): + var s ResourceUpdatePending + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceUpdatePending(&s) + case (&ResourceUpdated{}).EventType(): + var s ResourceUpdated + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceUpdated(&s) + case (&ResourceCreatePending{}).EventType(): + var s ResourceCreatePending + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceCreatePending(&s) + case (&ResourceCreated{}).EventType(): + var s ResourceCreated + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceCreated(&s) + case (&ResourceChanged{}).EventType(): + var s ResourceChanged + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceChanged(&s) + case (&ResourceDeleted{}).EventType(): + var s ResourceDeleted + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceDeleted(&s) + case (&ResourceDeletePending{}).EventType(): + var s ResourceDeletePending + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceDeletePending(&s) + case (&ResourceRetrieved{}).EventType(): + var s ResourceRetrieved + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceRetrieved(&s) + case (&ResourceRetrievePending{}).EventType(): + var s ResourceRetrievePending + if err := eu.Unmarshal(&s); err != nil { + return status.Errorf(codes.Internal, "%v", err) + } + _ = e.handleEventResourceRetrievePending(&s) + } + return nil +} + func (e *ResourceStateSnapshotTaken) Handle(ctx context.Context, iter eventstore.Iter) error { for { eu, ok := iter.Next(ctx) if !ok { break } - if eu.EventType() == "" { - return status.Errorf(codes.Internal, "cannot determine type of event") - } - switch eu.EventType() { - case (&ResourceStateSnapshotTaken{}).EventType(): - var s ResourceStateSnapshotTaken - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - e.handleEventResourceStateSnapshotTaken(&s) - case (&ResourceUpdatePending{}).EventType(): - var s ResourceUpdatePending - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceUpdatePending(&s) - case (&ResourceUpdated{}).EventType(): - var s ResourceUpdated - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceUpdated(&s) - case (&ResourceCreatePending{}).EventType(): - var s ResourceCreatePending - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceCreatePending(&s) - case (&ResourceCreated{}).EventType(): - var s ResourceCreated - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceCreated(&s) - case (&ResourceChanged{}).EventType(): - var s ResourceChanged - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceChanged(&s) - case (&ResourceDeleted{}).EventType(): - var s ResourceDeleted - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceDeleted(&s) - case (&ResourceDeletePending{}).EventType(): - var s ResourceDeletePending - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceDeletePending(&s) - case (&ResourceRetrieved{}).EventType(): - var s ResourceRetrieved - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceRetrieved(&s) - case (&ResourceRetrievePending{}).EventType(): - var s ResourceRetrievePending - if err := eu.Unmarshal(&s); err != nil { - return status.Errorf(codes.Internal, "%v", err) - } - _ = e.handleEventResourceRetrievePending(&s) + if err := e.handleByEvent(eu); err != nil { + return err } } return iter.Err() @@ -407,15 +423,11 @@ func convertContent(content *commands.Content, supportedContentType string) (new encode = cbor.Encode coapContentFormat = int32(message.AppCBOR) case message.AppOcfCbor.String(): - if encode == nil { - encode = cbor.Encode - coapContentFormat = int32(message.AppOcfCbor) - } + encode = cbor.Encode + coapContentFormat = int32(message.AppOcfCbor) case message.AppJSON.String(): - if encode == nil { - encode = json.Encode - coapContentFormat = int32(message.AppJSON) - } + encode = json.Encode + coapContentFormat = int32(message.AppJSON) } if encode == nil { @@ -450,7 +462,7 @@ func convertContent(content *commands.Content, supportedContentType string) (new } func (e *ResourceStateSnapshotTakenForCommand) confirmResourceUpdateRequest(ctx context.Context, req *commands.ConfirmResourceUpdateRequest, newVersion uint64) ([]eventstore.Event, error) { - if req.CommandMetadata == nil { + if req.GetCommandMetadata() == nil { return nil, status.Errorf(codes.InvalidArgument, errInvalidCommandMetadata) } @@ -633,7 +645,7 @@ func (e *ResourceStateSnapshotTakenForCommand) CancelPendingCommandsRequest(ctx } func (e *ResourceStateSnapshotTakenForCommand) handleNotifyResourceChangedRequest(ctx context.Context, req *commands.NotifyResourceChangedRequest, newVersion uint64) ([]eventstore.Event, error) { - if req.CommandMetadata == nil { + if req.GetCommandMetadata() == nil { return nil, status.Errorf(codes.InvalidArgument, errInvalidCommandMetadata) } diff --git a/resource-aggregate/events/resourceStateSnapshotTaken_test.go b/resource-aggregate/events/resourceStateSnapshotTaken_test.go index 383d3f343..805fcfb88 100644 --- a/resource-aggregate/events/resourceStateSnapshotTaken_test.go +++ b/resource-aggregate/events/resourceStateSnapshotTaken_test.go @@ -117,21 +117,21 @@ func TestEqual(t *testing.T) { ContentType: "text", CoapContentFormat: int32(message.TextPlain), }, - AuditContext: res.AuditContext, - Status: res.Status, + AuditContext: res.GetAuditContext(), + Status: res.GetStatus(), } resWithChangedAuditContext := events.ResourceChanged{ - Content: res.Content, + Content: res.GetContent(), AuditContext: &commands.AuditContext{ UserId: "502", }, - Status: res.Status, + Status: res.GetStatus(), } resWithChangedStatus := events.ResourceChanged{ - Content: res.Content, - AuditContext: res.AuditContext, + Content: res.GetContent(), + AuditContext: res.GetAuditContext(), Status: commands.Status_ERROR, } diff --git a/resource-aggregate/events/serviceMetadataSnapshotTaken.go b/resource-aggregate/events/serviceMetadataSnapshotTaken.go index 8ea150e85..7e166d845 100644 --- a/resource-aggregate/events/serviceMetadataSnapshotTaken.go +++ b/resource-aggregate/events/serviceMetadataSnapshotTaken.go @@ -2,6 +2,7 @@ package events import ( "context" + "errors" "fmt" "sort" "time" @@ -73,7 +74,7 @@ func (d *ServiceMetadataSnapshotTaken) CheckInitialized() bool { } func (d *ServiceMetadataSnapshotTaken) HandleServiceMetadataUpdated(_ context.Context, upd *ServiceMetadataUpdated) (bool, error) { - if d.ServiceMetadataUpdated.Equal(upd) { + if d.GetServiceMetadataUpdated().Equal(upd) { return false, nil } valid := make(map[string]*ServicesHeartbeat_Heartbeat, len(d.GetServiceMetadataUpdated().GetServicesHeartbeat().GetValid())+len(upd.GetServicesHeartbeat().GetValid())) @@ -322,7 +323,7 @@ func (d *ServiceMetadataSnapshotTaken) confirmExpiredServices(ctx context.Contex d.EventMetadata = em snapshot, ok := d.TakeSnapshot(em.GetVersion()) if !ok { - return nil, fmt.Errorf("cannot take snapshot") + return nil, errors.New("cannot take snapshot") } return []eventstore.Event{snapshot}, nil } diff --git a/resource-aggregate/events/serviceMetadataUpdated.go b/resource-aggregate/events/serviceMetadataUpdated.go index d79755a53..e1406f39a 100644 --- a/resource-aggregate/events/serviceMetadataUpdated.go +++ b/resource-aggregate/events/serviceMetadataUpdated.go @@ -55,8 +55,9 @@ func (d *ServiceMetadataUpdated) CopyData(event *ServiceMetadataUpdated) { d.EventMetadata = event.GetEventMetadata() d.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() - d.ServicesHeartbeat = &ServicesHeartbeat{} - d.ServicesHeartbeat.CopyData(event.GetServicesHeartbeat()) + sh := &ServicesHeartbeat{} + sh.CopyData(event.GetServicesHeartbeat()) + d.ServicesHeartbeat = sh } func (d *ServiceMetadataUpdated) CheckInitialized() bool { diff --git a/resource-aggregate/events/utils.go b/resource-aggregate/events/utils.go index de67bbeb6..6f4a97125 100644 --- a/resource-aggregate/events/utils.go +++ b/resource-aggregate/events/utils.go @@ -18,15 +18,15 @@ func MakeEventMeta(connectionID string, sequence, version uint64, hubID string) } func EqualResource(x, y *commands.Resource) bool { - return x.DeviceId == y.DeviceId && - EqualStringSlice(x.ResourceTypes, y.ResourceTypes) && - EqualStringSlice(x.Interfaces, y.Interfaces) && - x.Anchor == y.Anchor && - x.Title == y.Title && - EqualStringSlice(x.SupportedContentTypes, y.SupportedContentTypes) && - x.ValidUntil == y.ValidUntil && - ((x.Policy == nil && y.Policy == nil) || - (x.Policy != nil && y.Policy != nil && x.Policy.BitFlags == y.Policy.BitFlags)) + return x.GetDeviceId() == y.GetDeviceId() && + EqualStringSlice(x.GetResourceTypes(), y.GetResourceTypes()) && + EqualStringSlice(x.GetInterfaces(), y.GetInterfaces()) && + x.GetAnchor() == y.GetAnchor() && + x.GetTitle() == y.GetTitle() && + EqualStringSlice(x.GetSupportedContentTypes(), y.GetSupportedContentTypes()) && + x.GetValidUntil() == y.GetValidUntil() && + ((x.GetPolicy() == nil && y.GetPolicy() == nil) || + (x.GetPolicy() != nil && y.GetPolicy() != nil && x.GetPolicy().GetBitFlags() == y.GetPolicy().GetBitFlags())) } func EqualStringSlice(x, y []string) bool { diff --git a/resource-aggregate/events/utils_test.go b/resource-aggregate/events/utils_test.go index 6d5a3e625..f9dee92f6 100644 --- a/resource-aggregate/events/utils_test.go +++ b/resource-aggregate/events/utils_test.go @@ -94,8 +94,9 @@ func TestEqualResource(t *testing.T) { resInterfacesNil.Interfaces = nil resInterfaces2 := createResource() - resInterfaces2.Interfaces = make([]string, 1) - copy(resInterfaces2.Interfaces, res.Interfaces) + interfaces := make([]string, 1) + copy(interfaces, res.GetInterfaces()) + resInterfaces2.Interfaces = interfaces resAnchor := createResource() resAnchor.Anchor = "Anchor2" diff --git a/resource-aggregate/service/aggregate_test.go b/resource-aggregate/service/aggregate_test.go index 7885f9aaa..d1730c875 100644 --- a/resource-aggregate/service/aggregate_test.go +++ b/resource-aggregate/service/aggregate_test.go @@ -2,7 +2,7 @@ package service_test import ( "context" - "fmt" + "errors" "testing" "time" @@ -27,7 +27,6 @@ import ( raTest "github.com/plgd-dev/hub/v2/resource-aggregate/test" hubTest "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/grpc/codes" @@ -99,12 +98,12 @@ func TestAggregateHandlePublishResourceLinks(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -113,7 +112,7 @@ func TestAggregateHandlePublishResourceLinks(t *testing.T) { naClient.Close() }() - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range test { tfunc := func(t *testing.T) { ag, err := service.NewAggregate(commands.NewResourceID(tt.args.request.GetDeviceId(), commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(tt.args.userID, tt.args.owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) @@ -123,7 +122,7 @@ func TestAggregateHandlePublishResourceLinks(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.want, s.Code()) + require.Equal(t, tt.want, s.Code()) } else { require.NoError(t, err) service.PublishEvents(publisher, tt.args.userID, tt.args.request.GetDeviceId(), ag.ResourceID(), events, logger) @@ -137,7 +136,7 @@ func testHandlePublishResource(ctx context.Context, t *testing.T, publisher *pub pc := testMakePublishResourceRequest(deviceID, hrefs) ag, err := service.NewAggregate(commands.NewResourceID(pc.GetDeviceId(), commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, hubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) events, err := ag.PublishResourceLinks(ctx, pc) require.NoError(t, err) service.PublishEvents(publisher, userID, deviceID, ag.ResourceID(), events, log.Get()) @@ -150,7 +149,7 @@ func TestAggregateDuplicitPublishResource(t *testing.T) { const owner = "owner" pool, err := ants.NewPool(16) - assert.NoError(t, err) + require.NoError(t, err) defer pool.Release() cfg := raTest.MakeConfig(t) @@ -172,7 +171,7 @@ func TestAggregateDuplicitPublishResource(t *testing.T) { require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) @@ -181,21 +180,21 @@ func TestAggregateDuplicitPublishResource(t *testing.T) { events, err := ag.PublishResourceLinks(ctx, pc1) require.NoError(t, err) - assert.Equal(t, 1, len(events)) + require.Len(t, events, 1) ag2, err := service.NewAggregate(commands.NewResourceID(deviceID, commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) require.NoError(t, err) pc2 := testMakePublishResourceRequest(deviceID, []string{resourceID}) events, err = ag2.PublishResourceLinks(ctx, pc2) require.NoError(t, err) - assert.Empty(t, events) + require.Empty(t, events) ag3, err := service.NewAggregate(commands.NewResourceID(deviceID, commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) require.NoError(t, err) pc3 := testMakePublishResourceRequest(deviceID, []string{resourceID, resourceID, resourceID}) events, err = ag3.PublishResourceLinks(ctx, pc3) require.NoError(t, err) - assert.Empty(t, events) + require.Empty(t, events) } func TestAggregateHandleUnpublishResource(t *testing.T) { @@ -224,12 +223,12 @@ func TestAggregateHandleUnpublishResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -243,14 +242,14 @@ func TestAggregateHandleUnpublishResource(t *testing.T) { pc := testMakeUnpublishResourceRequest(deviceID, []string{resourceID}) ag, err := service.NewAggregate(commands.NewResourceID(pc.GetDeviceId(), commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) events, err := ag.UnpublishResourceLinks(ctx, pc) - assert.NoError(t, err) + require.NoError(t, err) service.PublishEvents(publisher, userID, deviceID, ag.ResourceID(), events, logger) _, err = ag.UnpublishResourceLinks(ctx, pc) - assert.NoError(t, err) + require.NoError(t, err) } func TestAggregateHandleUnpublishAllResources(t *testing.T) { @@ -278,12 +277,12 @@ func TestAggregateHandleUnpublishAllResources(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -297,14 +296,14 @@ func TestAggregateHandleUnpublishAllResources(t *testing.T) { pc := testMakeUnpublishResourceRequest(deviceID, []string{}) ag, err := service.NewAggregate(commands.NewResourceID(pc.GetDeviceId(), commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) events, err := ag.UnpublishResourceLinks(ctx, pc) - assert.NoError(t, err) - assert.Equal(t, 1, len(events)) + require.NoError(t, err) + require.Len(t, events, 1) unpublishedResourceLinks := (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs - assert.Equal(t, 3, len(unpublishedResourceLinks)) - assert.Contains(t, unpublishedResourceLinks, resourceID1, resourceID2, resourceID3) + require.Len(t, unpublishedResourceLinks, 3) + require.Contains(t, unpublishedResourceLinks, resourceID1, resourceID2, resourceID3) service.PublishEvents(publisher, userID, deviceID, ag.ResourceID(), events, logger) @@ -339,12 +338,12 @@ func TestAggregateHandleUnpublishResourceSubset(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -356,20 +355,20 @@ func TestAggregateHandleUnpublishResourceSubset(t *testing.T) { testHandlePublishResource(ctx, t, publisher, eventstore, userID, deviceID, owner, cfg.HubID, []string{resourceID1, resourceID2, resourceID3, resourceID4}) ag, err := service.NewAggregate(commands.NewResourceID(deviceID, commands.ResourceLinksHref), eventstore, service.NewResourceLinksFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) pc := testMakeUnpublishResourceRequest(deviceID, []string{resourceID1, resourceID3}) events, err := ag.UnpublishResourceLinks(ctx, pc) - assert.NoError(t, err) - assert.Equal(t, 1, len(events)) - assert.Equal(t, []string{resourceID1, resourceID3}, (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs) + require.NoError(t, err) + require.Len(t, events, 1) + require.Equal(t, []string{resourceID1, resourceID3}, (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs) service.PublishEvents(publisher, userID, deviceID, ag.ResourceID(), events, logger) pc = testMakeUnpublishResourceRequest(deviceID, []string{resourceID1, resourceID4, resourceID4}) events, err = ag.UnpublishResourceLinks(ctx, pc) - assert.NoError(t, err) - assert.Equal(t, 1, len(events)) - assert.Equal(t, []string{resourceID4}, (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs) + require.NoError(t, err) + require.Len(t, events, 1) + require.Equal(t, []string{resourceID4}, (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs) } func testMakePublishResourceRequest(deviceID string, href []string) *commands.PublishResourceLinksRequest { @@ -652,12 +651,12 @@ func TestAggregateHandleNotifyContentChanged(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -669,7 +668,7 @@ func TestAggregateHandleNotifyContentChanged(t *testing.T) { testHandlePublishResource(ctx, t, publisher, eventstore, userID, deviceID, owner, cfg.HubID, []string{resourceID}) ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -678,12 +677,12 @@ func TestAggregateHandleNotifyContentChanged(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } }) } @@ -770,16 +769,16 @@ func TestAggregateHandleUpdateResourceContent(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -793,12 +792,12 @@ func TestAggregateHandleUpdateResourceContent(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } time.Sleep(tt.args.sleep) }) @@ -857,12 +856,12 @@ func TestAggregateHandleConfirmResourceUpdate(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) @@ -884,12 +883,12 @@ func TestAggregateHandleConfirmResourceUpdate(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } }) } @@ -967,16 +966,16 @@ func TestAggregateHandleRetrieveResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -989,12 +988,12 @@ func TestAggregateHandleRetrieveResource(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } time.Sleep(tt.args.sleep) }) @@ -1053,16 +1052,16 @@ func TestAggregateHandleNotifyResourceContentResourceProcessed(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) _, err = ag.NotifyResourceChanged(ctx, testMakeNotifyResourceChangedRequest(deviceID, resourceID, 0)) require.NoError(t, err) @@ -1080,12 +1079,12 @@ func TestAggregateHandleNotifyResourceContentResourceProcessed(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } }) } @@ -1093,7 +1092,7 @@ func TestAggregateHandleNotifyResourceContentResourceProcessed(t *testing.T) { func testListDevicesOfUserFunc(userID string) ([]string, codes.Code, error) { if userID == testUnauthorizedUser { - return nil, codes.Unauthenticated, fmt.Errorf("unauthorized access") + return nil, codes.Unauthenticated, errors.New("unauthorized access") } return testUserDevices, codes.OK, nil } @@ -1171,16 +1170,16 @@ func TestAggregateHandleDeleteResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1193,12 +1192,12 @@ func TestAggregateHandleDeleteResource(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } time.Sleep(tt.args.sleep) }) @@ -1258,16 +1257,16 @@ func TestAggregateHandleConfirmResourceDelete(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) _, err = ag.NotifyResourceChanged(ctx, testMakeNotifyResourceChangedRequest(deviceID, resourceID, 0)) require.NoError(t, err) @@ -1285,13 +1284,13 @@ func TestAggregateHandleConfirmResourceDelete(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } }) } @@ -1369,16 +1368,16 @@ func TestAggregateHandleCreateResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1391,12 +1390,12 @@ func TestAggregateHandleCreateResource(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } time.Sleep(tt.args.sleep) }) @@ -1456,16 +1455,16 @@ func TestAggregateHandleConfirmResourceCreate(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() ag, err := service.NewAggregate(commands.NewResourceID(deviceID, resourceID), eventstore, service.NewResourceStateFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) - assert.NoError(t, err) + require.NoError(t, err) _, err = ag.NotifyResourceChanged(ctx, testMakeNotifyResourceChangedRequest(deviceID, resourceID, 0)) require.NoError(t, err) @@ -1483,13 +1482,13 @@ func TestAggregateHandleConfirmResourceCreate(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.wantStatusCode, s.Code()) + require.Equal(t, tt.wantStatusCode, s.Code()) return } require.NoError(t, err) if tt.wantEvents { - assert.NotEmpty(t, gotEvents) + require.NotEmpty(t, gotEvents) } }) } diff --git a/resource-aggregate/service/cancelDeviceMetadataUpdates_test.go b/resource-aggregate/service/cancelDeviceMetadataUpdates_test.go index ec3501ab5..d4cdf4088 100644 --- a/resource-aggregate/service/cancelDeviceMetadataUpdates_test.go +++ b/resource-aggregate/service/cancelDeviceMetadataUpdates_test.go @@ -89,12 +89,12 @@ func TestAggregateHandleCancelPendingMetadataUpdates(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -212,12 +212,12 @@ func TestRequestHandlerCancelPendingMetadataUpdates(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -244,10 +244,10 @@ func TestRequestHandlerCancelPendingMetadataUpdates(t *testing.T) { for _, tt := range test { tfunc := func(t *testing.T) { - ctx := kitNetGrpc.CtxWithIncomingToken(ctx, config.CreateJwtToken(t, jwt.MapClaims{ + cpmuCtx := kitNetGrpc.CtxWithIncomingToken(ctx, config.CreateJwtToken(t, jwt.MapClaims{ "sub": tt.args.userID, })) - want, err := requestHandler.CancelPendingMetadataUpdates(ctx, tt.args.request) + want, err := requestHandler.CancelPendingMetadataUpdates(cpmuCtx, tt.args.request) if tt.wantErr { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) diff --git a/resource-aggregate/service/cancelResourceCommands_test.go b/resource-aggregate/service/cancelResourceCommands_test.go index 614021c52..76bdd1ed0 100644 --- a/resource-aggregate/service/cancelResourceCommands_test.go +++ b/resource-aggregate/service/cancelResourceCommands_test.go @@ -162,12 +162,12 @@ func TestRequestHandlerCancelPendingCommands(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) diff --git a/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go b/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go index 31eb7d9bc..41fad2923 100644 --- a/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go +++ b/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go @@ -84,12 +84,12 @@ func TestAggregateHandleConfirmDeviceMetadataUpdate(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -187,12 +187,12 @@ func TestRequestHandlerConfirmDeviceMetadataUpdate(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) diff --git a/resource-aggregate/service/grpcApi_test.go b/resource-aggregate/service/grpcApi_test.go index bd3441083..43752408d 100644 --- a/resource-aggregate/service/grpcApi_test.go +++ b/resource-aggregate/service/grpcApi_test.go @@ -113,12 +113,12 @@ func TestRequestHandlerPublishResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -136,9 +136,9 @@ func TestRequestHandlerPublishResource(t *testing.T) { tfunc := func(t *testing.T) { response, err := requestHandler.PublishResourceLinks(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } if tt.want != nil { assert.Equal(t, tt.want.AuditContext, response.AuditContext) @@ -232,12 +232,12 @@ func TestRequestHandlerUnpublishResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -253,7 +253,7 @@ func TestRequestHandlerUnpublishResource(t *testing.T) { pubReq := testMakePublishResourceRequest(deviceID, []string{href}) _, err = requestHandler.PublishResourceLinks(ctx, pubReq) - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range test { tfunc := func(t *testing.T) { @@ -262,9 +262,9 @@ func TestRequestHandlerUnpublishResource(t *testing.T) { })) response, err := requestHandler.UnpublishResourceLinks(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tt.want, response) } @@ -321,12 +321,12 @@ func TestRequestHandlerNotifyResourceChanged(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -344,9 +344,9 @@ func TestRequestHandlerNotifyResourceChanged(t *testing.T) { tfunc := func(t *testing.T) { response, err := requestHandler.NotifyResourceChanged(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tt.want, response) } @@ -422,12 +422,12 @@ func TestRequestHandlerUpdateResourceContent(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -448,7 +448,7 @@ func TestRequestHandlerUpdateResourceContent(t *testing.T) { } response, err := requestHandler.UpdateResource(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) @@ -519,12 +519,12 @@ func TestRequestHandlerConfirmResourceUpdate(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -547,9 +547,9 @@ func TestRequestHandlerConfirmResourceUpdate(t *testing.T) { tfunc := func(t *testing.T) { response, err := requestHandler.ConfirmResourceUpdate(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tt.want, response) } @@ -614,12 +614,12 @@ func TestRequestHandlerRetrieveResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -640,7 +640,7 @@ func TestRequestHandlerRetrieveResource(t *testing.T) { } response, err := requestHandler.RetrieveResource(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) @@ -711,12 +711,12 @@ func TestRequestHandlerConfirmResourceRetrieve(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -742,9 +742,9 @@ func TestRequestHandlerConfirmResourceRetrieve(t *testing.T) { } response, err := requestHandler.ConfirmResourceRetrieve(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) } else { - assert.NoError(t, err) + require.NoError(t, err) } assert.Equal(t, tt.want, response) } @@ -809,12 +809,12 @@ func TestRequestHandlerDeleteResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -836,7 +836,7 @@ func TestRequestHandlerDeleteResource(t *testing.T) { } response, err := requestHandler.DeleteResource(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) @@ -907,12 +907,12 @@ func TestRequestHandlerConfirmResourceDelete(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -938,7 +938,7 @@ func TestRequestHandlerConfirmResourceDelete(t *testing.T) { } response, err := requestHandler.ConfirmResourceDelete(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) @@ -1005,12 +1005,12 @@ func TestRequestHandlerCreateResource(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -1032,7 +1032,7 @@ func TestRequestHandlerCreateResource(t *testing.T) { } response, err := requestHandler.CreateResource(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) @@ -1103,12 +1103,12 @@ func TestRequestHandlerConfirmResourceCreate(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -1134,7 +1134,7 @@ func TestRequestHandlerConfirmResourceCreate(t *testing.T) { } response, err := requestHandler.ConfirmResourceCreate(ctx, tt.args.request) if tt.wantError { - assert.Error(t, err) + require.Error(t, err) return } require.NoError(t, err) diff --git a/resource-aggregate/service/updateDeviceMetadata_test.go b/resource-aggregate/service/updateDeviceMetadata_test.go index 5ca336f71..1bd7c32d2 100644 --- a/resource-aggregate/service/updateDeviceMetadata_test.go +++ b/resource-aggregate/service/updateDeviceMetadata_test.go @@ -105,12 +105,12 @@ func TestAggregateHandleUpdateDeviceMetadata(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, cfg.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(cfg.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -119,7 +119,7 @@ func TestAggregateHandleUpdateDeviceMetadata(t *testing.T) { naClient.Close() }() - assert.NoError(t, err) + require.NoError(t, err) for _, tt := range test { tfunc := func(t *testing.T) { ag, err := service.NewAggregate(commands.NewResourceID(tt.args.request.GetDeviceId(), commands.StatusHref), eventstore, service.NewDeviceMetadataFactoryModel(userID, owner, cfg.HubID), cqrsAggregate.NewDefaultRetryFunc(1)) @@ -235,12 +235,12 @@ func TestRequestHandlerUpdateDeviceMetadata(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) diff --git a/resource-aggregate/service/updateServiceHeartbeat.go b/resource-aggregate/service/updateServiceHeartbeat.go index 9084c8ead..245f36a9c 100644 --- a/resource-aggregate/service/updateServiceHeartbeat.go +++ b/resource-aggregate/service/updateServiceHeartbeat.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "sync" "time" @@ -336,10 +337,10 @@ func (s *ServiceHeartbeat) pop() []UpdateServiceMetadataReqResp { func (s *ServiceHeartbeat) ProcessRequest(r UpdateServiceMetadataReqResp) error { if r.Request == nil { - return fmt.Errorf("invalid request") + return errors.New("invalid request") } if r.ResponseChan == nil { - return fmt.Errorf("invalid response channel") + return errors.New("invalid response channel") } s.push(r) s.wakeUp() diff --git a/resource-aggregate/service/updateServiceHeartbeat_test.go b/resource-aggregate/service/updateServiceHeartbeat_test.go index d97a03997..db6ca48ec 100644 --- a/resource-aggregate/service/updateServiceHeartbeat_test.go +++ b/resource-aggregate/service/updateServiceHeartbeat_test.go @@ -17,7 +17,6 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/utils" "github.com/plgd-dev/hub/v2/resource-aggregate/service" raTest "github.com/plgd-dev/hub/v2/resource-aggregate/test" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" ) @@ -37,12 +36,12 @@ func TestNewServiceHeartbeat(t *testing.T) { err = eventstore.Clear(ctx) require.NoError(t, err) err = eventstore.Close(ctx) - assert.NoError(t, err) + require.NoError(t, err) eventstore, err = mongodb.New(ctx, config.Clients.Eventstore.Connection.MongoDB, fileWatcher, logger, noop.NewTracerProvider(), mongodb.WithUnmarshaler(utils.Unmarshal), mongodb.WithMarshaler(utils.Marshal)) require.NoError(t, err) defer func() { errC := eventstore.Close(ctx) - assert.NoError(t, errC) + require.NoError(t, errC) }() naClient, publisher, err := natsTest.NewClientAndPublisher(config.Clients.Eventbus.NATS, fileWatcher, logger, publisher.WithMarshaler(utils.Marshal)) require.NoError(t, err) @@ -74,7 +73,7 @@ func TestNewServiceHeartbeat(t *testing.T) { }, ResponseChan: chans[j], }) - assert.NoError(t, err) + require.NoError(t, err) }(i) } wg.Wait() @@ -87,15 +86,15 @@ func TestNewServiceHeartbeat(t *testing.T) { chosen, value, ok := reflect.Select(cases) if ok { if chosen == 0 { - assert.Fail(t, "context canceled") + require.Fail(t, "context canceled") } if chosen != 0 { data := value.Interface().(service.UpdateServiceMetadataResponseChanData) - assert.NoError(t, data.Err) + require.NoError(t, data.Err) } } if !ok { - assert.Fail(t, "channel closed") + require.Fail(t, "channel closed") break } } diff --git a/resource-directory/service/deviceDirectory.go b/resource-directory/service/deviceDirectory.go index 31c4764f0..20660d1aa 100644 --- a/resource-directory/service/deviceDirectory.go +++ b/resource-directory/service/deviceDirectory.go @@ -1,6 +1,7 @@ package service import ( + "errors" "fmt" "github.com/plgd-dev/device/v2/schema/device" @@ -52,7 +53,7 @@ func NewDeviceDirectory(projection *Projection, deviceIds []string) *DeviceDirec func decodeContent(content *commands.Content, v interface{}) error { if content == nil { - return fmt.Errorf("cannot parse empty content") + return errors.New("cannot parse empty content") } var decoder func([]byte, interface{}) error diff --git a/resource-directory/service/getPendingCommands_test.go b/resource-directory/service/getPendingCommands_test.go index 5193f3573..f3a01667d 100644 --- a/resource-directory/service/getPendingCommands_test.go +++ b/resource-directory/service/getPendingCommands_test.go @@ -350,9 +350,9 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { secureGWShutdown() createFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -362,27 +362,27 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { }, TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errC) } createFn(time.Millisecond * 500) // for test expired event createFn(0) retrieveFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, platform.ResourceURI), TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn(time.Millisecond * 500) // for test expired event retrieveFn(0) updateFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -392,32 +392,32 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { }, TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errU) } updateFn(time.Millisecond * 500) // for test expired event updateFn(0) deleteFn := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, device.ResourceURI), TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn(time.Millisecond * 500) // for test expired event deleteFn(0) updateDeviceMetadata := func(timeToLive time.Duration) { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(updateCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, TimeToLive: int64(timeToLive), }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadata(time.Millisecond * 500) // for test expired event updateDeviceMetadata(0) // for test expired event diff --git a/resource-directory/service/resourceDirectory_test.go b/resource-directory/service/resourceDirectory_test.go index 02218cfdd..5e44afdb3 100644 --- a/resource-directory/service/resourceDirectory_test.go +++ b/resource-directory/service/resourceDirectory_test.go @@ -20,7 +20,6 @@ import ( "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" pbTest "github.com/plgd-dev/hub/v2/test/pb" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" ) @@ -86,7 +85,7 @@ func TestResourceDirectoryGetResourceLinks(t *testing.T) { var s testGrpcGateway_GetResourceLinksServer err := rd.GetResourceLinks(tt.args.request, &s) require.NoError(t, err) - test.CheckProtobufs(t, tt.want, s.got, test.AssertToCheckFunc(assert.Equal)) + test.CheckProtobufs(t, tt.want, s.got, test.RequireToCheckFunc(require.Equal)) } t.Run(tt.name, fn) } diff --git a/resource-directory/service/resourceShadow_test.go b/resource-directory/service/resourceShadow_test.go index df326fe8e..b5daead33 100644 --- a/resource-directory/service/resourceShadow_test.go +++ b/resource-directory/service/resourceShadow_test.go @@ -19,7 +19,6 @@ import ( "github.com/plgd-dev/hub/v2/resource-directory/service" "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" ) @@ -235,8 +234,8 @@ func TestResourceTwinGetResources(t *testing.T) { fmt.Println(tt.name) var s testGrpcGateway_GetResourcesServer err := rd.GetResources(tt.args.req, &s) - assert.NoError(t, err) - test.CheckProtobufs(t, tt.want, s.got, test.AssertToCheckFunc(assert.Equal)) + require.NoError(t, err) + test.CheckProtobufs(t, tt.want, s.got, test.RequireToCheckFunc(require.Equal)) }) } } diff --git a/test/coap-gateway/service/resourceDirectory.go b/test/coap-gateway/service/resourceDirectory.go index 3188fe7e9..d14a81d0d 100644 --- a/test/coap-gateway/service/resourceDirectory.go +++ b/test/coap-gateway/service/resourceDirectory.go @@ -1,6 +1,7 @@ package service import ( + "errors" "fmt" "net/url" "regexp" @@ -58,7 +59,7 @@ func resourceDirectoryPublishHandler(req *mux.Message, client *Client) { } p.SequenceNumber = req.Sequence() - if err := client.handler.PublishResources(p); err != nil { + if err = client.handler.PublishResources(p); err != nil { client.logAndWriteErrorResponse(err, coapCodes.InternalServerError, req.Token()) return } @@ -99,7 +100,7 @@ func parseUnpublishRequestFromQuery(queries []string) (UnpublishRequest, error) } if req.DeviceID == "" { - return UnpublishRequest{}, fmt.Errorf("deviceID not found") + return UnpublishRequest{}, errors.New("deviceID not found") } return req, nil diff --git a/test/coap-gateway/service/service.go b/test/coap-gateway/service/service.go index 9d407c989..9586308ef 100644 --- a/test/coap-gateway/service/service.go +++ b/test/coap-gateway/service/service.go @@ -2,6 +2,7 @@ package service import ( "context" + "errors" "fmt" "os" "os/signal" @@ -154,7 +155,7 @@ func validateCommand(s mux.ResponseWriter, req *mux.Message, server *Service, fn fnc(req, client) case coapCodes.Empty: if !ok { - client.logAndWriteErrorResponse(fmt.Errorf("cannot handle command: client not found"), coapCodes.InternalServerError, req.Token()) + client.logAndWriteErrorResponse(errors.New("cannot handle command: client not found"), coapCodes.InternalServerError, req.Token()) closeClient(client) return } diff --git a/test/http/request.go b/test/http/request.go index 600475108..17f64a5a8 100644 --- a/test/http/request.go +++ b/test/http/request.go @@ -3,6 +3,7 @@ package http import ( "context" "crypto/tls" + "errors" "fmt" "io" "net/http" @@ -42,7 +43,7 @@ func NewHTTPRequest(method, url string, body io.Reader) *HTTPRequestBuilder { } func (c *HTTPRequestBuilder) AuthToken(token string) *HTTPRequestBuilder { - c.header["Authorization"] = fmt.Sprintf("bearer %s", token) + c.header["Authorization"] = "bearer " + token return c } @@ -144,7 +145,7 @@ func DoHTTPRequest(t *testing.T, req *http.Request) *http.Response { func ReadHTTPResponse(t *testing.T, w io.Reader, contentType string, data interface{}) { readFrom := func(_ io.Reader, _ interface{}) error { - return fmt.Errorf("not supported") + return errors.New("not supported") } switch contentType { case message.AppJSON.String(): @@ -159,7 +160,7 @@ func ReadHTTPResponse(t *testing.T, w io.Reader, contentType string, data interf } val := reflect.ValueOf(v) if val.Kind() != reflect.Ptr { - return fmt.Errorf("some: check must be a pointer") + return errors.New("some: check must be a pointer") } val.Elem().Set(reflect.ValueOf(string(b))) return nil diff --git a/test/iotivity-lite/service/offboard_test.go b/test/iotivity-lite/service/offboard_test.go index 06ba674c4..245ea010f 100644 --- a/test/iotivity-lite/service/offboard_test.go +++ b/test/iotivity-lite/service/offboard_test.go @@ -3,7 +3,7 @@ package service_test import ( "context" "crypto/tls" - "fmt" + "errors" "strings" "sync" "testing" @@ -21,7 +21,6 @@ import ( iotService "github.com/plgd-dev/hub/v2/test/iotivity-lite/service" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/atomic" "google.golang.org/grpc" @@ -50,13 +49,13 @@ func TestOffboard(t *testing.T) { log.Debugf("%+v", h.CallCounter.Data) signInCount, ok := h.CallCounter.Data[iotService.SignInKey] require.True(t, ok) - require.True(t, signInCount > 0) + require.Greater(t, signInCount, 0) publishCount, ok := h.CallCounter.Data[iotService.PublishKey] require.True(t, ok) require.Equal(t, 1, publishCount) singOffCount, ok := h.CallCounter.Data[iotService.SignOffKey] require.True(t, ok) - require.True(t, singOffCount > 0) + require.Greater(t, singOffCount, 0) } coapShutdown := coapgwTest.SetUp(t, makeHandler, validateHandler) @@ -120,7 +119,7 @@ func (sh *switchableHandler) blockSignInChannel() chan struct{} { func (sh *switchableHandler) SignIn(req coapgwService.CoapSignInReq) (coapgwService.CoapSignInResp, error) { resp, err := sh.CoapHandlerWithCounter.SignIn(req) if sh.failSignIn.Load() { - return coapgwService.CoapSignInResp{}, fmt.Errorf("sign in disabled") + return coapgwService.CoapSignInResp{}, errors.New("sign in disabled") } b := sh.blockSignInChannel() if b != nil { @@ -146,7 +145,7 @@ func (sh *switchableHandler) blockSignOff() chan struct{} { func (sh *switchableHandler) SignOff() error { err := sh.CoapHandlerWithCounter.SignOff() if sh.failSignOff.Load() { - return fmt.Errorf("sign off disabled") + return errors.New("sign off disabled") } b := sh.blockSignOffChannel() if b != nil { @@ -172,7 +171,7 @@ func (sh *switchableHandler) blockRefresh() chan struct{} { func (sh *switchableHandler) RefreshToken(req coapgwService.CoapRefreshTokenReq) (coapgwService.CoapRefreshTokenResp, error) { resp, err := sh.CoapHandlerWithCounter.RefreshToken(req) if sh.failRefreshToken.Load() { - return coapgwService.CoapRefreshTokenResp{}, fmt.Errorf("refresh token disabled") + return coapgwService.CoapRefreshTokenResp{}, errors.New("refresh token disabled") } b := sh.blockRefreshChannel() if b != nil { @@ -334,14 +333,14 @@ func TestOffboardWithSignInByRefreshToken(t *testing.T) { defer h.CallCounter.Lock.Unlock() log.Debugf("%+v", h.CallCounter.Data) signInCount, ok := h.CallCounter.Data[iotService.SignInKey] - assert.True(t, ok) - assert.True(t, signInCount > 1) + require.True(t, ok) + require.Greater(t, signInCount, 1) refreshCount, ok := h.CallCounter.Data[iotService.RefreshTokenKey] - assert.True(t, ok) - assert.True(t, refreshCount > 0) + require.True(t, ok) + require.Greater(t, refreshCount, 0) signOffCount, ok := h.CallCounter.Data[iotService.SignOffKey] - assert.True(t, ok) - assert.Equal(t, 1, signOffCount) + require.True(t, ok) + require.Equal(t, 1, signOffCount) } coapShutdown := coapgwTest.SetUp(t, makeHandler, func(coapgwTestService.ServiceHandler) {}) diff --git a/test/iotivity-lite/service/republish_test.go b/test/iotivity-lite/service/republish_test.go index 404e4a365..f70ad22af 100644 --- a/test/iotivity-lite/service/republish_test.go +++ b/test/iotivity-lite/service/republish_test.go @@ -42,10 +42,10 @@ func TestRepublishAfterRefresh(t *testing.T) { log.Debugf("%+v", h.CallCounter.Data) signInCount, ok := h.CallCounter.Data[iotService.SignInKey] require.True(t, ok) - require.True(t, signInCount > 1) + require.Greater(t, signInCount, 1) refreshCount, ok := h.CallCounter.Data[iotService.RefreshTokenKey] require.True(t, ok) - require.True(t, refreshCount > 0) + require.Greater(t, refreshCount, 0) publishCount, ok := h.CallCounter.Data[iotService.PublishKey] require.True(t, ok) require.Equal(t, 1, publishCount) diff --git a/test/oauth-server/service/getJWKs_test.go b/test/oauth-server/service/getJWKs_test.go index 8a7994372..2c3e10792 100644 --- a/test/oauth-server/service/getJWKs_test.go +++ b/test/oauth-server/service/getJWKs_test.go @@ -29,6 +29,6 @@ func getJWKs(t *testing.T) map[string]interface{} { err := json.ReadFrom(res.Body, &body) require.NoError(t, err) require.NotEmpty(t, body["keys"]) - require.Equal(t, 2, len(body["keys"].([]interface{}))) + require.Len(t, body["keys"].([]interface{}), 2) return body } diff --git a/test/oauth-server/service/loadKeys.go b/test/oauth-server/service/loadKeys.go index 908199024..683dadf40 100644 --- a/test/oauth-server/service/loadKeys.go +++ b/test/oauth-server/service/loadKeys.go @@ -3,7 +3,7 @@ package service import ( "crypto/x509" "encoding/pem" - "fmt" + "errors" "github.com/plgd-dev/hub/v2/pkg/config/property/urischeme" ) @@ -15,7 +15,7 @@ func LoadPrivateKey(path urischeme.URIScheme) (interface{}, error) { } certDERBlock, _ := pem.Decode(certPEMBlock) if certDERBlock == nil { - return nil, fmt.Errorf("cannot decode pem block") + return nil, errors.New("cannot decode pem block") } if key, err := x509.ParsePKCS8PrivateKey(certDERBlock.Bytes); err == nil { @@ -27,5 +27,5 @@ func LoadPrivateKey(path urischeme.URIScheme) (interface{}, error) { if key, err := x509.ParsePKCS1PrivateKey(certDERBlock.Bytes); err == nil { return key, nil } - return nil, fmt.Errorf("unknown type") + return nil, errors.New("unknown type") } diff --git a/test/oauth-server/service/token.go b/test/oauth-server/service/token.go index cd53a91d5..50cd3e0e2 100644 --- a/test/oauth-server/service/token.go +++ b/test/oauth-server/service/token.go @@ -4,6 +4,7 @@ import ( "crypto/rand" "crypto/rsa" "encoding/hex" + "errors" "fmt" "net/http" "strings" @@ -234,7 +235,7 @@ func (requestHandler *RequestHandler) getToken(w http.ResponseWriter, r *http.Re if clientID == "" { clientID, _, ok = r.BasicAuth() if !ok { - writeError(w, fmt.Errorf("authorization header is not set"), http.StatusBadRequest) + writeError(w, errors.New("authorization header is not set"), http.StatusBadRequest) return } } @@ -303,7 +304,7 @@ func (requestHandler *RequestHandler) validateTokenRequest(clientCfg *Client, to return fmt.Errorf("client(%v) not found", tokenReq.ClientID) } if clientCfg.ClientSecret != "" && clientCfg.ClientSecret != tokenReq.Password { - return fmt.Errorf("invalid client secret") + return errors.New("invalid client secret") } if clientCfg.RequiredRedirectURI != "" && clientCfg.RequiredRedirectURI != tokenReq.RedirectURI { return fmt.Errorf("invalid redirect uri(%v)", tokenReq.RedirectURI) diff --git a/test/oauth-server/service/token_test.go b/test/oauth-server/service/token_test.go index 2a148195e..a2ebf51c1 100644 --- a/test/oauth-server/service/token_test.go +++ b/test/oauth-server/service/token_test.go @@ -63,7 +63,7 @@ func TestRequestHandlerGetTokenWithDefaultScopes(t *testing.T) { token := getToken(t, test.ClientTest, "", "", "", code, "", "", "", service.AllowedGrantType_AUTHORIZATION_CODE, http.StatusOK) require.NotEmpty(t, token["access_token"]) - require.Equal(t, token["scope"], service.DefaultScope) + require.Equal(t, service.DefaultScope, token["scope"]) validator := test.GetJWTValidator(fmt.Sprintf("https://%s%s", config.OAUTH_SERVER_HOST, uri.JWKs)) accessToken, err := validator.Parse(token["access_token"]) require.NoError(t, err) @@ -78,7 +78,7 @@ func TestRequestHandlerGetTokenWithCuscomScopes(t *testing.T) { token := getToken(t, test.ClientTest, "", "", "", code, "", "", "", service.AllowedGrantType_AUTHORIZATION_CODE, http.StatusOK) require.NotEmpty(t, token["access_token"]) - require.Equal(t, token["scope"], "r:* w:*") + require.Equal(t, "r:* w:*", token["scope"]) validator := test.GetJWTValidator(fmt.Sprintf("https://%s%s", config.OAUTH_SERVER_HOST, uri.JWKs)) accessToken, err := validator.Parse(token["access_token"]) require.NoError(t, err) @@ -125,7 +125,7 @@ func TestRequestHandlerGetTokenWithValidRequiredParams(t *testing.T) { code := getAuthorize(t, test.ClientTestRequiredParams, "", "http://localhost:7777", "", "r:*", "code", http.StatusFound, false, false) token := getToken(t, test.ClientTestRequiredParams, test.ClientTestRequiredParamsSecret, "", "http://localhost:7777", code, "", "", "", service.AllowedGrantType_AUTHORIZATION_CODE, http.StatusOK) require.NotEmpty(t, token["access_token"]) - require.Equal(t, token["scope"], "r:*") + require.Equal(t, "r:*", token["scope"]) validator := test.GetJWTValidator(fmt.Sprintf("https://%s%s", config.OAUTH_SERVER_HOST, uri.JWKs)) accessToken, err := validator.Parse(token["access_token"]) require.NoError(t, err) @@ -153,7 +153,7 @@ func TestRequestHandlerGetTokenWithValidRefreshToken(t *testing.T) { token := getToken(t, test.ClientTest, test.ClientTestRequiredParamsSecret, "invalidRefreshToken", "http://localhost:7777", "", "refresh-token", "", "", service.AllowedGrantType_REFRESH_TOKEN, http.StatusOK) require.NotEmpty(t, token["access_token"]) - require.Equal(t, token["scope"], service.DefaultScope) + require.Equal(t, service.DefaultScope, token["scope"]) validator := test.GetJWTValidator(fmt.Sprintf("https://%s%s", config.OAUTH_SERVER_HOST, uri.JWKs)) accessToken, err := validator.Parse(token["access_token"]) require.NoError(t, err) @@ -229,12 +229,12 @@ func TestGetRequestHandlerGetTokenWithDeviceIDAndOwnerClaim(t *testing.T) { if tt.wantDeviceID == "" { require.Empty(t, claims[uri.DeviceIDClaimKey]) } else { - require.Equal(t, claims[uri.DeviceIDClaimKey], tt.wantDeviceID) + require.Equal(t, tt.wantDeviceID, claims[uri.DeviceIDClaimKey]) } if tt.wantOwner == "" { require.Empty(t, claims[uri.OwnerClaimKey]) } else { - require.Equal(t, claims[uri.OwnerClaimKey], tt.wantOwner) + require.Equal(t, tt.wantOwner, claims[uri.OwnerClaimKey]) } }) } diff --git a/test/pb/pendingCommand.go b/test/pb/pendingCommand.go index bbaa9cc58..7579fd031 100644 --- a/test/pb/pendingCommand.go +++ b/test/pb/pendingCommand.go @@ -108,9 +108,9 @@ func InitPendingEvents(ctx context.Context, t *testing.T) (pb.GrpcGatewayClient, secureGWShutdown() createFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + createCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.CreateResource(ctx, &pb.CreateResourceRequest{ + _, errC := c.CreateResource(createCtx, &pb.CreateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -119,22 +119,22 @@ func InitPendingEvents(ctx context.Context, t *testing.T) (pb.GrpcGatewayClient, }), }, }) - require.Error(t, err) + require.Error(t, errC) } createFn() retrieveFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + retrieveCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ + _, errG := c.GetResourceFromDevice(retrieveCtx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), }) - require.Error(t, err) + require.Error(t, errG) } retrieveFn() updateFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateResource(ctx, &pb.UpdateResourceRequest{ + _, errU := c.UpdateResource(updateCtx, &pb.UpdateResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), Content: &pb.Content{ ContentType: message.AppOcfCbor.String(), @@ -143,26 +143,26 @@ func InitPendingEvents(ctx context.Context, t *testing.T) (pb.GrpcGatewayClient, }), }, }) - require.Error(t, err) + require.Error(t, errU) } updateFn() deleteFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + deleteCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.DeleteResource(ctx, &pb.DeleteResourceRequest{ + _, errD := c.DeleteResource(deleteCtx, &pb.DeleteResourceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), }) - require.Error(t, err) + require.Error(t, errD) } deleteFn() updateDeviceMetadataFn := func() { - ctx, cancel := context.WithTimeout(ctx, time.Second) + updateCtx, cancel := context.WithTimeout(ctx, time.Second) defer cancel() - _, err := c.UpdateDeviceMetadata(ctx, &pb.UpdateDeviceMetadataRequest{ + _, errU := c.UpdateDeviceMetadata(updateCtx, &pb.UpdateDeviceMetadataRequest{ DeviceId: deviceID, TwinEnabled: false, }) - require.Error(t, err) + require.Error(t, errU) } updateDeviceMetadataFn() updateDeviceMetadataFn() diff --git a/test/sdk/client.go b/test/sdk/client.go index 28a4b719b..598511952 100644 --- a/test/sdk/client.go +++ b/test/sdk/client.go @@ -6,6 +6,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/pem" + "errors" "fmt" "os" "time" @@ -22,7 +23,7 @@ type testSetupSecureClient struct { mfgCert tls.Certificate } -var errNotSet = fmt.Errorf("not set") +var errNotSet = errors.New("not set") func (c *testSetupSecureClient) GetManufacturerCertificate() (tls.Certificate, error) { if c.mfgCert.PrivateKey == nil { @@ -132,7 +133,7 @@ func NewClient(opts ...Option) (*client.Client, error) { mfgTrustedCABlock, _ := pem.Decode(MfgTrustedCA) if mfgTrustedCABlock == nil { - return nil, fmt.Errorf("mfgTrustedCABlock is empty") + return nil, errors.New("mfgTrustedCABlock is empty") } mfgCA, err := x509.ParseCertificates(mfgTrustedCABlock.Bytes) if err != nil { @@ -145,16 +146,16 @@ func NewClient(opts ...Option) (*client.Client, error) { identityIntermediateCABlock, _ := pem.Decode(identityIntermediateCA) if identityIntermediateCABlock == nil { - return nil, fmt.Errorf("identityIntermediateCABlock is empty") + return nil, errors.New("identityIntermediateCABlock is empty") } identityIntermediateCAKeyBlock, _ := pem.Decode(identityIntermediateCAKey) if identityIntermediateCAKeyBlock == nil { - return nil, fmt.Errorf("identityIntermediateCAKeyBlock is empty") + return nil, errors.New("identityIntermediateCAKeyBlock is empty") } identityTrustedCABlock, _ := pem.Decode(identityTrustedCA) if identityTrustedCABlock == nil { - return nil, fmt.Errorf("identityTrustedCABlock is empty") + return nil, errors.New("identityTrustedCABlock is empty") } identityTrustedCACert, err := x509.ParseCertificates(identityTrustedCABlock.Bytes) if err != nil { diff --git a/test/test.go b/test/test.go index 44c54f357..d81b8b3f0 100644 --- a/test/test.go +++ b/test/test.go @@ -41,7 +41,6 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/sdk" "github.com/plgd-dev/kit/v2/codec/json" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ugorji/go/codec" ) @@ -123,8 +122,8 @@ func (d *ResourceLinkRepresentation) UnmarshalJSON(data []byte) error { } dec := func(data []byte) (interface{}, error) { var r interface{} - err := json.Decode(data, &r) - return r, err + errD := json.Decode(data, &r) + return r, errD } for k, v := range reps { if strings.HasSuffix(rep.Href, k) { @@ -874,7 +873,7 @@ func DeviceIsBatchObservable(ctx context.Context, t *testing.T, deviceID string) var links schema.ResourceLinks err := GetResource(ctx, deviceID, resources.ResourceURI, resources.ResourceType, &links, deviceClient.WithQuery("di="+deviceID)) require.NoError(t, err) - require.Equal(t, 1, len(links)) + require.Len(t, links, 1) return links[0].Policy.BitMask.Has(schema.Observable) && pkgStrings.Contains(links[0].Interfaces, interfaces.OC_IF_B) } @@ -894,13 +893,7 @@ func ProtobufToInterface(t *testing.T, val interface{}) interface{} { func RequireToCheckFunc(checFunc func(t require.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{})) func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { return func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - checFunc(t, expected, actual, msgAndArgs) - } -} - -func AssertToCheckFunc(checFunc func(t assert.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool) func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - return func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { - checFunc(t, expected, actual, msgAndArgs) + checFunc(t, expected, actual, msgAndArgs...) } } diff --git a/test/virtual-device/cmd/main.go b/test/virtual-device/cmd/main.go index bf485ad61..c4fc551ba 100644 --- a/test/virtual-device/cmd/main.go +++ b/test/virtual-device/cmd/main.go @@ -9,6 +9,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/pem" + "errors" "flag" "fmt" "os" @@ -75,7 +76,7 @@ func generateIdentityCert(deviceID string, signerCert []*x509.Certificate, signe func makeVerifyCertificate(signerCert []*x509.Certificate) func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { return func(rawCerts [][]byte, _ [][]*x509.Certificate) error { if len(rawCerts) == 0 { - return fmt.Errorf("empty certificates chain") + return errors.New("empty certificates chain") } intermediateCAPool := x509.NewCertPool() certs := make([]*x509.Certificate, 0, len(rawCerts)) @@ -191,7 +192,7 @@ func signUpDevice(ctx context.Context, deviceID string, co *client.Conn) (servic return service.CoapSignUpResponse{}, err } if signUpResp.AccessToken == "" { - return service.CoapSignUpResponse{}, fmt.Errorf("cannot sign up device: empty access token") + return service.CoapSignUpResponse{}, errors.New("cannot sign up device: empty access token") } return signUpResp, nil } @@ -286,12 +287,12 @@ func publishResources(ctx context.Context, deviceID string, co *client.Conn, num }) } - wkRd := wkRd{ + wk := wkRd{ DeviceID: deviceID, Links: links, TimeToLive: 0, } - inputCbor, err := cbor.Encode(wkRd) + inputCbor, err := cbor.Encode(wk) if err != nil { return err } @@ -341,7 +342,7 @@ func encodePlatformResource(w *responsewriter.ResponseWriter[*client.Conn]) []by pCbor, err := cbor.Encode(p) if err != nil { fmt.Printf("cannot encode platform: %v", err) - err := w.SetResponse(codes.Content, message.AppOcfCbor, bytes.NewReader([]byte{})) + err = w.SetResponse(codes.Content, message.AppOcfCbor, bytes.NewReader([]byte{})) if err != nil { fmt.Printf(errSetResponseFmt, err) } @@ -426,7 +427,7 @@ func processBatchResourceLinks(w *responsewriter.ResponseWriter[*client.Conn], d inputCbor, err := cbor.Encode(data) if err != nil { fmt.Printf("cannot encode resource data: %v", err) - err := w.SetResponse(codes.Content, message.AppOcfCbor, bytes.NewReader([]byte{})) + err = w.SetResponse(codes.Content, message.AppOcfCbor, bytes.NewReader([]byte{})) if err != nil { fmt.Printf(errSetResponseFmt, err) } @@ -514,7 +515,7 @@ func processGetResourceLinks(w *responsewriter.ResponseWriter[*client.Conn], dev inputCbor, err := cbor.Encode(links) if err != nil { fmt.Printf("cannot encode resource links: %v", err) - err := w.SetResponse(codes.Content, message.AppOcfCbor, bytes.NewReader([]byte{})) + err = w.SetResponse(codes.Content, message.AppOcfCbor, bytes.NewReader([]byte{})) if err != nil { fmt.Printf(errSetResponseFmt, err) } From fbad2f31e1eddf0073c87167c0dad6d299070812 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Wed, 3 Apr 2024 01:14:27 +0200 Subject: [PATCH 23/31] Upgrade dependencies Submodule: github.com/googleapis/googleapis 1406704ced81daab07a859aa8a870ff39432d370 Direct: github.com/go-co-op/gocron/v2 v2.2.9 github.com/nats-io/nats.go v1.34.0 github.com/panjf2000/ants/v2 v2.9.1 github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0 github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 google.golang.org/api v0.172.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda Indirect: cloud.google.com/go/compute v1.25.1 github.com/cenkalti/backoff/v4 v4.3.0 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/googleapis/gax-go/v2 v2.12.3 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 github.com/pion/transport/v3 v3.0.2 google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda --- dependency/googleapis | 2 +- go.mod | 34 +++++++++---------- go.sum | 79 +++++++++++++++++++++---------------------- 3 files changed, 56 insertions(+), 59 deletions(-) diff --git a/dependency/googleapis b/dependency/googleapis index abe813038..1406704ce 160000 --- a/dependency/googleapis +++ b/dependency/googleapis @@ -1 +1 @@ -Subproject commit abe813038ee35695ddf10675fb3690f06c8f9cd4 +Subproject commit 1406704ced81daab07a859aa8a870ff39432d370 diff --git a/go.mod b/go.mod index da40ff847..dd3286125 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/fullstorydev/grpchan v1.1.1 github.com/fxamacker/cbor/v2 v2.6.0 - github.com/go-co-op/gocron/v2 v2.2.5 + github.com/go-co-op/gocron/v2 v2.2.9 github.com/gocql/gocql v1.6.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/snappy v0.0.4 @@ -24,12 +24,12 @@ require ( github.com/jtacoma/uritemplates v1.0.0 github.com/karrick/tparse/v2 v2.8.2 github.com/lestrrat-go/jwx/v2 v2.0.21 - github.com/nats-io/nats.go v1.33.1 - github.com/panjf2000/ants/v2 v2.9.0 - github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 + github.com/nats-io/nats.go v1.34.0 + github.com/panjf2000/ants/v2 v2.9.1 + github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c - github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba + github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0 + github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664 github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 github.com/sirupsen/logrus v1.9.3 @@ -49,12 +49,12 @@ require ( go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/atomic v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 + golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 golang.org/x/net v0.22.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.6.0 - google.golang.org/api v0.169.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 + google.golang.org/api v0.172.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda google.golang.org/grpc v1.62.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/protobuf v1.33.0 @@ -62,15 +62,15 @@ require ( ) require ( - cloud.google.com/go/compute v1.25.0 // indirect + cloud.google.com/go/compute v1.25.1 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/sprig v2.15.0+incompatible // indirect github.com/aokoli/goutils v1.0.1 // indirect github.com/bufbuild/protocompile v0.9.0 // indirect - github.com/cenkalti/backoff/v4 v4.2.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dsnet/golib/memfile v1.0.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect github.com/go-logr/logr v1.4.1 // indirect @@ -81,8 +81,8 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.2 // indirect - github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect + github.com/googleapis/gax-go/v2 v2.12.3 // indirect + github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/huandu/xstrings v1.0.0 // indirect @@ -101,7 +101,7 @@ require ( github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect - github.com/pion/transport/v3 v3.0.1 // indirect + github.com/pion/transport/v3 v3.0.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pseudomuto/protokit v0.2.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect @@ -121,10 +121,10 @@ require ( golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) // note: github.com/pion/dtls/v2/pkg/net package is not yet available in release branches, // so we force to the use of the pinned master branch -replace github.com/pion/dtls/v2 => github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 +replace github.com/pion/dtls/v2 => github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 diff --git a/go.sum b/go.sum index d0575bf89..51a442faf 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.25.0 h1:H1/4SqSUhjPFE7L5ddzHOfY2bCAvjwNRZPNl6Ni5oYU= -cloud.google.com/go/compute v1.25.0/go.mod h1:GR7F0ZPZH8EhChlMo9FkLd7eUTwEymjqQagxzilIxIE= +cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= 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= @@ -19,8 +19,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR github.com/bufbuild/protocompile v0.9.0 h1:DI8qLG5PEO0Mu1Oj51YFPqtx6I3qYXUAhJVJ/IzAVl0= github.com/bufbuild/protocompile v0.9.0/go.mod h1:s89m1O8CqSYpyE/YaSGtg1r1YFMF5nLTwh4vlj6O444= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -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/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 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= @@ -28,8 +28,8 @@ github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnht 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/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dsnet/golib/memfile v0.0.0-20190531212259-571cdbcff553/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= github.com/dsnet/golib/memfile v0.0.0-20200723050859-c110804dfa93/go.mod h1:tXGNW9q3RwvWt1VV2qrRKlSSz0npnh12yftCSCy2T64= @@ -55,8 +55,8 @@ github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= -github.com/go-co-op/gocron/v2 v2.2.5 h1:AGyUDXmSmqnclltaMVrLCtl3viJMY3TcpWdU4dbi/mE= -github.com/go-co-op/gocron/v2 v2.2.5/go.mod h1:igssOwzZkfcnu3m2kwnCf/mYj4SmhP9ecSgmYjCOHkk= +github.com/go-co-op/gocron/v2 v2.2.9 h1:aoKosYWSSdXFLecjFWX1i8+R6V7XdZb8sB2ZKAY5Yis= +github.com/go-co-op/gocron/v2 v2.2.9/go.mod h1:mZx3gMSlFnb97k3hRqX3+GdlG3+DUwTh6B8fnsTScXg= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -123,8 +123,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= @@ -133,8 +133,8 @@ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZH github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 h1:HcUWd006luQPljE73d5sk+/VgYPGUReEVz2y1/qylwY= -github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1/go.mod h1:w9Y7gY31krpLmrVU5ZPG9H7l9fZuRu5/3R3S3FMtVQ4= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk= +github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ/U4HP0zS2Z9Fh8Ps9a+6X26m/tmI= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= @@ -205,31 +205,31 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 h1:28i1IjGcx8AofiB4N3q5Yls55VEaitzuEPkFJEVgGkA= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= -github.com/nats-io/nats.go v1.33.1 h1:8TxLZZ/seeEfR97qV0/Bl939tpDnt2Z2fK3HkPypj70= -github.com/nats-io/nats.go v1.33.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nats.go v1.34.0 h1:fnxnPCNiwIG5w08rlMcEKTUw4AV/nKyGCOJE8TdhSPk= +github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/panjf2000/ants/v2 v2.4.3/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A= -github.com/panjf2000/ants/v2 v2.9.0 h1:SztCLkVxBRigbg+vt0S5QvF5vxAbxbKt09/YfAJ0tEo= -github.com/panjf2000/ants/v2 v2.9.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= +github.com/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw= +github.com/panjf2000/ants/v2 v2.9.1/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8 h1:r7K+oQUYubeA0am08kTAvd2wT2D8PZggs/CpMGp0nkM= -github.com/pion/dtls/v2 v2.2.8-0.20240201071732-2597464081c8/go.mod h1:/gft3czh67pwl4nM1BBUvF7eTy72uGkObJXOYfxRDbA= +github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 h1:Yiqcf3WfIu66j820RdYDjnnTsrDwMKYsuqFvzDJn4uk= +github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01/go.mod h1:eLnUKAwQ5J17w2P583p4UXWBlOK5OkkLY7sXZANcwj0= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= -github.com/pion/transport/v3 v3.0.1 h1:gDTlPJwROfSfz6QfSi0ZmeCSkFcnWWiiR9ES0ouANiM= -github.com/pion/transport/v3 v3.0.1/go.mod h1:UY7kiITrlMv7/IKgd5eTUcaahZx5oUN3l9SzK5f5xE0= +github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= +github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c h1:d6CMhw6Lx/fJpeZrbnbeHULtbfRfPLDprMWmKP/YxnA= -github.com/plgd-dev/device/v2 v2.3.2-0.20240305073234-ee311673e17c/go.mod h1:4hzgXvOY/u2+EvQDehDCe77UKuhD+9SouLiPKEFexes= +github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0 h1:EEDaxD3RCCD5uAtmJxE+S7DncGh00/8NvIwTmu1AEKE= +github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0/go.mod h1:T0ePJIrEkK8uvHkq43qA8J/eHGsV3w7zriDh5S7xJgE= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= -github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba h1:bDpB1PPdUzgaTdcPr4jMdbb78ODxvG9CE7lSOQngL9Y= -github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240303135359-ce5dcc5ef1ba/go.mod h1:rUgy/k2SX0esIM7JT01euQALT5YrYkROwxMSwfiIzhw= +github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664 h1:iMMYyd666v1oHmR642hYFoRgRyrN/qMoCoY0X/Cj6RE= +github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664/go.mod h1:flkLrn0JqGJyW25Uybwg0g0PZUt+pZ1O7aaPeIhEEbs= github.com/plgd-dev/kit v0.0.0-20200819113605-d5fcf3e94f63/go.mod h1:Yl9zisyXfPdtP9hTWlJqjJYXmgU/jtSDKttz9/CeD90= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 h1:TC1HJ/UbyflJFPvaOdGmNZ5TeFGex1/dyr9urNGLy7M= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSGQjdi8eInxwFCs0tSApuEM1o0qNck+sJYp4M= @@ -253,6 +253,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -348,13 +349,12 @@ golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= -golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= +golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= 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= @@ -385,8 +385,7 @@ golang.org/x/net v0.0.0-20210502030024-e5908800b52b/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -422,16 +421,15 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -440,7 +438,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -465,8 +462,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= -google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk= +google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -476,10 +473,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7 h1:bITUotW/BD35GhBwrwGexWa8/P5CKHXACICrmuFJBa8= -google.golang.org/genproto/googleapis/api v0.0.0-20240308144416-29370a3891b7/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 h1:em/y72n4XlYRtayY/cVj6pnVzHa//BDA1BdoO+z9mdE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda h1:b6F6WIV4xHHD0FA4oIyzU6mHWg2WI2X1RBehwa5QN38= +google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda/go.mod h1:AHcE/gZH76Bk/ROZhQphlRoWo5xKDEtz3eVEO1LfA8c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 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= From 44aa415c82fced5e3934fb7a40af839a7a80ca5a Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Thu, 4 Apr 2024 16:03:39 +0200 Subject: [PATCH 24/31] Update golangci-lint configuration and fix issues --- .golangci.yml | 26 ++- .../service/grpc/deleteSigningRecords_test.go | 2 +- .../service/grpc/getSigningRecords_test.go | 2 +- .../store/cqldb/signingRecords.go | 2 +- .../store/cqldb/signingRecords_test.go | 13 +- .../store/mongodb/signingRecords_test.go | 9 +- .../service/devicesSubscription.go | 2 +- .../service/getDevices_test.go | 2 +- cloud2cloud-connector/service/pull.go | 4 +- cloud2cloud-gateway/service/retrieveDevice.go | 6 +- .../service/subscribeToDevice_test.go | 2 +- .../service/subscribeToDevices_test.go | 25 +-- cloud2cloud-gateway/service/subscriptions.go | 21 +- cloud2cloud-gateway/service/updateResource.go | 2 +- cloud2cloud-gateway/test/events.go | 32 +-- coap-gateway/service/clientCreateHandler.go | 6 +- coap-gateway/service/clientDeleteHandler.go | 6 +- coap-gateway/service/clientObserveHandler.go | 2 +- coap-gateway/service/clientRetrieveHandler.go | 10 +- coap-gateway/service/clientUpdateHandler.go | 6 +- .../service/devicesStatusUpdater_test.go | 2 +- coap-gateway/service/service.go | 36 ++-- coap-gateway/service/session.go | 10 +- coap-gateway/service/signIn.go | 4 +- grpc-gateway/client/client.go | 11 +- grpc-gateway/client/deviceSubscriber.go | 2 +- grpc-gateway/service/deleteDevices.go | 2 +- grpc-gateway/service/deleteDevices_test.go | 8 +- grpc-gateway/service/deleteResource_test.go | 4 +- grpc-gateway/service/getDevices_test.go | 2 +- .../service/getHubConfiguration_test.go | 2 +- .../service/subscribeToEvents_test.go | 41 ++-- .../service/updateDeviceMetadata_test.go | 2 +- grpc-gateway/service/updateResource_test.go | 3 +- .../subscription/subscription_test.go | 2 +- http-gateway/service/deleteDevices_test.go | 2 +- http-gateway/service/getDevice_test.go | 2 +- http-gateway/service/getDevices_test.go | 4 +- .../service/subscribeToEvents_test.go | 14 +- http-gateway/test/pendingCommands.go | 2 +- identity-store/client/ownerCache.go | 2 +- identity-store/client/ownerCache_test.go | 2 +- identity-store/persistence/cqldb/store.go | 2 +- identity-store/service/addDevice.go | 11 +- identity-store/service/deleteDevices.go | 14 +- identity-store/service/deleteDevices_test.go | 4 +- identity-store/service/getDevices_test.go | 2 +- pkg/net/coap/service/service_test.go | 11 +- pkg/opentelemetry/otelcoap/opentelemetry.go | 2 +- pkg/sync/task/future/future_test.go | 5 +- .../cqrs/aggregate/aggregateParallel_test.go | 3 +- .../cqrs/aggregate/test/aggregate.go | 32 +-- .../eventbus/nats/subscriber/subscriber.go | 2 +- .../cqrs/eventstore/cqldb/eventstore.go | 2 +- .../cqrs/eventstore/cqldb/save.go | 40 ++-- .../cqrs/eventstore/projection.go | 54 ++--- .../projection/projectionInternal_test.go | 16 +- .../cqrs/projection/projection_test.go | 204 +++++++++--------- resource-aggregate/cqrs/utils/utils_test.go | 12 +- resource-aggregate/service/aggregate.go | 22 +- resource-aggregate/service/aggregate_test.go | 6 +- .../service/confirmDeviceMetadataUpdate.go | 2 +- .../confirmDeviceMetadataUpdate_test.go | 2 +- resource-aggregate/service/deleteDevices.go | 2 +- .../service/deleteDevices_test.go | 8 +- resource-aggregate/service/grpcApi.go | 26 +-- resource-aggregate/service/grpcApi_test.go | 2 +- .../service/updateDeviceMetadata_test.go | 9 +- .../service/updateServiceHeartbeat_test.go | 3 +- resource-directory/service/deviceDirectory.go | 6 +- .../service/deviceDirectory_test.go | 36 ++-- resource-directory/service/getDevices_test.go | 2 +- resource-directory/service/getEvents.go | 14 +- .../service/getHubConfiguration_test.go | 4 +- resource-directory/service/projection.go | 8 +- .../service/resourceDirectory.go | 4 +- .../service/resourceDirectory_test.go | 2 +- .../service/resourceLinksProjection.go | 2 +- .../service/resourceProjection.go | 22 +- resource-directory/service/resourceShadow.go | 15 +- test/cbor.go | 6 +- test/pb/device.go | 10 +- test/pb/event.go | 21 ++ test/pb/pendingCommand.go | 6 +- test/pb/resource.go | 4 +- test/pb/snapshot.go | 2 +- test/test.go | 9 +- test/virtual-device/virtualDevice.go | 19 +- 88 files changed, 544 insertions(+), 485 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index e9ae1112c..26c9aef22 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,9 +21,6 @@ linters-settings: - shadow stylecheck: checks: ["all", "-ST1003"] - testifylint: - disable: - - go-require linters: enable: @@ -32,10 +29,11 @@ linters: - bidichk # Checks for dangerous unicode character sequences - bodyclose # Checks whether HTTP response body is closed successfully # - copyloopvar # Detects places where loop variables are copied - - decorder # check declaration order and count of types, constants, variables and functions + - decorder # Check declaration order and count of types, constants, variables and functions - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) - dupl # Tool for code clone detection - - durationcheck # check for two durations multiplied together + - dupword # A linter that checks for duplicate words in the source code (usually miswritten) + - durationcheck # Check for two durations multiplied together - errcheck # Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases - errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted. - errname # Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`. @@ -69,18 +67,21 @@ linters: - loggercheck # Checks key value pairs for common logger libraries (kitlog,klog,logr,zap). - mirror # Reports wrong mirror patterns of bytes/strings usage - misspell # Finds commonly misspelled English words in comments + - nakedret # Finds naked returns in functions greater than a specified function length + - nestif # Reports deeply nested if statements - nilerr # Finds the code that returns nil even if it checks that the error is not nil. # - nilnil # Checks that there is no simultaneous return of `nil` error and an invalid value. # - noctx # noctx finds sending http request without context.Context - nolintlint # Reports ill-formed or insufficient nolint directives - nosprintfhostport # Checks for misuse of Sprintf to construct a host with port in a URL - perfsprint # Checks that fmt.Sprintf can be replaced with a faster alternative. + - prealloc # Finds slice declarations that could potentially be preallocated - predeclared # find code that shadows one of Go's predeclared identifiers - # - protogetter # Reports direct reads from proto message fields when getters should be used. + - protogetter # Reports direct reads from proto message fields when getters should be used. - revive # golint replacement, finds style mistakes - reassign # Checks that package variables are not reassigned - sloglint # Ensure consistent code style when using log/slog - # - spancheck # Checks for mistakes with OpenTelemetry/Census spans + - spancheck # Checks for mistakes with OpenTelemetry/Census spans - staticcheck # Staticcheck is a go vet on steroids, applying a ton of static analysis checks - stylecheck # Stylecheck is a replacement for golint - tenv # tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 @@ -115,18 +116,15 @@ linters: - maintidx # maintidx measures the maintainability index of each function. - makezero # Finds slice declarations with non-zero initial length - maligned # Tool to detect Go structs that would take less memory if their fields were sorted - - nakedret # Finds naked returns in functions greater than a specified function length - - nestif # Reports deeply nested if statements - nlreturn # nlreturn checks for a new line before return and branch statements to increase code clarity - nonamedreturns # Reports all named returns - paralleltest # paralleltest detects missing usage of t.Parallel() method in your Go test - - prealloc # Finds slice declarations that could potentially be preallocated - promlinter # Check Prometheus metrics naming via promlint - rowserrcheck # checks whether Err of rows is checked successfully - sqlclosecheck # Checks that sql.Rows and sql.Stmt are closed. - - structcheck # Finds unused struct fields - tagalign # Check that struct tags are well aligned. - tagliatelle # Checks the struct tags. + - testableexamples # linter checks if examples are testable (have an expected output) - testpackage # linter that makes you use a separate _test package - thelper # thelper detects golang test helpers without t.Helper() call and checks the consistency of test helpers - varnamelen # checks that the length of a variable's name matches its scope @@ -159,6 +157,9 @@ issues: text: "SA1019:" linters: - staticcheck + - path: grpc-gateway/client/client.go + linters: + - dupword - path: coap-gateway/service/session.go linters: - dupl @@ -170,3 +171,6 @@ issues: - dupl # Fix found issues (if it's supported by the linter). # fix: true + +run: + go: "1.20" diff --git a/certificate-authority/service/grpc/deleteSigningRecords_test.go b/certificate-authority/service/grpc/deleteSigningRecords_test.go index e1a6e9c88..573fdff84 100644 --- a/certificate-authority/service/grpc/deleteSigningRecords_test.go +++ b/certificate-authority/service/grpc/deleteSigningRecords_test.go @@ -55,7 +55,7 @@ func TestCertificateAuthorityServerDeleteSigningRecords(t *testing.T) { name: "valid", args: args{ req: &pb.DeleteSigningRecordsRequest{ - IdFilter: []string{r.Id}, + IdFilter: []string{r.GetId()}, }, }, want: 1, diff --git a/certificate-authority/service/grpc/getSigningRecords_test.go b/certificate-authority/service/grpc/getSigningRecords_test.go index 21a744c10..c7f1d859a 100644 --- a/certificate-authority/service/grpc/getSigningRecords_test.go +++ b/certificate-authority/service/grpc/getSigningRecords_test.go @@ -63,7 +63,7 @@ func TestCertificateAuthorityServerGetSigningRecords(t *testing.T) { name: "valid", args: args{ req: &pb.GetSigningRecordsRequest{ - IdFilter: []string{r.Id}, + IdFilter: []string{r.GetId()}, }, }, want: []*pb.SigningRecord{r}, diff --git a/certificate-authority/store/cqldb/signingRecords.go b/certificate-authority/store/cqldb/signingRecords.go index 76739b95e..73924579c 100644 --- a/certificate-authority/store/cqldb/signingRecords.go +++ b/certificate-authority/store/cqldb/signingRecords.go @@ -393,7 +393,7 @@ func (i *SigningRecordsIterator) close() error { func (i *SigningRecordsIterator) Next(_ context.Context, s *store.SigningRecord) bool { for i.next(s) { - if _, ok := i.provided[s.Id]; !ok { + if _, ok := i.provided[s.GetId()]; !ok { // filter duplicated records i.provided[s.GetId()] = struct{}{} return true diff --git a/certificate-authority/store/cqldb/signingRecords_test.go b/certificate-authority/store/cqldb/signingRecords_test.go index 075b1da6d..f2421c41d 100644 --- a/certificate-authority/store/cqldb/signingRecords_test.go +++ b/certificate-authority/store/cqldb/signingRecords_test.go @@ -12,6 +12,7 @@ import ( "github.com/plgd-dev/hub/v2/certificate-authority/store" "github.com/plgd-dev/hub/v2/certificate-authority/test" hubTest "github.com/plgd-dev/hub/v2/test" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -174,8 +175,8 @@ func TestStoreUpdateSigningRecord(t *testing.T) { } require.NoError(t, err) var h testSigningRecordHandler - err = s.LoadSigningRecords(ctx, tt.args.sub.Owner, &pb.GetSigningRecordsRequest{ - IdFilter: []string{tt.args.sub.Id}, + err = s.LoadSigningRecords(ctx, tt.args.sub.GetOwner(), &pb.GetSigningRecordsRequest{ + IdFilter: []string{tt.args.sub.GetId()}, }, h.Handle) require.NoError(t, err) require.Len(t, h.lcs, 1) @@ -466,7 +467,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { name: "id - another owner", args: args{ owner: "another owner", - query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].Id}}, + query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].GetId()}}, }, want: []*store.SigningRecord{lcs[1]}, }, @@ -474,7 +475,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { name: "multiple queries", args: args{ owner: "owner", - query: &store.SigningRecordsQuery{IdFilter: []string{lcs[0].Id, lcs[2].Id}}, + query: &store.SigningRecordsQuery{IdFilter: []string{lcs[0].GetId(), lcs[2].GetId()}}, }, want: []*store.SigningRecord{lcs[0], lcs[2]}, }, @@ -497,7 +498,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { args: args{ owner: "owner", query: &store.SigningRecordsQuery{ - IdFilter: []string{lcs[0].Id, lcs[2].Id}, + IdFilter: []string{lcs[0].GetId(), lcs[2].GetId()}, DeviceIdFilter: []string{lcs[0].GetDeviceId()}, }, }, @@ -569,7 +570,7 @@ func BenchmarkSigningRecords(b *testing.B) { go func(l *pb.SigningRecord) { defer wg.Done() err := s.UpdateSigningRecord(ctx, l) - require.NoError(b, err) + assert.NoError(b, err) }(l) } wg.Wait() diff --git a/certificate-authority/store/mongodb/signingRecords_test.go b/certificate-authority/store/mongodb/signingRecords_test.go index 8dde1808c..f260cf1a7 100644 --- a/certificate-authority/store/mongodb/signingRecords_test.go +++ b/certificate-authority/store/mongodb/signingRecords_test.go @@ -11,6 +11,7 @@ import ( "github.com/plgd-dev/hub/v2/certificate-authority/store" "github.com/plgd-dev/hub/v2/certificate-authority/test" hubTest "github.com/plgd-dev/hub/v2/test" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -395,7 +396,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { name: "id - another owner", args: args{ owner: "another owner", - query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].Id}}, + query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].GetId()}}, }, want: []*store.SigningRecord{lcs[1]}, }, @@ -403,7 +404,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { name: "multiple queries", args: args{ owner: "owner", - query: &store.SigningRecordsQuery{IdFilter: []string{lcs[0].Id, lcs[2].Id}}, + query: &store.SigningRecordsQuery{IdFilter: []string{lcs[0].GetId(), lcs[2].GetId()}}, }, want: []*store.SigningRecord{lcs[0], lcs[2]}, }, @@ -482,12 +483,12 @@ func BenchmarkSigningRecords(b *testing.B) { go func(l *pb.SigningRecord) { defer wg.Done() err := s.UpdateSigningRecord(ctx, l) - require.NoError(b, err) + assert.NoError(b, err) }(l) } wg.Wait() err := s.FlushBulkWriter() - require.NoError(b, err) + assert.NoError(b, err) }() } } diff --git a/cloud2cloud-connector/service/devicesSubscription.go b/cloud2cloud-connector/service/devicesSubscription.go index 439f2a8e4..f68b47a6c 100644 --- a/cloud2cloud-connector/service/devicesSubscription.go +++ b/cloud2cloud-connector/service/devicesSubscription.go @@ -135,7 +135,7 @@ func (s *SubscriptionManager) handleDevicesUnregistered(ctx context.Context, sub if err != nil { errors = multierror.Append(errors, fmt.Errorf("cannot remove device %v from user: %w", device.ID, err)) } - if err == nil && len(resp.DeviceIds) != 1 { + if err == nil && len(resp.GetDeviceIds()) != 1 { errors = multierror.Append(errors, fmt.Errorf("cannot remove device %v from user", device.ID)) } err = s.devicesSubscription.Delete(userID, device.ID) diff --git a/cloud2cloud-connector/service/getDevices_test.go b/cloud2cloud-connector/service/getDevices_test.go index c2cd276e7..ae9f5ec03 100644 --- a/cloud2cloud-connector/service/getDevices_test.go +++ b/cloud2cloud-connector/service/getDevices_test.go @@ -94,7 +94,7 @@ func testRequestHandlerGetDevices(t *testing.T, events store.Events) { break } require.NoError(t, err) - assert.NotEmpty(t, dev.ProtocolIndependentId) + assert.NotEmpty(t, dev.GetProtocolIndependentId()) dev.ProtocolIndependentId = "" if dev.GetMetadata().GetConnection() != nil { dev.GetMetadata().GetConnection().Id = "" diff --git a/cloud2cloud-connector/service/pull.go b/cloud2cloud-connector/service/pull.go index 3bc4589de..ca97e02e2 100644 --- a/cloud2cloud-connector/service/pull.go +++ b/cloud2cloud-connector/service/pull.go @@ -70,7 +70,7 @@ func getOwnerDevices(ctx context.Context, isClient pbIS.IdentityStoreClient) (ma continue } - ownerDevices[device.DeviceId] = true + ownerDevices[device.GetDeviceId()] = true } return ownerDevices, nil } @@ -193,7 +193,7 @@ func (p *pullDevicesHandler) deleteDevice(ctx context.Context, userID, deviceID if err != nil { errors = multierror.Append(errors, fmt.Errorf("cannot delete device %v: %w", deviceID, err)) } - if err == nil && len(resp.DeviceIds) != 1 { + if err == nil && len(resp.GetDeviceIds()) != 1 { errors = multierror.Append(errors, fmt.Errorf("cannot remove device %v", deviceID)) } return errors.ErrorOrNil() diff --git a/cloud2cloud-gateway/service/retrieveDevice.go b/cloud2cloud-gateway/service/retrieveDevice.go index 4aa7cc798..36fde2079 100644 --- a/cloud2cloud-gateway/service/retrieveDevice.go +++ b/cloud2cloud-gateway/service/retrieveDevice.go @@ -91,11 +91,11 @@ func unmarshalContent(c *commands.Content, m interface{}) error { case message.TextPlain.String(): switch v := m.(type) { case *string: - *v = string(c.Data) + *v = string(c.GetData()) case *[]byte: - *v = c.Data + *v = c.GetData() case *interface{}: - *v = string(c.Data) + *v = string(c.GetData()) default: return fmt.Errorf("cannot unmarshal resource content: invalid type (%T)", m) } diff --git a/cloud2cloud-gateway/service/subscribeToDevice_test.go b/cloud2cloud-gateway/service/subscribeToDevice_test.go index 8540c2887..2d94b770d 100644 --- a/cloud2cloud-gateway/service/subscribeToDevice_test.go +++ b/cloud2cloud-gateway/service/subscribeToDevice_test.go @@ -157,7 +157,7 @@ func TestRequestHandlerSubscribeToDevice(t *testing.T) { resources = testSubscribeToDeviceDecodeResources(links) var unpublishedSwitches []*commands.Resource for _, res := range resources { - if res.Href == test.TestResourceSwitchesInstanceHref(switchID2) { + if res.GetHref() == test.TestResourceSwitchesInstanceHref(switchID2) { unpublishedSwitches = append(unpublishedSwitches, &commands.Resource{ DeviceId: deviceID, Href: test.TestResourceSwitchesInstanceHref(switchID2), diff --git a/cloud2cloud-gateway/service/subscribeToDevices_test.go b/cloud2cloud-gateway/service/subscribeToDevices_test.go index 8bbb23755..512aab2c6 100644 --- a/cloud2cloud-gateway/service/subscribeToDevices_test.go +++ b/cloud2cloud-gateway/service/subscribeToDevices_test.go @@ -25,6 +25,7 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/service" "github.com/plgd-dev/kit/v2/codec/json" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -77,20 +78,20 @@ func TestRequestHandlerSubscribeToDevices(t *testing.T) { r.StrictSlash(true) r.HandleFunc(eventsURI, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h, err2 := events.ParseEventHeader(r) - require.NoError(t, err2) + assert.NoError(t, err2) //nolint:testifylint defer func() { _ = r.Body.Close() }() - require.Equal(t, wantEventType, h.EventType) + assert.Equal(t, wantEventType, h.EventType) buf, err2 := io.ReadAll(r.Body) - require.NoError(t, err2) + assert.NoError(t, err2) //nolint:testifylint var v interface{} err2 = json.Decode(buf, &v) - require.NoError(t, err2) - require.Equal(t, wantEventContent, v) + assert.NoError(t, err2) //nolint:testifylint + assert.Equal(t, wantEventContent, v) w.WriteHeader(http.StatusOK) err2 = eventsServer.Close() - require.NoError(t, err2) + assert.NoError(t, err2) })).Methods("POST") _ = http.Serve(eventsServer, r) }() @@ -170,20 +171,20 @@ func TestRequestHandlerSubscribeToDevicesOffline(t *testing.T) { r.StrictSlash(true) r.HandleFunc(eventsURI, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h, err2 := events.ParseEventHeader(r) - require.NoError(t, err2) + assert.NoError(t, err2) //nolint:testifylint defer func() { _ = r.Body.Close() }() - require.Equal(t, wantEventType, h.EventType) + assert.Equal(t, wantEventType, h.EventType) buf, err2 := io.ReadAll(r.Body) - require.NoError(t, err2) + assert.NoError(t, err2) //nolint:testifylint var v interface{} err2 = json.Decode(buf, &v) - require.NoError(t, err2) - require.Equal(t, wantEventContent, v) + assert.NoError(t, err2) //nolint:testifylint + assert.Equal(t, wantEventContent, v) w.WriteHeader(http.StatusOK) err2 = eventsServer.Close() - require.NoError(t, err2) + assert.NoError(t, err2) })).Methods("POST") _ = http.Serve(eventsServer, r) }() diff --git a/cloud2cloud-gateway/service/subscriptions.go b/cloud2cloud-gateway/service/subscriptions.go index 4e917a343..80db85b77 100644 --- a/cloud2cloud-gateway/service/subscriptions.go +++ b/cloud2cloud-gateway/service/subscriptions.go @@ -361,20 +361,19 @@ func (s *SubscriptionData) Connect(ctx context.Context, emitEvent emitEventFunc, } sub, err := createSubscriptionFunc(ctx, emitEvent, &h) - if err != nil { - if status.Convert(err).Code() == codes.Unauthenticated { - subToCancel, errSub := deleteSub(ctx, s.data.ID, "") - if errSub == nil { - if err2 := cancelSubscription(ctx, emitEvent, subToCancel); err2 != nil { - log.Errorf("cannot cancel subscription %v: %w", subToCancel.ID, err2) - } + if err == nil { + s.Store(sub) + return nil + } + if status.Convert(err).Code() == codes.Unauthenticated { + subToCancel, errSub := deleteSub(ctx, s.data.ID, "") + if errSub == nil { + if err2 := cancelSubscription(ctx, emitEvent, subToCancel); err2 != nil { + log.Errorf("cannot cancel subscription %v: %w", subToCancel.ID, err2) } } - return err } - - s.Store(sub) - return nil + return err } func (s *SubscriptionData) IncrementSequenceNumber(ctx context.Context) (uint64, error) { diff --git a/cloud2cloud-gateway/service/updateResource.go b/cloud2cloud-gateway/service/updateResource.go index 9e4703487..60cb21109 100644 --- a/cloud2cloud-gateway/service/updateResource.go +++ b/cloud2cloud-gateway/service/updateResource.go @@ -47,7 +47,7 @@ func statusToHttpStatus(status commands.Status) int { func sendResponse(w http.ResponseWriter, processed *raEvents.ResourceUpdated) (int, error) { statusCode := statusToHttpStatus(processed.GetStatus()) - if processed.Content != nil { + if processed.GetContent() != nil { var content interface{} err := unmarshalContent(processed.GetContent(), &content) if err != nil { diff --git a/cloud2cloud-gateway/test/events.go b/cloud2cloud-gateway/test/events.go index e30b3fe52..aad72ac83 100644 --- a/cloud2cloud-gateway/test/events.go +++ b/cloud2cloud-gateway/test/events.go @@ -17,6 +17,7 @@ import ( "github.com/plgd-dev/hub/v2/pkg/security/certManager/server" "github.com/plgd-dev/hub/v2/test/config" "github.com/plgd-dev/kit/v2/codec/json" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -56,25 +57,29 @@ func WaitForEvents(ch EventChan, timeout time.Duration) []Event { return events } -func DecodeEvent(t *testing.T, etype events.EventType, data []byte) interface{} { +func decodeEvent(etype events.EventType, data []byte) (interface{}, error) { switch etype { case events.EventType_ResourcesPublished: fallthrough case events.EventType_ResourcesUnpublished: var links schema.ResourceLinks err := json.Decode(data, &links) - require.NoError(t, err) - return links + if err != nil { + return nil, err + } + return links, nil case events.EventType_ResourceChanged: var colContent []map[interface{}]interface{} err := json.Decode(data, &colContent) if err == nil { - return colContent + return colContent, nil } var content map[interface{}]interface{} err = json.Decode(data, &content) - require.NoError(t, err) - return content + if err != nil { + return nil, err + } + return content, nil case events.EventType_DevicesRegistered: fallthrough case events.EventType_DevicesUnregistered: @@ -84,11 +89,13 @@ func DecodeEvent(t *testing.T, etype events.EventType, data []byte) interface{} case events.EventType_DevicesOffline: var devices []map[string]string err := json.Decode(data, &devices) - require.NoError(t, err) - return devices + if err != nil { + return nil, err + } + return devices, nil } - return nil + return nil, nil } func NewEventsServer(t *testing.T, uri string) *EventsServer { @@ -133,14 +140,15 @@ func (s *EventsServer) Run(t *testing.T) EventChan { r.StrictSlash(true) r.HandleFunc(s.uri, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { h, err := events.ParseEventHeader(r) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint defer func() { _ = r.Body.Close() }() buf, err := io.ReadAll(r.Body) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint - data := DecodeEvent(t, h.EventType, buf) + data, err := decodeEvent(h.EventType, buf) + assert.NoError(t, err) //nolint:testifylint dataChan <- Event{ header: h, data: data, diff --git a/coap-gateway/service/clientCreateHandler.go b/coap-gateway/service/clientCreateHandler.go index b61c21d28..1cd264066 100644 --- a/coap-gateway/service/clientCreateHandler.go +++ b/coap-gateway/service/clientCreateHandler.go @@ -37,14 +37,14 @@ func clientCreateHandler(req *mux.Message, client *session) (*pool.Message, erro code = coapconv.GrpcErr2CoapCode(err, coapconv.Create) return nil, statusErrorf(code, errFmtCreateResource, fmt.Sprintf(" /%v%v", deviceID, href), err) } - if content == nil || len(content.Data) == 0 { + if len(content.GetData()) == 0 { return client.createResponse(code, req.Token(), coapMessage.TextPlain, nil), nil } - mediaType, err := coapconv.MakeMediaType(-1, content.ContentType) + mediaType, err := coapconv.MakeMediaType(-1, content.GetContentType()) if err != nil { return nil, statusErrorf(coapCodes.BadRequest, "cannot encode response for create resource %v: %w", fmt.Sprintf(" /%v%v", deviceID, href), err) } - return client.createResponse(code, req.Token(), mediaType, content.Data), nil + return client.createResponse(code, req.Token(), mediaType, content.GetData()), nil } func clientCreateDeviceHandler(req *mux.Message, client *session, deviceID, href string) (*commands.Content, error) { diff --git a/coap-gateway/service/clientDeleteHandler.go b/coap-gateway/service/clientDeleteHandler.go index 1f346c765..cc5ed7488 100644 --- a/coap-gateway/service/clientDeleteHandler.go +++ b/coap-gateway/service/clientDeleteHandler.go @@ -38,14 +38,14 @@ func clientDeleteHandler(req *mux.Message, client *session) (*pool.Message, erro return nil, statusErrorf(code, errFmtDeleteResource, fmt.Sprintf(" /%v%v", deviceID, href), err) } - if content == nil || len(content.Data) == 0 { + if len(content.GetData()) == 0 { return client.createResponse(code, req.Token(), coapMessage.TextPlain, nil), nil } - mediaType, err := coapconv.MakeMediaType(-1, content.ContentType) + mediaType, err := coapconv.MakeMediaType(-1, content.GetContentType()) if err != nil { return nil, statusErrorf(code, errFmtDeleteResource, fmt.Sprintf(" /%v%v", deviceID, href), err) } - return client.createResponse(code, req.Token(), mediaType, content.Data), nil + return client.createResponse(code, req.Token(), mediaType, content.GetData()), nil } func clientDeleteResourceHandler(req *mux.Message, client *session, deviceID, href string) (*commands.Content, error) { diff --git a/coap-gateway/service/clientObserveHandler.go b/coap-gateway/service/clientObserveHandler.go index 16e9705b7..00f8d4813 100644 --- a/coap-gateway/service/clientObserveHandler.go +++ b/coap-gateway/service/clientObserveHandler.go @@ -185,7 +185,7 @@ func (s *resourceSubscription) Init(ctx context.Context) error { if errR != nil { return errR } - d = resource.Data + d = resource.GetData() } authCtx, err := s.client.GetAuthorizationContext() if err != nil { diff --git a/coap-gateway/service/clientRetrieveHandler.go b/coap-gateway/service/clientRetrieveHandler.go index 353f1b194..c00f265e0 100644 --- a/coap-gateway/service/clientRetrieveHandler.go +++ b/coap-gateway/service/clientRetrieveHandler.go @@ -57,14 +57,14 @@ func clientRetrieveHandler(req *mux.Message, client *session) (*pool.Message, er } } - if content == nil || len(content.Data) == 0 { + if len(content.GetData()) == 0 { return client.createResponse(code, req.Token(), coapMessage.TextPlain, nil), nil } - mediaType, err := coapconv.MakeMediaType(-1, content.ContentType) + mediaType, err := coapconv.MakeMediaType(-1, content.GetContentType()) if err != nil { return nil, statusErrorf(code, errFmtRetrieveResource, fmt.Sprintf(" /%v%v", deviceID, href), err) } - return client.createResponse(code, req.Token(), mediaType, content.Data), nil + return client.createResponse(code, req.Token(), mediaType, content.GetData()), nil } func clientRetrieveFromResourceTwinHandler(ctx context.Context, client *session, deviceID, href string, etag []byte) (*commands.Content, coapCodes.Code, error) { @@ -91,11 +91,11 @@ func clientRetrieveFromResourceTwinHandler(ctx context.Context, client *session, if err != nil { return nil, coapconv.GrpcErr2CoapCode(err, coapconv.Retrieve), err } - if resourceValue.GetData().GetResourceId().GetDeviceId() == deviceID && resourceValue.GetData().GetResourceId().GetHref() == href && resourceValue.GetData().Content != nil { + if resourceValue.GetData().GetResourceId().GetDeviceId() == deviceID && resourceValue.GetData().GetResourceId().GetHref() == href && resourceValue.GetData().GetContent() != nil { if etag != nil && bytes.Equal(etag, resourceValue.GetData().GetEtag()) { return nil, coapCodes.Valid, nil } - return resourceValue.GetData().Content, coapCodes.Content, nil + return resourceValue.GetData().GetContent(), coapCodes.Content, nil } } return nil, coapCodes.NotFound, errors.New("not found") diff --git a/coap-gateway/service/clientUpdateHandler.go b/coap-gateway/service/clientUpdateHandler.go index 4d76f09db..c3b6564ba 100644 --- a/coap-gateway/service/clientUpdateHandler.go +++ b/coap-gateway/service/clientUpdateHandler.go @@ -47,14 +47,14 @@ func clientUpdateHandler(req *mux.Message, client *session) (*pool.Message, erro code = coapconv.GrpcErr2CoapCode(err, coapconv.Update) return nil, statusErrorf(code, errFmtUpdateResource, fmt.Sprintf(" /%v%v", deviceID, href), err) } - if content == nil || len(content.Data) == 0 { + if len(content.GetData()) == 0 { return client.createResponse(code, req.Token(), coapMessage.TextPlain, nil), nil } - mediaType, err := coapconv.MakeMediaType(-1, content.ContentType) + mediaType, err := coapconv.MakeMediaType(-1, content.GetContentType()) if err != nil { return nil, statusErrorf(code, "cannot encode response for update resource /%v%v: %w", deviceID, href, err) } - return client.createResponse(code, req.Token(), mediaType, content.Data), nil + return client.createResponse(code, req.Token(), mediaType, content.GetData()), nil } func clientUpdateDeviceHandler(req *mux.Message, client *session, deviceID, href string) (*commands.Content, error) { diff --git a/coap-gateway/service/devicesStatusUpdater_test.go b/coap-gateway/service/devicesStatusUpdater_test.go index ba2690cb0..d745b60a0 100644 --- a/coap-gateway/service/devicesStatusUpdater_test.go +++ b/coap-gateway/service/devicesStatusUpdater_test.go @@ -64,7 +64,7 @@ func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device. break } require.NoError(t, err) - assert.NotEmpty(t, dev.ProtocolIndependentId) + assert.NotEmpty(t, dev.GetProtocolIndependentId()) dev.ProtocolIndependentId = "" devices = append(devices, dev) } diff --git a/coap-gateway/service/service.go b/coap-gateway/service/service.go index 7aa1a6247..e01492659 100644 --- a/coap-gateway/service/service.go +++ b/coap-gateway/service/service.go @@ -496,25 +496,27 @@ func getTLSInfo(conn net.Conn, logger log.Logger) (deviceID string, validUntil t logger.Debugf("cannot get deviceID from certificate: certificate is not set") return "", time.Time{} } - if tlsCon, ok := conn.(*dtls.Conn); ok { - peerCertificates := tlsCon.ConnectionState().PeerCertificates - if len(peerCertificates) > 0 { - cert, err := x509.ParseCertificate(peerCertificates[0]) - if err != nil { - logger.Warnf("cannot get deviceID from certificate: %w", err) - return "", time.Time{} - } - deviceID, err := coap.GetDeviceIDFromIdentityCertificate(cert) - if err == nil { - return deviceID, cert.NotAfter - } - logger.Warnf("cannot get deviceID from certificate %v: %w", cert.Subject.CommonName, err) - return "", cert.NotAfter - } - logger.Debugf("cannot get deviceID from certificate: certificate is not set") + + tlsCon, ok := conn.(*dtls.Conn) + if !ok { + logger.Debugf("cannot get deviceID from certificate: unsupported connection type") return "", time.Time{} } - logger.Debugf("cannot get deviceID from certificate: unsupported connection type") + peerCertificates := tlsCon.ConnectionState().PeerCertificates + if len(peerCertificates) > 0 { + cert, err := x509.ParseCertificate(peerCertificates[0]) + if err != nil { + logger.Warnf("cannot get deviceID from certificate: %w", err) + return "", time.Time{} + } + deviceID, err := coap.GetDeviceIDFromIdentityCertificate(cert) + if err == nil { + return deviceID, cert.NotAfter + } + logger.Warnf("cannot get deviceID from certificate %v: %w", cert.Subject.CommonName, err) + return "", cert.NotAfter + } + logger.Debugf("cannot get deviceID from certificate: certificate is not set") return "", time.Time{} } diff --git a/coap-gateway/service/session.go b/coap-gateway/service/session.go index 6a8899d20..4900f5f8d 100644 --- a/coap-gateway/service/session.go +++ b/coap-gateway/service/session.go @@ -827,21 +827,21 @@ func (c *session) unpublishResourceLinks(ctx context.Context, hrefs []string, in return nil } - if len(resp.UnpublishedHrefs) == 0 { + if len(resp.GetUnpublishedHrefs()) == 0 { return nil } observer, ok, err := c.getDeviceObserver(ctx) if err != nil { logUnpublishError(err) - return resp.UnpublishedHrefs + return resp.GetUnpublishedHrefs() } if !ok { logUnpublishError(errors.New("device observer not found")) - return resp.UnpublishedHrefs + return resp.GetUnpublishedHrefs() } - observer.RemovePublishedResources(ctx, resp.UnpublishedHrefs) - return resp.UnpublishedHrefs + observer.RemovePublishedResources(ctx, resp.GetUnpublishedHrefs()) + return resp.GetUnpublishedHrefs() } func (c *session) sendErrorConfirmResourceCreate(ctx context.Context, resourceID *commands.ResourceId, correlationID string, code codes.Code, errToSend error) { diff --git a/coap-gateway/service/signIn.go b/coap-gateway/service/signIn.go index f49bf5d60..fcf6ff884 100644 --- a/coap-gateway/service/signIn.go +++ b/coap-gateway/service/signIn.go @@ -170,10 +170,10 @@ func subscribeToDeviceEvents(client *session, owner, deviceID string) error { if evt == nil { return } - if evt.Owner != owner { + if evt.GetOwner() != owner { return } - if !strings.Contains(evt.DeviceIds, deviceID) { + if !strings.Contains(evt.GetDeviceIds(), deviceID) { return } client.Close() diff --git a/grpc-gateway/client/client.go b/grpc-gateway/client/client.go index 491410b68..7c8951874 100644 --- a/grpc-gateway/client/client.go +++ b/grpc-gateway/client/client.go @@ -45,7 +45,7 @@ func New(client pb.GrpcGatewayClient) *Client { // NewFromConfig constructs a new client client. For every call there is expected jwt token for grpc stored in context. func NewFromConfig(cfg *Config, tlsCfg *tls.Config) (*Client, error) { if cfg == nil || cfg.GatewayAddress == "" { - return nil, errors.New("missing client client config") + return nil, errors.New("missing client config") } keepAlive := keepalive.ClientParameters{ @@ -195,19 +195,20 @@ func (c *Client) GetResourceLinksIterator(ctx context.Context, deviceIDs []strin // GetResourcesIterator gets resources contents from resource twin (cache of backend). JWT token must be stored in context for grpc call. // By resourceIDs you can specify resources by deviceID and Href which will be retrieved from the backend, nil means all resources. // Or by deviceIDs or resourceTypes you can filter output when you get all resources. -// Eg: +// +// Example: // // get all resources // it := client.GetResourcesIterator(ctx, nil, nil) // // get all oic.wk.d resources -// iter := client.GetResourcesIterator(ctx, nil, nil, "oic.wk.d") +// it := client.GetResourcesIterator(ctx, nil, nil, "oic.wk.d") // // get oic.wk.d resources of 2 devices -// iter := client.GetResourcesIterator(ctx, nil, string["60f6869d-343a-4989-7462-81ef215d31af", "07ef9eb6-1ce9-4ce4-73a6-9ee0a1d534d2"], "oic.wk.d") +// it := client.GetResourcesIterator(ctx, nil, string["60f6869d-343a-4989-7462-81ef215d31af", "07ef9eb6-1ce9-4ce4-73a6-9ee0a1d534d2"], "oic.wk.d") // // get a certain resource /oic/p of the device"60f6869d-343a-4989-7462-81ef215d31af" -// iter := client.GetResourcesIterator(ctx, commands.NewResourceID("60f6869d-343a-4989-7462-81ef215d31af", /oic/p), nil) +// it := client.GetResourcesIterator(ctx, commands.NewResourceID("60f6869d-343a-4989-7462-81ef215d31af", /oic/p), nil) // // Next queries the next resource value. // Returns false when failed or having no more items. diff --git a/grpc-gateway/client/deviceSubscriber.go b/grpc-gateway/client/deviceSubscriber.go index e4daefa5e..23e76688a 100644 --- a/grpc-gateway/client/deviceSubscriber.go +++ b/grpc-gateway/client/deviceSubscriber.go @@ -322,7 +322,7 @@ func (s *DeviceSubscriber) createSpanEvent(ctx context.Context, name string) (co opentelemetry.InstrumentationName, trace.WithInstrumentationVersion(opentelemetry.SemVersion()), ) - return tracer.Start(ctx, name, trace.WithSpanKind(trace.SpanKindConsumer)) + return tracer.Start(ctx, name, trace.WithSpanKind(trace.SpanKindConsumer)) //nolint:spancheck } func (s *DeviceSubscriber) processPendingCommand(ctx context.Context, h *DeviceSubscriptionHandlers, ev *pbGRPC.PendingCommand) error { diff --git a/grpc-gateway/service/deleteDevices.go b/grpc-gateway/service/deleteDevices.go index 134b500a6..692ab8be2 100644 --- a/grpc-gateway/service/deleteDevices.go +++ b/grpc-gateway/service/deleteDevices.go @@ -28,7 +28,7 @@ func partitionDeletedDevices(expected, actual []string) ([]string, []string) { func (r *RequestHandler) DeleteDevices(ctx context.Context, req *pb.DeleteDevicesRequest) (*pb.DeleteDevicesResponse, error) { // get unique non-empty ids - deviceIDs, _ := strings.Split(strings.Unique(req.DeviceIdFilter), func(s string) bool { + deviceIDs, _ := strings.Split(strings.Unique(req.GetDeviceIdFilter()), func(s string) bool { return s != "" }) diff --git a/grpc-gateway/service/deleteDevices_test.go b/grpc-gateway/service/deleteDevices_test.go index 40b742fbf..d77ba76fe 100644 --- a/grpc-gateway/service/deleteDevices_test.go +++ b/grpc-gateway/service/deleteDevices_test.go @@ -78,7 +78,7 @@ func TestRequestHandlerDeleteDevices(t *testing.T) { t.Run(tt.name, func(t *testing.T) { resp, err := c.DeleteDevices(ctx, tt.args.req) require.NoError(t, err) - require.Equal(t, tt.want.DeviceIds, resp.DeviceIds) + require.Equal(t, tt.want.GetDeviceIds(), resp.GetDeviceIds()) }) } } @@ -87,7 +87,7 @@ func waitForOperationProcessedEvent(t *testing.T, subClient pb.GrpcGateway_Subsc ev, err := subClient.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: corID, Type: &pb.Event_OperationProcessed_{ OperationProcessed: &pb.Event_OperationProcessed{ @@ -105,7 +105,7 @@ func waitForStopEvent(t *testing.T, subClient pb.GrpcGateway_SubscribeToEventsCl require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: corID, Type: &pb.Event_DeviceUnregistered_{ DeviceUnregistered: &pb.Event_DeviceUnregistered{ @@ -161,7 +161,7 @@ func TestRequestHandlerReconnectAfterDeleteDevice(t *testing.T) { DeviceIdFilter: []string{deviceID}, }) require.NoError(t, err) - require.Equal(t, []string{deviceID}, resp.DeviceIds) + require.Equal(t, []string{deviceID}, resp.GetDeviceIds()) waitForStopEvent(t, subClient, deviceID, correlationID) err = subClient.CloseSend() require.NoError(t, err) diff --git a/grpc-gateway/service/deleteResource_test.go b/grpc-gateway/service/deleteResource_test.go index 0b66e8559..9401e475a 100644 --- a/grpc-gateway/service/deleteResource_test.go +++ b/grpc-gateway/service/deleteResource_test.go @@ -187,8 +187,8 @@ func TestRequestHandlerDeleteResourceAfterUnpublish(t *testing.T) { }, }) require.NoError(t, err) - require.Len(t, respUnpublish.UnpublishedHrefs, 1) - require.Equal(t, respUnpublish.UnpublishedHrefs[0], test.TestResourceSwitchesInstanceHref(switchID2)) + require.Len(t, respUnpublish.GetUnpublishedHrefs(), 1) + require.Equal(t, respUnpublish.GetUnpublishedHrefs()[0], test.TestResourceSwitchesInstanceHref(switchID2)) // for update resource-directory cache time.Sleep(time.Second) diff --git a/grpc-gateway/service/getDevices_test.go b/grpc-gateway/service/getDevices_test.go index c074499a1..08b99bf6d 100644 --- a/grpc-gateway/service/getDevices_test.go +++ b/grpc-gateway/service/getDevices_test.go @@ -96,7 +96,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { break } require.NoError(t, err) - assert.NotEmpty(t, dev.ProtocolIndependentId) + assert.NotEmpty(t, dev.GetProtocolIndependentId()) assert.NotEmpty(t, dev.GetData().GetContent().GetData()) assert.NotEmpty(t, dev.GetMetadata().GetConnection().GetServiceId()) devices = append(devices, dev) diff --git a/grpc-gateway/service/getHubConfiguration_test.go b/grpc-gateway/service/getHubConfiguration_test.go index e374ff4fc..5e9d0ee65 100644 --- a/grpc-gateway/service/getHubConfiguration_test.go +++ b/grpc-gateway/service/getHubConfiguration_test.go @@ -51,7 +51,7 @@ func TestRequestHandlerGetHubConfiguration(t *testing.T) { got, err := c.GetHubConfiguration(ctxWithoutToken, &pb.HubConfigurationRequest{}) require.NoError(t, err) require.NotEmpty(t, got.GetBuildInfo()) - got.BuildInfo.ReleaseUrl = expected.BuildInfo.ReleaseUrl + got.BuildInfo.ReleaseUrl = expected.GetBuildInfo().GetReleaseUrl() pbTest.CmpHubConfigurationResponse(t, tt.want, got) }) } diff --git a/grpc-gateway/service/subscribeToEvents_test.go b/grpc-gateway/service/subscribeToEvents_test.go index 4ea25baf1..86d72f88a 100644 --- a/grpc-gateway/service/subscribeToEvents_test.go +++ b/grpc-gateway/service/subscribeToEvents_test.go @@ -35,6 +35,7 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" serviceTest "github.com/plgd-dev/hub/v2/test/service" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/grpc" @@ -212,10 +213,10 @@ func TestRequestHandlerSubscribeToEvents(t *testing.T) { if errors.Is(errR, io.EOF) { break } - require.NoError(t, errR) + assert.NoError(t, errR) events = append(events, ev) } - pbTest.CmpEvents(t, tt.want, events) + pbTest.AssertCmpEvents(t, tt.want, events) }() err = client.Send(tt.args.sub) require.NoError(t, err) @@ -264,7 +265,7 @@ func TestRequestHandlerSubscribeForCreateEvents(t *testing.T) { ev, err := client.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: pbTest.OperationProcessedOK(), CorrelationId: "testToken", } @@ -277,7 +278,7 @@ func TestRequestHandlerSubscribeForCreateEvents(t *testing.T) { ev, err = client.Recv() require.NoError(t, err) pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreatePending{ ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, "", @@ -298,7 +299,7 @@ func TestRequestHandlerSubscribeForCreateEvents(t *testing.T) { ev, err = client.Recv() require.NoError(t, err) pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreated{ ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, "", switchData), @@ -345,7 +346,7 @@ func TestRequestHandlerSubscribeForHrefEvents(t *testing.T) { ev, err := client.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: pbTest.OperationProcessedOK(), CorrelationId: "testToken", } @@ -363,7 +364,7 @@ func TestRequestHandlerSubscribeForHrefEvents(t *testing.T) { } if ev.GetResourceCreatePending() != nil { pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreatePending{ ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, "", @@ -394,7 +395,7 @@ func TestRequestHandlerSubscribeForHrefEvents(t *testing.T) { } if ev.GetResourceCreated() != nil { pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreated{ ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, "", switchData), @@ -750,12 +751,12 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { ev, err := client.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: pbTest.OperationProcessedOK(), CorrelationId: correlationID, } test.CheckProtobufs(t, expectedEvent, ev, test.RequireToCheckFunc(require.Equal)) - subscriptionID := ev.SubscriptionId + subscriptionID := ev.GetSubscriptionId() fmt.Printf("sub %v\n", subscriptionID) values := make([]*pb.PendingCommand, 0, 1) @@ -859,17 +860,17 @@ func TestRequestHandlerIssue270(t *testing.T) { ev, err := client.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: pbTest.OperationProcessedOK(), CorrelationId: "testToken", } - fmt.Printf("SUBSCRIPTION ID: %v\n", ev.SubscriptionId) + fmt.Printf("SUBSCRIPTION ID: %v\n", ev.GetSubscriptionId()) test.CheckProtobufs(t, expectedEvent, ev, test.RequireToCheckFunc(require.Equal)) ev, err = client.Recv() require.NoError(t, err) expectedEvent = &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceRegistered_{ DeviceRegistered: &pb.Event_DeviceRegistered{ DeviceIds: []string{}, @@ -886,7 +887,7 @@ func TestRequestHandlerIssue270(t *testing.T) { ev, err = client.Recv() require.NoError(t, err) expectedEvent = &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceRegistered_{ DeviceRegistered: &pb.Event_DeviceRegistered{ DeviceIds: []string{deviceID}, @@ -902,7 +903,7 @@ func TestRequestHandlerIssue270(t *testing.T) { ev, err = client.Recv() require.NoError(t, err) pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ DeviceId: deviceID, @@ -930,7 +931,7 @@ func TestRequestHandlerIssue270(t *testing.T) { if ev.GetDeviceUnregistered() != nil { expectedEvent = &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceUnregistered_{ DeviceUnregistered: &pb.Event_DeviceUnregistered{ DeviceIds: []string{deviceID}, @@ -961,7 +962,7 @@ func waitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, // this alternate to multiple values ev.GetDeviceMetadataUpdated().TwinSynchronization = nil pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ DeviceId: deviceID, @@ -1036,7 +1037,7 @@ func TestCoAPGatewayServiceHeartbeat(t *testing.T) { ev, err := client.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: pbTest.OperationProcessedOK(), CorrelationId: "testToken", } @@ -1066,7 +1067,7 @@ func TestCoAPGatewayServiceHeartbeat(t *testing.T) { ev, err = client.Recv() require.NoError(t, err) pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ DeviceId: deviceID, @@ -1107,7 +1108,7 @@ func TestCoAPGatewayServiceHeartbeat(t *testing.T) { ev, err = client.Recv() require.NoError(t, err) pbTest.CmpEvent(t, &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ DeviceId: deviceID, diff --git a/grpc-gateway/service/updateDeviceMetadata_test.go b/grpc-gateway/service/updateDeviceMetadata_test.go index d30978aaf..45eb23d25 100644 --- a/grpc-gateway/service/updateDeviceMetadata_test.go +++ b/grpc-gateway/service/updateDeviceMetadata_test.go @@ -265,7 +265,7 @@ func waitForResourceChanged(filter *contentChangedFilter, ignoreHrefs ...string) return ev } for _, ignoreHref := range ignoreHrefs { - if ignoreHref == evChanged.GetResourceId().Href { + if ignoreHref == evChanged.GetResourceId().GetHref() { return waitForResourceChanged(filter, ignoreHrefs...) } } diff --git a/grpc-gateway/service/updateResource_test.go b/grpc-gateway/service/updateResource_test.go index 0b0480fce..d19ca017d 100644 --- a/grpc-gateway/service/updateResource_test.go +++ b/grpc-gateway/service/updateResource_test.go @@ -25,6 +25,7 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" "github.com/plgd-dev/hub/v2/test/service" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -404,7 +405,7 @@ func TestRequestHandlerRunMultipleParallelUpdateResource(t *testing.T) { }), }, }) - require.NoError(t, err) + assert.NoError(t, err) } }() } diff --git a/grpc-gateway/subscription/subscription_test.go b/grpc-gateway/subscription/subscription_test.go index ac4a50619..f190aa43e 100644 --- a/grpc-gateway/subscription/subscription_test.go +++ b/grpc-gateway/subscription/subscription_test.go @@ -43,7 +43,7 @@ func waitForEvent(ctx context.Context, t *testing.T, recvChan <-chan *pb.Event) func check(t *testing.T, ev *pb.Event, expectedEvent *pb.Event) { if expectedEvent.GetResourcePublished() != nil { - expectedEvent.SubscriptionId = ev.SubscriptionId + expectedEvent.SubscriptionId = ev.GetSubscriptionId() } pbTest.CmpEvent(t, expectedEvent, ev, "") } diff --git a/http-gateway/service/deleteDevices_test.go b/http-gateway/service/deleteDevices_test.go index 3a5ab5309..3533631c3 100644 --- a/http-gateway/service/deleteDevices_test.go +++ b/http-gateway/service/deleteDevices_test.go @@ -93,7 +93,7 @@ func TestRequestHandlerDeleteDevices(t *testing.T) { var got pb.DeleteDevicesResponse err = httpgwTest.Unmarshal(resp.StatusCode, resp.Body, &got) require.NoError(t, err) - require.Equal(t, tt.want.DeviceIds, got.DeviceIds) + require.Equal(t, tt.want.GetDeviceIds(), got.GetDeviceIds()) }) } } diff --git a/http-gateway/service/getDevice_test.go b/http-gateway/service/getDevice_test.go index 3e3c09c98..3fbe5d2eb 100644 --- a/http-gateway/service/getDevice_test.go +++ b/http-gateway/service/getDevice_test.go @@ -101,7 +101,7 @@ func TestRequestHandlerGetDevice(t *testing.T) { return } require.NoError(t, err) - assert.NotEmpty(t, dev.ProtocolIndependentId) + assert.NotEmpty(t, dev.GetProtocolIndependentId()) devices = append(devices, &dev) } pbTest.CmpDeviceValues(t, tt.want, devices) diff --git a/http-gateway/service/getDevices_test.go b/http-gateway/service/getDevices_test.go index db6db4416..5407ca37b 100644 --- a/http-gateway/service/getDevices_test.go +++ b/http-gateway/service/getDevices_test.go @@ -134,7 +134,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { defer shutdownDevSim() toStringSlice := func(s []pb.GetDevicesRequest_Status) []string { - var sf []string + sf := make([]string, 0, len(s)) for _, v := range s { sf = append(sf, strconv.FormatInt(int64(v), 10)) } @@ -158,7 +158,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { break } require.NoError(t, err) - assert.NotEmpty(t, dev.ProtocolIndependentId) + assert.NotEmpty(t, dev.GetProtocolIndependentId()) devices = append(devices, &dev) } pbTest.CmpDeviceValues(t, tt.want, devices) diff --git a/http-gateway/service/subscribeToEvents_test.go b/http-gateway/service/subscribeToEvents_test.go index db3118b19..ed329e8ec 100644 --- a/http-gateway/service/subscribeToEvents_test.go +++ b/http-gateway/service/subscribeToEvents_test.go @@ -212,7 +212,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource ev, err := recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_OperationProcessed_{ OperationProcessed: &pb.Event_OperationProcessed{ ErrorStatus: &pb.Event_OperationProcessed_ErrorStatus{ @@ -223,7 +223,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource CorrelationId: "testToken", } pbTest.CmpEvent(t, expectedEvent, ev, "") - baseSubID := ev.SubscriptionId + baseSubID := ev.GetSubscriptionId() deviceID, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, nil) @@ -269,7 +269,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource ev, err = recv() require.NoError(t, err) expectedEvent = &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_OperationProcessed_{ OperationProcessed: &pb.Event_OperationProcessed{ ErrorStatus: &pb.Event_OperationProcessed_ErrorStatus{ @@ -285,7 +285,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource c: c, deviceID: deviceID, baseSubID: baseSubID, - subUpdatedID: ev.SubscriptionId, + subUpdatedID: ev.GetSubscriptionId(), recv: recv, } updChecker.checkUpdateLightResource(ctx, t, 99) @@ -308,7 +308,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource ev, err = recv() require.NoError(t, err) expectedEvent = &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_OperationProcessed_{ OperationProcessed: &pb.Event_OperationProcessed{ ErrorStatus: &pb.Event_OperationProcessed_ErrorStatus{ @@ -319,7 +319,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource CorrelationId: "receivePending + resourceReceived", } pbTest.CmpEvent(t, expectedEvent, ev, "") - subReceivedID := ev.SubscriptionId + subReceivedID := ev.GetSubscriptionId() _, err = c.GetResourceFromDevice(ctx, &pb.GetResourceFromDeviceRequest{ ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), @@ -367,7 +367,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource if ev.GetDeviceUnregistered() != nil { expectedEvent = &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), Type: &pb.Event_DeviceUnregistered_{ DeviceUnregistered: &pb.Event_DeviceUnregistered{ DeviceIds: []string{deviceID}, diff --git a/http-gateway/test/pendingCommands.go b/http-gateway/test/pendingCommands.go index 81b1a6c10..0fe922f86 100644 --- a/http-gateway/test/pendingCommands.go +++ b/http-gateway/test/pendingCommands.go @@ -7,7 +7,7 @@ import ( ) func ToCommandsFilter(s []pb.GetPendingCommandsRequest_Command) []string { - var sf []string + sf := make([]string, 0, len(s)) for _, v := range s { sf = append(sf, strconv.FormatInt(int64(v), 10)) } diff --git a/identity-store/client/ownerCache.go b/identity-store/client/ownerCache.go index 634b1337c..559cb6358 100644 --- a/identity-store/client/ownerCache.go +++ b/identity-store/client/ownerCache.go @@ -186,7 +186,7 @@ func (c *OwnerCache) getOwnerDevices(ctx context.Context, isClient pbIS.Identity if err != nil { return nil, status.Errorf(status.Convert(err).Code(), "cannot receive owners devices: %v", err) } - ownerDevices = append(ownerDevices, device.DeviceId) + ownerDevices = append(ownerDevices, device.GetDeviceId()) } return ownerDevices, nil } diff --git a/identity-store/client/ownerCache_test.go b/identity-store/client/ownerCache_test.go index 1da485754..233ea169a 100644 --- a/identity-store/client/ownerCache_test.go +++ b/identity-store/client/ownerCache_test.go @@ -171,7 +171,7 @@ func TestOwnerCacheSubscribe(t *testing.T) { DeviceIds: devices[:1], }) require.NoError(t, err) - assert.Equal(t, devices[:1], deleted.DeviceIds) + assert.Equal(t, devices[:1], deleted.GetDeviceIds()) // check update - after expiration time.Sleep(time.Millisecond * 100) // wait for synchronize the cache, so update doesn't change the cache diff --git a/identity-store/persistence/cqldb/store.go b/identity-store/persistence/cqldb/store.go index e4e75e3af..2c73504d9 100644 --- a/identity-store/persistence/cqldb/store.go +++ b/identity-store/persistence/cqldb/store.go @@ -15,7 +15,7 @@ import ( // Document const ( - // cqldbdb has all keys in in lowercase + // cqldbdb has all keys in lowercase ownerKey = "ownerkey" deviceIDKey = "deviceid" ) diff --git a/identity-store/service/addDevice.go b/identity-store/service/addDevice.go index 46da8cc35..b4e9d72f6 100644 --- a/identity-store/service/addDevice.go +++ b/identity-store/service/addDevice.go @@ -90,13 +90,14 @@ func (s *Service) AddDevice(ctx context.Context, request *pb.AddDeviceRequest) ( return nil, log.LogAndReturnError(status.Errorf(codes.InvalidArgument, "cannot add device: %v", err)) } - if request.DeviceId == "" { + deviceID := request.GetDeviceId() + if deviceID == "" { return nil, log.LogAndReturnError(status.Errorf(codes.InvalidArgument, "cannot add device: invalid DeviceId")) } - dev, ok, err := tx.RetrieveByDevice(request.DeviceId) + dev, ok, err := tx.RetrieveByDevice(deviceID) if err != nil { - return nil, log.LogAndReturnError(status.Errorf(codes.Internal, "cannot add device %v: %v", request.DeviceId, err.Error())) + return nil, log.LogAndReturnError(status.Errorf(codes.Internal, "cannot add device %v: %v", deviceID, err.Error())) } if ok { if dev.Owner == owner { @@ -106,7 +107,7 @@ func (s *Service) AddDevice(ctx context.Context, request *pb.AddDeviceRequest) ( } d := persistence.AuthorizedDevice{ - DeviceID: request.DeviceId, + DeviceID: deviceID, Owner: owner, } @@ -114,7 +115,7 @@ func (s *Service) AddDevice(ctx context.Context, request *pb.AddDeviceRequest) ( return nil, log.LogAndReturnError(status.Errorf(codes.Internal, "cannot add device up: %v", err.Error())) } - s.publishDevicesRegistered(ctx, owner, userID, s.hubID, []string{request.DeviceId}) + s.publishDevicesRegistered(ctx, owner, userID, s.hubID, []string{deviceID}) return &pb.AddDeviceResponse{}, nil } diff --git a/identity-store/service/deleteDevices.go b/identity-store/service/deleteDevices.go index ef9a6193d..1347b7324 100644 --- a/identity-store/service/deleteDevices.go +++ b/identity-store/service/deleteDevices.go @@ -64,14 +64,14 @@ func (s *Service) publishDevicesUnregistered(ctx context.Context, owner, userID, func getDeviceIDs(request *pb.DeleteDevicesRequest, tx persistence.PersistenceTx, owner string) ([]string, error) { var deviceIds []string - if len(request.DeviceIds) == 0 { + if len(request.GetDeviceIds()) == 0 { var err error if deviceIds, err = getOwnerDevices(tx, owner); err != nil { return nil, status.Errorf(codes.InvalidArgument, "cannot delete devices: %v", err) } return deviceIds, nil } - deviceIds = getUniqueDeviceIds(request.DeviceIds) + deviceIds = getUniqueDeviceIds(request.GetDeviceIds()) if len(deviceIds) == 0 { return nil, status.Errorf(codes.InvalidArgument, "cannot delete devices: invalid DeviceIds") } @@ -112,7 +112,7 @@ func (s *Service) DeleteDevices(ctx context.Context, request *pb.DeleteDevicesRe return &pb.DeleteDevicesResponse{}, nil } - var deletedDeviceIDs []string + deletedDeviceIDs := make([]string, 0, len(deviceIDs)) for _, deviceID := range deviceIDs { ok, err := deleteDevice(tx, deviceID, owner) if err != nil { @@ -126,7 +126,9 @@ func (s *Service) DeleteDevices(ctx context.Context, request *pb.DeleteDevicesRe s.publishDevicesUnregistered(ctx, owner, userID, s.hubID, deletedDeviceIDs) - return &pb.DeleteDevicesResponse{ - DeviceIds: deletedDeviceIDs, - }, nil + resp := &pb.DeleteDevicesResponse{} + if len(deletedDeviceIDs) > 0 { + resp.DeviceIds = deletedDeviceIDs + } + return resp, nil } diff --git a/identity-store/service/deleteDevices_test.go b/identity-store/service/deleteDevices_test.go index 6ddddda66..1ee423c75 100644 --- a/identity-store/service/deleteDevices_test.go +++ b/identity-store/service/deleteDevices_test.go @@ -145,8 +145,8 @@ func TestServiceDeleteDevices(t *testing.T) { return } require.NoError(t, err) - sort.Strings(tt.want.DeviceIds) - sort.Strings(got.DeviceIds) + sort.Strings(tt.want.GetDeviceIds()) + sort.Strings(got.GetDeviceIds()) require.Equal(t, tt.want, got) }) } diff --git a/identity-store/service/getDevices_test.go b/identity-store/service/getDevices_test.go index 31506a12c..1d1544012 100644 --- a/identity-store/service/getDevices_test.go +++ b/identity-store/service/getDevices_test.go @@ -84,7 +84,7 @@ func (d *mockGeDevicesServer) Send(r *pb.Device) error { if d.resourceValues == nil { d.resourceValues = make(map[string]*pb.Device) } - d.resourceValues[r.DeviceId] = r + d.resourceValues[r.GetDeviceId()] = r return nil } diff --git a/pkg/net/coap/service/service_test.go b/pkg/net/coap/service/service_test.go index f48269fd5..93d560629 100644 --- a/pkg/net/coap/service/service_test.go +++ b/pkg/net/coap/service/service_test.go @@ -16,6 +16,7 @@ import ( "github.com/plgd-dev/hub/v2/pkg/log" "github.com/plgd-dev/hub/v2/pkg/service" "github.com/plgd-dev/hub/v2/test/config" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.uber.org/atomic" ) @@ -108,7 +109,7 @@ func TestNew(t *testing.T) { require.NoError(t, err) go func() { errS := got.Serve() - require.NoError(t, errS) + assert.NoError(t, errS) }() err = got.Close() require.NoError(t, err) @@ -153,7 +154,7 @@ func TestOnClientInactivityTCP(t *testing.T) { require.NoError(t, err) go func() { errS := got.Serve() - require.NoError(t, errS) + assert.NoError(t, errS) }() time.Sleep(time.Second * 3) @@ -218,7 +219,7 @@ func TestOnClientInactivityUDP(t *testing.T) { require.NoError(t, err) go func() { errS := got.Serve() - require.NoError(t, errS) + assert.NoError(t, errS) }() time.Sleep(time.Second * 3) @@ -288,7 +289,7 @@ func TestOnClientInactivityCustomTCP(t *testing.T) { require.NoError(t, err) go func() { errS := got.Serve() - require.NoError(t, errS) + assert.NoError(t, errS) }() time.Sleep(time.Second * 3) @@ -359,7 +360,7 @@ func TestOnClientInactivityCustomUDP(t *testing.T) { require.NoError(t, err) go func() { errS := got.Serve() - require.NoError(t, errS) + assert.NoError(t, errS) }() time.Sleep(time.Second * 3) diff --git a/pkg/opentelemetry/otelcoap/opentelemetry.go b/pkg/opentelemetry/otelcoap/opentelemetry.go index 6057bf73f..cbe67c104 100644 --- a/pkg/opentelemetry/otelcoap/opentelemetry.go +++ b/pkg/opentelemetry/otelcoap/opentelemetry.go @@ -109,5 +109,5 @@ func Start(ctx context.Context, path, method string, opts ...Option) (context.Co spanOpts = append(spanOpts, cfg.SpanStartOptions...) } - return tracer.Start(ctx, DefaultTransportFormatter(path), spanOpts...) + return tracer.Start(ctx, DefaultTransportFormatter(path), spanOpts...) //nolint:spancheck } diff --git a/pkg/sync/task/future/future_test.go b/pkg/sync/task/future/future_test.go index af1f13525..452a9edd9 100644 --- a/pkg/sync/task/future/future_test.go +++ b/pkg/sync/task/future/future_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/plgd-dev/hub/v2/test/config" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -60,8 +61,8 @@ func TestFutureGetMultithreaded(t *testing.T) { go func() { defer wg.Done() value, err := fut.Get(ctx) - require.NoError(t, err) - require.Equal(t, val, value.(string)) + assert.NoError(t, err) + assert.Equal(t, val, value.(string)) }() } diff --git a/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go b/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go index d309c1343..73cd5a789 100644 --- a/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go +++ b/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go @@ -19,6 +19,7 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore/mongodb" "github.com/plgd-dev/hub/v2/resource-aggregate/events" "github.com/plgd-dev/hub/v2/test/config" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" "go.uber.org/atomic" @@ -65,7 +66,7 @@ func testNewEventstore(ctx context.Context, t *testing.T) (eventstore.EventStore func cleanUpToSnapshot(ctx context.Context, t *testing.T, store eventstore.EventStore, evs []eventstore.Event) { for _, event := range evs { if err := store.RemoveUpToVersion(ctx, []eventstore.VersionQuery{{GroupID: event.GroupID(), AggregateID: event.AggregateID(), Version: event.Version()}}); err != nil && !errors.Is(err, eventstore.ErrNotSupported) { - require.NoError(t, err) + assert.NoError(t, err) } fmt.Printf("snapshot at version %v\n", event.Version()) } diff --git a/resource-aggregate/cqrs/aggregate/test/aggregate.go b/resource-aggregate/cqrs/aggregate/test/aggregate.go index 57d960a5e..16fd1834f 100644 --- a/resource-aggregate/cqrs/aggregate/test/aggregate.go +++ b/resource-aggregate/cqrs/aggregate/test/aggregate.go @@ -13,43 +13,43 @@ import ( type Command = interface{} -func (e *Published) Version() uint64 { return e.EventVersion } +func (e *Published) Version() uint64 { return e.GetEventVersion() } func (e *Published) EventType() string { return "published" } func (e *Published) Marshal() ([]byte, error) { return proto.Marshal(e) } func (e *Published) Unmarshal(b []byte) error { return proto.Unmarshal(b, e) } func (e *Published) AggregateID() string { - return commands.NewResourceID(e.DeviceId, e.Href).ToUUID().String() + return commands.NewResourceID(e.GetDeviceId(), e.GetHref()).ToUUID().String() } -func (e *Published) GroupID() string { return e.DeviceId } +func (e *Published) GroupID() string { return e.GetDeviceId() } func (e *Published) IsSnapshot() bool { return false } -func (e *Published) Timestamp() time.Time { return time.Unix(0, e.EventTimestamp) } +func (e *Published) Timestamp() time.Time { return time.Unix(0, e.GetEventTimestamp()) } func (e *Published) ETag() *eventstore.ETagData { return nil } func (e *Published) ServiceID() (string, bool) { return "", false } -func (e *Unpublished) Version() uint64 { return e.EventVersion } +func (e *Unpublished) Version() uint64 { return e.GetEventVersion() } func (e *Unpublished) EventType() string { return "unpublished" } func (e *Unpublished) Marshal() ([]byte, error) { return proto.Marshal(e) } func (e *Unpublished) Unmarshal(b []byte) error { return proto.Unmarshal(b, e) } func (e *Unpublished) AggregateID() string { - return commands.NewResourceID(e.DeviceId, e.Href).ToUUID().String() + return commands.NewResourceID(e.GetDeviceId(), e.GetHref()).ToUUID().String() } -func (e *Unpublished) GroupID() string { return e.DeviceId } +func (e *Unpublished) GroupID() string { return e.GetDeviceId() } func (e *Unpublished) IsSnapshot() bool { return false } -func (e *Unpublished) Timestamp() time.Time { return time.Unix(0, e.EventTimestamp) } +func (e *Unpublished) Timestamp() time.Time { return time.Unix(0, e.GetEventTimestamp()) } func (e *Unpublished) ETag() *eventstore.ETagData { return nil } func (e *Unpublished) ServiceID() (string, bool) { return "", false } -func (e *Snapshot) Version() uint64 { return e.EventVersion } +func (e *Snapshot) Version() uint64 { return e.GetEventVersion() } func (e *Snapshot) EventType() string { return "snapshot" } func (e *Snapshot) Marshal() ([]byte, error) { return proto.Marshal(e) } func (e *Snapshot) Unmarshal(b []byte) error { return proto.Unmarshal(b, e) } func (e *Snapshot) AggregateID() string { - return commands.NewResourceID(e.DeviceId, e.Href).ToUUID().String() + return commands.NewResourceID(e.GetDeviceId(), e.GetHref()).ToUUID().String() } -func (e *Snapshot) GroupId() string { return e.DeviceId } -func (e *Snapshot) GroupID() string { return e.DeviceId } +func (e *Snapshot) GroupId() string { return e.GetDeviceId() } +func (e *Snapshot) GroupID() string { return e.GetDeviceId() } func (e *Snapshot) IsSnapshot() bool { return true } -func (e *Snapshot) Timestamp() time.Time { return time.Unix(0, e.EventTimestamp) } +func (e *Snapshot) Timestamp() time.Time { return time.Unix(0, e.GetEventTimestamp()) } func (e *Snapshot) ETag() *eventstore.ETagData { return nil } func (e *Snapshot) ServiceID() (string, bool) { return "", false } @@ -106,13 +106,13 @@ func (e *Snapshot) HandleCommand(_ context.Context, cmd Command, newVersion uint switch req := cmd.(type) { case *Publish: e.IsPublished = true - return []eventstore.Event{&Published{DeviceId: req.DeviceId, Href: req.Href, EventVersion: newVersion}}, nil + return []eventstore.Event{&Published{DeviceId: req.GetDeviceId(), Href: req.GetHref(), EventVersion: newVersion}}, nil case *Unpublish: - if !e.IsPublished { + if !e.GetIsPublished() { return nil, errors.New("not allowed to unpublish twice in tests") } e.IsPublished = false - return []eventstore.Event{&Unpublished{DeviceId: req.DeviceId, Href: req.Href, EventVersion: newVersion}}, nil + return []eventstore.Event{&Unpublished{DeviceId: req.GetDeviceId(), Href: req.GetHref(), EventVersion: newVersion}}, nil } return nil, fmt.Errorf("unknown command %T", cmd) } diff --git a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go index 0556a828b..64a6ef115 100644 --- a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go +++ b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber.go @@ -294,7 +294,7 @@ func (o *Observer) handleMsg(msg *nats.Msg) { hasNext: true, e: &e, dataUnmarshaler: func(v interface{}) error { - return o.dataUnmarshaler(e.Data, v) + return o.dataUnmarshaler(e.GetData(), v) }, } diff --git a/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go b/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go index 2796a4fc0..bd9fc0a9f 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/eventstore.go @@ -17,7 +17,7 @@ import ( // Document const ( - // cqldbdb has all keys in in lowercase + // cqldbdb has all keys in lowercase idKey = "id" versionKey = "version" snapshotKey = "snapshot" diff --git a/resource-aggregate/cqrs/eventstore/cqldb/save.go b/resource-aggregate/cqrs/eventstore/cqldb/save.go index 24684855f..9d2255c35 100644 --- a/resource-aggregate/cqrs/eventstore/cqldb/save.go +++ b/resource-aggregate/cqrs/eventstore/cqldb/save.go @@ -109,27 +109,27 @@ func (s *EventStore) Save(ctx context.Context, events ...eventstore.Event) (even if err := eventstore.ValidateEventsBeforeSave(events); err != nil { return eventstore.Fail, err } - if events[0].Version() == 0 { - lastEvent, data, err := getLatestEventsSnapshot(events, s.config.marshalerFunc) - if err != nil { - return eventstore.Fail, err - } - kvs := eventToKeyValues(lastEvent, true, data) - keys := kvs.Keys() - values := kvs.Values() + if events[0].Version() != 0 { + return s.saveEvent(ctx, events) + } + lastEvent, data, err := getLatestEventsSnapshot(events, s.config.marshalerFunc) + if err != nil { + return eventstore.Fail, err + } + kvs := eventToKeyValues(lastEvent, true, data) + keys := kvs.Keys() + values := kvs.Values() - q := "insert into " + s.Table() + " (" + strings.Join(keys, ",") + ") values (" + strings.Join(values, ",") + ") if not exists;" - ok, err := s.client.Session().Query(q).WithContext(ctx).ScanCAS(nil, nil, nil, nil, nil, nil, nil, nil, nil) - if err != nil { - if errors.Is(err, gocql.ErrNotFound) { - return eventstore.Ok, nil - } - return eventstore.Fail, fmt.Errorf("cannot insert first events('%v'): %w", events, err) - } - if !ok { - return eventstore.ConcurrencyException, nil + q := "insert into " + s.Table() + " (" + strings.Join(keys, ",") + ") values (" + strings.Join(values, ",") + ") if not exists;" + ok, err := s.client.Session().Query(q).WithContext(ctx).ScanCAS(nil, nil, nil, nil, nil, nil, nil, nil, nil) + if err != nil { + if errors.Is(err, gocql.ErrNotFound) { + return eventstore.Ok, nil } - return eventstore.Ok, nil + return eventstore.Fail, fmt.Errorf("cannot insert first events('%v'): %w", events, err) } - return s.saveEvent(ctx, events) + if !ok { + return eventstore.ConcurrencyException, nil + } + return eventstore.Ok, nil } diff --git a/resource-aggregate/cqrs/eventstore/projection.go b/resource-aggregate/cqrs/eventstore/projection.go index 345a8ff01..505f1f4bc 100644 --- a/resource-aggregate/cqrs/eventstore/projection.go +++ b/resource-aggregate/cqrs/eventstore/projection.go @@ -137,37 +137,37 @@ func (i *iterator) RewindIgnore(ctx context.Context) (EventUnmarshaler, bool) { } func (i *iterator) Next(ctx context.Context) (EventUnmarshaler, bool) { - if i.firstEvent != nil { - tmp := i.firstEvent - i.firstEvent = nil - ignore, reload := i.model.Update(tmp) - i.model.LogDebugfFunc("projection.iterator.next: GroupID %v: AggregateID %v: Version %v, EvenType %v, ignore %v reload %v", tmp.GroupID, tmp.AggregateID, tmp.Version, tmp.EventType, ignore, reload) - if reload { - snapshot, nextAggregateEvent := i.RewindToSnapshot(ctx) - if snapshot == nil { - i.nextEventToProcess = nextAggregateEvent - i.reload = &VersionQuery{GroupID: tmp.GroupID(), AggregateID: tmp.AggregateID(), Version: i.model.version} - return nil, false - } - tmp = snapshot - ignore, reload = i.model.Update(tmp) - if reload { - i.nextEventToProcess = i.RewindToNextAggregateEvent(ctx) - i.reload = &VersionQuery{GroupID: tmp.GroupID(), AggregateID: tmp.AggregateID(), Version: i.model.version} - return nil, false - } + if i.firstEvent == nil { + e, ok := i.RewindIgnore(ctx) + if ok { + i.model.LogDebugfFunc("projection.iterator.next: GroupID %v: AggregateID %v: Version %v, EvenType %v", e.GroupID, e.AggregateID, e.Version, e.EventType) } - if ignore { - return i.RewindIgnore(ctx) - } - return tmp, true + return e, ok } - e, ok := i.RewindIgnore(ctx) - if ok { - i.model.LogDebugfFunc("projection.iterator.next: GroupID %v: AggregateID %v: Version %v, EvenType %v", e.GroupID, e.AggregateID, e.Version, e.EventType) + tmp := i.firstEvent + i.firstEvent = nil + ignore, reload := i.model.Update(tmp) + i.model.LogDebugfFunc("projection.iterator.next: GroupID %v: AggregateID %v: Version %v, EvenType %v, ignore %v reload %v", tmp.GroupID, tmp.AggregateID, tmp.Version, tmp.EventType, ignore, reload) + if reload { + snapshot, nextAggregateEvent := i.RewindToSnapshot(ctx) + if snapshot == nil { + i.nextEventToProcess = nextAggregateEvent + i.reload = &VersionQuery{GroupID: tmp.GroupID(), AggregateID: tmp.AggregateID(), Version: i.model.version} + return nil, false + } + tmp = snapshot + ignore, reload = i.model.Update(tmp) + if reload { + i.nextEventToProcess = i.RewindToNextAggregateEvent(ctx) + i.reload = &VersionQuery{GroupID: tmp.GroupID(), AggregateID: tmp.AggregateID(), Version: i.model.version} + return nil, false + } + } + if ignore { + return i.RewindIgnore(ctx) } - return e, ok + return tmp, true } func (i *iterator) Err() error { diff --git a/resource-aggregate/cqrs/projection/projectionInternal_test.go b/resource-aggregate/cqrs/projection/projectionInternal_test.go index c4aa32152..bf537dd85 100644 --- a/resource-aggregate/cqrs/projection/projectionInternal_test.go +++ b/resource-aggregate/cqrs/projection/projectionInternal_test.go @@ -132,7 +132,7 @@ func TestProjection(t *testing.T) { CommandMetadata: &commands.CommandMetadata{}, } - a1, err := aggregate.NewAggregate(res1.DeviceId, res1.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { + a1, err := aggregate.NewAggregate(res1.GetDeviceId(), res1.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") s.ResourceId = &res1 return s, nil @@ -143,7 +143,7 @@ func TestProjection(t *testing.T) { require.NoError(t, err) require.NotNil(t, evs) - a2, err := aggregate.NewAggregate(res2.DeviceId, res2.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { + a2, err := aggregate.NewAggregate(res2.GetDeviceId(), res2.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") s.ResourceId = &res2 return s, nil @@ -158,7 +158,7 @@ func TestProjection(t *testing.T) { require.NoError(t, err) err = projection.Project(ctx, []eventstore.SnapshotQuery{{ - GroupID: res1.DeviceId, + GroupID: res1.GetDeviceId(), AggregateID: res1.ToUUID().String(), }}) require.NoError(t, err) @@ -170,7 +170,7 @@ func TestProjection(t *testing.T) { require.Len(t, models, 1) err = projection.Project(ctx, []eventstore.SnapshotQuery{{ - GroupID: res2.DeviceId, + GroupID: res2.GetDeviceId(), AggregateID: res2.ToUUID().String(), }}) require.NoError(t, err) @@ -186,7 +186,7 @@ func TestProjection(t *testing.T) { time.Sleep(waitForSubscription) - a3, err := aggregate.NewAggregate(res3.DeviceId, res3.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { + a3, err := aggregate.NewAggregate(res3.GetDeviceId(), res3.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") s.ResourceId = &res3 return s, nil @@ -197,7 +197,7 @@ func TestProjection(t *testing.T) { require.NoError(t, err) require.NotNil(t, evs) for _, e := range evs { - err = publisher.Publish(ctx, topics, res3.DeviceId, res3.ToUUID().String(), e) + err = publisher.Publish(ctx, topics, res3.GetDeviceId(), res3.ToUUID().String(), e) require.NoError(t, err) } time.Sleep(time.Second) @@ -215,7 +215,7 @@ func TestProjection(t *testing.T) { time.Sleep(waitForSubscription) err = projection.Forget([]eventstore.SnapshotQuery{{ - GroupID: res3.DeviceId, + GroupID: res3.GetDeviceId(), AggregateID: res3.ToUUID().String(), }}) require.NoError(t, err) @@ -242,7 +242,7 @@ func TestProjection(t *testing.T) { require.NoError(t, err) require.NotNil(t, evs) for _, e := range evs { - err = publisher.Publish(ctx, topics, res1.DeviceId, res1.ToUUID().String(), e) + err = publisher.Publish(ctx, topics, res1.GetDeviceId(), res1.ToUUID().String(), e) require.NoError(t, err) } diff --git a/resource-aggregate/cqrs/projection/projection_test.go b/resource-aggregate/cqrs/projection/projection_test.go index 071896d7c..12a308356 100644 --- a/resource-aggregate/cqrs/projection/projection_test.go +++ b/resource-aggregate/cqrs/projection/projection_test.go @@ -95,32 +95,32 @@ func makeEventMeta(connectionID string, version uint64) *events.EventMetadata { func prepareResourceLinksEventstore() *mockEvents.MockEventStore { eventstore := mockEvents.NewMockEventStore() - d1resID := commands.MakeLinksResourceUUID(d1res1.DeviceId) - eventstore.Append(d1res1.DeviceId, d1resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d1res1}, d1res1.DeviceId, makeEventMeta("a", 0))) - eventstore.Append(d1res2.DeviceId, d1resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d1res2, &d1res3}, d1res2.DeviceId, makeEventMeta("a", 1))) - eventstore.Append(d1res2.DeviceId, d1resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d1res2.Href}, d1res2.DeviceId, makeEventMeta("a", 2))) - eventstore.Append(d1res4.DeviceId, d1resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d1res4, &d1res5}, d1res4.DeviceId, makeEventMeta("a", 3))) - - d2resID := commands.MakeLinksResourceUUID(d2res1.DeviceId) - eventstore.Append(d2res1.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d2res1, &d2res2}, d2res1.DeviceId, makeEventMeta("a", 0))) - eventstore.Append(d2res1.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res1.Href}, d2res1.DeviceId, makeEventMeta("a", 1))) - eventstore.Append(d2res2.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res2.Href}, d2res2.DeviceId, makeEventMeta("a", 2))) - eventstore.Append(d2res2.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res2.Href}, d2res2.DeviceId, makeEventMeta("a", 3))) - eventstore.Append(d2res1.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d2res1, &d2res1}, d2res1.DeviceId, makeEventMeta("a", 4))) - eventstore.Append(d2res2.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res2.Href, d2res2.Href}, d2res2.DeviceId, makeEventMeta("a", 5))) - eventstore.Append(d2res1.DeviceId, d2resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d2res1}, d2res1.DeviceId, makeEventMeta("a", 6))) - - d3resID := commands.MakeLinksResourceUUID(d3res1.DeviceId) - eventstore.Append(d3res1.DeviceId, d3resID.String(), mockEvents.MakeResourceLinksSnapshotTaken(map[string]*commands.Resource{d3res1.Href: &d3res1, d3res2.Href: &d3res2}, d3res1.DeviceId, makeEventMeta("a", 0))) - eventstore.Append(d3res1.DeviceId, d3resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d3res1.Href}, d3res1.DeviceId, makeEventMeta("a", 1))) - - d4resID := commands.MakeLinksResourceUUID(d4res1.DeviceId) - eventstore.Append(d4res1.DeviceId, d4resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d4res1, &d4res2}, d4res1.DeviceId, makeEventMeta("a", 0))) - eventstore.Append(d4res1.DeviceId, d4resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{}, d4res1.DeviceId, makeEventMeta("a", 1))) - - d5resID := commands.MakeLinksResourceUUID(d5res1.DeviceId) - eventstore.Append(d5res1.DeviceId, d5resID.String(), mockEvents.MakeResourceLinksSnapshotTaken(map[string]*commands.Resource{d5res1.Href: &d5res1, d5res2.Href: &d5res2}, d5res1.DeviceId, makeEventMeta("a", 0))) - eventstore.Append(d5res1.DeviceId, d5resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{}, d5res1.DeviceId, makeEventMeta("a", 1))) + d1resID := commands.MakeLinksResourceUUID(d1res1.GetDeviceId()) + eventstore.Append(d1res1.GetDeviceId(), d1resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d1res1}, d1res1.GetDeviceId(), makeEventMeta("a", 0))) + eventstore.Append(d1res2.GetDeviceId(), d1resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d1res2, &d1res3}, d1res2.GetDeviceId(), makeEventMeta("a", 1))) + eventstore.Append(d1res2.GetDeviceId(), d1resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d1res2.GetHref()}, d1res2.GetDeviceId(), makeEventMeta("a", 2))) + eventstore.Append(d1res4.GetDeviceId(), d1resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d1res4, &d1res5}, d1res4.GetDeviceId(), makeEventMeta("a", 3))) + + d2resID := commands.MakeLinksResourceUUID(d2res1.GetDeviceId()) + eventstore.Append(d2res1.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d2res1, &d2res2}, d2res1.GetDeviceId(), makeEventMeta("a", 0))) + eventstore.Append(d2res1.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res1.GetHref()}, d2res1.GetDeviceId(), makeEventMeta("a", 1))) + eventstore.Append(d2res2.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res2.GetHref()}, d2res2.GetDeviceId(), makeEventMeta("a", 2))) + eventstore.Append(d2res2.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res2.GetHref()}, d2res2.GetDeviceId(), makeEventMeta("a", 3))) + eventstore.Append(d2res1.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d2res1, &d2res1}, d2res1.GetDeviceId(), makeEventMeta("a", 4))) + eventstore.Append(d2res2.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d2res2.GetHref(), d2res2.GetHref()}, d2res2.GetDeviceId(), makeEventMeta("a", 5))) + eventstore.Append(d2res1.GetDeviceId(), d2resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d2res1}, d2res1.GetDeviceId(), makeEventMeta("a", 6))) + + d3resID := commands.MakeLinksResourceUUID(d3res1.GetDeviceId()) + eventstore.Append(d3res1.GetDeviceId(), d3resID.String(), mockEvents.MakeResourceLinksSnapshotTaken(map[string]*commands.Resource{d3res1.GetHref(): &d3res1, d3res2.GetHref(): &d3res2}, d3res1.GetDeviceId(), makeEventMeta("a", 0))) + eventstore.Append(d3res1.GetDeviceId(), d3resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{d3res1.GetHref()}, d3res1.GetDeviceId(), makeEventMeta("a", 1))) + + d4resID := commands.MakeLinksResourceUUID(d4res1.GetDeviceId()) + eventstore.Append(d4res1.GetDeviceId(), d4resID.String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{&d4res1, &d4res2}, d4res1.GetDeviceId(), makeEventMeta("a", 0))) + eventstore.Append(d4res1.GetDeviceId(), d4resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{}, d4res1.GetDeviceId(), makeEventMeta("a", 1))) + + d5resID := commands.MakeLinksResourceUUID(d5res1.GetDeviceId()) + eventstore.Append(d5res1.GetDeviceId(), d5resID.String(), mockEvents.MakeResourceLinksSnapshotTaken(map[string]*commands.Resource{d5res1.GetHref(): &d5res1, d5res2.GetHref(): &d5res2}, d5res1.GetDeviceId(), makeEventMeta("a", 0))) + eventstore.Append(d5res1.GetDeviceId(), d5resID.String(), mockEvents.MakeResourceLinksUnpublishedEvent([]string{}, d5res1.GetDeviceId(), makeEventMeta("a", 1))) return eventstore } @@ -129,38 +129,38 @@ func prepareResourceStateEventstore() *mockEvents.MockEventStore { eventstore := mockEvents.NewMockEventStore() resourceChangedEventMetadata := makeEventMeta("", 0) - d1r1 := commands.NewResourceID(d1res1.DeviceId, d1res1.Href) - eventstore.Append(d1res1.DeviceId, d1r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d1res1.DeviceId, d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d1res1.DeviceId, d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{})) - eventstore.Append(d1res1.DeviceId, d1r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"))) - eventstore.Append(d1res1.DeviceId, d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"), time.Time{})) - - d1r2 := commands.NewResourceID(d1res2.DeviceId, d1res2.Href) - eventstore.Append(d1res2.DeviceId, d1r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) - - d1r3 := commands.NewResourceID(d1res3.DeviceId, d1res3.Href) - eventstore.Append(d1res3.DeviceId, d1r3.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r3, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) - eventstore.Append(d1res3.DeviceId, d1r3.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r3, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "3"), time.Time{})) - - d1r4 := commands.NewResourceID(d1res4.DeviceId, d1res4.Href) - eventstore.Append(d1res4.DeviceId, d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d1res4.DeviceId, d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d1res4.DeviceId, d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{})) - eventstore.Append(d1res4.DeviceId, d1r4.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r4, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"))) - eventstore.Append(d1res4.DeviceId, d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"))) - eventstore.Append(d1res4.DeviceId, d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 5), mockEvents.MakeAuditContext("userId", "4"), time.Time{})) - - d2r1 := commands.NewResourceID(d2res1.DeviceId, d2res1.Href) - eventstore.Append(d2res1.DeviceId, d2r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d2res1.DeviceId, d2r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d2res1.DeviceId, d2r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"))) - - d2r2 := commands.NewResourceID(d2res2.DeviceId, d2res2.Href) - eventstore.Append(d2res2.DeviceId, d2r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d2res2.DeviceId, d2r2.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r2, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d2res2.DeviceId, d2r2.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r2, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"))) - eventstore.Append(d2res2.DeviceId, d2r2.ToUUID().String(), mockEvents.MakeResourceChangedEvent(d2r2, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "2"))) + d1r1 := commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{})) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"))) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"), time.Time{})) + + d1r2 := commands.NewResourceID(d1res2.GetDeviceId(), d1res2.GetHref()) + eventstore.Append(d1res2.GetDeviceId(), d1r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) + + d1r3 := commands.NewResourceID(d1res3.GetDeviceId(), d1res3.GetHref()) + eventstore.Append(d1res3.GetDeviceId(), d1r3.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r3, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) + eventstore.Append(d1res3.GetDeviceId(), d1r3.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r3, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "3"), time.Time{})) + + d1r4 := commands.NewResourceID(d1res4.GetDeviceId(), d1res4.GetHref()) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{})) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r4, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"))) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"))) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 5), mockEvents.MakeAuditContext("userId", "4"), time.Time{})) + + d2r1 := commands.NewResourceID(d2res1.GetDeviceId(), d2res1.GetHref()) + eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) + eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) + eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"))) + + d2r2 := commands.NewResourceID(d2res2.GetDeviceId(), d2res2.GetHref()) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r2, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r2, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"))) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceChangedEvent(d2r2, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "2"))) return eventstore } @@ -222,14 +222,14 @@ func TestResourceProjection_Register(t *testing.T) { { name: "first valid", args: args{ - deviceID: d1res1.DeviceId, + deviceID: d1res1.GetDeviceId(), }, wantLoaded: true, }, { name: "second valid", args: args{ - deviceID: d1res1.DeviceId, + deviceID: d1res1.GetDeviceId(), }, }, { @@ -283,26 +283,26 @@ func TestResourceProjection_Unregister(t *testing.T) { { name: "first time", args: args{ - deviceID: d1res1.DeviceId, + deviceID: d1res1.GetDeviceId(), }, }, { - name: "second second", + name: "second time", args: args{ - deviceID: d1res1.DeviceId, + deviceID: d1res1.GetDeviceId(), }, }, { name: "third error", args: args{ - deviceID: d1res1.DeviceId, + deviceID: d1res1.GetDeviceId(), }, wantErr: true, }, { name: "not registered", args: args{ - deviceID: d2res1.DeviceId, + deviceID: d2res1.GetDeviceId(), }, wantErr: true, }, @@ -320,9 +320,9 @@ func TestResourceProjection_Unregister(t *testing.T) { }, ) require.NoError(t, err) - _, err = p.Register(ctx, d1res1.DeviceId) + _, err = p.Register(ctx, d1res1.GetDeviceId()) require.NoError(t, err) - _, err = p.Register(ctx, d1res1.DeviceId) + _, err = p.Register(ctx, d1res1.GetDeviceId()) require.NoError(t, err) for _, tt := range tests { @@ -349,17 +349,17 @@ func TestResourceLinksProjection_Models(t *testing.T) { { name: "valid dev1", args: args{ - deviceID: d1res1.DeviceId, + deviceID: d1res1.GetDeviceId(), }, want: []cqrsEventStore.Model{ &events.ResourceLinksSnapshotTaken{ Resources: map[string]*commands.Resource{ - d1res1.Href: &d1res1, - d1res3.Href: &d1res3, - d1res4.Href: &d1res4, - d1res5.Href: &d1res5, + d1res1.GetHref(): &d1res1, + d1res3.GetHref(): &d1res3, + d1res4.GetHref(): &d1res4, + d1res5.GetHref(): &d1res5, }, - DeviceId: d1res1.DeviceId, + DeviceId: d1res1.GetDeviceId(), EventMetadata: &events.EventMetadata{ Version: 3, Timestamp: 12345, @@ -372,14 +372,14 @@ func TestResourceLinksProjection_Models(t *testing.T) { { name: "valid dev2", args: args{ - deviceID: d2res1.DeviceId, + deviceID: d2res1.GetDeviceId(), }, want: []cqrsEventStore.Model{ &events.ResourceLinksSnapshotTaken{ Resources: map[string]*commands.Resource{ - d2res1.Href: &d2res1, + d2res1.GetHref(): &d2res1, }, - DeviceId: d2res1.DeviceId, + DeviceId: d2res1.GetDeviceId(), EventMetadata: &events.EventMetadata{ Version: 6, Timestamp: 12345, @@ -392,14 +392,14 @@ func TestResourceLinksProjection_Models(t *testing.T) { { name: "valid dev3", args: args{ - deviceID: d3res2.DeviceId, + deviceID: d3res2.GetDeviceId(), }, want: []cqrsEventStore.Model{ &events.ResourceLinksSnapshotTaken{ Resources: map[string]*commands.Resource{ - d3res2.Href: &d3res2, + d3res2.GetHref(): &d3res2, }, - DeviceId: d3res2.DeviceId, + DeviceId: d3res2.GetDeviceId(), EventMetadata: &events.EventMetadata{ Version: 1, Timestamp: 12345, @@ -412,12 +412,12 @@ func TestResourceLinksProjection_Models(t *testing.T) { { name: "valid dev4", args: args{ - deviceID: d4res1.DeviceId, + deviceID: d4res1.GetDeviceId(), }, want: []cqrsEventStore.Model{ &events.ResourceLinksSnapshotTaken{ Resources: map[string]*commands.Resource{}, - DeviceId: d4res1.DeviceId, + DeviceId: d4res1.GetDeviceId(), EventMetadata: &events.EventMetadata{ Version: 1, Timestamp: 12345, @@ -430,12 +430,12 @@ func TestResourceLinksProjection_Models(t *testing.T) { { name: "valid dev5", args: args{ - deviceID: d5res1.DeviceId, + deviceID: d5res1.GetDeviceId(), }, want: []cqrsEventStore.Model{ &events.ResourceLinksSnapshotTaken{ Resources: map[string]*commands.Resource{}, - DeviceId: d5res1.DeviceId, + DeviceId: d5res1.GetDeviceId(), EventMetadata: &events.EventMetadata{ Version: 1, Timestamp: 12345, @@ -498,11 +498,11 @@ func TestResourceStateProjection_Models(t *testing.T) { { name: "valid dev1r1", args: args{ - resourceID: commands.NewResourceID(d1res1.DeviceId, d1res1.Href), + resourceID: commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()), }, want: []cqrsEventStore.Model{ &events.ResourceStateSnapshotTaken{ - ResourceId: commands.NewResourceID(d1res1.DeviceId, d1res1.Href), + ResourceId: commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()), LatestResourceChange: &events.ResourceChanged{ Content: &commands.Content{}, EventMetadata: &events.EventMetadata{ @@ -520,7 +520,7 @@ func TestResourceStateProjection_Models(t *testing.T) { }, ResourceUpdatePendings: []*events.ResourceUpdatePending{ { - ResourceId: commands.NewResourceID(d1res1.DeviceId, d1res1.Href), + ResourceId: commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()), Content: &commands.Content{}, AuditContext: &commands.AuditContext{ UserId: "userId", @@ -533,7 +533,7 @@ func TestResourceStateProjection_Models(t *testing.T) { }, }, { - ResourceId: commands.NewResourceID(d1res1.DeviceId, d1res1.Href), + ResourceId: commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()), Content: &commands.Content{}, AuditContext: &commands.AuditContext{ UserId: "userId", @@ -552,11 +552,11 @@ func TestResourceStateProjection_Models(t *testing.T) { { name: "valid dev1r2", args: args{ - resourceID: commands.NewResourceID(d1res2.DeviceId, d1res2.Href), + resourceID: commands.NewResourceID(d1res2.GetDeviceId(), d1res2.GetHref()), }, want: []cqrsEventStore.Model{ &events.ResourceStateSnapshotTaken{ - ResourceId: commands.NewResourceID(d1res2.DeviceId, d1res2.Href), + ResourceId: commands.NewResourceID(d1res2.GetDeviceId(), d1res2.GetHref()), LatestResourceChange: &events.ResourceChanged{ Content: &commands.Content{}, EventMetadata: &events.EventMetadata{ @@ -575,11 +575,11 @@ func TestResourceStateProjection_Models(t *testing.T) { { name: "valid dev1r3", args: args{ - resourceID: commands.NewResourceID(d1res3.DeviceId, d1res3.Href), + resourceID: commands.NewResourceID(d1res3.GetDeviceId(), d1res3.GetHref()), }, want: []cqrsEventStore.Model{ &events.ResourceStateSnapshotTaken{ - ResourceId: commands.NewResourceID(d1res3.DeviceId, d1res3.Href), + ResourceId: commands.NewResourceID(d1res3.GetDeviceId(), d1res3.GetHref()), LatestResourceChange: &events.ResourceChanged{ Content: &commands.Content{}, EventMetadata: &events.EventMetadata{ @@ -597,7 +597,7 @@ func TestResourceStateProjection_Models(t *testing.T) { }, ResourceUpdatePendings: []*events.ResourceUpdatePending{ { - ResourceId: commands.NewResourceID(d1res3.DeviceId, d1res3.Href), + ResourceId: commands.NewResourceID(d1res3.GetDeviceId(), d1res3.GetHref()), Content: &commands.Content{}, AuditContext: &commands.AuditContext{ UserId: "userId", @@ -617,11 +617,11 @@ func TestResourceStateProjection_Models(t *testing.T) { { name: "valid dev1r4", args: args{ - resourceID: commands.NewResourceID(d1res4.DeviceId, d1res4.Href), + resourceID: commands.NewResourceID(d1res4.GetDeviceId(), d1res4.GetHref()), }, want: []cqrsEventStore.Model{ &events.ResourceStateSnapshotTaken{ - ResourceId: commands.NewResourceID(d1res4.DeviceId, d1res4.Href), + ResourceId: commands.NewResourceID(d1res4.GetDeviceId(), d1res4.GetHref()), LatestResourceChange: &events.ResourceChanged{ Content: &commands.Content{}, EventMetadata: &events.EventMetadata{ @@ -639,7 +639,7 @@ func TestResourceStateProjection_Models(t *testing.T) { }, ResourceUpdatePendings: []*events.ResourceUpdatePending{ { - ResourceId: commands.NewResourceID(d1res4.DeviceId, d1res4.Href), + ResourceId: commands.NewResourceID(d1res4.GetDeviceId(), d1res4.GetHref()), Content: &commands.Content{}, AuditContext: &commands.AuditContext{ UserId: "userId", @@ -658,11 +658,11 @@ func TestResourceStateProjection_Models(t *testing.T) { { name: "valid dev2r1", args: args{ - resourceID: commands.NewResourceID(d2res1.DeviceId, d2res1.Href), + resourceID: commands.NewResourceID(d2res1.GetDeviceId(), d2res1.GetHref()), }, want: []cqrsEventStore.Model{ &events.ResourceStateSnapshotTaken{ - ResourceId: commands.NewResourceID(d2res1.DeviceId, d2res1.Href), + ResourceId: commands.NewResourceID(d2res1.GetDeviceId(), d2res1.GetHref()), LatestResourceChange: &events.ResourceChanged{ Content: &commands.Content{}, EventMetadata: &events.EventMetadata{ @@ -685,13 +685,13 @@ func TestResourceStateProjection_Models(t *testing.T) { { name: "valid dev2r2", args: args{ - resourceID: commands.NewResourceID(d2res2.DeviceId, d2res2.Href), + resourceID: commands.NewResourceID(d2res2.GetDeviceId(), d2res2.GetHref()), }, want: []cqrsEventStore.Model{ &events.ResourceStateSnapshotTaken{ - ResourceId: commands.NewResourceID(d2res2.DeviceId, d2res2.Href), + ResourceId: commands.NewResourceID(d2res2.GetDeviceId(), d2res2.GetHref()), LatestResourceChange: &events.ResourceChanged{ - ResourceId: commands.NewResourceID(d2res2.DeviceId, d2res2.Href), + ResourceId: commands.NewResourceID(d2res2.GetDeviceId(), d2res2.GetHref()), Content: &commands.Content{}, AuditContext: &commands.AuditContext{UserId: "userId", CorrelationId: "2"}, EventMetadata: &events.EventMetadata{ @@ -766,7 +766,7 @@ func TestResourceProjection_ForceUpdate(t *testing.T) { { name: "valid", args: args{ - resourceID: commands.NewResourceID(d1res1.DeviceId, d1res1.Href), + resourceID: commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()), }, }, { @@ -790,7 +790,7 @@ func TestResourceProjection_ForceUpdate(t *testing.T) { }, ) require.NoError(t, err) - _, err = p.Register(ctx, d1res1.DeviceId) + _, err = p.Register(ctx, d1res1.GetDeviceId()) require.NoError(t, err) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/resource-aggregate/cqrs/utils/utils_test.go b/resource-aggregate/cqrs/utils/utils_test.go index b4afa5b9b..75d294e57 100644 --- a/resource-aggregate/cqrs/utils/utils_test.go +++ b/resource-aggregate/cqrs/utils/utils_test.go @@ -22,13 +22,13 @@ func TestDummyForCoverage(t *testing.T) { hubID := "h" em := events.MakeEventMeta(connID, sequence, version, hubID) - assert.Equal(t, connID, em.ConnectionId) - assert.Equal(t, sequence, em.Sequence) - assert.Equal(t, version, em.Version) - assert.Equal(t, hubID, em.HubId) + assert.Equal(t, connID, em.GetConnectionId()) + assert.Equal(t, sequence, em.GetSequence()) + assert.Equal(t, version, em.GetVersion()) + assert.Equal(t, hubID, em.GetHubId()) ac := commands.NewAuditContext(userID, corID, userID) - assert.Equal(t, corID, ac.CorrelationId) - assert.Equal(t, userID, ac.UserId) + assert.Equal(t, corID, ac.GetCorrelationId()) + assert.Equal(t, userID, ac.GetUserId()) } func TestProtobufMarshaler(t *testing.T) { diff --git a/resource-aggregate/service/aggregate.go b/resource-aggregate/service/aggregate.go index 0ed337c31..d866ff1d2 100644 --- a/resource-aggregate/service/aggregate.go +++ b/resource-aggregate/service/aggregate.go @@ -82,18 +82,20 @@ var ( ) func validatePublish(request *commands.PublishResourceLinksRequest) error { - if len(request.Resources) == 0 { + resources := request.GetResources() + if len(resources) == 0 { return status.Errorf(codes.InvalidArgument, "empty publish is not accepted") } - for _, res := range request.Resources { - if len(res.Href) <= 1 || res.Href[:1] != "/" { + for _, res := range resources { + href := res.GetHref() + if len(href) <= 1 || href[:1] != "/" { return status.Errorf(codes.InvalidArgument, "invalid resource href") } - if res.DeviceId == "" { + if res.GetDeviceId() == "" { return status.Errorf(codes.InvalidArgument, "invalid device id") } } - if request.DeviceId == "" { + if request.GetDeviceId() == "" { return errInvalidDeviceID } return nil @@ -103,7 +105,7 @@ func validateUnpublish(request *commands.UnpublishResourceLinksRequest) error { if request.GetDeviceId() == "" { return errInvalidDeviceID } - for _, href := range request.Hrefs { + for _, href := range request.GetHrefs() { if href == "" { return status.Errorf(codes.InvalidArgument, "invalid resource id") } @@ -112,7 +114,7 @@ func validateUnpublish(request *commands.UnpublishResourceLinksRequest) error { } func validateNotifyContentChanged(request *commands.NotifyResourceChangedRequest) error { - if request.Content == nil { + if request.GetContent() == nil { return errInvalidContent } if request.GetResourceId().GetDeviceId() == "" { @@ -128,7 +130,7 @@ func validateUpdateResourceContent(request *commands.UpdateResourceRequest) erro if err := checkTimeToLive(request.GetTimeToLive()); err != nil { return err } - if request.Content == nil { + if request.GetContent() == nil { return errInvalidContent } if request.GetResourceId().GetDeviceId() == "" { @@ -160,7 +162,7 @@ func validateRetrieveResource(request *commands.RetrieveResourceRequest) error { } func validateConfirmResourceUpdate(request *commands.ConfirmResourceUpdateRequest) error { - if request.Content == nil { + if request.GetContent() == nil { return errInvalidContent } if request.GetResourceId().GetDeviceId() == "" { @@ -177,7 +179,7 @@ func validateConfirmResourceUpdate(request *commands.ConfirmResourceUpdateReques } func validateConfirmResourceRetrieve(request *commands.ConfirmResourceRetrieveRequest) error { - if request.Content == nil { + if request.GetContent() == nil { return errInvalidContent } if request.GetResourceId().GetDeviceId() == "" { diff --git a/resource-aggregate/service/aggregate_test.go b/resource-aggregate/service/aggregate_test.go index d1730c875..91b19faf4 100644 --- a/resource-aggregate/service/aggregate_test.go +++ b/resource-aggregate/service/aggregate_test.go @@ -301,7 +301,7 @@ func TestAggregateHandleUnpublishAllResources(t *testing.T) { require.NoError(t, err) require.Len(t, events, 1) - unpublishedResourceLinks := (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs + unpublishedResourceLinks := (events[0].(*raEvents.ResourceLinksUnpublished)).GetHrefs() require.Len(t, unpublishedResourceLinks, 3) require.Contains(t, unpublishedResourceLinks, resourceID1, resourceID2, resourceID3) @@ -360,7 +360,7 @@ func TestAggregateHandleUnpublishResourceSubset(t *testing.T) { events, err := ag.UnpublishResourceLinks(ctx, pc) require.NoError(t, err) require.Len(t, events, 1) - require.Equal(t, []string{resourceID1, resourceID3}, (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs) + require.Equal(t, []string{resourceID1, resourceID3}, (events[0].(*raEvents.ResourceLinksUnpublished)).GetHrefs()) service.PublishEvents(publisher, userID, deviceID, ag.ResourceID(), events, logger) @@ -368,7 +368,7 @@ func TestAggregateHandleUnpublishResourceSubset(t *testing.T) { events, err = ag.UnpublishResourceLinks(ctx, pc) require.NoError(t, err) require.Len(t, events, 1) - require.Equal(t, []string{resourceID4}, (events[0].(*raEvents.ResourceLinksUnpublished)).Hrefs) + require.Equal(t, []string{resourceID4}, (events[0].(*raEvents.ResourceLinksUnpublished)).GetHrefs()) } func testMakePublishResourceRequest(deviceID string, href []string) *commands.PublishResourceLinksRequest { diff --git a/resource-aggregate/service/confirmDeviceMetadataUpdate.go b/resource-aggregate/service/confirmDeviceMetadataUpdate.go index f8687cd8d..821279b1a 100644 --- a/resource-aggregate/service/confirmDeviceMetadataUpdate.go +++ b/resource-aggregate/service/confirmDeviceMetadataUpdate.go @@ -47,7 +47,7 @@ func (r RequestHandler) ConfirmDeviceMetadataUpdate(ctx context.Context, request return nil, log.LogAndReturnError(kitNetGrpc.ForwardErrorf(codes.Internal, "cannot validate user access: %v", err)) } - resID := commands.NewResourceID(request.DeviceId, commands.StatusHref) + resID := commands.NewResourceID(request.GetDeviceId(), commands.StatusHref) aggregate, err := NewAggregate(resID, r.eventstore, NewDeviceMetadataFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm device('%v') metadata update: %v", request.GetDeviceId(), err)) diff --git a/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go b/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go index 41fad2923..52fa9987b 100644 --- a/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go +++ b/resource-aggregate/service/confirmDeviceMetadataUpdate_test.go @@ -220,7 +220,7 @@ func TestRequestHandlerConfirmDeviceMetadataUpdate(t *testing.T) { } require.NoError(t, err) if tt.want != nil { - assert.Equal(t, tt.want.AuditContext, response.AuditContext) + assert.Equal(t, tt.want.GetAuditContext(), response.GetAuditContext()) } } t.Run(tt.name, tfunc) diff --git a/resource-aggregate/service/deleteDevices.go b/resource-aggregate/service/deleteDevices.go index 849f728cd..df4c77ffe 100644 --- a/resource-aggregate/service/deleteDevices.go +++ b/resource-aggregate/service/deleteDevices.go @@ -13,7 +13,7 @@ import ( func getUniqueDeviceIdsFromDeleteRequest(request *commands.DeleteDevicesRequest) []string { deviceIDs := make(strings.Set) - for _, deviceID := range request.DeviceIds { + for _, deviceID := range request.GetDeviceIds() { if deviceID != "" { deviceIDs.Add(deviceID) } diff --git a/resource-aggregate/service/deleteDevices_test.go b/resource-aggregate/service/deleteDevices_test.go index efab95c4d..0f24b59dd 100644 --- a/resource-aggregate/service/deleteDevices_test.go +++ b/resource-aggregate/service/deleteDevices_test.go @@ -139,10 +139,10 @@ func TestRequestHandler_DeleteDevices(t *testing.T) { } require.NoError(t, err) if tt.want != nil { - sort.Strings(tt.want.DeviceIds) - sort.Strings(response.DeviceIds) - require.Equal(t, tt.want.DeviceIds, response.DeviceIds) - require.Equal(t, tt.want.AuditContext, response.AuditContext) + sort.Strings(tt.want.GetDeviceIds()) + sort.Strings(response.GetDeviceIds()) + require.Equal(t, tt.want.GetDeviceIds(), response.GetDeviceIds()) + require.Equal(t, tt.want.GetAuditContext(), response.GetAuditContext()) } }) } diff --git a/resource-aggregate/service/grpcApi.go b/resource-aggregate/service/grpcApi.go index 5e8f8798a..9139bea7e 100644 --- a/resource-aggregate/service/grpcApi.go +++ b/resource-aggregate/service/grpcApi.go @@ -118,7 +118,7 @@ func (r RequestHandler) PublishResourceLinks(ctx context.Context, request *comma return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - resID := commands.NewResourceID(request.DeviceId, commands.ResourceLinksHref) + resID := commands.NewResourceID(request.GetDeviceId(), commands.ResourceLinksHref) aggregate, err := NewAggregate(resID, r.eventstore, NewResourceLinksFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot publish resource links: %v", err)) @@ -139,7 +139,7 @@ func newPublishResourceLinksResponse(events []eventstore.Event, deviceID string, if rlp, ok := event.(*raEvents.ResourceLinksPublished); ok { return &commands.PublishResourceLinksResponse{ AuditContext: auditContext, - PublishedResources: rlp.Resources, + PublishedResources: rlp.GetResources(), DeviceId: deviceID, } } @@ -156,7 +156,7 @@ func (r RequestHandler) UnpublishResourceLinks(ctx context.Context, request *com return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - resID := commands.NewResourceID(request.DeviceId, commands.ResourceLinksHref) + resID := commands.NewResourceID(request.GetDeviceId(), commands.ResourceLinksHref) aggregate, err := NewAggregate(resID, r.eventstore, NewResourceLinksFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot unpublish resource links: %v", err)) @@ -193,7 +193,7 @@ func newUnpublishResourceLinksResponse(events []eventstore.Event, deviceID strin if rlu, ok := event.(*raEvents.ResourceLinksUnpublished); ok { return &commands.UnpublishResourceLinksResponse{ AuditContext: auditContext, - UnpublishedHrefs: rlu.Hrefs, + UnpublishedHrefs: rlu.GetHrefs(), DeviceId: deviceID, } } @@ -205,7 +205,7 @@ func newUnpublishResourceLinksResponse(events []eventstore.Event, deviceID strin } func (r RequestHandler) notifyResourceChanged(ctx context.Context, request *commands.NotifyResourceChangedRequest, userID, owner string) error { - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot notify about resource content change: %v", err)) } @@ -243,7 +243,7 @@ func (r RequestHandler) UpdateResource(ctx context.Context, request *commands.Up } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot update resource content: %v", err)) } @@ -275,7 +275,7 @@ func (r RequestHandler) ConfirmResourceUpdate(ctx context.Context, request *comm if err != nil { return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm resource content update: %v", err)) } @@ -299,7 +299,7 @@ func (r RequestHandler) RetrieveResource(ctx context.Context, request *commands. } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot retrieve resource content: %v", err)) } @@ -331,7 +331,7 @@ func (r RequestHandler) ConfirmResourceRetrieve(ctx context.Context, request *co if err != nil { return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "ccannot confirm resource content retrieve: %v", err)) } @@ -356,7 +356,7 @@ func (r RequestHandler) DeleteResource(ctx context.Context, request *commands.De } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot delete resource: %v", err)) } @@ -389,7 +389,7 @@ func (r RequestHandler) ConfirmResourceDelete(ctx context.Context, request *comm return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm resource deletion: %v", err)) } @@ -414,7 +414,7 @@ func (r RequestHandler) CreateResource(ctx context.Context, request *commands.Cr } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot create resource: %v", err)) } @@ -447,7 +447,7 @@ func (r RequestHandler) ConfirmResourceCreate(ctx context.Context, request *comm return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.ResourceId, r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm resource creation: %v", err)) } diff --git a/resource-aggregate/service/grpcApi_test.go b/resource-aggregate/service/grpcApi_test.go index 43752408d..50ae3c3c7 100644 --- a/resource-aggregate/service/grpcApi_test.go +++ b/resource-aggregate/service/grpcApi_test.go @@ -141,7 +141,7 @@ func TestRequestHandlerPublishResource(t *testing.T) { require.NoError(t, err) } if tt.want != nil { - assert.Equal(t, tt.want.AuditContext, response.AuditContext) + require.Equal(t, tt.want.GetAuditContext(), response.GetAuditContext()) } } t.Run(tt.name, tfunc) diff --git a/resource-aggregate/service/updateDeviceMetadata_test.go b/resource-aggregate/service/updateDeviceMetadata_test.go index 1bd7c32d2..3f8077b0d 100644 --- a/resource-aggregate/service/updateDeviceMetadata_test.go +++ b/resource-aggregate/service/updateDeviceMetadata_test.go @@ -20,7 +20,6 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/service" raTest "github.com/plgd-dev/hub/v2/resource-aggregate/test" "github.com/plgd-dev/hub/v2/test/config" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" "google.golang.org/grpc/codes" @@ -129,7 +128,7 @@ func TestAggregateHandleUpdateDeviceMetadata(t *testing.T) { require.Error(t, err) s, ok := status.FromError(kitNetGrpc.ForwardFromError(codes.Unknown, err)) require.True(t, ok) - assert.Equal(t, tt.want, s.Code()) + require.Equal(t, tt.want, s.Code()) return } require.NoError(t, err) @@ -263,12 +262,12 @@ func TestRequestHandlerUpdateDeviceMetadata(t *testing.T) { } require.NoError(t, err) if tt.want != nil { - assert.Equal(t, tt.want.AuditContext, response.AuditContext) + require.Equal(t, tt.want.GetAuditContext(), response.GetAuditContext()) } if tt.want.GetValidUntil() == 0 { - assert.Equal(t, tt.want.ValidUntil, response.GetValidUntil()) + require.Equal(t, tt.want.GetValidUntil(), response.GetValidUntil()) } else { - assert.Less(t, tt.want.ValidUntil, response.GetValidUntil()) + require.Less(t, tt.want.GetValidUntil(), response.GetValidUntil()) } time.Sleep(tt.args.sleep) } diff --git a/resource-aggregate/service/updateServiceHeartbeat_test.go b/resource-aggregate/service/updateServiceHeartbeat_test.go index db6ca48ec..88aa7b3f5 100644 --- a/resource-aggregate/service/updateServiceHeartbeat_test.go +++ b/resource-aggregate/service/updateServiceHeartbeat_test.go @@ -17,6 +17,7 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/utils" "github.com/plgd-dev/hub/v2/resource-aggregate/service" raTest "github.com/plgd-dev/hub/v2/resource-aggregate/test" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace/noop" ) @@ -73,7 +74,7 @@ func TestNewServiceHeartbeat(t *testing.T) { }, ResponseChan: chans[j], }) - require.NoError(t, err) + assert.NoError(t, err) }(i) } wg.Wait() diff --git a/resource-directory/service/deviceDirectory.go b/resource-directory/service/deviceDirectory.go index 20660d1aa..2e44ccffb 100644 --- a/resource-directory/service/deviceDirectory.go +++ b/resource-directory/service/deviceDirectory.go @@ -132,10 +132,10 @@ func filterDevices(deviceIds strings.Set, deviceIDsFilter []string) strings.Set func (dd *DeviceDirectory) sendDevices(deviceIDs strings.Set, req *pb.GetDevicesRequest, srv pb.GrpcGateway_GetDevicesServer, toReloadDevices strings.Set) (err error) { typeFilter := make(strings.Set) - typeFilter.Add(req.TypeFilter...) + typeFilter.Add(req.GetTypeFilter()...) return dd.projection.LoadDevicesMetadata(deviceIDs, toReloadDevices, func(m *deviceMetadataProjection) error { deviceMetadataUpdated := m.GetDeviceMetadataUpdated() - if !hasMatchingStatus(deviceMetadataUpdated.GetConnection().IsOnline(), req.StatusFilter) { + if !hasMatchingStatus(deviceMetadataUpdated.GetConnection().IsOnline(), req.GetStatusFilter()) { return nil } resourceIdFilter := []*commands.ResourceId{commands.NewResourceID(m.GetDeviceID(), device.ResourceURI)} @@ -161,7 +161,7 @@ func (dd *DeviceDirectory) sendDevices(deviceIDs strings.Set, req *pb.GetDevices } func (dd *DeviceDirectory) GetDevices(req *pb.GetDevicesRequest, srv pb.GrpcGateway_GetDevicesServer) (err error) { - deviceIDs := filterDevices(dd.userDeviceIds, req.DeviceIdFilter) + deviceIDs := filterDevices(dd.userDeviceIds, req.GetDeviceIdFilter()) if len(deviceIDs) == 0 { log.Debug("DeviceDirectory.GetDevices.filterDevices returns empty deviceIDs") return nil diff --git a/resource-directory/service/deviceDirectory_test.go b/resource-directory/service/deviceDirectory_test.go index f2c1d009a..023208f7f 100644 --- a/resource-directory/service/deviceDirectory_test.go +++ b/resource-directory/service/deviceDirectory_test.go @@ -47,7 +47,7 @@ func TestDeviceDirectoryGetDevices(t *testing.T) { }, wantStatusCode: codes.OK, wantResponse: map[string]*pb.Device{ - ddResource2.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource2.Resource.DeviceId, deviceResourceTypes, true), + ddResource2.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource2.Resource.GetDeviceId(), deviceResourceTypes, true), }, }, @@ -60,7 +60,7 @@ func TestDeviceDirectoryGetDevices(t *testing.T) { }, wantStatusCode: codes.OK, wantResponse: map[string]*pb.Device{ - ddResource1.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource1.Resource.DeviceId, deviceResourceTypes, false), + ddResource1.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource1.Resource.GetDeviceId(), deviceResourceTypes, false), }, }, { @@ -72,8 +72,8 @@ func TestDeviceDirectoryGetDevices(t *testing.T) { }, wantStatusCode: codes.OK, wantResponse: map[string]*pb.Device{ - ddResource1.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource1.Resource.DeviceId, deviceResourceTypes, false), - ddResource2.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource2.Resource.DeviceId, deviceResourceTypes, true), + ddResource1.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource1.Resource.GetDeviceId(), deviceResourceTypes, false), + ddResource2.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource2.Resource.GetDeviceId(), deviceResourceTypes, true), }, }, { @@ -94,20 +94,20 @@ func TestDeviceDirectoryGetDevices(t *testing.T) { }, wantStatusCode: codes.OK, wantResponse: map[string]*pb.Device{ - ddResource1.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource1.Resource.DeviceId, deviceResourceTypes, false), - ddResource2.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource2.Resource.DeviceId, deviceResourceTypes, true), + ddResource1.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource1.Resource.GetDeviceId(), deviceResourceTypes, false), + ddResource2.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource2.Resource.GetDeviceId(), deviceResourceTypes, true), }, }, { name: "project_one_device", args: args{ request: &pb.GetDevicesRequest{ - DeviceIdFilter: []string{ddResource1.Resource.DeviceId}, + DeviceIdFilter: []string{ddResource1.Resource.GetDeviceId()}, }, }, wantStatusCode: codes.OK, wantResponse: map[string]*pb.Device{ - ddResource1.Resource.DeviceId: testMakeDeviceResouceProtobuf(ddResource1.Resource.DeviceId, deviceResourceTypes, false), + ddResource1.Resource.GetDeviceId(): testMakeDeviceResouceProtobuf(ddResource1.Resource.GetDeviceId(), deviceResourceTypes, false), }, }, } @@ -269,20 +269,20 @@ func testCreateResourceDeviceEventstores() (resourceEventStore *mockEvents.MockE resourceEventStore = mockEvents.NewMockEventStore() // without cloud state - resourceEventStore.Append(ddResource0.DeviceId, commands.MakeLinksResourceUUID(ddResource0.DeviceId).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource0.Resource}, ddResource0.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - resourceEventStore.Append(ddResource0.DeviceId, ddResource0.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource0.Resource.GetResourceID(), ddResource0.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + resourceEventStore.Append(ddResource0.GetDeviceId(), commands.MakeLinksResourceUUID(ddResource0.GetDeviceId()).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource0.Resource}, ddResource0.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) + resourceEventStore.Append(ddResource0.GetDeviceId(), ddResource0.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource0.Resource.GetResourceID(), ddResource0.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) - resourceEventStore.Append(ddResource1.DeviceId, commands.MakeLinksResourceUUID(ddResource1.DeviceId).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource1.Resource}, ddResource1.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - resourceEventStore.Append(ddResource1.DeviceId, ddResource1.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource1.Resource.GetResourceID(), ddResource1.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) - resourceEventStore.Append(ddResource1Cloud.DeviceId, ddResource1Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource1Cloud.DeviceId, ddResource1Cloud, events.MakeEventMeta("a", 0, 0, "hubID"))) + resourceEventStore.Append(ddResource1.GetDeviceId(), commands.MakeLinksResourceUUID(ddResource1.GetDeviceId()).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource1.Resource}, ddResource1.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) + resourceEventStore.Append(ddResource1.GetDeviceId(), ddResource1.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource1.Resource.GetResourceID(), ddResource1.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + resourceEventStore.Append(ddResource1Cloud.GetDeviceId(), ddResource1Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource1Cloud.GetDeviceId(), ddResource1Cloud, events.MakeEventMeta("a", 0, 0, "hubID"))) // with cloud state - online - resourceEventStore.Append(ddResource2.DeviceId, commands.MakeLinksResourceUUID(ddResource2.DeviceId).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource2.Resource}, ddResource2.Resource.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - resourceEventStore.Append(ddResource2.DeviceId, ddResource2.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource2.Resource.GetResourceID(), ddResource2.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) - resourceEventStore.Append(ddResource2Cloud.DeviceId, ddResource2Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource2Cloud.DeviceId, ddResource2Cloud, events.MakeEventMeta("a", 0, 0, "hubID"))) + resourceEventStore.Append(ddResource2.GetDeviceId(), commands.MakeLinksResourceUUID(ddResource2.GetDeviceId()).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource2.Resource}, ddResource2.Resource.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) + resourceEventStore.Append(ddResource2.GetDeviceId(), ddResource2.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource2.Resource.GetResourceID(), ddResource2.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + resourceEventStore.Append(ddResource2Cloud.GetDeviceId(), ddResource2Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource2Cloud.GetDeviceId(), ddResource2Cloud, events.MakeEventMeta("a", 0, 0, "hubID"))) // without device resource - resourceEventStore.Append(ddResource4Cloud.DeviceId, ddResource4Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource4Cloud.DeviceId, ddResource2Cloud, events.MakeEventMeta("a", 0, 1, "hubID"))) + resourceEventStore.Append(ddResource4Cloud.GetDeviceId(), ddResource4Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource4Cloud.GetDeviceId(), ddResource2Cloud, events.MakeEventMeta("a", 0, 1, "hubID"))) return resourceEventStore } @@ -300,6 +300,6 @@ func (s *testGrpcGateway_GetDevicesServer) Send(d *pb.Device) error { if s.got == nil { s.got = make(map[string]*pb.Device) } - s.got[d.Id] = d + s.got[d.GetId()] = d return nil } diff --git a/resource-directory/service/getDevices_test.go b/resource-directory/service/getDevices_test.go index c07fa1645..2eb70ed90 100644 --- a/resource-directory/service/getDevices_test.go +++ b/resource-directory/service/getDevices_test.go @@ -161,7 +161,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { break } require.NoError(t, err) - assert.NotEmpty(t, dev.ProtocolIndependentId) + assert.NotEmpty(t, dev.GetProtocolIndependentId()) assert.NotEmpty(t, dev.GetData().GetContent().GetData()) dev.ProtocolIndependentId = "" dev.Metadata.Connection.Id = "" diff --git a/resource-directory/service/getEvents.go b/resource-directory/service/getEvents.go index b76f00d72..c942a38f2 100644 --- a/resource-directory/service/getEvents.go +++ b/resource-directory/service/getEvents.go @@ -285,7 +285,7 @@ func (p *resourceEvent) Handle(ctx context.Context, iter eventstore.Iter) error } func getDeviceQueries(deviceIDFilter []string, userDeviceIDs strings.Set) []eventstore.GetEventsQuery { - var queries []eventstore.GetEventsQuery + queries := make([]eventstore.GetEventsQuery, 0, len(deviceIDFilter)) for _, deviceID := range deviceIDFilter { if _, ok := userDeviceIDs[deviceID]; !ok { log.Debugf("permission denied, device with id %v skipped", deviceID) @@ -299,7 +299,7 @@ func getDeviceQueries(deviceIDFilter []string, userDeviceIDs strings.Set) []even } func getResourceQueries(resourceFilter []*pb.ResourceIdFilter, userDeviceIDs strings.Set) []eventstore.GetEventsQuery { - var queries []eventstore.GetEventsQuery + queries := make([]eventstore.GetEventsQuery, 0, len(resourceFilter)) for _, filter := range resourceFilter { if !userDeviceIDs.HasOneOf(filter.GetResourceId().GetDeviceId()) { log.Debugf("permission denied, resource belonging to device %v skipped", filter.GetResourceId().GetDeviceId()) @@ -314,7 +314,7 @@ func getResourceQueries(resourceFilter []*pb.ResourceIdFilter, userDeviceIDs str } func getUserDeviceQueries(userDeviceIds strings.Set) []eventstore.GetEventsQuery { - var queries []eventstore.GetEventsQuery + queries := make([]eventstore.GetEventsQuery, 0, len(userDeviceIds)) for device := range userDeviceIds { queries = append(queries, eventstore.GetEventsQuery{ GroupID: device, @@ -342,13 +342,13 @@ func (r *RequestHandler) GetEvents(req *pb.GetEventsRequest, srv pb.GrpcGateway_ } // for backward compatibility and http api - req.ResourceIdFilter = append(req.ResourceIdFilter, req.ConvertHTTPResourceIDFilter()...) + req.ResourceIdFilter = append(req.GetResourceIdFilter(), req.ConvertHTTPResourceIDFilter()...) var queries []eventstore.GetEventsQuery - if len(req.DeviceIdFilter) == 0 && len(req.GetResourceIdFilter()) == 0 { + if len(req.GetDeviceIdFilter()) == 0 && len(req.GetResourceIdFilter()) == 0 { queries = getUserDeviceQueries(mapUserDeviceIDs) } else { - queries = getDeviceQueries(req.DeviceIdFilter, mapUserDeviceIDs) + queries = getDeviceQueries(req.GetDeviceIdFilter(), mapUserDeviceIDs) queries = append(queries, getResourceQueries(req.GetResourceIdFilter(), mapUserDeviceIDs)...) if len(queries) == 0 { log.Debugf("None of the filters are satisfied for user %v", owner) @@ -356,7 +356,7 @@ func (r *RequestHandler) GetEvents(req *pb.GetEventsRequest, srv pb.GrpcGateway_ } } - err = r.eventStore.GetEvents(srv.Context(), queries, req.TimestampFilter, &resourceEvent{srv: srv}) + err = r.eventStore.GetEvents(srv.Context(), queries, req.GetTimestampFilter(), &resourceEvent{srv: srv}) if err != nil { return log.LogAndReturnError(status.Errorf(status.Convert(err).Code(), "cannot get events: %v", err)) } diff --git a/resource-directory/service/getHubConfiguration_test.go b/resource-directory/service/getHubConfiguration_test.go index 10ff190cb..12cd99d2a 100644 --- a/resource-directory/service/getHubConfiguration_test.go +++ b/resource-directory/service/getHubConfiguration_test.go @@ -52,9 +52,9 @@ func TestRequestHandlerGetHubConfiguration(t *testing.T) { require.Error(t, err) } else { require.NoError(t, err) - require.NotEmpty(t, got.CertificateAuthorities) + require.NotEmpty(t, got.GetCertificateAuthorities()) got.CertificateAuthorities = "" - require.NotEqual(t, int64(0), got.CurrentTime) + require.NotEqual(t, int64(0), got.GetCurrentTime()) got.CurrentTime = 0 test.CheckProtobufs(t, tt.want, got, test.RequireToCheckFunc(require.Equal)) } diff --git a/resource-directory/service/projection.go b/resource-directory/service/projection.go index 73e408e9f..cde5507b1 100644 --- a/resource-directory/service/projection.go +++ b/resource-directory/service/projection.go @@ -151,14 +151,14 @@ func (p *Projection) wantToReloadDevice(rl *resourceLinksProjection, hrefFilter if len(hrefFilter) > 0 && !hrefFilter[res.GetHref()] { return true } - if !hasMatchingType(res.ResourceTypes, typeFilter) { + if !hasMatchingType(res.GetResourceTypes(), typeFilter) { return true } reload := true p.Models(func(eventstore.Model) (wantNext bool) { reload = false return true - }, commands.NewResourceID(rl.GetDeviceID(), res.Href)) + }, commands.NewResourceID(rl.GetDeviceID(), res.GetHref())) if reload { finalReload = true return false @@ -173,7 +173,7 @@ func (p *Projection) loadResourceWithLinks(deviceID string, hrefFilter map[strin if len(hrefFilter) > 0 && !hrefFilter[res.GetHref()] { return false } - if !hasMatchingType(res.ResourceTypes, typeFilter) { + if !hasMatchingType(res.GetResourceTypes(), typeFilter) { return false } return true @@ -204,7 +204,7 @@ func (p *Projection) loadResourceWithLinks(deviceID string, hrefFilter map[strin Resource: res, }) return err == nil - }, commands.NewResourceID(rl.GetDeviceID(), res.Href)) + }, commands.NewResourceID(rl.GetDeviceID(), res.GetHref())) return true }) return err diff --git a/resource-directory/service/resourceDirectory.go b/resource-directory/service/resourceDirectory.go index e85466553..045d8fb9d 100644 --- a/resource-directory/service/resourceDirectory.go +++ b/resource-directory/service/resourceDirectory.go @@ -35,14 +35,14 @@ func (rd *ResourceDirectory) sendResourceLinks(srv pb.GrpcGateway_GetResourceLin } func (rd *ResourceDirectory) GetResourceLinks(in *pb.GetResourceLinksRequest, srv pb.GrpcGateway_GetResourceLinksServer) error { - deviceIDs := filterDevices(rd.userDeviceIds, in.DeviceIdFilter) + deviceIDs := filterDevices(rd.userDeviceIds, in.GetDeviceIdFilter()) if len(deviceIDs) == 0 { log.Debug("ResourceDirectory.GetResourceLinks.filterDevices returns empty deviceIDs") return nil } typeFilter := make(strings.Set) - typeFilter.Add(in.TypeFilter...) + typeFilter.Add(in.GetTypeFilter()...) toReloadDevices := make(strings.Set) err := rd.sendResourceLinks(srv, deviceIDs, typeFilter, toReloadDevices) diff --git a/resource-directory/service/resourceDirectory_test.go b/resource-directory/service/resourceDirectory_test.go index 5e44afdb3..5fb96eabf 100644 --- a/resource-directory/service/resourceDirectory_test.go +++ b/resource-directory/service/resourceDirectory_test.go @@ -131,6 +131,6 @@ func (s *testGrpcGateway_GetResourceLinksServer) Send(d *events.ResourceLinksPub if s.got == nil { s.got = make(map[string]*events.ResourceLinksPublished) } - s.got[d.DeviceId] = pbTest.CleanUpResourceLinksPublished(d, true) + s.got[d.GetDeviceId()] = pbTest.CleanUpResourceLinksPublished(d, true) return nil } diff --git a/resource-directory/service/resourceLinksProjection.go b/resource-directory/service/resourceLinksProjection.go index dd3a76515..de825dd6d 100644 --- a/resource-directory/service/resourceLinksProjection.go +++ b/resource-directory/service/resourceLinksProjection.go @@ -117,7 +117,7 @@ func (rlp *resourceLinksProjection) ToResourceLinksPublished(typeFilter strings. rlp.private.lock.RLock() defer rlp.private.lock.RUnlock() for _, resource := range rlp.private.snapshot.GetResources() { - if hasMatchingType(resource.ResourceTypes, typeFilter) { + if hasMatchingType(resource.GetResourceTypes(), typeFilter) { resources = append(resources, resource) } } diff --git a/resource-directory/service/resourceProjection.go b/resource-directory/service/resourceProjection.go index 6cf0bb8e2..e4ea61d9a 100644 --- a/resource-directory/service/resourceProjection.go +++ b/resource-directory/service/resourceProjection.go @@ -54,8 +54,8 @@ func (rp *resourceProjection) handleResourceStateSnapshotTakenLocked(eu eventsto if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId - rp.private.content = s.LatestResourceChange + rp.private.resourceID = s.GetResourceId() + rp.private.content = s.GetLatestResourceChange() rp.private.onResourceChangedVersion = eu.Version() rp.private.resourceUpdatePendings = s.GetResourceUpdatePendings() rp.private.resourceCreatePendings = s.GetResourceCreatePendings() @@ -69,7 +69,7 @@ func (rp *resourceProjection) handleResourceChangedLocked(eu eventstore.EventUnm if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() rp.private.content = &s rp.private.onResourceChangedVersion = eu.Version() return nil @@ -81,7 +81,7 @@ func (rp *resourceProjection) handleResourceUpdatePendingLocked(eu eventstore.Ev return err } rp.private.resourceUpdatePendings = append(rp.private.resourceUpdatePendings, &s) - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() return nil } @@ -90,7 +90,7 @@ func (rp *resourceProjection) handleResourceUpdatedLocked(eu eventstore.EventUnm if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() tmp := make([]*events.ResourceUpdatePending, 0, 16) var found bool for _, cu := range rp.private.resourceUpdatePendings { @@ -111,7 +111,7 @@ func (rp *resourceProjection) handleResourceRetrievePendingLocked(eu eventstore. if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() rp.private.resourceRetrievePendings = append(rp.private.resourceRetrievePendings, &s) return nil } @@ -121,7 +121,7 @@ func (rp *resourceProjection) handleResourceDeletePendingLocked(eu eventstore.Ev if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() rp.private.resourceDeletePendings = append(rp.private.resourceDeletePendings, &s) return nil } @@ -131,7 +131,7 @@ func (rp *resourceProjection) handleResourceRetrievedLocked(eu eventstore.EventU if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() tmp := make([]*events.ResourceRetrievePending, 0, 16) var found bool for _, cu := range rp.private.resourceRetrievePendings { @@ -152,7 +152,7 @@ func (rp *resourceProjection) handleResourceDeletedLocked(eu eventstore.EventUnm if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() tmp := make([]*events.ResourceDeletePending, 0, 16) var found bool for _, cu := range rp.private.resourceDeletePendings { @@ -174,7 +174,7 @@ func (rp *resourceProjection) handleResourceCreatePendingLocked(eu eventstore.Ev return err } rp.private.resourceCreatePendings = append(rp.private.resourceCreatePendings, &s) - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() return nil } @@ -183,7 +183,7 @@ func (rp *resourceProjection) handleResourceCreatedLocked(eu eventstore.EventUnm if err := eu.Unmarshal(&s); err != nil { return err } - rp.private.resourceID = s.ResourceId + rp.private.resourceID = s.GetResourceId() tmp := make([]*events.ResourceCreatePending, 0, 16) var found bool for _, cu := range rp.private.resourceCreatePendings { diff --git a/resource-directory/service/resourceShadow.go b/resource-directory/service/resourceShadow.go index 99d4b1910..93b880c68 100644 --- a/resource-directory/service/resourceShadow.go +++ b/resource-directory/service/resourceShadow.go @@ -84,12 +84,13 @@ func updateContentForResponseForETag(v *pb.ResourceIdFilter, val *pb.Resource) b continue } rc := val.GetData() - val.Data = &events.ResourceChanged{} - val.Data.CopyData(rc) - val.Data.Status = commands.Status_NOT_MODIFIED - val.Data.Content = &commands.Content{ + data := &events.ResourceChanged{} + data.CopyData(rc) + data.Status = commands.Status_NOT_MODIFIED + data.Content = &commands.Content{ CoapContentFormat: int32(-1), } + val.Data = data return true } return false @@ -236,7 +237,7 @@ func (rd *ResourceTwin) sendDevicesMetadata(srv pb.GrpcGateway_GetDevicesMetadat } return nil } - if len(typeFilter) > 0 && !typeFilter.HasOneOf(res.ResourceTypes...) { + if len(typeFilter) > 0 && !typeFilter.HasOneOf(res.GetResourceTypes()...) { return nil } return rd.projection.LoadDevicesMetadata(strings.MakeSet(m.GetDeviceID()), toReloadDevices, func(m *deviceMetadataProjection) error { @@ -254,9 +255,9 @@ func (rd *ResourceTwin) sendDevicesMetadata(srv pb.GrpcGateway_GetDevicesMetadat } func (rd *ResourceTwin) GetDevicesMetadata(req *pb.GetDevicesMetadataRequest, srv pb.GrpcGateway_GetDevicesMetadataServer) error { - deviceIDs := filterDevices(rd.userDeviceIds, req.DeviceIdFilter) + deviceIDs := filterDevices(rd.userDeviceIds, req.GetDeviceIdFilter()) typeFilter := make(strings.Set) - typeFilter.Add(req.TypeFilter...) + typeFilter.Add(req.GetTypeFilter()...) toReloadDevices := make(strings.Set) err := rd.sendDevicesMetadata(srv, deviceIDs, typeFilter, toReloadDevices) if err != nil { diff --git a/test/cbor.go b/test/cbor.go index 8c23ee146..0e0d48571 100644 --- a/test/cbor.go +++ b/test/cbor.go @@ -5,13 +5,13 @@ import ( "github.com/fxamacker/cbor/v2" pkgCbor "github.com/plgd-dev/kit/v2/codec/cbor" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/assert" ) func DecodeCbor(t *testing.T, data []byte) interface{} { var v interface{} err := pkgCbor.Decode(data, &v) - require.NoError(t, err) + assert.NoError(t, err) return v } @@ -25,6 +25,6 @@ func EncodeToSortedCbor(v interface{}) ([]byte, error) { func EncodeToCbor(t *testing.T, v interface{}) []byte { d, err := EncodeToSortedCbor(v) - require.NoError(t, err) + assert.NoError(t, err) return d } diff --git a/test/pb/device.go b/test/pb/device.go index b94a06927..652fef0ea 100644 --- a/test/pb/device.go +++ b/test/pb/device.go @@ -20,10 +20,10 @@ func CmpDeviceValues(t *testing.T, expected, got []*pbGrpc.Device) { dev.Metadata.Connection.ConnectedAt = 0 dev.Metadata.Connection.LocalEndpoints = nil dev.Metadata.Connection.ServiceId = "" - if dev.Metadata.TwinSynchronization != nil { - dev.Metadata.TwinSynchronization.SyncingAt = 0 - dev.Metadata.TwinSynchronization.InSyncAt = 0 - dev.Metadata.TwinSynchronization.CommandMetadata = nil + if dev.GetMetadata().GetTwinSynchronization() != nil { + dev.GetMetadata().GetTwinSynchronization().SyncingAt = 0 + dev.GetMetadata().GetTwinSynchronization().InSyncAt = 0 + dev.GetMetadata().GetTwinSynchronization().CommandMetadata = nil } dev.Data = nil } @@ -73,7 +73,7 @@ func CleanUpDeviceMetadataUpdated(e *events.DeviceMetadataUpdated, resetCorrelat } func CleanUpDeviceMetadataSnapshotTaken(e *events.DeviceMetadataSnapshotTaken, resetCorrelationID bool) { - CleanUpDeviceMetadataUpdated(e.DeviceMetadataUpdated, resetCorrelationID) + CleanUpDeviceMetadataUpdated(e.GetDeviceMetadataUpdated(), resetCorrelationID) e.EventMetadata = nil } diff --git a/test/pb/event.go b/test/pb/event.go index 4a16cfef0..e32c9d45f 100644 --- a/test/pb/event.go +++ b/test/pb/event.go @@ -13,6 +13,7 @@ import ( "github.com/plgd-dev/hub/v2/resource-aggregate/events" "github.com/plgd-dev/hub/v2/test" oauthService "github.com/plgd-dev/hub/v2/test/oauth-server/service" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -329,6 +330,26 @@ func CmpEvent(t *testing.T, expected, got *pb.Event, cmpInterface string) { cmp(t, expected, got, cmpInterface) } +func AssertCmpEvents(t *testing.T, expected, got []*pb.Event) { + assert.Len(t, got, len(expected)) + + // normalize + for i := range expected { + expected[i].SubscriptionId = "" + got[i].SubscriptionId = "" + CleanUpEvent(t, expected[i]) + CleanUpEvent(t, got[i]) + } + + // compare + for _, gotV := range got { + test.CheckProtobufs(t, expected, gotV, test.AssertToCheckFunc(assert.Contains)) + } + for _, expectedV := range expected { + test.CheckProtobufs(t, got, expectedV, test.AssertToCheckFunc(assert.Contains)) + } +} + func CmpEvents(t *testing.T, expected, got []*pb.Event) { require.Len(t, got, len(expected)) diff --git a/test/pb/pendingCommand.go b/test/pb/pendingCommand.go index 7579fd031..8fb7506d2 100644 --- a/test/pb/pendingCommand.go +++ b/test/pb/pendingCommand.go @@ -243,9 +243,9 @@ func CmpPendingCmds(t *testing.T, want []*pb.PendingCommand, got []*pb.PendingCo } func CmpCancelPendingCmdResponses(t *testing.T, want *pb.CancelPendingCommandsResponse, got *pb.CancelPendingCommandsResponse) { - sort.Strings(want.CorrelationIds) - sort.Strings(got.CorrelationIds) - require.Equal(t, want.CorrelationIds, got.CorrelationIds) + sort.Strings(want.GetCorrelationIds()) + sort.Strings(got.GetCorrelationIds()) + require.Equal(t, want.GetCorrelationIds(), got.GetCorrelationIds()) } func CleanUpResourceCreatePending(e *events.ResourceCreatePending, resetCorrelationID bool) *events.ResourceCreatePending { diff --git a/test/pb/resource.go b/test/pb/resource.go index de5b1b4d3..d6cc02561 100644 --- a/test/pb/resource.go +++ b/test/pb/resource.go @@ -412,9 +412,9 @@ func CmpResourceValuesBasic(t *testing.T, expected, got []*pb.Resource) { } func CmpHubConfigurationResponse(t *testing.T, expected, got *pb.HubConfigurationResponse) { - require.NotEmpty(t, got.CertificateAuthorities) + require.NotEmpty(t, got.GetCertificateAuthorities()) got.CertificateAuthorities = "" - require.NotEqual(t, int64(0), got.CurrentTime) + require.NotEqual(t, int64(0), got.GetCurrentTime()) got.CurrentTime = 0 test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } diff --git a/test/pb/snapshot.go b/test/pb/snapshot.go index a8fa34d77..bf9c22aa0 100644 --- a/test/pb/snapshot.go +++ b/test/pb/snapshot.go @@ -15,7 +15,7 @@ func CleanUpResourceStateSnapshotTaken(e *events.ResourceStateSnapshotTaken, res if e.GetAuditContext() != nil && resetCorrelationID { e.GetAuditContext().CorrelationId = "" } - CleanUpResourceChanged(e.LatestResourceChange, resetCorrelationID) + CleanUpResourceChanged(e.GetLatestResourceChange(), resetCorrelationID) if e.GetLatestResourceChange().GetContent().GetData() != nil { e.LatestResourceChange.Content.Data = nil } diff --git a/test/test.go b/test/test.go index d81b8b3f0..df1064c4c 100644 --- a/test/test.go +++ b/test/test.go @@ -41,6 +41,7 @@ import ( oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" "github.com/plgd-dev/hub/v2/test/sdk" "github.com/plgd-dev/kit/v2/codec/json" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ugorji/go/codec" ) @@ -511,7 +512,7 @@ func OnboardDeviceForClient(ctx context.Context, t *testing.T, c pb.GrpcGatewayC ev, err := subClient.Recv() require.NoError(t, err) expectedEvent := &pb.Event{ - SubscriptionId: ev.SubscriptionId, + SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "allEvents", Type: &pb.Event_OperationProcessed_{ OperationProcessed: &pb.Event_OperationProcessed{ @@ -897,6 +898,12 @@ func RequireToCheckFunc(checFunc func(t require.TestingT, expected interface{}, } } +func AssertToCheckFunc(checFunc func(t assert.TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool) func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + return func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { + checFunc(t, expected, actual, msgAndArgs...) + } +} + func CheckProtobufs(t *testing.T, expected interface{}, actual interface{}, checkFunc func(t *testing.T, expected interface{}, actual interface{}, msgAndArgs ...interface{})) { v1 := ProtobufToInterface(t, expected) v2 := ProtobufToInterface(t, actual) diff --git a/test/virtual-device/virtualDevice.go b/test/virtual-device/virtualDevice.go index ce2948774..9673ef18b 100644 --- a/test/virtual-device/virtualDevice.go +++ b/test/virtual-device/virtualDevice.go @@ -20,6 +20,7 @@ import ( "github.com/plgd-dev/hub/v2/test" "github.com/plgd-dev/hub/v2/test/config" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/sync/semaphore" "google.golang.org/grpc" @@ -72,7 +73,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin _, err := isClient.AddDevice(ctx, &pb.AddDeviceRequest{ DeviceId: deviceID, }) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint for { _, err = raClient.UpdateDeviceMetadata(ctx, &commands.UpdateDeviceMetadataRequest{ @@ -101,7 +102,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin // device is still not loaded to owner in resource-aggregate continue } - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint } resources := CreateDeviceResourceLinks(deviceID, numResources) @@ -114,7 +115,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin }, } _, err = raClient.PublishResourceLinks(ctx, &pub) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint _, err = raClient.UpdateDeviceMetadata(ctx, &commands.UpdateDeviceMetadataRequest{ DeviceId: deviceID, @@ -131,7 +132,8 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin Sequence: incSeq(), }, }) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint + for i := 0; i < numResources; i++ { _, err = raClient.NotifyResourceChanged(ctx, &commands.NotifyResourceChangedRequest{ ResourceId: commands.NewResourceID(deviceID, fmt.Sprintf("/res-%v", i)), @@ -145,8 +147,9 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin }, Status: commands.Status_OK, }) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint } + _, err = raClient.NotifyResourceChanged(ctx, &commands.NotifyResourceChangedRequest{ ResourceId: commands.NewResourceID(deviceID, "/oic/d"), CommandMetadata: &commands.CommandMetadata{ @@ -159,7 +162,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin }, Status: commands.Status_OK, }) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint _, err = raClient.NotifyResourceChanged(ctx, &commands.NotifyResourceChangedRequest{ ResourceId: commands.NewResourceID(deviceID, "/oic/p"), @@ -173,7 +176,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin }, Status: commands.Status_OK, }) - require.NoError(t, err) + assert.NoError(t, err) //nolint:testifylint _, err = raClient.UpdateDeviceMetadata(ctx, &commands.UpdateDeviceMetadataRequest{ DeviceId: deviceID, @@ -190,7 +193,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin Sequence: incSeq(), }, }) - require.NoError(t, err) + assert.NoError(t, err) } func CreateDevices(ctx context.Context, t *testing.T, numDevices int, numResourcesPerDevice int, protocol commands.Connection_Protocol) { From 8e71027de8afd839089298e473e76de5c2429d17 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Thu, 4 Apr 2024 16:25:28 +0200 Subject: [PATCH 25/31] Upgrade dependencies Direct: github.com/nats-io/nats.go v1.34.1 github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 golang.org/x/net v0.23.0 google.golang.org/grpc v1.63.0 --- bundle/client/grpc/main.go | 2 +- bundle/client/ob/main.go | 2 +- .../service/grpc/signCertificate_test.go | 4 ++-- .../grpc/signIdentityCertificate_test.go | 4 ++-- .../service/getDevices_test.go | 2 +- .../retrieveResourceFromDevice_test.go | 2 +- .../service/updateResource_test.go | 2 +- cloud2cloud-connector/test/test.go | 2 +- .../retrieveAllDevicesSubscription_test.go | 2 +- .../retrieveDeviceSubscription_test.go | 2 +- .../service/retrieveDevice_test.go | 2 +- .../retrieveResourceSubscription_test.go | 2 +- .../service/retrieveResource_test.go | 2 +- .../service/subscribeToDevice_test.go | 4 ++-- .../service/subscribeToDevices_test.go | 4 ++-- .../service/subscribeToResource_test.go | 4 ++-- .../service/clientObserveHandler_test.go | 2 +- .../service/devicesStatusUpdater_test.go | 2 +- coap-gateway/service/mem_test.go | 2 +- .../observation/deviceObserver_test.go | 4 ++-- .../service/observation/observation_test.go | 2 +- coap-gateway/service/service_test.go | 2 +- coap-gateway/service/signIn_test.go | 2 +- go.mod | 10 +++++----- go.sum | 19 ++++++++++--------- grpc-gateway/client/client.go | 2 +- .../service/createAndDeleteResource_test.go | 2 +- grpc-gateway/service/createResource_test.go | 2 +- grpc-gateway/service/deleteDevices_test.go | 4 ++-- grpc-gateway/service/deleteResource_test.go | 6 +++--- .../service/getDevicesMetadata_test.go | 2 +- grpc-gateway/service/getDevices_test.go | 2 +- grpc-gateway/service/getEvents_test.go | 2 +- .../service/getHubConfiguration_test.go | 2 +- .../service/getResourceFromDevice_test.go | 4 ++-- grpc-gateway/service/getResourceLinks_test.go | 2 +- grpc-gateway/service/getResources_test.go | 2 +- .../service/subscribeToEvents_test.go | 8 ++++---- .../service/updateDeviceMetadata_test.go | 4 ++-- grpc-gateway/service/updateResource_test.go | 8 ++++---- http-gateway/service/createResource_test.go | 2 +- http-gateway/service/deleteDevices_test.go | 2 +- http-gateway/service/deleteResource_test.go | 4 ++-- .../service/getDevicePendingCommands_test.go | 2 +- .../service/getDeviceResourceLinks_test.go | 2 +- .../service/getDeviceResources_test.go | 2 +- http-gateway/service/getDevice_test.go | 2 +- .../service/getDevicesMetadata_test.go | 2 +- http-gateway/service/getDevices_test.go | 2 +- http-gateway/service/getEvents_test.go | 2 +- .../service/getPendingCommands_test.go | 2 +- .../service/getPendingMetadataUpdates_test.go | 2 +- http-gateway/service/getResourceLinks_test.go | 2 +- .../getResourcePendingCommands_test.go | 2 +- http-gateway/service/getResource_test.go | 2 +- http-gateway/service/getResources_test.go | 2 +- .../service/subscribeToEvents_test.go | 2 +- .../service/updateDeviceMetadata_test.go | 2 +- http-gateway/service/updateResource_test.go | 2 +- pkg/net/grpc/client/client.go | 1 + pkg/net/grpc/stub_test.go | 2 +- .../service/getDevicesMetadata_test.go | 2 +- resource-directory/service/getDevices_test.go | 4 ++-- .../service/getEventsSnapshot_test.go | 2 +- resource-directory/service/getEvents_test.go | 2 +- .../service/getHubConfiguration_test.go | 2 +- .../service/getPendingCommands_test.go | 2 +- .../service/getResourceLinks_test.go | 2 +- .../service/getResources_test.go | 2 +- .../service/deleteResource_test.go | 2 +- test/iotivity-lite/service/offboard_test.go | 12 ++++++------ test/iotivity-lite/service/republish_test.go | 2 +- test/pb/pendingCommand.go | 2 +- test/virtual-device/virtualDevice.go | 4 ++-- 74 files changed, 112 insertions(+), 110 deletions(-) diff --git a/bundle/client/grpc/main.go b/bundle/client/grpc/main.go index 3e17d02cd..11659f814 100644 --- a/bundle/client/grpc/main.go +++ b/bundle/client/grpc/main.go @@ -235,7 +235,7 @@ func main() { *accesstoken = getAccessToken(*authAddr, &tlsCfg) } - conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(credentials.NewTLS(&tlsCfg))) + conn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(credentials.NewTLS(&tlsCfg))) if err != nil { log.Fatalf("Error dialing: %v", err) } diff --git a/bundle/client/ob/main.go b/bundle/client/ob/main.go index 1d0970a5a..9f88fdd43 100644 --- a/bundle/client/ob/main.go +++ b/bundle/client/ob/main.go @@ -178,7 +178,7 @@ func main() { tlsCfg := tls.Config{ InsecureSkipVerify: true, } - grpcConn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(credentials.NewTLS(&tlsCfg))) + grpcConn, err := grpc.NewClient(*addr, grpc.WithTransportCredentials(credentials.NewTLS(&tlsCfg))) if err != nil { log.Fatalf("cannot connect to grpc: %v", err) } diff --git a/certificate-authority/service/grpc/signCertificate_test.go b/certificate-authority/service/grpc/signCertificate_test.go index 0f0d2a05a..38189e797 100644 --- a/certificate-authority/service/grpc/signCertificate_test.go +++ b/certificate-authority/service/grpc/signCertificate_test.go @@ -66,7 +66,7 @@ func testSigningByFunction(t *testing.T, signFn ClientSignFunc, csr ...[]byte) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -113,7 +113,7 @@ func TestCertificateAuthorityServerSignCSRWithDifferentPublicKeys(t *testing.T) defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/certificate-authority/service/grpc/signIdentityCertificate_test.go b/certificate-authority/service/grpc/signIdentityCertificate_test.go index 9c81133f8..a4a1b4260 100644 --- a/certificate-authority/service/grpc/signIdentityCertificate_test.go +++ b/certificate-authority/service/grpc/signIdentityCertificate_test.go @@ -51,7 +51,7 @@ func TestCertificateAuthorityServerSignDeviceIdentityCSRWithDifferentPublicKeys( defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -79,7 +79,7 @@ func TestCertificateAuthorityServerSignOwnerIdentityCSRWithDifferentPublicKeys(t defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.CERTIFICATE_AUTHORITY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-connector/service/getDevices_test.go b/cloud2cloud-connector/service/getDevices_test.go index ae9f5ec03..db3ee190b 100644 --- a/cloud2cloud-connector/service/getDevices_test.go +++ b/cloud2cloud-connector/service/getDevices_test.go @@ -70,7 +70,7 @@ func testRequestHandlerGetDevices(t *testing.T, events store.Events) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(c2cConnectorTest.GRPC_GATEWAY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(c2cConnectorTest.GRPC_GATEWAY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go b/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go index 4f74d2905..bb9d931ad 100644 --- a/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go +++ b/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go @@ -107,7 +107,7 @@ func testRequestHandlerGetResourceFromDevice(t *testing.T, events store.Events) defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(c2cConnectorTest.GRPC_GATEWAY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(c2cConnectorTest.GRPC_GATEWAY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-connector/service/updateResource_test.go b/cloud2cloud-connector/service/updateResource_test.go index 89fc58e6c..ae77c7add 100644 --- a/cloud2cloud-connector/service/updateResource_test.go +++ b/cloud2cloud-connector/service/updateResource_test.go @@ -137,7 +137,7 @@ func testRequestHandlerUpdateResource(t *testing.T, events store.Events) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(c2cConnectorTest.GRPC_GATEWAY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(c2cConnectorTest.GRPC_GATEWAY_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-connector/test/test.go b/cloud2cloud-connector/test/test.go index 94b90604a..398879c7b 100644 --- a/cloud2cloud-connector/test/test.go +++ b/cloud2cloud-connector/test/test.go @@ -51,7 +51,7 @@ func SetUpClouds(ctx context.Context, t *testing.T, deviceID string, supportedEv cloud2 := SetUpCloudWithConnector(t) ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - cloud1Conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + cloud1Conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/retrieveAllDevicesSubscription_test.go b/cloud2cloud-gateway/service/retrieveAllDevicesSubscription_test.go index 455e38a8f..d894edc55 100644 --- a/cloud2cloud-gateway/service/retrieveAllDevicesSubscription_test.go +++ b/cloud2cloud-gateway/service/retrieveAllDevicesSubscription_test.go @@ -32,7 +32,7 @@ func TestRequestHandlerRetrieveDevicesSubscription(t *testing.T) { tearDown := service.SetUp(ctx, t) defer tearDown() - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/retrieveDeviceSubscription_test.go b/cloud2cloud-gateway/service/retrieveDeviceSubscription_test.go index faa15c1d6..023a3200e 100644 --- a/cloud2cloud-gateway/service/retrieveDeviceSubscription_test.go +++ b/cloud2cloud-gateway/service/retrieveDeviceSubscription_test.go @@ -35,7 +35,7 @@ func TestRequestHandlerRetrieveDeviceSubscription(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/retrieveDevice_test.go b/cloud2cloud-gateway/service/retrieveDevice_test.go index 81cea0cbb..2f9a3f738 100644 --- a/cloud2cloud-gateway/service/retrieveDevice_test.go +++ b/cloud2cloud-gateway/service/retrieveDevice_test.go @@ -92,7 +92,7 @@ func TestRequestHandlerRetrieveDevice(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/retrieveResourceSubscription_test.go b/cloud2cloud-gateway/service/retrieveResourceSubscription_test.go index 051879cf0..ee53eb16d 100644 --- a/cloud2cloud-gateway/service/retrieveResourceSubscription_test.go +++ b/cloud2cloud-gateway/service/retrieveResourceSubscription_test.go @@ -35,7 +35,7 @@ func TestRequestHandlerRetrieveResourceSubscription(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/retrieveResource_test.go b/cloud2cloud-gateway/service/retrieveResource_test.go index ba3868ed4..84ca55784 100644 --- a/cloud2cloud-gateway/service/retrieveResource_test.go +++ b/cloud2cloud-gateway/service/retrieveResource_test.go @@ -34,7 +34,7 @@ func TestRequestHandlerRetrieveResource(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/subscribeToDevice_test.go b/cloud2cloud-gateway/service/subscribeToDevice_test.go index 2d94b770d..bc920e07b 100644 --- a/cloud2cloud-gateway/service/subscribeToDevice_test.go +++ b/cloud2cloud-gateway/service/subscribeToDevice_test.go @@ -46,7 +46,7 @@ func TestRequestHandlerSubscribeToDevicePublishedOnly(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -91,7 +91,7 @@ func TestRequestHandlerSubscribeToDevice(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/subscribeToDevices_test.go b/cloud2cloud-gateway/service/subscribeToDevices_test.go index 512aab2c6..c8cef2096 100644 --- a/cloud2cloud-gateway/service/subscribeToDevices_test.go +++ b/cloud2cloud-gateway/service/subscribeToDevices_test.go @@ -54,7 +54,7 @@ func TestRequestHandlerSubscribeToDevices(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -147,7 +147,7 @@ func TestRequestHandlerSubscribeToDevicesOffline(t *testing.T) { gwShutdown := coapgwTest.New(t, coapgwCfg) ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/cloud2cloud-gateway/service/subscribeToResource_test.go b/cloud2cloud-gateway/service/subscribeToResource_test.go index ba1f60bef..b4cf32957 100644 --- a/cloud2cloud-gateway/service/subscribeToResource_test.go +++ b/cloud2cloud-gateway/service/subscribeToResource_test.go @@ -31,7 +31,7 @@ func TestRequestHandlerSubscribeToResource(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -78,7 +78,7 @@ func TestRequestHandlerSubscribeToResourceTokenTimeout(t *testing.T) { defer tearDown() c2cgwShutdown := c2cTest.SetUp(t) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/clientObserveHandler_test.go b/coap-gateway/service/clientObserveHandler_test.go index aa8fa146d..1c67158fe 100644 --- a/coap-gateway/service/clientObserveHandler_test.go +++ b/coap-gateway/service/clientObserveHandler_test.go @@ -145,7 +145,7 @@ func TestClientObserveHandlerCloseObservation(t *testing.T) { require.NoError(t, err) ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/devicesStatusUpdater_test.go b/coap-gateway/service/devicesStatusUpdater_test.go index d745b60a0..02eba2127 100644 --- a/coap-gateway/service/devicesStatusUpdater_test.go +++ b/coap-gateway/service/devicesStatusUpdater_test.go @@ -33,7 +33,7 @@ func onboardDeviceAndGetDevice(ctx context.Context, t *testing.T, device device. servicesTeardown := testService.SetUpServices(context.Background(), t, testService.SetUpServicesCertificateAuthority|testService.SetUpServicesId|testService.SetUpServicesResourceAggregate|testService.SetUpServicesResourceDirectory|testService.SetUpServicesCoapGateway|testService.SetUpServicesGrpcGateway, testService.WithCOAPGWConfig(coapCfg)) ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/mem_test.go b/coap-gateway/service/mem_test.go index 4795e6203..94a502d2b 100644 --- a/coap-gateway/service/mem_test.go +++ b/coap-gateway/service/mem_test.go @@ -256,7 +256,7 @@ func testDevices(t *testing.T, numDevices, numResources, expRSSInMB int, resourc wg.Wait() } defer coapShutdown() - grpcConn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + grpcConn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/observation/deviceObserver_test.go b/coap-gateway/service/observation/deviceObserver_test.go index bf25e3e2d..8ec7a8bab 100644 --- a/coap-gateway/service/observation/deviceObserver_test.go +++ b/coap-gateway/service/observation/deviceObserver_test.go @@ -270,7 +270,7 @@ func TestDeviceObserverRegisterForDiscoveryResource(t *testing.T) { } func testPreregisterVirtualDevice(ctx context.Context, t *testing.T, deviceID string, grpcClient pb.GrpcGatewayClient, raClient raPb.ResourceAggregateClient) { - isConn, err := grpc.Dial(config.IDENTITY_STORE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + isConn, err := grpc.NewClient(config.IDENTITY_STORE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -451,7 +451,7 @@ func runTestDeviceObserverRegister(ctx context.Context, t *testing.T, deviceID s coapShutdown := coapgwTest.SetUp(t, makeHandler, validateHandler) defer coapShutdown() - grpcConn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + grpcConn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/observation/observation_test.go b/coap-gateway/service/observation/observation_test.go index 2136fceca..f8f88c16d 100644 --- a/coap-gateway/service/observation/observation_test.go +++ b/coap-gateway/service/observation/observation_test.go @@ -69,7 +69,7 @@ func TestIsResourceObservableWithInterface(t *testing.T) { coapShutdown := coapgwTest.SetUp(t, makeHandler, nil) defer coapShutdown() - grpcConn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + grpcConn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/service_test.go b/coap-gateway/service/service_test.go index 4adc86f91..c705725fa 100644 --- a/coap-gateway/service/service_test.go +++ b/coap-gateway/service/service_test.go @@ -97,7 +97,7 @@ func TestShutdownServiceWithDeviceIssue627(t *testing.T) { coapShutdown := coapgwTest.SetUp(t) defer coapShutdown() - grpcConn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + grpcConn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/coap-gateway/service/signIn_test.go b/coap-gateway/service/signIn_test.go index ea3c67858..c93de8701 100644 --- a/coap-gateway/service/signIn_test.go +++ b/coap-gateway/service/signIn_test.go @@ -74,7 +74,7 @@ func TestSignInDeviceSubscriptionHandler(t *testing.T) { defer shutdown() ctx := kitNetGrpc.CtxWithToken(context.Background(), oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/go.mod b/go.mod index dd3286125..ac9c8d1df 100644 --- a/go.mod +++ b/go.mod @@ -24,12 +24,12 @@ require ( github.com/jtacoma/uritemplates v1.0.0 github.com/karrick/tparse/v2 v2.8.2 github.com/lestrrat-go/jwx/v2 v2.0.21 - github.com/nats-io/nats.go v1.34.0 + github.com/nats-io/nats.go v1.34.1 github.com/panjf2000/ants/v2 v2.9.1 github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0 - github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664 + github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b + github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 github.com/sirupsen/logrus v1.9.3 @@ -50,12 +50,12 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 - golang.org/x/net v0.22.0 + golang.org/x/net v0.23.0 golang.org/x/oauth2 v0.18.0 golang.org/x/sync v0.6.0 google.golang.org/api v0.172.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda - google.golang.org/grpc v1.62.1 + google.golang.org/grpc v1.63.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 51a442faf..098ce863a 100644 --- a/go.sum +++ b/go.sum @@ -205,8 +205,8 @@ github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8 github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007 h1:28i1IjGcx8AofiB4N3q5Yls55VEaitzuEPkFJEVgGkA= github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= -github.com/nats-io/nats.go v1.34.0 h1:fnxnPCNiwIG5w08rlMcEKTUw4AV/nKyGCOJE8TdhSPk= -github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nats.go v1.34.1 h1:syWey5xaNHZgicYBemv0nohUPPmaLteiBEUT6Q5+F/4= +github.com/nats-io/nats.go v1.34.1/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -224,12 +224,12 @@ github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkL github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0 h1:EEDaxD3RCCD5uAtmJxE+S7DncGh00/8NvIwTmu1AEKE= -github.com/plgd-dev/device/v2 v2.4.5-0.20240403073803-48efa094e7b0/go.mod h1:T0ePJIrEkK8uvHkq43qA8J/eHGsV3w7zriDh5S7xJgE= +github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b h1:hADIFZn9Ck0qRW8xOiGuogzKjWjLyVgczZpuCEqFy2k= +github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b/go.mod h1:vkQxyY8+PsKdkh/4TGP6hq3T37jd1pLvIR7XS83WyMg= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= -github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664 h1:iMMYyd666v1oHmR642hYFoRgRyrN/qMoCoY0X/Cj6RE= -github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240403064319-6ed2ef2c4664/go.mod h1:flkLrn0JqGJyW25Uybwg0g0PZUt+pZ1O7aaPeIhEEbs= +github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 h1:Kaf/67M7+UVsRbNHQx3DDOLzpDI6RE/oYZz2v+a4csg= +github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79/go.mod h1:UKObEIXVvPfdNGv7QoKegxPwT12UBy26tNUEOebFkls= github.com/plgd-dev/kit v0.0.0-20200819113605-d5fcf3e94f63/go.mod h1:Yl9zisyXfPdtP9hTWlJqjJYXmgU/jtSDKttz9/CeD90= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 h1:TC1HJ/UbyflJFPvaOdGmNZ5TeFGex1/dyr9urNGLy7M= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSGQjdi8eInxwFCs0tSApuEM1o0qNck+sJYp4M= @@ -386,8 +386,9 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 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.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= @@ -484,8 +485,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= +google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/grpc-gateway/client/client.go b/grpc-gateway/client/client.go index 7c8951874..c049e8255 100644 --- a/grpc-gateway/client/client.go +++ b/grpc-gateway/client/client.go @@ -53,7 +53,7 @@ func NewFromConfig(cfg *Config, tlsCfg *tls.Config) (*Client, error) { PermitWithoutStream: true, } - conn, err := grpc.Dial(cfg.GatewayAddress, grpc.WithKeepaliveParams(keepAlive), grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg))) + conn, err := grpc.NewClient(cfg.GatewayAddress, grpc.WithKeepaliveParams(keepAlive), grpc.WithTransportCredentials(credentials.NewTLS(tlsCfg))) if err != nil { return nil, fmt.Errorf("cannot create certificate authority client: %w", err) } diff --git a/grpc-gateway/service/createAndDeleteResource_test.go b/grpc-gateway/service/createAndDeleteResource_test.go index 3214465a0..c0e311325 100644 --- a/grpc-gateway/service/createAndDeleteResource_test.go +++ b/grpc-gateway/service/createAndDeleteResource_test.go @@ -297,7 +297,7 @@ func TestCreateAndDeleteResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/createResource_test.go b/grpc-gateway/service/createResource_test.go index 8ca708517..2942532fc 100644 --- a/grpc-gateway/service/createResource_test.go +++ b/grpc-gateway/service/createResource_test.go @@ -151,7 +151,7 @@ func TestRequestHandlerCreateResource(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/deleteDevices_test.go b/grpc-gateway/service/deleteDevices_test.go index d77ba76fe..210bdd884 100644 --- a/grpc-gateway/service/deleteDevices_test.go +++ b/grpc-gateway/service/deleteDevices_test.go @@ -62,7 +62,7 @@ func TestRequestHandlerDeleteDevices(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -129,7 +129,7 @@ func TestRequestHandlerReconnectAfterDeleteDevice(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/deleteResource_test.go b/grpc-gateway/service/deleteResource_test.go index 9401e475a..295f19f56 100644 --- a/grpc-gateway/service/deleteResource_test.go +++ b/grpc-gateway/service/deleteResource_test.go @@ -105,7 +105,7 @@ func TestRequestHandlerDeleteResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -147,7 +147,7 @@ func TestRequestHandlerDeleteResourceAfterUnpublish(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -289,7 +289,7 @@ func TestRequestHandlerBatchDeleteResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getDevicesMetadata_test.go b/grpc-gateway/service/getDevicesMetadata_test.go index aaf941553..9ee9c7612 100644 --- a/grpc-gateway/service/getDevicesMetadata_test.go +++ b/grpc-gateway/service/getDevicesMetadata_test.go @@ -126,7 +126,7 @@ func TestRequestHandlerGetDevicesMetadata(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getDevices_test.go b/grpc-gateway/service/getDevices_test.go index 08b99bf6d..26412bdbb 100644 --- a/grpc-gateway/service/getDevices_test.go +++ b/grpc-gateway/service/getDevices_test.go @@ -70,7 +70,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getEvents_test.go b/grpc-gateway/service/getEvents_test.go index 3209b14c1..e468a32c1 100644 --- a/grpc-gateway/service/getEvents_test.go +++ b/grpc-gateway/service/getEvents_test.go @@ -49,7 +49,7 @@ func TestRequestHandlerGetEvents(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getHubConfiguration_test.go b/grpc-gateway/service/getHubConfiguration_test.go index 5e9d0ee65..2de53c938 100644 --- a/grpc-gateway/service/getHubConfiguration_test.go +++ b/grpc-gateway/service/getHubConfiguration_test.go @@ -36,7 +36,7 @@ func TestRequestHandlerGetHubConfiguration(t *testing.T) { tearDown := service.SetUp(ctx, t) defer tearDown() - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getResourceFromDevice_test.go b/grpc-gateway/service/getResourceFromDevice_test.go index e5243fca1..e4265b18f 100644 --- a/grpc-gateway/service/getResourceFromDevice_test.go +++ b/grpc-gateway/service/getResourceFromDevice_test.go @@ -146,7 +146,7 @@ func TestRequestHandlerGetResourceFromDevice(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -254,7 +254,7 @@ func TestRequestHandlerCheckResourceETag(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getResourceLinks_test.go b/grpc-gateway/service/getResourceLinks_test.go index 5d8107b0f..b79b3e50b 100644 --- a/grpc-gateway/service/getResourceLinks_test.go +++ b/grpc-gateway/service/getResourceLinks_test.go @@ -36,7 +36,7 @@ func TestRequestHandlerGetResourceLinks(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/getResources_test.go b/grpc-gateway/service/getResources_test.go index a92ed0017..1cf72338c 100644 --- a/grpc-gateway/service/getResources_test.go +++ b/grpc-gateway/service/getResources_test.go @@ -34,7 +34,7 @@ func TestRequestHandlerGetResources(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/subscribeToEvents_test.go b/grpc-gateway/service/subscribeToEvents_test.go index 86d72f88a..da15fdcb3 100644 --- a/grpc-gateway/service/subscribeToEvents_test.go +++ b/grpc-gateway/service/subscribeToEvents_test.go @@ -51,7 +51,7 @@ func TestRequestHandlerSubscribeToEvents(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -234,7 +234,7 @@ func TestRequestHandlerSubscribeForCreateEvents(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -316,7 +316,7 @@ func TestRequestHandlerSubscribeForHrefEvents(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -645,7 +645,7 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/updateDeviceMetadata_test.go b/grpc-gateway/service/updateDeviceMetadata_test.go index 45eb23d25..74a5cea9d 100644 --- a/grpc-gateway/service/updateDeviceMetadata_test.go +++ b/grpc-gateway/service/updateDeviceMetadata_test.go @@ -121,7 +121,7 @@ func TestRequestHandlerUpdateDeviceMetadataTwinEnabled(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -283,7 +283,7 @@ func TestRequestHandlerUpdateDeviceMetadataTwinForceSynchronization(t *testing.T defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/grpc-gateway/service/updateResource_test.go b/grpc-gateway/service/updateResource_test.go index d19ca017d..86c9a6191 100644 --- a/grpc-gateway/service/updateResource_test.go +++ b/grpc-gateway/service/updateResource_test.go @@ -183,7 +183,7 @@ func TestUpdateResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -227,7 +227,7 @@ func TestRequestHandlerGetAfterUpdateResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -290,7 +290,7 @@ func TestRequestHandlerRunMultipleUpdateResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -373,7 +373,7 @@ func TestRequestHandlerRunMultipleParallelUpdateResource(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/createResource_test.go b/http-gateway/service/createResource_test.go index 404371fe3..509f5fbcc 100644 --- a/http-gateway/service/createResource_test.go +++ b/http-gateway/service/createResource_test.go @@ -187,7 +187,7 @@ func TestRequestHandler_CreateResource(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/deleteDevices_test.go b/http-gateway/service/deleteDevices_test.go index 3533631c3..2ebb1bb9d 100644 --- a/http-gateway/service/deleteDevices_test.go +++ b/http-gateway/service/deleteDevices_test.go @@ -34,7 +34,7 @@ func TestRequestHandlerDeleteDevices(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/deleteResource_test.go b/http-gateway/service/deleteResource_test.go index 1b832a95b..323019cbd 100644 --- a/http-gateway/service/deleteResource_test.go +++ b/http-gateway/service/deleteResource_test.go @@ -119,7 +119,7 @@ func TestRequestHandlerDeleteResource(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -229,7 +229,7 @@ func TestRequestHandlerBatchDeleteResource(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getDevicePendingCommands_test.go b/http-gateway/service/getDevicePendingCommands_test.go index 8bdef9aff..8c00605fa 100644 --- a/http-gateway/service/getDevicePendingCommands_test.go +++ b/http-gateway/service/getDevicePendingCommands_test.go @@ -231,7 +231,7 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getDeviceResourceLinks_test.go b/http-gateway/service/getDeviceResourceLinks_test.go index bd5549d93..889ddcd9b 100644 --- a/http-gateway/service/getDeviceResourceLinks_test.go +++ b/http-gateway/service/getDeviceResourceLinks_test.go @@ -41,7 +41,7 @@ func TestRequestHandlerGetDeviceResourceLinks(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getDeviceResources_test.go b/http-gateway/service/getDeviceResources_test.go index 7cecbea5e..d6274ec46 100644 --- a/http-gateway/service/getDeviceResources_test.go +++ b/http-gateway/service/getDeviceResources_test.go @@ -154,7 +154,7 @@ func TestRequestHandlerGetDeviceResources(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) defer func() { diff --git a/http-gateway/service/getDevice_test.go b/http-gateway/service/getDevice_test.go index 3fbe5d2eb..e3390aeb5 100644 --- a/http-gateway/service/getDevice_test.go +++ b/http-gateway/service/getDevice_test.go @@ -68,7 +68,7 @@ func TestRequestHandlerGetDevice(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getDevicesMetadata_test.go b/http-gateway/service/getDevicesMetadata_test.go index 8e542ec94..4ffc9668d 100644 --- a/http-gateway/service/getDevicesMetadata_test.go +++ b/http-gateway/service/getDevicesMetadata_test.go @@ -121,7 +121,7 @@ func TestRequestHandlerGetDevicesMetadata(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getDevices_test.go b/http-gateway/service/getDevices_test.go index 5407ca37b..b7604c9ed 100644 --- a/http-gateway/service/getDevices_test.go +++ b/http-gateway/service/getDevices_test.go @@ -121,7 +121,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) defer func() { diff --git a/http-gateway/service/getEvents_test.go b/http-gateway/service/getEvents_test.go index ae72ae375..9cec4e49d 100644 --- a/http-gateway/service/getEvents_test.go +++ b/http-gateway/service/getEvents_test.go @@ -56,7 +56,7 @@ func TestRequestHandlerGetEvents(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getPendingCommands_test.go b/http-gateway/service/getPendingCommands_test.go index ed07951f0..660e6d6a6 100644 --- a/http-gateway/service/getPendingCommands_test.go +++ b/http-gateway/service/getPendingCommands_test.go @@ -278,7 +278,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getPendingMetadataUpdates_test.go b/http-gateway/service/getPendingMetadataUpdates_test.go index 33eef6ebb..622861bb7 100644 --- a/http-gateway/service/getPendingMetadataUpdates_test.go +++ b/http-gateway/service/getPendingMetadataUpdates_test.go @@ -93,7 +93,7 @@ func TestRequestHandlerGetPendingMetadataUpdates(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getResourceLinks_test.go b/http-gateway/service/getResourceLinks_test.go index 49d301598..053984318 100644 --- a/http-gateway/service/getResourceLinks_test.go +++ b/http-gateway/service/getResourceLinks_test.go @@ -40,7 +40,7 @@ func TestRequestHandlerGetResourceLinks(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) defer func() { diff --git a/http-gateway/service/getResourcePendingCommands_test.go b/http-gateway/service/getResourcePendingCommands_test.go index 161cdffc1..90833d95e 100644 --- a/http-gateway/service/getResourcePendingCommands_test.go +++ b/http-gateway/service/getResourcePendingCommands_test.go @@ -146,7 +146,7 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getResource_test.go b/http-gateway/service/getResource_test.go index 242e14092..2f264150b 100644 --- a/http-gateway/service/getResource_test.go +++ b/http-gateway/service/getResource_test.go @@ -47,7 +47,7 @@ func TestRequestHandlerGetResource(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/getResources_test.go b/http-gateway/service/getResources_test.go index 0d1544a0b..8a0ace16a 100644 --- a/http-gateway/service/getResources_test.go +++ b/http-gateway/service/getResources_test.go @@ -47,7 +47,7 @@ func TestRequestHandlerGetResources(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/subscribeToEvents_test.go b/http-gateway/service/subscribeToEvents_test.go index ed329e8ec..a2cff6db2 100644 --- a/http-gateway/service/subscribeToEvents_test.go +++ b/http-gateway/service/subscribeToEvents_test.go @@ -134,7 +134,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource shutdownHttp := httpgwTest.SetUp(t) defer shutdownHttp() - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/updateDeviceMetadata_test.go b/http-gateway/service/updateDeviceMetadata_test.go index aa4123696..12437af39 100644 --- a/http-gateway/service/updateDeviceMetadata_test.go +++ b/http-gateway/service/updateDeviceMetadata_test.go @@ -127,7 +127,7 @@ func TestRequestHandlerUpdateDeviceMetadata(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/http-gateway/service/updateResource_test.go b/http-gateway/service/updateResource_test.go index c22997670..e798b7bc1 100644 --- a/http-gateway/service/updateResource_test.go +++ b/http-gateway/service/updateResource_test.go @@ -186,7 +186,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/pkg/net/grpc/client/client.go b/pkg/net/grpc/client/client.go index 30ca18856..87952f0b6 100644 --- a/pkg/net/grpc/client/client.go +++ b/pkg/net/grpc/client/client.go @@ -60,6 +60,7 @@ func New(ctx context.Context, config Config, fileWatcher *fsnotify.Watcher, logg v = append(v, opts...) } + //nolint:staticcheck // TODO: update once the replacement is available conn, err := grpc.DialContext(ctx, config.Addr, v...) if err != nil { return nil, fmt.Errorf("cannot dial: %w", err) diff --git a/pkg/net/grpc/stub_test.go b/pkg/net/grpc/stub_test.go index 039d4f60c..ea2575ff2 100644 --- a/pkg/net/grpc/stub_test.go +++ b/pkg/net/grpc/stub_test.go @@ -17,7 +17,7 @@ func StubGrpcServer(opts ...grpc.ServerOption) *server.Server { } func StubGrpcClient(addr string) StubServiceClient { - conn, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { panic(err) } diff --git a/resource-directory/service/getDevicesMetadata_test.go b/resource-directory/service/getDevicesMetadata_test.go index 88ffa2fd5..db36dedf6 100644 --- a/resource-directory/service/getDevicesMetadata_test.go +++ b/resource-directory/service/getDevicesMetadata_test.go @@ -125,7 +125,7 @@ func TestRequestHandlerGetDevicesMetadata(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getDevices_test.go b/resource-directory/service/getDevices_test.go index 2eb70ed90..a3e81b10e 100644 --- a/resource-directory/service/getDevices_test.go +++ b/resource-directory/service/getDevices_test.go @@ -48,7 +48,7 @@ func TestRequestHandlerGetDevicesParallel(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) virtualdevice.CreateDevices(ctx, t, numDevices, numResources, test.StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -135,7 +135,7 @@ func TestRequestHandlerGetDevices(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getEventsSnapshot_test.go b/resource-directory/service/getEventsSnapshot_test.go index 5e265f62c..d4524e5ab 100644 --- a/resource-directory/service/getEventsSnapshot_test.go +++ b/resource-directory/service/getEventsSnapshot_test.go @@ -51,7 +51,7 @@ func TestRequestHandlerGetEventsStateSnapshot(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getEvents_test.go b/resource-directory/service/getEvents_test.go index ec346e0c1..a5f275efa 100644 --- a/resource-directory/service/getEvents_test.go +++ b/resource-directory/service/getEvents_test.go @@ -83,7 +83,7 @@ func TestRequestHandlerGetEventsOnOnboard(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getHubConfiguration_test.go b/resource-directory/service/getHubConfiguration_test.go index 12cd99d2a..b93961302 100644 --- a/resource-directory/service/getHubConfiguration_test.go +++ b/resource-directory/service/getHubConfiguration_test.go @@ -35,7 +35,7 @@ func TestRequestHandlerGetHubConfiguration(t *testing.T) { tearDown := service.SetUp(ctx, t) defer tearDown() - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getPendingCommands_test.go b/resource-directory/service/getPendingCommands_test.go index f3a01667d..321ff6d91 100644 --- a/resource-directory/service/getPendingCommands_test.go +++ b/resource-directory/service/getPendingCommands_test.go @@ -335,7 +335,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getResourceLinks_test.go b/resource-directory/service/getResourceLinks_test.go index b6fb18c75..5a622a298 100644 --- a/resource-directory/service/getResourceLinks_test.go +++ b/resource-directory/service/getResourceLinks_test.go @@ -56,7 +56,7 @@ func TestRequestHandlerGetResourceLinks(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/resource-directory/service/getResources_test.go b/resource-directory/service/getResources_test.go index 86b74bb2c..3055db469 100644 --- a/resource-directory/service/getResources_test.go +++ b/resource-directory/service/getResources_test.go @@ -65,7 +65,7 @@ func TestRequestHandlerGetResources(t *testing.T) { defer tearDown() ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/test/iotivity-lite/service/deleteResource_test.go b/test/iotivity-lite/service/deleteResource_test.go index fd096fb15..185fdd616 100644 --- a/test/iotivity-lite/service/deleteResource_test.go +++ b/test/iotivity-lite/service/deleteResource_test.go @@ -162,7 +162,7 @@ func TestBatchDeleteResources(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/test/iotivity-lite/service/offboard_test.go b/test/iotivity-lite/service/offboard_test.go index 245ea010f..7a44b2571 100644 --- a/test/iotivity-lite/service/offboard_test.go +++ b/test/iotivity-lite/service/offboard_test.go @@ -63,7 +63,7 @@ func TestOffboard(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -219,7 +219,7 @@ func TestOffboardWithoutSignIn(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -282,7 +282,7 @@ func TestOffboardWithSignIn(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -347,7 +347,7 @@ func TestOffboardWithSignInByRefreshToken(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -418,7 +418,7 @@ func TestOffboardWithRepeat(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -483,7 +483,7 @@ func TestOffboardInterrupt(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/test/iotivity-lite/service/republish_test.go b/test/iotivity-lite/service/republish_test.go index f70ad22af..9e43def74 100644 --- a/test/iotivity-lite/service/republish_test.go +++ b/test/iotivity-lite/service/republish_test.go @@ -56,7 +56,7 @@ func TestRepublishAfterRefresh(t *testing.T) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/test/pb/pendingCommand.go b/test/pb/pendingCommand.go index 8fb7506d2..d6beb7d61 100644 --- a/test/pb/pendingCommand.go +++ b/test/pb/pendingCommand.go @@ -93,7 +93,7 @@ func InitPendingEvents(ctx context.Context, t *testing.T) (pb.GrpcGatewayClient, token := oauthTest.GetDefaultAccessToken(t) ctx = kitNetGrpc.CtxWithToken(ctx, token) - conn, err := grpc.Dial(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) diff --git a/test/virtual-device/virtualDevice.go b/test/virtual-device/virtualDevice.go index 9673ef18b..cb7d87378 100644 --- a/test/virtual-device/virtualDevice.go +++ b/test/virtual-device/virtualDevice.go @@ -199,7 +199,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin func CreateDevices(ctx context.Context, t *testing.T, numDevices int, numResourcesPerDevice int, protocol commands.Connection_Protocol) { ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) - isConn, err := grpc.Dial(config.IDENTITY_STORE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + isConn, err := grpc.NewClient(config.IDENTITY_STORE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) @@ -208,7 +208,7 @@ func CreateDevices(ctx context.Context, t *testing.T, numDevices int, numResourc }() isClient := pb.NewIdentityStoreClient(isConn) - raConn, err := grpc.Dial(config.RESOURCE_AGGREGATE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + raConn, err := grpc.NewClient(config.RESOURCE_AGGREGATE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ RootCAs: test.GetRootCertificatePool(t), }))) require.NoError(t, err) From 0db14b52b3892da3bca54edcb1fd863269e6f357 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Tue, 9 Apr 2024 11:54:00 +0000 Subject: [PATCH 26/31] certificate authority: Only certificates belonging to the owner are obtained --- .../store/mongodb/signingRecords.go | 7 ++- .../store/mongodb/signingRecords_test.go | 62 ++++++++++++++----- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/certificate-authority/store/mongodb/signingRecords.go b/certificate-authority/store/mongodb/signingRecords.go index 00a73514d..1217f9ca7 100644 --- a/certificate-authority/store/mongodb/signingRecords.go +++ b/certificate-authority/store/mongodb/signingRecords.go @@ -79,7 +79,12 @@ func toSigningRecordsQueryFilter(owner string, queries *store.SigningRecordsQuer } switch len(or) { case 0: - return bson.D{} + if owner == "" { + return bson.D{} + } + return bson.D{ + {Key: store.OwnerKey, Value: owner}, + } case 1: return or[0] } diff --git a/certificate-authority/store/mongodb/signingRecords_test.go b/certificate-authority/store/mongodb/signingRecords_test.go index f260cf1a7..312f1a29b 100644 --- a/certificate-authority/store/mongodb/signingRecords_test.go +++ b/certificate-authority/store/mongodb/signingRecords_test.go @@ -308,10 +308,13 @@ func TestStoreLoadSigningRecords(t *testing.T) { const id = "9d017fad-2961-4fcc-94a9-1e1291a88ffc" const id1 = "9d017fad-2961-4fcc-94a9-1e1291a88ffd" const id2 = "9d017fad-2961-4fcc-94a9-1e1291a88ffe" + const owner = "owner" + const differentOwner = "owner2" + const differentOwnerRecordId = "9d017fad-2961-4fcc-94a9-1e1291a88fff" upds := pb.SigningRecords{ { Id: id, - Owner: "owner", + Owner: owner, CommonName: "commonName", PublicKey: "publicKey", DeviceId: hubTest.GenerateDeviceIDbyIdx(0), @@ -324,7 +327,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { }, { Id: id1, - Owner: "owner", + Owner: owner, CommonName: "commonName1", CreationDate: constDate().UnixNano(), PublicKey: "publicKey", @@ -337,7 +340,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { }, { Id: id2, - Owner: "owner", + Owner: owner, CommonName: "commonName2", CreationDate: constDate().UnixNano(), PublicKey: "publicKey", @@ -348,6 +351,19 @@ func TestStoreLoadSigningRecords(t *testing.T) { ValidUntilDate: constDate().UnixNano(), }, }, + { + Id: differentOwnerRecordId, + Owner: differentOwner, + CommonName: "commonName2", + CreationDate: constDate().UnixNano(), + PublicKey: "publicKey", + DeviceId: hubTest.GenerateDeviceIDbyIdx(3), + Credential: &pb.CredentialStatus{ + CertificatePem: "certificate", + Date: constDate().UnixNano(), + ValidUntilDate: constDate().UnixNano(), + }, + }, } lcs := upds @@ -371,7 +387,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { { name: "id", args: args{ - owner: "owner", + owner: owner, query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].GetId()}}, }, want: []*store.SigningRecord{lcs[1]}, @@ -379,7 +395,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { { name: "commonName", args: args{ - owner: "owner", + owner: owner, query: &store.SigningRecordsQuery{CommonNameFilter: []string{lcs[1].GetCommonName()}}, }, want: []*store.SigningRecord{lcs[1]}, @@ -387,26 +403,40 @@ func TestStoreLoadSigningRecords(t *testing.T) { { name: "DeviceID", args: args{ - owner: "owner", + owner: owner, query: &store.SigningRecordsQuery{DeviceIdFilter: []string{lcs[1].GetDeviceId()}}, }, want: []*store.SigningRecord{lcs[1]}, }, { - name: "id - another owner", + name: "multiple queries", args: args{ - owner: "another owner", - query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].GetId()}}, + owner: owner, + query: &store.SigningRecordsQuery{IdFilter: []string{lcs[0].GetId(), lcs[2].GetId()}}, }, - want: []*store.SigningRecord{lcs[1]}, + want: []*store.SigningRecord{lcs[0], lcs[2]}, }, { - name: "multiple queries", + name: "different owner", args: args{ - owner: "owner", - query: &store.SigningRecordsQuery{IdFilter: []string{lcs[0].GetId(), lcs[2].GetId()}}, + owner: differentOwner, + }, + want: []*store.SigningRecord{lcs[3]}, + }, + { + name: "different owner - id", + args: args{ + owner: differentOwner, + query: &store.SigningRecordsQuery{IdFilter: []string{differentOwnerRecordId}}, + }, + want: []*store.SigningRecord{lcs[3]}, + }, + { + name: "different owner but id belongs to owner", + args: args{ + owner: differentOwner, + query: &store.SigningRecordsQuery{IdFilter: []string{lcs[1].GetId()}}, }, - want: []*store.SigningRecord{lcs[0], lcs[2]}, }, { name: "all records", @@ -418,7 +448,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { { name: "not found", args: args{ - owner: "owner", + owner: owner, query: &store.SigningRecordsQuery{IdFilter: []string{"not found"}}, }, }, @@ -436,7 +466,7 @@ func TestStoreLoadSigningRecords(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var h testSigningRecordHandler - err := s.LoadSigningRecords(ctx, "owner", tt.args.query, h.Handle) + err := s.LoadSigningRecords(ctx, tt.args.owner, tt.args.query, h.Handle) require.NoError(t, err) require.Len(t, h.lcs, len(tt.want)) h.lcs.Sort() From 539028c93cbc839fa34f0701a0c9a56447b168aa Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Wed, 17 Apr 2024 10:44:05 +0200 Subject: [PATCH 27/31] resource-aggregate: propagate resource types to resource events (#1272) * resource-aggregate: propagate the resource types to the resource events --- .../retrieveResourceFromDevice_test.go | 6 +- .../service/updateResource_test.go | 15 +- .../service/retrieveDevice_test.go | 5 + coap-gateway/coapconv/coapconv.go | 40 +- .../observation/deviceObserver_test.go | 8 +- .../service/observation/observedResource.go | 20 +- .../service/observation/resourcesObserver.go | 14 +- coap-gateway/service/session.go | 16 +- go.mod | 2 +- go.sum | 4 +- .../client/deviceSubscriptions_test.go | 17 +- grpc-gateway/pb/README.md | 10 + grpc-gateway/pb/doc.html | 70 ++ grpc-gateway/pb/service.swagger.json | 60 ++ .../service/createAndDeleteResource_test.go | 23 +- grpc-gateway/service/createResource_test.go | 2 +- grpc-gateway/service/deleteResource_test.go | 4 +- .../service/getResourceFromDevice_test.go | 8 +- grpc-gateway/service/getResources_test.go | 7 +- .../service/subscribeToEvents_test.go | 30 +- grpc-gateway/service/updateResource_test.go | 13 +- .../subscription/subscription_test.go | 15 +- http-gateway/serverMux/jsonMarshaler_test.go | 5 +- http-gateway/service/createResource_test.go | 2 +- http-gateway/service/deleteResource_test.go | 4 +- .../service/getDevicePendingCommands_test.go | 25 +- .../service/getDeviceResources_test.go | 8 +- .../service/getPendingCommands_test.go | 27 +- .../getResourcePendingCommands_test.go | 10 +- http-gateway/service/getResource_test.go | 13 +- http-gateway/service/getResources_test.go | 10 +- .../service/subscribeToEvents_test.go | 13 +- http-gateway/service/updateResource_test.go | 11 +- resource-aggregate/commands/commands.pb.go | 857 ++++++++-------- .../cqrs/aggregate/aggregate.go | 87 +- .../cqrs/aggregate/aggregateParallel_test.go | 4 +- .../cqrs/aggregate/aggregate_test.go | 6 +- .../cqrs/aggregate/test/aggregate.go | 3 + resource-aggregate/cqrs/eventbus/event.go | 1 + .../eventbus/nats/publisher/publisher_test.go | 5 + .../nats/subscriber/subscriber_test.go | 5 + resource-aggregate/cqrs/eventstore/event.go | 1 + .../cqrs/eventstore/event_test.go | 5 + .../cqrs/eventstore/eventstore.go | 10 +- .../mongodb/acceptance_testing_events_test.go | 31 +- .../cqrs/eventstore/mongodb/eventstore.go | 23 +- .../cqrs/eventstore/mongodb/getevents.go | 2 +- .../cqrs/eventstore/mongodb/getevents_test.go | 5 + .../cqrs/eventstore/mongodb/load.go | 228 ++++- .../eventstore/mongodb/load_internal_test.go | 163 +++ .../cqrs/eventstore/mongodb/load_test.go | 126 +++ .../cqrs/eventstore/mongodb/save.go | 5 +- .../cqrs/eventstore/test/events.go | 229 ++--- .../projection/projectionInternal_test.go | 12 +- .../cqrs/projection/projection_test.go | 128 ++- .../events/deviceMetadataSnapshotTaken.go | 4 + .../events/deviceMetadataUpdatePending.go | 4 + .../events/deviceMetadataUpdated.go | 4 + resource-aggregate/events/events.pb.go | 925 ++++++++++-------- resource-aggregate/events/resourceChanged.go | 9 + .../events/resourceChanged_test.go | 5 +- .../events/resourceCreatePending.go | 5 + .../events/resourceCreatePending_test.go | 1 + resource-aggregate/events/resourceCreated.go | 5 + .../events/resourceCreated_test.go | 3 +- .../events/resourceDeletePending.go | 5 + .../events/resourceDeletePending_test.go | 3 +- resource-aggregate/events/resourceDeleted.go | 5 + .../events/resourceDeleted_test.go | 1 + .../events/resourceLinksPublished.go | 4 + .../events/resourceLinksSnapshotTaken.go | 4 + .../events/resourceLinksUnpublished.go | 4 + .../events/resourceRetrievePending.go | 5 + .../events/resourceRetrievePending_test.go | 3 +- .../events/resourceRetrieved.go | 5 + .../events/resourceRetrieved_test.go | 5 +- .../events/resourceStateSnapshotTaken.go | 65 +- .../events/resourceStateSnapshotTaken_test.go | 64 +- .../events/resourceUpdatePending.go | 5 + .../events/resourceUpdatePending_test.go | 3 +- resource-aggregate/events/resourceUpdated.go | 5 + .../events/resourceUpdated_test.go | 3 +- .../events/serviceMetadataSnapshotTaken.go | 4 + .../events/serviceMetadataUpdated.go | 4 + resource-aggregate/pb/commands.proto | 1 + resource-aggregate/pb/events.proto | 10 + resource-aggregate/service/aggregate.go | 48 +- resource-aggregate/service/grpcApi.go | 18 +- .../service/updateDeviceMetadata.go | 2 +- .../service/updateServiceHeartbeat.go | 4 +- .../service/deviceDirectory_test.go | 6 +- .../service/getEventsSnapshot_test.go | 3 +- resource-directory/service/getEvents_test.go | 3 +- .../service/getPendingCommands_test.go | 33 +- .../service/getResources_test.go | 2 +- .../service/resourceDirectory_test.go | 8 +- .../service/resourceShadow_test.go | 30 +- test/coap-gateway/test/defaultHandler.go | 8 +- test/pb/pendingCommand.go | 22 +- test/pb/resource.go | 33 +- test/test.go | 151 ++- 101 files changed, 2534 insertions(+), 1463 deletions(-) create mode 100644 resource-aggregate/cqrs/eventstore/mongodb/load_internal_test.go create mode 100644 resource-aggregate/cqrs/eventstore/mongodb/load_test.go diff --git a/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go b/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go index bb9d931ad..80e41a20e 100644 --- a/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go +++ b/cloud2cloud-connector/service/retrieveResourceFromDevice_test.go @@ -48,7 +48,7 @@ func testRequestHandlerGetResourceFromDevice(t *testing.T, events store.Events) }, }, wantContentType: message.AppOcfCbor.String(), - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), "", map[string]interface{}{ + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "name": "Light", "power": uint64(0), "state": false, @@ -62,7 +62,7 @@ func testRequestHandlerGetResourceFromDevice(t *testing.T, events store.Events) }, }, wantContentType: message.AppOcfCbor.String(), - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceSwitchesHref, "", []map[interface{}]interface{}{ + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", []map[interface{}]interface{}{ { "href": test.TestResourceSwitchesInstanceHref(switchID), "if": []interface{}{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE}, @@ -80,7 +80,7 @@ func testRequestHandlerGetResourceFromDevice(t *testing.T, events store.Events) }, }, wantContentType: message.AppOcfCbor.String(), - want: pbTest.MakeResourceRetrieved(t, deviceID, device.ResourceURI, "", map[string]interface{}{ + want: pbTest.MakeResourceRetrieved(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "di": deviceID, "dmv": "ocf.res.1.3.0", "icv": "ocf.2.0.5", diff --git a/cloud2cloud-connector/service/updateResource_test.go b/cloud2cloud-connector/service/updateResource_test.go index ae77c7add..652cb58f6 100644 --- a/cloud2cloud-connector/service/updateResource_test.go +++ b/cloud2cloud-connector/service/updateResource_test.go @@ -54,8 +54,9 @@ func testRequestHandlerUpdateResource(t *testing.T, events store.Events) { Content: &commands.Content{ CoapContentFormat: -1, }, - Status: commands.Status_OK, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + Status: commands.Status_OK, + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, { @@ -77,8 +78,9 @@ func testRequestHandlerUpdateResource(t *testing.T, events store.Events) { Content: &commands.Content{ CoapContentFormat: -1, }, - Status: commands.Status_OK, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + Status: commands.Status_OK, + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, { @@ -100,8 +102,9 @@ func testRequestHandlerUpdateResource(t *testing.T, events store.Events) { Content: &commands.Content{ CoapContentFormat: -1, }, - Status: commands.Status_OK, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + Status: commands.Status_OK, + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, { diff --git a/cloud2cloud-gateway/service/retrieveDevice_test.go b/cloud2cloud-gateway/service/retrieveDevice_test.go index 2f9a3f738..b8abebabb 100644 --- a/cloud2cloud-gateway/service/retrieveDevice_test.go +++ b/cloud2cloud-gateway/service/retrieveDevice_test.go @@ -61,12 +61,14 @@ type DevicesAllRepresentation struct { func getDevicesAllRepresentation(t *testing.T, deviceID, deviceName, switchID string) DevicesAllRepresentation { links := test.GetAllBackendResourceRepresentations(t, deviceID, deviceName) for i := range links { + links[i].ResourceTypes = nil if strings.HasSuffix(links[i].Href, test.TestResourceSwitchesHref) { l := test.DefaultSwitchResourceLink(deviceID, switchID) l.DeviceID = "" links[i].Representation = schema.ResourceLinks{l} continue } + // according OCF spec, resource link should not contain resource types field with content } links = append(links, test.ResourceLinkRepresentation{ Href: "/" + commands.NewResourceID(deviceID, test.TestResourceSwitchesInstanceHref(switchID)).ToString(), @@ -268,6 +270,9 @@ func TestRequestHandlerRetrieveDevice(t *testing.T) { d.Device.ProtocolIndependentID = "" d.Device.ManufacturerName = nil d.Links = d.Links.Sort() + for i := range d.Links { + d.Links[i].ResourceTypes = nil + } got = d } else if _, ok := tt.want.(DevicesBaseRepresentation); ok { d := DevicesBaseRepresentation{} diff --git a/coap-gateway/coapconv/coapconv.go b/coap-gateway/coapconv/coapconv.go index e6975e0e5..7ff762d5c 100644 --- a/coap-gateway/coapconv/coapconv.go +++ b/coap-gateway/coapconv/coapconv.go @@ -9,6 +9,8 @@ import ( "strings" "github.com/google/uuid" + "github.com/plgd-dev/device/v2/pkg/codec/cbor" + "github.com/plgd-dev/device/v2/pkg/codec/json" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/device/v2/schema/resources" "github.com/plgd-dev/go-coap/v3/message" @@ -18,7 +20,6 @@ import ( "github.com/plgd-dev/hub/v2/coap-gateway/uri" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/events" - "github.com/plgd-dev/kit/v2/codec/cbor" ) func StatusToCoapCode(status commands.Status, operation Operation) codes.Code { @@ -310,14 +311,20 @@ func NewConfirmResourceDeleteRequest(resourceID *commands.ResourceId, correlatio } } -func NewNotifyResourceChangedRequest(resourceID *commands.ResourceId, connectionID string, req *pool.Message) *commands.NotifyResourceChangedRequest { +func NewNotifyResourceChangedRequest(resourceID *commands.ResourceId, resourceTypes []string, connectionID string, req *pool.Message) *commands.NotifyResourceChangedRequest { content := NewContent(req.Options(), req.Body()) metadata := NewCommandMetadata(req.Sequence(), connectionID) + rtFromBody := tryToGetResourceTypesFromContent(content.GetCoapContentFormat(), content.GetData()) + if len(rtFromBody) > 0 { + resourceTypes = rtFromBody + } + return &commands.NotifyResourceChangedRequest{ ResourceId: resourceID, Content: content, CommandMetadata: metadata, + ResourceTypes: resourceTypes, Status: CoapCodeToStatus(req.Code(), Update), Etag: getETagFromMessage(req), } @@ -344,6 +351,30 @@ func filterOutEmptyResource(resource resources.BatchRepresentation) (isEmpty boo return isEmpty, false } +type ct struct { + ResourceTypes []string `json:"rt"` +} + +func tryToGetResourceTypesFromContent(contentFormat int32, content []byte) []string { + if len(content) == 0 { + return nil + } + decode := func([]byte, interface{}) error { + return errors.New("unsupported") + } + switch contentFormat { + case int32(message.AppOcfCbor), int32(message.AppCBOR): + decode = cbor.Decode + case int32(message.AppJSON): + decode = json.Decode + } + var c ct + if err := decode(content, &c); err == nil { + return c.ResourceTypes + } + return nil +} + func NewNotifyResourceChangedRequestsFromBatchResourceDiscovery(deviceID, connectionID string, req *pool.Message) ([]*commands.NotifyResourceChangedRequest, error) { data, contentFormat := GetContentData(req.Options(), req.Body()) metadata := NewCommandMetadata(req.Sequence(), connectionID) @@ -378,6 +409,10 @@ func NewNotifyResourceChangedRequestsFromBatchResourceDiscovery(deviceID, connec data = nil code = commands.Status_NOT_FOUND } + resourceTypes := r.ResourceTypes + if len(resourceTypes) == 0 { + resourceTypes = tryToGetResourceTypesFromContent(contentFormat, r.Content) + } resourceChangedReq := &commands.NotifyResourceChangedRequest{ ResourceId: commands.NewResourceID(deviceID, r.Href()), Content: &commands.Content{ @@ -388,6 +423,7 @@ func NewNotifyResourceChangedRequestsFromBatchResourceDiscovery(deviceID, connec CommandMetadata: metadata, Status: code, Etag: r.ETag, + ResourceTypes: resourceTypes, } if len(etag) > 0 && bytes.Equal(etag, r.ETag) { latestETagResource = resourceChangedReq diff --git a/coap-gateway/service/observation/deviceObserver_test.go b/coap-gateway/service/observation/deviceObserver_test.go index 8ec7a8bab..19561a498 100644 --- a/coap-gateway/service/observation/deviceObserver_test.go +++ b/coap-gateway/service/observation/deviceObserver_test.go @@ -160,8 +160,8 @@ func (h *observerHandler) PublishResources(req coapgwTestService.PublishRequest) return nil } -func (h *observerHandler) OnObserveResource(ctx context.Context, deviceID, resourceHref string, _ bool, notification *pool.Message) error { - err := h.DefaultObserverHandler.OnObserveResource(ctx, deviceID, resourceHref, notification) +func (h *observerHandler) OnObserveResource(ctx context.Context, deviceID, resourceHref string, resourceTypes []string, _ bool, notification *pool.Message) error { + err := h.DefaultObserverHandler.OnObserveResource(ctx, deviceID, resourceHref, resourceTypes, notification) require.NoError(h.t, err) if !h.done.Load() { h.observedResourceChan <- commands.NewResourceID(deviceID, resourceHref) @@ -169,8 +169,8 @@ func (h *observerHandler) OnObserveResource(ctx context.Context, deviceID, resou return nil } -func (h *observerHandler) OnGetResourceContent(ctx context.Context, deviceID, resourceHref string, notification *pool.Message) error { - err := h.DefaultObserverHandler.OnGetResourceContent(ctx, deviceID, resourceHref, notification) +func (h *observerHandler) OnGetResourceContent(ctx context.Context, deviceID, resourceHref string, resourceTypes []string, notification *pool.Message) error { + err := h.DefaultObserverHandler.OnGetResourceContent(ctx, deviceID, resourceHref, resourceTypes, notification) require.NoError(h.t, err) if !h.done.Load() { h.retrievedResourceChan <- commands.NewResourceID(deviceID, resourceHref) diff --git a/coap-gateway/service/observation/observedResource.go b/coap-gateway/service/observation/observedResource.go index 560b72aab..2f269a5f1 100644 --- a/coap-gateway/service/observation/observedResource.go +++ b/coap-gateway/service/observation/observedResource.go @@ -20,21 +20,23 @@ type Observation = interface { // Thread-safe wrapper with additional data for *tcp.Observation. type observedResource struct { - href string - resInterface string - synced atomic.Bool - isObservable bool - private struct { // guarded by mutex + href string + resInterface string + synced atomic.Bool + isObservable bool + resourceTypes []string + private struct { // guarded by mutex mutex sync.Mutex observation Observation } } -func newObservedResource(href, resInterface string, isObservable bool) *observedResource { +func newObservedResource(href, resInterface string, isObservable bool, resourceTypes []string) *observedResource { return &observedResource{ - href: href, - resInterface: resInterface, - isObservable: isObservable, + href: href, + resInterface: resInterface, + isObservable: isObservable, + resourceTypes: resourceTypes, } } diff --git a/coap-gateway/service/observation/resourcesObserver.go b/coap-gateway/service/observation/resourcesObserver.go index 0ea55ea89..e8897ac1c 100644 --- a/coap-gateway/service/observation/resourcesObserver.go +++ b/coap-gateway/service/observation/resourcesObserver.go @@ -16,8 +16,8 @@ import ( ) type ( - OnObserveResource = func(ctx context.Context, deviceID, resourceHref string, batch bool, notification *pool.Message) error - OnGetResourceContent = func(ctx context.Context, deviceID, resourceHref string, notification *pool.Message) error + OnObserveResource = func(ctx context.Context, deviceID, resourceHref string, resourceTypes []string, batch bool, notification *pool.Message) error + OnGetResourceContent = func(ctx context.Context, deviceID, resourceHref string, resourceTypes []string, notification *pool.Message) error UpdateTwinSynchronization = func(ctx context.Context, deviceID string, status commands.TwinSynchronization_State, t time.Time) error ) @@ -153,7 +153,7 @@ func (o *resourcesObserver) addResourceLocked(res *commands.Resource, obsInterfa if o.private.resources.contains(href) { return nil, nil } - obsRes := newObservedResource(href, obsInterface, res.IsObservable()) + obsRes := newObservedResource(href, obsInterface, res.IsObservable(), res.GetResourceTypes()) o.private.resources = o.private.resources.insert(obsRes) return obsRes, nil } @@ -179,7 +179,7 @@ func (o *resourcesObserver) handleResource(ctx context.Context, obsRes *observed if len(etags) > 0 { etag = etags[0] } - return o.getResourceContent(ctx, obsRes.Href(), etag) + return o.getResourceContent(ctx, obsRes.Href(), obsRes.resourceTypes, etag) } // Register to COAP-GW resource observation for given resource @@ -203,7 +203,7 @@ func (o *resourcesObserver) observeResource(ctx context.Context, obsRes *observe } } - if err2 := o.callbacks.OnObserveResource(ctx, o.deviceID, obsRes.Href(), batchObservation, msg); err2 != nil { + if err2 := o.callbacks.OnObserveResource(ctx, o.deviceID, obsRes.Href(), obsRes.resourceTypes, batchObservation, msg); err2 != nil { _ = o.logger.LogAndReturnError(cannotObserveResourceError(o.deviceID, obsRes.Href(), err2)) return } @@ -218,7 +218,7 @@ func (o *resourcesObserver) observeResource(ctx context.Context, obsRes *observe } // Request resource content form COAP-GW -func (o *resourcesObserver) getResourceContent(ctx context.Context, href string, etag []byte) error { +func (o *resourcesObserver) getResourceContent(ctx context.Context, href string, resourceTypes []string, etag []byte) error { cannotGetResourceError := func(deviceID, href string, err error) error { return fmt.Errorf("cannot get resource /%v%v content: %w", deviceID, href, err) } @@ -242,7 +242,7 @@ func (o *resourcesObserver) getResourceContent(ctx context.Context, href string, o.coapConn.ReleaseMessage(resp) } }() - if err := o.callbacks.OnGetResourceContent(ctx, o.deviceID, href, resp); err != nil { + if err := o.callbacks.OnGetResourceContent(ctx, o.deviceID, href, resourceTypes, resp); err != nil { return cannotGetResourceError(o.deviceID, href, err) } return nil diff --git a/coap-gateway/service/session.go b/coap-gateway/service/session.go index 4900f5f8d..b4f7f7803 100644 --- a/coap-gateway/service/session.go +++ b/coap-gateway/service/session.go @@ -317,7 +317,7 @@ func (c *session) cancelResourceSubscription(token string) (bool, error) { // // The received notification is released by this function at the correct moment and must not be released // by the caller. -func (c *session) onGetResourceContent(ctx context.Context, deviceID, href string, notification *pool.Message) error { +func (c *session) onGetResourceContent(ctx context.Context, deviceID, href string, resourceTypes []string, notification *pool.Message) error { cannotGetResourceContentError := func(deviceID, href string, err error) error { return fmt.Errorf("cannot get resource /%v%v content: %w", deviceID, href, err) } @@ -327,6 +327,7 @@ func (c *session) onGetResourceContent(ctx context.Context, deviceID, href strin notification *pool.Message deviceID string href string + resourceTypes []string c *session cannotGetResourceContentError func(deviceID, href string, err error) error }{ @@ -334,6 +335,7 @@ func (c *session) onGetResourceContent(ctx context.Context, deviceID, href strin notification: notification, deviceID: deviceID, href: href, + resourceTypes: resourceTypes, c: c, cannotGetResourceContentError: cannotGetResourceContentError, } @@ -342,7 +344,7 @@ func (c *session) onGetResourceContent(ctx context.Context, deviceID, href strin if x.notification.Code() == codes.NotFound { x.c.unpublishResourceLinks(x.c.getUserAuthorizedContext(x.ctx), []string{x.href}, nil) } - err2 := x.c.notifyContentChanged(x.deviceID, x.href, false, x.notification) + err2 := x.c.notifyContentChanged(x.deviceID, x.href, x.resourceTypes, false, x.notification) if err2 != nil { // hub is out of sync with the device, for recovery, the device is disconnected from the hub x.c.Close() @@ -370,7 +372,7 @@ func (c *session) onGetResourceContent(ctx context.Context, deviceID, href strin // // The received notification is released by this function at the correct moment and must not be released // by the caller. -func (c *session) onObserveResource(ctx context.Context, deviceID, href string, batch bool, notification *pool.Message) error { +func (c *session) onObserveResource(ctx context.Context, deviceID, href string, resourceTypes []string, batch bool, notification *pool.Message) error { cannotObserResourceError := func(err error) error { return fmt.Errorf("cannot handle resource observation: %w", err) } @@ -380,6 +382,7 @@ func (c *session) onObserveResource(ctx context.Context, deviceID, href string, notification *pool.Message deviceID string href string + resourceTypes []string c *session cannotObserResourceError func(err error) error batch bool @@ -388,6 +391,7 @@ func (c *session) onObserveResource(ctx context.Context, deviceID, href string, notification: notification, deviceID: deviceID, href: href, + resourceTypes: resourceTypes, c: c, cannotObserResourceError: cannotObserResourceError, batch: batch, @@ -397,7 +401,7 @@ func (c *session) onObserveResource(ctx context.Context, deviceID, href string, if x.notification.Code() == codes.NotFound { x.c.unpublishResourceLinks(x.c.getUserAuthorizedContext(x.notification.Context()), []string{x.href}, nil) } - err2 := x.c.notifyContentChanged(x.deviceID, x.href, x.batch, x.notification) + err2 := x.c.notifyContentChanged(x.deviceID, x.href, x.resourceTypes, x.batch, x.notification) if err2 != nil { // hub is out of sync with the device, for recovery, the device is disconnected from the hub x.c.Close() @@ -527,7 +531,7 @@ func (c *session) getLocalEndpoints() []string { return localEndpoints } -func (c *session) notifyContentChanged(deviceID, href string, batch bool, notification *pool.Message) error { +func (c *session) notifyContentChanged(deviceID, href string, resourceTypes []string, batch bool, notification *pool.Message) error { if !c.blockSignOff.TryAcquire(1) { c.getLogger().Debugf("cannot notify resource /%v%v content changed: signOff processing", deviceID, href) return nil @@ -561,7 +565,7 @@ func (c *session) notifyContentChanged(deviceID, href string, batch bool, notifi } return nil } - _, err = c.server.raClient.NotifyResourceChanged(ctx, coapconv.NewNotifyResourceChangedRequest(commands.NewResourceID(deviceID, href), c.RemoteAddr().String(), notification)) + _, err = c.server.raClient.NotifyResourceChanged(ctx, coapconv.NewNotifyResourceChangedRequest(commands.NewResourceID(deviceID, href), resourceTypes, c.RemoteAddr().String(), notification)) if err != nil { return notifyError(deviceID, href, err) } diff --git a/go.mod b/go.mod index ac9c8d1df..7e6e020c3 100644 --- a/go.mod +++ b/go.mod @@ -28,7 +28,7 @@ require ( github.com/panjf2000/ants/v2 v2.9.1 github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b + github.com/plgd-dev/device/v2 v2.4.5-0.20240412110951-d7aeb36bc7ba github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 diff --git a/go.sum b/go.sum index 098ce863a..2aad31e67 100644 --- a/go.sum +++ b/go.sum @@ -224,8 +224,8 @@ github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkL github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b h1:hADIFZn9Ck0qRW8xOiGuogzKjWjLyVgczZpuCEqFy2k= -github.com/plgd-dev/device/v2 v2.4.5-0.20240404111749-b0552c0bf48b/go.mod h1:vkQxyY8+PsKdkh/4TGP6hq3T37jd1pLvIR7XS83WyMg= +github.com/plgd-dev/device/v2 v2.4.5-0.20240412110951-d7aeb36bc7ba h1:yj1G0KaKRe88A3flQ8RHE0fxo/M+oEBFPrktCBgqpZc= +github.com/plgd-dev/device/v2 v2.4.5-0.20240412110951-d7aeb36bc7ba/go.mod h1:vkQxyY8+PsKdkh/4TGP6hq3T37jd1pLvIR7XS83WyMg= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 h1:Kaf/67M7+UVsRbNHQx3DDOLzpDI6RE/oYZz2v+a4csg= diff --git a/grpc-gateway/client/deviceSubscriptions_test.go b/grpc-gateway/client/deviceSubscriptions_test.go index 7750a7621..15d19b7a3 100644 --- a/grpc-gateway/client/deviceSubscriptions_test.go +++ b/grpc-gateway/client/deviceSubscriptions_test.go @@ -114,14 +114,14 @@ func TestObserveDeviceResourcesRetrieve(t *testing.T) { SubscriptionId: sub.ID(), CorrelationId: retrieveCorrelationID, Type: &pb.Event_ResourceRetrievePending{ - ResourceRetrievePending: pbTest.MakeResourceRetrievePending(deviceID, platform.ResourceURI, retrieveCorrelationID), + ResourceRetrievePending: pbTest.MakeResourceRetrievePending(deviceID, platform.ResourceURI, []string{platform.ResourceType}, retrieveCorrelationID), }, }, { SubscriptionId: sub.ID(), CorrelationId: retrieveCorrelationID, Type: &pb.Event_ResourceRetrieved{ - ResourceRetrieved: pbTest.MakeResourceRetrieved(t, deviceID, platform.ResourceURI, retrieveCorrelationID, + ResourceRetrieved: pbTest.MakeResourceRetrieved(t, deviceID, platform.ResourceURI, []string{platform.ResourceType}, retrieveCorrelationID, map[string]interface{}{ "mnmn": "ocfcloud.com", "x.org.iotivity.version": test.GetIotivityLiteVersion(t, deviceID), @@ -224,7 +224,7 @@ func TestObserveDeviceResourcesUpdate(t *testing.T) { SubscriptionId: sub.ID(), CorrelationId: updCorrelationID, Type: &pb.Event_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), updCorrelationID, + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, updCorrelationID, map[string]interface{}{ "value": true, }), @@ -252,7 +252,8 @@ func TestObserveDeviceResourcesUpdate(t *testing.T) { return d }(), }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, updCorrelationID, oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, updCorrelationID, oauthService.DeviceUserID), + ResourceTypes: test.TestResourceSwitchesInstanceResourceTypes, }, }, }, @@ -344,7 +345,7 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { SubscriptionId: sub.ID(), CorrelationId: createCorrelationID, Type: &pb.Event_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, createCorrelationID, + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, createCorrelationID, test.MakeSwitchResourceDefaultData()), }, }, @@ -352,7 +353,7 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { SubscriptionId: sub.ID(), CorrelationId: createCorrelationID, Type: &pb.Event_ResourceCreated{ - ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, createCorrelationID, + ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, createCorrelationID, pbTest.MakeCreateSwitchResourceResponseData(switchID)), }, }, @@ -382,7 +383,7 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { SubscriptionId: sub.ID(), CorrelationId: delCorrelationID, Type: &pb.Event_ResourceDeletePending{ - ResourceDeletePending: pbTest.MakeResourceDeletePending(deviceID, test.TestResourceSwitchesInstanceHref(switchID), + ResourceDeletePending: pbTest.MakeResourceDeletePending(deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, delCorrelationID), }, }, @@ -390,7 +391,7 @@ func TestObserveDeviceResourcesCreateAndDelete(t *testing.T) { SubscriptionId: sub.ID(), CorrelationId: delCorrelationID, Type: &pb.Event_ResourceDeleted{ - ResourceDeleted: pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesInstanceHref(switchID), + ResourceDeleted: pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, delCorrelationID), }, }, diff --git a/grpc-gateway/pb/README.md b/grpc-gateway/pb/README.md index 0cb9b99e9..50ea16d47 100644 --- a/grpc-gateway/pb/README.md +++ b/grpc-gateway/pb/README.md @@ -1491,6 +1491,7 @@ https://github.com/openconnectivityfoundation/core/blob/master/schemas/oic.links | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | | etag | [bytes](#bytes) | | etag of the resource used by twin synchronization | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceChanged.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceChanged-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1527,6 +1528,7 @@ https://github.com/openconnectivityfoundation/core/blob/master/schemas/oic.links | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | | valid_until | [int64](#int64) | | unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceCreatePending.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceCreatePending-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1563,6 +1565,7 @@ https://github.com/openconnectivityfoundation/core/blob/master/schemas/oic.links | content | [Content](#resourceaggregate-pb-Content) | | | | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceCreated.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceCreated-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1599,6 +1602,7 @@ https://github.com/openconnectivityfoundation/core/blob/master/schemas/oic.links | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | | valid_until | [int64](#int64) | | unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. | | resource_interface | [string](#string) | | | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceDeletePending.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceDeletePending-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1635,6 +1639,7 @@ https://github.com/openconnectivityfoundation/core/blob/master/schemas/oic.links | content | [Content](#resourceaggregate-pb-Content) | | | | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceDeleted.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceDeleted-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1776,6 +1781,7 @@ https://github.com/openconnectivityfoundation/cloud-services/blob/master/swagger | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | | valid_until | [int64](#int64) | | unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. | | etag | [bytes](#bytes) | repeated | | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceRetrievePending.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceRetrievePending-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1813,6 +1819,7 @@ https://github.com/openconnectivityfoundation/cloud-services/blob/master/swagger | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | | etag | [bytes](#bytes) | | | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceRetrieved.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceRetrieved-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1852,6 +1859,7 @@ https://github.com/openconnectivityfoundation/cloud-services/blob/master/swagger | resource_delete_pendings | [ResourceDeletePending](#resourceaggregate-pb-ResourceDeletePending) | repeated | expired events will be removed by creating a new snapshot. | | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | +| resource_types | [string](#string) | repeated | | @@ -1872,6 +1880,7 @@ https://github.com/openconnectivityfoundation/cloud-services/blob/master/swagger | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | | valid_until | [int64](#int64) | | unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceUpdatePending.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceUpdatePending-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | @@ -1908,6 +1917,7 @@ https://github.com/openconnectivityfoundation/cloud-services/blob/master/swagger | content | [Content](#resourceaggregate-pb-Content) | | | | audit_context | [AuditContext](#resourceaggregate-pb-AuditContext) | | | | event_metadata | [EventMetadata](#resourceaggregate-pb-EventMetadata) | | | +| resource_types | [string](#string) | repeated | | | open_telemetry_carrier | [ResourceUpdated.OpenTelemetryCarrierEntry](#resourceaggregate-pb-ResourceUpdated-OpenTelemetryCarrierEntry) | repeated | Open telemetry data propagated to asynchronous events | diff --git a/grpc-gateway/pb/doc.html b/grpc-gateway/pb/doc.html index 8d4c2586b..94218a2ae 100644 --- a/grpc-gateway/pb/doc.html +++ b/grpc-gateway/pb/doc.html @@ -4178,6 +4178,13 @@

ResourceChanged

etag of the resource used by twin synchronization

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceChanged.OpenTelemetryCarrierEntry @@ -4268,6 +4275,13 @@

ResourceCreatePending

unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever.

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceCreatePending.OpenTelemetryCarrierEntry @@ -4358,6 +4372,13 @@

ResourceCreated

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceCreated.OpenTelemetryCarrierEntry @@ -4448,6 +4469,13 @@

ResourceDeletePending

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceDeletePending.OpenTelemetryCarrierEntry @@ -4538,6 +4566,13 @@

ResourceDeleted

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceDeleted.OpenTelemetryCarrierEntry @@ -4877,6 +4912,13 @@

ResourceRetrievePending

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceRetrievePending.OpenTelemetryCarrierEntry @@ -4974,6 +5016,13 @@

ResourceRetrieved

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceRetrieved.OpenTelemetryCarrierEntry @@ -5085,6 +5134,13 @@

ResourceStateSnapshotTa

+ + resource_types + string + repeated +

+ + @@ -5144,6 +5200,13 @@

ResourceUpdatePending

unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever.

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceUpdatePending.OpenTelemetryCarrierEntry @@ -5234,6 +5297,13 @@

ResourceUpdated

+ + resource_types + string + repeated +

+ + open_telemetry_carrier ResourceUpdated.OpenTelemetryCarrierEntry diff --git a/grpc-gateway/pb/service.swagger.json b/grpc-gateway/pb/service.swagger.json index 826952e78..a67e85522 100644 --- a/grpc-gateway/pb/service.swagger.json +++ b/grpc-gateway/pb/service.swagger.json @@ -1772,6 +1772,12 @@ "format": "byte", "title": "etag of the resource used by twin synchronization" }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -1801,6 +1807,12 @@ "format": "int64", "description": "unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever." }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -1828,6 +1840,12 @@ "eventMetadata": { "$ref": "#/definitions/resourceaggregatepbEventMetadata" }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -1857,6 +1875,12 @@ "resourceInterface": { "type": "string" }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -1884,6 +1908,12 @@ "eventMetadata": { "$ref": "#/definitions/resourceaggregatepbEventMetadata" }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -2025,6 +2055,12 @@ "format": "byte" } }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -2056,6 +2092,12 @@ "type": "string", "format": "byte" }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -2111,6 +2153,12 @@ }, "eventMetadata": { "$ref": "#/definitions/resourceaggregatepbEventMetadata" + }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } } } }, @@ -2137,6 +2185,12 @@ "format": "int64", "description": "unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever." }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { @@ -2164,6 +2218,12 @@ "eventMetadata": { "$ref": "#/definitions/resourceaggregatepbEventMetadata" }, + "resourceTypes": { + "type": "array", + "items": { + "type": "string" + } + }, "openTelemetryCarrier": { "type": "object", "additionalProperties": { diff --git a/grpc-gateway/service/createAndDeleteResource_test.go b/grpc-gateway/service/createAndDeleteResource_test.go index c0e311325..38866992a 100644 --- a/grpc-gateway/service/createAndDeleteResource_test.go +++ b/grpc-gateway/service/createAndDeleteResource_test.go @@ -58,7 +58,7 @@ func createSwitchResource(ctx context.Context, t *testing.T, c pb.GrpcGatewayCli }) require.NoError(t, err) switchData := pbTest.MakeCreateSwitchResourceResponseData(switchID) - want := pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, "", switchData) + want := pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", switchData) pbTest.CmpResourceCreated(t, want, got.GetData()) } @@ -67,7 +67,7 @@ func deleteSwitchResource(ctx context.Context, t *testing.T, c pb.GrpcGatewayCli ResourceId: commands.NewResourceID(deviceID, test.TestResourceSwitchesInstanceHref(switchID)), }) require.NoError(t, err) - want := pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesInstanceHref(switchID), "") + want := pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "") pbTest.CmpResourceDeleted(t, want, got.GetData()) } @@ -76,7 +76,7 @@ func createSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", test.MakeSwitchResourceDefaultData()), }, } @@ -85,7 +85,7 @@ func createSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceChanged{ - ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesHref, "", + ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", []map[string]interface{}{ { "href": test.TestResourceSwitchesInstanceHref(switchID), @@ -105,7 +105,7 @@ func createSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceCreated{ - ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, "", + ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", test.MakeSwitchResourceData(map[string]interface{}{ "href": test.TestResourceSwitchesInstanceHref(switchID), "rep": map[string]interface{}{ @@ -144,7 +144,7 @@ func createSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceChanged{ - ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), "", + ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "", map[string]interface{}{ "value": false, }), @@ -209,8 +209,9 @@ func deleteSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati CorrelationId: correlationID, Type: &pb.Event_ResourceDeletePending{ ResourceDeletePending: &events.ResourceDeletePending{ - ResourceId: commands.NewResourceID(deviceID, test.TestResourceSwitchesInstanceHref(switchID)), - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceId: commands.NewResourceID(deviceID, test.TestResourceSwitchesInstanceHref(switchID)), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceSwitchesInstanceResourceTypes, }, }, } @@ -219,7 +220,7 @@ func deleteSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceDeleted{ - ResourceDeleted: pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesInstanceHref(switchID), ""), + ResourceDeleted: pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, ""), }, } @@ -239,11 +240,11 @@ func deleteSwitchResourceExpectedEvents(t *testing.T, deviceID, subID, correlati SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceChanged{ - ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesHref, "", []interface{}{}), + ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", []interface{}{}), }, } - res := pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), "", nil) + res := pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "", nil) res.Status = commands.Status_NOT_FOUND res.Content.CoapContentFormat = -1 res.Content.ContentType = "" diff --git a/grpc-gateway/service/createResource_test.go b/grpc-gateway/service/createResource_test.go index 2942532fc..28fe924cf 100644 --- a/grpc-gateway/service/createResource_test.go +++ b/grpc-gateway/service/createResource_test.go @@ -173,7 +173,7 @@ func TestRequestHandlerCreateResource(t *testing.T) { return } require.NoError(t, err) - resp := pbTest.MakeResourceCreated(t, deviceID, tt.args.href, "", tt.wantData) + resp := pbTest.MakeResourceCreated(t, deviceID, tt.args.href, test.TestResourceSwitchesResourceTypes, "", tt.wantData) pbTest.CmpResourceCreated(t, resp, got.GetData()) }) } diff --git a/grpc-gateway/service/deleteResource_test.go b/grpc-gateway/service/deleteResource_test.go index 295f19f56..d73b0a64d 100644 --- a/grpc-gateway/service/deleteResource_test.go +++ b/grpc-gateway/service/deleteResource_test.go @@ -131,7 +131,7 @@ func TestRequestHandlerDeleteResource(t *testing.T) { } require.NoError(t, err) - want := pbTest.MakeResourceDeleted(deviceID, tt.args.href, "") + want := pbTest.MakeResourceDeleted(deviceID, tt.args.href, test.TestResourceSwitchesInstanceResourceTypes, "") pbTest.CmpResourceDeleted(t, want, got.GetData()) }) } @@ -264,7 +264,7 @@ func TestRequestHandlerBatchDeleteResource(t *testing.T) { href: test.TestResourceSwitchesHref, }, want: func() *events.ResourceDeleted { - rdel := pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesHref, "") + rdel := pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "") links := test.CollectionLinkRepresentations{} for _, switchID := range switchIDs { links = append(links, test.CollectionLinkRepresentation{ diff --git a/grpc-gateway/service/getResourceFromDevice_test.go b/grpc-gateway/service/getResourceFromDevice_test.go index e4265b18f..048728654 100644 --- a/grpc-gateway/service/getResourceFromDevice_test.go +++ b/grpc-gateway/service/getResourceFromDevice_test.go @@ -72,7 +72,7 @@ func TestRequestHandlerGetResourceFromDevice(t *testing.T) { TimeToLive: int64(time.Hour), }, }, - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "name": "Light", "power": uint64(0), @@ -88,7 +88,7 @@ func TestRequestHandlerGetResourceFromDevice(t *testing.T) { TimeToLive: int64(time.Hour), }, }, - want: pbTest.MakeResourceRetrieved(t, deviceID, device.ResourceURI, "", + want: pbTest.MakeResourceRetrieved(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "n": deviceName, "di": deviceID, @@ -107,7 +107,7 @@ func TestRequestHandlerGetResourceFromDevice(t *testing.T) { TimeToLive: int64(time.Hour), }, }, - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceSwitchesHref, "", + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", []map[string]interface{}{ { "href": test.TestResourceSwitchesInstanceHref(switchID), @@ -130,7 +130,7 @@ func TestRequestHandlerGetResourceFromDevice(t *testing.T) { TimeToLive: int64(time.Hour), }, }, - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), "", + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "", map[string]interface{}{ "value": false, }, diff --git a/grpc-gateway/service/getResources_test.go b/grpc-gateway/service/getResources_test.go index 1cf72338c..e16e45e11 100644 --- a/grpc-gateway/service/getResources_test.go +++ b/grpc-gateway/service/getResources_test.go @@ -118,7 +118,7 @@ func TestRequestHandlerGetResources(t *testing.T) { want: []*pb.Resource{ { Types: []string{types.CORE_LIGHT}, - Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "state": false, "power": uint64(0), @@ -153,7 +153,8 @@ func TestRequestHandlerGetResources(t *testing.T) { Content: &commands.Content{ CoapContentFormat: -1, }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, }, @@ -168,7 +169,7 @@ func TestRequestHandlerGetResources(t *testing.T) { want: []*pb.Resource{ { Types: []string{types.BINARY_SWITCH}, - Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), "", + Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "", map[string]interface{}{ "value": false, }), diff --git a/grpc-gateway/service/subscribeToEvents_test.go b/grpc-gateway/service/subscribeToEvents_test.go index da15fdcb3..60af3bc2b 100644 --- a/grpc-gateway/service/subscribeToEvents_test.go +++ b/grpc-gateway/service/subscribeToEvents_test.go @@ -281,7 +281,7 @@ func TestRequestHandlerSubscribeForCreateEvents(t *testing.T) { SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", switchData), }, }, ev, "") @@ -302,7 +302,7 @@ func TestRequestHandlerSubscribeForCreateEvents(t *testing.T) { SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreated{ - ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, "", switchData), + ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", switchData), }, }, ev, "") } @@ -367,7 +367,7 @@ func TestRequestHandlerSubscribeForHrefEvents(t *testing.T) { SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", switchData), }, }, ev, "") @@ -398,7 +398,7 @@ func TestRequestHandlerSubscribeForHrefEvents(t *testing.T) { SubscriptionId: ev.GetSubscriptionId(), CorrelationId: "testToken", Type: &pb.Event_ResourceCreated{ - ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, "", switchData), + ResourceCreated: pbTest.MakeResourceCreated(t, deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "", switchData), }, }, ev, "") break @@ -438,7 +438,7 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -479,13 +479,14 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -498,13 +499,14 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -529,7 +531,8 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, @@ -547,7 +550,7 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -573,7 +576,8 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -591,7 +595,7 @@ func TestRequestHandlerSubscribeForPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), diff --git a/grpc-gateway/service/updateResource_test.go b/grpc-gateway/service/updateResource_test.go index 86c9a6191..10e1f05f5 100644 --- a/grpc-gateway/service/updateResource_test.go +++ b/grpc-gateway/service/updateResource_test.go @@ -111,7 +111,7 @@ func TestUpdateResource(t *testing.T) { }, }, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), }, { name: "valid with interface", @@ -127,7 +127,7 @@ func TestUpdateResource(t *testing.T) { }, }, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), }, { name: "revert update", @@ -143,7 +143,7 @@ func TestUpdateResource(t *testing.T) { }, }, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), }, { name: "update /switches/1", @@ -170,8 +170,9 @@ func TestUpdateResource(t *testing.T) { "value": true, }), }, - Status: commands.Status_OK, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + Status: commands.Status_OK, + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceSwitchesInstanceResourceTypes, }, }, } @@ -352,7 +353,7 @@ func TestRequestHandlerRunMultipleUpdateResource(t *testing.T) { for j := 1; j >= 0; j-- { ev, err = subClient.Recv() require.NoError(t, err) - pbTest.CmpResourceChanged(t, pbTest.MakeResourceChanged(t, deviceID, lightHref, "", makeLightData(j)), ev.GetResourceChanged(), "") + pbTest.CmpResourceChanged(t, pbTest.MakeResourceChanged(t, deviceID, lightHref, test.TestResourceLightInstanceResourceTypes, "", makeLightData(j)), ev.GetResourceChanged(), "") } }() } diff --git a/grpc-gateway/subscription/subscription_test.go b/grpc-gateway/subscription/subscription_test.go index f190aa43e..79762f6b0 100644 --- a/grpc-gateway/subscription/subscription_test.go +++ b/grpc-gateway/subscription/subscription_test.go @@ -70,7 +70,7 @@ func checkAndValidateUpdate(ctx context.Context, t *testing.T, rac raservice.Res }) require.NoError(t, err) - resourceUpdatePending := pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), updCorrelationID, + resourceUpdatePending := pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, updCorrelationID, map[string]interface{}{ "power": value, }, @@ -90,7 +90,7 @@ func checkAndValidateUpdate(ctx context.Context, t *testing.T, rac raservice.Res check(t, ev, &pb.Event{ SubscriptionId: s.Id(), Type: &pb.Event_ResourceUpdated{ - ResourceUpdated: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), updCorrelationID, nil), + ResourceUpdated: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, updCorrelationID, nil), }, CorrelationId: correlationID, }) @@ -98,7 +98,7 @@ func checkAndValidateUpdate(ctx context.Context, t *testing.T, rac raservice.Res check(t, ev, &pb.Event{ SubscriptionId: s.Id(), Type: &pb.Event_ResourceChanged{ - ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", test.LightResourceRepresentation{ Name: "Light", Power: value, @@ -126,8 +126,9 @@ func checkAndValidateRetrieve(ctx context.Context, t *testing.T, rac raservice.R SubscriptionId: s.Id(), Type: &pb.Event_ResourceRetrievePending{ ResourceRetrievePending: &events.ResourceRetrievePending{ - ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, retrieveCorrelationID, oauthService.DeviceUserID), + ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, retrieveCorrelationID, oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, CorrelationId: correlationID, @@ -135,7 +136,7 @@ func checkAndValidateRetrieve(ctx context.Context, t *testing.T, rac raservice.R check(t, waitForEvent(ctx, t, recvChan), &pb.Event{ SubscriptionId: s.Id(), Type: &pb.Event_ResourceRetrieved{ - ResourceRetrieved: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), + ResourceRetrieved: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, retrieveCorrelationID, test.LightResourceRepresentation{ Name: "Light", @@ -154,7 +155,7 @@ func getResourceChangedEvents(t *testing.T, deviceID, correlationID, subscriptio events[rid.GetHref()] = &pb.Event{ SubscriptionId: subscriptionID, Type: &pb.Event_ResourceChanged{ - ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), "", res.Representation), + ResourceChanged: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), res.ResourceTypes, "", res.Representation), }, CorrelationId: correlationID, } diff --git a/http-gateway/serverMux/jsonMarshaler_test.go b/http-gateway/serverMux/jsonMarshaler_test.go index e4263e59e..567dfc578 100644 --- a/http-gateway/serverMux/jsonMarshaler_test.go +++ b/http-gateway/serverMux/jsonMarshaler_test.go @@ -27,7 +27,7 @@ func TestJsonMarshalerMarshal(t *testing.T) { { name: "valid", args: args{ - v: pb.MakeResourceChanged(t, "deviceID", "/href", "correlationID", map[interface{}]interface{}{ + v: pb.MakeResourceChanged(t, "deviceID", "/href", []string{"type"}, "correlationID", map[interface{}]interface{}{ "key": "value", }), }, @@ -44,7 +44,8 @@ func TestJsonMarshalerMarshal(t *testing.T) { "deviceId": "deviceID", "href": "/href", }, - "status": "OK", + "status": "OK", + "resourceTypes": []interface{}{"type"}, }, }, } diff --git a/http-gateway/service/createResource_test.go b/http-gateway/service/createResource_test.go index 509f5fbcc..55008bf06 100644 --- a/http-gateway/service/createResource_test.go +++ b/http-gateway/service/createResource_test.go @@ -219,7 +219,7 @@ func TestRequestHandler_CreateResource(t *testing.T) { return } require.NoError(t, err) - want := pbTest.MakeResourceCreated(t, deviceID, tt.args.href, "", tt.wantData) + want := pbTest.MakeResourceCreated(t, deviceID, tt.args.href, test.TestResourceSwitchesResourceTypes, "", tt.wantData) pbTest.CmpResourceCreated(t, want, got.GetData()) }) } diff --git a/http-gateway/service/deleteResource_test.go b/http-gateway/service/deleteResource_test.go index 323019cbd..95742cae3 100644 --- a/http-gateway/service/deleteResource_test.go +++ b/http-gateway/service/deleteResource_test.go @@ -149,7 +149,7 @@ func TestRequestHandlerDeleteResource(t *testing.T) { return } require.NoError(t, err) - want := pbTest.MakeResourceDeleted(deviceID, tt.args.href, "") + want := pbTest.MakeResourceDeleted(deviceID, tt.args.href, test.TestResourceSwitchesInstanceResourceTypes, "") pbTest.CmpResourceDeleted(t, want, got.GetData()) }) } @@ -198,7 +198,7 @@ func TestRequestHandlerBatchDeleteResource(t *testing.T) { href: test.TestResourceSwitchesHref, }, want: func() *events.ResourceDeleted { - rdel := pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesHref, "") + rdel := pbTest.MakeResourceDeleted(deviceID, test.TestResourceSwitchesHref, test.TestResourceSwitchesResourceTypes, "") links := test.CollectionLinkRepresentations{} for _, switchID := range switchIDs { links = append(links, test.CollectionLinkRepresentation{ diff --git a/http-gateway/service/getDevicePendingCommands_test.go b/http-gateway/service/getDevicePendingCommands_test.go index 8c00605fa..af60afb90 100644 --- a/http-gateway/service/getDevicePendingCommands_test.go +++ b/http-gateway/service/getDevicePendingCommands_test.go @@ -63,13 +63,14 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -82,13 +83,14 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -111,7 +113,8 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, @@ -127,7 +130,7 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }, @@ -151,7 +154,8 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -167,7 +171,7 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -185,7 +189,7 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -198,7 +202,8 @@ func TestRequestHandlerGetDevicePendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, diff --git a/http-gateway/service/getDeviceResources_test.go b/http-gateway/service/getDeviceResources_test.go index d6274ec46..284c2d396 100644 --- a/http-gateway/service/getDeviceResources_test.go +++ b/http-gateway/service/getDeviceResources_test.go @@ -34,7 +34,7 @@ func getResourceChanged(t *testing.T, deviceID string, href string) *events.Reso for _, l := range test.GetAllBackendResourceRepresentations(t, deviceID, test.TestDeviceName) { rid := commands.ResourceIdFromString(l.Href) if rid.GetHref() == href { - return pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), "", l.Representation) + return pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), l.ResourceTypes, "", l.Representation) } } return nil @@ -65,7 +65,7 @@ func getResources(t *testing.T, deviceID, deviceName, switchID string) []*pb.Res if rid.GetHref() == test.TestResourceSwitchesHref { resources = append(resources, &pb.Resource{ Types: getResourceType(rid.GetHref()), - Data: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), "", []interface{}{ + Data: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), res.ResourceTypes, "", []interface{}{ map[string]interface{}{ "href": test.TestResourceSwitchesInstanceHref(switchID), "if": []string{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE}, @@ -80,13 +80,13 @@ func getResources(t *testing.T, deviceID, deviceName, switchID string) []*pb.Res } else { resources = append(resources, &pb.Resource{ Types: getResourceType(rid.GetHref()), - Data: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), "", res.Representation), + Data: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), res.ResourceTypes, "", res.Representation), }) } } resources = append(resources, &pb.Resource{ Types: []string{types.BINARY_SWITCH}, - Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), "", test.SwitchResourceRepresentation{}), + Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "", test.SwitchResourceRepresentation{}), }) return resources } diff --git a/http-gateway/service/getPendingCommands_test.go b/http-gateway/service/getPendingCommands_test.go index 660e6d6a6..3682ba020 100644 --- a/http-gateway/service/getPendingCommands_test.go +++ b/http-gateway/service/getPendingCommands_test.go @@ -63,7 +63,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -96,13 +96,14 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -115,13 +116,14 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -143,7 +145,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, @@ -158,7 +161,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -180,7 +183,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -195,7 +199,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -212,7 +216,7 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -225,7 +229,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, diff --git a/http-gateway/service/getResourcePendingCommands_test.go b/http-gateway/service/getResourcePendingCommands_test.go index 90833d95e..885a82939 100644 --- a/http-gateway/service/getResourcePendingCommands_test.go +++ b/http-gateway/service/getResourcePendingCommands_test.go @@ -59,7 +59,7 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -72,7 +72,8 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -89,7 +90,7 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { want: []*pb.PendingCommand{ { Command: &pb.PendingCommand_ResourceCreatePending{ - ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, "", + ResourceCreatePending: pbTest.MakeResourceCreatePending(t, deviceID, device.ResourceURI, test.TestResourceDeviceResourceTypes, "", map[string]interface{}{ "power": 1, }), @@ -113,7 +114,8 @@ func TestRequestHandlerGetResourcePendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, diff --git a/http-gateway/service/getResource_test.go b/http-gateway/service/getResource_test.go index 2f264150b..f71eb6400 100644 --- a/http-gateway/service/getResource_test.go +++ b/http-gateway/service/getResource_test.go @@ -91,9 +91,10 @@ func TestRequestHandlerGetResource(t *testing.T) { DeviceId: deviceID, Href: test.TestResourceLightInstanceHref("1"), }, - Status: commands.Status_OK, - Content: &commands.Content{}, // content is encoded as json - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + Status: commands.Status_OK, + Content: &commands.Content{}, // content is encoded as json + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, wantCode: http.StatusOK, }, @@ -104,7 +105,7 @@ func TestRequestHandlerGetResource(t *testing.T) { deviceID: deviceID, resourceHref: test.TestResourceLightInstanceHref("1"), }, - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "state": false, "power": uint64(0), @@ -152,7 +153,7 @@ func TestRequestHandlerGetResource(t *testing.T) { resourceHref: test.TestResourceLightInstanceHref("1"), resourceInterface: interfaces.OC_IF_BASELINE, }, - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "state": false, "power": uint64(0), @@ -171,7 +172,7 @@ func TestRequestHandlerGetResource(t *testing.T) { resourceHref: test.TestResourceLightInstanceHref("1"), twin: newBool(false), }, - want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + want: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "state": false, "power": uint64(0), diff --git a/http-gateway/service/getResources_test.go b/http-gateway/service/getResources_test.go index 8a0ace16a..e2206e5c3 100644 --- a/http-gateway/service/getResources_test.go +++ b/http-gateway/service/getResources_test.go @@ -128,7 +128,7 @@ func TestRequestHandlerGetResources(t *testing.T) { want: []*pb.Resource{ { Types: []string{types.CORE_LIGHT}, - Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "state": false, "power": uint64(0), @@ -147,7 +147,7 @@ func TestRequestHandlerGetResources(t *testing.T) { want: []*pb.Resource{ { Types: []string{types.BINARY_SWITCH}, - Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), "", + Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceSwitchesInstanceHref(switchID), test.TestResourceSwitchesInstanceResourceTypes, "", map[string]interface{}{ "value": false, }, @@ -178,7 +178,8 @@ func TestRequestHandlerGetResources(t *testing.T) { Content: &commands.Content{ CoapContentFormat: -1, }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, }, @@ -206,7 +207,8 @@ func TestRequestHandlerGetResources(t *testing.T) { Content: &commands.Content{ CoapContentFormat: -1, }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, }, diff --git a/http-gateway/service/subscribeToEvents_test.go b/http-gateway/service/subscribeToEvents_test.go index a2cff6db2..d284a2438 100644 --- a/http-gateway/service/subscribeToEvents_test.go +++ b/http-gateway/service/subscribeToEvents_test.go @@ -79,7 +79,7 @@ func (u *updateChecker) checkUpdateLightResource(ctx context.Context, t *testing expectedEvent := &pb.Event{ SubscriptionId: u.subUpdatedID, Type: &pb.Event_ResourceUpdatePending{ - ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, u.deviceID, test.TestResourceLightInstanceHref("1"), updCorrelationID, + ResourceUpdatePending: pbTest.MakeResourceUpdatePending(t, u.deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, updCorrelationID, map[string]interface{}{ "power": power, }), @@ -91,7 +91,7 @@ func (u *updateChecker) checkUpdateLightResource(ctx context.Context, t *testing expectedEvent := &pb.Event{ SubscriptionId: u.subUpdatedID, Type: &pb.Event_ResourceUpdated{ - ResourceUpdated: pbTest.MakeResourceUpdated(t, u.deviceID, test.TestResourceLightInstanceHref("1"), updCorrelationID, nil), + ResourceUpdated: pbTest.MakeResourceUpdated(t, u.deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, updCorrelationID, nil), }, CorrelationId: "updatePending + resourceUpdated", } @@ -100,7 +100,7 @@ func (u *updateChecker) checkUpdateLightResource(ctx context.Context, t *testing expectedEvent := &pb.Event{ SubscriptionId: u.baseSubID, Type: &pb.Event_ResourceChanged{ - ResourceChanged: pbTest.MakeResourceChanged(t, u.deviceID, test.TestResourceLightInstanceHref("1"), + ResourceChanged: pbTest.MakeResourceChanged(t, u.deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, ev.GetResourceChanged().GetAuditContext().GetCorrelationId(), map[string]interface{}{ "state": false, @@ -331,8 +331,9 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource SubscriptionId: subReceivedID, Type: &pb.Event_ResourceRetrievePending{ ResourceRetrievePending: &events.ResourceRetrievePending{ - ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), - AuditContext: ev.GetResourceRetrievePending().GetAuditContext(), + ResourceId: commands.NewResourceID(deviceID, test.TestResourceLightInstanceHref("1")), + AuditContext: ev.GetResourceRetrievePending().GetAuditContext(), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, CorrelationId: "receivePending + resourceReceived", @@ -345,7 +346,7 @@ func testRequestHandlerSubscribeToEvents(t *testing.T, deviceID string, resource expectedEvent = &pb.Event{ SubscriptionId: subReceivedID, Type: &pb.Event_ResourceRetrieved{ - ResourceRetrieved: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), recvCorrelationID, + ResourceRetrieved: pbTest.MakeResourceRetrieved(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, recvCorrelationID, map[string]interface{}{ "name": "Light", "power": 0x0, diff --git a/http-gateway/service/updateResource_test.go b/http-gateway/service/updateResource_test.go index e798b7bc1..06b5502c7 100644 --- a/http-gateway/service/updateResource_test.go +++ b/http-gateway/service/updateResource_test.go @@ -100,7 +100,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { "power": 1, }, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), wantHTTPCode: http.StatusOK, }, { @@ -114,7 +114,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { "power": 102, }, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), wantHTTPCode: http.StatusOK, }, { @@ -128,7 +128,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { }, resourceInterface: interfaces.OC_IF_BASELINE, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), wantHTTPCode: http.StatusOK, }, { @@ -142,7 +142,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { }, resourceInterface: interfaces.OC_IF_BASELINE, }, - want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), "", nil), + want: pbTest.MakeResourceUpdated(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", nil), wantHTTPCode: http.StatusOK, }, { @@ -168,7 +168,8 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { "value": true, }), }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceSwitchesInstanceResourceTypes, }, wantHTTPCode: http.StatusOK, }, diff --git a/resource-aggregate/commands/commands.pb.go b/resource-aggregate/commands/commands.pb.go index 9b7f22483..4635eacdc 100644 --- a/resource-aggregate/commands/commands.pb.go +++ b/resource-aggregate/commands/commands.pb.go @@ -503,6 +503,7 @@ type NotifyResourceChangedRequest struct { CommandMetadata *CommandMetadata `protobuf:"bytes,3,opt,name=command_metadata,json=commandMetadata,proto3" json:"command_metadata,omitempty"` Status Status `protobuf:"varint,4,opt,name=status,proto3,enum=resourceaggregate.pb.Status" json:"status,omitempty"` Etag []byte `protobuf:"bytes,5,opt,name=etag,proto3" json:"etag,omitempty"` + ResourceTypes []string `protobuf:"bytes,6,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` } func (x *NotifyResourceChangedRequest) Reset() { @@ -572,6 +573,13 @@ func (x *NotifyResourceChangedRequest) GetEtag() []byte { return nil } +func (x *NotifyResourceChangedRequest) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + type NotifyResourceChangedResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2898,7 +2906,7 @@ var file_resource_aggregate_pb_commands_proto_rawDesc = []byte{ 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, - 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xb6, 0x02, 0x0a, + 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xdd, 0x02, 0x0a, 0x1c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, @@ -2918,455 +2926,458 @@ var file_resource_aggregate_pb_commands_proto_rawDesc = []byte{ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x65, 0x74, 0x61, 0x67, 0x22, 0x68, 0x0a, 0x1d, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, + 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0x68, 0x0a, 0x1d, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, + 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x6d, 0x0a, 0x21, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x05, 0x62, + 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, + 0x62, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x05, + 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x6d, 0x0a, 0x22, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, + 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x22, 0xdd, 0x02, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, + 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, + 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, + 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, + 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x1c, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, + 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x68, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, - 0x6d, 0x0a, 0x21, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, - 0x79, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x05, 0x62, 0x61, 0x74, 0x63, 0x68, 0x22, 0x6d, - 0x0a, 0x22, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x79, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, + 0xba, 0x02, 0x0a, 0x17, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, + 0x66, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, + 0x6c, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, + 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x22, 0x84, 0x01, 0x0a, + 0x18, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, + 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x22, 0xdf, 0x02, 0x0a, 0x1e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, - 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xdd, 0x02, - 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, - 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x82, 0x01, - 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, - 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, - 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x68, - 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xba, 0x02, 0x0a, 0x17, 0x52, 0x65, 0x74, - 0x72, 0x69, 0x65, 0x76, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x2d, - 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x66, 0x61, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x20, 0x0a, - 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, + 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, + 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, - 0x04, 0x65, 0x74, 0x61, 0x67, 0x22, 0x84, 0x01, 0x0a, 0x18, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x76, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, - 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, - 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, - 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xdf, 0x02, 0x0a, - 0x1e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, - 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, - 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x22, 0x6a, - 0x0a, 0x1f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x61, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x04, 0x65, 0x74, 0x61, 0x67, 0x22, 0x6a, 0x0a, 0x1f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x22, 0xa4, 0x02, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, + 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, + 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, + 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, + 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, + 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc9, 0x02, + 0x0a, 0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, + 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, - 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xa4, 0x02, 0x0a, 0x15, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x20, - 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, - 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, - 0x65, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, - 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, - 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, + 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, + 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, + 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x68, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, + 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x22, 0xae, 0x02, 0x0a, 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, + 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x22, 0x68, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, - 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xae, 0x02, 0x0a, - 0x15, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, + 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, + 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x22, 0x82, 0x01, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, + 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, + 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x1c, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, + 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, + 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, + 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x68, 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, + 0xa0, 0x03, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x41, 0x74, 0x12, 0x45, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, + 0x6c, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x0e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x22, 0x21, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x4f, + 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, + 0x4e, 0x45, 0x10, 0x01, 0x22, 0x52, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, + 0x04, 0x43, 0x4f, 0x41, 0x50, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4f, 0x41, 0x50, 0x53, + 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x4f, 0x41, 0x50, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x03, + 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x41, 0x50, 0x53, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x04, 0x12, + 0x07, 0x0a, 0x03, 0x43, 0x32, 0x43, 0x10, 0x05, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x12, + 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, + 0x69, 0x6c, 0x22, 0xe7, 0x02, 0x0a, 0x13, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x41, 0x74, + 0x12, 0x1c, 0x0a, 0x0a, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x74, 0x12, 0x50, + 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, + 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x38, 0x0a, 0x18, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, + 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x16, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x74, 0x22, 0x40, 0x0a, 0x05, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x53, 0x59, + 0x4e, 0x43, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, + 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, + 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, - 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5e, 0x0a, 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, + 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, + 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, + 0x13, 0x74, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, + 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, + 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, + 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, + 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, + 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x82, 0x01, - 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, - 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, - 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x22, 0xc9, 0x02, 0x0a, 0x1c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x10, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x08, 0x0a, + 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xab, 0x01, + 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, + 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, + 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, + 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, + 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xe6, 0x02, 0x0a, 0x22, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, + 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0c, + 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, + 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, + 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4a, 0x04, + 0x08, 0x04, 0x10, 0x05, 0x22, 0x6e, 0x0a, 0x23, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x44, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, + 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x22, 0xe7, 0x01, 0x0a, 0x1c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, + 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x68, - 0x0a, 0x1d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x91, + 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, + 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x23, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, 0x65, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, + 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, + 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x98, 0x01, + 0x0a, 0x24, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xa0, 0x03, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3f, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x45, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, - 0x69, 0x6e, 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x6f, 0x63, 0x61, - 0x6c, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x21, 0x0a, 0x06, 0x53, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x46, 0x46, 0x4c, 0x49, 0x4e, 0x45, 0x10, - 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4f, 0x4e, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x01, 0x22, 0x52, 0x0a, - 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, - 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x41, 0x50, 0x10, 0x01, - 0x12, 0x09, 0x0a, 0x05, 0x43, 0x4f, 0x41, 0x50, 0x53, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x43, - 0x4f, 0x41, 0x50, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x41, - 0x50, 0x53, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x04, 0x12, 0x07, 0x0a, 0x03, 0x43, 0x32, 0x43, 0x10, - 0x05, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x12, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0xe7, 0x02, 0x0a, 0x13, - 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x45, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x79, - 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, - 0x73, 0x79, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x41, 0x74, 0x12, 0x1c, 0x0a, 0x0a, 0x69, 0x6e, 0x5f, - 0x73, 0x79, 0x6e, 0x63, 0x5f, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, - 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x41, 0x74, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, - 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x18, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x16, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x41, 0x74, 0x22, 0x40, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0f, 0x0a, 0x0b, - 0x4f, 0x55, 0x54, 0x5f, 0x4f, 0x46, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x00, 0x12, 0x0c, 0x0a, - 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x53, - 0x59, 0x4e, 0x43, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x49, 0x4e, 0x5f, 0x53, - 0x59, 0x4e, 0x43, 0x10, 0x03, 0x22, 0xee, 0x03, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, - 0x00, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5e, 0x0a, - 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x13, 0x74, 0x77, 0x69, 0x6e, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a, - 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, - 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, - 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, - 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, - 0x4c, 0x69, 0x76, 0x65, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x35, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x22, + 0x7f, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0xab, 0x01, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x22, 0xe6, 0x02, 0x0a, 0x22, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x63, 0x6f, 0x72, 0x72, - 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x23, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, - 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, - 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, - 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, - 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, - 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, - 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x09, 0x0a, 0x07, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x6e, 0x0a, - 0x23, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, - 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xe7, 0x01, - 0x0a, 0x1c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, - 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x41, - 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, - 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x91, 0x01, 0x0a, 0x1d, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, - 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, - 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0xc8, 0x01, 0x0a, 0x23, - 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, - 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x69, 0x64, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x13, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x46, 0x69, - 0x6c, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x98, 0x01, 0x0a, 0x24, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x22, 0x35, 0x0a, 0x14, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, 0x22, 0x7f, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x73, - 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, - 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, - 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x8d, 0x01, 0x0a, 0x10, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, - 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, - 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x22, 0x70, 0x0a, 0x1c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x46, 0x0a, 0x09, 0x68, 0x65, 0x61, - 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, - 0x62, 0x65, 0x61, 0x74, 0x48, 0x00, 0x52, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, - 0x74, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x22, 0x53, 0x0a, 0x1d, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, - 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, - 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x13, 0x68, 0x65, 0x61, - 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, - 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x22, 0x8d, 0x01, 0x0a, 0x10, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, + 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x49, 0x64, 0x12, 0x20, 0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x6f, 0x5f, + 0x6c, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x74, 0x69, 0x6d, 0x65, + 0x54, 0x6f, 0x4c, 0x69, 0x76, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x22, 0x70, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x46, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x48, 0x00, 0x52, 0x09, 0x68, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x42, 0x08, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x22, 0x53, 0x0a, 0x1d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x15, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x13, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x42, 0x41, 0x5a, 0x3f, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, + 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, + 0x73, 0x3b, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/resource-aggregate/cqrs/aggregate/aggregate.go b/resource-aggregate/cqrs/aggregate/aggregate.go index d7aabadcb..bec81ca0f 100644 --- a/resource-aggregate/cqrs/aggregate/aggregate.go +++ b/resource-aggregate/cqrs/aggregate/aggregate.go @@ -37,20 +37,26 @@ func NewDefaultRetryFunc(limit int) RetryFunc { } // FactoryModelFunc creates model for aggregate -type FactoryModelFunc = func(ctx context.Context) (AggregateModel, error) +type FactoryModelFunc = func(ctx context.Context, groupID, aggregateID string) (AggregateModel, error) // Aggregate holds data for Handle command type Aggregate struct { - groupID string - aggregateID string - store eventstore.EventStore - retryFunc RetryFunc - factoryModel FactoryModelFunc - LogDebugfFunc eventstore.LogDebugfFunc + groupID string + aggregateID string + store eventstore.EventStore + retryFunc RetryFunc + factoryModel FactoryModelFunc + LogDebugfFunc eventstore.LogDebugfFunc + additionalModels []AdditionalModel +} + +type AdditionalModel struct { + GroupID string + AggregateID string } // NewAggregate creates aggregate. it load and store events created from commands -func NewAggregate(groupID, aggregateID string, retryFunc RetryFunc, store eventstore.EventStore, factoryModel FactoryModelFunc, logDebugfFunc eventstore.LogDebugfFunc) (*Aggregate, error) { +func NewAggregate(groupID, aggregateID string, retryFunc RetryFunc, store eventstore.EventStore, factoryModel FactoryModelFunc, logDebugfFunc eventstore.LogDebugfFunc, additionalModels ...AdditionalModel) (*Aggregate, error) { if groupID == "" { return nil, errors.New("cannot create aggregate: invalid groupID") } @@ -65,12 +71,13 @@ func NewAggregate(groupID, aggregateID string, retryFunc RetryFunc, store events } return &Aggregate{ - groupID: groupID, - aggregateID: aggregateID, - store: store, - factoryModel: factoryModel, - retryFunc: retryFunc, - LogDebugfFunc: logDebugfFunc, + groupID: groupID, + aggregateID: aggregateID, + store: store, + factoryModel: factoryModel, + retryFunc: retryFunc, + LogDebugfFunc: logDebugfFunc, + additionalModels: additionalModels, }, nil } @@ -135,23 +142,50 @@ func HandleRetry(ctx context.Context, retryFunc RetryFunc) error { return nil } -func NewAggregateModel(ctx context.Context, groupID, aggregateID string, store eventstore.EventStore, logDebugfFunc eventstore.LogDebugfFunc, model AggregateModel) (*AggregateModelWrapper, error) { +func NewAggregateModel(ctx context.Context, groupID, aggregateID string, store eventstore.EventStore, logDebugfFunc eventstore.LogDebugfFunc, factoryModel FactoryModelFunc, additionalModels ...AdditionalModel) (*AggregateModelWrapper, error) { + models := make(map[string]AggregateModel, 1+len(additionalModels)) + model, err := factoryModel(ctx, groupID, aggregateID) + if err != nil { + return nil, fmt.Errorf("cannot create aggregate model: %w", err) + } + models[aggregateID] = model amodel := &AggregateModelWrapper{model: model} - ep := eventstore.NewProjection(store, func(_ context.Context, _, _ string) (eventstore.Model, error) { return amodel, nil }, logDebugfFunc) - err := ep.Project(ctx, []eventstore.SnapshotQuery{ - { - GroupID: groupID, - AggregateID: aggregateID, - }, + for _, r := range additionalModels { + model, err = factoryModel(ctx, r.GroupID, r.AggregateID) + if err != nil { + return nil, fmt.Errorf("cannot create aggregate model: %w", err) + } + models[r.AggregateID] = model + } + ep := eventstore.NewProjection(store, func(_ context.Context, _, projectionAggregateID string) (eventstore.Model, error) { + if projectionAggregateID == aggregateID { + return amodel, nil + } + if model, ok := models[projectionAggregateID]; ok { + return model, nil + } + return nil, fmt.Errorf("cannot create aggregate model for %v %v : not found", groupID, aggregateID) + }, logDebugfFunc) + q := make([]eventstore.SnapshotQuery, 0, 1+len(additionalModels)) + q = append(q, eventstore.SnapshotQuery{ + GroupID: groupID, + AggregateID: aggregateID, }) + for _, r := range additionalModels { + q = append(q, eventstore.SnapshotQuery{ + GroupID: r.GroupID, + AggregateID: r.AggregateID, + }) + } + err = ep.Project(ctx, q) if err != nil { return nil, fmt.Errorf("cannot load aggregate model: %w", err) } return amodel, nil } -func (a *Aggregate) FactoryModel(ctx context.Context) (AggregateModel, error) { - return a.factoryModel(ctx) +func (a *Aggregate) FactoryModel(ctx context.Context, groupID, aggregateID string) (AggregateModel, error) { + return a.factoryModel(ctx, groupID, aggregateID) } func (a *Aggregate) HandleCommandWithAggregateModelWrapper(ctx context.Context, cmd Command, amodel *AggregateModelWrapper) (events []eventstore.Event, concurrencyExcpetion bool, err error) { @@ -206,12 +240,7 @@ func (a *Aggregate) HandleCommand(ctx context.Context, cmd Command) ([]eventstor } firstIteration = false - model, err := a.factoryModel(ctx) - if err != nil { - return nil, errHandleCommand(err) - } - - amodel, err := NewAggregateModel(ctx, a.groupID, a.aggregateID, a.store, a.LogDebugfFunc, model) + amodel, err := NewAggregateModel(ctx, a.groupID, a.aggregateID, a.store, a.LogDebugfFunc, a.factoryModel, a.additionalModels...) if err != nil { return nil, errHandleCommand(err) } diff --git a/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go b/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go index 73cd5a789..0189f7496 100644 --- a/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go +++ b/resource-aggregate/cqrs/aggregate/aggregateParallel_test.go @@ -83,8 +83,8 @@ func TestParallelRequest(t *testing.T) { href := "/test/resource/1" newAggregate := func(deviceID, href string) *aggregate.Aggregate { - a, err := aggregate.NewAggregate(deviceID, commands.NewResourceID(deviceID, href).ToUUID().String(), aggregate.NewDefaultRetryFunc(128), store, func(context.Context) (aggregate.AggregateModel, error) { - ev := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") + a, err := aggregate.NewAggregate(deviceID, commands.NewResourceID(deviceID, href).ToUUID().String(), aggregate.NewDefaultRetryFunc(128), store, func(context.Context, string, string) (aggregate.AggregateModel, error) { + ev := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID", nil) ev.ResourceId = commands.NewResourceID(deviceID, href) return ev, nil }, nil) diff --git a/resource-aggregate/cqrs/aggregate/aggregate_test.go b/resource-aggregate/cqrs/aggregate/aggregate_test.go index 4b5a8a092..aed8ee43c 100644 --- a/resource-aggregate/cqrs/aggregate/aggregate_test.go +++ b/resource-aggregate/cqrs/aggregate/aggregate_test.go @@ -75,7 +75,7 @@ func TestAggregate(t *testing.T) { } newAggregate := func(deviceID, href string) *aggregate.Aggregate { - a, err := aggregate.NewAggregate(deviceID, commands.NewResourceID(deviceID, href).ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { + a, err := aggregate.NewAggregate(deviceID, commands.NewResourceID(deviceID, href).ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context, string, string) (aggregate.AggregateModel, error) { return &raTest.Snapshot{DeviceId: deviceID, Href: href, IsPublished: true}, nil }, nil) require.NoError(t, err) @@ -134,10 +134,8 @@ func TestAggregate(t *testing.T) { require.NoError(t, err) concurrencyExcepTestA := newAggregate(commandPub1.GetDeviceId(), commandPub1.GetHref()) - model, err := concurrencyExcepTestA.FactoryModel(ctx) - require.NoError(t, err) - amodel, err := aggregate.NewAggregateModel(ctx, a.GroupID(), a.AggregateID(), store, a.LogDebugfFunc, model) + amodel, err := aggregate.NewAggregateModel(ctx, a.GroupID(), a.AggregateID(), store, a.LogDebugfFunc, concurrencyExcepTestA.FactoryModel) require.NoError(t, err) ev, concurrencyException, err := a.HandleCommandWithAggregateModelWrapper(ctx, &commandPub1, amodel) diff --git a/resource-aggregate/cqrs/aggregate/test/aggregate.go b/resource-aggregate/cqrs/aggregate/test/aggregate.go index 16fd1834f..7c1078d12 100644 --- a/resource-aggregate/cqrs/aggregate/test/aggregate.go +++ b/resource-aggregate/cqrs/aggregate/test/aggregate.go @@ -25,6 +25,7 @@ func (e *Published) IsSnapshot() bool { return false } func (e *Published) Timestamp() time.Time { return time.Unix(0, e.GetEventTimestamp()) } func (e *Published) ETag() *eventstore.ETagData { return nil } func (e *Published) ServiceID() (string, bool) { return "", false } +func (e *Published) Types() []string { return nil } func (e *Unpublished) Version() uint64 { return e.GetEventVersion() } func (e *Unpublished) EventType() string { return "unpublished" } @@ -38,6 +39,7 @@ func (e *Unpublished) IsSnapshot() bool { return false } func (e *Unpublished) Timestamp() time.Time { return time.Unix(0, e.GetEventTimestamp()) } func (e *Unpublished) ETag() *eventstore.ETagData { return nil } func (e *Unpublished) ServiceID() (string, bool) { return "", false } +func (e *Unpublished) Types() []string { return nil } func (e *Snapshot) Version() uint64 { return e.GetEventVersion() } func (e *Snapshot) EventType() string { return "snapshot" } @@ -52,6 +54,7 @@ func (e *Snapshot) IsSnapshot() bool { return true } func (e *Snapshot) Timestamp() time.Time { return time.Unix(0, e.GetEventTimestamp()) } func (e *Snapshot) ETag() *eventstore.ETagData { return nil } func (e *Snapshot) ServiceID() (string, bool) { return "", false } +func (e *Snapshot) Types() []string { return nil } func (e *Snapshot) handleEvent(eu eventstore.EventUnmarshaler) error { if eu.EventType() == "" { diff --git a/resource-aggregate/cqrs/eventbus/event.go b/resource-aggregate/cqrs/eventbus/event.go index b8af0c925..0c096f11b 100644 --- a/resource-aggregate/cqrs/eventbus/event.go +++ b/resource-aggregate/cqrs/eventbus/event.go @@ -17,6 +17,7 @@ type Event = interface { Timestamp() time.Time ETag() *eventstore.ETagData ServiceID() (string, bool) + Types() []string } // EventUnmarshaler provides event. diff --git a/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go b/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go index 162818451..8f95fca5c 100644 --- a/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go +++ b/resource-aggregate/cqrs/eventbus/nats/publisher/publisher_test.go @@ -132,6 +132,7 @@ type mockEvent struct { timestamp int64 Data string ETagI []byte + TypesI []string } func (e mockEvent) Version() uint64 { @@ -172,6 +173,10 @@ func (e mockEvent) ServiceID() (string, bool) { return "", false } +func (e mockEvent) Types() []string { + return e.TypesI +} + type mockEventHandler struct { newEvent chan mockEvent } diff --git a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go index bad00781b..c65db81d4 100644 --- a/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go +++ b/resource-aggregate/cqrs/eventbus/nats/subscriber/subscriber_test.go @@ -66,6 +66,7 @@ type mockEvent struct { timestamp int64 Data string ETagI []byte + TypesI []string } func (e mockEvent) Version() uint64 { @@ -106,6 +107,10 @@ func (e mockEvent) ServiceID() (string, bool) { return "", false } +func (e mockEvent) Types() []string { + return e.TypesI +} + type mockEventHandler struct { newEvent chan mockEvent } diff --git a/resource-aggregate/cqrs/eventstore/event.go b/resource-aggregate/cqrs/eventstore/event.go index 47e8d5789..10065bf49 100644 --- a/resource-aggregate/cqrs/eventstore/event.go +++ b/resource-aggregate/cqrs/eventstore/event.go @@ -24,6 +24,7 @@ type Event = interface { ServiceID() (string, bool) Timestamp() time.Time ETag() *ETagData + Types() []string } // EventUnmarshaler provides event. diff --git a/resource-aggregate/cqrs/eventstore/event_test.go b/resource-aggregate/cqrs/eventstore/event_test.go index 3d3ce3179..7b2c3348a 100644 --- a/resource-aggregate/cqrs/eventstore/event_test.go +++ b/resource-aggregate/cqrs/eventstore/event_test.go @@ -14,6 +14,7 @@ type mockEvent struct { etagData *ETagData isSnapshot bool serviceID string + types []string } func (e *mockEvent) AggregateID() string { @@ -51,6 +52,10 @@ func (e *mockEvent) IsSnapshot() bool { return e.isSnapshot } +func (e *mockEvent) Types() []string { + return e.types +} + func TestValidateEventsBeforeSave(t *testing.T) { ev := mockEvent{ aggregateID: "d9e7e4a0-49b7-4e6e-8f00-9ebefb3f6f5d", diff --git a/resource-aggregate/cqrs/eventstore/eventstore.go b/resource-aggregate/cqrs/eventstore/eventstore.go index 6925728de..c6f0a2e02 100644 --- a/resource-aggregate/cqrs/eventstore/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/eventstore.go @@ -14,15 +14,17 @@ type VersionQuery struct { // SnapshotQuery used to load events from snapshot. type SnapshotQuery struct { - GroupID string // filter by group ID - AggregateID string // filter to certain aggregateID, groupID is required + GroupID string // filter by group ID + AggregateID string // filter to certain aggregateID, groupID is required + Types []string // filter to certain event types, optional } // Get events with given attributes. // All filtering options are optional, if none are given then all events are returned, type GetEventsQuery struct { - GroupID string // filter by group ID, optional - AggregateID string // filter to certain aggregateID, optional + GroupID string // filter by group ID, optional + AggregateID string // filter to certain aggregateID, optional + Types []string // filter to certain event types, optional } // Delete documents with given group id diff --git a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go index e76aef4e4..15a0aa328 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/acceptance_testing_events_test.go @@ -422,15 +422,16 @@ func MakeDeviceMetadata(deviceID string, deviceMetadataUpdated *events.DeviceMet } type MockEvent struct { - VersionI uint64 `bson:"version"` - EventTypeI string `bson:"eventtype"` - IsSnapshotI bool `bson:"issnapshot"` - AggregateIDI string `bson:"aggregateid"` - GroupIDI string `bson:"groupid"` - DataI []byte `bson:"data"` - TimestampI int64 `bson:"timestamp"` - ETagI []byte `bson:"etag"` - ServiceIDI string `bson:"serviceid"` + VersionI uint64 `bson:"version"` + EventTypeI string `bson:"eventtype"` + IsSnapshotI bool `bson:"issnapshot"` + AggregateIDI string `bson:"aggregateid"` + GroupIDI string `bson:"groupid"` + DataI []byte `bson:"data"` + TimestampI int64 `bson:"timestamp"` + ETagI []byte `bson:"etag"` + ServiceIDI string `bson:"serviceid"` + ResourceTypesI []string `bson:"resourcetypes"` } func (e MockEvent) Version() uint64 { @@ -471,6 +472,10 @@ func (e MockEvent) ServiceID() (string, bool) { return e.ServiceIDI, true } +func (e MockEvent) Types() []string { + return e.ResourceTypesI +} + type MockEventHandler struct { lock sync.Mutex events map[string]map[string][]eventstore.Event @@ -480,6 +485,14 @@ func NewMockEventHandler() *MockEventHandler { return &MockEventHandler{events: make(map[string]map[string][]eventstore.Event)} } +func (eh *MockEventHandler) PopEvents() map[string]map[string][]eventstore.Event { + eh.lock.Lock() + defer eh.lock.Unlock() + events := eh.events + eh.events = make(map[string]map[string][]eventstore.Event) + return events +} + func (eh *MockEventHandler) SetElement(groupID, aggregateID string, e MockEvent) { var device map[string][]eventstore.Event var ok bool diff --git a/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go b/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go index 32823d387..7d84b0c52 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/eventstore.go @@ -49,6 +49,7 @@ const ( isActiveKey = "isactive" latestETagKey = "latestetag" etagKey = "etag" + typesKey = "types" latestETagKeyTimestampKey = latestETagKey + "." + timestampKey serviceIDKey = "serviceid" ) @@ -94,6 +95,12 @@ var groupIDETagLatestTimestampQueryIndex = bson.D{ {Key: latestETagKeyTimestampKey, Value: -1}, } +var groupIDTypesQueryIndex = bson.D{ + {Key: groupIDKey, Value: 1}, + {Key: typesKey, Value: 1}, + {Key: isActiveKey, Value: 1}, +} + type signOperator string const ( @@ -206,6 +213,7 @@ func newEventStoreWithClient(ctx context.Context, store *pkgMongo.Store, dbPrefi aggregateIDLatestTimestampQueryIndex, groupIDETagLatestTimestampQueryIndex, serviceIDQueryIndex, + groupIDTypesQueryIndex, ) if err != nil { return nil, fmt.Errorf("cannot save events: %w", err) @@ -290,7 +298,7 @@ func tryToSetServiceID(doc bson.M, events []eventstore.Event) bson.M { } func makeDBDoc(events []eventstore.Event, marshaler MarshalerFunc) (bson.M, error) { - etag, e, err := makeDBEventsAndGetETag(events, marshaler) + etag, types, e, err := makeDBEventsAndGetETag(events, marshaler) if err != nil { return nil, fmt.Errorf("cannot insert first events('%v'): %w", events, err) } @@ -313,6 +321,9 @@ func makeDBDoc(events []eventstore.Event, marshaler MarshalerFunc) (bson.M, erro if etag != nil { d[etagKey] = etag.ETag } + if len(types) > 0 { + d[typesKey] = types + } return tryToSetServiceID(d, events), nil } @@ -354,14 +365,15 @@ func (s *EventStore) Close(ctx context.Context) error { } // newDBEvent returns a new dbEvent for an eventstore. -func makeDBEventsAndGetETag(events []eventstore.Event, marshaler MarshalerFunc) (*eventstore.ETagData, []bson.M, error) { +func makeDBEventsAndGetETag(events []eventstore.Event, marshaler MarshalerFunc) (*eventstore.ETagData, []string, []bson.M, error) { dbEvents := make([]bson.M, 0, len(events)) var etag *eventstore.ETagData + var types []string for idx, event := range events { // Marshal event data if there is any. raw, err := marshaler(event) if err != nil { - return nil, nil, fmt.Errorf("cannot create db event from event[%v]: %w", idx, err) + return nil, nil, nil, fmt.Errorf("cannot create db event from event[%v]: %w", idx, err) } dbEvents = append(dbEvents, bson.M{ versionKey: event.Version(), @@ -374,6 +386,9 @@ func makeDBEventsAndGetETag(events []eventstore.Event, marshaler MarshalerFunc) if et != nil { etag = et } + if len(event.Types()) > 0 { + types = event.Types() + } } - return etag, dbEvents, nil + return etag, types, dbEvents, nil } diff --git a/resource-aggregate/cqrs/eventstore/mongodb/getevents.go b/resource-aggregate/cqrs/eventstore/mongodb/getevents.go index 1eadae300..f9a77bd4b 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/getevents.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/getevents.go @@ -107,7 +107,7 @@ func getEventsQueriesToMongoQuery(groupID string, queries []eventstore.GetEvents func (s *EventStore) getEvents(ctx context.Context, groupID string, queries []eventstore.GetEventsQuery, timestamp int64, eventHandler eventstore.Handler) error { filter, opts := getEventsQueriesToMongoQuery(groupID, queries, timestamp) - return s.loadEventsQuery(ctx, eventHandler, nil, filter, opts) + return s.loadEventsQuery(ctx, eventHandler, nil, []mongoQuery{{filter: filter, options: opts}}) } type ResourceIdFilter struct { diff --git a/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go b/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go index ba9d3f940..3d093163b 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/getevents_test.go @@ -55,6 +55,10 @@ func getETag(deviceIndex int, resourceIndex int) []byte { return []byte("device" + strconv.Itoa(deviceIndex) + ".resource" + strconv.Itoa(resourceIndex)) } +func getTypes(resourceIndex int) []string { + return []string{"type" + strconv.Itoa(resourceIndex%3), "type" + strconv.Itoa((resourceIndex%3)+3)} +} + func getNLatestETag(deviceIndex int, limit int) [][]byte { if limit == 0 { limit = getEventsResourceCount / getEventsDeviceCount @@ -88,6 +92,7 @@ func addEventsForGetEventsToDB(ctx context.Context, t *testing.T, store *mongodb TimestampI: 1 + resourceTimestamp[resourceIndex], ETagI: getETag(deviceIndex, resourceIndex), ServiceIDI: getServiceID(serviceIndex), + TypesI: getTypes(resourceIndex), }) resourceVersion[resourceIndex]++ diff --git a/resource-aggregate/cqrs/eventstore/mongodb/load.go b/resource-aggregate/cqrs/eventstore/mongodb/load.go index 2ec7428f7..3826c16b2 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/load.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/load.go @@ -199,22 +199,29 @@ func (r *queryResolver) check(aggregateID string, version int64) bool { } // Create mongodb find query to load events -func (s *EventStore) loadEventsQuery(ctx context.Context, eh eventstore.Handler, queryResolver *queryResolver, filter interface{}, opts ...*options.FindOptions) error { +func (s *EventStore) loadEventsQuery(ctx context.Context, eh eventstore.Handler, queryResolver *queryResolver, queries []mongoQuery) error { col := s.client().Database(s.DBName()).Collection(getEventCollectionName()) - iter, err := col.Find(ctx, filter, opts...) - if errors.Is(err, mongo.ErrNilDocument) { - return nil - } - if err != nil { - return err - } - i := newIterator(iter, queryResolver, s.dataUnmarshaler, s.LogDebugfFunc) - err = eh.Handle(ctx, i) - errClose := iter.Close(ctx) - if err == nil { - return errClose + var errs *multierror.Error + for _, q := range queries { + iter, err := col.Find(ctx, q.filter, q.options) + if errors.Is(err, mongo.ErrNilDocument) { + continue + } + if err != nil { + errs = multierror.Append(errs, err) + continue + } + i := newIterator(iter, queryResolver, s.dataUnmarshaler, s.LogDebugfFunc) + err = eh.Handle(ctx, i) + if err != nil { + errs = multierror.Append(errs, err) + } + err = iter.Close(ctx) + if err != nil { + errs = multierror.Append(errs, err) + } } - return err + return errs.ErrorOrNil() } func (r *queryResolver) toMongoQuery(maxVersionKey string) (filter bson.M, hint bson.D) { @@ -288,10 +295,15 @@ func (s *EventStore) loadMongoQuery(ctx context.Context, eh eventstore.Handler, filter, hint := queryResolver.toMongoQuery(maxVersionKey) opts := options.Find() opts.SetHint(hint) - return s.loadEventsQuery(ctx, eh, queryResolver, filter, opts) + return s.loadEventsQuery(ctx, eh, queryResolver, []mongoQuery{{filter: filter, options: opts}}) +} + +type mongoQuery struct { + filter interface{} + options *options.FindOptions } -func snapshotQueriesToMongoQuery(groupID string, queries []eventstore.SnapshotQuery) (interface{}, *options.FindOptions) { +func snapshotQueriesToMongoQuery(groupID string, queries []eventstore.SnapshotQuery) []mongoQuery { opts := options.Find() opts.SetAllowDiskUse(true) opts.SetProjection(bson.M{ @@ -309,26 +321,169 @@ func snapshotQueriesToMongoQuery(groupID string, queries []eventstore.SnapshotQu }) if len(queries) == 0 { opts.SetHint(groupIDQueryIndex) - return bson.D{ - {Key: groupIDKey, Value: groupID}, {Key: isActiveKey, Value: true}, - }, opts + return []mongoQuery{ + { + filter: bson.D{ + {Key: groupIDKey, Value: groupID}, {Key: isActiveKey, Value: true}, + }, + options: opts, + }, + } } - opts.SetHint(groupIDaggregateIDQueryIndex) - orQueries := make([]bson.D, 0, 32) + optsTypes := options.Find() + // create a copy of the options + *optsTypes = *opts + resourceQueries := make([]bson.D, 0, 32) + typeQueries := make([]bson.D, 0, 32) for _, q := range queries { + if q.AggregateID == "" && len(q.Types) == 0 { + opts.SetHint(groupIDQueryIndex) + return []mongoQuery{ + { + filter: bson.D{ + {Key: groupIDKey, Value: groupID}, {Key: isActiveKey, Value: true}, + }, + options: opts, + }, + } + } + if q.AggregateID == "" && len(q.Types) > 0 { + optsTypes.SetHint(groupIDTypesQueryIndex) + typeQueries = append(typeQueries, bson.D{{Key: groupIDKey, Value: groupID}, {Key: typesKey, Value: bson.M{"$all": q.Types}}, {Key: isActiveKey, Value: true}}) + continue + } + if q.AggregateID != "" { - orQueries = append(orQueries, bson.D{{Key: groupIDKey, Value: groupID}, {Key: aggregateIDKey, Value: q.AggregateID}, {Key: isActiveKey, Value: true}}) + opts.SetHint(groupIDaggregateIDQueryIndex) + resourceQueries = append(resourceQueries, bson.D{{Key: groupIDKey, Value: groupID}, {Key: aggregateIDKey, Value: q.AggregateID}, {Key: isActiveKey, Value: true}}) } } - return bson.M{ - "$or": orQueries, - }, opts + + r := make([]mongoQuery, 0, 2) + if len(resourceQueries) > 0 { + r = append(r, mongoQuery{ + filter: bson.M{"$or": resourceQueries}, + options: opts, + }) + } + if len(typeQueries) > 0 { + r = append(r, mongoQuery{ + filter: bson.M{"$or": typeQueries}, + options: optsTypes, + }) + } + return r } func (s *EventStore) loadFromSnapshot(ctx context.Context, groupID string, queries []eventstore.SnapshotQuery, eventHandler eventstore.Handler) error { - filter, opts := snapshotQueriesToMongoQuery(groupID, queries) - return s.loadEventsQuery(ctx, eventHandler, nil, filter, opts) + mongoQueries := snapshotQueriesToMongoQuery(groupID, queries) + if len(mongoQueries) > 1 { + return errors.New("too many types of queries") + } + return s.loadEventsQuery(ctx, eventHandler, nil, mongoQueries) +} + +func resourceTypesIsSubset(slice, subset []string) bool { + if len(slice) == 0 { + return false + } + if len(slice) > len(subset) { + return false + } + set := make(map[string]struct{}, len(slice)) + for _, s := range slice { + set[s] = struct{}{} + } + for _, s := range subset { + delete(set, s) + if len(set) == 0 { + return true + } + } + return false +} + +func uniqueQueryWithEmptyAggregateID(queries []eventstore.SnapshotQuery, query eventstore.SnapshotQuery) []eventstore.SnapshotQuery { + if len(query.Types) == 0 { + // get all events without filter + return []eventstore.SnapshotQuery{query} + } + for idx, q := range queries { + if resourceTypesIsSubset(query.Types, q.Types) { + // get all events with the certain type, replace the queries with the more or equal general one + queries[idx] = query + queries = removeDuplicates(queries, idx, func(qa eventstore.SnapshotQuery) bool { return resourceTypesIsSubset(query.Types, qa.Types) }) + return queries + } + } + return append(queries, query) +} + +func uniqueQueryHandleAtIndex(queries []eventstore.SnapshotQuery, query eventstore.SnapshotQuery, idx int) ([]eventstore.SnapshotQuery, bool) { + q := queries[idx] + if q.AggregateID == "" && len(q.Types) == 0 || resourceTypesIsSubset(q.Types, query.Types) { + return queries, true // No need to add more specific one if there's a general query + } + + if q.AggregateID == query.AggregateID { + if len(query.Types) == 0 { + queries[idx] = query + queries = removeDuplicates(queries, idx, func(qa eventstore.SnapshotQuery) bool { return qa.AggregateID == query.AggregateID }) + return queries, true + } + if len(q.Types) == 0 || resourceTypesIsSubset(q.Types, query.Types) { + return queries, true // No need to add more general one if there's a more specific query + } + if resourceTypesIsSubset(query.Types, q.Types) { + // replace query with the more general one + queries[idx] = query + queries = removeDuplicates(queries, idx, func(qa eventstore.SnapshotQuery) bool { return resourceTypesIsSubset(qa.Types, query.Types) }) + return queries, true + } + } + return queries, false +} + +func uniqueQuery(queries []eventstore.SnapshotQuery, query eventstore.SnapshotQuery) []eventstore.SnapshotQuery { + if query.AggregateID == "" { + return uniqueQueryWithEmptyAggregateID(queries, query) + } + + for idx := range queries { + newQueries, handled := uniqueQueryHandleAtIndex(queries, query, idx) + if handled { + return newQueries + } + } + + return append(queries, query) +} + +func removeDuplicates(queries []eventstore.SnapshotQuery, startIdx int, remove func(q eventstore.SnapshotQuery) bool) []eventstore.SnapshotQuery { + for i := startIdx + 1; i < len(queries); i++ { + if remove(queries[i]) { + queries = append(queries[:i], queries[i+1:]...) + i-- + } + } + return queries +} + +func normalizeSnapshotQuery(queries []eventstore.SnapshotQuery) map[string][]eventstore.SnapshotQuery { + normalizedQuery := make(map[string][]eventstore.SnapshotQuery, len(queries)) + // split queries by groupID + for _, query := range queries { + if query.GroupID == "" { + continue + } + v, ok := normalizedQuery[query.GroupID] + if !ok { + v = make([]eventstore.SnapshotQuery, 0, 4) + } + normalizedQuery[query.GroupID] = uniqueQuery(v, query) + } + return normalizedQuery } // LoadFromSnapshot loads events from the last snapshot eventstore. @@ -342,24 +497,7 @@ func (s *EventStore) LoadFromSnapshot(ctx context.Context, queries []eventstore. return errors.New("not supported") } - normalizeQuery := make(map[string][]eventstore.SnapshotQuery) - for _, query := range queries { - if query.GroupID == "" { - continue - } - if query.AggregateID == "" { - normalizeQuery[query.GroupID] = make([]eventstore.SnapshotQuery, 0, 1) - continue - } - v, ok := normalizeQuery[query.GroupID] - if !ok { - v = make([]eventstore.SnapshotQuery, 0, 4) - } else if len(v) == 0 { - continue - } - v = append(v, query) - normalizeQuery[query.GroupID] = v - } + normalizeQuery := normalizeSnapshotQuery(queries) var errors *multierror.Error for groupID, queries := range normalizeQuery { diff --git a/resource-aggregate/cqrs/eventstore/mongodb/load_internal_test.go b/resource-aggregate/cqrs/eventstore/mongodb/load_internal_test.go new file mode 100644 index 000000000..e91bf1ece --- /dev/null +++ b/resource-aggregate/cqrs/eventstore/mongodb/load_internal_test.go @@ -0,0 +1,163 @@ +package mongodb + +import ( + "testing" + + "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" + "github.com/stretchr/testify/require" +) + +func TestUniqueQuery(t *testing.T) { + type args struct { + queries []eventstore.SnapshotQuery + query eventstore.SnapshotQuery + } + test := []struct { + name string + args args + want []eventstore.SnapshotQuery + }{ + { + name: "first query", + args: args{ + queries: nil, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + }, + { + name: "same query", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + }, + { + name: "two queries", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + query: eventstore.SnapshotQuery{Types: []string{"type2"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + {Types: []string{"type2"}}, + }, + }, + { + name: "most general query", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + query: eventstore.SnapshotQuery{}, + }, + want: []eventstore.SnapshotQuery{ + {}, + }, + }, + { + name: "replace a query with more general query", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + {AggregateID: "1", Types: []string{"type2"}}, + {AggregateID: "2", Types: []string{"type2"}}, + }, + query: eventstore.SnapshotQuery{Types: []string{"type2"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + {Types: []string{"type2"}}, + }, + }, + { + name: "replace more queries with more general query with the aggregateID", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + {AggregateID: "1", Types: []string{"type2"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1"}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1"}, + }, + }, + { + name: "replace a query with more general query with the aggregateID", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type2", "type1"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + }, + { + name: "use general query instead of more specific query with the aggregateID", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1", "type2"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1"}}, + }, + }, + { + name: "use general query instead of more specific query with multiple type and the aggregateID ", + args: args{ + queries: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1", "type2", "type3"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1", "type3"}}, + }, + want: []eventstore.SnapshotQuery{ + {AggregateID: "1", Types: []string{"type1", "type3"}}, + }, + }, + { + name: "use general query instead of more specific query", + args: args{ + queries: []eventstore.SnapshotQuery{ + {Types: []string{"type1"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1", "type2"}}, + }, + want: []eventstore.SnapshotQuery{ + {Types: []string{"type1"}}, + }, + }, + { + name: "general and specific query with types", + args: args{ + queries: []eventstore.SnapshotQuery{ + {Types: []string{"type2", "type1"}}, + }, + query: eventstore.SnapshotQuery{AggregateID: "1", Types: []string{"type1"}}, + }, + want: []eventstore.SnapshotQuery{ + {Types: []string{"type2", "type1"}}, + {AggregateID: "1", Types: []string{"type1"}}, + }, + }, + } + for _, tt := range test { + t.Run(tt.name, func(t *testing.T) { + got := uniqueQuery(tt.args.queries, tt.args.query) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/resource-aggregate/cqrs/eventstore/mongodb/load_test.go b/resource-aggregate/cqrs/eventstore/mongodb/load_test.go new file mode 100644 index 000000000..3f6c376f5 --- /dev/null +++ b/resource-aggregate/cqrs/eventstore/mongodb/load_test.go @@ -0,0 +1,126 @@ +package mongodb_test + +import ( + "context" + "testing" + + "github.com/plgd-dev/hub/v2/pkg/fsnotify" + "github.com/plgd-dev/hub/v2/pkg/log" + "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" + "github.com/stretchr/testify/require" +) + +func TestLoadFromSnapshot(t *testing.T) { + type args struct { + queries []eventstore.SnapshotQuery + } + type device struct { + ID string + NumResources int + } + tests := []struct { + name string + args args + want []device + wantErr bool + }{ + { + name: "All group events", + args: args{ + queries: []eventstore.SnapshotQuery{ + { + GroupID: getDeviceID(0), + }, + }, + }, + want: []device{ + { + ID: getDeviceID(0), + NumResources: 20, + }, + }, + }, + { + name: "Group events with aggregateID", + args: args{ + queries: []eventstore.SnapshotQuery{ + { + GroupID: getDeviceID(0), + AggregateID: getAggregateID(0), + }, + }, + }, + want: []device{ + { + ID: getDeviceID(0), + NumResources: 1, + }, + }, + }, + { + name: "Group events with type filter", + args: args{ + queries: []eventstore.SnapshotQuery{ + { + GroupID: getDeviceID(0), + Types: getTypes(0), + }, + { + GroupID: getDeviceID(1), + Types: getTypes(3)[0:1], + }, + }, + }, + want: []device{ + { + ID: getDeviceID(0), + NumResources: 7, + }, + { + ID: getDeviceID(1), + NumResources: 6, + }, + }, + }, + } + logger := log.NewLogger(log.MakeDefaultConfig()) + fileWatcher, err := fsnotify.NewWatcher(logger) + require.NoError(t, err) + defer func() { + errC := fileWatcher.Close() + require.NoError(t, errC) + }() + + ctx := context.Background() + store, err := NewTestEventStore(ctx, fileWatcher, logger) + require.NoError(t, err) + require.NotNil(t, store) + defer func() { + t.Log("clearing db") + err = store.Clear(ctx) + require.NoError(t, err) + err := store.Close(ctx) + require.NoError(t, err) + }() + + _ = addEventsForGetEventsToDB(ctx, t, store) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + h := NewMockEventHandler() + err := store.LoadFromSnapshot(ctx, tt.args.queries, h) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + events := h.PopEvents() + require.Len(t, events, len(tt.want)) + for _, want := range tt.want { + ags, ok := events[want.ID] + require.True(t, ok) + require.Len(t, ags, want.NumResources) + } + }) + } +} diff --git a/resource-aggregate/cqrs/eventstore/mongodb/save.go b/resource-aggregate/cqrs/eventstore/mongodb/save.go index 2e3978574..a95f1f192 100644 --- a/resource-aggregate/cqrs/eventstore/mongodb/save.go +++ b/resource-aggregate/cqrs/eventstore/mongodb/save.go @@ -39,7 +39,7 @@ func IsDup(err error) bool { } func (s *EventStore) saveEvent(ctx context.Context, col *mongo.Collection, events []eventstore.Event) (status eventstore.SaveStatus, err error) { - etag, e, err := makeDBEventsAndGetETag(events, s.dataMarshaler) + etag, types, e, err := makeDBEventsAndGetETag(events, s.dataMarshaler) if err != nil { return eventstore.Fail, err } @@ -57,6 +57,9 @@ func (s *EventStore) saveEvent(ctx context.Context, col *mongo.Collection, event updateSet[latestETagKey] = makeDBETag(etag) } tryToSetServiceID(updateSet, events) + if len(types) > 0 { + updateSet[typesKey] = types + } // find document of aggregate with previous version // latestVersion shall be lower by 1 as new event otherwise other event was stored (occ). diff --git a/resource-aggregate/cqrs/eventstore/test/events.go b/resource-aggregate/cqrs/eventstore/test/events.go index 086c4d48d..95747c70d 100644 --- a/resource-aggregate/cqrs/eventstore/test/events.go +++ b/resource-aggregate/cqrs/eventstore/test/events.go @@ -100,24 +100,23 @@ func MakeAuditContext(userID string, correlationID string) *commands.AuditContex } } -func MakeResourceUpdatePending(resourceID *commands.ResourceId, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time) eventstore.EventUnmarshaler { - e := events.ResourceUpdatePending{ - ResourceId: resourceID, - Content: content, - AuditContext: auditContext, - EventMetadata: eventMetadata, - ValidUntil: pkgTime.UnixNano(validUntil), - } +func newResourceEvent[T interface { + GetResourceId() *commands.ResourceId + EventType() string + CopyData(e T) + GetEventMetadata() *events.EventMetadata + IsSnapshot() bool +}](e T) eventstore.EventUnmarshaler { return eventstore.NewLoadedEvent( e.GetEventMetadata().GetVersion(), - (&events.ResourceUpdatePending{}).EventType(), + e.EventType(), e.GetResourceId().ToUUID().String(), e.GetResourceId().GetDeviceId(), - false, + e.IsSnapshot(), time.Unix(0, e.GetEventMetadata().GetTimestamp()), func(v interface{}) error { - if x, ok := v.(*events.ResourceUpdatePending); ok { - x.CopyData(&e) + if x, ok := v.(T); ok { + x.CopyData(e) return nil } return errCannotUnmarshalEvent @@ -125,226 +124,121 @@ func MakeResourceUpdatePending(resourceID *commands.ResourceId, content *command ) } -func MakeResourceUpdated(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext) eventstore.EventUnmarshaler { +func MakeResourceUpdatePending(resourceID *commands.ResourceId, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time, resourceTypes []string) eventstore.EventUnmarshaler { + e := events.ResourceUpdatePending{ + ResourceId: resourceID, + Content: content, + AuditContext: auditContext, + EventMetadata: eventMetadata, + ValidUntil: pkgTime.UnixNano(validUntil), + ResourceTypes: resourceTypes, + } + return newResourceEvent(&e) +} + +func MakeResourceUpdated(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceUpdated{ ResourceId: resourceID, Content: content, Status: status, AuditContext: auditContext, EventMetadata: eventMetadata, + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceUpdated{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceUpdated); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceCreatePending(resourceID *commands.ResourceId, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time) eventstore.EventUnmarshaler { +func MakeResourceCreatePending(resourceID *commands.ResourceId, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceCreatePending{ ResourceId: resourceID, Content: content, AuditContext: auditContext, EventMetadata: eventMetadata, ValidUntil: pkgTime.UnixNano(validUntil), + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceCreatePending{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceCreatePending); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceCreated(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext) eventstore.EventUnmarshaler { +func MakeResourceCreated(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceCreated{ ResourceId: resourceID, Content: content, Status: status, AuditContext: auditContext, EventMetadata: eventMetadata, + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceCreated{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceCreated); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceChangedEvent(resourceID *commands.ResourceId, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext) eventstore.EventUnmarshaler { +func MakeResourceChangedEvent(resourceID *commands.ResourceId, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceChanged{ ResourceId: resourceID, AuditContext: auditContext, Content: content, EventMetadata: eventMetadata, + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceChanged{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceChanged); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceRetrievePending(resourceID *commands.ResourceId, resourceInterface string, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time) eventstore.EventUnmarshaler { +func MakeResourceRetrievePending(resourceID *commands.ResourceId, resourceInterface string, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceRetrievePending{ ResourceId: resourceID, ResourceInterface: resourceInterface, AuditContext: auditContext, EventMetadata: eventMetadata, ValidUntil: pkgTime.UnixNano(validUntil), + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceRetrievePending{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceRetrievePending); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceRetrieved(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext) eventstore.EventUnmarshaler { +func MakeResourceRetrieved(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceRetrieved{ ResourceId: resourceID, Content: content, Status: status, AuditContext: auditContext, EventMetadata: eventMetadata, + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceRetrieved{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceRetrieved); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceDeletePending(resourceID *commands.ResourceId, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time) eventstore.EventUnmarshaler { +func MakeResourceDeletePending(resourceID *commands.ResourceId, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceDeletePending{ ResourceId: resourceID, AuditContext: auditContext, EventMetadata: eventMetadata, ValidUntil: pkgTime.UnixNano(validUntil), + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceDeletePending{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceDeletePending); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceDeleted(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext) eventstore.EventUnmarshaler { +func MakeResourceDeleted(resourceID *commands.ResourceId, status commands.Status, content *commands.Content, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, resourceTypes []string) eventstore.EventUnmarshaler { e := events.ResourceDeleted{ ResourceId: resourceID, Content: content, Status: status, AuditContext: auditContext, EventMetadata: eventMetadata, + ResourceTypes: resourceTypes, } - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceDeleted{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - false, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceDeleted); ok { - x.CopyData(&e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(&e) } -func MakeResourceStateSnapshotTaken(resourceID *commands.ResourceId, latestResourceChange *events.ResourceChanged, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext) eventstore.EventUnmarshaler { +func MakeResourceStateSnapshotTaken(resourceID *commands.ResourceId, latestResourceChange *events.ResourceChanged, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, resourceTypes []string) eventstore.EventUnmarshaler { e := events.NewResourceStateSnapshotTaken() e.ResourceId = resourceID e.LatestResourceChange = latestResourceChange e.EventMetadata = eventMetadata e.AuditContext = auditContext + e.ResourceTypes = resourceTypes - return eventstore.NewLoadedEvent( - e.GetEventMetadata().GetVersion(), - (&events.ResourceStateSnapshotTaken{}).EventType(), - e.GetResourceId().ToUUID().String(), - e.GetResourceId().GetDeviceId(), - true, - time.Unix(0, e.GetEventMetadata().GetTimestamp()), - func(v interface{}) error { - if x, ok := v.(*events.ResourceStateSnapshotTaken); ok { - x.CopyData(e) - return nil - } - return errCannotUnmarshalEvent - }, - ) + return newResourceEvent(e) } func MakeDeviceMetadataUpdatePending(deviceID string, twinEnabled *events.DeviceMetadataUpdatePending_TwinEnabled, eventMetadata *events.EventMetadata, auditContext *commands.AuditContext, validUntil time.Time) eventstore.EventUnmarshaler { @@ -422,15 +316,16 @@ func MakeDeviceMetadata(deviceID string, deviceMetadataUpdated *events.DeviceMet } type MockEvent struct { - VersionI uint64 `bson:"version"` - EventTypeI string `bson:"eventtype"` - IsSnapshotI bool `bson:"issnapshot"` - AggregateIDI string `bson:"aggregateid"` - GroupIDI string `bson:"groupid"` - DataI []byte `bson:"data"` - TimestampI int64 `bson:"timestamp"` - ETagI []byte `bson:"etag"` - ServiceIDI string `bson:"serviceid"` + VersionI uint64 `bson:"version"` + EventTypeI string `bson:"eventtype"` + IsSnapshotI bool `bson:"issnapshot"` + AggregateIDI string `bson:"aggregateid"` + GroupIDI string `bson:"groupid"` + DataI []byte `bson:"data"` + TimestampI int64 `bson:"timestamp"` + ETagI []byte `bson:"etag"` + ServiceIDI string `bson:"serviceid"` + TypesI []string `bson:"resourcetypes"` } func (e MockEvent) Version() uint64 { @@ -471,6 +366,10 @@ func (e MockEvent) ServiceID() (string, bool) { return e.ServiceIDI, true } +func (e MockEvent) Types() []string { + return e.TypesI +} + type MockEventHandler struct { lock sync.Mutex events map[string]map[string][]eventstore.Event diff --git a/resource-aggregate/cqrs/projection/projectionInternal_test.go b/resource-aggregate/cqrs/projection/projectionInternal_test.go index bf537dd85..301ede29c 100644 --- a/resource-aggregate/cqrs/projection/projectionInternal_test.go +++ b/resource-aggregate/cqrs/projection/projectionInternal_test.go @@ -132,8 +132,8 @@ func TestProjection(t *testing.T) { CommandMetadata: &commands.CommandMetadata{}, } - a1, err := aggregate.NewAggregate(res1.GetDeviceId(), res1.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { - s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") + a1, err := aggregate.NewAggregate(res1.GetDeviceId(), res1.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context, string, string) (aggregate.AggregateModel, error) { + s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID", nil) s.ResourceId = &res1 return s, nil }, nil) @@ -143,8 +143,8 @@ func TestProjection(t *testing.T) { require.NoError(t, err) require.NotNil(t, evs) - a2, err := aggregate.NewAggregate(res2.GetDeviceId(), res2.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { - s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") + a2, err := aggregate.NewAggregate(res2.GetDeviceId(), res2.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context, string, string) (aggregate.AggregateModel, error) { + s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID", nil) s.ResourceId = &res2 return s, nil }, nil) @@ -186,8 +186,8 @@ func TestProjection(t *testing.T) { time.Sleep(waitForSubscription) - a3, err := aggregate.NewAggregate(res3.GetDeviceId(), res3.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context) (aggregate.AggregateModel, error) { - s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID") + a3, err := aggregate.NewAggregate(res3.GetDeviceId(), res3.ToUUID().String(), aggregate.NewDefaultRetryFunc(1), store, func(context.Context, string, string) (aggregate.AggregateModel, error) { + s := events.NewResourceStateSnapshotTakenForCommand("test", "test", "hubID", nil) s.ResourceId = &res3 return s, nil }, nil) diff --git a/resource-aggregate/cqrs/projection/projection_test.go b/resource-aggregate/cqrs/projection/projection_test.go index 12a308356..089b16191 100644 --- a/resource-aggregate/cqrs/projection/projection_test.go +++ b/resource-aggregate/cqrs/projection/projection_test.go @@ -22,68 +22,81 @@ var ( ) var d1res1 = commands.Resource{ - DeviceId: dev1, - Href: "/res1", + DeviceId: dev1, + Href: "/res1", + ResourceTypes: []string{"typeDev1Res"}, } var d1res2 = commands.Resource{ - DeviceId: dev1, - Href: "/res2", + DeviceId: dev1, + Href: "/res2", + ResourceTypes: []string{"typeDev1Res2"}, } var d1res3 = commands.Resource{ - DeviceId: dev1, - Href: "/res3", + DeviceId: dev1, + Href: "/res3", + ResourceTypes: []string{"typeDev1Res3"}, } var d1res4 = commands.Resource{ - DeviceId: dev1, - Href: "/res4", + DeviceId: dev1, + Href: "/res4", + ResourceTypes: []string{"typeDev1Res4"}, } var d1res5 = commands.Resource{ - DeviceId: dev1, - Href: "/res5", + DeviceId: dev1, + Href: "/res5", + ResourceTypes: []string{"typeDev1Res5"}, } var d2res1 = commands.Resource{ - DeviceId: dev2, - Href: "/res1", + DeviceId: dev2, + Href: "/res1", + ResourceTypes: []string{"typeDev2Res1"}, } var d2res2 = commands.Resource{ - DeviceId: dev2, - Href: "/res2", + DeviceId: dev2, + Href: "/res2", + ResourceTypes: []string{"typeDev2Res2"}, } var d3res1 = commands.Resource{ - DeviceId: "dev3", - Href: "/res1", + DeviceId: "dev3", + Href: "/res1", + ResourceTypes: []string{"typeDev3Res1"}, } var d3res2 = commands.Resource{ - DeviceId: "dev3", - Href: "/res2", + DeviceId: "dev3", + Href: "/res2", + ResourceTypes: []string{"typeDev3Res2"}, } var d4res1 = commands.Resource{ - DeviceId: "dev4", - Href: "/res1", + DeviceId: "dev4", + Href: "/res1", + ResourceTypes: []string{"typeDev4Res1"}, } var d4res2 = commands.Resource{ - DeviceId: "dev4", - Href: "/res2", + DeviceId: "dev4", + Href: "/res2", + ResourceTypes: []string{"typeDev4Res2"}, } var d5res1 = commands.Resource{ - DeviceId: "dev5", - Href: "/res1", + DeviceId: "dev5", + Href: "/res1", + ResourceTypes: []string{"typeDev5Res1"}, } var d5res2 = commands.Resource{ - DeviceId: "dev5", - Href: "/res2", + DeviceId: "dev5", + Href: "/res2", + ResourceTypes: []string{"typeDev5Res2"}, } func makeEventMeta(connectionID string, version uint64) *events.EventMetadata { @@ -130,37 +143,37 @@ func prepareResourceStateEventstore() *mockEvents.MockEventStore { resourceChangedEventMetadata := makeEventMeta("", 0) d1r1 := commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()) - eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{})) - eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"))) - eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"), time.Time{})) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata, ResourceTypes: d1res1.GetResourceTypes()}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"), d1res1.GetResourceTypes())) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{}, d1res1.GetResourceTypes())) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{}, d1res1.GetResourceTypes())) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"), d1res1.GetResourceTypes())) + eventstore.Append(d1res1.GetDeviceId(), d1r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r1, &commands.Content{}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"), time.Time{}, d1res1.GetResourceTypes())) d1r2 := commands.NewResourceID(d1res2.GetDeviceId(), d1res2.GetHref()) - eventstore.Append(d1res2.GetDeviceId(), d1r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) + eventstore.Append(d1res2.GetDeviceId(), d1r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata, ResourceTypes: d1res2.GetResourceTypes()}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"), d1res2.GetResourceTypes())) d1r3 := commands.NewResourceID(d1res3.GetDeviceId(), d1res3.GetHref()) - eventstore.Append(d1res3.GetDeviceId(), d1r3.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r3, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) - eventstore.Append(d1res3.GetDeviceId(), d1r3.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r3, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "3"), time.Time{})) + eventstore.Append(d1res3.GetDeviceId(), d1r3.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r3, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata, ResourceTypes: d1res3.GetResourceTypes()}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"), d1res3.GetResourceTypes())) + eventstore.Append(d1res3.GetDeviceId(), d1r3.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r3, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "3"), time.Time{}, d1res3.GetResourceTypes())) d1r4 := commands.NewResourceID(d1res4.GetDeviceId(), d1res4.GetHref()) - eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{})) - eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r4, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"))) - eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"))) - eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 5), mockEvents.MakeAuditContext("userId", "4"), time.Time{})) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata, ResourceTypes: d1res4.GetResourceTypes()}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"), d1res4.GetResourceTypes())) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{}, d1res4.GetResourceTypes())) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "2"), time.Time{}, d1res4.GetResourceTypes())) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdated(d1r4, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "1"), d1res4.GetResourceTypes())) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d1r4, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 4), mockEvents.MakeAuditContext("userId", "3"), d1res4.GetResourceTypes())) + eventstore.Append(d1res4.GetDeviceId(), d1r4.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d1r4, &commands.Content{}, makeEventMeta("a", 5), mockEvents.MakeAuditContext("userId", "4"), time.Time{}, d1res4.GetResourceTypes())) d2r1 := commands.NewResourceID(d2res1.GetDeviceId(), d2res1.GetHref()) - eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"))) + eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r1, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata, ResourceTypes: d2res1.GetResourceTypes()}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"), d2res1.GetResourceTypes())) + eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r1, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{}, d2res1.GetResourceTypes())) + eventstore.Append(d2res1.GetDeviceId(), d2r1.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r1, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"), d2res1.GetResourceTypes())) d2r2 := commands.NewResourceID(d2res2.GetDeviceId(), d2res2.GetHref()) - eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"))) - eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r2, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{})) - eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r2, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"))) - eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceChangedEvent(d2r2, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "2"))) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(d2r2, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata, ResourceTypes: d2res2.GetResourceTypes()}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "0"), d2res2.GetResourceTypes())) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceUpdatePending(d2r2, &commands.Content{}, makeEventMeta("a", 1), mockEvents.MakeAuditContext("userId", "1"), time.Time{}, d2res2.GetResourceTypes())) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceUpdated(d2r2, commands.Status_OK, &commands.Content{}, makeEventMeta("a", 2), mockEvents.MakeAuditContext("userId", "1"), d2res2.GetResourceTypes())) + eventstore.Append(d2res2.GetDeviceId(), d2r2.ToUUID().String(), mockEvents.MakeResourceChangedEvent(d2r2, &commands.Content{}, makeEventMeta("a", 3), mockEvents.MakeAuditContext("userId", "2"), d2res2.GetResourceTypes())) return eventstore } @@ -175,7 +188,7 @@ func TestResourceProjectionTestLoadParallelModels(t *testing.T) { for i := 0; i < numDevices; i++ { for j := 0; j < numResources; j++ { resourceID := commands.NewResourceID(fmt.Sprintf("dev-%v", i), fmt.Sprintf("res-%v", j)) - eventstore.Append(resourceID.GetDeviceId(), resourceID.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(resourceID, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"))) + eventstore.Append(resourceID.GetDeviceId(), resourceID.ToUUID().String(), mockEvents.MakeResourceStateSnapshotTaken(resourceID, &events.ResourceChanged{Content: &commands.Content{}, EventMetadata: resourceChangedEventMetadata}, makeEventMeta("a", 0), mockEvents.MakeAuditContext("userId", "2"), []string{"type1", "type2"})) } } @@ -486,7 +499,7 @@ func TestResourceLinksProjection_Models(t *testing.T) { } } -func TestResourceStateProjection_Models(t *testing.T) { +func TestResourceStateProjectionModels(t *testing.T) { type args struct { resourceID *commands.ResourceId } @@ -508,6 +521,7 @@ func TestResourceStateProjection_Models(t *testing.T) { EventMetadata: &events.EventMetadata{ Timestamp: 12345, }, + ResourceTypes: d1res1.GetResourceTypes(), }, EventMetadata: &events.EventMetadata{ Version: 4, @@ -531,6 +545,7 @@ func TestResourceStateProjection_Models(t *testing.T) { Timestamp: 12345, ConnectionId: "a", }, + ResourceTypes: d1res1.GetResourceTypes(), }, { ResourceId: commands.NewResourceID(d1res1.GetDeviceId(), d1res1.GetHref()), @@ -544,8 +559,10 @@ func TestResourceStateProjection_Models(t *testing.T) { Timestamp: 12345, ConnectionId: "a", }, + ResourceTypes: d1res1.GetResourceTypes(), }, }, + ResourceTypes: d1res1.GetResourceTypes(), }, }, }, @@ -562,13 +579,15 @@ func TestResourceStateProjection_Models(t *testing.T) { EventMetadata: &events.EventMetadata{ Timestamp: 12345, }, + ResourceTypes: d1res2.GetResourceTypes(), }, EventMetadata: &events.EventMetadata{ Version: 0, Timestamp: 12345, ConnectionId: "a", }, - AuditContext: commands.NewAuditContext("userId", "2", ""), + AuditContext: commands.NewAuditContext("userId", "2", ""), + ResourceTypes: d1res2.GetResourceTypes(), }, }, }, @@ -585,6 +604,7 @@ func TestResourceStateProjection_Models(t *testing.T) { EventMetadata: &events.EventMetadata{ Timestamp: 12345, }, + ResourceTypes: d1res3.GetResourceTypes(), }, EventMetadata: &events.EventMetadata{ Version: 1, @@ -608,8 +628,10 @@ func TestResourceStateProjection_Models(t *testing.T) { Timestamp: 12345, ConnectionId: "a", }, + ResourceTypes: d1res3.GetResourceTypes(), }, }, + ResourceTypes: d1res3.GetResourceTypes(), }, }, }, @@ -650,8 +672,10 @@ func TestResourceStateProjection_Models(t *testing.T) { Timestamp: 12345, ConnectionId: "a", }, + ResourceTypes: d1res4.GetResourceTypes(), }, }, + ResourceTypes: d1res4.GetResourceTypes(), }, }, }, @@ -668,6 +692,7 @@ func TestResourceStateProjection_Models(t *testing.T) { EventMetadata: &events.EventMetadata{ Timestamp: 12345, }, + ResourceTypes: d2res1.GetResourceTypes(), }, EventMetadata: &events.EventMetadata{ Version: 2, @@ -679,6 +704,7 @@ func TestResourceStateProjection_Models(t *testing.T) { CorrelationId: "1", }, ResourceUpdatePendings: []*events.ResourceUpdatePending{}, + ResourceTypes: d2res1.GetResourceTypes(), }, }, }, @@ -699,6 +725,7 @@ func TestResourceStateProjection_Models(t *testing.T) { Timestamp: 12345, ConnectionId: "a", }, + ResourceTypes: d2res2.GetResourceTypes(), }, EventMetadata: &events.EventMetadata{ Version: 3, @@ -710,6 +737,7 @@ func TestResourceStateProjection_Models(t *testing.T) { CorrelationId: "2", }, ResourceUpdatePendings: []*events.ResourceUpdatePending{}, + ResourceTypes: d2res2.GetResourceTypes(), }, }, }, diff --git a/resource-aggregate/events/deviceMetadataSnapshotTaken.go b/resource-aggregate/events/deviceMetadataSnapshotTaken.go index 4c1fca6a8..2e896fe01 100644 --- a/resource-aggregate/events/deviceMetadataSnapshotTaken.go +++ b/resource-aggregate/events/deviceMetadataSnapshotTaken.go @@ -58,6 +58,10 @@ func (d *DeviceMetadataSnapshotTaken) ServiceID() (string, bool) { return d.GetDeviceMetadataUpdated().GetConnection().GetServiceId(), true } +func (d *DeviceMetadataSnapshotTaken) Types() []string { + return nil +} + func (d *DeviceMetadataSnapshotTaken) CopyData(event *DeviceMetadataSnapshotTaken) { d.DeviceId = event.GetDeviceId() d.DeviceMetadataUpdated = event.GetDeviceMetadataUpdated() diff --git a/resource-aggregate/events/deviceMetadataUpdatePending.go b/resource-aggregate/events/deviceMetadataUpdatePending.go index 2506b5d59..6d86da1c3 100644 --- a/resource-aggregate/events/deviceMetadataUpdatePending.go +++ b/resource-aggregate/events/deviceMetadataUpdatePending.go @@ -47,6 +47,10 @@ func (d *DeviceMetadataUpdatePending) ETag() *eventstore.ETagData { return nil } +func (d *DeviceMetadataUpdatePending) Types() []string { + return nil +} + func (d *DeviceMetadataUpdatePending) CopyData(event *DeviceMetadataUpdatePending) { d.DeviceId = event.GetDeviceId() d.UpdatePending = event.GetUpdatePending() diff --git a/resource-aggregate/events/deviceMetadataUpdated.go b/resource-aggregate/events/deviceMetadataUpdated.go index 07085dcdd..e446f3660 100644 --- a/resource-aggregate/events/deviceMetadataUpdated.go +++ b/resource-aggregate/events/deviceMetadataUpdated.go @@ -52,6 +52,10 @@ func (d *DeviceMetadataUpdated) ServiceID() (string, bool) { return d.GetConnection().GetServiceId(), true } +func (d *DeviceMetadataUpdated) Types() []string { + return nil +} + func (d *DeviceMetadataUpdated) CopyData(event *DeviceMetadataUpdated) { d.DeviceId = event.GetDeviceId() d.Connection = event.GetConnection() diff --git a/resource-aggregate/events/events.pb.go b/resource-aggregate/events/events.pb.go index c5c2d3ac4..53edbf02c 100644 --- a/resource-aggregate/events/events.pb.go +++ b/resource-aggregate/events/events.pb.go @@ -344,6 +344,7 @@ type ResourceChanged struct { AuditContext *commands.AuditContext `protobuf:"bytes,4,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,5,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` Etag []byte `protobuf:"bytes,6,opt,name=etag,proto3" json:"etag,omitempty"` // etag of the resource used by twin synchronization + ResourceTypes []string `protobuf:"bytes,7,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -422,6 +423,13 @@ func (x *ResourceChanged) GetEtag() []byte { return nil } +func (x *ResourceChanged) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceChanged) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -440,6 +448,7 @@ type ResourceUpdatePending struct { AuditContext *commands.AuditContext `protobuf:"bytes,4,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,5,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` ValidUntil int64 `protobuf:"varint,6,opt,name=valid_until,json=validUntil,proto3" json:"valid_until,omitempty"` // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. + ResourceTypes []string `protobuf:"bytes,7,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -518,6 +527,13 @@ func (x *ResourceUpdatePending) GetValidUntil() int64 { return 0 } +func (x *ResourceUpdatePending) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceUpdatePending) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -535,6 +551,7 @@ type ResourceUpdated struct { Content *commands.Content `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` AuditContext *commands.AuditContext `protobuf:"bytes,4,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,5,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` + ResourceTypes []string `protobuf:"bytes,6,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -606,6 +623,13 @@ func (x *ResourceUpdated) GetEventMetadata() *EventMetadata { return nil } +func (x *ResourceUpdated) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceUpdated) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -624,6 +648,7 @@ type ResourceRetrievePending struct { EventMetadata *EventMetadata `protobuf:"bytes,4,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` ValidUntil int64 `protobuf:"varint,5,opt,name=valid_until,json=validUntil,proto3" json:"valid_until,omitempty"` // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. Etag [][]byte `protobuf:"bytes,6,rep,name=etag,proto3" json:"etag,omitempty"` + ResourceTypes []string `protobuf:"bytes,7,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -702,6 +727,13 @@ func (x *ResourceRetrievePending) GetEtag() [][]byte { return nil } +func (x *ResourceRetrievePending) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceRetrievePending) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -720,6 +752,7 @@ type ResourceRetrieved struct { AuditContext *commands.AuditContext `protobuf:"bytes,4,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,5,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` Etag []byte `protobuf:"bytes,6,opt,name=etag,proto3" json:"etag,omitempty"` + ResourceTypes []string `protobuf:"bytes,7,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -798,6 +831,13 @@ func (x *ResourceRetrieved) GetEtag() []byte { return nil } +func (x *ResourceRetrieved) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceRetrieved) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -815,6 +855,7 @@ type ResourceDeletePending struct { EventMetadata *EventMetadata `protobuf:"bytes,3,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` ValidUntil int64 `protobuf:"varint,4,opt,name=valid_until,json=validUntil,proto3" json:"valid_until,omitempty"` // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. ResourceInterface string `protobuf:"bytes,5,opt,name=resource_interface,json=resourceInterface,proto3" json:"resource_interface,omitempty"` + ResourceTypes []string `protobuf:"bytes,6,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -886,6 +927,13 @@ func (x *ResourceDeletePending) GetResourceInterface() string { return "" } +func (x *ResourceDeletePending) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceDeletePending) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -903,6 +951,7 @@ type ResourceDeleted struct { Content *commands.Content `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` AuditContext *commands.AuditContext `protobuf:"bytes,4,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,5,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` + ResourceTypes []string `protobuf:"bytes,6,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -974,6 +1023,13 @@ func (x *ResourceDeleted) GetEventMetadata() *EventMetadata { return nil } +func (x *ResourceDeleted) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceDeleted) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -991,6 +1047,7 @@ type ResourceCreatePending struct { AuditContext *commands.AuditContext `protobuf:"bytes,3,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,4,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` ValidUntil int64 `protobuf:"varint,5,opt,name=valid_until,json=validUntil,proto3" json:"valid_until,omitempty"` // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. + ResourceTypes []string `protobuf:"bytes,6,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -1062,6 +1119,13 @@ func (x *ResourceCreatePending) GetValidUntil() int64 { return 0 } +func (x *ResourceCreatePending) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceCreatePending) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -1079,6 +1143,7 @@ type ResourceCreated struct { Content *commands.Content `protobuf:"bytes,3,opt,name=content,proto3" json:"content,omitempty"` AuditContext *commands.AuditContext `protobuf:"bytes,4,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,5,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` + ResourceTypes []string `protobuf:"bytes,6,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` // Open telemetry data propagated to asynchronous events OpenTelemetryCarrier map[string]string `protobuf:"bytes,100,rep,name=open_telemetry_carrier,json=openTelemetryCarrier,proto3" json:"open_telemetry_carrier,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } @@ -1150,6 +1215,13 @@ func (x *ResourceCreated) GetEventMetadata() *EventMetadata { return nil } +func (x *ResourceCreated) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + func (x *ResourceCreated) GetOpenTelemetryCarrier() map[string]string { if x != nil { return x.OpenTelemetryCarrier @@ -1170,6 +1242,7 @@ type ResourceStateSnapshotTaken struct { ResourceDeletePendings []*ResourceDeletePending `protobuf:"bytes,6,rep,name=resource_delete_pendings,json=resourceDeletePendings,proto3" json:"resource_delete_pendings,omitempty"` // expired events will be removed by creating a new snapshot. AuditContext *commands.AuditContext `protobuf:"bytes,7,opt,name=audit_context,json=auditContext,proto3" json:"audit_context,omitempty"` EventMetadata *EventMetadata `protobuf:"bytes,8,opt,name=event_metadata,json=eventMetadata,proto3" json:"event_metadata,omitempty"` + ResourceTypes []string `protobuf:"bytes,9,rep,name=resource_types,json=resourceTypes,proto3" json:"resource_types,omitempty"` } func (x *ResourceStateSnapshotTaken) Reset() { @@ -1260,6 +1333,13 @@ func (x *ResourceStateSnapshotTaken) GetEventMetadata() *EventMetadata { return nil } +func (x *ResourceStateSnapshotTaken) GetResourceTypes() []string { + if x != nil { + return x.ResourceTypes + } + return nil +} + type DeviceMetadataUpdated struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1897,7 +1977,7 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xac, 0x04, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd3, 0x04, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, @@ -1920,28 +2000,69 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, - 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x2e, 0x4f, 0x70, - 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, - 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, - 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, - 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbe, 0x04, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, - 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, - 0x63, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, + 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x75, 0x0a, + 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, + 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, + 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, + 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, + 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, 0x04, + 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, + 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, + 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, + 0x7b, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, + 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x45, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, + 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, + 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, + 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, + 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbf, 0x04, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, + 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x61, @@ -1954,13 +2075,122 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, - 0x6c, 0x12, 0x7b, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, + 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, + 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, + 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, + 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, + 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, + 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, + 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, + 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc4, 0x04, 0x0a, 0x17, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, + 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x65, + 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, + 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x7d, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, + 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, + 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, + 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd7, + 0x04, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, + 0x65, 0x76, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, + 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, + 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x65, + 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, + 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x77, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, + 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x2e, + 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, + 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, + 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, + 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, + 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xac, 0x04, 0x0a, 0x15, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, + 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x12, 0x7b, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, + 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, @@ -1968,8 +2198,8 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x98, 0x04, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbf, 0x04, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, @@ -1990,11 +2220,49 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, + 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, + 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, + 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, + 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, + 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, + 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, + 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, + 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb6, 0x04, 0x0a, 0x15, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, + 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, + 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, + 0x74, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x7b, 0x0a, 0x16, + 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, + 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, @@ -2002,33 +2270,124 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0x9d, 0x04, 0x0a, 0x17, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x41, - 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, - 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, - 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, - 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, - 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, - 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0c, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x7d, 0x0a, 0x16, 0x6f, 0x70, - 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, - 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x47, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, - 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, + 0x38, 0x01, 0x22, 0xbf, 0x04, 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, + 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, + 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, + 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, + 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, + 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, + 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, + 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, + 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, + 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9a, 0x06, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x61, + 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x5b, 0x0a, 0x16, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, + 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x14, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x12, 0x65, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x52, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x6b, 0x0a, 0x1a, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x5f, + 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x18, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x65, + 0x0a, 0x18, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x16, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, + 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, + 0x73, 0x22, 0xf4, 0x04, 0x0a, 0x15, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, + 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x14, 0x74, 0x77, + 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, + 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x74, 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, + 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x0d, 0x61, + 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, + 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x7b, 0x0a, 0x16, + 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, + 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, + 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, @@ -2036,66 +2395,33 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0xb0, 0x04, 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, - 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, - 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x38, 0x01, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x22, 0xba, 0x04, 0x0a, 0x1b, 0x44, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, + 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, + 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, + 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, + 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, + 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, + 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, + 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, + 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x65, - 0x74, 0x61, 0x67, 0x12, 0x77, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, - 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, - 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, - 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x85, 0x04, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, - 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, - 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, - 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, - 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, - 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, + 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, + 0x12, 0x81, 0x01, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x4b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, + 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, @@ -2103,221 +2429,66 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x98, 0x04, - 0x0a, 0x0f, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x64, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, - 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, - 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, - 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x2e, - 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, - 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, - 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, - 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8f, 0x04, 0x0a, 0x15, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x47, - 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, - 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, - 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, - 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x7b, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, - 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, - 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, - 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, - 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x98, 0x04, 0x0a, 0x0f, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x41, - 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x34, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x1c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, - 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x37, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, - 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, - 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x75, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, - 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, - 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, - 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, - 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, - 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, - 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, - 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf3, 0x05, 0x0a, 0x1a, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, - 0x61, 0x6b, 0x65, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x52, 0x0a, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x5b, 0x0a, 0x16, 0x6c, 0x61, 0x74, 0x65, 0x73, - 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x52, 0x14, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x12, 0x65, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x52, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x6b, 0x0a, 0x1a, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, - 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x2d, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, - 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x18, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x65, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x16, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, - 0x65, 0x0a, 0x18, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x64, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x16, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, - 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, - 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf4, 0x04, 0x0a, 0x15, - 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x10, 0x0a, + 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4a, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xc7, 0x02, 0x0a, 0x1b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, + 0x54, 0x61, 0x6b, 0x65, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x40, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x14, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x73, 0x79, 0x6e, - 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x54, 0x77, 0x69, 0x6e, 0x53, 0x79, - 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x74, - 0x77, 0x69, 0x6e, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, - 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, - 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, - 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x12, 0x7b, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, - 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, - 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, - 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, - 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, - 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, - 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x03, - 0x10, 0x04, 0x22, 0xba, 0x04, 0x0a, 0x1b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, - 0x6e, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, - 0x23, 0x0a, 0x0c, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0b, 0x74, 0x77, 0x69, 0x6e, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x12, 0x3e, 0x0a, 0x1a, 0x74, 0x77, 0x69, 0x6e, 0x5f, 0x66, 0x6f, 0x72, - 0x63, 0x65, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x18, 0x74, 0x77, 0x69, 0x6e, - 0x46, 0x6f, 0x72, 0x63, 0x65, 0x53, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, + 0x49, 0x64, 0x12, 0x63, 0x0a, 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x52, 0x15, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x5a, 0x0a, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, - 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x4a, 0x0a, - 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, - 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, - 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x81, 0x01, 0x0a, 0x16, 0x6f, - 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, - 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4b, 0x2e, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, - 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x2e, 0x4f, + 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, + 0xf6, 0x01, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, + 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, + 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x2e, 0x48, 0x65, + 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x4b, + 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x52, 0x07, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x4b, 0x0a, 0x09, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0xcc, 0x03, 0x0a, 0x16, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x12, 0x56, 0x0a, 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, + 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, + 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, + 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x11, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, + 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, + 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, + 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, + 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x12, 0x7c, 0x0a, 0x16, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x46, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, + 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, @@ -2325,91 +2496,25 @@ var file_resource_aggregate_pb_events_proto_rawDesc = []byte{ 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, - 0xc7, 0x02, 0x0a, 0x1b, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x61, 0x6b, 0x65, 0x6e, 0x12, - 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x63, 0x0a, 0x17, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x15, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x64, 0x12, 0x5a, 0x0a, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x65, 0x6e, 0x64, - 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x62, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x52, 0x0e, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4a, 0x0a, - 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xf6, 0x01, 0x0a, 0x11, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, - 0x47, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, - 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, - 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, - 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, - 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x4b, 0x0a, 0x07, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, - 0x61, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x52, 0x07, 0x65, 0x78, - 0x70, 0x69, 0x72, 0x65, 0x64, 0x1a, 0x4b, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, - 0x61, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x75, 0x6e, 0x74, 0x69, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x55, 0x6e, 0x74, - 0x69, 0x6c, 0x22, 0xcc, 0x03, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x56, 0x0a, - 0x12, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, - 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x72, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, - 0x61, 0x74, 0x52, 0x11, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x48, 0x65, 0x61, 0x72, - 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, - 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x47, 0x0a, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, - 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, - 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0c, 0x61, 0x75, - 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x7c, 0x0a, 0x16, 0x6f, 0x70, - 0x65, 0x6e, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x61, 0x72, - 0x72, 0x69, 0x65, 0x72, 0x18, 0x64, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x46, 0x2e, 0x72, 0x65, 0x73, + 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xd2, 0x01, 0x0a, 0x1c, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6e, 0x61, 0x70, 0x73, + 0x68, 0x6f, 0x74, 0x54, 0x61, 0x6b, 0x65, 0x6e, 0x12, 0x66, 0x0a, 0x18, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, - 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x1a, 0x47, 0x0a, 0x19, 0x4f, 0x70, 0x65, 0x6e, - 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x22, 0xd2, 0x01, 0x0a, 0x1c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6e, 0x61, 0x70, 0x73, 0x68, 0x6f, 0x74, 0x54, 0x61, 0x6b, - 0x65, 0x6e, 0x12, 0x66, 0x0a, 0x18, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, - 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x52, 0x16, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, - 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2d, 0x61, 0x67, - 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x3b, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x52, 0x16, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x12, 0x4a, 0x0a, 0x0e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x62, 0x2e, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x0d, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x3d, 0x5a, 0x3b, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6c, 0x67, 0x64, 0x2d, + 0x64, 0x65, 0x76, 0x2f, 0x68, 0x75, 0x62, 0x2f, 0x76, 0x32, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x2d, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x2f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x3b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/resource-aggregate/events/resourceChanged.go b/resource-aggregate/events/resourceChanged.go index f4c694d12..91cb5d649 100644 --- a/resource-aggregate/events/resourceChanged.go +++ b/resource-aggregate/events/resourceChanged.go @@ -7,6 +7,7 @@ import ( pkgTime "github.com/plgd-dev/hub/v2/pkg/time" commands "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "github.com/plgd-dev/hub/v2/resource-aggregate/cqrs/eventstore" + "golang.org/x/exp/slices" "google.golang.org/protobuf/proto" ) @@ -58,6 +59,10 @@ func (rc *ResourceChanged) ServiceID() (string, bool) { return "", false } +func (rc *ResourceChanged) Types() []string { + return rc.GetResourceTypes() +} + func (rc *ResourceChanged) CopyData(event *ResourceChanged) { rc.ResourceId = event.GetResourceId() rc.Content = event.GetContent() @@ -66,6 +71,7 @@ func (rc *ResourceChanged) CopyData(event *ResourceChanged) { rc.Status = event.GetStatus() rc.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() rc.Etag = event.GetEtag() + rc.ResourceTypes = event.GetResourceTypes() } func (rc *ResourceChanged) CheckInitialized() bool { @@ -90,6 +96,9 @@ func (rc *ResourceChanged) Equal(changed *ResourceChanged) bool { if rc.GetAuditContext().GetUserId() != changed.GetAuditContext().GetUserId() { return false } + if !slices.Equal(rc.GetResourceTypes(), changed.GetResourceTypes()) { + return false + } return true } diff --git a/resource-aggregate/events/resourceChanged_test.go b/resource-aggregate/events/resourceChanged_test.go index 500204d94..bda33bf20 100644 --- a/resource-aggregate/events/resourceChanged_test.go +++ b/resource-aggregate/events/resourceChanged_test.go @@ -30,10 +30,11 @@ var testEventResourceChanged events.ResourceChanged = events.ResourceChanged{ ConnectionId: "con1", Sequence: 1, }, - Status: commands.Status_ACCEPTED, + Status: commands.Status_ACCEPTED, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceChanged_CopyData(t *testing.T) { +func TestResourceChangedCopyData(t *testing.T) { type args struct { event *events.ResourceChanged } diff --git a/resource-aggregate/events/resourceCreatePending.go b/resource-aggregate/events/resourceCreatePending.go index 3934a7c01..87c7d43a4 100644 --- a/resource-aggregate/events/resourceCreatePending.go +++ b/resource-aggregate/events/resourceCreatePending.go @@ -50,6 +50,10 @@ func (e *ResourceCreatePending) ServiceID() (string, bool) { return "", false } +func (e *ResourceCreatePending) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceCreatePending) CopyData(event *ResourceCreatePending) { e.ResourceId = event.GetResourceId() e.Content = event.GetContent() @@ -57,6 +61,7 @@ func (e *ResourceCreatePending) CopyData(event *ResourceCreatePending) { e.EventMetadata = event.GetEventMetadata() e.ValidUntil = event.GetValidUntil() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceCreatePending) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceCreatePending_test.go b/resource-aggregate/events/resourceCreatePending_test.go index a2a45790f..5858142d6 100644 --- a/resource-aggregate/events/resourceCreatePending_test.go +++ b/resource-aggregate/events/resourceCreatePending_test.go @@ -30,6 +30,7 @@ var testEventResourceCreatePending events.ResourceCreatePending = events.Resourc ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } func TestResourceCreatePending_CopyData(t *testing.T) { diff --git a/resource-aggregate/events/resourceCreated.go b/resource-aggregate/events/resourceCreated.go index c826136ea..1bc4cb380 100644 --- a/resource-aggregate/events/resourceCreated.go +++ b/resource-aggregate/events/resourceCreated.go @@ -51,6 +51,10 @@ func (e *ResourceCreated) ServiceID() (string, bool) { return "", false } +func (e *ResourceCreated) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceCreated) CopyData(event *ResourceCreated) { e.ResourceId = event.GetResourceId() e.Status = event.GetStatus() @@ -58,6 +62,7 @@ func (e *ResourceCreated) CopyData(event *ResourceCreated) { e.AuditContext = event.GetAuditContext() e.EventMetadata = event.GetEventMetadata() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceCreated) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceCreated_test.go b/resource-aggregate/events/resourceCreated_test.go index 93efddb2a..e2983d14d 100644 --- a/resource-aggregate/events/resourceCreated_test.go +++ b/resource-aggregate/events/resourceCreated_test.go @@ -31,9 +31,10 @@ var testEventResourceCreated events.ResourceCreated = events.ResourceCreated{ ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceCreated_CopyData(t *testing.T) { +func TestResourceCreatedCopyData(t *testing.T) { type args struct { event *events.ResourceCreated } diff --git a/resource-aggregate/events/resourceDeletePending.go b/resource-aggregate/events/resourceDeletePending.go index ef12ee02f..477fee130 100644 --- a/resource-aggregate/events/resourceDeletePending.go +++ b/resource-aggregate/events/resourceDeletePending.go @@ -50,6 +50,10 @@ func (e *ResourceDeletePending) ServiceID() (string, bool) { return "", false } +func (e *ResourceDeletePending) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceDeletePending) CopyData(event *ResourceDeletePending) { e.ResourceId = event.GetResourceId() e.AuditContext = event.GetAuditContext() @@ -57,6 +61,7 @@ func (e *ResourceDeletePending) CopyData(event *ResourceDeletePending) { e.ValidUntil = event.GetValidUntil() e.ResourceInterface = event.GetResourceInterface() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceDeletePending) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceDeletePending_test.go b/resource-aggregate/events/resourceDeletePending_test.go index 1a629c707..a6964408b 100644 --- a/resource-aggregate/events/resourceDeletePending_test.go +++ b/resource-aggregate/events/resourceDeletePending_test.go @@ -26,9 +26,10 @@ var testEventResourceDeletePending events.ResourceDeletePending = events.Resourc Sequence: 1, }, ResourceInterface: interfaces.OC_IF_BASELINE, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceDeletePending_CopyData(t *testing.T) { +func TestResourceDeletePendingCopyData(t *testing.T) { type args struct { event *events.ResourceDeletePending } diff --git a/resource-aggregate/events/resourceDeleted.go b/resource-aggregate/events/resourceDeleted.go index feb9047e0..1f4ab2d3b 100644 --- a/resource-aggregate/events/resourceDeleted.go +++ b/resource-aggregate/events/resourceDeleted.go @@ -51,6 +51,10 @@ func (e *ResourceDeleted) ServiceID() (string, bool) { return "", false } +func (e *ResourceDeleted) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceDeleted) CopyData(event *ResourceDeleted) { e.ResourceId = event.GetResourceId() e.Status = event.GetStatus() @@ -58,6 +62,7 @@ func (e *ResourceDeleted) CopyData(event *ResourceDeleted) { e.AuditContext = event.GetAuditContext() e.EventMetadata = event.GetEventMetadata() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceDeleted) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceDeleted_test.go b/resource-aggregate/events/resourceDeleted_test.go index 89fe66bb0..c34b44244 100644 --- a/resource-aggregate/events/resourceDeleted_test.go +++ b/resource-aggregate/events/resourceDeleted_test.go @@ -31,6 +31,7 @@ var testEventResourceDeleted events.ResourceDeleted = events.ResourceDeleted{ ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } func TestResourceDeleted_CopyData(t *testing.T) { diff --git a/resource-aggregate/events/resourceLinksPublished.go b/resource-aggregate/events/resourceLinksPublished.go index 3c361dfc8..e3e32426e 100644 --- a/resource-aggregate/events/resourceLinksPublished.go +++ b/resource-aggregate/events/resourceLinksPublished.go @@ -51,6 +51,10 @@ func (e *ResourceLinksPublished) ServiceID() (string, bool) { return "", false } +func (e *ResourceLinksPublished) Types() []string { + return nil +} + func (e *ResourceLinksPublished) CopyData(event *ResourceLinksPublished) { e.Resources = event.GetResources() e.DeviceId = event.GetDeviceId() diff --git a/resource-aggregate/events/resourceLinksSnapshotTaken.go b/resource-aggregate/events/resourceLinksSnapshotTaken.go index 897f0d641..654b1bdec 100644 --- a/resource-aggregate/events/resourceLinksSnapshotTaken.go +++ b/resource-aggregate/events/resourceLinksSnapshotTaken.go @@ -58,6 +58,10 @@ func (e *ResourceLinksSnapshotTaken) ServiceID() (string, bool) { return "", false } +func (e *ResourceLinksSnapshotTaken) Types() []string { + return nil +} + func (e *ResourceLinksSnapshotTaken) CloneData(event *ResourceLinksSnapshotTaken) { e.DeviceId = event.GetDeviceId() e.Resources = commands.CloneResourcesMap(event.GetResources()) diff --git a/resource-aggregate/events/resourceLinksUnpublished.go b/resource-aggregate/events/resourceLinksUnpublished.go index 52e4a0379..2ca78c775 100644 --- a/resource-aggregate/events/resourceLinksUnpublished.go +++ b/resource-aggregate/events/resourceLinksUnpublished.go @@ -51,6 +51,10 @@ func (e *ResourceLinksUnpublished) ServiceID() (string, bool) { return "", false } +func (e *ResourceLinksUnpublished) Types() []string { + return nil +} + func (e *ResourceLinksUnpublished) CopyData(event *ResourceLinksUnpublished) { e.Hrefs = event.GetHrefs() e.DeviceId = event.GetDeviceId() diff --git a/resource-aggregate/events/resourceRetrievePending.go b/resource-aggregate/events/resourceRetrievePending.go index 73e5ccd87..fc2821bcf 100644 --- a/resource-aggregate/events/resourceRetrievePending.go +++ b/resource-aggregate/events/resourceRetrievePending.go @@ -50,6 +50,10 @@ func (e *ResourceRetrievePending) ServiceID() (string, bool) { return "", false } +func (e *ResourceRetrievePending) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceRetrievePending) CopyData(event *ResourceRetrievePending) { e.ResourceId = event.GetResourceId() e.ResourceInterface = event.GetResourceInterface() @@ -57,6 +61,7 @@ func (e *ResourceRetrievePending) CopyData(event *ResourceRetrievePending) { e.EventMetadata = event.GetEventMetadata() e.ValidUntil = event.GetValidUntil() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceRetrievePending) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceRetrievePending_test.go b/resource-aggregate/events/resourceRetrievePending_test.go index 0c9b56dcc..356519e09 100644 --- a/resource-aggregate/events/resourceRetrievePending_test.go +++ b/resource-aggregate/events/resourceRetrievePending_test.go @@ -25,9 +25,10 @@ var testEventResourceRetrievePending events.ResourceRetrievePending = events.Res ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceRetrievePending_CopyData(t *testing.T) { +func TestResourceRetrievePendingCopyData(t *testing.T) { type args struct { event *events.ResourceRetrievePending } diff --git a/resource-aggregate/events/resourceRetrieved.go b/resource-aggregate/events/resourceRetrieved.go index e1b539df9..f84e4639c 100644 --- a/resource-aggregate/events/resourceRetrieved.go +++ b/resource-aggregate/events/resourceRetrieved.go @@ -51,6 +51,10 @@ func (e *ResourceRetrieved) ServiceID() (string, bool) { return "", false } +func (e *ResourceRetrieved) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceRetrieved) CopyData(event *ResourceRetrieved) { e.ResourceId = event.GetResourceId() e.Content = event.GetContent() @@ -58,6 +62,7 @@ func (e *ResourceRetrieved) CopyData(event *ResourceRetrieved) { e.EventMetadata = event.GetEventMetadata() e.Status = event.GetStatus() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceRetrieved) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceRetrieved_test.go b/resource-aggregate/events/resourceRetrieved_test.go index b86d62d79..2d175d992 100644 --- a/resource-aggregate/events/resourceRetrieved_test.go +++ b/resource-aggregate/events/resourceRetrieved_test.go @@ -30,10 +30,11 @@ var testEventResourceRetrieved events.ResourceRetrieved = events.ResourceRetriev ConnectionId: "con1", Sequence: 1, }, - Status: commands.Status_ACCEPTED, + Status: commands.Status_ACCEPTED, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceRetrieved_CopyData(t *testing.T) { +func TestResourceRetrievedCopyData(t *testing.T) { type args struct { event *events.ResourceRetrieved } diff --git a/resource-aggregate/events/resourceStateSnapshotTaken.go b/resource-aggregate/events/resourceStateSnapshotTaken.go index 05881fad4..1fb060e94 100644 --- a/resource-aggregate/events/resourceStateSnapshotTaken.go +++ b/resource-aggregate/events/resourceStateSnapshotTaken.go @@ -66,6 +66,10 @@ func (e *ResourceStateSnapshotTaken) ServiceID() (string, bool) { return "", false } +func (e *ResourceStateSnapshotTaken) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceStateSnapshotTaken) CopyData(event *ResourceStateSnapshotTaken) { e.ResourceId = event.GetResourceId() e.LatestResourceChange = event.GetLatestResourceChange() @@ -75,6 +79,7 @@ func (e *ResourceStateSnapshotTaken) CopyData(event *ResourceStateSnapshotTaken) e.ResourceDeletePendings = event.GetResourceDeletePendings() e.AuditContext = event.GetAuditContext() e.EventMetadata = event.GetEventMetadata() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceStateSnapshotTaken) CheckInitialized() bool { @@ -155,9 +160,17 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceCreatePending(createPend e.EventMetadata = createPending.GetEventMetadata() e.ResourceCreatePendings = append(e.ResourceCreatePendings, createPending) e.AuditContext = createPending.GetAuditContext() + e.setResourceTypes(createPending.GetResourceTypes()) return nil } +func (e *ResourceStateSnapshotTaken) setResourceTypes(resourceTypes []string) { + if len(resourceTypes) == 0 { + return + } + e.ResourceTypes = resourceTypes +} + func (e *ResourceStateSnapshotTaken) handleEventResourceUpdatePending(updatePending *ResourceUpdatePending) error { now := time.Now() if ok := e.processValidUntil(updatePending, now); !ok { @@ -171,6 +184,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceUpdatePending(updatePend e.EventMetadata = updatePending.GetEventMetadata() e.ResourceUpdatePendings = append(e.ResourceUpdatePendings, updatePending) e.AuditContext = updatePending.GetAuditContext() + e.setResourceTypes(updatePending.GetResourceTypes()) return nil } @@ -187,6 +201,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceRetrievePending(retrieve e.EventMetadata = retrievePending.GetEventMetadata() e.ResourceRetrievePendings = append(e.ResourceRetrievePendings, retrievePending) e.AuditContext = retrievePending.GetAuditContext() + e.setResourceTypes(retrievePending.GetResourceTypes()) return nil } @@ -203,6 +218,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceDeletePending(deletePend e.EventMetadata = deletePending.GetEventMetadata() e.ResourceDeletePendings = append(e.ResourceDeletePendings, deletePending) e.AuditContext = deletePending.GetAuditContext() + e.setResourceTypes(deletePending.GetResourceTypes()) return nil } @@ -227,6 +243,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceCreated(created *Resourc resourceCreatePendings = append(resourceCreatePendings[:index], resourceCreatePendings[index+1:]...) e.ResourceCreatePendings = resourceCreatePendings e.AuditContext = created.GetAuditContext() + e.setResourceTypes(created.GetResourceTypes()) return nil } @@ -247,6 +264,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceUpdated(updated *Resourc resourceUpdatePendings = append(resourceUpdatePendings[:index], resourceUpdatePendings[index+1:]...) e.ResourceUpdatePendings = resourceUpdatePendings e.AuditContext = updated.GetAuditContext() + e.setResourceTypes(updated.GetResourceTypes()) return nil } @@ -267,6 +285,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceRetrieved(retrieved *Res resourceRetrievePendings = append(resourceRetrievePendings[:index], resourceRetrievePendings[index+1:]...) e.ResourceRetrievePendings = resourceRetrievePendings e.AuditContext = retrieved.GetAuditContext() + e.setResourceTypes(retrieved.GetResourceTypes()) return nil } @@ -287,6 +306,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceChanged(changed *Resourc e.EventMetadata = changed.GetEventMetadata() e.LatestResourceChange = changed e.AuditContext = changed.GetAuditContext() + e.setResourceTypes(changed.GetResourceTypes()) return true } return false @@ -316,6 +336,7 @@ func (e *ResourceStateSnapshotTaken) handleEventResourceDeleted(deleted *Resourc e.ResourceId = deleted.GetResourceId() e.EventMetadata = deleted.GetEventMetadata() e.AuditContext = deleted.GetAuditContext() + e.setResourceTypes(deleted.GetResourceTypes()) return nil } @@ -475,6 +496,7 @@ func (e *ResourceStateSnapshotTakenForCommand) confirmResourceUpdateRequest(ctx Content: req.GetContent(), Status: req.GetStatus(), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err := e.handleEventResourceUpdated(&rc); err != nil { return nil, err @@ -497,6 +519,7 @@ func (e *ResourceStateSnapshotTakenForCommand) confirmResourceRetrieveRequest(ct Status: req.GetStatus(), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), Etag: req.GetEtag(), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err := e.handleEventResourceRetrieved(&rc); err != nil { return nil, err @@ -518,6 +541,7 @@ func (e *ResourceStateSnapshotTakenForCommand) confirmResourceDeleteRequest(ctx Content: req.GetContent(), Status: req.GetStatus(), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err := e.handleEventResourceDeleted(&rc); err != nil { return nil, err @@ -539,7 +563,9 @@ func (e *ResourceStateSnapshotTakenForCommand) confirmResourceCreateRequest(ctx Content: req.GetContent(), Status: req.GetStatus(), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } + if err := e.handleEventResourceCreated(&rc); err != nil { return nil, err } @@ -660,6 +686,7 @@ func (e *ResourceStateSnapshotTakenForCommand) handleNotifyResourceChangedReques Status: req.GetStatus(), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), Etag: req.GetEtag(), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), req.GetResourceTypes()), } if e.handleEventResourceChanged(&rc) { @@ -688,6 +715,7 @@ func (e *ResourceStateSnapshotTakenForCommand) handleUpdateResourceRequest(ctx c Content: content, ValidUntil: timeToLive2ValidUntil(req.GetTimeToLive()), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err = e.handleEventResourceUpdatePending(&rc); err != nil { @@ -712,6 +740,7 @@ func (e *ResourceStateSnapshotTakenForCommand) handleRetrieveResourceRequest(ctx ValidUntil: timeToLive2ValidUntil(req.GetTimeToLive()), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), Etag: req.GetEtag(), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err := e.handleEventResourceRetrievePending(&rc); err != nil { @@ -735,6 +764,7 @@ func (e *ResourceStateSnapshotTakenForCommand) handleDeleteResourceRequest(ctx c ValidUntil: timeToLive2ValidUntil(req.GetTimeToLive()), ResourceInterface: req.GetResourceInterface(), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err := e.handleEventResourceDeletePending(&rc); err != nil { @@ -743,6 +773,29 @@ func (e *ResourceStateSnapshotTakenForCommand) handleDeleteResourceRequest(ctx c return []eventstore.Event{&rc}, nil } +func (e *ResourceStateSnapshotTakenForCommand) resolveResourceTypes(href string, resourceTypes []string) []string { + if len(resourceTypes) > 0 { + // resourceTypes from command has higher priority + return resourceTypes + } + if e.resourceLinks == nil { + // if no resourceLinks, return resourceTypes from snapshot + return e.GetResourceTypes() + } + resources := e.resourceLinks.GetResources() + if len(resources) == 0 { + // if no resourceLinks, return resourceTypes from snapshot + return e.GetResourceTypes() + } + link, ok := e.resourceLinks.GetResources()[href] + if !ok { + // if resourceLinks doesn't contain resource, return resourceTypes from snapshot + return e.GetResourceTypes() + } + // return resourceTypes from link + return link.GetResourceTypes() +} + func (e *ResourceStateSnapshotTakenForCommand) handleCreateResourceRequest(ctx context.Context, req *commands.CreateResourceRequest, newVersion uint64) ([]eventstore.Event, error) { if req.GetCommandMetadata() == nil { return nil, status.Errorf(codes.InvalidArgument, errInvalidCommandMetadata) @@ -761,6 +814,7 @@ func (e *ResourceStateSnapshotTakenForCommand) handleCreateResourceRequest(ctx c EventMetadata: em, ValidUntil: timeToLive2ValidUntil(req.GetTimeToLive()), OpenTelemetryCarrier: propagation.TraceFromCtx(ctx), + ResourceTypes: e.resolveResourceTypes(req.GetResourceId().GetHref(), nil), } if err := e.handleEventResourceCreatePending(&rc); err != nil { @@ -811,22 +865,25 @@ func (e *ResourceStateSnapshotTaken) TakeSnapshot(version uint64) (eventstore.Ev ResourceRetrievePendings: e.GetResourceRetrievePendings(), ResourceDeletePendings: e.GetResourceDeletePendings(), AuditContext: e.GetAuditContext(), + ResourceTypes: e.GetResourceTypes(), }, true } type ResourceStateSnapshotTakenForCommand struct { - owner string - hubID string - userID string + owner string + hubID string + userID string + resourceLinks *ResourceLinksSnapshotTakenForCommand *ResourceStateSnapshotTaken } -func NewResourceStateSnapshotTakenForCommand(userID string, owner string, hubID string) *ResourceStateSnapshotTakenForCommand { +func NewResourceStateSnapshotTakenForCommand(userID string, owner string, hubID string, resourceLinks *ResourceLinksSnapshotTakenForCommand) *ResourceStateSnapshotTakenForCommand { return &ResourceStateSnapshotTakenForCommand{ ResourceStateSnapshotTaken: NewResourceStateSnapshotTaken(), userID: userID, owner: owner, hubID: hubID, + resourceLinks: resourceLinks, } } diff --git a/resource-aggregate/events/resourceStateSnapshotTaken_test.go b/resource-aggregate/events/resourceStateSnapshotTaken_test.go index 805fcfb88..18af0389c 100644 --- a/resource-aggregate/events/resourceStateSnapshotTaken_test.go +++ b/resource-aggregate/events/resourceStateSnapshotTaken_test.go @@ -39,7 +39,41 @@ func (i *iterator) Err() error { return nil } -func TestResourceStateSnapshotTaken_Handle(t *testing.T) { +func TestResourceStateSnapshotTakenResourceTypes(t *testing.T) { + const ( + href = "/a" + deviceID = "a" + hubID = "hubID" + userID = "userID" + ) + resourceTypes := []string{"type1", "type2"} + + e := events.NewResourceStateSnapshotTaken() + require.Empty(t, e.Types()) + err := e.Handle(context.TODO(), newIterator([]eventstore.EventUnmarshaler{test.MakeResourceChangedEvent(commands.NewResourceID(deviceID, href), &commands.Content{}, events.MakeEventMeta("", 0, 0, hubID), commands.NewAuditContext(userID, "0", userID), resourceTypes)})) + require.NoError(t, err) + require.Equal(t, resourceTypes, e.Types()) + nextEvents := newIterator([]eventstore.EventUnmarshaler{ + test.MakeResourceCreatePending(commands.NewResourceID(deviceID, href), &commands.Content{}, events.MakeEventMeta("", 0, 1, hubID), commands.NewAuditContext(userID, "0", userID), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceCreated(commands.NewResourceID(deviceID, href), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 2, hubID), commands.NewAuditContext(userID, "0", userID), resourceTypes), + test.MakeResourceRetrievePending(commands.NewResourceID(deviceID, href), "", events.MakeEventMeta("", 0, 3, hubID), commands.NewAuditContext(userID, "1", userID), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceRetrieved(commands.NewResourceID(deviceID, href), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 4, hubID), commands.NewAuditContext(userID, "1", userID), resourceTypes), + test.MakeResourceUpdatePending(commands.NewResourceID(deviceID, href), &commands.Content{}, events.MakeEventMeta("", 0, 5, hubID), commands.NewAuditContext(userID, "2", userID), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceUpdated(commands.NewResourceID(deviceID, href), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 6, hubID), commands.NewAuditContext(userID, "2", userID), resourceTypes), + test.MakeResourceDeletePending(commands.NewResourceID(deviceID, href), events.MakeEventMeta("", 0, 7, hubID), commands.NewAuditContext(userID, "3", userID), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceDeleted(commands.NewResourceID(deviceID, href), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 8, hubID), commands.NewAuditContext(userID, "3", userID), resourceTypes), + }) + err = e.Handle(context.TODO(), nextEvents) + require.NoError(t, err) + require.Equal(t, resourceTypes, e.Types()) + resourceTypes = append(resourceTypes, "type3") + err = e.Handle(context.TODO(), newIterator([]eventstore.EventUnmarshaler{test.MakeResourceChangedEvent(commands.NewResourceID(deviceID, href), &commands.Content{}, events.MakeEventMeta("", 1, 9, hubID), commands.NewAuditContext(userID, "0", userID), resourceTypes)})) + require.NoError(t, err) + require.Equal(t, resourceTypes, e.Types()) +} + +func TestResourceStateSnapshotTakenHandle(t *testing.T) { + resourceTypes := []string{"type1", "type2"} type args struct { events *iterator } @@ -52,8 +86,8 @@ func TestResourceStateSnapshotTaken_Handle(t *testing.T) { name: "createPending, created", args: args{ events: newIterator([]eventstore.EventUnmarshaler{ - test.MakeResourceCreatePending(commands.NewResourceID("a", "/a"), &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "0", "userID"), time.Now().Add(-time.Second)), - test.MakeResourceCreated(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "0", "userID")), + test.MakeResourceCreatePending(commands.NewResourceID("a", "/a"), &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "0", "userID"), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceCreated(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "0", "userID"), resourceTypes), }), }, }, @@ -61,8 +95,8 @@ func TestResourceStateSnapshotTaken_Handle(t *testing.T) { name: "retrievePending, retrieved", args: args{ events: newIterator([]eventstore.EventUnmarshaler{ - test.MakeResourceRetrievePending(commands.NewResourceID("a", "/a"), "", events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "1", "userID"), time.Now().Add(-time.Second)), - test.MakeResourceRetrieved(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "1", "userID")), + test.MakeResourceRetrievePending(commands.NewResourceID("a", "/a"), "", events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "1", "userID"), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceRetrieved(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "1", "userID"), resourceTypes), }), }, }, @@ -70,17 +104,17 @@ func TestResourceStateSnapshotTaken_Handle(t *testing.T) { name: "updatePending, updated", args: args{ events: newIterator([]eventstore.EventUnmarshaler{ - test.MakeResourceUpdatePending(commands.NewResourceID("a", "/a"), &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "2", "userID"), time.Now().Add(-time.Second)), - test.MakeResourceUpdated(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "2", "userID")), + test.MakeResourceUpdatePending(commands.NewResourceID("a", "/a"), &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "2", "userID"), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceUpdated(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "2", "userID"), resourceTypes), }), }, }, { - name: "retrievePending, retrieved", + name: "deletePending, deleted", args: args{ events: newIterator([]eventstore.EventUnmarshaler{ - test.MakeResourceDeletePending(commands.NewResourceID("a", "/a"), events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "3", "userID"), time.Now().Add(-time.Second)), - test.MakeResourceDeleted(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "3", "userID")), + test.MakeResourceDeletePending(commands.NewResourceID("a", "/a"), events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "3", "userID"), time.Now().Add(-time.Second), resourceTypes), + test.MakeResourceDeleted(commands.NewResourceID("a", "/a"), commands.Status_OK, &commands.Content{}, events.MakeEventMeta("", 0, 0, "hubID"), commands.NewAuditContext("userID", "3", "userID"), resourceTypes), }), }, }, @@ -195,7 +229,8 @@ var testEventResourceStateSnapshotTaken events.ResourceStateSnapshotTaken = even DeviceId: "devLatest", Href: "/devLatest", }, - Content: &commands.Content{}, + Content: &commands.Content{}, + ResourceTypes: []string{"type1", "type2"}, }, ResourceCreatePendings: []*events.ResourceCreatePending{ { @@ -203,6 +238,7 @@ var testEventResourceStateSnapshotTaken events.ResourceStateSnapshotTaken = even DeviceId: "devCreate", Href: "/devCreate", }, + ResourceTypes: []string{"type1", "type2"}, }, }, ResourceRetrievePendings: []*events.ResourceRetrievePending{ @@ -211,6 +247,7 @@ var testEventResourceStateSnapshotTaken events.ResourceStateSnapshotTaken = even DeviceId: "devRetrieve", Href: "/devRetrieve", }, + ResourceTypes: []string{"type1", "type2"}, }, }, ResourceUpdatePendings: []*events.ResourceUpdatePending{ @@ -219,6 +256,7 @@ var testEventResourceStateSnapshotTaken events.ResourceStateSnapshotTaken = even DeviceId: "devUpdate", Href: "/devUpdate", }, + ResourceTypes: []string{"type1", "type2"}, }, }, ResourceDeletePendings: []*events.ResourceDeletePending{ @@ -227,6 +265,7 @@ var testEventResourceStateSnapshotTaken events.ResourceStateSnapshotTaken = even DeviceId: "devDelete", Href: "/devDelete", }, + ResourceTypes: []string{"type1", "type2"}, }, }, AuditContext: &commands.AuditContext{ @@ -239,9 +278,10 @@ var testEventResourceStateSnapshotTaken events.ResourceStateSnapshotTaken = even ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceStateSnapshotTaken_CopyData(t *testing.T) { +func TestResourceStateSnapshotTakenCopyData(t *testing.T) { type args struct { event *events.ResourceStateSnapshotTaken } diff --git a/resource-aggregate/events/resourceUpdatePending.go b/resource-aggregate/events/resourceUpdatePending.go index 0fdbc5013..45c51e072 100644 --- a/resource-aggregate/events/resourceUpdatePending.go +++ b/resource-aggregate/events/resourceUpdatePending.go @@ -50,6 +50,10 @@ func (e *ResourceUpdatePending) ServiceID() (string, bool) { return "", false } +func (e *ResourceUpdatePending) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceUpdatePending) CopyData(event *ResourceUpdatePending) { e.ResourceId = event.GetResourceId() e.ResourceInterface = event.GetResourceInterface() @@ -58,6 +62,7 @@ func (e *ResourceUpdatePending) CopyData(event *ResourceUpdatePending) { e.EventMetadata = event.GetEventMetadata() e.ValidUntil = event.GetValidUntil() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceUpdatePending) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceUpdatePending_test.go b/resource-aggregate/events/resourceUpdatePending_test.go index 4a823a9f7..9bd0d050e 100644 --- a/resource-aggregate/events/resourceUpdatePending_test.go +++ b/resource-aggregate/events/resourceUpdatePending_test.go @@ -34,9 +34,10 @@ var testEventResourceUpdatePending events.ResourceUpdatePending = events.Resourc ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceUpdatePending_CopyData(t *testing.T) { +func TestResourceUpdatePendingCopyData(t *testing.T) { type args struct { event *events.ResourceUpdatePending } diff --git a/resource-aggregate/events/resourceUpdated.go b/resource-aggregate/events/resourceUpdated.go index 6845923c0..6c7bac5c8 100644 --- a/resource-aggregate/events/resourceUpdated.go +++ b/resource-aggregate/events/resourceUpdated.go @@ -51,6 +51,10 @@ func (e *ResourceUpdated) ServiceID() (string, bool) { return "", false } +func (e *ResourceUpdated) Types() []string { + return e.GetResourceTypes() +} + func (e *ResourceUpdated) CopyData(event *ResourceUpdated) { e.ResourceId = event.GetResourceId() e.Status = event.GetStatus() @@ -58,6 +62,7 @@ func (e *ResourceUpdated) CopyData(event *ResourceUpdated) { e.AuditContext = event.GetAuditContext() e.EventMetadata = event.GetEventMetadata() e.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() + e.ResourceTypes = event.GetResourceTypes() } func (e *ResourceUpdated) CheckInitialized() bool { diff --git a/resource-aggregate/events/resourceUpdated_test.go b/resource-aggregate/events/resourceUpdated_test.go index e18e8edf1..e0631614c 100644 --- a/resource-aggregate/events/resourceUpdated_test.go +++ b/resource-aggregate/events/resourceUpdated_test.go @@ -31,9 +31,10 @@ var testEventResourceUpdated events.ResourceUpdated = events.ResourceUpdated{ ConnectionId: "con1", Sequence: 1, }, + ResourceTypes: []string{"type1", "type2"}, } -func TestResourceUpdated_CopyData(t *testing.T) { +func TestResourceUpdatedCopyData(t *testing.T) { type args struct { event *events.ResourceUpdated } diff --git a/resource-aggregate/events/serviceMetadataSnapshotTaken.go b/resource-aggregate/events/serviceMetadataSnapshotTaken.go index 7e166d845..4110973eb 100644 --- a/resource-aggregate/events/serviceMetadataSnapshotTaken.go +++ b/resource-aggregate/events/serviceMetadataSnapshotTaken.go @@ -63,6 +63,10 @@ func (d *ServiceMetadataSnapshotTaken) ServiceID() (string, bool) { return "", false } +func (d *ServiceMetadataSnapshotTaken) Types() []string { + return nil +} + func (d *ServiceMetadataSnapshotTaken) CopyData(event *ServiceMetadataSnapshotTaken) { d.ServiceMetadataUpdated = event.GetServiceMetadataUpdated() d.EventMetadata = event.GetEventMetadata() diff --git a/resource-aggregate/events/serviceMetadataUpdated.go b/resource-aggregate/events/serviceMetadataUpdated.go index e1406f39a..81db2566b 100644 --- a/resource-aggregate/events/serviceMetadataUpdated.go +++ b/resource-aggregate/events/serviceMetadataUpdated.go @@ -51,6 +51,10 @@ func (d *ServiceMetadataUpdated) ServiceID() (string, bool) { return "", false } +func (d *ServiceMetadataUpdated) Types() []string { + return nil +} + func (d *ServiceMetadataUpdated) CopyData(event *ServiceMetadataUpdated) { d.EventMetadata = event.GetEventMetadata() d.OpenTelemetryCarrier = event.GetOpenTelemetryCarrier() diff --git a/resource-aggregate/pb/commands.proto b/resource-aggregate/pb/commands.proto index ed8163b1b..41bf7b09e 100644 --- a/resource-aggregate/pb/commands.proto +++ b/resource-aggregate/pb/commands.proto @@ -95,6 +95,7 @@ message NotifyResourceChangedRequest { CommandMetadata command_metadata = 3; Status status = 4; bytes etag = 5; + repeated string resource_types = 6; } message NotifyResourceChangedResponse { diff --git a/resource-aggregate/pb/events.proto b/resource-aggregate/pb/events.proto index 1cd534e45..080eb74b5 100644 --- a/resource-aggregate/pb/events.proto +++ b/resource-aggregate/pb/events.proto @@ -54,6 +54,7 @@ message ResourceChanged { AuditContext audit_context = 4; EventMetadata event_metadata = 5; bytes etag = 6; // etag of the resource used by twin synchronization + repeated string resource_types = 7; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -66,6 +67,7 @@ message ResourceUpdatePending { AuditContext audit_context = 4; EventMetadata event_metadata = 5; int64 valid_until = 6; // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. + repeated string resource_types = 7; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -77,6 +79,7 @@ message ResourceUpdated { Content content = 3; AuditContext audit_context = 4; EventMetadata event_metadata = 5; + repeated string resource_types = 6; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -89,6 +92,7 @@ message ResourceRetrievePending { EventMetadata event_metadata = 4; int64 valid_until = 5; // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. repeated bytes etag = 6; + repeated string resource_types = 7; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -101,6 +105,7 @@ message ResourceRetrieved { AuditContext audit_context = 4; EventMetadata event_metadata = 5; bytes etag = 6; + repeated string resource_types = 7; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -112,6 +117,7 @@ message ResourceDeletePending { EventMetadata event_metadata = 3; int64 valid_until = 4; // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. string resource_interface = 5; + repeated string resource_types = 6; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -123,6 +129,7 @@ message ResourceDeleted { Content content = 3; AuditContext audit_context = 4; EventMetadata event_metadata = 5; + repeated string resource_types = 6; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -134,6 +141,7 @@ message ResourceCreatePending { AuditContext audit_context = 3; EventMetadata event_metadata = 4; int64 valid_until = 5; // unix timestamp in nanoseconds (https://golang.org/pkg/time/#Time.UnixNano) when pending event is considered as expired. 0 means forever. + repeated string resource_types = 6; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -145,6 +153,7 @@ message ResourceCreated { Content content = 3; AuditContext audit_context = 4; EventMetadata event_metadata = 5; + repeated string resource_types = 6; // Open telemetry data propagated to asynchronous events map open_telemetry_carrier = 100; @@ -159,6 +168,7 @@ message ResourceStateSnapshotTaken { repeated ResourceDeletePending resource_delete_pendings = 6; // expired events will be removed by creating a new snapshot. AuditContext audit_context = 7; EventMetadata event_metadata = 8; + repeated string resource_types = 9; // Open telemetry data propagated to asynchronous events // map open_telemetry_carrier = 100; diff --git a/resource-aggregate/service/aggregate.go b/resource-aggregate/service/aggregate.go index d866ff1d2..f25bdad35 100644 --- a/resource-aggregate/service/aggregate.go +++ b/resource-aggregate/service/aggregate.go @@ -21,43 +21,60 @@ type Aggregate struct { eventstore eventstore.EventStore } -func NewResourceStateFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(context.Context) (cqrsAggregate.AggregateModel, error) { - return events.NewResourceStateSnapshotTakenForCommand(userID, owner, hubID), nil +func NewResourceStateFactoryModel(userID, owner, hubID string) func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { + resourceLinks := events.NewResourceLinksSnapshotTakenForCommand(userID, owner, hubID) + resourceState := events.NewResourceStateSnapshotTakenForCommand(userID, owner, hubID, resourceLinks) + return func(_ context.Context, groupID string, aggregateID string) (cqrsAggregate.AggregateModel, error) { + resID := commands.NewResourceID(groupID, commands.ResourceLinksHref) + if aggregateID == resID.ToUUID().String() { + return resourceLinks, nil + } + return resourceState, nil } } -func NewResourceLinksFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(context.Context) (cqrsAggregate.AggregateModel, error) { +func NewResourceLinksFactoryModel(userID, owner, hubID string) func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { + return func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { return events.NewResourceLinksSnapshotTakenForCommand(userID, owner, hubID), nil } } -func NewDeviceMetadataFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(context.Context) (cqrsAggregate.AggregateModel, error) { +func NewDeviceMetadataFactoryModel(userID, owner, hubID string) func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { + return func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { return events.NewDeviceMetadataSnapshotTakenForCommand(userID, owner, hubID), nil } } -func NewServicesMetadataFactoryModel(userID, owner, hubID string) func(ctx context.Context) (cqrsAggregate.AggregateModel, error) { - return func(context.Context) (cqrsAggregate.AggregateModel, error) { +func NewServicesMetadataFactoryModel(userID, owner, hubID string) func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { + return func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { return events.NewServiceMetadataSnapshotTakenForCommand(userID, owner, hubID), nil } } -// NewAggregate creates new resource aggreate - it must be created for every run command. -func NewAggregate(resourceID *commands.ResourceId, store eventstore.EventStore, factoryModel cqrsAggregate.FactoryModelFunc, retry cqrsAggregate.RetryFunc) (*Aggregate, error) { +// NewResourceAggregate for creating new resource aggregate. +func NewResourceAggregate(resourceID *commands.ResourceId, store eventstore.EventStore, factoryModel cqrsAggregate.FactoryModelFunc, retry cqrsAggregate.RetryFunc, addLinkedResources bool) (*Aggregate, error) { a := &Aggregate{ eventstore: store, } + addLink := make([]cqrsAggregate.AdditionalModel, 0, 1) + if addLinkedResources { + addLink = append(addLink, cqrsAggregate.AdditionalModel{ + GroupID: resourceID.GetDeviceId(), + AggregateID: commands.NewResourceID(resourceID.GetDeviceId(), commands.ResourceLinksHref).ToUUID().String(), + }) + } + cqrsAg, err := cqrsAggregate.NewAggregate(resourceID.GetDeviceId(), resourceID.ToUUID().String(), retry, store, factoryModel, func(string, ...interface{}) { - // TODO: add debug log - }) + // no-op - we don't want to log debug/trace messages + }, + // load also links state + addLink..., + ) if err != nil { return nil, fmt.Errorf("cannot create aggregate for resource: %w", err) } @@ -65,6 +82,11 @@ func NewAggregate(resourceID *commands.ResourceId, store eventstore.EventStore, return a, nil } +// NewAggregate creates new resource aggreate - it must be created for every run command. +func NewAggregate(resourceID *commands.ResourceId, store eventstore.EventStore, factoryModel cqrsAggregate.FactoryModelFunc, retry cqrsAggregate.RetryFunc) (*Aggregate, error) { + return NewResourceAggregate(resourceID, store, factoryModel, retry, false) +} + func (a *Aggregate) HandleCommand(ctx context.Context, cmd cqrsAggregate.Command) ([]eventstore.Event, error) { events, err := a.ag.HandleCommand(ctx, cmd) if err == nil { diff --git a/resource-aggregate/service/grpcApi.go b/resource-aggregate/service/grpcApi.go index 9139bea7e..fcecaf4ff 100644 --- a/resource-aggregate/service/grpcApi.go +++ b/resource-aggregate/service/grpcApi.go @@ -205,7 +205,7 @@ func newUnpublishResourceLinksResponse(events []eventstore.Event, deviceID strin } func (r RequestHandler) notifyResourceChanged(ctx context.Context, request *commands.NotifyResourceChangedRequest, userID, owner string) error { - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), len(request.GetResourceTypes()) == 0) if err != nil { return log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot notify about resource content change: %v", err)) } @@ -243,7 +243,7 @@ func (r RequestHandler) UpdateResource(ctx context.Context, request *commands.Up } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot update resource content: %v", err)) } @@ -275,7 +275,7 @@ func (r RequestHandler) ConfirmResourceUpdate(ctx context.Context, request *comm if err != nil { return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm resource content update: %v", err)) } @@ -299,7 +299,7 @@ func (r RequestHandler) RetrieveResource(ctx context.Context, request *commands. } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot retrieve resource content: %v", err)) } @@ -331,7 +331,7 @@ func (r RequestHandler) ConfirmResourceRetrieve(ctx context.Context, request *co if err != nil { return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "ccannot confirm resource content retrieve: %v", err)) } @@ -356,7 +356,7 @@ func (r RequestHandler) DeleteResource(ctx context.Context, request *commands.De } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot delete resource: %v", err)) } @@ -389,7 +389,7 @@ func (r RequestHandler) ConfirmResourceDelete(ctx context.Context, request *comm return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm resource deletion: %v", err)) } @@ -414,7 +414,7 @@ func (r RequestHandler) CreateResource(ctx context.Context, request *commands.Cr } request.TimeToLive = checkTimeToLiveForDefault(r.config.Clients.Eventstore.DefaultCommandTimeToLive, request.GetTimeToLive()) - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot create resource: %v", err)) } @@ -447,7 +447,7 @@ func (r RequestHandler) ConfirmResourceCreate(ctx context.Context, request *comm return nil, log.LogAndReturnError(cannotValidateAccessError(err)) } - aggregate, err := NewAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry)) + aggregate, err := NewResourceAggregate(request.GetResourceId(), r.eventstore, NewResourceStateFactoryModel(userID, owner, r.config.HubID), cqrsAggregate.NewDefaultRetryFunc(r.config.Clients.Eventstore.ConcurrencyExceptionMaxRetry), true) if err != nil { return nil, log.LogAndReturnError(grpc.ForwardErrorf(codes.InvalidArgument, "cannot confirm resource creation: %v", err)) } diff --git a/resource-aggregate/service/updateDeviceMetadata.go b/resource-aggregate/service/updateDeviceMetadata.go index 04428df06..74cdea693 100644 --- a/resource-aggregate/service/updateDeviceMetadata.go +++ b/resource-aggregate/service/updateDeviceMetadata.go @@ -70,7 +70,7 @@ func (r RequestHandler) updateDeviceMetadata(ctx context.Context, request *comma resID := commands.NewResourceID(request.GetDeviceId(), commands.StatusHref) var latestSnapshot *events.DeviceMetadataSnapshotTakenForCommand - deviceMetadataFactoryModel := func(context.Context) (cqrsAggregate.AggregateModel, error) { + deviceMetadataFactoryModel := func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { latestSnapshot = events.NewDeviceMetadataSnapshotTakenForCommand(userID, owner, r.config.HubID) return latestSnapshot, nil } diff --git a/resource-aggregate/service/updateServiceHeartbeat.go b/resource-aggregate/service/updateServiceHeartbeat.go index 245f36a9c..83e0b6a74 100644 --- a/resource-aggregate/service/updateServiceHeartbeat.go +++ b/resource-aggregate/service/updateServiceHeartbeat.go @@ -198,7 +198,7 @@ func (s *ServiceHeartbeat) updateServiceMetadata(aggregate *Aggregate, r UpdateS func (s *ServiceHeartbeat) processRequest(r UpdateServiceMetadataReqResp) time.Time { resID := commands.NewResourceID(s.config.HubID, commands.ServicesResourceHref) var snapshot *events.ServiceMetadataSnapshotTakenForCommand - newServicesMetadataFactoryModelFunc := func(context.Context) (cqrsAggregate.AggregateModel, error) { + newServicesMetadataFactoryModelFunc := func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { snapshot = events.NewServiceMetadataSnapshotTakenForCommand(ServiceUserID, ServiceUserID, s.config.HubID) return snapshot, nil } @@ -373,7 +373,7 @@ func (s *ServiceHeartbeat) updateDeviceToExpired(ctx context.Context, serviceID, resID := commands.NewResourceID(deviceID, commands.StatusHref) var latestSnapshot *events.DeviceMetadataSnapshotTakenForCommand - deviceMetadataFactoryModel := func(context.Context) (cqrsAggregate.AggregateModel, error) { + deviceMetadataFactoryModel := func(context.Context, string, string) (cqrsAggregate.AggregateModel, error) { latestSnapshot = events.NewDeviceMetadataSnapshotTakenForCommand(userID, "", s.config.HubID) return latestSnapshot, nil } diff --git a/resource-directory/service/deviceDirectory_test.go b/resource-directory/service/deviceDirectory_test.go index 023208f7f..b43de0d09 100644 --- a/resource-directory/service/deviceDirectory_test.go +++ b/resource-directory/service/deviceDirectory_test.go @@ -270,15 +270,15 @@ func testCreateResourceDeviceEventstores() (resourceEventStore *mockEvents.MockE // without cloud state resourceEventStore.Append(ddResource0.GetDeviceId(), commands.MakeLinksResourceUUID(ddResource0.GetDeviceId()).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource0.Resource}, ddResource0.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - resourceEventStore.Append(ddResource0.GetDeviceId(), ddResource0.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource0.Resource.GetResourceID(), ddResource0.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + resourceEventStore.Append(ddResource0.GetDeviceId(), ddResource0.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource0.Resource.GetResourceID(), ddResource0.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), []string{"type0"})) resourceEventStore.Append(ddResource1.GetDeviceId(), commands.MakeLinksResourceUUID(ddResource1.GetDeviceId()).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource1.Resource}, ddResource1.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - resourceEventStore.Append(ddResource1.GetDeviceId(), ddResource1.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource1.Resource.GetResourceID(), ddResource1.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + resourceEventStore.Append(ddResource1.GetDeviceId(), ddResource1.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource1.Resource.GetResourceID(), ddResource1.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), []string{"type1"})) resourceEventStore.Append(ddResource1Cloud.GetDeviceId(), ddResource1Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource1Cloud.GetDeviceId(), ddResource1Cloud, events.MakeEventMeta("a", 0, 0, "hubID"))) // with cloud state - online resourceEventStore.Append(ddResource2.GetDeviceId(), commands.MakeLinksResourceUUID(ddResource2.GetDeviceId()).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{ddResource2.Resource}, ddResource2.Resource.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - resourceEventStore.Append(ddResource2.GetDeviceId(), ddResource2.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource2.Resource.GetResourceID(), ddResource2.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + resourceEventStore.Append(ddResource2.GetDeviceId(), ddResource2.Resource.ToUUID().String(), mockEvents.MakeResourceChangedEvent(ddResource2.Resource.GetResourceID(), ddResource2.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), []string{"type2"})) resourceEventStore.Append(ddResource2Cloud.GetDeviceId(), ddResource2Cloud.AggregateID(), mockEvents.MakeDeviceMetadata(ddResource2Cloud.GetDeviceId(), ddResource2Cloud, events.MakeEventMeta("a", 0, 0, "hubID"))) // without device resource diff --git a/resource-directory/service/getEventsSnapshot_test.go b/resource-directory/service/getEventsSnapshot_test.go index d4524e5ab..8a5ca80e9 100644 --- a/resource-directory/service/getEventsSnapshot_test.go +++ b/resource-directory/service/getEventsSnapshot_test.go @@ -106,8 +106,9 @@ func TestRequestHandlerGetEventsStateSnapshot(t *testing.T) { case *events.ResourceStateSnapshotTaken: pbTest.CmpResourceStateSnapshotTaken(t, &events.ResourceStateSnapshotTaken{ ResourceId: commands.NewResourceID(deviceID, lightHref), - LatestResourceChange: pbTest.MakeResourceChanged(t, deviceID, lightHref, "", makeLightData(0)), + LatestResourceChange: pbTest.MakeResourceChanged(t, deviceID, lightHref, test.TestResourceLightInstanceResourceTypes, "", makeLightData(0)), AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, event) default: assert.Fail(t, "unexpected event", "event: %v", ev) diff --git a/resource-directory/service/getEvents_test.go b/resource-directory/service/getEvents_test.go index a5f275efa..87b84f743 100644 --- a/resource-directory/service/getEvents_test.go +++ b/resource-directory/service/getEvents_test.go @@ -52,8 +52,9 @@ func getAllOnboardEvents(t *testing.T, deviceID string, links []schema.ResourceL Type: &pb.GetEventsResponse_ResourceStateSnapshotTaken{ ResourceStateSnapshotTaken: &events.ResourceStateSnapshotTaken{ ResourceId: rid, - LatestResourceChange: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), "", r.Representation), + LatestResourceChange: pbTest.MakeResourceChanged(t, deviceID, rid.GetHref(), r.ResourceTypes, "", r.Representation), AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, "", oauthService.DeviceUserID), + ResourceTypes: r.ResourceTypes, }, }, }) diff --git a/resource-directory/service/getPendingCommands_test.go b/resource-directory/service/getPendingCommands_test.go index 321ff6d91..b99d882fd 100644 --- a/resource-directory/service/getPendingCommands_test.go +++ b/resource-directory/service/getPendingCommands_test.go @@ -69,7 +69,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, }, @@ -101,7 +102,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, @@ -119,7 +121,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -130,7 +133,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -148,7 +152,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, }, @@ -169,7 +174,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: platform.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: []string{platform.ResourceType}, }, }, }, @@ -197,7 +203,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -218,7 +225,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -246,7 +254,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceLightInstanceResourceTypes, }, }, }, @@ -274,7 +283,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { "power": 1, }), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, @@ -285,7 +295,8 @@ func TestRequestHandlerGetPendingCommands(t *testing.T) { DeviceId: deviceID, Href: device.ResourceURI, }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, "", service.DeviceUserID), + ResourceTypes: test.TestResourceDeviceResourceTypes, }, }, }, diff --git a/resource-directory/service/getResources_test.go b/resource-directory/service/getResources_test.go index 3055db469..f0ac7a214 100644 --- a/resource-directory/service/getResources_test.go +++ b/resource-directory/service/getResources_test.go @@ -46,7 +46,7 @@ func TestRequestHandlerGetResources(t *testing.T) { want: []*pb.Resource{ { Types: []string{types.CORE_LIGHT}, - Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), "", + Data: pbTest.MakeResourceChanged(t, deviceID, test.TestResourceLightInstanceHref("1"), test.TestResourceLightInstanceResourceTypes, "", map[string]interface{}{ "state": false, "power": uint64(0), diff --git a/resource-directory/service/resourceDirectory_test.go b/resource-directory/service/resourceDirectory_test.go index 5fb96eabf..64e0a116c 100644 --- a/resource-directory/service/resourceDirectory_test.go +++ b/resource-directory/service/resourceDirectory_test.go @@ -111,10 +111,10 @@ func testCreateEventstore() *mockEvents.MockEventStore { store.Append(Resource1.DeviceId, commands.MakeLinksResourceUUID(Resource1.DeviceId).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{Resource1.Resource}, Resource1.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) store.Append(Resource2.DeviceId, commands.MakeLinksResourceUUID(Resource2.DeviceId).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{Resource2.Resource}, Resource2.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) store.Append(Resource3.DeviceId, commands.MakeLinksResourceUUID(Resource3.DeviceId).String(), mockEvents.MakeResourceLinksPublishedEvent([]*commands.Resource{Resource3.Resource}, Resource3.GetDeviceId(), events.MakeEventMeta("a", 0, 0, "hubID"))) - store.Append(Resource0.DeviceId, Resource0.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource0.Resource.GetResourceID(), Resource0.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) - store.Append(Resource1.DeviceId, Resource1.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource1.Resource.GetResourceID(), Resource1.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) - store.Append(Resource2.DeviceId, Resource2.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource2.Resource.GetResourceID(), Resource2.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) - store.Append(Resource3.DeviceId, Resource3.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource3.Resource.GetResourceID(), Resource3.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"))) + store.Append(Resource0.DeviceId, Resource0.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource0.Resource.GetResourceID(), Resource0.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), Resource0.ResourceTypes)) + store.Append(Resource1.DeviceId, Resource1.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource1.Resource.GetResourceID(), Resource1.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), Resource1.ResourceTypes)) + store.Append(Resource2.DeviceId, Resource2.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource2.Resource.GetResourceID(), Resource2.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), Resource2.ResourceTypes)) + store.Append(Resource3.DeviceId, Resource3.ToUUID().String(), mockEvents.MakeResourceChangedEvent(Resource3.Resource.GetResourceID(), Resource3.Content, events.MakeEventMeta("a", 0, 0, "hubID"), mockEvents.MakeAuditContext("userId", "0"), Resource3.ResourceTypes)) return store } diff --git a/resource-directory/service/resourceShadow_test.go b/resource-directory/service/resourceShadow_test.go index b5daead33..087278913 100644 --- a/resource-directory/service/resourceShadow_test.go +++ b/resource-directory/service/resourceShadow_test.go @@ -62,7 +62,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource1.DeviceId, Href: Resource1.Href, }, - Content: Resource1.Content, + Content: Resource1.Content, + ResourceTypes: Resource1.ResourceTypes, }, Types: Resource1.ResourceTypes, }, @@ -72,7 +73,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource2.DeviceId, Href: Resource2.Href, }, - Content: Resource2.Content, + Content: Resource2.Content, + ResourceTypes: Resource2.ResourceTypes, }, Types: Resource2.ResourceTypes, }, @@ -93,7 +95,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource1.DeviceId, Href: Resource1.Href, }, - Content: Resource1.Content, + Content: Resource1.Content, + ResourceTypes: Resource1.ResourceTypes, }, Types: Resource1.ResourceTypes, }, @@ -103,7 +106,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource3.DeviceId, Href: Resource3.Href, }, - Content: Resource3.Content, + Content: Resource3.Content, + ResourceTypes: Resource3.ResourceTypes, }, Types: Resource3.ResourceTypes, }, @@ -124,7 +128,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource1.DeviceId, Href: Resource1.Href, }, - Content: Resource1.Content, + Content: Resource1.Content, + ResourceTypes: Resource1.ResourceTypes, }, Types: Resource1.ResourceTypes, }, @@ -134,7 +139,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource2.DeviceId, Href: Resource2.Href, }, - Content: Resource2.Content, + Content: Resource2.Content, + ResourceTypes: Resource2.ResourceTypes, }, Types: Resource2.ResourceTypes, }, @@ -156,7 +162,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource1.DeviceId, Href: Resource1.Href, }, - Content: Resource1.Content, + Content: Resource1.Content, + ResourceTypes: Resource1.ResourceTypes, }, Types: Resource1.ResourceTypes, }, @@ -175,7 +182,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource1.DeviceId, Href: Resource1.Href, }, - Content: Resource1.Content, + Content: Resource1.Content, + ResourceTypes: Resource1.ResourceTypes, }, Types: Resource1.ResourceTypes, }, @@ -185,7 +193,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource2.DeviceId, Href: Resource2.Href, }, - Content: Resource2.Content, + Content: Resource2.Content, + ResourceTypes: Resource2.ResourceTypes, }, Types: Resource2.ResourceTypes, }, @@ -195,7 +204,8 @@ func TestResourceTwinGetResources(t *testing.T) { DeviceId: Resource3.DeviceId, Href: Resource3.Href, }, - Content: Resource3.Content, + Content: Resource3.Content, + ResourceTypes: Resource3.ResourceTypes, }, Types: Resource3.ResourceTypes, }, diff --git a/test/coap-gateway/test/defaultHandler.go b/test/coap-gateway/test/defaultHandler.go index 12a2fec30..65c6f4078 100644 --- a/test/coap-gateway/test/defaultHandler.go +++ b/test/coap-gateway/test/defaultHandler.go @@ -100,15 +100,15 @@ func (h *DefaultObserverHandler) RefreshToken(req coapgwService.CoapRefreshToken }, nil } -func (h *DefaultObserverHandler) OnObserveResource(_ context.Context, deviceID, resourceHref string, notification *pool.Message) error { - log.Debugf("OnObserveResource: %v%v", deviceID, resourceHref) +func (h *DefaultObserverHandler) OnObserveResource(_ context.Context, deviceID, resourceHref string, resourceTypes []string, notification *pool.Message) error { + log.Debugf("OnObserveResource: %v%v %v", deviceID, resourceHref, resourceTypes) msg := message.ToJson(notification, true, true) log.Get().With("notification", msg).Debug("RECEIVED-OBSERVE") return nil } -func (h *DefaultObserverHandler) OnGetResourceContent(_ context.Context, deviceID, resourceHref string, notification *pool.Message) error { - log.Debugf("OnGetResourceContent: %v%v", deviceID, resourceHref) +func (h *DefaultObserverHandler) OnGetResourceContent(_ context.Context, deviceID, resourceHref string, resourceTypes []string, notification *pool.Message) error { + log.Debugf("OnGetResourceContent: %v%v %v", deviceID, resourceHref, resourceTypes) msg := message.ToJson(notification, true, false) log.Get().With("notification", msg).Debug("RECEIVED-GET") return nil diff --git a/test/pb/pendingCommand.go b/test/pb/pendingCommand.go index d6beb7d61..54d5f9753 100644 --- a/test/pb/pendingCommand.go +++ b/test/pb/pendingCommand.go @@ -273,7 +273,7 @@ func CmpResourceCreatePending(t *testing.T, expected, got *events.ResourceCreate test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } -func MakeResourceCreatePending(t *testing.T, deviceID, href, correlationID string, data interface{}) *events.ResourceCreatePending { +func MakeResourceCreatePending(t *testing.T, deviceID, href string, resourceTypes []string, correlationID string, data interface{}) *events.ResourceCreatePending { return &events.ResourceCreatePending{ ResourceId: &commands.ResourceId{ DeviceId: deviceID, @@ -284,7 +284,8 @@ func MakeResourceCreatePending(t *testing.T, deviceID, href, correlationID strin CoapContentFormat: -1, Data: test.EncodeToCbor(t, data), }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + ResourceTypes: resourceTypes, } } @@ -313,7 +314,7 @@ func CmpResourceUpdatePending(t *testing.T, expected, got *events.ResourceUpdate test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } -func MakeResourceUpdatePending(t *testing.T, deviceID, href, correlationID string, data interface{}) *events.ResourceUpdatePending { +func MakeResourceUpdatePending(t *testing.T, deviceID, href string, resourceTypes []string, correlationID string, data interface{}) *events.ResourceUpdatePending { return &events.ResourceUpdatePending{ ResourceId: &commands.ResourceId{ DeviceId: deviceID, @@ -324,7 +325,8 @@ func MakeResourceUpdatePending(t *testing.T, deviceID, href, correlationID strin CoapContentFormat: -1, Data: test.EncodeToCbor(t, data), }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + ResourceTypes: resourceTypes, } } @@ -346,13 +348,14 @@ func CmpResourceRetrievePending(t *testing.T, expected, got *events.ResourceRetr test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } -func MakeResourceRetrievePending(deviceID, href, correlationID string) *events.ResourceRetrievePending { +func MakeResourceRetrievePending(deviceID, href string, resourceTypes []string, correlationID string) *events.ResourceRetrievePending { return &events.ResourceRetrievePending{ ResourceId: &commands.ResourceId{ DeviceId: deviceID, Href: href, }, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + ResourceTypes: resourceTypes, } } @@ -374,10 +377,11 @@ func CmpResourceDeletePending(t *testing.T, expected, got *events.ResourceDelete test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } -func MakeResourceDeletePending(deviceID, href, correlationID string) *events.ResourceDeletePending { +func MakeResourceDeletePending(deviceID, href string, resourceTypes []string, correlationID string) *events.ResourceDeletePending { return &events.ResourceDeletePending{ - ResourceId: &commands.ResourceId{DeviceId: deviceID, Href: href}, - AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + ResourceId: &commands.ResourceId{DeviceId: deviceID, Href: href}, + AuditContext: commands.NewAuditContext(oauthService.DeviceUserID, correlationID, oauthService.DeviceUserID), + ResourceTypes: resourceTypes, } } diff --git a/test/pb/resource.go b/test/pb/resource.go index d6cc02561..da32f6f4f 100644 --- a/test/pb/resource.go +++ b/test/pb/resource.go @@ -54,7 +54,7 @@ func MakeCreateSwitchResourceResponseData(id string) map[string]interface{} { } } -func MakeResourceCreated(t *testing.T, deviceID, href, correlationID string, data map[string]interface{}) *events.ResourceCreated { +func MakeResourceCreated(t *testing.T, deviceID, href string, resourceTypes []string, correlationID string, data map[string]interface{}) *events.ResourceCreated { return &events.ResourceCreated{ ResourceId: commands.NewResourceID(deviceID, href), Status: commands.Status_CREATED, @@ -68,7 +68,8 @@ func MakeResourceCreated(t *testing.T, deviceID, href, correlationID string, dat return test.EncodeToCbor(t, data) }(), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + ResourceTypes: resourceTypes, } } @@ -180,26 +181,28 @@ func makeCborContent(t *testing.T, data interface{}) *commands.Content { } } -func MakeResourceChanged(t *testing.T, deviceID, href, correlationID string, data interface{}) *events.ResourceChanged { +func MakeResourceChanged(t *testing.T, deviceID, href string, resourceTypes []string, correlationID string, data interface{}) *events.ResourceChanged { return &events.ResourceChanged{ ResourceId: &commands.ResourceId{ DeviceId: deviceID, Href: href, }, - Status: commands.Status_OK, - Content: makeCborContent(t, data), - AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + Status: commands.Status_OK, + Content: makeCborContent(t, data), + AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + ResourceTypes: resourceTypes, } } -func MakeResourceDeleted(deviceID, href, correlationID string) *events.ResourceDeleted { +func MakeResourceDeleted(deviceID, href string, resourceTypes []string, correlationID string) *events.ResourceDeleted { return &events.ResourceDeleted{ ResourceId: commands.NewResourceID(deviceID, href), Status: commands.Status_OK, Content: &commands.Content{ CoapContentFormat: int32(-1), }, - AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + ResourceTypes: resourceTypes, } } @@ -262,15 +265,16 @@ func CmpResourceDeleted(t *testing.T, expected, got *events.ResourceDeleted) { test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } -func MakeResourceRetrieved(t *testing.T, deviceID, href, correlationID string, data interface{}) *events.ResourceRetrieved { +func MakeResourceRetrieved(t *testing.T, deviceID, href string, resourceTypes []string, correlationID string, data interface{}) *events.ResourceRetrieved { return &events.ResourceRetrieved{ ResourceId: &commands.ResourceId{ DeviceId: deviceID, Href: href, }, - Status: commands.Status_OK, - Content: makeCborContent(t, data), - AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + Status: commands.Status_OK, + Content: makeCborContent(t, data), + AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + ResourceTypes: resourceTypes, } } @@ -294,7 +298,7 @@ func CmpResourceRetrieved(t *testing.T, expected, got *events.ResourceRetrieved) test.CheckProtobufs(t, expected, got, test.RequireToCheckFunc(require.Equal)) } -func MakeResourceUpdated(t *testing.T, deviceID, href, correlationID string, data interface{}) *events.ResourceUpdated { +func MakeResourceUpdated(t *testing.T, deviceID, href string, resourceTypes []string, correlationID string, data interface{}) *events.ResourceUpdated { return &events.ResourceUpdated{ ResourceId: &commands.ResourceId{ DeviceId: deviceID, @@ -309,7 +313,8 @@ func MakeResourceUpdated(t *testing.T, deviceID, href, correlationID string, dat } return makeCborContent(t, data) }(), - AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + AuditContext: commands.NewAuditContext(service.DeviceUserID, correlationID, service.DeviceUserID), + ResourceTypes: resourceTypes, } } diff --git a/test/test.go b/test/test.go index df1064c4c..cf9a5b146 100644 --- a/test/test.go +++ b/test/test.go @@ -17,6 +17,7 @@ import ( "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/acl" "github.com/plgd-dev/device/v2/schema/cloud" + "github.com/plgd-dev/device/v2/schema/collection" "github.com/plgd-dev/device/v2/schema/configuration" schemaDevice "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" @@ -48,6 +49,7 @@ import ( type ResourceLinkRepresentation struct { Href string /*`json:"href"`*/ + ResourceTypes []string /*`json:"rt"`*/ Representation interface{} /*`json:"rep"`*/ } @@ -60,57 +62,85 @@ func (d *ResourceLinkRepresentation) MarshalJSON() ([]byte, error) { } func (d *ResourceLinkRepresentation) UnmarshalJSON(data []byte) error { - reps := map[string]func(data []byte) (interface{}, error){ - configuration.ResourceURI: func(data []byte) (interface{}, error) { - var r configuration.Configuration - err := json.Decode(data, &r) - return r, err + type representation struct { + decode func(data []byte) (interface{}, error) + resourceTypes []string + } + reps := map[string]representation{ + configuration.ResourceURI: { + decode: func(data []byte) (interface{}, error) { + var r configuration.Configuration + err := json.Decode(data, &r) + return r, err + }, + resourceTypes: []string{configuration.ResourceType}, }, - schemaDevice.ResourceURI: func(data []byte) (interface{}, error) { - var r schemaDevice.Device - err := json.Decode(data, &r) - r.ProtocolIndependentID = "" - return r, err + schemaDevice.ResourceURI: { + decode: func(data []byte) (interface{}, error) { + var r schemaDevice.Device + err := json.Decode(data, &r) + r.ProtocolIndependentID = "" + return r, err + }, + resourceTypes: TestResourceDeviceResourceTypes, }, - platform.ResourceURI: func(data []byte) (interface{}, error) { - var r platform.Platform - err := json.Decode(data, &r) - r.PlatformIdentifier = "" - return r, err + platform.ResourceURI: { + decode: func(data []byte) (interface{}, error) { + var r platform.Platform + err := json.Decode(data, &r) + r.PlatformIdentifier = "" + return r, err + }, + resourceTypes: []string{platform.ResourceType}, }, - maintenance.ResourceURI: func(data []byte) (interface{}, error) { - var r MaintenanceResourceRepresentation - err := json.Decode(data, &r) - return r, err + maintenance.ResourceURI: { + decode: func(data []byte) (interface{}, error) { + var r MaintenanceResourceRepresentation + err := json.Decode(data, &r) + return r, err + }, + resourceTypes: []string{maintenance.ResourceType}, }, - plgdtime.ResourceURI: func(data []byte) (interface{}, error) { - var r PlgdTimeResourceRepresentation - err := json.Decode(data, &r) - return r, err + plgdtime.ResourceURI: { + decode: func(data []byte) (interface{}, error) { + var r PlgdTimeResourceRepresentation + err := json.Decode(data, &r) + return r, err + }, + resourceTypes: []string{plgdtime.ResourceType}, }, - TestResourceLightInstanceHref("1"): func(data []byte) (interface{}, error) { - var r LightResourceRepresentation - err := json.Decode(data, &r) - return r, err + TestResourceLightInstanceHref("1"): { + decode: func(data []byte) (interface{}, error) { + var r LightResourceRepresentation + err := json.Decode(data, &r) + return r, err + }, + resourceTypes: TestResourceLightInstanceResourceTypes, }, - TestResourceSwitchesHref: func(data []byte) (interface{}, error) { - var r schema.ResourceLinks - err := json.Decode(data, &r) - if err != nil { - return nil, err - } - r.Sort() - for i := range r { - r[i].Endpoints = nil - r[i].InstanceID = 0 - } + TestResourceSwitchesHref: { + decode: func(data []byte) (interface{}, error) { + var r schema.ResourceLinks + err := json.Decode(data, &r) + if err != nil { + return nil, err + } + r.Sort() + for i := range r { + r[i].Endpoints = nil + r[i].InstanceID = 0 + } - return r, err + return r, err + }, + resourceTypes: TestResourceSwitchesResourceTypes, }, - TestResourceSwitchesInstanceHref("1"): func(data []byte) (interface{}, error) { - var r SwitchResourceRepresentation - err := json.Decode(data, &r) - return r, err + TestResourceSwitchesInstanceHref("1"): { + decode: func(data []byte) (interface{}, error) { + var r SwitchResourceRepresentation + err := json.Decode(data, &r) + return r, err + }, + resourceTypes: TestResourceLightInstanceResourceTypes, }, } var rep struct { @@ -121,10 +151,12 @@ func (d *ResourceLinkRepresentation) UnmarshalJSON(data []byte) error { if err != nil { return err } - dec := func(data []byte) (interface{}, error) { - var r interface{} - errD := json.Decode(data, &r) - return r, errD + dec := representation{ + decode: func(data []byte) (interface{}, error) { + var r interface{} + errD := json.Decode(data, &r) + return r, errD + }, } for k, v := range reps { if strings.HasSuffix(rep.Href, k) { @@ -133,7 +165,8 @@ func (d *ResourceLinkRepresentation) UnmarshalJSON(data []byte) error { } } d.Href = rep.Href - d.Representation, err = dec(rep.Rep) + d.ResourceTypes = dec.resourceTypes + d.Representation, err = dec.decode(rep.Rep) if err != nil { return err } @@ -147,6 +180,11 @@ var ( TestDeviceSoftwareVersion = "1.0.1-rc1" TestDeviceType device.Type + TestResourceSwitchesInstanceResourceTypes = []string{types.BINARY_SWITCH} + TestResourceSwitchesResourceTypes = []string{collection.ResourceType} + TestResourceLightInstanceResourceTypes = []string{types.CORE_LIGHT} + TestResourceDeviceResourceTypes = []string{types.DEVICE_CLOUD, schemaDevice.ResourceType} + testIovityLiteVersion *sync.Map[string, uint32] ) @@ -209,7 +247,7 @@ func GetDeviceResourceRepresentation(deviceID, deviceName string) schemaDevice.D ID: deviceID, Interfaces: []string{interfaces.OC_IF_R, interfaces.OC_IF_BASELINE}, Name: deviceName, - ResourceTypes: []string{types.DEVICE_CLOUD, schemaDevice.ResourceType}, + ResourceTypes: TestResourceDeviceResourceTypes, DataModelVersion: "ocf.res.1.3.0", SpecificationVersion: "ocf.2.0.5", ModelNumber: TestDeviceModelNumber, @@ -239,20 +277,24 @@ func GetAllBackendResourceRepresentations(t *testing.T, deviceID, deviceName str Power: 0, State: false, }, + ResourceTypes: TestResourceLightInstanceResourceTypes, }, { Href: "/" + commands.NewResourceID(deviceID, configuration.ResourceURI).ToString(), Representation: configuration.Configuration{ Name: deviceName, }, + ResourceTypes: []string{configuration.ResourceType}, }, { Href: "/" + commands.NewResourceID(deviceID, schemaDevice.ResourceURI).ToString(), Representation: dev, + ResourceTypes: TestResourceDeviceResourceTypes, }, { Href: "/" + commands.NewResourceID(deviceID, maintenance.ResourceURI).ToString(), Representation: MaintenanceResourceRepresentation{}, + ResourceTypes: []string{maintenance.ResourceType}, }, { Href: "/" + commands.NewResourceID(deviceID, platform.ResourceURI).ToString(), @@ -260,14 +302,17 @@ func GetAllBackendResourceRepresentations(t *testing.T, deviceID, deviceName str ManufacturerName: "ocfcloud.com", Version: iotVersion, }, + ResourceTypes: []string{platform.ResourceType}, }, { Href: "/" + commands.NewResourceID(deviceID, TestResourceSwitchesHref).ToString(), Representation: schema.ResourceLinks{}, + ResourceTypes: []string{collection.ResourceType}, }, { Href: "/" + commands.NewResourceID(deviceID, plgdtime.ResourceURI).ToString(), Representation: PlgdTimeResourceRepresentation{}, + ResourceTypes: []string{plgdtime.ResourceType}, }, { Href: "/" + commands.NewResourceID(deviceID, softwareupdate.ResourceURI).ToString(), @@ -280,6 +325,7 @@ func GetAllBackendResourceRepresentations(t *testing.T, deviceID, deviceName str "swupdateresult": uint64(0), "updatetime": "1970-01-01T00:00:00Z", }, + ResourceTypes: []string{softwareupdate.ResourceType}, }, } } @@ -298,7 +344,7 @@ func DefaultSwitchResourceLink(deviceID, id string) schema.ResourceLink { return schema.ResourceLink{ DeviceID: deviceID, Href: TestResourceSwitchesInstanceHref(id), - ResourceTypes: []string{types.BINARY_SWITCH}, + ResourceTypes: TestResourceSwitchesInstanceResourceTypes, Interfaces: []string{interfaces.OC_IF_A, interfaces.OC_IF_BASELINE}, Policy: &schema.Policy{ BitMask: schema.Discoverable | schema.Observable, @@ -738,8 +784,9 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, CorrelationId: correlationID, Type: &pb.Event_ResourceChanged{ ResourceChanged: &events.ResourceChanged{ - ResourceId: commands.NewResourceID(deviceID, r.Href), - Status: commands.Status_OK, + ResourceId: commands.NewResourceID(deviceID, r.Href), + Status: commands.Status_OK, + ResourceTypes: r.ResourceTypes, }, }, } From 9a6468febafa6bcc3f1cb16e25c923b7ea32bddb Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Wed, 1 May 2024 21:38:07 +0200 Subject: [PATCH 28/31] Update GitHub actions golangci/golangci-lint-action: v4 -> v5 --- .github/workflows/golangci-lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 313bb1dae..54abad392 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -30,7 +30,7 @@ jobs: - run: go version - name: golangci-lint - uses: golangci/golangci-lint-action@v4 + uses: golangci/golangci-lint-action@v5 with: version: latest args: --timeout=5m From 331c4dbb67d7b6dfebbf239293a7d37ec6e720c6 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Thu, 2 May 2024 08:54:37 +0200 Subject: [PATCH 29/31] Upgrade dependencies Submodule: github.com/googleapis/googleapis 7002406181eb300da880701035a25157a5099abb Direct: github.com/go-co-op/gocron/v2 v2.3.0 github.com/pion/dtls/v2 v2.2.8-0.20240501061905-2c36d63320a0 github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b github.com/plgd-dev/go-coap/v3 v3.3.4 go.mongodb.org/mongo-driver v1.15.0 golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f golang.org/x/net v0.24.0 golang.org/x/oauth2 v0.19.0 golang.org/x/sync v0.7.0 google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.34.0 Indirect: github.com/bufbuild/protocompile v0.13.0 github.com/jhump/protoreflect v1.16.0 github.com/klauspost/compress v1.17.8 go.opentelemetry.io/proto/otlp v1.2.0 golang.org/x/crypto v0.22.0 golang.org/x/sys v0.19.0 google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6 --- .golangci.yml | 8 +-- dependency/googleapis | 2 +- go.mod | 65 ++++++++++++----------- go.sum | 98 ++++++++++++++--------------------- pkg/net/grpc/client/client.go | 1 - 5 files changed, 80 insertions(+), 94 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 26c9aef22..5a273e2d1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -3,9 +3,6 @@ linters-settings: default-signifies-exhaustive: true gocyclo: min-complexity: 15 - gomoddirectives: - replace-allow-list: - - github.com/pion/dtls/v2 gomodguard: blocked: modules: @@ -53,7 +50,7 @@ linters: - gofumpt # Gofumpt checks whether code was gofumpt-ed. - goheader # Checks is file header matches to pattern - goimports # Goimports does everything that gofmt does. Additionally it checks unused imports - - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. + # - gomoddirectives # Manage the use of 'replace', 'retract', and 'excludes' directives in go.mod. - gomodguard # Allow and block list linter for direct Go module dependencies. This is different from depguard where there are different block types for example version constraints and module recommendations. - goprintffuncname # Checks that printf-like functions are named with `f` at the end - gosec # Inspects source code for security problems @@ -135,6 +132,9 @@ issues: exclude-dirs: - dependency - http-gateway/grpc-websocket-proxy + exclude-files: + - ".*\\.pb\\.go$" + - ".*\\.pb\\.gw\\.go$" exclude-rules: - path: _test.go linters: diff --git a/dependency/googleapis b/dependency/googleapis index 1406704ce..700240618 160000 --- a/dependency/googleapis +++ b/dependency/googleapis @@ -1 +1 @@ -Subproject commit 1406704ced81daab07a859aa8a870ff39432d370 +Subproject commit 7002406181eb300da880701035a25157a5099abb diff --git a/go.mod b/go.mod index 7e6e020c3..41c5cdb1d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/fullstorydev/grpchan v1.1.1 github.com/fxamacker/cbor/v2 v2.6.0 - github.com/go-co-op/gocron/v2 v2.2.9 + github.com/go-co-op/gocron/v2 v2.3.0 github.com/gocql/gocql v1.6.0 github.com/golang-jwt/jwt/v5 v5.2.1 github.com/golang/snappy v0.0.4 @@ -26,10 +26,10 @@ require ( github.com/lestrrat-go/jwx/v2 v2.0.21 github.com/nats-io/nats.go v1.34.1 github.com/panjf2000/ants/v2 v2.9.1 - github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 + github.com/pion/dtls/v2 v2.2.8-0.20240501061905-2c36d63320a0 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.4.5-0.20240412110951-d7aeb36bc7ba - github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 + github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b + github.com/plgd-dev/go-coap/v3 v3.3.4 github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 github.com/sirupsen/logrus v1.9.3 @@ -38,7 +38,7 @@ require ( github.com/tidwall/sjson v1.2.5 github.com/ugorji/go/codec v1.2.12 github.com/vincent-petithory/dataurl v1.0.0 - go.mongodb.org/mongo-driver v1.14.0 + go.mongodb.org/mongo-driver v1.15.0 go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 @@ -49,25 +49,23 @@ require ( go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/atomic v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 - golang.org/x/net v0.23.0 - golang.org/x/oauth2 v0.18.0 - golang.org/x/sync v0.6.0 - google.golang.org/api v0.172.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda - google.golang.org/grpc v1.63.0 + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f + golang.org/x/net v0.24.0 + golang.org/x/oauth2 v0.19.0 + golang.org/x/sync v0.7.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 + google.golang.org/grpc v1.63.2 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.33.0 + google.golang.org/protobuf v1.34.0 gopkg.in/yaml.v3 v3.0.1 ) require ( cloud.google.com/go/compute v1.25.1 // indirect - cloud.google.com/go/compute/metadata v0.2.3 // indirect github.com/Masterminds/semver v1.4.2 // indirect github.com/Masterminds/sprig v2.15.0+incompatible // indirect github.com/aokoli/goutils v1.0.1 // indirect - github.com/bufbuild/protocompile v0.9.0 // indirect + github.com/bufbuild/protocompile v0.13.0 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect @@ -77,19 +75,15 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/s2a-go v0.1.7 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.3 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/huandu/xstrings v1.0.0 // indirect github.com/imdario/mergo v0.3.4 // indirect - github.com/jhump/protoreflect v1.15.6 // indirect + github.com/jhump/protoreflect v1.16.0 // indirect github.com/jonboulle/clockwork v0.4.0 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.5 // indirect @@ -113,18 +107,29 @@ require ( github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect - go.opentelemetry.io/proto/otlp v1.1.0 // indirect + go.opentelemetry.io/proto/otlp v1.2.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.21.0 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/crypto v0.22.0 // indirect + golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6 // indirect gopkg.in/inf.v0 v0.9.1 // indirect ) -// note: github.com/pion/dtls/v2/pkg/net package is not yet available in release branches, -// so we force to the use of the pinned master branch -replace github.com/pion/dtls/v2 => github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 +replace ( + // note: github.com/pion/dtls/v2/pkg/net package is not yet available in release branches, + // so we force to the use of the pinned master branch + github.com/pion/dtls/v2 => github.com/pion/dtls/v2 v2.2.8-0.20240501061905-2c36d63320a0 + // later versions require go 1.22 + github.com/youmark/pkcs8 => github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a + // later versions require go 1.21 + go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo => go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc => go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp => go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 + go.opentelemetry.io/otel => go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc => go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 + go.opentelemetry.io/otel/metric => go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk => go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace => go.opentelemetry.io/otel/trace v1.24.0 +) diff --git a/go.sum b/go.sum index 2aad31e67..76fbaf440 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= 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/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -16,8 +16,8 @@ github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYE github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bufbuild/protocompile v0.9.0 h1:DI8qLG5PEO0Mu1Oj51YFPqtx6I3qYXUAhJVJ/IzAVl0= -github.com/bufbuild/protocompile v0.9.0/go.mod h1:s89m1O8CqSYpyE/YaSGtg1r1YFMF5nLTwh4vlj6O444= +github.com/bufbuild/protocompile v0.13.0 h1:6cwUB0Y2tSvmNxsbunwzmIto3xOlJOV7ALALuVOs92M= +github.com/bufbuild/protocompile v0.13.0/go.mod h1:dr++fGGeMPWHv7jPeT06ZKukm45NJscd7rUxQVzEKRk= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= @@ -55,8 +55,8 @@ github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrt github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= -github.com/go-co-op/gocron/v2 v2.2.9 h1:aoKosYWSSdXFLecjFWX1i8+R6V7XdZb8sB2ZKAY5Yis= -github.com/go-co-op/gocron/v2 v2.2.9/go.mod h1:mZx3gMSlFnb97k3hRqX3+GdlG3+DUwTh6B8fnsTScXg= +github.com/go-co-op/gocron/v2 v2.3.0 h1:UmXdUuql3h/+JN3rFDhZdDvgeCjR+r/zrSsQNZje8uo= +github.com/go-co-op/gocron/v2 v2.3.0/go.mod h1:ckPQw96ZuZLRUGu88vVpd9a6d9HakI14KWahFZtGvNw= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -81,9 +81,6 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69 github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 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= @@ -95,9 +92,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W 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.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -109,22 +104,15 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw 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.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= -github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA= -github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= @@ -155,8 +143,8 @@ github.com/jhump/gopoet v0.0.0-20190322174617-17282ff210b3/go.mod h1:me9yfT6IJSl github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jhump/protoreflect v1.11.0/go.mod h1:U7aMIjN0NWq9swDP7xDdoMfRHb35uiuTd3Z9nFXJf5E= -github.com/jhump/protoreflect v1.15.6 h1:WMYJbw2Wo+KOWwZFvgY0jMoVHM6i4XIvRs2RcBj5VmI= -github.com/jhump/protoreflect v1.15.6/go.mod h1:jCHoyYQIJnaabEYnbGwyo9hUqfyUMTbJw/tAut5t97E= +github.com/jhump/protoreflect v1.16.0 h1:54fZg+49widqXYQ0b+usAFHbMkBGR4PpXrsHc8+TBDg= +github.com/jhump/protoreflect v1.16.0/go.mod h1:oYPd7nPvcBw/5wlDfm/AVmU9zH9BgqGCI469pGxfj/8= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -171,8 +159,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 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= @@ -216,20 +204,20 @@ github.com/panjf2000/ants/v2 v2.4.3/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OI github.com/panjf2000/ants/v2 v2.9.1 h1:Q5vh5xohbsZXGcD6hhszzGqB7jSSc2/CRr3QKIga8Kw= github.com/panjf2000/ants/v2 v2.9.1/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01 h1:Yiqcf3WfIu66j820RdYDjnnTsrDwMKYsuqFvzDJn4uk= -github.com/pion/dtls/v2 v2.2.8-0.20240327211025-8244c4570c01/go.mod h1:eLnUKAwQ5J17w2P583p4UXWBlOK5OkkLY7sXZANcwj0= +github.com/pion/dtls/v2 v2.2.8-0.20240501061905-2c36d63320a0 h1:050ahk2K4HqwxPi2YM6Yc4lIttwNSY2+n9xPVsS3zoQ= +github.com/pion/dtls/v2 v2.2.8-0.20240501061905-2c36d63320a0/go.mod h1:tjBBbkwKGSQQZl36HQa2va5HqR9rWhujhlJMrgE2b/o= github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkLg4= github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.4.5-0.20240412110951-d7aeb36bc7ba h1:yj1G0KaKRe88A3flQ8RHE0fxo/M+oEBFPrktCBgqpZc= -github.com/plgd-dev/device/v2 v2.4.5-0.20240412110951-d7aeb36bc7ba/go.mod h1:vkQxyY8+PsKdkh/4TGP6hq3T37jd1pLvIR7XS83WyMg= +github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b h1:AF0/TUHEdt/fqQT0GjEoIXe53XB8qsOHzOu6Npg19Ig= +github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b/go.mod h1:y/OnxPhE+FLRcme8i0/bEpeP8qWO8+KFRpU6nTgsozo= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= -github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79 h1:Kaf/67M7+UVsRbNHQx3DDOLzpDI6RE/oYZz2v+a4csg= -github.com/plgd-dev/go-coap/v3 v3.3.4-0.20240404104253-8d54d1cdfc79/go.mod h1:UKObEIXVvPfdNGv7QoKegxPwT12UBy26tNUEOebFkls= +github.com/plgd-dev/go-coap/v3 v3.3.4 h1:clDLFOXXmXfhZqB0eSk6WJs2iYfjC2J22Ixwu5MHiO0= +github.com/plgd-dev/go-coap/v3 v3.3.4/go.mod h1:vxBvAgXxL+Au/58XYTM+8ftqO/ycFC9/Dh+uI72xYjA= github.com/plgd-dev/kit v0.0.0-20200819113605-d5fcf3e94f63/go.mod h1:Yl9zisyXfPdtP9hTWlJqjJYXmgU/jtSDKttz9/CeD90= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 h1:TC1HJ/UbyflJFPvaOdGmNZ5TeFGex1/dyr9urNGLy7M= github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90/go.mod h1:Z7oKFLSGQjdi8eInxwFCs0tSApuEM1o0qNck+sJYp4M= @@ -262,7 +250,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= @@ -299,10 +286,8 @@ github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= -go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= +go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 h1:qF3LdpkD3Kbaw0Smsh+SVcJI/mtYGz9ZdCmu0YF2Lo4= go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0/go.mod h1:eqNF9g7W06ubrU7jk6M6UW9OTrcSPZvVY10cw9DUJ7c= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= @@ -321,8 +306,8 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= -go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= -go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= +go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= +go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -350,11 +335,12 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= +golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= 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= @@ -379,7 +365,6 @@ golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210502030024-e5908800b52b/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -387,12 +372,12 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= 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.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= +golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= 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= @@ -402,8 +387,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -423,14 +408,16 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/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/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -463,30 +450,25 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk= -google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis= 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.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 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-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda h1:b6F6WIV4xHHD0FA4oIyzU6mHWg2WI2X1RBehwa5QN38= -google.golang.org/genproto/googleapis/api v0.0.0-20240401170217-c3f982113cda/go.mod h1:AHcE/gZH76Bk/ROZhQphlRoWo5xKDEtz3eVEO1LfA8c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda h1:LI5DOvAxUPMv/50agcLLoo+AdWc1irS9Rzz4vPuD1V4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240401170217-c3f982113cda/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6 h1:DTJM0R8LECCgFeUwApvcEJHz85HLagW8uRENYxHh1ww= +google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6/go.mod h1:10yRODfgim2/T8csjQsMPgZOMvtytXKTDRzH6HRGzRw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6 h1:DujSIu+2tC9Ht0aPNA7jgj23Iq8Ewi5sgkQ++wdvonE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= 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.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8= -google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -500,8 +482,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= +google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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= diff --git a/pkg/net/grpc/client/client.go b/pkg/net/grpc/client/client.go index 87952f0b6..30ca18856 100644 --- a/pkg/net/grpc/client/client.go +++ b/pkg/net/grpc/client/client.go @@ -60,7 +60,6 @@ func New(ctx context.Context, config Config, fileWatcher *fsnotify.Watcher, logg v = append(v, opts...) } - //nolint:staticcheck // TODO: update once the replacement is available conn, err := grpc.DialContext(ctx, config.Addr, v...) if err != nil { return nil, fmt.Errorf("cannot dial: %w", err) From 7cfb6e51e3e3e541265ca490485d7bf9cf1f3944 Mon Sep 17 00:00:00 2001 From: Daniel Adam Date: Wed, 15 May 2024 09:17:32 +0200 Subject: [PATCH 30/31] http-gateway: Implement Web of Things Interface ## New Features - **/things Endpoint**: Introduced a new endpoint, `/things`, to retrieve resource links for devices. This endpoint provides a standardized way to access and interact with connected devices. ## Tests - **Endpoint Testing**: Added comprehensive tests for the new `/things` endpoint. These tests ensure that device resources are properly retrieved and formatted, maintaining robustness and reliability in various scenarios. ## Refactor - **JSON Unmarshalling**: Enhanced the JSON unmarshalling process in HTTP gateway tests. This improvement focuses on better error handling and more efficient processing of JSON data, contributing to overall test stability and readability. ## Documentation - **Updated Documentation**: Revised the documentation to reflect changes in the usage of constants and parameters during virtual device creation. The updates include support for conditional resource addition based on the availability of device descriptions, making the documentation more accurate and helpful. ## New Endpoints - **/api/v1/things**: Implemented the `/api/v1/things` endpoint to list all device resources. - **/api/v1/things/{deviceID}**: Implemented the `/api/v1/things/{deviceID}` endpoint to access resources specific to a device identified by `deviceID`. ## Miscellaneous - **Golang Upgrade**: Upgraded the Golang version to 1.22, ensuring compatibility with the latest features and improvements in the Go ecosystem. --------- Co-authored-by: Jozef Kralik --- .github/workflows/builds.yml | 6 +- .github/workflows/checkFormat.yml | 2 +- .github/workflows/golangci-lint.yml | 2 +- .github/workflows/staticAnalysis.yml | 2 +- .github/workflows/test.yml | 8 + .golangci.yml | 2 +- .vscode/settings.json | 3 +- Dockerfile.test | 2 +- Makefile | 62 ++- bundle/Dockerfile | 2 +- .../observation/deviceObserver_test.go | 7 +- go.mod | 9 +- go.sum | 31 +- http-gateway/Dockerfile | 4 +- http-gateway/service/deleteDevice.go | 2 +- http-gateway/service/getDevice.go | 28 +- .../service/getDeviceResourceLinks.go | 2 +- http-gateway/service/getResource.go | 122 ++++- http-gateway/service/getResource_test.go | 78 +++ http-gateway/service/getThings.go | 392 +++++++++++++++ http-gateway/service/getThings_test.go | 452 ++++++++++++++++++ .../service/getWebConfiguration_test.go | 16 +- http-gateway/service/requestHandler.go | 33 +- http-gateway/service/service.go | 2 +- http-gateway/service/updateResource.go | 12 +- http-gateway/service/updateResource_test.go | 106 +++- http-gateway/swagger.yaml | 9 + http-gateway/test/http.go | 5 + http-gateway/test/test.go | 20 +- http-gateway/uri/uri.go | 9 + test/bridge-device/bridge-device.jsonld | 8 + test/bridge-device/config.yaml | 19 + test/cloud-server/Dockerfile | 2 +- test/device/bridge/device.go | 43 +- test/device/device.go | 25 +- test/device/ocf/device.go | 4 + test/test.go | 54 ++- test/thingDescription.go | 33 ++ test/virtual-device/virtualDevice.go | 22 +- tools/cert-tool/Dockerfile | 2 +- tools/docker/Dockerfile.in | 2 +- 41 files changed, 1528 insertions(+), 116 deletions(-) create mode 100644 http-gateway/service/getThings.go create mode 100644 http-gateway/service/getThings_test.go create mode 100644 test/bridge-device/bridge-device.jsonld create mode 100644 test/bridge-device/config.yaml create mode 100644 test/thingDescription.go diff --git a/.github/workflows/builds.yml b/.github/workflows/builds.yml index 844e49223..da7cc5758 100644 --- a/.github/workflows/builds.yml +++ b/.github/workflows/builds.yml @@ -12,8 +12,8 @@ jobs: matrix: include: # check support for oldest supported golang version - - name: go1.20 - go-version: "~1.20" + - name: go1.22 + go-version: "~1.22" runs-on: ubuntu-latest steps: - name: Checkout @@ -22,7 +22,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: ${{ matrix.go-version || '^1.20' }} + go-version: ${{ matrix.go-version || '^1.22' }} check-latest: true - run: | diff --git a/.github/workflows/checkFormat.yml b/.github/workflows/checkFormat.yml index d81d5976e..a6226037e 100644 --- a/.github/workflows/checkFormat.yml +++ b/.github/workflows/checkFormat.yml @@ -22,7 +22,7 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v5 with: - go-version: "^1.20" # The Go version to download (if necessary) and use. + go-version: "^1.22" # The Go version to download (if necessary) and use. check-latest: true - name: Check formatting diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 54abad392..6a7b33e10 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -24,7 +24,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: "^1.20" # The Go version to download (if necessary) and use. + go-version: "^1.22" # The Go version to download (if necessary) and use. check-latest: true cache: false diff --git a/.github/workflows/staticAnalysis.yml b/.github/workflows/staticAnalysis.yml index e32c75abf..8acc7d31f 100644 --- a/.github/workflows/staticAnalysis.yml +++ b/.github/workflows/staticAnalysis.yml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: "^1.20" # The Go version to download (if necessary) and use. + go-version: "^1.22" # The Go version to download (if necessary) and use. check-latest: true - run: go version diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 418962e3c..5c7139d79 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -98,6 +98,14 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + # login to ghcr.io so we can download device/bridge-device package + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Run a test run: | make ${{ matrix.cmd }} TEST_CHECK_RACE=${{ matrix.checkRace }} \ diff --git a/.golangci.yml b/.golangci.yml index 5a273e2d1..9a83c0b0a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -173,4 +173,4 @@ issues: # fix: true run: - go: "1.20" + go: "1.22" diff --git a/.vscode/settings.json b/.vscode/settings.json index b9dead665..cfa605fd3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -35,7 +35,8 @@ "TEST_IDENTITY_STORE_LOG_LEVEL": "info", "TEST_IDENTITY_STORE_LOG_DUMP_BODY": "false", "TEST_DATABASE": "mongoDB", - // "TEST_DEVICE_NAME": "bridged-device", + "TEST_BRIDGE_DEVICE_CONFIG": "${workspaceFolder}/.tmp/bridge/config-test.yaml", + // "TEST_DEVICE_NAME": "bridged-device-0", // "TEST_DEVICE_TYPE": "bridged", // "GODEBUG": "scavtrace=1", // "TEST_COAP_GATEWAY_UDP_ENABLED": "true", diff --git a/Dockerfile.test b/Dockerfile.test index 6de8e49e3..620c3a696 100644 --- a/Dockerfile.test +++ b/Dockerfile.test @@ -6,7 +6,7 @@ RUN apt-get update \ # apt: ca-certificates git make sudo RUN git clone https://github.com/udhos/update-golang.git \ && cd update-golang \ - && sudo RELEASE=1.20.14 ./update-golang.sh \ + && sudo RELEASE=1.22.3 ./update-golang.sh \ && ln -s /usr/local/go/bin/go /usr/bin/go WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ diff --git a/Makefile b/Makefile index 0393820b2..c193868d7 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ TEST_DATABASE ?= mongodb CERT_TOOL_SIGN_ALG ?= ECDSA-SHA256 # supported values: P256, P384, P521 CERT_TOOL_ELLIPTIC_CURVE ?= P256 -CERT_TOOL_IMAGE=ghcr.io/plgd-dev/hub/cert-tool:vnext +CERT_TOOL_IMAGE = ghcr.io/plgd-dev/hub/cert-tool:vnext SUBDIRS := bundle certificate-authority cloud2cloud-connector cloud2cloud-gateway coap-gateway grpc-gateway resource-aggregate resource-directory http-gateway identity-store test/oauth-server tools/cert-tool .PHONY: $(SUBDIRS) push proto/generate clean build test env mongo nats certificates hub-build http-gateway-www simulators @@ -225,6 +225,64 @@ simulators: simulators/clean $(call RUN-DOCKER-DEVICE,$(DEVICE_SIMULATOR_RES_OBSERVABLE_NAME),$(DEVICE_SIMULATOR_RES_OBSERVABLE_IMG)) .PHONY: simulators +BRIDGE_DEVICE_SRC_DIR = $(WORKING_DIRECTORY)/test/bridge-device +BRIDGE_DEVICE_IMAGE = ghcr.io/plgd-dev/device/bridge-device:vnext +BRIDGE_DEVICE_NAME = bridgedev +BRIDGE_DEVICE_ID ?= 8f596b43-29c0-4147-8b40-e99268ab30f7 +BRIDGE_DEVICE_RESOURCES_PER_DEVICE ?= 3 +BRIDGE_DEVICES_COUNT ?= 3 + +define SET-BRIDGE-DEVICE-CONFIG + yq -i '.apis.coap.id = "$(BRIDGE_DEVICE_ID)"' $(1) + yq -i '.apis.coap.externalAddresses=["127.0.0.1:15683","[::1]:15683"]' $(1) + yq -i '.cloud.enabled=true' $(1) + yq -i '.cloud.cloudID="$(CLOUD_SID)"' $(1) + yq -i '.cloud.tls.caPoolPath="$(2)/certs/root_ca.crt"' $(1) + yq -i '.cloud.tls.keyPath="$(2)/certs/coap.key"' $(1) + yq -i '.cloud.tls.certPath="$(2)/certs/coap.crt"' $(1) + yq -i '.numGeneratedBridgedDevices=$(BRIDGE_DEVICES_COUNT)' $(1) + yq -i '.numResourcesPerDevice=$(BRIDGE_DEVICE_RESOURCES_PER_DEVICE)' $(1) + yq -i '.thingDescription.enabled=true' $(1) + yq -i '.thingDescription.file="$(2)/bridge/bridge-device.jsonld"' $(1) +endef + +# config-docker.yaml -> copy of configuration with paths valid inside docker container +# config-test.yaml -> copy of configuration with paths valid on host machine +simulators/bridge/env: simulators/bridge/clean certificates + mkdir -p $(WORKING_DIRECTORY)/.tmp/bridge + cp $(BRIDGE_DEVICE_SRC_DIR)/bridge-device.jsonld $(WORKING_DIRECTORY)/.tmp/bridge/ + cp $(BRIDGE_DEVICE_SRC_DIR)/config.yaml $(WORKING_DIRECTORY)/.tmp/bridge/config-docker.yaml + $(call SET-BRIDGE-DEVICE-CONFIG,$(WORKING_DIRECTORY)/.tmp/bridge/config-docker.yaml,) + cp $(BRIDGE_DEVICE_SRC_DIR)/config.yaml $(WORKING_DIRECTORY)/.tmp/bridge/config-test.yaml + $(call SET-BRIDGE-DEVICE-CONFIG,$(WORKING_DIRECTORY)/.tmp/bridge/config-test.yaml,$(WORKING_DIRECTORY)/.tmp) + +.PHONY: simulators/bridge/env + +define RUN-BRIDGE-DOCKER-DEVICE + docker pull $(BRIDGE_DEVICE_IMAGE) ; \ + docker run \ + -d \ + --name=$(BRIDGE_DEVICE_NAME) \ + --network=host \ + -v $(WORKING_DIRECTORY)/.tmp/certs:/certs \ + -v $(WORKING_DIRECTORY)/.tmp/bridge:/bridge \ + $(BRIDGE_DEVICE_IMAGE) -config /bridge/config-docker.yaml +endef + +simulators/bridge: simulators/bridge/env + $(call RUN-BRIDGE-DOCKER-DEVICE) + +.PHONY: simulators/bridge + +simulators/bridge/clean: + rm -rf $(WORKING_DIRECTORY)/.tmp/bridge || : + $(call REMOVE-DOCKER-DEVICE,$(BRIDGE_DEVICE_NAME)) + +.PHONY: simulators/bridge/clean + +simulators: simulators/bridge +simulators/clean: simulators/bridge/clean + env/test/mem: clean certificates nats mongo privateKeys scylla .PHONY: env/test/mem @@ -235,6 +293,7 @@ define RUN-DOCKER docker run \ --rm \ --network=host \ + -v $(WORKING_DIRECTORY)/.tmp/bridge:/bridge \ -v $(WORKING_DIRECTORY)/.tmp/certs:/certs \ -v $(WORKING_DIRECTORY)/.tmp/coverage:/coverage \ -v $(WORKING_DIRECTORY)/.tmp/report:/report \ @@ -253,6 +312,7 @@ define RUN-DOCKER -e TEST_OAUTH_SERVER_ID_TOKEN_PRIVATE_KEY=/privKeys/idTokenKey.pem \ -e TEST_OAUTH_SERVER_ACCESS_TOKEN_PRIVATE_KEY=/privKeys/accessTokenKey.pem \ -e TEST_HTTP_GW_WWW_ROOT=/usr/local/www \ + -e TEST_BRIDGE_DEVICE_CONFIG=/bridge/config-docker.yaml \ hub-test \ $(1) ; endef diff --git a/bundle/Dockerfile b/bundle/Dockerfile index 8ca905053..a31a14308 100644 --- a/bundle/Dockerfile +++ b/bundle/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.14-alpine AS build +FROM golang:1.22.3-alpine AS build RUN apk add --no-cache curl git build-base WORKDIR $GOPATH/src/github.com/plgd-dev/hub COPY go.mod go.sum ./ diff --git a/coap-gateway/service/observation/deviceObserver_test.go b/coap-gateway/service/observation/deviceObserver_test.go index 19561a498..04e3e489a 100644 --- a/coap-gateway/service/observation/deviceObserver_test.go +++ b/coap-gateway/service/observation/deviceObserver_test.go @@ -34,6 +34,7 @@ import ( coapgwTestService "github.com/plgd-dev/hub/v2/test/coap-gateway/service" coapgwTest "github.com/plgd-dev/hub/v2/test/coap-gateway/test" "github.com/plgd-dev/hub/v2/test/config" + "github.com/plgd-dev/hub/v2/test/device/ocf" oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" pbTest "github.com/plgd-dev/hub/v2/test/pb" "github.com/plgd-dev/hub/v2/test/service" @@ -299,13 +300,13 @@ func testPreregisterVirtualDevice(ctx context.Context, t *testing.T, deviceID st require.NoError(t, err) require.NotEmpty(t, ev.GetOperationProcessed()) require.Equal(t, pb.Event_OperationProcessed_ErrorStatus_OK, ev.GetOperationProcessed().GetErrorStatus().GetCode()) - virtualdevice.CreateDevice(ctx, t, "name-"+deviceID, deviceID, numResources, test.StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME), isClient, raClient) - resources := virtualdevice.CreateDeviceResourceLinks(deviceID, numResources) + virtualdevice.CreateDevice(ctx, t, "name-"+deviceID, deviceID, numResources, false, test.StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME), isClient, raClient) + resources := virtualdevice.CreateDeviceResourceLinks(deviceID, numResources, false) links := make([]schema.ResourceLink, 0, len(resources)) for _, r := range resources { links = append(links, r.ToSchema()) } - test.WaitForDevice(t, client, deviceID, ev.GetSubscriptionId(), ev.GetCorrelationId(), links) + test.WaitForDevice(t, client, ocf.NewDevice(deviceID, test.TestDeviceName), ev.GetSubscriptionId(), ev.GetCorrelationId(), links) } func testValidateResourceLinks(ctx context.Context, t *testing.T, deviceID string, grpcClient pb.GrpcGatewayClient, _ raPb.ResourceAggregateClient) { diff --git a/go.mod b/go.mod index 41c5cdb1d..7de771a99 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,8 @@ module github.com/plgd-dev/hub/v2 -go 1.20 +go 1.22 + +toolchain go1.22.0 require ( github.com/favadi/protoc-go-inject-tag v1.4.0 @@ -28,7 +30,7 @@ require ( github.com/panjf2000/ants/v2 v2.9.1 github.com/pion/dtls/v2 v2.2.8-0.20240501061905-2c36d63320a0 github.com/pion/logging v0.2.2 - github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b + github.com/plgd-dev/device/v2 v2.5.1-0.20240513064831-b553d1a87e1c github.com/plgd-dev/go-coap/v3 v3.3.4 github.com/plgd-dev/kit/v2 v2.0.0-20211006190727-057b33161b90 github.com/pseudomuto/protoc-gen-doc v1.5.1 @@ -38,6 +40,7 @@ require ( github.com/tidwall/sjson v1.2.5 github.com/ugorji/go/codec v1.2.12 github.com/vincent-petithory/dataurl v1.0.0 + github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510130416-741fef736e1e go.mongodb.org/mongo-driver v1.15.0 go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo v0.49.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 @@ -71,6 +74,8 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/dsnet/golib/memfile v1.0.0 // indirect github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect + github.com/fredbi/uri v1.1.0 // indirect + github.com/go-json-experiment/json v0.0.0-20240418180308-af2d5061e6c2 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/goccy/go-json v0.10.2 // indirect diff --git a/go.sum b/go.sum index 76fbaf440..588ba6832 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= 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/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -44,8 +45,12 @@ github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/favadi/protoc-go-inject-tag v1.4.0 h1:K3KXxbgRw5WT4f43LbglARGz/8jVsDOS7uMjG4oNvXY= github.com/favadi/protoc-go-inject-tag v1.4.0/go.mod h1:AZ+PK+QDKUOLlBRG0rYiKkUX5Hw7+7GTFzlU99GFSbQ= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= +github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= @@ -57,6 +62,8 @@ github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXE github.com/go-acme/lego v2.7.2+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= github.com/go-co-op/gocron/v2 v2.3.0 h1:UmXdUuql3h/+JN3rFDhZdDvgeCjR+r/zrSsQNZje8uo= github.com/go-co-op/gocron/v2 v2.3.0/go.mod h1:ckPQw96ZuZLRUGu88vVpd9a6d9HakI14KWahFZtGvNw= +github.com/go-json-experiment/json v0.0.0-20240418180308-af2d5061e6c2 h1:lhCu2IkNoFfDdcjHos2ZtLdAsyxLZbkpijNzhvvM6BY= +github.com/go-json-experiment/json v0.0.0-20240418180308-af2d5061e6c2/go.mod h1:6daplAwHHGbUGib4990V3Il26O0OC4aRyvewaaAihaA= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -106,9 +113,12 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= @@ -165,9 +175,11 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv 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.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= @@ -212,8 +224,18 @@ github.com/pion/transport/v3 v3.0.2 h1:r+40RJR25S9w3jbA6/5uEPTzcdn7ncyU44RWCbHkL github.com/pion/transport/v3 v3.0.2/go.mod h1:nIToODoOlb5If2jF9y2Igfx3PFYWfuXi37m0IlWa/D0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b h1:AF0/TUHEdt/fqQT0GjEoIXe53XB8qsOHzOu6Npg19Ig= -github.com/plgd-dev/device/v2 v2.5.1-0.20240502072920-6021006ea86b/go.mod h1:y/OnxPhE+FLRcme8i0/bEpeP8qWO8+KFRpU6nTgsozo= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510131130-e10f602b7f77 h1:bxo0wjO1xpTvEYMgWex2rdQLgSTw1yWbaWJg37R6tXc= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510131130-e10f602b7f77/go.mod h1:2mFPs55x2Li76zkrHdRNY3yOqVWSh59hiUw+6FYXA0k= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510134226-6cd2643faa0a h1:HXUPcCLl6eHqp9zIxFRgwC9GgmBJUb/CU53Ql0S//Js= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510134226-6cd2643faa0a/go.mod h1:2mFPs55x2Li76zkrHdRNY3yOqVWSh59hiUw+6FYXA0k= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510135039-6a9dce16a657 h1:/RhBj4mSkB3+KN5ra5xT84fwQhfSZZTOpKRYWw+zueY= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510135039-6a9dce16a657/go.mod h1:2mFPs55x2Li76zkrHdRNY3yOqVWSh59hiUw+6FYXA0k= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510135326-9604b2607b7f h1:G0kV13UqowsZoyIQ5y3q8ZlgzG/euaCf+p+9gryZtw4= +github.com/plgd-dev/device/v2 v2.5.1-0.20240510135326-9604b2607b7f/go.mod h1:2mFPs55x2Li76zkrHdRNY3yOqVWSh59hiUw+6FYXA0k= +github.com/plgd-dev/device/v2 v2.5.1-0.20240513064831-b553d1a87e1c h1:kNF2KvyCzA8IMERdHUrL/LMdsuZM/tXGjLVzEX2lcg4= +github.com/plgd-dev/device/v2 v2.5.1-0.20240513064831-b553d1a87e1c/go.mod h1:2mFPs55x2Li76zkrHdRNY3yOqVWSh59hiUw+6FYXA0k= github.com/plgd-dev/go-coap/v2 v2.0.4-0.20200819112225-8eb712b901bc/go.mod h1:+tCi9Q78H/orWRtpVWyBgrr4vKFo2zYtbbxUllerBp4= github.com/plgd-dev/go-coap/v2 v2.4.1-0.20210517130748-95c37ac8e1fa/go.mod h1:rA7fc7ar+B/qa+Q0hRqv7yj/EMtIlmo1l7vkQGSrHPU= github.com/plgd-dev/go-coap/v3 v3.3.4 h1:clDLFOXXmXfhZqB0eSk6WJs2iYfjC2J22Ixwu5MHiO0= @@ -232,6 +254,7 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -273,6 +296,8 @@ github.com/valyala/fasthttp v1.12.0/go.mod h1:229t1eWu9UXTPmoUkbpN/fctKPBY4IJoFX github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= +github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510130416-741fef736e1e h1:blQyU8WqqyRcBmaAPLiU5cTg9BSQu04CJZ/ffEzgI1s= +github.com/web-of-things-open-source/thingdescription-go v0.0.0-20240510130416-741fef736e1e/go.mod h1:L/jWuWf+v7rmuFykpUP/runRXTnnA0QdGGgou8vzPrw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= @@ -315,6 +340,7 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= @@ -488,6 +514,7 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8 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-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= diff --git a/http-gateway/Dockerfile b/http-gateway/Dockerfile index 452259cf4..ea2ea05a4 100644 --- a/http-gateway/Dockerfile +++ b/http-gateway/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.14-alpine AS build +FROM golang:1.22.3-alpine AS build ARG VERSION ARG COMMIT_DATE ARG SHORT_COMMIT @@ -16,7 +16,7 @@ RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/shri WORKDIR $GOPATH/src/github.com/plgd-dev/hub/vendor/golang.org/x/oauth2 RUN ( patch -p1 < "$GOPATH/src/github.com/plgd-dev/hub/tools/docker/patches/golang_org_x_oauth2_propagate_error.patch" ) WORKDIR $GOPATH/src/github.com/plgd-dev/hub/http-gateway -RUN CGO_ENABLED=0 go build \ +RUN go build \ -mod=vendor \ -ldflags "-linkmode external -extldflags -static -X github.com/plgd-dev/hub/v2/pkg/build.CommitDate=$COMMIT_DATE -X github.com/plgd-dev/hub/v2/pkg/build.CommitHash=$SHORT_COMMIT -X github.com/plgd-dev/hub/v2/pkg/build.BuildDate=$DATE -X github.com/plgd-dev/hub/v2/pkg/build.Version=$VERSION -X github.com/plgd-dev/hub/v2/pkg/build.ReleaseURL=$RELEASE_URL" \ -o /go/bin/http-gateway \ diff --git a/http-gateway/service/deleteDevice.go b/http-gateway/service/deleteDevice.go index 61748966e..a43eb8076 100644 --- a/http-gateway/service/deleteDevice.go +++ b/http-gateway/service/deleteDevice.go @@ -14,7 +14,7 @@ func (requestHandler *RequestHandler) deleteDevice(w http.ResponseWriter, r *htt serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot delete device('%v'): %v", deviceID, err)) return } - toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { + toSimpleResponse(w, rec, false, func(w http.ResponseWriter, err error) { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot delete device('%v'): %v", deviceID, err)) }, streamResponseKey) } diff --git a/http-gateway/service/getDevice.go b/http-gateway/service/getDevice.go index d9119ed00..8a3eac3c7 100644 --- a/http-gateway/service/getDevice.go +++ b/http-gateway/service/getDevice.go @@ -65,7 +65,10 @@ func writeSimpleResponse(w http.ResponseWriter, rec *httptest.ResponseRecorder, } } -func toSimpleResponse(w http.ResponseWriter, rec *httptest.ResponseRecorder, writeError func(w http.ResponseWriter, err error), responseKeys ...string) { +func getResponse(rec *httptest.ResponseRecorder, allowEmpty bool, responseKeys ...string) (interface{}, error) { + if len(rec.Body.Bytes()) == 0 && allowEmpty { + return nil, nil + } iter := json.NewDecoder(bytes.NewReader(rec.Body.Bytes())) datas := make([]interface{}, 0, 1) for { @@ -75,21 +78,17 @@ func toSimpleResponse(w http.ResponseWriter, rec *httptest.ResponseRecorder, wri break } if err != nil { - writeError(w, err) - return + return nil, err } datas = append(datas, v) } if len(datas) == 0 { - writeError(w, kitNetGrpc.ForwardErrorf(codes.NotFound, "not found")) - return + return nil, kitNetGrpc.ForwardErrorf(codes.NotFound, "not found") } if len(datas) != 1 { - writeError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "invalid number of responses")) - return + return nil, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "invalid number of responses") } - var result interface{} - result = datas[0] + result := datas[0] for _, key := range responseKeys { m, ok := result.(map[string]interface{}) if !ok { @@ -102,6 +101,15 @@ func toSimpleResponse(w http.ResponseWriter, rec *httptest.ResponseRecorder, wri break } } + return result, nil +} + +func toSimpleResponse(w http.ResponseWriter, rec *httptest.ResponseRecorder, allowEmpty bool, writeError func(w http.ResponseWriter, err error), responseKeys ...string) { + result, err := getResponse(rec, allowEmpty, responseKeys...) + if err != nil { + writeError(w, err) + return + } writeSimpleResponse(w, rec, result, writeError) } @@ -131,7 +139,7 @@ func (requestHandler *RequestHandler) getDevice(w http.ResponseWriter, r *http.R serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get device('%v'): %v", deviceID, err)) return } - toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { + toSimpleResponse(w, rec, false, func(w http.ResponseWriter, err error) { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get device('%v'): %v", deviceID, err)) }, streamResponseKey) } diff --git a/http-gateway/service/getDeviceResourceLinks.go b/http-gateway/service/getDeviceResourceLinks.go index bc9c865b8..7eb6b3d90 100644 --- a/http-gateway/service/getDeviceResourceLinks.go +++ b/http-gateway/service/getDeviceResourceLinks.go @@ -40,7 +40,7 @@ func (requestHandler *RequestHandler) getDeviceResourceLinks(w http.ResponseWrit rec := httptest.NewRecorder() requestHandler.mux.ServeHTTP(rec, r) - toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { + toSimpleResponse(w, rec, false, func(w http.ResponseWriter, err error) { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get device('%v') resource links: %v", deviceID, err)) }, streamResponseKey) } diff --git a/http-gateway/service/getResource.go b/http-gateway/service/getResource.go index 1f0272cd6..e3e0eb2a4 100644 --- a/http-gateway/service/getResource.go +++ b/http-gateway/service/getResource.go @@ -2,18 +2,22 @@ package service import ( "encoding/base64" + "fmt" "net/http" "net/http/httptest" + "strconv" "strings" "github.com/google/go-querystring/query" "github.com/gorilla/mux" + "github.com/plgd-dev/device/v2/pkg/codec/json" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" "github.com/plgd-dev/hub/v2/http-gateway/serverMux" "github.com/plgd-dev/hub/v2/http-gateway/uri" kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" "github.com/plgd-dev/hub/v2/resource-aggregate/commands" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/encoding/protojson" ) const errFmtFromTwin = "cannot get resource('%v') from twin: %w" @@ -47,7 +51,7 @@ func getETags(r *http.Request) [][]byte { return etags } -func (requestHandler *RequestHandler) getResourceFromTwin(w http.ResponseWriter, r *http.Request, resourceID *pb.ResourceIdFilter) { +func (requestHandler *RequestHandler) getResourceFromTwin(r *http.Request, resourceID *pb.ResourceIdFilter) (*httptest.ResponseRecorder, error) { type Options struct { ResourceIDFilter []string `url:"httpResourceIdFilter"` } @@ -57,33 +61,35 @@ func (requestHandler *RequestHandler) getResourceFromTwin(w http.ResponseWriter, v, err := query.Values(opt) if err != nil { - serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, errFmtFromTwin, resourceID, err)) - return + return nil, err } r.URL.Path = uri.Resources r.URL.RawQuery = v.Encode() rec := httptest.NewRecorder() requestHandler.mux.ServeHTTP(rec, r) + return rec, nil +} - toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { - serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, errFmtFromTwin, resourceID, err)) - }, streamResponseKey) +func parseBoolQuery(str string) bool { + val, err := strconv.ParseBool(str) + if err != nil { + return false + } + return val } -func (requestHandler *RequestHandler) getResource(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - deviceID := vars[uri.DeviceIDKey] - resourceHref := vars[uri.ResourceHrefKey] - twin := r.URL.Query().Get(uri.TwinQueryKey) - resourceInterface := r.URL.Query().Get(uri.ResourceInterfaceQueryKey) +func (requestHandler *RequestHandler) serveResourceRequest(r *http.Request, deviceID, resourceHref, twin, resourceInterface string) (*httptest.ResponseRecorder, error) { resourceID := pb.ResourceIdFilter{ ResourceId: commands.NewResourceID(deviceID, resourceHref), Etag: getETags(r), } - if (twin == "" || strings.ToLower(twin) == "true") && resourceInterface == "" { - requestHandler.getResourceFromTwin(w, r, &resourceID) - return + if (twin == "" || parseBoolQuery(twin)) && resourceInterface == "" { + rec, err := requestHandler.getResourceFromTwin(r, &resourceID) + if err != nil { + return nil, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, errFmtFromTwin, &resourceID, err) + } + return rec, nil } query := r.URL.Query() @@ -97,7 +103,87 @@ func (requestHandler *RequestHandler) getResource(w http.ResponseWriter, r *http rec := httptest.NewRecorder() requestHandler.mux.ServeHTTP(rec, r) - toSimpleResponse(w, rec, func(w http.ResponseWriter, err error) { - serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get resource('%v') from the device: %v", resourceID.ToString(), err)) - }) + return rec, nil +} + +func jsonGetValueOnPath(v interface{}, path ...string) (interface{}, error) { + for idx, p := range path { + if v == nil { + return nil, fmt.Errorf("doesn't contains %v", strings.Join(path[:idx+1], ".")) + } + m, ok := v.(map[interface{}]interface{}) + if !ok { + return nil, fmt.Errorf("%v is not a map but %T", strings.Join(path[:idx+1], "."), v) + } + v, ok = m[p] + if !ok { + return nil, fmt.Errorf("doesn't contains %v", strings.Join(path[:idx+1], ".")) + } + } + return v, nil +} + +func isContentEmpty(data []byte) bool { + if len(data) == 0 { + return true + } + var ct commands.Content + err := protojson.Unmarshal(data, &ct) + if err != nil { + return false + } + return len(ct.GetData()) == 0 && ct.GetCoapContentFormat() == -1 +} + +func (requestHandler *RequestHandler) filterOnlyContent(rec *httptest.ResponseRecorder, contentPath ...string) (resetContent bool) { + if rec.Code == http.StatusNotModified { + rec.Body.Reset() + return false + } + if rec.Code != http.StatusOK { + return false + } + var v map[interface{}]interface{} + err := json.Decode(rec.Body.Bytes(), &v) + if err != nil { + requestHandler.logger.Debugf("filter only content: cannot decode response : %v", err) + return false + } + content, err := jsonGetValueOnPath(v, contentPath...) + if err != nil { + requestHandler.logger.With("body", v).Debugf("filter only content: %v", err) + return false + } + body, err := json.Encode(content) + if err != nil { + requestHandler.logger.With("body", v).Debugf("filter only content: cannot encode 'content' object: %v", err) + return false + } + rec.Body.Reset() + if !isContentEmpty(body) { + _, _ = rec.Body.Write(body) + return false + } + return true +} + +func (requestHandler *RequestHandler) getResource(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + deviceID := vars[uri.DeviceIDKey] + resourceHref := vars[uri.ResourceHrefKey] + twin := r.URL.Query().Get(uri.TwinQueryKey) + onlyContent := r.URL.Query().Get(uri.OnlyContentQueryKey) + resourceInterface := r.URL.Query().Get(uri.ResourceInterfaceQueryKey) + rec, err := requestHandler.serveResourceRequest(r, deviceID, resourceHref, twin, resourceInterface) + if err != nil { + serverMux.WriteError(w, err) + return + } + allowEmptyContent := false + if parseBoolQuery(onlyContent) { + allowEmptyContent = requestHandler.filterOnlyContent(rec, "result", "data", "content") + } + toSimpleResponse(w, rec, allowEmptyContent, func(w http.ResponseWriter, err error) { + serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get resource('%v/%v') from the device: %v", deviceID, resourceHref, err)) + }, streamResponseKey) } diff --git a/http-gateway/service/getResource_test.go b/http-gateway/service/getResource_test.go index f71eb6400..3cd1b3f65 100644 --- a/http-gateway/service/getResource_test.go +++ b/http-gateway/service/getResource_test.go @@ -9,6 +9,7 @@ import ( "net/http" "testing" + "github.com/plgd-dev/device/v2/pkg/codec/json" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/device/v2/test/resource/types" "github.com/plgd-dev/hub/v2/grpc-gateway/pb" @@ -215,3 +216,80 @@ func TestRequestHandlerGetResource(t *testing.T) { }) } } + +func TestRequestHandlerGetResourceWithOnlyContent(t *testing.T) { + deviceID := test.MustFindDeviceByName(test.TestDeviceName) + + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + + tearDown := service.SetUp(ctx, t) + defer tearDown() + + shutdownHttp := httpgwTest.SetUp(t) + defer shutdownHttp() + + token := oauthTest.GetDefaultAccessToken(t) + ctx = kitNetGrpc.CtxWithToken(ctx, token) + + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = conn.Close() + }() + c := pb.NewGrpcGatewayClient(conn) + + _, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) + defer shutdownDevSim() + + type args struct { + deviceID string + resourceHref string + } + tests := []struct { + name string + args args + want interface{} + wantCode int + }{ + { + name: "json: get from resource twin", + args: args{ + deviceID: deviceID, + resourceHref: test.TestResourceLightInstanceHref("1"), + }, + want: map[interface{}]interface{}{"name": "Light", "power": uint64(0x0), "state": false}, + wantCode: http.StatusOK, + }, + { + name: "json: not exists", + args: args{ + deviceID: deviceID, + resourceHref: "/not-exists", + }, + wantCode: http.StatusNotFound, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rb := httpgwTest.NewRequest(http.MethodGet, uri.AliasDeviceResource, nil).AuthToken(token) + rb.DeviceId(tt.args.deviceID).ResourceHref(tt.args.resourceHref) + rb.OnlyContent(true) + resp := httpgwTest.HTTPDo(t, rb.Build()) + defer func() { + _ = resp.Body.Close() + }() + require.Equal(t, tt.wantCode, resp.StatusCode) + if tt.wantCode != http.StatusOK { + return + } + var got interface{} + err := json.ReadFrom(resp.Body, &got) + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/http-gateway/service/getThings.go b/http-gateway/service/getThings.go new file mode 100644 index 000000000..468248eac --- /dev/null +++ b/http-gateway/service/getThings.go @@ -0,0 +1,392 @@ +package service + +import ( + "context" + "errors" + "fmt" + "io" + "net/http" + "net/http/httptest" + "net/url" + + "github.com/google/uuid" + "github.com/gorilla/mux" + jsoniter "github.com/json-iterator/go" + bridgeDeviceTD "github.com/plgd-dev/device/v2/bridge/device/thingDescription" + "github.com/plgd-dev/device/v2/bridge/resources" + bridgeResourcesTD "github.com/plgd-dev/device/v2/bridge/resources/thingDescription" + schemaCloud "github.com/plgd-dev/device/v2/schema/cloud" + schemaCredential "github.com/plgd-dev/device/v2/schema/credential" + schemaDevice "github.com/plgd-dev/device/v2/schema/device" + schemaMaintenance "github.com/plgd-dev/device/v2/schema/maintenance" + "github.com/plgd-dev/go-coap/v3/message" + "github.com/plgd-dev/hub/v2/grpc-gateway/pb" + "github.com/plgd-dev/hub/v2/http-gateway/serverMux" + "github.com/plgd-dev/hub/v2/http-gateway/uri" + "github.com/plgd-dev/hub/v2/pkg/log" + kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" + "github.com/plgd-dev/hub/v2/pkg/security/openid" + "github.com/plgd-dev/hub/v2/resource-aggregate/events" + wotTD "github.com/web-of-things-open-source/thingdescription-go/thingDescription" + "google.golang.org/grpc/codes" +) + +type ThingLink struct { + Href string `json:"href"` + Rel string `json:"rel"` +} + +type GetThingsResponse struct { + Base string `json:"base"` + Security *wotTD.TypeDeclaration `json:"security"` + ID string `json:"id"` + SecurityDefinitions map[string]wotTD.SecurityScheme `json:"securityDefinitions"` + Links []ThingLink `json:"links"` +} + +const ( + ThingLinkRelationItem = "item" + ThingLinkRelationCollection = "collection" +) + +func (requestHandler *RequestHandler) getResourceLinks(ctx context.Context, deviceFilter []string, typeFilter []string) ([]*events.ResourceLinksPublished, error) { + client, err := requestHandler.client.GrpcGatewayClient().GetResourceLinks(ctx, &pb.GetResourceLinksRequest{ + DeviceIdFilter: deviceFilter, + TypeFilter: typeFilter, + }) + if err != nil { + return nil, fmt.Errorf("cannot get resource links: %w", err) + } + links := make([]*events.ResourceLinksPublished, 0, 16) + for { + link, err := client.Recv() + if errors.Is(err, io.EOF) { + break + } + if err != nil { + return nil, fmt.Errorf("cannot receive resource link: %w", err) + } + links = append(links, link) + } + return links, nil +} + +func (requestHandler *RequestHandler) getThings(w http.ResponseWriter, r *http.Request) { + resLinks, err := requestHandler.getResourceLinks(r.Context(), nil, []string{bridgeResourcesTD.ResourceType}) + if err != nil { + serverMux.WriteError(w, err) + return + } + hubCfg, err := requestHandler.client.GrpcGatewayClient().GetHubConfiguration(r.Context(), &pb.HubConfigurationRequest{}) + if err != nil { + serverMux.WriteError(w, err) + return + } + + links := make([]ThingLink, 0, len(resLinks)) + for _, l := range resLinks { + links = append(links, ThingLink{ + Href: "/" + l.GetDeviceId(), + Rel: ThingLinkRelationItem, + }) + } + var td wotTD.ThingDescription + ThingSetSecurity(&td, requestHandler.openIDConfig) + + things := GetThingsResponse{ + Base: requestHandler.config.UI.WebConfiguration.HTTPGatewayAddress + uri.Things, + Links: links, + Security: td.Security, + SecurityDefinitions: td.SecurityDefinitions, + ID: "urn:uuid:" + hubCfg.GetId(), + } + if err := jsonResponseWriter(w, things); err != nil { + log.Errorf("failed to write response: %v", err) + } +} + +func CreateHTTPForms(hrefUri *url.URL, opsBits resources.SupportedOperation, contentType message.MediaType) []wotTD.FormElementProperty { + supportedByOps := map[resources.SupportedOperation]wotTD.StickyDescription{ + resources.SupportedOperationRead: wotTD.Readproperty, + resources.SupportedOperationWrite: wotTD.Writeproperty, + } + + ops := make([]string, 0, len(supportedByOps)) + for opBit, op := range supportedByOps { + if opsBits.HasOperation(opBit) { + ops = append(ops, string(op)) + } + } + if len(ops) == 0 { + return nil + } + q := hrefUri.Query() + if len(q) > 0 && q.Has("di") { + q.Del("di") + } + q.Add(uri.OnlyContentQueryKey, "1") + hrefUri.RawQuery = q.Encode() + return []wotTD.FormElementProperty{ + { + ContentType: bridgeDeviceTD.StringToPtr(contentType.String()), + Href: *hrefUri, + Op: &wotTD.FormElementPropertyOp{ + StringArray: ops, + }, + }, + } +} + +func patchProperty(pe wotTD.PropertyElement, deviceID, href string, contentType message.MediaType) (wotTD.PropertyElement, error) { + deviceUUID, err := uuid.Parse(deviceID) + if err != nil { + return wotTD.PropertyElement{}, fmt.Errorf("cannot parse deviceID: %w", err) + } + propertyBaseURL := "/" + uri.DevicesPathKey + "/" + deviceID + "/" + uri.ResourcesPathKey + patchFnMap := map[string]func(wotTD.PropertyElement) (wotTD.PropertyElement, error){ + schemaDevice.ResourceURI: func(pe wotTD.PropertyElement) (wotTD.PropertyElement, error) { + return bridgeResourcesTD.PatchDeviceResourcePropertyElement(pe, deviceUUID, propertyBaseURL, contentType, "", CreateHTTPForms) + }, + schemaMaintenance.ResourceURI: func(pe wotTD.PropertyElement) (wotTD.PropertyElement, error) { + return bridgeResourcesTD.PatchMaintenanceResourcePropertyElement(pe, deviceUUID, propertyBaseURL, contentType, CreateHTTPForms) + }, + schemaCloud.ResourceURI: func(pe wotTD.PropertyElement) (wotTD.PropertyElement, error) { + return bridgeResourcesTD.PatchCloudResourcePropertyElement(pe, deviceUUID, propertyBaseURL, contentType, CreateHTTPForms) + }, + schemaCredential.ResourceURI: func(pe wotTD.PropertyElement) (wotTD.PropertyElement, error) { + return bridgeResourcesTD.PatchCredentialResourcePropertyElement(pe, deviceUUID, propertyBaseURL, contentType, CreateHTTPForms) + }, + } + patchFn, ok := patchFnMap[href] + if ok { + pe, err = patchFn(pe) + if err != nil { + return wotTD.PropertyElement{}, err + } + return pe, nil + } + + propOps := bridgeDeviceTD.GetPropertyElementOperations(pe) + pe, err = bridgeDeviceTD.PatchPropertyElement(pe, nil, deviceUUID, propertyBaseURL+href, + propOps.ToSupportedOperations(), contentType, CreateHTTPForms) + if err != nil { + return wotTD.PropertyElement{}, err + } + return pe, nil +} + +var validRefs = map[string]struct{}{ + ThingLinkRelationItem: {}, + ThingLinkRelationCollection: {}, +} + +func isDeviceLink(le wotTD.IconLinkElement) (string, bool) { + if le.Href == "" { + return "", false + } + if le.Href[0] != '/' { + return "", false + } + if le.Rel == nil { + return "", false + } + + if _, ok := validRefs[*le.Rel]; !ok { + return "", false + } + linkedDeviceID := le.Href + if linkedDeviceID[0] == '/' { + linkedDeviceID = linkedDeviceID[1:] + } + uuidDeviceID, err := uuid.Parse(linkedDeviceID) + if err != nil { + return "", false + } + if uuidDeviceID == uuid.Nil { + return "", false + } + return linkedDeviceID, true +} + +func getLinkedDevices(links []wotTD.IconLinkElement) []string { + devices := make([]string, 0, len(links)) + for _, l := range links { + if deviceID, ok := isDeviceLink(l); ok { + devices = append(devices, deviceID) + } + } + return devices +} + +func ThingPatchLink(le wotTD.IconLinkElement, validateDevice map[string]struct{}) (wotTD.IconLinkElement, bool) { + if le.Href == "" { + return wotTD.IconLinkElement{}, false + } + device, ok := isDeviceLink(le) + if !ok { + return le, true + } + if len(validateDevice) == 0 { + return wotTD.IconLinkElement{}, false + } + if _, ok := validateDevice[device]; !ok { + return wotTD.IconLinkElement{}, false + } + le.Href = "/" + uri.ThingsPathKey + le.Href + return le, true +} + +func makeDevicePropertiesValidator(deviceID string, links []*events.ResourceLinksPublished) (map[string]struct{}, bool) { + for _, l := range links { + if l.GetDeviceId() == deviceID { + validateProperties := map[string]struct{}{} + for _, r := range l.GetResources() { + validateProperties[r.GetHref()] = struct{}{} + } + return validateProperties, true + } + } + return nil, false +} + +func makeDeviceLinkValidator(links []*events.ResourceLinksPublished) map[string]struct{} { + validator := make(map[string]struct{}) + for _, l := range links { + validator[l.GetDeviceId()] = struct{}{} + } + return validator +} + +func (requestHandler *RequestHandler) thingSetBase(td *wotTD.ThingDescription) error { + baseURL := requestHandler.config.UI.WebConfiguration.HTTPGatewayAddress + uri.API + base, err := url.Parse(baseURL) + if err != nil { + return fmt.Errorf("cannot parse base url: %w", err) + } + td.Base = *base + return nil +} + +func (requestHandler *RequestHandler) thingSetProperties(ctx context.Context, deviceID string, td *wotTD.ThingDescription) error { + deviceLinks, err := requestHandler.getResourceLinks(ctx, []string{deviceID}, nil) + if err != nil { + return fmt.Errorf("cannot get resource links: %w", err) + } + validateProperties, ok := makeDevicePropertiesValidator(deviceID, deviceLinks) + if !ok { + return fmt.Errorf("cannot get resource links for device %v", deviceID) + } + for href, prop := range td.Properties { + _, ok := validateProperties[href] + if !ok { + _, ok = validateProperties["/"+href] + } + if !ok { + delete(td.Properties, href) + continue + } + patchedProp, err := patchProperty(prop, deviceID, href, message.AppJSON) + if err != nil { + return fmt.Errorf("cannot patch device resource property element: %w", err) + } + td.Properties[href] = patchedProp + } + return nil +} + +func (requestHandler *RequestHandler) thingSetLinks(ctx context.Context, td *wotTD.ThingDescription) { + linkedDevices := getLinkedDevices(td.Links) + var validLinkedDevices map[string]struct{} + if len(linkedDevices) > 0 { + links, err := requestHandler.getResourceLinks(ctx, linkedDevices, []string{bridgeResourcesTD.ResourceType}) + if err == nil { + validLinkedDevices = makeDeviceLinkValidator(links) + } + } + patchedLinks := make([]wotTD.IconLinkElement, 0, len(td.Links)) + for _, link := range td.Links { + patchedLink, ok := ThingPatchLink(link, validLinkedDevices) + if !ok { + continue + } + patchedLinks = append(patchedLinks, patchedLink) + } + if len(patchedLinks) == 0 { + td.Links = nil + } else { + td.Links = patchedLinks + } +} + +func ThingSetSecurity(td *wotTD.ThingDescription, openIDConfig openid.Config) { + td.Security = &wotTD.TypeDeclaration{ + String: bridgeDeviceTD.StringToPtr("oauth2_sc"), + } + td.SecurityDefinitions = map[string]wotTD.SecurityScheme{ + "oauth2_sc": { + Scheme: "oauth2", + Flow: bridgeDeviceTD.StringToPtr("code"), + Authorization: &openIDConfig.AuthURL, + Token: &openIDConfig.TokenURL, + }, + } +} + +func (requestHandler *RequestHandler) thingDescriptionResponse(ctx context.Context, w http.ResponseWriter, rec *httptest.ResponseRecorder, writeError func(w http.ResponseWriter, err error), deviceID string) { + content := jsoniter.Get(rec.Body.Bytes(), streamResponseKey, "data", "content") + if content.ValueType() != jsoniter.ObjectValue { + writeError(w, errors.New("cannot decode thingDescription content")) + return + } + var td wotTD.ThingDescription + err := td.UnmarshalJSON([]byte(content.ToString())) + if err != nil { + writeError(w, fmt.Errorf("cannot decode thingDescription content: %w", err)) + return + } + + // .security + ThingSetSecurity(&td, requestHandler.openIDConfig) + + // .base + if err = requestHandler.thingSetBase(&td); err != nil { + writeError(w, fmt.Errorf("cannot set base url: %w", err)) + return + } + + // .properties.forms + if err = requestHandler.thingSetProperties(ctx, deviceID, &td); err != nil { + writeError(w, fmt.Errorf("cannot set properties: %w", err)) + } + + // .links + requestHandler.thingSetLinks(ctx, &td) + + // marshal thingDescription + data, err := td.MarshalJSON() + if err != nil { + writeError(w, fmt.Errorf("cannot encode thingDescription: %w", err)) + return + } + // copy everything from response recorder + // to actual response writer + for k, v := range rec.Header() { + w.Header()[k] = v + } + w.WriteHeader(rec.Code) + _, err = w.Write(data) + if err != nil { + writeError(w, kitNetGrpc.ForwardErrorf(codes.Internal, "cannot encode response: %v", err)) + } +} + +func (requestHandler *RequestHandler) getThing(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + deviceID := vars[uri.DeviceIDKey] + rec, err := requestHandler.serveResourceRequest(r, deviceID, bridgeResourcesTD.ResourceURI, "", "") + if err != nil { + serverMux.WriteError(w, err) + return + } + requestHandler.thingDescriptionResponse(r.Context(), w, rec, serverMux.WriteError, deviceID) +} diff --git a/http-gateway/service/getThings_test.go b/http-gateway/service/getThings_test.go new file mode 100644 index 000000000..176c9142d --- /dev/null +++ b/http-gateway/service/getThings_test.go @@ -0,0 +1,452 @@ +package service_test + +import ( + "context" + "crypto/tls" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "testing" + + "github.com/google/uuid" + bridgeTD "github.com/plgd-dev/device/v2/bridge/device/thingDescription" + bridgeResourcesTD "github.com/plgd-dev/device/v2/bridge/resources/thingDescription" + "github.com/plgd-dev/device/v2/client/core" + bridgeDevice "github.com/plgd-dev/device/v2/cmd/bridge-device/device" + "github.com/plgd-dev/device/v2/pkg/codec/json" + deviceCoap "github.com/plgd-dev/device/v2/pkg/net/coap" + schemaDevice "github.com/plgd-dev/device/v2/schema/device" + schemaMaintenance "github.com/plgd-dev/device/v2/schema/maintenance" + "github.com/plgd-dev/go-coap/v3/message" + "github.com/plgd-dev/hub/v2/grpc-gateway/pb" + httpgwService "github.com/plgd-dev/hub/v2/http-gateway/service" + httpgwTest "github.com/plgd-dev/hub/v2/http-gateway/test" + httpgwUri "github.com/plgd-dev/hub/v2/http-gateway/uri" + isPb "github.com/plgd-dev/hub/v2/identity-store/pb" + isTest "github.com/plgd-dev/hub/v2/identity-store/test" + kitNetGrpc "github.com/plgd-dev/hub/v2/pkg/net/grpc" + "github.com/plgd-dev/hub/v2/pkg/security/openid" + "github.com/plgd-dev/hub/v2/resource-aggregate/commands" + raPb "github.com/plgd-dev/hub/v2/resource-aggregate/service" + raTest "github.com/plgd-dev/hub/v2/resource-aggregate/test" + "github.com/plgd-dev/hub/v2/test" + "github.com/plgd-dev/hub/v2/test/config" + "github.com/plgd-dev/hub/v2/test/device/bridge" + oauthTest "github.com/plgd-dev/hub/v2/test/oauth-server/test" + "github.com/plgd-dev/hub/v2/test/service" + vd "github.com/plgd-dev/hub/v2/test/virtual-device" + "github.com/stretchr/testify/require" + wotTD "github.com/web-of-things-open-source/thingdescription-go/thingDescription" + "golang.org/x/sync/semaphore" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" +) + +type virtualDevice struct { + name string + deviceID string + tdEnabled bool +} + +func createDevices(ctx context.Context, t *testing.T, numDevices int, protocol commands.Connection_Protocol) []virtualDevice { + ctx = kitNetGrpc.CtxWithToken(ctx, oauthTest.GetDefaultAccessToken(t)) + + isConn, err := grpc.NewClient(config.IDENTITY_STORE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = isConn.Close() + }() + isClient := isPb.NewIdentityStoreClient(isConn) + + raConn, err := grpc.NewClient(config.RESOURCE_AGGREGATE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = raConn.Close() + }() + raClient := raPb.NewResourceAggregateClient(raConn) + + devices := make([]virtualDevice, 0, numDevices) + for i := 0; i < numDevices; i++ { + tdEnabled := (i%2 == 0) + devices = append(devices, virtualDevice{ + name: fmt.Sprintf("dev-%v", i), + deviceID: uuid.NewString(), + tdEnabled: tdEnabled, + }) + } + + numGoRoutines := int64(8) + sem := semaphore.NewWeighted(numGoRoutines) + for i := range devices { + err = sem.Acquire(ctx, 1) + require.NoError(t, err) + go func(dev virtualDevice) { + vd.CreateDevice(ctx, t, dev.name, dev.deviceID, 0, dev.tdEnabled, protocol, isClient, raClient) + sem.Release(1) + }(devices[i]) + } + err = sem.Acquire(ctx, numGoRoutines) + require.NoError(t, err) + return devices +} + +func TestRequestHandlerGetThings(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + + const services = service.SetUpServicesOAuth | service.SetUpServicesId | service.SetUpServicesResourceDirectory | + service.SetUpServicesGrpcGateway | service.SetUpServicesResourceAggregate + isConfig := isTest.MakeConfig(t) + isConfig.APIs.GRPC.TLS.ClientCertificateRequired = false + raConfig := raTest.MakeConfig(t) + raConfig.APIs.GRPC.TLS.ClientCertificateRequired = false + tearDown := service.SetUpServices(ctx, t, services, service.WithISConfig(isConfig), service.WithRAConfig(raConfig)) + defer tearDown() + + httpgwCfg := httpgwTest.MakeConfig(t, true) + shutdownHttp := httpgwTest.New(t, httpgwCfg) + defer shutdownHttp() + + token := oauthTest.GetDefaultAccessToken(t) + ctx = kitNetGrpc.CtxWithToken(ctx, token) + + numDevices := 10 + vds := createDevices(ctx, t, numDevices, test.StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME)) + + rb := httpgwTest.NewRequest(http.MethodGet, httpgwUri.Things, nil).AuthToken(token) + resp := httpgwTest.HTTPDo(t, rb.Build()) + defer func() { + _ = resp.Body.Close() + }() + + var v httpgwService.GetThingsResponse + err := httpgwTest.UnmarshalJson(resp.StatusCode, resp.Body, &v) + require.NoError(t, err) + require.Equal(t, httpgwCfg.UI.WebConfiguration.HTTPGatewayAddress+httpgwUri.Things, v.Base) + vdsWithTD := []virtualDevice{} + for _, vd := range vds { + if vd.tdEnabled { + vdsWithTD = append(vdsWithTD, vd) + } + } + require.Len(t, v.Links, len(vdsWithTD)) + for _, dev := range vdsWithTD { + require.Contains(t, v.Links, httpgwService.ThingLink{ + Href: "/" + dev.deviceID, + Rel: httpgwService.ThingLinkRelationItem, + }) + } +} + +func TestBridgeDeviceGetThings(t *testing.T) { + bridgeDeviceCfg, err := test.GetBridgeDeviceConfig() + require.NoError(t, err) + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + tearDown := service.SetUp(ctx, t) + defer tearDown() + token := oauthTest.GetDefaultAccessToken(t) + ctx = kitNetGrpc.CtxWithToken(ctx, token) + + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = conn.Close() + }() + c := pb.NewGrpcGatewayClient(conn) + + httpgwCfg := httpgwTest.MakeConfig(t, true) + shutdownHttp := httpgwTest.New(t, httpgwCfg) + defer shutdownHttp() + + var devIDs []string + for i := 0; i < bridgeDeviceCfg.NumGeneratedBridgedDevices; i++ { + bdName := test.TestBridgeDeviceInstanceName(strconv.Itoa(i)) + bdID := test.MustFindDeviceByName(bdName, func(d *core.Device) deviceCoap.OptionFunc { + return deviceCoap.WithQuery("di=" + d.DeviceID()) + }) + devIDs = append(devIDs, bdID) + bd := bridge.NewDevice(bdID, bdName, bridgeDeviceCfg.NumResourcesPerDevice, true) + shutdownBd := test.OnboardDevice(ctx, t, c, bd, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, bd.GetDefaultResources()) + defer shutdownBd() + } + + rb := httpgwTest.NewRequest(http.MethodGet, httpgwUri.Things, nil).AuthToken(token) + resp := httpgwTest.HTTPDo(t, rb.Build()) + defer func() { + _ = resp.Body.Close() + }() + + var v httpgwService.GetThingsResponse + err = httpgwTest.UnmarshalJson(resp.StatusCode, resp.Body, &v) + require.NoError(t, err) + require.Equal(t, httpgwCfg.UI.WebConfiguration.HTTPGatewayAddress+httpgwUri.Things, v.Base) + require.Len(t, v.Links, bridgeDeviceCfg.NumGeneratedBridgedDevices) + for _, devID := range devIDs { + require.Contains(t, v.Links, httpgwService.ThingLink{ + Href: "/" + devID, + Rel: httpgwService.ThingLinkRelationItem, + }) + } +} + +func getPatchedTD(t *testing.T, deviceCfg bridgeDevice.Config, deviceID string, links []wotTD.IconLinkElement, validateDevices map[string]struct{}, title, host string) *wotTD.ThingDescription { + td, err := bridgeDevice.GetThingDescription(deviceCfg.ThingDescription.File, deviceCfg.NumResourcesPerDevice) + require.NoError(t, err) + + baseURL := host + httpgwUri.API + base, err := url.Parse(baseURL) + require.NoError(t, err) + td.Base = *base + td.Title = title + id, err := bridgeTD.GetThingDescriptionID(deviceID) + require.NoError(t, err) + td.ID = id + + deviceUUID, err := uuid.Parse(deviceID) + require.NoError(t, err) + propertyBaseURL := "/" + httpgwUri.DevicesPathKey + "/" + deviceID + "/" + httpgwUri.ResourcesPathKey + dev, ok := bridgeResourcesTD.GetOCFResourcePropertyElement(schemaDevice.ResourceURI) + require.True(t, ok) + dev, err = bridgeResourcesTD.PatchDeviceResourcePropertyElement(dev, deviceUUID, propertyBaseURL, message.AppJSON, bridgeDevice.DeviceResourceType, httpgwService.CreateHTTPForms) + require.NoError(t, err) + schemaMap := bridgeDevice.GetDataSchemaForAdditionalProperties() + for name, schema := range schemaMap { + dev.Properties.DataSchemaMap[name] = schema + } + td.Properties[schemaDevice.ResourceURI] = dev + + httpgwService.ThingSetSecurity(&td, openid.Config{ + TokenURL: "https://localhost:20009/oauth/token", + AuthURL: "https://localhost:20009/authorize", + }) + + mnt, ok := bridgeResourcesTD.GetOCFResourcePropertyElement(schemaMaintenance.ResourceURI) + require.True(t, ok) + mnt, err = bridgeResourcesTD.PatchMaintenanceResourcePropertyElement(mnt, deviceUUID, propertyBaseURL, message.AppJSON, httpgwService.CreateHTTPForms) + require.NoError(t, err) + td.Properties[schemaMaintenance.ResourceURI] = mnt + + for i := 0; i < deviceCfg.NumResourcesPerDevice; i++ { + href := bridgeDevice.GetTestResourceHref(i) + prop := bridgeDevice.GetPropertyDescriptionForTestResource() + prop, err := bridgeDevice.PatchTestResourcePropertyElement(prop, deviceUUID, propertyBaseURL+href, message.AppJSON, httpgwService.CreateHTTPForms) + require.NoError(t, err) + td.Properties[href] = prop + } + + expectedLinks := make([]wotTD.IconLinkElement, 0, len(links)) + for _, link := range links { + patchedLink, ok := httpgwService.ThingPatchLink(link, validateDevices) + if !ok { + continue + } + expectedLinks = append(expectedLinks, patchedLink) + } + td.Links = expectedLinks + + return &td +} + +func bridgeDeviceInstanceName(idx int) string { + return test.TestBridgeDeviceInstanceName(strconv.Itoa(idx)) +} + +func onboardBridgeDevice(ctx context.Context, t *testing.T, idx int, c pb.GrpcGatewayClient, bridgeDeviceCfg bridgeDevice.Config) (string, func()) { + bdName := bridgeDeviceInstanceName(idx) + bdID := test.MustFindDeviceByName(bdName, func(d *core.Device) deviceCoap.OptionFunc { + return deviceCoap.WithQuery("di=" + d.DeviceID()) + }) + bd := bridge.NewDevice(bdID, bdName, bridgeDeviceCfg.NumResourcesPerDevice, true) + shutdownBd := test.OnboardDevice(ctx, t, c, bd, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, bd.GetDefaultResources()) + return bdID, shutdownBd +} + +func TestBridgeDeviceGetThing(t *testing.T) { + bridgeDeviceCfg, err := test.GetBridgeDeviceConfig() + require.NoError(t, err) + + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + raCfg := raTest.MakeConfig(t) + raCfg.APIs.GRPC.TLS.ClientCertificateRequired = false + tearDown := service.SetUp(ctx, t, service.WithRAConfig(raCfg)) + defer tearDown() + token := oauthTest.GetDefaultAccessToken(t) + ctx = kitNetGrpc.CtxWithToken(ctx, token) + + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = conn.Close() + }() + c := pb.NewGrpcGatewayClient(conn) + + httpgwCfg := httpgwTest.MakeConfig(t, true) + shutdownHttp := httpgwTest.New(t, httpgwCfg) + defer shutdownHttp() + + deviceIDs := make([]string, 0, 2) + validLinkedDevices := make(map[string]struct{}, 2) + for i := 0; i < 2; i++ { + bdID, shutdownBd := onboardBridgeDevice(ctx, t, i, c, bridgeDeviceCfg) + defer shutdownBd() + deviceIDs = append(deviceIDs, bdID) + validLinkedDevices[bdID] = struct{}{} + } + + // update TD links in resource twin + wotRes, err := c.GetResources(ctx, &pb.GetResourcesRequest{ + ResourceIdFilter: []*pb.ResourceIdFilter{ + { + ResourceId: &commands.ResourceId{ + DeviceId: deviceIDs[0], + Href: bridgeResourcesTD.ResourceURI, + }, + }, + }, + }) + require.NoError(t, err) + resources := make([]*pb.Resource, 0, 1) + for { + res, errR := wotRes.Recv() + if errors.Is(errR, io.EOF) { + break + } + require.NoError(t, errR) + resources = append(resources, res) + } + require.Len(t, resources, 1) + + var updateLinksTD wotTD.ThingDescription + err = json.Decode(resources[0].GetData().GetContent().GetData(), &updateLinksTD) + require.NoError(t, err) + links := []wotTD.IconLinkElement{ + { + Rel: bridgeTD.StringToPtr("icon"), + Href: "https://example.com/icon.png", + }, + { + Rel: bridgeTD.StringToPtr(httpgwService.ThingLinkRelationItem), + Href: "/" + deviceIDs[1], + }, + { + Rel: bridgeTD.StringToPtr(httpgwService.ThingLinkRelationCollection), + Href: "/" + deviceIDs[1], + }, + { + Rel: bridgeTD.StringToPtr(httpgwService.ThingLinkRelationItem), + Href: "/" + uuid.NewString(), + }, + } + updateLinksTD.Links = links + data, err := json.Encode(updateLinksTD) + require.NoError(t, err) + + sub, err := c.SubscribeToEvents(ctx) + require.NoError(t, err) + + err = sub.Send(&pb.SubscribeToEvents{ + Action: &pb.SubscribeToEvents_CreateSubscription_{CreateSubscription: &pb.SubscribeToEvents_CreateSubscription{ + EventFilter: []pb.SubscribeToEvents_CreateSubscription_Event{pb.SubscribeToEvents_CreateSubscription_RESOURCE_CHANGED}, + ResourceIdFilter: []*pb.ResourceIdFilter{ + { + ResourceId: resources[0].GetData().GetResourceId(), + }, + }, + }}, + }) + require.NoError(t, err) + s, err := sub.Recv() + require.NoError(t, err) + require.Equal(t, pb.Event_OperationProcessed_ErrorStatus_OK, s.GetOperationProcessed().GetErrorStatus().GetCode()) + + // overwrite TD links in resource twin + raConn, err := grpc.NewClient(config.RESOURCE_AGGREGATE_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = raConn.Close() + }() + raC := raPb.NewResourceAggregateClient(raConn) + _, err = raC.NotifyResourceChanged(ctx, &commands.NotifyResourceChangedRequest{ + ResourceId: resources[0].GetData().GetResourceId(), + Status: commands.Status_OK, + Content: &commands.Content{ + Data: data, + CoapContentFormat: int32(message.AppJSON), + ContentType: message.AppJSON.String(), + }, + CommandMetadata: &commands.CommandMetadata{ + ConnectionId: "test", + Sequence: 1, + }, + }) + require.NoError(t, err) + + ev, err := sub.Recv() + require.NoError(t, err) + require.Equal(t, commands.Status_OK, ev.GetResourceChanged().GetStatus()) + + err = sub.CloseSend() + require.NoError(t, err) + + type args struct { + accept string + deviceID string + } + tests := []struct { + name string + args args + want *wotTD.ThingDescription + wantCode int + }{ + { + name: "json: get from resource twin", + args: args{ + deviceID: deviceIDs[0], + }, + want: getPatchedTD(t, bridgeDeviceCfg, deviceIDs[0], links, validLinkedDevices, bridgeDeviceInstanceName(0), httpgwCfg.UI.WebConfiguration.HTTPGatewayAddress), + wantCode: http.StatusOK, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rb := httpgwTest.NewRequest(http.MethodGet, httpgwUri.AliasDeviceThing, nil).AuthToken(token).Accept(tt.args.accept).DeviceId(tt.args.deviceID) + resp := httpgwTest.HTTPDo(t, rb.Build()) + defer func() { + _ = resp.Body.Close() + }() + require.Equal(t, tt.wantCode, resp.StatusCode) + values := make([]*wotTD.ThingDescription, 0, 1) + for { + var td wotTD.ThingDescription + err := json.ReadFrom(resp.Body, &td) + if errors.Is(err, io.EOF) { + break + } + require.NoError(t, err) + values = append(values, &td) + } + if tt.wantCode != http.StatusOK { + require.Empty(t, values) + return + } + require.Len(t, values, 1) + test.CmpThingDescription(t, tt.want, values[0]) + }) + } +} diff --git a/http-gateway/service/getWebConfiguration_test.go b/http-gateway/service/getWebConfiguration_test.go index 2bf1019bf..6f3f5d1f0 100644 --- a/http-gateway/service/getWebConfiguration_test.go +++ b/http-gateway/service/getWebConfiguration_test.go @@ -2,7 +2,6 @@ package service_test import ( "context" - "encoding/json" "io" "net/http" "os" @@ -18,19 +17,6 @@ import ( "github.com/stretchr/testify/require" ) -func unmarshalWebConfiguration(code int, input io.Reader, v *httpgwService.WebConfiguration) error { - var data json.RawMessage - err := json.NewDecoder(input).Decode(&data) - if err != nil { - return err - } - if code != http.StatusOK { - return httpgwTest.UnmarshalError(data) - } - err = json.Unmarshal(data, v) - return err -} - func TestRegexpAPI(t *testing.T) { tests := []struct { val string @@ -104,7 +90,7 @@ func TestRequestHandlerGetWebConfiguration(t *testing.T) { assert.Equal(t, tt.wantHTTPCode, resp.StatusCode) var got httpgwService.WebConfiguration - err := unmarshalWebConfiguration(resp.StatusCode, resp.Body, &got) + err := httpgwTest.UnmarshalJson(resp.StatusCode, resp.Body, &got) if tt.wantErr { require.Error(t, err) return diff --git a/http-gateway/service/requestHandler.go b/http-gateway/service/requestHandler.go index 6bca657e8..66c15d7c5 100644 --- a/http-gateway/service/requestHandler.go +++ b/http-gateway/service/requestHandler.go @@ -16,14 +16,17 @@ import ( "github.com/plgd-dev/hub/v2/http-gateway/uri" "github.com/plgd-dev/hub/v2/pkg/log" kitHttp "github.com/plgd-dev/hub/v2/pkg/net/http" + "github.com/plgd-dev/hub/v2/pkg/security/openid" pkgStrings "github.com/plgd-dev/hub/v2/pkg/strings" ) // RequestHandler for handling incoming request type RequestHandler struct { - client *client.Client - config *Config - mux *runtime.ServeMux + client *client.Client + config *Config + mux *runtime.ServeMux + openIDConfig openid.Config + logger log.Logger } func matchPrefixAndSplitURIPath(requestURI, prefix string) []string { @@ -114,6 +117,19 @@ func resourceEventsMatcher(r *http.Request, rm *mux.RouteMatch) bool { return false } +func thingMatcher(r *http.Request, rm *mux.RouteMatch) bool { + // /api/v1/things/{deviceId} + paths := matchPrefixAndSplitURIPath(r.RequestURI, uri.Things) + if len(paths) == 1 { + if rm.Vars == nil { + rm.Vars = make(map[string]string) + } + rm.Vars[uri.DeviceIDKey] = unescapeString(paths[0]) + return true + } + return false +} + func wsRequestMutator(incoming, outgoing *http.Request) *http.Request { outgoing.Method = http.MethodPost accept := getAccept(incoming) @@ -153,10 +169,12 @@ func (requestHandler *RequestHandler) setupUIHandler(r *mux.Router) { } // NewHTTP returns HTTP handler -func NewRequestHandler(config *Config, r *mux.Router, client *client.Client) (*RequestHandler, error) { +func NewRequestHandler(config *Config, r *mux.Router, client *client.Client, openIDConfig openid.Config, logger log.Logger) (*RequestHandler, error) { requestHandler := &RequestHandler{ - client: client, - config: config, + client: client, + config: config, + openIDConfig: openIDConfig, + logger: logger, mux: serverMux.New( runtime.WithMarshalerOption(ApplicationSubscribeToEventsMIMEWildcard, newSubscribeToEventsMarshaler(serverMux.NewJsonMarshaler())), runtime.WithMarshalerOption(ApplicationSubscribeToEventsProtoJsonContentType, serverMux.NewJsonpbMarshaler()), @@ -173,6 +191,7 @@ func NewRequestHandler(config *Config, r *mux.Router, client *client.Client) (*R r.HandleFunc(uri.AliasDeviceEvents, requestHandler.getEvents).Methods(http.MethodGet) r.HandleFunc(uri.Configuration, requestHandler.getHubConfiguration).Methods(http.MethodGet) r.HandleFunc(uri.HubConfiguration, requestHandler.getHubConfiguration).Methods(http.MethodGet) + r.HandleFunc(uri.Things, requestHandler.getThings).Methods(http.MethodGet) r.PathPrefix(uri.Devices).Methods(http.MethodPost).MatcherFunc(resourceLinksMatcher).HandlerFunc(requestHandler.createResource) r.PathPrefix(uri.Devices).Methods(http.MethodGet).MatcherFunc(resourcePendingCommandsMatcher).HandlerFunc(requestHandler.getResourcePendingCommands) @@ -181,6 +200,8 @@ func NewRequestHandler(config *Config, r *mux.Router, client *client.Client) (*R r.PathPrefix(uri.Devices).Methods(http.MethodPut).MatcherFunc(resourceMatcher).HandlerFunc(requestHandler.updateResource) r.PathPrefix(uri.Devices).Methods(http.MethodGet).MatcherFunc(resourceEventsMatcher).HandlerFunc(requestHandler.getEvents) + r.PathPrefix(uri.Things).Methods(http.MethodGet).MatcherFunc(thingMatcher).HandlerFunc(requestHandler.getThing) + // register grpc-proxy handler if err := pb.RegisterGrpcGatewayHandlerClient(context.Background(), requestHandler.mux, requestHandler.client.GrpcGatewayClient()); err != nil { return nil, fmt.Errorf("failed to register grpc-gateway handler: %w", err) diff --git a/http-gateway/service/service.go b/http-gateway/service/service.go index b18d9ffee..8f4161b2b 100644 --- a/http-gateway/service/service.go +++ b/http-gateway/service/service.go @@ -86,7 +86,7 @@ func New(ctx context.Context, config Config, fileWatcher *fsnotify.Watcher, logg }) grpcClient := pb.NewGrpcGatewayClient(grpcConn.GRPC()) client := client.New(grpcClient) - _, err = NewRequestHandler(&config, s.GetRouter(), client) + _, err = NewRequestHandler(&config, s.GetRouter(), client, validator.OpenIDConfiguration(), logger) if err != nil { var errors *multierror.Error errors = multierror.Append(errors, fmt.Errorf("cannot create request handler: %w", err)) diff --git a/http-gateway/service/updateResource.go b/http-gateway/service/updateResource.go index 332930a18..e47c06cbf 100644 --- a/http-gateway/service/updateResource.go +++ b/http-gateway/service/updateResource.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "net/http" + "net/http/httptest" "github.com/gorilla/mux" "github.com/plgd-dev/go-coap/v3/message" @@ -53,5 +54,14 @@ func (requestHandler *RequestHandler) updateResource(w http.ResponseWriter, r *h } r.Body = newBody - requestHandler.mux.ServeHTTP(w, r) + rec := httptest.NewRecorder() + onlyContent := r.URL.Query().Get(uri.OnlyContentQueryKey) + requestHandler.mux.ServeHTTP(rec, r) + allowEmptyContent := false + if parseBoolQuery(onlyContent) { + allowEmptyContent = requestHandler.filterOnlyContent(rec, "data", "content") + } + toSimpleResponse(w, rec, allowEmptyContent, func(w http.ResponseWriter, err error) { + serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot update resource('/%v%v') from the device: %v", deviceID, href, err)) + }, streamResponseKey) } diff --git a/http-gateway/service/updateResource_test.go b/http-gateway/service/updateResource_test.go index 06b5502c7..19609f3e9 100644 --- a/http-gateway/service/updateResource_test.go +++ b/http-gateway/service/updateResource_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/plgd-dev/device/v2/pkg/codec/json" "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" "github.com/plgd-dev/go-coap/v3/message" @@ -38,6 +39,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { deviceID string resourceHref string resourceInterface string + onlyContent bool resourceData interface{} ttl time.Duration } @@ -54,6 +56,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { accept: uri.ApplicationProtoJsonContentType, deviceID: deviceID, resourceHref: "/unknown", + onlyContent: true, }, wantErr: true, wantHTTPCode: http.StatusNotFound, @@ -211,7 +214,7 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { require.NoError(t, err) rb := httpgwTest.NewRequest(http.MethodPut, uri.AliasDeviceResource, bytes.NewReader(data)).AuthToken(token).Accept(tt.args.accept) rb.DeviceId(tt.args.deviceID).ResourceHref(tt.args.resourceHref).ResourceInterface(tt.args.resourceInterface).ContentType(tt.args.contentType) - rb.AddTimeToLive(tt.args.ttl) + rb.AddTimeToLive(tt.args.ttl).OnlyContent(tt.args.onlyContent) resp := httpgwTest.HTTPDo(t, rb.Build()) defer func() { _ = resp.Body.Close() @@ -229,3 +232,104 @@ func TestRequestHandlerUpdateResourcesValues(t *testing.T) { }) } } + +func TestRequestHandlerUpdateResourcesValuesWithOnlyContent(t *testing.T) { + deviceID := test.MustFindDeviceByName(test.TestDeviceName) + switchID := "1" + type args struct { + accept string + contentType string + deviceID string + resourceHref string + resourceData interface{} + } + tests := []struct { + name string + args args + want interface{} + wantErr bool + wantHTTPCode int + }{ + { + name: "valid - accept " + uri.ApplicationProtoJsonContentType, + args: args{ + accept: uri.ApplicationProtoJsonContentType, + contentType: message.AppJSON.String(), + deviceID: deviceID, + resourceHref: test.TestResourceLightInstanceHref("1"), + resourceData: map[string]interface{}{ + "power": 102, + }, + }, + want: nil, + wantHTTPCode: http.StatusOK, + }, + { + name: "revert-update - accept empty", + args: args{ + contentType: message.AppJSON.String(), + deviceID: deviceID, + resourceHref: test.TestResourceLightInstanceHref("1"), + resourceData: map[string]interface{}{ + "power": 0, + }, + }, + want: nil, + wantHTTPCode: http.StatusOK, + }, + } + + ctx, cancel := context.WithTimeout(context.Background(), config.TEST_TIMEOUT) + defer cancel() + + tearDown := service.SetUp(ctx, t) + defer tearDown() + + shutdownHttp := httpgwTest.SetUp(t) + defer shutdownHttp() + + token := oauthTest.GetDefaultAccessToken(t) + ctx = kitNetGrpc.CtxWithToken(ctx, token) + + conn, err := grpc.NewClient(config.GRPC_GW_HOST, grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ + RootCAs: test.GetRootCertificatePool(t), + }))) + require.NoError(t, err) + defer func() { + _ = conn.Close() + }() + c := pb.NewGrpcGatewayClient(conn) + + _, shutdownDevSim := test.OnboardDevSim(ctx, t, c, deviceID, config.ACTIVE_COAP_SCHEME+"://"+config.COAP_GW_HOST, test.GetAllBackendResourceLinks()) + defer shutdownDevSim() + + test.AddDeviceSwitchResources(ctx, t, deviceID, c, switchID) + time.Sleep(200 * time.Millisecond) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + data, err := httpgwTest.GetContentData(&pb.Content{ + Data: test.EncodeToCbor(t, tt.args.resourceData), + ContentType: message.AppOcfCbor.String(), + }, tt.args.contentType) + require.NoError(t, err) + rb := httpgwTest.NewRequest(http.MethodPut, uri.AliasDeviceResource, bytes.NewReader(data)).AuthToken(token).Accept(tt.args.accept) + rb.DeviceId(tt.args.deviceID).ResourceHref(tt.args.resourceHref).ContentType(tt.args.contentType) + rb.OnlyContent(true) + resp := httpgwTest.HTTPDo(t, rb.Build()) + defer func() { + _ = resp.Body.Close() + }() + assert.Equal(t, tt.wantHTTPCode, resp.StatusCode) + + var got interface{} + err = json.ReadFrom(resp.Body, &got) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + assert.Equal(t, tt.want, got) + }) + } +} diff --git a/http-gateway/swagger.yaml b/http-gateway/swagger.yaml index c43d8b28a..e07d35627 100644 --- a/http-gateway/swagger.yaml +++ b/http-gateway/swagger.yaml @@ -389,6 +389,7 @@ paths: - $ref: "#/components/parameters/shadow" - $ref: "#/components/parameters/timeToLive" - $ref: "#/components/parameters/etag" + - $ref: "#/components/parameters/onlyContent" responses: 200: description: "Resource content." @@ -419,6 +420,7 @@ paths: parameters: - $ref: "#/components/parameters/interface" - $ref: "#/components/parameters/timeToLive" + - $ref: "#/components/parameters/onlyContent" requestBody: description: "Updated content of the resource." content: @@ -1762,6 +1764,13 @@ components: schema: type: string format: base64 + onlyContent: + name: onlyContent + in: query + description: "Return only content of the resource in the response." + schema: + type: boolean + default: false responses: ok: description: Content is stored in body. diff --git a/http-gateway/test/http.go b/http-gateway/test/http.go index 466a248a0..ad47b5b3c 100644 --- a/http-gateway/test/http.go +++ b/http-gateway/test/http.go @@ -114,6 +114,11 @@ func (c *RequestBuilder) Accept(accept string) *RequestBuilder { return c } +func (c *RequestBuilder) OnlyContent(v bool) *RequestBuilder { + c.AddQuery(uri.OnlyContentQueryKey, strconv.FormatBool(v)) + return c +} + func (c *RequestBuilder) ContentType(contentType string) *RequestBuilder { if contentType == "" { return c diff --git a/http-gateway/test/test.go b/http-gateway/test/test.go index 2e7b7dd79..8c63f9714 100644 --- a/http-gateway/test/test.go +++ b/http-gateway/test/test.go @@ -2,6 +2,9 @@ package test import ( "context" + "encoding/json" + "io" + "net/http" "os" "sync" "time" @@ -11,7 +14,7 @@ import ( "github.com/plgd-dev/hub/v2/http-gateway/uri" "github.com/plgd-dev/hub/v2/pkg/fsnotify" "github.com/plgd-dev/hub/v2/pkg/log" - "github.com/plgd-dev/hub/v2/pkg/net/http" + pkgHttp "github.com/plgd-dev/hub/v2/pkg/net/http" "github.com/plgd-dev/hub/v2/test/config" testHttp "github.com/plgd-dev/hub/v2/test/http" "github.com/plgd-dev/kit/v2/codec/cbor" @@ -53,7 +56,7 @@ func MakeConfig(t require.TestingT, enableUI bool) service.Config { cfg.APIs.HTTP.Server = config.MakeHttpServerConfig() cfg.Clients.GrpcGateway.Connection = config.MakeGrpcClientConfig(config.GRPC_GW_HOST) - cfg.Clients.OpenTelemetryCollector = http.OpenTelemetryCollectorConfig{ + cfg.Clients.OpenTelemetryCollector = pkgHttp.OpenTelemetryCollectorConfig{ Config: config.MakeOpenTelemetryCollectorClient(), } @@ -111,3 +114,16 @@ func GetContentData(content *pb.Content, desiredContentType string) ([]byte, err } return []byte(v), err } + +func UnmarshalJson(code int, input io.Reader, v any) error { + var data json.RawMessage + err := json.NewDecoder(input).Decode(&data) + if err != nil { + return err + } + if code != http.StatusOK { + return UnmarshalError(data) + } + err = json.Unmarshal(data, v) + return err +} diff --git a/http-gateway/uri/uri.go b/http-gateway/uri/uri.go index b20a5e6e8..54e53ab6f 100644 --- a/http-gateway/uri/uri.go +++ b/http-gateway/uri/uri.go @@ -21,6 +21,7 @@ const ( TimestampFilterQueryKey = "timestampFilter" CorrelationIdFilterQueryKey = "correlationIdFilter" ETagQueryKey = "etag" + OnlyContentQueryKey = "onlyContent" AliasInterfaceQueryKey = "interface" AliasCommandFilterQueryKey = "command" @@ -34,11 +35,13 @@ const ( AcceptHeaderKey = "Accept" ETagHeaderKey = "ETag" + DevicesPathKey = "devices" ResourcesPathKey = "resources" ResourceLinksPathKey = "resource-links" PendingCommandsPathKey = "pending-commands" PendingMetadataUpdatesPathKey = "pending-metadata-updates" EventsPathKey = "events" + ThingsPathKey = "things" ApplicationProtoJsonContentType = "application/protojson" @@ -53,6 +56,11 @@ const ( // web configuration for ui WebConfiguration = "/web_configuration.json" + // list devices with thing descriptions + Things = API + "/" + ThingsPathKey + // (HTTP ALIAS) GET /api/v1/things/{deviceId} + AliasDeviceThing = Things + "/{" + DeviceIDKey + "}" + // (GRPC + HTTP) GET /api/v1/devices -> rpc GetDevices // (GRPC + HTTP) DELETE /api/v1/devices -> rpc DeleteDevices Devices = API + "/devices" @@ -133,4 +141,5 @@ var QueryCaseInsensitive = map[string]string{ strings.ToLower(TimestampFilterQueryKey): TimestampFilterQueryKey, strings.ToLower(TimeToLiveQueryKey): TimeToLiveQueryKey, strings.ToLower(CorrelationIdFilterQueryKey): CorrelationIdFilterQueryKey, + strings.ToLower(OnlyContentQueryKey): OnlyContentQueryKey, } diff --git a/test/bridge-device/bridge-device.jsonld b/test/bridge-device/bridge-device.jsonld new file mode 100644 index 000000000..4b72a02b6 --- /dev/null +++ b/test/bridge-device/bridge-device.jsonld @@ -0,0 +1,8 @@ +{ + "@context": "https://www.w3.org/2019/wot/td/v1", + "@type": [ + "Thing" + ], + "id": "urn:uuid:bridge-test", + "properties": {} +} \ No newline at end of file diff --git a/test/bridge-device/config.yaml b/test/bridge-device/config.yaml new file mode 100644 index 000000000..5be18ae10 --- /dev/null +++ b/test/bridge-device/config.yaml @@ -0,0 +1,19 @@ +apis: + coap: + id: 8f596b43-29c0-4147-8b40-e99268ab30f7 + name: "bridge-test" + externalAddresses: + - "127.0.0.1:15683" + - "[::1]:15683" + maxMessageSize: 2097152 +log: + level: "info" +cloud: + enabled: true +credential: + enabled: true +thingDescription: + enabled: true + file: "bridge-device.jsonld" +numGeneratedBridgedDevices: 3 +numResourcesPerDevice: 3 diff --git a/test/cloud-server/Dockerfile b/test/cloud-server/Dockerfile index ca78855ee..a4542f439 100644 --- a/test/cloud-server/Dockerfile +++ b/test/cloud-server/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.14-alpine AS build +FROM golang:1.22.3-alpine AS build ARG VERSION ARG COMMIT_DATE ARG SHORT_COMMIT diff --git a/test/device/bridge/device.go b/test/device/bridge/device.go index 46e9f2967..80af77d79 100644 --- a/test/device/bridge/device.go +++ b/test/device/bridge/device.go @@ -21,6 +21,8 @@ package bridge import ( "time" + "github.com/plgd-dev/device/v2/bridge/resources/thingDescription" + bridgeDevice "github.com/plgd-dev/device/v2/cmd/bridge-device/device" "github.com/plgd-dev/device/v2/schema" schemaDevice "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" @@ -32,10 +34,10 @@ import ( var TestResources = []schema.ResourceLink{ { Href: schemaDevice.ResourceURI, - ResourceTypes: []string{"oic.d.virtual", schemaDevice.ResourceType}, + ResourceTypes: []string{bridgeDevice.DeviceResourceType, schemaDevice.ResourceType}, Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_R}, Policy: &schema.Policy{ - BitMask: 1, + BitMask: schema.Discoverable, }, }, { @@ -43,21 +45,29 @@ var TestResources = []schema.ResourceLink{ ResourceTypes: []string{maintenance.ResourceType}, Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_RW}, Policy: &schema.Policy{ - BitMask: 1, + BitMask: schema.Discoverable, }, }, } type Device struct { device.BaseDevice + testResources int // number of test resources + tdEnabled bool // thingDescription resource enabled } -func NewDevice(id, name string) *Device { +func NewDevice(id, name string, testResources int, tdEnabled bool) *Device { return &Device{ - BaseDevice: device.MakeBaseDevice(id, name), + BaseDevice: device.MakeBaseDevice(id, name), + testResources: testResources, + tdEnabled: tdEnabled, } } +func (d *Device) GetType() device.Type { + return device.Bridged +} + func (d *Device) GetSDKClientOptions() []sdk.Option { return []sdk.Option{sdk.WithUseDeviceIDInQuery(true)} } @@ -67,5 +77,26 @@ func (d *Device) GetRetryInterval(int) time.Duration { } func (d *Device) GetDefaultResources() schema.ResourceLinks { - return TestResources + testResources := TestResources + for i := 0; i < d.testResources; i++ { + testResources = append(testResources, schema.ResourceLink{ + Href: bridgeDevice.GetTestResourceHref(i), + ResourceTypes: []string{bridgeDevice.TestResourceType}, + Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_RW}, + Policy: &schema.Policy{ + BitMask: schema.Discoverable | schema.Observable, + }, + }) + } + if d.tdEnabled { + testResources = append(testResources, schema.ResourceLink{ + Href: thingDescription.ResourceURI, + ResourceTypes: []string{thingDescription.ResourceType}, + Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_R}, + Policy: &schema.Policy{ + BitMask: schema.Discoverable | schema.Observable, + }, + }) + } + return testResources } diff --git a/test/device/device.go b/test/device/device.go index 28ccb9933..de3e9d92c 100644 --- a/test/device/device.go +++ b/test/device/device.go @@ -33,7 +33,17 @@ import ( "github.com/plgd-dev/hub/v2/test/sdk" ) +type Type int + +const ( + OCF Type = iota + Bridged +) + type Device interface { + // GetType returns device type + GetType() Type + // GetID returns device ID GetID() string @@ -81,14 +91,9 @@ func (bd *BaseDevice) GetSDKClientOptions() []sdk.Option { return nil } -type Type int +type GetResourceOpts func(*core.Device) deviceCoap.OptionFunc -const ( - OCF Type = iota - Bridged -) - -func FindDeviceByName(ctx context.Context, name string, getResourceOpts func(*core.Device) deviceCoap.OptionFunc) (deviceID string, _ error) { +func FindDeviceByName(ctx context.Context, name string, getResourceOpts ...GetResourceOpts) (deviceID string, _ error) { client := core.NewClient() ctx, cancel := context.WithCancel(ctx) @@ -115,7 +120,7 @@ type findDeviceIDByNameHandler struct { id atomic.Value name string cancel context.CancelFunc - getResourceOptions func(*core.Device) deviceCoap.OptionFunc + getResourceOptions []GetResourceOpts } func (h *findDeviceIDByNameHandler) Handle(ctx context.Context, dev *core.Device) { @@ -136,7 +141,9 @@ func (h *findDeviceIDByNameHandler) Handle(ctx context.Context, dev *core.Device var d device.Device var getResourceOpts []deviceCoap.OptionFunc if h.getResourceOptions != nil { - getResourceOpts = append(getResourceOpts, h.getResourceOptions(dev)) + for _, opts := range h.getResourceOptions { + getResourceOpts = append(getResourceOpts, opts(dev)) + } } err = dev.GetResource(ctx, l, &d, getResourceOpts...) if err != nil { diff --git a/test/device/ocf/device.go b/test/device/ocf/device.go index 495377798..3000bfea4 100644 --- a/test/device/ocf/device.go +++ b/test/device/ocf/device.go @@ -119,6 +119,10 @@ func NewDevice(id, name string) *Device { } } +func (d *Device) GetType() device.Type { + return device.OCF +} + func (d *Device) GetRetryInterval(attempt int) time.Duration { /* [2s, 4s, 8s, 16s, 32s, 64s] */ return time.Duration(math.Exp2(float64(attempt))) * time.Second diff --git a/test/test.go b/test/test.go index cf9a5b146..605679d74 100644 --- a/test/test.go +++ b/test/test.go @@ -2,6 +2,7 @@ package test import ( "context" + "errors" "fmt" "net" "os" @@ -13,6 +14,7 @@ import ( deviceClient "github.com/plgd-dev/device/v2/client" "github.com/plgd-dev/device/v2/client/core" + bridgeDevice "github.com/plgd-dev/device/v2/cmd/bridge-device/device" deviceCoap "github.com/plgd-dev/device/v2/pkg/net/coap" "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/acl" @@ -200,6 +202,10 @@ func TestResourceSwitchesInstanceHref(id string) string { return TestResourceSwitchesHref + "/" + id } +func TestBridgeDeviceInstanceName(id string) string { + return "bridged-device-" + id +} + type LightResourceRepresentation struct { Name string `json:"name"` Power uint64 `json:"power"` @@ -570,7 +576,7 @@ func OnboardDeviceForClient(ctx context.Context, t *testing.T, c pb.GrpcGatewayC } CheckProtobufs(t, expectedEvent, ev, RequireToCheckFunc(require.Equal)) onboard() - WaitForDevice(t, subClient, d.GetID(), ev.GetSubscriptionId(), ev.GetCorrelationId(), expectedResources) + WaitForDevice(t, subClient, d, ev.GetSubscriptionId(), ev.GetCorrelationId(), expectedResources) err = subClient.CloseSend() require.NoError(t, err) } else { @@ -606,7 +612,7 @@ func OffBoardDevSim(ctx context.Context, t *testing.T, deviceID string) { OffboardDevice(ctx, t, ocf.NewDevice(deviceID, TestDeviceName)) } -func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, deviceID, subID, correlationID string, expectedResources []schema.ResourceLink) { +func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, dev device.Device, subID, correlationID string, expectedResources []schema.ResourceLink) { getID := func(ev *pb.Event) string { switch v := ev.GetType().(type) { case *pb.Event_DeviceRegistered_: @@ -638,7 +644,7 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, val.DeviceMetadataUpdated.GetConnection().ConnectedAt = 0 require.NotEmpty(t, val.DeviceMetadataUpdated.GetConnection().GetServiceId()) val.DeviceMetadataUpdated.GetConnection().ServiceId = "" - if TestDeviceType != device.Bridged && !config.COAP_GATEWAY_UDP_ENABLED { + if dev.GetType() != device.Bridged && !config.COAP_GATEWAY_UDP_ENABLED { // TODO: fix bug in iotivity-lite, for DTLS it is not fill endpoints require.NotEmpty(t, val.DeviceMetadataUpdated.GetConnection().GetLocalEndpoints()) } @@ -675,7 +681,7 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, CorrelationId: correlationID, Type: &pb.Event_DeviceRegistered_{ DeviceRegistered: &pb.Event_DeviceRegistered{ - DeviceIds: []string{deviceID}, + DeviceIds: []string{dev.GetID()}, EventMetadata: &isEvents.EventMetadata{ HubId: config.HubID(), }, @@ -695,7 +701,7 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, CorrelationId: correlationID, Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ - DeviceId: deviceID, + DeviceId: dev.GetID(), Connection: &commands.Connection{ Status: commands.Connection_ONLINE, Protocol: StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME), @@ -723,7 +729,7 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, CorrelationId: correlationID, Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ - DeviceId: deviceID, + DeviceId: dev.GetID(), Connection: &commands.Connection{ Status: commands.Connection_ONLINE, Protocol: StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME), @@ -751,7 +757,7 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, CorrelationId: correlationID, Type: &pb.Event_DeviceMetadataUpdated{ DeviceMetadataUpdated: &events.DeviceMetadataUpdated{ - DeviceId: deviceID, + DeviceId: dev.GetID(), Connection: &commands.Connection{ Status: commands.Connection_ONLINE, Protocol: StringToApplicationProtocol(config.ACTIVE_COAP_SCHEME), @@ -768,8 +774,8 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, CorrelationId: correlationID, Type: &pb.Event_ResourcePublished{ ResourcePublished: &events.ResourceLinksPublished{ - DeviceId: deviceID, - Resources: ResourceLinksToResources(deviceID, expectedResources), + DeviceId: dev.GetID(), + Resources: ResourceLinksToResources(dev.GetID(), expectedResources), }, }, }, @@ -777,14 +783,14 @@ func WaitForDevice(t *testing.T, client pb.GrpcGateway_SubscribeToEventsClient, for _, r := range expectedResources { expectedEvents[getID(&pb.Event{Type: &pb.Event_ResourceChanged{ ResourceChanged: &events.ResourceChanged{ - ResourceId: commands.NewResourceID(deviceID, r.Href), + ResourceId: commands.NewResourceID(dev.GetID(), r.Href), }, }})] = &pb.Event{ SubscriptionId: subID, CorrelationId: correlationID, Type: &pb.Event_ResourceChanged{ ResourceChanged: &events.ResourceChanged{ - ResourceId: commands.NewResourceID(deviceID, r.Href), + ResourceId: commands.NewResourceID(dev.GetID(), r.Href), Status: commands.Status_OK, ResourceTypes: r.ResourceTypes, }, @@ -824,12 +830,12 @@ func MustGetHostname() string { return n } -func MustFindDeviceByName(name string) (deviceID string) { +func MustFindDeviceByName(name string, getResourceOpts ...device.GetResourceOpts) (deviceID string) { var err error for i := 0; i < 3; i++ { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - deviceID, err = device.FindDeviceByName(ctx, name, nil) + deviceID, err = device.FindDeviceByName(ctx, name, getResourceOpts...) if err == nil { return deviceID } @@ -837,12 +843,20 @@ func MustFindDeviceByName(name string) (deviceID string) { panic(err) } +func GetBridgeDeviceConfig() (bridgeDevice.Config, error) { + cfgFile := os.Getenv("TEST_BRIDGE_DEVICE_CONFIG") + if cfgFile == "" { + return bridgeDevice.Config{}, errors.New("TEST_BRIDGE_DEVICE_CONFIG not set") + } + return bridgeDevice.LoadConfig(cfgFile) +} + func MustFindTestDevice() device.Device { - var getResourceOpts func(*core.Device) deviceCoap.OptionFunc + var getResourceOpts []device.GetResourceOpts if TestDeviceType == device.Bridged { - getResourceOpts = func(d *core.Device) deviceCoap.OptionFunc { + getResourceOpts = append(getResourceOpts, func(d *core.Device) deviceCoap.OptionFunc { return deviceCoap.WithQuery("di=" + d.DeviceID()) - } + }) } var deviceID string @@ -850,7 +864,7 @@ func MustFindTestDevice() device.Device { for i := 0; i < 3; i++ { ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() - deviceID, err = device.FindDeviceByName(ctx, TestDeviceName, getResourceOpts) + deviceID, err = device.FindDeviceByName(ctx, TestDeviceName, getResourceOpts...) if err == nil { break } @@ -861,7 +875,11 @@ func MustFindTestDevice() device.Device { } if TestDeviceType == device.Bridged { - return bridge.NewDevice(deviceID, TestDeviceName) + bridgeDeviceCfg, err := GetBridgeDeviceConfig() + if err != nil { + panic(err) + } + return bridge.NewDevice(deviceID, TestDeviceName, bridgeDeviceCfg.NumResourcesPerDevice, true) } return ocf.NewDevice(deviceID, TestDeviceName) } diff --git a/test/thingDescription.go b/test/thingDescription.go new file mode 100644 index 000000000..bbe9e8a11 --- /dev/null +++ b/test/thingDescription.go @@ -0,0 +1,33 @@ +package test + +import ( + "sort" + "testing" + + "github.com/stretchr/testify/require" + wotTD "github.com/web-of-things-open-source/thingdescription-go/thingDescription" +) + +func CmpThingDescription(t *testing.T, expected, got *wotTD.ThingDescription) { + sort.Strings(expected.Type.StringArray) + sort.Strings(got.Type.StringArray) + sortProperties := func(td *wotTD.ThingDescription) { + for key, prop := range td.Properties { + for idx, form := range prop.Forms { + if form.Op.StringArray == nil { + continue + } + sort.Strings(form.Op.StringArray) + prop.Forms[idx] = form + } + if prop.Type == nil { + continue + } + sort.Strings(prop.Type.StringArray) + td.Properties[key] = prop + } + } + sortProperties(expected) + sortProperties(got) + require.Equal(t, expected, got) +} diff --git a/test/virtual-device/virtualDevice.go b/test/virtual-device/virtualDevice.go index cb7d87378..54b23096a 100644 --- a/test/virtual-device/virtualDevice.go +++ b/test/virtual-device/virtualDevice.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/plgd-dev/device/v2/bridge/resources/thingDescription" "github.com/plgd-dev/device/v2/schema" "github.com/plgd-dev/device/v2/schema/device" "github.com/plgd-dev/device/v2/schema/interfaces" @@ -29,7 +30,7 @@ import ( "google.golang.org/grpc/status" ) -func CreateDeviceResourceLinks(deviceID string, numResources int) []*commands.Resource { +func CreateDeviceResourceLinks(deviceID string, numResources int, tdEnabled bool) []*commands.Resource { resources := make([]*commands.Resource, 0, numResources) for i := 0; i < numResources; i++ { resources = append(resources, &commands.Resource{ @@ -60,10 +61,23 @@ func CreateDeviceResourceLinks(deviceID string, numResources int) []*commands.Re BitFlags: int32(schema.Observable | schema.Discoverable), }, }) + + if tdEnabled { + resources = append(resources, &commands.Resource{ + Href: thingDescription.ResourceURI, + DeviceId: deviceID, + ResourceTypes: []string{thingDescription.ResourceType}, + Interfaces: []string{interfaces.OC_IF_BASELINE, interfaces.OC_IF_R}, + Policy: &commands.Policy{ + BitFlags: int32(schema.Discoverable), + }, + }) + } + return resources } -func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID string, numResources int, protocol commands.Connection_Protocol, isClient pb.IdentityStoreClient, raClient raPb.ResourceAggregateClient) { +func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID string, numResources int, tdEnabled bool, protocol commands.Connection_Protocol, isClient pb.IdentityStoreClient, raClient raPb.ResourceAggregateClient) { const connID = "conn-Id" var conSeq uint64 incSeq := func() uint64 { @@ -105,7 +119,7 @@ func CreateDevice(ctx context.Context, t *testing.T, name string, deviceID strin assert.NoError(t, err) //nolint:testifylint } - resources := CreateDeviceResourceLinks(deviceID, numResources) + resources := CreateDeviceResourceLinks(deviceID, numResources, tdEnabled) pub := commands.PublishResourceLinksRequest{ DeviceId: deviceID, Resources: resources, @@ -223,7 +237,7 @@ func CreateDevices(ctx context.Context, t *testing.T, numDevices int, numResourc err = sem.Acquire(ctx, 1) require.NoError(t, err) go func(i int) { - CreateDevice(ctx, t, fmt.Sprintf("dev-%v", i), uuid.NewString(), numResourcesPerDevice, protocol, isClient, raClient) + CreateDevice(ctx, t, fmt.Sprintf("dev-%v", i), uuid.NewString(), numResourcesPerDevice, false, protocol, isClient, raClient) sem.Release(1) }(i) } diff --git a/tools/cert-tool/Dockerfile b/tools/cert-tool/Dockerfile index 370f7d98b..73dd69940 100644 --- a/tools/cert-tool/Dockerfile +++ b/tools/cert-tool/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20.14-alpine AS build +FROM golang:1.22.3-alpine AS build ARG DIRECTORY ARG NAME ARG VERSION diff --git a/tools/docker/Dockerfile.in b/tools/docker/Dockerfile.in index 50782a0a8..46e1e79b4 100644 --- a/tools/docker/Dockerfile.in +++ b/tools/docker/Dockerfile.in @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM golang:1.20.14-alpine AS build +FROM golang:1.22.3-alpine AS build ARG VERSION ARG COMMIT_DATE ARG SHORT_COMMIT From 0e6a7635691171a21281217ebf19be58681f3d52 Mon Sep 17 00:00:00 2001 From: Jozef Kralik Date: Wed, 15 May 2024 08:40:49 +0000 Subject: [PATCH 31/31] http-gateway: get property value from the device without hub metadata --- http-gateway/service/getResource.go | 16 +- http-gateway/service/getResource_test.go | 16 +- http-gateway/service/getThings.go | 2 +- http-gateway/swagger.wot.yaml | 970 +++++++++++++++++++++++ http-gateway/swagger.yaml | 34 + 5 files changed, 1030 insertions(+), 8 deletions(-) create mode 100644 http-gateway/swagger.wot.yaml diff --git a/http-gateway/service/getResource.go b/http-gateway/service/getResource.go index e3e0eb2a4..9f8db8a07 100644 --- a/http-gateway/service/getResource.go +++ b/http-gateway/service/getResource.go @@ -78,7 +78,7 @@ func parseBoolQuery(str string) bool { return val } -func (requestHandler *RequestHandler) serveResourceRequest(r *http.Request, deviceID, resourceHref, twin, resourceInterface string) (*httptest.ResponseRecorder, error) { +func (requestHandler *RequestHandler) serveResourceRequest(r *http.Request, deviceID, resourceHref, twin, resourceInterface string) (*httptest.ResponseRecorder, bool, error) { resourceID := pb.ResourceIdFilter{ ResourceId: commands.NewResourceID(deviceID, resourceHref), Etag: getETags(r), @@ -87,9 +87,9 @@ func (requestHandler *RequestHandler) serveResourceRequest(r *http.Request, devi if (twin == "" || parseBoolQuery(twin)) && resourceInterface == "" { rec, err := requestHandler.getResourceFromTwin(r, &resourceID) if err != nil { - return nil, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, errFmtFromTwin, &resourceID, err) + return nil, false, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, errFmtFromTwin, &resourceID, err) } - return rec, nil + return rec, true, nil } query := r.URL.Query() @@ -103,7 +103,7 @@ func (requestHandler *RequestHandler) serveResourceRequest(r *http.Request, devi rec := httptest.NewRecorder() requestHandler.mux.ServeHTTP(rec, r) - return rec, nil + return rec, false, nil } func jsonGetValueOnPath(v interface{}, path ...string) (interface{}, error) { @@ -174,14 +174,18 @@ func (requestHandler *RequestHandler) getResource(w http.ResponseWriter, r *http twin := r.URL.Query().Get(uri.TwinQueryKey) onlyContent := r.URL.Query().Get(uri.OnlyContentQueryKey) resourceInterface := r.URL.Query().Get(uri.ResourceInterfaceQueryKey) - rec, err := requestHandler.serveResourceRequest(r, deviceID, resourceHref, twin, resourceInterface) + rec, fromTwin, err := requestHandler.serveResourceRequest(r, deviceID, resourceHref, twin, resourceInterface) if err != nil { serverMux.WriteError(w, err) return } allowEmptyContent := false if parseBoolQuery(onlyContent) { - allowEmptyContent = requestHandler.filterOnlyContent(rec, "result", "data", "content") + filterPath := []string{"result", "data", "content"} + if !fromTwin { + filterPath = []string{"data", "content"} + } + allowEmptyContent = requestHandler.filterOnlyContent(rec, filterPath...) } toSimpleResponse(w, rec, allowEmptyContent, func(w http.ResponseWriter, err error) { serverMux.WriteError(w, kitNetGrpc.ForwardErrorf(codes.InvalidArgument, "cannot get resource('%v/%v') from the device: %v", deviceID, resourceHref, err)) diff --git a/http-gateway/service/getResource_test.go b/http-gateway/service/getResource_test.go index 3cd1b3f65..cc2fa9006 100644 --- a/http-gateway/service/getResource_test.go +++ b/http-gateway/service/getResource_test.go @@ -247,6 +247,7 @@ func TestRequestHandlerGetResourceWithOnlyContent(t *testing.T) { type args struct { deviceID string resourceHref string + twin *bool } tests := []struct { name string @@ -255,7 +256,7 @@ func TestRequestHandlerGetResourceWithOnlyContent(t *testing.T) { wantCode int }{ { - name: "json: get from resource twin", + name: "json: get resource from twin", args: args{ deviceID: deviceID, resourceHref: test.TestResourceLightInstanceHref("1"), @@ -263,6 +264,16 @@ func TestRequestHandlerGetResourceWithOnlyContent(t *testing.T) { want: map[interface{}]interface{}{"name": "Light", "power": uint64(0x0), "state": false}, wantCode: http.StatusOK, }, + { + name: "json: get resource from device", + args: args{ + deviceID: deviceID, + resourceHref: test.TestResourceLightInstanceHref("1"), + twin: newBool(false), + }, + want: map[interface{}]interface{}{"name": "Light", "power": uint64(0x0), "state": false}, + wantCode: http.StatusOK, + }, { name: "json: not exists", args: args{ @@ -278,6 +289,9 @@ func TestRequestHandlerGetResourceWithOnlyContent(t *testing.T) { rb := httpgwTest.NewRequest(http.MethodGet, uri.AliasDeviceResource, nil).AuthToken(token) rb.DeviceId(tt.args.deviceID).ResourceHref(tt.args.resourceHref) rb.OnlyContent(true) + if tt.args.twin != nil { + rb.Twin(*tt.args.twin) + } resp := httpgwTest.HTTPDo(t, rb.Build()) defer func() { _ = resp.Body.Close() diff --git a/http-gateway/service/getThings.go b/http-gateway/service/getThings.go index 468248eac..56b09aee6 100644 --- a/http-gateway/service/getThings.go +++ b/http-gateway/service/getThings.go @@ -383,7 +383,7 @@ func (requestHandler *RequestHandler) thingDescriptionResponse(ctx context.Conte func (requestHandler *RequestHandler) getThing(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) deviceID := vars[uri.DeviceIDKey] - rec, err := requestHandler.serveResourceRequest(r, deviceID, bridgeResourcesTD.ResourceURI, "", "") + rec, _, err := requestHandler.serveResourceRequest(r, deviceID, bridgeResourcesTD.ResourceURI, "", "") if err != nil { serverMux.WriteError(w, err) return diff --git a/http-gateway/swagger.wot.yaml b/http-gateway/swagger.wot.yaml new file mode 100644 index 000000000..ca7386796 --- /dev/null +++ b/http-gateway/swagger.wot.yaml @@ -0,0 +1,970 @@ +openapi: 3.1.0 +info: + title: plgd HTTP Gateway + version: 2.7.19 +servers: + - url: "https://try.plgd.cloud" +paths: + "/api/v1/things": + get: + tags: + - "Web of Things" + summary: "Retrieve Hub Thing Description" + description: | + Retrieve the description of the PLGD hub, including links to all associated things. + responses: + 200: + description: "Thing description of the plgd hub." + content: + application/json: + schema: + $ref: "#/components/schemas/thing" +components: + schemas: + anyUri: + type: string + description: + type: string + descriptions: + type: object + additionalProperties: + type: string + title: + type: string + titles: + type: object + additionalProperties: + type: string + security: + oneOf: + - type: array + items: + type: string + minItems: 1 + - type: string + scopes: + oneOf: + - type: array + items: + type: string + - type: string + subprotocol: + type: string + examples: + - longpoll + - websub + - sse + thing-context-td-uri-v1: + type: string + const: https://www.w3.org/2019/wot/td/v1 + thing-context-td-uri-v1.1: + type: string + const: https://www.w3.org/2022/wot/td/v1.1 + thing-context-td-uri-temp: + type: string + const: http://www.w3.org/ns/td + thing-context: + anyOf: + - $comment: New context URI with other vocabularies after it but not the old one + type: array + items: + - $ref: '#/components/schemas/thing-context-td-uri-v1.1' + additionalItems: + anyOf: + - $ref: '#/components/schemas/anyUri' + - type: object + not: + $ref: '#/components/schemas/thing-context-td-uri-v1' + - $comment: Only the new context URI + $ref: '#/components/schemas/thing-context-td-uri-v1.1' + - $comment: >- + Old context URI, followed by the new one and possibly other + vocabularies. minItems and contains are required since prefixItems + does not say all items should be provided + type: array + prefixItems: + - $ref: '#/components/schemas/thing-context-td-uri-v1' + - $ref: '#/components/schemas/thing-context-td-uri-v1.1' + minItems: 2 + contains: + $ref: '#/components/schemas/thing-context-td-uri-v1.1' + additionalItems: + anyOf: + - $ref: '#/components/schemas/anyUri' + - type: object + - $comment: >- + Old context URI, followed by possibly other vocabularies. minItems and + contains are required since prefixItems does not say all items should + be provided + type: array + prefixItems: + - $ref: '#/components/schemas/thing-context-td-uri-v1' + minItems: 1 + contains: + $ref: '#/components/schemas/thing-context-td-uri-v1' + additionalItems: + anyOf: + - $ref: '#/components/schemas/anyUri' + - type: object + - $comment: Only the old context URI + $ref: '#/components/schemas/thing-context-td-uri-v1' + bcp47_string: + type: string + pattern: >- + ^(((([A-Za-z]{2,3}(-([A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-([A-Za-z]{4}))?(-([A-Za-z]{2}|[0-9]{3}))?(-([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-([0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(x(-[A-Za-z0-9]{1,8})+))?)|(x(-[A-Za-z0-9]{1,8})+)|((en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)))$ + type_declaration: + oneOf: + - type: string + not: + const: tm:ThingModel + - type: array + items: + type: string + not: + const: tm:ThingModel + dataSchema-type: + type: string + enum: + - boolean + - integer + - number + - string + - object + - array + - 'null' + dataSchema: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + title: + $ref: '#/components/schemas/title' + descriptions: + $ref: '#/components/schemas/descriptions' + titles: + $ref: '#/components/schemas/titles' + writeOnly: + type: boolean + readOnly: + type: boolean + oneOf: + type: array + items: + $ref: '#/components/schemas/dataSchema' + unit: + type: string + enum: + type: array + minItems: 1 + uniqueItems: true + format: + type: string + const: {} + default: {} + contentEncoding: + type: string + contentMediaType: + type: string + type: + $ref: '#/components/schemas/dataSchema-type' + items: + oneOf: + - $ref: '#/components/schemas/dataSchema' + - type: array + items: + $ref: '#/components/schemas/dataSchema' + maxItems: + type: integer + minimum: 0 + minItems: + type: integer + minimum: 0 + minimum: + type: number + maximum: + type: number + exclusiveMinimum: + type: number + exclusiveMaximum: + type: number + minLength: + type: integer + minimum: 0 + maxLength: + type: integer + minimum: 0 + multipleOf: + $ref: '#/components/schemas/multipleOfDefinition' + properties: + additionalProperties: + $ref: '#/components/schemas/dataSchema' + required: + type: array + items: + type: string + additionalResponsesDefinition: + type: array + items: + type: object + properties: + contentType: + type: string + schema: + type: string + success: + type: boolean + multipleOfDefinition: + type: + - integer + - number + exclusiveMinimum: 0 + expectedResponse: + type: object + properties: + contentType: + type: string + required: + - contentType + form_element_base: + type: object + properties: + op: + oneOf: + - type: string + - type: array + items: + type: string + href: + $ref: '#/components/schemas/anyUri' + contentType: + type: string + contentCoding: + type: string + subprotocol: + $ref: '#/components/schemas/subprotocol' + security: + $ref: '#/components/schemas/security' + scopes: + $ref: '#/components/schemas/scopes' + response: + $ref: '#/components/schemas/expectedResponse' + additionalResponses: + $ref: '#/components/schemas/additionalResponsesDefinition' + required: + - href + additionalProperties: true + form_element_property: + allOf: + - $ref: '#/components/schemas/form_element_base' + type: object + properties: + op: + oneOf: + - type: string + enum: + - readproperty + - writeproperty + - observeproperty + - unobserveproperty + - type: array + items: + type: string + enum: + - readproperty + - writeproperty + - observeproperty + - unobserveproperty + minItems: 1 + additionalProperties: true + form_element_action: + allOf: + - $ref: '#/components/schemas/form_element_base' + type: object + properties: + op: + oneOf: + - type: string + enum: + - invokeaction + - queryaction + - cancelaction + - type: array + items: + type: string + enum: + - invokeaction + - queryaction + - cancelaction + minItems: 1 + additionalProperties: true + form_element_event: + allOf: + - $ref: '#/components/schemas/form_element_base' + type: object + properties: + op: + oneOf: + - type: string + enum: + - subscribeevent + - unsubscribeevent + - type: array + items: + type: string + enum: + - subscribeevent + - unsubscribeevent + minItems: 1 + additionalProperties: true + form_element_root: + allOf: + - $ref: '#/components/schemas/form_element_base' + type: object + properties: + op: + oneOf: + - type: string + enum: + - readallproperties + - writeallproperties + - readmultipleproperties + - writemultipleproperties + - observeallproperties + - unobserveallproperties + - queryallactions + - subscribeallevents + - unsubscribeallevents + - type: array + items: + type: string + enum: + - readallproperties + - writeallproperties + - readmultipleproperties + - writemultipleproperties + - observeallproperties + - unobserveallproperties + - queryallactions + - subscribeallevents + - unsubscribeallevents + minItems: 1 + additionalProperties: true + required: + - op + form: + $comment: >- + This is NOT for validation purposes but for automatic generation of TS + types. For more info, please see: + https://github.com/w3c/wot-thing-description/pull/1319#issuecomment-994950057 + oneOf: + - $ref: '#/components/schemas/form_element_property' + - $ref: '#/components/schemas/form_element_action' + - $ref: '#/components/schemas/form_element_event' + - $ref: '#/components/schemas/form_element_root' + property_element: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + title: + $ref: '#/components/schemas/title' + titles: + $ref: '#/components/schemas/titles' + forms: + type: array + minItems: 1 + items: + $ref: '#/components/schemas/form_element_property' + uriVariables: + type: object + additionalProperties: + $ref: '#/components/schemas/dataSchema' + observable: + type: boolean + writeOnly: + type: boolean + readOnly: + type: boolean + oneOf: + type: array + items: + $ref: '#/components/schemas/dataSchema' + unit: + type: string + enum: + type: array + minItems: 1 + uniqueItems: true + format: + type: string + const: {} + default: {} + type: + $ref: '#/components/schemas/dataSchema-type' + items: + oneOf: + - $ref: '#/components/schemas/dataSchema' + - type: array + items: + $ref: '#/components/schemas/dataSchema' + maxItems: + type: integer + minimum: 0 + minItems: + type: integer + minimum: 0 + minimum: + type: number + maximum: + type: number + exclusiveMinimum: + type: number + exclusiveMaximum: + type: number + minLength: + type: integer + minimum: 0 + maxLength: + type: integer + minimum: 0 + multipleOf: + $ref: '#/components/schemas/multipleOfDefinition' + properties: + additionalProperties: + $ref: '#/components/schemas/dataSchema' + required: + type: array + items: + type: string + required: + - forms + additionalProperties: true + action_element: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + title: + $ref: '#/components/schemas/title' + titles: + $ref: '#/components/schemas/titles' + forms: + type: array + minItems: 1 + items: + $ref: '#/components/schemas/form_element_action' + uriVariables: + type: object + additionalProperties: + $ref: '#/components/schemas/dataSchema' + input: + $ref: '#/components/schemas/dataSchema' + output: + $ref: '#/components/schemas/dataSchema' + safe: + type: boolean + idempotent: + type: boolean + synchronous: + type: boolean + required: + - forms + additionalProperties: true + event_element: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + title: + $ref: '#/components/schemas/title' + titles: + $ref: '#/components/schemas/titles' + forms: + type: array + minItems: 1 + items: + $ref: '#/components/schemas/form_element_event' + uriVariables: + type: object + additionalProperties: + $ref: '#/components/schemas/dataSchema' + subscription: + $ref: '#/components/schemas/dataSchema' + data: + $ref: '#/components/schemas/dataSchema' + dataResponse: + $ref: '#/components/schemas/dataSchema' + cancellation: + $ref: '#/components/schemas/dataSchema' + required: + - forms + additionalProperties: true + base_link_element: + type: object + properties: + href: + $ref: '#/components/schemas/anyUri' + type: + type: string + rel: + type: string + anchor: + $ref: '#/components/schemas/anyUri' + hreflang: + anyOf: + - $ref: '#/components/schemas/bcp47_string' + - type: array + items: + $ref: '#/components/schemas/bcp47_string' + required: + - href + additionalProperties: true + link_element: + allOf: + - $ref: '#/components/schemas/base_link_element' + - not: + description: A basic link element should not contain sizes + type: object + properties: + sizes: {} + required: + - sizes + - not: + description: A basic link element should not contain icon or tm:extends + properties: + rel: + enum: + - icon + - tm:extends + required: + - rel + icon_link_element: + allOf: + - $ref: '#/components/schemas/base_link_element' + - properties: + rel: + const: icon + sizes: + type: string + pattern: '[0-9]*x[0-9]+' + required: + - rel + additionalSecurityScheme: + description: >- + Applies to additional SecuritySchemes not defined in the WoT TD + specification. + $comment: >- + Additional SecuritySchemes should always be defined via a context + extension, using a prefixed value for the scheme. This prefix (e.g. 'ace', + see the example below) must contain at least one character in order to + reference a valid JSON-LD context extension. + examples: + - scheme: ace:ACESecurityScheme + ace:as: coaps://as.example.com/token + ace:audience: coaps://rs.example.com + ace:scopes: + - limited + - special + ace:cnonce: true + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + pattern: .+:.* + required: + - scheme + additionalProperties: true + noSecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - nosec + required: + - scheme + additionalProperties: true + autoSecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - auto + not: + required: + - name + required: + - scheme + additionalProperties: true + comboSecurityScheme: + oneOf: + - type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - combo + oneOf: + type: array + minItems: 2 + items: + type: string + required: + - scheme + - oneOf + additionalProperties: true + - type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - combo + allOf: + type: array + minItems: 2 + items: + type: string + required: + - scheme + - allOf + additionalProperties: true + basicSecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - basic + in: + type: string + enum: + - header + - query + - body + - cookie + - auto + name: + type: string + required: + - scheme + additionalProperties: true + digestSecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - digest + qop: + type: string + enum: + - auth + - auth-int + in: + type: string + enum: + - header + - query + - body + - cookie + - auto + name: + type: string + required: + - scheme + additionalProperties: true + apiKeySecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - apikey + in: + type: string + enum: + - header + - query + - body + - cookie + - uri + - auto + name: + type: string + required: + - scheme + additionalProperties: true + bearerSecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - bearer + authorization: + $ref: '#/components/schemas/anyUri' + alg: + type: string + format: + type: string + in: + type: string + enum: + - header + - query + - body + - cookie + - auto + name: + type: string + required: + - scheme + additionalProperties: true + pskSecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - psk + identity: + type: string + required: + - scheme + additionalProperties: true + oAuth2SecurityScheme: + type: object + properties: + '@type': + $ref: '#/components/schemas/type_declaration' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + proxy: + $ref: '#/components/schemas/anyUri' + scheme: + type: string + enum: + - oauth2 + authorization: + $ref: '#/components/schemas/anyUri' + token: + $ref: '#/components/schemas/anyUri' + refresh: + $ref: '#/components/schemas/anyUri' + scopes: + oneOf: + - type: array + items: + type: string + - type: string + flow: + anyOf: + - type: string + - type: string + enum: + - code + - client + required: + - scheme + additionalProperties: true + securityScheme: + oneOf: + - $ref: '#/components/schemas/noSecurityScheme' + - $ref: '#/components/schemas/autoSecurityScheme' + - $ref: '#/components/schemas/comboSecurityScheme' + - $ref: '#/components/schemas/basicSecurityScheme' + - $ref: '#/components/schemas/digestSecurityScheme' + - $ref: '#/components/schemas/apiKeySecurityScheme' + - $ref: '#/components/schemas/bearerSecurityScheme' + - $ref: '#/components/schemas/pskSecurityScheme' + - $ref: '#/components/schemas/oAuth2SecurityScheme' + - $ref: '#/components/schemas/additionalSecurityScheme' + thing: + type: object + properties: + id: + type: string + format: uri + title: + $ref: '#/components/schemas/title' + titles: + $ref: '#/components/schemas/titles' + properties: + type: object + additionalProperties: + $ref: '#/components/schemas/property_element' + actions: + type: object + additionalProperties: + $ref: '#/components/schemas/action_element' + events: + type: object + additionalProperties: + $ref: '#/components/schemas/event_element' + description: + $ref: '#/components/schemas/description' + descriptions: + $ref: '#/components/schemas/descriptions' + version: + type: object + properties: + instance: + type: string + required: + - instance + links: + type: array + items: + oneOf: + - $ref: '#/components/schemas/link_element' + - $ref: '#/components/schemas/icon_link_element' + forms: + type: array + minItems: 1 + items: + $ref: '#/components/schemas/form_element_root' + base: + $ref: '#/components/schemas/anyUri' + securityDefinitions: + type: object + minProperties: 1 + additionalProperties: + $ref: '#/components/schemas/securityScheme' + schemaDefinitions: + type: object + minProperties: 1 + additionalProperties: + $ref: '#/components/schemas/dataSchema' + support: + $ref: '#/components/schemas/anyUri' + created: + type: string + format: date-time + modified: + type: string + format: date-time + profile: + oneOf: + - $ref: '#/components/schemas/anyUri' + - type: array + minItems: 1 + items: + $ref: '#/components/schemas/anyUri' + security: + oneOf: + - type: string + - type: array + minItems: 1 + items: + type: string + uriVariables: + type: object + additionalProperties: + $ref: '#/components/schemas/dataSchema' + '@type': + $ref: '#/components/schemas/type_declaration' + '@context': + $ref: '#/components/schemas/thing-context' + required: + - title + - security + - securityDefinitions + - '@context' + additionalProperties: true diff --git a/http-gateway/swagger.yaml b/http-gateway/swagger.yaml index e07d35627..72329ff07 100644 --- a/http-gateway/swagger.yaml +++ b/http-gateway/swagger.yaml @@ -19,6 +19,40 @@ paths: application/json: schema: $ref: "#/components/schemas/HubConfiguration" + "/api/v1/things": + get: + tags: + - "Web of Things" + summary: "Retrieve Hub Thing Description" + description: | + Retrieve the description of the PLGD hub, including links to all associated things. + responses: + 200: + description: "Thing description of the plgd hub." + content: + application/json: + schema: + $ref: "https://raw.githubusercontent.com/plgd-dev/hub/main/http-gateway/swagger.wot.yaml#/components/schemas/thing" + 401: + $ref: "#/components/responses/unauthorized" + "/api/v1/things/{deviceId}": + get: + tags: + - "Web of Things" + summary: "Retrieve Device Thing Description" + description: | + Retrieve the thing description for a specific device. The device must be listed in the links of /api/v1/things. + parameters: + - $ref: "#/components/parameters/deviceId" + responses: + 200: + description: "Thing description of the device." + content: + application/json: + schema: + $ref: "https://raw.githubusercontent.com/plgd-dev/hub/main/http-gateway/swagger.wot.yaml#/components/schemas/thing" + 401: + $ref: "#/components/responses/unauthorized" "/api/v1/devices": get: tags: