Skip to content

Commit

Permalink
mt_start_sql: enable enterprise features for multitenant sql servers
Browse files Browse the repository at this point in the history
Enterprise features are controlled by the enterprise.license setting.
Currently this setting applies only to the host tenant cluster. This
change enables enterprise features for all tenant clusters. Enabling
enterprise features for all tenants is reasonable, because multi tenant
deployments are an enterprise feature.

Release note: None
  • Loading branch information
jeffswenson committed Aug 19, 2021
1 parent e3d9851 commit 7850559
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 15 deletions.
16 changes: 16 additions & 0 deletions pkg/ccl/serverccl/server_sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,22 @@ func TestTenantCannotSetClusterSetting(t *testing.T) {
require.Equal(t, pq.ErrorCode(pgcode.InsufficientPrivilege.String()), pqErr.Code, "err %v has unexpected code", err)
}

func TestTenantCanUseEnterpriseFeatures(t *testing.T) {
defer leaktest.AfterTest(t)()
defer log.Scope(t).Close(t)

tc := serverutils.StartNewTestCluster(t, 1, base.TestClusterArgs{})
defer tc.Stopper().Stop(context.Background())

_, db := serverutils.StartTenant(t, tc.Server(0), base.TestTenantArgs{TenantID: serverutils.TestTenantID(), AllowSettingClusterSettings: false})
defer db.Close()

_, err := db.Exec(`BACKUP INTO 'userfile:///backup'`)
require.NoError(t, err)
_, err = db.Exec(`BACKUP INTO LATEST IN 'userfile:///backup'`)
require.NoError(t, err)
}

