mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Signed-off-by: Amit Krishnan <krish.amit@gmail.com> Signed-off-by: Alexander Morozov <lk4d4@docker.com>
		
			
				
	
	
		
			478 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			478 lines
		
	
	
	
		
			14 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build !solaris
 | 
						|
 | 
						|
package registry
 | 
						|
 | 
						|
import (
 | 
						|
	"encoding/json"
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"io"
 | 
						|
	"io/ioutil"
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"net/http/httptest"
 | 
						|
	"net/url"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	registrytypes "github.com/docker/docker/api/types/registry"
 | 
						|
	"github.com/docker/docker/reference"
 | 
						|
	"github.com/gorilla/mux"
 | 
						|
 | 
						|
	"github.com/Sirupsen/logrus"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	testHTTPServer  *httptest.Server
 | 
						|
	testHTTPSServer *httptest.Server
 | 
						|
	testLayers      = map[string]map[string]string{
 | 
						|
		"77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20": {
 | 
						|
			"json": `{"id":"77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20",
 | 
						|
				"comment":"test base image","created":"2013-03-23T12:53:11.10432-07:00",
 | 
						|
				"container_config":{"Hostname":"","User":"","Memory":0,"MemorySwap":0,
 | 
						|
				"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,
 | 
						|
				"Tty":false,"OpenStdin":false,"StdinOnce":false,
 | 
						|
				"Env":null,"Cmd":null,"Dns":null,"Image":"","Volumes":null,
 | 
						|
				"VolumesFrom":"","Entrypoint":null},"Size":424242}`,
 | 
						|
			"checksum_simple": "sha256:1ac330d56e05eef6d438586545ceff7550d3bdcb6b19961f12c5ba714ee1bb37",
 | 
						|
			"checksum_tarsum": "tarsum+sha256:4409a0685741ca86d38df878ed6f8cbba4c99de5dc73cd71aef04be3bb70be7c",
 | 
						|
			"ancestry":        `["77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20"]`,
 | 
						|
			"layer": string([]byte{
 | 
						|
				0x1f, 0x8b, 0x08, 0x08, 0x0e, 0xb0, 0xee, 0x51, 0x02, 0x03, 0x6c, 0x61, 0x79, 0x65,
 | 
						|
				0x72, 0x2e, 0x74, 0x61, 0x72, 0x00, 0xed, 0xd2, 0x31, 0x0e, 0xc2, 0x30, 0x0c, 0x05,
 | 
						|
				0x50, 0xcf, 0x9c, 0xc2, 0x27, 0x48, 0xed, 0x38, 0x4e, 0xce, 0x13, 0x44, 0x2b, 0x66,
 | 
						|
				0x62, 0x24, 0x8e, 0x4f, 0xa0, 0x15, 0x63, 0xb6, 0x20, 0x21, 0xfc, 0x96, 0xbf, 0x78,
 | 
						|
				0xb0, 0xf5, 0x1d, 0x16, 0x98, 0x8e, 0x88, 0x8a, 0x2a, 0xbe, 0x33, 0xef, 0x49, 0x31,
 | 
						|
				0xed, 0x79, 0x40, 0x8e, 0x5c, 0x44, 0x85, 0x88, 0x33, 0x12, 0x73, 0x2c, 0x02, 0xa8,
 | 
						|
				0xf0, 0x05, 0xf7, 0x66, 0xf5, 0xd6, 0x57, 0x69, 0xd7, 0x7a, 0x19, 0xcd, 0xf5, 0xb1,
 | 
						|
				0x6d, 0x1b, 0x1f, 0xf9, 0xba, 0xe3, 0x93, 0x3f, 0x22, 0x2c, 0xb6, 0x36, 0x0b, 0xf6,
 | 
						|
				0xb0, 0xa9, 0xfd, 0xe7, 0x94, 0x46, 0xfd, 0xeb, 0xd1, 0x7f, 0x2c, 0xc4, 0xd2, 0xfb,
 | 
						|
				0x97, 0xfe, 0x02, 0x80, 0xe4, 0xfd, 0x4f, 0x77, 0xae, 0x6d, 0x3d, 0x81, 0x73, 0xce,
 | 
						|
				0xb9, 0x7f, 0xf3, 0x04, 0x41, 0xc1, 0xab, 0xc6, 0x00, 0x0a, 0x00, 0x00,
 | 
						|
			}),
 | 
						|
		},
 | 
						|
		"42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d": {
 | 
						|
			"json": `{"id":"42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
 | 
						|
				"parent":"77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20",
 | 
						|
				"comment":"test base image","created":"2013-03-23T12:55:11.10432-07:00",
 | 
						|
				"container_config":{"Hostname":"","User":"","Memory":0,"MemorySwap":0,
 | 
						|
				"CpuShares":0,"AttachStdin":false,"AttachStdout":false,"AttachStderr":false,
 | 
						|
				"Tty":false,"OpenStdin":false,"StdinOnce":false,
 | 
						|
				"Env":null,"Cmd":null,"Dns":null,"Image":"","Volumes":null,
 | 
						|
				"VolumesFrom":"","Entrypoint":null},"Size":424242}`,
 | 
						|
			"checksum_simple": "sha256:bea7bf2e4bacd479344b737328db47b18880d09096e6674165533aa994f5e9f2",
 | 
						|
			"checksum_tarsum": "tarsum+sha256:68fdb56fb364f074eec2c9b3f85ca175329c4dcabc4a6a452b7272aa613a07a2",
 | 
						|
			"ancestry": `["42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
 | 
						|
				"77dbf71da1d00e3fbddc480176eac8994025630c6590d11cfc8fe1209c2a1d20"]`,
 | 
						|
			"layer": string([]byte{
 | 
						|
				0x1f, 0x8b, 0x08, 0x08, 0xbd, 0xb3, 0xee, 0x51, 0x02, 0x03, 0x6c, 0x61, 0x79, 0x65,
 | 
						|
				0x72, 0x2e, 0x74, 0x61, 0x72, 0x00, 0xed, 0xd1, 0x31, 0x0e, 0xc2, 0x30, 0x0c, 0x05,
 | 
						|
				0x50, 0xcf, 0x9c, 0xc2, 0x27, 0x48, 0x9d, 0x38, 0x8e, 0xcf, 0x53, 0x51, 0xaa, 0x56,
 | 
						|
				0xea, 0x44, 0x82, 0xc4, 0xf1, 0x09, 0xb4, 0xea, 0x98, 0x2d, 0x48, 0x08, 0xbf, 0xe5,
 | 
						|
				0x2f, 0x1e, 0xfc, 0xf5, 0xdd, 0x00, 0xdd, 0x11, 0x91, 0x8a, 0xe0, 0x27, 0xd3, 0x9e,
 | 
						|
				0x14, 0xe2, 0x9e, 0x07, 0xf4, 0xc1, 0x2b, 0x0b, 0xfb, 0xa4, 0x82, 0xe4, 0x3d, 0x93,
 | 
						|
				0x02, 0x0a, 0x7c, 0xc1, 0x23, 0x97, 0xf1, 0x5e, 0x5f, 0xc9, 0xcb, 0x38, 0xb5, 0xee,
 | 
						|
				0xea, 0xd9, 0x3c, 0xb7, 0x4b, 0xbe, 0x7b, 0x9c, 0xf9, 0x23, 0xdc, 0x50, 0x6e, 0xb9,
 | 
						|
				0xb8, 0xf2, 0x2c, 0x5d, 0xf7, 0x4f, 0x31, 0xb6, 0xf6, 0x4f, 0xc7, 0xfe, 0x41, 0x55,
 | 
						|
				0x63, 0xdd, 0x9f, 0x89, 0x09, 0x90, 0x6c, 0xff, 0xee, 0xae, 0xcb, 0xba, 0x4d, 0x17,
 | 
						|
				0x30, 0xc6, 0x18, 0xf3, 0x67, 0x5e, 0xc1, 0xed, 0x21, 0x5d, 0x00, 0x0a, 0x00, 0x00,
 | 
						|
			}),
 | 
						|
		},
 | 
						|
	}
 | 
						|
	testRepositories = map[string]map[string]string{
 | 
						|
		"foo42/bar": {
 | 
						|
			"latest": "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
 | 
						|
			"test":   "42d718c941f5c532ac049bf0b0ab53f0062f09a03afd4aa4a02c098e46032b9d",
 | 
						|
		},
 | 
						|
	}
 | 
						|
	mockHosts = map[string][]net.IP{
 | 
						|
		"":            {net.ParseIP("0.0.0.0")},
 | 
						|
		"localhost":   {net.ParseIP("127.0.0.1"), net.ParseIP("::1")},
 | 
						|
		"example.com": {net.ParseIP("42.42.42.42")},
 | 
						|
		"other.com":   {net.ParseIP("43.43.43.43")},
 | 
						|
	}
 | 
						|
)
 | 
						|
 | 
						|
