mirror of
https://github.com/containers/podman.git
synced 2025-05-20 16:47:39 +08:00
APIv2 review corrections #3
The third pass of corrections for the APIv2. Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
19
libpod/define/podstate.go
Normal file
19
libpod/define/podstate.go
Normal file
@ -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"
|
||||
)
|
59
libpod/pod_status.go
Normal file
59
libpod/pod_status.go
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
@ -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"`
|
||||
}
|
@ -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{}
|
||||
//
|
||||
// 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{})
|
||||
for k, v := range query.Filters {
|
||||
for _, val := range v {
|
||||
filters = append(filters, fmt.Sprintf("%s=%s", k, val))
|
||||
}
|
||||
}
|
||||
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"))
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"]
|
||||
|
@ -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),
|
||||
})
|
||||
}
|
||||
|
@ -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()))
|
||||
pruned, err := runtime.PrunePods()
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
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"))
|
||||
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) {
|
||||
|
@ -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"`
|
||||
}
|
||||
|
@ -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", ""))
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user