diff options
Diffstat (limited to 'libpod/container_inspect.go')
-rw-r--r-- | libpod/container_inspect.go | 140 |
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 +} |