Skip to content

Commit

Permalink
Enable restore NSE name in setid
Browse files Browse the repository at this point in the history
Signed-off-by: Vladimir Popov <vladimir.popov@xored.com>
  • Loading branch information
Vladimir Popov committed May 18, 2021
1 parent d09236b commit 211ddd1
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 54 deletions.
44 changes: 28 additions & 16 deletions pkg/registry/common/setid/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ import (

"github.com/golang/protobuf/ptypes/empty"
"github.com/google/uuid"
"github.com/networkservicemesh/api/pkg/api/registry"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/networkservicemesh/api/pkg/api/registry"

"github.com/networkservicemesh/sdk/pkg/registry/core/next"
"github.com/networkservicemesh/sdk/pkg/tools/grpcutils"
)

type setIDClient struct {
Expand All @@ -46,27 +45,40 @@ func (c *setIDClient) Register(ctx context.Context, nse *registry.NetworkService
return next.NetworkServiceEndpointRegistryClient(ctx).Register(ctx, nse, opts...)
}

nameSuffix := nse.Name
if nameSuffix == "" {
nameSuffix = strings.Join(nse.NetworkServiceNames, "-")
if nse.Name == "" {
nse.Name = strings.Join(nse.NetworkServiceNames, "-")
}

nameSuffix := "-" + nse.Name

stream, err := next.NetworkServiceEndpointRegistryClient(ctx).Find(ctx, &registry.NetworkServiceEndpointQuery{
NetworkServiceEndpoint: nse,
})
if err != nil {
return nil, err
}
nameSuffix = "-" + nameSuffix

for err = status.Error(codes.AlreadyExists, ""); err != nil && isAlreadyExistsError(err); {
name := uuid.New().String() + nameSuffix
nse.Name = uuid.New().String() + nameSuffix
for _, foundNSE := range registry.ReadNetworkServiceEndpointList(stream) {
if foundNSE.Url == nse.Url {
nse.Name = foundNSE.Name
break
}
}

nse.Name = name
for {
name := nse.Name
if reg, err = next.NetworkServiceEndpointRegistryClient(ctx).Register(ctx, nse, opts...); err == nil {
c.names.Store(name, struct{}{})
return reg, nil
}
}

return reg, err
}
if err != nil && grpcutils.UnwrapCode(err) != codes.AlreadyExists {
return nil, err
}

func isAlreadyExistsError(e error) bool {
grpcStatus, ok := status.FromError(e)
return ok && grpcStatus.Code() == codes.AlreadyExists
nse.Name = uuid.New().String() + nameSuffix
}
}

func (c *setIDClient) Find(ctx context.Context, query *registry.NetworkServiceEndpointQuery, opts ...grpc.CallOption) (registry.NetworkServiceEndpointRegistry_FindClient, error) {
Expand Down
196 changes: 158 additions & 38 deletions pkg/registry/common/setid/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,62 +29,111 @@ import (

"github.com/networkservicemesh/api/pkg/api/registry"

"github.com/networkservicemesh/sdk/pkg/registry/common/checkid"
"github.com/networkservicemesh/sdk/pkg/registry/common/memory"
"github.com/networkservicemesh/sdk/pkg/registry/common/setid"
"github.com/networkservicemesh/sdk/pkg/registry/core/adapters"
"github.com/networkservicemesh/sdk/pkg/registry/core/next"
)

func TestSetIDClient_EmptyName(t *testing.T) {
c := setid.NewNetworkServiceEndpointRegistryClient()
const (
url1 = "tcp://1.1.1.1"
url2 = "tcp://2.2.2.2"
)

nse := &registry.NetworkServiceEndpoint{
NetworkServiceNames: []string{"ns-1", "ns-2"},
}
func testEndpoints(nse *registry.NetworkServiceEndpoint) (nses [2]*registry.NetworkServiceEndpoint) {
nses[0] = nse.Clone()
nses[0].Url = url1

// 1. Register
reg1, err := c.Register(context.Background(), nse.Clone())
require.NoError(t, err)
require.Contains(t, reg1.Name, nse.NetworkServiceNames[0])
require.Contains(t, reg1.Name, nse.NetworkServiceNames[1])
nses[1] = nse.Clone()
nses[1].Url = url2

reg2, err := c.Register(context.Background(), nse.Clone())
require.NoError(t, err)
require.Contains(t, reg2.Name, nse.NetworkServiceNames[0])
require.Contains(t, reg2.Name, nse.NetworkServiceNames[1])
return nses
}

require.NotEqual(t, reg1.Name, reg2.Name)
func TestSetIDClient(t *testing.T) {
samples := []struct {
name string
nse *registry.NetworkServiceEndpoint
nameCheck func(t *testing.T, name string)
}{
{
name: "Empty name",
nse: &registry.NetworkServiceEndpoint{
NetworkServiceNames: []string{"ns-1", "ns-2"},
},
nameCheck: func(t *testing.T, name string) {
require.Contains(t, name, "ns-1")
require.Contains(t, name, "ns-2")
},
},
{
name: "Empty NS names",
nse: &registry.NetworkServiceEndpoint{
Name: "nse",
},
nameCheck: func(t *testing.T, name string) {
require.Contains(t, name, "nse")
},
},
{
name: "All set",
nse: &registry.NetworkServiceEndpoint{
Name: "nse",
NetworkServiceNames: []string{"ns-1", "ns-2"},
},
nameCheck: func(t *testing.T, name string) {
require.Contains(t, name, "nse")
},
},
}

// 2. Refresh
refresh, err := c.Register(context.Background(), reg1.Clone())
require.NoError(t, err)
require.Equal(t, reg1.Name, refresh.Name)
for _, sample := range samples {
// nolint:scopelint
t.Run(sample.name, func(t *testing.T) {
testSetIDClient(t, sample.nse, sample.nameCheck)
})
}
}

// 3. Unregister
_, err = c.Unregister(context.Background(), reg1.Clone())
require.NoError(t, err)
func testSetIDClient(t *testing.T, nse *registry.NetworkServiceEndpoint, nameCheck func(t *testing.T, name string)) {
c := next.NewNetworkServiceEndpointRegistryClient(
setid.NewNetworkServiceEndpointRegistryClient(),
adapters.NetworkServiceEndpointServerToClient(next.NewNetworkServiceEndpointRegistryServer(
checkid.NewNetworkServiceEndpointRegistryServer(),
memory.NewNetworkServiceEndpointRegistryServer(),
)),
)

refresh, err = c.Register(context.Background(), reg1.Clone())
require.NoError(t, err)
nses := testEndpoints(nse)

require.NotEqual(t, reg1.Name, refresh.Name)
require.NotEqual(t, reg2.Name, refresh.Name)
}
// 1. Register
var regs [2]*registry.NetworkServiceEndpoint
var err error
for i := range nses {
regs[i], err = c.Register(context.Background(), nses[i].Clone())
require.NoError(t, err)
nameCheck(t, regs[i].Name)
}

func TestSetIDClient_NotEmptyName(t *testing.T) {
c := setid.NewNetworkServiceEndpointRegistryClient()
require.NotEqual(t, regs[0].Name, regs[1].Name)

nse := &registry.NetworkServiceEndpoint{
Name: "nse",
// 2. Refresh
for _, reg := range regs {
refresh, refreshErr := c.Register(context.Background(), reg.Clone())
require.NoError(t, refreshErr)
require.Equal(t, reg.Name, refresh.Name)
}

reg1, err := c.Register(context.Background(), nse.Clone())
// 3. Unregister
_, err = c.Unregister(context.Background(), regs[0].Clone())
require.NoError(t, err)
require.Contains(t, reg1.Name, nse.Name)

reg2, err := c.Register(context.Background(), nse.Clone())
refresh, err := c.Register(context.Background(), regs[0].Clone())
require.NoError(t, err)
require.Contains(t, reg2.Name, nse.Name)

require.NotEqual(t, reg1.Name, reg2.Name)
require.NotEqual(t, regs[0].Name, refresh.Name)
require.NotEqual(t, regs[1].Name, refresh.Name)
}

func TestSetIDClient_Duplicate(t *testing.T) {
Expand Down Expand Up @@ -114,11 +163,78 @@ func TestSetIDClient_Error(t *testing.T) {
require.Error(t, err)
}

func TestSetIDClient_Restore(t *testing.T) {
samples := []struct {
name string
nse *registry.NetworkServiceEndpoint
}{
{
name: "Empty name",
nse: &registry.NetworkServiceEndpoint{
NetworkServiceNames: []string{"ns-1", "ns-2"},
},
},
{
name: "Empty NS names",
nse: &registry.NetworkServiceEndpoint{
Name: "nse",
},
},
{
name: "All set",
nse: &registry.NetworkServiceEndpoint{
Name: "nse",
NetworkServiceNames: []string{"ns-1", "ns-2"},
},
},
}

for _, sample := range samples {
// nolint:scopelint
t.Run(sample.name, func(t *testing.T) {
testSetIDClientRestore(t, sample.nse)
})
}
}

func testSetIDClientRestore(t *testing.T, nse *registry.NetworkServiceEndpoint) {
s := next.NewNetworkServiceEndpointRegistryServer(
checkid.NewNetworkServiceEndpointRegistryServer(),
memory.NewNetworkServiceEndpointRegistryServer(),
)

nses := testEndpoints(nse)

// 1. Register
c := next.NewNetworkServiceEndpointRegistryClient(
setid.NewNetworkServiceEndpointRegistryClient(),
adapters.NetworkServiceEndpointServerToClient(s),
)

var regs [2]*registry.NetworkServiceEndpoint
var err error
for i := range nses {
regs[i], err = c.Register(context.Background(), nses[i].Clone())
require.NoError(t, err)
}

// 2. Restore registration
c = next.NewNetworkServiceEndpointRegistryClient(
setid.NewNetworkServiceEndpointRegistryClient(),
adapters.NetworkServiceEndpointServerToClient(s),
)

var restores [2]*registry.NetworkServiceEndpoint
for i := range nses {
restores[i], err = c.Register(context.Background(), nses[i].Clone())
require.NoError(t, err)
require.Equal(t, regs[i].Name, restores[i].Name)
}
}

type errorClient struct {
count, expected int
err error

registry.NetworkServiceEndpointRegistryClient
}

func (c *errorClient) Register(ctx context.Context, nse *registry.NetworkServiceEndpoint, opts ...grpc.CallOption) (*registry.NetworkServiceEndpoint, error) {
Expand All @@ -131,6 +247,10 @@ func (c *errorClient) Register(ctx context.Context, nse *registry.NetworkService
return next.NetworkServiceEndpointRegistryClient(ctx).Register(ctx, nse, opts...)
}

func (c *errorClient) Find(ctx context.Context, query *registry.NetworkServiceEndpointQuery, opts ...grpc.CallOption) (registry.NetworkServiceEndpointRegistry_FindClient, error) {
return next.NetworkServiceEndpointRegistryClient(ctx).Find(ctx, query, opts...)
}

func (c *errorClient) Unregister(ctx context.Context, nse *registry.NetworkServiceEndpoint, opts ...grpc.CallOption) (*empty.Empty, error) {
return next.NetworkServiceEndpointRegistryClient(ctx).Unregister(ctx, nse, opts...)
}

0 comments on commit 211ddd1

Please sign in to comment.