github.com/rita33cool1/iot-system-gateway@v0.0.0-20200911033302-e65bde238cc5/docker-engine/api/server/router/image/image_routes.go (about)

     1  package image // import "github.com/docker/docker/api/server/router/image"
     2  
     3  import (
     4  	"encoding/base64"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/docker/docker/api/server/httputils"
    12  	"github.com/docker/docker/api/types"
    13  	"github.com/docker/docker/api/types/filters"
    14  	"github.com/docker/docker/api/types/versions"
    15  	"github.com/docker/docker/errdefs"
    16  	"github.com/docker/docker/pkg/ioutils"
    17  	"github.com/docker/docker/pkg/streamformatter"
    18  	"github.com/docker/docker/pkg/system"
    19  	"github.com/docker/docker/registry"
    20  	specs "github.com/opencontainers/image-spec/specs-go/v1"
    21  	"github.com/pkg/errors"
    22  	"golang.org/x/net/context"
    23  )
    24  
    25  // Creates an image from Pull or from Import
    26  func (s *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    27  
    28  	if err := httputils.ParseForm(r); err != nil {
    29  		return err
    30  	}
    31  
    32  	var (
    33  		image    = r.Form.Get("fromImage")
    34  		repo     = r.Form.Get("repo")
    35  		tag      = r.Form.Get("tag")
    36  		message  = r.Form.Get("message")
    37  		err      error
    38  		output   = ioutils.NewWriteFlusher(w)
    39  		platform = &specs.Platform{}
    40  	)
    41  	defer output.Close()
    42  
    43  	w.Header().Set("Content-Type", "application/json")
    44  
    45  	version := httputils.VersionFromContext(ctx)
    46  	if versions.GreaterThanOrEqualTo(version, "1.32") {
    47  		apiPlatform := r.FormValue("platform")
    48  		platform = system.ParsePlatform(apiPlatform)
    49  		if err = system.ValidatePlatform(platform); err != nil {
    50  			err = fmt.Errorf("invalid platform: %s", err)
    51  		}
    52  	}
    53  
    54  	if err == nil {
    55  		if image != "" { //pull
    56  			metaHeaders := map[string][]string{}
    57  			for k, v := range r.Header {
    58  				if strings.HasPrefix(k, "X-Meta-") {
    59  					metaHeaders[k] = v
    60  				}
    61  			}
    62  
    63  			authEncoded := r.Header.Get("X-Registry-Auth")
    64  			authConfig := &types.AuthConfig{}
    65  			if authEncoded != "" {
    66  				authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
    67  				if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
    68  					// for a pull it is not an error if no auth was given
    69  					// to increase compatibility with the existing api it is defaulting to be empty
    70  					authConfig = &types.AuthConfig{}
    71  				}
    72  			}
    73  			err = s.backend.PullImage(ctx, image, tag, platform.OS, metaHeaders, authConfig, output)
    74  		} else { //import
    75  			src := r.Form.Get("fromSrc")
    76  			// 'err' MUST NOT be defined within this block, we need any error
    77  			// generated from the download to be available to the output
    78  			// stream processing below
    79  			err = s.backend.ImportImage(src, repo, platform.OS, tag, message, r.Body, output, r.Form["changes"])
    80  		}
    81  	}
    82  	if err != nil {
    83  		if !output.Flushed() {
    84  			return err
    85  		}
    86  		output.Write(streamformatter.FormatError(err))
    87  	}
    88  
    89  	return nil
    90  }
    91  
    92  func (s *imageRouter) postImagesPush(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
    93  	metaHeaders := map[string][]string{}
    94  	for k, v := range r.Header {
    95  		if strings.HasPrefix(k, "X-Meta-") {
    96  			metaHeaders[k] = v
    97  		}
    98  	}
    99  	if err := httputils.ParseForm(r); err != nil {
   100  		return err
   101  	}
   102  	authConfig := &types.AuthConfig{}
   103  
   104  	authEncoded := r.Header.Get("X-Registry-Auth")
   105  	if authEncoded != "" {
   106  		// the new format is to handle the authConfig as a header
   107  		authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
   108  		if err := json.NewDecoder(authJSON).Decode(authConfig); err != nil {
   109  			// to increase compatibility to existing api it is defaulting to be empty
   110  			authConfig = &types.AuthConfig{}
   111  		}
   112  	} else {
   113  		// the old format is supported for compatibility if there was no authConfig header
   114  		if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
   115  			return errors.Wrap(errdefs.InvalidParameter(err), "Bad parameters and missing X-Registry-Auth")
   116  		}
   117  	}
   118  
   119  	image := vars["name"]
   120  	tag := r.Form.Get("tag")
   121  
   122  	output := ioutils.NewWriteFlusher(w)
   123  	defer output.Close()
   124  
   125  	w.Header().Set("Content-Type", "application/json")
   126  
   127  	if err := s.backend.PushImage(ctx, image, tag, metaHeaders, authConfig, output); err != nil {
   128  		if !output.Flushed() {
   129  			return err
   130  		}
   131  		output.Write(streamformatter.FormatError(err))
   132  	}
   133  	return nil
   134  }
   135  
   136  func (s *imageRouter) getImagesGet(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   137  	if err := httputils.ParseForm(r); err != nil {
   138  		return err
   139  	}
   140  
   141  	w.Header().Set("Content-Type", "application/x-tar")
   142  
   143  	output := ioutils.NewWriteFlusher(w)
   144  	defer output.Close()
   145  	var names []string
   146  	if name, ok := vars["name"]; ok {
   147  		names = []string{name}
   148  	} else {
   149  		names = r.Form["names"]
   150  	}
   151  
   152  	if err := s.backend.ExportImage(names, output); err != nil {
   153  		if !output.Flushed() {
   154  			return err
   155  		}
   156  		output.Write(streamformatter.FormatError(err))
   157  	}
   158  	return nil
   159  }
   160  
   161  func (s *imageRouter) postImagesLoad(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   162  	if err := httputils.ParseForm(r); err != nil {
   163  		return err
   164  	}
   165  	quiet := httputils.BoolValueOrDefault(r, "quiet", true)
   166  
   167  	w.Header().Set("Content-Type", "application/json")
   168  
   169  	output := ioutils.NewWriteFlusher(w)
   170  	defer output.Close()
   171  	if err := s.backend.LoadImage(r.Body, output, quiet); err != nil {
   172  		output.Write(streamformatter.FormatError(err))
   173  	}
   174  	return nil
   175  }
   176  
   177  type missingImageError struct{}
   178  
   179  func (missingImageError) Error() string {
   180  	return "image name cannot be blank"
   181  }
   182  
   183  func (missingImageError) InvalidParameter() {}
   184  
   185  func (s *imageRouter) deleteImages(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   186  	if err := httputils.ParseForm(r); err != nil {
   187  		return err
   188  	}
   189  
   190  	name := vars["name"]
   191  
   192  	if strings.TrimSpace(name) == "" {
   193  		return missingImageError{}
   194  	}
   195  
   196  	force := httputils.BoolValue(r, "force")
   197  	prune := !httputils.BoolValue(r, "noprune")
   198  
   199  	list, err := s.backend.ImageDelete(name, force, prune)
   200  	if err != nil {
   201  		return err
   202  	}
   203  
   204  	return httputils.WriteJSON(w, http.StatusOK, list)
   205  }
   206  
   207  func (s *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   208  	imageInspect, err := s.backend.LookupImage(vars["name"])
   209  	if err != nil {
   210  		return err
   211  	}
   212  
   213  	return httputils.WriteJSON(w, http.StatusOK, imageInspect)
   214  }
   215  
   216  func (s *imageRouter) getImagesJSON(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   217  	if err := httputils.ParseForm(r); err != nil {
   218  		return err
   219  	}
   220  
   221  	imageFilters, err := filters.FromJSON(r.Form.Get("filters"))
   222  	if err != nil {
   223  		return err
   224  	}
   225  
   226  	filterParam := r.Form.Get("filter")
   227  	// FIXME(vdemeester) This has been deprecated in 1.13, and is target for removal for v17.12
   228  	if filterParam != "" {
   229  		imageFilters.Add("reference", filterParam)
   230  	}
   231  
   232  	images, err := s.backend.Images(imageFilters, httputils.BoolValue(r, "all"), false)
   233  	if err != nil {
   234  		return err
   235  	}
   236  
   237  	return httputils.WriteJSON(w, http.StatusOK, images)
   238  }
   239  
   240  func (s *imageRouter) getImagesHistory(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   241  	name := vars["name"]
   242  	history, err := s.backend.ImageHistory(name)
   243  	if err != nil {
   244  		return err
   245  	}
   246  
   247  	return httputils.WriteJSON(w, http.StatusOK, history)
   248  }
   249  
   250  func (s *imageRouter) postImagesTag(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   251  	if err := httputils.ParseForm(r); err != nil {
   252  		return err
   253  	}
   254  	if _, err := s.backend.TagImage(vars["name"], r.Form.Get("repo"), r.Form.Get("tag")); err != nil {
   255  		return err
   256  	}
   257  	w.WriteHeader(http.StatusCreated)
   258  	return nil
   259  }
   260  
   261  func (s *imageRouter) getImagesSearch(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   262  	if err := httputils.ParseForm(r); err != nil {
   263  		return err
   264  	}
   265  	var (
   266  		config      *types.AuthConfig
   267  		authEncoded = r.Header.Get("X-Registry-Auth")
   268  		headers     = map[string][]string{}
   269  	)
   270  
   271  	if authEncoded != "" {
   272  		authJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(authEncoded))
   273  		if err := json.NewDecoder(authJSON).Decode(&config); err != nil {
   274  			// for a search it is not an error if no auth was given
   275  			// to increase compatibility with the existing api it is defaulting to be empty
   276  			config = &types.AuthConfig{}
   277  		}
   278  	}
   279  	for k, v := range r.Header {
   280  		if strings.HasPrefix(k, "X-Meta-") {
   281  			headers[k] = v
   282  		}
   283  	}
   284  	limit := registry.DefaultSearchLimit
   285  	if r.Form.Get("limit") != "" {
   286  		limitValue, err := strconv.Atoi(r.Form.Get("limit"))
   287  		if err != nil {
   288  			return err
   289  		}
   290  		limit = limitValue
   291  	}
   292  	query, err := s.backend.SearchRegistryForImages(ctx, r.Form.Get("filters"), r.Form.Get("term"), limit, config, headers)
   293  	if err != nil {
   294  		return err
   295  	}
   296  	return httputils.WriteJSON(w, http.StatusOK, query.Results)
   297  }
   298  
   299  func (s *imageRouter) postImagesPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
   300  	if err := httputils.ParseForm(r); err != nil {
   301  		return err
   302  	}
   303  
   304  	pruneFilters, err := filters.FromJSON(r.Form.Get("filters"))
   305  	if err != nil {
   306  		return err
   307  	}
   308  
   309  	pruneReport, err := s.backend.ImagesPrune(ctx, pruneFilters)
   310  	if err != nil {
   311  		return err
   312  	}
   313  	return httputils.WriteJSON(w, http.StatusOK, pruneReport)
   314  }