Fix concurrent uploads that share layers
Concurrent uploads which share layers worked correctly as of #18353, but unfortunately #18785 caused a regression. This PR removed the logic that shares digests between different push sessions. This overlooked the case where one session was waiting for another session to upload a layer. This commit adds back the ability to propagate this digest information, using the distribution.Descriptor type because this is what is received from stats and uploads, and also what is ultimately needed for building the manifest. Surprisingly, there was no test covering this case. This commit adds one. It fails without the fix. See recent comments on #9132. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com> Upstream-commit: 5c99eebe81958a227dfaed1145840374ce50bbbb Component: engine
This commit is contained in:
@ -148,6 +148,61 @@ func (s *DockerSchema1RegistrySuite) TestPushEmptyLayer(c *check.C) {
|
||||
testPushEmptyLayer(c)
|
||||
}
|
||||
|
||||
// testConcurrentPush pushes multiple tags to the same repo
|
||||
// concurrently.
|
||||
func testConcurrentPush(c *check.C) {
|
||||
repoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
|
||||
|
||||
repos := []string{}
|
||||
for _, tag := range []string{"push1", "push2", "push3"} {
|
||||
repo := fmt.Sprintf("%v:%v", repoName, tag)
|
||||
_, err := buildImage(repo, fmt.Sprintf(`
|
||||
FROM busybox
|
||||
ENTRYPOINT ["/bin/echo"]
|
||||
ENV FOO foo
|
||||
ENV BAR bar
|
||||
CMD echo %s
|
||||
`, repo), true)
|
||||
c.Assert(err, checker.IsNil)
|
||||
repos = append(repos, repo)
|
||||
}
|
||||
|
||||
// Push tags, in parallel
|
||||
results := make(chan error)
|
||||
|
||||
for _, repo := range repos {
|
||||
go func(repo string) {
|
||||
_, _, err := runCommandWithOutput(exec.Command(dockerBinary, "push", repo))
|
||||
results <- err
|
||||
}(repo)
|
||||
}
|
||||
|
||||
for range repos {
|
||||
err := <-results
|
||||
c.Assert(err, checker.IsNil, check.Commentf("concurrent push failed with error: %v", err))
|
||||
}
|
||||
|
||||
// Clear local images store.
|
||||
args := append([]string{"rmi"}, repos...)
|
||||
dockerCmd(c, args...)
|
||||
|
||||
// Re-pull and run individual tags, to make sure pushes succeeded
|
||||
for _, repo := range repos {
|
||||
dockerCmd(c, "pull", repo)
|
||||
dockerCmd(c, "inspect", repo)
|
||||
out, _ := dockerCmd(c, "run", "--rm", repo)
|
||||
c.Assert(strings.TrimSpace(out), checker.Equals, "/bin/sh -c echo "+repo)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerRegistrySuite) TestConcurrentPush(c *check.C) {
|
||||
testConcurrentPush(c)
|
||||
}
|
||||
|
||||
func (s *DockerSchema1RegistrySuite) TestConcurrentPush(c *check.C) {
|
||||
testConcurrentPush(c)
|
||||
}
|
||||
|
||||
func (s *DockerRegistrySuite) TestCrossRepositoryLayerPush(c *check.C) {
|
||||
sourceRepoName := fmt.Sprintf("%v/dockercli/busybox", privateRegistryURL)
|
||||
// tag the image to upload it to the private registry
|
||||
|
||||
Reference in New Issue
Block a user