MCPcopy Index your code
hub / github.com/coder/coder / EnvInfo

Function EnvInfo

agent/agentcontainers/containers_dockercli.go:38–114  ·  view source on GitHub ↗

EnvInfo returns information about the environment of a container.

(ctx context.Context, execer agentexec.Execer, container, containerUser string)

Source from the content-addressed store, hash-verified

36
37// EnvInfo returns information about the environment of a container.
38func EnvInfo(ctx context.Context, execer agentexec.Execer, container, containerUser string) (*DockerEnvInfoer, error) {
39 var dei DockerEnvInfoer
40 dei.container = container
41
42 if containerUser == "" {
43 // Get the "default" user of the container if no user is specified.
44 // TODO: handle different container runtimes.
45 cmd, args := wrapDockerExec(container, "", "whoami")
46 stdout, stderr, err := run(ctx, execer, cmd, args...)
47 if err != nil {
48 return nil, xerrors.Errorf("get container user: run whoami: %w: %s", err, stderr)
49 }
50 if len(stdout) == 0 {
51 return nil, xerrors.Errorf("get container user: run whoami: empty output")
52 }
53 containerUser = stdout
54 }
55 // Now that we know the username, get the required info from the container.
56 // We can't assume the presence of `getent` so we'll just have to sniff /etc/passwd.
57 cmd, args := wrapDockerExec(container, containerUser, "cat", "/etc/passwd")
58 stdout, stderr, err := run(ctx, execer, cmd, args...)
59 if err != nil {
60 return nil, xerrors.Errorf("get container user: read /etc/passwd: %w: %q", err, stderr)
61 }
62
63 scanner := bufio.NewScanner(strings.NewReader(stdout))
64 var foundLine string
65 for scanner.Scan() {
66 line := strings.TrimSpace(scanner.Text())
67 if !strings.HasPrefix(line, containerUser+":") {
68 continue
69 }
70 foundLine = line
71 break
72 }
73 if err := scanner.Err(); err != nil {
74 return nil, xerrors.Errorf("get container user: scan /etc/passwd: %w", err)
75 }
76 if foundLine == "" {
77 return nil, xerrors.Errorf("get container user: no matching entry for %q found in /etc/passwd", containerUser)
78 }
79
80 // Parse the output of /etc/passwd. It looks like this:
81 // postgres:x:999:999::/var/lib/postgresql:/bin/bash
82 passwdFields := strings.Split(foundLine, ":")
83 if len(passwdFields) != 7 {
84 return nil, xerrors.Errorf("get container user: invalid line in /etc/passwd: %q", foundLine)
85 }
86
87 // The fifth entry in /etc/passwd contains GECOS information, which is a
88 // comma-separated list of fields. The first field is the user's full name.
89 gecos := strings.Split(passwdFields[4], ",")
90 fullName := ""
91 if len(gecos) > 1 {
92 fullName = gecos[0]
93 }
94
95 dei.user = &user.User{

Callers 4

handleConnMethod · 0.92
sessionStartMethod · 0.92
TestIntegrationDockerFunction · 0.92
TestDockerEnvInfoerFunction · 0.92

Calls 7

wrapDockerExecFunction · 0.85
devcontainerEnvFunction · 0.85
ErrMethod · 0.80
runFunction · 0.70
ErrorfMethod · 0.45
ScanMethod · 0.45
TextMethod · 0.45

Tested by 2

TestIntegrationDockerFunction · 0.74
TestDockerEnvInfoerFunction · 0.74