func SafeAttachWaitContainer(p DockerProvisioner, opts docker.AttachToContainerOptions) (int, error) { cluster := p.Cluster() resultCh := make(chan waitResult, 1) go func() { err := cluster.AttachToContainer(opts) if err != nil { resultCh <- waitResult{err: err} return } status, err := cluster.WaitContainer(opts.Container) resultCh <- waitResult{status: status, err: err} }() for { select { case result := <-resultCh: return result.status, result.err case <-time.After(safeAttachInspectTimeout): } contData, err := cluster.InspectContainer(opts.Container) if err != nil { return 0, err } if !contData.State.Running { return contData.State.ExitCode, nil } } }
func (p *dockerProvisioner) UploadDeploy(app provision.App, archiveFile io.ReadCloser, w io.Writer) (string, error) { defer archiveFile.Close() filePath := "/home/application/archive.tar.gz" user, err := config.GetString("docker:user") if err != nil { user, _ = config.GetString("docker:ssh:user") } options := docker.CreateContainerOptions{ Config: &docker.Config{ AttachStdout: true, AttachStderr: true, AttachStdin: true, OpenStdin: true, StdinOnce: true, User: user, Image: p.getBuildImage(app), Cmd: []string{"/bin/bash", "-c", "cat > " + filePath}, }, } cluster := p.Cluster() _, container, err := cluster.CreateContainerSchedulerOpts(options, []string{app.GetName(), ""}) if err != nil { return "", err } defer cluster.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID, Force: true}) err = cluster.StartContainer(container.ID, nil) if err != nil { return "", err } var output bytes.Buffer err = cluster.AttachToContainer(docker.AttachToContainerOptions{ Container: container.ID, OutputStream: &output, ErrorStream: &output, InputStream: archiveFile, Stream: true, Stdin: true, Stdout: true, Stderr: true, }) if err != nil { return "", err } status, err := cluster.WaitContainer(container.ID) if err != nil { return "", err } if status != 0 { log.Errorf("Failed to deploy container from upload: %s", &output) return "", fmt.Errorf("container exited with status %d", status) } image, err := cluster.CommitContainer(docker.CommitContainerOptions{Container: container.ID}) if err != nil { return "", err } imageId, err := p.archiveDeploy(app, image.ID, "file://"+filePath, w) if err != nil { return "", err } return imageId, p.deployAndClean(app, imageId, w) }