summaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/compat/containers.go45
-rw-r--r--pkg/api/handlers/compat/containers_archive.go17
-rw-r--r--pkg/api/handlers/compat/images_build.go19
-rw-r--r--pkg/api/handlers/libpod/containers_create.go1
-rw-r--r--pkg/api/handlers/libpod/containers_stats.go12
-rw-r--r--pkg/api/handlers/types.go7
-rw-r--r--pkg/api/server/docs.go2
-rw-r--r--pkg/api/server/register_archive.go4
-rw-r--r--pkg/api/server/register_containers.go4
-rw-r--r--pkg/api/server/register_volumes.go2
-rw-r--r--pkg/api/server/server.go9
11 files changed, 87 insertions, 35 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 2a0a0b725..95c09ff0e 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -403,22 +403,24 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
state.Status = define.ContainerStateCreated.String()
}
- state.Health = &types.Health{
- Status: inspect.State.Healthcheck.Status,
- FailingStreak: inspect.State.Healthcheck.FailingStreak,
- }
-
- log := inspect.State.Healthcheck.Log
+ if l.HasHealthCheck() && state.Status != "created" {
+ state.Health = &types.Health{
+ Status: inspect.State.Healthcheck.Status,
+ FailingStreak: inspect.State.Healthcheck.FailingStreak,
+ }
- for _, item := range log {
- res := &types.HealthcheckResult{}
- s, _ := time.Parse(time.RFC3339Nano, item.Start)
- e, _ := time.Parse(time.RFC3339Nano, item.End)
- res.Start = s
- res.End = e
- res.ExitCode = item.ExitCode
- res.Output = item.Output
- state.Health.Log = append(state.Health.Log, res)
+ log := inspect.State.Healthcheck.Log
+
+ for _, item := range log {
+ res := &types.HealthcheckResult{}
+ s, _ := time.Parse(time.RFC3339Nano, item.Start)
+ e, _ := time.Parse(time.RFC3339Nano, item.End)
+ res.Start = s
+ res.End = e
+ res.ExitCode = item.ExitCode
+ res.Output = item.Output
+ state.Health.Log = append(state.Health.Log, res)
+ }
}
formatCapabilities(inspect.HostConfig.CapDrop)
@@ -495,6 +497,17 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
exposedPorts[exposedPort] = struct{}{}
}
+ var healthcheck *container.HealthConfig
+ if inspect.Config.Healthcheck != nil {
+ healthcheck = &container.HealthConfig{
+ Test: inspect.Config.Healthcheck.Test,
+ Interval: inspect.Config.Healthcheck.Interval,
+ Timeout: inspect.Config.Healthcheck.Timeout,
+ StartPeriod: inspect.Config.Healthcheck.StartPeriod,
+ Retries: inspect.Config.Healthcheck.Retries,
+ }
+ }
+
config := container.Config{
Hostname: l.Hostname(),
Domainname: inspect.Config.DomainName,
@@ -508,7 +521,7 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON,
StdinOnce: inspect.Config.StdinOnce,
Env: inspect.Config.Env,
Cmd: l.Command(),
- Healthcheck: nil,
+ Healthcheck: healthcheck,
ArgsEscaped: false,
Image: imageName,
Volumes: nil,
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index a9d74e5f4..541f702e7 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -1,6 +1,7 @@
package compat
import (
+ "encoding/json"
"fmt"
"net/http"
"os"
@@ -93,8 +94,9 @@ func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.De
func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
query := struct {
- Path string `schema:"path"`
- Chown bool `schema:"copyUIDGID"`
+ Path string `schema:"path"`
+ Chown bool `schema:"copyUIDGID"`
+ Rename string `schema:"rename"`
// TODO handle params below
NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
}{
@@ -107,10 +109,19 @@ func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder,
return
}
+ var rename map[string]string
+ if query.Rename != "" {
+ if err := json.Unmarshal([]byte(query.Rename), &rename); err != nil {
+ utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+ return
+ }
+ }
+
containerName := utils.GetName(r)
containerEngine := abi.ContainerEngine{Libpod: runtime}
- copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, entities.CopyOptions{Chown: query.Chown})
+ copyOptions := entities.CopyOptions{Chown: query.Chown, Rename: rename}
+ copyFunc, err := containerEngine.ContainerCopyFromArchive(r.Context(), containerName, query.Path, r.Body, copyOptions)
if errors.Cause(err) == define.ErrNoSuchCtr || os.IsNotExist(err) {
// 404 is returned for an absent container and path. The
// clients must deal with it accordingly.
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index 64805b7fa..2c98a5361 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -393,16 +393,16 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
defer auth.RemoveAuthfile(authfile)
// Channels all mux'ed in select{} below to follow API build protocol
- stdout := channel.NewWriter(make(chan []byte, 1))
+ stdout := channel.NewWriter(make(chan []byte))
defer stdout.Close()
- auxout := channel.NewWriter(make(chan []byte, 1))
+ auxout := channel.NewWriter(make(chan []byte))
defer auxout.Close()
- stderr := channel.NewWriter(make(chan []byte, 1))
+ stderr := channel.NewWriter(make(chan []byte))
defer stderr.Close()
- reporter := channel.NewWriter(make(chan []byte, 1))
+ reporter := channel.NewWriter(make(chan []byte))
defer reporter.Close()
runtime := r.Context().Value("runtime").(*libpod.Runtime)
@@ -529,7 +529,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(body)
enc.SetEscapeHTML(true)
-loop:
+
for {
m := struct {
Stream string `json:"stream,omitempty"`
@@ -543,13 +543,13 @@ loop:
stderr.Write([]byte(err.Error()))
}
flush()
- case e := <-auxout.Chan():
+ case e := <-reporter.Chan():
m.Stream = string(e)
if err := enc.Encode(m); err != nil {
stderr.Write([]byte(err.Error()))
}
flush()
- case e := <-reporter.Chan():
+ case e := <-auxout.Chan():
m.Stream = string(e)
if err := enc.Encode(m); err != nil {
stderr.Write([]byte(err.Error()))
@@ -561,8 +561,8 @@ loop:
logrus.Warnf("Failed to json encode error %v", err)
}
flush()
+ return
case <-runCtx.Done():
- flush()
if success {
if !utils.IsLibpodRequest(r) {
m.Stream = fmt.Sprintf("Successfully built %12.12s\n", imageID)
@@ -579,7 +579,8 @@ loop:
}
}
}
- break loop
+ flush()
+ return
case <-r.Context().Done():
cancel()
logrus.Infof("Client disconnect reported for build %q / %q.", registry, query.Dockerfile)
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index b92588346..65951861b 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -22,6 +22,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
+
warn, err := generate.CompleteSpec(r.Context(), runtime, &sg)
if err != nil {
utils.InternalServerError(w, err)
diff --git a/pkg/api/handlers/libpod/containers_stats.go b/pkg/api/handlers/libpod/containers_stats.go
index 1807823fa..8a04884b0 100644
--- a/pkg/api/handlers/libpod/containers_stats.go
+++ b/pkg/api/handlers/libpod/containers_stats.go
@@ -6,8 +6,10 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
+ "github.com/containers/podman/v3/pkg/cgroups"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
+ "github.com/containers/podman/v3/pkg/rootless"
"github.com/gorilla/schema"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -17,6 +19,16 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
+ // Check if service is running rootless (cheap check)
+ if rootless.IsRootless() {
+ // if so, then verify cgroup v2 available (more expensive check)
+ if isV2, _ := cgroups.IsCgroup2UnifiedMode(); !isV2 {
+ msg := "Container stats resource only available for cgroup v2"
+ utils.Error(w, msg, http.StatusConflict, errors.New(msg))
+ return
+ }
+ }
+
query := struct {
Containers []string `schema:"containers"`
Stream bool `schema:"stream"`
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 3cc10d70f..af5878798 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -176,6 +176,11 @@ func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) {
}
containerCount := len(containers)
+ isDangling, err := l.IsDangling(context.TODO())
+ if err != nil {
+ return nil, errors.Wrapf(err, "failed to check if image %s is dangling", l.ID())
+ }
+
is := entities.ImageSummary{
ID: l.ID(),
ParentId: imageData.Parent,
@@ -188,7 +193,7 @@ func ImageToImageSummary(l *libimage.Image) (*entities.ImageSummary, error) {
Labels: imageData.Labels,
Containers: containerCount,
ReadOnly: l.IsReadOnly(),
- Dangling: l.IsDangling(),
+ Dangling: isDangling,
Names: l.Names(),
Digest: string(imageData.Digest),
ConfigDigest: "", // TODO: libpod/image didn't set it but libimage should
diff --git a/pkg/api/server/docs.go b/pkg/api/server/docs.go
index e72b78221..bf15afbf9 100644
--- a/pkg/api/server/docs.go
+++ b/pkg/api/server/docs.go
@@ -42,7 +42,7 @@
//
// InfoExtensions:
// x-logo:
-// - url: https://raw.githubusercontent.com/containers/libpod/master/logo/podman-logo.png
+// - url: https://raw.githubusercontent.com/containers/libpod/main/logo/podman-logo.png
// - altText: "Podman logo"
//
// Produces:
diff --git a/pkg/api/server/register_archive.go b/pkg/api/server/register_archive.go
index ee7449fbb..82d72ee6a 100644
--- a/pkg/api/server/register_archive.go
+++ b/pkg/api/server/register_archive.go
@@ -151,6 +151,10 @@ func (s *APIServer) registerArchiveHandlers(r *mux.Router) error {
// type: string
// description: Path to a directory in the container to extract
// required: true
+ // - in: query
+ // name: rename
+ // type: string
+ // description: JSON encoded map[string]string to translate paths
// responses:
// 200:
// description: no error
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 5a4137533..0ec4f95d9 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -1085,6 +1085,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// description: no error
// 404:
// $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/{name}/stats"), s.APIHandler(compat.StatsContainer)).Methods(http.MethodGet)
@@ -1118,6 +1120,8 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// description: no error
// 404:
// $ref: "#/responses/NoSuchContainer"
+ // 409:
+ // $ref: "#/responses/ConflictError"
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/containers/stats"), s.APIHandler(libpod.StatsContainer)).Methods(http.MethodGet)
diff --git a/pkg/api/server/register_volumes.go b/pkg/api/server/register_volumes.go
index d58bf0662..fb02cffcf 100644
--- a/pkg/api/server/register_volumes.go
+++ b/pkg/api/server/register_volumes.go
@@ -68,6 +68,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// - label=<key> or label=<key>:<value> Matches volumes based on the presence of a label alone or a label and a value.
// - name=<volume-name> Matches all of volume name.
// - opt=<driver-option> Matches a storage driver options
+ // - `until=<timestamp>` List volumes 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.
// responses:
// '200':
// "$ref": "#/responses/VolumeList"
@@ -166,6 +167,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// - driver=<volume-driver-name> Matches volumes based on their driver.
// - label=<key> or label=<key>:<value> Matches volumes based on the presence of a label alone or a label and a value.
// - name=<volume-name> Matches all of volume name.
+ // - `until=<timestamp>` List volumes 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.
//
// Note:
// The boolean `dangling` filter is not yet implemented for this endpoint.
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 1e8faf8f5..72ae27276 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -90,11 +90,10 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
server := APIServer{
Server: http.Server{
- Handler: router,
- ReadHeaderTimeout: 20 * time.Second,
- IdleTimeout: duration * 2,
- ConnState: idle.ConnState,
- ErrorLog: log.New(logrus.StandardLogger().Out, "", 0),
+ Handler: router,
+ IdleTimeout: duration * 2,
+ ConnState: idle.ConnState,
+ ErrorLog: log.New(logrus.StandardLogger().Out, "", 0),
},
Decoder: handlers.NewAPIDecoder(),
idleTracker: idle,