Skip to content

Commit

Permalink
add support for external dns in sdk
Browse files Browse the repository at this point in the history
Signed-off-by: Denis Tingaikin <[email protected]>
  • Loading branch information
denis-tingaikin committed Jun 25, 2023
1 parent a8c394e commit bb6e3ec
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 10 deletions.
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,6 @@ issues:
linters:
- interfacer
text: "`rawSrv` can be `github.com/networkservicemesh/sdk/pkg/networkservice/common/monitor.EventConsumer`"
- path: ppkg/networkservice/chains/dnsresolve/.*_test.go
linters:
- unlambda
15 changes: 13 additions & 2 deletions pkg/registry/chains/proxydns/server.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) 2020-2022 Doc.ai and/or its affiliates.
//
// Copyright (c) 2023 Cisco Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -43,6 +45,7 @@ type serverOptions struct {
authorizeNSERegistryServer registryapi.NetworkServiceEndpointRegistryServer
authorizeNSRegistryClient registryapi.NetworkServiceRegistryClient
authorizeNSERegistryClient registryapi.NetworkServiceEndpointRegistryClient
dnsresolveOptions []dnsresolve.Option
dialOptions []grpc.DialOption
}

Expand Down Expand Up @@ -89,6 +92,13 @@ func WithAuthorizeNSERegistryClient(authorizeNSERegistryClient registryapi.Netwo
}
}

// WithDNSResolveOptions overrides default dns resolve options
func WithDNSResolveOptions(opts ...dnsresolve.Option) Option {
return func(o *serverOptions) {
o.dnsresolveOptions = opts
}
}

