mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Remove reference package dependency from the api.
Signed-off-by: David Calavera <david.calavera@gmail.com>
This commit is contained in:
parent
e82830ecde
commit
47afe6bd0a
10 changed files with 259 additions and 213 deletions
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/reference"
|
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
"github.com/docker/engine-api/types/registry"
|
"github.com/docker/engine-api/types/registry"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
@ -28,17 +27,17 @@ type imageBackend interface {
|
||||||
ImageHistory(imageName string) ([]*types.ImageHistory, error)
|
ImageHistory(imageName string) ([]*types.ImageHistory, error)
|
||||||
Images(filterArgs string, filter string, all bool) ([]*types.Image, error)
|
Images(filterArgs string, filter string, all bool) ([]*types.Image, error)
|
||||||
LookupImage(name string) (*types.ImageInspect, error)
|
LookupImage(name string) (*types.ImageInspect, error)
|
||||||
TagImage(newTag reference.Named, imageName string) error
|
TagImage(imageName, repository, tag string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type importExportBackend interface {
|
type importExportBackend interface {
|
||||||
LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
LoadImage(inTar io.ReadCloser, outStream io.Writer, quiet bool) error
|
||||||
ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
ImportImage(src string, repository, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
|
||||||
ExportImage(names []string, outStream io.Writer) error
|
ExportImage(names []string, outStream io.Writer) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type registryBackend interface {
|
type registryBackend interface {
|
||||||
PullImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
||||||
PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error
|
||||||
SearchRegistryForImages(ctx context.Context, term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
|
SearchRegistryForImages(ctx context.Context, term string, authConfig *types.AuthConfig, metaHeaders map[string][]string) (*registry.SearchResults, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,20 +3,17 @@ package image
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/docker/distribution/digest"
|
|
||||||
"github.com/docker/distribution/registry/api/errcode"
|
"github.com/docker/distribution/registry/api/errcode"
|
||||||
"github.com/docker/docker/api/server/httputils"
|
"github.com/docker/docker/api/server/httputils"
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
"github.com/docker/docker/pkg/ioutils"
|
"github.com/docker/docker/pkg/ioutils"
|
||||||
"github.com/docker/docker/pkg/streamformatter"
|
"github.com/docker/docker/pkg/streamformatter"
|
||||||
"github.com/docker/docker/reference"
|
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
"github.com/docker/engine-api/types/container"
|
"github.com/docker/engine-api/types/container"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
|
|
@ -89,46 +86,26 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
if image != "" { //pull
|
if image != "" { //pull
|
||||||
// Special case: "pull -a" may send an image name with a
|
metaHeaders := map[string][]string{}
|
||||||
// trailing :. This is ugly, but let's not break API
|
for k, v := range r.Header {
|
||||||
// compatibility.
|
if strings.HasPrefix(k, "X-Meta-") {
|
||||||
image = strings.TrimSuffix(image, ":")
|
metaHeaders[k] = v
|
||||||
|
|
||||||
var ref reference.Named
|
|
||||||
ref, err = reference.ParseNamed(image)
|
|
||||||
if err == nil {
|
|
||||||
if tag != "" {
|
|
||||||
// The "tag" could actually be a digest.
|
|
||||||
var dgst digest.Digest
|
|
||||||
dgst, err = digest.ParseDigest(tag)
|
|
||||||
if err == nil {
|
|
||||||
ref, err = reference.WithDigest(ref, dgst)
|
|
||||||
} else {
|
|
||||||
ref, err = reference.WithTag(ref, tag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
metaHeaders := map[string][]string{}
|
|
||||||
for k, v := range r.Header {
|
|
||||||
if strings.HasPrefix(k, "X-Meta-") {
|
|
||||||
metaHeaders[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
authEncoded := r.Header.Get("X-Registry-Auth")
|
|
||||||
authConfig := &types.AuthConfig{}
|
|
||||||
if authEncoded != "" {
|
|
||||||
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
|
||||||
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
|
|
||||||
// for a pull it is not an error if no auth was given
|
|
||||||
// to increase compatibility with the existing api it is defaulting to be empty
|
|
||||||
authConfig = &types.AuthConfig{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.backend.PullImage(ctx, ref, metaHeaders, authConfig, output)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authEncoded := r.Header.Get("X-Registry-Auth")
|
||||||
|
authConfig := &types.AuthConfig{}
|
||||||
|
if authEncoded != "" {
|
||||||
|
authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
|
||||||
|
if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
|
||||||
|
// for a pull it is not an error if no auth was given
|
||||||
|
// to increase compatibility with the existing api it is defaulting to be empty
|
||||||
|
authConfig = &types.AuthConfig{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.backend.PullImage(ctx, image, tag, metaHeaders, authConfig, output)
|
||||||
|
|
||||||
// Check the error from pulling an image to make sure the request
|
// Check the error from pulling an image to make sure the request
|
||||||
// was authorized. Modify the status if the request was
|
// was authorized. Modify the status if the request was
|
||||||
// unauthorized to respond with 401 rather than 500.
|
// unauthorized to respond with 401 rather than 500.
|
||||||
|
|
@ -136,31 +113,11 @@ func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrite
|
||||||
err = errcode.ErrorCodeUnauthorized.WithMessage(fmt.Sprintf("Authentication is required: %s", err))
|
err = errcode.ErrorCodeUnauthorized.WithMessage(fmt.Sprintf("Authentication is required: %s", err))
|
||||||
}
|
}
|
||||||
} else { //import
|
} else { //import
|
||||||
var newRef reference.Named
|
|
||||||
if repo != "" {
|
|
||||||
var err error
|
|
||||||
newRef, err = reference.ParseNamed(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, isCanonical := newRef.(reference.Canonical); isCanonical {
|
|
||||||
return errors.New("cannot import digest reference")
|
|
||||||
}
|
|
||||||
|
|
||||||
if tag != "" {
|
|
||||||
newRef, err = reference.WithTag(newRef, tag)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
src := r.Form.Get("fromSrc")
|
src := r.Form.Get("fromSrc")
|
||||||
// 'err' MUST NOT be defined within this block, we need any error
|
// 'err' MUST NOT be defined within this block, we need any error
|
||||||
// generated from the download to be available to the output
|
// generated from the download to be available to the output
|
||||||
// stream processing below
|
// stream processing below
|
||||||
err = s.backend.ImportImage(src, newRef, message, r.Body, output, r.Form["changes"])
|
err = s.backend.ImportImage(src, repo, tag, message, r.Body, output, r.Form["changes"])
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !output.Flushed() {
|
if !output.Flushed() {
|
||||||
|
|
@ -200,25 +157,15 @@ func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ref, err := reference.ParseNamed(vars["name"])
|
image := vars["name"]
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tag := r.Form.Get("tag")
|
tag := r.Form.Get("tag")
|
||||||
if tag != "" {
|
|
||||||
// Push by digest is not supported, so only tags are supported.
|
|
||||||
ref, err = reference.WithTag(ref, tag)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output := ioutils.NewWriteFlusher(w)
|
output := ioutils.NewWriteFlusher(w)
|
||||||
defer output.Close()
|
defer output.Close()
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
if err := s.backend.PushImage(ctx, ref, metaHeaders, authConfig, output); err != nil {
|
if err := s.backend.PushImage(ctx, image, tag, metaHeaders, authConfig, output); err != nil {
|
||||||
if !output.Flushed() {
|
if !output.Flushed() {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -322,18 +269,7 @@ func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter,
|
||||||
if err := httputils.ParseForm(r); err != nil {
|
if err := httputils.ParseForm(r); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
repo := r.Form.Get("repo")
|
if err := s.backend.TagImage(vars["name"], r.Form.Get("repo"), r.Form.Get("tag")); err != nil {
|
||||||
tag := r.Form.Get("tag")
|
|
||||||
newTag, err := reference.WithName(repo)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if tag != "" {
|
|
||||||
if newTag, err = reference.WithTag(newTag, tag); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := s.backend.TagImage(newTag, vars["name"]); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types/backend"
|
"github.com/docker/docker/api/types/backend"
|
||||||
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/reference"
|
"github.com/docker/docker/reference"
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
"github.com/docker/engine-api/types/container"
|
"github.com/docker/engine-api/types/container"
|
||||||
|
|
@ -109,7 +110,7 @@ type Backend interface {
|
||||||
// GetImageOnBuild looks up a Docker image referenced by `name`.
|
// GetImageOnBuild looks up a Docker image referenced by `name`.
|
||||||
GetImageOnBuild(name string) (Image, error)
|
GetImageOnBuild(name string) (Image, error)
|
||||||
// TagImage tags an image with newTag
|
// TagImage tags an image with newTag
|
||||||
TagImage(newTag reference.Named, imageName string) error
|
TagImageWithReference(image.ID, reference.Named) error
|
||||||
// PullOnBuild tells Docker to pull image referenced by `name`.
|
// PullOnBuild tells Docker to pull image referenced by `name`.
|
||||||
PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (Image, error)
|
PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (Image, error)
|
||||||
// ContainerAttachRaw attaches to container.
|
// ContainerAttachRaw attaches to container.
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/docker/docker/builder"
|
"github.com/docker/docker/builder"
|
||||||
"github.com/docker/docker/builder/dockerfile/parser"
|
"github.com/docker/docker/builder/dockerfile/parser"
|
||||||
|
"github.com/docker/docker/image"
|
||||||
"github.com/docker/docker/pkg/stringid"
|
"github.com/docker/docker/pkg/stringid"
|
||||||
"github.com/docker/docker/reference"
|
"github.com/docker/docker/reference"
|
||||||
"github.com/docker/engine-api/types"
|
"github.com/docker/engine-api/types"
|
||||||
|
|
@ -256,8 +257,9 @@ func (b *Builder) build(config *types.ImageBuildOptions, context builder.Context
|
||||||
return "", fmt.Errorf("No image was generated. Is your Dockerfile empty?")
|
return "", fmt.Errorf("No image was generated. Is your Dockerfile empty?")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imageID := image.ID(b.image)
|
||||||
for _, rt := range repoAndTags {
|
for _, rt := range repoAndTags {
|
||||||
if err := b.docker.TagImage(rt, b.image); err != nil {
|
if err := b.docker.TagImageWithReference(imageID, rt); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,7 @@ func (daemon *Daemon) Commit(name string, c *backend.ContainerCommitConfig) (str
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := daemon.TagImage(newTag, id.String()); err != nil {
|
if err := daemon.TagImageWithReference(id, newTag); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
114
daemon/daemon.go
114
daemon/daemon.go
|
|
@ -38,7 +38,6 @@ import (
|
||||||
_ "github.com/docker/docker/daemon/graphdriver/register"
|
_ "github.com/docker/docker/daemon/graphdriver/register"
|
||||||
"github.com/docker/docker/daemon/logger"
|
"github.com/docker/docker/daemon/logger"
|
||||||
"github.com/docker/docker/daemon/network"
|
"github.com/docker/docker/daemon/network"
|
||||||
"github.com/docker/docker/distribution"
|
|
||||||
dmetadata "github.com/docker/docker/distribution/metadata"
|
dmetadata "github.com/docker/docker/distribution/metadata"
|
||||||
"github.com/docker/docker/distribution/xfer"
|
"github.com/docker/docker/distribution/xfer"
|
||||||
"github.com/docker/docker/dockerversion"
|
"github.com/docker/docker/dockerversion"
|
||||||
|
|
@ -951,21 +950,6 @@ func (daemon *Daemon) changes(container *container.Container) ([]archive.Change,
|
||||||
return container.RWLayer.Changes()
|
return container.RWLayer.Changes()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagImage creates the tag specified by newTag, pointing to the image named
|
|
||||||
// imageName (alternatively, imageName can also be an image ID).
|
|
||||||
func (daemon *Daemon) TagImage(newTag reference.Named, imageName string) error {
|
|
||||||
imageID, err := daemon.GetImageID(imageName)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := daemon.referenceStore.AddTag(newTag, imageID, true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
daemon.LogImageEvent(imageID.String(), newTag.String(), "tag")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) {
|
func writeDistributionProgress(cancelFunc func(), outStream io.Writer, progressChan <-chan progress.Progress) {
|
||||||
progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false)
|
progressOutput := streamformatter.NewJSONStreamFormatter().NewProgressOutput(outStream, false)
|
||||||
operationCancelled := false
|
operationCancelled := false
|
||||||
|
|
@ -996,69 +980,6 @@ func isBrokenPipe(e error) bool {
|
||||||
return e == syscall.EPIPE
|
return e == syscall.EPIPE
|
||||||
}
|
}
|
||||||
|
|
||||||
// PullImage initiates a pull operation. image is the repository name to pull, and
|
|
||||||
// tag may be either empty, or indicate a specific tag to pull.
|
|
||||||
func (daemon *Daemon) PullImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
|
|
||||||
// Include a buffer so that slow client connections don't affect
|
|
||||||
// transfer performance.
|
|
||||||
progressChan := make(chan progress.Progress, 100)
|
|
||||||
|
|
||||||
writesDone := make(chan struct{})
|
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(ctx)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
writeDistributionProgress(cancelFunc, outStream, progressChan)
|
|
||||||
close(writesDone)
|
|
||||||
}()
|
|
||||||
|
|
||||||
imagePullConfig := &distribution.ImagePullConfig{
|
|
||||||
MetaHeaders: metaHeaders,
|
|
||||||
AuthConfig: authConfig,
|
|
||||||
ProgressOutput: progress.ChanOutput(progressChan),
|
|
||||||
RegistryService: daemon.RegistryService,
|
|
||||||
ImageEventLogger: daemon.LogImageEvent,
|
|
||||||
MetadataStore: daemon.distributionMetadataStore,
|
|
||||||
ImageStore: daemon.imageStore,
|
|
||||||
ReferenceStore: daemon.referenceStore,
|
|
||||||
DownloadManager: daemon.downloadManager,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := distribution.Pull(ctx, ref, imagePullConfig)
|
|
||||||
close(progressChan)
|
|
||||||
<-writesDone
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// PullOnBuild tells Docker to pull image referenced by `name`.
|
|
||||||
func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
|
|
||||||
ref, err := reference.ParseNamed(name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ref = reference.WithDefaultTag(ref)
|
|
||||||
|
|
||||||
pullRegistryAuth := &types.AuthConfig{}
|
|
||||||
if len(authConfigs) > 0 {
|
|
||||||
// The request came with a full auth config file, we prefer to use that
|
|
||||||
repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resolvedConfig := registry.ResolveAuthConfig(
|
|
||||||
authConfigs,
|
|
||||||
repoInfo.Index,
|
|
||||||
)
|
|
||||||
pullRegistryAuth = &resolvedConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := daemon.PullImage(ctx, ref, nil, pullRegistryAuth, output); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return daemon.GetImage(name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExportImage exports a list of images to the given output stream. The
|
// ExportImage exports a list of images to the given output stream. The
|
||||||
// exported images are archived into a tar when written to the output
|
// exported images are archived into a tar when written to the output
|
||||||
// stream. All images with the given tag and all versions containing
|
// stream. All images with the given tag and all versions containing
|
||||||
|
|
@ -1069,41 +990,6 @@ func (daemon *Daemon) ExportImage(names []string, outStream io.Writer) error {
|
||||||
return imageExporter.Save(names, outStream)
|
return imageExporter.Save(names, outStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushImage initiates a push operation on the repository named localName.
|
|
||||||
func (daemon *Daemon) PushImage(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
|
|
||||||
// Include a buffer so that slow client connections don't affect
|
|
||||||
// transfer performance.
|
|
||||||
progressChan := make(chan progress.Progress, 100)
|
|
||||||
|
|
||||||
writesDone := make(chan struct{})
|
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(ctx)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
writeDistributionProgress(cancelFunc, outStream, progressChan)
|
|
||||||
close(writesDone)
|
|
||||||
}()
|
|
||||||
|
|
||||||
imagePushConfig := &distribution.ImagePushConfig{
|
|
||||||
MetaHeaders: metaHeaders,
|
|
||||||
AuthConfig: authConfig,
|
|
||||||
ProgressOutput: progress.ChanOutput(progressChan),
|
|
||||||
RegistryService: daemon.RegistryService,
|
|
||||||
ImageEventLogger: daemon.LogImageEvent,
|
|
||||||
MetadataStore: daemon.distributionMetadataStore,
|
|
||||||
LayerStore: daemon.layerStore,
|
|
||||||
ImageStore: daemon.imageStore,
|
|
||||||
ReferenceStore: daemon.referenceStore,
|
|
||||||
TrustKey: daemon.trustKey,
|
|
||||||
UploadManager: daemon.uploadManager,
|
|
||||||
}
|
|
||||||
|
|
||||||
err := distribution.Push(ctx, ref, imagePushConfig)
|
|
||||||
close(progressChan)
|
|
||||||
<-writesDone
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupImage looks up an image by name and returns it as an ImageInspect
|
// LookupImage looks up an image by name and returns it as an ImageInspect
|
||||||
// structure.
|
// structure.
|
||||||
func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
|
func (daemon *Daemon) LookupImage(name string) (*types.ImageInspect, error) {
|
||||||
|
|
|
||||||
106
daemon/image_pull.go
Normal file
106
daemon/image_pull.go
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/distribution/digest"
|
||||||
|
"github.com/docker/docker/builder"
|
||||||
|
"github.com/docker/docker/distribution"
|
||||||
|
"github.com/docker/docker/pkg/progress"
|
||||||
|
"github.com/docker/docker/reference"
|
||||||
|
"github.com/docker/docker/registry"
|
||||||
|
"github.com/docker/engine-api/types"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PullImage initiates a pull operation. image is the repository name to pull, and
|
||||||
|
// tag may be either empty, or indicate a specific tag to pull.
|
||||||
|
func (daemon *Daemon) PullImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
|
||||||
|
// Special case: "pull -a" may send an image name with a
|
||||||
|
// trailing :. This is ugly, but let's not break API
|
||||||
|
// compatibility.
|
||||||
|
image = strings.TrimSuffix(image, ":")
|
||||||
|
|
||||||
|
ref, err := reference.ParseNamed(image)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != "" {
|
||||||
|
// The "tag" could actually be a digest.
|
||||||
|
var dgst digest.Digest
|
||||||
|
dgst, err = digest.ParseDigest(tag)
|
||||||
|
if err == nil {
|
||||||
|
ref, err = reference.WithDigest(ref, dgst)
|
||||||
|
} else {
|
||||||
|
ref, err = reference.WithTag(ref, tag)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return daemon.pullImageWithReference(ctx, ref, metaHeaders, authConfig, outStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PullOnBuild tells Docker to pull image referenced by `name`.
|
||||||
|
func (daemon *Daemon) PullOnBuild(ctx context.Context, name string, authConfigs map[string]types.AuthConfig, output io.Writer) (builder.Image, error) {
|
||||||
|
ref, err := reference.ParseNamed(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ref = reference.WithDefaultTag(ref)
|
||||||
|
|
||||||
|
pullRegistryAuth := &types.AuthConfig{}
|
||||||
|
if len(authConfigs) > 0 {
|
||||||
|
// The request came with a full auth config file, we prefer to use that
|
||||||
|
repoInfo, err := daemon.RegistryService.ResolveRepository(ref)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedConfig := registry.ResolveAuthConfig(
|
||||||
|
authConfigs,
|
||||||
|
repoInfo.Index,
|
||||||
|
)
|
||||||
|
pullRegistryAuth = &resolvedConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := daemon.pullImageWithReference(ctx, ref, nil, pullRegistryAuth, output); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return daemon.GetImage(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (daemon *Daemon) pullImageWithReference(ctx context.Context, ref reference.Named, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
|
||||||
|
// Include a buffer so that slow client connections don't affect
|
||||||
|
// transfer performance.
|
||||||
|
progressChan := make(chan progress.Progress, 100)
|
||||||
|
|
||||||
|
writesDone := make(chan struct{})
|
||||||
|
|
||||||
|
ctx, cancelFunc := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
writeDistributionProgress(cancelFunc, outStream, progressChan)
|
||||||
|
close(writesDone)
|
||||||
|
}()
|
||||||
|
|
||||||
|
imagePullConfig := &distribution.ImagePullConfig{
|
||||||
|
MetaHeaders: metaHeaders,
|
||||||
|
AuthConfig: authConfig,
|
||||||
|
ProgressOutput: progress.ChanOutput(progressChan),
|
||||||
|
RegistryService: daemon.RegistryService,
|
||||||
|
ImageEventLogger: daemon.LogImageEvent,
|
||||||
|
MetadataStore: daemon.distributionMetadataStore,
|
||||||
|
ImageStore: daemon.imageStore,
|
||||||
|
ReferenceStore: daemon.referenceStore,
|
||||||
|
DownloadManager: daemon.downloadManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := distribution.Pull(ctx, ref, imagePullConfig)
|
||||||
|
close(progressChan)
|
||||||
|
<-writesDone
|
||||||
|
return err
|
||||||
|
}
|
||||||
58
daemon/image_push.go
Normal file
58
daemon/image_push.go
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/docker/docker/distribution"
|
||||||
|
"github.com/docker/docker/pkg/progress"
|
||||||
|
"github.com/docker/docker/reference"
|
||||||
|
"github.com/docker/engine-api/types"
|
||||||
|
"golang.org/x/net/context"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PushImage initiates a push operation on the repository named localName.
|
||||||
|
func (daemon *Daemon) PushImage(ctx context.Context, image, tag string, metaHeaders map[string][]string, authConfig *types.AuthConfig, outStream io.Writer) error {
|
||||||
|
ref, err := reference.ParseNamed(image)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if tag != "" {
|
||||||
|
// Push by digest is not supported, so only tags are supported.
|
||||||
|
ref, err = reference.WithTag(ref, tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include a buffer so that slow client connections don't affect
|
||||||
|
// transfer performance.
|
||||||
|
progressChan := make(chan progress.Progress, 100)
|
||||||
|
|
||||||
|
writesDone := make(chan struct{})
|
||||||
|
|
||||||
|
ctx, cancelFunc := context.WithCancel(ctx)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
writeDistributionProgress(cancelFunc, outStream, progressChan)
|
||||||
|
close(writesDone)
|
||||||
|
}()
|
||||||
|
|
||||||
|
imagePushConfig := &distribution.ImagePushConfig{
|
||||||
|
MetaHeaders: metaHeaders,
|
||||||
|
AuthConfig: authConfig,
|
||||||
|
ProgressOutput: progress.ChanOutput(progressChan),
|
||||||
|
RegistryService: daemon.RegistryService,
|
||||||
|
ImageEventLogger: daemon.LogImageEvent,
|
||||||
|
MetadataStore: daemon.distributionMetadataStore,
|
||||||
|
LayerStore: daemon.layerStore,
|
||||||
|
ImageStore: daemon.imageStore,
|
||||||
|
ReferenceStore: daemon.referenceStore,
|
||||||
|
TrustKey: daemon.trustKey,
|
||||||
|
UploadManager: daemon.uploadManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = distribution.Push(ctx, ref, imagePushConfig)
|
||||||
|
close(progressChan)
|
||||||
|
<-writesDone
|
||||||
|
return err
|
||||||
|
}
|
||||||
37
daemon/image_tag.go
Normal file
37
daemon/image_tag.go
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
package daemon
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/docker/docker/image"
|
||||||
|
"github.com/docker/docker/reference"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TagImage creates the tag specified by newTag, pointing to the image named
|
||||||
|
// imageName (alternatively, imageName can also be an image ID).
|
||||||
|
func (daemon *Daemon) TagImage(imageName, repository, tag string) error {
|
||||||
|
imageID, err := daemon.GetImageID(imageName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newTag, err := reference.WithName(repository)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if tag != "" {
|
||||||
|
if newTag, err = reference.WithTag(newTag, tag); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return daemon.TagImageWithReference(imageID, newTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TagImageWithReference adds the given reference to the image ID provided.
|
||||||
|
func (daemon *Daemon) TagImageWithReference(imageID image.ID, newTag reference.Named) error {
|
||||||
|
if err := daemon.referenceStore.AddTag(newTag, imageID, true); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon.LogImageEvent(imageID.String(), newTag.String(), "tag")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package daemon
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
@ -24,13 +25,33 @@ import (
|
||||||
// inConfig (if src is "-"), or from a URI specified in src. Progress output is
|
// inConfig (if src is "-"), or from a URI specified in src. Progress output is
|
||||||
// written to outStream. Repository and tag names can optionally be given in
|
// written to outStream. Repository and tag names can optionally be given in
|
||||||
// the repo and tag arguments, respectively.
|
// the repo and tag arguments, respectively.
|
||||||
func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
|
func (daemon *Daemon) ImportImage(src string, repository, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
|
||||||
var (
|
var (
|
||||||
sf = streamformatter.NewJSONStreamFormatter()
|
sf = streamformatter.NewJSONStreamFormatter()
|
||||||
rc io.ReadCloser
|
rc io.ReadCloser
|
||||||
resp *http.Response
|
resp *http.Response
|
||||||
|
newRef reference.Named
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if repository != "" {
|
||||||
|
var err error
|
||||||
|
newRef, err = reference.ParseNamed(repository)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, isCanonical := newRef.(reference.Canonical); isCanonical {
|
||||||
|
return errors.New("cannot import digest reference")
|
||||||
|
}
|
||||||
|
|
||||||
|
if tag != "" {
|
||||||
|
newRef, err = reference.WithTag(newRef, tag)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
|
config, err := dockerfile.BuildFromConfig(&container.Config{}, changes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -103,7 +124,7 @@ func (daemon *Daemon) ImportImage(src string, newRef reference.Named, msg string
|
||||||
|
|
||||||
// FIXME: connect with commit code and call refstore directly
|
// FIXME: connect with commit code and call refstore directly
|
||||||
if newRef != nil {
|
if newRef != nil {
|
||||||
if err := daemon.TagImage(newRef, id.String()); err != nil {
|
if err := daemon.TagImageWithReference(id, newRef); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue