Adds network id. Skips processing routes when router is the origin.
This commit is contained in:
		| @@ -34,8 +34,8 @@ type network struct { | |||||||
| 	proxy.Proxy | 	proxy.Proxy | ||||||
| 	// tun is network tunnel | 	// tun is network tunnel | ||||||
| 	tunnel.Tunnel | 	tunnel.Tunnel | ||||||
| 	// srv is network server | 	// server is network server | ||||||
| 	srv server.Server | 	server server.Server | ||||||
| 	// client is network client | 	// client is network client | ||||||
| 	client client.Client | 	client client.Client | ||||||
|  |  | ||||||
| @@ -59,13 +59,19 @@ func newNetwork(opts ...Option) Network { | |||||||
| 		tunnel.Address(options.Address), | 		tunnel.Address(options.Address), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
|  | 	// init router Id to the network id | ||||||
|  | 	options.Router.Init( | ||||||
|  | 		router.Id(options.Id), | ||||||
|  | 	) | ||||||
|  |  | ||||||
| 	// create tunnel client with tunnel transport | 	// create tunnel client with tunnel transport | ||||||
| 	tunTransport := trn.NewTransport( | 	tunTransport := trn.NewTransport( | ||||||
| 		trn.WithTunnel(options.Tunnel), | 		trn.WithTunnel(options.Tunnel), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	// srv is network server | 	// server is network server | ||||||
| 	srv := server.NewServer( | 	server := server.NewServer( | ||||||
|  | 		server.Id(options.Id), | ||||||
| 		server.Address(options.Address), | 		server.Address(options.Address), | ||||||
| 		server.Name(options.Name), | 		server.Name(options.Name), | ||||||
| 		server.Transport(tunTransport), | 		server.Transport(tunTransport), | ||||||
| @@ -86,7 +92,7 @@ func newNetwork(opts ...Option) Network { | |||||||
| 		Router:  options.Router, | 		Router:  options.Router, | ||||||
| 		Proxy:   options.Proxy, | 		Proxy:   options.Proxy, | ||||||
| 		Tunnel:  options.Tunnel, | 		Tunnel:  options.Tunnel, | ||||||
| 		srv:     srv, | 		server:  server, | ||||||
| 		client:  client, | 		client:  client, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -333,7 +339,7 @@ func (n *network) Connect() error { | |||||||
| 	go n.process(listener) | 	go n.process(listener) | ||||||
|  |  | ||||||
| 	// start the server | 	// start the server | ||||||
| 	if err := n.srv.Start(); err != nil { | 	if err := n.server.Start(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -345,7 +351,7 @@ func (n *network) Connect() error { | |||||||
|  |  | ||||||
| func (n *network) close() error { | func (n *network) close() error { | ||||||
| 	// stop the server | 	// stop the server | ||||||
| 	if err := n.srv.Stop(); err != nil { | 	if err := n.server.Stop(); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -390,5 +396,5 @@ func (n *network) Client() client.Client { | |||||||
|  |  | ||||||
| // Server returns network server | // Server returns network server | ||||||
| func (n *network) Server() server.Server { | func (n *network) Server() server.Server { | ||||||
| 	return n.srv | 	return n.server | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| package network | package network | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"github.com/google/uuid" | ||||||
| 	"github.com/micro/go-micro/network/resolver" | 	"github.com/micro/go-micro/network/resolver" | ||||||
| 	"github.com/micro/go-micro/network/resolver/registry" | 	"github.com/micro/go-micro/network/resolver/registry" | ||||||
| 	"github.com/micro/go-micro/proxy" | 	"github.com/micro/go-micro/proxy" | ||||||
| @@ -13,6 +14,8 @@ type Option func(*Options) | |||||||
|  |  | ||||||
| // Options configure network | // Options configure network | ||||||
| type Options struct { | type Options struct { | ||||||
|  | 	// Id of the node | ||||||
|  | 	Id string | ||||||
| 	// Name of the network | 	// Name of the network | ||||||
| 	Name string | 	Name string | ||||||
| 	// Address to bind to | 	// Address to bind to | ||||||
| @@ -27,14 +30,21 @@ type Options struct { | |||||||
| 	Resolver resolver.Resolver | 	Resolver resolver.Resolver | ||||||
| } | } | ||||||
|  |  | ||||||
| // Name is the network name | // Id sets the id of the network node | ||||||
|  | func Id(id string) Option { | ||||||
|  | 	return func(o *Options) { | ||||||
|  | 		o.Id = id | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Name sets the network name | ||||||
| func Name(n string) Option { | func Name(n string) Option { | ||||||
| 	return func(o *Options) { | 	return func(o *Options) { | ||||||
| 		o.Name = n | 		o.Name = n | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Address is the network address | // Address sets the network address | ||||||
| func Address(a string) Option { | func Address(a string) Option { | ||||||
| 	return func(o *Options) { | 	return func(o *Options) { | ||||||
| 		o.Address = a | 		o.Address = a | ||||||
| @@ -72,6 +82,7 @@ func Resolver(r resolver.Resolver) Option { | |||||||
| // DefaultOptions returns network default options | // DefaultOptions returns network default options | ||||||
| func DefaultOptions() Options { | func DefaultOptions() Options { | ||||||
| 	return Options{ | 	return Options{ | ||||||
|  | 		Id:       uuid.New().String(), | ||||||
| 		Name:     DefaultName, | 		Name:     DefaultName, | ||||||
| 		Address:  DefaultAddress, | 		Address:  DefaultAddress, | ||||||
| 		Tunnel:   tunnel.NewTunnel(), | 		Tunnel:   tunnel.NewTunnel(), | ||||||
|   | |||||||
| @@ -43,7 +43,7 @@ var ( | |||||||
| // router implements default router | // router implements default router | ||||||
| type router struct { | type router struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	opts      Options | 	options   Options | ||||||
| 	status    Status | 	status    Status | ||||||
| 	table     *table | 	table     *table | ||||||
| 	exit      chan struct{} | 	exit      chan struct{} | ||||||
| @@ -70,7 +70,7 @@ func newRouter(opts ...Option) Router { | |||||||
| 	status := Status{Code: Stopped, Error: nil} | 	status := Status{Code: Stopped, Error: nil} | ||||||
|  |  | ||||||
| 	return &router{ | 	return &router{ | ||||||
| 		opts:        options, | 		options:     options, | ||||||
| 		status:      status, | 		status:      status, | ||||||
| 		table:       newTable(), | 		table:       newTable(), | ||||||
| 		advertWg:    &sync.WaitGroup{}, | 		advertWg:    &sync.WaitGroup{}, | ||||||
| @@ -85,7 +85,7 @@ func (r *router) Init(opts ...Option) error { | |||||||
| 	defer r.Unlock() | 	defer r.Unlock() | ||||||
|  |  | ||||||
| 	for _, o := range opts { | 	for _, o := range opts { | ||||||
| 		o(&r.opts) | 		o(&r.options) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @@ -94,10 +94,10 @@ func (r *router) Init(opts ...Option) error { | |||||||
| // Options returns router options | // Options returns router options | ||||||
| func (r *router) Options() Options { | func (r *router) Options() Options { | ||||||
| 	r.Lock() | 	r.Lock() | ||||||
| 	opts := r.opts | 	options := r.options | ||||||
| 	r.Unlock() | 	r.Unlock() | ||||||
|  |  | ||||||
| 	return opts | 	return options | ||||||
| } | } | ||||||
|  |  | ||||||
| // Table returns routing table | // Table returns routing table | ||||||
| @@ -139,7 +139,8 @@ func (r *router) manageServiceRoutes(service *registry.Service, action string) e | |||||||
| 			Service: service.Name, | 			Service: service.Name, | ||||||
| 			Address: node.Address, | 			Address: node.Address, | ||||||
| 			Gateway: "", | 			Gateway: "", | ||||||
| 			Network: r.opts.Network, | 			Network: r.options.Network, | ||||||
|  | 			Router:  r.options.Id, | ||||||
| 			Link:    DefaultLink, | 			Link:    DefaultLink, | ||||||
| 			Metric:  DefaultLocalMetric, | 			Metric:  DefaultLocalMetric, | ||||||
| 		} | 		} | ||||||
| @@ -278,7 +279,7 @@ func (r *router) publishAdvert(advType AdvertType, events []*Event) { | |||||||
| 	defer r.advertWg.Done() | 	defer r.advertWg.Done() | ||||||
|  |  | ||||||
| 	a := &Advert{ | 	a := &Advert{ | ||||||
| 		Id:        r.opts.Id, | 		Id:        r.options.Id, | ||||||
| 		Type:      advType, | 		Type:      advType, | ||||||
| 		TTL:       DefaultAdvertTTL, | 		TTL:       DefaultAdvertTTL, | ||||||
| 		Timestamp: time.Now(), | 		Timestamp: time.Now(), | ||||||
| @@ -529,20 +530,22 @@ func (r *router) Start() error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// add all local service routes into the routing table | 	// add all local service routes into the routing table | ||||||
| 	if err := r.manageRegistryRoutes(r.opts.Registry, "create"); err != nil { | 	if err := r.manageRegistryRoutes(r.options.Registry, "create"); err != nil { | ||||||
| 		e := fmt.Errorf("failed adding registry routes: %s", err) | 		e := fmt.Errorf("failed adding registry routes: %s", err) | ||||||
| 		r.status = Status{Code: Error, Error: e} | 		r.status = Status{Code: Error, Error: e} | ||||||
| 		return e | 		return e | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// add default gateway into routing table | 	// add default gateway into routing table | ||||||
| 	if r.opts.Gateway != "" { | 	if r.options.Gateway != "" { | ||||||
| 		// note, the only non-default value is the gateway | 		// note, the only non-default value is the gateway | ||||||
| 		route := Route{ | 		route := Route{ | ||||||
| 			Service: "*", | 			Service: "*", | ||||||
| 			Address: "*", | 			Address: "*", | ||||||
| 			Gateway: r.opts.Gateway, | 			Gateway: r.options.Gateway, | ||||||
| 			Network: "*", | 			Network: "*", | ||||||
|  | 			Router:  r.options.Id, | ||||||
|  | 			Link:    DefaultLink, | ||||||
| 			Metric:  DefaultLocalMetric, | 			Metric:  DefaultLocalMetric, | ||||||
| 		} | 		} | ||||||
| 		if err := r.table.Create(route); err != nil { | 		if err := r.table.Create(route); err != nil { | ||||||
| @@ -557,7 +560,7 @@ func (r *router) Start() error { | |||||||
| 	r.exit = make(chan struct{}) | 	r.exit = make(chan struct{}) | ||||||
|  |  | ||||||
| 	// registry watcher | 	// registry watcher | ||||||
| 	regWatcher, err := r.opts.Registry.Watch() | 	regWatcher, err := r.options.Registry.Watch() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e := fmt.Errorf("failed creating registry watcher: %v", err) | 		e := fmt.Errorf("failed creating registry watcher: %v", err) | ||||||
| 		r.status = Status{Code: Error, Error: e} | 		r.status = Status{Code: Error, Error: e} | ||||||
| @@ -669,6 +672,10 @@ func (r *router) Process(a *Advert) error { | |||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
| 	for _, event := range events { | 	for _, event := range events { | ||||||
|  | 		// skip if the router is the origin of this route | ||||||
|  | 		if event.Route.Router == r.options.Id { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
| 		// create a copy of the route | 		// create a copy of the route | ||||||
| 		route := event.Route | 		route := event.Route | ||||||
| 		action := event.Type | 		action := event.Type | ||||||
|   | |||||||
| @@ -11,29 +11,38 @@ type QueryOptions struct { | |||||||
| 	Gateway string | 	Gateway string | ||||||
| 	// Network is network address | 	// Network is network address | ||||||
| 	Network string | 	Network string | ||||||
|  | 	// Router is router id | ||||||
|  | 	Router string | ||||||
| } | } | ||||||
|  |  | ||||||
| // QueryService sets destination address | // QueryService sets service to query | ||||||
| func QueryService(s string) QueryOption { | func QueryService(s string) QueryOption { | ||||||
| 	return func(o *QueryOptions) { | 	return func(o *QueryOptions) { | ||||||
| 		o.Service = s | 		o.Service = s | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // QueryGateway sets route gateway | // QueryGateway sets gateway address to query | ||||||
| func QueryGateway(g string) QueryOption { | func QueryGateway(g string) QueryOption { | ||||||
| 	return func(o *QueryOptions) { | 	return func(o *QueryOptions) { | ||||||
| 		o.Gateway = g | 		o.Gateway = g | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| // QueryNetwork sets route network address | // QueryNetwork sets network name to query | ||||||
| func QueryNetwork(n string) QueryOption { | func QueryNetwork(n string) QueryOption { | ||||||
| 	return func(o *QueryOptions) { | 	return func(o *QueryOptions) { | ||||||
| 		o.Network = n | 		o.Network = n | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // QueryRouter sets router id to query | ||||||
|  | func QueryRouter(r string) QueryOption { | ||||||
|  | 	return func(o *QueryOptions) { | ||||||
|  | 		o.Router = r | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // Query is routing table query | // Query is routing table query | ||||||
| type Query interface { | type Query interface { | ||||||
| 	// Options returns query options | 	// Options returns query options | ||||||
| @@ -52,6 +61,7 @@ func NewQuery(opts ...QueryOption) Query { | |||||||
| 		Service: "*", | 		Service: "*", | ||||||
| 		Gateway: "*", | 		Gateway: "*", | ||||||
| 		Network: "*", | 		Network: "*", | ||||||
|  | 		Router:  "*", | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, o := range opts { | 	for _, o := range opts { | ||||||
| @@ -67,8 +77,3 @@ func NewQuery(opts ...QueryOption) Query { | |||||||
| func (q *query) Options() QueryOptions { | func (q *query) Options() QueryOptions { | ||||||
| 	return q.opts | 	return q.opts | ||||||
| } | } | ||||||
|  |  | ||||||
| // String prints routing table query in human readable form |  | ||||||
| func (q query) String() string { |  | ||||||
| 	return "query" |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -7,9 +7,9 @@ import ( | |||||||
| var ( | var ( | ||||||
| 	// DefaultLink is default network link | 	// DefaultLink is default network link | ||||||
| 	DefaultLink = "local" | 	DefaultLink = "local" | ||||||
| 	// DefaultLocalMetric is default route cost metric for the local network | 	// DefaultLocalMetric is default route cost for a local route | ||||||
| 	DefaultLocalMetric = 1 | 	DefaultLocalMetric = 1 | ||||||
| 	// DefaultNetworkMetric is default route cost metric for the micro network | 	// DefaultNetworkMetric is default route cost for a network route | ||||||
| 	DefaultNetworkMetric = 10 | 	DefaultNetworkMetric = 10 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -23,6 +23,8 @@ type Route struct { | |||||||
| 	Gateway string | 	Gateway string | ||||||
| 	// Network is network address | 	// Network is network address | ||||||
| 	Network string | 	Network string | ||||||
|  | 	// Router is router id | ||||||
|  | 	Router string | ||||||
| 	// Link is network link | 	// Link is network link | ||||||
| 	Link string | 	Link string | ||||||
| 	// Metric is the route cost metric | 	// Metric is the route cost metric | ||||||
| @@ -33,6 +35,6 @@ type Route struct { | |||||||
| func (r *Route) Hash() uint64 { | func (r *Route) Hash() uint64 { | ||||||
| 	h := fnv.New64() | 	h := fnv.New64() | ||||||
| 	h.Reset() | 	h.Reset() | ||||||
| 	h.Write([]byte(r.Service + r.Address + r.Gateway + r.Network + r.Link)) | 	h.Write([]byte(r.Service + r.Address + r.Gateway + r.Network + r.Router + r.Link)) | ||||||
| 	return h.Sum64() | 	return h.Sum64() | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,7 +8,14 @@ import ( | |||||||
| 	"github.com/google/uuid" | 	"github.com/google/uuid" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // table is an in memory routing table | var ( | ||||||
|  | 	// ErrRouteNotFound is returned when no route was found in the routing table | ||||||
|  | 	ErrRouteNotFound = errors.New("route not found") | ||||||
|  | 	// ErrDuplicateRoute is returned when the route already exists | ||||||
|  | 	ErrDuplicateRoute = errors.New("duplicate route") | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // table is an in-memory routing table | ||||||
| type table struct { | type table struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	// routes stores service routes | 	// routes stores service routes | ||||||
| @@ -25,6 +32,19 @@ func newTable(opts ...Option) *table { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // sendEvent sends events to all subscribed watchers | ||||||
|  | func (t *table) sendEvent(e *Event) { | ||||||
|  | 	t.RLock() | ||||||
|  | 	defer t.RUnlock() | ||||||
|  |  | ||||||
|  | 	for _, w := range t.watchers { | ||||||
|  | 		select { | ||||||
|  | 		case w.resChan <- e: | ||||||
|  | 		case <-w.done: | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| // Create creates new route in the routing table | // Create creates new route in the routing table | ||||||
| func (t *table) Create(r Route) error { | func (t *table) Create(r Route) error { | ||||||
| 	service := r.Service | 	service := r.Service | ||||||
| @@ -106,21 +126,23 @@ func (t *table) List() ([]Route, error) { | |||||||
| 	return routes, nil | 	return routes, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // isMatch checks if the route matches given network and router | // isMatch checks if the route matches given query options | ||||||
| func isMatch(route Route, network, router string) bool { | func isMatch(route Route, gateway, network, router string) bool { | ||||||
|  | 	if gateway == "*" || gateway == route.Gateway { | ||||||
| 		if network == "*" || network == route.Network { | 		if network == "*" || network == route.Network { | ||||||
| 		if router == "*" || router == route.Gateway { | 			if router == "*" || router == route.Router { | ||||||
| 				return true | 				return true | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| // findRoutes finds all the routes for given network and router and returns them | // findRoutes finds all the routes for given network and router and returns them | ||||||
| func findRoutes(routes map[uint64]Route, network, router string) []Route { | func findRoutes(routes map[uint64]Route, gateway, network, router string) []Route { | ||||||
| 	var results []Route | 	var results []Route | ||||||
| 	for _, route := range routes { | 	for _, route := range routes { | ||||||
| 		if isMatch(route, network, router) { | 		if isMatch(route, gateway, network, router) { | ||||||
| 			results = append(results, route) | 			results = append(results, route) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -136,13 +158,13 @@ func (t *table) Query(q Query) ([]Route, error) { | |||||||
| 		if _, ok := t.routes[q.Options().Service]; !ok { | 		if _, ok := t.routes[q.Options().Service]; !ok { | ||||||
| 			return nil, ErrRouteNotFound | 			return nil, ErrRouteNotFound | ||||||
| 		} | 		} | ||||||
| 		return findRoutes(t.routes[q.Options().Service], q.Options().Network, q.Options().Gateway), nil | 		return findRoutes(t.routes[q.Options().Service], q.Options().Gateway, q.Options().Network, q.Options().Router), nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var results []Route | 	var results []Route | ||||||
| 	// search through all destinations | 	// search through all destinations | ||||||
| 	for _, routes := range t.routes { | 	for _, routes := range t.routes { | ||||||
| 		results = append(results, findRoutes(routes, q.Options().Network, q.Options().Gateway)...) | 		results = append(results, findRoutes(routes, q.Options().Gateway, q.Options().Network, q.Options().Router)...) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return results, nil | 	return results, nil | ||||||
| @@ -181,23 +203,3 @@ func (t *table) Watch(opts ...WatchOption) (Watcher, error) { | |||||||
|  |  | ||||||
| 	return w, nil | 	return w, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // sendEvent sends events to all subscribed watchers |  | ||||||
| func (t *table) sendEvent(e *Event) { |  | ||||||
| 	t.RLock() |  | ||||||
| 	defer t.RUnlock() |  | ||||||
|  |  | ||||||
| 	for _, w := range t.watchers { |  | ||||||
| 		select { |  | ||||||
| 		case w.resChan <- e: |  | ||||||
| 		case <-w.done: |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// ErrRouteNotFound is returned when no route was found in the routing table |  | ||||||
| 	ErrRouteNotFound = errors.New("route not found") |  | ||||||
| 	// ErrDuplicateRoute is returned when the route already exists |  | ||||||
| 	ErrDuplicateRoute = errors.New("duplicate route") |  | ||||||
| ) |  | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ func testSetup() (*table, Route) { | |||||||
| 		Service: "dest.svc", | 		Service: "dest.svc", | ||||||
| 		Gateway: "dest.gw", | 		Gateway: "dest.gw", | ||||||
| 		Network: "dest.network", | 		Network: "dest.network", | ||||||
|  | 		Router:  "src.router", | ||||||
| 		Link:    "det.link", | 		Link:    "det.link", | ||||||
| 		Metric:  10, | 		Metric:  10, | ||||||
| 	} | 	} | ||||||
| @@ -109,11 +110,13 @@ func TestQuery(t *testing.T) { | |||||||
| 	svc := []string{"svc1", "svc2", "svc3"} | 	svc := []string{"svc1", "svc2", "svc3"} | ||||||
| 	net := []string{"net1", "net2", "net1"} | 	net := []string{"net1", "net2", "net1"} | ||||||
| 	gw := []string{"gw1", "gw2", "gw3"} | 	gw := []string{"gw1", "gw2", "gw3"} | ||||||
|  | 	rtr := []string{"rtr1", "rt2", "rt3"} | ||||||
|  |  | ||||||
| 	for i := 0; i < len(svc); i++ { | 	for i := 0; i < len(svc); i++ { | ||||||
| 		route.Service = svc[i] | 		route.Service = svc[i] | ||||||
| 		route.Network = net[i] | 		route.Network = net[i] | ||||||
| 		route.Gateway = gw[i] | 		route.Gateway = gw[i] | ||||||
|  | 		route.Router = rtr[i] | ||||||
| 		if err := table.Create(route); err != nil { | 		if err := table.Create(route); err != nil { | ||||||
| 			t.Errorf("error adding route: %s", err) | 			t.Errorf("error adding route: %s", err) | ||||||
| 		} | 		} | ||||||
| @@ -127,8 +130,9 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("error looking up routes: %s", err) | 		t.Errorf("error looking up routes: %s", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// query particular net | 	// query routes particular network | ||||||
| 	query = NewQuery(QueryNetwork("net1")) | 	network := "net1" | ||||||
|  | 	query = NewQuery(QueryNetwork(network)) | ||||||
|  |  | ||||||
| 	routes, err = table.Query(query) | 	routes, err = table.Query(query) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -139,7 +143,13 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("incorrect number of routes returned. Expected: %d, found: %d", 2, len(routes)) | 		t.Errorf("incorrect number of routes returned. Expected: %d, found: %d", 2, len(routes)) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// query particular gateway | 	for _, route := range routes { | ||||||
|  | 		if route.Network != network { | ||||||
|  | 			t.Errorf("incorrect route returned. Expected network: %s, found: %s", network, route.Network) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// query routes for particular gateway | ||||||
| 	gateway := "gw1" | 	gateway := "gw1" | ||||||
| 	query = NewQuery(QueryGateway(gateway)) | 	query = NewQuery(QueryGateway(gateway)) | ||||||
|  |  | ||||||
| @@ -156,11 +166,28 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("incorrect route returned. Expected gateway: %s, found: %s", gateway, routes[0].Gateway) | 		t.Errorf("incorrect route returned. Expected gateway: %s, found: %s", gateway, routes[0].Gateway) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// query particular route | 	// query routes for particular router | ||||||
| 	network := "net1" | 	router := "rtr1" | ||||||
|  | 	query = NewQuery(QueryRouter(router)) | ||||||
|  |  | ||||||
|  | 	routes, err = table.Query(query) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Errorf("error looking up routes: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(routes) != 1 { | ||||||
|  | 		t.Errorf("incorrect number of routes returned. Expected: %d, found: %d", 1, len(routes)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if routes[0].Router != router { | ||||||
|  | 		t.Errorf("incorrect route returned. Expected router: %s, found: %s", router, routes[0].Router) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// query particular gateway and network | ||||||
| 	query = NewQuery( | 	query = NewQuery( | ||||||
| 		QueryGateway(gateway), | 		QueryGateway(gateway), | ||||||
| 		QueryNetwork(network), | 		QueryNetwork(network), | ||||||
|  | 		QueryRouter(router), | ||||||
| 	) | 	) | ||||||
|  |  | ||||||
| 	routes, err = table.Query(query) | 	routes, err = table.Query(query) | ||||||
| @@ -180,7 +207,11 @@ func TestQuery(t *testing.T) { | |||||||
| 		t.Errorf("incorrect network returned. Expected network: %s, found: %s", network, routes[0].Network) | 		t.Errorf("incorrect network returned. Expected network: %s, found: %s", network, routes[0].Network) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// bullshit route query | 	if routes[0].Router != router { | ||||||
|  | 		t.Errorf("incorrect route returned. Expected router: %s, found: %s", router, routes[0].Router) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// non-existen route query | ||||||
| 	query = NewQuery(QueryService("foobar")) | 	query = NewQuery(QueryService("foobar")) | ||||||
|  |  | ||||||
| 	routes, err = table.Query(query) | 	routes, err = table.Query(query) | ||||||
|   | |||||||
| @@ -6,6 +6,11 @@ import ( | |||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var ( | ||||||
|  | 	// ErrWatcherStopped is returned when routing table watcher has been stopped | ||||||
|  | 	ErrWatcherStopped = errors.New("watcher stopped") | ||||||
|  | ) | ||||||
|  |  | ||||||
| // EventType defines routing table event | // EventType defines routing table event | ||||||
| type EventType int | type EventType int | ||||||
|  |  | ||||||
| @@ -42,9 +47,6 @@ type Event struct { | |||||||
| 	Route Route | 	Route Route | ||||||
| } | } | ||||||
|  |  | ||||||
| // WatchOption is used to define what routes to watch in the table |  | ||||||
| type WatchOption func(*WatchOptions) |  | ||||||
|  |  | ||||||
| // Watcher defines routing table watcher interface | // Watcher defines routing table watcher interface | ||||||
| // Watcher returns updates to the routing table | // Watcher returns updates to the routing table | ||||||
| type Watcher interface { | type Watcher interface { | ||||||
| @@ -56,7 +58,11 @@ type Watcher interface { | |||||||
| 	Stop() | 	Stop() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // WatchOption is used to define what routes to watch in the table | ||||||
|  | type WatchOption func(*WatchOptions) | ||||||
|  |  | ||||||
| // WatchOptions are table watcher options | // WatchOptions are table watcher options | ||||||
|  | // TODO: expand the options to watch based on other criteria | ||||||
| type WatchOptions struct { | type WatchOptions struct { | ||||||
| 	// Service allows to watch specific service routes | 	// Service allows to watch specific service routes | ||||||
| 	Service string | 	Service string | ||||||
| @@ -70,6 +76,7 @@ func WatchService(s string) WatchOption { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // tableWatcher implements routing table Watcher | ||||||
| type tableWatcher struct { | type tableWatcher struct { | ||||||
| 	sync.RWMutex | 	sync.RWMutex | ||||||
| 	id      string | 	id      string | ||||||
| @@ -113,8 +120,3 @@ func (w *tableWatcher) Stop() { | |||||||
| 		close(w.done) | 		close(w.done) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| var ( |  | ||||||
| 	// ErrWatcherStopped is returned when routing table watcher has been stopped |  | ||||||
| 	ErrWatcherStopped = errors.New("watcher stopped") |  | ||||||
| ) |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user