Return image references from the storage package

The image's canonical reference is a name with a digest of the image's
manifest, so in imageService.ImageStatus() and
imageService.ListImages(), divide the image's name list into tagged and
digested values, and if we have names, add canonical versions.

In Server.ContainerStatus(), return the image name as it was given to us
as the image, and the image digested reference as the image reference.

In Server.ListImages(), be sure to only return tagged names in the
RepoTags field.  In Server.ImageStatus(), also return canonical
references in the RepoDigests field.

In Server.PullImage(), be sure that we consistently return the same
image reference for an image, whether we ended up pulling it or not.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
Nalin Dahyabhai 2017-07-12 12:41:38 -04:00
parent 553979e1fc
commit f3b7065bd8
13 changed files with 265 additions and 126 deletions

View File

@ -9,6 +9,7 @@ import (
"github.com/containers/image/copy"
"github.com/containers/image/docker/reference"
"github.com/containers/image/image"
"github.com/containers/image/manifest"
"github.com/containers/image/signature"
istorage "github.com/containers/image/storage"
"github.com/containers/image/transports/alltransports"
@ -25,12 +26,12 @@ var (
// ImageResult wraps a subset of information about an image: its ID, its names,
// and the size, if known, or nil if it isn't.
type ImageResult struct {
ID string
Names []string
Size *uint64
// TODO(runcom): this is an hack for https://github.com/kubernetes-incubator/cri-o/pull/1136
// drop this when we have proper image IDs (as in, image IDs should be just
// the config blog digest which is stable across same images).
ID string
Name string
RepoTags []string
RepoDigests []string
Size *uint64
Digest digest.Digest
ConfigDigest digest.Digest
}
@ -47,6 +48,11 @@ type imageService struct {
registries []string
}
// sizer knows its size.
type sizer interface {
Size() (int64, error)
}
// ImageServer wraps up various CRI-related activities into a reusable
// implementation.
type ImageServer interface {
@ -88,6 +94,66 @@ func (svc *imageService) getRef(name string) (types.ImageReference, error) {
return ref, nil
}
func sortNamesByType(names []string) (bestName string, tags, digests []string) {
for _, name := range names {
if len(name) > 72 && name[len(name)-72:len(name)-64] == "@sha256:" {
digests = append(digests, name)
} else {
tags = append(tags, name)
}
}
if len(digests) > 0 {
bestName = digests[0]
}
if len(tags) > 0 {
bestName = tags[0]
}
return bestName, tags, digests
}
func (svc *imageService) makeRepoDigests(knownRepoDigests, tags []string, imageID string) (imageDigest digest.Digest, repoDigests []string) {
// Look up the image's digest.
img, err := svc.store.Image(imageID)
if err != nil {
return "", knownRepoDigests
}
imageDigest = img.Digest
if imageDigest == "" {
imgDigest, err := svc.store.ImageBigDataDigest(imageID, storage.ImageDigestBigDataKey)
if err != nil || imgDigest == "" {
return "", knownRepoDigests
}
imageDigest = imgDigest
}
// If there are no names to convert to canonical references, we're done.
if len(tags) == 0 {
return imageDigest, knownRepoDigests
}
// We only want to supplement what's already explicitly in the list, so keep track of values
// that we already know.
digestMap := make(map[string]struct{})
repoDigests = knownRepoDigests
for _, repoDigest := range knownRepoDigests {
digestMap[repoDigest] = struct{}{}
}
// For each tagged name, parse the name, and if we can extract a named reference, convert
// it into a canonical reference using the digest and add it to the list.
for _, tag := range tags {
if ref, err2 := reference.ParseAnyReference(tag); err2 == nil {
if name, ok := ref.(reference.Named); ok {
trimmed := reference.TrimNamed(name)
if imageRef, err3 := reference.WithDigest(trimmed, imageDigest); err3 == nil {
if _, ok := digestMap[imageRef.String()]; !ok {
repoDigests = append(repoDigests, imageRef.String())
digestMap[imageRef.String()] = struct{}{}
}
}
}
}
}
return imageDigest, repoDigests
}
func (svc *imageService) ListImages(systemContext *types.SystemContext, filter string) ([]ImageResult, error) {
results := []ImageResult{}
if filter != "" {
@ -96,16 +162,26 @@ func (svc *imageService) ListImages(systemContext *types.SystemContext, filter s
return nil, err
}
if image, err := istorage.Transport.GetStoreImage(svc.store, ref); err == nil {
img, err := ref.NewImage(systemContext)
img, err := ref.NewImageSource(systemContext)
if err != nil {
return nil, err
}
size := imageSize(img)
configDigest, err := imageConfigDigest(img, nil)
img.Close()
if err != nil {
return nil, err
}
name, tags, digests := sortNamesByType(image.Names)
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
results = append(results, ImageResult{
ID: image.ID,
Names: image.Names,
Size: size,
ID: image.ID,
Name: name,
RepoTags: tags,
RepoDigests: repoDigests,
Size: size,
Digest: imageDigest,
ConfigDigest: configDigest,
})
}
} else {
@ -118,16 +194,26 @@ func (svc *imageService) ListImages(systemContext *types.SystemContext, filter s
if err != nil {
return nil, err
}
img, err := ref.NewImage(systemContext)
img, err := ref.NewImageSource(systemContext)
if err != nil {
return nil, err
}
size := imageSize(img)
configDigest, err := imageConfigDigest(img, nil)
img.Close()
if err != nil {
return nil, err
}
name, tags, digests := sortNamesByType(image.Names)
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
results = append(results, ImageResult{
ID: image.ID,
Names: image.Names,
Size: size,
ID: image.ID,
Name: name,
RepoTags: tags,
RepoDigests: repoDigests,
Size: size,
Digest: imageDigest,
ConfigDigest: configDigest,
})
}
}
@ -152,29 +238,54 @@ func (svc *imageService) ImageStatus(systemContext *types.SystemContext, nameOrI
return nil, err
}
img, err := ref.NewImage(systemContext)
img, err := ref.NewImageSource(systemContext)
if err != nil {
return nil, err
}
defer img.Close()
size := imageSize(img)
configDigest, err := imageConfigDigest(img, nil)
if err != nil {
return nil, err
}
return &ImageResult{
name, tags, digests := sortNamesByType(image.Names)
imageDigest, repoDigests := svc.makeRepoDigests(digests, tags, image.ID)
result := ImageResult{
ID: image.ID,
Names: image.Names,
Name: name,
RepoTags: tags,
RepoDigests: repoDigests,
Size: size,
ConfigDigest: img.ConfigInfo().Digest,
}, nil
Digest: imageDigest,
ConfigDigest: configDigest,
}
return &result, nil
}
func imageSize(img types.Image) *uint64 {
if sum, err := img.Size(); err == nil {
usum := uint64(sum)
return &usum
func imageSize(img types.ImageSource) *uint64 {
if s, ok := img.(sizer); ok {
if sum, err := s.Size(); err == nil {
usum := uint64(sum)
return &usum
}
}
return nil
}
func imageConfigDigest(img types.ImageSource, instanceDigest *digest.Digest) (digest.Digest, error) {
manifestBytes, manifestType, err := img.GetManifest(instanceDigest)
if err != nil {
return "", err
}
imgManifest, err := manifest.FromBlob(manifestBytes, manifestType)
if err != nil {
return "", err
}
return imgManifest.ConfigInfo().Digest, nil
}
func (svc *imageService) CanPull(imageName string, options *copy.Options) (bool, error) {
srcRef, err := svc.prepareReference(imageName, options)
if err != nil {

View File

@ -14,7 +14,6 @@ import (
"strings"
"time"
"github.com/docker/distribution/reference"
dockermounts "github.com/docker/docker/pkg/mount"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/docker/pkg/symlink"
@ -963,40 +962,19 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
return nil, err
}
}
image = images[0]
// Get imageName and imageRef that are requested in container status
imageName := image
status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), image)
// Get imageName and imageRef that are later requested in container status
status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), images[0])
if err != nil {
return nil, err
}
imageName := status.Name
imageRef := status.ID
//
// TODO: https://github.com/kubernetes-incubator/cri-o/issues/531
//
//for _, n := range status.Names {
//r, err := reference.ParseNormalizedNamed(n)
//if err != nil {
//return nil, fmt.Errorf("failed to normalize image name for ImageRef: %v", err)
//}
//if digested, isDigested := r.(reference.Canonical); isDigested {
//imageRef = reference.FamiliarString(digested)
//break
//}
//}
for _, n := range status.Names {
r, err := reference.ParseNormalizedNamed(n)
if err != nil {
return nil, fmt.Errorf("failed to normalize image name for Image: %v", err)
}
if tagged, isTagged := r.(reference.Tagged); isTagged {
imageName = reference.FamiliarString(tagged)
break
}
if len(status.RepoDigests) > 0 {
imageRef = status.RepoDigests[0]
}
specgen.AddAnnotation(annotations.Image, image)
specgen.AddAnnotation(annotations.ImageName, imageName)
specgen.AddAnnotation(annotations.ImageRef, imageRef)
specgen.AddAnnotation(annotations.IP, sb.IP())
@ -1043,7 +1021,6 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
specgen.AddAnnotation(annotations.TTY, fmt.Sprintf("%v", containerConfig.Tty))
specgen.AddAnnotation(annotations.Stdin, fmt.Sprintf("%v", containerConfig.Stdin))
specgen.AddAnnotation(annotations.StdinOnce, fmt.Sprintf("%v", containerConfig.StdinOnce))
specgen.AddAnnotation(annotations.Image, image)
specgen.AddAnnotation(annotations.ResolvPath, sb.InfraContainer().CrioAnnotations()[annotations.ResolvPath])
created := time.Now()
@ -1079,7 +1056,7 @@ func (s *Server) createSandboxContainer(ctx context.Context, containerID string,
attempt := metadata.Attempt
containerInfo, err := s.StorageRuntimeServer().CreateContainer(s.ImageContext(),
sb.Name(), sb.ID(),
image, image,
image, status.ID,
containerName, containerID,
metaname,
attempt,

View File

@ -97,6 +97,7 @@ func (s *Server) ListContainers(ctx context.Context, req *pb.ListContainersReque
Metadata: ctr.Metadata(),
Annotations: ctr.Annotations(),
Image: img,
ImageRef: ctr.ImageRef(),
}
switch cState.Status {

View File

@ -3,6 +3,7 @@ package server
import (
"time"
"github.com/containers/image/types"
"github.com/kubernetes-incubator/cri-o/oci"
"github.com/sirupsen/logrus"
"golang.org/x/net/context"
@ -38,7 +39,10 @@ func (s *Server) ContainerStatus(ctx context.Context, req *pb.ContainerStatusReq
ImageRef: c.ImageRef(),
},
}
resp.Status.Image = &pb.ImageSpec{Image: c.ImageName()}
resp.Status.Image = &pb.ImageSpec{Image: c.Image()}
if status, err := s.StorageImageServer().ImageStatus(&types.SystemContext{}, c.ImageRef()); err == nil {
resp.Status.Image.Image = status.Name
}
mounts := []*pb.Mount{}
for _, cv := range c.Volumes() {

View File

@ -33,14 +33,16 @@ func (s *Server) ListImages(ctx context.Context, req *pb.ListImagesRequest) (res
for _, result := range results {
if result.Size != nil {
resp.Images = append(resp.Images, &pb.Image{
Id: result.ID,
RepoTags: result.Names,
Size_: *result.Size,
Id: result.ID,
RepoTags: result.RepoTags,
RepoDigests: result.RepoDigests,
Size_: *result.Size,
})
} else {
resp.Images = append(resp.Images, &pb.Image{
Id: result.ID,
RepoTags: result.Names,
Id: result.ID,
RepoTags: result.RepoTags,
RepoDigests: result.RepoDigests,
})
}
}

View File

@ -104,8 +104,16 @@ func (s *Server) PullImage(ctx context.Context, req *pb.PullImageRequest) (resp
if pulled == "" && err != nil {
return nil, err
}
status, err := s.StorageImageServer().ImageStatus(s.ImageContext(), pulled)
if err != nil {
return nil, err
}
imageRef := status.ID
if len(status.RepoDigests) > 0 {
imageRef = status.RepoDigests[0]
}
resp = &pb.PullImageResponse{
ImageRef: pulled,
ImageRef: imageRef,
}
logrus.Debugf("PullImageResponse: %+v", resp)
return resp, nil

View File

@ -48,10 +48,10 @@ func (s *Server) ImageStatus(ctx context.Context, req *pb.ImageStatusRequest) (r
}
resp = &pb.ImageStatusResponse{
Image: &pb.Image{
Id: status.ID,
RepoTags: status.Names,
Size_: *status.Size,
// TODO: https://github.com/kubernetes-incubator/cri-o/issues/531
Id: status.ID,
RepoTags: status.RepoTags,
RepoDigests: status.RepoDigests,
Size_: *status.Size,
},
}
logrus.Debugf("ImageStatusResponse: %+v", resp)

View File

@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
cimage "github.com/containers/image/types"
"github.com/go-zoo/bone"
"github.com/kubernetes-incubator/cri-o/lib/sandbox"
"github.com/kubernetes-incubator/cri-o/oci"
@ -45,10 +46,17 @@ func (s *Server) getContainerInfo(id string, getContainerFunc func(id string) *o
logrus.Debugf("can't find sandbox %s for container %s", ctr.Sandbox(), id)
return types.ContainerInfo{}, errSandboxNotFound
}
image := ctr.Image()
if s.ContainerServer != nil && s.ContainerServer.StorageImageServer() != nil {
if status, err := s.ContainerServer.StorageImageServer().ImageStatus(&cimage.SystemContext{}, ctr.ImageRef()); err == nil {
image = status.Name
}
}
return types.ContainerInfo{
Name: ctr.Name(),
Pid: ctrState.Pid,
Image: ctr.ImageName(),
Image: image,
ImageRef: ctr.ImageRef(),
CreatedTime: ctrState.Created.UnixNano(),
Labels: ctr.Labels(),
Annotations: ctr.Annotations(),

View File

@ -67,7 +67,7 @@ func TestGetContainerInfo(t *testing.T) {
"io.kubernetes.test1": "value1",
}
getContainerFunc := func(id string) *oci.Container {
container, err := oci.NewContainer("testid", "testname", "", "/container/logs", mockNetNS{}, labels, annotations, annotations, "imageName", "imageName", "imageRef", &runtime.ContainerMetadata{}, "testsandboxid", false, false, false, false, false, "/root/for/container", created, "SIGKILL")
container, err := oci.NewContainer("testid", "testname", "", "/container/logs", mockNetNS{}, labels, annotations, annotations, "image", "imageName", "imageRef", &runtime.ContainerMetadata{}, "testsandboxid", false, false, false, false, false, "/root/for/container", created, "SIGKILL")
if err != nil {
t.Fatal(err)
}
@ -101,8 +101,11 @@ func TestGetContainerInfo(t *testing.T) {
if ci.Name != "testname" {
t.Fatalf("expected name testname, got %s", ci.Name)
}
if ci.Image != "imageName" {
t.Fatalf("expected image name imageName, got %s", ci.Image)
if ci.Image != "image" {
t.Fatalf("expected image name image, got %s", ci.Image)
}
if ci.ImageRef != "imageRef" {
t.Fatalf("expected image ref imageRef, got %s", ci.ImageRef)
}
if ci.Root != "/var/foo/container" {
t.Fatalf("expected root to be /var/foo/container, got %s", ci.Root)

View File

@ -103,7 +103,7 @@ cp "$CONMON_BINARY" "$TESTDIR/conmon"
PATH=$PATH:$TESTDIR
# Make sure we have a copy of the redis:latest image.
# Make sure we have a copy of the redis:alpine image.
if ! [ -d "$ARTIFACTS_PATH"/redis-image ]; then
mkdir -p "$ARTIFACTS_PATH"/redis-image
if ! "$COPYIMG_BINARY" --import-from=docker://redis:alpine --export-to=dir:"$ARTIFACTS_PATH"/redis-image --signature-policy="$INTEGRATION_ROOT"/policy.json ; then
@ -113,19 +113,6 @@ if ! [ -d "$ARTIFACTS_PATH"/redis-image ]; then
fi
fi
# TODO: remove the code below for redis digested image id when
# https://github.com/kubernetes-incubator/cri-o/issues/531 is complete
# as the digested reference will be auto-stored when pulling the tag
# above
if ! [ -d "$ARTIFACTS_PATH"/redis-image-digest ]; then
mkdir -p "$ARTIFACTS_PATH"/redis-image-digest
if ! "$COPYIMG_BINARY" --import-from=docker://redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b --export-to=dir:"$ARTIFACTS_PATH"/redis-image-digest --signature-policy="$INTEGRATION_ROOT"/policy.json ; then
echo "Error pulling docker://redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b"
rm -fr "$ARTIFACTS_PATH"/redis-image-digest
exit 1
fi
fi
# Make sure we have a copy of the runcom/stderr-test image.
if ! [ -d "$ARTIFACTS_PATH"/stderr-test ]; then
mkdir -p "$ARTIFACTS_PATH"/stderr-test
@ -226,13 +213,8 @@ function start_crio() {
"$BIN2IMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --source-binary "$PAUSE_BINARY"
fi
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=redis:alpine --import-from=dir:"$ARTIFACTS_PATH"/redis-image --add-name=docker.io/library/redis:alpine --signature-policy="$INTEGRATION_ROOT"/policy.json
# TODO: remove the code below for redis:alpine digested image id when
# https://github.com/kubernetes-incubator/cri-o/issues/531 is complete
# as the digested reference will be auto-stored when pulling the tag
# above
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b --import-from=dir:"$ARTIFACTS_PATH"/redis-image-digest --add-name=docker.io/library/redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=mrunalp/oom --import-from=dir:"$ARTIFACTS_PATH"/oom-image --add-name=docker.io/library/mrunalp/oom --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=mrunalp/image-volume-test --import-from=dir:"$ARTIFACTS_PATH"/image-volume-test-image --add-name=docker.io/library/mrunalp/image-volume-test --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=mrunalp/oom --import-from=dir:"$ARTIFACTS_PATH"/oom-image --add-name=docker.io/mrunalp/oom --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=mrunalp/image-volume-test --import-from=dir:"$ARTIFACTS_PATH"/image-volume-test-image --add-name=docker.io/mrunalp/image-volume-test --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=busybox:latest --import-from=dir:"$ARTIFACTS_PATH"/busybox-image --add-name=docker.io/library/busybox:latest --signature-policy="$INTEGRATION_ROOT"/policy.json
"$COPYIMG_BINARY" --root "$TESTDIR/crio" $STORAGE_OPTIONS --runroot "$TESTDIR/crio-run" --image-name=runcom/stderr-test:latest --import-from=dir:"$ARTIFACTS_PATH"/stderr-test --add-name=docker.io/runcom/stderr-test:latest --signature-policy="$INTEGRATION_ROOT"/policy.json
"$CRIO_BINARY" ${DEFAULT_MOUNTS_OPTS} ${HOOKS_OPTS} --conmon "$CONMON_BINARY" --listen "$CRIO_SOCKET" --cgroup-manager "$CGROUP_MANAGER" --registry "docker.io" --runtime "$RUNTIME_BINARY" --root "$TESTDIR/crio" --runroot "$TESTDIR/crio-run" $STORAGE_OPTIONS --seccomp-profile "$seccomp" --apparmor-profile "$apparmor" --cni-config-dir "$CRIO_CNI_CONFIG" --cni-plugin-dir "$CRIO_CNI_PLUGIN" --signature-policy "$INTEGRATION_ROOT"/policy.json --image-volumes "$IMAGE_VOLUMES" --pids-limit "$PIDS_LIMIT" --enable-shared-pid-namespace=${ENABLE_SHARED_PID_NAMESPACE} --log-size-max "$LOG_SIZE_MAX_LIMIT" --config /dev/null config >$CRIO_CONFIG
@ -252,44 +234,28 @@ function start_crio() {
if [ "$status" -ne 0 ] ; then
crictl pull redis:alpine
fi
REDIS_IMAGEID=$(crictl inspecti redis:alpine | head -1 | sed -e "s/ID: //g")
REDIS_IMAGEID=$(crictl inspecti redis:alpine | grep ^ID: | head -n 1 | sed -e "s/ID: //g")
REDIS_IMAGEREF=$(crictl inspecti redis:alpine | grep ^Digest: | head -n 1 | sed -e "s/Digest: //g")
run crictl inspecti mrunalp/oom
if [ "$status" -ne 0 ] ; then
crictl pull mrunalp/oom
fi
#
#
#
# TODO: remove the code below for redis digested image id when
# https://github.com/kubernetes-incubator/cri-o/issues/531 is complete
# as the digested reference will be auto-stored when pulling the tag
# above
#
#
#
REDIS_IMAGEID_DIGESTED="redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b"
run crictl inspecti $REDIS_IMAGEID_DIGESTED
if [ "$status" -ne 0 ]; then
crictl pull $REDIS_IMAGEID_DIGESTED
fi
#
#
#
run crictl inspecti runcom/stderr-test
OOM_IMAGEID=$(crictl inspecti mrunalp/oom | grep ^ID: | head -n 1 | sed -e "s/ID: //g")
run crioctl image status --id=runcom/stderr-test
if [ "$status" -ne 0 ] ; then
crictl pull runcom/stderr-test:latest
fi
STDERR_IMAGEID=$(crictl inspecti runcom/stderr-test | head -1 | sed -e "s/ID: //g")
STDERR_IMAGEID=$(crictl inspecti runcom/stderr-test | grep ^ID: | head -n 1 | sed -e "s/ID: //g")
run crictl inspecti busybox
if [ "$status" -ne 0 ] ; then
crictl pull busybox:latest
fi
BUSYBOX_IMAGEID=$(crictl inspecti busybox | head -1 | sed -e "s/ID: //g")
BUSYBOX_IMAGEID=$(crictl inspecti busybox | grep ^ID: | head -n 1 | sed -e "s/ID: //g")
run crictl inspecti mrunalp/image-volume-test
if [ "$status" -ne 0 ] ; then
crictl pull mrunalp/image-volume-test:latest
fi
VOLUME_IMAGEID=$(crictl inspecti mrunalp/image-volume-test | head -1 | sed -e "s/ID: //g")
VOLUME_IMAGEID=$(crictl inspecti mrunalp/image-volume-test | grep ^ID: | head -n 1 | sed -e "s/ID: //g")
}
function cleanup_ctrs() {

View File

@ -25,7 +25,7 @@ function teardown() {
stop_crio
}
@test "container status return image:tag if created by image ID" {
@test "container status when created by image ID" {
start_crio
run crictl runs "$TESTDATA"/sandbox_config.json
@ -43,16 +43,15 @@ function teardown() {
run crictl inspect "$ctr_id" --output yaml
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" =~ "image: redis:alpine" ]]
[[ "$output" =~ "image: docker.io/library/redis:alpine" ]]
[[ "$output" =~ "imageRef: $REDIS_IMAGEREF" ]]
cleanup_ctrs
cleanup_pods
stop_crio
}
@test "container status return image@digest if created by image ID and digest available" {
skip "depends on https://github.com/kubernetes-incubator/cri-o/issues/531"
@test "container status when created by image tagged reference" {
start_crio
run crictl runs "$TESTDATA"/sandbox_config.json
@ -60,9 +59,9 @@ function teardown() {
[ "$status" -eq 0 ]
pod_id="$output"
sed -e "s/%VALUE%/$REDIS_IMAGEID_DIGESTED/g" "$TESTDATA"/container_config_by_imageid.json > "$TESTDIR"/ctr_by_imageid.json
sed -e "s/%VALUE%/redis:alpine/g" "$TESTDATA"/container_config_by_imageid.json > "$TESTDIR"/ctr_by_imagetag.json
run crictl create "$pod_id" "$TESTDIR"/ctr_by_imageid.json "$TESTDATA"/sandbox_config.json
run crictl create "$pod_id" "$TESTDIR"/ctr_by_imagetag.json "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
ctr_id="$output"
@ -70,22 +69,51 @@ function teardown() {
run crictl inspect "$ctr_id" --output yaml
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" =~ "image_ref: redis@sha256:03789f402b2ecfb98184bf128d180f398f81c63364948ff1454583b02442f73b" ]]
[[ "$output" =~ "image: docker.io/library/redis:alpine" ]]
[[ "$output" =~ "imageRef: $REDIS_IMAGEREF" ]]
cleanup_ctrs
cleanup_pods
stop_crio
}
@test "image pull" {
@test "container status when created by image canonical reference" {
start_crio
run crictl runs "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
pod_id="$output"
sed -e "s|%VALUE%|$REDIS_IMAGEREF|g" "$TESTDATA"/container_config_by_imageid.json > "$TESTDIR"/ctr_by_imageref.json
run crictl create "$pod_id" "$TESTDIR"/ctr_by_imageref.json "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
ctr_id="$output"
run crictl inspect "$ctr_id" --output yaml
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" =~ "image: docker.io/library/redis:alpine" ]]
[[ "$output" =~ "imageRef: $REDIS_IMAGEREF" ]]
cleanup_ctrs
cleanup_pods
stop_crio
}
@test "image pull and list" {
start_crio "" "" --no-pause-image
run crictl pull "$IMAGE"
echo "$output"
[ "$status" -eq 0 ]
run crictl inspecti "$IMAGE"
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" =~ "$IMAGE" ]]
cleanup_images
stop_crio
}
@ -108,7 +136,33 @@ function teardown() {
stop_crio
}
@test "image pull and list by digest" {
@test "image pull and list by tag and ID" {
start_crio "" "" --no-pause-image
run crictl pull "$IMAGE:go"
echo "$output"
[ "$status" -eq 0 ]
run crictl images --quiet "$IMAGE:go"
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]
imageid="$output"
run crictl images --quiet @"$imageid"
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]
run crictl images --quiet "$imageid"
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]
cleanup_images
stop_crio
}
@test "image pull and list by digest and ID" {
start_crio "" "" --no-pause-image
run crictl pull nginx@sha256:33eb1ed1e802d4f71e52421f56af028cdf12bb3bfff5affeaf5bf0e328ffa1bc
echo "$output"
@ -118,18 +172,20 @@ function teardown() {
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]
imageid="$output"
run crictl images --quiet nginx@33eb1ed1e802d4f71e52421f56af028cdf12bb3bfff5affeaf5bf0e328ffa1bc
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]
imageid="$output"
run crictl images --quiet @33eb1ed1e802d4f71e52421f56af028cdf12bb3bfff5affeaf5bf0e328ffa1bc
run crictl images --quiet @"$imageid"
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]
run crictl images --quiet 33eb1ed1e802d4f71e52421f56af028cdf12bb3bfff5affeaf5bf0e328ffa1bc
run crictl images --quiet "$imageid"
[ "$status" -eq 0 ]
echo "$output"
[ "$output" != "" ]

View File

@ -30,13 +30,15 @@ function teardown() {
out=`echo -e "GET /containers/$ctr_id HTTP/1.1\r\nHost: crio\r\n" | socat - UNIX-CONNECT:$CRIO_SOCKET`
echo "$out"
[[ "$out" =~ "\"sandbox\":\"$pod_id\"" ]]
[[ "$out" =~ "\"image\":\"redis:alpine\"" ]]
[[ "$out" =~ "\"image\":\"docker.io/library/redis:alpine\"" ]]
[[ "$out" =~ "\"image_ref\":\"$REDIS_IMAGEREF\"" ]]
run crictl inspect --output json "$ctr_id"
echo "$output"
[ "$status" -eq 0 ]
[[ "$output" =~ "\"id\": \"$ctr_id\"" ]]
[[ "$output" =~ "\"image\": \"redis:alpine\"" ]]
[[ "$output" =~ "\"image\": \"docker.io/library/redis:alpine\"" ]]
[[ "$output" =~ "\"imageRef\": \"$REDIS_IMAGEREF\"" ]]
run crictl inspects --output json "$pod_id"
echo "$output"

View File

@ -5,6 +5,7 @@ type ContainerInfo struct {
Name string `json:"name"`
Pid int `json:"pid"`
Image string `json:"image"`
ImageRef string `json:"image_ref"`
CreatedTime int64 `json:"created_time"`
Labels map[string]string `json:"labels"`
Annotations map[string]string `json:"annotations"`