diff options
-rw-r--r-- | cmd/podman/shared/pod.go | 56 | ||||
-rw-r--r-- | libpod/define/podstate.go | 19 | ||||
-rw-r--r-- | libpod/pod_status.go | 59 | ||||
-rw-r--r-- | libpod/runtime_pod.go | 28 | ||||
-rw-r--r-- | pkg/adapter/pods.go | 4 | ||||
-rw-r--r-- | pkg/adapter/pods_remote.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/containers_create.go (renamed from pkg/api/handlers/generic/containers_create.go) | 9 | ||||
-rw-r--r-- | pkg/api/handlers/generic/config.go | 9 | ||||
-rw-r--r-- | pkg/api/handlers/generic/images.go | 70 | ||||
-rw-r--r-- | pkg/api/handlers/generic/swagger.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/images.go | 41 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/containers.go | 6 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 60 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/pods.go | 41 | ||||
-rw-r--r-- | pkg/api/handlers/types.go | 8 | ||||
-rw-r--r-- | pkg/api/handlers/utils/images.go | 12 | ||||
-rw-r--r-- | pkg/api/server/docs.go | 3 | ||||
-rw-r--r-- | pkg/api/server/register_containers.go | 4 | ||||
-rw-r--r-- | pkg/api/server/register_images.go | 62 | ||||
-rw-r--r-- | pkg/api/server/register_pods.go | 16 |
20 files changed, 299 insertions, 216 deletions
diff --git a/cmd/podman/shared/pod.go b/cmd/podman/shared/pod.go index d8d69c8fc..7b0b497fc 100644 --- a/cmd/podman/shared/pod.go +++ b/cmd/podman/shared/pod.go @@ -10,14 +10,8 @@ import ( "github.com/pkg/errors" ) -const ( - PodStateStopped = "Stopped" - PodStateRunning = "Running" - PodStatePaused = "Paused" - PodStateExited = "Exited" - PodStateErrored = "Error" - PodStateCreated = "Created" -) +// TODO GetPodStatus and CreatePodStatusResults should removed once the adapter +// and shared packages are reworked. It has now been duplicated in libpod proper. // GetPodStatus determines the status of the pod based on the // statuses of the containers in the pod. @@ -25,7 +19,7 @@ const ( func GetPodStatus(pod *libpod.Pod) (string, error) { ctrStatuses, err := pod.Status() if err != nil { - return PodStateErrored, err + return define.PodStateErrored, err } return CreatePodStatusResults(ctrStatuses) } @@ -33,45 +27,45 @@ func GetPodStatus(pod *libpod.Pod) (string, error) { func CreatePodStatusResults(ctrStatuses map[string]define.ContainerStatus) (string, error) { ctrNum := len(ctrStatuses) if ctrNum == 0 { - return PodStateCreated, nil + return define.PodStateCreated, nil } statuses := map[string]int{ - PodStateStopped: 0, - PodStateRunning: 0, - PodStatePaused: 0, - PodStateCreated: 0, - PodStateErrored: 0, + define.PodStateStopped: 0, + define.PodStateRunning: 0, + define.PodStatePaused: 0, + define.PodStateCreated: 0, + define.PodStateErrored: 0, } for _, ctrStatus := range ctrStatuses { switch ctrStatus { case define.ContainerStateExited: fallthrough case define.ContainerStateStopped: - statuses[PodStateStopped]++ + statuses[define.PodStateStopped]++ case define.ContainerStateRunning: - statuses[PodStateRunning]++ + statuses[define.PodStateRunning]++ case define.ContainerStatePaused: - statuses[PodStatePaused]++ + statuses[define.PodStatePaused]++ case define.ContainerStateCreated, define.ContainerStateConfigured: - statuses[PodStateCreated]++ + statuses[define.PodStateCreated]++ default: - statuses[PodStateErrored]++ + statuses[define.PodStateErrored]++ } } switch { - case statuses[PodStateRunning] > 0: - return PodStateRunning, nil - case statuses[PodStatePaused] == ctrNum: - return PodStatePaused, nil - case statuses[PodStateStopped] == ctrNum: - return PodStateExited, nil - case statuses[PodStateStopped] > 0: - return PodStateStopped, nil - case statuses[PodStateErrored] > 0: - return PodStateErrored, nil + case statuses[define.PodStateRunning] > 0: + return define.PodStateRunning, nil + case statuses[define.PodStatePaused] == ctrNum: + return define.PodStatePaused, nil + case statuses[define.PodStateStopped] == ctrNum: + return define.PodStateExited, nil + case statuses[define.PodStateStopped] > 0: + return define.PodStateStopped, nil + case statuses[define.PodStateErrored] > 0: + return define.PodStateErrored, nil default: - return PodStateCreated, nil + return define.PodStateCreated, nil } } diff --git a/libpod/define/podstate.go b/libpod/define/podstate.go new file mode 100644 index 000000000..2b59aabfb --- /dev/null +++ b/libpod/define/podstate.go @@ -0,0 +1,19 @@ +package define + +const ( + // PodStateCreated indicates the pod is created but has not been started + PodStateCreated = "Created" + // PodStateErrored indicates the pod is in an errored state where + // information about it can no longer be retrieved + PodStateErrored = "Error" + // PodStateExited indicates the pod ran but has been stopped + PodStateExited = "Exited" + // PodStatePaused indicates the pod has been paused + PodStatePaused = "Paused" + // PodStateRunning indicates that one or more of the containers in + // the pod is running + PodStateRunning = "Running" + // PodStateStopped indicates all of the containers belonging to the pod + // are stopped. + PodStateStopped = "Stopped" +) diff --git a/libpod/pod_status.go b/libpod/pod_status.go new file mode 100644 index 000000000..3a44c4457 --- /dev/null +++ b/libpod/pod_status.go @@ -0,0 +1,59 @@ +package libpod + +import "github.com/containers/libpod/libpod/define" + +// GetPodStatus determines the status of the pod based on the +// statuses of the containers in the pod. +// Returns a string representation of the pod status +func (p *Pod) GetPodStatus() (string, error) { + ctrStatuses, err := p.Status() + if err != nil { + return define.PodStateErrored, err + } + return CreatePodStatusResults(ctrStatuses) +} + +func CreatePodStatusResults(ctrStatuses map[string]define.ContainerStatus) (string, error) { + ctrNum := len(ctrStatuses) + if ctrNum == 0 { + return define.PodStateCreated, nil + } + statuses := map[string]int{ + define.PodStateStopped: 0, + define.PodStateRunning: 0, + define.PodStatePaused: 0, + define.PodStateCreated: 0, + define.PodStateErrored: 0, + } + for _, ctrStatus := range ctrStatuses { + switch ctrStatus { + case define.ContainerStateExited: + fallthrough + case define.ContainerStateStopped: + statuses[define.PodStateStopped]++ + case define.ContainerStateRunning: + statuses[define.PodStateRunning]++ + case define.ContainerStatePaused: + statuses[define.PodStatePaused]++ + case define.ContainerStateCreated, define.ContainerStateConfigured: + statuses[define.PodStateCreated]++ + default: + statuses[define.PodStateErrored]++ + } + } + + switch { + case statuses[define.PodStateRunning] > 0: + return define.PodStateRunning, nil + case statuses[define.PodStatePaused] == ctrNum: + return define.PodStatePaused, nil + case statuses[define.PodStateStopped] == ctrNum: + return define.PodStateExited, nil + case statuses[define.PodStateStopped] > 0: + return define.PodStateStopped, nil + case statuses[define.PodStateErrored] > 0: + return define.PodStateErrored, nil + default: + return define.PodStateCreated, nil + } +} diff --git a/libpod/runtime_pod.go b/libpod/runtime_pod.go index 66f9b10c9..e1dc31391 100644 --- a/libpod/runtime_pod.go +++ b/libpod/runtime_pod.go @@ -182,3 +182,31 @@ func (r *Runtime) GetRunningPods() ([]*Pod, error) { } return runningPods, nil } + +// PrunePods removes unused pods and their containers from local storage. +// If force is given, then running pods are also included in the pruning. +func (r *Runtime) PrunePods() (map[string]error, error) { + response := make(map[string]error) + states := []string{define.PodStateStopped, define.PodStateExited} + filterFunc := func(p *Pod) bool { + state, _ := p.GetPodStatus() + for _, status := range states { + if state == status { + return true + } + } + return false + } + pods, err := r.Pods(filterFunc) + if err != nil { + return nil, err + } + if len(pods) < 1 { + return response, nil + } + for _, pod := range pods { + err := r.removePod(context.TODO(), pod, true, false) + response[pod.ID()] = err + } + return response, nil +} diff --git a/pkg/adapter/pods.go b/pkg/adapter/pods.go index 5891c361f..f89fc7011 100644 --- a/pkg/adapter/pods.go +++ b/pkg/adapter/pods.go @@ -58,9 +58,9 @@ func (r *LocalRuntime) PrunePods(ctx context.Context, cli *cliconfig.PodPruneVal } logrus.Debugf("Setting maximum rm workers to %d", maxWorkers) - states := []string{shared.PodStateStopped, shared.PodStateExited} + states := []string{define.PodStateStopped, define.PodStateExited} if cli.Force { - states = append(states, shared.PodStateRunning) + states = append(states, define.PodStateRunning) } pods, err := r.GetPodsByStatus(states) diff --git a/pkg/adapter/pods_remote.go b/pkg/adapter/pods_remote.go index 16d34769e..5ef1a9216 100644 --- a/pkg/adapter/pods_remote.go +++ b/pkg/adapter/pods_remote.go @@ -540,9 +540,9 @@ func (r *LocalRuntime) PrunePods(ctx context.Context, cli *cliconfig.PodPruneVal ok = []string{} failures = map[string]error{} ) - states := []string{shared.PodStateStopped, shared.PodStateExited} + states := []string{define.PodStateStopped, define.PodStateExited} if cli.Force { - states = append(states, shared.PodStateRunning) + states = append(states, define.PodStateRunning) } ids, err := iopodman.GetPodsByStatus().Call(r.Conn, states) diff --git a/pkg/api/handlers/generic/containers_create.go b/pkg/api/handlers/containers_create.go index edefd5757..4781b23bc 100644 --- a/pkg/api/handlers/generic/containers_create.go +++ b/pkg/api/handlers/containers_create.go @@ -1,4 +1,4 @@ -package generic +package handlers import ( "encoding/json" @@ -10,7 +10,6 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" image2 "github.com/containers/libpod/libpod/image" - "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/namespaces" createconfig "github.com/containers/libpod/pkg/spec" @@ -25,7 +24,7 @@ import ( func CreateContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) - input := handlers.CreateContainerConfig{} + input := CreateContainerConfig{} query := struct { Name string `schema:"name"` }{ @@ -74,13 +73,13 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { } response := ContainerCreateResponse{ - Id: ctr.ID(), + ID: ctr.ID(), Warnings: []string{}} utils.WriteResponse(w, http.StatusCreated, response) } -func makeCreateConfig(input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) { +func makeCreateConfig(input CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) { var ( err error init bool diff --git a/pkg/api/handlers/generic/config.go b/pkg/api/handlers/generic/config.go deleted file mode 100644 index f715d25eb..000000000 --- a/pkg/api/handlers/generic/config.go +++ /dev/null @@ -1,9 +0,0 @@ -package generic - -// ContainerCreateResponse is the response struct for creating a container -type ContainerCreateResponse struct { - // ID of the container created - Id string `json:"Id"` - // Warnings during container creation - Warnings []string `json:"Warnings"` -} diff --git a/pkg/api/handlers/generic/images.go b/pkg/api/handlers/generic/images.go index 93adb7f69..ba1cf47b4 100644 --- a/pkg/api/handlers/generic/images.go +++ b/pkg/api/handlers/generic/images.go @@ -6,7 +6,6 @@ import ( "io/ioutil" "net/http" "os" - "strconv" "strings" "github.com/containers/buildah" @@ -16,12 +15,10 @@ import ( "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/util" - "github.com/containers/storage" "github.com/docker/docker/api/types" "github.com/gorilla/mux" "github.com/gorilla/schema" "github.com/pkg/errors" - "github.com/sirupsen/logrus" ) func ExportImage(w http.ResponseWriter, r *http.Request) { @@ -59,11 +56,8 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { } func PruneImages(w http.ResponseWriter, r *http.Request) { - // 200 no error - // 500 internal var ( - dangling = true - err error + filters []string ) decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) @@ -79,60 +73,24 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { return } - // until ts is not supported on podman prune - if v, found := query.Filters["until"]; found { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "until=%s is not supported yet", v)) - return - } - // labels are not supported on podman prune - if _, found := query.Filters["since"]; found { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "labelis not supported yet")) - return - } - - if v, found := query.Filters["dangling"]; found { - dangling, err = strconv.ParseBool(v[0]) - if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "processing dangling filter")) - return + idr := []types.ImageDeleteResponseItem{} + for k, v := range query.Filters { + for _, val := range v { + filters = append(filters, fmt.Sprintf("%s=%s", k, val)) } } - - idr := []types.ImageDeleteResponseItem{} - // - // This code needs to be migrated to libpod to work correctly. I could not - // work my around the information docker needs with the existing prune in libpod. - // - pruneImages, err := runtime.ImageRuntime().GetPruneImages(!dangling, []image2.ImageFilter{}) + pruneCids, err := runtime.ImageRuntime().PruneImages(r.Context(), false, filters) if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to get images to prune")) + utils.InternalServerError(w, err) return } - for _, p := range pruneImages { - repotags, err := p.RepoTags() - if err != nil { - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to get repotags for image")) - return - } - if err := p.Remove(r.Context(), true); err != nil { - if errors.Cause(err) == storage.ErrImageUsedByContainer { - logrus.Warnf("Failed to prune image %s as it is in use: %v", p.ID(), err) - continue - } - utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to prune image")) - return - } - // newimageevent is not export therefore we cannot record the event. this will be fixed - // when the prune is fixed in libpod - // defer p.newImageEvent(events.Prune) - response := types.ImageDeleteResponseItem{ - Deleted: fmt.Sprintf("sha256:%s", p.ID()), // I ack this is not ideal - } - if len(repotags) > 0 { - response.Untagged = repotags[0] - } - idr = append(idr, response) + for _, p := range pruneCids { + idr = append(idr, types.ImageDeleteResponseItem{ + Deleted: p, + }) } + + //FIXME/TODO to do this exacty correct, pruneimages needs to return idrs and space-reclaimed, then we are golden ipr := types.ImagesPruneReport{ ImagesDeleted: idr, SpaceReclaimed: 1, // TODO we cannot supply this right now @@ -342,8 +300,6 @@ func GetImage(w http.ResponseWriter, r *http.Request) { } func GetImages(w http.ResponseWriter, r *http.Request) { - // 200 ok - // 500 internal images, err := utils.GetImages(w, r) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Failed get images")) diff --git a/pkg/api/handlers/generic/swagger.go b/pkg/api/handlers/generic/swagger.go index 27e1fc18d..bfe527c41 100644 --- a/pkg/api/handlers/generic/swagger.go +++ b/pkg/api/handlers/generic/swagger.go @@ -1,11 +1,13 @@ package generic +import "github.com/containers/libpod/pkg/api/handlers" + // Create container // swagger:response ContainerCreateResponse type swagCtrCreateResponse struct { // in:body Body struct { - ContainerCreateResponse + handlers.ContainerCreateResponse } } diff --git a/pkg/api/handlers/images.go b/pkg/api/handlers/images.go index b4acdc312..3f66a63c8 100644 --- a/pkg/api/handlers/images.go +++ b/pkg/api/handlers/images.go @@ -3,7 +3,6 @@ package handlers import ( "fmt" "io" - "io/ioutil" "net/http" "os" "strconv" @@ -127,46 +126,6 @@ func GetImage(r *http.Request, name string) (*image.Image, error) { return runtime.ImageRuntime().NewFromLocal(name) } -func LoadImage(w http.ResponseWriter, r *http.Request) { - decoder := r.Context().Value("decoder").(*schema.Decoder) - runtime := r.Context().Value("runtime").(*libpod.Runtime) - - query := struct { - //quiet bool # quiet is currently unused - }{ - // 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 := 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, "") - 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), - }) -} - func SaveFromBody(f *os.File, r *http.Request) error { // nolint if _, err := io.Copy(f, r.Body); err != nil { return err diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index df16843c7..db1cf26ff 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -19,8 +19,6 @@ func StopContainer(w http.ResponseWriter, r *http.Request) { } func ContainerExists(w http.ResponseWriter, r *http.Request) { - // 404 no such container - // 200 ok runtime := r.Context().Value("runtime").(*libpod.Runtime) name := mux.Vars(r)["name"] _, err := runtime.LookupContainer(name) @@ -147,10 +145,6 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) { // tail string } -func CreateContainer(w http.ResponseWriter, r *http.Request) { - -} - func UnmountContainer(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) name := mux.Vars(r)["name"] diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index bbc8c9346..9f0876618 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -2,9 +2,11 @@ package libpod import ( "fmt" + "io" "io/ioutil" "net/http" "os" + "strconv" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/api/handlers" @@ -91,12 +93,13 @@ func GetImages(w http.ResponseWriter, r *http.Request) { } func PruneImages(w http.ResponseWriter, r *http.Request) { - // 200 ok - // 500 internal + var ( + all bool + err error + ) runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - All bool `schema:"all"` Filters map[string][]string `schema:"filters"` }{ // override any golang type defaults @@ -110,11 +113,16 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { 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(), query.All, libpodFilters) + cids, err := runtime.ImageRuntime().PruneImages(r.Context(), all, libpodFilters) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) return @@ -171,3 +179,47 @@ func ExportImage(w http.ResponseWriter, r *http.Request) { 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), + }) +} diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index 656a75646..50d763338 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -268,7 +268,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) { decoder = r.Context().Value("decoder").(*schema.Decoder) ) query := struct { - force bool `schema:"force"` + Force bool `schema:"force"` }{ // override any golang type defaults } @@ -284,7 +284,7 @@ func PodDelete(w http.ResponseWriter, r *http.Request) { utils.PodNotFound(w, name, err) return } - if err := runtime.RemovePod(r.Context(), pod, true, query.force); err != nil { + if err := runtime.RemovePod(r.Context(), pod, true, query.Force); err != nil { utils.Error(w, "Something went wrong", http.StatusInternalServerError, err) return } @@ -309,43 +309,14 @@ func PodRestart(w http.ResponseWriter, r *http.Request) { func PodPrune(w http.ResponseWriter, r *http.Request) { var ( - err error - pods []*libpod.Pod runtime = r.Context().Value("runtime").(*libpod.Runtime) - decoder = r.Context().Value("decoder").(*schema.Decoder) ) - query := struct { - force bool `schema:"force"` - }{ - // 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 query.force { - pods, err = runtime.GetAllPods() - if err != nil { - utils.Error(w, "Something went wrong", http.StatusInternalServerError, err) - return - } - } else { - // TODO We need to make a libpod.PruneVolumes or this code will be a mess. Volumes - // already does this right. It will also help clean this code path up with less - // conditionals. We do this when we integrate with libpod again. - utils.Error(w, "not implemented", http.StatusInternalServerError, errors.New("not implemented")) + pruned, err := runtime.PrunePods() + if err != nil { + utils.InternalServerError(w, err) return } - for _, p := range pods { - if err := runtime.RemovePod(r.Context(), p, true, query.force); err != nil { - utils.Error(w, "Something went wrong", http.StatusInternalServerError, err) - return - } - } - utils.WriteResponse(w, http.StatusNoContent, "") + utils.WriteResponse(w, http.StatusOK, pruned) } func PodPause(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 33cd51164..33cf1e95d 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -537,3 +537,11 @@ func portsToPortSet(input map[string]struct{}) (nat.PortSet, error) { } return ports, nil } + +// ContainerCreateResponse is the response struct for creating a container +type ContainerCreateResponse struct { + // ID of the container created + ID string `json:"id"` + // Warnings during container creation + Warnings []string `json:"Warnings"` +} diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index a0d340471..2b651584a 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -6,6 +6,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" + "github.com/gorilla/mux" "github.com/gorilla/schema" ) @@ -15,17 +16,22 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) { decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { - // all bool # all is currently unused + All bool Filters map[string][]string `schema:"filters"` - // digests bool # digests is currently unused + Digests bool }{ // This is where you can override the golang default value for one of fields } + // TODO I think all is implemented with a filter? + if err := decoder.Decode(&query, r.URL.Query()); err != nil { return nil, err } - var filters = []string{} + if _, found := mux.Vars(r)["digests"]; found && query.Digests { + UnSupportedParameter("digests") + } + if _, found := r.URL.Query()["filters"]; found { filters = append(filters, fmt.Sprintf("reference=%s", "")) } diff --git a/pkg/api/server/docs.go b/pkg/api/server/docs.go index e028c6302..c989c7927 100644 --- a/pkg/api/server/docs.go +++ b/pkg/api/server/docs.go @@ -12,7 +12,8 @@ // Version: 0.0.1 // License: Apache-2.0 https://opensource.org/licenses/Apache-2.0 // Contact: Podman <podman@lists.podman.io> https://podman.io/community/ -// Extensions: +// +// InfoExtensions: // x-logo: // - url: https://raw.githubusercontent.com/containers/libpod/master/logo/podman-logo.png // - altText: "Podman logo" diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go index b2d2ab388..abae81c38 100644 --- a/pkg/api/server/register_containers.go +++ b/pkg/api/server/register_containers.go @@ -33,7 +33,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { // $ref: "#/responses/ConflictError" // 500: // $ref: "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/create"), APIHandler(s.Context, generic.CreateContainer)).Methods(http.MethodPost) + r.HandleFunc(VersionedPath("/containers/create"), APIHandler(s.Context, handlers.CreateContainer)).Methods(http.MethodPost) // swagger:operation GET /containers/json compat listContainers // --- // tags: @@ -550,7 +550,7 @@ func (s *APIServer) RegisterContainersHandlers(r *mux.Router) error { libpod endpoints */ - r.HandleFunc(VersionedPath("/libpod/containers/create"), APIHandler(s.Context, libpod.CreateContainer)).Methods(http.MethodPost) + r.HandleFunc(VersionedPath("/libpod/containers/create"), APIHandler(s.Context, handlers.CreateContainer)).Methods(http.MethodPost) // swagger:operation GET /libpod/containers/json libpod libpodListContainers // --- // tags: diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 6e8b79313..c59d3d379 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -55,6 +55,27 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - images (compat) // summary: List Images // description: Returns a list of images on the server. Note that it uses a different, smaller representation of an image than inspecting a single image. + // parameters: + // - name: all + // in: query + // description: "Show all images. Only images from a final layer (no children) are shown by default." + // type: boolean + // default: false + // - name: filters + // in: query + // description: | + // A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters: + // - `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) + // - `dangling=true` + // - `label=key` or `label="key=value"` of an image label + // - `reference`=(`<image-name>[:<tag>]`) + // - `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) + // type: string + // - name: digests + // in: query + // description: Not supported + // type: boolean + // default: false // produces: // - application/json // responses: @@ -63,7 +84,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/images/json"), APIHandler(s.Context, generic.GetImages)).Methods(http.MethodGet) - // swagger:operation POST /images/load compat loadImage + // swagger:operation POST /images/load compat importImage // --- // tags: // - images (compat) @@ -86,7 +107,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: no error // 500: // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost) + r.Handle(VersionedPath("/images/load"), APIHandler(s.Context, libpod.ImportImage)).Methods(http.MethodPost) // swagger:operation POST /images/prune compat pruneImages // --- // tags: @@ -585,6 +606,27 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // - images // summary: List Images // description: Returns a list of images on the server + // parameters: + // - name: "all" + // in: "query" + // description: "Show all images. Only images from a final layer (no children) are shown by default." + // type: "boolean" + // default: false + // - name: "filters" + // in: "query" + // description: | + // A JSON encoded value of the filters (a `map[string][]string`) to process on the images list. Available filters: + // - `before`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) + // - `dangling=true` + // - `label=key` or `label="key=value"` of an image label + // - `reference`=(`<image-name>[:<tag>]`) + // - `since`=(`<image-name>[:<tag>]`, `<image id>` or `<image@digest>`) + // type: "string" + // - name: "digests" + // in: "query" + // description: Not supported + // type: "boolean" + // default: false // produces: // - application/json // responses: @@ -593,7 +635,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // 500: // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/json"), APIHandler(s.Context, libpod.GetImages)).Methods(http.MethodGet) - // swagger:operation POST /libpod/images/load libpod libpodLoadImage + // swagger:operation POST /libpod/images/load libpod libpodImportImage // --- // tags: // - images @@ -604,6 +646,14 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // name: quiet // type: boolean // description: not supported + // - in: query + // name: change + // description: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR. JSON encoded string" + // type: string + // - in: query + // name: message + // description: Set commit message for imported image + // type: string // - in: body // name: request // description: tarball of container image @@ -617,7 +667,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: no error // 500: // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, handlers.LoadImage)).Methods(http.MethodPost) + r.Handle(VersionedPath("/libpod/images/load"), APIHandler(s.Context, libpod.ImportImage)).Methods(http.MethodPost) // swagger:operation POST /libpod/images/prune libpod libpodPruneImages // --- // tags: @@ -635,10 +685,6 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // (or `0`), all unused images are pruned. // - `until=<string>` Prune images created before this timestamp. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon machine’s time. // - `label` (`label=<key>`, `label=<key>=<value>`, `label!=<key>`, or `label!=<key>=<value>`) Prune images with (or without, in case `label!=...` is used) the specified labels. - // - in: query - // name: all - // type: boolean - // description: prune all images // produces: // - application/json // responses: diff --git a/pkg/api/server/register_pods.go b/pkg/api/server/register_pods.go index 1ef14b58c..5c7b51871 100644 --- a/pkg/api/server/register_pods.go +++ b/pkg/api/server/register_pods.go @@ -30,17 +30,15 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // swagger:operation POST /libpod/pods/prune pods PrunePods // --- // summary: Prune unused pods - // parameters: - // - in: query - // name: force - // description: force delete - // type: boolean - // default: false // produces: // - application/json // responses: - // 204: - // description: no error + // 200: + // description: tbd + // schema: + // type: object + // additionalProperties: + // type: string // 400: // $ref: "#/responses/BadParamError" // 500: @@ -60,7 +58,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error { // - in: query // name: force // type: boolean - // description: force delete + // description : force removal of a running pod by first stopping all containers, then removing all containers in the pod // responses: // 204: // description: no error |