github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/api/handlers/utils/images.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"github.com/containers/common/libimage"
     9  	"github.com/containers/image/v5/docker"
    10  	storageTransport "github.com/containers/image/v5/storage"
    11  	"github.com/containers/image/v5/transports/alltransports"
    12  	"github.com/containers/image/v5/types"
    13  	"github.com/hanks177/podman/v4/libpod"
    14  	api "github.com/hanks177/podman/v4/pkg/api/types"
    15  	"github.com/hanks177/podman/v4/pkg/util"
    16  	"github.com/containers/storage"
    17  	"github.com/docker/distribution/reference"
    18  	"github.com/pkg/errors"
    19  )
    20  
    21  // NormalizeToDockerHub normalizes the specified nameOrID to Docker Hub if the
    22  // request is for the compat API and if containers.conf set the specific mode.
    23  // If nameOrID is a (short) ID for a local image, the full ID will be returned.
    24  func NormalizeToDockerHub(r *http.Request, nameOrID string) (string, error) {
    25  	if IsLibpodRequest(r) || !util.DefaultContainerConfig().Engine.CompatAPIEnforceDockerHub {
    26  		return nameOrID, nil
    27  	}
    28  
    29  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
    30  
    31  	// The candidate may resolve to a local non-Docker Hub image, such as
    32  	// 'busybox' -> 'registry.com/busybox'.
    33  	img, candidate, err := runtime.LibimageRuntime().LookupImage(nameOrID, nil)
    34  	if err != nil {
    35  		if errors.Cause(err) != storage.ErrImageUnknown {
    36  			return "", fmt.Errorf("normalizing name for compat API: %v", err)
    37  		}
    38  		// If the image could not be resolved locally, set the
    39  		// candidate back to the input.
    40  		candidate = nameOrID
    41  	} else if strings.HasPrefix(img.ID(), strings.TrimPrefix(nameOrID, "sha256:")) {
    42  		return img.ID(), nil
    43  	}
    44  
    45  	// No ID, so we can normalize.
    46  	named, err := reference.ParseNormalizedNamed(candidate)
    47  	if err != nil {
    48  		return "", fmt.Errorf("normalizing name %q (orig: %q) for compat API: %v", candidate, nameOrID, err)
    49  	}
    50  
    51  	return named.String(), nil
    52  }
    53  
    54  // PossiblyEnforceDockerHub sets fields in the system context to enforce
    55  // resolving short names to Docker Hub if the request is for the compat API and
    56  // if containers.conf set the specific mode.
    57  func PossiblyEnforceDockerHub(r *http.Request, sys *types.SystemContext) {
    58  	if IsLibpodRequest(r) || !util.DefaultContainerConfig().Engine.CompatAPIEnforceDockerHub {
    59  		return
    60  	}
    61  	sys.PodmanOnlyShortNamesIgnoreRegistriesConfAndForceDockerHub = true
    62  }
    63  
    64  // IsRegistryReference checks if the specified name points to the "docker://"
    65  // transport.  If it points to no supported transport, we'll assume a
    66  // non-transport reference pointing to an image (e.g., "fedora:latest").
    67  func IsRegistryReference(name string) error {
    68  	imageRef, err := alltransports.ParseImageName(name)
    69  	if err != nil {
    70  		// No supported transport -> assume a docker-stype reference.
    71  		return nil // nolint: nilerr
    72  	}
    73  	if imageRef.Transport().Name() == docker.Transport.Name() {
    74  		return nil
    75  	}
    76  	return errors.Errorf("unsupported transport %s in %q: only docker transport is supported", imageRef.Transport().Name(), name)
    77  }
    78  
    79  // ParseStorageReference parses the specified image name to a
    80  // `types.ImageReference` and enforces it to refer to a
    81  // containers-storage-transport reference.
    82  func ParseStorageReference(name string) (types.ImageReference, error) {
    83  	storagePrefix := storageTransport.Transport.Name()
    84  	imageRef, err := alltransports.ParseImageName(name)
    85  	if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
    86  		return nil, errors.Errorf("reference %q must be a storage reference", name)
    87  	} else if err != nil {
    88  		origErr := err
    89  		imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s:%s", storagePrefix, name))
    90  		if err != nil {
    91  			return nil, errors.Wrapf(origErr, "reference %q must be a storage reference", name)
    92  		}
    93  	}
    94  	return imageRef, nil
    95  }
    96  
    97  func GetImage(r *http.Request, name string) (*libimage.Image, error) {
    98  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
    99  	image, _, err := runtime.LibimageRuntime().LookupImage(name, nil)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	return image, err
   104  }