// WithDialOptions sets grpc.DialOptions for the server
func WithDialOptions(dialOptions ...grpc.DialOption) Option {
return func(o *serverOptions) {
Expand All @@ -103,6 +113,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResol
authorizeNSERegistryServer: registryauthorize.NewNetworkServiceEndpointRegistryServer(registryauthorize.Any()),
authorizeNSRegistryClient: registryauthorize.NewNetworkServiceRegistryClient(registryauthorize.Any()),
authorizeNSERegistryClient: registryauthorize.NewNetworkServiceEndpointRegistryClient(registryauthorize.Any()),
dnsresolveOptions: []dnsresolve.Option{dnsresolve.WithResolver(dnsResolver)},
}
for _, opt := range options {
opt(opts)
Expand All @@ -113,7 +124,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResol
updatepath.NewNetworkServiceEndpointRegistryServer(tokenGenerator),
opts.authorizeNSERegistryServer,
begin.NewNetworkServiceEndpointRegistryServer(),
dnsresolve.NewNetworkServiceEndpointRegistryServer(dnsresolve.WithResolver(dnsResolver)),
dnsresolve.NewNetworkServiceEndpointRegistryServer(opts.dnsresolveOptions...),
connect.NewNetworkServiceEndpointRegistryServer(
chain.NewNetworkServiceEndpointRegistryClient(
clientconn.NewNetworkServiceEndpointRegistryClient(),
Expand All @@ -130,7 +141,7 @@ func NewServer(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResol
updatepath.NewNetworkServiceRegistryServer(tokenGenerator),
begin.NewNetworkServiceRegistryServer(),
opts.authorizeNSRegistryServer,
dnsresolve.NewNetworkServiceRegistryServer(dnsresolve.WithResolver(dnsResolver)),
dnsresolve.NewNetworkServiceRegistryServer(opts.dnsresolveOptions...),
connect.NewNetworkServiceRegistryServer(
chain.NewNetworkServiceRegistryClient(
clientconn.NewNetworkServiceRegistryClient(),
Expand Down
87 changes: 86 additions & 1 deletion pkg/registry/chains/proxydns/server_ns_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2020-2022 Doc.ai and/or its affiliates.
//
// Copyright (c) 2022 Cisco Systems, Inc.
// Copyright (c) 2022-2023 Cisco Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
Expand Down Expand Up @@ -30,12 +30,97 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

"github.com/networkservicemesh/sdk/pkg/registry"
registryclient "github.com/networkservicemesh/sdk/pkg/registry/chains/client"
"github.com/networkservicemesh/sdk/pkg/registry/chains/proxydns"
"github.com/networkservicemesh/sdk/pkg/registry/common/dnsresolve"

"github.com/networkservicemesh/sdk/pkg/tools/grpcutils"
"github.com/networkservicemesh/sdk/pkg/tools/sandbox"
"github.com/networkservicemesh/sdk/pkg/tools/token"
)

func TestInterdomainNetworkServiceRegistryWithDifferentDNSScheme(t *testing.T) {
t.Cleanup(func() { goleak.VerifyNone(t) })

ctx, cancel := context.WithTimeout(context.Background(), time.Hour*10)
defer cancel()

dnsServer := sandbox.NewFakeResolver()

domain1 := sandbox.NewBuilder(ctx, t).
SetNodesCount(0).
SetDNSResolver(dnsServer).
SetRegistryProxySupplier(func(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResolver dnsresolve.Resolver, options ...proxydns.Option) registry.Registry {
return proxydns.NewServer(
ctx,
tokenGenerator,
dnsResolver,
append(options,
proxydns.WithDNSResolveOptions(
dnsresolve.WithNSMgrProxyService("nsmgr-proxy2"),
dnsresolve.WithRegistryService("registry2"),
dnsresolve.WithResolver(dnsResolver),
))...,
)
}).
Build()

dnsServer.DeleteSRVEntry(dnsresolve.DefaultNsmgrProxyService, domain1.Name)
dnsServer.DeleteSRVEntry(dnsresolve.DefaultRegistryService, domain1.Name)

dnsServer.AddSRVEntry("example.com", "nsmgr-proxy1", domain1.NSMgrProxy.URL)
dnsServer.AddSRVEntry("example.com", "registry1", domain1.Registry.URL)

domain2 := sandbox.NewBuilder(ctx, t).
SetNodesCount(0).
SetDNSResolver(dnsServer).
SetRegistryProxySupplier(func(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResolver dnsresolve.Resolver, options ...proxydns.Option) registry.Registry {
return proxydns.NewServer(
ctx,
tokenGenerator,
dnsResolver,
append(options,
proxydns.WithDNSResolveOptions(
dnsresolve.WithNSMgrProxyService("nsmgr-proxy1"),
dnsresolve.WithRegistryService("registry1"),
dnsresolve.WithResolver(dnsResolver),
))...,
)
}).
Build()

dnsServer.DeleteSRVEntry(dnsresolve.DefaultNsmgrProxyService, domain2.Name)
dnsServer.DeleteSRVEntry(dnsresolve.DefaultRegistryService, domain2.Name)

dnsServer.AddSRVEntry("example.com", "nsmgr-proxy2", domain2.NSMgrProxy.URL)
dnsServer.AddSRVEntry("example.com", "registry2", domain2.Registry.URL)

client1 := registryclient.NewNetworkServiceRegistryClient(ctx,
registryclient.WithDialOptions(grpc.WithTransportCredentials(insecure.NewCredentials())),
registryclient.WithClientURL(domain1.Registry.URL))

client2 := registryclient.NewNetworkServiceRegistryClient(ctx,
registryclient.WithDialOptions(grpc.WithTransportCredentials(insecure.NewCredentials())),
registryclient.WithClientURL(domain2.Registry.URL))

_, err := client2.Register(context.Background(), &registryapi.NetworkService{Name: "ns-1"})
require.NoError(t, err)

stream, err := client1.Find(ctx, &registryapi.NetworkServiceQuery{
NetworkService: &registryapi.NetworkService{
Name: "ns-1@" + "example.com",
},
})

require.Nil(t, err)

list := registryapi.ReadNetworkServiceList(stream)

require.Len(t, list, 1)
require.Equal(t, "ns-1@"+"example.com", list[0].Name)
}

/*
TestInterdomainNetworkServiceEndpointRegistry covers the next scenario:
1. local registry from domain2 has entry "ns-1"
Expand Down
101 changes: 101 additions & 0 deletions pkg/registry/chains/proxydns/server_nse_test.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) 2020-2022 Doc.ai and/or its affiliates.
//
// Copyright (c) 2023 Cisco Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -30,11 +32,110 @@ import (

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

"github.com/networkservicemesh/sdk/pkg/registry"
registryclient "github.com/networkservicemesh/sdk/pkg/registry/chains/client"
"github.com/networkservicemesh/sdk/pkg/registry/chains/proxydns"
"github.com/networkservicemesh/sdk/pkg/registry/common/dnsresolve"
"github.com/networkservicemesh/sdk/pkg/tools/grpcutils"
"github.com/networkservicemesh/sdk/pkg/tools/sandbox"
"github.com/networkservicemesh/sdk/pkg/tools/token"
)

func TestInterdomainNetworkServiceEndpointRegistryWithDifferentDNSScheme(t *testing.T) {
t.Cleanup(func() { goleak.VerifyNone(t) })

ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()

dnsServer := sandbox.NewFakeResolver()

domain1 := sandbox.NewBuilder(ctx, t).
SetNodesCount(0).
SetDNSResolver(dnsServer).
SetRegistryProxySupplier(func(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResolver dnsresolve.Resolver, options ...proxydns.Option) registry.Registry {
return proxydns.NewServer(
ctx,
tokenGenerator,
dnsResolver,
append(options,
proxydns.WithDNSResolveOptions(
dnsresolve.WithNSMgrProxyService("nsmgr-proxy2"),
dnsresolve.WithRegistryService("registry2"),
dnsresolve.WithResolver(dnsResolver),
))...,
)
}).
Build()

dnsServer.DeleteSRVEntry(dnsresolve.DefaultNsmgrProxyService, domain1.Name)
dnsServer.DeleteSRVEntry(dnsresolve.DefaultRegistryService, domain1.Name)

dnsServer.AddSRVEntry("example.com", "nsmgr-proxy1", domain1.NSMgrProxy.URL)
dnsServer.AddSRVEntry("example.com", "registry1", domain1.Registry.URL)

domain2 := sandbox.NewBuilder(ctx, t).
SetNodesCount(0).
SetDNSResolver(dnsServer).
SetRegistryProxySupplier(func(ctx context.Context, tokenGenerator token.GeneratorFunc, dnsResolver dnsresolve.Resolver, options ...proxydns.Option) registry.Registry {
return proxydns.NewServer(
ctx,
tokenGenerator,
dnsResolver,
append(options,
proxydns.WithDNSResolveOptions(
dnsresolve.WithNSMgrProxyService("nsmgr-proxy1"),
dnsresolve.WithRegistryService("registry1"),
dnsresolve.WithResolver(dnsResolver),
))...,
)
}).
Build()

dnsServer.DeleteSRVEntry(dnsresolve.DefaultNsmgrProxyService, domain2.Name)
dnsServer.DeleteSRVEntry(dnsresolve.DefaultRegistryService, domain2.Name)

dnsServer.AddSRVEntry("example.com", "nsmgr-proxy2", domain2.NSMgrProxy.URL)
dnsServer.AddSRVEntry("example.com", "registry2", domain2.Registry.URL)

expirationTime := timestamppb.New(time.Now().Add(time.Hour))

registryClient := registryclient.NewNetworkServiceEndpointRegistryClient(ctx,
registryclient.WithDialOptions(grpc.WithTransportCredentials(insecure.NewCredentials())),
registryclient.WithClientURL(domain2.Registry.URL))

reg, err := registryClient.Register(
context.Background(),
&registryapi.NetworkServiceEndpoint{
Name: "nse-1",
Url: "nsmgr-url",
ExpirationTime: expirationTime,
},
)
require.Nil(t, err)

cc, err := grpc.DialContext(ctx, grpcutils.URLToTarget(domain1.Registry.URL), grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()))
require.Nil(t, err)

defer func() {
_ = cc.Close()
}()

client := registryapi.NewNetworkServiceEndpointRegistryClient(cc)

stream, err := client.Find(ctx, &registryapi.NetworkServiceEndpointQuery{
NetworkServiceEndpoint: &registryapi.NetworkServiceEndpoint{
Name: reg.Name + "@" + "example.com",
},
})

require.Nil(t, err)

list := registryapi.ReadNetworkServiceEndpointList(stream)

require.Len(t, list, 1)
require.Equal(t, reg.Name+"@"+"example.com", list[0].Name)
}

/*
TestInterdomainNetworkServiceEndpointRegistry covers the next scenario:
1. local registry from domain2 has entry "nse-1"
Expand Down
10 changes: 6 additions & 4 deletions pkg/tools/sandbox/builder.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) 2020-2022 Doc.ai and/or its affiliates.
//
// Copyright (c) 2023 Cisco Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -54,7 +56,7 @@ type Builder struct {
setupNode SetupNodeFunc

name string
dnsResolver dnsresolve.Resolver
dnsResolver TestingResolver
generateTokenFunc token.GeneratorFunc
registryDefaultExpiration time.Duration

Expand Down Expand Up @@ -140,7 +142,7 @@ func (b *Builder) SetDNSDomainName(name string) *Builder {
}

// SetDNSResolver sets DNS resolver for proxy registries
func (b *Builder) SetDNSResolver(d dnsresolve.Resolver) *Builder {
func (b *Builder) SetDNSResolver(d TestingResolver) *Builder {
b.dnsResolver = d
return b
}
Expand Down Expand Up @@ -330,9 +332,9 @@ func (b *Builder) newNode(nodeNum int) *Node {

func (b *Builder) buildDNSServer() {
if b.domain.Registry != nil {
require.NoError(b.t, AddSRVEntry(b.dnsResolver, b.name, dnsresolve.DefaultRegistryService, CloneURL(b.domain.Registry.URL)))
require.NoError(b.t, b.dnsResolver.AddSRVEntry(b.name, dnsresolve.DefaultRegistryService, CloneURL(b.domain.Registry.URL)))
}
if b.domain.NSMgrProxy != nil {
require.NoError(b.t, AddSRVEntry(b.dnsResolver, b.name, dnsresolve.DefaultNsmgrProxyService, CloneURL(b.domain.NSMgrProxy.URL)))
require.NoError(b.t, b.dnsResolver.AddSRVEntry(b.name, dnsresolve.DefaultNsmgrProxyService, CloneURL(b.domain.NSMgrProxy.URL)))
}
}
25 changes: 22 additions & 3 deletions pkg/tools/sandbox/fake_resolver.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright (c) 2020-2022 Doc.ai and/or its affiliates.
//
// Copyright (c) 2023 Cisco Systems, Inc.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -28,9 +30,16 @@ import (
"github.com/networkservicemesh/sdk/pkg/registry/common/dnsresolve"
)

// TestingResolver provides API for editing dns entries in unit tests
type TestingResolver interface {
dnsresolve.Resolver
AddSRVEntry(name, service string, u *url.URL) error
DeleteSRVEntry(name, service string)
}

// NewFakeResolver returns a fake Resolver that can have records added
// to it using AddSRVEntry.
func NewFakeResolver() dnsresolve.Resolver {
func NewFakeResolver() TestingResolver {
return &fakeResolver{
ports: map[string]string{},
addresses: map[string]string{},
Expand All @@ -40,8 +49,7 @@ func NewFakeResolver() dnsresolve.Resolver {
// AddSRVEntry adds a DNS record to r using name and service as the
// key, and the host and port in u as the values. r must be a Resolver
// that was created by NewFakeDNSResolver.
func AddSRVEntry(r dnsresolve.Resolver, name, service string, u *url.URL) (err error) {
f := r.(*fakeResolver)
func (f *fakeResolver) AddSRVEntry(name, service string, u *url.URL) (err error) {
f.Lock()
defer f.Unlock()

Expand All @@ -51,6 +59,17 @@ func AddSRVEntry(r dnsresolve.Resolver, name, service string, u *url.URL) (err e
return
}

// DeleteSRVEntry deletes a DNS srv entry from the mock dns server
func (f *fakeResolver) DeleteSRVEntry(name, service string) {
f.Lock()
defer f.Unlock()

key := fmt.Sprintf("%v.%v", service, name)

delete(f.addresses, key)
delete(f.ports, key)
}

// fakeResolver implements the dnsresolve.Resolver interface and can
// be used for logic DNS testing.
type fakeResolver struct {
Expand Down

0 comments on commit bb6e3ec

Please sign in to comment.