Skip to content

Commit ec7eb59

Browse files
committed
cmd/run, pkg/podman: Make podman.InspectContainer() return a Container
Unmarshal the JSON from 'podman inspect --format json --type container' directly inside podman.InspectContainer() to confine the details within the podman package. The JSON samples for the unit tests were taken using the default Toolbx container on versions of Fedora that shipped a specific Podman and Toolbx version. This accounts for differences in the JSON caused by different major versions of Podman and the way different Toolbx versions set up the containers. One exception was Fedora 28, which had Podman 1.1.2 and Toolbx 0.0.9, which was the last Toolbx version before 'toolbox init-container' became the entry point for all Toolbx containers [1]. However, the default Toolbx image is no longer available from registry.fedoraproject.org. Hence, the image for Fedora 29 was used. The minimum required Podman version is 1.6.4 [2], and the Go implementation has been encouraging users to create containers with Toolbx version 0.0.17 or newer [3]. The versions used to collect the JSON samples for the unit tests were chosen accordingly. They don't exhaustively cover all possible supported and unsupported version combinations, but hopefully enough to be useful. [1] Commit 8b84b5e containers@8b84b5e4604921fa https://github.com/debarshiray/toolbox/pull/160 [2] Commit 8e80dd5 containers@8e80dd5db1e6f40b containers#1253 [3] Commit 238f245 containers@238f2451e7d7d54a containers#318 containers#1490
1 parent e611969 commit ec7eb59

File tree

6 files changed

+2390
-35
lines changed

6 files changed

+2390
-35
lines changed

.codespellexcludefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
{"/var/lib/flatpak", "/run/host/var/lib/flatpak", "ro"},
1414
{"/var/lib/systemd/coredump", "/run/host/var/lib/systemd/coredump", "ro"},
1515
{"/var/log/journal", "/run/host/var/log/journal", "ro"},
16+
" \"ro\"," +

