Example #1
0
func TestTree(t *testing.T) {
	oldWalk := process.Walk
	defer func() { process.Walk = oldWalk }()

	process.Walk = func(_ string, f func(*process.Process)) error {
		for _, p := range []*process.Process{
			{PID: 1, PPID: 0},
			{PID: 2, PPID: 1},
			{PID: 3, PPID: 1},
			{PID: 4, PPID: 2},
		} {
			f(p)
		}
		return nil
	}

	tree, err := process.NewTree("foo")
	if err != nil {
		t.Fatalf("newProcessTree error: %v", err)
	}

	for pid, want := range map[int]int{2: 1, 3: 1, 4: 2} {
		have, err := tree.GetParent(pid)
		if err != nil || !reflect.DeepEqual(want, have) {
			t.Errorf("%d: want %#v, have %#v (%v)", pid, want, have, err)
		}
	}
}
Example #2
0
func (t *tracer) pidsForContainer(id string) ([]int, error) {
	var container docker.Container
	t.docker.WalkContainers(func(c docker.Container) {
		if c.ID() == id {
			container = c
		}
	})

	if container == nil {
		return []int{}, fmt.Errorf("Not Found")
	}

	pidTree, err := process.NewTree(process.NewWalker("/proc"))
	if err != nil {
		return []int{}, err
	}

	return pidTree.GetChildren(container.PID())
}
Example #3
0
func TestTree(t *testing.T) {
	walker := &mockWalker{
		processes: []process.Process{
			{PID: 1, PPID: 0, Comm: "init"},
			{PID: 2, PPID: 1, Comm: "bash"},
			{PID: 3, PPID: 1, Comm: "apache", Threads: 2},
			{PID: 4, PPID: 2, Comm: "ping", Cmdline: "ping foo.bar.local"},
		},
	}

	tree, err := process.NewTree(walker)
	if err != nil {
		t.Fatalf("newProcessTree error: %v", err)
	}

	for pid, want := range map[int]int{2: 1, 3: 1, 4: 2} {
		have, err := tree.GetParent(pid)
		if err != nil || !reflect.DeepEqual(want, have) {
			t.Errorf("%d: want %#v, have %#v (%v)", pid, want, have, err)
		}
	}
}
Example #4
0
func (t *tracer) http(port int) {
	router := mux.NewRouter()

	router.Methods("GET").Path("/container").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		pidTree, err := process.NewTree(process.NewWalker("/proc"))
		if err != nil {
			respondWith(w, http.StatusBadRequest, err.Error())
			return
		}

		containers := []Container{}
		t.docker.WalkContainers(func(container docker.Container) {
			children, _ := pidTree.GetChildren(container.PID())
			out := Container{
				Name: strings.TrimPrefix(container.Container().Name, "/"),
				ID:   container.ID(),
				PIDs: children,
			}
			containers = append(containers, out)
		})

		respondWith(w, http.StatusOK, containers)
	})

	router.Methods("POST").Path("/container/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		id := mux.Vars(r)["id"]
		children, err := t.pidsForContainer(id)
		if err != nil {
			respondWith(w, http.StatusBadRequest, err.Error())
			return
		}

		for _, pid := range children {
			t.ptrace.TraceProcess(pid)
		}
		w.WriteHeader(204)
	})

	router.Methods("DELETE").Path("/container/{id}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		id := mux.Vars(r)["id"]
		children, err := t.pidsForContainer(id)
		if err != nil {
			respondWith(w, http.StatusBadRequest, err.Error())
			return
		}

		for _, pid := range children {
			t.ptrace.StopTracing(pid)
		}
		w.WriteHeader(204)
	})

	router.Methods("GET").Path("/pid").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		respondWith(w, http.StatusOK, t.ptrace.AttachedPIDs())
	})

	router.Methods("POST").Path("/pid/{pid:\\d+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		pid, err := strconv.Atoi(mux.Vars(r)["pid"])
		if err != nil {
			respondWith(w, http.StatusBadRequest, err.Error())
			return
		}

		t.ptrace.TraceProcess(pid)
		w.WriteHeader(204)
	})

	router.Methods("DELETE").Path("/pid/{pid:\\d+}").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		pid, err := strconv.Atoi(mux.Vars(r)["pid"])
		if err != nil {
			respondWith(w, http.StatusBadRequest, err.Error())
			return
		}

		t.ptrace.StopTracing(pid)
		w.WriteHeader(204)
	})

	router.Methods("GET").Path("/traces").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		respondWith(w, http.StatusOK, t.store.Traces())
	})

	mime.AddExtensionType(".svg", "image/svg+xml")

	router.Methods("GET").PathPrefix("/").Handler(http.FileServer(FS(false))) // everything else is static

	log.Printf("Launching HTTP API on port %d", port)
	srv := &http.Server{
		Addr:    fmt.Sprintf(":%d", port),
		Handler: router,
	}

	if err := srv.ListenAndServe(); err != nil {
		log.Printf("Unable to create http listener: %v", err)
	}
}