github.com/containerd/Containerd@v1.4.13/images/archive/reference.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 archive
    18  
    19  import (
    20  	"strings"
    21  
    22  	"github.com/containerd/containerd/reference"
    23  	distref "github.com/containerd/containerd/reference/docker"
    24  	"github.com/opencontainers/go-digest"
    25  	"github.com/pkg/errors"
    26  )
    27  
    28  // FilterRefPrefix restricts references to having the given image
    29  // prefix. Tag-only references will have the prefix prepended.
    30  func FilterRefPrefix(image string) func(string) string {
    31  	return refTranslator(image, true)
    32  }
    33  
    34  // AddRefPrefix prepends the given image prefix to tag-only references,
    35  // while leaving returning full references unmodified.
    36  func AddRefPrefix(image string) func(string) string {
    37  	return refTranslator(image, false)
    38  }
    39  
    40  // refTranslator creates a reference which only has a tag or verifies
    41  // a full reference.
    42  func refTranslator(image string, checkPrefix bool) func(string) string {
    43  	return func(ref string) string {
    44  		// Check if ref is full reference
    45  		if strings.ContainsAny(ref, "/:@") {
    46  			// If not prefixed, don't include image
    47  			if checkPrefix && !isImagePrefix(ref, image) {
    48  				return ""
    49  			}
    50  			return ref
    51  		}
    52  		return image + ":" + ref
    53  	}
    54  }
    55  
    56  func isImagePrefix(s, prefix string) bool {
    57  	if !strings.HasPrefix(s, prefix) {
    58  		return false
    59  	}
    60  	if len(s) > len(prefix) {
    61  		switch s[len(prefix)] {
    62  		case '/', ':', '@':
    63  			// Prevent matching partial namespaces
    64  		default:
    65  			return false
    66  		}
    67  	}
    68  	return true
    69  }
    70  
    71  func normalizeReference(ref string) (string, error) {
    72  	// TODO: Replace this function to not depend on reference package
    73  	normalized, err := distref.ParseDockerRef(ref)
    74  	if err != nil {
    75  		return "", errors.Wrapf(err, "normalize image ref %q", ref)
    76  	}
    77  
    78  	return normalized.String(), nil
    79  }
    80  
    81  func familiarizeReference(ref string) (string, error) {
    82  	named, err := distref.ParseNormalizedNamed(ref)
    83  	if err != nil {
    84  		return "", errors.Wrapf(err, "failed to parse %q", ref)
    85  	}
    86  	named = distref.TagNameOnly(named)
    87  
    88  	return distref.FamiliarString(named), nil
    89  }
    90  
    91  func ociReferenceName(name string) string {
    92  	// OCI defines the reference name as only a tag excluding the
    93  	// repository. The containerd annotation contains the full image name
    94  	// since the tag is insufficient for correctly naming and referring to an
    95  	// image
    96  	var ociRef string
    97  	if spec, err := reference.Parse(name); err == nil {
    98  		ociRef = spec.Object
    99  	} else {
   100  		ociRef = name
   101  	}
   102  
   103  	return ociRef
   104  }
   105  
   106  // DigestTranslator creates a digest reference by adding the
   107  // digest to an image name
   108  func DigestTranslator(prefix string) func(digest.Digest) string {
   109  	return func(dgst digest.Digest) string {
   110  		return prefix + "@" + dgst.String()
   111  	}
   112  }