summaryrefslogtreecommitdiff
path: root/pkg/api/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers')
-rw-r--r--pkg/api/handlers/compat/containers.go7
-rw-r--r--pkg/api/handlers/compat/containers_archive.go319
-rw-r--r--pkg/api/handlers/compat/containers_create.go6
-rw-r--r--pkg/api/handlers/compat/containers_pause.go2
-rw-r--r--pkg/api/handlers/compat/containers_restart.go2
-rw-r--r--pkg/api/handlers/compat/containers_start.go4
-rw-r--r--pkg/api/handlers/compat/containers_stop.go4
-rw-r--r--pkg/api/handlers/compat/containers_unpause.go2
-rw-r--r--pkg/api/handlers/compat/images.go2
-rw-r--r--pkg/api/handlers/compat/images_build.go8
-rw-r--r--pkg/api/handlers/compat/images_push.go1
-rw-r--r--pkg/api/handlers/compat/networks.go64
-rw-r--r--pkg/api/handlers/compat/ping.go1
-rw-r--r--pkg/api/handlers/compat/system.go82
-rw-r--r--pkg/api/handlers/compat/volumes.go4
-rw-r--r--pkg/api/handlers/libpod/images.go2
-rw-r--r--pkg/api/handlers/libpod/networks.go4
-rw-r--r--pkg/api/handlers/types.go71
18 files changed, 217 insertions, 368 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 5886455e7..7a3e5dd84 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -17,6 +17,7 @@ import (
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
+ "github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -73,7 +74,7 @@ func RemoveContainer(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
func ListContainers(w http.ResponseWriter, r *http.Request) {
@@ -207,7 +208,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
}
}
// Success
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
func WaitContainer(w http.ResponseWriter, r *http.Request) {
@@ -215,8 +216,10 @@ func WaitContainer(w http.ResponseWriter, r *http.Request) {
// /{version}/containers/(name)/wait
exitCode, err := utils.WaitContainer(w, r)
if err != nil {
+ logrus.Warnf("failed to wait on container %q: %v", mux.Vars(r)["name"], err)
return
}
+
utils.WriteResponse(w, http.StatusOK, handlers.ContainerWaitOKBody{
StatusCode: int(exitCode),
Error: struct {
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 1dd563393..223eb2cd5 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -5,24 +5,16 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
- "path/filepath"
- "strings"
-
- "github.com/containers/buildah/copier"
- "github.com/containers/buildah/pkg/chrootuser"
- "github.com/containers/podman/v2/libpod"
- "github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/pkg/api/handlers/utils"
- "github.com/containers/storage/pkg/idtools"
- "github.com/opencontainers/runtime-spec/specs-go"
-
"net/http"
"os"
"time"
+ "github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/define"
+ "github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/copy"
"github.com/gorilla/schema"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
func Archive(w http.ResponseWriter, r *http.Request) {
@@ -32,14 +24,14 @@ func Archive(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodPut:
handlePut(w, r, decoder, runtime)
- case http.MethodGet, http.MethodHead:
- handleHeadOrGet(w, r, decoder, runtime)
+ case http.MethodHead, http.MethodGet:
+ handleHeadAndGet(w, r, decoder, runtime)
default:
- utils.Error(w, fmt.Sprintf("not implemented, method: %v", r.Method), http.StatusNotImplemented, errors.New(fmt.Sprintf("not implemented, method: %v", r.Method)))
+ utils.Error(w, fmt.Sprintf("unsupported method: %v", r.Method), http.StatusNotImplemented, errors.New(fmt.Sprintf("unsupported method: %v", r.Method)))
}
}
-func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
+func handleHeadAndGet(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
query := struct {
Path string `schema:"path"`
}{}
@@ -66,170 +58,62 @@ func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Dec
return
}
- mountPoint, err := ctr.Mount()
+ source, err := copy.CopyItemForContainer(ctr, query.Path, true, true)
+ defer source.CleanUp()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to mount the container"))
+ utils.Error(w, "Not found.", http.StatusNotFound, errors.Wrapf(err, "error stating container path %q", query.Path))
return
}
- defer func() {
- if err := ctr.Unmount(false); err != nil {
- logrus.Warnf("failed to unmount container %s: %q", containerName, err)
- }
- }()
-
- opts := copier.StatOptions{}
-
- mountPoint, path, err := fixUpMountPointAndPath(runtime, ctr, mountPoint, query.Path)
+ // NOTE: Docker always sets the header.
+ info, err := source.Stat()
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, "Not found.", http.StatusNotFound, errors.Wrapf(err, "error stating container path %q", query.Path))
return
}
-
- stats, err := copier.Stat(mountPoint, "", opts, []string{filepath.Join(mountPoint, path)})
+ statHeader, err := fileInfoToDockerStats(info)
if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to get stats about file"))
- return
- }
-
- if len(stats) <= 0 || len(stats[0].Globbed) <= 0 {
- errs := make([]string, 0, len(stats))
-
- for _, stat := range stats {
- if stat.Error != "" {
- errs = append(errs, stat.Error)
- }
- }
-
- utils.Error(w, "Not found.", http.StatusNotFound, fmt.Errorf("file doesn't exist (errs: %q)", strings.Join(errs, ";")))
-
- return
- }
-
- statHeader, err := statsToHeader(stats[0].Results[stats[0].Globbed[0]])
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
-
w.Header().Add("X-Docker-Container-Path-Stat", statHeader)
- if r.Method == http.MethodGet {
- idMappingOpts, err := ctr.IDMappings()
- if err != nil {
- utils.Error(w, "Not found.", http.StatusInternalServerError,
- errors.Wrapf(err, "error getting IDMappingOptions"))
- return
- }
-
- destOwner := idtools.IDPair{UID: os.Getuid(), GID: os.Getgid()}
-
- opts := copier.GetOptions{
- UIDMap: idMappingOpts.UIDMap,
- GIDMap: idMappingOpts.GIDMap,
- ChownDirs: &destOwner,
- ChownFiles: &destOwner,
- KeepDirectoryNames: true,
- }
-
- w.WriteHeader(http.StatusOK)
-
- err = copier.Get(mountPoint, "", opts, []string{filepath.Join(mountPoint, path)}, w)
- if err != nil {
- logrus.Error(errors.Wrapf(err, "failed to copy from the %s container path %s", containerName, query.Path))
- return
- }
- } else {
+ // Our work is done when the user is interested in the header only.
+ if r.Method == http.MethodHead {
w.WriteHeader(http.StatusOK)
- }
-}
-
-func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
- query := struct {
- Path string `schema:"path"`
- // TODO handle params below
- NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
- CopyUIDGID bool `schema:"copyUIDGID"`
- }{}
-
- err := decoder.Decode(&query, r.URL.Query())
- if err != nil {
- utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
return
}
- ctrName := utils.GetName(r)
-
- ctr, err := runtime.LookupContainer(ctrName)
- if err != nil {
- utils.Error(w, "Not found", http.StatusNotFound, errors.Wrapf(err, "the %s container doesn't exists", ctrName))
- return
- }
-
- mountPoint, err := ctr.Mount()
- if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, errors.Wrapf(err, "failed to mount the %s container", ctrName))
- return
- }
-
- defer func() {
- if err := ctr.Unmount(false); err != nil {
- logrus.Warnf("failed to unmount container %s", ctrName)
- }
- }()
-
- user, err := getUser(mountPoint, ctr.User())
- if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
- return
- }
-
- idMappingOpts, err := ctr.IDMappings()
- if err != nil {
- utils.Error(w, "Something went wrong", http.StatusInternalServerError, errors.Wrapf(err, "error getting IDMappingOptions"))
- return
- }
-
- destOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)}
-
- opts := copier.PutOptions{
- UIDMap: idMappingOpts.UIDMap,
- GIDMap: idMappingOpts.GIDMap,
- ChownDirs: &destOwner,
- ChownFiles: &destOwner,
- }
-
- mountPoint, path, err := fixUpMountPointAndPath(runtime, ctr, mountPoint, query.Path)
+ // Alright, the users wants data from the container.
+ destination, err := copy.CopyItemForWriter(w)
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
w.WriteHeader(http.StatusOK)
-
- err = copier.Put(mountPoint, filepath.Join(mountPoint, path), opts, r.Body)
- if err != nil {
- logrus.Error(errors.Wrapf(err, "failed to copy to the %s container path %s", ctrName, query.Path))
+ if err := copy.Copy(&source, &destination, false); err != nil {
+ utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
}
-func statsToHeader(stats *copier.StatForItem) (string, error) {
- statsDTO := struct {
+func fileInfoToDockerStats(info *copy.FileInfo) (string, error) {
+ dockerStats := struct {
Name string `json:"name"`
Size int64 `json:"size"`
Mode os.FileMode `json:"mode"`
ModTime time.Time `json:"mtime"`
LinkTarget string `json:"linkTarget"`
}{
- Name: filepath.Base(stats.Name),
- Size: stats.Size,
- Mode: stats.Mode,
- ModTime: stats.ModTime,
- LinkTarget: stats.ImmediateTarget,
+ Name: info.Name,
+ Size: info.Size,
+ Mode: info.Mode,
+ ModTime: info.ModTime,
+ LinkTarget: info.LinkTarget,
}
- jsonBytes, err := json.Marshal(&statsDTO)
+ jsonBytes, err := json.Marshal(&dockerStats)
if err != nil {
return "", errors.Wrap(err, "failed to serialize file stats")
}
@@ -250,130 +134,45 @@ func statsToHeader(stats *copier.StatForItem) (string, error) {
return buff.String(), nil
}
-// the utility functions below are copied from abi/cp.go
-
-func getUser(mountPoint string, userspec string) (specs.User, error) {
- uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec)
- u := specs.User{
- UID: uid,
- GID: gid,
- Username: userspec,
- }
-
- if !strings.Contains(userspec, ":") {
- groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID))
- if err2 != nil {
- if errors.Cause(err2) != chrootuser.ErrNoSuchUser && err == nil {
- err = err2
- }
- } else {
- u.AdditionalGids = groups
- }
- }
-
- return u, err
-}
-
-func fixUpMountPointAndPath(runtime *libpod.Runtime, ctr *libpod.Container, mountPoint, ctrPath string) (string, string, error) {
- if !filepath.IsAbs(ctrPath) {
- endsWithSep := strings.HasSuffix(ctrPath, string(filepath.Separator))
- ctrPath = filepath.Join(ctr.WorkingDir(), ctrPath)
-
- if endsWithSep {
- ctrPath = ctrPath + string(filepath.Separator)
- }
- }
- if isVol, volDestName, volName := isVolumeDestName(ctrPath, ctr); isVol { //nolint(gocritic)
- newMountPoint, path, err := pathWithVolumeMount(runtime, volDestName, volName, ctrPath)
- if err != nil {
- return "", "", errors.Wrapf(err, "error getting source path from volume %s", volDestName)
- }
-
- mountPoint = newMountPoint
- ctrPath = path
- } else if isBindMount, mount := isBindMountDestName(ctrPath, ctr); isBindMount { //nolint(gocritic)
- newMountPoint, path := pathWithBindMountSource(mount, ctrPath)
- mountPoint = newMountPoint
- ctrPath = path
- }
-
- return mountPoint, ctrPath, nil
-}
-
-func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string) {
- separator := string(os.PathSeparator)
-
- if filepath.IsAbs(path) {
- path = strings.TrimPrefix(path, separator)
- }
-
- if path == "" {
- return false, "", ""
- }
-
- for _, vol := range ctr.Config().NamedVolumes {
- volNamePath := strings.TrimPrefix(vol.Dest, separator)
- if matchVolumePath(path, volNamePath) {
- return true, vol.Dest, vol.Name
- }
- }
-
- return false, "", ""
-}
+func handlePut(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
+ query := struct {
+ Path string `schema:"path"`
+ // TODO handle params below
+ NoOverwriteDirNonDir bool `schema:"noOverwriteDirNonDir"`
+ CopyUIDGID bool `schema:"copyUIDGID"`
+ }{}
-func pathWithVolumeMount(runtime *libpod.Runtime, volDestName, volName, path string) (string, string, error) {
- destVolume, err := runtime.GetVolume(volName)
+ err := decoder.Decode(&query, r.URL.Query())
if err != nil {
- return "", "", errors.Wrapf(err, "error getting volume destination %s", volName)
- }
-
- if !filepath.IsAbs(path) {
- path = filepath.Join(string(os.PathSeparator), path)
+ utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.Wrap(err, "couldn't decode the query"))
+ return
}
- return destVolume.MountPoint(), strings.TrimPrefix(path, volDestName), err
-}
-
-func isBindMountDestName(path string, ctr *libpod.Container) (bool, specs.Mount) {
- separator := string(os.PathSeparator)
-
- if filepath.IsAbs(path) {
- path = strings.TrimPrefix(path, string(os.PathSeparator))
- }
+ ctrName := utils.GetName(r)
- if path == "" {
- return false, specs.Mount{}
+ ctr, err := runtime.LookupContainer(ctrName)
+ if err != nil {
+ utils.Error(w, "Not found", http.StatusNotFound, errors.Wrapf(err, "the %s container doesn't exists", ctrName))
+ return
}
- for _, m := range ctr.Config().Spec.Mounts {
- if m.Type != "bind" {
- continue
- }
-
- mDest := strings.TrimPrefix(m.Destination, separator)
- if matchVolumePath(path, mDest) {
- return true, m
- }
+ destination, err := copy.CopyItemForContainer(ctr, query.Path, true, false)
+ defer destination.CleanUp()
+ if err != nil {
+ utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ return
}
- return false, specs.Mount{}
-}
-
-func matchVolumePath(path, target string) bool {
- pathStr := filepath.Clean(path)
- target = filepath.Clean(target)
-
- for len(pathStr) > len(target) && strings.Contains(pathStr, string(os.PathSeparator)) {
- pathStr = pathStr[:strings.LastIndex(pathStr, string(os.PathSeparator))]
+ source, err := copy.CopyItemForReader(r.Body)
+ defer source.CleanUp()
+ if err != nil {
+ utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ return
}
- return pathStr == target
-}
-
-func pathWithBindMountSource(m specs.Mount, path string) (string, string) {
- if !filepath.IsAbs(path) {
- path = filepath.Join(string(os.PathSeparator), path)
+ w.WriteHeader(http.StatusOK)
+ if err := copy.Copy(&source, &destination, false); err != nil {
+ utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
+ return
}
-
- return m.Source, strings.TrimPrefix(path, m.Destination)
}
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 729639928..409a74de2 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -37,6 +37,9 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
return
}
+ // Override the container name in the body struct
+ body.Name = query.Name
+
if len(body.HostConfig.Links) > 0 {
utils.Error(w, utils.ErrLinkNotSupport.Error(), http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter"))
return
@@ -69,9 +72,6 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
return
}
- // Override the container name in the body struct
- body.Name = query.Name
-
ic := abi.ContainerEngine{Libpod: runtime}
report, err := ic.ContainerCreate(r.Context(), sg)
if err != nil {
diff --git a/pkg/api/handlers/compat/containers_pause.go b/pkg/api/handlers/compat/containers_pause.go
index 8712969c0..a7e0a66f1 100644
--- a/pkg/api/handlers/compat/containers_pause.go
+++ b/pkg/api/handlers/compat/containers_pause.go
@@ -24,5 +24,5 @@ func PauseContainer(w http.ResponseWriter, r *http.Request) {
return
}
// Success
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
diff --git a/pkg/api/handlers/compat/containers_restart.go b/pkg/api/handlers/compat/containers_restart.go
index f4d8f06a1..e8928596a 100644
--- a/pkg/api/handlers/compat/containers_restart.go
+++ b/pkg/api/handlers/compat/containers_restart.go
@@ -41,5 +41,5 @@ func RestartContainer(w http.ResponseWriter, r *http.Request) {
}
// Success
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
diff --git a/pkg/api/handlers/compat/containers_start.go b/pkg/api/handlers/compat/containers_start.go
index 6236b1357..726da6f99 100644
--- a/pkg/api/handlers/compat/containers_start.go
+++ b/pkg/api/handlers/compat/containers_start.go
@@ -39,12 +39,12 @@ func StartContainer(w http.ResponseWriter, r *http.Request) {
return
}
if state == define.ContainerStateRunning {
- utils.WriteResponse(w, http.StatusNotModified, "")
+ utils.WriteResponse(w, http.StatusNotModified, nil)
return
}
if err := con.Start(r.Context(), len(con.PodID()) > 0); err != nil {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
diff --git a/pkg/api/handlers/compat/containers_stop.go b/pkg/api/handlers/compat/containers_stop.go
index 13fe25338..8bc58cf59 100644
--- a/pkg/api/handlers/compat/containers_stop.go
+++ b/pkg/api/handlers/compat/containers_stop.go
@@ -40,7 +40,7 @@ func StopContainer(w http.ResponseWriter, r *http.Request) {
}
// If the Container is stopped already, send a 304
if state == define.ContainerStateStopped || state == define.ContainerStateExited {
- utils.WriteResponse(w, http.StatusNotModified, "")
+ utils.WriteResponse(w, http.StatusNotModified, nil)
return
}
@@ -56,5 +56,5 @@ func StopContainer(w http.ResponseWriter, r *http.Request) {
}
// Success
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
diff --git a/pkg/api/handlers/compat/containers_unpause.go b/pkg/api/handlers/compat/containers_unpause.go
index f87b95b64..760e85814 100644
--- a/pkg/api/handlers/compat/containers_unpause.go
+++ b/pkg/api/handlers/compat/containers_unpause.go
@@ -24,5 +24,5 @@ func UnpauseContainer(w http.ResponseWriter, r *http.Request) {
}
// Success
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index d177b2335..a51dd8ed3 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -390,7 +390,7 @@ func LoadImages(w http.ResponseWriter, r *http.Request) {
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.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
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index a4bb72140..43478c1d3 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -104,9 +104,6 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
if len(query.Tag) > 0 {
output = query.Tag[0]
}
- if _, found := r.URL.Query()["target"]; found {
- output = query.Target
- }
var additionalNames []string
if len(query.Tag) > 1 {
@@ -162,7 +159,6 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
reporter := channel.NewWriter(make(chan []byte, 1))
defer reporter.Close()
-
buildOptions := imagebuildah.BuildOptions{
ContextDirectory: contextDirectory,
PullPolicy: pullPolicy,
@@ -267,7 +263,7 @@ loop:
failed = true
m.Error = string(e)
if err := enc.Encode(m); err != nil {
- logrus.Warnf("Failed to json encode error %q", err.Error())
+ logrus.Warnf("Failed to json encode error %v", err)
}
flush()
case <-runCtx.Done():
@@ -275,7 +271,7 @@ loop:
if !utils.IsLibpodRequest(r) {
m.Stream = fmt.Sprintf("Successfully built %12.12s\n", imageID)
if err := enc.Encode(m); err != nil {
- logrus.Warnf("Failed to json encode error %q", err.Error())
+ logrus.Warnf("Failed to json encode error %v", err)
}
flush()
}
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
index 12593a68c..0f3da53e8 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -81,5 +81,4 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, "")
-
}
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index c74cdb840..fe13971b0 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -50,7 +50,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.NetworkNotFound(w, name, err)
return
}
- report, err := getNetworkResourceByName(name, runtime)
+ report, err := getNetworkResourceByNameOrID(name, runtime, nil)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -58,7 +58,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
}
-func getNetworkResourceByName(name string, runtime *libpod.Runtime) (*types.NetworkResource, error) {
+func getNetworkResourceByNameOrID(nameOrID string, runtime *libpod.Runtime, filters map[string][]string) (*types.NetworkResource, error) {
var (
ipamConfigs []dockerNetwork.IPAMConfig
)
@@ -68,7 +68,7 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime) (*types.Netw
}
containerEndpoints := map[string]types.EndpointResource{}
// Get the network path so we can get created time
- networkConfigPath, err := network.GetCNIConfigPathByName(config, name)
+ networkConfigPath, err := network.GetCNIConfigPathByNameOrID(config, nameOrID)
if err != nil {
return nil, err
}
@@ -85,6 +85,16 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime) (*types.Netw
if err != nil {
return nil, err
}
+ if len(filters) > 0 {
+ ok, err := network.IfPassesFilter(conf, filters)
+ if err != nil {
+ return nil, err
+ }
+ if !ok {
+ // do not return the config if we did not match the filter
+ return nil, nil
+ }
+ }
// No Bridge plugin means we bail
bridge, err := genericPluginsToBridge(conf.Plugins, network.DefaultNetworkDriver)
@@ -106,7 +116,7 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime) (*types.Netw
if err != nil {
return nil, err
}
- if netData, ok := data.NetworkSettings.Networks[name]; ok {
+ if netData, ok := data.NetworkSettings.Networks[conf.Name]; ok {
containerEndpoint := types.EndpointResource{
Name: netData.NetworkID,
EndpointID: netData.EndpointID,
@@ -118,8 +128,8 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime) (*types.Netw
}
}
report := types.NetworkResource{
- Name: name,
- ID: name,
+ Name: conf.Name,
+ ID: network.GetNetworkID(conf.Name),
Created: time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec)), // nolint: unconvert
Scope: "",
Driver: network.DefaultNetworkDriver,
@@ -129,14 +139,14 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime) (*types.Netw
Options: nil,
Config: ipamConfigs,
},
- Internal: false,
+ Internal: !bridge.IsGW,
Attachable: false,
Ingress: false,
ConfigFrom: dockerNetwork.ConfigReference{},
ConfigOnly: false,
Containers: containerEndpoints,
Options: nil,
- Labels: nil,
+ Labels: network.GetNetworkLabels(conf),
Peers: nil,
Services: nil,
}
@@ -180,41 +190,23 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
return
}
- filterNames, nameFilterExists := query.Filters["name"]
- // TODO remove when filters are implemented
- if (!nameFilterExists && len(query.Filters) > 0) || len(query.Filters) > 1 {
- utils.InternalServerError(w, errors.New("only the name filter for listing networks is implemented"))
- return
- }
netNames, err := network.GetNetworkNamesFromFileSystem(config)
if err != nil {
utils.InternalServerError(w, err)
return
}
- // filter by name
- if nameFilterExists {
- names := []string{}
- for _, name := range netNames {
- for _, filter := range filterNames {
- if strings.Contains(name, filter) {
- names = append(names, name)
- break
- }
- }
- }
- netNames = names
- }
-
- reports := make([]*types.NetworkResource, 0, len(netNames))
+ var reports []*types.NetworkResource
logrus.Errorf("netNames: %q", strings.Join(netNames, ", "))
for _, name := range netNames {
- report, err := getNetworkResourceByName(name, runtime)
+ report, err := getNetworkResourceByNameOrID(name, runtime, query.Filters)
if err != nil {
utils.InternalServerError(w, err)
return
}
- reports = append(reports, report)
+ if report != nil {
+ reports = append(reports, report)
+ }
}
utils.WriteResponse(w, http.StatusOK, reports)
}
@@ -245,6 +237,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
ncOptions := entities.NetworkCreateOptions{
Driver: network.DefaultNetworkDriver,
Internal: networkCreate.Internal,
+ Labels: networkCreate.Labels,
}
if networkCreate.IPAM != nil && networkCreate.IPAM.Config != nil {
if len(networkCreate.IPAM.Config) > 1 {
@@ -278,11 +271,16 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
return
}
+ net, err := getNetworkResourceByNameOrID(name, runtime, nil)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
body := struct {
Id string
Warning []string
}{
- Id: name,
+ Id: net.ID,
}
utils.WriteResponse(w, http.StatusCreated, body)
}
@@ -327,7 +325,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
return
}
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
// Connect adds a container to a network
diff --git a/pkg/api/handlers/compat/ping.go b/pkg/api/handlers/compat/ping.go
index 9f6611b30..5513e902e 100644
--- a/pkg/api/handlers/compat/ping.go
+++ b/pkg/api/handlers/compat/ping.go
@@ -15,6 +15,7 @@ import (
func Ping(w http.ResponseWriter, r *http.Request) {
// Note API-Version and Libpod-API-Version are set in handler_api.go
w.Header().Set("BuildKit-Version", "")
+ w.Header().Set("Builder-Version", "")
w.Header().Set("Docker-Experimental", "true")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Pragma", "no-cache")
diff --git a/pkg/api/handlers/compat/system.go b/pkg/api/handlers/compat/system.go
index 322bfa7ed..e21ae160a 100644
--- a/pkg/api/handlers/compat/system.go
+++ b/pkg/api/handlers/compat/system.go
@@ -2,17 +2,91 @@ package compat
import (
"net/http"
+ "strings"
+ "github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/domain/infra/abi"
docker "github.com/docker/docker/api/types"
)
func GetDiskUsage(w http.ResponseWriter, r *http.Request) {
+ options := entities.SystemDfOptions{}
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ ic := abi.ContainerEngine{Libpod: runtime}
+ df, err := ic.SystemDf(r.Context(), options)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ }
+
+ imgs := make([]*docker.ImageSummary, len(df.Images))
+ for i, o := range df.Images {
+ t := docker.ImageSummary{
+ Containers: int64(o.Containers),
+ Created: o.Created.Unix(),
+ ID: o.ImageID,
+ Labels: map[string]string{},
+ ParentID: "",
+ RepoDigests: nil,
+ RepoTags: []string{o.Tag},
+ SharedSize: o.SharedSize,
+ Size: o.Size,
+ VirtualSize: o.Size - o.UniqueSize,
+ }
+ imgs[i] = &t
+ }
+
+ ctnrs := make([]*docker.Container, len(df.Containers))
+ for i, o := range df.Containers {
+ t := docker.Container{
+ ID: o.ContainerID,
+ Names: []string{o.Names},
+ Image: o.Image,
+ ImageID: o.Image,
+ Command: strings.Join(o.Command, " "),
+ Created: o.Created.Unix(),
+ Ports: nil,
+ SizeRw: o.RWSize,
+ SizeRootFs: o.Size,
+ Labels: map[string]string{},
+ State: o.Status,
+ Status: o.Status,
+ HostConfig: struct {
+ NetworkMode string `json:",omitempty"`
+ }{},
+ NetworkSettings: nil,
+ Mounts: nil,
+ }
+ ctnrs[i] = &t
+ }
+
+ vols := make([]*docker.Volume, len(df.Volumes))
+ for i, o := range df.Volumes {
+ t := docker.Volume{
+ CreatedAt: "",
+ Driver: "",
+ Labels: map[string]string{},
+ Mountpoint: "",
+ Name: o.VolumeName,
+ Options: nil,
+ Scope: "local",
+ Status: nil,
+ UsageData: &docker.VolumeUsageData{
+ RefCount: 1,
+ Size: o.Size,
+ },
+ }
+ vols[i] = &t
+ }
+
utils.WriteResponse(w, http.StatusOK, handlers.DiskUsage{DiskUsage: docker.DiskUsage{
- LayersSize: 0,
- Images: nil,
- Containers: nil,
- Volumes: nil,
+ LayersSize: 0,
+ Images: imgs,
+ Containers: ctnrs,
+ Volumes: vols,
+ BuildCache: []*docker.BuildCache{},
+ BuilderSize: 0,
}})
}
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index a3c9fbd2f..71b848932 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -223,7 +223,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
} else {
// Success
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
} else {
if !query.Force {
@@ -232,7 +232,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
// Volume does not exist and `force` is truthy - this emulates what
// Docker would do when told to `force` removal of a nonextant
// volume
- utils.WriteResponse(w, http.StatusNoContent, "")
+ utils.WriteResponse(w, http.StatusNoContent, nil)
}
}
}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index be5a394de..6145207ca 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -336,7 +336,7 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
}
tmpfile.Close()
- loadedImage, err := runtime.LoadImage(context.Background(), query.Reference, tmpfile.Name(), os.Stderr, "")
+ loadedImage, err := runtime.LoadImage(context.Background(), tmpfile.Name(), os.Stderr, "")
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image"))
return
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index f1578f829..8511e2733 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -48,7 +48,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
- Filter string `schema:"filter"`
+ Filters map[string][]string `schema:"filters"`
}{
// override any golang type defaults
}
@@ -59,7 +59,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
}
options := entities.NetworkListOptions{
- Filter: query.Filter,
+ Filters: query.Filters,
}
ic := abi.ContainerEngine{Libpod: runtime}
reports, err := ic.NetworkList(r.Context(), options)
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index 40cf16807..c9adde09d 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -145,13 +145,14 @@ type PodCreateConfig struct {
Share string `json:"share"`
}
+// HistoryResponse provides details on image layers
type HistoryResponse struct {
- ID string `json:"Id"`
- Created int64 `json:"Created"`
- CreatedBy string `json:"CreatedBy"`
- Tags []string `json:"Tags"`
- Size int64 `json:"Size"`
- Comment string `json:"Comment"`
+ ID string `json:"Id"`
+ Created int64
+ CreatedBy string
+ Tags []string
+ Size int64
+ Comment string
}
type ImageLayer struct{}
@@ -177,55 +178,34 @@ type ExecStartConfig struct {
}
func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) {
- containers, err := l.Containers()
- if err != nil {
- return nil, errors.Wrapf(err, "failed to obtain Containers for image %s", l.ID())
- }
- containerCount := len(containers)
-
- // FIXME: GetParent() panics
- // parent, err := l.GetParent(context.TODO())
- // if err != nil {
- // return nil, errors.Wrapf(err, "failed to obtain ParentID for image %s", l.ID())
- // }
-
- labels, err := l.Labels(context.TODO())
- if err != nil {
- return nil, errors.Wrapf(err, "failed to obtain Labels for image %s", l.ID())
- }
-
- size, err := l.Size(context.TODO())
+ imageData, err := l.Inspect(context.TODO())
if err != nil {
- return nil, errors.Wrapf(err, "failed to obtain Size for image %s", l.ID())
+ return nil, errors.Wrapf(err, "failed to obtain summary for image %s", l.ID())
}
- repoTags, err := l.RepoTags()
+ containers, err := l.Containers()
if err != nil {
- return nil, errors.Wrapf(err, "failed to obtain RepoTags for image %s", l.ID())
- }
-
- digests := make([]string, len(l.Digests()))
- for i, d := range l.Digests() {
- digests[i] = string(d)
+ return nil, errors.Wrapf(err, "failed to obtain Containers for image %s", l.ID())
}
+ containerCount := len(containers)
is := entities.ImageSummary{
ID: l.ID(),
- ParentId: l.Parent,
- RepoTags: repoTags,
+ ParentId: imageData.Parent,
+ RepoTags: imageData.RepoTags,
+ RepoDigests: imageData.RepoDigests,
Created: l.Created().Unix(),
- Size: int64(*size),
+ Size: imageData.Size,
SharedSize: 0,
- VirtualSize: l.VirtualSize,
- Labels: labels,
+ VirtualSize: imageData.VirtualSize,
+ Labels: imageData.Labels,
Containers: containerCount,
ReadOnly: l.IsReadOnly(),
Dangling: l.Dangling(),
Names: l.Names(),
- Digest: string(l.Digest()),
- Digests: digests,
+ Digest: string(imageData.Digest),
ConfigDigest: string(l.ConfigDigest),
- History: l.NamesHistory(),
+ History: imageData.NamesHistory,
}
return &is, nil
}
@@ -282,8 +262,8 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
}
}
dockerImageInspect := docker.ImageInspect{
- Architecture: l.Architecture,
- Author: l.Author,
+ Architecture: info.Architecture,
+ Author: info.Author,
Comment: info.Comment,
Config: &config,
Created: l.Created().Format(time.RFC3339Nano),
@@ -291,9 +271,9 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
GraphDriver: docker.GraphDriverData{},
ID: fmt.Sprintf("sha256:%s", l.ID()),
Metadata: docker.ImageMetadata{},
- Os: l.Os,
- OsVersion: l.Version,
- Parent: l.Parent,
+ Os: info.Os,
+ OsVersion: info.Version,
+ Parent: info.Parent,
RepoDigests: info.RepoDigests,
RepoTags: info.RepoTags,
RootFS: rootfs,
@@ -329,7 +309,6 @@ func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageI
dockerImageInspect.Parent = d.Parent.String()
}
return &ImageInspect{dockerImageInspect}, nil
-
}
// portsToPortSet converts libpods exposed ports to dockers structs