1/*
2 *
3 * Copyright 2017 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
19// Package resolver defines APIs for name resolution in gRPC.
20// All APIs in this package are experimental.
21package resolver
22
23import (
24 "context"
25 "errors"
26 "fmt"
27 "net"
28 "net/url"
29 "strings"
30
31 "google.golang.org/grpc/attributes"
32 "google.golang.org/grpc/credentials"
33 "google.golang.org/grpc/experimental/stats"
34 "google.golang.org/grpc/internal"
35 "google.golang.org/grpc/serviceconfig"
36)
37
38var (
39 // m is a map from scheme to resolver builder.
40 m = make(map[string]Builder)
41 // defaultScheme is the default scheme to use.
42 defaultScheme = "passthrough"
43)
44
45// TODO(bar) install dns resolver in init(){}.
46
47// Register registers the resolver builder to the resolver map. b.Scheme will
48// be used as the scheme registered with this builder. The registry is case
49// sensitive, and schemes should not contain any uppercase characters.
50//
51// NOTE: this function must only be called during initialization time (i.e. in
52// an init() function), and is not thread-safe. If multiple Resolvers are
53// registered with the same name, the one registered last will take effect.
54func Register(b Builder) {
55 m[b.Scheme()] = b
56}
57
58// Get returns the resolver builder registered with the given scheme.
59//
60// If no builder is register with the scheme, nil will be returned.
61func Get(scheme string) Builder {
62 if b, ok := m[scheme]; ok {
63 return b
64 }
65 return nil
66}
67
68// SetDefaultScheme sets the default scheme that will be used. The default
69// scheme is initially set to "passthrough".
70//
71// NOTE: this function must only be called during initialization time (i.e. in
72// an init() function), and is not thread-safe. The scheme set last overrides
73// previously set values.
74func SetDefaultScheme(scheme string) {
75 defaultScheme = scheme
76 internal.UserSetDefaultScheme = true
77}
78
79// GetDefaultScheme gets the default scheme that will be used by grpc.Dial. If
80// SetDefaultScheme is never called, the default scheme used by grpc.NewClient is "dns" instead.
81func GetDefaultScheme() string {
82 return defaultScheme
83}
84
85// Address represents a server the client connects to.
86//
87// # Experimental
88//
89// Notice: This type is EXPERIMENTAL and may be changed or removed in a
90// later release.
91type Address struct {
92 // Addr is the server address on which a connection will be established.
93 Addr string
94
95 // ServerName is the name of this address.
96 // If non-empty, the ServerName is used as the transport certification authority for
97 // the address, instead of the hostname from the Dial target string. In most cases,
98 // this should not be set.
99 //
100 // WARNING: ServerName must only be populated with trusted values. It
101 // is insecure to populate it with data from untrusted inputs since untrusted
102 // values could be used to bypass the authority checks performed by TLS.
103 ServerName string
104
105 // Attributes contains arbitrary data about this address intended for
106 // consumption by the SubConn.
107 Attributes *attributes.Attributes
108
109 // BalancerAttributes contains arbitrary data about this address intended
110 // for consumption by the LB policy. These attributes do not affect SubConn
111 // creation, connection establishment, handshaking, etc.
112 //
113 // Deprecated: when an Address is inside an Endpoint, this field should not
114 // be used, and it will eventually be removed entirely.
115 BalancerAttributes *attributes.Attributes
116
117 // Metadata is the information associated with Addr, which may be used
118 // to make load balancing decision.
119 //
120 // Deprecated: use Attributes instead.
121 Metadata any
122}
123
124// Equal returns whether a and o are identical. Metadata is compared directly,
125// not with any recursive introspection.
126//
127// This method compares all fields of the address. When used to tell apart
128// addresses during subchannel creation or connection establishment, it might be
129// more appropriate for the caller to implement custom equality logic.
130func (a Address) Equal(o Address) bool {
131 return a.Addr == o.Addr && a.ServerName == o.ServerName &&
132 a.Attributes.Equal(o.Attributes) &&
133 a.BalancerAttributes.Equal(o.BalancerAttributes) &&
134 a.Metadata == o.Metadata
135}
136
137// String returns JSON formatted string representation of the address.
138func (a Address) String() string {
139 var sb strings.Builder
140 sb.WriteString(fmt.Sprintf("{Addr: %q, ", a.Addr))
141 sb.WriteString(fmt.Sprintf("ServerName: %q, ", a.ServerName))
142 if a.Attributes != nil {
143 sb.WriteString(fmt.Sprintf("Attributes: %v, ", a.Attributes.String()))
144 }
145 if a.BalancerAttributes != nil {
146 sb.WriteString(fmt.Sprintf("BalancerAttributes: %v", a.BalancerAttributes.String()))
147 }
148 sb.WriteString("}")
149 return sb.String()
150}
151
152// BuildOptions includes additional information for the builder to create
153// the resolver.
154type BuildOptions struct {
155 // DisableServiceConfig indicates whether a resolver implementation should
156 // fetch service config data.
157 DisableServiceConfig bool
158 // DialCreds is the transport credentials used by the ClientConn for
159 // communicating with the target gRPC service (set via
160 // WithTransportCredentials). In cases where a name resolution service
161 // requires the same credentials, the resolver may use this field. In most
162 // cases though, it is not appropriate, and this field may be ignored.
163 DialCreds credentials.TransportCredentials
164 // CredsBundle is the credentials bundle used by the ClientConn for
165 // communicating with the target gRPC service (set via
166 // WithCredentialsBundle). In cases where a name resolution service
167 // requires the same credentials, the resolver may use this field. In most
168 // cases though, it is not appropriate, and this field may be ignored.
169 CredsBundle credentials.Bundle
170 // Dialer is the custom dialer used by the ClientConn for dialling the
171 // target gRPC service (set via WithDialer). In cases where a name
172 // resolution service requires the same dialer, the resolver may use this
173 // field. In most cases though, it is not appropriate, and this field may
174 // be ignored.
175 Dialer func(context.Context, string) (net.Conn, error)
176 // Authority is the effective authority of the clientconn for which the
177 // resolver is built.
178 Authority string
179 // MetricsRecorder is the metrics recorder to do recording.
180 MetricsRecorder stats.MetricsRecorder
181}
182
183// An Endpoint is one network endpoint, or server, which may have multiple
184// addresses with which it can be accessed.
185type Endpoint struct {
186 // Addresses contains a list of addresses used to access this endpoint.
187 Addresses []Address
188
189 // Attributes contains arbitrary data about this endpoint intended for
190 // consumption by the LB policy.
191 Attributes *attributes.Attributes
192}
193
194// State contains the current Resolver state relevant to the ClientConn.
195type State struct {
196 // Addresses is the latest set of resolved addresses for the target.
197 //
198 // If a resolver sets Addresses but does not set Endpoints, one Endpoint
199 // will be created for each Address before the State is passed to the LB
200 // policy. The BalancerAttributes of each entry in Addresses will be set
201 // in Endpoints.Attributes, and be cleared in the Endpoint's Address's
202 // BalancerAttributes.
203 //
204 // Soon, Addresses will be deprecated and replaced fully by Endpoints.
205 Addresses []Address
206
207 // Endpoints is the latest set of resolved endpoints for the target.
208 //
209 // If a resolver produces a State containing Endpoints but not Addresses,
210 // it must take care to ensure the LB policies it selects will support
211 // Endpoints.
212 Endpoints []Endpoint
213
214 // ServiceConfig contains the result from parsing the latest service
215 // config. If it is nil, it indicates no service config is present or the
216 // resolver does not provide service configs.
217 ServiceConfig *serviceconfig.ParseResult
218
219 // Attributes contains arbitrary data about the resolver intended for
220 // consumption by the load balancing policy.
221 Attributes *attributes.Attributes
222}
223
224// ClientConn contains the callbacks for resolver to notify any updates
225// to the gRPC ClientConn.
226//
227// This interface is to be implemented by gRPC. Users should not need a
228// brand new implementation of this interface. For the situations like
229// testing, the new implementation should embed this interface. This allows
230// gRPC to add new methods to this interface.
231type ClientConn interface {
232 // UpdateState updates the state of the ClientConn appropriately.
233 //
234 // If an error is returned, the resolver should try to resolve the
235 // target again. The resolver should use a backoff timer to prevent
236 // overloading the server with requests. If a resolver is certain that
237 // reresolving will not change the result, e.g. because it is
238 // a watch-based resolver, returned errors can be ignored.
239 //
240 // If the resolved State is the same as the last reported one, calling
241 // UpdateState can be omitted.
242 UpdateState(State) error
243 // ReportError notifies the ClientConn that the Resolver encountered an
244 // error. The ClientConn then forwards this error to the load balancing
245 // policy.
246 ReportError(error)
247 // NewAddress is called by resolver to notify ClientConn a new list
248 // of resolved addresses.
249 // The address list should be the complete list of resolved addresses.
250 //
251 // Deprecated: Use UpdateState instead.
252 NewAddress(addresses []Address)
253 // ParseServiceConfig parses the provided service config and returns an
254 // object that provides the parsed config.
255 ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult
256}
257
258// Target represents a target for gRPC, as specified in:
259// https://github.com/grpc/grpc/blob/master/doc/naming.md.
260// It is parsed from the target string that gets passed into Dial or DialContext
261// by the user. And gRPC passes it to the resolver and the balancer.
262//
263// If the target follows the naming spec, and the parsed scheme is registered
264// with gRPC, we will parse the target string according to the spec. If the
265// target does not contain a scheme or if the parsed scheme is not registered
266// (i.e. no corresponding resolver available to resolve the endpoint), we will
267// apply the default scheme, and will attempt to reparse it.
268type Target struct {
269 // URL contains the parsed dial target with an optional default scheme added
270 // to it if the original dial target contained no scheme or contained an
271 // unregistered scheme. Any query params specified in the original dial
272 // target can be accessed from here.
273 URL url.URL
274}
275
276// Endpoint retrieves endpoint without leading "/" from either `URL.Path`
277// or `URL.Opaque`. The latter is used when the former is empty.
278func (t Target) Endpoint() string {
279 endpoint := t.URL.Path
280 if endpoint == "" {
281 endpoint = t.URL.Opaque
282 }
283 // For targets of the form "[scheme]://[authority]/endpoint, the endpoint
284 // value returned from url.Parse() contains a leading "/". Although this is
285 // in accordance with RFC 3986, we do not want to break existing resolver
286 // implementations which expect the endpoint without the leading "/". So, we
287 // end up stripping the leading "/" here. But this will result in an
288 // incorrect parsing for something like "unix:///path/to/socket". Since we
289 // own the "unix" resolver, we can workaround in the unix resolver by using
290 // the `URL` field.
291 return strings.TrimPrefix(endpoint, "/")
292}
293
294// String returns the canonical string representation of Target.
295func (t Target) String() string {
296 return t.URL.Scheme + "://" + t.URL.Host + "/" + t.Endpoint()
297}
298
299// Builder creates a resolver that will be used to watch name resolution updates.
300type Builder interface {
301 // Build creates a new resolver for the given target.
302 //
303 // gRPC dial calls Build synchronously, and fails if the returned error is
304 // not nil.
305 Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error)
306 // Scheme returns the scheme supported by this resolver. Scheme is defined
307 // at https://github.com/grpc/grpc/blob/master/doc/naming.md. The returned
308 // string should not contain uppercase characters, as they will not match
309 // the parsed target's scheme as defined in RFC 3986.
310 Scheme() string
311}
312
313// ResolveNowOptions includes additional information for ResolveNow.
314type ResolveNowOptions struct{}
315
316// Resolver watches for the updates on the specified target.
317// Updates include address updates and service config updates.
318type Resolver interface {
319 // ResolveNow will be called by gRPC to try to resolve the target name
320 // again. It's just a hint, resolver can ignore this if it's not necessary.
321 //
322 // It could be called multiple times concurrently.
323 ResolveNow(ResolveNowOptions)
324 // Close closes the resolver.
325 Close()
326}
327
328// AuthorityOverrider is implemented by Builders that wish to override the
329// default authority for the ClientConn.
330// By default, the authority used is target.Endpoint().
331type AuthorityOverrider interface {
332 // OverrideAuthority returns the authority to use for a ClientConn with the
333 // given target. The implementation must generate it without blocking,
334 // typically in line, and must keep it unchanged.
335 OverrideAuthority(Target) string
336}
337
338// ValidateEndpoints validates endpoints from a petiole policy's perspective.
339// Petiole policies should call this before calling into their children. See
340// [gRPC A61](https://github.com/grpc/proposal/blob/master/A61-IPv4-IPv6-dualstack-backends.md)
341// for details.
342func ValidateEndpoints(endpoints []Endpoint) error {
343 if len(endpoints) == 0 {
344 return errors.New("endpoints list is empty")
345 }
346
347 for _, endpoint := range endpoints {
348 for range endpoint.Addresses {
349 return nil
350 }
351 }
352 return errors.New("endpoints list contains no addresses")
353}