aboutsummaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
authorumohnani8 <umohnani@redhat.com>2017-11-29 16:56:18 -0500
committerumohnani8 <umohnani@redhat.com>2017-12-12 09:46:23 -0500
commit74ee579375654c79fa710f13b7c2ee3810366f82 (patch)
tree36f1b98582875e497b7e76457cb969d85cef6426 /libpod
parent88121e0747c03084c233d22fadfd3c227e73a885 (diff)
downloadpodman-74ee579375654c79fa710f13b7c2ee3810366f82.tar.gz
podman-74ee579375654c79fa710f13b7c2ee3810366f82.tar.bz2
podman-74ee579375654c79fa710f13b7c2ee3810366f82.zip
Update kpod inspect to use the new container state
kpod inspect now uses the new libpod container state and closely matches the output of docker inspect some aspects of it are still WIP as the libpod container state is still being worked on Signed-off-by: umohnani8 <umohnani@redhat.com>
Diffstat (limited to 'libpod')
-rw-r--r--libpod/container.go90
-rw-r--r--libpod/container_inspect.go70
-rw-r--r--libpod/driver/driver.go20
-rw-r--r--libpod/image_inspect.go81
-rw-r--r--libpod/images/image_data.go202
-rw-r--r--libpod/inspect_data.go103
-rw-r--r--libpod/runtime_img.go69
7 files changed, 383 insertions, 252 deletions
diff --git a/libpod/container.go b/libpod/container.go
index fce64b0dd..d53a863c0 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -22,6 +22,7 @@ import (
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
+ "github.com/projectatomic/libpod/libpod/driver"
crioAnnotations "github.com/projectatomic/libpod/pkg/annotations"
"github.com/sirupsen/logrus"
"github.com/ulule/deepcopier"
@@ -132,6 +133,7 @@ type ContainerConfig struct {
SharedNamespaceMap map[string]string `json:"sharedNamespaces"`
// Time container was created
CreatedTime time.Time `json:"createdTime"`
+
// TODO save log location here and pass into OCI code
// TODO allow overriding of log path
}
@@ -192,7 +194,6 @@ func (c *Container) Labels() map[string]string {
for key, value := range c.config.Labels {
labels[key] = value
}
-
return labels
}
@@ -204,6 +205,68 @@ func (c *Container) Config() *ContainerConfig {
return returnConfig
}
+// RuntimeName returns the name of the runtime
+func (c *Container) RuntimeName() string {
+ return c.runtime.ociRuntime.name
+}
+
+// rootFsSize gets the size of the container's root filesystem
+// A container FS is split into two parts. The first is the top layer, a
+// mutable layer, and the rest is the RootFS: the set of immutable layers
+// that make up the image on which the container is based.
+func (c *Container) rootFsSize() (int64, error) {
+ container, err := c.runtime.store.Container(c.ID())
+ if err != nil {
+ return 0, err
+ }
+
+ // Ignore the size of the top layer. The top layer is a mutable RW layer
+ // and is not considered a part of the rootfs
+ rwLayer, err := c.runtime.store.Layer(container.LayerID)
+ if err != nil {
+ return 0, err
+ }
+ layer, err := c.runtime.store.Layer(rwLayer.Parent)
+ if err != nil {
+ return 0, err
+ }
+
+ size := int64(0)
+ for layer.Parent != "" {
+ layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID)
+ if err != nil {
+ return size, errors.Wrapf(err, "getting diffsize of layer %q and its parent %q", layer.ID, layer.Parent)
+ }
+ size += layerSize
+ layer, err = c.runtime.store.Layer(layer.Parent)
+ if err != nil {
+ return 0, err
+ }
+ }
+ // Get the size of the last layer. Has to be outside of the loop
+ // because the parent of the last layer is "", andlstore.Get("")
+ // will return an error.
+ layerSize, err := c.runtime.store.DiffSize(layer.Parent, layer.ID)
+ return size + layerSize, err
+}
+
+// rwSize Gets the size of the mutable top layer of the container.
+func (c *Container) rwSize() (int64, error) {
+ container, err := c.runtime.store.Container(c.ID())
+ if err != nil {
+ return 0, err
+ }
+
+ // Get the size of the top layer by calculating the size of the diff
+ // between the layer and its parent. The top layer of a container is
+ // the only RW layer, all others are immutable
+ layer, err := c.runtime.store.Layer(container.LayerID)
+ if err != nil {
+ return 0, err
+ }
+ return c.runtime.store.DiffSize(layer.Parent, layer.ID)
+}
+
// LogPath returns the path to the container's log file
// This file will only be present after Init() is called to create the container
// in runc
@@ -829,6 +892,31 @@ func (c *Container) getArtifactPath(name string) string {
return filepath.Join(c.config.StaticDir, artifactsDir, name)
}
+// Inspect a container for low-level information
+func (c *Container) Inspect(size bool) (*ContainerInspectData, error) {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if err := c.syncContainer(); err != nil {
+ return nil, err
+ }
+
+ storeCtr, err := c.runtime.store.Container(c.ID())
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting container from store %q", c.ID())
+ }
+ layer, err := c.runtime.store.Layer(storeCtr.LayerID)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading information about layer %q", storeCtr.LayerID)
+ }
+ driverData, err := driver.GetDriverData(c.runtime.store, layer.ID)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting graph driver info %q", c.ID())
+ }
+
+ return c.getContainerInspectData(size, driverData)
+}
+
// Commit commits the changes between a container and its image, creating a new
// image
func (c *Container) Commit() (*storage.Image, error) {
diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go
new file mode 100644
index 000000000..5f29a231e
--- /dev/null
+++ b/libpod/container_inspect.go
@@ -0,0 +1,70 @@
+package libpod
+
+import (
+ "github.com/projectatomic/libpod/libpod/driver"
+ "github.com/sirupsen/logrus"
+)
+
+func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) (*ContainerInspectData, error) {
+ config := c.config
+ runtimeInfo := c.state
+ spec := c.config.Spec
+
+ args := config.Spec.Process.Args
+ var path string
+ if len(args) > 0 {
+ path = args[0]
+ }
+ if len(args) > 1 {
+ args = args[1:]
+ }
+
+ data := &ContainerInspectData{
+ ID: config.ID,
+ Created: config.CreatedTime,
+ Path: path,
+ Args: args,
+ State: &ContainerInspectState{
+ OciVersion: spec.Version,
+ Status: runtimeInfo.State.String(),
+ Running: runtimeInfo.State == ContainerStateRunning,
+ Paused: runtimeInfo.State == ContainerStatePaused,
+ OOMKilled: runtimeInfo.OOMKilled,
+ Dead: runtimeInfo.State.String() == "bad state",
+ Pid: runtimeInfo.PID,
+ ExitCode: runtimeInfo.ExitCode,
+ Error: "", // can't get yet
+ StartedAt: runtimeInfo.StartedTime,
+ FinishedAt: runtimeInfo.FinishedTime,
+ },
+ ImageID: config.RootfsImageID,
+ ImageName: config.RootfsImageName,
+ ResolvConfPath: "", // TODO get from networking path
+ HostnamePath: spec.Annotations["io.kubernetes.cri-o.HostnamePath"], // not sure
+ HostsPath: "", // can't get yet
+ StaticDir: config.StaticDir,
+ LogPath: c.LogPath(),
+ Name: config.Name,
+ Driver: driverData.Name,
+ MountLabel: config.MountLabel,
+ ProcessLabel: spec.Process.SelinuxLabel,
+ AppArmorProfile: spec.Process.ApparmorProfile,
+ ExecIDs: []string{}, //TODO
+ GraphDriver: driverData,
+ Mounts: spec.Mounts,
+ NetworkSettings: &NetworkSettings{}, // TODO from networking patch
+ }
+ if size {
+ rootFsSize, err := c.rootFsSize()
+ if err != nil {
+ logrus.Errorf("error getting rootfs size %q: %v", config.ID, err)
+ }
+ rwSize, err := c.rwSize()
+ if err != nil {
+ logrus.Errorf("error getting rw size %q: %v", config.ID, err)
+ }
+ data.SizeRootFs = rootFsSize
+ data.SizeRw = rwSize
+ }
+ return data, nil
+}
diff --git a/libpod/driver/driver.go b/libpod/driver/driver.go
index 4db55852c..8475810a8 100644
--- a/libpod/driver/driver.go
+++ b/libpod/driver/driver.go
@@ -4,8 +4,8 @@ import cstorage "github.com/containers/storage"
// Data handles the data for a storage driver
type Data struct {
- Name string
- Data map[string]string
+ Name string `json:"Name"`
+ Data map[string]string `json:"Data"`
}
// GetDriverName returns the name of the driver for the given store
@@ -25,3 +25,19 @@ func GetDriverMetadata(store cstorage.Store, layerID string) (map[string]string,
}
return driver.Metadata(layerID)
}
+
+// GetDriverData returns the Data struct with information of the driver used by the store
+func GetDriverData(store cstorage.Store, layerID string) (*Data, error) {
+ name, err := GetDriverName(store)
+ if err != nil {
+ return nil, err
+ }
+ metaData, err := GetDriverMetadata(store, layerID)
+ if err != nil {
+ return nil, err
+ }
+ return &Data{
+ Name: name,
+ Data: metaData,
+ }, nil
+}
diff --git a/libpod/image_inspect.go b/libpod/image_inspect.go
new file mode 100644
index 000000000..a08665434
--- /dev/null
+++ b/libpod/image_inspect.go
@@ -0,0 +1,81 @@
+package libpod
+
+import (
+ "encoding/json"
+ "strings"
+
+ "github.com/containers/image/types"
+ "github.com/containers/storage"
+ digest "github.com/opencontainers/go-digest"
+ ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
+ "github.com/pkg/errors"
+ "github.com/projectatomic/libpod/libpod/driver"
+)
+
+func getImageData(img storage.Image, imgRef types.Image, size int64, driver *driver.Data) (*ImageData, error) {
+ imgSize, err := imgRef.Size()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading size of image %q", img.ID)
+ }
+ manifest, manifestType, err := imgRef.Manifest()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading manifest for image %q", img.ID)
+ }
+ imgDigest := digest.Digest("")
+ if len(manifest) > 0 {
+ imgDigest = digest.Canonical.FromBytes(manifest)
+ }
+ annotations := annotations(manifest, manifestType)
+
+ ociv1Img, err := imgRef.OCIConfig()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting oci image info %q", img.ID)
+ }
+ info, err := imgRef.Inspect()
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting image info %q", img.ID)
+ }
+
+ var repoDigests []string
+ for _, name := range img.Names {
+ repoDigests = append(repoDigests, strings.SplitN(name, ":", 2)[0]+"@"+imgDigest.String())
+ }
+
+ data := &ImageData{
+ ID: img.ID,
+ RepoTags: img.Names,
+ RepoDigests: repoDigests,
+ Comment: ociv1Img.History[0].Comment,
+ Created: ociv1Img.Created,
+ Author: ociv1Img.History[0].Author,
+ Architecture: ociv1Img.Architecture,
+ Os: ociv1Img.OS,
+ Config: &ociv1Img.Config,
+ Version: info.DockerVersion,
+ Size: size,
+ VirtualSize: size + imgSize,
+ Annotations: annotations,
+ Digest: imgDigest,
+ Labels: info.Labels,
+ RootFS: &RootFS{
+ Type: ociv1Img.RootFS.Type,
+ Layers: ociv1Img.RootFS.DiffIDs,
+ },
+ GraphDriver: driver,
+ }
+ return data, nil
+}
+
+func annotations(manifest []byte, manifestType string) map[string]string {
+ annotations := make(map[string]string)
+ switch manifestType {
+ case ociv1.MediaTypeImageManifest:
+ var m ociv1.Manifest
+ if err := json.Unmarshal(manifest, &m); err == nil {
+ for k, v := range m.Annotations {
+ annotations[k] = v
+ }
+ }
+ }
+ return annotations
+}
diff --git a/libpod/images/image_data.go b/libpod/images/image_data.go
deleted file mode 100644
index 1fa63f6cb..000000000
--- a/libpod/images/image_data.go
+++ /dev/null
@@ -1,202 +0,0 @@
-package images
-
-import (
- "encoding/json"
- "time"
-
- "github.com/containers/image/docker/reference"
- is "github.com/containers/image/storage"
- "github.com/containers/image/transports"
- "github.com/containers/image/types"
- "github.com/containers/storage"
- digest "github.com/opencontainers/go-digest"
- ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
- "github.com/pkg/errors"
- "github.com/projectatomic/libpod/libpod/driver"
-)
-
-// Data handles the data used when inspecting a container
-// nolint
-type Data struct {
- ID string
- Tags []string
- Digests []string
- Digest digest.Digest
- Comment string
- Created *time.Time
- Container string
- Author string
- Config ociv1.ImageConfig
- Architecture string
- OS string
- Annotations map[string]string
- CreatedBy string
- Size uint
- VirtualSize uint
- GraphDriver driver.Data
- RootFS ociv1.RootFS
-}
-
-// ParseImageNames parses the names we've stored with an image into a list of
-// tagged references and a list of references which contain digests.
-func ParseImageNames(names []string) (tags, digests []string, err error) {
- for _, name := range names {
- if named, err := reference.ParseNamed(name); err == nil {
- if digested, ok := named.(reference.Digested); ok {
- canonical, err := reference.WithDigest(named, digested.Digest())
- if err == nil {
- digests = append(digests, canonical.String())
- }
- } else {
- if reference.IsNameOnly(named) {
- named = reference.TagNameOnly(named)
- }
- if tagged, ok := named.(reference.Tagged); ok {
- namedTagged, err := reference.WithTag(named, tagged.Tag())
- if err == nil {
- tags = append(tags, namedTagged.String())
- }
- }
- }
- }
- }
- return tags, digests, nil
-}
-
-func annotations(manifest []byte, manifestType string) map[string]string {
- annotations := make(map[string]string)
- switch manifestType {
- case ociv1.MediaTypeImageManifest:
- var m ociv1.Manifest
- if err := json.Unmarshal(manifest, &m); err == nil {
- for k, v := range m.Annotations {
- annotations[k] = v
- }
- }
- }
- return annotations
-}
-
-// GetData gets the Data for a container with the given name in the given store.
-func GetData(store storage.Store, name string) (*Data, error) {
- img, err := FindImage(store, name)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading image %q", name)
- }
-
- imgRef, err := FindImageRef(store, "@"+img.ID)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading image %q", img.ID)
- }
-
- tags, digests, err := ParseImageNames(img.Names)
- if err != nil {
- return nil, errors.Wrapf(err, "error parsing image names for %q", name)
- }
-
- driverName, err := driver.GetDriverName(store)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading name of storage driver")
- }
-
- topLayerID := img.TopLayer
-
- driverMetadata, err := driver.GetDriverMetadata(store, topLayerID)
- if err != nil {
- return nil, errors.Wrapf(err, "error asking storage driver %q for metadata", driverName)
- }
-
- layer, err := store.Layer(topLayerID)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading information about layer %q", topLayerID)
- }
- size, err := store.DiffSize(layer.Parent, layer.ID)
- if err != nil {
- return nil, errors.Wrapf(err, "error determining size of layer %q", layer.ID)
- }
-
- imgSize, err := imgRef.Size()
- if err != nil {
- return nil, errors.Wrapf(err, "error determining size of image %q", transports.ImageName(imgRef.Reference()))
- }
-
- manifest, manifestType, err := imgRef.Manifest()
- if err != nil {
- return nil, errors.Wrapf(err, "error reading manifest for image %q", img.ID)
- }
- manifestDigest := digest.Digest("")
- if len(manifest) > 0 {
- manifestDigest = digest.Canonical.FromBytes(manifest)
- }
- annotations := annotations(manifest, manifestType)
-
- config, err := imgRef.OCIConfig()
- if err != nil {
- return nil, errors.Wrapf(err, "error reading image configuration for %q", img.ID)
- }
- historyComment := ""
- historyCreatedBy := ""
- if len(config.History) > 0 {
- historyComment = config.History[len(config.History)-1].Comment
- historyCreatedBy = config.History[len(config.History)-1].CreatedBy
- }
-
- return &Data{
- ID: img.ID,
- Tags: tags,
- Digests: digests,
- Digest: manifestDigest,
- Comment: historyComment,
- Created: config.Created,
- Author: config.Author,
- Config: config.Config,
- Architecture: config.Architecture,
- OS: config.OS,
- Annotations: annotations,
- CreatedBy: historyCreatedBy,
- Size: uint(size),
- VirtualSize: uint(size + imgSize),
- GraphDriver: driver.Data{
- Name: driverName,
- Data: driverMetadata,
- },
- RootFS: config.RootFS,
- }, nil
-}
-
-// FindImage searches for a *storage.Image with a matching the given name or ID in the given store.
-func FindImage(store storage.Store, image string) (*storage.Image, error) {
- var img *storage.Image
- ref, err := is.Transport.ParseStoreReference(store, image)
- if err == nil {
- img, err = is.Transport.GetStoreImage(store, ref)
- }
- if err != nil {
- img2, err2 := store.Image(image)
- if err2 != nil {
- if ref == nil {
- return nil, errors.Wrapf(err, "error parsing reference to image %q", image)
- }
- return nil, errors.Wrapf(err, "unable to locate image %q", image)
- }
- img = img2
- }
- return img, nil
-}
-
-// FindImageRef searches for and returns a new types.Image matching the given name or ID in the given store.
-func FindImageRef(store storage.Store, image string) (types.Image, error) {
- img, err := FindImage(store, image)
- if err != nil {
- return nil, errors.Wrapf(err, "unable to locate image %q", image)
- }
- ref, err := is.Transport.ParseStoreReference(store, "@"+img.ID)
- if err != nil {
- return nil, errors.Wrapf(err, "error parsing reference to image %q", img.ID)
- }
- imgRef, err := ref.NewImage(nil)
- if err != nil {
- return nil, errors.Wrapf(err, "error reading image %q", img.ID)
- }
- return imgRef, nil
-}
diff --git a/libpod/inspect_data.go b/libpod/inspect_data.go
new file mode 100644
index 000000000..072b94ab2
--- /dev/null
+++ b/libpod/inspect_data.go
@@ -0,0 +1,103 @@
+package libpod
+
+import (
+ "time"
+
+ digest "github.com/opencontainers/go-digest"
+ "github.com/opencontainers/image-spec/specs-go/v1"
+ specs "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/projectatomic/libpod/libpod/driver"
+)
+
+// ContainerInspectData handles the data used when inspecting a container
+type ContainerInspectData struct {
+ ID string `json:"ID"`
+ Created time.Time `json:"Created"`
+ Path string `json:"Path"`
+ Args []string `json:"Args"`
+ State *ContainerInspectState `json:"State"`
+ ImageID string `json:"Image"`
+ ImageName string `json:"ImageName"`
+ ResolvConfPath string `json:"ResolvConfPath"`
+ HostnamePath string `json:"HostnamePath"` //TODO
+ HostsPath string `json:"HostsPath"` //TODO
+ StaticDir string `json:"StaticDir"`
+ LogPath string `json:"LogPath"`
+ Name string `json:"Name"`
+ RestartCount int32 `json:"RestartCount"` //TODO
+ Driver string `json:"Driver"`
+ MountLabel string `json:"MountLabel"`
+ ProcessLabel string `json:"ProcessLabel"`
+ AppArmorProfile string `json:"AppArmorProfile"`
+ ExecIDs []string `json:"ExecIDs"` //TODO
+ GraphDriver *driver.Data `json:"GraphDriver"`
+ SizeRw int64 `json:"SizeRw,omitempty"`
+ SizeRootFs int64 `json:"SizeRootFs,omitempty"`
+ Mounts []specs.Mount `json:"Mounts"`
+ NetworkSettings *NetworkSettings `json:"NetworkSettings"` //TODO
+}
+
+// ContainerInspectState represents the state of a container.
+type ContainerInspectState 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"`
+ ExitCode int32 `json:"ExitCode"`
+ Error string `json:"Error"` // TODO
+ StartedAt time.Time `json:"StartedAt"`
+ FinishedAt time.Time `json:"FinishedAt"`
+}
+
+// NetworkSettings holds information about the newtwork settings of the container
+type NetworkSettings struct {
+ Bridge string `json:"Bridge"`
+ SandboxID string `json:"SandboxID"`
+ HairpinMode bool `json:"HairpinMode"`
+ LinkLocalIPv6Address string `json:"LinkLocalIPv6Address"`
+ LinkLocalIPv6PrefixLen int `json:"LinkLocalIPv6PrefixLen"`
+ Ports map[string]struct{} `json:"Ports"`
+ SandboxKey string `json:"SandboxKey"`
+ SecondaryIPAddresses string `json:"SecondaryIPAddresses"` //idk type
+ SecondaryIPv6Addresses string `json:"SecondaryIPv6Addresses"` //idk type
+ EndpointID string `json:"EndpointID"`
+ Gateway string `json:"Gateway"`
+ GlobalIPv6Addresses string `json:"GlobalIPv6Addresses"`
+ GlobalIPv6PrefixLen int `json:"GlobalIPv6PrefixLen"`
+ IPAddress string `json:"IPAddress"`
+ IPPrefixLen int `json:"IPPrefixLen"`
+ IPv6Gateway string `json:"IPv6Gateway"`
+ MacAddress string `json:"MacAddress"`
+}
+
+// ImageData holds the inspect information of an image
+type ImageData struct {
+ ID string `json:"ID"`
+ Digest digest.Digest `json:"Digest"`
+ RepoTags []string `json:"RepoTags"`
+ RepoDigests []string `json:"RepoDigests"`
+ Parent string `json:"Parent"`
+ Comment string `json:"Comment"`
+ Created *time.Time `json:"Created"`
+ Config *v1.ImageConfig `json:"Config"`
+ Version string `json:"Version"`
+ Author string `json:"Author"`
+ Architecture string `json:"Architecture"`
+ Os string `json:"Os"`
+ Size int64 `json:"Size"`
+ VirtualSize int64 `json:"VirtualSize"`
+ GraphDriver *driver.Data `json:"GraphDriver"`
+ RootFS *RootFS `json:"RootFS"`
+ Labels map[string]string `json:"Labels"`
+ Annotations map[string]string `json:"Annotations"`
+}
+
+// RootFS holds the root fs information of an image
+type RootFS struct {
+ Type string `json:"Type"`
+ Layers []digest.Digest `json:"Layers"`
+}
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index 26f85b037..d5da35c42 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -20,15 +20,14 @@ import (
"github.com/containers/image/signature"
is "github.com/containers/image/storage"
"github.com/containers/image/tarball"
- "github.com/containers/image/transports"
"github.com/containers/image/transports/alltransports"
"github.com/containers/image/types"
"github.com/containers/storage"
"github.com/containers/storage/pkg/archive"
- digest "github.com/opencontainers/go-digest"
ociv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/libpod/common"
+ "github.com/projectatomic/libpod/libpod/driver"
)
// Runtime API
@@ -452,7 +451,7 @@ func getRegistries() ([]string, error) {
// ImageFilter is a function to determine whether an image is included in
// command output. Images to be outputted are tested using the function. A true
// return will include the image, a false return will exclude it.
-type ImageFilter func(*storage.Image, *types.ImageInspectInfo) bool
+type ImageFilter func(*storage.Image, *ImageData) bool
func (ips imageDecomposeStruct) returnFQName() string {
return fmt.Sprintf("%s%s/%s:%s", ips.transport, ips.registry, ips.imageName, ips.tag)
@@ -1032,7 +1031,7 @@ func (r *Runtime) ImportImage(path string, options CopyOptions) error {
}
// GetImageInspectInfo returns the inspect information of an image
-func (r *Runtime) GetImageInspectInfo(image storage.Image) (*types.ImageInspectInfo, error) {
+func (r *Runtime) GetImageInspectInfo(image storage.Image) (*ImageData, error) {
r.lock.RLock()
defer r.lock.RUnlock()
@@ -1042,12 +1041,25 @@ func (r *Runtime) GetImageInspectInfo(image storage.Image) (*types.ImageInspectI
return r.getImageInspectInfo(image)
}
-func (r *Runtime) getImageInspectInfo(image storage.Image) (*types.ImageInspectInfo, error) {
- img, err := r.getImageRef(image.ID)
+func (r *Runtime) getImageInspectInfo(image storage.Image) (*ImageData, error) {
+ imgRef, err := r.getImageRef("@" + image.ID)
if err != nil {
- return nil, err
+ return nil, errors.Wrapf(err, "error reading image %q", image.ID)
+ }
+
+ layer, err := r.store.Layer(image.TopLayer)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error reading information about layer %q", image.TopLayer)
+ }
+ size, err := r.store.DiffSize(layer.Parent, layer.ID)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error determining size of layer %q", layer.ID)
+ }
+ driverData, err := driver.GetDriverData(r.store, layer.ID)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting graph driver info %q", image.ID)
}
- return img.Inspect()
+ return getImageData(image, imgRef, size, driverData)
}
// ParseImageFilter takes a set of images and a filter string as input, and returns the libpod.ImageFilterParams struct
@@ -1093,7 +1105,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
if err != nil {
return nil, err
}
- params.BeforeImage = info.Created
+ params.BeforeImage = *info.Created
} else {
return nil, fmt.Errorf("no such id: %s", pair[0])
}
@@ -1103,7 +1115,7 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
if err != nil {
return nil, err
}
- params.SinceImage = info.Created
+ params.SinceImage = *info.Created
} else {
return nil, fmt.Errorf("no such id: %s``", pair[0])
}
@@ -1116,43 +1128,6 @@ func (r *Runtime) ParseImageFilter(imageInput, filter string) (*ImageFilterParam
return &params, nil
}
-// InfoAndDigestAndSize returns the inspection info and size of the image in the given
-// store and the digest of its manifest, if it has one, or "" if it doesn't.
-func (r *Runtime) InfoAndDigestAndSize(img storage.Image) (*types.ImageInspectInfo, digest.Digest, int64, error) {
- r.lock.RLock()
- defer r.lock.RUnlock()
-
- if !r.valid {
- return nil, "", -1, ErrRuntimeStopped
- }
-
- imgRef, err := r.getImageRef("@" + img.ID)
- if err != nil {
- return nil, "", -1, errors.Wrapf(err, "error reading image %q", img.ID)
- }
- return infoAndDigestAndSize(imgRef)
-}
-
-func infoAndDigestAndSize(imgRef types.Image) (*types.ImageInspectInfo, digest.Digest, int64, error) {
- imgSize, err := imgRef.Size()
- if err != nil {
- return nil, "", -1, errors.Wrapf(err, "error reading size of image %q", transports.ImageName(imgRef.Reference()))
- }
- manifest, _, err := imgRef.Manifest()
- if err != nil {
- return nil, "", -1, errors.Wrapf(err, "error reading manifest for image %q", transports.ImageName(imgRef.Reference()))
- }
- manifestDigest := digest.Digest("")
- if len(manifest) > 0 {
- manifestDigest = digest.Canonical.FromBytes(manifest)
- }
- info, err := imgRef.Inspect()
- if err != nil {
- return nil, "", -1, errors.Wrapf(err, "error inspecting image %q", transports.ImageName(imgRef.Reference()))
- }
- return info, manifestDigest, imgSize, nil
-}
-
// MatchesID returns true if argID is a full or partial match for id
func MatchesID(id, argID string) bool {
return strings.HasPrefix(argID, id)