func TestTenantUnauthenticatedAccess(t *testing.T) {
defer leaktest.AfterTest(t)()
defer log.Scope(t).Close(t)
Expand Down
1 change: 1 addition & 0 deletions pkg/ccl/utilccl/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ go_library(
"//pkg/base",
"//pkg/ccl/utilccl/licenseccl",
"//pkg/kv/kvclient/kvcoord:with-mocks",
"//pkg/server",
"//pkg/settings",
"//pkg/settings/cluster",
"//pkg/sql/catalog/colinfo",
Expand Down
38 changes: 23 additions & 15 deletions pkg/ccl/utilccl/license_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

"github.com/cockroachdb/cockroach/pkg/base"
"github.com/cockroachdb/cockroach/pkg/ccl/utilccl/licenseccl"
"github.com/cockroachdb/cockroach/pkg/server"
"github.com/cockroachdb/cockroach/pkg/settings"
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
Expand Down Expand Up @@ -45,16 +46,13 @@ var enterpriseLicense = func() *settings.StringSetting {
return s
}()

// testingEnterprise determines whether the cluster is enabled
// or disabled for the purposes of testing.
// It should be loaded and stored using atomic as it can race with an
// in progress kv reader during TestingDisableEnterprise /
// TestingEnableEnterprise.
var testingEnterprise int32
// enterpriseStatus determines whether the cluster is enabled
// for enterprise features or if enterprise status depends on the license.
var enterpriseStatus int32 = deferToLicense

const (
testingEnterpriseDisabled = 0
testingEnterpriseEnabled = 1
deferToLicense = 0
enterpriseEnabled = 1
)

// errEnterpriseRequired is returned by check() when the caller does
Expand All @@ -68,22 +66,31 @@ type licenseCacheKey string

// TestingEnableEnterprise allows overriding the license check in tests.
func TestingEnableEnterprise() func() {
before := atomic.LoadInt32(&testingEnterprise)
atomic.StoreInt32(&testingEnterprise, testingEnterpriseEnabled)
before := atomic.LoadInt32(&enterpriseStatus)
atomic.StoreInt32(&enterpriseStatus, enterpriseEnabled)
return func() {
atomic.StoreInt32(&testingEnterprise, before)
atomic.StoreInt32(&enterpriseStatus, before)
}
}

// TestingDisableEnterprise allows re-enabling the license check in tests.
func TestingDisableEnterprise() func() {
before := atomic.LoadInt32(&testingEnterprise)
atomic.StoreInt32(&testingEnterprise, testingEnterpriseDisabled)
before := atomic.LoadInt32(&enterpriseStatus)
atomic.StoreInt32(&enterpriseStatus, deferToLicense)
return func() {
atomic.StoreInt32(&testingEnterprise, before)
atomic.StoreInt32(&enterpriseStatus, before)
}
}

// EnableEnterpriseWithImpliedLicense enables enterprise features without
// setting a license. This is used by the multi tenant sql server. Multitenany
// is an enterprise feature, so it is not necessary to install a license within
// a the tenant cluster. The existence of the multi tenant cluster implies the
// host cluster has an enterprise license enabled.
func EnableEnterpriseWithImpliedLicense() {
atomic.StoreInt32(&enterpriseStatus, enterpriseEnabled)
}

// CheckEnterpriseEnabled returns a non-nil error if the requested enterprise
// feature is not enabled, including information or a link explaining how to
// enable it.
Expand All @@ -108,6 +115,7 @@ func init() {
base.CheckEnterpriseEnabled = CheckEnterpriseEnabled
base.LicenseType = getLicenseType
base.TimeToEnterpriseLicenseExpiry = TimeToEnterpriseLicenseExpiry
server.EnableEnterpriseForTenant = EnableEnterpriseWithImpliedLicense
}

// TimeToEnterpriseLicenseExpiry returns a Duration from `asOf` until the current
Expand All @@ -128,7 +136,7 @@ func TimeToEnterpriseLicenseExpiry(
func checkEnterpriseEnabledAt(
st *cluster.Settings, at time.Time, cluster uuid.UUID, org, feature string, withDetails bool,
) error {
if atomic.LoadInt32(&testingEnterprise) == testingEnterpriseEnabled {
if atomic.LoadInt32(&enterpriseStatus) == enterpriseEnabled {
return nil
}
license, err := getLicense(st)
Expand Down
14 changes: 14 additions & 0 deletions pkg/ccl/utilccl/license_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,17 @@ func TestTimeToEnterpriseLicenseExpiry(t *testing.T) {
})
}
}

func TestEnableEnterpriseWithImpliedLicense(t *testing.T) {
settings := cluster.MakeClusterSettings()

require.Error(t, CheckEnterpriseEnabled(settings, uuid.MakeV4(), "", ""))
require.False(t, IsEnterpriseEnabled(settings, uuid.MakeV4(), "", ""))
EnableEnterpriseWithImpliedLicense()
require.NoError(t, CheckEnterpriseEnabled(settings, uuid.MakeV4(), "", ""))
require.True(t, IsEnterpriseEnabled(settings, uuid.MakeV4(), "", ""))

// Clean up license setting
_ = TestingDisableEnterprise()
require.False(t, IsEnterpriseEnabled(settings, uuid.MakeV4(), "", ""))
}
5 changes: 5 additions & 0 deletions pkg/server/tenant.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ func StartTenant(
baseCfg BaseConfig,
sqlCfg SQLConfig,
) (sqlServer *SQLServer, pgAddr string, httpAddr string, _ error) {
EnableEnterpriseForTenant()
args, err := makeTenantSQLServerArgs(stopper, kvClusterName, baseCfg, sqlCfg)
if err != nil {
return nil, "", "", err
Expand Down Expand Up @@ -405,6 +406,10 @@ var NewTenantSideCostController = func(
return noopTenantSideCostController{}, nil
}

// EnableEnterpriseForTenant is a hook for CCL code which enables enterprise
// features for the tenant process.
var EnableEnterpriseForTenant = func() { /* no-op */ }

// noopTenantSideCostController is a no-op implementation of
// TenantSideCostController.
type noopTenantSideCostController struct{}
Expand Down

0 comments on commit 7850559

Please sign in to comment.