• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

golang-migrate / migrate / 10757516114

08 Sep 2024 05:58AM UTC coverage: 56.319%. Remained the same
10757516114

push

github

web-flow
Merge pull request #1153 from joschi/fix-docker-imports

fix(tests): fix Docker imports

0 of 5 new or added lines in 2 files covered. (0.0%)

54 existing lines in 2 files now uncovered.

4559 of 8095 relevant lines covered (56.32%)

63.9 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/testing/docker.go
1
// Package testing is used in driver tests and should only be used by migrate tests.
2
//
3
// Deprecated: If you'd like to test using Docker images, use package github.com/dhui/dktest instead
4
package testing
5

6
import (
7
        "bufio"
8
        "context"
9
        "encoding/json"
10
        "errors"
11
        "fmt"
12
        "io"
13
        "math/rand/v2"
14
        "strconv"
15
        "strings"
16
        "testing"
17

18
        dockertypes "github.com/docker/docker/api/types"
19
        dockercontainer "github.com/docker/docker/api/types/container"
20
        dockerimage "github.com/docker/docker/api/types/image"
21
        dockernetwork "github.com/docker/docker/api/types/network"
22
        dockerclient "github.com/docker/docker/client"
23
        "github.com/hashicorp/go-multierror"
24
)
25

UNCOV
26
func NewDockerContainer(t testing.TB, image string, env []string, cmd []string) (*DockerContainer, error) {
×
UNCOV
27
        c, err := dockerclient.NewClientWithOpts(
×
28
                dockerclient.FromEnv,
×
29
                dockerclient.WithAPIVersionNegotiation(),
×
30
        )
×
31
        if err != nil {
×
32
                return nil, err
×
33
        }
×
34

35
        if cmd == nil {
×
UNCOV
36
                cmd = make([]string, 0)
×
37
        }
×
38

39
        contr := &DockerContainer{
×
UNCOV
40
                t:         t,
×
41
                client:    c,
×
42
                ImageName: image,
×
43
                ENV:       env,
×
44
                Cmd:       cmd,
×
45
        }
×
46

×
47
        if err := contr.PullImage(); err != nil {
×
48
                return nil, err
×
49
        }
×
50

51
        if err := contr.Start(); err != nil {
×
UNCOV
52
                return nil, err
×
53
        }
×
54

55
        return contr, nil
×
56
}
57

58
// DockerContainer implements Instance interface
59
type DockerContainer struct {
60
        t                  testing.TB
61
        client             *dockerclient.Client
62
        ImageName          string
63
        ENV                []string
64
        Cmd                []string
65
        ContainerId        string
66
        ContainerName      string
67
        ContainerJSON      dockertypes.ContainerJSON
68
        containerInspected bool
69
        keepForDebugging   bool
70
}
71

UNCOV
72
func (d *DockerContainer) PullImage() (err error) {
×
UNCOV
73
        if d == nil {
×
74
                return errors.New("Cannot pull image on a nil *DockerContainer")
×
75
        }
×
76
        d.t.Logf("Docker: Pull image %v", d.ImageName)
×
NEW
77
        r, err := d.client.ImagePull(context.Background(), d.ImageName, dockerimage.PullOptions{})
×
78
        if err != nil {
×
79
                return err
×
80
        }
×
81
        defer func() {
×
82
                if errClose := r.Close(); errClose != nil {
×
83
                        err = multierror.Append(errClose)
×
84
                }
×
85
        }()
86

87
        // read output and log relevant lines
UNCOV
88
        bf := bufio.NewScanner(r)
×
UNCOV
89
        for bf.Scan() {
×
90
                var resp dockerImagePullOutput
×
91
                if err := json.Unmarshal(bf.Bytes(), &resp); err != nil {
×
92
                        return err
×
93
                }
×
94
                if strings.HasPrefix(resp.Status, "Status: ") {
×
95
                        d.t.Logf("Docker: %v", resp.Status)
×
96
                }
×
97
        }
98
        return bf.Err()
×
99
}
100

