//RecoverInteractive restarts the box with a terminal attached func (b *DockerBox) RecoverInteractive(cwd string, pipeline core.Pipeline, step core.Step) error { // TODO(termie): maybe move the container manipulation outside of here? client := b.client container, err := b.Restart() if err != nil { b.logger.Panicln("box restart failed") return err } env := []string{} env = append(env, pipeline.Env().Export()...) env = append(env, pipeline.Env().Hidden.Export()...) env = append(env, step.Env().Export()...) env = append(env, fmt.Sprintf("cd %s", cwd)) cmd := []string{b.cmd} return client.AttachInteractive(container.ID, cmd, env) }
// RunStep runs a step and tosses error if it fails func (p *Runner) RunStep(shared *RunnerShared, step core.Step, order int) (*StepResult, error) { finisher := p.StartStep(shared, step, order) sr := &StepResult{ Success: false, Artifact: nil, Message: "", ExitCode: 1, } defer finisher.Finish(sr) if step.ShouldSyncEnv() { err := shared.pipeline.SyncEnvironment(shared.sessionCtx, shared.sess) if err != nil { // If an error occured, just log and ignore it p.logger.WithField("Error", err).Warn("Unable to sync environment") } } step.InitEnv(shared.pipeline.Env()) p.logger.Debugln("Step Environment") for _, pair := range step.Env().Ordered() { p.logger.Debugln(" ", pair[0], pair[1]) } exit, err := step.Execute(shared.sessionCtx, shared.sess) if exit != 0 { sr.ExitCode = exit if p.options.AttachOnError { shared.box.RecoverInteractive( p.options.SourcePath(), shared.pipeline, step, ) } } else if err == nil { sr.Success = true sr.ExitCode = 0 } // Grab the message var message bytes.Buffer messageErr := step.CollectFile(shared.containerID, step.ReportPath(), "message.txt", &message) if messageErr != nil { if messageErr != util.ErrEmptyTarball { return sr, messageErr } } sr.Message = message.String() // This is the error from the step.Execute above if err != nil { if sr.Message == "" { sr.Message = err.Error() } return sr, err } // Grab artifacts if we want them if p.options.ShouldArtifacts { artifact, err := step.CollectArtifact(shared.containerID) if err != nil { return sr, err } if artifact != nil { artificer := dockerlocal.NewArtificer(p.options, p.dockerOptions) err = artificer.Upload(artifact) if err != nil { return sr, err } } sr.Artifact = artifact } if !sr.Success { return sr, fmt.Errorf("Step failed with exit code: %d", sr.ExitCode) } return sr, nil }