src/cmd/run.go

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -433,17 +433,16 @@ func runHelp(cmd *cobra.Command, args []string) {
433433
func callFlatpakSessionHelper(container string) error {
434434
logrus.Debugf("Inspecting mounts of container %s", container)
435435

436-
info, err := podman.InspectContainer(container)
436+
containerObj, err := podman.InspectContainer(container)
437437
if err != nil {
438438
return fmt.Errorf("failed to inspect entry point of container %s", container)
439439
}
440440

441441
var needsFlatpakSessionHelper bool
442442

443-
mounts := info["Mounts"].([]interface{})
443+
mounts := containerObj.Mounts()
444444
for _, mount := range mounts {
445-
destination := mount.(map[string]interface{})["Destination"].(string)
446-
if destination == "/run/host/monitor" {
445+
if mount == "/run/host/monitor" {
447446
logrus.Debug("Requires org.freedesktop.Flatpak.SessionHelper")
448447
needsFlatpakSessionHelper = true
449448
break
@@ -526,30 +525,17 @@ func constructExecArgs(container, preserveFDs string,
526525
func getEntryPointAndPID(container string) (string, int, error) {
527526
logrus.Debugf("Inspecting entry point of container %s", container)
528527

529-
info, err := podman.InspectContainer(container)
528+
containerObj, err := podman.InspectContainer(container)
530529
if err != nil {
531530
return "", 0, fmt.Errorf("failed to inspect entry point of container %s", container)
532531
}
533532

534-
config := info["Config"].(map[string]interface{})
535-
entryPoint := config["Cmd"].([]interface{})[0].(string)
533+
entryPoint := containerObj.EntryPoint()
534+
entryPointPID := containerObj.EntryPointPID()
536535

537-
state := info["State"].(map[string]interface{})
538-
entryPointPID := state["Pid"]
539-
logrus.Debugf("Entry point PID is a %T", entryPointPID)
536+
logrus.Debugf("Entry point of container %s is %s (PID=%d)", container, entryPoint, entryPointPID)
540537

541-
var entryPointPIDInt int
542-
543-
switch entryPointPID := entryPointPID.(type) {
544-
case float64:
545-
entryPointPIDInt = int(entryPointPID)
546-
default:
547-
return "", 0, fmt.Errorf("failed to inspect entry point PID of container %s", container)
548-
}
549-
550-
logrus.Debugf("Entry point of container %s is %s (PID=%d)", container, entryPoint, entryPointPIDInt)
551-
552-
return entryPoint, entryPointPIDInt, nil
538+
return entryPoint, entryPointPID, nil
553539
}
554540

555541
func isCommandPresent(container, command string) (bool, error) {

src/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ sources = files(
2323
'pkg/podman/container.go',
2424
'pkg/podman/errors.go',
2525
'pkg/podman/podman.go',
26+
'pkg/podman/containerInspect_test.go',
2627
'pkg/shell/shell.go',
2728
'pkg/shell/shell_test.go',
2829
'pkg/skopeo/skopeo.go',

src/pkg/podman/container.go

Lines changed: 134 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,38 +18,152 @@ package podman
1818

1919
import (
2020
"encoding/json"
21+
"time"
2122

2223
"github.com/containers/toolbox/pkg/utils"
2324
)
2425

2526
type Container interface {
2627
Created() string
28+
EntryPoint() string
29+
EntryPointPID() int
2730
ID() string
2831
Image() string
2932
Labels() map[string]string
33+
Mounts() []string
3034
Name() string
3135
Names() []string
3236
Status() string
3337
}
3438

39+
type containerInspect struct {
40+
created string
41+
entryPoint string
42+
entryPointPID int
43+
id string
44+
image string
45+
labels map[string]string
46+
mounts []string
47+
name string
48+
status string
49+
}
50+
3551
type containerPS struct {
36-
created string
37-
id string
38-
image string
39-
labels map[string]string
40-
names []string
41-
status string
52+
created string
53+
entryPoint string
54+
entryPointPID int
55+
id string
56+
image string
57+
labels map[string]string
58+
mounts []string
59+
names []string
60+
status string
4261
}
4362

4463
type Containers struct {
4564
data []containerPS
4665
i int
4766
}
4867

68+
func (container *containerInspect) Created() string {
69+
return container.created
70+
}
71+
72+
func (container *containerInspect) EntryPoint() string {
73+
return container.entryPoint
74+
}
75+
76+
func (container *containerInspect) EntryPointPID() int {
77+
return container.entryPointPID
78+
}
79+
80+
func (container *containerInspect) ID() string {
81+
return container.id
82+
}
83+
84+
func (container *containerInspect) Image() string {
85+
return container.image
86+
}
87+
88+
func (container *containerInspect) Labels() map[string]string {
89+
return container.labels
90+
}
91+
92+
func (container *containerInspect) Mounts() []string {
93+
return container.mounts
94+
}
95+
96+
func (container *containerInspect) Name() string {
97+
return container.name
98+
}
99+
100+
func (container *containerInspect) Names() []string {
101+
return []string{container.name}
102+
}
103+
104+
func (container *containerInspect) Status() string {
105+
return container.status
106+
}
107+
108+
func (container *containerInspect) UnmarshalJSON(data []byte) error {
109+
var raw struct {
110+
Config struct {
111+
Cmd []string
112+
Labels map[string]string
113+
}
114+
Created time.Time
115+
ID string
116+
ImageName string
117+
Mounts []struct {
118+
Destination string
119+
}
120+
Name string
121+
State struct {
122+
PID int
123+
Status string
124+
}
125+
}
126+
127+
if err := json.Unmarshal(data, &raw); err != nil {
128+
return err
129+
}
130+
131+
if len(raw.Config.Cmd) > 0 {
132+
container.entryPoint = raw.Config.Cmd[0]
133+
}
134+
135+
container.entryPointPID = raw.State.PID
136+
137+
created := raw.Created.Unix()
138+
container.created = utils.HumanDuration(created)
139+
140+
container.id = raw.ID
141+
container.image = raw.ImageName
142+
container.labels = raw.Config.Labels
143+
144+
for _, mount := range raw.Mounts {
145+
if mount.Destination != "" {
146+
container.mounts = append(container.mounts, mount.Destination)
147+
}
148+
}
149+
150+
container.name = raw.Name
151+
container.status = raw.State.Status
152+
return nil
153+
}
154+
49155
func (container *containerPS) Created() string {
50156
return container.created
51157
}
52158

159+
func (container *containerPS) EntryPoint() string {
160+
return container.entryPoint
161+
}
162+
163+
func (container *containerPS) EntryPointPID() int {
164+
return container.entryPointPID
165+
}
166+
53167
func (container *containerPS) ID() string {
54168
return container.id
55169
}
@@ -62,6 +176,10 @@ func (container *containerPS) Labels() map[string]string {
62176
return container.labels
63177
}
64178

179+
func (container *containerPS) Mounts() []string {
180+
return container.mounts
181+
}
182+
65183
func (container *containerPS) Name() string {
66184
return container.names[0]
67185
}
@@ -76,11 +194,14 @@ func (container *containerPS) Status() string {
76194

77195
func (container *containerPS) UnmarshalJSON(data []byte) error {
78196
var raw struct {
197+
Command []string
79198
Created interface{}
80199
ID string
81200
Image string
82201
Labels map[string]string
202+
Mounts []string
83203
Names interface{}
204+
PID int
84205
State interface{}
85206
Status string
86207
}
@@ -89,6 +210,12 @@ func (container *containerPS) UnmarshalJSON(data []byte) error {
89210
return err
90211
}
91212

213+
if len(raw.Command) > 0 {
214+
container.entryPoint = raw.Command[0]
215+
}
216+
217+
container.entryPointPID = raw.PID
218+
92219
// In Podman V1 the field 'Created' held a human-readable string in format
93220
// "5 minutes ago". Since Podman V2 the field holds an integer with Unix time.
94221
// After a discussion in https://github.com/containers/podman/issues/6594 the
@@ -106,6 +233,7 @@ func (container *containerPS) UnmarshalJSON(data []byte) error {
106233
container.id = raw.ID
107234
container.image = raw.Image
108235
container.labels = raw.Labels
236+
container.mounts = raw.Mounts
109237

110238
// In Podman V1 the field 'Names' held a single string but since Podman V2 the
111239
// field holds an array of strings

0 commit comments

Comments
 (0)