github.com/demonoid81/containerd@v1.3.4/image_test.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package containerd 18 19 import ( 20 "context" 21 "fmt" 22 "runtime" 23 "strings" 24 "testing" 25 26 "github.com/containerd/containerd/errdefs" 27 "github.com/containerd/containerd/images" 28 "github.com/containerd/containerd/platforms" 29 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 30 ) 31 32 func TestImageIsUnpacked(t *testing.T) { 33 if runtime.GOOS == "windows" { 34 t.Skip() 35 } 36 37 const imageName = "docker.io/library/busybox:latest" 38 ctx, cancel := testContext(t) 39 defer cancel() 40 41 client, err := newClient(t, address) 42 if err != nil { 43 t.Fatal(err) 44 } 45 defer client.Close() 46 47 // Cleanup 48 err = client.ImageService().Delete(ctx, imageName) 49 if err != nil && !errdefs.IsNotFound(err) { 50 t.Fatal(err) 51 } 52 53 // By default pull does not unpack an image 54 image, err := client.Pull(ctx, imageName, WithPlatform("linux/amd64")) 55 if err != nil { 56 t.Fatal(err) 57 } 58 59 // Check that image is not unpacked 60 unpacked, err := image.IsUnpacked(ctx, DefaultSnapshotter) 61 if err != nil { 62 t.Fatal(err) 63 } 64 if unpacked { 65 t.Fatalf("image should not be unpacked") 66 } 67 68 // Check that image is unpacked 69 err = image.Unpack(ctx, DefaultSnapshotter) 70 if err != nil { 71 t.Fatal(err) 72 } 73 unpacked, err = image.IsUnpacked(ctx, DefaultSnapshotter) 74 if err != nil { 75 t.Fatal(err) 76 } 77 if !unpacked { 78 t.Fatalf("image should be unpacked") 79 } 80 } 81 82 func TestImagePullWithDistSourceLabel(t *testing.T) { 83 var ( 84 source = "docker.io" 85 repoName = "library/busybox" 86 tag = "latest" 87 ) 88 89 ctx, cancel := testContext(t) 90 defer cancel() 91 92 client, err := newClient(t, address) 93 if err != nil { 94 t.Fatal(err) 95 } 96 defer client.Close() 97 98 imageName := fmt.Sprintf("%s/%s:%s", source, repoName, tag) 99 pMatcher := platforms.Default() 100 101 // pull content without unpack and add distribution source label 102 image, err := client.Pull(ctx, imageName, WithPlatformMatcher(pMatcher)) 103 if err != nil { 104 t.Fatal(err) 105 } 106 defer client.ImageService().Delete(ctx, imageName) 107 108 cs := client.ContentStore() 109 key := fmt.Sprintf("containerd.io/distribution.source.%s", source) 110 111 // only check the target platform 112 childrenHandler := images.FilterPlatforms(images.ChildrenHandler(cs), pMatcher) 113 114 checkLabelHandler := func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { 115 children, err := childrenHandler(ctx, desc) 116 if err != nil { 117 return nil, err 118 } 119 120 info, err := cs.Info(ctx, desc.Digest) 121 if err != nil { 122 return nil, err 123 } 124 125 // check the label 126 if got := info.Labels[key]; !strings.Contains(got, repoName) { 127 return nil, fmt.Errorf("expected to have %s repo name in label, but got %s", repoName, got) 128 } 129 return children, nil 130 } 131 132 if err := images.Dispatch(ctx, images.HandlerFunc(checkLabelHandler), nil, image.Target()); err != nil { 133 t.Fatal(err) 134 } 135 } 136 137 func TestImageUsage(t *testing.T) { 138 if testing.Short() || runtime.GOOS == "windows" { 139 t.Skip() 140 } 141 142 imageName := "docker.io/library/busybox:latest" 143 ctx, cancel := testContext(t) 144 defer cancel() 145 146 client, err := newClient(t, address) 147 if err != nil { 148 t.Fatal(err) 149 } 150 defer client.Close() 151 152 // Cleanup 153 err = client.ImageService().Delete(ctx, imageName) 154 if err != nil && !errdefs.IsNotFound(err) { 155 t.Fatal(err) 156 } 157 158 testPlatform := platforms.Only(ocispec.Platform{ 159 OS: "linux", 160 Architecture: "amd64", 161 }) 162 163 // Pull single platform, do not unpack 164 image, err := client.Pull(ctx, imageName, WithPlatformMatcher(testPlatform)) 165 if err != nil { 166 t.Fatal(err) 167 } 168 169 s1, err := image.Usage(ctx, WithUsageManifestLimit(1)) 170 if err != nil { 171 t.Fatal(err) 172 } 173 174 if _, err := image.Usage(ctx, WithUsageManifestLimit(0), WithManifestUsage()); err == nil { 175 t.Fatal("expected NotFound with missing manifests") 176 } else if !errdefs.IsNotFound(err) { 177 t.Fatalf("unexpected error: %+v", err) 178 } 179 180 // Pin image name to specific version for future fetches 181 imageName = imageName + "@" + image.Target().Digest.String() 182 183 // Fetch single platforms, but all manifests pulled 184 if _, err := client.Fetch(ctx, imageName, WithPlatformMatcher(testPlatform), WithAllMetadata()); err != nil { 185 t.Fatal(err) 186 } 187 188 if s, err := image.Usage(ctx, WithUsageManifestLimit(1)); err != nil { 189 t.Fatal(err) 190 } else if s != s1 { 191 t.Fatalf("unexpected usage %d, expected %d", s, s1) 192 } 193 194 s2, err := image.Usage(ctx, WithUsageManifestLimit(0)) 195 if err != nil { 196 t.Fatal(err) 197 } 198 199 if s2 <= s1 { 200 t.Fatalf("Expected larger usage counting all manifests: %d <= %d", s2, s1) 201 } 202 203 s3, err := image.Usage(ctx, WithUsageManifestLimit(0), WithManifestUsage()) 204 if err != nil { 205 t.Fatal(err) 206 } 207 208 if s3 <= s2 { 209 t.Fatalf("Expected larger usage counting all manifest reported sizes: %d <= %d", s3, s2) 210 } 211 212 // Fetch everything 213 if _, err = client.Fetch(ctx, imageName); err != nil { 214 t.Fatal(err) 215 } 216 217 if s, err := image.Usage(ctx); err != nil { 218 t.Fatal(err) 219 } else if s != s3 { 220 t.Fatalf("Expected actual usage to equal manifest reported usage of %d: got %d", s3, s) 221 } 222 223 err = image.Unpack(ctx, DefaultSnapshotter) 224 if err != nil { 225 t.Fatal(err) 226 } 227 228 if s, err := image.Usage(ctx, WithSnapshotUsage()); err != nil { 229 t.Fatal(err) 230 } else if s <= s3 { 231 t.Fatalf("Expected actual usage with snapshots to be greater: %d <= %d", s, s3) 232 } 233 }