github.com/lalkh/containerd@v1.4.3/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  }