Skip to content

Commit 80ac9a3

Browse files
committed
chore(agent/agentcontainers): refactor runDockerInspect and convertDockerInspect
1 parent 4987de6 commit 80ac9a3

File tree

1 file changed

+69
-61
lines changed

1 file changed

+69
-61
lines changed

agent/agentcontainers/containers_dockercli.go

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -162,23 +162,28 @@ func (dei *DockerEnvInfoer) ModifyCommand(cmd string, args ...string) (string, [
162162
// devcontainerEnv is a helper function that inspects the container labels to
163163
// find the required environment variables for running a command in the container.
164164
func devcontainerEnv(ctx context.Context, execer agentexec.Execer, container string) ([]string, error) {
165-
ins, stderr, err := runDockerInspect(ctx, execer, container)
165+
stdout, stderr, err := runDockerInspect(ctx, execer, container)
166166
if err != nil {
167167
return nil, xerrors.Errorf("inspect container: %w: %q", err, stderr)
168168
}
169169

170+
ins, _, err := convertDockerInspect(stdout)
171+
if err != nil {
172+
return nil, xerrors.Errorf("inspect container: %w", err)
173+
}
174+
170175
if len(ins) != 1 {
171176
return nil, xerrors.Errorf("inspect container: expected 1 container, got %d", len(ins))
172177
}
173178

174179
in := ins[0]
175-
if in.Config.Labels == nil {
180+
if in.Labels == nil {
176181
return nil, nil
177182
}
178183

179184
// We want to look for the devcontainer metadata, which is in the
180185
// value of the label `devcontainer.metadata`.
181-
rawMeta, ok := in.Config.Labels["devcontainer.metadata"]
186+
rawMeta, ok := in.Labels["devcontainer.metadata"]
182187
if !ok {
183188
return nil, nil
184189
}
@@ -279,42 +284,36 @@ func (dcl *DockerCLILister) List(ctx context.Context) (codersdk.WorkspaceAgentLi
279284
return codersdk.WorkspaceAgentListContainersResponse{}, xerrors.Errorf("run docker inspect: %w", err)
280285
}
281286

282-
for _, in := range ins {
283-
out, warns := convertDockerInspect(in)
284-
res.Warnings = append(res.Warnings, warns...)
285-
res.Containers = append(res.Containers, out)
286-
}
287-
288-
if dockerPsStderr != "" {
289-
res.Warnings = append(res.Warnings, dockerPsStderr)
290-
}
291287
if dockerInspectStderr != "" {
292288
res.Warnings = append(res.Warnings, dockerInspectStderr)
293289
}
294290

291+
outs, warns, err := convertDockerInspect(ins)
292+
if err != nil {
293+
return codersdk.WorkspaceAgentListContainersResponse{}, xerrors.Errorf("convert docker inspect output: %w", err)
294+
}
295+
res.Warnings = append(res.Warnings, warns...)
296+
res.Containers = append(res.Containers, outs...)
297+
295298
return res, nil
296299
}
297300

298301
// runDockerInspect is a helper function that runs `docker inspect` on the given
299302
// container IDs and returns the parsed output.
300303
// The stderr output is also returned for logging purposes.
301-
func runDockerInspect(ctx context.Context, execer agentexec.Execer, ids ...string) ([]dockerInspect, string, error) {
304+
func runDockerInspect(ctx context.Context, execer agentexec.Execer, ids ...string) (stdout, stderr string, err error) {
302305
var stdoutBuf, stderrBuf bytes.Buffer
303306
cmd := execer.CommandContext(ctx, "docker", append([]string{"inspect"}, ids...)...)
304307
cmd.Stdout = &stdoutBuf
305308
cmd.Stderr = &stderrBuf
306-
err := cmd.Run()
307-
stderr := strings.TrimSpace(stderrBuf.String())
309+
err = cmd.Run()
310+
stdout = strings.TrimSpace(stdoutBuf.String())
311+
stderr = strings.TrimSpace(stderrBuf.String())
308312
if err != nil {
309-
return nil, stderr, err
313+
return stdout, stderr, err
310314
}
311315

312-
var ins []dockerInspect
313-
if err := json.NewDecoder(&stdoutBuf).Decode(&ins); err != nil {
314-
return nil, stderr, xerrors.Errorf("decode docker inspect output: %w", err)
315-
}
316-
317-
return ins, stderr, nil
316+
return stdoutBuf.String(), stderr, nil
318317
}
319318

320319
// To avoid a direct dependency on the Docker API, we use the docker CLI
@@ -367,50 +366,59 @@ func (dis dockerInspectState) String() string {
367366
return sb.String()
368367
}
369368

370-
func convertDockerInspect(in dockerInspect) (codersdk.WorkspaceAgentDevcontainer, []string) {
369+
func convertDockerInspect(raw string) ([]codersdk.WorkspaceAgentDevcontainer, []string, error) {
371370
var warns []string
372-
out := codersdk.WorkspaceAgentDevcontainer{
373-
CreatedAt: in.Created,
374-
// Remove the leading slash from the container name
375-
FriendlyName: strings.TrimPrefix(in.Name, "/"),
376-
ID: in.ID,
377-
Image: in.Config.Image,
378-
Labels: in.Config.Labels,
379-
Ports: make([]codersdk.WorkspaceAgentListeningPort, 0),
380-
Running: in.State.Running,
381-
Status: in.State.String(),
382-
Volumes: make(map[string]string, len(in.Mounts)),
383-
}
384-
385-
if in.HostConfig.PortBindings == nil {
386-
in.HostConfig.PortBindings = make(map[string]any)
387-
}
388-
portKeys := maps.Keys(in.HostConfig.PortBindings)
389-
// Sort the ports for deterministic output.
390-
sort.Strings(portKeys)
391-
for _, p := range portKeys {
392-
if port, network, err := convertDockerPort(p); err != nil {
393-
warns = append(warns, err.Error())
394-
} else {
395-
out.Ports = append(out.Ports, codersdk.WorkspaceAgentListeningPort{
396-
Network: network,
397-
Port: port,
398-
})
399-
}
371+
var ins []dockerInspect
372+
if err := json.NewDecoder(strings.NewReader(raw)).Decode(&ins); err != nil {
373+
return nil, nil, xerrors.Errorf("decode docker inspect output: %w", err)
400374
}
375+
outs := make([]codersdk.WorkspaceAgentDevcontainer, 0, len(ins))
401376

402-
if in.Mounts == nil {
403-
in.Mounts = []dockerInspectMount{}
404-
}
405-
// Sort the mounts for deterministic output.
406-
sort.Slice(in.Mounts, func(i, j int) bool {
407-
return in.Mounts[i].Source < in.Mounts[j].Source
408-
})
409-
for _, k := range in.Mounts {
410-
out.Volumes[k.Source] = k.Destination
377+
for _, in := range ins {
378+
out := codersdk.WorkspaceAgentDevcontainer{
379+
CreatedAt: in.Created,
380+
// Remove the leading slash from the container name
381+
FriendlyName: strings.TrimPrefix(in.Name, "/"),
382+
ID: in.ID,
383+
Image: in.Config.Image,
384+
Labels: in.Config.Labels,
385+
Ports: make([]codersdk.WorkspaceAgentListeningPort, 0),
386+
Running: in.State.Running,
387+
Status: in.State.String(),
388+
Volumes: make(map[string]string, len(in.Mounts)),
389+
}
390+
391+
if in.HostConfig.PortBindings == nil {
392+
in.HostConfig.PortBindings = make(map[string]any)
393+
}
394+
portKeys := maps.Keys(in.HostConfig.PortBindings)
395+
// Sort the ports for deterministic output.
396+
sort.Strings(portKeys)
397+
for _, p := range portKeys {
398+
if port, network, err := convertDockerPort(p); err != nil {
399+
warns = append(warns, err.Error())
400+
} else {
401+
out.Ports = append(out.Ports, codersdk.WorkspaceAgentListeningPort{
402+
Network: network,
403+
Port: port,
404+
})
405+
}
406+
}
407+
408+
if in.Mounts == nil {
409+
in.Mounts = []dockerInspectMount{}
410+
}
411+
// Sort the mounts for deterministic output.
412+
sort.Slice(in.Mounts, func(i, j int) bool {
413+
return in.Mounts[i].Source < in.Mounts[j].Source
414+
})
415+
for _, k := range in.Mounts {
416+
out.Volumes[k.Source] = k.Destination
417+
}
418+
outs = append(outs, out)
411419
}
412420

413-
return out, warns
421+
return outs, warns, nil
414422
}
415423

416424
// convertDockerPort converts a Docker port string to a port number and network

0 commit comments

Comments
 (0)