Files
threshold/internal/tests/cluster/sequential/worker_bytesupdown_test.go
T
846c849589 Worker Domain Refactor (#5338)
* feat(server): Refactor LookupWorkerByName to be a test method

* feat(server): Split worker tags table

* refact(worker): Export api and config tags

* refact(server): Return worker id from UpsertWorkerStatus

* refact(server): Create ListWorkerStorageBucketUpdates domain function

* refact(server): Use dedicated HCPb-worker list func

* refact(server): Create ConnectionRoute domain function

* refact(handlers): Move worker selection logic to internal/server package

This commit moves all the logic to select a worker to handle a session
to the internal/server package. Most functions were moved to this
package with no changes, however, there are a couple of notable
exceptions:

- Given that we don't use GRPC errors in repos, all errors were adjusted
  to use the internal/errors package instead.
- StorageBucketFilterCredIdFn is now used to prevent the internal/server
  package from importing internal/storage/plugin, which would cause a
  dep cycle. Callers of SelectSessionWorkers must implement this func
  which is responsible for returning a storage bucket's worker filter as
  well as its associated credential id.
- authorizeSessionWithWorkerFilter now receives an
  internal/server.(*Repository) object when called. This is transparent
  to SelectSessionWorkers callers as it is handled internally.

* feat(server): Add FilteredWithFeatures fn and new server options

* refact(server): create new list and lookup worker queries

* test(server): Add WorkerList unit tests

* feat(server): Implement WorkerList randomness using crypto/rand pkg

* chore(db): add index to server_worker table

* refact(server): prefix test method with Test

* refact(server): rename Downstreamers interface to Graph

* chore(server): unexport and rename method

* chore: add doc string to WorkerAddress (#5420)

---------

Co-authored-by: Irena Rindos <irenarindos@users.noreply.github.com>
Co-authored-by: irenarindos <irena.rindos@gmail.com>
2025-01-08 15:18:03 +00:00

145 lines
4.7 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package sequential
import (
"context"
"net"
"testing"
"github.com/hashicorp/boundary/api/sessions"
"github.com/hashicorp/boundary/api/targets"
"github.com/hashicorp/boundary/internal/cmd/config"
"github.com/hashicorp/boundary/internal/daemon/controller"
"github.com/hashicorp/boundary/internal/daemon/worker"
"github.com/hashicorp/boundary/internal/server"
"github.com/hashicorp/boundary/internal/tests/helper"
"github.com/hashicorp/dawdle"
"github.com/hashicorp/go-hclog"
"github.com/stretchr/testify/require"
)
func TestWorkerBytesUpDown(t *testing.T) {
require := require.New(t)
// This prevents us from running tests in parallel.
server.TestUseCommunityFilterWorkersFn(t)
logger := hclog.New(&hclog.LoggerOptions{
Name: t.Name(),
Level: hclog.Trace,
})
conf, err := config.DevController(config.WithIPv6Enabled(true))
require.NoError(err)
pl, err := net.Listen("tcp", "[::1]:")
require.NoError(err)
// update cluster listener to utilize proxy listener address
for _, l := range conf.Listeners {
if l.Purpose[0] == "cluster" {
l.Address = pl.Addr().String()
}
}
c1 := controller.NewTestController(t, &controller.TestControllerOpts{
Config: conf,
InitialResourcesSuffix: "1234567890",
Logger: logger.Named("c1"),
WorkerStatusGracePeriodDuration: helper.DefaultWorkerStatusGracePeriod,
})
helper.ExpectWorkers(t, c1)
// Wire up the testing proxies
require.Len(c1.ClusterAddrs(), 1)
proxy, err := dawdle.NewProxy("tcp", "", c1.ClusterAddrs()[0],
dawdle.WithListener(pl),
dawdle.WithRbufSize(256),
dawdle.WithWbufSize(256),
)
require.NoError(err)
require.NotEmpty(t, proxy.ListenerAddr())
t.Cleanup(func() { _ = proxy.Close() })
w1 := worker.NewTestWorker(t, &worker.TestWorkerOpts{
WorkerAuthKms: c1.Config().WorkerAuthKms,
InitialUpstreams: []string{proxy.ListenerAddr()},
Logger: logger.Named("w1"),
SuccessfulStatusGracePeriodDuration: helper.DefaultSuccessfulStatusGracePeriod,
EnableIPv6: true,
})
helper.ExpectWorkers(t, c1, w1)
// Use an independent context for test things that take a context so
// that we aren't tied to any timeouts in the controller, etc. This
// can interfere with some of the test operations.
ctx := context.Background()
// Connect target
client := c1.Client()
client.SetToken(c1.Token().Token)
tcl := targets.NewClient(client)
tgt, err := tcl.Read(ctx, "ttcp_1234567890")
require.NoError(err)
require.NotNil(tgt)
// Create test server, update default port on target
ts := helper.NewTestTcpServer(t)
require.NotNil(t, ts)
t.Cleanup(ts.Close)
tgt, err = tcl.Update(ctx, tgt.Item.Id, tgt.Item.Version, targets.WithTcpTargetDefaultPort(ts.Port()), targets.WithSessionConnectionLimit(-1))
require.NoError(err)
require.NotNil(tgt)
// Authorize a session, connect and send/recv some traffic
workerInfo := []*targets.WorkerInfo{
{
Address: w1.ProxyAddrs()[0],
},
}
sess := helper.NewTestSession(ctx, t, tcl, "ttcp_1234567890", helper.WithWorkerInfo(workerInfo))
conn := sess.Connect(ctx, t)
conn.TestSendRecvAll(t)
// Wait for next status and then check DB for bytes up and down
helper.ExpectWorkers(t, c1, w1)
dbConns1, err := c1.ConnectionsRepo().ListConnectionsBySessionId(ctx, sess.SessionId)
require.NoError(err)
require.Len(dbConns1, 1)
require.NotZero(dbConns1[0].BytesUp)
require.NotZero(dbConns1[0].BytesDown)
// Also check the connection data via the API
sc := sessions.NewClient(c1.Client())
apiRes1, err := sc.Read(ctx, sess.SessionId)
require.NoError(err)
require.Len(apiRes1.Item.Connections, 1)
require.NotZero(apiRes1.Item.Connections[0].BytesUp)
require.NotZero(apiRes1.Item.Connections[0].BytesDown)
// Send/recv some more traffic, close connection, wait for the next status
// update and check everything again.
conn.TestSendRecvAll(t)
require.NoError(conn.Close())
helper.ExpectWorkers(t, c1, w1)
dbConns2, err := c1.ConnectionsRepo().ListConnectionsBySessionId(ctx, sess.SessionId)
require.NoError(err)
require.Len(dbConns2, 1)
require.Greater(dbConns2[0].BytesUp, dbConns1[0].BytesUp)
require.Greater(dbConns2[0].BytesDown, dbConns1[0].BytesDown)
require.NotEmpty(dbConns2[0].ClosedReason)
apiRes2, err := sc.Read(ctx, sess.SessionId)
require.NoError(err)
require.Len(apiRes2.Item.Connections, 1)
require.Greater(apiRes2.Item.Connections[0].BytesUp, apiRes1.Item.Connections[0].BytesUp)
require.Greater(apiRes2.Item.Connections[0].BytesDown, apiRes1.Item.Connections[0].BytesDown)
require.NotEmpty(apiRes2.Item.Connections[0].ClosedReason)
}