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

golang-migrate / migrate / 10637761005

30 Aug 2024 06:53PM UTC coverage: 56.319% (-0.02%) from 56.335%
10637761005

Pull #1143

github

dhui
Fix redshift tests

Newer versions of postgres require a password
Pull Request #1143: Fix builds

0 of 1 new or added line in 1 file covered. (0.0%)

2 existing lines in 1 file now uncovered.

4559 of 8095 relevant lines covered (56.32%)

52.76 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
        dockertypes "github.com/docker/docker/api/types"
13
        dockercontainer "github.com/docker/docker/api/types/container"
14
        dockernetwork "github.com/docker/docker/api/types/network"
15
        dockerclient "github.com/docker/docker/client"
16
        "github.com/hashicorp/go-multierror"
17
        "io"
18
        "math/rand/v2"
19
        "strconv"
20
        "strings"
21
        "testing"
22
)
23

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

33
        if cmd == nil {
×
34
                cmd = make([]string, 0)
×
35
        }
×
36

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

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

49
        if err := contr.Start(); err != nil {
×
50
                return nil, err
×
51
        }
×
52

53
        return contr, nil
×
54
}
55

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

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

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

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

104
        containerName := fmt.Sprintf("migrate_test_%s", pseudoRandStr(10))
×
105

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

124
        d.ContainerId = resp.ID
×
125
        d.ContainerName = containerName
×
126

×
127
        // then start it
×
128
        if err := d.client.ContainerStart(context.Background(), resp.ID, dockertypes.ContainerStartOptions{}); err != nil {
×
129
                return err
×
130
        }
×
131

132
        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())
×
133
        for _, v := range resp.Warnings {
×
134
                d.t.Logf("Docker: Warning: %v", v)
×
135
        }
×
136
        return nil
×
137
}
138

139
func (d *DockerContainer) KeepForDebugging() {
×
140
        if d == nil {
×
141
                return
×
142
        }
×
143

144
        d.keepForDebugging = true
×
145
}
146

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

152
        if d.keepForDebugging {
×
153
                return nil
×
154
        }
×
155

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

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

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

183
        d.ContainerJSON = resp
×
184
        d.containerInspected = true
×
185
        return nil
×
186
}
187

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

196
        return d.client.ContainerLogs(context.Background(), d.ContainerId, dockertypes.ContainerLogsOptions{
×
197
                ShowStdout: true,
×
198
                ShowStderr: true,
×
199
        })
×
200
}
201

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

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

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

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

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

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

241
        if hostIP == "0.0.0.0" {
×
242
                return "127.0.0.1"
×
243
        } else {
×
244
                return hostIP
×
245
        }
×
246
}
247

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

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

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

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

UNCOV
288
func pseudoRandStr(n int) string {
×
UNCOV
289
        var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz0123456789")
×
290
        b := make([]rune, n)
×
291
        for i := range b {
×
NEW
292
                b[i] = letterRunes[rand.IntN(len(letterRunes))]
×
293
        }
×
294
        return string(b)
×
295
}
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