@@ -22,9 +22,11 @@ import (
22
22
"github.com/coder/coder/v2/agent"
23
23
"github.com/coder/coder/v2/coderd/batchstats"
24
24
"github.com/coder/coder/v2/coderd/coderdtest"
25
+ "github.com/coder/coder/v2/coderd/database"
25
26
"github.com/coder/coder/v2/coderd/database/dbauthz"
27
+ "github.com/coder/coder/v2/coderd/database/dbgen"
28
+ "github.com/coder/coder/v2/coderd/database/dbtestutil"
26
29
"github.com/coder/coder/v2/coderd/rbac"
27
- "github.com/coder/coder/v2/coderd/util/slice"
28
30
"github.com/coder/coder/v2/coderd/workspaceapps"
29
31
"github.com/coder/coder/v2/codersdk"
30
32
"github.com/coder/coder/v2/codersdk/agentsdk"
@@ -580,19 +582,6 @@ func TestTemplateInsights(t *testing.T) {
580
582
func TestTemplateInsights_Golden (t * testing.T ) {
581
583
t .Parallel ()
582
584
583
- stabilizeReportForGoldenComparison := func (report * codersdk.TemplateInsightsResponse , toStableTemplateIDs func ([]uuid.UUID )) {
584
- toStableTemplateIDs (report .Report .TemplateIDs )
585
- for _ , param := range report .Report .ParametersUsage {
586
- toStableTemplateIDs (param .TemplateIDs )
587
- }
588
- for _ , app := range report .Report .AppsUsage {
589
- toStableTemplateIDs (app .TemplateIDs )
590
- }
591
- for _ , intervalReport := range report .IntervalReports {
592
- toStableTemplateIDs (intervalReport .TemplateIDs )
593
- }
594
- }
595
-
596
585
// Prepare test data types.
597
586
type templateParameterOption struct {
598
587
name string
@@ -613,7 +602,7 @@ func TestTemplateInsights_Golden(t *testing.T) {
613
602
apps []templateApp
614
603
615
604
// Filled later.
616
- id uuid.UUID // Set to the created template ID.
605
+ id uuid.UUID
617
606
}
618
607
type buildParameter struct {
619
608
templateParameter * templateParameter
@@ -778,7 +767,17 @@ func TestTemplateInsights_Golden(t *testing.T) {
778
767
},
779
768
}
780
769
781
- // Post-process workspaces.
770
+ // Post-process.
771
+ var stableIDs []uuid.UUID
772
+ newStableUUID := func () uuid.UUID {
773
+ stableIDs = append (stableIDs , uuid .MustParse (fmt .Sprintf ("00000000-0000-0000-0000-%012d" , len (stableIDs )+ 1 )))
774
+ stableID := stableIDs [len (stableIDs )- 1 ]
775
+ return stableID
776
+ }
777
+
778
+ for _ , template := range templates {
779
+ template .id = newStableUUID ()
780
+ }
782
781
for _ , user := range users {
783
782
for _ , workspace := range user .workspaces {
784
783
workspace .user = user
@@ -792,14 +791,16 @@ func TestTemplateInsights_Golden(t *testing.T) {
792
791
return templates , users
793
792
}
794
793
795
- prepare := func (t * testing.T , templates []* testTemplate , users []* testUser , testData map [* testWorkspace ]testDataGen ) ( * codersdk.Client , func ([]uuid. UUID )) {
794
+ prepare := func (t * testing.T , templates []* testTemplate , users []* testUser , testData map [* testWorkspace ]testDataGen ) * codersdk.Client {
796
795
logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : false }).Leveled (slog .LevelDebug )
797
- opts := & coderdtest.Options {
796
+ db , pubsub := dbtestutil .NewDB (t )
797
+ client := coderdtest .New (t , & coderdtest.Options {
798
+ Database : db ,
799
+ Pubsub : pubsub ,
798
800
Logger : & logger ,
799
801
IncludeProvisionerDaemon : true ,
800
802
AgentStatsRefreshInterval : time .Hour , // Not relevant for this test.
801
- }
802
- client , _ , coderdAPI := coderdtest .NewWithAPI (t , opts )
803
+ })
803
804
firstUser := coderdtest .CreateFirstUser (t , client )
804
805
805
806
// Prepare all test users.
@@ -926,11 +927,28 @@ func TestTemplateInsights_Golden(t *testing.T) {
926
927
},
927
928
}},
928
929
})
929
- createdTemplate := coderdtest .CreateTemplate (t , client , firstUser .OrganizationID , version .ID )
930
- require .Empty (t , createdTemplate .BuildTimeStats [codersdk .WorkspaceTransitionStart ])
931
930
coderdtest .AwaitTemplateVersionJob (t , client , version .ID )
932
931
933
- template .id = createdTemplate .ID
932
+ // Create template, essentially a modified version of CreateTemplate
933
+ // where we can control the template ID.
934
+ // createdTemplate := coderdtest.CreateTemplate(t, client, firstUser.OrganizationID, version.ID)
935
+ createdTemplate := dbgen .Template (t , db , database.Template {
936
+ ID : template .id ,
937
+ ActiveVersionID : version .ID ,
938
+ OrganizationID : firstUser .OrganizationID ,
939
+ CreatedBy : firstUser .UserID ,
940
+ GroupACL : database.TemplateACL {
941
+ firstUser .OrganizationID .String (): []rbac.Action {rbac .ActionRead },
942
+ },
943
+ })
944
+ err := db .UpdateTemplateVersionByID (context .Background (), database.UpdateTemplateVersionByIDParams {
945
+ ID : version .ID ,
946
+ TemplateID : uuid.NullUUID {
947
+ UUID : createdTemplate .ID ,
948
+ Valid : true ,
949
+ },
950
+ })
951
+ require .NoError (t , err , "want no error updating template version" )
934
952
935
953
// Create all workspaces and wait for them.
936
954
for _ , createWorkspace := range createWorkspaces {
@@ -949,7 +967,7 @@ func TestTemplateInsights_Golden(t *testing.T) {
949
967
// the database.
950
968
batcher , batcherCloser , err := batchstats .New (
951
969
ctx ,
952
- batchstats .WithStore (coderdAPI . Database ),
970
+ batchstats .WithStore (db ),
953
971
batchstats .WithLogger (logger .Named ("batchstats" )),
954
972
batchstats .WithInterval (time .Hour ),
955
973
)
@@ -1000,80 +1018,57 @@ func TestTemplateInsights_Golden(t *testing.T) {
1000
1018
})
1001
1019
}
1002
1020
}
1003
- reporter := workspaceapps .NewStatsDBReporter (coderdAPI . Database , workspaceapps .DefaultStatsDBReporterBatchSize )
1021
+ reporter := workspaceapps .NewStatsDBReporter (db , workspaceapps .DefaultStatsDBReporterBatchSize )
1004
1022
//nolint:gocritic // This is a test.
1005
1023
err = reporter .Report (dbauthz .AsSystemRestricted (ctx ), stats )
1006
1024
require .NoError (t , err , "want no error inserting app stats" )
1007
1025
1008
- var stableTemplateIDs []uuid.UUID
1009
- stableTemplateIDMap := make (map [uuid.UUID ]uuid.UUID )
1010
- toStableTemplateID := func (id uuid.UUID ) uuid.UUID {
1011
- if stableID , ok := stableTemplateIDMap [id ]; ok {
1012
- return stableID
1013
- }
1014
- stableTemplateIDs = append (stableTemplateIDs , uuid .MustParse (fmt .Sprintf ("00000000-0000-0000-0000-%012d" , len (stableTemplateIDs )+ 1 )))
1015
- stableID := stableTemplateIDs [len (stableTemplateIDs )- 1 ]
1016
- stableTemplateIDMap [id ] = stableID
1017
- return stableID
1018
- }
1019
- // Prime the map.
1020
- for _ , template := range templates {
1021
- _ = toStableTemplateID (template .id )
1022
- }
1023
-
1024
- return client , func (ids []uuid.UUID ) {
1025
- for i , id := range ids {
1026
- ids [i ] = toStableTemplateID (id )
1027
- }
1028
- slices .SortFunc (ids , func (a , b uuid.UUID ) int {
1029
- return slice .Ascending (a .String (), b .String ())
1030
- })
1031
- }
1026
+ return client
1032
1027
}
1033
1028
1034
1029
// Time range for report, test data will be generated within and
1035
1030
// outside this range, but only data within the range should be
1036
1031
// included in the report.
1037
- lastNight := time .Now (). UTC (). Truncate ( 24 * time .Hour )
1038
- weekAgo := lastNight .AddDate (0 , 0 , - 7 )
1032
+ frozenLastNight := time .Date ( 2023 , 8 , 22 , 0 , 0 , 0 , 0 , time .UTC )
1033
+ frozenWeekAgo := frozenLastNight .AddDate (0 , 0 , - 7 )
1039
1034
1040
1035
saoPaulo , err := time .LoadLocation ("America/Sao_Paulo" )
1041
1036
require .NoError (t , err )
1042
- weekAgoSaoPaulo , err := time .ParseInLocation (time .DateTime , weekAgo .Format (time .DateTime ), saoPaulo )
1037
+ frozenWeekAgoSaoPaulo , err := time .ParseInLocation (time .DateTime , frozenWeekAgo .Format (time .DateTime ), saoPaulo )
1043
1038
require .NoError (t , err )
1044
1039
1045
1040
makeBaseTestData := func (templates []* testTemplate , users []* testUser ) map [* testWorkspace ]testDataGen {
1046
1041
return map [* testWorkspace ]testDataGen {
1047
1042
users [0 ].workspaces [0 ]: {
1048
1043
agentStats : []agentStat {
1049
1044
{ // One hour of usage.
1050
- startedAt : weekAgo ,
1051
- endedAt : weekAgo .Add (time .Hour ),
1045
+ startedAt : frozenWeekAgo ,
1046
+ endedAt : frozenWeekAgo .Add (time .Hour ),
1052
1047
sessionCountVSCode : 1 ,
1053
1048
sessionCountSSH : 1 ,
1054
1049
},
1055
1050
{ // 12 minutes of usage -> 15 minutes.
1056
- startedAt : weekAgo .AddDate (0 , 0 , 1 ),
1057
- endedAt : weekAgo .AddDate (0 , 0 , 1 ).Add (12 * time .Minute ),
1051
+ startedAt : frozenWeekAgo .AddDate (0 , 0 , 1 ),
1052
+ endedAt : frozenWeekAgo .AddDate (0 , 0 , 1 ).Add (12 * time .Minute ),
1058
1053
sessionCountSSH : 1 ,
1059
1054
},
1060
1055
{ // 2 minutes of usage -> 10 minutes because it crosses the 5 minute interval boundary.
1061
- startedAt : weekAgo .AddDate (0 , 0 , 2 ).Add (4 * time .Minute ),
1062
- endedAt : weekAgo .AddDate (0 , 0 , 2 ).Add (6 * time .Minute ),
1056
+ startedAt : frozenWeekAgo .AddDate (0 , 0 , 2 ).Add (4 * time .Minute ),
1057
+ endedAt : frozenWeekAgo .AddDate (0 , 0 , 2 ).Add (6 * time .Minute ),
1063
1058
sessionCountJetBrains : 1 ,
1064
1059
},
1065
1060
},
1066
1061
appUsage : []appUsage {
1067
1062
{ // One hour of usage.
1068
1063
app : users [0 ].workspaces [0 ].apps [0 ],
1069
- startedAt : weekAgo ,
1070
- endedAt : weekAgo .Add (time .Hour ),
1064
+ startedAt : frozenWeekAgo ,
1065
+ endedAt : frozenWeekAgo .Add (time .Hour ),
1071
1066
requests : 1 ,
1072
1067
},
1073
1068
{ // used an app on the last day, counts as active user, 12m -> 15m rounded.
1074
1069
app : users [0 ].workspaces [0 ].apps [2 ],
1075
- startedAt : weekAgo .AddDate (0 , 0 , 6 ),
1076
- endedAt : weekAgo .AddDate (0 , 0 , 6 ).Add (12 * time .Minute ),
1070
+ startedAt : frozenWeekAgo .AddDate (0 , 0 , 6 ),
1071
+ endedAt : frozenWeekAgo .AddDate (0 , 0 , 6 ).Add (12 * time .Minute ),
1077
1072
requests : 1 ,
1078
1073
},
1079
1074
},
@@ -1085,8 +1080,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1085
1080
// as in first template. When selecting both templates
1086
1081
// this user and their app usage will only be counted
1087
1082
// once but the template ID will show up in the data.
1088
- startedAt : weekAgo ,
1089
- endedAt : weekAgo .Add (time .Hour ),
1083
+ startedAt : frozenWeekAgo ,
1084
+ endedAt : frozenWeekAgo .Add (time .Hour ),
1090
1085
sessionCountVSCode : 1 ,
1091
1086
sessionCountSSH : 1 ,
1092
1087
},
@@ -1105,8 +1100,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1105
1100
// Different templates but identical apps, apps will be
1106
1101
// combined and usage will be summed.
1107
1102
app : users [0 ].workspaces [1 ].apps [0 ],
1108
- startedAt : weekAgo .AddDate (0 , 0 , 2 ),
1109
- endedAt : weekAgo .AddDate (0 , 0 , 2 ).Add (6 * time .Hour ),
1103
+ startedAt : frozenWeekAgo .AddDate (0 , 0 , 2 ),
1104
+ endedAt : frozenWeekAgo .AddDate (0 , 0 , 2 ).Add (6 * time .Hour ),
1110
1105
requests : 1 ,
1111
1106
},
1112
1107
},
@@ -1128,6 +1123,7 @@ func TestTemplateInsights_Golden(t *testing.T) {
1128
1123
type testRequest struct {
1129
1124
name string
1130
1125
makeRequest func ([]* testTemplate ) codersdk.TemplateInsightsRequest
1126
+ ignoreTimes bool
1131
1127
}
1132
1128
tests := []struct {
1133
1129
name string
@@ -1142,8 +1138,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1142
1138
name : "week deployment wide" ,
1143
1139
makeRequest : func (templates []* testTemplate ) codersdk.TemplateInsightsRequest {
1144
1140
return codersdk.TemplateInsightsRequest {
1145
- StartTime : weekAgo ,
1146
- EndTime : weekAgo .AddDate (0 , 0 , 7 ),
1141
+ StartTime : frozenWeekAgo ,
1142
+ EndTime : frozenWeekAgo .AddDate (0 , 0 , 7 ),
1147
1143
Interval : codersdk .InsightsReportIntervalDay ,
1148
1144
}
1149
1145
},
@@ -1153,8 +1149,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1153
1149
makeRequest : func (templates []* testTemplate ) codersdk.TemplateInsightsRequest {
1154
1150
return codersdk.TemplateInsightsRequest {
1155
1151
TemplateIDs : []uuid.UUID {templates [0 ].id , templates [1 ].id , templates [2 ].id },
1156
- StartTime : weekAgo ,
1157
- EndTime : weekAgo .AddDate (0 , 0 , 7 ),
1152
+ StartTime : frozenWeekAgo ,
1153
+ EndTime : frozenWeekAgo .AddDate (0 , 0 , 7 ),
1158
1154
Interval : codersdk .InsightsReportIntervalDay ,
1159
1155
}
1160
1156
},
@@ -1164,8 +1160,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1164
1160
makeRequest : func (templates []* testTemplate ) codersdk.TemplateInsightsRequest {
1165
1161
return codersdk.TemplateInsightsRequest {
1166
1162
TemplateIDs : []uuid.UUID {templates [0 ].id },
1167
- StartTime : weekAgo ,
1168
- EndTime : weekAgo .AddDate (0 , 0 , 7 ),
1163
+ StartTime : frozenWeekAgo ,
1164
+ EndTime : frozenWeekAgo .AddDate (0 , 0 , 7 ),
1169
1165
Interval : codersdk .InsightsReportIntervalDay ,
1170
1166
}
1171
1167
},
@@ -1175,8 +1171,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1175
1171
makeRequest : func (templates []* testTemplate ) codersdk.TemplateInsightsRequest {
1176
1172
return codersdk.TemplateInsightsRequest {
1177
1173
TemplateIDs : []uuid.UUID {templates [1 ].id },
1178
- StartTime : weekAgo ,
1179
- EndTime : weekAgo .AddDate (0 , 0 , 7 ),
1174
+ StartTime : frozenWeekAgo ,
1175
+ EndTime : frozenWeekAgo .AddDate (0 , 0 , 7 ),
1180
1176
Interval : codersdk .InsightsReportIntervalDay ,
1181
1177
}
1182
1178
},
@@ -1186,8 +1182,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1186
1182
makeRequest : func (templates []* testTemplate ) codersdk.TemplateInsightsRequest {
1187
1183
return codersdk.TemplateInsightsRequest {
1188
1184
TemplateIDs : []uuid.UUID {templates [2 ].id },
1189
- StartTime : weekAgo ,
1190
- EndTime : weekAgo .AddDate (0 , 0 , 7 ),
1185
+ StartTime : frozenWeekAgo ,
1186
+ EndTime : frozenWeekAgo .AddDate (0 , 0 , 7 ),
1191
1187
Interval : codersdk .InsightsReportIntervalDay ,
1192
1188
}
1193
1189
},
@@ -1198,8 +1194,8 @@ func TestTemplateInsights_Golden(t *testing.T) {
1198
1194
name : "week other timezone (São Paulo)" ,
1199
1195
makeRequest : func (templates []* testTemplate ) codersdk.TemplateInsightsRequest {
1200
1196
return codersdk.TemplateInsightsRequest {
1201
- StartTime : weekAgoSaoPaulo ,
1202
- EndTime : weekAgoSaoPaulo .AddDate (0 , 0 , 7 ),
1197
+ StartTime : frozenWeekAgoSaoPaulo ,
1198
+ EndTime : frozenWeekAgoSaoPaulo .AddDate (0 , 0 , 7 ),
1203
1199
Interval : codersdk .InsightsReportIntervalDay ,
1204
1200
}
1205
1201
},
@@ -1233,7 +1229,7 @@ func TestTemplateInsights_Golden(t *testing.T) {
1233
1229
}
1234
1230
}
1235
1231
1236
- client , toStableTemplateIDs := prepare (t , templates , users , testData )
1232
+ client := prepare (t , templates , users , testData )
1237
1233
1238
1234
for _ , req := range tt .requests {
1239
1235
req := req
@@ -1245,7 +1241,15 @@ func TestTemplateInsights_Golden(t *testing.T) {
1245
1241
report , err := client .TemplateInsights (ctx , req .makeRequest (templates ))
1246
1242
require .NoError (t , err , "want no error getting template insights" )
1247
1243
1248
- stabilizeReportForGoldenComparison (& report , toStableTemplateIDs )
1244
+ if req .ignoreTimes {
1245
+ // Ignore times, we're only interested in the data.
1246
+ report .Report .StartTime = time.Time {}
1247
+ report .Report .EndTime = time.Time {}
1248
+ for i := range report .IntervalReports {
1249
+ report .IntervalReports [i ].StartTime = time.Time {}
1250
+ report .IntervalReports [i ].EndTime = time.Time {}
1251
+ }
1252
+ }
1249
1253
1250
1254
partialName := strings .Join (strings .Split (t .Name (), "/" )[1 :], "_" )
1251
1255
goldenFile := filepath .Join ("testdata" , "insights" , partialName + ".json.golden" )
0 commit comments