UNCOV
101
func (d *DockerContainer) Start() error {
×
UNCOV
102
        if d == nil {
×
103
                return errors.New("Cannot start a nil *DockerContainer")
×
104
        }
×
105

106
        containerName := fmt.Sprintf("migrate_test_%s", pseudoRandStr(10))
×
UNCOV
107

×
108
        // create container first
×
109
        resp, err := d.client.ContainerCreate(context.Background(),
×
110
                &dockercontainer.Config{
×
111
                        Image:  d.ImageName,
×
112
                        Labels: map[string]string{"migrate_test": "true"},
×
113
                        Env:    d.ENV,
×
114
                        Cmd:    d.Cmd,
×
115
                },
×
116
                &dockercontainer.HostConfig{
×
117
                        PublishAllPorts: true,
×
118
                },
×
119
                &dockernetwork.NetworkingConfig{},
×
120
                nil,
×
121
                containerName)
×
122
        if err != nil {
×
123
                return err
×
124
        }
×
125

126
        d.ContainerId = resp.ID
×
UNCOV
127
        d.ContainerName = containerName
×
128

×
129
        // then start it
×
NEW
130
        if err := d.client.ContainerStart(context.Background(), resp.ID, dockercontainer.StartOptions{}); err != nil {
×
131
                return err
×
132
        }
×
133

134
        d.t.Logf("Docker: Started container %v (%v) for image %v listening at %v:%v", resp.ID[0:12], containerName, d.ImageName, d.Host(), d.Port())
×
UNCOV
135
        for _, v := range resp.Warnings {
×
136
                d.t.Logf("Docker: Warning: %v", v)
×
137
        }
×
138
        return nil
×
139
}
140

UNCOV
141
func (d *DockerContainer) KeepForDebugging() {
×
UNCOV
142
        if d == nil {
×
143
                return
×
144
        }
×
145

146
        d.keepForDebugging = true
×
147
}
148

UNCOV
149
func (d *DockerContainer) Remove() error {
×
UNCOV
150
        if d == nil {
×
151
                return errors.New("Cannot remove a nil *DockerContainer")
×
152
        }
×
153

154
        if d.keepForDebugging {
×
UNCOV
155
                return nil
×
156
        }
×
157

158
        if len(d.ContainerId) == 0 {
×
UNCOV
159
                return errors.New("missing containerId")
×
160
        }
×
161
        if err := d.client.ContainerRemove(context.Background(), d.ContainerId,
×
NEW
162
                dockercontainer.RemoveOptions{
×
163
                        Force: true,
×
164
                }); err != nil {
×
165
                d.t.Log(err)
×
166
                return err
×
167
        }
×
168
        d.t.Logf("Docker: Removed %v", d.ContainerName)
×
169
        return nil
×
170
}
171

UNCOV
172
func (d *DockerContainer) Inspect() error {
×
UNCOV
173
        if d == nil {
×
174
                return errors.New("Cannot inspect a nil *DockerContainer")
×
175
        }
×
176

177
        if len(d.ContainerId) == 0 {
×
UNCOV
178
                return errors.New("missing containerId")
×
179
        }
×
180
        resp, err := d.client.ContainerInspect(context.Background(), d.ContainerId)
×
181
        if err != nil {
×
182
                return err
×
183
        }
×
184

185
        d.ContainerJSON = resp
×
UNCOV
186
        d.containerInspected = true
×
187
        return nil
×
188
}
189

UNCOV
190
func (d *DockerContainer) Logs() (io.ReadCloser, error) {
×
UNCOV
191
        if d == nil {
×
192
                return nil, errors.New("Cannot view logs for a nil *DockerContainer")
×
193
        }
×
194
        if len(d.ContainerId) == 0 {
×
195
                return nil, errors.New("missing containerId")
×
196
        }
×
197

NEW
198
        return d.client.ContainerLogs(context.Background(), d.ContainerId, dockercontainer.LogsOptions{
×
UNCOV
199
                ShowStdout: true,
×
200
                ShowStderr: true,
×
201
        })
×
202
}
203

