Skip to content

Commit

Permalink
base, licenseccl: Revise resolution strategy for LicenseTTL
Browse files Browse the repository at this point in the history
Previously, for resolving the cluster's license expiry we relied on a metric
whose value was regularly ticked down by an async task. This change seeks to
only the resolve value at read time by reading directly from the cluster
settings when its requested.

Release note: None

Fixes: cockroachdb#77376
Part of: https://cockroachlabs.atlassian.net/browse/DOC-1355
Informs: cockroachdb#33316
Epic: CRDB-8035
  • Loading branch information
angles-n-daemons committed Aug 19, 2024
1 parent b903b22 commit 41d78d7
Show file tree
Hide file tree
Showing 8 changed files with 24 additions and 63 deletions.
21 changes: 7 additions & 14 deletions pkg/base/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (

"github.com/cockroachdb/cockroach/pkg/settings/cluster"
"github.com/cockroachdb/cockroach/pkg/util/metric"
"github.com/cockroachdb/cockroach/pkg/util/stop"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
"github.com/cockroachdb/errors"
)
Expand All @@ -39,7 +38,7 @@ var CCLDistributionAndEnterpriseEnabled = func(st *cluster.Settings) bool {
return CheckEnterpriseEnabled(st, "" /* feature */) == nil
}

