integration-cli/docker_cli_registry_user_agent_test.go
d1502afb
 package main
 
 import (
 	"fmt"
ebe66b1d
 	"io/ioutil"
d1502afb
 	"net/http"
ebe66b1d
 	"os"
d1502afb
 	"regexp"
 
4300e5e8
 	"github.com/docker/docker/integration-cli/registry"
d1502afb
 	"github.com/go-check/check"
 )
 
 // unescapeBackslashSemicolonParens unescapes \;()
 func unescapeBackslashSemicolonParens(s string) string {
c44e7a3e
 	re := regexp.MustCompile(`\\;`)
d1502afb
 	ret := re.ReplaceAll([]byte(s), []byte(";"))
 
c44e7a3e
 	re = regexp.MustCompile(`\\\(`)
d1502afb
 	ret = re.ReplaceAll([]byte(ret), []byte("("))
 
c44e7a3e
 	re = regexp.MustCompile(`\\\)`)
d1502afb
 	ret = re.ReplaceAll([]byte(ret), []byte(")"))
 
c44e7a3e
 	re = regexp.MustCompile(`\\\\`)
 	ret = re.ReplaceAll([]byte(ret), []byte(`\`))
d1502afb
 
 	return string(ret)
 }
 
 func regexpCheckUA(c *check.C, ua string) {
 	re := regexp.MustCompile("(?P<dockerUA>.+) UpstreamClient(?P<upstreamUA>.+)")
 	substrArr := re.FindStringSubmatch(ua)
 
 	c.Assert(substrArr, check.HasLen, 3, check.Commentf("Expected 'UpstreamClient()' with upstream client UA"))
 	dockerUA := substrArr[1]
 	upstreamUAEscaped := substrArr[2]
 
 	// check dockerUA looks correct
 	reDockerUA := regexp.MustCompile("^docker/[0-9A-Za-z+]")
 	bMatchDockerUA := reDockerUA.MatchString(dockerUA)
 	c.Assert(bMatchDockerUA, check.Equals, true, check.Commentf("Docker Engine User-Agent malformed"))
 
 	// check upstreamUA looks correct
 	// Expecting something like:  Docker-Client/1.11.0-dev (linux)
 	upstreamUA := unescapeBackslashSemicolonParens(upstreamUAEscaped)
 	reUpstreamUA := regexp.MustCompile("^\\(Docker-Client/[0-9A-Za-z+]")
 	bMatchUpstreamUA := reUpstreamUA.MatchString(upstreamUA)
 	c.Assert(bMatchUpstreamUA, check.Equals, true, check.Commentf("(Upstream) Docker Client User-Agent malformed"))
 }
 
5d04fe73
 // registerUserAgentHandler registers a handler for the `/v2/*` endpoint.
 // Note that a 404 is returned to prevent the client to proceed.
 // We are only checking if the client sent a valid User Agent string along
 // with the request.
4300e5e8
 func registerUserAgentHandler(reg *registry.Mock, result *string) {
 	reg.RegisterHandler("/v2/", func(w http.ResponseWriter, r *http.Request) {
d1502afb
 		w.WriteHeader(404)
5d04fe73
 		w.Write([]byte(`{"errors":[{"code": "UNSUPPORTED","message": "this is a mock registry"}]}`))
d1502afb
 		var ua string
 		for k, v := range r.Header {
 			if k == "User-Agent" {
 				ua = v[0]
 			}
 		}
c44e7a3e
 		*result = ua
d1502afb
 	})
c44e7a3e
 }
 
427869fe
 // TestUserAgentPassThrough verifies that when an image is pulled from
c44e7a3e
 // a registry, the registry should see a User-Agent string of the form
40af5691
 // [docker engine UA] UpstreamClientSTREAM-CLIENT([client UA])
c44e7a3e
 func (s *DockerRegistrySuite) TestUserAgentPassThrough(c *check.C) {
5d04fe73
 	var ua string
d1502afb
 
5d04fe73
 	reg, err := registry.NewMock(c)
 	defer reg.Close()
c44e7a3e
 	c.Assert(err, check.IsNil)
5d04fe73
 	registerUserAgentHandler(reg, &ua)
 	repoName := fmt.Sprintf("%s/busybox", reg.URL())
d1502afb
 
5d04fe73
 	s.d.StartWithBusybox(c, "--insecure-registry", reg.URL())
c44e7a3e
 
ebe66b1d
 	tmp, err := ioutil.TempDir("", "integration-cli-")
 	c.Assert(err, check.IsNil)
 	defer os.RemoveAll(tmp)
 
5d04fe73
 	dockerfile, err := makefile(tmp, fmt.Sprintf("FROM %s", repoName))
c44e7a3e
 	c.Assert(err, check.IsNil, check.Commentf("Unable to create test dockerfile"))
ebe66b1d
 
5d04fe73
 	s.d.Cmd("build", "--file", dockerfile, tmp)
 	regexpCheckUA(c, ua)
d1502afb
 
5d04fe73
 	s.d.Cmd("login", "-u", "richard", "-p", "testtest", reg.URL())
 	regexpCheckUA(c, ua)
c44e7a3e
 
5d04fe73
 	s.d.Cmd("pull", repoName)
 	regexpCheckUA(c, ua)
d1502afb
 
5d04fe73
 	s.d.Cmd("tag", "busybox", repoName)
 	s.d.Cmd("push", repoName)
 	regexpCheckUA(c, ua)
d1502afb
 }