Skip to content

Commit

Permalink
Merge pull request #2 from jlhawn/vbatts-v2_hacking
Browse files Browse the repository at this point in the history
Retrofit of registry v2 client
  • Loading branch information
vbatts committed Aug 28, 2014
2 parents 6639555 + 766db75 commit 8f55a8b
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 54 deletions.
149 changes: 95 additions & 54 deletions registry/session_prov.go
@@ -1,46 +1,61 @@
package registry

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/url"
"strings"

"github.com/docker/docker/registry/v2/routes"
"github.com/docker/docker/utils"
)

// APIVersion2 /v2/
var v2HTTPRoutes = map[string]map[string]HTTPRoute{
"GET": {
"Version": HTTPRoute("version"), // XXX DONE
"ImageManifest": HTTPRoute("manifest/{imgname:.*}/{tagname}"), // XXX DONE
"ImageTags": HTTPRoute("tags/{imgname:.*}"), // XXX
"ImageBlobSum": HTTPRoute("blob/{imgname:.*}/{sumtype}/{sum}"), // XXX
},
"PUT": {
"ImageManifest": HTTPRoute("manifest/{imgname:.*}/{tagname}"), // XXX
"ImageBlobSum": HTTPRoute("blob/{imgname:.*}/{sumtype}/{sum}"), // XXX
},
"POST": {
"ImageBlob": HTTPRoute("blob/{imgname:.*}/{sumtype}"), // XXX DONE
"ImageMountBlob": HTTPRoute("mountblob/{imgname:.*}/{sumtype}/{sum}"), // XXX DONE
},
"DELETE": {
"ImageManifest": HTTPRoute("manifest/{imgname:.*}/{tagname}"), // XXX
},
var v2HTTPRoutes = routes.NewRegistryRouter()

func getV2URL(e Endpoint, routeName string, vars map[string]string) (*url.URL, error) {
route := v2HTTPRoutes.Get(routeName)
if route == nil {
return nil, fmt.Errorf("unknown regisry v2 route name: %q", routeName)
}

varReplace := make([]string, 0, len(vars)*2)
for key, val := range vars {
varReplace = append(varReplace, key, val)
}

routePath, err := route.URLPath(varReplace...)
if err != nil {
return nil, fmt.Errorf("unable to make registry route %q with vars %v: %s", routeName, vars, err)
}

return &url.URL{
Scheme: e.URL.Scheme,
Host: e.URL.Host,
Path: routePath.Path,
}
}

// V2 Provenance POC

func (r *Session) GetV2Version(token []string) (*RegistryInfo, error) {
if r.indexEndpoint.Version != APIVersion2 {
return nil, ErrIncorrectAPIVersion
}

routeURL, err := getV2URL(r.indexEndpoint, routes.VersionRoutename, nil)
if err != nil {
return nil, err
}

method := "GET"
hr := v2HTTPRoutes[method]["Version"]
log.Printf("[registry] Calling %q %s", method, r.indexEndpoint.String()+string(hr))
log.Printf("[registry] Calling %q %s", method, routeURL.String())

req, err := r.reqFactory.NewRequest(method, r.indexEndpoint.String()+string(hr), nil)
req, err := r.reqFactory.NewRequest(method, routeURL.String(), nil)
if err != nil {
return nil, err
}
Expand All @@ -61,7 +76,6 @@ func (r *Session) GetV2Version(token []string) (*RegistryInfo, error) {
return &RegistryInfo{Version: strings.TrimSpace(string(buf))}, nil
}

// V2 Provenance POC
//
// 1) Check if TarSum of each layer exists /v2/
// 1.a) if 200, continue
Expand All @@ -74,15 +88,20 @@ func (r *Session) GetV2ImageManifest(imageName, tagName string, token []string)
return nil, ErrIncorrectAPIVersion
}

method := "GET"
hr := v2HTTPRoutes[method]["ImageManifest"]
values := map[string]string{
"imgname": imageName,
"tagname": tagName,
vars := map[string]string{
"imagename": imageName,
"tagname": tagName,
}

routeURL, err := getV2URL(r.indexEndpoint, routes.ManifestsRouteName, vars)
if err != nil {
return nil, err
}
log.Printf("[registry] Calling %q %s", method, r.indexEndpoint.String()+hr.Format(values))

req, err := r.reqFactory.NewRequest(method, r.indexEndpoint.String()+hr.Format(values), nil)
method := "GET"
log.Printf("[registry] Calling %q %s", method, routeURL.String())

req, err := r.reqFactory.NewRequest(method, routeURL.String(), nil)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -114,16 +133,21 @@ func (r *Session) PostV2ImageMountBlob(imageName, sumType, sum string, token []s
return false, ErrIncorrectAPIVersion
}

method := "POST"
hr := v2HTTPRoutes[method]["ImageMountBlob"]
values := map[string]string{
"imgname": imageName,
"sumtype": sumType,
"sum": sum,
vars := map[string]string{
"imagename": imageName,
"sumtype": sumType,
"sum": sum,
}
log.Printf("[registry] Calling %q %s", method, r.indexEndpoint.String()+hr.Format(values))

req, err := r.reqFactory.NewRequest(method, r.indexEndpoint.String()+hr.Format(values), nil)
routeURL, err := getV2URL(r.indexEndpoint, routes.MountBlobRouteName, vars)
if err != nil {
return nil, err
}

method := "POST"
log.Printf("[registry] Calling %q %s", method, routeURL.String())

req, err := r.reqFactory.NewRequest(method, routeURL.String(), nil)
if err != nil {
return false, err
}
Expand All @@ -147,19 +171,24 @@ func (r *Session) PostV2ImageMountBlob(imageName, sumType, sum string, token []s
// Push the image to the server for storage.
// 'layer' is an uncompressed reader of the blob to be pushed.
// The server will generate it's own checksum calculation.
func (r *Session) PostV2ImageBlob(imageName, sumType string, blobRdr io.Reader, token []string) (serverChecksum string, err error) {
func (r *Session) PutV2ImageBlob(imageName, sumType string, blobRdr io.Reader, token []string) (serverChecksum string, err error) {
if r.indexEndpoint.Version != APIVersion2 {
return "", ErrIncorrectAPIVersion
}

method := "POST"
hr := v2HTTPRoutes[method]["ImageBlob"]
values := map[string]string{
"imgname": imageName,
"sumtype": sumType,
vars := map[string]string{
"imagename": imageName,
"sumtype": sumType,
}
log.Printf("[registry] Calling %q %s", method, r.indexEndpoint.String()+hr.Format(values))
req, err := r.reqFactory.NewRequest(method, r.indexEndpoint.String()+hr.Format(values), blobRdr)

routeURL, err := getV2URL(r.indexEndpoint, routes.UploadBlobRouteName, vars)
if err != nil {
return nil, err
}

method := "PUT"
log.Printf("[registry] Calling %q %s", method, routeURL.String())
req, err := r.reqFactory.NewRequest(method, routeURL.String(), blobRdr)
if err != nil {
return "", err
}
Expand All @@ -176,13 +205,20 @@ func (r *Session) PostV2ImageBlob(imageName, sumType string, blobRdr io.Reader,
return "", utils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to push %s blob", res.StatusCode, imageName), res)
}

jsonBuf, err := ioutil.ReadAll(res.Body)
type sumReturn struct {
Checksum string `json:"checksum"`
}

decoder := json.NewDecoder(res.Body)
var sumInfo sumReturn

err = decoder.Decode(&sumInfo)
if err != nil {
return "", fmt.Errorf("Error while reading the http response: %s", err)
return "", fmt.Errorf("unable to decode PutV2ImageBlob JSON response: %s", err)
}

// XXX this is a json struct from the registry, with its checksum
return string(jsonBuf), nil
return sumInfo.Checksum, nil
}

// Finally Push the (signed) manifest of the blobs we've just pushed
Expand All @@ -191,14 +227,19 @@ func (r *Session) PutV2ImageManifest(imageName, tagName string, manifestRdr io.R
return ErrIncorrectAPIVersion
}

method := "PUT"
hr := v2HTTPRoutes[method]["ImageManifest"]
values := map[string]string{
"imgname": imageName,
"tagname": tagName,
vars := map[string]string{
"imagename": imageName,
"tagname": tagName,
}
log.Printf("[registry] Calling %q %s", method, r.indexEndpoint.String()+hr.Format(values))
req, err := r.reqFactory.NewRequest(method, r.indexEndpoint.String()+hr.Format(values), manifestRdr)

routeURL, err := getV2URL(r.indexEndpoint, routes.ManifestsRouteName, vars)
if err != nil {
return nil, err
}

method := "PUT"
log.Printf("[registry] Calling %q %s", method, routeURL.String())
req, err := r.reqFactory.NewRequest(method, routeURL.String(), manifestRdr)
if err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions registry/v2/routes/router.go
Expand Up @@ -10,6 +10,7 @@ const (
DownloadBlobRouteName = "downloadBlob"
UploadBlobRouteName = "uploadBlob"
MountBlobRouteName = "mountBlob"
VersionRoutename = "version"
)

func NewRegistryRouter() *mux.Router {
Expand Down

0 comments on commit 8f55a8b

Please sign in to comment.