mirror of
				https://github.com/containers/podman.git
				synced 2025-11-01 02:42:11 +08:00 
			
		
		
		
	 7938f32c53
			
		
	
	7938f32c53
	
	
	
		
			
			This commit removes error message string from utils.Error in pkg/api. Param was not used inside a function for quite a long time [NO NEW TESTS NEEDED] Signed-off-by: Jakub Guzik <jguzik@redhat.com>
		
			
				
	
	
		
			146 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			146 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package libpod
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"encoding/json"
 | |
| 	"net/http"
 | |
| 
 | |
| 	"github.com/containers/common/libimage"
 | |
| 	"github.com/containers/common/pkg/config"
 | |
| 	"github.com/containers/image/v5/types"
 | |
| 	"github.com/containers/podman/v4/libpod"
 | |
| 	"github.com/containers/podman/v4/pkg/api/handlers/utils"
 | |
| 	api "github.com/containers/podman/v4/pkg/api/types"
 | |
| 	"github.com/containers/podman/v4/pkg/auth"
 | |
| 	"github.com/containers/podman/v4/pkg/channel"
 | |
| 	"github.com/containers/podman/v4/pkg/domain/entities"
 | |
| 	"github.com/gorilla/schema"
 | |
| 	"github.com/pkg/errors"
 | |
| 	"github.com/sirupsen/logrus"
 | |
| )
 | |
| 
 | |
| // ImagesPull is the v2 libpod endpoint for pulling images.  Note that the
 | |
| // mandatory `reference` must be a reference to a registry (i.e., of docker
 | |
| // transport or be normalized to one).  Other transports are rejected as they
 | |
| // do not make sense in a remote context.
 | |
| func ImagesPull(w http.ResponseWriter, r *http.Request) {
 | |
| 	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
 | |
| 	decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
 | |
| 	query := struct {
 | |
| 		Reference  string `schema:"reference"`
 | |
| 		OS         string `schema:"OS"`
 | |
| 		Arch       string `schema:"Arch"`
 | |
| 		Variant    string `schema:"Variant"`
 | |
| 		TLSVerify  bool   `schema:"tlsVerify"`
 | |
| 		AllTags    bool   `schema:"allTags"`
 | |
| 		PullPolicy string `schema:"policy"`
 | |
| 		Quiet      bool   `schema:"quiet"`
 | |
| 	}{
 | |
| 		TLSVerify:  true,
 | |
| 		PullPolicy: "always",
 | |
| 	}
 | |
| 
 | |
| 	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
 | |
| 		utils.Error(w, http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	if len(query.Reference) == 0 {
 | |
| 		utils.InternalServerError(w, errors.New("reference parameter cannot be empty"))
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	// Make sure that the reference has no transport or the docker one.
 | |
| 	if err := utils.IsRegistryReference(query.Reference); err != nil {
 | |
| 		utils.Error(w, http.StatusBadRequest, err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	pullOptions := &libimage.PullOptions{}
 | |
| 	pullOptions.AllTags = query.AllTags
 | |
| 	pullOptions.Architecture = query.Arch
 | |
| 	pullOptions.OS = query.OS
 | |
| 	pullOptions.Variant = query.Variant
 | |
| 
 | |
| 	if _, found := r.URL.Query()["tlsVerify"]; found {
 | |
| 		pullOptions.InsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
 | |
| 	}
 | |
| 
 | |
| 	// Do the auth dance.
 | |
| 	authConf, authfile, err := auth.GetCredentials(r)
 | |
| 	if err != nil {
 | |
| 		utils.Error(w, http.StatusBadRequest, err)
 | |
| 		return
 | |
| 	}
 | |
| 	defer auth.RemoveAuthfile(authfile)
 | |
| 
 | |
| 	pullOptions.AuthFilePath = authfile
 | |
| 	if authConf != nil {
 | |
| 		pullOptions.Username = authConf.Username
 | |
| 		pullOptions.Password = authConf.Password
 | |
| 		pullOptions.IdentityToken = authConf.IdentityToken
 | |
| 	}
 | |
| 
 | |
| 	writer := channel.NewWriter(make(chan []byte))
 | |
| 	defer writer.Close()
 | |
| 
 | |
| 	pullOptions.Writer = writer
 | |
| 
 | |
| 	pullPolicy, err := config.ParsePullPolicy(query.PullPolicy)
 | |
| 	if err != nil {
 | |
| 		utils.Error(w, http.StatusBadRequest, err)
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	var pulledImages []*libimage.Image
 | |
| 	var pullError error
 | |
| 	runCtx, cancel := context.WithCancel(r.Context())
 | |
| 	go func() {
 | |
| 		defer cancel()
 | |
| 		pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, pullPolicy, pullOptions)
 | |
| 	}()
 | |
| 
 | |
| 	flush := func() {
 | |
| 		if flusher, ok := w.(http.Flusher); ok {
 | |
| 			flusher.Flush()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	w.WriteHeader(http.StatusOK)
 | |
| 	w.Header().Set("Content-Type", "application/json")
 | |
| 	flush()
 | |
| 
 | |
| 	enc := json.NewEncoder(w)
 | |
| 	enc.SetEscapeHTML(true)
 | |
| 	for {
 | |
| 		var report entities.ImagePullReport
 | |
| 		select {
 | |
| 		case s := <-writer.Chan():
 | |
| 			report.Stream = string(s)
 | |
| 			if !query.Quiet {
 | |
| 				if err := enc.Encode(report); err != nil {
 | |
| 					logrus.Warnf("Failed to encode json: %v", err)
 | |
| 				}
 | |
| 			}
 | |
| 			flush()
 | |
| 		case <-runCtx.Done():
 | |
| 			for _, image := range pulledImages {
 | |
| 				report.Images = append(report.Images, image.ID())
 | |
| 				// Pull last ID from list and publish in 'id' stanza.  This maintains previous API contract
 | |
| 				report.ID = image.ID()
 | |
| 			}
 | |
| 			if pullError != nil {
 | |
| 				report.Error = pullError.Error()
 | |
| 			}
 | |
| 			if err := enc.Encode(report); err != nil {
 | |
| 				logrus.Warnf("Failed to encode json: %v", err)
 | |
| 			}
 | |
| 			flush()
 | |
| 			return
 | |
| 		case <-r.Context().Done():
 | |
| 			// Client has closed connection
 | |
| 			return
 | |
| 		}
 | |
| 	}
 | |
| }
 |