Skip to content

Commit

Permalink
[probes.http] Handle resolve_first resolve errors properly (cloudprob…
Browse files Browse the repository at this point in the history
…er#616)

- Also, resolve URL host if resolving first. That's what Go's stdlib will resolve.
- Increase "total" count for resolve first errors.
  • Loading branch information
manugarg authored Nov 1, 2023
1 parent 3faa199 commit 930b3cd
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 5 deletions.
2 changes: 2 additions & 0 deletions probes/http/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,8 @@ func (p *Probe) startForTarget(ctx context.Context, target endpoint.Endpoint, da
// creation gets retried at a regular interval (stats export interval).
if req != nil {
p.runProbe(ctx, target, clients, req, result)
} else {
result.total += int64(p.c.GetRequestsPerProbe())
}

// Export stats if it's the time to do so.
Expand Down
7 changes: 4 additions & 3 deletions probes/http/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,9 @@ func (p *Probe) urlHostAndIPLabel(target endpoint.Endpoint, host string) (string
return host, "", nil
}

ip, err := target.Resolve(p.opts.IPVersion, p.opts.Targets)
ip, err := target.Resolve(p.opts.IPVersion, p.opts.Targets, endpoint.WithNameOverride(host))
if err != nil {
p.l.Error("target: ", target.Name, ", resolve error: ", err.Error())
return "", "", nil
return "", "", fmt.Errorf("error resolving target: %s, %v", target.Name, err)
}

ipStr := ip.String()
Expand All @@ -158,6 +157,8 @@ func (p *Probe) httpRequestForTarget(target endpoint.Endpoint) *http.Request {

urlHost, ipForLabel, err := p.urlHostAndIPLabel(target, host)
if err != nil {
// We just return a nil request. The caller will skip nil requests.
p.l.Error(err.Error())
return nil
}

Expand Down
25 changes: 23 additions & 2 deletions targets/endpoint/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,26 @@ func (ep *Endpoint) Dst() string {
return net.JoinHostPort(ep.Name, strconv.Itoa(ep.Port))
}

type resolverOptions struct {
nameOverride string
}

type ResolverOption func(*resolverOptions)

func WithNameOverride(nameOverride string) ResolverOption {
return func(ro *resolverOptions) {
ro.nameOverride = nameOverride
}
}

// Resolve resolves endpoint to an IP address. If endpoint has an embedded IP
// address it uses that, otherwise a global reolver is used.
func (ep *Endpoint) Resolve(ipVersion int, resolver Resolver) (net.IP, error) {
func (ep *Endpoint) Resolve(ipVersion int, resolver Resolver, opts ...ResolverOption) (net.IP, error) {
ro := &resolverOptions{}
for _, opt := range opts {
opt(ro)
}

if ep.IP != nil {
if ipVersion == 0 || iputils.IPVersion(ep.IP) == ipVersion {
return ep.IP, nil
Expand All @@ -99,7 +116,11 @@ func (ep *Endpoint) Resolve(ipVersion int, resolver Resolver) (net.IP, error) {
return nil, fmt.Errorf("no IPv%d address (IP: %s) for %s", ipVersion, ep.IP.String(), ep.Name)
}

return resolver.Resolve(ep.Name, ipVersion)
name := ep.Name
if ro.nameOverride != "" {
name = ro.nameOverride
}
return resolver.Resolve(name, ipVersion)
}

// NamesFromEndpoints is convenience function to build a list of names
Expand Down
75 changes: 75 additions & 0 deletions targets/endpoint/endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,78 @@ func TestFromProtoMessage(t *testing.T) {
})
}
}

type testResolver struct {
data map[string]net.IP
}

func (tr *testResolver) Resolve(name string, ipVersion int) (net.IP, error) {
if tr.data == nil {
tr.data = make(map[string]net.IP)
}
if tr.data[name] == nil {
return nil, fmt.Errorf("no such host: %s", name)
}
return tr.data[name], nil
}

func TestEndpointResolve(t *testing.T) {
res := &testResolver{
data: map[string]net.IP{
"host1": net.ParseIP("10.10.3.4"),
"host2": net.ParseIP("2001:db8::1"),
},
}

tests := []struct {
name string
ep Endpoint
ipVersion int
opts []ResolverOption
wantIP string
wantErr bool
}{
{
name: "contains valid ip",
ep: Endpoint{Name: "host0", IP: net.ParseIP("10.1.1.1")},
wantIP: "10.1.1.1",
},
{
name: "no ipv6",
ep: Endpoint{Name: "host0", IP: net.ParseIP("10.1.1.1")},
ipVersion: 6,
wantErr: true,
},
{
name: "use_resolver",
ep: Endpoint{Name: "host1"},
wantIP: "10.10.3.4",
},
{
name: "name_override",
ep: Endpoint{Name: "host0"},
opts: []ResolverOption{WithNameOverride("host2")},
ipVersion: 6,
wantIP: "2001:db8::1",
},
{
name: "no host",
ep: Endpoint{Name: "host0"},
opts: []ResolverOption{WithNameOverride("host3")},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := tt.ep.Resolve(tt.ipVersion, res, tt.opts...)
if (err != nil) != tt.wantErr {
t.Errorf("Endpoint.Resolve() error = %v, wantErr %v", err, tt.wantErr)
return
}
if err != nil {
return
}
assert.Equal(t, tt.wantIP, got.String(), "resolved IP")
})
}
}

0 comments on commit 930b3cd

Please sign in to comment.