@@ -29,12 +29,13 @@ import (
29
29
)
30
30
31
31
type ReplayCmd struct {
32
- client * sdk.Client
33
- from TimeValue
34
- configPaths []string
35
- sloName string
36
- project string
37
- deleteAll bool
32
+ client * sdk.Client
33
+ from TimeValue
34
+ configPaths []string
35
+ sloName string
36
+ project string
37
+ deleteAll bool
38
+ playlistsAvailable bool
38
39
}
39
40
40
41
//go:embed replay_example.sh
@@ -76,6 +77,7 @@ func (r *ReplayCmd) Run(cmd *cobra.Command) error {
76
77
if r .client .Config .Project == "*" {
77
78
return errProjectWildcardIsNotAllowed
78
79
}
80
+ r .arePlaylistEnabled (cmd .Context ())
79
81
replays , err := r .prepareConfigs ()
80
82
if err != nil {
81
83
return err
@@ -89,9 +91,7 @@ func (r *ReplayCmd) RunReplays(cmd *cobra.Command, replays []ReplayConfig) (fail
89
91
return 0 , err
90
92
}
91
93
92
- arePlaylistEnabled := r .arePlaylistEnabled (cmd .Context ())
93
-
94
- if arePlaylistEnabled {
94
+ if r .playlistsAvailable {
95
95
cmd .Println (colorstring .Color ("[yellow]- Your organization has access to Replay queues!" ))
96
96
cmd .Println (colorstring .Color ("[yellow]- To learn more about Replay queues, follow this link: " +
97
97
"https://docs.nobl9.com/replay/replay-sloctl [reset]" ))
@@ -104,7 +104,7 @@ func (r *ReplayCmd) RunReplays(cmd *cobra.Command, replays []ReplayConfig) (fail
104
104
i + 1 , len (replays ), replay .SLO , replay .Project ,
105
105
replay .From .Format (timeLayout ), time .Now ().In (replay .From .Location ()).Format (timeLayout ))))
106
106
107
- if arePlaylistEnabled {
107
+ if r . playlistsAvailable {
108
108
cmd .Println ("Replay is added to the queue..." )
109
109
err = r .runReplay (cmd .Context (), replay )
110
110
@@ -134,7 +134,12 @@ func (r *ReplayCmd) RunReplays(cmd *cobra.Command, replays []ReplayConfig) (fail
134
134
return len (failedIndexes ), nil
135
135
}
136
136
137
- func (r * ReplayCmd ) arePlaylistEnabled (ctx context.Context ) bool {
137
+ type PlaylistConfiguration struct {
138
+ EnabledPlaylists bool `json:"enabledPlaylists"`
139
+ }
140
+
141
+ func (r * ReplayCmd ) arePlaylistEnabled (ctx context.Context ) {
142
+ r .playlistsAvailable = true
138
143
data , _ , err := r .doRequest (
139
144
ctx ,
140
145
http .MethodGet ,
@@ -143,17 +148,13 @@ func (r *ReplayCmd) arePlaylistEnabled(ctx context.Context) bool {
143
148
nil ,
144
149
nil )
145
150
if err != nil {
146
- return true
151
+ fmt . Printf ( "error checking playlist availability: %v \n " , err )
147
152
}
148
153
var pc PlaylistConfiguration
149
154
if err = json .Unmarshal (data , & pc ); err != nil {
150
- return true
155
+ fmt . Printf ( "error unmarshalling playlist configuration: %v \n " , err )
151
156
}
152
- return pc .EnabledPlaylists
153
- }
154
-
155
- type PlaylistConfiguration struct {
156
- EnabledPlaylists bool `json:"enabledPlaylists"`
157
+ r .playlistsAvailable = pc .EnabledPlaylists
157
158
}
158
159
159
160
type ReplayConfig struct {
@@ -345,16 +346,28 @@ outer:
345
346
}
346
347
347
348
// Check Replay availability.
349
+ if err := r .checkReplayAvailability (ctx , replays ); err != nil {
350
+ return err
351
+ }
352
+
353
+ return nil
354
+ }
355
+
356
+ func (r * ReplayCmd ) checkReplayAvailability (ctx context.Context , replays []ReplayConfig ) error {
348
357
notAvailable := make ([]string , 0 )
349
358
mu := sync.Mutex {}
350
359
eg , ctx := errgroup .WithContext (ctx )
351
360
eg .SetLimit (10 )
361
+
352
362
for i := range replays {
353
363
eg .Go (func () error {
354
364
c := replays [i ]
355
365
timeNow := time .Now ()
356
366
tt := c .ToReplay (timeNow )
357
- offset := i * int (averageReplayDuration .Minutes ())
367
+ offset := 0
368
+ if ! r .playlistsAvailable {
369
+ offset = i * int (averageReplayDuration .Minutes ())
370
+ }
358
371
expectedDuration := offset + tt .Duration .Value
359
372
av , err := r .getReplayAvailability (ctx , c , tt .Duration .Unit , expectedDuration )
360
373
if err != nil {
@@ -363,6 +376,7 @@ outer:
363
376
}
364
377
if ! av .Available {
365
378
mu .Lock ()
379
+ defer mu .Unlock ()
366
380
notAvailable = append (notAvailable ,
367
381
fmt .Sprintf ("['%s' SLO in '%s' Project] %s" ,
368
382
c .SLO , c .Project , r .replayUnavailabilityReasonExplanation (
@@ -371,18 +385,20 @@ outer:
371
385
time .Duration (expectedDuration )* time .Minute ,
372
386
time .Duration (offset )* time .Minute ,
373
387
timeNow )))
374
- mu .Unlock ()
375
388
}
376
389
return nil
377
390
})
378
391
}
379
- if err = eg .Wait (); err != nil {
392
+
393
+ if err := eg .Wait (); err != nil {
380
394
return err
381
395
}
396
+
382
397
if len (notAvailable ) > 0 {
383
398
return errors .Errorf ("The following SLOs are not available for Replay: \n - %s" ,
384
399
strings .Join (notAvailable , "\n - " ))
385
400
}
401
+
386
402
return nil
387
403
}
388
404
@@ -542,7 +558,7 @@ func (r *ReplayCmd) replayUnavailabilityReasonExplanation(
542
558
" + %dm (start offset to ensure Replay covers the desired time window) %s." +
543
559
" Edit the Data Source and run Replay once again." ,
544
560
replay .metricSource .Name , replay .metricSource .Project , expectedDuration .String (),
545
- timeNow .Format (timeLayout ), r . from .Format (timeLayout ), startOffsetMinutes , offsetNotice )
561
+ timeNow .Format (timeLayout ), replay . From .Format (timeLayout ), startOffsetMinutes , offsetNotice )
546
562
case sdkModels .ReplayConcurrentReplayRunsLimitExhausted :
547
563
return "You've exceeded the limit of concurrent Replay runs. Wait until the current Replay(s) are done."
548
564
case sdkModels .ReplayUnknownAgentVersion :
0 commit comments