From 018d40cd56fc65c6f91f314b9d5b65b43b83ab33 Mon Sep 17 00:00:00 2001 From: Raphael 'kena' Poss Date: Wed, 26 Jul 2023 19:53:25 +0200 Subject: [PATCH] testutils: move import interfaces to api.go Release note: None --- pkg/testutils/serverutils/BUILD.bazel | 1 + pkg/testutils/serverutils/api.go | 474 ++++++++++++++++++ pkg/testutils/serverutils/test_server_shim.go | 195 ------- pkg/testutils/serverutils/test_tenant_shim.go | 266 +--------- 4 files changed, 476 insertions(+), 460 deletions(-) create mode 100644 pkg/testutils/serverutils/api.go diff --git a/pkg/testutils/serverutils/BUILD.bazel b/pkg/testutils/serverutils/BUILD.bazel index 4f0c84d2878e..710374a6598c 100644 --- a/pkg/testutils/serverutils/BUILD.bazel +++ b/pkg/testutils/serverutils/BUILD.bazel @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "serverutils", srcs = [ + "api.go", "test_cluster_shim.go", "test_cluster_utils.go", "test_server_shim.go", diff --git a/pkg/testutils/serverutils/api.go b/pkg/testutils/serverutils/api.go new file mode 100644 index 000000000000..32c545f272d0 --- /dev/null +++ b/pkg/testutils/serverutils/api.go @@ -0,0 +1,474 @@ +// Copyright 2023 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. +// +// This file provides generic interfaces that allow tests to set up test tenants +// without importing the server package (avoiding circular dependencies). This + +package serverutils + +import ( + "context" + gosql "database/sql" + "net/http" + + "github.com/cockroachdb/cockroach/pkg/base" + "github.com/cockroachdb/cockroach/pkg/config" + "github.com/cockroachdb/cockroach/pkg/keys" + "github.com/cockroachdb/cockroach/pkg/kv" + "github.com/cockroachdb/cockroach/pkg/kv/kvprober" + "github.com/cockroachdb/cockroach/pkg/kv/kvserver/liveness/livenesspb" + "github.com/cockroachdb/cockroach/pkg/multitenant/tenantcapabilities" + "github.com/cockroachdb/cockroach/pkg/roachpb" + "github.com/cockroachdb/cockroach/pkg/rpc" + "github.com/cockroachdb/cockroach/pkg/security/username" + "github.com/cockroachdb/cockroach/pkg/server/serverpb" + "github.com/cockroachdb/cockroach/pkg/server/status" + "github.com/cockroachdb/cockroach/pkg/settings/cluster" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" + "github.com/cockroachdb/cockroach/pkg/storage" + "github.com/cockroachdb/cockroach/pkg/util/hlc" + "github.com/cockroachdb/cockroach/pkg/util/log" + "github.com/cockroachdb/cockroach/pkg/util/stop" + "github.com/cockroachdb/cockroach/pkg/util/tracing" + "github.com/cockroachdb/cockroach/pkg/util/uuid" +) + +// TestServerInterface defines test server functionality that tests need; it is +// implemented by server.TestServer. +type TestServerInterface interface { + StorageLayerInterface + ApplicationLayerInterface + TenantControlInterface + + Start(context.Context) error + + // ApplicationLayer returns the interface to the application layer that is + // exercised by the test. Depending on how the test server is started + // and (optionally) randomization, this can be either the SQL layer + // of a secondary tenant or that of the system tenant. + ApplicationLayer() ApplicationLayerInterface + + // SystemLayer returns the interface to the application layer + // of the system tenant. + SystemLayer() ApplicationLayerInterface + + // StorageLayer returns the interface to the storage layer. + StorageLayer() StorageLayerInterface + + // BinaryVersionOverride returns the value of an override if set using + // TestingKnobs. + BinaryVersionOverride() roachpb.Version +} + +// ApplicationLayerInterface defines accessors to the application +// layer of a test server. Tests written against this interface are +// effectively agnostic to whether they use a secondary tenant or not. +// This interface is implemented by server.Test{Tenant,Server}. +type ApplicationLayerInterface interface { + // SQLInstanceID is the ephemeral ID assigned to a running instance of the + // SQLServer. Each tenant can have zero or more running SQLServer instances. + SQLInstanceID() base.SQLInstanceID + + // AdvRPCAddr returns the server's advertised address. + AdvRPCAddr() string + + // AdvSQLAddr returns the server's advertised SQL address. + AdvSQLAddr() string + + // SQLAddr returns the server's SQL address. Note that for "shared-process + // tenants" (i.e. tenants created with TestServer.StartSharedProcessTenant), + // simply connecting to this address connects to the system tenant, not to + // this tenant. In order to connect to this tenant, + // "cluster:/" needs to be added to the connection + // string as the database name. + SQLAddr() string + + // HTTPAddr returns the server's http address. + HTTPAddr() string + + // RPCAddr returns the server's RPC address. + RPCAddr() string + + // DB returns a handle to the cluster's KV interface. + DB() *kv.DB + + // PGServer returns the server's *pgwire.Server as an interface{}. + PGServer() interface{} + + // PGPreServer returns the server's *pgwire.PreServeConnHandler as an interface{}. + PGPreServer() interface{} + + // DiagnosticsReporter returns the server's *diagnostics.Reporter as an + // interface{}. The DiagnosticsReporter periodically phones home to report + // diagnostics and usage. + DiagnosticsReporter() interface{} + + // StatusServer returns the server's *server.SQLStatusServer as an + // interface{}. + StatusServer() interface{} + + // TenantStatusServer returns the server's *server.TenantStatusServer as an + // interface{}. + TenantStatusServer() interface{} + + // HTTPAuthServer returns the authserver.Server as an interface{}. + HTTPAuthServer() interface{} + + // SQLServer returns the *sql.Server as an interface{}. + SQLServer() interface{} + + // DistSQLServer returns the *distsql.ServerImpl as an interface{}. + DistSQLServer() interface{} + + // SetDistSQLSpanResolver changes the SpanResolver used for DistSQL inside the + // server's executor. The argument must be a physicalplan.SpanResolver + // instance. + // + // This method exists because we cannot pass the fake span resolver with the + // server or cluster params: the fake span resolver needs the node IDs and + // addresses of the servers in a cluster, which are not available before we + // start the servers. + // + // It is the caller's responsibility to make sure no queries are being run + // with DistSQL at the same time. + SetDistSQLSpanResolver(spanResolver interface{}) + + // DistSenderI returns the *kvcoord.DistSender as an interface{}. + DistSenderI() interface{} + + // InternalDB returns an isql.DB as an interface{}. + InternalDB() interface{} + + // InternalExecutor returns a *sql.InternalExecutor as an interface{} (which + // also implements isql.Executor if the test cannot depend on sql). + InternalExecutor() interface{} + + // LeaseManager returns the *sql.LeaseManager as an interface{}. + LeaseManager() interface{} + + // JobRegistry returns the *jobs.Registry as an interface{}. + JobRegistry() interface{} + + // RPCContext returns the *rpc.Context used by the test tenant. + RPCContext() *rpc.Context + + // AnnotateCtx annotates a context. + AnnotateCtx(context.Context) context.Context + + // ExecutorConfig returns a copy of the server's ExecutorConfig. + // The real return type is sql.ExecutorConfig. + ExecutorConfig() interface{} + + // RangeFeedFactory returns the range feed factory used by the tenant. + // The real return type is *rangefeed.Factory. + RangeFeedFactory() interface{} + + // ClusterSettings returns the ClusterSettings shared by all components of + // this tenant. + ClusterSettings() *cluster.Settings + + // SettingsWatcher returns the *settingswatcher.SettingsWatcher used by the + // tenant server. + SettingsWatcher() interface{} + + // Stopper returns the stopper used by the tenant. + Stopper() *stop.Stopper + + // Clock returns the clock used by the tenant. + Clock() *hlc.Clock + + // SpanConfigKVAccessor returns the underlying spanconfig.KVAccessor as an + // interface{}. + SpanConfigKVAccessor() interface{} + + // SpanConfigReporter returns the underlying spanconfig.Reporter as an + // interface{}. + SpanConfigReporter() interface{} + + // SpanConfigReconciler returns the underlying spanconfig.Reconciler as an + // interface{}. + SpanConfigReconciler() interface{} + + // SpanConfigSQLTranslatorFactory returns the underlying + // spanconfig.SQLTranslatorFactory as an interface{}. + SpanConfigSQLTranslatorFactory() interface{} + + // SpanConfigSQLWatcher returns the underlying spanconfig.SQLWatcher as an + // interface{}. + SpanConfigSQLWatcher() interface{} + + // TestingKnobs returns the TestingKnobs in use by the test server. + TestingKnobs() *base.TestingKnobs + + // AmbientCtx retrieves the AmbientContext for this server, + // so that a test can instantiate additional one-off components + // using the same context details as the server. This should not + // be used in non-test code. + AmbientCtx() log.AmbientContext + + // AdminURL returns the URL for the admin UI. + AdminURL() *TestURL + + // GetUnauthenticatedHTTPClient returns an http client configured with the client TLS + // config required by the TestServer's configuration. + // Discourages implementer from using unauthenticated http connections + // with verbose method name. + GetUnauthenticatedHTTPClient() (http.Client, error) + + // GetAdminHTTPClient returns an http client which has been + // authenticated to access Admin API methods (via a cookie). + // The user has admin privileges. + GetAdminHTTPClient() (http.Client, error) + + // GetAuthenticatedHTTPClient returns an http client which has been + // authenticated to access Admin API methods (via a cookie). + GetAuthenticatedHTTPClient(isAdmin bool, sessionType SessionType) (http.Client, error) + + // GetAuthenticatedHTTPClientAndCookie returns an http client which + // has been authenticated to access Admin API methods and + // the corresponding session cookie. + GetAuthenticatedHTTPClientAndCookie( + authUser username.SQLUsername, isAdmin bool, session SessionType, + ) (http.Client, *serverpb.SessionCookie, error) + + // GetAuthSession returns a byte array containing a valid auth + // session. + GetAuthSession(isAdmin bool) (*serverpb.SessionCookie, error) + + // CreateAuthUser is exported for use in tests. + CreateAuthUser(userName username.SQLUsername, isAdmin bool) error + + // DrainClients shuts down client connections. + DrainClients(ctx context.Context) error + + // SystemConfigProvider provides access to the system config. + SystemConfigProvider() config.SystemConfigProvider + + // MustGetSQLCounter returns the value of a counter metric from the server's + // SQL Executor. Runs in O(# of metrics) time, which is fine for test code. + MustGetSQLCounter(name string) int64 + // MustGetSQLNetworkCounter returns the value of a counter metric from the + // server's SQL server. Runs in O(# of metrics) time, which is fine for test + // code. + MustGetSQLNetworkCounter(name string) int64 + + // Codec returns this server's codec (or keys.SystemSQLCodec if this is the + // system tenant). + Codec() keys.SQLCodec + + // RangeDescIteratorFactory returns the underlying rangedesc.IteratorFactory + // as an interface{}. + RangeDescIteratorFactory() interface{} + + // Tracer returns a reference to the server's Tracer. + Tracer() *tracing.Tracer + + // TracerI is the same as Tracer but returns an interface{}. + TracerI() interface{} + + // MigrationServer returns the server's migration server, which is used in + // upgrade testing. + MigrationServer() interface{} + + // CollectionFactory returns a *descs.CollectionFactory. + CollectionFactory() interface{} + + // SystemTableIDResolver returns a catalog.SystemTableIDResolver. + SystemTableIDResolver() interface{} + + // QueryDatabaseID provides access to the database name-to-ID conversion function + // for use in API tests. + QueryDatabaseID( + ctx context.Context, userName username.SQLUsername, dbName string, + ) (descpb.ID, error) + + // QueryTableID provides access to the table name-to-ID conversion function + // for use in API tests. + QueryTableID( + ctx context.Context, userName username.SQLUsername, dbName, tbName string, + ) (descpb.ID, error) + + // StatsForSpans provides access to the span stats inspection function + // for use in API tests. + StatsForSpan( + ctx context.Context, span roachpb.Span, + ) (*serverpb.TableStatsResponse, error) + + // ForceTableGC forces a KV GC round on the key range for the given table. + ForceTableGC( + ctx context.Context, database, table string, timestamp hlc.Timestamp, + ) error + + // TODO(irfansharif): We'd benefit from an API to construct a *gosql.DB, or + // better yet, a *sqlutils.SQLRunner. We use it all the time, constructing + // it by hand each time. +} + +// TenantControlInterface defines the API of a test server that can +// start the SQL and HTTP service for secondary tenants (virtual +// clusters). +type TenantControlInterface interface { + // StartSharedProcessTenant starts the service for a secondary tenant + // using the special configuration we define for shared-process deployments. + // + // args.TenantName must be specified. If a tenant with that name already + // exists, its ID is checked against args.TenantID (if set), and, if it + // matches, new tenant metadata is not created in the system.tenants table. + // + // See also StartTenant(), which starts a tenant mimicking out-of-process tenant + // servers. + // + // TODO(knz): fold with StartTenant below. + StartSharedProcessTenant( + ctx context.Context, args base.TestSharedProcessTenantArgs, + ) (ApplicationLayerInterface, *gosql.DB, error) + + // StartTenant starts the service for a secondary tenant using the special + // configuration we define for separate-process deployments. This incidentally + // is also the configuration we use in CC Serverless. + // + // TODO(knz): Rename this to StartApplicationService. Take the + // deployment mode as parameter instead of using a separate method. + StartTenant(ctx context.Context, params base.TestTenantArgs) (ApplicationLayerInterface, error) + + // DisableStartTenant prevents calls to StartTenant(). If an attempt + // is made, the server will return the specified error. + DisableStartTenant(reason error) + + // WaitForTenantReadiness waits until the tenant record is known + // to the in-RAM caches. Trying to start a tenant server before + // this is called can run into a "missing record" error even + // if the tenant record exists in KV. + WaitForTenantReadiness(ctx context.Context, tenantID roachpb.TenantID) error + + // TestTenants returns the test tenants associated with the server. + // + // TODO(knz): rename to TestApplicationServices. + TestTenants() []ApplicationLayerInterface + + // StartedDefaultTestTenant returns true if the server has started + // the service for the default test tenant. + StartedDefaultTestTenant() bool +} + +// StorageLayerInterface defines accessors to the storage layer of a +// test server. See ApplicationLayerInterface for the relevant +// application-level APIs. +type StorageLayerInterface interface { + // Node returns the server.Node as an interface{}. + Node() interface{} + + // NodeID returns the ID of this node within its cluster. + NodeID() roachpb.NodeID + + // StorageClusterID returns the storage cluster ID as understood by + // this node in the cluster. + StorageClusterID() uuid.UUID + + // GossipI returns the gossip used by the TestServer. + // The real return type is *gossip.Gossip. + GossipI() interface{} + + // SQLLivenessProvider returns the sqlliveness.Provider as an interface{}. + SQLLivenessProvider() interface{} + + // NodeLiveness exposes the NodeLiveness instance used by the TestServer as an + // interface{}. + NodeLiveness() interface{} + + // HeartbeatNodeLiveness heartbeats the server's NodeLiveness record. + HeartbeatNodeLiveness() error + + // NodeDialer exposes the NodeDialer instance used by the TestServer as an + // interface{}. + NodeDialer() interface{} + + // WriteSummaries records summaries of time-series data, which is required for + // any tests that query server stats. + WriteSummaries() error + + // GetFirstStoreID is a utility function returning the StoreID of the first + // store on this node. + GetFirstStoreID() roachpb.StoreID + + // GetStores returns the collection of stores from this TestServer's node. + // The return value is of type *kvserver.Stores. + GetStores() interface{} + + // Decommission idempotently sets the decommissioning flag for specified nodes. + Decommission(ctx context.Context, targetStatus livenesspb.MembershipStatus, nodeIDs []roachpb.NodeID) error + + // DecommissioningNodeMap returns a map of nodeIDs that are known to the + // server to be decommissioning. + DecommissioningNodeMap() map[roachpb.NodeID]interface{} + + // SplitRange splits the range containing splitKey. + SplitRange(splitKey roachpb.Key) (left roachpb.RangeDescriptor, right roachpb.RangeDescriptor, err error) + + // MergeRanges merges the range containing leftKey with the following adjacent + // range. + MergeRanges(leftKey roachpb.Key) (merged roachpb.RangeDescriptor, err error) + + // ExpectedInitialRangeCount returns the expected number of ranges that should + // be on the server after initial (asynchronous) splits have been completed, + // assuming no additional information is added outside of the normal bootstrap + // process. + ExpectedInitialRangeCount() (int, error) + + // ForceTableGC sends a GCRequest for the ranges corresponding to a table. + // + // An error will be returned if the same table name exists in multiple schemas + // inside the specified database. + ForceTableGC(ctx context.Context, database, table string, timestamp hlc.Timestamp) error + + // UpdateChecker returns the server's *diagnostics.UpdateChecker as an + // interface{}. The UpdateChecker periodically phones home to check for new + // updates that are available. + UpdateChecker() interface{} + + // ScratchRange splits off a range suitable to be used as KV scratch space. + // (it doesn't overlap system spans or SQL tables). + // + // Calling this multiple times is undefined (but see + // TestCluster.ScratchRange() which is idempotent). + ScratchRange() (roachpb.Key, error) + + // Engines returns the TestServer's engines. + Engines() []storage.Engine + + // MetricsRecorder periodically records node-level and store-level metrics. + MetricsRecorder() *status.MetricsRecorder + + // SpanConfigKVSubscriber returns the embedded spanconfig.KVSubscriber for + // the server. + SpanConfigKVSubscriber() interface{} + + // KVFlowController returns the embedded kvflowcontrol.Controller for the + // server. + KVFlowController() interface{} + + // KVFlowHandles returns the embedded kvflowcontrol.Handles for the server. + KVFlowHandles() interface{} + + // KvProber returns a *kvprober.Prober, which is useful when asserting the + //correctness of the prober from integration tests. + KvProber() *kvprober.Prober + + // TenantCapabilitiesReader retrieves a reference to the + // capabilities reader. + TenantCapabilitiesReader() tenantcapabilities.Reader +} + +// TestServerFactory encompasses the actual implementation of the shim +// service. +type TestServerFactory interface { + // New instantiates a test server. + New(params base.TestServerArgs) (interface{}, error) +} diff --git a/pkg/testutils/serverutils/test_server_shim.go b/pkg/testutils/serverutils/test_server_shim.go index a9c37cdd279f..048c63e0e626 100644 --- a/pkg/testutils/serverutils/test_server_shim.go +++ b/pkg/testutils/serverutils/test_server_shim.go @@ -27,25 +27,19 @@ import ( "github.com/cockroachdb/cockroach/pkg/base" "github.com/cockroachdb/cockroach/pkg/kv" - "github.com/cockroachdb/cockroach/pkg/kv/kvprober" - "github.com/cockroachdb/cockroach/pkg/kv/kvserver/liveness/livenesspb" "github.com/cockroachdb/cockroach/pkg/multitenant/tenantcapabilities" "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/security" "github.com/cockroachdb/cockroach/pkg/security/username" - "github.com/cockroachdb/cockroach/pkg/server/status" - "github.com/cockroachdb/cockroach/pkg/storage" "github.com/cockroachdb/cockroach/pkg/testutils" "github.com/cockroachdb/cockroach/pkg/testutils/skip" "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" "github.com/cockroachdb/cockroach/pkg/util" "github.com/cockroachdb/cockroach/pkg/util/envutil" - "github.com/cockroachdb/cockroach/pkg/util/hlc" "github.com/cockroachdb/cockroach/pkg/util/httputil" "github.com/cockroachdb/cockroach/pkg/util/log" "github.com/cockroachdb/cockroach/pkg/util/protoutil" "github.com/cockroachdb/cockroach/pkg/util/stop" - "github.com/cockroachdb/cockroach/pkg/util/uuid" "github.com/cockroachdb/errors" ) @@ -106,195 +100,6 @@ func ShouldStartDefaultTestTenant(t testing.TB, serverArgs base.TestServerArgs) return enabled } -// TestServerInterface defines test server functionality that tests need; it is -// implemented by server.TestServer. -type TestServerInterface interface { - StorageLayerInterface - ApplicationLayerInterface - TenantControlInterface - - Start(context.Context) error - - // ApplicationLayer returns the interface to the application layer that is - // exercised by the test. Depending on how the test server is started - // and (optionally) randomization, this can be either the SQL layer - // of a secondary tenant or that of the system tenant. - ApplicationLayer() ApplicationLayerInterface - - // SystemLayer returns the interface to the application layer - // of the system tenant. - SystemLayer() ApplicationLayerInterface - - // StorageLayer returns the interface to the storage layer. - StorageLayer() StorageLayerInterface - - // BinaryVersionOverride returns the value of an override if set using - // TestingKnobs. - BinaryVersionOverride() roachpb.Version -} - -// TenantControlInterface defines the API of a test server that can -// start the SQL and HTTP service for secondary tenants (virtual -// clusters). -type TenantControlInterface interface { - // StartSharedProcessTenant starts the service for a secondary tenant - // using the special configuration we define for shared-process deployments. - // - // args.TenantName must be specified. If a tenant with that name already - // exists, its ID is checked against args.TenantID (if set), and, if it - // matches, new tenant metadata is not created in the system.tenants table. - // - // See also StartTenant(), which starts a tenant mimicking out-of-process tenant - // servers. - // - // TODO(knz): fold with StartTenant below. - StartSharedProcessTenant( - ctx context.Context, args base.TestSharedProcessTenantArgs, - ) (ApplicationLayerInterface, *gosql.DB, error) - - // StartTenant starts the service for a secondary tenant using the special - // configuration we define for separate-process deployments. This incidentally - // is also the configuration we use in CC Serverless. - // - // TODO(knz): Rename this to StartApplicationService. Take the - // deployment mode as parameter instead of using a separate method. - StartTenant(ctx context.Context, params base.TestTenantArgs) (ApplicationLayerInterface, error) - - // DisableStartTenant prevents calls to StartTenant(). If an attempt - // is made, the server will return the specified error. - DisableStartTenant(reason error) - - // WaitForTenantReadiness waits until the tenant record is known - // to the in-RAM caches. Trying to start a tenant server before - // this is called can run into a "missing record" error even - // if the tenant record exists in KV. - WaitForTenantReadiness(ctx context.Context, tenantID roachpb.TenantID) error - - // TestTenants returns the test tenants associated with the server. - // - // TODO(knz): rename to TestApplicationServices. - TestTenants() []ApplicationLayerInterface - - // StartedDefaultTestTenant returns true if the server has started - // the service for the default test tenant. - StartedDefaultTestTenant() bool -} - -// StorageLayerInterface defines accessors to the storage layer of a -// test server. See ApplicationLayerInterface for the relevant -// application-level APIs. -type StorageLayerInterface interface { - // Node returns the server.Node as an interface{}. - Node() interface{} - - // NodeID returns the ID of this node within its cluster. - NodeID() roachpb.NodeID - - // StorageClusterID returns the storage cluster ID as understood by - // this node in the cluster. - StorageClusterID() uuid.UUID - - // GossipI returns the gossip used by the TestServer. - // The real return type is *gossip.Gossip. - GossipI() interface{} - - // SQLLivenessProvider returns the sqlliveness.Provider as an interface{}. - SQLLivenessProvider() interface{} - - // NodeLiveness exposes the NodeLiveness instance used by the TestServer as an - // interface{}. - NodeLiveness() interface{} - - // HeartbeatNodeLiveness heartbeats the server's NodeLiveness record. - HeartbeatNodeLiveness() error - - // NodeDialer exposes the NodeDialer instance used by the TestServer as an - // interface{}. - NodeDialer() interface{} - - // WriteSummaries records summaries of time-series data, which is required for - // any tests that query server stats. - WriteSummaries() error - - // GetFirstStoreID is a utility function returning the StoreID of the first - // store on this node. - GetFirstStoreID() roachpb.StoreID - - // GetStores returns the collection of stores from this TestServer's node. - // The return value is of type *kvserver.Stores. - GetStores() interface{} - - // Decommission idempotently sets the decommissioning flag for specified nodes. - Decommission(ctx context.Context, targetStatus livenesspb.MembershipStatus, nodeIDs []roachpb.NodeID) error - - // DecommissioningNodeMap returns a map of nodeIDs that are known to the - // server to be decommissioning. - DecommissioningNodeMap() map[roachpb.NodeID]interface{} - - // SplitRange splits the range containing splitKey. - SplitRange(splitKey roachpb.Key) (left roachpb.RangeDescriptor, right roachpb.RangeDescriptor, err error) - - // MergeRanges merges the range containing leftKey with the following adjacent - // range. - MergeRanges(leftKey roachpb.Key) (merged roachpb.RangeDescriptor, err error) - - // ExpectedInitialRangeCount returns the expected number of ranges that should - // be on the server after initial (asynchronous) splits have been completed, - // assuming no additional information is added outside of the normal bootstrap - // process. - ExpectedInitialRangeCount() (int, error) - - // ForceTableGC sends a GCRequest for the ranges corresponding to a table. - // - // An error will be returned if the same table name exists in multiple schemas - // inside the specified database. - ForceTableGC(ctx context.Context, database, table string, timestamp hlc.Timestamp) error - - // UpdateChecker returns the server's *diagnostics.UpdateChecker as an - // interface{}. The UpdateChecker periodically phones home to check for new - // updates that are available. - UpdateChecker() interface{} - - // ScratchRange splits off a range suitable to be used as KV scratch space. - // (it doesn't overlap system spans or SQL tables). - // - // Calling this multiple times is undefined (but see - // TestCluster.ScratchRange() which is idempotent). - ScratchRange() (roachpb.Key, error) - - // Engines returns the TestServer's engines. - Engines() []storage.Engine - - // MetricsRecorder periodically records node-level and store-level metrics. - MetricsRecorder() *status.MetricsRecorder - - // SpanConfigKVSubscriber returns the embedded spanconfig.KVSubscriber for - // the server. - SpanConfigKVSubscriber() interface{} - - // KVFlowController returns the embedded kvflowcontrol.Controller for the - // server. - KVFlowController() interface{} - - // KVFlowHandles returns the embedded kvflowcontrol.Handles for the server. - KVFlowHandles() interface{} - - // KvProber returns a *kvprober.Prober, which is useful when asserting the - //correctness of the prober from integration tests. - KvProber() *kvprober.Prober - - // TenantCapabilitiesReader retrieves a reference to the - // capabilities reader. - TenantCapabilitiesReader() tenantcapabilities.Reader -} - -// TestServerFactory encompasses the actual implementation of the shim -// service. -type TestServerFactory interface { - // New instantiates a test server. - New(params base.TestServerArgs) (interface{}, error) -} - var srvFactoryImpl TestServerFactory // InitTestServerFactory should be called once to provide the implementation diff --git a/pkg/testutils/serverutils/test_tenant_shim.go b/pkg/testutils/serverutils/test_tenant_shim.go index 32338504a50a..a8563113ce68 100644 --- a/pkg/testutils/serverutils/test_tenant_shim.go +++ b/pkg/testutils/serverutils/test_tenant_shim.go @@ -13,26 +13,7 @@ package serverutils -import ( - "context" - "net/http" - "net/url" - - "github.com/cockroachdb/cockroach/pkg/base" - "github.com/cockroachdb/cockroach/pkg/config" - "github.com/cockroachdb/cockroach/pkg/keys" - "github.com/cockroachdb/cockroach/pkg/kv" - "github.com/cockroachdb/cockroach/pkg/roachpb" - "github.com/cockroachdb/cockroach/pkg/rpc" - "github.com/cockroachdb/cockroach/pkg/security/username" - "github.com/cockroachdb/cockroach/pkg/server/serverpb" - "github.com/cockroachdb/cockroach/pkg/settings/cluster" - "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" - "github.com/cockroachdb/cockroach/pkg/util/hlc" - "github.com/cockroachdb/cockroach/pkg/util/log" - "github.com/cockroachdb/cockroach/pkg/util/stop" - "github.com/cockroachdb/cockroach/pkg/util/tracing" -) +import "net/url" type SessionType int @@ -67,248 +48,3 @@ func (t *TestURL) WithPath(path string) *TestURL { t.Path = newPath return t } - -// ApplicationLayerInterface defines accessors to the application -// layer of a test server. Tests written against this interface are -// effectively agnostic to whether they use a secondary tenant or not. -// This interface is implemented by server.Test{Tenant,Server}. -type ApplicationLayerInterface interface { - // SQLInstanceID is the ephemeral ID assigned to a running instance of the - // SQLServer. Each tenant can have zero or more running SQLServer instances. - SQLInstanceID() base.SQLInstanceID - - // AdvRPCAddr returns the server's advertised address. - AdvRPCAddr() string - - // AdvSQLAddr returns the server's advertised SQL address. - AdvSQLAddr() string - - // SQLAddr returns the tenant's SQL address. Note that for "shared-process - // tenants" (i.e. tenants created with TestServer.StartSharedProcessTenant), - // simply connecting to this address connects to the system tenant, not to - // this tenant. In order to connect to this tenant, - // "cluster:/" needs to be added to the connection - // string as the database name. - SQLAddr() string - - // HTTPAddr returns the tenant's http address. - HTTPAddr() string - - // RPCAddr returns the tenant's RPC address. - RPCAddr() string - - // DB returns a handle to the cluster's KV interface. - DB() *kv.DB - - // PGServer returns the tenant's *pgwire.Server as an interface{}. - PGServer() interface{} - - // PGPreServer returns the tenant's *pgwire.PreServeConnHandler as an interface{}. - PGPreServer() interface{} - - // DiagnosticsReporter returns the tenant's *diagnostics.Reporter as an - // interface{}. The DiagnosticsReporter periodically phones home to report - // diagnostics and usage. - DiagnosticsReporter() interface{} - - // StatusServer returns the tenant's *server.SQLStatusServer as an - // interface{}. - StatusServer() interface{} - - // TenantStatusServer returns the tenant's *server.TenantStatusServer as an - // interface{}. - TenantStatusServer() interface{} - - // HTTPAuthServer returns the authserver.Server as an interface{}. - HTTPAuthServer() interface{} - - // SQLServer returns the *sql.Server as an interface{}. - SQLServer() interface{} - - // DistSQLServer returns the *distsql.ServerImpl as an interface{}. - DistSQLServer() interface{} - - // SetDistSQLSpanResolver changes the SpanResolver used for DistSQL inside the - // server's executor. The argument must be a physicalplan.SpanResolver - // instance. - // - // This method exists because we cannot pass the fake span resolver with the - // server or cluster params: the fake span resolver needs the node IDs and - // addresses of the servers in a cluster, which are not available before we - // start the servers. - // - // It is the caller's responsibility to make sure no queries are being run - // with DistSQL at the same time. - SetDistSQLSpanResolver(spanResolver interface{}) - - // DistSenderI returns the *kvcoord.DistSender as an interface{}. - DistSenderI() interface{} - - // InternalDB returns an isql.DB as an interface{}. - InternalDB() interface{} - - // InternalExecutor returns a *sql.InternalExecutor as an interface{} (which - // also implements isql.Executor if the test cannot depend on sql). - InternalExecutor() interface{} - - // LeaseManager returns the *sql.LeaseManager as an interface{}. - LeaseManager() interface{} - - // JobRegistry returns the *jobs.Registry as an interface{}. - JobRegistry() interface{} - - // RPCContext returns the *rpc.Context used by the test tenant. - RPCContext() *rpc.Context - - // AnnotateCtx annotates a context. - AnnotateCtx(context.Context) context.Context - - // ExecutorConfig returns a copy of the tenant's ExecutorConfig. - // The real return type is sql.ExecutorConfig. - ExecutorConfig() interface{} - - // RangeFeedFactory returns the range feed factory used by the tenant. - // The real return type is *rangefeed.Factory. - RangeFeedFactory() interface{} - - // ClusterSettings returns the ClusterSettings shared by all components of - // this tenant. - ClusterSettings() *cluster.Settings - - // SettingsWatcher returns the *settingswatcher.SettingsWatcher used by the - // tenant server. - SettingsWatcher() interface{} - - // Stopper returns the stopper used by the tenant. - Stopper() *stop.Stopper - - // Clock returns the clock used by the tenant. - Clock() *hlc.Clock - - // SpanConfigKVAccessor returns the underlying spanconfig.KVAccessor as an - // interface{}. - SpanConfigKVAccessor() interface{} - - // SpanConfigReporter returns the underlying spanconfig.Reporter as an - // interface{}. - SpanConfigReporter() interface{} - - // SpanConfigReconciler returns the underlying spanconfig.Reconciler as an - // interface{}. - SpanConfigReconciler() interface{} - - // SpanConfigSQLTranslatorFactory returns the underlying - // spanconfig.SQLTranslatorFactory as an interface{}. - SpanConfigSQLTranslatorFactory() interface{} - - // SpanConfigSQLWatcher returns the underlying spanconfig.SQLWatcher as an - // interface{}. - SpanConfigSQLWatcher() interface{} - - // TestingKnobs returns the TestingKnobs in use by the test server. - TestingKnobs() *base.TestingKnobs - - // AmbientCtx retrieves the AmbientContext for this server, - // so that a test can instantiate additional one-off components - // using the same context details as the server. This should not - // be used in non-test code. - AmbientCtx() log.AmbientContext - - // AdminURL returns the URL for the admin UI. - AdminURL() *TestURL - - // GetUnauthenticatedHTTPClient returns an http client configured with the client TLS - // config required by the TestServer's configuration. - // Discourages implementer from using unauthenticated http connections - // with verbose method name. - GetUnauthenticatedHTTPClient() (http.Client, error) - - // GetAdminHTTPClient returns an http client which has been - // authenticated to access Admin API methods (via a cookie). - // The user has admin privileges. - GetAdminHTTPClient() (http.Client, error) - - // GetAuthenticatedHTTPClient returns an http client which has been - // authenticated to access Admin API methods (via a cookie). - GetAuthenticatedHTTPClient(isAdmin bool, sessionType SessionType) (http.Client, error) - - // GetAuthenticatedHTTPClientAndCookie returns an http client which - // has been authenticated to access Admin API methods and - // the corresponding session cookie. - GetAuthenticatedHTTPClientAndCookie( - authUser username.SQLUsername, isAdmin bool, session SessionType, - ) (http.Client, *serverpb.SessionCookie, error) - - // GetAuthSession returns a byte array containing a valid auth - // session. - GetAuthSession(isAdmin bool) (*serverpb.SessionCookie, error) - - // CreateAuthUser is exported for use in tests. - CreateAuthUser(userName username.SQLUsername, isAdmin bool) error - - // DrainClients shuts down client connections. - DrainClients(ctx context.Context) error - - // SystemConfigProvider provides access to the system config. - SystemConfigProvider() config.SystemConfigProvider - - // MustGetSQLCounter returns the value of a counter metric from the tenant's - // SQL Executor. Runs in O(# of metrics) time, which is fine for test code. - MustGetSQLCounter(name string) int64 - // MustGetSQLNetworkCounter returns the value of a counter metric from the - // tenant's SQL server. Runs in O(# of metrics) time, which is fine for test - // code. - MustGetSQLNetworkCounter(name string) int64 - - // Codec returns this tenant's codec (or keys.SystemSQLCodec if this is the - // system tenant). - Codec() keys.SQLCodec - - // RangeDescIteratorFactory returns the underlying rangedesc.IteratorFactory - // as an interface{}. - RangeDescIteratorFactory() interface{} - - // Tracer returns a reference to the tenant's Tracer. - Tracer() *tracing.Tracer - - // TracerI is the same as Tracer but returns an interface{}. - TracerI() interface{} - - // MigrationServer returns the tenant's migration server, which is used in - // upgrade testing. - MigrationServer() interface{} - - // CollectionFactory returns a *descs.CollectionFactory. - CollectionFactory() interface{} - - // SystemTableIDResolver returns a catalog.SystemTableIDResolver. - SystemTableIDResolver() interface{} - - // QueryDatabaseID provides access to the database name-to-ID conversion function - // for use in API tests. - QueryDatabaseID( - ctx context.Context, userName username.SQLUsername, dbName string, - ) (descpb.ID, error) - - // QueryTableID provides access to the table name-to-ID conversion function - // for use in API tests. - QueryTableID( - ctx context.Context, userName username.SQLUsername, dbName, tbName string, - ) (descpb.ID, error) - - // StatsForSpans provides access to the span stats inspection function - // for use in API tests. - StatsForSpan( - ctx context.Context, span roachpb.Span, - ) (*serverpb.TableStatsResponse, error) - - // ForceTableGC sends a GCRequest for the ranges corresponding to a table. - // - // An error will be returned if the same table name exists in multiple schemas - // inside the specified database. - ForceTableGC(ctx context.Context, database, table string, timestamp hlc.Timestamp) error - - // TODO(irfansharif): We'd benefit from an API to construct a *gosql.DB, or - // better yet, a *sqlutils.SQLRunner. We use it all the time, constructing - // it by hand each time. -}