diff --git a/pkg/storage/image.go b/pkg/storage/image.go index 4ea8eb8c..f3f2d43d 100644 --- a/pkg/storage/image.go +++ b/pkg/storage/image.go @@ -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 { diff --git a/server/container_create.go b/server/container_create.go index 78c7e6c9..e23dedb6 100644 --- a/server/container_create.go +++ b/server/container_create.go @@ -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, diff --git a/server/container_list.go b/server/container_list.go index d32eea2d..060fa2af 100644 --- a/server/container_list.go +++ b/server/container_list.go @@ -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 { diff --git a/server/container_status.go b/server/container_status.go index f81be56f..3b84468f 100644 --- a/server/container_status.go +++ b/server/container_status.go @@ -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() { diff --git a/server/image_list.go b/server/image_list.go index cbbd0d83..bcdc1036 100644 --- a/server/image_list.go +++ b/server/image_list.go @@ -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, }) } } diff --git a/server/image_pull.go b/server/image_pull.go index 2c7e8b2c..67dfc469 100644 --- a/server/image_pull.go +++ b/server/image_pull.go @@ -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 diff --git a/server/image_status.go b/server/image_status.go index c01a350c..4e2e6a0e 100644 --- a/server/image_status.go +++ b/server/image_status.go @@ -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) diff --git a/server/inspect.go b/server/inspect.go index 2aaac841..d1fe6abe 100644 --- a/server/inspect.go +++ b/server/inspect.go @@ -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(), diff --git a/server/inspect_test.go b/server/inspect_test.go index c970fcd0..7246ef86 100644 --- a/server/inspect_test.go +++ b/server/inspect_test.go @@ -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) diff --git a/test/helpers.bash b/test/helpers.bash index c698687a..60f24ce5 100644 --- a/test/helpers.bash +++ b/test/helpers.bash @@ -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() { diff --git a/test/image.bats b/test/image.bats index 65a047f6..ac609180 100644 --- a/test/image.bats +++ b/test/image.bats @@ -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" != "" ] diff --git a/test/inspect.bats b/test/inspect.bats index bfbf82a0..bb7977e5 100644 --- a/test/inspect.bats +++ b/test/inspect.bats @@ -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" diff --git a/types/types.go b/types/types.go index 63780143..cedc3abd 100644 --- a/types/types.go +++ b/types/types.go @@ -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"`