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 }