package dns import ( "fmt" "net" "strconv" "github.com/micro/go-micro/v2/router" ) // NewRouter returns an initialized dns router func NewRouter(opts ...router.Option) router.Router { options := router.DefaultOptions() for _, o := range opts { o(&options) } if len(options.Network) == 0 { options.Network = "micro" } return &dns{options, &table{options}} } type dns struct { options router.Options table *table } func (d *dns) Init(opts ...router.Option) error { for _, o := range opts { o(&d.options) } d.table.options = d.options return nil } func (d *dns) Options() router.Options { return d.options } func (d *dns) Table() router.Table { return d.table } func (d *dns) Advertise() (<-chan *router.Advert, error) { return nil, nil } func (d *dns) Process(*router.Advert) error { return nil } func (d *dns) Lookup(opts ...router.QueryOption) ([]router.Route, error) { return d.table.Query(opts...) } func (d *dns) Watch(opts ...router.WatchOption) (router.Watcher, error) { return nil, nil } func (d *dns) Close() error { return nil } func (d *dns) String() string { return "dns" } type table struct { options router.Options } func (t *table) Create(router.Route) error { return nil } func (t *table) Delete(router.Route) error { return nil } func (t *table) Update(router.Route) error { return nil } func (t *table) List() ([]router.Route, error) { return nil, nil } func (t *table) Query(opts ...router.QueryOption) ([]router.Route, error) { options := router.NewQuery(opts...) // check to see if we have the port provided in the service, e.g. go-micro-srv-foo:8000 host, port, err := net.SplitHostPort(options.Service) if err == nil { // lookup the service using A records ips, err := net.LookupHost(host) if err != nil { return nil, err } p, _ := strconv.Atoi(port) // convert the ip addresses to routes result := make([]router.Route, len(ips)) for i, ip := range ips { result[i] = router.Route{ Service: options.Service, Address: fmt.Sprintf("%s:%d", ip, uint16(p)), } } return result, nil } // we didn't get the port so we'll lookup the service using SRV records. If we can't lookup the // service using the SRV record, we return the error. _, nodes, err := net.LookupSRV(options.Service, "tcp", t.options.Network) if err != nil { return nil, err } // convert the nodes (net services) to routes result := make([]router.Route, len(nodes)) for i, n := range nodes { result[i] = router.Route{ Service: options.Service, Address: fmt.Sprintf("%s:%d", n.Target, n.Port), Network: t.options.Network, } } return result, nil }