diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers_archive.go | 373 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_build.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/compat/networks.go | 55 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/networks.go | 4 | ||||
-rw-r--r-- | pkg/api/server/register_networks.go | 17 | ||||
-rw-r--r-- | pkg/bindings/network/network.go | 9 | ||||
-rw-r--r-- | pkg/bindings/test/containers_test.go | 8 | ||||
-rw-r--r-- | pkg/domain/entities/network.go | 10 | ||||
-rw-r--r-- | pkg/domain/infra/abi/images.go | 2 | ||||
-rw-r--r-- | pkg/domain/infra/abi/network.go | 45 | ||||
-rw-r--r-- | pkg/domain/infra/abi/system.go | 17 | ||||
-rw-r--r-- | pkg/specgen/generate/container_create.go | 2 | ||||
-rw-r--r-- | pkg/util/utils_supported.go | 13 | ||||
-rw-r--r-- | pkg/util/utils_windows.go | 6 |
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") |