github.com/containerd/Containerd@v1.4.13/images/mediatypes.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 images 18 19 import ( 20 "context" 21 "sort" 22 "strings" 23 24 "github.com/containerd/containerd/errdefs" 25 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 26 "github.com/pkg/errors" 27 ) 28 29 // mediatype definitions for image components handled in containerd. 30 // 31 // oci components are generally referenced directly, although we may centralize 32 // here for clarity. 33 const ( 34 MediaTypeDockerSchema2Layer = "application/vnd.docker.image.rootfs.diff.tar" 35 MediaTypeDockerSchema2LayerForeign = "application/vnd.docker.image.rootfs.foreign.diff.tar" 36 MediaTypeDockerSchema2LayerGzip = "application/vnd.docker.image.rootfs.diff.tar.gzip" 37 MediaTypeDockerSchema2LayerForeignGzip = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip" 38 MediaTypeDockerSchema2Config = "application/vnd.docker.container.image.v1+json" 39 MediaTypeDockerSchema2Manifest = "application/vnd.docker.distribution.manifest.v2+json" 40 MediaTypeDockerSchema2ManifestList = "application/vnd.docker.distribution.manifest.list.v2+json" 41 // Checkpoint/Restore Media Types 42 MediaTypeContainerd1Checkpoint = "application/vnd.containerd.container.criu.checkpoint.criu.tar" 43 MediaTypeContainerd1CheckpointPreDump = "application/vnd.containerd.container.criu.checkpoint.predump.tar" 44 MediaTypeContainerd1Resource = "application/vnd.containerd.container.resource.tar" 45 MediaTypeContainerd1RW = "application/vnd.containerd.container.rw.tar" 46 MediaTypeContainerd1CheckpointConfig = "application/vnd.containerd.container.checkpoint.config.v1+proto" 47 MediaTypeContainerd1CheckpointOptions = "application/vnd.containerd.container.checkpoint.options.v1+proto" 48 MediaTypeContainerd1CheckpointRuntimeName = "application/vnd.containerd.container.checkpoint.runtime.name" 49 MediaTypeContainerd1CheckpointRuntimeOptions = "application/vnd.containerd.container.checkpoint.runtime.options+proto" 50 // Legacy Docker schema1 manifest 51 MediaTypeDockerSchema1Manifest = "application/vnd.docker.distribution.manifest.v1+prettyjws" 52 ) 53 54 // DiffCompression returns the compression as defined by the layer diff media 55 // type. For Docker media types without compression, "unknown" is returned to 56 // indicate that the media type may be compressed. If the media type is not 57 // recognized as a layer diff, then it returns errdefs.ErrNotImplemented 58 func DiffCompression(ctx context.Context, mediaType string) (string, error) { 59 base, ext := parseMediaTypes(mediaType) 60 switch base { 61 case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerForeign: 62 if len(ext) > 0 { 63 // Type is wrapped 64 return "", nil 65 } 66 // These media types may have been compressed but failed to 67 // use the correct media type. The decompression function 68 // should detect and handle this case. 69 return "unknown", nil 70 case MediaTypeDockerSchema2LayerGzip, MediaTypeDockerSchema2LayerForeignGzip: 71 if len(ext) > 0 { 72 // Type is wrapped 73 return "", nil 74 } 75 return "gzip", nil 76 case ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerNonDistributable: 77 if len(ext) > 0 { 78 switch ext[len(ext)-1] { 79 case "gzip": 80 return "gzip", nil 81 } 82 } 83 return "", nil 84 default: 85 return "", errors.Wrapf(errdefs.ErrNotImplemented, "unrecognised mediatype %s", mediaType) 86 } 87 } 88 89 // parseMediaTypes splits the media type into the base type and 90 // an array of sorted extensions 91 func parseMediaTypes(mt string) (string, []string) { 92 if mt == "" { 93 return "", []string{} 94 } 95 96 s := strings.Split(mt, "+") 97 ext := s[1:] 98 sort.Strings(ext) 99 100 return s[0], ext 101 } 102 103 // IsLayerTypes returns true if the media type is a layer 104 func IsLayerType(mt string) bool { 105 if strings.HasPrefix(mt, "application/vnd.oci.image.layer.") { 106 return true 107 } 108 109 // Parse Docker media types, strip off any + suffixes first 110 base, _ := parseMediaTypes(mt) 111 switch base { 112 case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip, 113 MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip: 114 return true 115 } 116 return false 117 } 118 119 // IsKnownConfig returns true if the media type is a known config type 120 func IsKnownConfig(mt string) bool { 121 switch mt { 122 case MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig, 123 MediaTypeContainerd1Checkpoint, MediaTypeContainerd1CheckpointConfig: 124 return true 125 } 126 return false 127 } 128 129 // ChildGCLabels returns the label for a given descriptor to reference it 130 func ChildGCLabels(desc ocispec.Descriptor) []string { 131 mt := desc.MediaType 132 if IsKnownConfig(mt) { 133 return []string{"containerd.io/gc.ref.content.config"} 134 } 135 136 switch mt { 137 case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: 138 return []string{"containerd.io/gc.ref.content.m."} 139 } 140 141 if IsLayerType(mt) { 142 return []string{"containerd.io/gc.ref.content.l."} 143 } 144 145 return []string{"containerd.io/gc.ref.content."} 146 } 147 148 // ChildGCLabelsFilterLayers returns the labels for a given descriptor to 149 // reference it, skipping layer media types 150 func ChildGCLabelsFilterLayers(desc ocispec.Descriptor) []string { 151 if IsLayerType(desc.MediaType) { 152 return nil 153 } 154 return ChildGCLabels(desc) 155 }