diff --git a/pkg/ccl/logictestccl/testdata/logic_test/tenant_capability b/pkg/ccl/logictestccl/testdata/logic_test/tenant_capability index 9be70cb85382..093a37aa0f61 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/tenant_capability +++ b/pkg/ccl/logictestccl/testdata/logic_test/tenant_capability @@ -31,6 +31,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "no-capabilities-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split false can_admin_unsplit false can_view_node_info false @@ -50,6 +51,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "bool-capability-no-value-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split true can_admin_unsplit false can_view_node_info false @@ -62,6 +64,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "bool-capability-no-value-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split false can_admin_unsplit false can_view_node_info false @@ -81,6 +84,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "bool-capability-with-value-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split true can_admin_unsplit false can_view_node_info false @@ -100,6 +104,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "bool-capability-with-expression-value-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split true can_admin_unsplit false can_view_node_info false @@ -119,6 +124,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "multiple-capability-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split true can_admin_unsplit false can_view_node_info true @@ -131,6 +137,7 @@ query TT colnames SELECT capability_id, capability_value FROM [SHOW TENANT "multiple-capability-tenant" WITH CAPABILITIES] ---- capability_id capability_value +can_admin_scatter false can_admin_split false can_admin_unsplit false can_view_node_info false diff --git a/pkg/multitenant/tenantcapabilities/capabilities.go b/pkg/multitenant/tenantcapabilities/capabilities.go index 40661c06b0a1..891782e6e998 100644 --- a/pkg/multitenant/tenantcapabilities/capabilities.go +++ b/pkg/multitenant/tenantcapabilities/capabilities.go @@ -160,6 +160,12 @@ type TenantCapabilities interface { const ( _ CapabilityID = iota + // CanAdminScatter describes the ability of a tenant to perform manual + // KV scatter requests. These operations need a capability + // because excessive KV range scatter can overwhelm the storage + // cluster. + CanAdminScatter // can_admin_scatter + // CanAdminSplit describes the ability of a tenant to perform manual // KV range split requests. These operations need a capability // because excessive KV range splits can overwhelm the storage @@ -222,6 +228,7 @@ const ( func (c CapabilityID) CapabilityType() Type { switch c { case + CanAdminScatter, CanAdminSplit, CanAdminUnsplit, CanViewNodeInfo, diff --git a/pkg/multitenant/tenantcapabilities/capabilityid_string.go b/pkg/multitenant/tenantcapabilities/capabilityid_string.go index dfb87a9988c8..f4dd2d5076b4 100644 --- a/pkg/multitenant/tenantcapabilities/capabilityid_string.go +++ b/pkg/multitenant/tenantcapabilities/capabilityid_string.go @@ -8,17 +8,18 @@ func _() { // An "invalid array index" compiler error signifies that the constant values have changed. // Re-run the stringer command to generate them again. var x [1]struct{} - _ = x[CanAdminSplit-1] - _ = x[CanAdminUnsplit-2] - _ = x[CanViewNodeInfo-3] - _ = x[CanViewTSDBMetrics-4] - _ = x[TenantSpanConfigBounds-5] - _ = x[MaxCapabilityID-5] + _ = x[CanAdminScatter-1] + _ = x[CanAdminSplit-2] + _ = x[CanAdminUnsplit-3] + _ = x[CanViewNodeInfo-4] + _ = x[CanViewTSDBMetrics-5] + _ = x[TenantSpanConfigBounds-6] + _ = x[MaxCapabilityID-6] } -const _CapabilityID_name = "can_admin_splitcan_admin_unsplitcan_view_node_infocan_view_tsdb_metricsspan_config_bounds" +const _CapabilityID_name = "can_admin_scattercan_admin_splitcan_admin_unsplitcan_view_node_infocan_view_tsdb_metricsspan_config_bounds" -var _CapabilityID_index = [...]uint8{0, 15, 32, 50, 71, 89} +var _CapabilityID_index = [...]uint8{0, 17, 32, 49, 67, 88, 106} func (i CapabilityID) String() string { i -= 1 diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/authorizer.go b/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/authorizer.go index acf7d3fed9fd..312b79b4cd43 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/authorizer.go +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/authorizer.go @@ -71,7 +71,8 @@ func (a *Authorizer) HasCapabilityForBatch( continue } if !hasCap || requiredCap == onlySystemTenant || !found || !cp.GetBool(requiredCap) { - if requiredCap == tenantcapabilities.CanAdminSplit && a.knobs.AuthorizerSkipAdminSplitCapabilityChecks { + if (requiredCap == tenantcapabilities.CanAdminSplit || requiredCap == tenantcapabilities.CanAdminScatter) && + a.knobs.AuthorizerSkipAdminSplitCapabilityChecks { continue } // All allowable request types must be explicitly opted into the @@ -118,6 +119,7 @@ var reqMethodToCap = map[kvpb.Method]tenantcapabilities.CapabilityID{ kvpb.Scan: noCapCheckNeeded, // The following are authorized via specific capabilities. + kvpb.AdminScatter: tenantcapabilities.CanAdminScatter, kvpb.AdminSplit: tenantcapabilities.CanAdminSplit, kvpb.AdminUnsplit: tenantcapabilities.CanAdminUnsplit, @@ -125,7 +127,6 @@ var reqMethodToCap = map[kvpb.Method]tenantcapabilities.CapabilityID{ kvpb.AdminChangeReplicas: noCapCheckNeeded, kvpb.AdminMerge: noCapCheckNeeded, kvpb.AdminRelocateRange: noCapCheckNeeded, - kvpb.AdminScatter: noCapCheckNeeded, kvpb.AdminTransferLease: noCapCheckNeeded, // TODO(knz,arul): Verify with the relevant teams whether secondary diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/testdata/basic b/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/testdata/basic index 0537a58abd89..553c6e3110ba 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/testdata/basic +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitiesauthorizer/testdata/basic @@ -1,8 +1,12 @@ -upsert ten=10 can_admin_split=true can_admin_unsplit=true can_view_node_info=true can_view_tsdb_metrics=true +upsert ten=10 can_admin_scatter=true can_admin_split=true can_admin_unsplit=true can_view_node_info=true can_view_tsdb_metrics=true ---- ok -upsert ten=11 can_admin_split=false can_admin_unsplit=false can_view_node_info=false can_view_tsdb_metrics=false +upsert ten=11 can_admin_scatter=false can_admin_split=false can_admin_unsplit=false can_view_node_info=false can_view_tsdb_metrics=false +---- +ok + +has-capability-for-batch ten=10 cmds=(AdminScatter, Scan, ConditionalPut) ---- ok @@ -16,6 +20,10 @@ has-capability-for-batch ten=10 cmds=(AdminUnsplit, Scan, ConditionalPut) ---- ok +has-capability-for-batch ten=11 cmds=(AdminScatter, Scan, ConditionalPut) +---- +client tenant does not have capability "can_admin_scatter" (*kvpb.AdminScatterRequest) + # Tenant 11 shouldn't be able to issue splits. has-capability-for-batch ten=11 cmds=(AdminSplit, Scan, ConditionalPut) ---- @@ -43,10 +51,14 @@ ok # Lastly, flip tenant 10's capability for splits; ensure it can no longer issue # splits as a result. -upsert ten=10 can_admin_split=false can_admin_unsplit=false can_view_node_info=true can_view_tsdb_metrics=true +upsert ten=10 can_admin_scatter=false can_admin_split=false can_admin_unsplit=false can_view_node_info=true can_view_tsdb_metrics=true ---- ok +has-capability-for-batch ten=10 cmds=(AdminScatter, Scan, ConditionalPut) +---- +client tenant does not have capability "can_admin_scatter" (*kvpb.AdminScatterRequest) + has-capability-for-batch ten=10 cmds=(AdminSplit, Scan, ConditionalPut) ---- client tenant does not have capability "can_admin_split" (*kvpb.AdminSplitRequest) diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.go b/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.go index c62059aa3c2d..f33e0318ad46 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.go +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.go @@ -52,6 +52,8 @@ func (t *TenantCapabilities) Cap( capabilityID tenantcapabilities.CapabilityID, ) tenantcapabilities.Capability { switch capabilityID { + case tenantcapabilities.CanAdminScatter: + return boolCap{&t.CanAdminScatter} case tenantcapabilities.CanAdminSplit: return boolCap{&t.CanAdminSplit} case tenantcapabilities.CanAdminUnsplit: @@ -69,6 +71,8 @@ func (t *TenantCapabilities) Cap( // GetBool implements the tenantcapabilities.TenantCapabilities interface. It is an optimization. func (t *TenantCapabilities) GetBool(capabilityID tenantcapabilities.CapabilityID) bool { switch capabilityID { + case tenantcapabilities.CanAdminScatter: + return t.CanAdminScatter case tenantcapabilities.CanAdminSplit: return t.CanAdminSplit case tenantcapabilities.CanAdminUnsplit: diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.proto b/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.proto index 096d4112bad4..922e4373ffe9 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.proto +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitiespb/capabilities.proto @@ -61,6 +61,10 @@ message TenantCapabilities { // CanAdminUnsplit if set to true, grants the tenant the ability to // successfully perform `AdminUnsplit` requests. bool can_admin_unsplit = 5; + + // CanAdminScatter if set to true, grants the tenant the ability to + // successfully perform `AdminScatter` requests. + bool can_admin_scatter = 6; }; // SpanConfigBound is used to constrain the possible values a SpanConfig may diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/basic b/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/basic index 7c9c956f9ddd..bde38ef1a181 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/basic +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/basic @@ -18,13 +18,13 @@ ok updates ---- Incremental Update -update: ten=10 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -update: ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=10 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} flush-state ---- -ten=10 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=10 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} upsert ten=11 can_admin_split=true ---- @@ -33,11 +33,11 @@ ok updates ---- Incremental Update -update: ten=11 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=11 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=11 ---- -{can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} delete ten=10 ---- @@ -64,7 +64,7 @@ updates # what we'd expect. flush-state ---- -ten=11 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=11 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} upsert ten=15 can_admin_split=true ---- @@ -73,7 +73,7 @@ ok updates ---- Incremental Update -update: ten=15 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=15 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} # Ensure only the last update is applied, even when there are multiple updates # to a single key. @@ -100,7 +100,7 @@ not-found flush-state ---- -ten=15 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=15 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} # Same thing, but this time instead of deleting the key, leave it behind. delete ten=15 @@ -118,12 +118,12 @@ ok updates ---- Incremental Update -update: ten=15 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=15 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} flush-state ---- -ten=15 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=15 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=15 ---- -{can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/initial_scan b/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/initial_scan index ae2fda0f78e3..a93b960655f7 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/initial_scan +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/initial_scan @@ -38,13 +38,13 @@ ok updates ---- Complete Update -update: ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -update: ten=15 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=15 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} flush-state ---- -ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -ten=15 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=15 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=10 ---- @@ -52,4 +52,4 @@ not-found get-capabilities ten=15 ---- -{can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} diff --git a/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/rangefeed_errors b/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/rangefeed_errors index 118ea7b65e78..a6202e19299f 100644 --- a/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/rangefeed_errors +++ b/pkg/multitenant/tenantcapabilities/tenantcapabilitieswatcher/testdata/rangefeed_errors @@ -25,9 +25,9 @@ ok updates ---- Incremental Update -update: ten=10 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -update: ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -update: ten=12 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=10 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=12 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} inject-error ---- @@ -56,9 +56,9 @@ updates flush-state ---- -ten=10 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -ten=12 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=10 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=12 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=50 ---- @@ -66,11 +66,11 @@ not-found get-capabilities ten=12 ---- -{can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=10 ---- -{can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} # Let the Watcher attempt to restart. restart-after-injected-error @@ -82,23 +82,23 @@ ok updates ---- Complete Update -update: ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -update: ten=12 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -update: ten=50 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=12 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +update: ten=50 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} flush-state ---- -ten=11 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -ten=12 cap={can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} -ten=50 cap={can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=11 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=12 cap={can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +ten=50 cap={can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=50 ---- -{can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:false can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=12 ---- -{can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} +{can_admin_scatter:false can_admin_split:true can_admin_unsplit:false can_view_node_info:false can_view_tsdb_metrics:false} get-capabilities ten=10 ---- diff --git a/pkg/sql/logictest/testdata/logic_test/tenant_builtins b/pkg/sql/logictest/testdata/logic_test/tenant_builtins index 8818e4e416f2..2cb686aee22a 100644 --- a/pkg/sql/logictest/testdata/logic_test/tenant_builtins +++ b/pkg/sql/logictest/testdata/logic_test/tenant_builtins @@ -47,10 +47,10 @@ FROM system.tenants ORDER BY id ---- id active name data_state service_mode crdb_internal.pb_to_json -1 true system 1 2 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "1", "droppedName": "", "tenantReplicationJobId": "0"} -2 true tenant-number-eleven 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "2", "droppedName": "", "tenantReplicationJobId": "0"} -5 true tenant-5 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "5", "droppedName": "", "tenantReplicationJobId": "0"} -10 true tenant-number-ten 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "10", "droppedName": "", "tenantReplicationJobId": "0"} +1 true system 1 2 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "1", "droppedName": "", "tenantReplicationJobId": "0"} +2 true tenant-number-eleven 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "2", "droppedName": "", "tenantReplicationJobId": "0"} +5 true tenant-5 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "5", "droppedName": "", "tenantReplicationJobId": "0"} +10 true tenant-number-ten 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "10", "droppedName": "", "tenantReplicationJobId": "0"} # Check we can add a name where none existed before. statement ok @@ -118,10 +118,10 @@ FROM system.tenants ORDER BY id ---- id active name data_state service_mode crdb_internal.pb_to_json -1 true system 1 2 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "1", "droppedName": "", "tenantReplicationJobId": "0"} -2 true tenant-number-eleven 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "2", "droppedName": "", "tenantReplicationJobId": "0"} -5 false NULL 2 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "DROP", "deprecatedId": "5", "droppedName": "my-new-tenant-name", "tenantReplicationJobId": "0"} -10 true tenant-number-ten 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "10", "droppedName": "", "tenantReplicationJobId": "0"} +1 true system 1 2 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "1", "droppedName": "", "tenantReplicationJobId": "0"} +2 true tenant-number-eleven 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "2", "droppedName": "", "tenantReplicationJobId": "0"} +5 false NULL 2 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "DROP", "deprecatedId": "5", "droppedName": "my-new-tenant-name", "tenantReplicationJobId": "0"} +10 true tenant-number-ten 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "10", "droppedName": "", "tenantReplicationJobId": "0"} # Try to recreate an existing tenant. @@ -229,9 +229,9 @@ FROM system.tenants ORDER BY id ---- id active name data_state service_mode crdb_internal.pb_to_json -1 true system 1 2 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "1", "droppedName": "", "tenantReplicationJobId": "0"} -2 true tenant-number-eleven 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "2", "droppedName": "", "tenantReplicationJobId": "0"} -10 true tenant-number-ten 1 0 {"capabilities": {"canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "10", "droppedName": "", "tenantReplicationJobId": "0"} +1 true system 1 2 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "1", "droppedName": "", "tenantReplicationJobId": "0"} +2 true tenant-number-eleven 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "2", "droppedName": "", "tenantReplicationJobId": "0"} +10 true tenant-number-ten 1 0 {"capabilities": {"canAdminScatter": false, "canAdminSplit": false, "canAdminUnsplit": false, "canViewNodeInfo": false, "canViewTsdbMetrics": false, "spanConfigBounds": null}, "deprecatedDataState": "READY", "deprecatedId": "10", "droppedName": "", "tenantReplicationJobId": "0"} query error tenant resource limits require a CCL binary SELECT crdb_internal.update_tenant_resource_limits(10, 1000, 100, 0, now(), 0) diff --git a/pkg/sql/multitenant_admin_function_test.go b/pkg/sql/multitenant_admin_function_test.go index 91d13f8a86ed..68b2b7c49a8c 100644 --- a/pkg/sql/multitenant_admin_function_test.go +++ b/pkg/sql/multitenant_admin_function_test.go @@ -570,7 +570,11 @@ func TestMultiTenantAdminFunction(t *testing.T) { secondaryWithoutClusterSetting: tenantExpected{ errorMessage: "tenant cluster setting sql.scatter.allow_for_secondary_tenant.enabled disabled", }, + secondaryWithoutCapability: tenantExpected{ + errorMessage: `does not have capability "can_admin_scatter"`, + }, queryClusterSetting: sql.SecondaryTenantScatterEnabled, + queryCapability: tenantcapabilities.CanAdminScatter, }, { desc: "ALTER INDEX x SCATTER", @@ -585,7 +589,11 @@ func TestMultiTenantAdminFunction(t *testing.T) { secondaryWithoutClusterSetting: tenantExpected{ errorMessage: "tenant cluster setting sql.scatter.allow_for_secondary_tenant.enabled disabled", }, + secondaryWithoutCapability: tenantExpected{ + errorMessage: `does not have capability "can_admin_scatter"`, + }, queryClusterSetting: sql.SecondaryTenantScatterEnabled, + queryCapability: tenantcapabilities.CanAdminScatter, }, } @@ -634,13 +642,13 @@ func TestTruncateTable(t *testing.T) { }, }, secondaryWithoutCapability: tenantExpected{ - result: [][]string{ - {"", "…/104/2/1"}, - {"…/104/2/1", ""}, - }, + // CanAdminScatter will default to true so this will open happen if it is + // set to false. + errorMessage: `does not have capability "can_admin_scatter"`, }, setupClusterSetting: sql.SecondaryTenantSplitAtEnabled, setupCapability: tenantcapabilities.CanAdminSplit, + queryCapability: tenantcapabilities.CanAdminScatter, } tc.runTest( t, @@ -651,10 +659,15 @@ func TestTruncateTable(t *testing.T) { require.NoErrorf(t, err, message) _, err = db.ExecContext(ctx, "ALTER TABLE t SPLIT AT VALUES (1);") require.NoErrorf(t, err, message) - _, err = db.ExecContext(ctx, "TRUNCATE TABLE t;") - require.NoErrorf(t, err, message) - rows, err := db.QueryContext(ctx, "SELECT start_key, end_key from [SHOW RANGES FROM INDEX t@primary];") - expected.validate(t, rows, err, message) + + // validateErr and validateRows come from separate queries for TRUNCATE. + _, validateErr := db.ExecContext(ctx, "TRUNCATE TABLE t;") + var validateRows *gosql.Rows + if err == nil { + validateRows, err = db.QueryContext(ctx, "SELECT start_key, end_key from [SHOW RANGES FROM INDEX t@primary];") + require.NoErrorf(t, err, message) + } + expected.validate(t, validateRows, validateErr, message) }, ) }