// retrieveResultsAndRemoveContainer copies the test.results file out of the Docker container and into // the expected location. It then removes the container. func retrieveResultsAndRemoveContainer(target *core.BuildTarget, containerFile string, warn bool) { cid, err := ioutil.ReadFile(containerFile) if err != nil { log.Warning("Failed to read Docker container file %s", containerFile) return } if !target.NoTestOutput { retrieveFile(target, cid, "test.results", warn) } if core.State.NeedCoverage { retrieveFile(target, cid, "test.coverage", false) } for _, output := range target.TestOutputs { retrieveFile(target, cid, output, false) } // Give this some time to complete. Processes inside the container might not be ready // to shut down immediately. timeout := core.State.Config.Docker.RemoveTimeout for i := 0; i < 5; i++ { cmd := []string{"docker", "rm", "-f", string(cid)} if _, err := core.ExecWithTimeoutSimple(timeout, cmd...); err == nil { return } time.Sleep(100 * time.Millisecond) } }
// retrieveFile retrieves a single file (or directory) from a Docker container. func retrieveFile(target *core.BuildTarget, cid []byte, filename string, warn bool) { log.Debug("Attempting to retrieve file %s for %s...", filename, target.Label) timeout := core.State.Config.Docker.ResultsTimeout cmd := []string{"docker", "cp", string(cid) + ":/tmp/test/" + filename, target.TestDir()} if out, err := core.ExecWithTimeoutSimple(timeout, cmd...); err != nil { if warn { log.Warning("Failed to retrieve results for %s: %s [%s]", target.Label, err, out) } else { log.Debug("Failed to retrieve results for %s: %s [%s]", target.Label, err, out) } } }