diff --git a/cmd/crictl/image.go b/cmd/crictl/image.go index 7e8b8a21c8..50a3fae349 100644 --- a/cmd/crictl/image.go +++ b/cmd/crictl/image.go @@ -20,6 +20,8 @@ import ( "context" "errors" "fmt" + "regexp" + "slices" "sort" "strings" "syscall" @@ -142,6 +144,11 @@ var listImageCommand = &cli.Command{ Aliases: []string{"q"}, Usage: "Only show image IDs", }, + &cli.StringSliceFlag{ + Name: "filter", + Aliases: []string{"f"}, + Usage: "The filtering flag format is of 'dangling=(true/false)', 'reference=regex', '(before|since)=<image-name>[:<tag>]|<image id>|<image@digest>'", + }, &cli.StringFlag{ Name: "output", Aliases: []string{"o"}, @@ -174,8 +181,16 @@ var listImageCommand = &cli.Command{ if err != nil { return fmt.Errorf("listing images: %w", err) } + sort.Sort(imageByRef(r.Images)) + if len(c.StringSlice("filter")) > 0 && len(r.Images) > 0 { + r.Images, err = filterImagesList(r.Images, c.StringSlice("filter")) + if err != nil { + return fmt.Errorf("listing images: %w", err) + } + } + switch c.String("output") { case "json": return outputProtobufObjAsJSON(r) @@ -524,7 +539,6 @@ var imageFsInfoCommand = &cli.Command{ tablePrintFileSystem("Image", r.ImageFilesystems) return nil - }, } @@ -650,6 +664,89 @@ func ListImages(client internalapi.ImageManagerService, image string) (*pb.ListI return resp, nil } +// filterImagesList filter images based on --filter flag +func filterImagesList(imageList []*pb.Image, filters []string) ([]*pb.Image, error) { + filtered := []*pb.Image{} + filtered = append(filtered, imageList...) + for _, filter := range filters { + switch { + case strings.HasPrefix(filter, "before="): + reversedList := filtered + slices.Reverse(reversedList) + filtered = filterByBeforeSince(strings.TrimPrefix(filter, "before="), reversedList) + slices.Reverse(filtered) + case strings.HasPrefix(filter, "dangling="): + filtered = filterByDangling(strings.TrimPrefix(filter, "dangling="), filtered) + case strings.HasPrefix(filter, "reference="): + filtered = filterByReference(strings.TrimPrefix(filter, "reference="), filtered) + case strings.HasPrefix(filter, "since="): + filtered = filterByBeforeSince(strings.TrimPrefix(filter, "since="), filtered) + default: + return []*pb.Image{}, fmt.Errorf("Unknown filter flag: %v", filter) + } + } + return filtered, nil +} + +func filterByBeforeSince(filterValue string, imageList []*pb.Image) []*pb.Image { + filtered := []*pb.Image{} + for _, img := range imageList { + // Filter by <image-name>[:<tag>] + if strings.Contains(filterValue, ":") && !strings.Contains(filterValue, "@") { + imageName, _ := normalizeRepoDigest(img.RepoDigests) + repoTagPairs := normalizeRepoTagPair(img.RepoTags, imageName) + if strings.Join(repoTagPairs[0], ":") == filterValue { + break + } + filtered = append(filtered, img) + } + // Filter by <image id> + if !strings.Contains(filterValue, ":") && !strings.Contains(filterValue, "@") { + if strings.HasPrefix(img.Id, filterValue) { + break + } + filtered = append(filtered, img) + } + // Filter by <image@sha> + if strings.Contains(filterValue, ":") && strings.Contains(filterValue, "@") { + if len(img.RepoDigests) > 0 { + if strings.HasPrefix(img.RepoDigests[0], filterValue) { + break + } + filtered = append(filtered, img) + } + } + } + return filtered +} + +func filterByReference(filterValue string, imageList []*pb.Image) []*pb.Image { + filtered := []*pb.Image{} + re, _ := regexp.Compile(filterValue) + for _, img := range imageList { + imgName, _ := normalizeRepoDigest(img.RepoDigests) + if re.MatchString(imgName) || imgName == filterValue { + filtered = append(filtered, img) + } + } + + return filtered +} + +func filterByDangling(filterValue string, imageList []*pb.Image) []*pb.Image { + filtered := []*pb.Image{} + for _, img := range imageList { + if filterValue == "true" && len(img.RepoTags) == 0 { + filtered = append(filtered, img) + } + if filterValue == "false" && len(img.RepoTags) > 0 { + filtered = append(filtered, img) + } + } + + return filtered +} + // ImageStatus sends an ImageStatusRequest to the server, and parses // the returned ImageStatusResponse. func ImageStatus(client internalapi.ImageManagerService, image string, verbose bool) (*pb.ImageStatusResponse, error) { diff --git a/cmd/crictl/image_test.go b/cmd/crictl/image_test.go new file mode 100644 index 0000000000..92ee54d5e5 --- /dev/null +++ b/cmd/crictl/image_test.go @@ -0,0 +1,181 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + pb "k8s.io/cri-api/pkg/apis/runtime/v1" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func fakeImage(id string, digest []string, tags []string) *pb.Image { + return &pb.Image{Id: id, RepoDigests: digest, RepoTags: tags} +} + +func assert(input []*pb.Image, options []string, images []string) { + actual, _ := filterImagesList(input, options) + expected := []string{} + for _, img := range actual { + expected = append(expected, img.Id) + } + Expect(images).To(Equal(expected)) +} + +var _ = DescribeTable("filterImagesListByDangling", assert, + Entry("returns filtered images with dangling --filter=dangling=true", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/busybox@sha256:1"}, []string{}), + fakeImage("2", []string{"docker.io/library/nginx@sha256:2"}, []string{"latest"}), + }, + []string{"dangling=true"}, + []string{"1"}, + ), + Entry("returns filtered images with dangling --filter=dangling=false", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"1.2.2"}), + }, + []string{"dangling=false"}, + []string{"2", "4"}, + ), +) + +var _ = DescribeTable("filterImagesListByReference", assert, + Entry("returns filtered images with one reference --filter=reference=busybox", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/busybox@sha256:1"}, []string{"latest"}), + fakeImage("2", []string{"docker.io/library/nginx@sha256:2"}, []string{"latest"}), + }, + []string{"reference=busybox"}, + []string{"1"}, + ), + Entry("returns filtered images with many reference --filter=reference=busybox, --filter=reference=k8s", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"1.2.2"}), + fakeImage("5", []string{"registry.k8s.io/e2e-test-images/busybox@sha256:5"}, []string{"1.2.2"}), + }, + []string{"reference=busybox", "reference=k8s"}, + []string{"5"}, + ), +) + +var _ = DescribeTable("filterImagesListByBefore", assert, + Entry("returns filtered images with --filter=before=<image-name>[:<tag>]", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"before=docker.io/library/nginx:1.0.0"}, + []string{"4"}, + ), + Entry("returns filtered images with --filter=before=<image id>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"before=1"}, + []string{"2", "3", "4"}, + ), + Entry("returns filtered images with --filter=before=<image@digest>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"before=docker.io/library/busybox@sha256:2"}, + []string{"3", "4"}, + ), +) + +var _ = DescribeTable("filterImagesListBySince", assert, + Entry("returns filtered images with --filter=since=<image-name>[:<tag>]", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"since=docker.io/library/busybox:1.2.0"}, + []string{"1"}, + ), + Entry("returns filtered images with --filter=since=<image id>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"since=3"}, + []string{"1", "2"}, + ), + Entry("returns filtered images with --filter=since=<image@digest>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"since=docker.io/library/nginx@sha256:3"}, + []string{"1", "2"}, + ), +) + +var _ = DescribeTable("filterImagesListByChainable", assert, + Entry("returns filtered images with --filter=since=<image-id> and --filter=reference=<ref>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"docker.io/library/server:0.0.0"}), + fakeImage("2", []string{"docker.io/library/busybox@sha256:2"}, []string{"docker.io/library/busybox:1.2.0"}), + fakeImage("3", []string{"docker.io/library/nginx@sha256:3"}, []string{"docker.io/library/nginx:1.0.0"}), + fakeImage("4", []string{"docker.io/library/app@sha256:4"}, []string{"docker.io/library/app:1.2.2"}), + }, + []string{"since=3", "reference=busybox"}, + []string{"2"}, + ), + Entry("returns filtered images with --filter=since=<image-id> and --filter=reference=<ref>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"0.0.0"}), + fakeImage("2", []string{"registry.k8s.io/e2e-test-images/busybox@sha256:5"}, []string{"1.2.2"}), + fakeImage("3", []string{"docker.io/library/busybox@sha256:2"}, []string{"1.2.0"}), + fakeImage("4", []string{"docker.io/library/nginx@sha256:3"}, []string{"1.0.0"}), + fakeImage("5", []string{"docker.io/library/app@sha256:4"}, []string{"1.2.2"}), + }, + []string{"since=5", "reference=busybox"}, + []string{"2", "3"}, + ), + Entry("returns empty images list --filter=since=<image-id> and --filter=reference=<ref>", + []*pb.Image{ + fakeImage("1", []string{"docker.io/library/server@sha256:1"}, []string{"0.0.0"}), + fakeImage("2", []string{"registry.k8s.io/e2e-test-images/busybox@sha256:5"}, []string{"1.2.2"}), + fakeImage("3", []string{"docker.io/library/busybox@sha256:2"}, []string{"1.2.0"}), + fakeImage("4", []string{"docker.io/library/nginx@sha256:3"}, []string{"1.0.0"}), + fakeImage("5", []string{"docker.io/library/app@sha256:4"}, []string{"1.2.2"}), + }, + []string{"since=5", "reference=kubefun"}, + []string{}, + ), +) diff --git a/docs/crictl.1 b/docs/crictl.1 index 3c7e08a519..1594fe989a 100644 --- a/docs/crictl.1 +++ b/docs/crictl.1 @@ -343,6 +343,22 @@ To override these default pull configuration settings, \fB\fC\-\-no\-pull\fR and .RE .SH Examples +.RS +.IP \(bu 2 +Run pod sandbox with config file +\[la]#run-pod-sandbox-with-config-file\[ra] +.IP \(bu 2 +Run pod sandbox with runtime handler +\[la]#run-pod-sandbox-with-runtime-handler\[ra] +.IP \(bu 2 +Pull a busybox image +\[la]#pull-a-busybox-image\[ra] +.IP \(bu 2 +Filter images +\[la]#filter-images\[ra] + +.RE + .SS Run pod sandbox with config file .PP .RS @@ -443,6 +459,153 @@ k8s.gcr.io/pause 3.1 da86e6ba6ca19 742kB .fi .RE +.SS Filter images +.PP +The following filters are available \fB\fC\-\-filter\fR, \fB\fC\-f\fR, filters are chainable and processed in the declared order: + +.RS +.IP " 1." 5 +\fB\fCbefore=<image\-name>[:<tag>]|<image id>|<image@digest>\fR +.IP " 2." 5 +\fB\fCdangling=(true/false)\fR +.IP " 3." 5 +\fB\fCreference=/regex/\fR +.IP " 4." 5 +\fB\fCsince=<image\-name>[:<tag>]|<image id>|<image@digest>\fR + +.RE + +.PP +List all images: + +.PP +.RS + +.nf +$ crictl images \-\-digests +IMAGE TAG DIGEST IMAGE ID SIZE +docker.io/library/busybox latest 538721340ded1 3f57d9401f8d4 4.5MB +docker.io/library/nginx latest 05aa73005987c e4720093a3c13 191MB +gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64 latest aa74ea387dbbe 1ee3f9825c42b 147MB +gcr.io/k8s\-staging\-cri\-tools/test\-image\-predefined\-group latest 2b2fc189c502a 84410ab6e30d9 5.11MB +registry.k8s.io/e2e\-test\-images/busybox 1.29\-2 c318242786b13 84eebb9ca1734 1.37MB +registry.k8s.io/e2e\-test\-images/httpd 2.4.39\-4 3fe7acf013d12 444b9e2765dc9 132MB +registry.k8s.io/e2e\-test\-images/nginx 1.14\-2 13616070e3f29 02e45a31af51c 17.2MB +registry.k8s.io/e2e\-test\-images/nonewprivs 1.3 8ac1264691820 3e3d1785c0b6e 7.37MB +registry.k8s.io/pause 3.9 7031c1b283388 e6f1816883972 750kB + +.fi +.RE + +.PP +List images by \fB\fCreference\fR: + +.PP +.RS + +.nf +$ crictl images \-\-filter 'reference=k8s' +IMAGE TAG IMAGE ID SIZE +gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64 latest 1ee3f9825c42b 147MB +gcr.io/k8s\-staging\-cri\-tools/test\-image\-predefined\-group latest 84410ab6e30d9 5.11MB +registry.k8s.io/e2e\-test\-images/busybox 1.29\-2 84eebb9ca1734 1.37MB +registry.k8s.io/e2e\-test\-images/httpd 2.4.39\-4 444b9e2765dc9 132MB +registry.k8s.io/e2e\-test\-images/nginx 1.14\-2 02e45a31af51c 17.2MB +registry.k8s.io/e2e\-test\-images/nonewprivs 1.3 3e3d1785c0b6e 7.37MB +registry.k8s.io/pause 3.9 e6f1816883972 750kB + +.fi +.RE + +.PP +List images by \fB\fCreference\fR with regex: + +.PP +.RS + +.nf +$ crictl images \-\-filter 'reference=nginx' +IMAGE TAG IMAGE ID SIZE +docker.io/library/nginx latest e4720093a3c13 191MB +gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64 latest 1ee3f9825c42b 147MB +registry.k8s.io/e2e\-test\-images/nginx 1.14\-2 02e45a31af51c 17.2MB +$ crictl images \-\-filter 'reference=.*(nginx)$' +IMAGE TAG IMAGE ID SIZE +docker.io/library/nginx latest e4720093a3c13 191MB +registry.k8s.io/e2e\-test\-images/nginx 1.14\-2 02e45a31af51c 17.2MB + +.fi +.RE + +.PP +Chain \fB\fC\-\-filter\fR: + +.PP +.RS + +.nf +$ crictl images \-\-filter 'reference=nginx' \-\-filter 'reference=\\.k8s\\.' +IMAGE TAG IMAGE ID SIZE +registry.k8s.io/e2e\-test\-images/nginx 1.14\-2 02e45a31af51c 17.2MB +$ crictl images \-\-filter 'since=registry.k8s.io/e2e\-test\-images/busybox@sha256:c318242786b139d18676b1c09a0ad7f15fc17f8f16a5b2e625cd0dc8c9703daf' \-\-filter 'reference=nginx' +IMAGE TAG IMAGE ID SIZE +docker.io/library/nginx latest e4720093a3c13 191MB +gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64 latest 1ee3f9825c42b 147MB + +.fi +.RE + +.PP +List images \fB\fCbefore=<image\-name>[:<tag>]\fR: + +.PP +.RS + +.nf +$ crictl images \-\-filter 'before=gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64:latest' +IMAGE TAG IMAGE ID SIZE +gcr.io/k8s\-staging\-cri\-tools/test\-image\-predefined\-group latest 84410ab6e30d9 5.11MB +registry.k8s.io/e2e\-test\-images/busybox 1.29\-2 84eebb9ca1734 1.37MB +registry.k8s.io/e2e\-test\-images/httpd 2.4.39\-4 444b9e2765dc9 132MB +registry.k8s.io/e2e\-test\-images/nginx 1.14\-2 02e45a31af51c 17.2MB +registry.k8s.io/e2e\-test\-images/nonewprivs 1.3 3e3d1785c0b6e 7.37MB +registry.k8s.io/pause 3.9 e6f1816883972 750kB + +.fi +.RE + +.PP +List images \fB\fCsince=<image\-name>[:<tag>]\fR: + +.PP +.RS + +.nf +$ crictl images \-\-filter 'since=gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64:latest' +IMAGE TAG IMAGE ID SIZE +docker.io/library/busybox latest 3f57d9401f8d4 4.5MB +docker.io/library/nginx latest e4720093a3c13 191MB + +.fi +.RE + +.PP +List images \fB\fCsince=<image@digest>\fR: + +.PP +.RS + +.nf +crictl images \-\-filter 'since=registry.k8s.io/e2e\-test\-images/busybox@sha256:c318242786b139d18676b1c09a0ad7f15fc17f8f16a5b2e625cd0dc8c9703daf' +IMAGE TAG IMAGE ID SIZE +docker.io/library/busybox latest 3f57d9401f8d4 4.5MB +docker.io/library/nginx latest e4720093a3c13 191MB +gcr.io/k8s\-staging\-cri\-tools/hostnet\-nginx\-amd64 latest 1ee3f9825c42b 147MB +gcr.io/k8s\-staging\-cri\-tools/test\-image\-predefined\-group latest 84410ab6e30d9 5.11MB + +.fi +.RE + .SS Create container in the pod sandbox with config file .PP .RS diff --git a/docs/crictl.md b/docs/crictl.md index 65c87ce452..8b049db796 100644 --- a/docs/crictl.md +++ b/docs/crictl.md @@ -182,6 +182,11 @@ Some users of `crictl` may desire to set `disable-pull-on-run` to `true` to not ## Examples +- [Run pod sandbox with config file](#run-pod-sandbox-with-config-file) +- [Run pod sandbox with runtime handler](#run-pod-sandbox-with-runtime-handler) +- [Pull a busybox image](#pull-a-busybox-image) +- [Filter images](#filter-images) + ### Run pod sandbox with config file ```sh @@ -257,6 +262,104 @@ busybox latest 8c811b4aec35f 1.15MB k8s.gcr.io/pause 3.1 da86e6ba6ca19 742kB ``` +### Filter images + +The following filters are available `--filter`, `-f`, filters are chainable and processed in the declared order: + +1. `before=<image-name>[:<tag>]|<image id>|<image@digest>` +1. `dangling=(true/false)` +1. `reference=/regex/` +1. `since=<image-name>[:<tag>]|<image id>|<image@digest>` + +List all images: + +```sh +$ crictl images --digests +IMAGE TAG DIGEST IMAGE ID SIZE +docker.io/library/busybox latest 538721340ded1 3f57d9401f8d4 4.5MB +docker.io/library/nginx latest 05aa73005987c e4720093a3c13 191MB +gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64 latest aa74ea387dbbe 1ee3f9825c42b 147MB +gcr.io/k8s-staging-cri-tools/test-image-predefined-group latest 2b2fc189c502a 84410ab6e30d9 5.11MB +registry.k8s.io/e2e-test-images/busybox 1.29-2 c318242786b13 84eebb9ca1734 1.37MB +registry.k8s.io/e2e-test-images/httpd 2.4.39-4 3fe7acf013d12 444b9e2765dc9 132MB +registry.k8s.io/e2e-test-images/nginx 1.14-2 13616070e3f29 02e45a31af51c 17.2MB +registry.k8s.io/e2e-test-images/nonewprivs 1.3 8ac1264691820 3e3d1785c0b6e 7.37MB +registry.k8s.io/pause 3.9 7031c1b283388 e6f1816883972 750kB +``` + +List images by `reference`: + +```sh +$ crictl images --filter 'reference=k8s' +IMAGE TAG IMAGE ID SIZE +gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64 latest 1ee3f9825c42b 147MB +gcr.io/k8s-staging-cri-tools/test-image-predefined-group latest 84410ab6e30d9 5.11MB +registry.k8s.io/e2e-test-images/busybox 1.29-2 84eebb9ca1734 1.37MB +registry.k8s.io/e2e-test-images/httpd 2.4.39-4 444b9e2765dc9 132MB +registry.k8s.io/e2e-test-images/nginx 1.14-2 02e45a31af51c 17.2MB +registry.k8s.io/e2e-test-images/nonewprivs 1.3 3e3d1785c0b6e 7.37MB +registry.k8s.io/pause 3.9 e6f1816883972 750kB +``` + +List images by `reference` with regex: + +```sh +$ crictl images --filter 'reference=nginx' +IMAGE TAG IMAGE ID SIZE +docker.io/library/nginx latest e4720093a3c13 191MB +gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64 latest 1ee3f9825c42b 147MB +registry.k8s.io/e2e-test-images/nginx 1.14-2 02e45a31af51c 17.2MB +$ crictl images --filter 'reference=.*(nginx)$' +IMAGE TAG IMAGE ID SIZE +docker.io/library/nginx latest e4720093a3c13 191MB +registry.k8s.io/e2e-test-images/nginx 1.14-2 02e45a31af51c 17.2MB +``` + +Chain `--filter`: + +```sh +$ crictl images --filter 'reference=nginx' --filter 'reference=\.k8s\.' +IMAGE TAG IMAGE ID SIZE +registry.k8s.io/e2e-test-images/nginx 1.14-2 02e45a31af51c 17.2MB +$ crictl images --filter 'since=registry.k8s.io/e2e-test-images/busybox@sha256:c318242786b139d18676b1c09a0ad7f15fc17f8f16a5b2e625cd0dc8c9703daf' --filter 'reference=nginx' +IMAGE TAG IMAGE ID SIZE +docker.io/library/nginx latest e4720093a3c13 191MB +gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64 latest 1ee3f9825c42b 147MB +``` + +List images `before=<image-name>[:<tag>]`: + +```sh +$ crictl images --filter 'before=gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64:latest' +IMAGE TAG IMAGE ID SIZE +gcr.io/k8s-staging-cri-tools/test-image-predefined-group latest 84410ab6e30d9 5.11MB +registry.k8s.io/e2e-test-images/busybox 1.29-2 84eebb9ca1734 1.37MB +registry.k8s.io/e2e-test-images/httpd 2.4.39-4 444b9e2765dc9 132MB +registry.k8s.io/e2e-test-images/nginx 1.14-2 02e45a31af51c 17.2MB +registry.k8s.io/e2e-test-images/nonewprivs 1.3 3e3d1785c0b6e 7.37MB +registry.k8s.io/pause 3.9 e6f1816883972 750kB +``` + +List images `since=<image-name>[:<tag>]`: + +```sh +$ crictl images --filter 'since=gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64:latest' +IMAGE TAG IMAGE ID SIZE +docker.io/library/busybox latest 3f57d9401f8d4 4.5MB +docker.io/library/nginx latest e4720093a3c13 191MB +``` + +List images `since=<image@digest>`: + +```sh +crictl images --filter 'since=registry.k8s.io/e2e-test-images/busybox@sha256:c318242786b139d18676b1c09a0ad7f15fc17f8f16a5b2e625cd0dc8c9703daf' +IMAGE TAG IMAGE ID SIZE +docker.io/library/busybox latest 3f57d9401f8d4 4.5MB +docker.io/library/nginx latest e4720093a3c13 191MB +gcr.io/k8s-staging-cri-tools/hostnet-nginx-amd64 latest 1ee3f9825c42b 147MB +gcr.io/k8s-staging-cri-tools/test-image-predefined-group latest 84410ab6e30d9 5.11MB +``` + ### Create container in the pod sandbox with config file ```sh