package libpod import ( "fmt" "io" "io/ioutil" "net/http" "os" "strconv" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/gorilla/schema" "github.com/pkg/errors" ) // Commit // author string // "container" // repo string // tag string // message // pause bool // changes []string // create func ImageExists(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) name := utils.GetName(r) _, err := runtime.ImageRuntime().NewFromLocal(name) if err != nil { utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Wrapf(err, "Failed to find image %s", name)) return } utils.WriteResponse(w, http.StatusNoContent, "") } func ImageTree(w http.ResponseWriter, r *http.Request) { // tree is a bit of a mess ... logic is in adapter and therefore not callable from here. needs rework // name := utils.GetName(r) // _, layerInfoMap, _, err := s.Runtime.Tree(name) // if err != nil { // Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "Failed to find image information for %q", name)) // return // } // it is not clear to me how to deal with this given all the processing of the image // is in main. we need to discuss how that really should be and return something useful. handlers.UnsupportedHandler(w, r) } func GetImage(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) newImage, err := handlers.GetImage(r, name) if err != nil { utils.Error(w, "Something went wrong.", http.StatusNotFound, errors.Wrapf(err, "Failed to find image %s", name)) return } inspect, err := newImage.Inspect(r.Context()) if err != nil { utils.Error(w, "Server error", http.StatusInternalServerError, errors.Wrapf(err, "failed in inspect image %s", inspect.ID)) return } utils.WriteResponse(w, http.StatusOK, inspect) } func GetImages(w http.ResponseWriter, r *http.Request) { images, err := utils.GetImages(w, r) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Failed get images")) return } var summaries = make([]*handlers.ImageSummary, len(images)) for j, img := range images { is, err := handlers.ImageToImageSummary(img) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Failed transform image summaries")) return } // libpod has additional fields that we need to populate. is.CreatedTime = img.Created() is.ReadOnly = img.IsReadOnly() summaries[j] = is } utils.WriteResponse(w, http.StatusOK, summaries) } func PruneImages(w http.ResponseWriter, r *http.Request) { var ( all bool err error ) runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { Filters map[string][]string `schema:"filters"` }{ // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) return } var libpodFilters = []string{} if _, found := r.URL.Query()["filters"]; found { all, err = strconv.ParseBool(query.Filters["all"][0]) if err != nil { utils.InternalServerError(w, err) return } for k, v := range query.Filters { libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", k, v[0])) } } cids, err := runtime.ImageRuntime().PruneImages(r.Context(), all, libpodFilters) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) return } utils.WriteResponse(w, http.StatusOK, cids) } func ExportImage(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { Compress bool `schema:"compress"` Format string `schema:"format"` }{ // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) return } if len(query.Format) < 1 { utils.InternalServerError(w, errors.New("format parameter cannot be empty.")) return } tmpfile, err := ioutil.TempFile("", "api.tar") if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) return } if err := tmpfile.Close(); err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile")) return } name := utils.GetName(r) newImage, err := runtime.ImageRuntime().NewFromLocal(name) if err != nil { utils.ImageNotFound(w, name, err) return } if err := newImage.Save(r.Context(), name, query.Format, tmpfile.Name(), []string{}, false, query.Compress); err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err) return } rdr, err := os.Open(tmpfile.Name()) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile")) return } defer rdr.Close() defer os.Remove(tmpfile.Name()) utils.WriteResponse(w, http.StatusOK, rdr) } func ImportImage(w http.ResponseWriter, r *http.Request) { // TODO this is basically wrong decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { Changes map[string]string `json:"changes"` Message string `json:"message"` Quiet bool `json:"quiet"` }{ // This is where you can override the golang default value for one of fields } if err := decoder.Decode(&query, r.URL.Query()); err != nil { utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) return } var ( err error writer io.Writer ) f, err := ioutil.TempFile("", "api_load.tar") if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to create tempfile")) return } if err := handlers.SaveFromBody(f, r); err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to write temporary file")) return } id, err := runtime.LoadImage(r.Context(), "", f.Name(), writer, "") //id, err := runtime.Import(r.Context()) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to load image")) return } utils.WriteResponse(w, http.StatusOK, struct { Stream string `json:"stream"` }{ Stream: fmt.Sprintf("Loaded image: %s\n", id), }) }