Skip to content

Commit 5a0bf15

Browse files
committed
add HasLicense field to Options and update UsageChecker
1 parent e184cf4 commit 5a0bf15

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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy