Skip to content

Commit

Permalink
Updates for compatibility with new gRPC target interface
Browse files Browse the repository at this point in the history
  • Loading branch information
wyattanderson committed Feb 28, 2023
1 parent 4bdf89a commit d8a3bdc
Show file tree
Hide file tree
Showing 4 changed files with 1,110 additions and 76 deletions.
79 changes: 42 additions & 37 deletions builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,50 +73,55 @@ type kubeBuilder struct {
schema string
}

func parseResolverTarget(target resolver.Target) (targetInfo, error) {
// kubernetes://default/service:port
end := target.Endpoint
snamespace := target.Authority
// kubernetes://service.default:port/
if end == "" {
end = target.Authority
snamespace = ""
func splitServicePortNamespace(hpn string) (service, port, namespace string) {
service = hpn

colon := strings.LastIndexByte(service, ':')
if colon != -1 {
service, port = service[:colon], service[colon+1:]
}
ti := targetInfo{}
if end == "" {
return targetInfo{}, fmt.Errorf("target(%q) is empty", target)

dot := strings.LastIndexByte(service, '.')
if dot != -1 {
service, namespace = service[:dot], service[dot+1:]
}
var name string
var port string
if strings.LastIndex(end, ":") < 0 {
name = end
port = ""
ti.useFirstPort = true

return
}

func parseResolverTarget(target resolver.Target) (targetInfo, error) {
var service, port, namespace string
if target.URL.Host == "" {
// kubernetes:///service.namespace:port
service, port, namespace = splitServicePortNamespace(target.Endpoint())
} else if target.URL.Port() == "" && target.Endpoint() != "" {
// kubernetes://namespace/service:port
service, port, _ = splitServicePortNamespace(target.Endpoint())
namespace = target.URL.Hostname()
} else {
var err error
name, port, err = net.SplitHostPort(end)
if err != nil {
return targetInfo{}, fmt.Errorf("target endpoint='%s' is invalid. grpc target is %#v, err=%v", end, target, err)
}
// kubernetes://service.namespace:port
service, port, namespace = splitServicePortNamespace(target.URL.Host)
}

namesplit := strings.SplitN(name, ".", 2)
sname := name
if len(namesplit) == 2 {
sname = namesplit[0]
snamespace = namesplit[1]
if service == "" {
return targetInfo{}, fmt.Errorf("target %s must specify a service", &target.URL)
}
ti.serviceName = sname
ti.serviceNamespace = snamespace
ti.port = port
if !ti.useFirstPort {
if _, err := strconv.Atoi(ti.port); err != nil {
ti.resolveByPortName = true
} else {
ti.resolveByPortName = false
}

resolveByPortName := false
useFirstPort := false
if port == "" {
useFirstPort = true
} else if _, err := strconv.Atoi(port); err != nil {
resolveByPortName = true
}
return ti, nil

return targetInfo{
serviceName: service,
serviceNamespace: namespace,
port: port,
resolveByPortName: resolveByPortName,
useFirstPort: useFirstPort,
}, nil
}

// Build creates a new resolver for the given target.
Expand Down
62 changes: 31 additions & 31 deletions builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package kuberesolver
import (
"fmt"
"log"
"net/url"
"strings"
"testing"

Expand All @@ -20,8 +21,8 @@ type fakeConn struct {
found []string
}

func (fc *fakeConn) UpdateState(resolver.State) {

func (fc *fakeConn) UpdateState(resolver.State) error {
return nil
}

func (fc *fakeConn) ReportError(e error) {
Expand Down Expand Up @@ -54,7 +55,7 @@ func TestBuilder(t *testing.T) {
fc := &fakeConn{
cmp: make(chan struct{}),
}
rs, err := bl.Build(resolver.Target{Endpoint: "kube-dns.kube-system:53", Scheme: "kubernetes", Authority: ""}, fc, resolver.BuildOptions{})
rs, err := bl.Build(parseTarget("kubernetes://kube-dns.kube-system:53"), fc, resolver.BuildOptions{})
if err != nil {
t.Fatal(err)
}
Expand All @@ -80,22 +81,22 @@ func split2(s, sep string) (string, string, bool) {
return spl[0], spl[1], true
}

// ParseTarget splits target into a resolver.Target struct containing scheme,
// authority and endpoint.
//
// If target is not a valid scheme://authority/endpoint, it returns {Endpoint:
// target}.
func parseTarget(target string) (ret resolver.Target) {
var ok bool
ret.Scheme, ret.Endpoint, ok = split2(target, "://")
if !ok {
return resolver.Target{Endpoint: target}
func parseTarget(target string) resolver.Target {
u, err := url.Parse(target)
if err != nil {
panic(err)
}
ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, "/")
if !ok {
return resolver.Target{Endpoint: target}

scheme := u.Scheme
if scheme == "" {
scheme = "kubernetes"
}

return resolver.Target{
Scheme: scheme,
Authority: u.Host,
URL: *u,
}
return ret
}

func TestParseResolverTarget(t *testing.T) {
Expand All @@ -104,17 +105,17 @@ func TestParseResolverTarget(t *testing.T) {
want targetInfo
err bool
}{
{resolver.Target{"", "", ""}, targetInfo{"", "", "", false, false}, true},
{resolver.Target{"", "a", ""}, targetInfo{"a", "", "", false, true}, false},
{resolver.Target{"", "", "a"}, targetInfo{"a", "", "", false, true}, false},
{resolver.Target{"", "a", "b"}, targetInfo{"b", "a", "", false, true}, false},
{resolver.Target{"", "a.b", ""}, targetInfo{"a", "b", "", false, true}, false},
{resolver.Target{"", "", "a.b"}, targetInfo{"a", "b", "", false, true}, false},
{resolver.Target{"", "", "a.b:80"}, targetInfo{"a", "b", "80", false, false}, false},
{resolver.Target{"", "", "a.b:port"}, targetInfo{"a", "b", "port", true, false}, false},
{resolver.Target{"", "a", "b:port"}, targetInfo{"b", "a", "port", true, false}, false},
{resolver.Target{"", "b.a:port", ""}, targetInfo{"b", "a", "port", true, false}, false},
{resolver.Target{"", "b.a:80", ""}, targetInfo{"b", "a", "80", false, false}, false},
{parseTarget("/"), targetInfo{"", "", "", false, false}, true},
{parseTarget("a"), targetInfo{"a", "", "", false, true}, false},
{parseTarget("/a"), targetInfo{"a", "", "", false, true}, false},
{parseTarget("//a/b"), targetInfo{"b", "a", "", false, true}, false},
{parseTarget("a.b"), targetInfo{"a", "b", "", false, true}, false},
{parseTarget("/a.b"), targetInfo{"a", "b", "", false, true}, false},
{parseTarget("/a.b:80"), targetInfo{"a", "b", "80", false, false}, false},
{parseTarget("/a.b:port"), targetInfo{"a", "b", "port", true, false}, false},
{parseTarget("//a/b:port"), targetInfo{"b", "a", "port", true, false}, false},
{parseTarget("//a/b:port"), targetInfo{"b", "a", "port", true, false}, false},
{parseTarget("//a/b:80"), targetInfo{"b", "a", "80", false, false}, false},
} {
got, err := parseResolverTarget(test.target)
if err == nil && test.err {
Expand All @@ -126,7 +127,7 @@ func TestParseResolverTarget(t *testing.T) {
continue
}
if got != test.want {
t.Errorf("case %d parseTarget(%q) = %+v, want %+v", i, test.target, got, test.want)
t.Errorf("case %d parseResolverTarget(%q) = %+v, want %+v", i, &test.target.URL, got, test.want)
}
}
}
Expand All @@ -139,7 +140,7 @@ func TestParseTargets(t *testing.T) {
}{
{"", targetInfo{}, true},
{"kubernetes:///", targetInfo{}, true},
{"kubernetes://a:30", targetInfo{}, true},
{"kubernetes://a:30", targetInfo{"a", "", "30", false, false}, false},
{"kubernetes://a/", targetInfo{"a", "", "", false, true}, false},
{"kubernetes:///a", targetInfo{"a", "", "", false, true}, false},
{"kubernetes://a/b", targetInfo{"b", "a", "", false, true}, false},
Expand All @@ -148,7 +149,6 @@ func TestParseTargets(t *testing.T) {
{"kubernetes:///a.b:port", targetInfo{"a", "b", "port", true, false}, false},
{"kubernetes:///a:port", targetInfo{"a", "", "port", true, false}, false},
{"kubernetes://x/a:port", targetInfo{"a", "x", "port", true, false}, false},
{"kubernetes://a.x:port/", targetInfo{"a", "x", "port", true, false}, false},
{"kubernetes://a.x:30/", targetInfo{"a", "x", "30", false, false}, false},
} {
got, err := parseResolverTarget(parseTarget(test.target))
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
module github.com/sercand/kuberesolver/v3
module github.com/sercand/kuberesolver/v4

go 1.14

require (
github.com/fsnotify/fsnotify v1.5.4
github.com/prometheus/client_golang v1.7.1
google.golang.org/grpc v1.31.0
golang.org/x/sys v0.5.0 // indirect
google.golang.org/grpc v1.53.0
)
Loading

0 comments on commit d8a3bdc

Please sign in to comment.