示例#1
0
// PullDockerImage pulls an image and streams to a logger respecting terminal features
func PullDockerImage(client *docker.Client, image *imagename.ImageName, auth *docker.AuthConfigurations) (*docker.Image, error) {
	if image.Storage == imagename.StorageS3 {
		s3storage := s3.New(client, os.TempDir())
		if err := s3storage.Pull(image.String()); err != nil {
			return nil, err
		}
	} else {
		pipeReader, pipeWriter := io.Pipe()

		pullOpts := docker.PullImageOptions{
			Repository:    image.NameWithRegistry(),
			Registry:      image.Registry,
			Tag:           image.Tag,
			OutputStream:  pipeWriter,
			RawJSONStream: true,
		}

		repoAuth, err := dockerclient.GetAuthForRegistry(auth, image)
		if err != nil {
			return nil, fmt.Errorf("Failed to authenticate registry %s, error: %s", image.Registry, err)
		}

		errch := make(chan error, 1)

		go func() {
			err := client.PullImage(pullOpts, repoAuth)

			if err := pipeWriter.Close(); err != nil {
				log.Errorf("Failed to close pull image stream for %s, error: %s", image, err)
			}

			errch <- err
		}()

		def := log.StandardLogger()
		fd, isTerminal := term.GetFdInfo(def.Out)
		out := def.Out

		if !isTerminal {
			out = def.Writer()
		}

		if err := jsonmessage.DisplayJSONMessagesStream(pipeReader, out, fd, isTerminal); err != nil {
			return nil, fmt.Errorf("Failed to process json stream for image: %s, error: %s", image, err)
		}

		if err := <-errch; err != nil {
			return nil, fmt.Errorf("Failed to pull image %s, error: %s", image, err)
		}
	}

	img, err := client.InspectImage(image.String())
	if err != nil {
		return nil, fmt.Errorf("Failed to inspect image %s after pull, error: %s", image, err)
	}

	return img, nil
}
示例#2
0
// PullImage pulls docker image
func (c *DockerClient) PullImage(name string) error {
	image := imagename.NewFromString(name)

	// e.g. s3:bucket-name/image-name
	if image.Storage == imagename.StorageS3 {
		if isOld, warning := imagename.WarnIfOldS3ImageName(name); isOld {
			c.log.Warn(warning)
		}

		return c.s3storage.Pull(name)
	}

	var (
		pipeReader, pipeWriter = io.Pipe()
		fdOut, isTerminalOut   = term.GetFdInfo(c.log.Out)
		out                    = c.log.Out
		errch                  = make(chan error, 1)
	)

	if !isTerminalOut {
		out = c.log.Writer()
	}

	opts := docker.PullImageOptions{
		Repository:    image.NameWithRegistry(),
		Registry:      image.Registry,
		Tag:           image.GetTag(),
		OutputStream:  pipeWriter,
		RawJSONStream: true,
	}

	c.log.Infof("| Pull image %s", image)
	c.log.Debugf("Pull image %s with options: %# v", image, opts)

	go func() {
		errch <- jsonmessage.DisplayJSONMessagesStream(pipeReader, out, fdOut, isTerminalOut)
	}()

	auth, err := dockerclient.GetAuthForRegistry(c.auth, image)
	if err != nil {
		return fmt.Errorf("Failed to authenticate registry %s, error: %s", image.Registry, err)
	}

	if err := c.client.PullImage(opts, auth); err != nil {
		return err
	}

	pipeWriter.Close()
	return <-errch
}
示例#3
0
// pushImageInner pushes the image is the inner straightforward push without retries
func (c *DockerClient) pushImageInner(imageName string) (digest string, err error) {
	img := imagename.NewFromString(imageName)

	// Use direct S3 image pusher instead
	if img.Storage == imagename.StorageS3 {
		if isOld, warning := imagename.WarnIfOldS3ImageName(imageName); isOld {
			c.log.Warn(warning)
		}
		return c.s3storage.Push(imageName)
	}

	var (
		buf                    bytes.Buffer
		pipeReader, pipeWriter = io.Pipe()
		outStream              = io.MultiWriter(pipeWriter, &buf)
		fdOut, isTerminalOut   = term.GetFdInfo(c.log.Out)
		out                    = c.log.Out

		opts = docker.PushImageOptions{
			Name:          img.NameWithRegistry(),
			Tag:           img.GetTag(),
			Registry:      img.Registry,
			OutputStream:  outStream,
			RawJSONStream: true,
		}
		errch = make(chan error, 1)
	)

	if !isTerminalOut {
		out = c.log.Writer()
	}

	c.log.Infof("| Push %s", img)

	c.log.Debugf("Push with options: %# v", opts)

	// TODO: DisplayJSONMessagesStream may fail by client.PushImage run without errors
	go func() {
		errch <- jsonmessage.DisplayJSONMessagesStream(pipeReader, out, fdOut, isTerminalOut)
	}()

	auth, err := dockerclient.GetAuthForRegistry(c.auth, img)
	if err != nil {
		return "", fmt.Errorf("Failed to authenticate registry %s, error: %s", img.Registry, err)
	}

	if err := c.client.PushImage(opts, auth); err != nil {
		return "", err
	}
	pipeWriter.Close()

	if err := <-errch; err != nil {
		return "", fmt.Errorf("Failed to process json stream, error %s", err)
	}

	// It is the best way to have pushed image digest so far
	matches := captureDigest.FindStringSubmatch(buf.String())
	if len(matches) > 0 {
		digest = matches[1]
	}

	return digest, nil
}