diff options
author | Brent Baude <bbaude@redhat.com> | 2020-03-26 13:37:09 -0500 |
---|---|---|
committer | Brent Baude <bbaude@redhat.com> | 2020-03-26 15:54:26 -0500 |
commit | 2fa78938a94e90e41755b68dd1af36f5b817ed55 (patch) | |
tree | f6a1161387751d8a413c0ebe66ba253f4a91a1af | |
parent | 6a46a87d08bd1e9ddda3dd3c9c30d21d2226a654 (diff) | |
download | podman-2fa78938a94e90e41755b68dd1af36f5b817ed55.tar.gz podman-2fa78938a94e90e41755b68dd1af36f5b817ed55.tar.bz2 podman-2fa78938a94e90e41755b68dd1af36f5b817ed55.zip |
podmanv2 container inspect
add ability to inspect a container
Signed-off-by: Brent Baude <bbaude@redhat.com>
-rw-r--r-- | cmd/podmanV2/containers/inspect.go | 53 | ||||
-rw-r--r-- | libpod/container_inspect.go | 652 | ||||
-rw-r--r-- | libpod/define/container_inspect.go | 624 | ||||
-rw-r--r-- | libpod/healthcheck.go | 32 | ||||
-rw-r--r-- | libpod/networking_linux.go | 12 | ||||
-rw-r--r-- | libpod/networking_unsupported.go | 2 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/swagger.go | 3 | ||||
-rw-r--r-- | pkg/api/server/swagger.go | 3 | ||||
-rw-r--r-- | pkg/bindings/containers/containers.go | 5 | ||||
-rw-r--r-- | pkg/bindings/containers/healthcheck.go | 6 | ||||
-rw-r--r-- | pkg/domain/entities/containers.go | 10 | ||||
-rw-r--r-- | pkg/domain/entities/engine_container.go | 1 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 16 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 18 | ||||
-rw-r--r-- | test/e2e/common_test.go | 7 |
16 files changed, 767 insertions, 681 deletions
diff --git a/cmd/podmanV2/containers/inspect.go b/cmd/podmanV2/containers/inspect.go index 635be4789..648289f0b 100644 --- a/cmd/podmanV2/containers/inspect.go +++ b/cmd/podmanV2/containers/inspect.go @@ -1,8 +1,15 @@ package containers import ( + "context" + "fmt" + "os" + "strings" + "text/template" + "github.com/containers/libpod/cmd/podmanV2/registry" "github.com/containers/libpod/pkg/domain/entities" + jsoniter "github.com/json-iterator/go" "github.com/spf13/cobra" ) @@ -12,31 +19,57 @@ var ( Use: "inspect [flags] CONTAINER", Short: "Display the configuration of a container", Long: `Displays the low-level information on a container identified by name or ID.`, - PreRunE: inspectPreRunE, + PreRunE: preRunE, RunE: inspect, Example: `podman container inspect myCtr podman container inspect -l --format '{{.Id}} {{.Config.Labels}}'`, } ) +var ( + inspectOptions entities.ContainerInspectOptions +) + func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: inspectCmd, Parent: containerCmd, }) -} - -func inspectPreRunE(cmd *cobra.Command, args []string) (err error) { - err = preRunE(cmd, args) - if err != nil { - return + flags := inspectCmd.Flags() + flags.StringVarP(&inspectOptions.Format, "format", "f", "", "Change the output format to a Go template") + flags.BoolVarP(&inspectOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") + flags.BoolVarP(&inspectOptions.Size, "size", "s", false, "Display total file size") + if registry.IsRemote() { + _ = flags.MarkHidden("latest") } - - _, err = registry.NewImageEngine(cmd, args) - return err } func inspect(cmd *cobra.Command, args []string) error { + responses, err := registry.ContainerEngine().ContainerInspect(context.Background(), args, inspectOptions) + if err != nil { + return err + } + if inspectOptions.Format == "" { + b, err := jsoniter.MarshalIndent(responses, "", " ") + if err != nil { + return err + } + fmt.Println(string(b)) + return nil + } + format := inspectOptions.Format + if !strings.HasSuffix(format, "\n") { + format += "\n" + } + tmpl, err := template.New("inspect").Parse(format) + if err != nil { + return err + } + for _, i := range responses { + if err := tmpl.Execute(os.Stdout, i); err != nil { + return err + } + } return nil } diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 50ae72499..7552eb483 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -3,13 +3,10 @@ package libpod import ( "fmt" "strings" - "time" - "github.com/containers/image/v5/manifest" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/driver" "github.com/containers/libpod/pkg/util" - "github.com/cri-o/ocicni/pkg/ocicni" spec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/runtime-tools/validate" @@ -85,602 +82,9 @@ const ( InspectResponseFalse = "FALSE" ) -// InspectContainerData provides a detailed record of a container's configuration -// and state as viewed by Libpod. -// Large portions of this structure are defined such that the output is -// compatible with `docker inspect` JSON, but additional fields have been added -// as required to share information not in the original output. -type InspectContainerData struct { - ID string `json:"Id"` - Created time.Time `json:"Created"` - Path string `json:"Path"` - Args []string `json:"Args"` - State *InspectContainerState `json:"State"` - Image string `json:"Image"` - ImageName string `json:"ImageName"` - Rootfs string `json:"Rootfs"` - Pod string `json:"Pod"` - ResolvConfPath string `json:"ResolvConfPath"` - HostnamePath string `json:"HostnamePath"` - HostsPath string `json:"HostsPath"` - StaticDir string `json:"StaticDir"` - OCIConfigPath string `json:"OCIConfigPath,omitempty"` - OCIRuntime string `json:"OCIRuntime,omitempty"` - LogPath string `json:"LogPath"` - LogTag string `json:"LogTag"` - ConmonPidFile string `json:"ConmonPidFile"` - Name string `json:"Name"` - RestartCount int32 `json:"RestartCount"` - Driver string `json:"Driver"` - MountLabel string `json:"MountLabel"` - ProcessLabel string `json:"ProcessLabel"` - AppArmorProfile string `json:"AppArmorProfile"` - EffectiveCaps []string `json:"EffectiveCaps"` - BoundingCaps []string `json:"BoundingCaps"` - ExecIDs []string `json:"ExecIDs"` - GraphDriver *driver.Data `json:"GraphDriver"` - SizeRw *int64 `json:"SizeRw,omitempty"` - SizeRootFs int64 `json:"SizeRootFs,omitempty"` - 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"` - HostConfig *InspectContainerHostConfig `json:"HostConfig"` -} - -// 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"` - // CreateCommand is the full command plus arguments of the process the - // container has been created with. - CreateCommand []string `json:"CreateCommand,omitempty"` -} - -// InspectContainerHostConfig holds information used when the container was -// created. -// It's very much a Docker-specific struct, retained (mostly) as-is for -// compatibility. We fill individual fields as best as we can, inferring as much -// as possible from the spec and container config. -// Some things cannot be inferred. These will be populated by spec annotations -// (if available). -// Field names are fixed for compatibility and cannot be changed. -// As such, silence lint warnings about them. -//nolint -type InspectContainerHostConfig struct { - // Binds contains an array of user-added mounts. - // Both volume mounts and named volumes are included. - // Tmpfs mounts are NOT included. - // In 'docker inspect' this is separated into 'Binds' and 'Mounts' based - // on how a mount was added. We do not make this distinction and do not - // include a Mounts field in inspect. - // Format: <src>:<destination>[:<comma-separated options>] - Binds []string `json:"Binds"` - // ContainerIDFile is a file created during container creation to hold - // the ID of the created container. - // This is not handled within libpod and is stored in an annotation. - ContainerIDFile string `json:"ContainerIDFile"` - // LogConfig contains information on the container's logging backend - LogConfig *InspectLogConfig `json:"LogConfig"` - // NetworkMode is the configuration of the container's network - // namespace. - // Populated as follows: - // default - A network namespace is being created and configured via CNI - // none - A network namespace is being created, not configured via CNI - // host - No network namespace created - // container:<id> - Using another container's network namespace - // ns:<path> - A path to a network namespace has been specified - NetworkMode string `json:"NetworkMode"` - // PortBindings contains the container's port bindings. - // It is formatted as map[string][]InspectHostPort. - // The string key here is formatted as <integer port number>/<protocol> - // and represents the container port. A single container port may be - // bound to multiple host ports (on different IPs). - PortBindings map[string][]InspectHostPort `json:"PortBindings"` - // RestartPolicy contains the container's restart policy. - RestartPolicy *InspectRestartPolicy `json:"RestartPolicy"` - // AutoRemove is whether the container will be automatically removed on - // exiting. - // It is not handled directly within libpod and is stored in an - // annotation. - AutoRemove bool `json:"AutoRemove"` - // VolumeDriver is presently unused and is retained for Docker - // compatibility. - VolumeDriver string `json:"VolumeDriver"` - // VolumesFrom is a list of containers which this container uses volumes - // from. This is not handled directly within libpod and is stored in an - // annotation. - // It is formatted as an array of container names and IDs. - VolumesFrom []string `json:"VolumesFrom"` - // CapAdd is a list of capabilities added to the container. - // It is not directly stored by Libpod, and instead computed from the - // capabilities listed in the container's spec, compared against a set - // of default capabilities. - CapAdd []string `json:"CapAdd"` - // CapDrop is a list of capabilities removed from the container. - // It is not directly stored by libpod, and instead computed from the - // capabilities listed in the container's spec, compared against a set - // of default capabilities. - CapDrop []string `json:"CapDrop"` - // Dns is a list of DNS nameservers that will be added to the - // container's resolv.conf - Dns []string `json:"Dns"` - // DnsOptions is a list of DNS options that will be set in the - // container's resolv.conf - DnsOptions []string `json:"DnsOptions"` - // DnsSearch is a list of DNS search domains that will be set in the - // container's resolv.conf - DnsSearch []string `json:"DnsSearch"` - // ExtraHosts contains hosts that will be aded to the container's - // /etc/hosts. - ExtraHosts []string `json:"ExtraHosts"` - // GroupAdd contains groups that the user inside the container will be - // added to. - GroupAdd []string `json:"GroupAdd"` - // IpcMode represents the configuration of the container's IPC - // namespace. - // Populated as follows: - // "" (empty string) - Default, an IPC namespace will be created - // host - No IPC namespace created - // container:<id> - Using another container's IPC namespace - // ns:<path> - A path to an IPC namespace has been specified - IpcMode string `json:"IpcMode"` - // Cgroup contains the container's cgroup. It is presently not - // populated. - // TODO. - Cgroup string `json:"Cgroup"` - // Cgroups contains the container's CGroup mode. - // Allowed values are "default" (container is creating CGroups) and - // "disabled" (container is not creating CGroups). - // This is Libpod-specific and not included in `docker inspect`. - Cgroups string `json:"Cgroups"` - // Links is unused, and provided purely for Docker compatibility. - Links []string `json:"Links"` - // OOMScoreAdj is an adjustment that will be made to the container's OOM - // score. - OomScoreAdj int `json:"OomScoreAdj"` - // PidMode represents the configuration of the container's PID - // namespace. - // Populated as follows: - // "" (empty string) - Default, a PID namespace will be created - // host - No PID namespace created - // container:<id> - Using another container's PID namespace - // ns:<path> - A path to a PID namespace has been specified - PidMode string `json:"PidMode"` - // Privileged indicates whether the container is running with elevated - // privileges. - // This has a very specific meaning in the Docker sense, so it's very - // difficult to decode from the spec and config, and so is stored as an - // annotation. - Privileged bool `json:"Privileged"` - // PublishAllPorts indicates whether image ports are being published. - // This is not directly stored in libpod and is saved as an annotation. - PublishAllPorts bool `json:"PublishAllPorts"` - // ReadonlyRootfs is whether the container will be mounted read-only. - ReadonlyRootfs bool `json:"ReadonlyRootfs"` - // SecurityOpt is a list of security-related options that are set in the - // container. - SecurityOpt []string `json:"SecurityOpt"` - // Tmpfs is a list of tmpfs filesystems that will be mounted into the - // container. - // It is a map of destination path to options for the mount. - Tmpfs map[string]string `json:"Tmpfs"` - // UTSMode represents the configuration of the container's UID - // namespace. - // Populated as follows: - // "" (empty string) - Default, a UTS namespace will be created - // host - no UTS namespace created - // container:<id> - Using another container's UTS namespace - // ns:<path> - A path to a UTS namespace has been specified - UTSMode string `json:"UTSMode"` - // UsernsMode represents the configuration of the container's user - // namespace. - // When running rootless, a user namespace is created outside of libpod - // to allow some privileged operations. This will not be reflected here. - // Populated as follows: - // "" (empty string) - No user namespace will be created - // private - The container will be run in a user namespace - // container:<id> - Using another container's user namespace - // ns:<path> - A path to a user namespace has been specified - // TODO Rootless has an additional 'keep-id' option, presently not - // reflected here. - UsernsMode string `json:"UsernsMode"` - // ShmSize is the size of the container's SHM device. - ShmSize int64 `json:"ShmSize"` - // Runtime is provided purely for Docker compatibility. - // It is set unconditionally to "oci" as Podman does not presently - // support non-OCI runtimes. - Runtime string `json:"Runtime"` - // ConsoleSize is an array of 2 integers showing the size of the - // container's console. - // It is only set if the container is creating a terminal. - // TODO. - ConsoleSize []uint `json:"ConsoleSize"` - // Isolation is presently unused and provided solely for Docker - // compatibility. - Isolation string `json:"Isolation"` - // CpuShares indicates the CPU resources allocated to the container. - // It is a relative weight in the scheduler for assigning CPU time - // versus other CGroups. - CpuShares uint64 `json:"CpuShares"` - // Memory indicates the memory resources allocated to the container. - // This is the limit (in bytes) of RAM the container may use. - Memory int64 `json:"Memory"` - // NanoCpus indicates number of CPUs allocated to the container. - // It is an integer where one full CPU is indicated by 1000000000 (one - // billion). - // Thus, 2.5 CPUs (fractional portions of CPUs are allowed) would be - // 2500000000 (2.5 billion). - // In 'docker inspect' this is set exclusively of two further options in - // the output (CpuPeriod and CpuQuota) which are both used to implement - // this functionality. - // We can't distinguish here, so if CpuQuota is set to the default of - // 100000, we will set both CpuQuota, CpuPeriod, and NanoCpus. If - // CpuQuota is not the default, we will not set NanoCpus. - NanoCpus int64 `json:"NanoCpus"` - // CgroupParent is the CGroup parent of the container. - // Only set if not default. - CgroupParent string `json:"CgroupParent"` - // BlkioWeight indicates the I/O resources allocated to the container. - // It is a relative weight in the scheduler for assigning I/O time - // versus other CGroups. - BlkioWeight uint16 `json:"BlkioWeight"` - // BlkioWeightDevice is an array of I/O resource priorities for - // individual device nodes. - // Unfortunately, the spec only stores the device's Major/Minor numbers - // and not the path, which is used here. - // Fortunately, the kernel provides an interface for retrieving the path - // of a given node by major:minor at /sys/dev/. However, the exact path - // in use may not be what was used in the original CLI invocation - - // though it is guaranteed that the device node will be the same, and - // using the given path will be functionally identical. - BlkioWeightDevice []InspectBlkioWeightDevice `json:"BlkioWeightDevice"` - // BlkioDeviceReadBps is an array of I/O throttle parameters for - // individual device nodes. - // This specifically sets read rate cap in bytes per second for device - // nodes. - // As with BlkioWeightDevice, we pull the path from /sys/dev, and we - // don't guarantee the path will be identical to the original (though - // the node will be). - BlkioDeviceReadBps []InspectBlkioThrottleDevice `json:"BlkioDeviceReadBps"` - // BlkioDeviceWriteBps is an array of I/O throttle parameters for - // individual device nodes. - // this specifically sets write rate cap in bytes per second for device - // nodes. - // as with BlkioWeightDevice, we pull the path from /sys/dev, and we - // don't guarantee the path will be identical to the original (though - // the node will be). - BlkioDeviceWriteBps []InspectBlkioThrottleDevice `json:"BlkioDeviceWriteBps"` - // BlkioDeviceReadIOps is an array of I/O throttle parameters for - // individual device nodes. - // This specifically sets the read rate cap in iops per second for - // device nodes. - // As with BlkioWeightDevice, we pull the path from /sys/dev, and we - // don't guarantee the path will be identical to the original (though - // the node will be). - BlkioDeviceReadIOps []InspectBlkioThrottleDevice `json:"BlkioDeviceReadIOps"` - // BlkioDeviceWriteIOps is an array of I/O throttle parameters for - // individual device nodes. - // This specifically sets the write rate cap in iops per second for - // device nodes. - // As with BlkioWeightDevice, we pull the path from /sys/dev, and we - // don't guarantee the path will be identical to the original (though - // the node will be). - BlkioDeviceWriteIOps []InspectBlkioThrottleDevice `json:"BlkioDeviceWriteIOps"` - // CpuPeriod is the length of a CPU period in microseconds. - // It relates directly to CpuQuota. - CpuPeriod uint64 `json:"CpuPeriod"` - // CpuPeriod is the amount of time (in microseconds) that a container - // can use the CPU in every CpuPeriod. - CpuQuota int64 `json:"CpuQuota"` - // CpuRealtimePeriod is the length of time (in microseconds) of the CPU - // realtime period. If set to 0, no time will be allocated to realtime - // tasks. - CpuRealtimePeriod uint64 `json:"CpuRealtimePeriod"` - // CpuRealtimeRuntime is the length of time (in microseconds) allocated - // for realtime tasks within every CpuRealtimePeriod. - CpuRealtimeRuntime int64 `json:"CpuRealtimeRuntime"` - // CpusetCpus is the is the set of CPUs that the container will execute - // on. Formatted as `0-3` or `0,2`. Default (if unset) is all CPUs. - CpusetCpus string `json:"CpusetCpus"` - // CpusetMems is the set of memory nodes the container will use. - // Formatted as `0-3` or `0,2`. Default (if unset) is all memory nodes. - CpusetMems string `json:"CpusetMems"` - // Devices is a list of device nodes that will be added to the - // container. - // These are stored in the OCI spec only as type, major, minor while we - // display the host path. We convert this with /sys/dev, but we cannot - // guarantee that the host path will be identical - only that the actual - // device will be. - Devices []InspectDevice `json:"Devices"` - // DiskQuota is the maximum amount of disk space the container may use - // (in bytes). - // Presently not populated. - // TODO. - DiskQuota uint64 `json:"DiskQuota"` - // KernelMemory is the maximum amount of memory the kernel will devote - // to the container. - KernelMemory int64 `json:"KernelMemory"` - // MemoryReservation is the reservation (soft limit) of memory available - // to the container. Soft limits are warnings only and can be exceeded. - MemoryReservation int64 `json:"MemoryReservation"` - // MemorySwap is the total limit for all memory available to the - // container, including swap. 0 indicates that there is no limit to the - // amount of memory available. - MemorySwap int64 `json:"MemorySwap"` - // MemorySwappiness is the willingness of the kernel to page container - // memory to swap. It is an integer from 0 to 100, with low numbers - // being more likely to be put into swap. - // -1, the default, will not set swappiness and use the system defaults. - MemorySwappiness int64 `json:"MemorySwappiness"` - // OomKillDisable indicates whether the kernel OOM killer is disabled - // for the container. - OomKillDisable bool `json:"OomKillDisable"` - // Init indicates whether the container has an init mounted into it. - Init bool `json:"Init,omitempty"` - // PidsLimit is the maximum number of PIDs what may be created within - // the container. 0, the default, indicates no limit. - PidsLimit int64 `json:"PidsLimit"` - // Ulimits is a set of ulimits that will be set within the container. - Ulimits []InspectUlimit `json:"Ulimits"` - // CpuCount is Windows-only and not presently implemented. - CpuCount uint64 `json:"CpuCount"` - // CpuPercent is Windows-only and not presently implemented. - CpuPercent uint64 `json:"CpuPercent"` - // IOMaximumIOps is Windows-only and not presently implemented. - IOMaximumIOps uint64 `json:"IOMaximumIOps"` - // IOMaximumBandwidth is Windows-only and not presently implemented. - IOMaximumBandwidth uint64 `json:"IOMaximumBandwidth"` -} - -// InspectLogConfig holds information about a container's configured log driver -// and is presently unused. It is retained for Docker compatibility. -type InspectLogConfig struct { - Type string `json:"Type"` - Config map[string]string `json:"Config"` //idk type, TODO -} - -// InspectRestartPolicy holds information about the container's restart policy. -type InspectRestartPolicy struct { - // Name contains the container's restart policy. - // Allowable values are "no" or "" (take no action), - // "on-failure" (restart on non-zero exit code, with an optional max - // retry count), and "always" (always restart on container stop, unless - // explicitly requested by API). - // Note that this is NOT actually a name of any sort - the poor naming - // is for Docker compatibility. - Name string `json:"Name"` - // MaximumRetryCount is the maximum number of retries allowed if the - // "on-failure" restart policy is in use. Not used if "on-failure" is - // not set. - MaximumRetryCount uint `json:"MaximumRetryCount"` -} - -// InspectBlkioWeightDevice holds information about the relative weight -// of an individual device node. Weights are used in the I/O scheduler to give -// relative priority to some accesses. -type InspectBlkioWeightDevice struct { - // Path is the path to the device this applies to. - Path string `json:"Path"` - // Weight is the relative weight the scheduler will use when scheduling - // I/O. - Weight uint16 `json:"Weight"` -} - -// InspectBlkioThrottleDevice holds information about a speed cap for a device -// node. This cap applies to a specific operation (read, write, etc) on the given -// node. -type InspectBlkioThrottleDevice struct { - // Path is the path to the device this applies to. - Path string `json:"Path"` - // Rate is the maximum rate. It is in either bytes per second or iops - // per second, determined by where it is used - documentation will - // indicate which is appropriate. - Rate uint64 `json:"Rate"` -} - -// InspectUlimit is a ulimit that will be applied to the container. -type InspectUlimit struct { - // Name is the name (type) of the ulimit. - Name string `json:"Name"` - // Soft is the soft limit that will be applied. - Soft uint64 `json:"Soft"` - // Hard is the hard limit that will be applied. - Hard uint64 `json:"Hard"` -} - -// InspectMount provides a record of a single mount in a container. It contains -// fields for both named and normal volumes. Only user-specified volumes will be -// included, and tmpfs volumes are not included even if the user specified them. -type InspectMount struct { - // Whether the mount is a volume or bind mount. Allowed values are - // "volume" and "bind". - Type string `json:"Type"` - // The name of the volume. Empty for bind mounts. - Name string `json:"Name,omptempty"` - // The source directory for the volume. - 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. - 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 - // goes in here. - Mode string `json:"Mode"` - // All remaining mount options. Additional data, not present in the - // original output. - Options []string `json:"Options"` - // Whether the volume is read-write - RW bool `json:"RW"` - // Mount propagation for the mount. Can be empty if not specified, but - // is always printed - no omitempty. - Propagation string `json:"Propagation"` -} - -// InspectDevice is a single device that will be mounted into the container. -type InspectDevice struct { - // PathOnHost is the path of the device on the host. - PathOnHost string `json:"PathOnHost"` - // PathInContainer is the path of the device within the container. - PathInContainer string `json:"PathInContainer"` - // CgroupPermissions is the permissions of the mounted device. - // Presently not populated. - // TODO. - CgroupPermissions string `json:"CgroupPermissions"` -} - -// InspectHostPort provides information on a port on the host that a container's -// port is bound to. -type InspectHostPort struct { - // IP on the host we are bound to. "" if not specified (binding to all - // IPs). - HostIP string `json:"HostIp"` - // Port on the host we are bound to. No special formatting - just an - // integer stuffed into a string. - HostPort string `json:"HostPort"` -} - -// InspectContainerState provides a detailed record of a container's current -// state. It is returned as part of InspectContainerData. -// As with InspectContainerData, many portions of this struct are matched to -// Docker, but here we see more fields that are unused (nonsensical in the -// context of Libpod). -type InspectContainerState struct { - OciVersion string `json:"OciVersion"` - Status string `json:"Status"` - Running bool `json:"Running"` - Paused bool `json:"Paused"` - Restarting bool `json:"Restarting"` // TODO - OOMKilled bool `json:"OOMKilled"` - Dead bool `json:"Dead"` - Pid int `json:"Pid"` - ConmonPid int `json:"ConmonPid,omitempty"` - ExitCode int32 `json:"ExitCode"` - Error string `json:"Error"` // TODO - StartedAt time.Time `json:"StartedAt"` - FinishedAt time.Time `json:"FinishedAt"` - Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"` -} - -// InspectBasicNetworkConfig holds basic configuration information (e.g. IP -// addresses, MAC address, subnet masks, etc) that are common for all networks -// (both additional and main). -type InspectBasicNetworkConfig struct { - // EndpointID is unused, maintained exclusively for compatibility. - EndpointID string `json:"EndpointID"` - // Gateway is the IP address of the gateway this network will use. - Gateway string `json:"Gateway"` - // IPAddress is the IP address for this network. - IPAddress string `json:"IPAddress"` - // IPPrefixLen is the length of the subnet mask of this network. - IPPrefixLen int `json:"IPPrefixLen"` - // SecondaryIPAddresses is a list of extra IP Addresses that the - // container has been assigned in this network. - SecondaryIPAddresses []string `json:"SecondaryIPAddresses,omitempty"` - // IPv6Gateway is the IPv6 gateway this network will use. - IPv6Gateway string `json:"IPv6Gateway"` - // GlobalIPv6Address is the global-scope IPv6 Address for this network. - GlobalIPv6Address string `json:"GlobalIPv6Address"` - // GlobalIPv6PrefixLen is the length of the subnet mask of this network. - GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"` - // SecondaryIPv6Addresses is a list of extra IPv6 Addresses that the - // container has been assigned in this networ. - SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses,omitempty"` - // MacAddress is the MAC address for the interface in this network. - MacAddress string `json:"MacAddress"` - // AdditionalMacAddresses is a set of additional MAC Addresses beyond - // the first. CNI may configure more than one interface for a single - // network, which can cause this. - AdditionalMacAddresses []string `json:"AdditionalMACAddresses,omitempty"` -} - -// InspectNetworkSettings holds information about the network settings of the -// container. -// Many fields are maintained only for compatibility with `docker inspect` and -// are unused within Libpod. -type InspectNetworkSettings struct { - InspectBasicNetworkConfig - - Bridge string `json:"Bridge"` - SandboxID string `json:"SandboxID"` - HairpinMode bool `json:"HairpinMode"` - LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"` - LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"` - Ports []ocicni.PortMapping `json:"Ports"` - SandboxKey string `json:"SandboxKey"` - // Networks contains information on non-default CNI networks this - // container has joined. - // It is a map of network name to network information. - Networks map[string]*InspectAdditionalNetwork `json:"Networks,omitempty"` -} - -// InspectAdditionalNetwork holds information about non-default CNI networks the -// container has been connected to. -// As with InspectNetworkSettings, many fields are unused and maintained only -// for compatibility with Docker. -type InspectAdditionalNetwork struct { - InspectBasicNetworkConfig - - // Name of the network we're connecting to. - NetworkID string `json:"NetworkID,omitempty"` - // DriverOpts is presently unused and maintained exclusively for - // compatibility. - DriverOpts map[string]string `json:"DriverOpts"` - // IPAMConfig is presently unused and maintained exclusively for - // compatibility. - IPAMConfig map[string]string `json:"IPAMConfig"` - // Links is presently unused and maintained exclusively for - // compatibility. - Links []string `json:"Links"` -} - // inspectLocked inspects a container for low-level information. // The caller must held c.lock. -func (c *Container) inspectLocked(size bool) (*InspectContainerData, error) { +func (c *Container) inspectLocked(size bool) (*define.InspectContainerData, error) { storeCtr, err := c.runtime.store.Container(c.ID()) if err != nil { return nil, errors.Wrapf(err, "error getting container from store %q", c.ID()) @@ -697,7 +101,7 @@ func (c *Container) inspectLocked(size bool) (*InspectContainerData, error) { } // Inspect a container for low-level information -func (c *Container) Inspect(size bool) (*InspectContainerData, error) { +func (c *Container) Inspect(size bool) (*define.InspectContainerData, error) { if !c.batched { c.lock.Lock() defer c.lock.Unlock() @@ -710,7 +114,7 @@ func (c *Container) Inspect(size bool) (*InspectContainerData, error) { return c.inspectLocked(size) } -func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) (*InspectContainerData, error) { +func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) (*define.InspectContainerData, error) { config := c.config runtimeInfo := c.state ctrSpec, err := c.specFromState() @@ -757,12 +161,12 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) return nil, err } - data := &InspectContainerData{ + data := &define.InspectContainerData{ ID: config.ID, Created: config.CreatedTime, Path: path, Args: args, - State: &InspectContainerState{ + State: &define.InspectContainerState{ OciVersion: ctrSpec.Version, Status: runtimeInfo.State.String(), Running: runtimeInfo.State == define.ContainerStateRunning, @@ -857,8 +261,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(ctrSpec *spec.Spec, namedVolumes []*ContainerNamedVolume, mounts []spec.Mount) ([]InspectMount, error) { - inspectMounts := []InspectMount{} +func (c *Container) getInspectMounts(ctrSpec *spec.Spec, namedVolumes []*ContainerNamedVolume, mounts []spec.Mount) ([]define.InspectMount, error) { + inspectMounts := []define.InspectMount{} // No mounts, return early if len(c.config.UserVolumes) == 0 { @@ -866,7 +270,7 @@ func (c *Container) getInspectMounts(ctrSpec *spec.Spec, namedVolumes []*Contain } for _, volume := range namedVolumes { - mountStruct := InspectMount{} + mountStruct := define.InspectMount{} mountStruct.Type = "volume" mountStruct.Destination = volume.Dest mountStruct.Name = volume.Name @@ -891,7 +295,7 @@ func (c *Container) getInspectMounts(ctrSpec *spec.Spec, namedVolumes []*Contain continue } - mountStruct := InspectMount{} + mountStruct := define.InspectMount{} mountStruct.Type = "bind" mountStruct.Source = mount.Source mountStruct.Destination = mount.Destination @@ -906,7 +310,7 @@ func (c *Container) getInspectMounts(ctrSpec *spec.Spec, namedVolumes []*Contain // Parse mount options so we can populate them in the mount structure. // The mount passed in will be modified. -func parseMountOptionsForInspect(options []string, mount *InspectMount) { +func parseMountOptionsForInspect(options []string, mount *define.InspectMount) { isRW := true mountProp := "" zZ := "" @@ -940,8 +344,8 @@ func parseMountOptionsForInspect(options []string, mount *InspectMount) { } // Generate the InspectContainerConfig struct for the Config field of Inspect. -func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectContainerConfig, error) { - ctrConfig := new(InspectContainerConfig) +func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*define.InspectContainerConfig, error) { + ctrConfig := new(define.InspectContainerConfig) ctrConfig.Hostname = c.Hostname() ctrConfig.User = c.config.User @@ -992,14 +396,14 @@ func (c *Container) generateInspectContainerConfig(spec *spec.Spec) (*InspectCon // Generate the InspectContainerHostConfig struct for the HostConfig field of // Inspect. -func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, namedVolumes []*ContainerNamedVolume, mounts []spec.Mount) (*InspectContainerHostConfig, error) { - hostConfig := new(InspectContainerHostConfig) +func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, namedVolumes []*ContainerNamedVolume, mounts []spec.Mount) (*define.InspectContainerHostConfig, error) { + hostConfig := new(define.InspectContainerHostConfig) - logConfig := new(InspectLogConfig) + logConfig := new(define.InspectLogConfig) logConfig.Type = c.config.LogDriver hostConfig.LogConfig = logConfig - restartPolicy := new(InspectRestartPolicy) + restartPolicy := new(define.InspectRestartPolicy) restartPolicy.Name = c.config.RestartPolicy restartPolicy.MaximumRetryCount = c.config.RestartRetries hostConfig.RestartPolicy = restartPolicy @@ -1126,7 +530,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named if ctrSpec.Linux.Resources.BlockIO.Weight != nil { hostConfig.BlkioWeight = *ctrSpec.Linux.Resources.BlockIO.Weight } - hostConfig.BlkioWeightDevice = []InspectBlkioWeightDevice{} + hostConfig.BlkioWeightDevice = []define.InspectBlkioWeightDevice{} for _, dev := range ctrSpec.Linux.Resources.BlockIO.WeightDevice { key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor) // TODO: how do we handle LeafWeight vs @@ -1148,14 +552,14 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named logrus.Warnf("Could not locate weight device %s in system devices", key) continue } - weightDev := InspectBlkioWeightDevice{} + weightDev := define.InspectBlkioWeightDevice{} weightDev.Path = path weightDev.Weight = *dev.Weight hostConfig.BlkioWeightDevice = append(hostConfig.BlkioWeightDevice, weightDev) } - handleThrottleDevice := func(devs []spec.LinuxThrottleDevice) ([]InspectBlkioThrottleDevice, error) { - out := []InspectBlkioThrottleDevice{} + handleThrottleDevice := func(devs []spec.LinuxThrottleDevice) ([]define.InspectBlkioThrottleDevice, error) { + out := []define.InspectBlkioThrottleDevice{} for _, dev := range devs { key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor) if deviceNodes == nil { @@ -1170,7 +574,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named logrus.Warnf("Could not locate throttle device %s in system devices", key) continue } - throttleDev := InspectBlkioThrottleDevice{} + throttleDev := define.InspectBlkioThrottleDevice{} throttleDev.Path = path throttleDev.Rate = dev.Rate out = append(out, throttleDev) @@ -1272,15 +676,15 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named // Port bindings. // Only populate if we're using CNI to configure the network. - portBindings := make(map[string][]InspectHostPort) + portBindings := make(map[string][]define.InspectHostPort) if c.config.CreateNetNS { for _, port := range c.config.PortMappings { key := fmt.Sprintf("%d/%s", port.ContainerPort, port.Protocol) hostPorts := portBindings[key] if hostPorts == nil { - hostPorts = []InspectHostPort{} + hostPorts = []define.InspectHostPort{} } - hostPorts = append(hostPorts, InspectHostPort{ + hostPorts = append(hostPorts, define.InspectHostPort{ HostIP: port.HostIP, HostPort: fmt.Sprintf("%d", port.HostPort), }) @@ -1449,7 +853,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named // Devices // Do not include if privileged - assumed that all devices will be // included. - hostConfig.Devices = []InspectDevice{} + hostConfig.Devices = []define.InspectDevice{} if ctrSpec.Linux != nil && !hostConfig.Privileged { for _, dev := range ctrSpec.Linux.Devices { key := fmt.Sprintf("%d:%d", dev.Major, dev.Minor) @@ -1465,7 +869,7 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named logrus.Warnf("Could not locate device %s on host", key) continue } - newDev := InspectDevice{} + newDev := define.InspectDevice{} newDev.PathOnHost = path newDev.PathInContainer = dev.Path hostConfig.Devices = append(hostConfig.Devices, newDev) @@ -1473,10 +877,10 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named } // Ulimits - hostConfig.Ulimits = []InspectUlimit{} + hostConfig.Ulimits = []define.InspectUlimit{} if ctrSpec.Process != nil { for _, limit := range ctrSpec.Process.Rlimits { - newLimit := InspectUlimit{} + newLimit := define.InspectUlimit{} newLimit.Name = limit.Type newLimit.Soft = limit.Soft newLimit.Hard = limit.Hard diff --git a/libpod/define/container_inspect.go b/libpod/define/container_inspect.go new file mode 100644 index 000000000..e6a19e5b4 --- /dev/null +++ b/libpod/define/container_inspect.go @@ -0,0 +1,624 @@ +package define + +import ( + "time" + + "github.com/containers/image/v5/manifest" + "github.com/containers/libpod/libpod/driver" + "github.com/cri-o/ocicni/pkg/ocicni" +) + +// 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"` + // CreateCommand is the full command plus arguments of the process the + // container has been created with. + CreateCommand []string `json:"CreateCommand,omitempty"` +} + +// InspectRestartPolicy holds information about the container's restart policy. +type InspectRestartPolicy struct { + // Name contains the container's restart policy. + // Allowable values are "no" or "" (take no action), + // "on-failure" (restart on non-zero exit code, with an optional max + // retry count), and "always" (always restart on container stop, unless + // explicitly requested by API). + // Note that this is NOT actually a name of any sort - the poor naming + // is for Docker compatibility. + Name string `json:"Name"` + // MaximumRetryCount is the maximum number of retries allowed if the + // "on-failure" restart policy is in use. Not used if "on-failure" is + // not set. + MaximumRetryCount uint `json:"MaximumRetryCount"` +} + +// InspectLogConfig holds information about a container's configured log driver +// and is presently unused. It is retained for Docker compatibility. +type InspectLogConfig struct { + Type string `json:"Type"` + Config map[string]string `json:"Config"` //idk type, TODO +} + +// InspectBlkioWeightDevice holds information about the relative weight +// of an individual device node. Weights are used in the I/O scheduler to give +// relative priority to some accesses. +type InspectBlkioWeightDevice struct { + // Path is the path to the device this applies to. + Path string `json:"Path"` + // Weight is the relative weight the scheduler will use when scheduling + // I/O. + Weight uint16 `json:"Weight"` +} + +// InspectBlkioThrottleDevice holds information about a speed cap for a device +// node. This cap applies to a specific operation (read, write, etc) on the given +// node. +type InspectBlkioThrottleDevice struct { + // Path is the path to the device this applies to. + Path string `json:"Path"` + // Rate is the maximum rate. It is in either bytes per second or iops + // per second, determined by where it is used - documentation will + // indicate which is appropriate. + Rate uint64 `json:"Rate"` +} + +// InspectUlimit is a ulimit that will be applied to the container. +type InspectUlimit struct { + // Name is the name (type) of the ulimit. + Name string `json:"Name"` + // Soft is the soft limit that will be applied. + Soft uint64 `json:"Soft"` + // Hard is the hard limit that will be applied. + Hard uint64 `json:"Hard"` +} + +// InspectDevice is a single device that will be mounted into the container. +type InspectDevice struct { + // PathOnHost is the path of the device on the host. + PathOnHost string `json:"PathOnHost"` + // PathInContainer is the path of the device within the container. + PathInContainer string `json:"PathInContainer"` + // CgroupPermissions is the permissions of the mounted device. + // Presently not populated. + // TODO. + CgroupPermissions string `json:"CgroupPermissions"` +} + +// InspectHostPort provides information on a port on the host that a container's +// port is bound to. +type InspectHostPort struct { + // IP on the host we are bound to. "" if not specified (binding to all + // IPs). + HostIP string `json:"HostIp"` + // Port on the host we are bound to. No special formatting - just an + // integer stuffed into a string. + HostPort string `json:"HostPort"` +} + +// InspectMount provides a record of a single mount in a container. It contains +// fields for both named and normal volumes. Only user-specified volumes will be +// included, and tmpfs volumes are not included even if the user specified them. +type InspectMount struct { + // Whether the mount is a volume or bind mount. Allowed values are + // "volume" and "bind". + Type string `json:"Type"` + // The name of the volume. Empty for bind mounts. + Name string `json:"Name,omptempty"` + // The source directory for the volume. + 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. + 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 + // goes in here. + Mode string `json:"Mode"` + // All remaining mount options. Additional data, not present in the + // original output. + Options []string `json:"Options"` + // Whether the volume is read-write + RW bool `json:"RW"` + // Mount propagation for the mount. Can be empty if not specified, but + // is always printed - no omitempty. + Propagation string `json:"Propagation"` +} + +// InspectContainerState provides a detailed record of a container's current +// state. It is returned as part of InspectContainerData. +// As with InspectContainerData, many portions of this struct are matched to +// Docker, but here we see more fields that are unused (nonsensical in the +// context of Libpod). +type InspectContainerState struct { + OciVersion string `json:"OciVersion"` + Status string `json:"Status"` + Running bool `json:"Running"` + Paused bool `json:"Paused"` + Restarting bool `json:"Restarting"` // TODO + OOMKilled bool `json:"OOMKilled"` + Dead bool `json:"Dead"` + Pid int `json:"Pid"` + ConmonPid int `json:"ConmonPid,omitempty"` + ExitCode int32 `json:"ExitCode"` + Error string `json:"Error"` // TODO + StartedAt time.Time `json:"StartedAt"` + FinishedAt time.Time `json:"FinishedAt"` + Healthcheck HealthCheckResults `json:"Healthcheck,omitempty"` +} + +// HealthCheckResults describes the results/logs from a healthcheck +type HealthCheckResults struct { + // Status healthy or unhealthy + Status string `json:"Status"` + // FailingStreak is the number of consecutive failed healthchecks + FailingStreak int `json:"FailingStreak"` + // Log describes healthcheck attempts and results + Log []HealthCheckLog `json:"Log"` +} + +// HealthCheckLog describes the results of a single healthcheck +type HealthCheckLog struct { + // Start time as string + Start string `json:"Start"` + // End time as a string + End string `json:"End"` + // Exitcode is 0 or 1 + ExitCode int `json:"ExitCode"` + // Output is the stdout/stderr from the healthcheck command + Output string `json:"Output"` +} + +// InspectContainerHostConfig holds information used when the container was +// created. +// It's very much a Docker-specific struct, retained (mostly) as-is for +// compatibility. We fill individual fields as best as we can, inferring as much +// as possible from the spec and container config. +// Some things cannot be inferred. These will be populated by spec annotations +// (if available). +// Field names are fixed for compatibility and cannot be changed. +// As such, silence lint warnings about them. +//nolint +type InspectContainerHostConfig struct { + // Binds contains an array of user-added mounts. + // Both volume mounts and named volumes are included. + // Tmpfs mounts are NOT included. + // In 'docker inspect' this is separated into 'Binds' and 'Mounts' based + // on how a mount was added. We do not make this distinction and do not + // include a Mounts field in inspect. + // Format: <src>:<destination>[:<comma-separated options>] + Binds []string `json:"Binds"` + // ContainerIDFile is a file created during container creation to hold + // the ID of the created container. + // This is not handled within libpod and is stored in an annotation. + ContainerIDFile string `json:"ContainerIDFile"` + // LogConfig contains information on the container's logging backend + LogConfig *InspectLogConfig `json:"LogConfig"` + // NetworkMode is the configuration of the container's network + // namespace. + // Populated as follows: + // default - A network namespace is being created and configured via CNI + // none - A network namespace is being created, not configured via CNI + // host - No network namespace created + // container:<id> - Using another container's network namespace + // ns:<path> - A path to a network namespace has been specified + NetworkMode string `json:"NetworkMode"` + // PortBindings contains the container's port bindings. + // It is formatted as map[string][]InspectHostPort. + // The string key here is formatted as <integer port number>/<protocol> + // and represents the container port. A single container port may be + // bound to multiple host ports (on different IPs). + PortBindings map[string][]InspectHostPort `json:"PortBindings"` + // RestartPolicy contains the container's restart policy. + RestartPolicy *InspectRestartPolicy `json:"RestartPolicy"` + // AutoRemove is whether the container will be automatically removed on + // exiting. + // It is not handled directly within libpod and is stored in an + // annotation. + AutoRemove bool `json:"AutoRemove"` + // VolumeDriver is presently unused and is retained for Docker + // compatibility. + VolumeDriver string `json:"VolumeDriver"` + // VolumesFrom is a list of containers which this container uses volumes + // from. This is not handled directly within libpod and is stored in an + // annotation. + // It is formatted as an array of container names and IDs. + VolumesFrom []string `json:"VolumesFrom"` + // CapAdd is a list of capabilities added to the container. + // It is not directly stored by Libpod, and instead computed from the + // capabilities listed in the container's spec, compared against a set + // of default capabilities. + CapAdd []string `json:"CapAdd"` + // CapDrop is a list of capabilities removed from the container. + // It is not directly stored by libpod, and instead computed from the + // capabilities listed in the container's spec, compared against a set + // of default capabilities. + CapDrop []string `json:"CapDrop"` + // Dns is a list of DNS nameservers that will be added to the + // container's resolv.conf + Dns []string `json:"Dns"` + // DnsOptions is a list of DNS options that will be set in the + // container's resolv.conf + DnsOptions []string `json:"DnsOptions"` + // DnsSearch is a list of DNS search domains that will be set in the + // container's resolv.conf + DnsSearch []string `json:"DnsSearch"` + // ExtraHosts contains hosts that will be aded to the container's + // /etc/hosts. + ExtraHosts []string `json:"ExtraHosts"` + // GroupAdd contains groups that the user inside the container will be + // added to. + GroupAdd []string `json:"GroupAdd"` + // IpcMode represents the configuration of the container's IPC + // namespace. + // Populated as follows: + // "" (empty string) - Default, an IPC namespace will be created + // host - No IPC namespace created + // container:<id> - Using another container's IPC namespace + // ns:<path> - A path to an IPC namespace has been specified + IpcMode string `json:"IpcMode"` + // Cgroup contains the container's cgroup. It is presently not + // populated. + // TODO. + Cgroup string `json:"Cgroup"` + // Cgroups contains the container's CGroup mode. + // Allowed values are "default" (container is creating CGroups) and + // "disabled" (container is not creating CGroups). + // This is Libpod-specific and not included in `docker inspect`. + Cgroups string `json:"Cgroups"` + // Links is unused, and provided purely for Docker compatibility. + Links []string `json:"Links"` + // OOMScoreAdj is an adjustment that will be made to the container's OOM + // score. + OomScoreAdj int `json:"OomScoreAdj"` + // PidMode represents the configuration of the container's PID + // namespace. + // Populated as follows: + // "" (empty string) - Default, a PID namespace will be created + // host - No PID namespace created + // container:<id> - Using another container's PID namespace + // ns:<path> - A path to a PID namespace has been specified + PidMode string `json:"PidMode"` + // Privileged indicates whether the container is running with elevated + // privileges. + // This has a very specific meaning in the Docker sense, so it's very + // difficult to decode from the spec and config, and so is stored as an + // annotation. + Privileged bool `json:"Privileged"` + // PublishAllPorts indicates whether image ports are being published. + // This is not directly stored in libpod and is saved as an annotation. + PublishAllPorts bool `json:"PublishAllPorts"` + // ReadonlyRootfs is whether the container will be mounted read-only. + ReadonlyRootfs bool `json:"ReadonlyRootfs"` + // SecurityOpt is a list of security-related options that are set in the + // container. + SecurityOpt []string `json:"SecurityOpt"` + // Tmpfs is a list of tmpfs filesystems that will be mounted into the + // container. + // It is a map of destination path to options for the mount. + Tmpfs map[string]string `json:"Tmpfs"` + // UTSMode represents the configuration of the container's UID + // namespace. + // Populated as follows: + // "" (empty string) - Default, a UTS namespace will be created + // host - no UTS namespace created + // container:<id> - Using another container's UTS namespace + // ns:<path> - A path to a UTS namespace has been specified + UTSMode string `json:"UTSMode"` + // UsernsMode represents the configuration of the container's user + // namespace. + // When running rootless, a user namespace is created outside of libpod + // to allow some privileged operations. This will not be reflected here. + // Populated as follows: + // "" (empty string) - No user namespace will be created + // private - The container will be run in a user namespace + // container:<id> - Using another container's user namespace + // ns:<path> - A path to a user namespace has been specified + // TODO Rootless has an additional 'keep-id' option, presently not + // reflected here. + UsernsMode string `json:"UsernsMode"` + // ShmSize is the size of the container's SHM device. + ShmSize int64 `json:"ShmSize"` + // Runtime is provided purely for Docker compatibility. + // It is set unconditionally to "oci" as Podman does not presently + // support non-OCI runtimes. + Runtime string `json:"Runtime"` + // ConsoleSize is an array of 2 integers showing the size of the + // container's console. + // It is only set if the container is creating a terminal. + // TODO. + ConsoleSize []uint `json:"ConsoleSize"` + // Isolation is presently unused and provided solely for Docker + // compatibility. + Isolation string `json:"Isolation"` + // CpuShares indicates the CPU resources allocated to the container. + // It is a relative weight in the scheduler for assigning CPU time + // versus other CGroups. + CpuShares uint64 `json:"CpuShares"` + // Memory indicates the memory resources allocated to the container. + // This is the limit (in bytes) of RAM the container may use. + Memory int64 `json:"Memory"` + // NanoCpus indicates number of CPUs allocated to the container. + // It is an integer where one full CPU is indicated by 1000000000 (one + // billion). + // Thus, 2.5 CPUs (fractional portions of CPUs are allowed) would be + // 2500000000 (2.5 billion). + // In 'docker inspect' this is set exclusively of two further options in + // the output (CpuPeriod and CpuQuota) which are both used to implement + // this functionality. + // We can't distinguish here, so if CpuQuota is set to the default of + // 100000, we will set both CpuQuota, CpuPeriod, and NanoCpus. If + // CpuQuota is not the default, we will not set NanoCpus. + NanoCpus int64 `json:"NanoCpus"` + // CgroupParent is the CGroup parent of the container. + // Only set if not default. + CgroupParent string `json:"CgroupParent"` + // BlkioWeight indicates the I/O resources allocated to the container. + // It is a relative weight in the scheduler for assigning I/O time + // versus other CGroups. + BlkioWeight uint16 `json:"BlkioWeight"` + // BlkioWeightDevice is an array of I/O resource priorities for + // individual device nodes. + // Unfortunately, the spec only stores the device's Major/Minor numbers + // and not the path, which is used here. + // Fortunately, the kernel provides an interface for retrieving the path + // of a given node by major:minor at /sys/dev/. However, the exact path + // in use may not be what was used in the original CLI invocation - + // though it is guaranteed that the device node will be the same, and + // using the given path will be functionally identical. + BlkioWeightDevice []InspectBlkioWeightDevice `json:"BlkioWeightDevice"` + // BlkioDeviceReadBps is an array of I/O throttle parameters for + // individual device nodes. + // This specifically sets read rate cap in bytes per second for device + // nodes. + // As with BlkioWeightDevice, we pull the path from /sys/dev, and we + // don't guarantee the path will be identical to the original (though + // the node will be). + BlkioDeviceReadBps []InspectBlkioThrottleDevice `json:"BlkioDeviceReadBps"` + // BlkioDeviceWriteBps is an array of I/O throttle parameters for + // individual device nodes. + // this specifically sets write rate cap in bytes per second for device + // nodes. + // as with BlkioWeightDevice, we pull the path from /sys/dev, and we + // don't guarantee the path will be identical to the original (though + // the node will be). + BlkioDeviceWriteBps []InspectBlkioThrottleDevice `json:"BlkioDeviceWriteBps"` + // BlkioDeviceReadIOps is an array of I/O throttle parameters for + // individual device nodes. + // This specifically sets the read rate cap in iops per second for + // device nodes. + // As with BlkioWeightDevice, we pull the path from /sys/dev, and we + // don't guarantee the path will be identical to the original (though + // the node will be). + BlkioDeviceReadIOps []InspectBlkioThrottleDevice `json:"BlkioDeviceReadIOps"` + // BlkioDeviceWriteIOps is an array of I/O throttle parameters for + // individual device nodes. + // This specifically sets the write rate cap in iops per second for + // device nodes. + // As with BlkioWeightDevice, we pull the path from /sys/dev, and we + // don't guarantee the path will be identical to the original (though + // the node will be). + BlkioDeviceWriteIOps []InspectBlkioThrottleDevice `json:"BlkioDeviceWriteIOps"` + // CpuPeriod is the length of a CPU period in microseconds. + // It relates directly to CpuQuota. + CpuPeriod uint64 `json:"CpuPeriod"` + // CpuPeriod is the amount of time (in microseconds) that a container + // can use the CPU in every CpuPeriod. + CpuQuota int64 `json:"CpuQuota"` + // CpuRealtimePeriod is the length of time (in microseconds) of the CPU + // realtime period. If set to 0, no time will be allocated to realtime + // tasks. + CpuRealtimePeriod uint64 `json:"CpuRealtimePeriod"` + // CpuRealtimeRuntime is the length of time (in microseconds) allocated + // for realtime tasks within every CpuRealtimePeriod. + CpuRealtimeRuntime int64 `json:"CpuRealtimeRuntime"` + // CpusetCpus is the is the set of CPUs that the container will execute + // on. Formatted as `0-3` or `0,2`. Default (if unset) is all CPUs. + CpusetCpus string `json:"CpusetCpus"` + // CpusetMems is the set of memory nodes the container will use. + // Formatted as `0-3` or `0,2`. Default (if unset) is all memory nodes. + CpusetMems string `json:"CpusetMems"` + // Devices is a list of device nodes that will be added to the + // container. + // These are stored in the OCI spec only as type, major, minor while we + // display the host path. We convert this with /sys/dev, but we cannot + // guarantee that the host path will be identical - only that the actual + // device will be. + Devices []InspectDevice `json:"Devices"` + // DiskQuota is the maximum amount of disk space the container may use + // (in bytes). + // Presently not populated. + // TODO. + DiskQuota uint64 `json:"DiskQuota"` + // KernelMemory is the maximum amount of memory the kernel will devote + // to the container. + KernelMemory int64 `json:"KernelMemory"` + // MemoryReservation is the reservation (soft limit) of memory available + // to the container. Soft limits are warnings only and can be exceeded. + MemoryReservation int64 `json:"MemoryReservation"` + // MemorySwap is the total limit for all memory available to the + // container, including swap. 0 indicates that there is no limit to the + // amount of memory available. + MemorySwap int64 `json:"MemorySwap"` + // MemorySwappiness is the willingness of the kernel to page container + // memory to swap. It is an integer from 0 to 100, with low numbers + // being more likely to be put into swap. + // -1, the default, will not set swappiness and use the system defaults. + MemorySwappiness int64 `json:"MemorySwappiness"` + // OomKillDisable indicates whether the kernel OOM killer is disabled + // for the container. + OomKillDisable bool `json:"OomKillDisable"` + // Init indicates whether the container has an init mounted into it. + Init bool `json:"Init,omitempty"` + // PidsLimit is the maximum number of PIDs what may be created within + // the container. 0, the default, indicates no limit. + PidsLimit int64 `json:"PidsLimit"` + // Ulimits is a set of ulimits that will be set within the container. + Ulimits []InspectUlimit `json:"Ulimits"` + // CpuCount is Windows-only and not presently implemented. + CpuCount uint64 `json:"CpuCount"` + // CpuPercent is Windows-only and not presently implemented. + CpuPercent uint64 `json:"CpuPercent"` + // IOMaximumIOps is Windows-only and not presently implemented. + IOMaximumIOps uint64 `json:"IOMaximumIOps"` + // IOMaximumBandwidth is Windows-only and not presently implemented. + IOMaximumBandwidth uint64 `json:"IOMaximumBandwidth"` +} + +// InspectBasicNetworkConfig holds basic configuration information (e.g. IP +// addresses, MAC address, subnet masks, etc) that are common for all networks +// (both additional and main). +type InspectBasicNetworkConfig struct { + // EndpointID is unused, maintained exclusively for compatibility. + EndpointID string `json:"EndpointID"` + // Gateway is the IP address of the gateway this network will use. + Gateway string `json:"Gateway"` + // IPAddress is the IP address for this network. + IPAddress string `json:"IPAddress"` + // IPPrefixLen is the length of the subnet mask of this network. + IPPrefixLen int `json:"IPPrefixLen"` + // SecondaryIPAddresses is a list of extra IP Addresses that the + // container has been assigned in this network. + SecondaryIPAddresses []string `json:"SecondaryIPAddresses,omitempty"` + // IPv6Gateway is the IPv6 gateway this network will use. + IPv6Gateway string `json:"IPv6Gateway"` + // GlobalIPv6Address is the global-scope IPv6 Address for this network. + GlobalIPv6Address string `json:"GlobalIPv6Address"` + // GlobalIPv6PrefixLen is the length of the subnet mask of this network. + GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"` + // SecondaryIPv6Addresses is a list of extra IPv6 Addresses that the + // container has been assigned in this networ. + SecondaryIPv6Addresses []string `json:"SecondaryIPv6Addresses,omitempty"` + // MacAddress is the MAC address for the interface in this network. + MacAddress string `json:"MacAddress"` + // AdditionalMacAddresses is a set of additional MAC Addresses beyond + // the first. CNI may configure more than one interface for a single + // network, which can cause this. + AdditionalMacAddresses []string `json:"AdditionalMACAddresses,omitempty"` +} + +// InspectAdditionalNetwork holds information about non-default CNI networks the +// container has been connected to. +// As with InspectNetworkSettings, many fields are unused and maintained only +// for compatibility with Docker. +type InspectAdditionalNetwork struct { + InspectBasicNetworkConfig + + // Name of the network we're connecting to. + NetworkID string `json:"NetworkID,omitempty"` + // DriverOpts is presently unused and maintained exclusively for + // compatibility. + DriverOpts map[string]string `json:"DriverOpts"` + // IPAMConfig is presently unused and maintained exclusively for + // compatibility. + IPAMConfig map[string]string `json:"IPAMConfig"` + // Links is presently unused and maintained exclusively for + // compatibility. + Links []string `json:"Links"` +} + +// InspectNetworkSettings holds information about the network settings of the +// container. +// Many fields are maintained only for compatibility with `docker inspect` and +// are unused within Libpod. +type InspectNetworkSettings struct { + InspectBasicNetworkConfig + + Bridge string `json:"Bridge"` + SandboxID string `json:"SandboxID"` + HairpinMode bool `json:"HairpinMode"` + LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"` + LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"` + Ports []ocicni.PortMapping `json:"Ports"` + SandboxKey string `json:"SandboxKey"` + // Networks contains information on non-default CNI networks this + // container has joined. + // It is a map of network name to network information. + Networks map[string]*InspectAdditionalNetwork `json:"Networks,omitempty"` +} + +// InspectContainerData provides a detailed record of a container's configuration +// and state as viewed by Libpod. +// Large portions of this structure are defined such that the output is +// compatible with `docker inspect` JSON, but additional fields have been added +// as required to share information not in the original output. +type InspectContainerData struct { + ID string `json:"Id"` + Created time.Time `json:"Created"` + Path string `json:"Path"` + Args []string `json:"Args"` + State *InspectContainerState `json:"State"` + Image string `json:"Image"` + ImageName string `json:"ImageName"` + Rootfs string `json:"Rootfs"` + Pod string `json:"Pod"` + ResolvConfPath string `json:"ResolvConfPath"` + HostnamePath string `json:"HostnamePath"` + HostsPath string `json:"HostsPath"` + StaticDir string `json:"StaticDir"` + OCIConfigPath string `json:"OCIConfigPath,omitempty"` + OCIRuntime string `json:"OCIRuntime,omitempty"` + LogPath string `json:"LogPath"` + LogTag string `json:"LogTag"` + ConmonPidFile string `json:"ConmonPidFile"` + Name string `json:"Name"` + RestartCount int32 `json:"RestartCount"` + Driver string `json:"Driver"` + MountLabel string `json:"MountLabel"` + ProcessLabel string `json:"ProcessLabel"` + AppArmorProfile string `json:"AppArmorProfile"` + EffectiveCaps []string `json:"EffectiveCaps"` + BoundingCaps []string `json:"BoundingCaps"` + ExecIDs []string `json:"ExecIDs"` + GraphDriver *driver.Data `json:"GraphDriver"` + SizeRw *int64 `json:"SizeRw,omitempty"` + SizeRootFs int64 `json:"SizeRootFs,omitempty"` + 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"` + HostConfig *InspectContainerHostConfig `json:"HostConfig"` +} diff --git a/libpod/healthcheck.go b/libpod/healthcheck.go index 76b7a1fcf..08a613dfe 100644 --- a/libpod/healthcheck.go +++ b/libpod/healthcheck.go @@ -53,28 +53,6 @@ const ( HealthCheckStarting string = "starting" ) -// HealthCheckResults describes the results/logs from a healthcheck -type HealthCheckResults struct { - // Status healthy or unhealthy - Status string `json:"Status"` - // FailingStreak is the number of consecutive failed healthchecks - FailingStreak int `json:"FailingStreak"` - // Log describes healthcheck attempts and results - Log []HealthCheckLog `json:"Log"` -} - -// HealthCheckLog describes the results of a single healthcheck -type HealthCheckLog struct { - // Start time as string - Start string `json:"Start"` - // End time as a string - End string `json:"End"` - // Exitcode is 0 or 1 - ExitCode int `json:"ExitCode"` - // Output is the stdout/stderr from the healthcheck command - Output string `json:"Output"` -} - // hcWriteCloser allows us to use bufio as a WriteCloser type hcWriteCloser struct { *bufio.Writer @@ -200,8 +178,8 @@ func checkHealthCheckCanBeRun(c *Container) (HealthCheckStatus, error) { return HealthCheckDefined, nil } -func newHealthCheckLog(start, end time.Time, exitCode int, log string) HealthCheckLog { - return HealthCheckLog{ +func newHealthCheckLog(start, end time.Time, exitCode int, log string) define.HealthCheckLog { + return define.HealthCheckLog{ Start: start.Format(time.RFC3339Nano), End: end.Format(time.RFC3339Nano), ExitCode: exitCode, @@ -225,7 +203,7 @@ func (c *Container) updateHealthStatus(status string) error { } // UpdateHealthCheckLog parses the health check results and writes the log -func (c *Container) updateHealthCheckLog(hcl HealthCheckLog, inStartPeriod bool) error { +func (c *Container) updateHealthCheckLog(hcl define.HealthCheckLog, inStartPeriod bool) error { healthCheck, err := c.GetHealthCheckLog() if err != nil { return err @@ -266,8 +244,8 @@ func (c *Container) healthCheckLogPath() string { // GetHealthCheckLog returns HealthCheck results by reading the container's // health check log file. If the health check log file does not exist, then // an empty healthcheck struct is returned -func (c *Container) GetHealthCheckLog() (HealthCheckResults, error) { - var healthCheck HealthCheckResults +func (c *Container) GetHealthCheckLog() (define.HealthCheckResults, error) { + var healthCheck define.HealthCheckResults if _, err := os.Stat(c.healthCheckLogPath()); os.IsNotExist(err) { return healthCheck, nil } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index a7f501bfe..ab6ec4439 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -573,8 +573,8 @@ func getContainerNetIO(ctr *Container) (*netlink.LinkStatistics, error) { // Produce an InspectNetworkSettings containing information on the container // network. -func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) { - settings := new(InspectNetworkSettings) +func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) { + settings := new(define.InspectNetworkSettings) settings.Ports = []ocicni.PortMapping{} if c.config.PortMappings != nil { // TODO: This may not be safe. @@ -600,13 +600,13 @@ func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) { return nil, errors.Wrapf(define.ErrInternal, "network inspection mismatch: asked to join %d CNI networks but have information on %d networks", len(c.config.Networks), len(c.state.NetworkStatus)) } - settings.Networks = make(map[string]*InspectAdditionalNetwork) + settings.Networks = make(map[string]*define.InspectAdditionalNetwork) // CNI results should be in the same order as the list of // networks we pass into CNI. for index, name := range c.config.Networks { cniResult := c.state.NetworkStatus[index] - addedNet := new(InspectAdditionalNetwork) + addedNet := new(define.InspectAdditionalNetwork) addedNet.NetworkID = name basicConfig, err := resultToBasicNetworkConfig(cniResult) @@ -640,8 +640,8 @@ func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) { // resultToBasicNetworkConfig produces an InspectBasicNetworkConfig from a CNI // result -func resultToBasicNetworkConfig(result *cnitypes.Result) (InspectBasicNetworkConfig, error) { - config := InspectBasicNetworkConfig{} +func resultToBasicNetworkConfig(result *cnitypes.Result) (define.InspectBasicNetworkConfig, error) { + config := define.InspectBasicNetworkConfig{} for _, ctrIP := range result.IPs { size, _ := ctrIP.Address.Mask.Size() diff --git a/libpod/networking_unsupported.go b/libpod/networking_unsupported.go index 32b354a44..1ef8fe2dc 100644 --- a/libpod/networking_unsupported.go +++ b/libpod/networking_unsupported.go @@ -20,7 +20,7 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) { return define.ErrNotImplemented } -func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) { +func (c *Container) getContainerNetworkInfo() (*define.InspectNetworkSettings, error) { return nil, define.ErrNotImplemented } diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index 32a84b60d..46db7ebe8 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -32,12 +32,12 @@ import ( ) // Inspect returns an inspect struct from varlink -func (c *Container) Inspect(size bool) (*libpod.InspectContainerData, error) { +func (c *Container) Inspect(size bool) (*define.InspectContainerData, error) { reply, err := iopodman.ContainerInspectData().Call(c.Runtime.Conn, c.ID(), size) if err != nil { return nil, err } - data := libpod.InspectContainerData{} + data := define.InspectContainerData{} if err := json.Unmarshal([]byte(reply), &data); err != nil { return nil, err } diff --git a/pkg/api/handlers/swagger.go b/pkg/api/handlers/swagger.go index 646ad45ea..e6e937729 100644 --- a/pkg/api/handlers/swagger.go +++ b/pkg/api/handlers/swagger.go @@ -2,6 +2,7 @@ package handlers import ( "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/domain/entities" "github.com/containers/libpod/pkg/inspect" @@ -109,7 +110,7 @@ type swagDockerTopResponse struct { type swagLibpodInspectContainerResponse struct { // in:body Body struct { - libpod.InspectContainerData + define.InspectContainerData } } diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go index 9156f3f8a..2433a6a05 100644 --- a/pkg/api/server/swagger.go +++ b/pkg/api/server/swagger.go @@ -2,6 +2,7 @@ package server import ( "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/domain/entities" ) @@ -178,6 +179,6 @@ type swagVolumeListResponse struct { type swagHealthCheckRunResponse struct { // in:body Body struct { - libpod.HealthCheckResults + define.HealthCheckResults } } diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go index 231b6f232..c2f10345f 100644 --- a/pkg/bindings/containers/containers.go +++ b/pkg/bindings/containers/containers.go @@ -6,7 +6,6 @@ import ( "net/url" "strconv" - "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod" "github.com/containers/libpod/pkg/bindings" @@ -106,7 +105,7 @@ func Remove(ctx context.Context, nameOrID string, force, volumes *bool) error { // or a partial/full ID. The size bool determines whether the size of the container's root filesystem // should be calculated. Calculating the size of a container requires extra work from the filesystem and // is therefore slower. -func Inspect(ctx context.Context, nameOrID string, size *bool) (*libpod.InspectContainerData, error) { +func Inspect(ctx context.Context, nameOrID string, size *bool) (*define.InspectContainerData, error) { conn, err := bindings.GetClient(ctx) if err != nil { return nil, err @@ -119,7 +118,7 @@ func Inspect(ctx context.Context, nameOrID string, size *bool) (*libpod.InspectC if err != nil { return nil, err } - inspect := libpod.InspectContainerData{} + inspect := define.InspectContainerData{} return &inspect, response.Process(&inspect) } diff --git a/pkg/bindings/containers/healthcheck.go b/pkg/bindings/containers/healthcheck.go index 85cc2814c..2b783ac73 100644 --- a/pkg/bindings/containers/healthcheck.go +++ b/pkg/bindings/containers/healthcheck.go @@ -4,19 +4,19 @@ import ( "context" "net/http" - "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/bindings" ) // RunHealthCheck executes the container's healthcheck and returns the health status of the // container. -func RunHealthCheck(ctx context.Context, nameOrID string) (*libpod.HealthCheckResults, error) { +func RunHealthCheck(ctx context.Context, nameOrID string) (*define.HealthCheckResults, error) { conn, err := bindings.GetClient(ctx) if err != nil { return nil, err } var ( - status libpod.HealthCheckResults + status define.HealthCheckResults ) response, err := conn.DoRequest(nil, http.MethodGet, "/containers/%s/healthcheck", nil, nameOrID) if err != nil { diff --git a/pkg/domain/entities/containers.go b/pkg/domain/entities/containers.go index 8b7406ae8..545452948 100644 --- a/pkg/domain/entities/containers.go +++ b/pkg/domain/entities/containers.go @@ -81,3 +81,13 @@ type RmReport struct { Err error Id string } + +type ContainerInspectOptions struct { + Format string + Latest bool + Size bool +} + +type ContainerInspectReport struct { + *define.InspectContainerData +} diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index 958061437..0217910fc 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -6,6 +6,7 @@ import ( type ContainerEngine interface { ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error) + ContainerInspect(ctx context.Context, namesOrIds []string, options ContainerInspectOptions) ([]*ContainerInspectReport, error) ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error) ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error) ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error) diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index a3da310c2..2e1a5aa82 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -239,3 +239,19 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, } return reports, nil } + +func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.ContainerInspectOptions) ([]*entities.ContainerInspectReport, error) { + var reports []*entities.ContainerInspectReport + ctrs, err := shortcuts.GetContainersByContext(false, options.Latest, namesOrIds, ic.Libpod) + if err != nil { + return nil, err + } + for _, c := range ctrs { + data, err := c.Inspect(options.Size) + if err != nil { + return nil, err + } + reports = append(reports, &entities.ContainerInspectReport{InspectContainerData: data}) + } + return reports, nil +} diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index a8ecff41b..367ea6e36 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -138,3 +138,21 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, } return reports, nil } + +func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.ContainerInspectOptions) ([]*entities.ContainerInspectReport, error) { + var ( + reports []*entities.ContainerInspectReport + ) + ctrs, err := getContainersByContext(ic.ClientCxt, false, namesOrIds) + if err != nil { + return nil, err + } + for _, con := range ctrs { + data, err := containers.Inspect(ic.ClientCxt, con.ID, &options.Size) + if err != nil { + return nil, err + } + reports = append(reports, &entities.ContainerInspectReport{InspectContainerData: data}) + } + return reports, nil +} diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 16b971e65..caa1683a2 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -15,6 +15,7 @@ import ( "time" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/rootless" . "github.com/containers/libpod/test/utils" @@ -320,7 +321,7 @@ func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { } // InspectContainer returns a container's inspect data in JSON format -func (p *PodmanTestIntegration) InspectContainer(name string) []libpod.InspectContainerData { +func (p *PodmanTestIntegration) InspectContainer(name string) []define.InspectContainerData { cmd := []string{"inspect", name} session := p.Podman(cmd) session.WaitWithDefaultTimeout() @@ -492,8 +493,8 @@ func (p *PodmanTestIntegration) PullImage(image string) error { // InspectContainerToJSON takes the session output of an inspect // container and returns json -func (s *PodmanSessionIntegration) InspectContainerToJSON() []libpod.InspectContainerData { - var i []libpod.InspectContainerData +func (s *PodmanSessionIntegration) InspectContainerToJSON() []define.InspectContainerData { + var i []define.InspectContainerData err := json.Unmarshal(s.Out.Contents(), &i) Expect(err).To(BeNil()) return i |