@@ -17,6 +17,17 @@ import (
17
17
)
18
18
19
19
const (
20
+ // These features are only included in the license and are not actually
21
+ // entitlements after the licenses are processed. These values will be
22
+ // merged into the codersdk.FeatureManagedAgentLimit feature.
23
+ //
24
+ // The reason we need two separate features is because the License v3 format
25
+ // uses map[string]int64 for features, so we're unable to use a single value
26
+ // with a struct like `{"soft": 100, "hard": 200}`. This is unfortunate and
27
+ // we should fix this with a new license format v4 in the future.
28
+ //
29
+ // These are intentionally not exported as they should not be used outside
30
+ // of this package (except tests).
20
31
featureManagedAgentLimitHard codersdk.FeatureName = "managed_agent_limit_hard"
21
32
featureManagedAgentLimitSoft codersdk.FeatureName = "managed_agent_limit_soft"
22
33
)
@@ -88,8 +99,9 @@ func Entitlements(
88
99
ActiveUserCount : activeUserCount ,
89
100
ReplicaCount : replicaCount ,
90
101
ExternalAuthCount : externalAuthCount ,
91
- ManagedAgentCountFn : func (ctx context.Context , from time.Time , to time.Time ) (int64 , error ) {
92
- // TODO: this
102
+ ManagedAgentCountFn : func (_ context.Context , _ time.Time , _ time.Time ) (int64 , error ) {
103
+ // TODO(@deansheather): replace this with a real implementation in a
104
+ // follow up PR.
93
105
return 0 , nil
94
106
},
95
107
})
@@ -107,9 +119,11 @@ type FeatureArguments struct {
107
119
// Unfortunately, managed agent count is not a simple count of the current
108
120
// state of the world, but a count between two points in time determined by
109
121
// the licenses.
110
- ManagedAgentCountFn func ( ctx context. Context , from time. Time , to time. Time ) ( int64 , error )
122
+ ManagedAgentCountFn ManagedAgentCountFn
111
123
}
112
124
125
+ type ManagedAgentCountFn func (ctx context.Context , from time.Time , to time.Time ) (int64 , error )
126
+
113
127
// LicensesEntitlements returns the entitlements for licenses. Entitlements are
114
128
// merged from all licenses and the highest entitlement is used for each feature.
115
129
// Arguments:
@@ -297,13 +311,15 @@ func LicensesEntitlements(
297
311
defaultHardAgentLimit = 1000 * featureValue
298
312
)
299
313
entitlements .AddFeature (codersdk .FeatureManagedAgentLimit , codersdk.Feature {
300
- Enabled : true ,
301
- Entitlement : entitlement ,
302
- SoftLimit : & defaultSoftAgentLimit ,
303
- Limit : & defaultHardAgentLimit ,
304
- UsagePeriodIssuedAt : & issueTime ,
305
- UsagePeriodStart : & usagePeriodStart ,
306
- UsagePeriodEnd : & usagePeriodEnd ,
314
+ Enabled : true ,
315
+ Entitlement : entitlement ,
316
+ SoftLimit : & defaultSoftAgentLimit ,
317
+ Limit : & defaultHardAgentLimit ,
318
+ UsagePeriod : & codersdk.UsagePeriod {
319
+ IssuedAt : issueTime ,
320
+ Start : usagePeriodStart ,
321
+ End : usagePeriodEnd ,
322
+ },
307
323
})
308
324
}
309
325
default :
@@ -342,11 +358,12 @@ func LicensesEntitlements(
342
358
Entitlement : entitlement ,
343
359
SoftLimit : ul .Soft ,
344
360
Limit : ul .Hard ,
345
- // Actual value will be populated below when warnings are
346
- // generated.
347
- UsagePeriodIssuedAt : & claims .IssuedAt .Time ,
348
- UsagePeriodStart : & usagePeriodStart ,
349
- UsagePeriodEnd : & usagePeriodEnd ,
361
+ // `Actual` will be populated below when warnings are generated.
362
+ UsagePeriod : & codersdk.UsagePeriod {
363
+ IssuedAt : claims .IssuedAt .Time ,
364
+ Start : usagePeriodStart ,
365
+ End : usagePeriodEnd ,
366
+ },
350
367
}
351
368
// If the hard limit is 0, the feature is disabled.
352
369
if * ul .Hard <= 0 {
@@ -404,15 +421,15 @@ func LicensesEntitlements(
404
421
// generate a warning if the license actually has managed agents.
405
422
// Note that agents are free when unlicensed.
406
423
agentLimit := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
407
- if entitlements .HasLicense && agentLimit .UsagePeriodStart != nil && agentLimit . UsagePeriodEnd != nil {
424
+ if entitlements .HasLicense && agentLimit .UsagePeriod != nil {
408
425
// Calculate the amount of agents between the usage period start and
409
426
// end.
410
427
var (
411
428
managedAgentCount int64
412
429
err = xerrors .New ("dev error: managed agent count function is not set" )
413
430
)
414
431
if featureArguments .ManagedAgentCountFn != nil {
415
- managedAgentCount , err = featureArguments .ManagedAgentCountFn (ctx , * agentLimit .UsagePeriodStart , * agentLimit .UsagePeriodEnd )
432
+ managedAgentCount , err = featureArguments .ManagedAgentCountFn (ctx , agentLimit .UsagePeriod . Start , agentLimit .UsagePeriod . End )
416
433
}
417
434
if err != nil {
418
435
entitlements .Errors = append (entitlements .Errors ,
@@ -421,30 +438,33 @@ func LicensesEntitlements(
421
438
agentLimit .Actual = & managedAgentCount
422
439
entitlements .AddFeature (codersdk .FeatureManagedAgentLimit , agentLimit )
423
440
424
- var softLimit int64
425
- if agentLimit .SoftLimit != nil {
426
- softLimit = * agentLimit .SoftLimit
427
- }
428
- var hardLimit int64
429
- if agentLimit .Limit != nil {
430
- hardLimit = * agentLimit .Limit
431
- }
441
+ // Only issue warnings if the feature is enabled.
442
+ if agentLimit .Enabled {
443
+ var softLimit int64
444
+ if agentLimit .SoftLimit != nil {
445
+ softLimit = * agentLimit .SoftLimit
446
+ }
447
+ var hardLimit int64
448
+ if agentLimit .Limit != nil {
449
+ hardLimit = * agentLimit .Limit
450
+ }
432
451
433
- // Issue a warning early:
434
- // 1. If the soft limit and hard limit are equal, at 75% of the hard
435
- // limit.
436
- // 2. If the limit is greater than the soft limit, at 75% of the
437
- // difference between the hard limit and the soft limit.
438
- softWarningThreshold := int64 (float64 (hardLimit ) * 0.75 )
439
- if hardLimit > softLimit && softLimit > 0 {
440
- softWarningThreshold = softLimit + int64 (float64 (hardLimit - softLimit )* 0.75 )
441
- }
442
- if managedAgentCount >= * agentLimit .Limit {
443
- entitlements .Warnings = append (entitlements .Warnings ,
444
- "You have built more workspaces with managed agents than your license allows. Further managed agent builds will be blocked." )
445
- } else if managedAgentCount >= softWarningThreshold {
446
- entitlements .Warnings = append (entitlements .Warnings ,
447
- "You are approaching the managed agent limit in your license. Please refer to the Deployment Licenses page for more information." )
452
+ // Issue a warning early:
453
+ // 1. If the soft limit and hard limit are equal, at 75% of the hard
454
+ // limit.
455
+ // 2. If the limit is greater than the soft limit, at 75% of the
456
+ // difference between the hard limit and the soft limit.
457
+ softWarningThreshold := int64 (float64 (hardLimit ) * 0.75 )
458
+ if hardLimit > softLimit && softLimit > 0 {
459
+ softWarningThreshold = softLimit + int64 (float64 (hardLimit - softLimit )* 0.75 )
460
+ }
461
+ if managedAgentCount >= * agentLimit .Limit {
462
+ entitlements .Warnings = append (entitlements .Warnings ,
463
+ "You have built more workspaces with managed agents than your license allows. Further managed agent builds will be blocked." )
464
+ } else if managedAgentCount >= softWarningThreshold {
465
+ entitlements .Warnings = append (entitlements .Warnings ,
466
+ "You are approaching the managed agent limit in your license. Please refer to the Deployment Licenses page for more information." )
467
+ }
448
468
}
449
469
}
450
470
}
0 commit comments