Example #1
0
func buildTorImage(cli *client.Client, ctx io.Reader) (string, error) {
	// XXX: There's currently no way to get the image ID of a build without
	//      manually parsing the output, or tagging the image. Since I'm not in
	//      the mood for the former, we can tag the build with a random name.
	//      Unfortunately, untagging of images isn't supported, so we'll have to
	//      use a name that allows us to not pollute the host.

	options := types.ImageBuildOptions{
		// XXX: If we SuppressOutput we can get just the image ID, but we lose
		//      being able to tell users what the status of the build is.
		//SuppressOutput: true,
		Tags:        []string{MkonionTag},
		Remove:      true,
		ForceRemove: true,
		Dockerfile:  "Dockerfile",
		Context:     ctx,
	}

	build, err := cli.ImageBuild(options)
	if err != nil {
		return "", err
	}

	// XXX: For some weird reason, at this point the build has not finished. We
	//      need to wait for build.Body to be closed. We might as well tell the
	//      user what the status of the build is.
	log.Infof("building %s", MkonionTag)
	dec := json.NewDecoder(build.Body)
	for {
		// Modified from pkg/jsonmessage in Docker.
		type JSONMessage struct {
			Stream string `json:"stream,omitempty"`
			Status string `json:"status,omitempty"`
		}

		// Decode the JSONMessages.
		var jm JSONMessage
		if err := dec.Decode(&jm); err != nil {
			if err == io.EOF {
				break
			}
			return "", err
		}

		jm.Stream = strings.TrimSpace(jm.Stream)
		jm.Status = strings.TrimSpace(jm.Status)

		// Log the status.
		if jm.Stream != "" {
			log.Info(jm.Stream)
		}
		if jm.Status != "" {
			log.Info(jm.Status)
		}
	}

	inspect, _, err := cli.ImageInspectWithRaw(MkonionTag, false)
	if err != nil {
		// XXX: Should probably clean up the built image here?
		return "", err
	}

	log.Infof("successfully built %s image", MkonionTag)
	return inspect.ID, nil
}