go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/processes/dockertop.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package processes 5 6 import ( 7 "context" 8 "fmt" 9 "strconv" 10 11 "go.mondoo.com/cnquery/providers/os/connection" 12 "go.mondoo.com/cnquery/providers/os/connection/shared" 13 ) 14 15 type DockerTopManager struct { 16 conn shared.Connection 17 } 18 19 func (lpm *DockerTopManager) Name() string { 20 return "Docker Top Process Manager" 21 } 22 23 // List lists the processes running in a Docker container. Note that currently this function returns child 24 // processes as well. 25 func (lpm *DockerTopManager) List() ([]*OSProcess, error) { 26 dockerConn, ok := lpm.conn.(*connection.DockerContainerConnection) 27 if !ok { 28 return nil, fmt.Errorf("wrong transport type") 29 } 30 31 ctx := context.Background() 32 client := dockerConn.Client 33 34 // The Docker API uses ps underneath so we can provide any ps arguments we want here. 35 resp, err := client.ContainerTop(ctx, dockerConn.ContainerId(), []string{"-o", "pid,user,comm,s,command"}) 36 if err != nil { 37 return nil, err 38 } 39 40 // The docker API returns a list of strings for each process with the following format: 41 // [0]: PID 42 // [1]: USER 43 // [2]: executable 44 // [3]: state 45 // [4]: command 46 var procs []*OSProcess 47 for _, p := range resp.Processes { 48 pid, err := strconv.Atoi(p[0]) 49 if err != nil { 50 continue 51 } 52 procs = append(procs, &OSProcess{ 53 Pid: int64(pid), // This will be the PID inside the container 54 Executable: p[2], 55 Command: p[4], 56 State: p[3], 57 SocketInodes: nil, 58 }) 59 } 60 61 return procs, nil 62 } 63 64 // check that the pid directory exists 65 func (lpm *DockerTopManager) Exists(pid int64) (bool, error) { 66 procs, err := lpm.List() 67 if err != nil { 68 return false, err 69 } 70 71 for _, p := range procs { 72 if p.Pid == pid { 73 return true, nil 74 } 75 } 76 77 return false, nil 78 } 79 80 func (lpm *DockerTopManager) Process(pid int64) (*OSProcess, error) { 81 procs, err := lpm.List() 82 if err != nil { 83 return nil, err 84 } 85 86 for _, p := range procs { 87 if p.Pid == pid { 88 return p, nil 89 } 90 } 91 return nil, fmt.Errorf("process with PID %d does not exist", pid) 92 }