github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/server/testserver.go (about) 1 // Copyright 2014 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package server 12 13 import ( 14 "context" 15 "fmt" 16 "net" 17 "net/http" 18 "net/http/cookiejar" 19 "net/url" 20 "path/filepath" 21 "sync" 22 "time" 23 24 "github.com/cenkalti/backoff" 25 circuit "github.com/cockroachdb/circuitbreaker" 26 "github.com/cockroachdb/cockroach/pkg/base" 27 "github.com/cockroachdb/cockroach/pkg/config" 28 "github.com/cockroachdb/cockroach/pkg/config/zonepb" 29 "github.com/cockroachdb/cockroach/pkg/gossip" 30 "github.com/cockroachdb/cockroach/pkg/gossip/resolver" 31 "github.com/cockroachdb/cockroach/pkg/jobs" 32 "github.com/cockroachdb/cockroach/pkg/keys" 33 "github.com/cockroachdb/cockroach/pkg/kv" 34 "github.com/cockroachdb/cockroach/pkg/kv/kvclient/kvcoord" 35 "github.com/cockroachdb/cockroach/pkg/kv/kvserver" 36 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts" 37 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts/ptpb" 38 "github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts/ptprovider" 39 "github.com/cockroachdb/cockroach/pkg/roachpb" 40 "github.com/cockroachdb/cockroach/pkg/rpc" 41 "github.com/cockroachdb/cockroach/pkg/rpc/nodedialer" 42 "github.com/cockroachdb/cockroach/pkg/security" 43 "github.com/cockroachdb/cockroach/pkg/server/serverpb" 44 "github.com/cockroachdb/cockroach/pkg/server/status" 45 "github.com/cockroachdb/cockroach/pkg/settings/cluster" 46 "github.com/cockroachdb/cockroach/pkg/sql" 47 "github.com/cockroachdb/cockroach/pkg/sql/pgwire" 48 "github.com/cockroachdb/cockroach/pkg/sql/physicalplan" 49 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 50 "github.com/cockroachdb/cockroach/pkg/sql/sqlbase" 51 "github.com/cockroachdb/cockroach/pkg/sqlmigrations" 52 "github.com/cockroachdb/cockroach/pkg/storage" 53 "github.com/cockroachdb/cockroach/pkg/storage/cloud" 54 "github.com/cockroachdb/cockroach/pkg/storage/enginepb" 55 "github.com/cockroachdb/cockroach/pkg/ts" 56 "github.com/cockroachdb/cockroach/pkg/util" 57 "github.com/cockroachdb/cockroach/pkg/util/hlc" 58 "github.com/cockroachdb/cockroach/pkg/util/metric" 59 "github.com/cockroachdb/cockroach/pkg/util/netutil" 60 "github.com/cockroachdb/cockroach/pkg/util/stop" 61 "github.com/cockroachdb/errors" 62 "github.com/gogo/protobuf/proto" 63 ) 64 65 const ( 66 // TestUser is a fixed user used in unittests. 67 // It has valid embedded client certs. 68 TestUser = "testuser" 69 ) 70 71 // makeTestConfig returns a config for testing. It overrides the 72 // Certs with the test certs directory. 73 // We need to override the certs loader. 74 func makeTestConfig(st *cluster.Settings) Config { 75 return Config{ 76 BaseConfig: makeTestBaseConfig(st), 77 KVConfig: makeTestKVConfig(), 78 SQLConfig: makeTestSQLConfig(st, roachpb.SystemTenantID), 79 } 80 } 81 82 func makeTestBaseConfig(st *cluster.Settings) BaseConfig { 83 baseCfg := MakeBaseConfig(st) 84 // Test servers start in secure mode by default. 85 baseCfg.Insecure = false 86 // Configure test storage engine. 87 baseCfg.StorageEngine = storage.DefaultStorageEngine 88 // Resolve the storage engine to a specific type if it's the default value. 89 if baseCfg.StorageEngine == enginepb.EngineTypeDefault { 90 baseCfg.StorageEngine = enginepb.EngineTypePebble 91 } 92 // Load test certs. In addition, the tests requiring certs 93 // need to call security.SetAssetLoader(securitytest.EmbeddedAssets) 94 // in their init to mock out the file system calls for calls to AssetFS, 95 // which has the test certs compiled in. Typically this is done 96 // once per package, in main_test.go. 97 baseCfg.SSLCertsDir = security.EmbeddedCertsDir 98 // Addr defaults to localhost with port set at time of call to 99 // Start() to an available port. May be overridden later (as in 100 // makeTestConfigFromParams). Call TestServer.ServingRPCAddr() and 101 // .ServingSQLAddr() for the full address (including bound port). 102 baseCfg.Addr = util.TestAddr.String() 103 baseCfg.SQLAddr = util.TestAddr.String() 104 baseCfg.AdvertiseAddr = util.TestAddr.String() 105 baseCfg.SQLAdvertiseAddr = util.TestAddr.String() 106 baseCfg.SplitListenSQL = true 107 baseCfg.HTTPAddr = util.TestAddr.String() 108 // Set standard user for intra-cluster traffic. 109 baseCfg.User = security.NodeUser 110 return baseCfg 111 } 112 113 func makeTestKVConfig() KVConfig { 114 kvCfg := MakeKVConfig(base.DefaultTestStoreSpec) 115 // Enable web session authentication. 116 kvCfg.EnableWebSessionAuthentication = true 117 return kvCfg 118 } 119 120 func makeTestSQLConfig(st *cluster.Settings, tenID roachpb.TenantID) SQLConfig { 121 sqlCfg := MakeSQLConfig(tenID, base.DefaultTestTempStorageConfig(st)) 122 // Configure the default in-memory temp storage for all tests unless 123 // otherwise configured. 124 sqlCfg.TempStorageConfig = base.DefaultTestTempStorageConfig(st) 125 return sqlCfg 126 } 127 128 // makeTestConfigFromParams creates a Config from a TestServerParams. 129 func makeTestConfigFromParams(params base.TestServerArgs) Config { 130 st := params.Settings 131 if params.Settings == nil { 132 st = cluster.MakeClusterSettings() 133 } 134 st.ExternalIODir = params.ExternalIODir 135 cfg := makeTestConfig(st) 136 cfg.TestingKnobs = params.Knobs 137 cfg.RaftConfig = params.RaftConfig 138 cfg.RaftConfig.SetDefaults() 139 if params.LeaseManagerConfig != nil { 140 cfg.LeaseManagerConfig = params.LeaseManagerConfig 141 } else { 142 cfg.LeaseManagerConfig = base.NewLeaseManagerConfig() 143 } 144 if params.JoinAddr != "" { 145 cfg.JoinList = []string{params.JoinAddr} 146 } 147 cfg.ClusterName = params.ClusterName 148 cfg.Insecure = params.Insecure 149 cfg.SocketFile = params.SocketFile 150 cfg.RetryOptions = params.RetryOptions 151 cfg.Locality = params.Locality 152 if knobs := params.Knobs.Store; knobs != nil { 153 if mo := knobs.(*kvserver.StoreTestingKnobs).MaxOffset; mo != 0 { 154 cfg.MaxOffset = MaxOffsetType(mo) 155 } 156 } 157 if params.Knobs.Server != nil { 158 if zoneConfig := params.Knobs.Server.(*TestingKnobs).DefaultZoneConfigOverride; zoneConfig != nil { 159 cfg.DefaultZoneConfig = *zoneConfig 160 } 161 if systemZoneConfig := params.Knobs.Server.(*TestingKnobs).DefaultSystemZoneConfigOverride; systemZoneConfig != nil { 162 cfg.DefaultSystemZoneConfig = *systemZoneConfig 163 } 164 } 165 if params.ScanInterval != 0 { 166 cfg.ScanInterval = params.ScanInterval 167 } 168 if params.ScanMinIdleTime != 0 { 169 cfg.ScanMinIdleTime = params.ScanMinIdleTime 170 } 171 if params.ScanMaxIdleTime != 0 { 172 cfg.ScanMaxIdleTime = params.ScanMaxIdleTime 173 } 174 if params.SSLCertsDir != "" { 175 cfg.SSLCertsDir = params.SSLCertsDir 176 } 177 if params.TimeSeriesQueryWorkerMax != 0 { 178 cfg.TimeSeriesServerConfig.QueryWorkerMax = params.TimeSeriesQueryWorkerMax 179 } 180 if params.TimeSeriesQueryMemoryBudget != 0 { 181 cfg.TimeSeriesServerConfig.QueryMemoryMax = params.TimeSeriesQueryMemoryBudget 182 } 183 if params.DisableEventLog { 184 cfg.EventLogEnabled = false 185 } 186 if params.SQLMemoryPoolSize != 0 { 187 cfg.MemoryPoolSize = params.SQLMemoryPoolSize 188 } 189 if params.CacheSize != 0 { 190 cfg.CacheSize = params.CacheSize 191 } 192 193 if params.JoinAddr != "" { 194 cfg.JoinList = []string{params.JoinAddr} 195 } 196 if cfg.Insecure { 197 // Whenever we can (i.e. in insecure mode), use IsolatedTestAddr 198 // to prevent issues that can occur when running a test under 199 // stress. 200 cfg.Addr = util.IsolatedTestAddr.String() 201 cfg.AdvertiseAddr = util.IsolatedTestAddr.String() 202 cfg.SQLAddr = util.IsolatedTestAddr.String() 203 cfg.SQLAdvertiseAddr = util.IsolatedTestAddr.String() 204 cfg.HTTPAddr = util.IsolatedTestAddr.String() 205 } else { 206 cfg.Addr = util.TestAddr.String() 207 cfg.AdvertiseAddr = util.TestAddr.String() 208 cfg.SQLAddr = util.TestAddr.String() 209 cfg.SQLAdvertiseAddr = util.TestAddr.String() 210 cfg.HTTPAddr = util.TestAddr.String() 211 } 212 if params.Addr != "" { 213 cfg.Addr = params.Addr 214 cfg.AdvertiseAddr = params.Addr 215 } 216 if params.SQLAddr != "" { 217 cfg.SQLAddr = params.SQLAddr 218 cfg.SQLAdvertiseAddr = params.SQLAddr 219 } 220 if params.HTTPAddr != "" { 221 cfg.HTTPAddr = params.HTTPAddr 222 } 223 cfg.DisableTLSForHTTP = params.DisableTLSForHTTP 224 if params.DisableWebSessionAuthentication { 225 cfg.EnableWebSessionAuthentication = false 226 } 227 228 // Ensure we have the correct number of engines. Add in-memory ones where 229 // needed. There must be at least one store/engine. 230 if len(params.StoreSpecs) == 0 { 231 params.StoreSpecs = []base.StoreSpec{base.DefaultTestStoreSpec} 232 } 233 // Validate the store specs. 234 for _, storeSpec := range params.StoreSpecs { 235 if storeSpec.InMemory { 236 if storeSpec.Size.Percent > 0 { 237 panic(fmt.Sprintf("test server does not yet support in memory stores based on percentage of total memory: %s", storeSpec)) 238 } 239 } else { 240 // The default store spec is in-memory, so if this one is on-disk then 241 // one specific test must have requested it. A failure is returned if 242 // the Path field is empty, which means the test is then forced to pick 243 // the dir (and the test is then responsible for cleaning it up, not 244 // TestServer). 245 246 // HeapProfileDirName and GoroutineDumpDirName are normally set by the 247 // cli, once, to the path of the first store. 248 if cfg.HeapProfileDirName == "" { 249 cfg.HeapProfileDirName = filepath.Join(storeSpec.Path, "logs", base.HeapProfileDir) 250 } 251 if cfg.GoroutineDumpDirName == "" { 252 cfg.GoroutineDumpDirName = filepath.Join(storeSpec.Path, "logs", base.GoroutineDumpDir) 253 } 254 } 255 } 256 cfg.Stores = base.StoreSpecList{Specs: params.StoreSpecs} 257 if params.TempStorageConfig.InMemory || params.TempStorageConfig.Path != "" { 258 cfg.TempStorageConfig = params.TempStorageConfig 259 } 260 261 if cfg.TestingKnobs.Store == nil { 262 cfg.TestingKnobs.Store = &kvserver.StoreTestingKnobs{} 263 } 264 cfg.TestingKnobs.Store.(*kvserver.StoreTestingKnobs).SkipMinSizeCheck = true 265 return cfg 266 } 267 268 // A TestServer encapsulates an in-memory instantiation of a cockroach node with 269 // a single store. It provides tests with access to Server internals. 270 // Where possible, it should be used through the 271 // testingshim.TestServerInterface. 272 // 273 // Example usage of a TestServer: 274 // 275 // s, db, kvDB := serverutils.StartServer(t, base.TestServerArgs{}) 276 // defer s.Stopper().Stop() 277 // // If really needed, in tests that can depend on server, downcast to 278 // // server.TestServer: 279 // ts := s.(*server.TestServer) 280 // 281 type TestServer struct { 282 Cfg *Config 283 // server is the embedded Cockroach server struct. 284 *Server 285 // authClient is an http.Client that has been authenticated to access the 286 // Admin UI. 287 authClient [2]struct { 288 httpClient http.Client 289 cookie *serverpb.SessionCookie 290 once sync.Once 291 err error 292 } 293 } 294 295 // Node returns the Node as an interface{}. 296 func (ts *TestServer) Node() interface{} { 297 return ts.node 298 } 299 300 // Stopper returns the embedded server's Stopper. 301 func (ts *TestServer) Stopper() *stop.Stopper { 302 return ts.stopper 303 } 304 305 // GossipI is part of TestServerInterface. 306 func (ts *TestServer) GossipI() interface{} { 307 return ts.Gossip() 308 } 309 310 // Gossip is like GossipI but returns the real type instead of interface{}. 311 func (ts *TestServer) Gossip() *gossip.Gossip { 312 if ts != nil { 313 return ts.gossip 314 } 315 return nil 316 } 317 318 // Clock returns the clock used by the TestServer. 319 func (ts *TestServer) Clock() *hlc.Clock { 320 if ts != nil { 321 return ts.clock 322 } 323 return nil 324 } 325 326 // JobRegistry returns the *jobs.Registry as an interface{}. 327 func (ts *TestServer) JobRegistry() interface{} { 328 if ts != nil { 329 return ts.sqlServer.jobRegistry 330 } 331 return nil 332 } 333 334 // MigrationManager returns the *sqlmigrations.Manager as an interface{}. 335 func (ts *TestServer) MigrationManager() interface{} { 336 if ts != nil { 337 return ts.sqlServer.migMgr 338 } 339 return nil 340 } 341 342 // RPCContext returns the rpc context used by the TestServer. 343 func (ts *TestServer) RPCContext() *rpc.Context { 344 if ts != nil { 345 return ts.rpcContext 346 } 347 return nil 348 } 349 350 // TsDB returns the ts.DB instance used by the TestServer. 351 func (ts *TestServer) TsDB() *ts.DB { 352 if ts != nil { 353 return ts.tsDB 354 } 355 return nil 356 } 357 358 // DB returns the client.DB instance used by the TestServer. 359 func (ts *TestServer) DB() *kv.DB { 360 if ts != nil { 361 return ts.db 362 } 363 return nil 364 } 365 366 // PGServer returns the pgwire.Server used by the TestServer. 367 func (ts *TestServer) PGServer() *pgwire.Server { 368 if ts != nil { 369 return ts.sqlServer.pgServer 370 } 371 return nil 372 } 373 374 // RaftTransport returns the RaftTransport used by the TestServer. 375 func (ts *TestServer) RaftTransport() *kvserver.RaftTransport { 376 if ts != nil { 377 return ts.raftTransport 378 } 379 return nil 380 } 381 382 // Start starts the TestServer by bootstrapping an in-memory store 383 // (defaults to maximum of 100M). The server is started, launching the 384 // node RPC server and all HTTP endpoints. Use the value of 385 // TestServer.ServingRPCAddr() after Start() for client connections. 386 // Use TestServer.Stopper().Stop() to shutdown the server after the test 387 // completes. 388 func (ts *TestServer) Start(params base.TestServerArgs) error { 389 if ts.Cfg == nil { 390 panic("Cfg not set") 391 } 392 393 if params.Stopper == nil { 394 params.Stopper = stop.NewStopper() 395 } 396 397 if !params.PartOfCluster { 398 ts.Cfg.DefaultZoneConfig.NumReplicas = proto.Int32(1) 399 } 400 401 ctx := context.Background() 402 403 // Needs to be called before NewServer to ensure resolvers are initialized. 404 if err := ts.Cfg.InitNode(ctx); err != nil { 405 return err 406 } 407 408 var err error 409 ts.Server, err = NewServer(*ts.Cfg, params.Stopper) 410 if err != nil { 411 return err 412 } 413 414 // Create a breaker which never trips and never backs off to avoid 415 // introducing timing-based flakes. 416 ts.rpcContext.BreakerFactory = func() *circuit.Breaker { 417 return circuit.NewBreakerWithOptions(&circuit.Options{ 418 BackOff: &backoff.ZeroBackOff{}, 419 }) 420 } 421 422 // Our context must be shared with our server. 423 ts.Cfg = &ts.Server.cfg 424 425 return ts.Server.Start(ctx) 426 } 427 428 type dummyProtectedTSProvider struct { 429 protectedts.Provider 430 } 431 432 func (d dummyProtectedTSProvider) Protect(context.Context, *kv.Txn, *ptpb.Record) error { 433 return errors.New("fake protectedts.Provider") 434 } 435 436 // TODO(asubiotto): Jobs don't play well with a weird node ID in a multitenant 437 // environment, so a node ID of 1 is used here to get tests to pass. Fixing 438 // this is tracked in https://github.com/cockroachdb/cockroach/issues/47892. 439 const fakeNodeID = roachpb.NodeID(1) 440 441 func makeSQLServerArgs( 442 stopper *stop.Stopper, kvClusterName string, baseCfg BaseConfig, sqlCfg SQLConfig, 443 ) sqlServerArgs { 444 st := baseCfg.Settings 445 baseCfg.AmbientCtx.AddLogTag("sql", nil) 446 // TODO(tbg): this is needed so that the RPC heartbeats between the testcluster 447 // and this tenant work. 448 // 449 // TODO(tbg): address this when we introduce the real tenant RPCs in: 450 // https://github.com/cockroachdb/cockroach/issues/47898 451 baseCfg.ClusterName = kvClusterName 452 453 clock := hlc.NewClock(hlc.UnixNano, time.Duration(baseCfg.MaxOffset)) 454 455 var rpcTestingKnobs rpc.ContextTestingKnobs 456 if p, ok := baseCfg.TestingKnobs.Server.(*TestingKnobs); ok { 457 rpcTestingKnobs = p.ContextTestingKnobs 458 } 459 rpcContext := rpc.NewContextWithTestingKnobs( 460 baseCfg.AmbientCtx, 461 baseCfg.Config, 462 clock, 463 stopper, 464 st, 465 rpcTestingKnobs, 466 ) 467 468 // TODO(tbg): expose this registry via prometheus. See: 469 // https://github.com/cockroachdb/cockroach/issues/47905 470 registry := metric.NewRegistry() 471 472 var dsKnobs kvcoord.ClientTestingKnobs 473 if dsKnobsP, ok := baseCfg.TestingKnobs.DistSQL.(*kvcoord.ClientTestingKnobs); ok { 474 dsKnobs = *dsKnobsP 475 } 476 rpcRetryOptions := base.DefaultRetryOptions() 477 478 // TODO(nvb): this use of Gossip needs to go. Tracked in: 479 // https://github.com/cockroachdb/cockroach/issues/47909 480 var g *gossip.Gossip 481 { 482 var nodeID base.NodeIDContainer 483 nodeID.Set(context.Background(), fakeNodeID) 484 var clusterID base.ClusterIDContainer 485 dummyGossipGRPC := rpc.NewServer(rpcContext) // never Serve()s anything 486 g = gossip.New( 487 baseCfg.AmbientCtx, 488 &clusterID, 489 &nodeID, 490 rpcContext, 491 dummyGossipGRPC, 492 stopper, 493 registry, 494 baseCfg.Locality, 495 &baseCfg.DefaultZoneConfig, 496 ) 497 } 498 499 nodeDialer := nodedialer.New( 500 rpcContext, 501 gossip.AddressResolver(g), // TODO(nvb): break gossip dep 502 ) 503 dsCfg := kvcoord.DistSenderConfig{ 504 AmbientCtx: baseCfg.AmbientCtx, 505 Settings: st, 506 Clock: clock, 507 RPCRetryOptions: &rpcRetryOptions, 508 RPCContext: rpcContext, 509 RangeDescriptorDB: nil, // use DistSender itself 510 NodeDialer: nodeDialer, 511 TestingKnobs: dsKnobs, 512 } 513 ds := kvcoord.NewDistSender(dsCfg, g) 514 515 var clientKnobs kvcoord.ClientTestingKnobs 516 if p, ok := baseCfg.TestingKnobs.KVClient.(*kvcoord.ClientTestingKnobs); ok { 517 clientKnobs = *p 518 } 519 520 txnMetrics := kvcoord.MakeTxnMetrics(baseCfg.HistogramWindowInterval()) 521 registry.AddMetricStruct(txnMetrics) 522 tcsFactory := kvcoord.NewTxnCoordSenderFactory( 523 kvcoord.TxnCoordSenderFactoryConfig{ 524 AmbientCtx: baseCfg.AmbientCtx, 525 Settings: st, 526 Clock: clock, 527 Stopper: stopper, 528 HeartbeatInterval: base.DefaultTxnHeartbeatInterval, 529 Linearizable: false, 530 Metrics: txnMetrics, 531 TestingKnobs: clientKnobs, 532 }, 533 ds, 534 ) 535 db := kv.NewDB( 536 baseCfg.AmbientCtx, 537 tcsFactory, 538 clock, 539 ) 540 541 circularInternalExecutor := &sql.InternalExecutor{} 542 // Protected timestamps won't be available (at first) in multi-tenant 543 // clusters. 544 var protectedTSProvider protectedts.Provider 545 { 546 pp, err := ptprovider.New(ptprovider.Config{ 547 DB: db, 548 InternalExecutor: circularInternalExecutor, 549 Settings: st, 550 }) 551 if err != nil { 552 panic(err) 553 } 554 protectedTSProvider = dummyProtectedTSProvider{pp} 555 } 556 557 dummyRecorder := &status.MetricsRecorder{} 558 559 var c base.NodeIDContainer 560 c.Set(context.Background(), fakeNodeID) 561 const sqlInstanceID = base.SQLInstanceID(10001) 562 idContainer := base.NewSQLIDContainer(sqlInstanceID, &c, false /* exposed */) 563 564 // We don't need this for anything except some services that want a gRPC 565 // server to register against (but they'll never get RPCs at the time of 566 // writing): the blob service and DistSQL. 567 dummyRPCServer := rpc.NewServer(rpcContext) 568 noStatusServer := serverpb.MakeOptionalStatusServer(nil) 569 return sqlServerArgs{ 570 sqlServerOptionalArgs: sqlServerOptionalArgs{ 571 rpcContext: rpcContext, 572 distSender: ds, 573 statusServer: noStatusServer, 574 nodeLiveness: sqlbase.MakeOptionalNodeLiveness(nil), 575 gossip: gossip.MakeUnexposedGossip(g), 576 nodeDialer: nodeDialer, 577 grpcServer: dummyRPCServer, 578 recorder: dummyRecorder, 579 isMeta1Leaseholder: func(timestamp hlc.Timestamp) (bool, error) { 580 return false, errors.New("isMeta1Leaseholder is not available to secondary tenants") 581 }, 582 nodeIDContainer: idContainer, 583 externalStorage: func(ctx context.Context, dest roachpb.ExternalStorage) (cloud.ExternalStorage, error) { 584 return nil, errors.New("external storage is not available to secondary tenants") 585 }, 586 externalStorageFromURI: func(ctx context.Context, uri string) (cloud.ExternalStorage, error) { 587 return nil, errors.New("external uri storage is not available to secondary tenants") 588 }, 589 }, 590 SQLConfig: &sqlCfg, 591 BaseConfig: &baseCfg, 592 stopper: stopper, 593 clock: clock, 594 runtime: status.NewRuntimeStatSampler(context.Background(), clock), 595 db: db, 596 registry: registry, 597 sessionRegistry: sql.NewSessionRegistry(), 598 circularInternalExecutor: circularInternalExecutor, 599 circularJobRegistry: &jobs.Registry{}, 600 protectedtsProvider: protectedTSProvider, 601 } 602 } 603 604 // StartTenant starts a SQL tenant communicating with this TestServer. 605 func (ts *TestServer) StartTenant(params base.TestTenantArgs) (pgAddr string, _ error) { 606 ctx := context.Background() 607 608 if _, err := ts.InternalExecutor().(*sql.InternalExecutor).Exec( 609 ctx, "testserver-create-tenant", nil /* txn */, fmt.Sprintf("SELECT crdb_internal.create_tenant(%d)", params.TenantID.ToUint64()), 610 ); err != nil { 611 return "", err 612 } 613 614 st := cluster.MakeTestingClusterSettings() 615 sqlCfg := makeTestSQLConfig(st, params.TenantID) 616 baseCfg := makeTestBaseConfig(st) 617 if params.AllowSettingClusterSettings { 618 baseCfg.TestingKnobs.TenantTestingKnobs = &sql.TenantTestingKnobs{ 619 ClusterSettingsUpdater: st.MakeUpdater(), 620 } 621 } 622 return startTenant( 623 ctx, 624 ts.Stopper(), 625 ts.Cfg.ClusterName, 626 ts.RPCAddr(), 627 baseCfg, 628 sqlCfg, 629 ) 630 } 631 632 func startTenant( 633 ctx context.Context, 634 stopper *stop.Stopper, 635 kvClusterName string, // NB: gone after https://github.com/cockroachdb/cockroach/issues/42519 636 tsRPCAddr string, 637 baseCfg BaseConfig, 638 sqlCfg SQLConfig, 639 ) (pgAddr string, _ error) { 640 args := makeSQLServerArgs(stopper, kvClusterName, baseCfg, sqlCfg) 641 s, err := newSQLServer(ctx, args) 642 if err != nil { 643 return "", err 644 } 645 646 // NB: this should no longer be necessary after #47902. Right now it keeps 647 // the tenant from crashing. 648 // 649 // NB: this NodeID is actually used by the DistSQL planner. 650 s.execCfg.DistSQLPlanner.SetNodeDesc(roachpb.NodeDescriptor{NodeID: fakeNodeID}) 651 652 connManager := netutil.MakeServer( 653 args.stopper, 654 // The SQL server only uses connManager.ServeWith. The both below 655 // are unused. 656 nil, // tlsConfig 657 nil, // handler 658 ) 659 660 pgL, err := net.Listen("tcp", args.Config.SQLAddr) 661 if err != nil { 662 return "", err 663 } 664 args.stopper.RunWorker(ctx, func(ctx context.Context) { 665 <-args.stopper.ShouldQuiesce() 666 // NB: we can't do this as a Closer because (*Server).ServeWith is 667 // running in a worker and usually sits on accept(pgL) which unblocks 668 // only when pgL closes. In other words, pgL needs to close when 669 // quiescing starts to allow that worker to shut down. 670 _ = pgL.Close() 671 }) 672 673 const ( 674 socketFile = "" // no unix socket 675 ) 676 orphanedLeasesTimeThresholdNanos := args.clock.Now().WallTime 677 678 { 679 rsvlr, err := resolver.NewResolver(tsRPCAddr) 680 if err != nil { 681 return "", err 682 } 683 // NB: gossip server is not bound to any address, so the advertise addr does 684 // not matter. 685 args.gossip.Start(pgL.Addr(), []resolver.Resolver{rsvlr}) 686 } 687 688 if err := s.start(ctx, 689 args.stopper, 690 args.TestingKnobs, 691 connManager, 692 pgL, 693 socketFile, 694 orphanedLeasesTimeThresholdNanos, 695 ); err != nil { 696 return "", err 697 } 698 return pgL.Addr().String(), nil 699 } 700 701 // ExpectedInitialRangeCount returns the expected number of ranges that should 702 // be on the server after initial (asynchronous) splits have been completed, 703 // assuming no additional information is added outside of the normal bootstrap 704 // process. 705 func (ts *TestServer) ExpectedInitialRangeCount() (int, error) { 706 return ExpectedInitialRangeCount(ts.DB(), &ts.cfg.DefaultZoneConfig, &ts.cfg.DefaultSystemZoneConfig) 707 } 708 709 // ExpectedInitialRangeCount returns the expected number of ranges that should 710 // be on the server after bootstrap. 711 func ExpectedInitialRangeCount( 712 db *kv.DB, defaultZoneConfig *zonepb.ZoneConfig, defaultSystemZoneConfig *zonepb.ZoneConfig, 713 ) (int, error) { 714 descriptorIDs, err := sqlmigrations.ExpectedDescriptorIDs( 715 context.Background(), db, keys.SystemSQLCodec, defaultZoneConfig, defaultSystemZoneConfig, 716 ) 717 if err != nil { 718 return 0, err 719 } 720 721 // System table splits occur at every possible table boundary between the end 722 // of the system config ID space (keys.MaxSystemConfigDescID) and the system 723 // table with the maximum ID (maxSystemDescriptorID), even when an ID within 724 // the span does not have an associated descriptor. 725 maxSystemDescriptorID := descriptorIDs[0] 726 for _, descID := range descriptorIDs { 727 if descID > maxSystemDescriptorID && descID <= keys.MaxReservedDescID { 728 maxSystemDescriptorID = descID 729 } 730 } 731 systemTableSplits := int(maxSystemDescriptorID - keys.MaxSystemConfigDescID) 732 733 // `n` splits create `n+1` ranges. 734 return len(config.StaticSplits()) + systemTableSplits + 1, nil 735 } 736 737 // Stores returns the collection of stores from this TestServer's node. 738 func (ts *TestServer) Stores() *kvserver.Stores { 739 return ts.node.stores 740 } 741 742 // GetStores is part of TestServerInterface. 743 func (ts *TestServer) GetStores() interface{} { 744 return ts.node.stores 745 } 746 747 // ClusterSettings returns the ClusterSettings. 748 func (ts *TestServer) ClusterSettings() *cluster.Settings { 749 return ts.Cfg.Settings 750 } 751 752 // Engines returns the TestServer's engines. 753 func (ts *TestServer) Engines() []storage.Engine { 754 return ts.engines 755 } 756 757 // ServingRPCAddr returns the server's RPC address. Should be used by clients. 758 func (ts *TestServer) ServingRPCAddr() string { 759 return ts.cfg.AdvertiseAddr 760 } 761 762 // ServingSQLAddr returns the server's SQL address. Should be used by clients. 763 func (ts *TestServer) ServingSQLAddr() string { 764 return ts.cfg.SQLAdvertiseAddr 765 } 766 767 // HTTPAddr returns the server's HTTP address. Should be used by clients. 768 func (ts *TestServer) HTTPAddr() string { 769 return ts.cfg.HTTPAddr 770 } 771 772 // RPCAddr returns the server's listening RPC address. 773 // Note: use ServingRPCAddr() instead unless there is a specific reason not to. 774 func (ts *TestServer) RPCAddr() string { 775 return ts.cfg.Addr 776 } 777 778 // DrainClients exports the drainClients() method for use by tests. 779 func (ts *TestServer) DrainClients(ctx context.Context) error { 780 return ts.drainClients(ctx, nil /* reporter */) 781 } 782 783 // SQLAddr returns the server's listening SQL address. 784 // Note: use ServingSQLAddr() instead unless there is a specific reason not to. 785 func (ts *TestServer) SQLAddr() string { 786 return ts.cfg.SQLAddr 787 } 788 789 // WriteSummaries implements TestServerInterface. 790 func (ts *TestServer) WriteSummaries() error { 791 return ts.node.writeNodeStatus(context.TODO(), time.Hour) 792 } 793 794 // AdminURL implements TestServerInterface. 795 func (ts *TestServer) AdminURL() string { 796 return ts.Cfg.AdminURL().String() 797 } 798 799 // GetHTTPClient implements TestServerInterface. 800 func (ts *TestServer) GetHTTPClient() (http.Client, error) { 801 return ts.Cfg.GetHTTPClient() 802 } 803 804 const authenticatedUserName = "authentic_user" 805 const authenticatedUserNameNoAdmin = "authentic_user_noadmin" 806 807 // GetAdminAuthenticatedHTTPClient implements the TestServerInterface. 808 func (ts *TestServer) GetAdminAuthenticatedHTTPClient() (http.Client, error) { 809 httpClient, _, err := ts.getAuthenticatedHTTPClientAndCookie(authenticatedUserName, true) 810 return httpClient, err 811 } 812 813 // GetAuthenticatedHTTPClient implements the TestServerInterface. 814 func (ts *TestServer) GetAuthenticatedHTTPClient(isAdmin bool) (http.Client, error) { 815 authUser := authenticatedUserName 816 if !isAdmin { 817 authUser = authenticatedUserNameNoAdmin 818 } 819 httpClient, _, err := ts.getAuthenticatedHTTPClientAndCookie(authUser, isAdmin) 820 return httpClient, err 821 } 822 823 func (ts *TestServer) getAuthenticatedHTTPClientAndCookie( 824 authUser string, isAdmin bool, 825 ) (http.Client, *serverpb.SessionCookie, error) { 826 authIdx := 0 827 if isAdmin { 828 authIdx = 1 829 } 830 authClient := &ts.authClient[authIdx] 831 authClient.once.Do(func() { 832 // Create an authentication session for an arbitrary admin user. 833 authClient.err = func() error { 834 // The user needs to exist as the admin endpoints will check its role. 835 if err := ts.createAuthUser(authUser, isAdmin); err != nil { 836 return err 837 } 838 839 id, secret, err := ts.authentication.newAuthSession(context.TODO(), authUser) 840 if err != nil { 841 return err 842 } 843 rawCookie := &serverpb.SessionCookie{ 844 ID: id, 845 Secret: secret, 846 } 847 // Encode a session cookie and store it in a cookie jar. 848 cookie, err := EncodeSessionCookie(rawCookie, false /* forHTTPSOnly */) 849 if err != nil { 850 return err 851 } 852 cookieJar, err := cookiejar.New(nil) 853 if err != nil { 854 return err 855 } 856 url, err := url.Parse(ts.AdminURL()) 857 if err != nil { 858 return err 859 } 860 cookieJar.SetCookies(url, []*http.Cookie{cookie}) 861 // Create an httpClient and attach the cookie jar to the client. 862 authClient.httpClient, err = ts.Cfg.GetHTTPClient() 863 if err != nil { 864 return err 865 } 866 authClient.httpClient.Jar = cookieJar 867 authClient.cookie = rawCookie 868 return nil 869 }() 870 }) 871 872 return authClient.httpClient, authClient.cookie, authClient.err 873 } 874 875 func (ts *TestServer) createAuthUser(userName string, isAdmin bool) error { 876 if _, err := ts.Server.sqlServer.internalExecutor.ExecEx(context.TODO(), 877 "create-auth-user", nil, 878 sqlbase.InternalExecutorSessionDataOverride{User: security.RootUser}, 879 "CREATE USER $1", userName, 880 ); err != nil { 881 return err 882 } 883 if isAdmin { 884 // We can't use the GRANT statement here because we don't want 885 // to rely on CCL code. 886 if _, err := ts.Server.sqlServer.internalExecutor.ExecEx(context.TODO(), 887 "grant-admin", nil, 888 sqlbase.InternalExecutorSessionDataOverride{User: security.RootUser}, 889 "INSERT INTO system.role_members (role, member, \"isAdmin\") VALUES ('admin', $1, true)", userName, 890 ); err != nil { 891 return err 892 } 893 } 894 return nil 895 } 896 897 // MustGetSQLCounter implements TestServerInterface. 898 func (ts *TestServer) MustGetSQLCounter(name string) int64 { 899 var c int64 900 var found bool 901 902 ts.registry.Each(func(n string, v interface{}) { 903 if name == n { 904 switch t := v.(type) { 905 case *metric.Counter: 906 c = t.Count() 907 found = true 908 case *metric.Gauge: 909 c = t.Value() 910 found = true 911 } 912 } 913 }) 914 if !found { 915 panic(fmt.Sprintf("couldn't find metric %s", name)) 916 } 917 return c 918 } 919 920 // MustGetSQLNetworkCounter implements TestServerInterface. 921 func (ts *TestServer) MustGetSQLNetworkCounter(name string) int64 { 922 var c int64 923 var found bool 924 925 reg := metric.NewRegistry() 926 for _, m := range ts.sqlServer.pgServer.Metrics() { 927 reg.AddMetricStruct(m) 928 } 929 reg.Each(func(n string, v interface{}) { 930 if name == n { 931 switch t := v.(type) { 932 case *metric.Counter: 933 c = t.Count() 934 found = true 935 case *metric.Gauge: 936 c = t.Value() 937 found = true 938 } 939 } 940 }) 941 if !found { 942 panic(fmt.Sprintf("couldn't find metric %s", name)) 943 } 944 return c 945 } 946 947 // LeaseManager is part of TestServerInterface. 948 func (ts *TestServer) LeaseManager() interface{} { 949 return ts.sqlServer.leaseMgr 950 } 951 952 // InternalExecutor is part of TestServerInterface. 953 func (ts *TestServer) InternalExecutor() interface{} { 954 return ts.sqlServer.internalExecutor 955 } 956 957 // GetNode exposes the Server's Node. 958 func (ts *TestServer) GetNode() *Node { 959 return ts.node 960 } 961 962 // DistSenderI is part of DistSendeInterface. 963 func (ts *TestServer) DistSenderI() interface{} { 964 return ts.distSender 965 } 966 967 // DistSender is like DistSenderI(), but returns the real type instead of 968 // interface{}. 969 func (ts *TestServer) DistSender() *kvcoord.DistSender { 970 return ts.DistSenderI().(*kvcoord.DistSender) 971 } 972 973 // SQLServer is part of TestServerInterface. 974 func (ts *TestServer) SQLServer() interface{} { 975 return ts.PGServer().SQLServer 976 } 977 978 // DistSQLServer is part of TestServerInterface. 979 func (ts *TestServer) DistSQLServer() interface{} { 980 return ts.sqlServer.distSQLServer 981 } 982 983 // SetDistSQLSpanResolver is part of TestServerInterface. 984 func (s *Server) SetDistSQLSpanResolver(spanResolver interface{}) { 985 s.sqlServer.execCfg.DistSQLPlanner.SetSpanResolver(spanResolver.(physicalplan.SpanResolver)) 986 } 987 988 // GetFirstStoreID is part of TestServerInterface. 989 func (ts *TestServer) GetFirstStoreID() roachpb.StoreID { 990 firstStoreID := roachpb.StoreID(-1) 991 err := ts.Stores().VisitStores(func(s *kvserver.Store) error { 992 if firstStoreID == -1 { 993 firstStoreID = s.Ident.StoreID 994 } 995 return nil 996 }) 997 if err != nil { 998 panic(err) 999 } 1000 return firstStoreID 1001 } 1002 1003 // LookupRange returns the descriptor of the range containing key. 1004 func (ts *TestServer) LookupRange(key roachpb.Key) (roachpb.RangeDescriptor, error) { 1005 rs, _, err := kv.RangeLookup(context.Background(), ts.DB().NonTransactionalSender(), 1006 key, roachpb.CONSISTENT, 0 /* prefetchNum */, false /* reverse */) 1007 if err != nil { 1008 return roachpb.RangeDescriptor{}, errors.Errorf( 1009 "%q: lookup range unexpected error: %s", key, err) 1010 } 1011 return rs[0], nil 1012 } 1013 1014 // MergeRanges merges the range containing leftKey with the range to its right. 1015 func (ts *TestServer) MergeRanges(leftKey roachpb.Key) (roachpb.RangeDescriptor, error) { 1016 1017 ctx := context.Background() 1018 mergeReq := roachpb.AdminMergeRequest{ 1019 RequestHeader: roachpb.RequestHeader{ 1020 Key: leftKey, 1021 }, 1022 } 1023 _, pErr := kv.SendWrapped(ctx, ts.DB().NonTransactionalSender(), &mergeReq) 1024 if pErr != nil { 1025 return roachpb.RangeDescriptor{}, 1026 errors.Errorf( 1027 "%q: merge unexpected error: %s", leftKey, pErr) 1028 } 1029 return ts.LookupRange(leftKey) 1030 } 1031 1032 // SplitRange splits the range containing splitKey. 1033 // The right range created by the split starts at the split key and extends to the 1034 // original range's end key. 1035 // Returns the new descriptors of the left and right ranges. 1036 // 1037 // splitKey must correspond to a SQL table key (it must end with a family ID / 1038 // col ID). 1039 func (ts *TestServer) SplitRange( 1040 splitKey roachpb.Key, 1041 ) (roachpb.RangeDescriptor, roachpb.RangeDescriptor, error) { 1042 ctx := context.Background() 1043 splitRKey, err := keys.Addr(splitKey) 1044 if err != nil { 1045 return roachpb.RangeDescriptor{}, roachpb.RangeDescriptor{}, err 1046 } 1047 splitReq := roachpb.AdminSplitRequest{ 1048 RequestHeader: roachpb.RequestHeader{ 1049 Key: splitKey, 1050 }, 1051 SplitKey: splitKey, 1052 ExpirationTime: hlc.MaxTimestamp, 1053 } 1054 _, pErr := kv.SendWrapped(ctx, ts.DB().NonTransactionalSender(), &splitReq) 1055 if pErr != nil { 1056 return roachpb.RangeDescriptor{}, roachpb.RangeDescriptor{}, 1057 errors.Errorf( 1058 "%q: split unexpected error: %s", splitReq.SplitKey, pErr) 1059 } 1060 1061 // The split point may not be exactly at the key we requested (we request 1062 // splits at valid table keys, and the split point corresponds to the row's 1063 // prefix). We scan for the range that includes the key we requested and the 1064 // one that precedes it. 1065 1066 // We use a transaction so that we get consistent results between the two 1067 // scans (in case there are other splits happening). 1068 var leftRangeDesc, rightRangeDesc roachpb.RangeDescriptor 1069 1070 // Errors returned from scanMeta cannot be wrapped or retryable errors won't 1071 // be retried. Instead, the message to wrap is stored in case of 1072 // non-retryable failures and then wrapped when the full transaction fails. 1073 var wrappedMsg string 1074 if err := ts.DB().Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { 1075 scanMeta := func(key roachpb.RKey, reverse bool) (desc roachpb.RangeDescriptor, err error) { 1076 var kvs []kv.KeyValue 1077 if reverse { 1078 // Find the last range that ends at or before key. 1079 kvs, err = txn.ReverseScan( 1080 ctx, keys.Meta2Prefix, keys.RangeMetaKey(key.Next()), 1, /* one result */ 1081 ) 1082 } else { 1083 // Find the first range that ends after key. 1084 kvs, err = txn.Scan( 1085 ctx, keys.RangeMetaKey(key.Next()), keys.Meta2Prefix.PrefixEnd(), 1, /* one result */ 1086 ) 1087 } 1088 if err != nil { 1089 return desc, err 1090 } 1091 if len(kvs) != 1 { 1092 return desc, fmt.Errorf("expected 1 result, got %d", len(kvs)) 1093 } 1094 err = kvs[0].ValueProto(&desc) 1095 return desc, err 1096 } 1097 1098 rightRangeDesc, err = scanMeta(splitRKey, false /* reverse */) 1099 if err != nil { 1100 wrappedMsg = "could not look up right-hand side descriptor" 1101 return err 1102 } 1103 1104 leftRangeDesc, err = scanMeta(splitRKey, true /* reverse */) 1105 if err != nil { 1106 wrappedMsg = "could not look up left-hand side descriptor" 1107 return err 1108 } 1109 1110 if !leftRangeDesc.EndKey.Equal(rightRangeDesc.StartKey) { 1111 return errors.Errorf( 1112 "inconsistent left (%v) and right (%v) descriptors", leftRangeDesc, rightRangeDesc, 1113 ) 1114 } 1115 return nil 1116 }); err != nil { 1117 if len(wrappedMsg) > 0 { 1118 err = errors.Wrapf(err, "%s", wrappedMsg) 1119 } 1120 return roachpb.RangeDescriptor{}, roachpb.RangeDescriptor{}, err 1121 } 1122 1123 return leftRangeDesc, rightRangeDesc, nil 1124 } 1125 1126 // GetRangeLease returns the current lease for the range containing key, and a 1127 // timestamp taken from the node. 1128 // 1129 // The lease is returned regardless of its status. 1130 func (ts *TestServer) GetRangeLease( 1131 ctx context.Context, key roachpb.Key, 1132 ) (_ roachpb.Lease, now hlc.Timestamp, _ error) { 1133 leaseReq := roachpb.LeaseInfoRequest{ 1134 RequestHeader: roachpb.RequestHeader{ 1135 Key: key, 1136 }, 1137 } 1138 leaseResp, pErr := kv.SendWrappedWith( 1139 ctx, 1140 ts.DB().NonTransactionalSender(), 1141 roachpb.Header{ 1142 // INCONSISTENT read, since we want to make sure that the node used to 1143 // send this is the one that processes the command, for the hint to 1144 // matter. 1145 ReadConsistency: roachpb.INCONSISTENT, 1146 }, 1147 &leaseReq, 1148 ) 1149 if pErr != nil { 1150 return roachpb.Lease{}, hlc.Timestamp{}, pErr.GoError() 1151 } 1152 return leaseResp.(*roachpb.LeaseInfoResponse).Lease, ts.Clock().Now(), nil 1153 1154 } 1155 1156 // ExecutorConfig is part of the TestServerInterface. 1157 func (ts *TestServer) ExecutorConfig() interface{} { 1158 return *ts.sqlServer.execCfg 1159 } 1160 1161 // GCSystemLog deletes entries in the given system log table between 1162 // timestamp and timestampUpperBound if the server is the lease holder 1163 // for range 1. 1164 // Leaseholder constraint is present so that only one node in the cluster 1165 // performs gc. 1166 // The system log table is expected to have a "timestamp" column. 1167 // It returns the timestampLowerBound to be used in the next iteration, number 1168 // of rows affected and error (if any). 1169 func (ts *TestServer) GCSystemLog( 1170 ctx context.Context, table string, timestampLowerBound, timestampUpperBound time.Time, 1171 ) (time.Time, int64, error) { 1172 return ts.gcSystemLog(ctx, table, timestampLowerBound, timestampUpperBound) 1173 } 1174 1175 // ForceTableGC is part of TestServerInterface. 1176 func (ts *TestServer) ForceTableGC( 1177 ctx context.Context, database, table string, timestamp hlc.Timestamp, 1178 ) error { 1179 tableIDQuery := ` 1180 SELECT tables.id FROM system.namespace tables 1181 JOIN system.namespace dbs ON dbs.id = tables."parentID" 1182 WHERE dbs.name = $1 AND tables.name = $2 1183 ` 1184 row, err := ts.sqlServer.internalExecutor.QueryRowEx( 1185 ctx, "resolve-table-id", nil, /* txn */ 1186 sqlbase.InternalExecutorSessionDataOverride{User: security.RootUser}, 1187 tableIDQuery, database, table) 1188 if err != nil { 1189 return err 1190 } 1191 if row == nil { 1192 return errors.Errorf("table not found") 1193 } 1194 if len(row) != 1 { 1195 return errors.AssertionFailedf("expected 1 column from internal query") 1196 } 1197 tableID := uint32(*row[0].(*tree.DInt)) 1198 tblKey := keys.SystemSQLCodec.TablePrefix(tableID) 1199 gcr := roachpb.GCRequest{ 1200 RequestHeader: roachpb.RequestHeader{ 1201 Key: tblKey, 1202 EndKey: tblKey.PrefixEnd(), 1203 }, 1204 Threshold: timestamp, 1205 } 1206 _, pErr := kv.SendWrapped(ctx, ts.distSender, &gcr) 1207 return pErr.GoError() 1208 } 1209 1210 type testServerFactoryImpl struct{} 1211 1212 // TestServerFactory can be passed to serverutils.InitTestServerFactory 1213 var TestServerFactory = testServerFactoryImpl{} 1214 1215 // New is part of TestServerFactory interface. 1216 func (testServerFactoryImpl) New(params base.TestServerArgs) interface{} { 1217 cfg := makeTestConfigFromParams(params) 1218 return &TestServer{Cfg: &cfg} 1219 }