UNCOV
204
func (d *DockerContainer) portMapping(selectFirst bool, cPort int) (containerPort uint, hostIP string, hostPort uint, err error) { // nolint:unparam
×
UNCOV
205
        if !d.containerInspected {
×
206
                if err := d.Inspect(); err != nil {
×
207
                        d.t.Fatal(err)
×
208
                }
×
209
        }
210

UNCOV
211
        for port, bindings := range d.ContainerJSON.NetworkSettings.Ports {
×
UNCOV
212
                if !selectFirst && port.Int() != cPort {
×
213
                        // Skip ahead until we find the port we want
×
214
                        continue
×
215
                }
216
                for _, binding := range bindings {
×
UNCOV
217

×
218
                        hostPortUint, err := strconv.ParseUint(binding.HostPort, 10, 64)
×
219
                        if err != nil {
×
220
                                return 0, "", 0, err
×
221
                        }
×
222

223
                        return uint(port.Int()), binding.HostIP, uint(hostPortUint), nil // nolint: staticcheck
×
224
                }
225
        }
226

UNCOV
227
        if selectFirst {
×
UNCOV
228
                return 0, "", 0, errors.New("no port binding")
×
229
        } else {
×
230
                return 0, "", 0, errors.New("specified port not bound")
×
231
        }
×
232
}
233

UNCOV
234
func (d *DockerContainer) Host() string {
×
UNCOV
235
        if d == nil {
×
236
                panic("Cannot get host for a nil *DockerContainer")
×
237
        }
238
        _, hostIP, _, err := d.portMapping(true, -1)
×
UNCOV
239
        if err != nil {
×
240
                d.t.Fatal(err)
×
241
        }
×
242

243
        if hostIP == "0.0.0.0" {
×
UNCOV
244
                return "127.0.0.1"
×
245
        } else {
×
246
                return hostIP
×
247
        }
×
248
}
249

UNCOV
250
func (d *DockerContainer) Port() uint {
×
UNCOV
251
        if d == nil {
×
252
                panic("Cannot get port for a nil *DockerContainer")
×
253
        }
254
        _, _, port, err := d.portMapping(true, -1)
×
UNCOV
255
        if err != nil {
×
256
                d.t.Fatal(err)
×
257
        }
×
258
        return port
×
259
}
260

UNCOV
261
func (d *DockerContainer) PortFor(cPort int) uint {
×
UNCOV
262
        if d == nil {
×
263
                panic("Cannot get port for a nil *DockerContainer")
×
264
        }
265
        _, _, port, err := d.portMapping(false, cPort)
×
UNCOV
266
        if err != nil {
×
267
                d.t.Fatal(err)
×
268
        }
×
269
        return port
×
270
}
271

UNCOV
272
func (d *DockerContainer) NetworkSettings() dockertypes.NetworkSettings {
×
UNCOV
273
        if d == nil {
×
274
                panic("Cannot get network settings for a nil *DockerContainer")
×
275
        }
276
        netSettings := d.ContainerJSON.NetworkSettings
×
UNCOV
277
        return *netSettings
×
278
}
279

280
type dockerImagePullOutput struct {
281
        Status          string `json:"status"`
282
        ProgressDetails struct {
283
                Current int `json:"current"`
284
                Total   int `json:"total"`
285
        } `json:"progressDetail"`
286
        Id       string `json:"id"`
287
        Progress string `json:"progress"`
288
}
289

UNCOV
290
func pseudoRandStr(n int) string {
×
UNCOV
291
        var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
×
292
        b := make([]rune, n)
×
293
        for i := range b {
×
294
                b[i] = letterRunes[rand.IntN(len(letterRunes))]
×
295
        }
×
296
        return string(b)
×
297
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc