| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | package grpc | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto/tls" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/core/dnsserver" | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin" | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/metrics" | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/pkg/parse" | 
					
						
							| 
									
										
										
										
											2019-12-17 16:15:31 +08:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/policy" | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 	pkgtls "github.com/coredns/coredns/plugin/pkg/tls" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-03 09:04:47 +08:00
										 |  |  | 	"github.com/caddyserver/caddy" | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-20 08:02:30 +01:00
										 |  |  | func init() { plugin.Register("grpc", setup) } | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func setup(c *caddy.Controller) error { | 
					
						
							|  |  |  | 	g, err := parseGRPC(c) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return plugin.Error("grpc", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if g.len() > max { | 
					
						
							|  |  |  | 		return plugin.Error("grpc", fmt.Errorf("more than %d TOs configured: %d", max, g.len())) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { | 
					
						
							|  |  |  | 		g.Next = next // Set the Next field, so the plugin chaining works. | 
					
						
							|  |  |  | 		return g | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c.OnStartup(func() error { | 
					
						
							|  |  |  | 		metrics.MustRegister(c, RequestCount, RcodeCount, RequestDuration) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func parseGRPC(c *caddy.Controller) (*GRPC, error) { | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		g   *GRPC | 
					
						
							|  |  |  | 		err error | 
					
						
							|  |  |  | 		i   int | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	for c.Next() { | 
					
						
							|  |  |  | 		if i > 0 { | 
					
						
							|  |  |  | 			return nil, plugin.ErrOnce | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		i++ | 
					
						
							| 
									
										
										
										
											2019-09-28 10:41:12 +01:00
										 |  |  | 		g, err = parseStanza(c) | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return g, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-28 10:41:12 +01:00
										 |  |  | func parseStanza(c *caddy.Controller) (*GRPC, error) { | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 	g := newGRPC() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !c.Args(&g.from) { | 
					
						
							|  |  |  | 		return g, c.ArgErr() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	g.from = plugin.Host(g.from).Normalize() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	to := c.RemainingArgs() | 
					
						
							|  |  |  | 	if len(to) == 0 { | 
					
						
							|  |  |  | 		return g, c.ArgErr() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	toHosts, err := parse.HostPortOrFile(to...) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return g, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-15 08:55:26 +01:00
										 |  |  | 	for c.NextBlock() { | 
					
						
							|  |  |  | 		if err := parseBlock(c, g); err != nil { | 
					
						
							|  |  |  | 			return g, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 	if g.tlsServerName != "" { | 
					
						
							|  |  |  | 		if g.tlsConfig == nil { | 
					
						
							|  |  |  | 			g.tlsConfig = new(tls.Config) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		g.tlsConfig.ServerName = g.tlsServerName | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	for _, host := range toHosts { | 
					
						
							|  |  |  | 		pr, err := newProxy(host, g.tlsConfig) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		g.proxies = append(g.proxies, pr) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return g, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-28 10:41:12 +01:00
										 |  |  | func parseBlock(c *caddy.Controller, g *GRPC) error { | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch c.Val() { | 
					
						
							|  |  |  | 	case "except": | 
					
						
							|  |  |  | 		ignore := c.RemainingArgs() | 
					
						
							|  |  |  | 		if len(ignore) == 0 { | 
					
						
							|  |  |  | 			return c.ArgErr() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for i := 0; i < len(ignore); i++ { | 
					
						
							|  |  |  | 			ignore[i] = plugin.Host(ignore[i]).Normalize() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		g.ignored = ignore | 
					
						
							|  |  |  | 	case "tls": | 
					
						
							|  |  |  | 		args := c.RemainingArgs() | 
					
						
							|  |  |  | 		if len(args) > 3 { | 
					
						
							|  |  |  | 			return c.ArgErr() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		tlsConfig, err := pkgtls.NewTLSConfigFromArgs(args...) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		g.tlsConfig = tlsConfig | 
					
						
							|  |  |  | 	case "tls_servername": | 
					
						
							|  |  |  | 		if !c.NextArg() { | 
					
						
							|  |  |  | 			return c.ArgErr() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		g.tlsServerName = c.Val() | 
					
						
							|  |  |  | 	case "policy": | 
					
						
							|  |  |  | 		if !c.NextArg() { | 
					
						
							|  |  |  | 			return c.ArgErr() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		switch x := c.Val(); x { | 
					
						
							|  |  |  | 		case "random": | 
					
						
							| 
									
										
										
										
											2019-12-17 16:15:31 +08:00
										 |  |  | 			g.p = &policy.Random{} | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 		case "round_robin": | 
					
						
							| 
									
										
										
										
											2019-12-17 16:15:31 +08:00
										 |  |  | 			g.p = &policy.RoundRobin{} | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 		case "sequential": | 
					
						
							| 
									
										
										
										
											2019-12-17 16:15:31 +08:00
										 |  |  | 			g.p = &policy.Sequential{} | 
					
						
							| 
									
										
										
										
											2019-03-14 08:12:28 +01:00
										 |  |  | 		default: | 
					
						
							|  |  |  | 			return c.Errf("unknown policy '%s'", x) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		if c.Val() != "}" { | 
					
						
							|  |  |  | 			return c.Errf("unknown property '%s'", c.Val()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const max = 15 // Maximum number of upstreams. |