https://github.com/thediveo/morbyd is a thin layer on top of the standard
Docker Go client to easily build and run throw-away test Docker images and
containers, and running commands inside them. It features a function option
API to keep the slightly excessive Docker API option parameters at bay.
(And large test coverage FWIW).
You might ask: why, when there's ory/dockertest/v3?
Because their Ory's proprietary Docker client (predating the canonical one)
is incompatible with the Docker daemon's 100 CONTINUE header when streaming
container and command stdout/stderr. I've reported this, but did not got
any response at all, so I finally cut my losses and wrote "morbyd" to be
able to move on. The proper Docker client allows me to easily dump and
analyse build and container output when tests go south.
Below is how morbyd feels, compared to ory/dockertest/v3, to give you an
idea which API design might be better suited for you (or not):
dockertest (using Gomega for assertions):
Expect(pool.Client.BuildImage(docker.BuildImageOptions{
Name: img.Name,
ContextDir: "./test/_kindisch", // sorry, couldn't resist the pun.
Dockerfile: "Dockerfile",
BuildArgs: []docker.BuildArg{
{Name: "KINDEST_BASE_TAG", Value: test.KindestBaseImageTag},
},
OutputStream: io.Discard,
})).To(Succeed())
providerCntr := Successful(pool.RunWithOptions(
&dockertest.RunOptions{
Name: kindischName,
Repository: img.Name,
Privileged: true,
Mounts: []string{
"/var", // well, this actually is an unnamed volume
"/dev/mapper:/dev/mapper",
"/lib/modules:/lib/modules:ro",
},
Tty: true,
}, func(hc *docker.HostConfig) {
hc.Init = false
hc.Tmpfs = map[string]string{
"/tmp": "",
"/run": "",
}
hc.Devices = []docker.Device{
{PathOnHost: "/dev/fuse"},
}
}))
morbyd (also using Gomega for assertions):
Expect(sess.BuildImage(ctx, "./test/_kindisch",
build.WithTag(img.Name),
build.WithBuildArg("KINDEST_BASE_TAG="+test.KindestBaseImageTag),
build.WithOutput(timestamper.New(GinkgoWriter)))).
Error().NotTo(HaveOccurred())
providerCntr := Successful(sess.Run(ctx, img.Name,
run.WithName(kindischName),
run.WithAutoRemove(),
run.WithPrivileged(),
run.WithSecurityOpt("label=disable"),
run.WithCgroupnsMode("private"),
run.WithVolume("/var"),
run.WithVolume("/dev/mapper:/dev/mapper"),
run.WithVolume("/lib/modules:/lib/modules:ro"),
run.WithTmpfs("/tmp"),
run.WithTmpfs("/run"),
run.WithDevice("/dev/fuse"),
run.WithCombinedOutput(timestamper.New(GinkgoWriter))))
Some of these options are not simply writing their arg in the same-name
struct field, but instead are parsing things, preferably in the same way as
the Docker CLI does. So the transition from CLI args to unit test args
should be much smoother without having to dig deep into the Docker API
parameter details.
While I tried to strive for more option completeness than just my own
minimal viable proof, there surely a bits and pieces missing. In case
morbyd might be interesting for you, I would be glad to hear from you and
also missing pieces; and preferably a PR if you would be so kind.
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/34643167-7222-4e7a-a1a8-79d757c2c8fen%40googlegroups.com.