diff options
Diffstat (limited to 'pkg/api/handlers')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 127 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_restart.go | 42 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_stop.go | 44 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_push.go | 64 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_search.go | 84 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/containers.go | 23 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 86 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/manifests.go | 12 | ||||
-rw-r--r-- | pkg/api/handlers/utils/containers.go | 33 |
9 files changed, 255 insertions, 260 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index aa12afc82..b41987800 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -22,6 +22,7 @@ import ( "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" + "github.com/docker/go-units" "github.com/gorilla/mux" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -31,11 +32,11 @@ import ( func RemoveContainer(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - All bool `schema:"all"` - Force bool `schema:"force"` - Ignore bool `schema:"ignore"` - Link bool `schema:"link"` - Volumes bool `schema:"v"` + Force bool `schema:"force"` + Ignore bool `schema:"ignore"` + Link bool `schema:"link"` + DockerVolumes bool `schema:"v"` + LibpodVolumes bool `schema:"volumes"` }{ // override any golang type defaults } @@ -46,10 +47,19 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { return } - if query.Link && !utils.IsLibpodRequest(r) { - utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, - utils.ErrLinkNotSupport) - return + options := entities.RmOptions{ + Force: query.Force, + Ignore: query.Ignore, + } + if utils.IsLibpodRequest(r) { + options.Volumes = query.LibpodVolumes + } else { + if query.Link { + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + utils.ErrLinkNotSupport) + return + } + options.Volumes = query.DockerVolumes } runtime := r.Context().Value("runtime").(*libpod.Runtime) @@ -57,12 +67,6 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { // code. containerEngine := abi.ContainerEngine{Libpod: runtime} name := utils.GetName(r) - options := entities.RmOptions{ - All: query.All, - Force: query.Force, - Volumes: query.Volumes, - Ignore: query.Ignore, - } report, err := containerEngine.ContainerRm(r.Context(), []string{name}, options) if err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { @@ -73,7 +77,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - if report[0].Err != nil { + if len(report) > 0 && report[0].Err != nil { utils.InternalServerError(w, report[0].Err) return } @@ -193,45 +197,48 @@ func KillContainer(w http.ResponseWriter, r *http.Request) { return } - sig, err := signal.ParseSignalNameOrNumber(query.Signal) - if err != nil { - utils.InternalServerError(w, err) - return - } + // Now use the ABI implementation to prevent us from having duplicate + // code. + containerEngine := abi.ContainerEngine{Libpod: runtime} name := utils.GetName(r) - con, err := runtime.LookupContainer(name) - if err != nil { - utils.ContainerNotFound(w, name, err) - return + options := entities.KillOptions{ + Signal: query.Signal, } - - state, err := con.State() + report, err := containerEngine.ContainerKill(r.Context(), []string{name}, options) if err != nil { - utils.InternalServerError(w, err) - return - } + if errors.Cause(err) == define.ErrCtrStateInvalid || + errors.Cause(err) == define.ErrCtrStopped { + utils.Error(w, fmt.Sprintf("Container %s is not running", name), http.StatusConflict, err) + return + } + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, name, err) + return + } - // If the Container is stopped already, send a 409 - if state == define.ContainerStateStopped || state == define.ContainerStateExited { - utils.Error(w, fmt.Sprintf("Container %s is not running", name), http.StatusConflict, errors.New(fmt.Sprintf("Cannot kill Container %s, it is not running", name))) + utils.InternalServerError(w, err) return } - signal := uint(sig) - - err = con.Kill(signal) - if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "unable to kill Container %s", name)) + if len(report) > 0 && report[0].Err != nil { + utils.InternalServerError(w, report[0].Err) return } - // Docker waits for the container to stop if the signal is 0 or // SIGKILL. - if !utils.IsLibpodRequest(r) && (signal == 0 || syscall.Signal(signal) == syscall.SIGKILL) { - if _, err = con.Wait(); err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to wait for Container %s", con.ID())) + if !utils.IsLibpodRequest(r) { + sig, err := signal.ParseSignalNameOrNumber(query.Signal) + if err != nil { + utils.InternalServerError(w, err) return } + if sig == 0 || syscall.Signal(sig) == syscall.SIGKILL { + var opts entities.WaitOptions + if _, err := containerEngine.ContainerWait(r.Context(), []string{name}, opts); err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) + return + } + } } // Success utils.WriteResponse(w, http.StatusNoContent, nil) @@ -242,6 +249,10 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) { // /{version}/containers/(name)/wait exitCode, err := utils.WaitContainer(w, r) if err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + logrus.Warnf("container not found %q: %v", utils.GetName(r), err) + return + } logrus.Warnf("failed to wait on container %q: %v", mux.Vars(r)["name"], err) return } @@ -264,6 +275,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error sizeRootFs int64 sizeRW int64 state define.ContainerStatus + status string ) if state, err = l.State(); err != nil { @@ -274,6 +286,35 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error stateStr = "created" } + if state == define.ContainerStateConfigured || state == define.ContainerStateCreated { + status = "Created" + } else if state == define.ContainerStateStopped || state == define.ContainerStateExited { + exitCode, _, err := l.ExitCode() + if err != nil { + return nil, err + } + finishedTime, err := l.FinishedTime() + if err != nil { + return nil, err + } + status = fmt.Sprintf("Exited (%d) %s ago", exitCode, units.HumanDuration(time.Since(finishedTime))) + } else if state == define.ContainerStateRunning || state == define.ContainerStatePaused { + startedTime, err := l.StartedTime() + if err != nil { + return nil, err + } + status = fmt.Sprintf("Up %s", units.HumanDuration(time.Since(startedTime))) + if state == define.ContainerStatePaused { + status += " (Paused)" + } + } else if state == define.ContainerStateRemoving { + status = "Removal In Progress" + } else if state == define.ContainerStateStopping { + status = "Stopping" + } else { + status = "Unknown" + } + if sz { if sizeRW, err = l.RWSize(); err != nil { return nil, err @@ -295,7 +336,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error SizeRootFs: sizeRootFs, Labels: l.Labels(), State: stateStr, - Status: "", + Status: status, HostConfig: struct { NetworkMode string `json:",omitempty"` }{ diff --git a/pkg/api/handlers/compat/containers_restart.go b/pkg/api/handlers/compat/containers_restart.go index e8928596a..70edfcbb3 100644 --- a/pkg/api/handlers/compat/containers_restart.go +++ b/pkg/api/handlers/compat/containers_restart.go @@ -4,7 +4,10 @@ import ( "net/http" "github.com/containers/podman/v2/libpod" + "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/api/handlers/utils" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -12,34 +15,49 @@ import ( func RestartContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) + // Now use the ABI implementation to prevent us from having duplicate + // code. + containerEngine := abi.ContainerEngine{Libpod: runtime} + // /{version}/containers/(name)/restart query := struct { - Timeout int `schema:"t"` + All bool `schema:"all"` + DockerTimeout uint `schema:"t"` + LibpodTimeout uint `schema:"timeout"` }{ - // Override golang default values for types + // override any golang type defaults } if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.BadRequest(w, "url", r.URL.String(), errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } name := utils.GetName(r) - con, err := runtime.LookupContainer(name) - if err != nil { - utils.ContainerNotFound(w, name, err) - return - } - timeout := con.StopTimeout() - if _, found := r.URL.Query()["t"]; found { - timeout = uint(query.Timeout) + options := entities.RestartOptions{ + All: query.All, + Timeout: &query.DockerTimeout, + } + if utils.IsLibpodRequest(r) { + options.Timeout = &query.LibpodTimeout } + report, err := containerEngine.ContainerRestart(r.Context(), []string{name}, options) + if err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, name, err) + return + } - if err := con.RestartWithTimeout(r.Context(), timeout); err != nil { utils.InternalServerError(w, err) return } + if len(report) > 0 && report[0].Err != nil { + utils.InternalServerError(w, report[0].Err) + return + } + // Success utils.WriteResponse(w, http.StatusNoContent, nil) } diff --git a/pkg/api/handlers/compat/containers_stop.go b/pkg/api/handlers/compat/containers_stop.go index 8bc58cf59..000685aa0 100644 --- a/pkg/api/handlers/compat/containers_stop.go +++ b/pkg/api/handlers/compat/containers_stop.go @@ -6,6 +6,8 @@ import ( "github.com/containers/podman/v2/libpod" "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/api/handlers/utils" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -13,10 +15,15 @@ import ( func StopContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) + // Now use the ABI implementation to prevent us from having duplicate + // code. + containerEngine := abi.ContainerEngine{Libpod: runtime} // /{version}/containers/(name)/stop query := struct { - Timeout int `schema:"t"` + Ignore bool `schema:"ignore"` + DockerTimeout uint `schema:"t"` + LibpodTimeout uint `schema:"timeout"` }{ // override any golang type defaults } @@ -27,31 +34,46 @@ func StopContainer(w http.ResponseWriter, r *http.Request) { } name := utils.GetName(r) + + options := entities.StopOptions{ + Ignore: query.Ignore, + } + if utils.IsLibpodRequest(r) { + if query.LibpodTimeout > 0 { + options.Timeout = &query.LibpodTimeout + } + } else { + if query.DockerTimeout > 0 { + options.Timeout = &query.DockerTimeout + } + } con, err := runtime.LookupContainer(name) if err != nil { utils.ContainerNotFound(w, name, err) return } - state, err := con.State() if err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "unable to get state for Container %s", name)) + utils.InternalServerError(w, err) return } - // If the Container is stopped already, send a 304 if state == define.ContainerStateStopped || state == define.ContainerStateExited { utils.WriteResponse(w, http.StatusNotModified, nil) return } + report, err := containerEngine.ContainerStop(r.Context(), []string{name}, options) + if err != nil { + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, name, err) + return + } - var stopError error - if query.Timeout > 0 { - stopError = con.StopWithTimeout(uint(query.Timeout)) - } else { - stopError = con.Stop() + utils.InternalServerError(w, err) + return } - if stopError != nil { - utils.InternalServerError(w, errors.Wrapf(stopError, "failed to stop %s", name)) + + if len(report) > 0 && report[0].Err != nil { + utils.InternalServerError(w, report[0].Err) return } diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go index 0f3da53e8..c352ac6cd 100644 --- a/pkg/api/handlers/compat/images_push.go +++ b/pkg/api/handlers/compat/images_push.go @@ -3,13 +3,15 @@ package compat import ( "context" "net/http" - "os" "strings" + "github.com/containers/image/v5/types" "github.com/containers/podman/v2/libpod" - "github.com/containers/podman/v2/libpod/image" "github.com/containers/podman/v2/pkg/api/handlers/utils" "github.com/containers/podman/v2/pkg/auth" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" + "github.com/containers/storage" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -18,11 +20,20 @@ import ( func PushImage(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) + // Now use the ABI implementation to prevent us from having duplicate + // code. + imageEngine := abi.ImageEngine{Libpod: runtime} query := struct { - Tag string `schema:"tag"` + All bool `schema:"all"` + Compress bool `schema:"compress"` + Destination string `schema:"destination"` + Format string `schema:"format"` + TLSVerify bool `schema:"tlsVerify"` + Tag string `schema:"tag"` }{ // This is where you can override the golang default value for one of fields + TLSVerify: true, } if err := decoder.Decode(&query, r.URL.Query()); err != nil { @@ -43,39 +54,34 @@ func PushImage(w http.ResponseWriter, r *http.Request) { return } - newImage, err := runtime.ImageRuntime().NewFromLocal(imageName) - if err != nil { - utils.ImageNotFound(w, imageName, errors.Wrapf(err, "failed to find image %s", imageName)) - return - } - - authConf, authfile, key, err := auth.GetCredentials(r) + authconf, authfile, key, err := auth.GetCredentials(r) if err != nil { utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) return } defer auth.RemoveAuthfile(authfile) - - dockerRegistryOptions := &image.DockerRegistryOptions{DockerRegistryCreds: authConf} - if sys := runtime.SystemContext(); sys != nil { - dockerRegistryOptions.DockerCertPath = sys.DockerCertPath - dockerRegistryOptions.RegistriesConfPath = sys.SystemRegistriesConfPath + var username, password string + if authconf != nil { + username = authconf.Username + password = authconf.Password + } + options := entities.ImagePushOptions{ + All: query.All, + Authfile: authfile, + Compress: query.Compress, + Format: query.Format, + Password: password, + Username: username, } + if _, found := r.URL.Query()["tlsVerify"]; found { + options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) + } + if err := imageEngine.Push(context.Background(), imageName, query.Destination, options); err != nil { + if errors.Cause(err) != storage.ErrImageUnknown { + utils.ImageNotFound(w, imageName, errors.Wrapf(err, "failed to find image %s", imageName)) + return + } - err = newImage.PushImageToHeuristicDestination( - context.Background(), - imageName, - "", // manifest type - authfile, - "", // digest file - "", // signature policy - os.Stderr, - false, // force compression - image.SigningOptions{}, - dockerRegistryOptions, - nil, // additional tags - ) - if err != nil { utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "error pushing image %q", imageName)) return } diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go index 6808cdad5..885112b31 100644 --- a/pkg/api/handlers/compat/images_search.go +++ b/pkg/api/handlers/compat/images_search.go @@ -1,25 +1,30 @@ package compat import ( + "fmt" "net/http" - "strconv" "github.com/containers/image/v5/types" - "github.com/containers/podman/v2/libpod/image" + "github.com/containers/podman/v2/libpod" + "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/api/handlers/utils" "github.com/containers/podman/v2/pkg/auth" - "github.com/docker/docker/api/types/registry" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" ) func SearchImages(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { Term string `json:"term"` Limit int `json:"limit"` + NoTrunc bool `json:"noTrunc"` Filters map[string][]string `json:"filters"` TLSVerify bool `json:"tlsVerify"` + ListTags bool `json:"listTags"` }{ // This is where you can override the golang default value for one of fields } @@ -29,67 +34,40 @@ func SearchImages(w http.ResponseWriter, r *http.Request) { return } - filter := image.SearchFilter{} - if len(query.Filters) > 0 { - if len(query.Filters["stars"]) > 0 { - stars, err := strconv.Atoi(query.Filters["stars"][0]) - if err != nil { - utils.InternalServerError(w, err) - return - } - filter.Stars = stars - } - if len(query.Filters["is-official"]) > 0 { - isOfficial, err := strconv.ParseBool(query.Filters["is-official"][0]) - if err != nil { - utils.InternalServerError(w, err) - return - } - filter.IsOfficial = types.NewOptionalBool(isOfficial) - } - if len(query.Filters["is-automated"]) > 0 { - isAutomated, err := strconv.ParseBool(query.Filters["is-automated"][0]) - if err != nil { - utils.InternalServerError(w, err) - return - } - filter.IsAutomated = types.NewOptionalBool(isAutomated) - } - } - options := image.SearchOptions{ - Filter: filter, - Limit: query.Limit, - } - - if _, found := r.URL.Query()["tlsVerify"]; found { - options.InsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) - } - _, authfile, key, err := auth.GetCredentials(r) if err != nil { utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) return } defer auth.RemoveAuthfile(authfile) - options.Authfile = authfile - results, err := image.SearchImages(query.Term, options) + filters := []string{} + for key, val := range query.Filters { + filters = append(filters, fmt.Sprintf("%s=%s", key, val[0])) + } + + options := entities.ImageSearchOptions{ + Authfile: authfile, + Limit: query.Limit, + NoTrunc: query.NoTrunc, + ListTags: query.ListTags, + Filters: filters, + } + if _, found := r.URL.Query()["tlsVerify"]; found { + options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) + } + ir := abi.ImageEngine{Libpod: runtime} + reports, err := ir.Search(r.Context(), query.Term, options) if err != nil { - utils.BadRequest(w, "term", query.Term, err) + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) return } - - compatResults := make([]registry.SearchResult, 0, len(results)) - for _, result := range results { - compatResult := registry.SearchResult{ - Name: result.Name, - Description: result.Description, - StarCount: result.Stars, - IsAutomated: result.Automated == "[OK]", - IsOfficial: result.Official == "[OK]", + if !utils.IsLibpodRequest(r) { + if len(reports) == 0 { + utils.ImageNotFound(w, query.Term, define.ErrNoSuchImage) + return } - compatResults = append(compatResults, compatResult) } - utils.WriteResponse(w, http.StatusOK, compatResults) + utils.WriteResponse(w, http.StatusOK, reports) } diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 6b07b1cc5..f6e348cef 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -12,7 +12,6 @@ import ( "github.com/containers/podman/v2/pkg/api/handlers/utils" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/domain/infra/abi" - "github.com/containers/podman/v2/pkg/ps" "github.com/gorilla/schema" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -63,6 +62,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { All bool `schema:"all"` + External bool `schema:"external"` Filters map[string][]string `schema:"filters"` Last int `schema:"last"` // alias for limit Limit int `schema:"limit"` @@ -90,17 +90,22 @@ func ListContainers(w http.ResponseWriter, r *http.Request) { } runtime := r.Context().Value("runtime").(*libpod.Runtime) + // Now use the ABI implementation to prevent us from having duplicate + // code. + containerEngine := abi.ContainerEngine{Libpod: runtime} opts := entities.ContainerListOptions{ All: query.All, + External: query.External, Filters: query.Filters, Last: limit, - Size: query.Size, - Sort: "", Namespace: query.Namespace, - Pod: true, - Sync: query.Sync, + // Always return Pod, should not be part of the API. + // https://github.com/containers/podman/pull/7223 + Pod: true, + Size: query.Size, + Sync: query.Sync, } - pss, err := ps.GetContainerLists(runtime, opts) + pss, err := containerEngine.ContainerList(r.Context(), opts) if err != nil { utils.InternalServerError(w, err) return @@ -143,6 +148,12 @@ func GetContainer(w http.ResponseWriter, r *http.Request) { func WaitContainer(w http.ResponseWriter, r *http.Request) { exitCode, err := utils.WaitContainer(w, r) if err != nil { + name := utils.GetName(r) + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, name, err) + return + } + logrus.Warnf("failed to wait on container %q: %v", name, err) return } utils.WriteResponse(w, http.StatusOK, strconv.Itoa(int(exitCode))) diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 97cd5a65e..3b531652f 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -589,92 +589,6 @@ func UntagImage(w http.ResponseWriter, r *http.Request) { utils.WriteResponse(w, http.StatusCreated, "") } -func SearchImages(w http.ResponseWriter, r *http.Request) { - decoder := r.Context().Value("decoder").(*schema.Decoder) - query := struct { - Term string `json:"term"` - Limit int `json:"limit"` - NoTrunc bool `json:"noTrunc"` - Filters map[string][]string `json:"filters"` - TLSVerify bool `json:"tlsVerify"` - ListTags bool `json:"listTags"` - }{ - // 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 - } - - filter := image.SearchFilter{} - if len(query.Filters) > 0 { - if len(query.Filters["stars"]) > 0 { - stars, err := strconv.Atoi(query.Filters["stars"][0]) - if err != nil { - utils.InternalServerError(w, err) - return - } - filter.Stars = stars - } - if len(query.Filters["is-official"]) > 0 { - isOfficial, err := strconv.ParseBool(query.Filters["is-official"][0]) - if err != nil { - utils.InternalServerError(w, err) - return - } - filter.IsOfficial = types.NewOptionalBool(isOfficial) - } - if len(query.Filters["is-automated"]) > 0 { - isAutomated, err := strconv.ParseBool(query.Filters["is-automated"][0]) - if err != nil { - utils.InternalServerError(w, err) - return - } - filter.IsAutomated = types.NewOptionalBool(isAutomated) - } - } - options := image.SearchOptions{ - Limit: query.Limit, - NoTrunc: query.NoTrunc, - ListTags: query.ListTags, - Filter: filter, - } - - if _, found := r.URL.Query()["tlsVerify"]; found { - options.InsecureSkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) - } - - _, authfile, key, err := auth.GetCredentials(r) - if err != nil { - utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) - return - } - defer auth.RemoveAuthfile(authfile) - options.Authfile = authfile - - searchResults, err := image.SearchImages(query.Term, options) - if err != nil { - utils.BadRequest(w, "term", query.Term, err) - return - } - // Convert from image.SearchResults to entities.ImageSearchReport. We don't - // want to leak any low-level packages into the remote client, which - // requires converting. - reports := make([]entities.ImageSearchReport, len(searchResults)) - for i := range searchResults { - reports[i].Index = searchResults[i].Index - reports[i].Name = searchResults[i].Name - reports[i].Description = searchResults[i].Description - reports[i].Stars = searchResults[i].Stars - reports[i].Official = searchResults[i].Official - reports[i].Automated = searchResults[i].Automated - reports[i].Tag = searchResults[i].Tag - } - - utils.WriteResponse(w, http.StatusOK, reports) -} - // ImagesBatchRemove is the endpoint for batch image removal. func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go index 35221ecf1..ded51a31f 100644 --- a/pkg/api/handlers/libpod/manifests.go +++ b/pkg/api/handlers/libpod/manifests.go @@ -147,7 +147,6 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { query := struct { All bool `schema:"all"` Destination string `schema:"destination"` - Format string `schema:"format"` TLSVerify bool `schema:"tlsVerify"` }{ // Add defaults here once needed. @@ -163,24 +162,21 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) { } source := utils.GetName(r) - authConf, authfile, key, err := auth.GetCredentials(r) + authconf, authfile, key, err := auth.GetCredentials(r) if err != nil { utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String())) return } defer auth.RemoveAuthfile(authfile) var username, password string - if authConf != nil { - username = authConf.Username - password = authConf.Password - + if authconf != nil { + username = authconf.Username + password = authconf.Password } - options := entities.ImagePushOptions{ Authfile: authfile, Username: username, Password: password, - Format: query.Format, All: query.All, } if sys := runtime.SystemContext(); sys != nil { diff --git a/pkg/api/handlers/utils/containers.go b/pkg/api/handlers/utils/containers.go index 1439a3a75..fac237f87 100644 --- a/pkg/api/handlers/utils/containers.go +++ b/pkg/api/handlers/utils/containers.go @@ -6,6 +6,8 @@ import ( "github.com/containers/podman/v2/libpod" "github.com/containers/podman/v2/libpod/define" + "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -16,10 +18,13 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) { interval time.Duration ) runtime := r.Context().Value("runtime").(*libpod.Runtime) + // Now use the ABI implementation to prevent us from having duplicate + // code. + containerEngine := abi.ContainerEngine{Libpod: runtime} decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - Interval string `schema:"interval"` - Condition string `schema:"condition"` + Interval string `schema:"interval"` + Condition define.ContainerStatus `schema:"condition"` }{ // Override golang default values for types } @@ -27,6 +32,10 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) { Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return 0, err } + options := entities.WaitOptions{ + Condition: define.ContainerStateStopped, + } + name := GetName(r) if _, found := r.URL.Query()["interval"]; found { interval, err = time.ParseDuration(query.Interval) if err != nil { @@ -40,19 +49,19 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) (int32, error) { return 0, err } } - condition := define.ContainerStateStopped + options.Interval = interval + if _, found := r.URL.Query()["condition"]; found { - condition, err = define.StringToContainerStatus(query.Condition) - if err != nil { - InternalServerError(w, err) - return 0, err - } + options.Condition = query.Condition } - name := GetName(r) - con, err := runtime.LookupContainer(name) + + report, err := containerEngine.ContainerWait(r.Context(), []string{name}, options) if err != nil { - ContainerNotFound(w, name, err) return 0, err } - return con.WaitForConditionWithInterval(interval, condition) + if len(report) == 0 { + InternalServerError(w, errors.New("No reports returned")) + return 0, err + } + return report[0].ExitCode, report[0].Error } |