@@ -888,6 +888,164 @@ func TestLicenseEntitlements(t *testing.T) {
888
888
entitlements .Features [codersdk .FeatureCustomRoles ].Entitlement )
889
889
},
890
890
},
891
+ {
892
+ Name :"ManagedAgentLimit" ,
893
+ Licenses : []* coderdenttest.LicenseOptions {
894
+ enterpriseLicense ().UserLimit (100 ).ManagedAgentLimit (100 ,200 ),
895
+ },
896
+ Arguments : license.FeatureArguments {
897
+ ManagedAgentCountFn :func (ctx context.Context ,from time.Time ,to time.Time ) (int64 ,error ) {
898
+ // 175 will generate a warning as it's over 75% of the
899
+ // difference between the soft and hard limit.
900
+ return 174 ,nil
901
+ },
902
+ },
903
+ AssertEntitlements :func (t * testing.T ,entitlements codersdk.Entitlements ) {
904
+ assertNoErrors (t ,entitlements )
905
+ assertNoWarnings (t ,entitlements )
906
+ feature := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
907
+ assert .Equal (t ,codersdk .EntitlementEntitled ,feature .Entitlement )
908
+ assert .True (t ,feature .Enabled )
909
+ assert .Equal (t ,int64 (100 ),* feature .SoftLimit )
910
+ assert .Equal (t ,int64 (200 ),* feature .Limit )
911
+ assert .Equal (t ,int64 (174 ),* feature .Actual )
912
+ },
913
+ },
914
+ {
915
+ Name :"ManagedAgentLimitWithGrace" ,
916
+ Licenses : []* coderdenttest.LicenseOptions {
917
+ // Add another license that is not entitled to managed agents to
918
+ // suppress warnings for other features.
919
+ enterpriseLicense ().
920
+ UserLimit (100 ).
921
+ WithIssuedAt (time .Now ().Add (- time .Hour * 2 )),
922
+ enterpriseLicense ().
923
+ UserLimit (100 ).
924
+ ManagedAgentLimit (100 ,100 ).
925
+ WithIssuedAt (time .Now ().Add (- time .Hour * 1 )).
926
+ GracePeriod (time .Now ()),
927
+ },
928
+ Arguments : license.FeatureArguments {
929
+ ManagedAgentCountFn :func (ctx context.Context ,from time.Time ,to time.Time ) (int64 ,error ) {
930
+ // When the soft and hard limit are equal, the warning is
931
+ // triggered at 75% of the hard limit.
932
+ return 74 ,nil
933
+ },
934
+ },
935
+ AssertEntitlements :func (t * testing.T ,entitlements codersdk.Entitlements ) {
936
+ assertNoErrors (t ,entitlements )
937
+ assertNoWarnings (t ,entitlements )
938
+ feature := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
939
+ assert .Equal (t ,codersdk .EntitlementGracePeriod ,feature .Entitlement )
940
+ assert .True (t ,feature .Enabled )
941
+ assert .Equal (t ,int64 (100 ),* feature .SoftLimit )
942
+ assert .Equal (t ,int64 (100 ),* feature .Limit )
943
+ assert .Equal (t ,int64 (74 ),* feature .Actual )
944
+ },
945
+ },
946
+ {
947
+ Name :"ManagedAgentLimitWithExpired" ,
948
+ Licenses : []* coderdenttest.LicenseOptions {
949
+ // Add another license that is not entitled to managed agents to
950
+ // suppress warnings for other features.
951
+ enterpriseLicense ().
952
+ UserLimit (100 ).
953
+ WithIssuedAt (time .Now ().Add (- time .Hour * 2 )),
954
+ enterpriseLicense ().
955
+ UserLimit (100 ).
956
+ ManagedAgentLimit (100 ,200 ).
957
+ WithIssuedAt (time .Now ().Add (- time .Hour * 1 )).
958
+ Expired (time .Now ()),
959
+ },
960
+ Arguments : license.FeatureArguments {
961
+ ManagedAgentCountFn :func (ctx context.Context ,from time.Time ,to time.Time ) (int64 ,error ) {
962
+ return 10 ,nil
963
+ },
964
+ },
965
+ AssertEntitlements :func (t * testing.T ,entitlements codersdk.Entitlements ) {
966
+ feature := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
967
+ assert .Equal (t ,codersdk .EntitlementNotEntitled ,feature .Entitlement )
968
+ assert .False (t ,feature .Enabled )
969
+ assert .Nil (t ,feature .SoftLimit )
970
+ assert .Nil (t ,feature .Limit )
971
+ assert .Nil (t ,feature .Actual )
972
+ },
973
+ },
974
+ {
975
+ Name :"ManagedAgentLimitWarning/ApproachingLimit/DifferentSoftAndHardLimit" ,
976
+ Licenses : []* coderdenttest.LicenseOptions {
977
+ enterpriseLicense ().
978
+ UserLimit (100 ).
979
+ ManagedAgentLimit (100 ,200 ),
980
+ },
981
+ Arguments : license.FeatureArguments {
982
+ ManagedAgentCountFn :func (ctx context.Context ,from time.Time ,to time.Time ) (int64 ,error ) {
983
+ return 175 ,nil
984
+ },
985
+ },
986
+ AssertEntitlements :func (t * testing.T ,entitlements codersdk.Entitlements ) {
987
+ assert .Len (t ,entitlements .Warnings ,1 )
988
+ assert .Equal (t ,"You are approaching the managed agent limit in your license. Please refer to the Deployment Licenses page for more information." ,entitlements .Warnings [0 ])
989
+ assertNoErrors (t ,entitlements )
990
+
991
+ feature := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
992
+ assert .Equal (t ,codersdk .EntitlementEntitled ,feature .Entitlement )
993
+ assert .True (t ,feature .Enabled )
994
+ assert .Equal (t ,int64 (100 ),* feature .SoftLimit )
995
+ assert .Equal (t ,int64 (200 ),* feature .Limit )
996
+ assert .Equal (t ,int64 (175 ),* feature .Actual )
997
+ },
998
+ },
999
+ {
1000
+ Name :"ManagedAgentLimitWarning/ApproachingLimit/EqualSoftAndHardLimit" ,
1001
+ Licenses : []* coderdenttest.LicenseOptions {
1002
+ enterpriseLicense ().
1003
+ UserLimit (100 ).
1004
+ ManagedAgentLimit (100 ,100 ),
1005
+ },
1006
+ Arguments : license.FeatureArguments {
1007
+ ManagedAgentCountFn :func (ctx context.Context ,from time.Time ,to time.Time ) (int64 ,error ) {
1008
+ return 75 ,nil
1009
+ },
1010
+ },
1011
+ AssertEntitlements :func (t * testing.T ,entitlements codersdk.Entitlements ) {
1012
+ assert .Len (t ,entitlements .Warnings ,1 )
1013
+ assert .Equal (t ,"You are approaching the managed agent limit in your license. Please refer to the Deployment Licenses page for more information." ,entitlements .Warnings [0 ])
1014
+ assertNoErrors (t ,entitlements )
1015
+
1016
+ feature := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
1017
+ assert .Equal (t ,codersdk .EntitlementEntitled ,feature .Entitlement )
1018
+ assert .True (t ,feature .Enabled )
1019
+ assert .Equal (t ,int64 (100 ),* feature .SoftLimit )
1020
+ assert .Equal (t ,int64 (100 ),* feature .Limit )
1021
+ assert .Equal (t ,int64 (75 ),* feature .Actual )
1022
+ },
1023
+ },
1024
+ {
1025
+ Name :"ManagedAgentLimitWarning/BreachedLimit" ,
1026
+ Licenses : []* coderdenttest.LicenseOptions {
1027
+ enterpriseLicense ().
1028
+ UserLimit (100 ).
1029
+ ManagedAgentLimit (100 ,200 ),
1030
+ },
1031
+ Arguments : license.FeatureArguments {
1032
+ ManagedAgentCountFn :func (ctx context.Context ,from time.Time ,to time.Time ) (int64 ,error ) {
1033
+ return 200 ,nil
1034
+ },
1035
+ },
1036
+ AssertEntitlements :func (t * testing.T ,entitlements codersdk.Entitlements ) {
1037
+ assert .Len (t ,entitlements .Warnings ,1 )
1038
+ assert .Equal (t ,"You have built more workspaces with managed agents than your license allows. Further managed agent builds will be blocked." ,entitlements .Warnings [0 ])
1039
+ assertNoErrors (t ,entitlements )
1040
+
1041
+ feature := entitlements .Features [codersdk .FeatureManagedAgentLimit ]
1042
+ assert .Equal (t ,codersdk .EntitlementEntitled ,feature .Entitlement )
1043
+ assert .True (t ,feature .Enabled )
1044
+ assert .Equal (t ,int64 (100 ),* feature .SoftLimit )
1045
+ assert .Equal (t ,int64 (200 ),* feature .Limit )
1046
+ assert .Equal (t ,int64 (200 ),* feature .Actual )
1047
+ },
1048
+ },
891
1049
}
892
1050
893
1051
for _ ,tc := range testCases {