Skip to content

Commit 96fcec1

Browse files
committed
Pull the docker container if it doesn't exist.
1 parent 136d4e6 commit 96fcec1

File tree

2 files changed

+41
-33
lines changed

2 files changed

+41
-33
lines changed

.github/workflows/go.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,11 @@ jobs:
4343
- name: Get dependencies
4444
run: |
4545
go get -v -t -d ./...
46-
- name: Get mongo image
47-
run: docker pull registry.hub.docker.com/library/mongo
4846
49-
- name: Test
47+
- name: Test easymongo
5048
run: go test -v .
5149
working-directory: ./easymongo
50+
51+
- name: Test mongotest
52+
run: go test -v .
53+
working-directory: ./pkg/mongotest

pkg/mongotest/mongotest.go

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package mongotest
88
import (
99
"context"
1010
"fmt"
11+
"io/ioutil"
1112
"net"
1213
"runtime/debug"
1314
"strconv"
@@ -31,9 +32,15 @@ type TestConnection struct {
3132
}
3233

3334
// NewTestConnection is the standard method for initializing a TestConnection - it has a side-effect
34-
// of spawning a new docker container
35+
// of spawning a new docker container if spinupDockerContainer is set to true.
36+
// Note that the first time this is called on a new system, the mongo docker
37+
// container will be pulled. Any subsequent calls on the system should succeed without
38+
// calls to pull.
39+
// If spinupDockerContainer is False, then no docker shenanigans occur, instead
40+
// an attempt is made to connect to a locally running mongo instance
41+
// (e.g. mongodb://127.0.0.1:27017).
3542
func NewTestConnection(spinupDockerContainer bool) (*TestConnection, error) {
36-
// TODO: How should we be handling logging? What do the base packages do?
43+
// TODO: How should we be handling logging? What do other libraries typically do?
3744
logger := logrus.New().WithField("src", "mongotest.TestConnection")
3845
mongoURI := "mongodb://127.0.0.1"
3946
testConn := &TestConnection{
@@ -46,9 +53,6 @@ func NewTestConnection(spinupDockerContainer bool) (*TestConnection, error) {
4653
"stack": string(debug.Stack()),
4754
}).Error("A panic occurred when trying to initialize a TestConnection")
4855
// Initialization crashed - ensure the mongo container is destroyed
49-
// if err = testConn.KillMongoContainer(); err != nil {
50-
// logger.WithField("err", err).Error("Could not kill mongo container after TestConnection panic")
51-
// }
5256
_ = testConn.KillMongoContainer()
5357
}
5458
}()
@@ -141,31 +145,29 @@ func GetAvailablePort() (port int, err error) {
141145
if err != nil {
142146
return 0, err
143147
}
144-
// Now try to listen/read on it - just for a few tics
145-
// Calling this makes osx prompt for firewall/network permission
146-
// conn, err := server.Accept()
147-
// defer conn.Close()
148-
// err = conn.SetReadDeadline(time.Now().Add(time.Minute))
149-
// if err != nil {
150-
// return 0, err
151-
// }
152-
// TODO: Fix this check
153-
// go func() {
154-
// b := []byte{}
155-
// _, err = conn.Read(b)
156-
// if err != nil {
157-
// // return 0, err
158-
// panic(err)
159-
// }
160-
// }()
161-
// // Write to connection
162-
// _, err = conn.Write([]byte{1})
163148

164149
// Return the port as an int
165150
// TODO: This is used as a string elsewhere - consider string
166151
return strconv.Atoi(portString)
167152
}
168153

154+
// pullMongoContainer fetches the mongo container from dockerhub
155+
func (tc *TestConnection) pullMongoContainer(mongoImageName string) (err error) {
156+
// TODO: Is this better to do as an error handler?
157+
// Pull the initial container
158+
tc.logger.Info("Starting mongo docker image pull")
159+
rc, err := tc.dockerClient.ImagePull(context.Background(), mongoImageName, types.ImagePullOptions{})
160+
defer rc.Close()
161+
if err != nil {
162+
return fmt.Errorf("could not pull mongo container: %v", err)
163+
}
164+
if _, err := ioutil.ReadAll(rc); err != nil {
165+
return fmt.Errorf("could not pull mongo container: %v", err)
166+
}
167+
tc.logger.Info("Done pulling mongo docker image")
168+
return nil
169+
}
170+
169171
// StartMongoContainer starts a mongo docker container
170172
// A note that the docker daemon on the system is expected to be running
171173
// TODO: Is there a way to spawn the docker daemon myself?
@@ -177,12 +179,7 @@ func (tc *TestConnection) StartMongoContainer(portNumber int) (containerID strin
177179
containerName := fmt.Sprintf("mongo-%d", portNumber)
178180

179181
mongoImageName := "registry.hub.docker.com/library/mongo:latest"
180-
// TODO: Explicitly pull the initial container - ensure user feedback is in place
181-
// rc, err := tc.dockerClient.ImagePull(nil, mongoImageName, types.ImagePullOptions{})
182-
// defer rc.Close()
183-
// if err != nil {
184182

185-
// }
186183
containerResp, err := tc.dockerClient.ContainerCreate(
187184
context.Background(),
188185
&container.Config{
@@ -210,7 +207,16 @@ func (tc *TestConnection) StartMongoContainer(portNumber int) (containerID strin
210207
// TODO: Does this config also need to be specified?
211208
&network.NetworkingConfig{},
212209
containerName)
213-
if err != nil {
210+
if err != nil && docker.IsErrNotFound(err) {
211+
// The image didn't exist locally - go grab it
212+
if err = tc.pullMongoContainer(mongoImageName); err != nil {
213+
// The pull didn't succeed, bail
214+
tc.logger.WithField("err", err).Error("Could not pull the docker container")
215+
return "", err
216+
}
217+
// Now that the pull is complete, we can try to call start again
218+
return tc.StartMongoContainer(portNumber)
219+
} else if err != nil {
214220
tc.logger.WithField("err", err).Error("Could not create the docker container")
215221
return "", err
216222
}

0 commit comments

Comments
 (0)