summaryrefslogtreecommitdiff
path: root/libpod/container_inspect.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_inspect.go')
-rw-r--r--libpod/container_inspect.go140
1 files changed, 125 insertions, 15 deletions
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
index 0a62ceb7c..3ac774060 100644
--- a/libpod/container_inspect.go
+++ b/libpod/container_inspect.go
@@ -1,8 +1,10 @@
package libpod
import (
+ "strings"
"time"
+ "github.com/containers/image/manifest"
"github.com/containers/libpod/libpod/driver"
"github.com/cri-o/ocicni/pkg/ocicni"
spec "github.com/opencontainers/runtime-spec/specs-go"
@@ -29,6 +31,7 @@ type InspectContainerData struct {
HostsPath string `json:"HostsPath"`
StaticDir string `json:"StaticDir"`
OCIConfigPath string `json:"OCIConfigPath,omitempty"`
+ OCIRuntime string `json:"OCIRuntime,omitempty"`
LogPath string `json:"LogPath"`
ConmonPidFile string `json:"ConmonPidFile"`
Name string `json:"Name"`
@@ -43,12 +46,59 @@ type InspectContainerData struct {
GraphDriver *driver.Data `json:"GraphDriver"`
SizeRw int64 `json:"SizeRw,omitempty"`
SizeRootFs int64 `json:"SizeRootFs,omitempty"`
- Mounts []*InspectMount `json:"Mounts"`
+ Mounts []InspectMount `json:"Mounts"`
Dependencies []string `json:"Dependencies"`
NetworkSettings *InspectNetworkSettings `json:"NetworkSettings"` //TODO
ExitCommand []string `json:"ExitCommand"`
Namespace string `json:"Namespace"`
IsInfra bool `json:"IsInfra"`
+ Config *InspectContainerConfig `json:"Config"`
+}
+
+// InspectContainerConfig holds further data about how a container was initially
+// configured.
+type InspectContainerConfig struct {
+ // Container hostname
+ Hostname string `json:"Hostname"`
+ // Container domain name - unused at present
+ DomainName string `json:"Domainname"`
+ // User the container was launched with
+ User string `json:"User"`
+ // Unused, at present
+ AttachStdin bool `json:"AttachStdin"`
+ // Unused, at present
+ AttachStdout bool `json:"AttachStdout"`
+ // Unused, at present
+ AttachStderr bool `json:"AttachStderr"`
+ // Whether the container creates a TTY
+ Tty bool `json:"Tty"`
+ // Whether the container leaves STDIN open
+ OpenStdin bool `json:"OpenStdin"`
+ // Whether STDIN is only left open once.
+ // Presently not supported by Podman, unused.
+ StdinOnce bool `json:"StdinOnce"`
+ // Container environment variables
+ Env []string `json:"Env"`
+ // Container command
+ Cmd []string `json:"Cmd"`
+ // Container image
+ Image string `json:"Image"`
+ // Unused, at present. I've never seen this field populated.
+ Volumes map[string]struct{} `json:"Volumes"`
+ // Container working directory
+ WorkingDir string `json:"WorkingDir"`
+ // Container entrypoint
+ Entrypoint string `json:"Entrypoint"`
+ // On-build arguments - presently unused. More of Buildah's domain.
+ OnBuild *string `json:"OnBuild"`
+ // Container labels
+ Labels map[string]string `json:"Labels"`
+ // Container annotations
+ Annotations map[string]string `json:"Annotations"`
+ // Container stop signal
+ StopSignal uint `json:"StopSignal"`
+ // Configured healthcheck for the container
+ Healthcheck *manifest.Schema2HealthConfig `json:"Healthcheck,omitempty"`
}
// InspectMount provides a record of a single mount in a container. It contains
@@ -61,10 +111,10 @@ type InspectMount struct {
// The name of the volume. Empty for bind mounts.
Name string `json:"Name,omptempty"`
// The source directory for the volume.
- Src string `json:"Source"`
+ Source string `json:"Source"`
// The destination directory for the volume. Specified as a path within
// the container, as it would be passed into the OCI runtime.
- Dst string `json:"Destination"`
+ Destination string `json:"Destination"`
// The driver used for the named volume. Empty for bind mounts.
Driver string `json:"Driver"`
// Contains SELinux :z/:Z mount options. Unclear what, if anything, else
@@ -192,7 +242,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
}
}
- mounts, err := c.getInspectMounts()
+ mounts, err := c.getInspectMounts(spec)
if err != nil {
return nil, err
}
@@ -225,6 +275,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
HostsPath: hostsPath,
StaticDir: config.StaticDir,
LogPath: config.LogPath,
+ OCIRuntime: config.OCIRuntime,
ConmonPidFile: config.ConmonPidFile,
Name: config.Name,
RestartCount: int32(runtimeInfo.RestartCount),
@@ -284,6 +335,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
// Get information on the container's network namespace (if present)
data = c.getContainerNetworkInfo(data)
+ inspectConfig, err := c.generateInspectContainerConfig(spec)
+ if err != nil {
+ return nil, err
+ }
+ data.Config = inspectConfig
+
if size {
rootFsSize, err := c.rootFsSize()
if err != nil {
@@ -302,8 +359,8 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data)
// Get inspect-formatted mounts list.
// Only includes user-specified mounts. Only includes bind mounts and named
// volumes, not tmpfs volumes.
-func (c *Container) getInspectMounts() ([]*InspectMount, error) {
- inspectMounts := []*InspectMount{}
+func (c *Container) getInspectMounts(ctrSpec *spec.Spec) ([]InspectMount, error) {
+ inspectMounts := []InspectMount{}
// No mounts, return early
if len(c.config.UserVolumes) == 0 {
@@ -319,7 +376,7 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) {
for _, namedVol := range c.config.NamedVolumes {
namedVolumes[namedVol.Dest] = namedVol
}
- for _, mount := range c.config.Spec.Mounts {
+ for _, mount := range ctrSpec.Mounts {
mounts[mount.Destination] = mount
}
@@ -327,9 +384,9 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) {
// We need to look up the volumes.
// First: is it a named volume?
if volume, ok := namedVolumes[vol]; ok {
- mountStruct := new(InspectMount)
+ mountStruct := InspectMount{}
mountStruct.Type = "volume"
- mountStruct.Dst = volume.Dest
+ mountStruct.Destination = volume.Dest
mountStruct.Name = volume.Name
// For src and driver, we need to look up the named
@@ -339,9 +396,9 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) {
return nil, errors.Wrapf(err, "error looking up volume %s in container %s config", volume.Name, c.ID())
}
mountStruct.Driver = volFromDB.Driver()
- mountStruct.Src = volFromDB.MountPoint()
+ mountStruct.Source = volFromDB.MountPoint()
- parseMountOptionsForInspect(volume.Options, mountStruct)
+ parseMountOptionsForInspect(volume.Options, &mountStruct)
inspectMounts = append(inspectMounts, mountStruct)
} else if mount, ok := mounts[vol]; ok {
@@ -351,12 +408,12 @@ func (c *Container) getInspectMounts() ([]*InspectMount, error) {
continue
}
- mountStruct := new(InspectMount)
+ mountStruct := InspectMount{}
mountStruct.Type = "bind"
- mountStruct.Src = mount.Source
- mountStruct.Dst = mount.Destination
+ mountStruct.Source = mount.Source
+ mountStruct.Destination = mount.Destination
- parseMountOptionsForInspect(mount.Options, mountStruct)
+ parseMountOptionsForInspect(mount.Options, &mountStruct)
inspectMounts = append(inspectMounts, mountStruct)
}
@@ -401,3 +458,56 @@ func parseMountOptionsForInspect(options []string, mount *InspectMount) {
mount.Mode = zZ
mount.Options = otherOpts
}
+
+// Generate the InspectContainerConfig struct for the Config field of Inspect.
+func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectContainerConfig, error) {
+ ctrConfig := new(InspectContainerConfig)
+
+ ctrConfig.Hostname = c.Hostname()
+ ctrConfig.User = c.config.User
+ if spec.Process != nil {
+ ctrConfig.Tty = spec.Process.Terminal
+ ctrConfig.Env = []string{}
+ for _, val := range spec.Process.Env {
+ ctrConfig.Env = append(ctrConfig.Env, val)
+ }
+ ctrConfig.WorkingDir = spec.Process.Cwd
+ }
+
+ ctrConfig.OpenStdin = c.config.Stdin
+ ctrConfig.Image = c.config.RootfsImageName
+
+ // Leave empty is not explicitly overwritten by user
+ if len(c.config.Command) != 0 {
+ ctrConfig.Cmd = []string{}
+ for _, val := range c.config.Command {
+ ctrConfig.Cmd = append(ctrConfig.Cmd, val)
+ }
+ }
+
+ // Leave empty if not explicitly overwritten by user
+ if len(c.config.Entrypoint) != 0 {
+ ctrConfig.Entrypoint = strings.Join(c.config.Entrypoint, " ")
+ }
+
+ if len(c.config.Labels) != 0 {
+ ctrConfig.Labels = make(map[string]string)
+ for k, v := range c.config.Labels {
+ ctrConfig.Labels[k] = v
+ }
+ }
+
+ if len(spec.Annotations) != 0 {
+ ctrConfig.Annotations = make(map[string]string)
+ for k, v := range spec.Annotations {
+ ctrConfig.Annotations[k] = v
+ }
+ }
+
+ ctrConfig.StopSignal = c.config.StopSignal
+ // TODO: should JSON deep copy this to ensure internal pointers don't
+ // leak.
+ ctrConfig.Healthcheck = c.config.HealthCheckConfig
+
+ return ctrConfig, nil
+}