summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
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)