var licenseTTLMetadata = metric.Metadata{
var LicenseTTLMetadata = metric.Metadata{
// This metric name isn't namespaced for backwards
// compatibility. The prior version of this metric was manually
// inserted into the prometheus output
Expand All @@ -49,21 +48,15 @@ var licenseTTLMetadata = metric.Metadata{
Unit: metric.Unit_SECONDS,
}

// LicenseTTL is a metric gauge that measures the number of seconds
// until the current enterprise license (if any) expires.
var LicenseTTL = metric.NewGauge(licenseTTLMetadata)

// UpdateMetricOnLicenseChange is a function that's called on startup
// in order to connect the enterprise license setting update to the
// prometheus metric provided as an argument.
var UpdateMetricOnLicenseChange = func(
// GetLicenseTTL is a function which returns the TTL for the active cluster.
// The implementation here returns 0, but if utilccl is started this function is
// overridden with an appropriate getter.
var GetLicenseTTL = func(
ctx context.Context,
st *cluster.Settings,
metric *metric.Gauge,
ts timeutil.TimeSource,
stopper *stop.Stopper,
) error {
return nil
) int64 {
return 0
}

// LicenseType returns what type of license the cluster is running with, or
Expand Down
2 changes: 1 addition & 1 deletion pkg/ccl/ccl_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func init() {
// this `ccl` pkg.
base.CheckEnterpriseEnabled = utilccl.CheckEnterpriseEnabled
base.LicenseType = utilccl.GetLicenseType
base.UpdateMetricOnLicenseChange = utilccl.UpdateMetricOnLicenseChange
base.GetLicenseTTL = utilccl.GetLicenseTTL
server.ApplyTenantLicense = utilccl.ApplyTenantLicense
}

Expand Down
2 changes: 0 additions & 2 deletions pkg/ccl/utilccl/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ go_library(
"//pkg/sql/sem/tree",
"//pkg/util/envutil",
"//pkg/util/log",
"//pkg/util/metric",
"//pkg/util/stop",
"//pkg/util/timeutil",
"@com_github_cockroachdb_errors//:errors",
"@com_github_cockroachdb_redact//:redact",
Expand Down
45 changes: 9 additions & 36 deletions pkg/ccl/utilccl/license_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
"github.com/cockroachdb/cockroach/pkg/util/envutil"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/metric"
"github.com/cockroachdb/cockroach/pkg/util/stop"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
"github.com/cockroachdb/errors"
"github.com/cockroachdb/redact"
Expand Down Expand Up @@ -145,49 +143,24 @@ func IsEnterpriseEnabled(st *cluster.Settings, feature string) bool {
st, timeutil.Now(), feature, false /* withDetails */) == nil
}

var licenseMetricUpdateFrequency = 1 * time.Minute

// UpdateMetricOnLicenseChange starts a task to periodically update
// the given metric with the seconds remaining until license expiry.
func UpdateMetricOnLicenseChange(
// GetLicenseTTL is a function which returns the TTL for the active cluster.
// This is done by reading the license information from the cluster settings
// and subtracting the epoch from the expiry timestamp.
var GetLicenseTTL = func(
ctx context.Context,
st *cluster.Settings,
metric *metric.Gauge,
ts timeutil.TimeSource,
stopper *stop.Stopper,
) error {
enterpriseLicense.SetOnChange(&st.SV, func(ctx context.Context) {
updateMetricWithLicenseTTL(ctx, st, metric, ts)
})
return stopper.RunAsyncTask(ctx, "write-license-expiry-metric", func(ctx context.Context) {
ticker := time.NewTicker(licenseMetricUpdateFrequency)
defer ticker.Stop()
for {
select {
case <-ticker.C:
updateMetricWithLicenseTTL(ctx, st, metric, ts)
case <-stopper.ShouldQuiesce():
return
}
}
})
}

func updateMetricWithLicenseTTL(
ctx context.Context, st *cluster.Settings, metric *metric.Gauge, ts timeutil.TimeSource,
) {
) int64 {
license, err := getLicense(st)
if err != nil {
log.Errorf(ctx, "unable to update license expiry metric: %v", err)
metric.Update(0)
return
log.Errorf(ctx, "unable to find license: %v", err)
return 0
}
if license == nil {
metric.Update(0)
return
return 0
}
sec := timeutil.Unix(license.ValidUntilUnixSec, 0).Sub(ts.Now()).Seconds()
metric.Update(int64(sec))
return int64(sec)
}

// AllCCLCodeImported is set by the `ccl` pkg in an init(), thereby
Expand Down
5 changes: 1 addition & 4 deletions pkg/ccl/utilccl/license_check_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,6 @@ func TestTimeToEnterpriseLicenseExpiry(t *testing.T) {
defer stopper.Stop(ctx)
manualTime := timeutil.NewManualTime(t0)

err := UpdateMetricOnLicenseChange(context.Background(), st, base.LicenseTTL, manualTime, stopper)
require.NoError(t, err)

for _, tc := range []struct {
desc string
lic string
Expand All @@ -195,7 +192,7 @@ func TestTimeToEnterpriseLicenseExpiry(t *testing.T) {
if err := setLicense(ctx, updater, tc.lic); err != nil {
t.Fatal(err)
}
actual := base.LicenseTTL.Value()
actual := base.GetLicenseTTL(context.Background(), st, manualTime)
require.Equal(t, tc.ttlSeconds, actual)
})
}
Expand Down
8 changes: 3 additions & 5 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,11 +419,9 @@ func NewServer(cfg Config, stopper *stop.Stopper) (serverctl.ServerStartupInterf
// started via the server controller.
cfg.RuntimeStatSampler = runtimeSampler

appRegistry.AddMetric(base.LicenseTTL)
err = base.UpdateMetricOnLicenseChange(ctx, cfg.Settings, base.LicenseTTL, timeutil.DefaultTimeSource{}, stopper)
if err != nil {
log.Errorf(ctx, "unable to initialize periodic license metric update: %v", err)
}
appRegistry.AddMetric(metric.NewFunctionalGauge(base.LicenseTTLMetadata, func() int64 {
return base.GetLicenseTTL(ctx, cfg.Settings, timeutil.DefaultTimeSource{})
}))

// Create and add KV metric rules.
kvserver.CreateAndAddRules(ctx, ruleRegistry)
Expand Down
1 change: 1 addition & 0 deletions pkg/ui/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ go_library(
"//pkg/settings/cluster",
"//pkg/util/httputil",
"//pkg/util/log",
"//pkg/util/timeutil",
],
)

Expand Down
3 changes: 2 additions & 1 deletion pkg/ui/ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/settings/cluster"
"github.com/cockroachdb/cockroach/pkg/util/httputil"
"github.com/cockroachdb/cockroach/pkg/util/log"
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
)

const (
Expand Down Expand Up @@ -168,7 +169,7 @@ func Handler(cfg Config) http.Handler {
if err != nil {
log.Errorf(context.Background(), "unable to get license type: %+v", err)
}
licenseTTL := base.LicenseTTL.Value()
licenseTTL := base.GetLicenseTTL(r.Context(), cfg.Settings, timeutil.DefaultTimeSource{})
oidcConf := cfg.OIDC.GetOIDCConf()
major, minor := build.BranchReleaseSeries()
args := indexHTMLArgs{
Expand Down

0 comments on commit 41d78d7

Please sign in to comment.