diff options
Diffstat (limited to 'pkg/api/handlers/libpod')
-rw-r--r-- | pkg/api/handlers/libpod/containers.go | 6 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/healthcheck.go | 24 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/manifests.go | 166 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/pods.go | 7 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/swagger.go | 36 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/volumes.go | 20 |
6 files changed, 246 insertions, 13 deletions
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go index 8020c391d..cdc34004f 100644 --- a/pkg/api/handlers/libpod/containers.go +++ b/pkg/api/handlers/libpod/containers.go @@ -21,8 +21,12 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) { name := utils.GetName(r) _, err := runtime.LookupContainer(name) if err != nil { - utils.ContainerNotFound(w, name, err) + if errors.Cause(err) == define.ErrNoSuchCtr { + utils.ContainerNotFound(w, name, err) + } + utils.InternalServerError(w, err) return + } utils.WriteResponse(w, http.StatusNoContent, "") } diff --git a/pkg/api/handlers/libpod/healthcheck.go b/pkg/api/handlers/libpod/healthcheck.go index 6c74500b9..6eb2ab0e3 100644 --- a/pkg/api/handlers/libpod/healthcheck.go +++ b/pkg/api/handlers/libpod/healthcheck.go @@ -14,8 +14,30 @@ func RunHealthCheck(w http.ResponseWriter, r *http.Request) { if err != nil { if status == libpod.HealthCheckContainerNotFound { utils.ContainerNotFound(w, name, err) + return } + if status == libpod.HealthCheckNotDefined { + utils.Error(w, "no healthcheck defined", http.StatusConflict, err) + return + } + if status == libpod.HealthCheckContainerStopped { + utils.Error(w, "container not running", http.StatusConflict, err) + return + } + utils.InternalServerError(w, err) + return + } + ctr, err := runtime.LookupContainer(name) + if err != nil { utils.InternalServerError(w, err) + return } - utils.WriteResponse(w, http.StatusOK, status) + + hcLog, err := ctr.GetHealthCheckLog() + if err != nil { + utils.InternalServerError(w, err) + return + } + + utils.WriteResponse(w, http.StatusOK, hcLog) } diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go new file mode 100644 index 000000000..a3d2caba6 --- /dev/null +++ b/pkg/api/handlers/libpod/manifests.go @@ -0,0 +1,166 @@ +package libpod + +import ( + "encoding/json" + "net/http" + + "github.com/containers/buildah/manifests" + copy2 "github.com/containers/image/v5/copy" + "github.com/containers/image/v5/transports/alltransports" + "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/api/handlers" + "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/gorilla/schema" + "github.com/opencontainers/go-digest" + "github.com/pkg/errors" +) + +func ManifestCreate(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Name []string `schema:"name"` + Image []string `schema:"image"` + All bool `schema:"all"` + }{ + // Add defaults here once needed. + } + 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 + } + rtc, err := runtime.GetConfig() + if err != nil { + utils.InternalServerError(w, err) + return + } + sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + manID, err := image.CreateManifestList(runtime.ImageRuntime(), *sc, query.Name, query.Image, query.All) + if err != nil { + utils.InternalServerError(w, err) + return + } + utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: manID}) +} + +func ManifestInspect(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + name := utils.GetName(r) + newImage, err := runtime.ImageRuntime().NewFromLocal(name) + if err != nil { + utils.ImageNotFound(w, name, err) + return + } + data, err := newImage.InspectManifest() + if err != nil { + utils.InternalServerError(w, err) + return + } + utils.WriteResponse(w, http.StatusOK, data) +} + +func ManifestAdd(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + var manifestInput image.ManifestAddOpts + if err := json.NewDecoder(r.Body).Decode(&manifestInput); err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + return + } + name := utils.GetName(r) + newImage, err := runtime.ImageRuntime().NewFromLocal(name) + if err != nil { + utils.ImageNotFound(w, name, err) + return + } + rtc, err := runtime.GetConfig() + if err != nil { + utils.InternalServerError(w, err) + return + } + sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + newID, err := newImage.AddManifest(*sc, manifestInput) + if err != nil { + utils.InternalServerError(w, err) + return + } + utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: newID}) +} + +func ManifestRemove(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + Digest string `schema:"digest"` + }{ + // Add defaults here once needed. + } + name := utils.GetName(r) + 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 + } + newImage, err := runtime.ImageRuntime().NewFromLocal(name) + if err != nil { + utils.ImageNotFound(w, name, err) + return + } + d, err := digest.Parse(query.Digest) + if err != nil { + utils.Error(w, "invalid digest", http.StatusBadRequest, err) + return + } + newID, err := newImage.RemoveManifest(d) + if err != nil { + utils.InternalServerError(w, err) + return + } + utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: newID}) +} +func ManifestPush(w http.ResponseWriter, r *http.Request) { + runtime := r.Context().Value("runtime").(*libpod.Runtime) + decoder := r.Context().Value("decoder").(*schema.Decoder) + query := struct { + All bool `schema:"all"` + Destination string `schema:"destination"` + }{ + // Add defaults here once needed. + } + 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 + } + name := utils.GetName(r) + newImage, err := runtime.ImageRuntime().NewFromLocal(name) + if err != nil { + utils.ImageNotFound(w, name, err) + return + } + dest, err := alltransports.ParseImageName(query.Destination) + if err != nil { + utils.Error(w, "invalid destination parameter", http.StatusBadRequest, errors.Errorf("invalid destination parameter %q", query.Destination)) + return + } + rtc, err := runtime.GetConfig() + if err != nil { + utils.InternalServerError(w, err) + return + } + sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false) + opts := manifests.PushOptions{ + ImageListSelection: copy2.CopySpecificImages, + SystemContext: sc, + } + if query.All { + opts.ImageListSelection = copy2.CopyAllImages + } + newD, err := newImage.PushManifest(dest, opts) + if err != nil { + utils.InternalServerError(w, err) + return + } + utils.WriteResponse(w, http.StatusOK, newD.String()) +} diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index f93c8f8d5..27ec64d89 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -103,7 +103,6 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { func Pods(w http.ResponseWriter, r *http.Request) { var ( - runtime = r.Context().Value("runtime").(*libpod.Runtime) podInspectData []*libpod.PodInspect ) decoder := r.Context().Value("decoder").(*schema.Decoder) @@ -118,12 +117,8 @@ func Pods(w http.ResponseWriter, r *http.Request) { return } - if len(query.Filters) > 0 { - utils.Error(w, "filters are not implemented yet", http.StatusInternalServerError, define.ErrNotImplemented) - return - } + pods, err := utils.GetPods(w, r) - pods, err := runtime.GetAllPods() if err != nil { utils.Error(w, "Something went wrong", http.StatusInternalServerError, err) return diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go index aec30ef56..149fa10dc 100644 --- a/pkg/api/handlers/libpod/swagger.go +++ b/pkg/api/handlers/libpod/swagger.go @@ -1,8 +1,44 @@ package libpod +import ( + "net/http" + "os" + + "github.com/containers/image/v5/manifest" + "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/pkg/errors" +) + +// DefaultPodmanSwaggerSpec provides the default path to the podman swagger spec file +const DefaultPodmanSwaggerSpec = "/usr/share/containers/podman/swagger.yaml" + // List Containers // swagger:response ListContainers type swagInspectPodResponse struct { // in:body Body []ListContainer } + +// Inspect Manifest +// swagger:response InspectManifest +type swagInspectManifestResponse struct { + // in:body + Body manifest.List +} + +func ServeSwagger(w http.ResponseWriter, r *http.Request) { + path := DefaultPodmanSwaggerSpec + if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found { + path = p + } + if _, err := os.Stat(path); err != nil { + if os.IsNotExist(err) { + utils.InternalServerError(w, errors.Errorf("file %q does not exist", path)) + return + } + utils.InternalServerError(w, err) + return + } + w.Header().Set("Content-Type", "text/yaml") + http.ServeFile(w, r, path) +} diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go index 9b10ee890..06ca1d225 100644 --- a/pkg/api/handlers/libpod/volumes.go +++ b/pkg/api/handlers/libpod/volumes.go @@ -8,8 +8,8 @@ import ( "github.com/containers/libpod/cmd/podman/shared" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/define" - "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" + "github.com/containers/libpod/pkg/domain/entities" "github.com/gorilla/schema" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -25,7 +25,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { }{ // override any golang type defaults } - input := handlers.VolumeCreateConfig{} + input := entities.VolumeCreateOptions{} 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())) @@ -46,8 +46,8 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { if len(input.Label) > 0 { volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Label)) } - if len(input.Opts) > 0 { - parsedOptions, err := shared.ParseVolumeOptions(input.Opts) + if len(input.Options) > 0 { + parsedOptions, err := shared.ParseVolumeOptions(input.Options) if err != nil { utils.InternalServerError(w, err) return @@ -64,7 +64,17 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) { utils.InternalServerError(w, err) return } - utils.WriteResponse(w, http.StatusOK, config) + volResponse := entities.VolumeConfigResponse{ + Name: config.Name, + Labels: config.Labels, + Driver: config.Driver, + MountPoint: config.MountPoint, + CreatedTime: config.CreatedTime, + Options: config.Options, + UID: config.UID, + GID: config.GID, + } + utils.WriteResponse(w, http.StatusOK, volResponse) } func InspectVolume(w http.ResponseWriter, r *http.Request) { |