33package cli
44
55import (
6+ "bytes"
67"context"
78"fmt"
89"net/http"
@@ -29,12 +30,13 @@ import (
2930
3031func (r * RootCmd )scaletestNotifications ()* serpent.Command {
3132var (
32- userCount int64
33- ownerUserPercentage float64
34- notificationTimeout time.Duration
35- dialTimeout time.Duration
36- noCleanup bool
37- smtpAPIURL string
33+ userCount int64
34+ templateAdminPercentage float64
35+ notificationTimeout time.Duration
36+ smtpRequestTimeout time.Duration
37+ dialTimeout time.Duration
38+ noCleanup bool
39+ smtpAPIURL string
3840
3941tracingFlags = & scaletestTracingFlags {}
4042
@@ -77,24 +79,24 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
7779return xerrors .Errorf ("--user-count must be greater than 0" )
7880}
7981
80- if ownerUserPercentage < 0 || ownerUserPercentage > 100 {
81- return xerrors .Errorf ("--owner-user -percentage must be between 0 and 100" )
82+ if templateAdminPercentage < 0 || templateAdminPercentage > 100 {
83+ return xerrors .Errorf ("--template-admin -percentage must be between 0 and 100" )
8284}
8385
8486if smtpAPIURL != "" && ! strings .HasPrefix (smtpAPIURL ,"http://" )&& ! strings .HasPrefix (smtpAPIURL ,"https://" ) {
8587return xerrors .Errorf ("--smtp-api-url must start with http:// or https://" )
8688}
8789
88- ownerUserCount := int64 (float64 (userCount )* ownerUserPercentage / 100 )
89- if ownerUserCount == 0 && ownerUserPercentage > 0 {
90- ownerUserCount = 1
90+ templateAdminCount := int64 (float64 (userCount )* templateAdminPercentage / 100 )
91+ if templateAdminCount == 0 && templateAdminPercentage > 0 {
92+ templateAdminCount = 1
9193}
92- regularUserCount := userCount - ownerUserCount
94+ regularUserCount := userCount - templateAdminCount
9395
9496_ ,_ = fmt .Fprintf (inv .Stderr ,"Distribution plan:\n " )
9597_ ,_ = fmt .Fprintf (inv .Stderr ," Total users: %d\n " ,userCount )
96- _ ,_ = fmt .Fprintf (inv .Stderr ,"Owner users : %d (%.1f%%)\n " ,ownerUserCount , ownerUserPercentage )
97- _ ,_ = fmt .Fprintf (inv .Stderr ," Regular users: %d (%.1f%%)\n " ,regularUserCount ,100.0 - ownerUserPercentage )
98+ _ ,_ = fmt .Fprintf (inv .Stderr ,"Template admins : %d (%.1f%%)\n " ,templateAdminCount , templateAdminPercentage )
99+ _ ,_ = fmt .Fprintf (inv .Stderr ," Regular users: %d (%.1f%%)\n " ,regularUserCount ,100.0 - templateAdminPercentage )
98100
99101outputs ,err := output .parse ()
100102if err != nil {
@@ -127,13 +129,12 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
127129_ ,_ = fmt .Fprintln (inv .Stderr ,"Creating users..." )
128130
129131dialBarrier := & sync.WaitGroup {}
130- ownerWatchBarrier := & sync.WaitGroup {}
132+ templateAdminWatchBarrier := & sync.WaitGroup {}
131133dialBarrier .Add (int (userCount ))
132- ownerWatchBarrier .Add (int (ownerUserCount ))
134+ templateAdminWatchBarrier .Add (int (templateAdminCount ))
133135
134136expectedNotificationIDs := map [uuid.UUID ]struct {}{
135- notificationsLib .TemplateUserAccountCreated : {},
136- notificationsLib .TemplateUserAccountDeleted : {},
137+ notificationsLib .TemplateTemplateDeleted : {},
137138}
138139
139140triggerTimes := make (map [uuid.UUID ]chan time.Time ,len (expectedNotificationIDs ))
@@ -142,19 +143,20 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
142143}
143144
144145configs := make ([]notifications.Config ,0 ,userCount )
145- for range ownerUserCount {
146+ for range templateAdminCount {
146147config := notifications.Config {
147148User : createusers.Config {
148149OrganizationID :me .OrganizationIDs [0 ],
149150},
150- Roles : []string {codersdk .RoleOwner },
151+ Roles : []string {codersdk .RoleTemplateAdmin },
151152NotificationTimeout :notificationTimeout ,
152153DialTimeout :dialTimeout ,
153154DialBarrier :dialBarrier ,
154- ReceivingWatchBarrier :ownerWatchBarrier ,
155+ ReceivingWatchBarrier :templateAdminWatchBarrier ,
155156ExpectedNotificationsIDs :expectedNotificationIDs ,
156157Metrics :metrics ,
157158SMTPApiURL :smtpAPIURL ,
159+ SMTPRequestTimeout :smtpRequestTimeout ,
158160}
159161if err := config .Validate ();err != nil {
160162return xerrors .Errorf ("validate config: %w" ,err )
@@ -170,17 +172,16 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
170172NotificationTimeout :notificationTimeout ,
171173DialTimeout :dialTimeout ,
172174DialBarrier :dialBarrier ,
173- ReceivingWatchBarrier :ownerWatchBarrier ,
175+ ReceivingWatchBarrier :templateAdminWatchBarrier ,
174176Metrics :metrics ,
175- SMTPApiURL :smtpAPIURL ,
176177}
177178if err := config .Validate ();err != nil {
178179return xerrors .Errorf ("validate config: %w" ,err )
179180}
180181configs = append (configs ,config )
181182}
182183
183- go triggerUserNotifications (
184+ go triggerNotifications (
184185ctx ,
185186logger ,
186187client ,
@@ -261,23 +262,30 @@ func (r *RootCmd) scaletestNotifications() *serpent.Command {
261262Required :true ,
262263},
263264{
264- Flag :"owner-user -percentage" ,
265- Env :"CODER_SCALETEST_NOTIFICATION_OWNER_USER_PERCENTAGE " ,
265+ Flag :"template-admin -percentage" ,
266+ Env :"CODER_SCALETEST_NOTIFICATION_TEMPLATE_ADMIN_PERCENTAGE " ,
266267Default :"20.0" ,
267- Description :"Percentage of users to assignOwner role to (0-100)." ,
268- Value :serpent .Float64Of (& ownerUserPercentage ),
268+ Description :"Percentage of users to assignTemplate Admin role to (0-100)." ,
269+ Value :serpent .Float64Of (& templateAdminPercentage ),
269270},
270271{
271272Flag :"notification-timeout" ,
272273Env :"CODER_SCALETEST_NOTIFICATION_TIMEOUT" ,
273- Default :"5m " ,
274+ Default :"10m " ,
274275Description :"How long to wait for notifications after triggering." ,
275276Value :serpent .DurationOf (& notificationTimeout ),
276277},
278+ {
279+ Flag :"smtp-request-timeout" ,
280+ Env :"CODER_SCALETEST_SMTP_REQUEST_TIMEOUT" ,
281+ Default :"5m" ,
282+ Description :"Timeout for SMTP requests." ,
283+ Value :serpent .DurationOf (& smtpRequestTimeout ),
284+ },
277285{
278286Flag :"dial-timeout" ,
279287Env :"CODER_SCALETEST_DIAL_TIMEOUT" ,
280- Default :"2m " ,
288+ Default :"10m " ,
281289Description :"Timeout for dialing the notification websocket endpoint." ,
282290Value :serpent .DurationOf (& dialTimeout ),
283291},
@@ -379,9 +387,9 @@ func computeNotificationLatencies(
379387return nil
380388}
381389
382- //triggerUserNotifications waits for all test users to connect,
383- // then creates and deletes a testuser to trigger notification events for testing.
384- func triggerUserNotifications (
390+ //triggerNotifications waits for all test users to connect,
391+ // then creates and deletes a testtemplate to trigger notification events for testing.
392+ func triggerNotifications (
385393ctx context.Context ,
386394logger slog.Logger ,
387395client * codersdk.Client ,
@@ -414,34 +422,49 @@ func triggerUserNotifications(
414422return
415423}
416424
417- const (
418- triggerUsername = "scaletest-trigger-user"
419- triggerEmail = "scaletest-trigger@example.com"
420- )
425+ logger .Info (ctx ,"creating test template to test notifications" )
426+
427+ // Upload empty template file.
428+ file ,err := client .Upload (ctx ,codersdk .ContentTypeTar ,bytes .NewReader ([]byte {}))
429+ if err != nil {
430+ logger .Error (ctx ,"upload test template" ,slog .Error (err ))
431+ return
432+ }
433+ logger .Info (ctx ,"test template uploaded" ,slog .F ("file_id" ,file .ID ))
421434
422- logger .Info (ctx ,"creating test user to test notifications" ,
423- slog .F ("username" ,triggerUsername ),
424- slog .F ("email" ,triggerEmail ),
425- slog .F ("org_id" ,orgID ))
435+ // Create template version.
436+ version ,err := client .CreateTemplateVersion (ctx ,orgID , codersdk.CreateTemplateVersionRequest {
437+ StorageMethod :codersdk .ProvisionerStorageMethodFile ,
438+ FileID :file .ID ,
439+ Provisioner :codersdk .ProvisionerTypeEcho ,
440+ })
441+ if err != nil {
442+ logger .Error (ctx ,"create test template version" ,slog .Error (err ))
443+ return
444+ }
445+ logger .Info (ctx ,"test template version created" ,slog .F ("template_version_id" ,version .ID ))
426446
427- testUser , err := client . CreateUserWithOrgs ( ctx , codersdk. CreateUserRequestWithOrgs {
428- OrganizationIDs : []uuid. UUID { orgID },
429- Username :triggerUsername ,
430- Email : triggerEmail ,
431- Password :"test-password-123" ,
447+ // Create template.
448+ testTemplate , err := client . CreateTemplate ( ctx , orgID , codersdk. CreateTemplateRequest {
449+ Name :"scaletest-test-template" ,
450+ Description : "scaletest-test-template" ,
451+ VersionID :version . ID ,
432452})
433453if err != nil {
434- logger .Error (ctx ,"create testuser " ,slog .Error (err ))
454+ logger .Error (ctx ,"create testtemplate " ,slog .Error (err ))
435455return
436456}
437- expectedNotifications [ notificationsLib . TemplateUserAccountCreated ] <- time . Now ( )
457+ logger . Info ( ctx , "test template created" , slog . F ( "template_id" , testTemplate . ID ) )
438458
439- err = client .DeleteUser (ctx ,testUser .ID )
459+ // Delete template to trigger notification.
460+ err = client .DeleteTemplate (ctx ,testTemplate .ID )
440461if err != nil {
441- logger .Error (ctx ,"delete testuser " ,slog .Error (err ))
462+ logger .Error (ctx ,"delete testtemplate " ,slog .Error (err ))
442463return
443464}
444- expectedNotifications [notificationsLib .TemplateUserAccountDeleted ]<- time .Now ()
445- close (expectedNotifications [notificationsLib .TemplateUserAccountCreated ])
446- close (expectedNotifications [notificationsLib .TemplateUserAccountDeleted ])
465+ logger .Info (ctx ,"test template deleted" ,slog .F ("template_id" ,testTemplate .ID ))
466+
467+ // Record expected notification.
468+ expectedNotifications [notificationsLib .TemplateTemplateDeleted ]<- time .Now ()
469+ close (expectedNotifications [notificationsLib .TemplateTemplateDeleted ])
447470}