-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
multitenant: add SQL server startup guardrails
This code change prevents a SQL server from starting if its binary version is less than the tenant's active version. It makes `RowDecoder.DecodeRow` thread safe by making it accept a `*tree.DatumAlloc` and use a new alloc if its nil. The check runs after we run permanent upgrades because that's when the version setting is written to the settings table of the system tenant (and we want to apply this check to both system and secondary tenants). To guard against future changes to where we set the version, if GetClusterVersionFromStorage doesn't find a value for the version setting it will return an error because this means the version is not set yet. Release note: None Epic: CRDB-10829
- Loading branch information
healthy-pod
committed
Jan 31, 2023
1 parent
58762ac
commit 6093dd3
Showing
15 changed files
with
274 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// Copyright 2023 The Cockroach Authors. | ||
// | ||
// Licensed as a CockroachDB Enterprise file under the Cockroach Community | ||
// License (the "License"); you may not use this file except in compliance with | ||
// the License. You may obtain a copy of the License at | ||
// | ||
// https://github.com/cockroachdb/cockroach/blob/master/licenses/CCL.txt | ||
|
||
package serverccl | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/cockroachdb/cockroach/pkg/base" | ||
"github.com/cockroachdb/cockroach/pkg/clusterversion" | ||
"github.com/cockroachdb/cockroach/pkg/roachpb" | ||
"github.com/cockroachdb/cockroach/pkg/server" | ||
"github.com/cockroachdb/cockroach/pkg/settings/cluster" | ||
"github.com/cockroachdb/cockroach/pkg/sql/sem/eval" | ||
"github.com/cockroachdb/cockroach/pkg/testutils" | ||
"github.com/cockroachdb/cockroach/pkg/testutils/serverutils" | ||
"github.com/cockroachdb/cockroach/pkg/util/leaktest" | ||
) | ||
|
||
// TestServerStartupGuardrails ensures that a SQL server will fail to start if | ||
// its binary version (TBV) is less than the tenant's logical version (TLV). | ||
func TestServerStartupGuardrails(t *testing.T) { | ||
defer leaktest.AfterTest(t)() | ||
|
||
v := func(major, minor int32) roachpb.Version { | ||
return roachpb.Version{Major: clusterversion.DevOffset + major, Minor: minor} | ||
} | ||
|
||
tests := []struct { | ||
storageBinaryVersion roachpb.Version | ||
storageBinaryMinSupportedVersion roachpb.Version | ||
tenantBinaryVersion roachpb.Version | ||
tenantBinaryMinSupportedVersion roachpb.Version | ||
TenantLogicalVersionKey clusterversion.Key | ||
expErrMatch string // empty if expecting a nil error | ||
}{ | ||
// First test case ensures that a tenant server can start if the server binary | ||
// version is not too low for the tenant logical version. | ||
{ | ||
storageBinaryVersion: v(22, 2), | ||
storageBinaryMinSupportedVersion: v(22, 1), | ||
tenantBinaryVersion: v(22, 2), | ||
tenantBinaryMinSupportedVersion: v(22, 2), | ||
TenantLogicalVersionKey: clusterversion.V22_2, | ||
expErrMatch: "", | ||
}, | ||
// Second test case ensures that a tenant server is prevented from starting if | ||
// its binary version is too low for the current tenant logical version. | ||
{ | ||
storageBinaryVersion: v(22, 2), | ||
storageBinaryMinSupportedVersion: v(22, 1), | ||
tenantBinaryVersion: v(22, 1), | ||
tenantBinaryMinSupportedVersion: v(21, 2), | ||
TenantLogicalVersionKey: clusterversion.V22_2, | ||
expErrMatch: fmt.Sprintf("preventing SQL server from starting because its binary version is too low for the tenant active version: "+ | ||
"server binary version = %v, tenant active version = %v", v(22, 1), v(22, 2)), | ||
}, | ||
} | ||
|
||
for i, test := range tests { | ||
storageSettings := cluster.MakeTestingClusterSettingsWithVersions( | ||
test.storageBinaryVersion, | ||
test.storageBinaryMinSupportedVersion, | ||
false, /* initializeVersion */ | ||
) | ||
|
||
s, _, _ := serverutils.StartServer(t, base.TestServerArgs{ | ||
// Disable the default test tenant, since we create one explicitly | ||
// below. | ||
DisableDefaultTestTenant: true, | ||
Settings: storageSettings, | ||
Knobs: base.TestingKnobs{ | ||
Server: &server.TestingKnobs{ | ||
BinaryVersionOverride: test.storageBinaryVersion, | ||
DisableAutomaticVersionUpgrade: make(chan struct{}), | ||
}, | ||
SQLEvalContext: &eval.TestingKnobs{ | ||
TenantLogicalVersionKeyOverride: test.TenantLogicalVersionKey, | ||
}, | ||
}, | ||
}) | ||
|
||
tenantSettings := cluster.MakeTestingClusterSettingsWithVersions( | ||
test.tenantBinaryVersion, | ||
test.tenantBinaryMinSupportedVersion, | ||
true, /* initializeVersion */ | ||
) | ||
|
||
// The tenant will be created with an active version equal to the version | ||
// corresponding to TenantLogicalVersionKey. Tenant creation is expected | ||
// to succeed for all test cases but server creation is expected to succeed | ||
// only if tenantBinaryVersion is at least equal to the version corresponding | ||
// to TenantLogicalVersionKey. | ||
tenantServer, err := s.StartTenant(context.Background(), | ||
base.TestTenantArgs{ | ||
Settings: tenantSettings, | ||
TenantID: serverutils.TestTenantID(), | ||
TestingKnobs: base.TestingKnobs{ | ||
Server: &server.TestingKnobs{ | ||
BinaryVersionOverride: test.tenantBinaryVersion, | ||
DisableAutomaticVersionUpgrade: make(chan struct{}), | ||
}, | ||
}, | ||
}) | ||
|
||
if !testutils.IsError(err, test.expErrMatch) { | ||
t.Fatalf("test %d: got error %s, wanted error matching '%s'", i, err, test.expErrMatch) | ||
} | ||
|
||
// Only attempt to stop the tenant if it was started successfully. | ||
if err == nil { | ||
tenantServer.Stopper().Stop(context.Background()) | ||
} | ||
s.Stopper().Stop(context.Background()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.