@@ -3,6 +3,7 @@ package license
3
3
import (
4
4
"context"
5
5
"crypto/ed25519"
6
+ "database/sql"
6
7
"fmt"
7
8
"math"
8
9
"time"
@@ -94,10 +95,34 @@ func Entitlements(
94
95
return codersdk.Entitlements {}, xerrors .Errorf ("query active user count: %w" , err )
95
96
}
96
97
98
+ // nolint:gocritic // Getting external workspaces is a system function.
99
+ externalWorkspaces , err := db .GetWorkspaces (dbauthz .AsSystemRestricted (ctx ), database.GetWorkspacesParams {
100
+ HasExternalAgent : sql.NullBool {
101
+ Bool : true ,
102
+ Valid : true ,
103
+ },
104
+ })
105
+ if err != nil {
106
+ return codersdk.Entitlements {}, xerrors .Errorf ("query external workspaces: %w" , err )
107
+ }
108
+
109
+ // nolint:gocritic // Getting external templates is a system function.
110
+ externalTemplates , err := db .GetTemplatesWithFilter (dbauthz .AsSystemRestricted (ctx ), database.GetTemplatesWithFilterParams {
111
+ HasExternalAgent : sql.NullBool {
112
+ Bool : true ,
113
+ Valid : true ,
114
+ },
115
+ })
116
+ if err != nil {
117
+ return codersdk.Entitlements {}, xerrors .Errorf ("query external templates: %w" , err )
118
+ }
119
+
97
120
entitlements , err := LicensesEntitlements (ctx , now , licenses , enablements , keys , FeatureArguments {
98
- ActiveUserCount : activeUserCount ,
99
- ReplicaCount : replicaCount ,
100
- ExternalAuthCount : externalAuthCount ,
121
+ ActiveUserCount : activeUserCount ,
122
+ ReplicaCount : replicaCount ,
123
+ ExternalAuthCount : externalAuthCount ,
124
+ ExternalWorkspaceCount : int64 (len (externalWorkspaces )),
125
+ ExternalTemplateCount : int64 (len (externalTemplates )),
101
126
ManagedAgentCountFn : func (ctx context.Context , startTime time.Time , endTime time.Time ) (int64 , error ) {
102
127
// nolint:gocritic // Requires permission to read all workspaces to read managed agent count.
103
128
return db .GetManagedAgentCount (dbauthz .AsSystemRestricted (ctx ), database.GetManagedAgentCountParams {
@@ -114,9 +139,11 @@ func Entitlements(
114
139
}
115
140
116
141
type FeatureArguments struct {
117
- ActiveUserCount int64
118
- ReplicaCount int
119
- ExternalAuthCount int
142
+ ActiveUserCount int64
143
+ ReplicaCount int
144
+ ExternalAuthCount int
145
+ ExternalWorkspaceCount int64
146
+ ExternalTemplateCount int64
120
147
// Unfortunately, managed agent count is not a simple count of the current
121
148
// state of the world, but a count between two points in time determined by
122
149
// the licenses.
@@ -418,6 +445,30 @@ func LicensesEntitlements(
418
445
}
419
446
}
420
447
448
+ if featureArguments .ExternalWorkspaceCount > 0 {
449
+ feature := entitlements .Features [codersdk .FeatureWorkspaceExternalAgent ]
450
+ switch feature .Entitlement {
451
+ case codersdk .EntitlementNotEntitled :
452
+ entitlements .Errors = append (entitlements .Errors ,
453
+ "You have external workspaces but your license is not entitled to this feature." )
454
+ case codersdk .EntitlementGracePeriod :
455
+ entitlements .Warnings = append (entitlements .Warnings ,
456
+ "You have external workspaces but your license is expired." )
457
+ }
458
+ }
459
+
460
+ if featureArguments .ExternalTemplateCount > 0 {
461
+ feature := entitlements .Features [codersdk .FeatureWorkspaceExternalAgent ]
462
+ switch feature .Entitlement {
463
+ case codersdk .EntitlementNotEntitled :
464
+ entitlements .Errors = append (entitlements .Errors ,
465
+ "You have templates which use external agents but your license is not entitled to this feature." )
466
+ case codersdk .EntitlementGracePeriod :
467
+ entitlements .Warnings = append (entitlements .Warnings ,
468
+ "You have templates which use external agents but your license is expired." )
469
+ }
470
+ }
471
+
421
472
// Managed agent warnings are applied based on usage period. We only
422
473
// generate a warning if the license actually has managed agents.
423
474
// Note that agents are free when unlicensed.
0 commit comments