Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 93eef7b

Browse files
authored
chore: keep entitlements in the options only, simplify fields (#14434)
* chore: refactor entitlements to keep it in just the options Duplicating the reference did not feel valuable, just confusing
1 parent fb6b954 commit 93eef7b

11 files changed

+27
-25
lines changed

enterprise/coderd/coderd.go

+12-14
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
7575
// from when an additional replica was started.
7676
options.ReplicaErrorGracePeriod = time.Minute
7777
}
78+
if options.Entitlements == nil {
79+
options.Entitlements = entitlements.New()
80+
}
7881

7982
ctx, cancelFunc := context.WithCancel(ctx)
8083

@@ -105,25 +108,22 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
105108
return nil, xerrors.Errorf("init database encryption: %w", err)
106109
}
107110

108-
entitlementsSet := entitlements.New()
109111
options.Database = cryptDB
110112
api := &API{
111-
ctx: ctx,
112-
cancel: cancelFunc,
113-
Options: options,
114-
entitlements: entitlementsSet,
113+
ctx: ctx,
114+
cancel: cancelFunc,
115+
Options: options,
115116
provisionerDaemonAuth: &provisionerDaemonAuth{
116117
psk: options.ProvisionerDaemonPSK,
117118
authorizer: options.Authorizer,
118119
db: options.Database,
119120
},
120121
licenseMetricsCollector: &license.MetricsCollector{
121-
Entitlements: entitlementsSet,
122+
Entitlements: options.Entitlements,
122123
},
123124
}
124125
// This must happen before coderd initialization!
125126
options.PostAuthAdditionalHeadersFunc = api.writeEntitlementWarningsHeader
126-
options.Options.Entitlements = api.entitlements
127127
api.AGPL = coderd.New(options.Options)
128128
defer func() {
129129
if err != nil {
@@ -561,8 +561,6 @@ type API struct {
561561
// ProxyHealth checks the reachability of all workspace proxies.
562562
ProxyHealth *proxyhealth.ProxyHealth
563563

564-
entitlements *entitlements.Set
565-
566564
provisionerDaemonAuth *provisionerDaemonAuth
567565

568566
licenseMetricsCollector *license.MetricsCollector
@@ -595,7 +593,7 @@ func (api *API) writeEntitlementWarningsHeader(a rbac.Subject, header http.Heade
595593
return
596594
}
597595

598-
api.entitlements.WriteEntitlementWarningHeaders(header)
596+
api.Entitlements.WriteEntitlementWarningHeaders(header)
599597
}
600598

601599
func (api *API) Close() error {
@@ -658,7 +656,7 @@ func (api *API) updateEntitlements(ctx context.Context) error {
658656
//
659657
// We don't simply append to entitlement.Errors since we don't want any
660658
// enterprise features enabled.
661-
api.entitlements.Update(func(entitlements *codersdk.Entitlements) {
659+
api.Entitlements.Update(func(entitlements *codersdk.Entitlements) {
662660
entitlements.Errors = []string{
663661
"License requires telemetry but telemetry is disabled",
664662
}
@@ -669,7 +667,7 @@ func (api *API) updateEntitlements(ctx context.Context) error {
669667
}
670668

671669
featureChanged := func(featureName codersdk.FeatureName) (initial, changed, enabled bool) {
672-
return api.entitlements.FeatureChanged(featureName, reloadedEntitlements.Features[featureName])
670+
return api.Entitlements.FeatureChanged(featureName, reloadedEntitlements.Features[featureName])
673671
}
674672

675673
shouldUpdate := func(initial, changed, enabled bool) bool {
@@ -835,7 +833,7 @@ func (api *API) updateEntitlements(ctx context.Context) error {
835833
}
836834
reloadedEntitlements.Features[codersdk.FeatureExternalTokenEncryption] = featureExternalTokenEncryption
837835

838-
api.entitlements.Replace(reloadedEntitlements)
836+
api.Entitlements.Replace(reloadedEntitlements)
839837
return nil
840838
}
841839

@@ -1015,7 +1013,7 @@ func derpMapper(logger slog.Logger, proxyHealth *proxyhealth.ProxyHealth) func(*
10151013
// @Router /entitlements [get]
10161014
func (api *API) serveEntitlements(rw http.ResponseWriter, r *http.Request) {
10171015
ctx := r.Context()
1018-
httpapi.Write(ctx, rw, http.StatusOK, api.entitlements.AsJSON())
1016+
httpapi.Write(ctx, rw, http.StatusOK, api.Entitlements.AsJSON())
10191017
}
10201018

10211019
func (api *API) runEntitlementsLoop(ctx context.Context) {

enterprise/coderd/coderd_test.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package coderd_test
33
import (
44
"bytes"
55
"context"
6+
"fmt"
67
"net/http"
78
"reflect"
89
"strings"
@@ -46,14 +47,17 @@ func TestEntitlements(t *testing.T) {
4647
t.Parallel()
4748
t.Run("NoLicense", func(t *testing.T) {
4849
t.Parallel()
49-
adminClient, adminUser := coderdenttest.New(t, &coderdenttest.Options{
50+
adminClient, _, api, adminUser := coderdenttest.NewWithAPI(t, &coderdenttest.Options{
5051
DontAddLicense: true,
5152
})
5253
anotherClient, _ := coderdtest.CreateAnotherUser(t, adminClient, adminUser.OrganizationID)
5354
res, err := anotherClient.Entitlements(context.Background())
5455
require.NoError(t, err)
5556
require.False(t, res.HasLicense)
5657
require.Empty(t, res.Warnings)
58+
59+
// Ensure the entitlements are the same reference
60+
require.Equal(t, fmt.Sprintf("%p", api.Entitlements), fmt.Sprintf("%p", api.AGPL.Entitlements))
5761
})
5862
t.Run("FullLicense", func(t *testing.T) {
5963
// PGCoordinator requires a real postgres

enterprise/coderd/jfrog.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (api *API) jfrogEnabledMW(next http.Handler) http.Handler {
107107
// This doesn't actually use the external auth feature but we want
108108
// to lock this behind an enterprise license and it's somewhat
109109
// related to external auth (in that it is JFrog integration).
110-
if !api.entitlements.Enabled(codersdk.FeatureMultipleExternalAuth) {
110+
if !api.Entitlements.Enabled(codersdk.FeatureMultipleExternalAuth) {
111111
httpapi.RouteNotFound(rw)
112112
return
113113
}

enterprise/coderd/licenses.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (api *API) postRefreshEntitlements(rw http.ResponseWriter, r *http.Request)
189189

190190
// Prevent abuse by limiting how often we allow a forced refresh.
191191
now := time.Now()
192-
if ok, wait := api.entitlements.AllowRefresh(now); !ok {
192+
if ok, wait := api.Entitlements.AllowRefresh(now); !ok {
193193
rw.Header().Set("Retry-After", strconv.Itoa(int(wait.Seconds())))
194194
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
195195
Message: fmt.Sprintf("Entitlements already recently refreshed, please wait %d seconds to force a new refresh", int(wait.Seconds())),

enterprise/coderd/provisionerdaemons.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import (
3939

4040
func (api *API) provisionerDaemonsEnabledMW(next http.Handler) http.Handler {
4141
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
42-
if !api.entitlements.Enabled(codersdk.FeatureExternalProvisionerDaemons) {
42+
if !api.Entitlements.Enabled(codersdk.FeatureExternalProvisionerDaemons) {
4343
httpapi.Write(r.Context(), rw, http.StatusForbidden, codersdk.Response{
4444
Message: "External provisioner daemons is an Enterprise feature. Contact sales!",
4545
})

enterprise/coderd/scim.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import (
2525

2626
func (api *API) scimEnabledMW(next http.Handler) http.Handler {
2727
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
28-
if !api.entitlements.Enabled(codersdk.FeatureSCIM) {
28+
if !api.Entitlements.Enabled(codersdk.FeatureSCIM) {
2929
httpapi.RouteNotFound(rw)
3030
return
3131
}

enterprise/coderd/templates.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ func (api *API) RequireFeatureMW(feat codersdk.FeatureName) func(http.Handler) h
349349
return func(next http.Handler) http.Handler {
350350
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
351351
// Entitlement must be enabled.
352-
if !api.entitlements.Enabled(feat) {
352+
if !api.Entitlements.Enabled(feat) {
353353
licenseType := "a Premium"
354354
if feat.Enterprise() {
355355
licenseType = "an Enterprise"

enterprise/coderd/userauth.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414

1515
// nolint: revive
1616
func (api *API) setUserGroups(ctx context.Context, logger slog.Logger, db database.Store, userID uuid.UUID, orgGroupNames map[uuid.UUID][]string, createMissingGroups bool) error {
17-
if !api.entitlements.Enabled(codersdk.FeatureTemplateRBAC) {
17+
if !api.Entitlements.Enabled(codersdk.FeatureTemplateRBAC) {
1818
return nil
1919
}
2020

@@ -78,7 +78,7 @@ func (api *API) setUserGroups(ctx context.Context, logger slog.Logger, db databa
7878
}
7979

8080
func (api *API) setUserSiteRoles(ctx context.Context, logger slog.Logger, db database.Store, userID uuid.UUID, roles []string) error {
81-
if !api.entitlements.Enabled(codersdk.FeatureUserRoleManagement) {
81+
if !api.Entitlements.Enabled(codersdk.FeatureUserRoleManagement) {
8282
logger.Warn(ctx, "attempted to assign OIDC user roles without enterprise entitlement, roles left unchanged",
8383
slog.F("user_id", userID), slog.F("roles", roles),
8484
)

enterprise/coderd/users.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const TimeFormatHHMM = "15:04"
1818

1919
func (api *API) autostopRequirementEnabledMW(next http.Handler) http.Handler {
2020
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
21-
feature, ok := api.entitlements.Feature(codersdk.FeatureAdvancedTemplateScheduling)
21+
feature, ok := api.Entitlements.Feature(codersdk.FeatureAdvancedTemplateScheduling)
2222
if !ok || !feature.Entitlement.Entitled() {
2323
httpapi.Write(r.Context(), rw, http.StatusForbidden, codersdk.Response{
2424
Message: "Advanced template scheduling (and user quiet hours schedule) is an Enterprise feature. Contact sales!",

enterprise/coderd/workspaceagents.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
)
1010

1111
func (api *API) shouldBlockNonBrowserConnections(rw http.ResponseWriter) bool {
12-
if api.entitlements.Enabled(codersdk.FeatureBrowserOnly) {
12+
if api.Entitlements.Enabled(codersdk.FeatureBrowserOnly) {
1313
httpapi.Write(context.Background(), rw, http.StatusConflict, codersdk.Response{
1414
Message: "Non-browser connections are disabled for your deployment.",
1515
})

enterprise/coderd/workspacequota.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func (api *API) workspaceQuota(rw http.ResponseWriter, r *http.Request) {
155155
user = httpmw.UserParam(r)
156156
)
157157

158-
licensed := api.entitlements.Enabled(codersdk.FeatureTemplateRBAC)
158+
licensed := api.Entitlements.Enabled(codersdk.FeatureTemplateRBAC)
159159

160160
// There are no groups and thus no allowance if RBAC isn't licensed.
161161
var quotaAllowance int64 = -1

0 commit comments

Comments
 (0)