From 090e3af3ac353d1e30af6fdd05fdaa49f477e04f Mon Sep 17 00:00:00 2001 From: Artem Glazychev Date: Wed, 3 Nov 2021 19:06:26 +0700 Subject: [PATCH] Add registration time chain element Signed-off-by: Artem Glazychev --- pkg/registry/chains/memory/server.go | 2 + .../common/setregistrationtime/doc.go | 18 ++++ .../common/setregistrationtime/nse_server.go | 52 +++++++++ .../setregistrationtime/nse_server_test.go | 101 ++++++++++++++++++ 4 files changed, 173 insertions(+) create mode 100644 pkg/registry/common/setregistrationtime/doc.go create mode 100644 pkg/registry/common/setregistrationtime/nse_server.go create mode 100644 pkg/registry/common/setregistrationtime/nse_server_test.go diff --git a/pkg/registry/chains/memory/server.go b/pkg/registry/chains/memory/server.go index df0c697030..2c67bd8e18 100644 --- a/pkg/registry/chains/memory/server.go +++ b/pkg/registry/chains/memory/server.go @@ -33,6 +33,7 @@ import ( "github.com/networkservicemesh/sdk/pkg/registry/common/serialize" "github.com/networkservicemesh/sdk/pkg/registry/common/setlogoption" "github.com/networkservicemesh/sdk/pkg/registry/common/setpayload" + "github.com/networkservicemesh/sdk/pkg/registry/common/setregistrationtime" "github.com/networkservicemesh/sdk/pkg/registry/core/chain" ) @@ -41,6 +42,7 @@ func NewServer(ctx context.Context, expiryDuration time.Duration, proxyRegistryU nseChain := chain.NewNetworkServiceEndpointRegistryServer( setlogoption.NewNetworkServiceEndpointRegistryServer(map[string]string{}), serialize.NewNetworkServiceEndpointRegistryServer(), + setregistrationtime.NewNetworkServiceEndpointRegistryServer(), expire.NewNetworkServiceEndpointRegistryServer(ctx, expiryDuration), checkid.NewNetworkServiceEndpointRegistryServer(), memory.NewNetworkServiceEndpointRegistryServer(), diff --git a/pkg/registry/common/setregistrationtime/doc.go b/pkg/registry/common/setregistrationtime/doc.go new file mode 100644 index 0000000000..67a5207482 --- /dev/null +++ b/pkg/registry/common/setregistrationtime/doc.go @@ -0,0 +1,18 @@ +// Copyright (c) 2021 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package setregistrationtime provides registry server chain elements for initial registration time setting +package setregistrationtime diff --git a/pkg/registry/common/setregistrationtime/nse_server.go b/pkg/registry/common/setregistrationtime/nse_server.go new file mode 100644 index 0000000000..77ac610e8d --- /dev/null +++ b/pkg/registry/common/setregistrationtime/nse_server.go @@ -0,0 +1,52 @@ +// Copyright (c) 2021 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package setregistrationtime + +import ( + "context" + + "github.com/golang/protobuf/ptypes/empty" + "github.com/networkservicemesh/api/pkg/api/registry" + "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/networkservicemesh/sdk/pkg/registry/core/next" + "github.com/networkservicemesh/sdk/pkg/tools/clock" +) + +type setregtimeNSEServer struct{} + +// NewNetworkServiceEndpointRegistryServer creates a new NetworkServiceServer chain element that sets initial +// registration time. +func NewNetworkServiceEndpointRegistryServer() registry.NetworkServiceEndpointRegistryServer { + return &setregtimeNSEServer{} +} + +func (r *setregtimeNSEServer) Register(ctx context.Context, nse *registry.NetworkServiceEndpoint) (*registry.NetworkServiceEndpoint, error) { + if nse.InitialRegistrationTime == nil { + nse.InitialRegistrationTime = timestamppb.New(clock.FromContext(ctx).Now()) + } + + return next.NetworkServiceEndpointRegistryServer(ctx).Register(ctx, nse) +} + +func (r *setregtimeNSEServer) Find(q *registry.NetworkServiceEndpointQuery, s registry.NetworkServiceEndpointRegistry_FindServer) error { + return next.NetworkServiceEndpointRegistryServer(s.Context()).Find(q, s) +} + +func (r *setregtimeNSEServer) Unregister(ctx context.Context, nse *registry.NetworkServiceEndpoint) (*empty.Empty, error) { + return next.NetworkServiceEndpointRegistryServer(ctx).Unregister(ctx, nse) +} diff --git a/pkg/registry/common/setregistrationtime/nse_server_test.go b/pkg/registry/common/setregistrationtime/nse_server_test.go new file mode 100644 index 0000000000..30d1004187 --- /dev/null +++ b/pkg/registry/common/setregistrationtime/nse_server_test.go @@ -0,0 +1,101 @@ +// Copyright (c) 2021 Doc.ai and/or its affiliates. +// +// SPDX-License-Identifier: Apache-2.0 +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at: +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package setregistrationtime_test + +import ( + "context" + "testing" + "time" + + "github.com/networkservicemesh/api/pkg/api/registry" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + + "github.com/networkservicemesh/sdk/pkg/tools/clock" + "github.com/networkservicemesh/sdk/pkg/tools/clockmock" + + "github.com/networkservicemesh/sdk/pkg/registry/common/memory" + "github.com/networkservicemesh/sdk/pkg/registry/common/setregistrationtime" + "github.com/networkservicemesh/sdk/pkg/registry/core/next" + "github.com/networkservicemesh/sdk/pkg/registry/core/streamchannel" +) + +func testNSE() *registry.NetworkServiceEndpoint { + return ®istry.NetworkServiceEndpoint{ + Name: "nse", + Url: "tcp://0.0.0.0", + } +} + +func TestRegTimeServer_Register(t *testing.T) { + s := next.NewNetworkServiceEndpointRegistryServer( + setregistrationtime.NewNetworkServiceEndpointRegistryServer(), + memory.NewNetworkServiceEndpointRegistryServer(), + ) + + ctx := context.Background() + clockMock := clockmock.New(ctx) + ctx = clock.WithClock(ctx, clockMock) + + // 1. Register + reg, err := s.Register(ctx, testNSE()) + require.NoError(t, err) + require.NotNil(t, reg.InitialRegistrationTime) + require.Equal(t, clockMock.Now(), reg.InitialRegistrationTime.AsTime().Local()) + registeredNse := reg.Clone() + + // 2. Find + nses := find(t, s, ®istry.NetworkServiceEndpointQuery{ + NetworkServiceEndpoint: new(registry.NetworkServiceEndpoint), + }) + require.Len(t, nses, 1) + require.True(t, proto.Equal(nses[0].InitialRegistrationTime, registeredNse.InitialRegistrationTime)) + + // 3. Refresh + reg, err = s.Register(ctx, reg.Clone()) + require.NoError(t, err) + require.NotNil(t, reg.InitialRegistrationTime) + require.True(t, proto.Equal(reg.InitialRegistrationTime, registeredNse.InitialRegistrationTime)) + + // 4. Unregister + _, err = s.Unregister(ctx, reg.Clone()) + require.NoError(t, err) + + // 5. Register again + clockMock.Add(time.Second * 3) + reg, err = s.Register(ctx, testNSE()) + require.NoError(t, err) + require.NotNil(t, reg.InitialRegistrationTime) + require.Equal(t, clockMock.Now(), reg.InitialRegistrationTime.AsTime().Local()) +} + +func find(t *testing.T, mem registry.NetworkServiceEndpointRegistryServer, query *registry.NetworkServiceEndpointQuery) (nses []*registry.NetworkServiceEndpoint) { + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) + defer cancel() + + ch := make(chan *registry.NetworkServiceEndpointResponse) + go func() { + defer close(ch) + require.NoError(t, mem.Find(query, streamchannel.NewNetworkServiceEndpointFindServer(ctx, ch))) + }() + + for nseResp := range ch { + nses = append(nses, nseResp.NetworkServiceEndpoint) + } + + return nses +}