本文整理匯總了Golang中github.com/cockroachdb/cockroach/pkg/util/log.AmbientContext類的典型用法代碼示例。如果您正苦於以下問題:Golang AmbientContext類的具體用法?Golang AmbientContext怎麽用?Golang AmbientContext使用的例子?那麽, 這裏精選的類代碼示例或許可以為您提供幫助。
在下文中一共展示了AmbientContext類的14個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: Start
// Start starts the test cluster by bootstrapping an in-memory store
// (defaults to maximum of 50M). The server is started, launching the
// node RPC server and all HTTP endpoints. Use the value of
// TestServer.Addr after Start() for client connections. Use Stop()
// to shutdown the server after the test completes.
func (ltc *LocalTestCluster) Start(t util.Tester, baseCtx *base.Config, initSender InitSenderFn) {
ambient := log.AmbientContext{Tracer: tracing.NewTracer()}
nc := &base.NodeIDContainer{}
ambient.AddLogTag("n", nc)
nodeID := roachpb.NodeID(1)
nodeDesc := &roachpb.NodeDescriptor{NodeID: nodeID}
ltc.tester = t
ltc.Manual = hlc.NewManualClock(0)
ltc.Clock = hlc.NewClock(ltc.Manual.UnixNano)
ltc.Stopper = stop.NewStopper()
rpcContext := rpc.NewContext(ambient, baseCtx, ltc.Clock, ltc.Stopper)
server := rpc.NewServer(rpcContext) // never started
ltc.Gossip = gossip.New(ambient, nc, rpcContext, server, nil, ltc.Stopper, metric.NewRegistry())
ltc.Eng = engine.NewInMem(roachpb.Attributes{}, 50<<20)
ltc.Stopper.AddCloser(ltc.Eng)
ltc.Stores = storage.NewStores(ambient, ltc.Clock)
ltc.Sender = initSender(nodeDesc, ambient.Tracer, ltc.Clock, ltc.Latency, ltc.Stores, ltc.Stopper,
ltc.Gossip)
if ltc.DBContext == nil {
dbCtx := client.DefaultDBContext()
ltc.DBContext = &dbCtx
}
ltc.DB = client.NewDBWithContext(ltc.Sender, *ltc.DBContext)
transport := storage.NewDummyRaftTransport()
cfg := storage.TestStoreConfig()
if ltc.RangeRetryOptions != nil {
cfg.RangeRetryOptions = *ltc.RangeRetryOptions
}
cfg.AmbientCtx = ambient
cfg.Clock = ltc.Clock
cfg.DB = ltc.DB
cfg.Gossip = ltc.Gossip
cfg.Transport = transport
cfg.MetricsSampleInterval = metric.TestSampleInterval
ltc.Store = storage.NewStore(cfg, ltc.Eng, nodeDesc)
if err := ltc.Store.Bootstrap(roachpb.StoreIdent{NodeID: nodeID, StoreID: 1}); err != nil {
t.Fatalf("unable to start local test cluster: %s", err)
}
ltc.Stores.AddStore(ltc.Store)
if err := ltc.Store.BootstrapRange(nil); err != nil {
t.Fatalf("unable to start local test cluster: %s", err)
}
if err := ltc.Store.Start(context.Background(), ltc.Stopper); err != nil {
t.Fatalf("unable to start local test cluster: %s", err)
}
nc.Set(context.TODO(), nodeDesc.NodeID)
if err := ltc.Gossip.SetNodeDescriptor(nodeDesc); err != nil {
t.Fatalf("unable to set node descriptor: %s", err)
}
}
示例2: MakeServer
// MakeServer instantiates a new Server which services requests with data from
// the supplied DB.
func MakeServer(ambient log.AmbientContext, db *DB, cfg ServerConfig, stopper *stop.Stopper) Server {
ambient.AddLogTag("ts-srv", nil)
queryWorkerMax := queryWorkerMax
if cfg.QueryWorkerMax != 0 {
queryWorkerMax = cfg.QueryWorkerMax
}
return Server{
AmbientContext: ambient,
db: db,
stopper: stopper,
workerSem: make(chan struct{}, queryWorkerMax),
}
}
示例3: New
// New creates an instance of a gossip node.
// The higher level manages the NodeIDContainer instance (which can be shared by
// various server components). The ambient context is expected to already
// contain the node ID.
func New(
ambient log.AmbientContext,
nodeID *base.NodeIDContainer,
rpcContext *rpc.Context,
grpcServer *grpc.Server,
resolvers []resolver.Resolver,
stopper *stop.Stopper,
registry *metric.Registry,
) *Gossip {
ambient.SetEventLog("gossip", "gossip")
g := &Gossip{
server: newServer(ambient, nodeID, stopper, registry),
Connected: make(chan struct{}),
rpcContext: rpcContext,
outgoing: makeNodeSet(minPeers, metric.NewGauge(MetaConnectionsOutgoingGauge)),
bootstrapping: map[string]struct{}{},
disconnected: make(chan *client, 10),
stalledCh: make(chan struct{}, 1),
stallInterval: defaultStallInterval,
bootstrapInterval: defaultBootstrapInterval,
cullInterval: defaultCullInterval,
nodeDescs: map[roachpb.NodeID]*roachpb.NodeDescriptor{},
resolverAddrs: map[util.UnresolvedAddr]resolver.Resolver{},
bootstrapAddrs: map[util.UnresolvedAddr]roachpb.NodeID{},
}
stopper.AddCloser(stop.CloserFn(g.server.AmbientContext.FinishEventLog))
registry.AddMetric(g.outgoing.gauge)
g.clientsMu.breakers = map[string]*circuit.Breaker{}
resolverAddrs := make([]string, len(resolvers))
for i, resolver := range resolvers {
resolverAddrs[i] = resolver.Addr()
}
ctx := g.AnnotateCtx(context.Background())
if log.V(1) {
log.Infof(ctx, "initial resolvers: %v", resolverAddrs)
}
g.SetResolvers(resolvers)
g.mu.Lock()
// Add ourselves as a SystemConfig watcher.
g.mu.is.registerCallback(KeySystemConfig, g.updateSystemConfig)
// Add ourselves as a node descriptor watcher.
g.mu.is.registerCallback(MakePrefixPattern(KeyNodeIDPrefix), g.updateNodeAddress)
g.mu.Unlock()
RegisterGossipServer(grpcServer, g.server)
return g
}
示例4: NewTest
// NewTest is a simplified wrapper around New that creates the NodeIDContainer
// internally. Used for testing.
func NewTest(
nodeID roachpb.NodeID,
rpcContext *rpc.Context,
grpcServer *grpc.Server,
resolvers []resolver.Resolver,
stopper *stop.Stopper,
registry *metric.Registry,
) *Gossip {
n := &base.NodeIDContainer{}
var ac log.AmbientContext
ac.AddLogTag("n", n)
gossip := New(ac, n, rpcContext, grpcServer, resolvers, stopper, registry)
if nodeID != 0 {
n.Set(context.TODO(), nodeID)
}
return gossip
}
示例5: TestAdminAPIUsers
func TestAdminAPIUsers(t *testing.T) {
defer leaktest.AfterTest(t)()
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
defer s.Stopper().Stop()
ts := s.(*TestServer)
// Create sample users.
ac := log.AmbientContext{Tracer: tracing.NewTracer()}
ctx, span := ac.AnnotateCtxWithSpan(context.Background(), "test")
defer span.Finish()
session := sql.NewSession(
ctx, sql.SessionArgs{User: security.RootUser}, ts.sqlExecutor, nil, &sql.MemoryMetrics{})
session.StartUnlimitedMonitor()
defer session.Finish(ts.sqlExecutor)
query := `
INSERT INTO system.users (username, hashedPassword)
VALUES ('admin', 'abc'), ('bob', 'xyz')`
res := ts.sqlExecutor.ExecuteStatements(session, query, nil)
defer res.Close()
if a, e := len(res.ResultList), 1; a != e {
t.Fatalf("len(results) %d != %d", a, e)
} else if res.ResultList[0].Err != nil {
t.Fatal(res.ResultList[0].Err)
}
// Query the API for users.
var resp serverpb.UsersResponse
if err := getAdminJSONProto(s, "users", &resp); err != nil {
t.Fatal(err)
}
expResult := serverpb.UsersResponse{
Users: []serverpb.UsersResponse_User{
{Username: "admin"},
{Username: "bob"},
},
}
// Verify results.
const sortKey = "Username"
testutils.SortStructs(resp.Users, sortKey)
testutils.SortStructs(expResult.Users, sortKey)
if !reflect.DeepEqual(resp, expResult) {
t.Fatalf("result %v != expected %v", resp, expResult)
}
}
示例6: PollSource
// PollSource begins a Goroutine which periodically queries the supplied
// DataSource for time series data, storing the returned data in the server.
// Stored data will be sampled using the provided Resolution. The polling
// process will continue until the provided stop.Stopper is stopped.
func (db *DB) PollSource(
ambient log.AmbientContext,
source DataSource,
frequency time.Duration,
r Resolution,
stopper *stop.Stopper,
) {
ambient.AddLogTag("ts-poll", nil)
p := &poller{
AmbientContext: ambient,
db: db,
source: source,
frequency: frequency,
r: r,
stopper: stopper,
}
p.start()
}
示例7: NewContext
// NewContext creates an rpc Context with the supplied values.
func NewContext(
ambient log.AmbientContext, baseCtx *base.Config, hlcClock *hlc.Clock, stopper *stop.Stopper,
) *Context {
ctx := &Context{
Config: baseCtx,
}
if hlcClock != nil {
ctx.localClock = hlcClock
} else {
ctx.localClock = hlc.NewClock(hlc.UnixNano)
}
ctx.breakerClock = breakerClock{
clock: ctx.localClock,
}
var cancel context.CancelFunc
ctx.masterCtx, cancel = context.WithCancel(ambient.AnnotateCtx(context.Background()))
ctx.Stopper = stopper
ctx.RemoteClocks = newRemoteClockMonitor(
ctx.masterCtx, ctx.localClock, 10*defaultHeartbeatInterval)
ctx.HeartbeatInterval = defaultHeartbeatInterval
ctx.HeartbeatTimeout = 2 * defaultHeartbeatInterval
ctx.conns.cache = make(map[string]*connMeta)
stopper.RunWorker(func() {
<-stopper.ShouldQuiesce()
cancel()
ctx.conns.Lock()
for key, meta := range ctx.conns.cache {
meta.Do(func() {
// Make sure initialization is not in progress when we're removing the
// conn. We need to set the error in case we win the race against the
// real initialization code.
if meta.err == nil {
meta.err = &roachpb.NodeUnavailableError{}
}
})
ctx.removeConnLocked(key, meta)
}
ctx.conns.Unlock()
})
return ctx
}
示例8: newStatusServer
// newStatusServer allocates and returns a statusServer.
func newStatusServer(
ambient log.AmbientContext,
db *client.DB,
gossip *gossip.Gossip,
metricSource metricMarshaler,
rpcCtx *rpc.Context,
stores *storage.Stores,
) *statusServer {
ambient.AddLogTag("status", nil)
server := &statusServer{
AmbientContext: ambient,
db: db,
gossip: gossip,
metricSource: metricSource,
rpcCtx: rpcCtx,
stores: stores,
}
return server
}
示例9: newRaftScheduler
func newRaftScheduler(
ambient log.AmbientContext, metrics *StoreMetrics, processor raftProcessor, numWorkers int,
) *raftScheduler {
s := &raftScheduler{
processor: processor,
numWorkers: numWorkers,
}
muLogger := syncutil.ThresholdLogger(
ambient.AnnotateCtx(context.Background()),
defaultReplicaMuWarnThreshold,
func(ctx context.Context, msg string, args ...interface{}) {
log.Warningf(ctx, "raftScheduler.mu: "+msg, args...)
},
func(t time.Duration) {
if metrics != nil {
metrics.MuSchedulerNanos.RecordValue(t.Nanoseconds())
}
},
)
s.mu.TimedMutex = syncutil.MakeTimedMutex(muLogger)
s.mu.cond = sync.NewCond(&s.mu.TimedMutex)
s.mu.state = make(map[roachpb.RangeID]raftScheduleState)
return s
}
示例10: TestAdminAPIEvents
func TestAdminAPIEvents(t *testing.T) {
defer leaktest.AfterTest(t)()
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
defer s.Stopper().Stop()
ts := s.(*TestServer)
ac := log.AmbientContext{Tracer: tracing.NewTracer()}
ctx, span := ac.AnnotateCtxWithSpan(context.Background(), "test")
defer span.Finish()
session := sql.NewSession(
ctx, sql.SessionArgs{User: security.RootUser}, ts.sqlExecutor, nil, &sql.MemoryMetrics{})
session.StartUnlimitedMonitor()
defer session.Finish(ts.sqlExecutor)
setupQueries := []string{
"CREATE DATABASE api_test",
"CREATE TABLE api_test.tbl1 (a INT)",
"CREATE TABLE api_test.tbl2 (a INT)",
"CREATE TABLE api_test.tbl3 (a INT)",
"DROP TABLE api_test.tbl1",
"DROP TABLE api_test.tbl2",
}
for _, q := range setupQueries {
res := ts.sqlExecutor.ExecuteStatements(session, q, nil)
defer res.Close()
if res.ResultList[0].Err != nil {
t.Fatalf("error executing '%s': %s", q, res.ResultList[0].Err)
}
}
var zeroTimestamp serverpb.EventsResponse_Event_Timestamp
testcases := []struct {
eventType sql.EventLogType
expCount int
}{
{"", 7},
{sql.EventLogNodeJoin, 1},
{sql.EventLogNodeRestart, 0},
{sql.EventLogDropDatabase, 0},
{sql.EventLogCreateDatabase, 1},
{sql.EventLogDropTable, 2},
{sql.EventLogCreateTable, 3},
}
for i, tc := range testcases {
url := "events"
if len(tc.eventType) > 0 {
url += "?type=" + string(tc.eventType)
}
var resp serverpb.EventsResponse
if err := getAdminJSONProto(s, url, &resp); err != nil {
t.Fatal(err)
}
if a, e := len(resp.Events), tc.expCount; a != e {
t.Errorf("%d: # of events %d != expected %d", i, a, e)
}
// Ensure we don't have blank / nonsensical fields.
for _, e := range resp.Events {
if e.Timestamp == zeroTimestamp {
t.Errorf("%d: missing/empty timestamp", i)
}
if len(tc.eventType) > 0 {
if a, e := e.EventType, string(tc.eventType); a != e {
t.Errorf("%d: event type %s != expected %s", i, a, e)
}
} else {
if len(e.EventType) == 0 {
t.Errorf("%d: missing event type in event", i)
}
}
if e.TargetID == 0 {
t.Errorf("%d: missing/empty TargetID", i)
}
if e.ReportingID == 0 {
t.Errorf("%d: missing/empty ReportingID", i)
}
if len(e.Info) == 0 {
t.Errorf("%d: missing/empty Info", i)
}
if len(e.UniqueID) == 0 {
t.Errorf("%d: missing/empty UniqueID", i)
}
}
}
}
示例11: TestAdminAPIZoneDetails
// TestAdminAPIZoneDetails verifies the zone configuration information returned
// for both DatabaseDetailsResponse AND TableDetailsResponse.
func TestAdminAPIZoneDetails(t *testing.T) {
defer leaktest.AfterTest(t)()
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
defer s.Stopper().Stop()
ts := s.(*TestServer)
// Create database and table.
ac := log.AmbientContext{Tracer: tracing.NewTracer()}
ctx, span := ac.AnnotateCtxWithSpan(context.Background(), "test")
defer span.Finish()
session := sql.NewSession(
ctx, sql.SessionArgs{User: security.RootUser}, ts.sqlExecutor, nil, &sql.MemoryMetrics{})
session.StartUnlimitedMonitor()
setupQueries := []string{
"CREATE DATABASE test",
"CREATE TABLE test.tbl (val STRING)",
}
for _, q := range setupQueries {
res := ts.sqlExecutor.ExecuteStatements(session, q, nil)
defer res.Close()
if res.ResultList[0].Err != nil {
t.Fatalf("error executing '%s': %s", q, res.ResultList[0].Err)
}
}
// Function to verify the zone for table "test.tbl" as returned by the Admin
// API.
verifyTblZone := func(
expectedZone config.ZoneConfig, expectedLevel serverpb.ZoneConfigurationLevel,
) {
var resp serverpb.TableDetailsResponse
if err := getAdminJSONProto(s, "databases/test/tables/tbl", &resp); err != nil {
t.Fatal(err)
}
if a, e := &resp.ZoneConfig, &expectedZone; !proto.Equal(a, e) {
t.Errorf("actual table zone config %v did not match expected value %v", a, e)
}
if a, e := resp.ZoneConfigLevel, expectedLevel; a != e {
t.Errorf("actual table ZoneConfigurationLevel %s did not match expected value %s", a, e)
}
if t.Failed() {
t.FailNow()
}
}
// Function to verify the zone for database "test" as returned by the Admin
// API.
verifyDbZone := func(
expectedZone config.ZoneConfig, expectedLevel serverpb.ZoneConfigurationLevel,
) {
var resp serverpb.DatabaseDetailsResponse
if err := getAdminJSONProto(s, "databases/test", &resp); err != nil {
t.Fatal(err)
}
if a, e := &resp.ZoneConfig, &expectedZone; !proto.Equal(a, e) {
t.Errorf("actual db zone config %v did not match expected value %v", a, e)
}
if a, e := resp.ZoneConfigLevel, expectedLevel; a != e {
t.Errorf("actual db ZoneConfigurationLevel %s did not match expected value %s", a, e)
}
if t.Failed() {
t.FailNow()
}
}
// Function to store a zone config for a given object ID.
setZone := func(zoneCfg config.ZoneConfig, id sqlbase.ID) {
zoneBytes, err := zoneCfg.Marshal()
if err != nil {
t.Fatal(err)
}
const query = `INSERT INTO system.zones VALUES($1, $2)`
params := parser.NewPlaceholderInfo()
params.SetValue(`1`, parser.NewDInt(parser.DInt(id)))
params.SetValue(`2`, parser.NewDBytes(parser.DBytes(zoneBytes)))
res := ts.sqlExecutor.ExecuteStatements(session, query, params)
defer res.Close()
if res.ResultList[0].Err != nil {
t.Fatalf("error executing '%s': %s", query, res.ResultList[0].Err)
}
}
// Verify zone matches cluster default.
verifyDbZone(config.DefaultZoneConfig(), serverpb.ZoneConfigurationLevel_CLUSTER)
verifyTblZone(config.DefaultZoneConfig(), serverpb.ZoneConfigurationLevel_CLUSTER)
// Get ID path for table. This will be an array of three IDs, containing the ID of the root namespace,
// the database, and the table (in that order).
idPath, err := ts.admin.queryDescriptorIDPath(session, []string{"test", "tbl"})
if err != nil {
t.Fatal(err)
}
// Apply zone configuration to database and check again.
dbZone := config.ZoneConfig{
RangeMinBytes: 456,
}
setZone(dbZone, idPath[1])
//.........這裏部分代碼省略.........
示例12: testAdminAPITableDetailsInner
func testAdminAPITableDetailsInner(t *testing.T, dbName, tblName string) {
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
defer s.Stopper().Stop()
ts := s.(*TestServer)
escDBName := parser.Name(dbName).String()
escTblName := parser.Name(tblName).String()
ac := log.AmbientContext{Tracer: tracing.NewTracer()}
ctx, span := ac.AnnotateCtxWithSpan(context.Background(), "test")
defer span.Finish()
session := sql.NewSession(
ctx, sql.SessionArgs{User: security.RootUser}, ts.sqlExecutor, nil, &sql.MemoryMetrics{})
session.StartUnlimitedMonitor()
defer session.Finish(ts.sqlExecutor)
setupQueries := []string{
fmt.Sprintf("CREATE DATABASE %s", escDBName),
fmt.Sprintf(`CREATE TABLE %s.%s (
nulls_allowed INT,
nulls_not_allowed INT NOT NULL DEFAULT 1000,
default2 INT DEFAULT 2,
string_default STRING DEFAULT 'default_string'
)`, escDBName, escTblName),
fmt.Sprintf("GRANT SELECT ON %s.%s TO readonly", escDBName, escTblName),
fmt.Sprintf("GRANT SELECT,UPDATE,DELETE ON %s.%s TO app", escDBName, escTblName),
fmt.Sprintf("CREATE INDEX descIdx ON %s.%s (default2 DESC)", escDBName, escTblName),
}
for _, q := range setupQueries {
res := ts.sqlExecutor.ExecuteStatements(session, q, nil)
defer res.Close()
if res.ResultList[0].Err != nil {
t.Fatalf("error executing '%s': %s", q, res.ResultList[0].Err)
}
}
// Perform API call.
var resp serverpb.TableDetailsResponse
url := fmt.Sprintf("databases/%s/tables/%s", dbName, tblName)
if err := getAdminJSONProto(s, url, &resp); err != nil {
t.Fatal(err)
}
// Verify columns.
expColumns := []serverpb.TableDetailsResponse_Column{
{Name: "nulls_allowed", Type: "INT", Nullable: true, DefaultValue: ""},
{Name: "nulls_not_allowed", Type: "INT", Nullable: false, DefaultValue: "1000"},
{Name: "default2", Type: "INT", Nullable: true, DefaultValue: "2"},
{Name: "string_default", Type: "STRING", Nullable: true, DefaultValue: "'default_string'"},
{Name: "rowid", Type: "INT", Nullable: false, DefaultValue: "unique_rowid()"},
}
testutils.SortStructs(expColumns, "Name")
testutils.SortStructs(resp.Columns, "Name")
if a, e := len(resp.Columns), len(expColumns); a != e {
t.Fatalf("# of result columns %d != expected %d (got: %#v)", a, e, resp.Columns)
}
for i, a := range resp.Columns {
e := expColumns[i]
if a.String() != e.String() {
t.Fatalf("mismatch at column %d: actual %#v != %#v", i, a, e)
}
}
// Verify grants.
expGrants := []serverpb.TableDetailsResponse_Grant{
{User: security.RootUser, Privileges: []string{"ALL"}},
{User: "app", Privileges: []string{"DELETE", "SELECT", "UPDATE"}},
{User: "readonly", Privileges: []string{"SELECT"}},
}
testutils.SortStructs(expGrants, "User")
testutils.SortStructs(resp.Grants, "User")
if a, e := len(resp.Grants), len(expGrants); a != e {
t.Fatalf("# of grant columns %d != expected %d (got: %#v)", a, e, resp.Grants)
}
for i, a := range resp.Grants {
e := expGrants[i]
sort.Strings(a.Privileges)
sort.Strings(e.Privileges)
if a.String() != e.String() {
t.Fatalf("mismatch at index %d: actual %#v != %#v", i, a, e)
}
}
// Verify indexes.
expIndexes := []serverpb.TableDetailsResponse_Index{
{Name: "primary", Column: "rowid", Direction: "ASC", Unique: true, Seq: 1},
{Name: "descIdx", Column: "default2", Direction: "DESC", Unique: false, Seq: 1},
}
testutils.SortStructs(expIndexes, "Column")
testutils.SortStructs(resp.Indexes, "Column")
for i, a := range resp.Indexes {
e := expIndexes[i]
if a.String() != e.String() {
t.Fatalf("mismatch at index %d: actual %#v != %#v", i, a, e)
}
}
// Verify range count.
if a, e := resp.RangeCount, int64(1); a != e {
//.........這裏部分代碼省略.........
示例13: TestAdminAPIDatabases
func TestAdminAPIDatabases(t *testing.T) {
defer leaktest.AfterTest(t)()
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
defer s.Stopper().Stop()
ts := s.(*TestServer)
ac := log.AmbientContext{Tracer: tracing.NewTracer()}
ctx, span := ac.AnnotateCtxWithSpan(context.Background(), "test")
defer span.Finish()
// Test databases endpoint.
const testdb = "test"
session := sql.NewSession(
ctx, sql.SessionArgs{User: security.RootUser}, ts.sqlExecutor, nil, &sql.MemoryMetrics{})
session.StartUnlimitedMonitor()
defer session.Finish(ts.sqlExecutor)
query := "CREATE DATABASE " + testdb
createRes := ts.sqlExecutor.ExecuteStatements(session, query, nil)
defer createRes.Close()
if createRes.ResultList[0].Err != nil {
t.Fatal(createRes.ResultList[0].Err)
}
var resp serverpb.DatabasesResponse
if err := getAdminJSONProto(s, "databases", &resp); err != nil {
t.Fatal(err)
}
expectedDBs := []string{"system", testdb}
if a, e := len(resp.Databases), len(expectedDBs); a != e {
t.Fatalf("length of result %d != expected %d", a, e)
}
sort.Strings(resp.Databases)
for i, e := range expectedDBs {
if a := resp.Databases[i]; a != e {
t.Fatalf("database name %s != expected %s", a, e)
}
}
// Test database details endpoint.
privileges := []string{"SELECT", "UPDATE"}
testuser := "testuser"
grantQuery := "GRANT " + strings.Join(privileges, ", ") + " ON DATABASE " + testdb + " TO " + testuser
grantRes := s.(*TestServer).sqlExecutor.ExecuteStatements(session, grantQuery, nil)
defer grantRes.Close()
if grantRes.ResultList[0].Err != nil {
t.Fatal(grantRes.ResultList[0].Err)
}
var details serverpb.DatabaseDetailsResponse
if err := getAdminJSONProto(s, "databases/"+testdb, &details); err != nil {
t.Fatal(err)
}
if a, e := len(details.Grants), 2; a != e {
t.Fatalf("# of grants %d != expected %d", a, e)
}
for _, grant := range details.Grants {
switch grant.User {
case security.RootUser:
if !reflect.DeepEqual(grant.Privileges, []string{"ALL"}) {
t.Fatalf("privileges %v != expected %v", details.Grants[0].Privileges, privileges)
}
case testuser:
sort.Strings(grant.Privileges)
if !reflect.DeepEqual(grant.Privileges, privileges) {
t.Fatalf("privileges %v != expected %v", grant.Privileges, privileges)
}
default:
t.Fatalf("unknown grant to user %s", grant.User)
}
}
// Verify Descriptor ID.
path, err := ts.admin.queryDescriptorIDPath(session, []string{testdb})
if err != nil {
t.Fatal(err)
}
if a, e := details.DescriptorID, int64(path[1]); a != e {
t.Fatalf("db had descriptorID %d, expected %d", a, e)
}
}
示例14: TestAdminAPITableDetailsForVirtualSchema
func TestAdminAPITableDetailsForVirtualSchema(t *testing.T) {
defer leaktest.AfterTest(t)()
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{})
defer s.Stopper().Stop()
ts := s.(*TestServer)
// Perform API call.
var resp serverpb.TableDetailsResponse
if err := getAdminJSONProto(s, "databases/information_schema/tables/schemata", &resp); err != nil {
t.Fatal(err)
}
// Verify columns.
expColumns := []serverpb.TableDetailsResponse_Column{
{Name: "CATALOG_NAME", Type: "STRING", Nullable: false, DefaultValue: "''"},
{Name: "SCHEMA_NAME", Type: "STRING", Nullable: false, DefaultValue: "''"},
{Name: "DEFAULT_CHARACTER_SET_NAME", Type: "STRING", Nullable: false, DefaultValue: "''"},
{Name: "SQL_PATH", Type: "STRING", Nullable: true},
}
testutils.SortStructs(expColumns, "Name")
testutils.SortStructs(resp.Columns, "Name")
if a, e := len(resp.Columns), len(expColumns); a != e {
t.Fatalf("# of result columns %d != expected %d (got: %#v)", a, e, resp.Columns)
}
for i, a := range resp.Columns {
e := expColumns[i]
if a.String() != e.String() {
t.Fatalf("mismatch at column %d: actual %#v != %#v", i, a, e)
}
}
// Verify grants.
if a, e := len(resp.Grants), 0; a != e {
t.Fatalf("# of grant columns %d != expected %d (got: %#v)", a, e, resp.Grants)
}
// Verify indexes.
if a, e := resp.RangeCount, int64(0); a != e {
t.Fatalf("# of indexes %d != expected %d", a, e)
}
// Verify range count.
if a, e := resp.RangeCount, int64(0); a != e {
t.Fatalf("# of ranges %d != expected %d", a, e)
}
// Verify Create Table Statement.
{
const (
showCreateTableQuery = "SHOW CREATE TABLE information_schema.schemata"
createTableCol = "CreateTable"
)
ac := log.AmbientContext{Tracer: tracing.NewTracer()}
ctx, span := ac.AnnotateCtxWithSpan(context.Background(), "test")
defer span.Finish()
session := sql.NewSession(
ctx, sql.SessionArgs{User: security.RootUser}, ts.sqlExecutor, nil, &sql.MemoryMetrics{})
session.StartUnlimitedMonitor()
defer session.Finish(ts.sqlExecutor)
resSet := ts.sqlExecutor.ExecuteStatements(session, showCreateTableQuery, nil)
defer resSet.Close()
res := resSet.ResultList[0]
if res.Err != nil {
t.Fatalf("error executing '%s': %s", showCreateTableQuery, res.Err)
}
scanner := makeResultScanner(res.Columns)
var createStmt string
if err := scanner.Scan(res.Rows.At(0), createTableCol, &createStmt); err != nil {
t.Fatal(err)
}
if a, e := resp.CreateTableStatement, createStmt; a != e {
t.Fatalf("mismatched create table statement; expected %s, got %s", e, a)
}
}
}