github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/router/query.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/tickoalcantara12/micro/v3/router/query.go
    14  
    15  package router
    16  
    17  // LookupOption sets routing table query options
    18  type LookupOption func(*LookupOptions)
    19  
    20  // LookupOptions are routing table query options
    21  // TODO replace with Filter(Route) bool
    22  type LookupOptions struct {
    23  	// Address of the service
    24  	Address string
    25  	// Gateway is route gateway
    26  	Gateway string
    27  	// Network is network address
    28  	Network string
    29  	// Router is router id
    30  	Router string
    31  	// Link to query
    32  	Link string
    33  }
    34  
    35  // LookupAddress sets service to query
    36  func LookupAddress(a string) LookupOption {
    37  	return func(o *LookupOptions) {
    38  		o.Address = a
    39  	}
    40  }
    41  
    42  // LookupGateway sets gateway address to query
    43  func LookupGateway(g string) LookupOption {
    44  	return func(o *LookupOptions) {
    45  		o.Gateway = g
    46  	}
    47  }
    48  
    49  // LookupNetwork sets network name to query
    50  func LookupNetwork(n string) LookupOption {
    51  	return func(o *LookupOptions) {
    52  		o.Network = n
    53  	}
    54  }
    55  
    56  // LookupRouter sets router id to query
    57  func LookupRouter(r string) LookupOption {
    58  	return func(o *LookupOptions) {
    59  		o.Router = r
    60  	}
    61  }
    62  
    63  // LookupLink sets the link to query
    64  func LookupLink(link string) LookupOption {
    65  	return func(o *LookupOptions) {
    66  		o.Link = link
    67  	}
    68  }
    69  
    70  // NewLookup creates new query and returns it
    71  func NewLookup(opts ...LookupOption) LookupOptions {
    72  	// default options
    73  	qopts := LookupOptions{
    74  		Address: "*",
    75  		Gateway: "*",
    76  		Network: "*",
    77  		Router:  "*",
    78  		Link:    DefaultLink,
    79  	}
    80  
    81  	for _, o := range opts {
    82  		o(&qopts)
    83  	}
    84  
    85  	return qopts
    86  }
    87  
    88  // isMatch checks if the route matches given query options
    89  func isMatch(route Route, address, gateway, network, rtr, link string) bool {
    90  	// matches the values provided
    91  	match := func(a, b string) bool {
    92  		if a == "*" || b == "*" || a == b {
    93  			return true
    94  		}
    95  		return false
    96  	}
    97  
    98  	// a simple struct to hold our values
    99  	type compare struct {
   100  		a string
   101  		b string
   102  	}
   103  
   104  	// compare the following values
   105  	values := []compare{
   106  		{gateway, route.Gateway},
   107  		{network, route.Network},
   108  		{rtr, route.Router},
   109  		{address, route.Address},
   110  		{link, route.Link},
   111  	}
   112  
   113  	for _, v := range values {
   114  		// attempt to match each value
   115  		if !match(v.a, v.b) {
   116  			return false
   117  		}
   118  	}
   119  
   120  	return true
   121  }
   122  
   123  // filterRoutes finds all the routes for given network and router and returns them
   124  func Filter(routes []Route, opts LookupOptions) []Route {
   125  	address := opts.Address
   126  	gateway := opts.Gateway
   127  	network := opts.Network
   128  	rtr := opts.Router
   129  	link := opts.Link
   130  
   131  	// routeMap stores the routes we're going to advertise
   132  	routeMap := make(map[string][]Route)
   133  
   134  	for _, route := range routes {
   135  		if isMatch(route, address, gateway, network, rtr, link) {
   136  			// add matchihg route to the routeMap
   137  			routeKey := route.Service + "@" + route.Network
   138  			routeMap[routeKey] = append(routeMap[routeKey], route)
   139  		}
   140  	}
   141  
   142  	var results []Route
   143  
   144  	for _, route := range routeMap {
   145  		results = append(results, route...)
   146  	}
   147  
   148  	return results
   149  }