-
Notifications
You must be signed in to change notification settings - Fork 2
/
podrick.go
85 lines (77 loc) · 1.96 KB
/
podrick.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package podrick
import (
"context"
"fmt"
"time"
backoff "github.com/cenkalti/backoff/v3"
"logur.dev/logur"
)
// StartContainer starts a container using the configured runtime.
// By default, a runtime is chosen automatically from those registered.
func StartContainer(ctx context.Context, repo, tag, port string, opts ...Option) (_ Container, err error) {
conf := config{
ContainerConfig: ContainerConfig{
Repo: repo,
Tag: tag,
Port: port,
},
logger: logur.NewNoopLogger(),
runtime: &autoRuntime{},
}
for _, o := range opts {
o(&conf)
}
err = conf.runtime.Connect(ctx)
if err != nil {
return nil, fmt.Errorf("failed to connect to runtime: %w", err)
}
defer func() {
if err != nil {
cErr := conf.runtime.Close(context.Background())
if cErr != nil {
conf.logger.Error("failed to close runtime", map[string]interface{}{
"error": cErr.Error(),
})
}
}
}()
ctr, err := conf.runtime.StartContainer(ctx, &conf.ContainerConfig)
if err != nil {
return nil, fmt.Errorf("failed to start container: %w", err)
}
defer func() {
if err != nil {
cErr := ctr.Close(context.Background())
if cErr != nil {
conf.logger.Error("failed to close container", map[string]interface{}{
"error": cErr.Error(),
})
}
}
}()
err = ctr.StreamLogs(ctx, logur.NewWriter(conf.logger))
if err != nil {
return nil, fmt.Errorf("failed to stream container logs: %w", err)
}
if conf.liveCheck != nil {
bk := backoff.NewExponentialBackOff()
bk.MaxElapsedTime = 30 * time.Second
cbk := backoff.WithContext(bk, ctx)
err = backoff.RetryNotify(
func() error {
return conf.liveCheck(ctr.Address())
},
cbk,
func(err error, next time.Duration) {
conf.logger.Error("Liveness check failed", map[string]interface{}{
"retry_in": next.Truncate(time.Millisecond).String(),
"error": err.Error(),
})
},
)
if err != nil {
return nil, fmt.Errorf("liveness check failed: %w", err)
}
}
return ctr, nil
}