github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/api/handlers/compat/images_push.go (about)

     1  package compat
     2  
     3  import (
     4  	"context"
     5  	"net/http"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/containers/libpod/libpod"
    10  	"github.com/containers/libpod/libpod/image"
    11  	"github.com/containers/libpod/pkg/api/handlers/utils"
    12  	"github.com/gorilla/schema"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  // PushImage is the handler for the compat http endpoint for pushing images.
    17  func PushImage(w http.ResponseWriter, r *http.Request) {
    18  	decoder := r.Context().Value("decoder").(*schema.Decoder)
    19  	runtime := r.Context().Value("runtime").(*libpod.Runtime)
    20  
    21  	query := struct {
    22  		Tag string `schema:"tag"`
    23  	}{
    24  		// This is where you can override the golang default value for one of fields
    25  	}
    26  
    27  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
    28  		utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
    29  		return
    30  	}
    31  
    32  	// Note that Docker's docs state "Image name or ID" to be in the path
    33  	// parameter but it really must be a name as Docker does not allow for
    34  	// pushing an image by ID.
    35  	imageName := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
    36  	if query.Tag != "" {
    37  		imageName += ":" + query.Tag
    38  	}
    39  	if _, err := utils.ParseStorageReference(imageName); err != nil {
    40  		utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
    41  			errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName))
    42  		return
    43  	}
    44  
    45  	newImage, err := runtime.ImageRuntime().NewFromLocal(imageName)
    46  	if err != nil {
    47  		utils.ImageNotFound(w, imageName, errors.Wrapf(err, "Failed to find image %s", imageName))
    48  		return
    49  	}
    50  
    51  	// TODO: the X-Registry-Auth header is not checked yet here nor in any other
    52  	// endpoint. Pushing does NOT work with authentication at the moment.
    53  	dockerRegistryOptions := &image.DockerRegistryOptions{}
    54  	authfile := ""
    55  	if sys := runtime.SystemContext(); sys != nil {
    56  		dockerRegistryOptions.DockerCertPath = sys.DockerCertPath
    57  		authfile = sys.AuthFilePath
    58  	}
    59  
    60  	err = newImage.PushImageToHeuristicDestination(
    61  		context.Background(),
    62  		imageName,
    63  		"", // manifest type
    64  		authfile,
    65  		"", // digest file
    66  		"", // signature policy
    67  		os.Stderr,
    68  		false, // force compression
    69  		image.SigningOptions{},
    70  		dockerRegistryOptions,
    71  		nil, // additional tags
    72  	)
    73  	if err != nil {
    74  		utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Error pushing image %q", imageName))
    75  		return
    76  	}
    77  
    78  	utils.WriteResponse(w, http.StatusOK, "")
    79  
    80  }