func cleanExistingContainer(t *testing.T, container string) { exists, err := docker.ContainerExists(container) if err != nil { t.Fatalf("Problem checking docker state; err: %v", err) } if exists { if result := docker.Stop(container, 0, true); result.Err != nil { t.Fatalf("Problem cleaning up the docker state; err: %v", result.Err) } } }
// startShipshapeService ensures that there is a service started with the given image and // attached analyzers that can analyze the directory at absRoot (an absolute path). If a // service is not started up that can do this, it will shut down the existing one and start // a new one. // The methods returns the (ready) client, the relative path from the docker container's mapped // volume to the absRoot that we are analyzing, and any errors from attempting to run the service. func startShipshapeService(image, absRoot string, analyzers []string, dind bool) (*client.Client, string, error) { glog.Infof("Starting shipshape...") container := "shipping_container" exists, err := docker.ContainerExists(container) if err != nil { return nil, "", err } var subPath string if !exists { result := docker.RunService(image, container, absRoot, localLogs, analyzers, dind) printStreams(result) if result.Err != nil { return nil, "", result.Err } subPath = "" } else { var isMapped bool // subPath is the relative path from the mapped volume on shipping container // to the directory we are analyzing (absRoot) isMapped, subPath = docker.MappedVolume(absRoot, container) // Stop and restart the container if: // 1: The container is not mapped to the right directory OR // 2: The container is not using the latest image OR // 3: The container is not linked to the right analyzer containers // Otherwise, use the existing container if !isMapped || !docker.ImageMatches(image, container) || !docker.ContainsLinks(container, analyzers) { glog.Infof("Restarting container with %s", image) stop(container, 0) result := docker.RunService(image, container, absRoot, localLogs, analyzers, dind) printStreams(result) if result.Err != nil { return nil, "", result.Err } subPath = "" } } glog.Infof("Image %s running in service mode", image) c := client.NewHTTPClient("localhost:10007") return c, subPath, c.WaitUntilReady(10 * time.Second) }
func (i *Invocation) Run() (int, error) { var c *client.Client var req *rpcpb.ShipshapeRequest var numNotes int // Run it on files c, paths, cleanup, err := i.startServices() defer cleanup() if err != nil { return 0, err } var files []string if !paths.fs.IsDir() { files = []string{filepath.Base(i.options.File)} } if len(i.options.TriggerCats) == 0 { glog.Infof("No categories provided. Will be using categories specified by the config file for the event %s", i.options.Event) } req = createRequest(i.options.TriggerCats, files, i.options.Event, filepath.Join(workspace, paths.relativeRoot), ctxpb.Stage_PRE_BUILD.Enum()) glog.Infof("Calling with request %v", req) numNotes, err = analyze(c, req, paths.origDir, i.options.HandleResponse) if err != nil { return numNotes, fmt.Errorf("error making service call: %v", err) } // If desired, generate compilation units with a kythe image if i.options.Build != "" { // TODO(ciera): Handle other build systems fullKytheImage := docker.FullImageName(i.options.Repo, kytheImage, i.options.Tag) if !i.options.LocalKythe { pull(fullKytheImage) } // Stop kythe if it is running otherwise we will fail when we start kythe below exists, err := docker.ContainerExists(fullKytheImage) if err != nil { return numNotes, fmt.Errorf("error making service call: %v", err) } if exists { stop(fullKytheImage, 0) } // Make sure we stop kythe after we are done defer stop("kythe", 10*time.Second) glog.Infof("Retrieving compilation units with %s", i.options.Build) result := docker.RunKythe(fullKytheImage, "kythe", paths.absRoot, i.options.Build, i.options.Dind) if result.Err != nil { // kythe spews output, so only capture it if something went wrong. printStreams(result) return numNotes, fmt.Errorf("error from run: %v", result.Err) } glog.Infoln("CompilationUnits prepared") req.Stage = ctxpb.Stage_POST_BUILD.Enum() glog.Infof("Calling with request %v", req) numBuildNotes, err := analyze(c, req, paths.origDir, i.options.HandleResponse) numNotes += numBuildNotes if err != nil { return numNotes, fmt.Errorf("error making service call: %v", err) } } if i.options.ResponsesDone != nil { if err := i.options.ResponsesDone(); err != nil { return numNotes, err } } glog.Infoln("End of Results.") return numNotes, nil }