Skip to content

Commit

Permalink
Introduce AddressTrie
Browse files Browse the repository at this point in the history
  • Loading branch information
eugercek committed Nov 28, 2022
1 parent 51a4d00 commit cd82d0d
Show file tree
Hide file tree
Showing 16 changed files with 334 additions and 60 deletions.
4 changes: 2 additions & 2 deletions core/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ func TestSentReceivedMetrics(t *testing.T) {
test := newTestEngine(t, nil, r, []output.Output{mockOutput}, lib.Options{
Iterations: null.IntFrom(tc.Iterations),
VUs: null.IntFrom(tc.VUs),
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts, Valid: true},
InsecureSkipTLSVerify: null.BoolFrom(true),
NoVUConnectionReuse: null.BoolFrom(noConnReuse),
Batch: null.IntFrom(20),
Expand Down Expand Up @@ -795,7 +795,7 @@ func TestRunTags(t *testing.T) {
test := newTestEngine(t, nil, r, []output.Output{mockOutput}, lib.Options{
Iterations: null.IntFrom(3),
VUs: null.IntFrom(2),
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts, Valid: true},
RunTags: runTags,
SystemTags: &metrics.DefaultSystemTagSet,
InsecureSkipTLSVerify: null.BoolFrom(true),
Expand Down
5 changes: 3 additions & 2 deletions js/http_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package js

import (
"context"
"go.k6.io/k6/lib/types"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -30,7 +31,7 @@ func BenchmarkHTTPRequests(b *testing.B) {
err = r.SetOptions(lib.Options{
Throw: null.BoolFrom(true),
MaxRedirects: null.IntFrom(10),
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts},
NoCookiesReset: null.BoolFrom(true),
SystemTags: &metrics.DefaultSystemTagSet,
RunTags: map[string]string{"myapp": "myhttpbench"},
Expand Down Expand Up @@ -70,7 +71,7 @@ func BenchmarkHTTPRequestsBase(b *testing.B) {
err = r.SetOptions(lib.Options{
Throw: null.BoolFrom(true),
MaxRedirects: null.IntFrom(10),
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts},
NoCookiesReset: null.BoolFrom(true),
})
require.NoError(b, err)
Expand Down
3 changes: 2 additions & 1 deletion js/module_loading_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package js
import (
"bytes"
"context"
"go.k6.io/k6/lib/types"
"os"
"testing"
"time"
Expand Down Expand Up @@ -197,7 +198,7 @@ func TestLoadDoesntBreakHTTPGet(t *testing.T) {
`, fs, lib.RuntimeOptions{CompatibilityMode: null.StringFrom("extended")})
require.NoError(t, err)

require.NoError(t, r1.SetOptions(lib.Options{Hosts: tb.Dialer.Hosts}))
require.NoError(t, r1.SetOptions(lib.Options{Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts}}))
arc := r1.MakeArchive()
registry := metrics.NewRegistry()
builtinMetrics := metrics.RegisterBuiltinMetrics(registry)
Expand Down
4 changes: 2 additions & 2 deletions js/modules/k6/execution/execution_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -292,12 +292,12 @@ func TestOptionsTestFull(t *testing.T) {
require.NoError(t, err)
return bh
}(),
Hosts: map[string]*types.HostAddress{
Hosts: types.NewNullAddressTrie(map[string]types.HostAddress{
"test.k6.io": {
IP: []byte{0x01, 0x02, 0x03, 0x04},
Port: 8443,
},
},
}),
External: map[string]json.RawMessage{
"ext-one": json.RawMessage(`{"rawkey":"rawvalue"}`),
},
Expand Down
14 changes: 7 additions & 7 deletions js/modules/k6/http/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2363,7 +2363,7 @@ func TestRequestAndBatchTLS(t *testing.T) {
require.NoError(t, err)
state.Transport = client.Transport
state.TLSConfig = s.TLS
state.Dialer = &netext.Dialer{Hosts: map[string]*types.HostAddress{"expired.localhost": mybadsslHostname}}
state.Dialer = &netext.Dialer{Hosts: types.NewAddressTrie(map[string]types.HostAddress{"expired.localhost": *mybadsslHostname})}
client.Transport.(*http.Transport).DialContext = state.Dialer.DialContext //nolint:forcetypeassert
_, err = rt.RunString(`throw JSON.stringify(http.get("https://expired.localhost/"));`)
require.Error(t, err)
Expand Down Expand Up @@ -2405,9 +2405,9 @@ func TestRequestAndBatchTLS(t *testing.T) {
ip := net.ParseIP(host)
mybadsslHostname, err := types.NewHostAddress(ip, port)
require.NoError(t, err)
state.Dialer = &netext.Dialer{Hosts: map[string]*types.HostAddress{
versionTest.URL: mybadsslHostname,
}}
state.Dialer = &netext.Dialer{Hosts: types.NewAddressTrie(map[string]types.HostAddress{
versionTest.URL: *mybadsslHostname,
})}
state.Transport = client.Transport
state.TLSConfig = s.TLS
client.Transport.(*http.Transport).DialContext = state.Dialer.DialContext //nolint:forcetypeassert
Expand Down Expand Up @@ -2445,9 +2445,9 @@ func TestRequestAndBatchTLS(t *testing.T) {
ip := net.ParseIP(host)
mybadsslHostname, err := types.NewHostAddress(ip, port)
require.NoError(t, err)
state.Dialer = &netext.Dialer{Hosts: map[string]*types.HostAddress{
cipherSuiteTest.URL: mybadsslHostname,
}}
state.Dialer = &netext.Dialer{Hosts: types.NewAddressTrie(map[string]types.HostAddress{
cipherSuiteTest.URL: *mybadsslHostname,
})}
state.Transport = client.Transport
state.TLSConfig = s.TLS
client.Transport.(*http.Transport).DialContext = state.Dialer.DialContext //nolint:forcetypeassert
Expand Down
2 changes: 1 addition & 1 deletion js/modules/k6/marshalling_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func TestSetupDataMarshalling(t *testing.T) {

err = runner.SetOptions(lib.Options{
SetupTimeout: types.NullDurationFrom(5 * time.Second),
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts},
})
require.NoError(t, err)

Expand Down
2 changes: 1 addition & 1 deletion js/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ func (r *Runner) newVU(idLocal, idGlobal uint64, samplesOut chan<- metrics.Sampl
Resolver: r.Resolver,
Blacklist: r.Bundle.Options.BlacklistIPs,
BlockedHostnames: r.Bundle.Options.BlockedHostnames.Trie,
Hosts: r.Bundle.Options.Hosts,
Hosts: r.Bundle.Options.Hosts.Trie,
}
if r.Bundle.Options.LocalIPs.Valid {
var ipIndex uint64
Expand Down
22 changes: 11 additions & 11 deletions js/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1033,9 +1033,9 @@ func TestVUIntegrationInsecureRequests(t *testing.T) {
require.NoError(t, err)
require.NoError(t, r1.SetOptions(lib.Options{Throw: null.BoolFrom(true)}.Apply(data.opts)))

r1.Bundle.Options.Hosts = map[string]*types.HostAddress{
"mybadssl.localhost": mybadsslHostname,
}
r1.Bundle.Options.Hosts = types.NewNullAddressTrie(map[string]types.HostAddress{
"mybadssl.localhost": *mybadsslHostname,
})
registry := metrics.NewRegistry()
builtinMetrics := metrics.RegisterBuiltinMetrics(registry)
r2, err := NewFromArchive(
Expand Down Expand Up @@ -1261,9 +1261,9 @@ func TestVUIntegrationHosts(t *testing.T) {

r1.SetOptions(lib.Options{
Throw: null.BoolFrom(true),
Hosts: map[string]*types.HostAddress{
Hosts: types.NewNullAddressTrie(map[string]types.HostAddress{
"test.loadimpact.com": {IP: net.ParseIP("127.0.0.1")},
},
}),
})

registry := metrics.NewRegistry()
Expand Down Expand Up @@ -1364,9 +1364,9 @@ func TestVUIntegrationTLSConfig(t *testing.T) {
opts := lib.Options{Throw: null.BoolFrom(true)}
require.NoError(t, r1.SetOptions(opts.Apply(data.opts)))

r1.Bundle.Options.Hosts = map[string]*types.HostAddress{
"sha256-badssl.localhost": mybadsslHostname,
}
r1.Bundle.Options.Hosts = types.NewNullAddressTrie(map[string]types.HostAddress{
"sha256-badssl.localhost": *mybadsslHostname,
})
r2, err := NewFromArchive(
&lib.TestPreInitState{
Logger: testutils.NewLogger(t),
Expand Down Expand Up @@ -1534,7 +1534,7 @@ func TestVUIntegrationCookiesReset(t *testing.T) {
require.NoError(t, err)
r1.Bundle.Options.Throw = null.BoolFrom(true)
r1.Bundle.Options.MaxRedirects = null.IntFrom(10)
r1.Bundle.Options.Hosts = tb.Dialer.Hosts
r1.Bundle.Options.Hosts = types.NullAddressTrie{Trie: tb.Dialer.Hosts}

registry := metrics.NewRegistry()
builtinMetrics := metrics.RegisterBuiltinMetrics(registry)
Expand Down Expand Up @@ -1592,7 +1592,7 @@ func TestVUIntegrationCookiesNoReset(t *testing.T) {
r1.SetOptions(lib.Options{
Throw: null.BoolFrom(true),
MaxRedirects: null.IntFrom(10),
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts},
NoCookiesReset: null.BoolFrom(true),
})

Expand Down Expand Up @@ -2531,7 +2531,7 @@ func TestForceHTTP1Feature(t *testing.T) {
require.NoError(t, err)

err = r1.SetOptions(lib.Options{
Hosts: tb.Dialer.Hosts,
Hosts: types.NullAddressTrie{Trie: tb.Dialer.Hosts},
// We disable TLS verify so that we don't get a TLS handshake error since
// the certificates on the endpoint are not certified by a certificate authority
InsecureSkipTLSVerify: null.BoolFrom(true),
Expand Down
14 changes: 8 additions & 6 deletions lib/netext/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Dialer struct {
Resolver Resolver
Blacklist []*lib.IPNet
BlockedHostnames *types.HostnameTrie
Hosts map[string]*types.HostAddress
Hosts *types.AddressTrie

BytesRead int64
BytesWritten int64
Expand Down Expand Up @@ -161,9 +161,11 @@ func (d *Dialer) findRemote(addr string) (*types.HostAddress, error) {
}
}

remote, err := d.getConfiguredHost(addr, host, port)
if err != nil || remote != nil {
return remote, err
if d.Hosts != nil {
remote, e := d.getConfiguredHost(addr, host, port)
if e != nil || remote != nil {
return remote, e
}
}

if ip != nil {
Expand All @@ -183,11 +185,11 @@ func (d *Dialer) findRemote(addr string) (*types.HostAddress, error) {
}

func (d *Dialer) getConfiguredHost(addr, host, port string) (*types.HostAddress, error) {
if remote, ok := d.Hosts[addr]; ok {
if remote := d.Hosts.Match(addr); remote != nil {
return remote, nil
}

if remote, ok := d.Hosts[host]; ok {
if remote := d.Hosts.Match(host); remote != nil {
if remote.Port != 0 || port == "" {
return remote, nil
}
Expand Down
27 changes: 14 additions & 13 deletions lib/netext/dialer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ import (
func TestDialerAddr(t *testing.T) {
t.Parallel()
dialer := NewDialer(net.Dialer{}, newResolver())
dialer.Hosts = map[string]*types.HostAddress{
"example.com": {IP: net.ParseIP("3.4.5.6")},
"example.com:443": {IP: net.ParseIP("3.4.5.6"), Port: 8443},
"example.com:8080": {IP: net.ParseIP("3.4.5.6"), Port: 9090},
"example-deny-host.com": {IP: net.ParseIP("8.9.10.11")},
"example-ipv6.com": {IP: net.ParseIP("2001:db8::68")},
"example-ipv6.com:443": {IP: net.ParseIP("2001:db8::68"), Port: 8443},
"example-ipv6-deny-host.com": {IP: net.ParseIP("::1")},
}
dialer.Hosts = types.NewAddressTrie(
map[string]types.HostAddress{
"example.com": {IP: net.ParseIP("3.4.5.6")},
"example.com:443": {IP: net.ParseIP("3.4.5.6"), Port: 8443},
"example.com:8080": {IP: net.ParseIP("3.4.5.6"), Port: 9090},
"example-deny-host.com": {IP: net.ParseIP("8.9.10.11")},
"example-ipv6.com": {IP: net.ParseIP("2001:db8::68")},
"example-ipv6.com:443": {IP: net.ParseIP("2001:db8::68"), Port: 8443},
"example-ipv6-deny-host.com": {IP: net.ParseIP("::1")},
})

ipNet, err := lib.ParseCIDR("8.9.10.0/24")
require.NoError(t, err)
Expand Down Expand Up @@ -75,9 +76,9 @@ func TestDialerAddr(t *testing.T) {
func TestDialerAddrBlockHostnamesStar(t *testing.T) {
t.Parallel()
dialer := NewDialer(net.Dialer{}, newResolver())
dialer.Hosts = map[string]*types.HostAddress{
dialer.Hosts = types.NewAddressTrie(map[string]types.HostAddress{
"example.com": {IP: net.ParseIP("3.4.5.6")},
}
})

blocked, err := types.NewHostnameTrie([]string{"*"})
require.NoError(t, err)
Expand Down Expand Up @@ -111,12 +112,12 @@ func TestDialerAddrBlockHostnamesStar(t *testing.T) {

// Benchmarks /etc/hosts like hostname mapping
func BenchmarkDialerHosts(b *testing.B) {
hosts := map[string]*types.HostAddress{
hosts := types.NewAddressTrie(map[string]types.HostAddress{
"k6.io": {IP: []byte("192.168.1.1"), Port: 80},
"specific.k6.io": {IP: []byte("192.168.1.2"), Port: 80},
"grafana.com": {IP: []byte("aa::ff"), Port: 80},
"specific.grafana.com": {IP: []byte("aa:bb:::ff"), Port: 80},
}
})

dialer := Dialer{
Dialer: net.Dialer{},
Expand Down
12 changes: 8 additions & 4 deletions lib/netext/httpext/error_codes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ func TestX509HostnameError(t *testing.T) {
}
var err error
badHostname := "somewhere.else"
tb.Dialer.Hosts[badHostname], err = types.NewHostAddress(net.ParseIP(tb.Replacer.Replace("HTTPSBIN_IP")), "")
badHostAddress, err := types.NewHostAddress(net.ParseIP(tb.Replacer.Replace("HTTPSBIN_IP")), "")

tb.Dialer.Hosts = types.NewAddressTrie(map[string]types.HostAddress{
badHostname: *badHostAddress,
})
require.NoError(t, err)
req, err := http.NewRequestWithContext(context.Background(), "GET", tb.Replacer.Replace("https://"+badHostname+":HTTPSBIN_PORT/get"), nil)
require.NoError(t, err)
Expand Down Expand Up @@ -355,9 +359,9 @@ func getHTTP2ServerWithCustomConnContext(t *testing.T) *httpmultibin.HTTPMultiBi
KeepAlive: 10 * time.Second,
DualStack: true,
}, netext.NewResolver(net.LookupIP, 0, types.DNSfirst, types.DNSpreferIPv4))
dialer.Hosts = map[string]*types.HostAddress{
http2Domain: http2DomainValue,
}
dialer.Hosts = types.NewAddressTrie(map[string]types.HostAddress{
http2Domain: *http2DomainValue,
})

transport := &http.Transport{
DialContext: dialer.DialContext,
Expand Down
4 changes: 2 additions & 2 deletions lib/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ type Options struct {
BlockedHostnames types.NullHostnameTrie `json:"blockHostnames" envconfig:"K6_BLOCK_HOSTNAMES"`

// Hosts overrides dns entries for given hosts
Hosts map[string]*types.HostAddress `json:"hosts" envconfig:"K6_HOSTS"`
Hosts types.NullAddressTrie `json:"hosts" envconfig:"K6_HOSTS"`

// Disable keep-alive connections
NoConnectionReuse null.Bool `json:"noConnectionReuse" envconfig:"K6_NO_CONNECTION_REUSE"`
Expand Down Expand Up @@ -442,7 +442,7 @@ func (o Options) Apply(opts Options) Options {
if opts.BlockedHostnames.Valid {
o.BlockedHostnames = opts.BlockedHostnames
}
if opts.Hosts != nil {
if opts.Hosts.Valid {
o.Hosts = opts.Hosts
}
if opts.NoConnectionReuse.Valid {
Expand Down
9 changes: 5 additions & 4 deletions lib/options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -459,12 +459,13 @@ func TestOptions(t *testing.T) {
host, err := types.NewHostAddress(net.ParseIP("192.0.2.1"), "80")
assert.NoError(t, err)

opts := Options{}.Apply(Options{Hosts: map[string]*types.HostAddress{
"test.loadimpact.com": host,
}})
opts := Options{}.Apply(Options{Hosts: types.NewNullAddressTrie(map[string]types.HostAddress{
"test.loadimpact.com": *host,
})})
assert.NotNil(t, opts.Hosts)
assert.NotEmpty(t, opts.Hosts)
assert.Equal(t, "192.0.2.1:80", opts.Hosts["test.loadimpact.com"].String())

assert.Equal(t, "192.0.2.1:80", opts.Hosts.Trie.Match("test.loadimpact.com").String())
})

t.Run("Throws", func(t *testing.T) {
Expand Down
8 changes: 4 additions & 4 deletions lib/testutils/httpmultibin/httpmultibin.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,10 @@ func NewHTTPMultiBin(t testing.TB) *HTTPMultiBin {
KeepAlive: 10 * time.Second,
DualStack: true,
}, netext.NewResolver(net.LookupIP, 0, types.DNSfirst, types.DNSpreferIPv4))
dialer.Hosts = map[string]*types.HostAddress{
httpDomain: httpDomainValue,
httpsDomain: httpsDomainValue,
}
dialer.Hosts = types.NewAddressTrie(map[string]types.HostAddress{
httpDomain: *httpDomainValue,
httpsDomain: *httpsDomainValue,
})

// Pre-configure the HTTP client transport with the dialer and TLS config (incl. HTTP2 support)
transport := &http.Transport{
Expand Down
Loading

0 comments on commit cd82d0d

Please sign in to comment.