зеркало из https://github.com/microsoft/docker.git
Checksum system overhaul
This commit is contained in:
Родитель
e81a53eea9
Коммит
6e2ddf6f60
|
@ -529,9 +529,6 @@ func (srv *Server) CmdPush(stdin io.ReadCloser, stdout rcli.DockerConn, args ...
|
||||||
Debugf("Pushing [%s] to [%s]\n", local, remote)
|
Debugf("Pushing [%s] to [%s]\n", local, remote)
|
||||||
|
|
||||||
// Try to get the image
|
// Try to get the image
|
||||||
// FIXME: Handle lookup
|
|
||||||
// FIXME: Also push the tags in case of ./docker push myrepo:mytag
|
|
||||||
// img, err := srv.runtime.LookupImage(cmd.Arg(0))
|
|
||||||
img, err := srv.runtime.graph.Get(local)
|
img, err := srv.runtime.graph.Get(local)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Debugf("The push refers to a repository [%s] (len: %d)\n", local, len(srv.runtime.repositories.Repositories[local]))
|
Debugf("The push refers to a repository [%s] (len: %d)\n", local, len(srv.runtime.repositories.Repositories[local]))
|
||||||
|
|
20
graph.go
20
graph.go
|
@ -81,13 +81,6 @@ func (graph *Graph) Get(name string) (*Image, error) {
|
||||||
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id)
|
return nil, fmt.Errorf("Image stored at '%s' has wrong id '%s'", id, img.Id)
|
||||||
}
|
}
|
||||||
img.graph = graph
|
img.graph = graph
|
||||||
|
|
||||||
if img.Checksum == "" {
|
|
||||||
err := img.FixChecksum()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,17 +98,11 @@ func (graph *Graph) Create(layerData Archive, container *Container, comment, aut
|
||||||
img.Parent = container.Image
|
img.Parent = container.Image
|
||||||
img.Container = container.Id
|
img.Container = container.Id
|
||||||
img.ContainerConfig = *container.Config
|
img.ContainerConfig = *container.Config
|
||||||
// FIXME: If an image is imported from a raw URL (not created from a container),
|
|
||||||
// its checksum will not be computed, which will cause a push to fail
|
|
||||||
checksum, err := container.RwChecksum()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
img.Checksum = checksum
|
|
||||||
}
|
}
|
||||||
if err := graph.Register(layerData, img); err != nil {
|
if err := graph.Register(layerData, img); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
img.Checksum()
|
||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +296,10 @@ func (graph *Graph) Checksums(repo Repository) ([]map[string]string, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = img.WalkHistory(func(image *Image) error {
|
err = img.WalkHistory(func(image *Image) error {
|
||||||
checksums[image.Id] = image.Checksum
|
checksums[image.Id], err = image.Checksum()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
60
image.go
60
image.go
|
@ -1,7 +1,9 @@
|
||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -18,7 +20,6 @@ import (
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Parent string `json:"parent,omitempty"`
|
Parent string `json:"parent,omitempty"`
|
||||||
Checksum string `json:"checksum,omitempty"`
|
|
||||||
Comment string `json:"comment,omitempty"`
|
Comment string `json:"comment,omitempty"`
|
||||||
Created time.Time `json:"created"`
|
Created time.Time `json:"created"`
|
||||||
Container string `json:"container,omitempty"`
|
Container string `json:"container,omitempty"`
|
||||||
|
@ -260,30 +261,57 @@ func (img *Image) layer() (string, error) {
|
||||||
return layerPath(root), nil
|
return layerPath(root), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (img *Image) FixChecksum() error {
|
func (img *Image) Checksum() (string, error) {
|
||||||
|
root, err := img.root()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
checksumDictPth := path.Join(root, "..", "..", "checksums")
|
||||||
|
checksums := new(map[string]string)
|
||||||
|
|
||||||
|
if checksumDict, err := ioutil.ReadFile(checksumDictPth); err == nil {
|
||||||
|
if err := json.Unmarshal(checksumDict, checksums); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if checksum, ok := (*checksums)[img.Id]; ok {
|
||||||
|
return checksum, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
layer, err := img.layer()
|
layer, err := img.layer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
layerData, err := Tar(layer, Xz)
|
layerData, err := Tar(layer, Xz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
sum, err := HashData(layerData)
|
h := sha256.New()
|
||||||
|
if _, err := io.Copy(h, layerData); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonData, err := ioutil.ReadFile(jsonPath(root))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
img.Checksum = sum
|
if _, err := io.Copy(h, bytes.NewBuffer(jsonData)); err != nil {
|
||||||
jsonData, err := json.Marshal(img)
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
hash := "sha256:"+hex.EncodeToString(h.Sum(nil))
|
||||||
|
if *checksums == nil {
|
||||||
|
*checksums = map[string]string{}
|
||||||
|
}
|
||||||
|
(*checksums)[img.Id] = hash
|
||||||
|
checksumJson, err := json.Marshal(checksums)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return hash, err
|
||||||
}
|
}
|
||||||
root, err := img.root()
|
|
||||||
if err != nil {
|
if err := ioutil.WriteFile(checksumDictPth, checksumJson, 0600); err != nil {
|
||||||
return err
|
return hash, err
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(jsonPath(root), jsonData, 0600); err != nil {
|
return hash, nil
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
14
registry.go
14
registry.go
|
@ -327,6 +327,12 @@ func pushImageRec(graph *Graph, stdout io.Writer, img *Image, registry string, t
|
||||||
}
|
}
|
||||||
req.Header.Add("Content-type", "application/json")
|
req.Header.Add("Content-type", "application/json")
|
||||||
req.Header.Set("Authorization", "Token " + strings.Join(token, ","))
|
req.Header.Set("Authorization", "Token " + strings.Join(token, ","))
|
||||||
|
|
||||||
|
checksum, err := img.Checksum()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Error while retrieving checksum for %s: %v", img.Id, err)
|
||||||
|
}
|
||||||
|
req.Header.Set("X-Docker-Checksum", checksum)
|
||||||
res, err := doWithCookies(client, req)
|
res, err := doWithCookies(client, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to upload metadata: %s", err)
|
return fmt.Errorf("Failed to upload metadata: %s", err)
|
||||||
|
@ -457,7 +463,7 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("PUT", INDEX_ENDPOINT+"/repositories/"+remote, bytes.NewReader(imgListJson))
|
req, err := http.NewRequest("PUT", INDEX_ENDPOINT+"/repositories/"+remote+"/", bytes.NewReader(imgListJson))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -468,7 +474,7 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
res.Body.Close()
|
defer res.Body.Close()
|
||||||
for res.StatusCode >= 300 && res.StatusCode < 400 {
|
for res.StatusCode >= 300 && res.StatusCode < 400 {
|
||||||
Debugf("Redirected to %s\n", res.Header.Get("Location"))
|
Debugf("Redirected to %s\n", res.Header.Get("Location"))
|
||||||
req, err = http.NewRequest("PUT", res.Header.Get("Location"), bytes.NewReader(imgListJson))
|
req, err = http.NewRequest("PUT", res.Header.Get("Location"), bytes.NewReader(imgListJson))
|
||||||
|
@ -482,10 +488,12 @@ func (graph *Graph) PushRepository(stdout io.Writer, remote string, localRepo Re
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
res.Body.Close()
|
defer res.Body.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if res.StatusCode != 200 && res.StatusCode != 201 {
|
if res.StatusCode != 200 && res.StatusCode != 201 {
|
||||||
|
info, err := ioutil.ReadAll(res.Body)
|
||||||
|
Debugf("%v %v", err, string(info))
|
||||||
return fmt.Errorf("Error: Status %d trying to push repository %s", res.StatusCode, remote)
|
return fmt.Errorf("Error: Status %d trying to push repository %s", res.StatusCode, remote)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче