Skip to content

Commit 1e0f0e5

Browse files
committed
add HasLicense field to Options and update UsageChecker
1 parent c89d618 commit 1e0f0e5

File tree

2 files changed

+33
-38
lines changed

2 files changed

+33
-38
lines changed

coderd/coderd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ type Options struct {
180180
// Entitlements can come from the enterprise caller if enterprise code is
181181
// included.
182182
Entitlements *entitlements.Set
183+
// HasLicense indicates if a license is installed.
184+
HasLicense bool
183185
// PostAuthAdditionalHeadersFunc is used to add additional headers to the response
184186
// after a successful authentication.
185187
// This is somewhat janky, but seemingly the only reasonable way to add a header

enterprise/coderd/coderd.go

Lines changed: 31 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,8 @@ func (api *API) updateEntitlements(ctx context.Context) error {
739739
return codersdk.Entitlements{}, err
740740
}
741741

742+
api.HasLicense = reloadedEntitlements.HasLicense
743+
742744
if reloadedEntitlements.RequireTelemetry && !api.DeploymentValues.Telemetry.Enable.Value() {
743745
api.Logger.Error(ctx, "license requires telemetry enabled")
744746
return codersdk.Entitlements{}, entitlements.ErrLicenseRequiresTelemetry
@@ -929,17 +931,9 @@ func (api *API) updateEntitlements(ctx context.Context) error {
929931
}
930932
reloadedEntitlements.Features[codersdk.FeatureExternalTokenEncryption] = featureExternalTokenEncryption
931933

932-
// If there's a license installed, we will use the enterprise build
933-
// limit checker.
934-
// This checker currently only enforces the managed agent limit.
935-
if reloadedEntitlements.HasLicense {
936-
var checker wsbuilder.UsageChecker = api
937-
api.AGPL.BuildUsageChecker.Store(&checker)
938-
} else {
939-
// Don't check any usage, just like AGPL.
940-
var checker wsbuilder.UsageChecker = wsbuilder.NoopUsageChecker{}
941-
api.AGPL.BuildUsageChecker.Store(&checker)
942-
}
934+
// Always use the enterprise usage checker
935+
var checker wsbuilder.UsageChecker = api
936+
api.AGPL.BuildUsageChecker.Store(&checker)
943937

944938
return reloadedEntitlements, nil
945939
})
@@ -948,10 +942,6 @@ func (api *API) updateEntitlements(ctx context.Context) error {
948942
var _ wsbuilder.UsageChecker = &API{}
949943

950944
func (api *API) CheckBuildUsage(ctx context.Context, store database.Store, templateVersion *database.TemplateVersion) (wsbuilder.UsageCheckResponse, error) {
951-
// We assume that if this function is called, a valid license is installed.
952-
// When there are no licenses installed, a noop usage checker is used
953-
// instead.
954-
955945
// If the template version has an external agent, we need to check that the
956946
// license is entitled to this feature.
957947
if templateVersion.HasExternalAgent.Valid && templateVersion.HasExternalAgent.Bool {
@@ -972,32 +962,35 @@ func (api *API) CheckBuildUsage(ctx context.Context, store database.Store, templ
972962
}, nil
973963
}
974964

975-
// Otherwise, we need to check that we haven't breached the managed agent
965+
// When unlicensed, we need to check that we haven't breached the managed agent
976966
// limit.
977-
managedAgentLimit, ok := api.Entitlements.Feature(codersdk.FeatureManagedAgentLimit)
978-
if !ok || !managedAgentLimit.Enabled || managedAgentLimit.Limit == nil || managedAgentLimit.UsagePeriod == nil {
979-
return wsbuilder.UsageCheckResponse{
980-
Permitted: false,
981-
Message: "Your license is not entitled to managed agents. Please contact sales to continue using managed agents.",
982-
}, nil
983-
}
967+
// Unlicensed deployments are allowed to use unlimited managed agents.
968+
if api.HasLicense {
969+
managedAgentLimit, ok := api.Entitlements.Feature(codersdk.FeatureManagedAgentLimit)
970+
if !ok || !managedAgentLimit.Enabled || managedAgentLimit.Limit == nil || managedAgentLimit.UsagePeriod == nil {
971+
return wsbuilder.UsageCheckResponse{
972+
Permitted: false,
973+
Message: "Your license is not entitled to managed agents. Please contact sales to continue using managed agents.",
974+
}, nil
975+
}
984976

985-
// This check is intentionally not committed to the database. It's fine if
986-
// it's not 100% accurate or allows for minor breaches due to build races.
987-
// nolint:gocritic // Requires permission to read all workspaces to read managed agent count.
988-
managedAgentCount, err := store.GetManagedAgentCount(agpldbauthz.AsSystemRestricted(ctx), database.GetManagedAgentCountParams{
989-
StartTime: managedAgentLimit.UsagePeriod.Start,
990-
EndTime: managedAgentLimit.UsagePeriod.End,
991-
})
992-
if err != nil {
993-
return wsbuilder.UsageCheckResponse{}, xerrors.Errorf("get managed agent count: %w", err)
994-
}
977+
// This check is intentionally not committed to the database. It's fine if
978+
// it's not 100% accurate or allows for minor breaches due to build races.
979+
// nolint:gocritic // Requires permission to read all workspaces to read managed agent count.
980+
managedAgentCount, err := store.GetManagedAgentCount(agpldbauthz.AsSystemRestricted(ctx), database.GetManagedAgentCountParams{
981+
StartTime: managedAgentLimit.UsagePeriod.Start,
982+
EndTime: managedAgentLimit.UsagePeriod.End,
983+
})
984+
if err != nil {
985+
return wsbuilder.UsageCheckResponse{}, xerrors.Errorf("get managed agent count: %w", err)
986+
}
995987

996-
if managedAgentCount >= *managedAgentLimit.Limit {
997-
return wsbuilder.UsageCheckResponse{
998-
Permitted: false,
999-
Message: "You have breached the managed agent limit in your license. Please contact sales to continue using managed agents.",
1000-
}, nil
988+
if managedAgentCount >= *managedAgentLimit.Limit {
989+
return wsbuilder.UsageCheckResponse{
990+
Permitted: false,
991+
Message: "You have breached the managed agent limit in your license. Please contact sales to continue using managed agents.",
992+
}, nil
993+
}
1001994
}
1002995

1003996
return wsbuilder.UsageCheckResponse{

0 commit comments

Comments
 (0)