Example #1
0
func pullImage(
	ctx context.Context, l *LocalCluster, ref string, options types.ImagePullOptions,
) error {
	// HACK: on CircleCI, docker pulls the image on the first access from an
	// acceptance test even though that image is already present. So we first
	// check to see if our image is present in order to avoid this slowness.
	if hasImage(ctx, l, ref) {
		log.Infof(ctx, "ImagePull %s already exists", ref)
		return nil
	}

	log.Infof(ctx, "ImagePull %s starting", ref)
	defer log.Infof(ctx, "ImagePull %s complete", ref)

	rc, err := l.client.ImagePull(ctx, ref, options)
	if err != nil {
		return err
	}
	defer rc.Close()
	out := os.Stderr
	outFd := out.Fd()
	isTerminal := isatty.IsTerminal(outFd)

	return jsonmessage.DisplayJSONMessagesStream(rc, out, outFd, isTerminal, nil)
}
Example #2
0
File: load.go Project: F21/docker
func runLoad(dockerCli *client.DockerCli, opts loadOptions) error {

	var input io.Reader = dockerCli.In()
	if opts.input != "" {
		file, err := os.Open(opts.input)
		if err != nil {
			return err
		}
		defer file.Close()
		input = file
	}
	if !dockerCli.IsTerminalOut() {
		opts.quiet = true
	}
	response, err := dockerCli.Client().ImageLoad(context.Background(), input, opts.quiet)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.Body != nil && response.JSON {
		return jsonmessage.DisplayJSONMessagesStream(response.Body, dockerCli.Out(), dockerCli.OutFd(), dockerCli.IsTerminalOut(), nil)
	}

	_, err = io.Copy(dockerCli.Out(), response.Body)
	return err
}
Example #3
0
// PullImage pulls docker image
func (c *DockerClient) PullImage(name string) error {

	var (
		image                  = imagename.NewFromString(name)
		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)
	}()

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

	return <-errch
}
Example #4
0
func pullImage(ctx context.Context, dockerCli *command.DockerCli, image string, out io.Writer) error {
	ref, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index)
	encodedAuth, err := command.EncodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	options := types.ImageCreateOptions{
		RegistryAuth: encodedAuth,
	}

	responseBody, err := dockerCli.Client().ImageCreate(ctx, image, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(
		responseBody,
		out,
		dockerCli.Out().FD(),
		dockerCli.Out().IsTerminal(),
		nil)
}
Example #5
0
func handleStreamResponse(resp *http.Response, streamOptions *streamOptions) error {
	var err error
	if !streamOptions.useJSONDecoder && resp.Header.Get("Content-Type") != "application/json" {
		if streamOptions.setRawTerminal {
			_, err = io.Copy(streamOptions.stdout, resp.Body)
		} else {
			_, err = stdcopy.StdCopy(streamOptions.stdout, streamOptions.stderr, resp.Body)
		}
		return err
	}
	// if we want to get raw json stream, just copy it back to output
	// without decoding it
	if streamOptions.rawJSONStream {
		_, err = io.Copy(streamOptions.stdout, resp.Body)
		return err
	}
	if st, ok := streamOptions.stdout.(interface {
		io.Writer
		FD() uintptr
		IsTerminal() bool
	}); ok {
		err = jsonmessage.DisplayJSONMessagesToStream(resp.Body, st, nil)
	} else {
		err = jsonmessage.DisplayJSONMessagesStream(resp.Body, streamOptions.stdout, 0, false, nil)
	}
	return err
}
Example #6
0
func runDeploy(cmd *Command, args []string) {
	r, w := io.Pipe()

	if len(args) < 1 {
		printFatal("You must specify an image to deploy")
	}

	image := args[0]
	message := getMessage()
	form := &PostDeployForm{Image: image}

	var endpoint string
	appName, _ := app()
	if appName != "" {
		endpoint = fmt.Sprintf("/apps/%s/deploys", appName)
	} else {
		endpoint = "/deploys"
	}

	rh := heroku.RequestHeaders{CommitMessage: message}
	go func() {
		must(client.PostWithHeaders(w, endpoint, form, rh.Headers()))
		must(w.Close())
	}()

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)
	must(jsonmessage.DisplayJSONMessagesStream(r, os.Stdout, outFd, isTerminalOut))
}
Example #7
0
// CmdLoad loads an image from a tar archive.
//
// The tar archive is read from STDIN by default, or from a tar archive file.
//
// Usage: docker load [OPTIONS]
func (cli *DockerCli) CmdLoad(args ...string) error {
	cmd := Cli.Subcmd("load", nil, Cli.DockerCommands["load"].Description, true)
	infile := cmd.String([]string{"i", "-input"}, "", "Read from a tar archive file, instead of STDIN")
	quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress the load output")
	cmd.Require(flag.Exact, 0)
	cmd.ParseFlags(args, true)

	var input io.Reader = cli.in
	if *infile != "" {
		file, err := os.Open(*infile)
		if err != nil {
			return err
		}
		defer file.Close()
		input = file
	}
	if !cli.isTerminalOut {
		*quiet = true
	}
	response, err := cli.client.ImageLoad(context.Background(), input, *quiet)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	if response.JSON {
		return jsonmessage.DisplayJSONMessagesStream(response.Body, cli.out, cli.outFd, cli.isTerminalOut, nil)
	}

	_, err = io.Copy(cli.out, response.Body)
	return err
}
Example #8
0
// CmdPush pushes an image or repository to the registry.
//
// Usage: docker push NAME[:TAG]
func (cli *DockerCli) CmdPush(args ...string) error {
	cmd := Cli.Subcmd("push", []string{"NAME[:TAG]"}, Cli.DockerCommands["push"].Description, true)
	addTrustedFlags(cmd, false)
	cmd.Require(flag.Exact, 1)

	cmd.ParseFlags(args, true)

	ref, err := reference.ParseNamed(cmd.Arg(0))
	if err != nil {
		return err
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}
	// Resolve the Auth config relevant for this server
	authConfig := cli.resolveAuthConfig(repoInfo.Index)

	requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push")
	if isTrusted() {
		return cli.trustedPush(repoInfo, ref, authConfig, requestPrivilege)
	}

	responseBody, err := cli.imagePushPrivileged(authConfig, ref.String(), requestPrivilege)
	if err != nil {
		return err
	}

	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil)
}
Example #9
0
func (cli *DockerCli) pullImage(image string, out io.Writer) error {
	ref, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	authConfig := cli.resolveAuthConfig(repoInfo.Index)
	encodedAuth, err := encodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	options := types.ImageCreateOptions{
		RegistryAuth: encodedAuth,
	}

	responseBody, err := cli.client.ImageCreate(context.Background(), image, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, out, cli.outFd, cli.isTerminalOut, nil)
}
Example #10
0
func runPush(dockerCli *client.DockerCli, remote string) error {
	ref, err := reference.ParseNamed(remote)
	if err != nil {
		return err
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	ctx := context.Background()

	// Resolve the Auth config relevant for this server
	authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index)
	requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "push")

	if client.IsTrusted() {
		return dockerCli.TrustedPush(ctx, repoInfo, ref, authConfig, requestPrivilege)
	}

	responseBody, err := dockerCli.ImagePushPrivileged(ctx, authConfig, ref.String(), requestPrivilege)
	if err != nil {
		return err
	}

	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, dockerCli.Out(), dockerCli.OutFd(), dockerCli.IsTerminalOut(), nil)
}
Example #11
0
// CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image.
//
// The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file or a path to local file relative to docker client. If the URL is '-', then the tar file is read from STDIN.
//
// Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
func (cli *DockerCli) CmdImport(args ...string) error {
	cmd := Cli.Subcmd("import", []string{"file|URL|- [REPOSITORY[:TAG]]"}, Cli.DockerCommands["import"].Description, true)
	flChanges := opts.NewListOpts(nil)
	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
	message := cmd.String([]string{"m", "-message"}, "", "Set commit message for imported image")
	cmd.Require(flag.Min, 1)

	cmd.ParseFlags(args, true)

	var (
		in         io.Reader
		tag        string
		src        = cmd.Arg(0)
		srcName    = src
		repository = cmd.Arg(1)
		changes    = flChanges.GetAll()
	)

	if cmd.NArg() == 3 {
		fmt.Fprintf(cli.err, "[DEPRECATED] The format 'file|URL|- [REPOSITORY [TAG]]' has been deprecated. Please use file|URL|- [REPOSITORY[:TAG]]\n")
		tag = cmd.Arg(2)
	}

	if repository != "" {
		//Check if the given image name can be resolved
		if _, err := reference.ParseNamed(repository); err != nil {
			return err
		}
	}

	if src == "-" {
		in = cli.in
	} else if !urlutil.IsURL(src) {
		srcName = "-"
		file, err := os.Open(src)
		if err != nil {
			return err
		}
		defer file.Close()
		in = file
	}

	options := types.ImageImportOptions{
		Source:         in,
		SourceName:     srcName,
		RepositoryName: repository,
		Message:        *message,
		Tag:            tag,
		Changes:        changes,
	}

	responseBody, err := cli.client.ImageImport(options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut)
}
Example #12
0
func NewDockerJsonWriter(under io.Writer) *DockerJsonWriter {
	r, w := io.Pipe()
	go func() {
		err := jsonmessage.DisplayJSONMessagesStream(r, under, 1, true, nil)
		log.Fatal(err)
	}()
	return &DockerJsonWriter{under, w}
}
Example #13
0
func pullImage(client client.APIClient, service *Service, image string) error {
	distributionRef, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	switch distributionRef.(type) {
	case reference.Canonical:
	case reference.NamedTagged:
	default:
		distributionRef, err = reference.WithTag(distributionRef, "latest")
		if err != nil {
			return err
		}
	}

	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	authConfig := types.AuthConfig{}
	if service.context.ConfigFile != nil && repoInfo != nil && repoInfo.Index != nil {
		authConfig = registry.ResolveAuthConfig(service.context.ConfigFile.AuthConfigs, repoInfo.Index)
	}

	encodedAuth, err := encodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	options := types.ImagePullOptions{
		RegistryAuth: encodedAuth,
	}
	responseBody, err := client.ImagePull(context.Background(), distributionRef.String(), options)
	if err != nil {
		logrus.Errorf("Failed to pull image %s: %v", image, err)
		return err
	}
	defer responseBody.Close()

	var writeBuff io.Writer = os.Stdout

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)

	err = jsonmessage.DisplayJSONMessagesStream(responseBody, writeBuff, outFd, isTerminalOut, nil)
	if err != nil {
		if jerr, ok := err.(*jsonmessage.JSONError); ok {
			// If no error code is set, default to 1
			if jerr.Code == 0 {
				jerr.Code = 1
			}
			fmt.Fprintf(os.Stderr, "%s", writeBuff)
			return fmt.Errorf("Status: %s, Code: %d", jerr.Message, jerr.Code)
		}
	}
	return err
}
Example #14
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
}
Example #15
0
func ensureImage(cli DockerClient, image string) (string, error) {
	ctx := context.Background()
	info, _, err := cli.ImageInspectWithRaw(ctx, image, false)
	if err == nil {
		logrus.Debugf("Image found locally %s", image)
		return info.ID, nil
	}

	if !client.IsErrImageNotFound(err) {
		logrus.Errorf("Error inspecting image %q: %v", image, err)
		return "", err
	}

	// Image must be tagged reference if it does not exist
	ref, err := reference.Parse(image)
	if err != nil {
		logrus.Errorf("Image is not valid reference %q: %v", image, err)
		return "", err
	}
	tagged, ok := ref.(reference.NamedTagged)
	if !ok {
		logrus.Errorf("Tagged reference required %q", image)
		return "", errors.New("invalid reference, tag needed")
	}

	pullStart := time.Now()
	pullOptions := types.ImagePullOptions{
		PrivilegeFunc: registryAuthNotSupported,
	}
	resp, err := cli.ImagePull(ctx, tagged.String(), pullOptions)
	if err != nil {
		logrus.Errorf("Error pulling image %q: %v", tagged.String(), err)
		return "", err
	}
	defer resp.Close()

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)

	if err = jsonmessage.DisplayJSONMessagesStream(resp, os.Stdout, outFd, isTerminalOut, nil); err != nil {
		logrus.Errorf("Error copying pull output: %v", err)
		return "", err
	}
	// TODO: Get pulled digest

	logFields := logrus.Fields{
		timerKey: time.Since(pullStart),
		"image":  tagged.String(),
	}
	logrus.WithFields(logFields).Info("image pulled")

	info, _, err = cli.ImageInspectWithRaw(ctx, tagged.String(), false)
	if err != nil {
		return "", nil
	}

	return info.ID, nil
}
Example #16
0
// Write decodes the jsonmessage stream in the bytes, and writes the decoded
// plain text to the underlying io.Writer.
func (w *DecodedJSONMessageWriter) Write(b []byte) (int, error) {
	err := jsonmessage.DisplayJSONMessagesStream(bytes.NewReader(b), w.w, w.fd, false)
	if err != nil {
		if err, ok := err.(*jsonmessage.JSONError); ok {
			w.err = err
			return len(b), nil
		}
	}
	return len(b), err
}
Example #17
0
// CmdImport creates an empty filesystem image, imports the contents of the tarball into the image, and optionally tags the image.
//
// The URL argument is the address of a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) file or a path to local file relative to docker client. If the URL is '-', then the tar file is read from STDIN.
//
// Usage: docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
func (cli *DockerCli) CmdImport(args ...string) error {
	cmd := Cli.Subcmd("import", []string{"file|URL|- [REPOSITORY[:TAG]]"}, Cli.DockerCommands["import"].Description, true)
	flChanges := opts.NewListOpts(nil)
	cmd.Var(&flChanges, []string{"c", "-change"}, "Apply Dockerfile instruction to the created image")
	message := cmd.String([]string{"m", "-message"}, "", "Set commit message for imported image")
	cmd.Require(flag.Min, 1)

	cmd.ParseFlags(args, true)

	var (
		in      io.Reader
		tag     string
		src     = cmd.Arg(0)
		srcName = src
		ref     = cmd.Arg(1)
		changes = flChanges.GetAll()
	)

	if cmd.NArg() == 3 {
		// FIXME(vdemeester) Which version has this been deprecated ? should we remove it ?
		fmt.Fprintf(cli.err, "[DEPRECATED] The format 'file|URL|- [REPOSITORY [TAG]]' has been deprecated. Please use file|URL|- [REPOSITORY[:TAG]]\n")
		tag = cmd.Arg(2)
	}

	if src == "-" {
		in = cli.in
	} else if !urlutil.IsURL(src) {
		srcName = "-"
		file, err := os.Open(src)
		if err != nil {
			return err
		}
		defer file.Close()
		in = file
	}

	source := types.ImageImportSource{
		Source:     in,
		SourceName: srcName,
	}

	options := types.ImageImportOptions{
		Message: *message,
		Tag:     tag,
		Changes: changes,
	}

	responseBody, err := cli.client.ImageImport(context.Background(), source, ref, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil)
}
Example #18
0
File: app.go Project: Gys/deployit
func (a *App) Build(e *env.Env, writer io.Writer) error {
	e.Log.Info(`Build app`)

	if a.Layer.ID == `` {
		return errors.New("layer not found")
	}

	if err := a.Config.Sync(e, a.Layer.ID); err != nil {
		return err
	}

	tar_path := fmt.Sprintf("%s/apps/%s", env.Default_root_path, a.Layer.ID)

	reader, err := os.Open(tar_path)
	if err != nil {
		return err
	}

	or, ow := io.Pipe()
	opts := interfaces.BuildImageOptions{
		Name:           a.Config.Image,
		RmTmpContainer: true,
		InputStream:    reader,
		OutputStream:   ow,
		RawJSONStream:  true,
	}

	ch := make(chan error, 1)

	go func() {
		defer ow.Close()
		defer close(ch)
		if err := e.Containers.BuildImage(opts); err != nil {
			e.Log.Error(err)
			return
		}
	}()

	jsonmessage.DisplayJSONMessagesStream(or, writer, os.Stdout.Fd(), term.IsTerminal(os.Stdout.Fd()), nil)
	if err, ok := <-ch; ok {
		if err != nil {
			e.Log.Error(err)
			return err
		}
	}

	if err := a.Update(e); err != nil {
		return err
	}

	reader.Close()
	or.Close()

	return nil
}
Example #19
0
func (s *Storage) RunDockerClient(reader io.Reader,
	fn func(ch chan error)) (err error) {
	errChan := make(chan error, 1)
	go fn(errChan)
	go func(ch chan error) {
		err := jsonmessage.DisplayJSONMessagesStream(reader, os.Stdout,
			os.Stdout.Fd(), true)
		ch <- err
	}(errChan)
	err = <-errChan
	return
}
Example #20
0
// PushImage pushes the image
func (c *DockerClient) PushImage(imageName string) (digest string, err error) {
	var (
		img = imagename.NewFromString(imageName)

		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)
	}()

	if err := c.client.PushImage(opts, c.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
}
Example #21
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
}
Example #22
0
// Build implements Builder. It consumes the docker build API endpoint and sends
// a tar of the specified service build context.
func (d *DaemonBuilder) Build(imageName string, p *project.Project, service project.Service) error {
	if service.Config().Build == "" {
		return fmt.Errorf("Specified service does not have a build section")
	}

	ctx, err := CreateTar(p, service.Name())
	if err != nil {
		return err
	}
	defer ctx.Close()

	var progBuff io.Writer = os.Stdout
	var buildBuff io.Writer = os.Stdout

	// Setup an upload progress bar
	progressOutput := streamformatter.NewStreamFormatter().NewProgressOutput(progBuff, true)

	var body io.Reader = progress.NewProgressReader(ctx, progressOutput, 0, "", "Sending build context to Docker daemon")

	client := d.context.ClientFactory.Create(service)

	logrus.Infof("Building %s...", imageName)

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)

	response, err := client.ImageBuild(context.Background(), types.ImageBuildOptions{
		Context:     body,
		Tags:        []string{imageName},
		NoCache:     d.context.NoCache,
		Remove:      true,
		Dockerfile:  service.Config().Dockerfile,
		AuthConfigs: d.context.ConfigFile.AuthConfigs,
	})

	err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, outFd, isTerminalOut, nil)
	if err != nil {
		if jerr, ok := err.(*jsonmessage.JSONError); ok {
			// If no error code is set, default to 1
			if jerr.Code == 0 {
				jerr.Code = 1
			}
			fmt.Fprintf(os.Stderr, "%s%s", progBuff, buildBuff)
			return fmt.Errorf("Status: %s, Code: %d", jerr.Message, jerr.Code)
		}
	}
	return err
}
Example #23
0
// PullImage pulls the specified image (can be a name, an id or a digest)
// to the daemon store with the specified client.
func PullImage(ctx context.Context, client client.ImageAPIClient, serviceName string, authLookup auth.Lookup, image string) error {
	fmt.Fprintf(os.Stderr, "Pulling %s (%s)...\n", serviceName, image)
	distributionRef, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
	if err != nil {
		return err
	}

	authConfig := authLookup.Lookup(repoInfo)

	// Use ConfigFile.SaveToWriter to not re-define encodeAuthToBase64
	encodedAuth, err := encodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}

	options := types.ImagePullOptions{
		RegistryAuth: encodedAuth,
	}
	responseBody, err := client.ImagePull(ctx, distributionRef.String(), options)
	if err != nil {
		logrus.Errorf("Failed to pull image %s: %v", image, err)
		return err
	}
	defer responseBody.Close()

	var writeBuff io.Writer = os.Stderr

	outFd, isTerminalOut := term.GetFdInfo(os.Stderr)

	err = jsonmessage.DisplayJSONMessagesStream(responseBody, writeBuff, outFd, isTerminalOut, nil)
	if err != nil {
		if jerr, ok := err.(*jsonmessage.JSONError); ok {
			// If no error code is set, default to 1
			if jerr.Code == 0 {
				jerr.Code = 1
			}
			fmt.Fprintf(os.Stderr, "%s", writeBuff)
			return fmt.Errorf("Status: %s, Code: %d", jerr.Message, jerr.Code)
		}
	}
	return err
}
Example #24
0
func (cli *HyperClient) readStreamOutput(body io.ReadCloser, contentType string, setRawTerminal bool, stdout, stderr io.Writer) error {
	defer body.Close()

	if utils.MatchesContentType(contentType, "application/json") {
		return jsonmessage.DisplayJSONMessagesStream(body, stdout, cli.outFd, cli.isTerminalOut, nil)
	}
	if stdout != nil || stderr != nil {
		// When TTY is ON, use regular copy
		var err error
		if setRawTerminal {
			_, err = io.Copy(stdout, body)
		} else {
			_, err = stdcopy.StdCopy(stdout, stderr, body)
		}
		return err
	}
	return nil
}
Example #25
0
func (client *DockerClient) PullImage(name string, auth *AuthConfig, cliOut io.Writer) (err error) {
	v := url.Values{}
	v.Set("fromImage", name)
	uri := fmt.Sprintf("/%s/images/create?%s", APIVersion, v.Encode())
	req, _ := http.NewRequest("POST", client.URL.String()+uri, nil)
	if auth != nil {
		req.Header.Add("X-Registry-Auth", auth.encode())
	}
	var resp *http.Response
	resp, err = client.HTTPClient.Do(req)
	if err != nil {
		return
	}
	defer resp.Body.Close()
	errorReader := io.Reader(resp.Body)
	if cliOut != nil {
		pipeReader, pipeWriter := io.Pipe()
		streamErrChan := make(chan error)
		defer func() {
			pipeWriter.Close()
			if err == nil {
				err = <-streamErrChan
			}
		}()
		errorReader = io.TeeReader(resp.Body, pipeWriter)
		go func() {
			fd, isTerminalIn := term.GetFdInfo(cliOut)
			streamErrChan <- jsonmessage.DisplayJSONMessagesStream(pipeReader, cliOut, fd, isTerminalIn)
		}()
	}
	var finalObj map[string]interface{}
	for decoder := json.NewDecoder(errorReader); err == nil; err = decoder.Decode(&finalObj) {
	}
	if err != io.EOF {
		return
	} else {
		err = nil
	}
	if errObj, ok := finalObj["error"]; ok {
		err = fmt.Errorf("%v", errObj)
		return
	}
	return
}
Example #26
0
// Build implements Builder. It consumes the docker build API endpoint and sends
// a tar of the specified service build context.
func (d *DaemonBuilder) Build(ctx context.Context, imageName string) error {
	buildCtx, err := createTar(d.ContextDirectory, d.Dockerfile)
	if err != nil {
		return err
	}
	defer buildCtx.Close()

	var progBuff io.Writer = os.Stdout
	var buildBuff io.Writer = os.Stdout

	// Setup an upload progress bar
	progressOutput := streamformatter.NewStreamFormatter().NewProgressOutput(progBuff, true)

	var body io.Reader = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")

	logrus.Infof("Building %s...", imageName)

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)

	response, err := d.Client.ImageBuild(ctx, body, types.ImageBuildOptions{
		Tags:        []string{imageName},
		NoCache:     d.NoCache,
		Remove:      true,
		ForceRemove: d.ForceRemove,
		PullParent:  d.Pull,
		Dockerfile:  d.Dockerfile,
		AuthConfigs: d.AuthConfigs,
	})
	if err != nil {
		return err
	}

	err = jsonmessage.DisplayJSONMessagesStream(response.Body, buildBuff, outFd, isTerminalOut, nil)
	if err != nil {
		if jerr, ok := err.(*jsonmessage.JSONError); ok {
			// If no error code is set, default to 1
			if jerr.Code == 0 {
				jerr.Code = 1
			}
			return fmt.Errorf("Status: %s, Code: %d", jerr.Message, jerr.Code)
		}
	}
	return err
}
Example #27
0
func (cli *DockerCli) streamBody(body io.ReadCloser, contentType string, rawTerminal bool, stdout, stderr io.Writer) error {
	defer body.Close()

	if api.MatchesContentType(contentType, "application/json") {
		return jsonmessage.DisplayJSONMessagesStream(body, stdout, cli.outFd, cli.isTerminalOut)
	}
	if stdout != nil || stderr != nil {
		// When TTY is ON, use regular copy
		var err error
		if rawTerminal {
			_, err = io.Copy(stdout, body)
		} else {
			_, err = stdcopy.StdCopy(stdout, stderr, body)
		}
		logrus.Debugf("[stream] End of stdout")
		return err
	}
	return nil
}
Example #28
0
func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
	ref, err := reference.ParseNamed(image)
	if err != nil {
		return err
	}

	var tag string
	switch x := ref.(type) {
	case reference.Digested:
		tag = x.Digest().String()
	case reference.Tagged:
		tag = x.Tag()
	default:
		// pull only the image tagged 'latest' if no tag was specified
		tag = tagpkg.DefaultTag
	}

	// Resolve the Repository name from fqn to RepositoryInfo
	repoInfo, err := registry.ParseRepositoryInfo(ref)
	if err != nil {
		return err
	}

	// Resolve the Auth config relevant for this server
	encodedAuth, err := cli.encodeRegistryAuth(repoInfo.Index)
	if err != nil {
		return err
	}

	options := types.ImageCreateOptions{
		Parent:       ref.Name(),
		Tag:          tag,
		RegistryAuth: encodedAuth,
	}

	responseBody, err := cli.client.ImageCreate(options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, out, cli.outFd, cli.isTerminalOut)
}
Example #29
0
func (cli *DockerCli) imagePullPrivileged(authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc) error {

	encodedAuth, err := encodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}
	options := types.ImagePullOptions{
		RegistryAuth:  encodedAuth,
		PrivilegeFunc: requestPrivilege,
	}

	responseBody, err := cli.client.ImagePull(context.Background(), ref, options)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil)
}
Example #30
0
func (cli *DockerCli) imagePushPrivileged(authConfig types.AuthConfig, imageID, tag string, outputStream io.Writer, requestPrivilege lib.RequestPrivilegeFunc) error {
	encodedAuth, err := encodeAuthToBase64(authConfig)
	if err != nil {
		return err
	}
	options := types.ImagePushOptions{
		ImageID:      imageID,
		Tag:          tag,
		RegistryAuth: encodedAuth,
	}

	responseBody, err := cli.client.ImagePush(options, requestPrivilege)
	if err != nil {
		return err
	}
	defer responseBody.Close()

	return jsonmessage.DisplayJSONMessagesStream(responseBody, outputStream, cli.outFd, cli.isTerminalOut)
}