func init() {
 | 
						|
	r := mux.NewRouter()
 | 
						|
 | 
						|
	// /v1/
 | 
						|
	r.HandleFunc("/v1/_ping", handlerGetPing).Methods("GET")
 | 
						|
	r.HandleFunc("/v1/images/{image_id:[^/]+}/{action:json|layer|ancestry}", handlerGetImage).Methods("GET")
 | 
						|
	r.HandleFunc("/v1/images/{image_id:[^/]+}/{action:json|layer|checksum}", handlerPutImage).Methods("PUT")
 | 
						|
	r.HandleFunc("/v1/repositories/{repository:.+}/tags", handlerGetDeleteTags).Methods("GET", "DELETE")
 | 
						|
	r.HandleFunc("/v1/repositories/{repository:.+}/tags/{tag:.+}", handlerGetTag).Methods("GET")
 | 
						|
	r.HandleFunc("/v1/repositories/{repository:.+}/tags/{tag:.+}", handlerPutTag).Methods("PUT")
 | 
						|
	r.HandleFunc("/v1/users{null:.*}", handlerUsers).Methods("GET", "POST", "PUT")
 | 
						|
	r.HandleFunc("/v1/repositories/{repository:.+}{action:/images|/}", handlerImages).Methods("GET", "PUT", "DELETE")
 | 
						|
	r.HandleFunc("/v1/repositories/{repository:.+}/auth", handlerAuth).Methods("PUT")
 | 
						|
	r.HandleFunc("/v1/search", handlerSearch).Methods("GET")
 | 
						|
 | 
						|
	// /v2/
 | 
						|
	r.HandleFunc("/v2/version", handlerGetPing).Methods("GET")
 | 
						|
 | 
						|
	testHTTPServer = httptest.NewServer(handlerAccessLog(r))
 | 
						|
	testHTTPSServer = httptest.NewTLSServer(handlerAccessLog(r))
 | 
						|
 | 
						|
	// override net.LookupIP
 | 
						|
	lookupIP = func(host string) ([]net.IP, error) {
 | 
						|
		if host == "127.0.0.1" {
 | 
						|
			// I believe in future Go versions this will fail, so let's fix it later
 | 
						|
			return net.LookupIP(host)
 | 
						|
		}
 | 
						|
		for h, addrs := range mockHosts {
 | 
						|
			if host == h {
 | 
						|
				return addrs, nil
 | 
						|
			}
 | 
						|
			for _, addr := range addrs {
 | 
						|
				if addr.String() == host {
 | 
						|
					return []net.IP{addr}, nil
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return nil, errors.New("lookup: no such host")
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func handlerAccessLog(handler http.Handler) http.Handler {
 | 
						|
	logHandler := func(w http.ResponseWriter, r *http.Request) {
 | 
						|
		logrus.Debugf("%s \"%s %s\"", r.RemoteAddr, r.Method, r.URL)
 | 
						|
		handler.ServeHTTP(w, r)
 | 
						|
	}
 | 
						|
	return http.HandlerFunc(logHandler)
 | 
						|
}
 | 
						|
 | 
						|
func makeURL(req string) string {
 | 
						|
	return testHTTPServer.URL + req
 | 
						|
}
 | 
						|
 | 
						|
func makeHTTPSURL(req string) string {
 | 
						|
	return testHTTPSServer.URL + req
 | 
						|
}
 | 
						|
 | 
						|
func makeIndex(req string) *registrytypes.IndexInfo {
 | 
						|
	index := ®istrytypes.IndexInfo{
 | 
						|
		Name: makeURL(req),
 | 
						|
	}
 | 
						|
	return index
 | 
						|
}
 | 
						|
 | 
						|
func makeHTTPSIndex(req string) *registrytypes.IndexInfo {
 | 
						|
	index := ®istrytypes.IndexInfo{
 | 
						|
		Name: makeHTTPSURL(req),
 | 
						|
	}
 | 
						|
	return index
 | 
						|
}
 | 
						|
 | 
						|
func makePublicIndex() *registrytypes.IndexInfo {
 | 
						|
	index := ®istrytypes.IndexInfo{
 | 
						|
		Name:     IndexServer,
 | 
						|
		Secure:   true,
 | 
						|
		Official: true,
 | 
						|
	}
 | 
						|
	return index
 | 
						|
}
 | 
						|
 | 
						|
func makeServiceConfig(mirrors []string, insecureRegistries []string) *serviceConfig {
 | 
						|
	options := ServiceOptions{
 | 
						|
		Mirrors:            mirrors,
 | 
						|
		InsecureRegistries: insecureRegistries,
 | 
						|
	}
 | 
						|
 | 
						|
	return newServiceConfig(options)
 | 
						|
}
 | 
						|
 | 
						|
func writeHeaders(w http.ResponseWriter) {
 | 
						|
	h := w.Header()
 | 
						|
	h.Add("Server", "docker-tests/mock")
 | 
						|
	h.Add("Expires", "-1")
 | 
						|
	h.Add("Content-Type", "application/json")
 | 
						|
	h.Add("Pragma", "no-cache")
 | 
						|
	h.Add("Cache-Control", "no-cache")
 | 
						|
	h.Add("X-Docker-Registry-Version", "0.0.0")
 | 
						|
	h.Add("X-Docker-Registry-Config", "mock")
 | 
						|
}
 | 
						|
 | 
						|
func writeResponse(w http.ResponseWriter, message interface{}, code int) {
 | 
						|
	writeHeaders(w)
 | 
						|
	w.WriteHeader(code)
 | 
						|
	body, err := json.Marshal(message)
 | 
						|
	if err != nil {
 | 
						|
		io.WriteString(w, err.Error())
 | 
						|
		return
 | 
						|
	}
 | 
						|
	w.Write(body)
 | 
						|
}
 | 
						|
 | 
						|
func readJSON(r *http.Request, dest interface{}) error {
 | 
						|
	body, err := ioutil.ReadAll(r.Body)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	return json.Unmarshal(body, dest)
 | 
						|
}
 | 
						|
 | 
						|
func apiError(w http.ResponseWriter, message string, code int) {
 | 
						|
	body := map[string]string{
 | 
						|
		"error": message,
 | 
						|
	}
 | 
						|
	writeResponse(w, body, code)
 | 
						|
}
 | 
						|
 | 
						|
func assertEqual(t *testing.T, a interface{}, b interface{}, message string) {
 | 
						|
	if a == b {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if len(message) == 0 {
 | 
						|
		message = fmt.Sprintf("%v != %v", a, b)
 | 
						|
	}
 | 
						|
	t.Fatal(message)
 | 
						|
}
 | 
						|
 | 
						|
func assertNotEqual(t *testing.T, a interface{}, b interface{}, message string) {
 | 
						|
	if a != b {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if len(message) == 0 {
 | 
						|
		message = fmt.Sprintf("%v == %v", a, b)
 | 
						|
	}
 | 
						|
	t.Fatal(message)
 | 
						|
}
 | 
						|
 | 
						|
// Similar to assertEqual, but does not stop test
 | 
						|
func checkEqual(t *testing.T, a interface{}, b interface{}, messagePrefix string) {
 | 
						|
	if a == b {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	message := fmt.Sprintf("%v != %v", a, b)
 | 
						|
	if len(messagePrefix) != 0 {
 | 
						|
		message = messagePrefix + ": " + message
 | 
						|
	}
 | 
						|
	t.Error(message)
 | 
						|
}
 | 
						|
 | 
						|
// Similar to assertNotEqual, but does not stop test
 | 
						|
func checkNotEqual(t *testing.T, a interface{}, b interface{}, messagePrefix string) {
 | 
						|
	if a != b {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	message := fmt.Sprintf("%v == %v", a, b)
 | 
						|
	if len(messagePrefix) != 0 {
 | 
						|
		message = messagePrefix + ": " + message
 | 
						|
	}
 | 
						|
	t.Error(message)
 | 
						|
}
 | 
						|
 | 
						|
func requiresAuth(w http.ResponseWriter, r *http.Request) bool {
 | 
						|
	writeCookie := func() {
 | 
						|
		value := fmt.Sprintf("FAKE-SESSION-%d", time.Now().UnixNano())
 | 
						|
		cookie := &http.Cookie{Name: "session", Value: value, MaxAge: 3600}
 | 
						|
		http.SetCookie(w, cookie)
 | 
						|
		//FIXME(sam): this should be sent only on Index routes
 | 
						|
		value = fmt.Sprintf("FAKE-TOKEN-%d", time.Now().UnixNano())
 | 
						|
		w.Header().Add("X-Docker-Token", value)
 | 
						|
	}
 | 
						|
	if len(r.Cookies()) > 0 {
 | 
						|
		writeCookie()
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	if len(r.Header.Get("Authorization")) > 0 {
 | 
						|
		writeCookie()
 | 
						|
		return true
 | 
						|
	}
 | 
						|
	w.Header().Add("WWW-Authenticate", "token")
 | 
						|
	apiError(w, "Wrong auth", 401)
 | 
						|
	return false
 | 
						|
}
 | 
						|
 | 
						|
func handlerGetPing(w http.ResponseWriter, r *http.Request) {
 | 
						|
	writeResponse(w, true, 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerGetImage(w http.ResponseWriter, r *http.Request) {
 | 
						|
	if !requiresAuth(w, r) {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	vars := mux.Vars(r)
 | 
						|
	layer, exists := testLayers[vars["image_id"]]
 | 
						|
	if !exists {
 | 
						|
		http.NotFound(w, r)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	writeHeaders(w)
 | 
						|
	layerSize := len(layer["layer"])
 | 
						|
	w.Header().Add("X-Docker-Size", strconv.Itoa(layerSize))
 | 
						|
	io.WriteString(w, layer[vars["action"]])
 | 
						|
}
 | 
						|
 | 
						|
func handlerPutImage(w http.ResponseWriter, r *http.Request) {
 | 
						|
	if !requiresAuth(w, r) {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	vars := mux.Vars(r)
 | 
						|
	imageID := vars["image_id"]
 | 
						|
	action := vars["action"]
 | 
						|
	layer, exists := testLayers[imageID]
 | 
						|
	if !exists {
 | 
						|
		if action != "json" {
 | 
						|
			http.NotFound(w, r)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		layer = make(map[string]string)
 | 
						|
		testLayers[imageID] = layer
 | 
						|
	}
 | 
						|
	if checksum := r.Header.Get("X-Docker-Checksum"); checksum != "" {
 | 
						|
		if checksum != layer["checksum_simple"] && checksum != layer["checksum_tarsum"] {
 | 
						|
			apiError(w, "Wrong checksum", 400)
 | 
						|
			return
 | 
						|
		}
 | 
						|
	}
 | 
						|
	body, err := ioutil.ReadAll(r.Body)
 | 
						|
	if err != nil {
 | 
						|
		apiError(w, fmt.Sprintf("Error: %s", err), 500)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	layer[action] = string(body)
 | 
						|
	writeResponse(w, true, 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerGetDeleteTags(w http.ResponseWriter, r *http.Request) {
 | 
						|
	if !requiresAuth(w, r) {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	repositoryName, err := reference.WithName(mux.Vars(r)["repository"])
 | 
						|
	if err != nil {
 | 
						|
		apiError(w, "Could not parse repository", 400)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	tags, exists := testRepositories[repositoryName.String()]
 | 
						|
	if !exists {
 | 
						|
		apiError(w, "Repository not found", 404)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if r.Method == "DELETE" {
 | 
						|
		delete(testRepositories, repositoryName.String())
 | 
						|
		writeResponse(w, true, 200)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	writeResponse(w, tags, 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerGetTag(w http.ResponseWriter, r *http.Request) {
 | 
						|
	if !requiresAuth(w, r) {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	vars := mux.Vars(r)
 | 
						|
	repositoryName, err := reference.WithName(vars["repository"])
 | 
						|
	if err != nil {
 | 
						|
		apiError(w, "Could not parse repository", 400)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	tagName := vars["tag"]
 | 
						|
	tags, exists := testRepositories[repositoryName.String()]
 | 
						|
	if !exists {
 | 
						|
		apiError(w, "Repository not found", 404)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	tag, exists := tags[tagName]
 | 
						|
	if !exists {
 | 
						|
		apiError(w, "Tag not found", 404)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	writeResponse(w, tag, 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerPutTag(w http.ResponseWriter, r *http.Request) {
 | 
						|
	if !requiresAuth(w, r) {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	vars := mux.Vars(r)
 | 
						|
	repositoryName, err := reference.WithName(vars["repository"])
 | 
						|
	if err != nil {
 | 
						|
		apiError(w, "Could not parse repository", 400)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	tagName := vars["tag"]
 | 
						|
	tags, exists := testRepositories[repositoryName.String()]
 | 
						|
	if !exists {
 | 
						|
		tags = make(map[string]string)
 | 
						|
		testRepositories[repositoryName.String()] = tags
 | 
						|
	}
 | 
						|
	tagValue := ""
 | 
						|
	readJSON(r, tagValue)
 | 
						|
	tags[tagName] = tagValue
 | 
						|
	writeResponse(w, true, 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerUsers(w http.ResponseWriter, r *http.Request) {
 | 
						|
	code := 200
 | 
						|
	if r.Method == "POST" {
 | 
						|
		code = 201
 | 
						|
	} else if r.Method == "PUT" {
 | 
						|
		code = 204
 | 
						|
	}
 | 
						|
	writeResponse(w, "", code)
 | 
						|
}
 | 
						|
 | 
						|
func handlerImages(w http.ResponseWriter, r *http.Request) {
 | 
						|
	u, _ := url.Parse(testHTTPServer.URL)
 | 
						|
	w.Header().Add("X-Docker-Endpoints", fmt.Sprintf("%s 	,  %s ", u.Host, "test.example.com"))
 | 
						|
	w.Header().Add("X-Docker-Token", fmt.Sprintf("FAKE-SESSION-%d", time.Now().UnixNano()))
 | 
						|
	if r.Method == "PUT" {
 | 
						|
		if strings.HasSuffix(r.URL.Path, "images") {
 | 
						|
			writeResponse(w, "", 204)
 | 
						|
			return
 | 
						|
		}
 | 
						|
		writeResponse(w, "", 200)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if r.Method == "DELETE" {
 | 
						|
		writeResponse(w, "", 204)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	images := []map[string]string{}
 | 
						|
	for imageID, layer := range testLayers {
 | 
						|
		image := make(map[string]string)
 | 
						|
		image["id"] = imageID
 | 
						|
		image["checksum"] = layer["checksum_tarsum"]
 | 
						|
		image["Tag"] = "latest"
 | 
						|
		images = append(images, image)
 | 
						|
	}
 | 
						|
	writeResponse(w, images, 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerAuth(w http.ResponseWriter, r *http.Request) {
 | 
						|
	writeResponse(w, "OK", 200)
 | 
						|
}
 | 
						|
 | 
						|
func handlerSearch(w http.ResponseWriter, r *http.Request) {
 | 
						|
	result := ®istrytypes.SearchResults{
 | 
						|
		Query:      "fakequery",
 | 
						|
		NumResults: 1,
 | 
						|
		Results:    []registrytypes.SearchResult{{Name: "fakeimage", StarCount: 42}},
 | 
						|
	}
 | 
						|
	writeResponse(w, result, 200)
 | 
						|
}
 | 
						|
 | 
						|
func TestPing(t *testing.T) {
 | 
						|
	res, err := http.Get(makeURL("/v1/_ping"))
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	assertEqual(t, res.StatusCode, 200, "")
 | 
						|
	assertEqual(t, res.Header.Get("X-Docker-Registry-Config"), "mock",
 | 
						|
		"This is not a Mocked Registry")
 | 
						|
}
 | 
						|
 | 
						|
/* Uncomment this to test Mocked Registry locally with curl
 | 
						|
 * WARNING: Don't push on the repos uncommented, it'll block the tests
 | 
						|
 *
 | 
						|
func TestWait(t *testing.T) {
 | 
						|
	logrus.Println("Test HTTP server ready and waiting:", testHTTPServer.URL)
 | 
						|
	c := make(chan int)
 | 
						|
	<-c
 | 
						|
}
 | 
						|
 | 
						|
//*/
 |