1/* 2 * 3 * Copyright 2021 gRPC authors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 */ 18 19package clusterresolver 20 21import ( 22 "fmt" 23 24 "google.golang.org/grpc/resolver" 25 "google.golang.org/grpc/serviceconfig" 26) 27 28var ( 29 newDNS = func(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { 30 // The dns resolver is registered by the grpc package. So, this call to 31 // resolver.Get() is never expected to return nil. 32 return resolver.Get("dns").Build(target, cc, opts) 33 } 34) 35 36// dnsDiscoveryMechanism watches updates for the given DNS hostname. 37// 38// It implements resolver.ClientConn interface to work with the DNS resolver. 39type dnsDiscoveryMechanism struct { 40 target string 41 topLevelResolver *resourceResolver 42 r resolver.Resolver 43 44 addrs []string 45 updateReceived bool 46} 47 48func newDNSResolver(target string, topLevelResolver *resourceResolver) *dnsDiscoveryMechanism { 49 ret := &dnsDiscoveryMechanism{ 50 target: target, 51 topLevelResolver: topLevelResolver, 52 } 53 r, err := newDNS(resolver.Target{Scheme: "dns", Endpoint: target}, ret, resolver.BuildOptions{}) 54 if err != nil { 55 select { 56 case <-topLevelResolver.updateChannel: 57 default: 58 } 59 topLevelResolver.updateChannel <- &resourceUpdate{err: err} 60 } 61 ret.r = r 62 return ret 63} 64 65func (dr *dnsDiscoveryMechanism) lastUpdate() (interface{}, bool) { 66 if !dr.updateReceived { 67 return nil, false 68 } 69 return dr.addrs, true 70} 71 72func (dr *dnsDiscoveryMechanism) resolveNow() { 73 dr.r.ResolveNow(resolver.ResolveNowOptions{}) 74} 75 76func (dr *dnsDiscoveryMechanism) stop() { 77 dr.r.Close() 78} 79 80// dnsDiscoveryMechanism needs to implement resolver.ClientConn interface to receive 81// updates from the real DNS resolver. 82 83func (dr *dnsDiscoveryMechanism) UpdateState(state resolver.State) error { 84 dr.topLevelResolver.mu.Lock() 85 defer dr.topLevelResolver.mu.Unlock() 86 addrs := make([]string, len(state.Addresses)) 87 for i, a := range state.Addresses { 88 addrs[i] = a.Addr 89 } 90 dr.addrs = addrs 91 dr.updateReceived = true 92 dr.topLevelResolver.generate() 93 return nil 94} 95 96func (dr *dnsDiscoveryMechanism) ReportError(err error) { 97 select { 98 case <-dr.topLevelResolver.updateChannel: 99 default: 100 } 101 dr.topLevelResolver.updateChannel <- &resourceUpdate{err: err} 102} 103 104func (dr *dnsDiscoveryMechanism) NewAddress(addresses []resolver.Address) { 105 dr.UpdateState(resolver.State{Addresses: addresses}) 106} 107 108func (dr *dnsDiscoveryMechanism) NewServiceConfig(string) { 109 // This method is deprecated, and service config isn't supported. 110} 111 112func (dr *dnsDiscoveryMechanism) ParseServiceConfig(string) *serviceconfig.ParseResult { 113 return &serviceconfig.ParseResult{Err: fmt.Errorf("service config not supported")} 114} 115