github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/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/podman/v2/libpod"
    10  	"github.com/containers/podman/v2/libpod/image"
    11  	"github.com/containers/podman/v2/pkg/api/handlers/utils"
    12  	"github.com/containers/podman/v2/pkg/auth"
    13  	"github.com/gorilla/schema"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  // PushImage is the handler for the compat http endpoint for pushing images.
    18  func PushImage(w http.ResponseWriter, r *http.Request) {
    19  	decoder := r.Context().Value("decoder").(*schema.Decoder)
    20  	runtime := r.Context().Value("runtime").(*libpod.Runtime)
    21  
    22  	query := struct {
    23  		Tag string `schema:"tag"`
    24  	}{
    25  		// This is where you can override the golang default value for one of fields
    26  	}
    27  
    28  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
    29  		utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
    30  		return
    31  	}
    32  
    33  	// Note that Docker's docs state "Image name or ID" to be in the path
    34  	// parameter but it really must be a name as Docker does not allow for
    35  	// pushing an image by ID.
    36  	imageName := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
    37  	if query.Tag != "" {
    38  		imageName += ":" + query.Tag
    39  	}
    40  	if _, err := utils.ParseStorageReference(imageName); err != nil {
    41  		utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
    42  			errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName))
    43  		return
    44  	}
    45  
    46  	newImage, err := runtime.ImageRuntime().NewFromLocal(imageName)
    47  	if err != nil {
    48  		utils.ImageNotFound(w, imageName, errors.Wrapf(err, "failed to find image %s", imageName))
    49  		return
    50  	}
    51  
    52  	authConf, authfile, key, err := auth.GetCredentials(r)
    53  	if err != nil {
    54  		utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String()))
    55  		return
    56  	}
    57  	defer auth.RemoveAuthfile(authfile)
    58  
    59  	dockerRegistryOptions := &image.DockerRegistryOptions{DockerRegistryCreds: authConf}
    60  	if sys := runtime.SystemContext(); sys != nil {
    61  		dockerRegistryOptions.DockerCertPath = sys.DockerCertPath
    62  		dockerRegistryOptions.RegistriesConfPath = sys.SystemRegistriesConfPath
    63  	}
    64  
    65  	err = newImage.PushImageToHeuristicDestination(
    66  		context.Background(),
    67  		imageName,
    68  		"", // manifest type
    69  		authfile,
    70  		"", // digest file
    71  		"", // signature policy
    72  		os.Stderr,
    73  		false, // force compression
    74  		image.SigningOptions{},
    75  		dockerRegistryOptions,
    76  		nil, // additional tags
    77  	)
    78  	if err != nil {
    79  		utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", imageName))
    80  		return
    81  	}
    82  
    83  	utils.WriteResponse(w, http.StatusOK, "")
    84  
    85  }