summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/containers_archive.go373
-rw-r--r--pkg/api/handlers/compat/images.go2
-rw-r--r--pkg/api/handlers/compat/images_build.go4
-rw-r--r--pkg/api/handlers/compat/networks.go55
-rw-r--r--pkg/api/handlers/libpod/images.go2
-rw-r--r--pkg/api/handlers/libpod/networks.go4
-rw-r--r--pkg/api/server/register_networks.go17
-rw-r--r--pkg/bindings/network/network.go9
-rw-r--r--pkg/bindings/test/containers_test.go8
-rw-r--r--pkg/domain/entities/network.go10
-rw-r--r--pkg/domain/infra/abi/images.go2
-rw-r--r--pkg/domain/infra/abi/network.go45
-rw-r--r--pkg/domain/infra/abi/system.go17
-rw-r--r--pkg/specgen/generate/container_create.go2
-rw-r--r--pkg/util/utils_supported.go13
-rw-r--r--pkg/util/utils_windows.go6
16 files changed, 472 insertions, 97 deletions
diff --git a/pkg/api/handlers/compat/containers_archive.go b/pkg/api/handlers/compat/containers_archive.go
index 293a17e0f..1dd563393 100644
--- a/pkg/api/handlers/compat/containers_archive.go
+++ b/pkg/api/handlers/compat/containers_archive.go
@@ -1,12 +1,379 @@
package compat
import (
- "errors"
- "net/http"
+ "bytes"
+ "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/gorilla/schema"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func Archive(w http.ResponseWriter, r *http.Request) {
- utils.Error(w, "not implemented", http.StatusNotImplemented, errors.New("not implemented"))
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ switch r.Method {
+ case http.MethodPut:
+ handlePut(w, r, decoder, runtime)
+ case http.MethodGet, http.MethodHead:
+ handleHeadOrGet(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)))
+ }
+}
+
+func handleHeadOrGet(w http.ResponseWriter, r *http.Request, decoder *schema.Decoder, runtime *libpod.Runtime) {
+ query := struct {
+ Path string `schema:"path"`
+ }{}
+
+ 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
+ }
+
+ if query.Path == "" {
+ utils.Error(w, "Bad Request.", http.StatusBadRequest, errors.New("missing `path` parameter"))
+ return
+ }
+
+ containerName := utils.GetName(r)
+
+ ctr, err := runtime.LookupContainer(containerName)
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ utils.Error(w, "Not found.", http.StatusNotFound, errors.Wrap(err, "the container doesn't exists"))
+ return
+ } else if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ return
+ }
+
+ mountPoint, err := ctr.Mount()
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to mount the container"))
+ 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)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ return
+ }
+
+ stats, err := copier.Stat(mountPoint, "", opts, []string{filepath.Join(mountPoint, path)})
+ 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)
+ 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 {
+ 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)
+ 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))
+ return
+ }
+}
+
+func statsToHeader(stats *copier.StatForItem) (string, error) {
+ statsDTO := 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,
+ }
+
+ jsonBytes, err := json.Marshal(&statsDTO)
+ if err != nil {
+ return "", errors.Wrap(err, "failed to serialize file stats")
+ }
+
+ buff := bytes.NewBuffer(make([]byte, 0, 128))
+ base64encoder := base64.NewEncoder(base64.StdEncoding, buff)
+
+ _, err = base64encoder.Write(jsonBytes)
+ if err != nil {
+ return "", err
+ }
+
+ err = base64encoder.Close()
+ if err != nil {
+ return "", err
+ }
+
+ 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 pathWithVolumeMount(runtime *libpod.Runtime, volDestName, volName, path string) (string, string, error) {
+ destVolume, err := runtime.GetVolume(volName)
+ if err != nil {
+ return "", "", errors.Wrapf(err, "error getting volume destination %s", volName)
+ }
+
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(string(os.PathSeparator), path)
+ }
+
+ 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))
+ }
+
+ if path == "" {
+ return false, specs.Mount{}
+ }
+
+ 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
+ }
+ }
+
+ 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))]
+ }
+
+ return pathStr == target
+}
+
+func pathWithBindMountSource(m specs.Mount, path string) (string, string) {
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(string(os.PathSeparator), path)
+ }
+
+ return m.Source, strings.TrimPrefix(path, m.Destination)
}
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..149050209 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,
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index c74cdb840..b4f3aa2f1 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 {
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/server/register_networks.go b/pkg/api/server/register_networks.go
index ea169cbdf..e6c85d244 100644
--- a/pkg/api/server/register_networks.go
+++ b/pkg/api/server/register_networks.go
@@ -65,7 +65,12 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// - in: query
// name: filters
// type: string
- // description: JSON encoded value of the filters (a map[string][]string) to process on the networks list. Only the name filter is supported.
+ // description: |
+ // JSON encoded value of the filters (a map[string][]string) to process on the network list. Currently available filters:
+ // - name=[name] Matches network name (accepts regex).
+ // - id=[id] Matches for full or partial ID.
+ // - driver=[driver] Only bridge is supported.
+ // - label=[key] or label=[key=value] Matches networks based on the presence of a label alone or a label and a value.
// produces:
// - application/json
// responses:
@@ -216,9 +221,15 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// description: Display summary of network configurations
// parameters:
// - in: query
- // name: filter
+ // name: filters
// type: string
- // description: Provide filter values (e.g. 'name=podman')
+ // description: |
+ // JSON encoded value of the filters (a map[string][]string) to process on the network list. Available filters:
+ // - name=[name] Matches network name (accepts regex).
+ // - id=[id] Matches for full or partial ID.
+ // - driver=[driver] Only bridge is supported.
+ // - label=[key] or label=[key=value] Matches networks based on the presence of a label alone or a label and a value.
+ // - plugin=[plugin] Matches CNI plugins included in a network (e.g `bridge`,`portmap`,`firewall`,`tuning`,`dnsname`,`macvlan`)
// produces:
// - application/json
// responses:
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index 1d4be8a4c..347f97703 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -2,6 +2,7 @@ package network
import (
"context"
+ "encoding/json"
"net/http"
"net/url"
"strconv"
@@ -79,8 +80,12 @@ func List(ctx context.Context, options entities.NetworkListOptions) ([]*entities
return nil, err
}
params := url.Values{}
- if options.Filter != "" {
- params.Set("filter", options.Filter)
+ if options.Filters != nil {
+ b, err := json.Marshal(options.Filters)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("filters", string(b))
}
response, err := conn.DoRequest(nil, http.MethodGet, "/networks/json", params, nil)
if err != nil {
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 0fb677768..15066ff1a 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -290,17 +290,17 @@ var _ = Describe("Podman containers ", func() {
Expect(wait).To(BeNil())
Expect(exitCode).To(BeNumerically("==", -1))
- errChan = make(chan error)
+ unpauseErrChan := make(chan error)
go func() {
defer GinkgoRecover()
_, waitErr := containers.Wait(bt.conn, name, &running)
- errChan <- waitErr
- close(errChan)
+ unpauseErrChan <- waitErr
+ close(unpauseErrChan)
}()
err = containers.Unpause(bt.conn, name)
Expect(err).To(BeNil())
- unPausewait := <-errChan
+ unPausewait := <-unpauseErrChan
Expect(unPausewait).To(BeNil())
Expect(exitCode).To(BeNumerically("==", -1))
})
diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go
index 86c2e1bcd..65a110fd9 100644
--- a/pkg/domain/entities/network.go
+++ b/pkg/domain/entities/network.go
@@ -8,14 +8,15 @@ import (
// NetworkListOptions describes options for listing networks in cli
type NetworkListOptions struct {
- Format string
- Quiet bool
- Filter string
+ Format string
+ Quiet bool
+ Filters map[string][]string
}
// NetworkListReport describes the results from listing networks
type NetworkListReport struct {
*libcni.NetworkConfigList
+ Labels map[string]string
}
// NetworkInspectReport describes the results from inspect networks
@@ -39,10 +40,13 @@ type NetworkCreateOptions struct {
Driver string
Gateway net.IP
Internal bool
+ Labels map[string]string
MacVLAN string
Range net.IPNet
Subnet net.IPNet
IPv6 bool
+ // Mapping of driver options and values.
+ Options map[string]string
}
// NetworkCreateReport describes a created network for the cli
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index ef0e15264..1b523f06a 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -458,7 +458,7 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions)
if !opts.Quiet {
writer = os.Stderr
}
- name, err := ir.Libpod.LoadImage(ctx, opts.Name, opts.Input, writer, opts.SignaturePolicy)
+ name, err := ir.Libpod.LoadImage(ctx, opts.Input, writer, opts.SignaturePolicy)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index c52584565..6a219edd5 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -2,10 +2,7 @@ package abi
import (
"context"
- "fmt"
- "strings"
- "github.com/containernetworking/cni/libcni"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/libpod/network"
"github.com/containers/podman/v2/pkg/domain/entities"
@@ -26,18 +23,16 @@ func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.Net
return nil, err
}
- var tokens []string
- // tokenize the networkListOptions.Filter in key=value.
- if len(options.Filter) > 0 {
- tokens = strings.Split(options.Filter, "=")
- if len(tokens) != 2 {
- return nil, fmt.Errorf("invalid filter syntax : %s", options.Filter)
- }
- }
-
for _, n := range networks {
- if ifPassesFilterTest(n, tokens) {
- reports = append(reports, &entities.NetworkListReport{NetworkConfigList: n})
+ ok, err := network.IfPassesFilter(n, options.Filters)
+ if err != nil {
+ return nil, err
+ }
+ if ok {
+ reports = append(reports, &entities.NetworkListReport{
+ NetworkConfigList: n,
+ Labels: network.GetNetworkLabels(n),
+ })
}
}
return reports, nil
@@ -117,28 +112,6 @@ func (ic *ContainerEngine) NetworkCreate(ctx context.Context, name string, optio
return network.Create(name, options, runtimeConfig)
}
-func ifPassesFilterTest(netconf *libcni.NetworkConfigList, filter []string) bool {
- result := false
- if len(filter) == 0 {
- // No filter, so pass
- return true
- }
- switch strings.ToLower(filter[0]) {
- case "name":
- if filter[1] == netconf.Name {
- result = true
- }
- case "plugin":
- plugins := network.GetCNIPlugins(netconf)
- if strings.Contains(plugins, filter[1]) {
- result = true
- }
- default:
- result = false
- }
- return result
-}
-
// NetworkDisconnect removes a container from a given network
func (ic *ContainerEngine) NetworkDisconnect(ctx context.Context, networkname string, options entities.NetworkDisconnectOptions) error {
return ic.Libpod.DisconnectContainerFromNetwork(options.Container, networkname, options.Force)
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 72fd98ac1..ec2532bea 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -11,6 +11,7 @@ import (
"strings"
"github.com/containers/common/pkg/config"
+ "github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/cgroups"
"github.com/containers/podman/v2/pkg/domain/entities"
@@ -86,7 +87,11 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
return nil
}
- pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ tmpDir, err := ic.Libpod.TmpDir()
+ if err != nil {
+ return err
+ }
+ pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(tmpDir)
if err != nil {
return errors.Wrapf(err, "could not get pause process pid file path")
}
@@ -112,7 +117,7 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
}
became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths)
- if err := movePauseProcessToScope(); err != nil {
+ if err := movePauseProcessToScope(ic.Libpod); err != nil {
conf, err := ic.Config(context.Background())
if err != nil {
return err
@@ -133,8 +138,12 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
return nil
}
-func movePauseProcessToScope() error {
- pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+func movePauseProcessToScope(r *libpod.Runtime) error {
+ tmpDir, err := r.TmpDir()
+ if err != nil {
+ return err
+ }
+ pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(tmpDir)
if err != nil {
return errors.Wrapf(err, "could not get pause process pid file path")
}
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 45a374216..95e4eeb8f 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -388,7 +388,7 @@ func CreateExitCommandArgs(storageConfig storage.StoreOptions, config *config.Co
}
if syslog {
- command = append(command, "--syslog", "true")
+ command = append(command, "--syslog")
}
command = append(command, []string{"container", "cleanup"}...)
diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go
index 2d636a7cb..a63c76415 100644
--- a/pkg/util/utils_supported.go
+++ b/pkg/util/utils_supported.go
@@ -99,7 +99,8 @@ func GetRootlessConfigHomeDir() (string, error) {
}
// GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for
-// the pause process
+// the pause process.
+// DEPRECATED - switch to GetRootlessPauseProcessPidPathGivenDir
func GetRootlessPauseProcessPidPath() (string, error) {
runtimeDir, err := GetRuntimeDir()
if err != nil {
@@ -107,3 +108,13 @@ func GetRootlessPauseProcessPidPath() (string, error) {
}
return filepath.Join(runtimeDir, "libpod", "pause.pid"), nil
}
+
+// GetRootlessPauseProcessPidPathGivenDir returns the path to the file that
+// holds the PID of the pause process, given the location of Libpod's temporary
+// files.
+func GetRootlessPauseProcessPidPathGivenDir(libpodTmpDir string) (string, error) {
+ if libpodTmpDir == "" {
+ return "", errors.Errorf("must provide non-empty tmporary directory")
+ }
+ return filepath.Join(libpodTmpDir, "pause.pid"), nil
+}
diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go
index 9bba2d1ee..46ca5e7f1 100644
--- a/pkg/util/utils_windows.go
+++ b/pkg/util/utils_windows.go
@@ -25,6 +25,12 @@ func GetRootlessPauseProcessPidPath() (string, error) {
return "", errors.Wrap(errNotImplemented, "GetRootlessPauseProcessPidPath")
}
+// GetRootlessPauseProcessPidPath returns the path to the file that holds the pid for
+// the pause process
+func GetRootlessPauseProcessPidPathGivenDir(unused string) (string, error) {
+ return "", errors.Wrap(errNotImplemented, "GetRootlessPauseProcessPidPath")
+}
+
// GetRuntimeDir returns the runtime directory
func GetRuntimeDir() (string, error) {
return "", errors.New("this function is not implemented for windows")