robocar-base/vendor/github.com/testcontainers/testcontainers-go/wait/log.go

121 lines
2.7 KiB
Go
Raw Normal View History

2020-03-01 16:06:34 +00:00
package wait
import (
"context"
"io"
2020-03-01 16:06:34 +00:00
"strings"
"time"
)
// Implement interface
var _ Strategy = (*LogStrategy)(nil)
var _ StrategyTimeout = (*LogStrategy)(nil)
2020-03-01 16:06:34 +00:00
// LogStrategy will wait until a given log entry shows up in the docker logs
type LogStrategy struct {
// all Strategies should have a startupTimeout to avoid waiting infinitely
timeout *time.Duration
2020-03-01 16:06:34 +00:00
// additional properties
Log string
Occurrence int
2021-01-17 18:00:46 +00:00
PollInterval time.Duration
2020-03-01 16:06:34 +00:00
}
// NewLogStrategy constructs with polling interval of 100 milliseconds and startup timeout of 60 seconds by default
2020-03-01 16:06:34 +00:00
func NewLogStrategy(log string) *LogStrategy {
return &LogStrategy{
Log: log,
Occurrence: 1,
PollInterval: defaultPollInterval(),
2020-03-01 16:06:34 +00:00
}
}
// fluent builders for each property
// since go has neither covariance nor generics, the return type must be the type of the concrete implementation
// this is true for all properties, even the "shared" ones like startupTimeout
// WithStartupTimeout can be used to change the default startup timeout
func (ws *LogStrategy) WithStartupTimeout(timeout time.Duration) *LogStrategy {
ws.timeout = &timeout
2020-03-01 16:06:34 +00:00
return ws
}
// WithPollInterval can be used to override the default polling interval of 100 milliseconds
func (ws *LogStrategy) WithPollInterval(pollInterval time.Duration) *LogStrategy {
ws.PollInterval = pollInterval
return ws
}
func (ws *LogStrategy) WithOccurrence(o int) *LogStrategy {
// the number of occurrence needs to be positive
2020-03-01 16:06:34 +00:00
if o <= 0 {
o = 1
}
ws.Occurrence = o
return ws
}
// ForLog is the default construction for the fluid interface.
//
// For Example:
//
// wait.
// ForLog("some text").
// WithPollInterval(1 * time.Second)
2020-03-01 16:06:34 +00:00
func ForLog(log string) *LogStrategy {
return NewLogStrategy(log)
}
func (ws *LogStrategy) Timeout() *time.Duration {
return ws.timeout
}
2020-03-01 16:06:34 +00:00
// WaitUntilReady implements Strategy.WaitUntilReady
func (ws *LogStrategy) WaitUntilReady(ctx context.Context, target StrategyTarget) (err error) {
timeout := defaultStartupTimeout()
if ws.timeout != nil {
timeout = *ws.timeout
}
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
length := 0
2020-03-01 16:06:34 +00:00
LOOP:
for {
select {
case <-ctx.Done():
return ctx.Err()
default:
checkErr := checkTarget(ctx, target)
2020-03-01 16:06:34 +00:00
reader, err := target.Logs(ctx)
if err != nil {
time.Sleep(ws.PollInterval)
continue
}
2020-03-01 16:06:34 +00:00
b, err := io.ReadAll(reader)
2020-03-01 16:06:34 +00:00
if err != nil {
time.Sleep(ws.PollInterval)
continue
}
2020-03-01 16:06:34 +00:00
logs := string(b)
if length == len(logs) && checkErr != nil {
return checkErr
} else if strings.Count(logs, ws.Log) >= ws.Occurrence {
break LOOP
2020-03-01 16:06:34 +00:00
} else {
length = len(logs)
2020-03-01 16:06:34 +00:00
time.Sleep(ws.PollInterval)
continue
}
}
}
return nil
}