summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/completion.go8
-rw-r--r--cmd/podman/common/create_opts.go4
-rw-r--r--cmd/podman/common/specgen.go14
-rw-r--r--cmd/podman/images/list.go4
-rw-r--r--cmd/podman/networks/list.go11
-rw-r--r--docs/source/markdown/podman-load.1.md2
-rw-r--r--docs/source/markdown/podman-network-ls.1.md31
-rw-r--r--docs/source/markdown/podman-run.1.md25
-rw-r--r--libpod/network/files.go18
-rw-r--r--libpod/network/netconflist.go10
-rw-r--r--libpod/network/network.go11
-rw-r--r--libpod/reset.go2
-rw-r--r--libpod/runtime.go11
-rw-r--r--libpod/runtime_img.go52
-rw-r--r--libpod/runtime_migrate.go6
-rw-r--r--libpod/runtime_migrate_unsupported.go2
-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.go14
-rw-r--r--pkg/api/handlers/libpod/images.go2
-rw-r--r--pkg/api/server/register_networks.go2
-rw-r--r--pkg/bindings/connection.go2
-rw-r--r--pkg/domain/infra/abi/images.go2
-rw-r--r--pkg/domain/infra/abi/system.go17
-rw-r--r--pkg/specgen/generate/config_linux.go53
-rw-r--r--pkg/specgen/generate/oci.go2
-rw-r--r--pkg/specgen/specgen.go7
-rw-r--r--pkg/util/utils_supported.go13
-rw-r--r--pkg/util/utils_windows.go6
-rw-r--r--test/apiv2/35-networks.at16
-rw-r--r--test/e2e/images_test.go2
-rw-r--r--test/e2e/network_test.go34
-rw-r--r--test/e2e/run_test.go33
-rw-r--r--test/system/010-images.bats13
-rw-r--r--test/system/120-load.bats30
-rw-r--r--test/system/400-unprivileged-access.bats2
36 files changed, 346 insertions, 121 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 9856e46ef..7fed15e5e 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -861,10 +861,10 @@ func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string)
"status=": func(_ string) ([]string, cobra.ShellCompDirective) {
return containerStatuses, cobra.ShellCompDirectiveNoFileComp
},
- "ancestor": func(s string) ([]string, cobra.ShellCompDirective) { return getImages(cmd, s) },
- "before=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
- "since=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
- "volume=": func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(cmd, s) },
+ "ancestor=": func(s string) ([]string, cobra.ShellCompDirective) { return getImages(cmd, s) },
+ "before=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
+ "since=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
+ "volume=": func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(cmd, s) },
"health=": func(_ string) ([]string, cobra.ShellCompDirective) {
return []string{define.HealthCheckHealthy,
define.HealthCheckUnhealthy}, cobra.ShellCompDirectiveNoFileComp
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go
index af53a3b67..4b0e40df2 100644
--- a/cmd/podman/common/create_opts.go
+++ b/cmd/podman/common/create_opts.go
@@ -204,10 +204,10 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroup
for _, m := range cc.HostConfig.Mounts {
mount := fmt.Sprintf("type=%s", m.Type)
if len(m.Source) > 0 {
- mount += fmt.Sprintf("source=%s", m.Source)
+ mount += fmt.Sprintf(",source=%s", m.Source)
}
if len(m.Target) > 0 {
- mount += fmt.Sprintf("dest=%s", m.Target)
+ mount += fmt.Sprintf(",dst=%s", m.Target)
}
mounts = append(mounts, mount)
}
diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go
index 0bb6e79e5..e0da142ad 100644
--- a/cmd/podman/common/specgen.go
+++ b/cmd/podman/common/specgen.go
@@ -517,18 +517,22 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string
}
switch con[0] {
- case "proc-opts":
- s.ProcOpts = strings.Split(con[1], ",")
+ case "apparmor":
+ s.ContainerSecurityConfig.ApparmorProfile = con[1]
+ s.Annotations[define.InspectAnnotationApparmor] = con[1]
case "label":
// TODO selinux opts and label opts are the same thing
s.ContainerSecurityConfig.SelinuxOpts = append(s.ContainerSecurityConfig.SelinuxOpts, con[1])
s.Annotations[define.InspectAnnotationLabel] = strings.Join(s.ContainerSecurityConfig.SelinuxOpts, ",label=")
- case "apparmor":
- s.ContainerSecurityConfig.ApparmorProfile = con[1]
- s.Annotations[define.InspectAnnotationApparmor] = con[1]
+ case "mask":
+ s.ContainerSecurityConfig.Mask = append(s.ContainerSecurityConfig.Mask, strings.Split(con[1], ":")...)
+ case "proc-opts":
+ s.ProcOpts = strings.Split(con[1], ",")
case "seccomp":
s.SeccompProfilePath = con[1]
s.Annotations[define.InspectAnnotationSeccomp] = con[1]
+ case "unmask":
+ s.ContainerSecurityConfig.Unmask = append(s.ContainerSecurityConfig.Unmask, strings.Split(con[1], ":")...)
default:
return fmt.Errorf("invalid --security-opt 2: %q", opt)
}
diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go
index bcb31e6ee..8a7951923 100644
--- a/cmd/podman/images/list.go
+++ b/cmd/podman/images/list.go
@@ -126,8 +126,8 @@ func images(cmd *cobra.Command, args []string) error {
case listFlag.quiet:
return writeID(imgs)
default:
- if cmd.Flag("format").Changed {
- listFlag.noHeading = true // V1 compatibility
+ if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
+ listFlag.noHeading = true
}
return writeTemplate(imgs)
}
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 6e6bbb07d..16ae980dc 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -37,6 +37,7 @@ var (
var (
networkListOptions entities.NetworkListOptions
filters []string
+ noTrunc bool
)
func networkListFlags(flags *pflag.FlagSet) {
@@ -45,6 +46,7 @@ func networkListFlags(flags *pflag.FlagSet) {
_ = networklistCommand.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteJSONFormat)
flags.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names")
+ flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate the network ID")
filterFlagName := "filter"
flags.StringArrayVarP(&filters, filterFlagName, "f", nil, "Provide filter values (e.g. 'name=podman')")
@@ -96,6 +98,7 @@ func networkList(cmd *cobra.Command, args []string) error {
"Version": "version",
"Plugins": "plugins",
"Labels": "labels",
+ "ID": "network id",
})
renderHeaders := true
row := "{{.Name}}\t{{.Version}}\t{{.Plugins}}\n"
@@ -155,3 +158,11 @@ func (n ListPrintReports) Labels() string {
}
return strings.Join(list, ",")
}
+
+func (n ListPrintReports) ID() string {
+ length := 12
+ if noTrunc {
+ length = 64
+ }
+ return network.GetNetworkID(n.Name)[:length]
+}
diff --git a/docs/source/markdown/podman-load.1.md b/docs/source/markdown/podman-load.1.md
index 177709a43..dc2a632e5 100644
--- a/docs/source/markdown/podman-load.1.md
+++ b/docs/source/markdown/podman-load.1.md
@@ -10,7 +10,7 @@ podman\-load - Load image(s) from a tar archive into container storage
## DESCRIPTION
**podman load** loads an image from either an **oci-archive** or a **docker-archive** stored on the local machine into container storage. **podman load** reads from stdin by default or a file if the **input** option is set.
-You can also specify a name for the image if the archive does not contain a named reference, of if you want an additional name for the local image.
+You can also specify a name for the image if the archive is of single image and load will tag an additional image with the name:tag.
**podman load** is used for loading from the archive generated by **podman save**, that includes the image parent layers. To load the archive of container's filesystem created by **podman export**, use **podman import**.
The local client further supports loading an **oci-dir** or a **docker-dir** as created with **podman save** (1).
diff --git a/docs/source/markdown/podman-network-ls.1.md b/docs/source/markdown/podman-network-ls.1.md
index fcba51190..a964c97e8 100644
--- a/docs/source/markdown/podman-network-ls.1.md
+++ b/docs/source/markdown/podman-network-ls.1.md
@@ -10,14 +10,6 @@ podman\-network\-ls - Display a summary of CNI networks
Displays a list of existing podman networks. This command is not available for rootless users.
## OPTIONS
-#### **--quiet**, **-q**
-
-The `quiet` option will restrict the output to only the network names.
-
-#### **--format**
-
-Pretty-print networks to JSON or using a Go template.
-
#### **--filter**, **-f**
Filter output based on conditions given.
@@ -30,10 +22,33 @@ Valid filters are listed below:
| **Filter** | **Description** |
| ---------- | ------------------------------------------------------------------------------------- |
| name | [Name] Network name (accepts regex) |
+| id | [ID] Full or partial network ID |
| label | [Key] or [Key=Value] Label assigned to a network |
| plugin | [Plugin] CNI plugins included in a network (e.g `bridge`,`portmap`,`firewall`,`tuning`,`dnsname`,`macvlan`) |
| driver | [Driver] Only `bridge` is supported |
+#### **--format**
+
+Change the default output format. This can be of a supported type like 'json'
+or a Go template.
+Valid placeholders for the Go template are listed below:
+
+| **Placeholder** | **Description** |
+| --------------- | --------------------------------|
+| .ID | Network ID |
+| .Name | Network name |
+| .Plugins | Network Plugins |
+| .Labels | Network labels |
+| .Version | CNI Version of the config file |
+
+#### **--no-trunc**
+
+Do not truncate the network ID. The network ID is not displayed by default and must be specified with **--format**.
+
+#### **--quiet**, **-q**
+
+The `quiet` option will restrict the output to only the network names.
+
## EXAMPLE
Display networks
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 83aaa33e8..1038906c0 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -885,11 +885,16 @@ Security Options
- **label=level:**_LEVEL_: Set the label level for the container processes
- **label=filetype:**TYPE_: Set the label file type for the container files
- **label=disable**: Turn off label separation for the container
+- **mask**=_/path/1:/path/2_: The paths to mask separated by a colon. A masked path
+ cannot be accessed inside the container.
- **no-new-privileges**: Disable container processes from gaining additional privileges
- **seccomp=unconfined**: Turn off seccomp confinement for the container
- **seccomp**=_profile.json_: Allowed syscall list seccomp JSON file to be used as a seccomp filter
- **proc-opts**=_OPTIONS_ : Comma separated list of options to use for the /proc mount. More details
for the possible mount options are specified at **proc(5)** man page.
+- **unmask**=_ALL_ or _/path/1:/path/2_: Paths to unmask separated by a colon. If set to **ALL**, it will
+ unmask all the paths that are masked by default.
+ The default masked paths are **/proc/acpi, /proc/kcore, /proc/keys, /proc/latency_stats, /proc/sched_debug, /proc/scsi, /proc/timer_list, /proc/timer_stats, /sys/firmware, and /sys/fs/selinux.**
Note: Labeling can be disabled for all containers by setting **label=false** in the **containers.conf**(5) file.
@@ -1479,6 +1484,26 @@ $ podman run --security-opt label=type:svirt_apache_t -i -t centos bash
Note you would have to write policy defining a **svirt_apache_t** type.
+To mask additional specific paths in the container, specify the paths
+separated by a colon using the **mask** option with the **--security-opt**
+flag.
+
+```
+$ podman run --security-opt mask=/foo/bar:/second/path fedora bash
+```
+
+To unmask all the paths that are masked by default, set the **unmask** option to
+**ALL**. Or to only unmask specific paths, specify the paths as shown above with
+the **mask** option.
+
+```
+$ podman run --security-opt unmask=ALL fedora bash
+```
+
+```
+$ podman run --security-opt unmask=/foo/bar:/sys/firmware fedora bash
+```
+
### Setting device weight
If you want to set _/dev/sda_ device weight to **200**, you can specify the device
diff --git a/libpod/network/files.go b/libpod/network/files.go
index 83cb1c23a..33cf01064 100644
--- a/libpod/network/files.go
+++ b/libpod/network/files.go
@@ -50,13 +50,15 @@ func LoadCNIConfsFromDir(dir string) ([]*libcni.NetworkConfigList, error) {
return configs, nil
}
-// GetCNIConfigPathByName finds a CNI network by name and
+// GetCNIConfigPathByNameOrID finds a CNI network by name and
// returns its configuration file path
-func GetCNIConfigPathByName(config *config.Config, name string) (string, error) {
+func GetCNIConfigPathByNameOrID(config *config.Config, name string) (string, error) {
files, err := libcni.ConfFiles(GetCNIConfDir(config), []string{".conflist"})
if err != nil {
return "", err
}
+ idMatch := 0
+ file := ""
for _, confFile := range files {
conf, err := libcni.ConfListFromFile(confFile)
if err != nil {
@@ -65,6 +67,16 @@ func GetCNIConfigPathByName(config *config.Config, name string) (string, error)
if conf.Name == name {
return confFile, nil
}
+ if strings.HasPrefix(GetNetworkID(conf.Name), name) {
+ idMatch++
+ file = confFile
+ }
+ }
+ if idMatch == 1 {
+ return file, nil
+ }
+ if idMatch > 1 {
+ return "", errors.Errorf("more than one result for network ID %s", name)
}
return "", errors.Wrap(define.ErrNoSuchNetwork, fmt.Sprintf("unable to find network configuration for %s", name))
}
@@ -72,7 +84,7 @@ func GetCNIConfigPathByName(config *config.Config, name string) (string, error)
// ReadRawCNIConfByName reads the raw CNI configuration for a CNI
// network by name
func ReadRawCNIConfByName(config *config.Config, name string) ([]byte, error) {
- confFile, err := GetCNIConfigPathByName(config, name)
+ confFile, err := GetCNIConfigPathByNameOrID(config, name)
if err != nil {
return nil, err
}
diff --git a/libpod/network/netconflist.go b/libpod/network/netconflist.go
index a5fec5e80..d61b96ecb 100644
--- a/libpod/network/netconflist.go
+++ b/libpod/network/netconflist.go
@@ -230,8 +230,16 @@ func IfPassesFilter(netconf *libcni.NetworkConfigList, filters map[string][]stri
}
}
+ case "id":
+ // matches part of one id
+ for _, filterValue := range filterValues {
+ if strings.Contains(GetNetworkID(netconf.Name), filterValue) {
+ result = true
+ break
+ }
+ }
+
// TODO: add dangling filter
- // TODO TODO: add id filter if we support ids
default:
return false, errors.Errorf("invalid filter %q", key)
diff --git a/libpod/network/network.go b/libpod/network/network.go
index 0febb52f6..89f0b67ac 100644
--- a/libpod/network/network.go
+++ b/libpod/network/network.go
@@ -1,6 +1,8 @@
package network
import (
+ "crypto/sha256"
+ "encoding/hex"
"encoding/json"
"net"
"os"
@@ -175,7 +177,7 @@ func RemoveNetwork(config *config.Config, name string) error {
return err
}
defer l.releaseCNILock()
- cniPath, err := GetCNIConfigPathByName(config, name)
+ cniPath, err := GetCNIConfigPathByNameOrID(config, name)
if err != nil {
return err
}
@@ -229,3 +231,10 @@ func Exists(config *config.Config, name string) (bool, error) {
}
return true, nil
}
+
+// GetNetworkID return the network ID for a given name.
+// It is just the sha256 hash but this should be good enough.
+func GetNetworkID(name string) string {
+ hash := sha256.Sum256([]byte(name))
+ return hex.EncodeToString(hash[:])
+}
diff --git a/libpod/reset.go b/libpod/reset.go
index f8828fed4..6d2842723 100644
--- a/libpod/reset.go
+++ b/libpod/reset.go
@@ -46,7 +46,7 @@ func (r *Runtime) Reset(ctx context.Context) error {
}
}
- if err := stopPauseProcess(); err != nil {
+ if err := r.stopPauseProcess(); err != nil {
logrus.Errorf("Error stopping pause process: %v", err)
}
diff --git a/libpod/runtime.go b/libpod/runtime.go
index df3dfae2b..cdf66a4d0 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -472,7 +472,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
// we will need to access the storage.
if os.Geteuid() != 0 {
aliveLock.Unlock() // Unlock to avoid deadlock as BecomeRootInUserNS will reexec.
- pausePid, err := util.GetRootlessPauseProcessPidPath()
+ pausePid, err := util.GetRootlessPauseProcessPidPathGivenDir(runtime.config.Engine.TmpDir)
if err != nil {
return errors.Wrapf(err, "could not get pause process pid file path")
}
@@ -538,6 +538,15 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) {
return nil
}
+// TmpDir gets the current Libpod temporary files directory.
+func (r *Runtime) TmpDir() (string, error) {
+ if !r.valid {
+ return "", define.ErrRuntimeStopped
+ }
+
+ return r.config.Engine.TmpDir, nil
+}
+
// GetConfig returns a copy of the configuration used by the runtime
func (r *Runtime) GetConfig() (*config.Config, error) {
r.lock.RLock()
diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go
index e57890fa2..a2d9a875e 100644
--- a/libpod/runtime_img.go
+++ b/libpod/runtime_img.go
@@ -8,7 +8,6 @@ import (
"net/http"
"net/url"
"os"
- "strings"
"github.com/containers/buildah/imagebuildah"
"github.com/containers/image/v5/directory"
@@ -276,56 +275,47 @@ func DownloadFromFile(reader *os.File) (string, error) {
}
// LoadImage loads a container image into local storage
-func (r *Runtime) LoadImage(ctx context.Context, name, inputFile string, writer io.Writer, signaturePolicy string) (string, error) {
- var (
- newImages []*image.Image
- err error
- src types.ImageReference
- )
+func (r *Runtime) LoadImage(ctx context.Context, inputFile string, writer io.Writer, signaturePolicy string) (string, error) {
+ if newImages, err := r.LoadAllImageFromArchive(ctx, writer, inputFile, signaturePolicy); err == nil {
+ return newImages, nil
+ }
+ return r.LoadImageFromSingleImageArchive(ctx, writer, inputFile, signaturePolicy)
+}
- if name == "" {
- newImages, err = r.ImageRuntime().LoadAllImagesFromDockerArchive(ctx, inputFile, signaturePolicy, writer)
- if err == nil {
- return getImageNames(newImages), nil
- }
+// LoadAllImageFromArchive loads all images from the archive of multi-image that inputFile points to.
+func (r *Runtime) LoadAllImageFromArchive(ctx context.Context, writer io.Writer, inputFile, signaturePolicy string) (string, error) {
+ newImages, err := r.ImageRuntime().LoadAllImagesFromDockerArchive(ctx, inputFile, signaturePolicy, writer)
+ if err == nil {
+ return getImageNames(newImages), nil
}
+ return "", err
+}
+// LoadImageFromSingleImageArchive load image from the archive of single image that inputFile points to.
+func (r *Runtime) LoadImageFromSingleImageArchive(ctx context.Context, writer io.Writer, inputFile, signaturePolicy string) (string, error) {
+ var err error
for _, referenceFn := range []func() (types.ImageReference, error){
func() (types.ImageReference, error) {
return dockerarchive.ParseReference(inputFile)
},
func() (types.ImageReference, error) {
- return ociarchive.NewReference(inputFile, name) // name may be ""
- },
- func() (types.ImageReference, error) {
- // prepend "localhost/" to support local image saved with this semantics
- if !strings.Contains(name, "/") {
- return ociarchive.NewReference(inputFile, fmt.Sprintf("%s/%s", image.DefaultLocalRegistry, name))
- }
- return nil, nil
+ return ociarchive.NewReference(inputFile, "")
},
func() (types.ImageReference, error) {
return directory.NewReference(inputFile)
},
func() (types.ImageReference, error) {
- return layout.NewReference(inputFile, name)
- },
- func() (types.ImageReference, error) {
- // prepend "localhost/" to support local image saved with this semantics
- if !strings.Contains(name, "/") {
- return layout.NewReference(inputFile, fmt.Sprintf("%s/%s", image.DefaultLocalRegistry, name))
- }
- return nil, nil
+ return layout.NewReference(inputFile, "")
},
} {
- src, err = referenceFn()
+ src, err := referenceFn()
if err == nil && src != nil {
- if newImages, err = r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer); err == nil {
+ if newImages, err := r.ImageRuntime().LoadFromArchiveReference(ctx, src, signaturePolicy, writer); err == nil {
return getImageNames(newImages), nil
}
}
}
- return "", errors.Wrapf(err, "error pulling %q", name)
+ return "", errors.Wrapf(err, "error pulling image")
}
func getImageNames(images []*image.Image) string {
diff --git a/libpod/runtime_migrate.go b/libpod/runtime_migrate.go
index 1ad32fe9c..f0f800ef0 100644
--- a/libpod/runtime_migrate.go
+++ b/libpod/runtime_migrate.go
@@ -18,9 +18,9 @@ import (
"github.com/sirupsen/logrus"
)
-func stopPauseProcess() error {
+func (r *Runtime) stopPauseProcess() error {
if rootless.IsRootless() {
- pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ pausePidPath, err := util.GetRootlessPauseProcessPidPathGivenDir(r.config.Engine.TmpDir)
if err != nil {
return errors.Wrapf(err, "could not get pause process pid file path")
}
@@ -98,5 +98,5 @@ func (r *Runtime) migrate(ctx context.Context) error {
}
}
- return stopPauseProcess()
+ return r.stopPauseProcess()
}
diff --git a/libpod/runtime_migrate_unsupported.go b/libpod/runtime_migrate_unsupported.go
index e362cca63..a9d351318 100644
--- a/libpod/runtime_migrate_unsupported.go
+++ b/libpod/runtime_migrate_unsupported.go
@@ -10,6 +10,6 @@ func (r *Runtime) migrate(ctx context.Context) error {
return nil
}
-func stopPauseProcess() error {
+func (r *Runtime) stopPauseProcess() error {
return 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..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 762f88a68..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, nil)
+ 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, filters map[string][]string) (*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, filters map[
}
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
}
@@ -116,7 +116,7 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime, filters map[
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,
@@ -128,8 +128,8 @@ func getNetworkResourceByName(name string, runtime *libpod.Runtime, filters map[
}
}
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,
@@ -199,7 +199,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
var reports []*types.NetworkResource
logrus.Errorf("netNames: %q", strings.Join(netNames, ", "))
for _, name := range netNames {
- report, err := getNetworkResourceByName(name, runtime, query.Filters)
+ report, err := getNetworkResourceByNameOrID(name, runtime, query.Filters)
if err != nil {
utils.InternalServerError(w, err)
return
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/server/register_networks.go b/pkg/api/server/register_networks.go
index 193b05e6d..e6c85d244 100644
--- a/pkg/api/server/register_networks.go
+++ b/pkg/api/server/register_networks.go
@@ -68,6 +68,7 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// 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:
@@ -225,6 +226,7 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// 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`)
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 31435ae91..a5683796a 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -152,7 +152,7 @@ func pingNewConnection(ctx context.Context) error {
return err
}
// the ping endpoint sits at / in this case
- response, err := client.DoRequest(nil, http.MethodGet, "../../../_ping", nil, nil)
+ response, err := client.DoRequest(nil, http.MethodGet, "/_ping", nil, nil)
if err != nil {
return err
}
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/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/config_linux.go b/pkg/specgen/generate/config_linux.go
index 2d40dba8f..1808f99b8 100644
--- a/pkg/specgen/generate/config_linux.go
+++ b/pkg/specgen/generate/config_linux.go
@@ -4,13 +4,16 @@ import (
"fmt"
"io/ioutil"
"os"
+ "path"
"path/filepath"
"strings"
"github.com/containers/podman/v2/pkg/rootless"
+ "github.com/containers/podman/v2/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
)
@@ -137,22 +140,33 @@ func DevicesFromPath(g *generate.Generator, devicePath string) error {
return addDevice(g, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":"))
}
-func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, g *generate.Generator) {
+func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, mask, unmask []string, g *generate.Generator) {
+ defaultMaskPaths := []string{"/proc/acpi",
+ "/proc/kcore",
+ "/proc/keys",
+ "/proc/latency_stats",
+ "/proc/timer_list",
+ "/proc/timer_stats",
+ "/proc/sched_debug",
+ "/proc/scsi",
+ "/sys/firmware",
+ "/sys/fs/selinux",
+ "/sys/dev/block",
+ }
+
+ unmaskAll := false
+ if unmask != nil && unmask[0] == "ALL" {
+ unmaskAll = true
+ }
+
if !privileged {
- for _, mp := range []string{
- "/proc/acpi",
- "/proc/kcore",
- "/proc/keys",
- "/proc/latency_stats",
- "/proc/timer_list",
- "/proc/timer_stats",
- "/proc/sched_debug",
- "/proc/scsi",
- "/sys/firmware",
- "/sys/fs/selinux",
- "/sys/dev",
- } {
- g.AddLinuxMaskedPaths(mp)
+ if !unmaskAll {
+ for _, mp := range defaultMaskPaths {
+ // check that the path to mask is not in the list of paths to unmask
+ if !util.StringInSlice(mp, unmask) {
+ g.AddLinuxMaskedPaths(mp)
+ }
+ }
}
if pidModeIsHost && rootless.IsRootless() {
@@ -170,6 +184,15 @@ func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, g *generate.
g.AddLinuxReadonlyPaths(rp)
}
}
+
+ // mask the paths provided by the user
+ for _, mp := range mask {
+ if !path.IsAbs(mp) && mp != "" {
+ logrus.Errorf("Path %q is not an absolute path, skipping...", mp)
+ continue
+ }
+ g.AddLinuxMaskedPaths(mp)
+ }
}
// based on getDevices from runc (libcontainer/devices/devices.go)
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index 8454458a8..0368ab205 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -298,7 +298,7 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
}
}
- BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), &g)
+ BlockAccessToKernelFilesystems(s.Privileged, s.PidNS.IsHost(), s.Mask, s.Unmask, &g)
for name, val := range s.Env {
g.AddProcessEnv(name, val)
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index fad2406e5..964b89fa4 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -307,6 +307,13 @@ type ContainerSecurityConfig struct {
Umask string `json:"umask,omitempty"`
// ProcOpts are the options used for the proc mount.
ProcOpts []string `json:"procfs_opts,omitempty"`
+ // Mask is the path we want to mask in the container. This masks the paths
+ // given in addition to the default list.
+ // Optional
+ Mask []string `json:"mask,omitempty"`
+ // Unmask is the path we want to unmask in the container. To override
+ // all the default paths that are masked, set unmask=ALL.
+ Unmask []string `json:"unmask,omitempty"`
}
// ContainerCgroupConfig contains configuration information about a container's
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")
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index d9556d59f..0ce56ee3c 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -38,9 +38,19 @@ length=2
# filters={"label":["abc"]}
t GET networks?filters=%7B%22label%22%3A%5B%22abc%22%5D%7D 200 \
length=1
-# invalid filter filters={"id":["abc"]}
-t GET networks?filters=%7B%22id%22%3A%5B%22abc%22%5D%7D 500 \
-.cause='invalid filter "id"'
+# id filter filters={"id":["a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1"]}
+t GET networks?filters=%7B%22id%22%3A%5B%22a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1%22%5D%7D 200 \
+length=1 \
+.[0].Name=network1 \
+.[0].Id=a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1
+# invalid filter filters={"dangling":["1"]}
+t GET networks?filters=%7B%22dangling%22%3A%5B%221%22%5D%7D 500 \
+.cause='invalid filter "dangling"'
+
+# network inspect docker
+t GET networks/a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1 200 \
+.Name=network1 \
+.Id=a7662f44d65029fd4635c91feea3d720a57cef52e2a9fcc7772b69072cc1ccd1
# clean the network
t DELETE libpod/networks/network1 200 \
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index b69d2597e..281b2c313 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -278,7 +278,7 @@ WORKDIR /test
It("podman images sort by values", func() {
sortValueTest := func(value string, result int, format string) []string {
f := fmt.Sprintf("{{.%s}}", format)
- session := podmanTest.Podman([]string{"images", "--sort", value, "--format", f})
+ session := podmanTest.Podman([]string{"images", "--noheading", "--sort", value, "--format", f})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(result))
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index ad6af61c7..ffc914bc2 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -135,6 +135,40 @@ var _ = Describe("Podman network", func() {
Expect(session.LineInOutputContains(name)).To(BeFalse())
})
+ It("podman network ID test", func() {
+ net := "networkIDTest"
+ // the network id should be the sha256 hash of the network name
+ netID := "6073aefe03cdf8f29be5b23ea9795c431868a3a22066a6290b187691614fee84"
+ session := podmanTest.Podman([]string{"network", "create", net})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeCNINetwork(net)
+ Expect(session.ExitCode()).To(BeZero())
+
+ session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}} {{.ID}}", "--filter", "id=" + netID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(net + " " + netID[:12]))
+
+ session = podmanTest.Podman([]string{"network", "ls", "--format", "{{.Name}} {{.ID}}", "--filter", "id=" + netID[10:50], "--no-trunc"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(net + " " + netID))
+
+ session = podmanTest.Podman([]string{"network", "inspect", netID[:40]})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ Expect(session.OutputToString()).To(ContainSubstring(net))
+
+ session = podmanTest.Podman([]string{"network", "inspect", netID[1:]})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).ToNot(BeZero())
+ Expect(session.ErrorToString()).To(ContainSubstring("no such network"))
+
+ session = podmanTest.Podman([]string{"network", "rm", netID})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(BeZero())
+ })
+
rm_func := func(rm string) {
It(fmt.Sprintf("podman network %s no args", rm), func() {
session := podmanTest.Podman([]string{"network", rm})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 0d65a3e59..efc125d2b 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -233,6 +233,39 @@ var _ = Describe("Podman run", func() {
return jsonFile
}
+ It("podman run mask and unmask path test", func() {
+ session := podmanTest.Podman([]string{"run", "-d", "--name=maskCtr1", "--security-opt", "unmask=ALL", "--security-opt", "mask=/proc/acpi", ALPINE, "sleep", "200"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"exec", "maskCtr1", "ls", "/sys/firmware"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(Not(BeEmpty()))
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"exec", "maskCtr1", "ls", "/proc/acpi"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(BeEmpty())
+
+ session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr2", "--security-opt", "unmask=/proc/acpi:/sys/firmware", ALPINE, "sleep", "200"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"exec", "maskCtr2", "ls", "/sys/firmware"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(Not(BeEmpty()))
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"exec", "maskCtr2", "ls", "/proc/acpi"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(Not(BeEmpty()))
+ Expect(session.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"run", "-d", "--name=maskCtr3", "--security-opt", "mask=/sys/power/disk", ALPINE, "sleep", "200"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ session = podmanTest.Podman([]string{"exec", "maskCtr3", "cat", "/sys/power/disk"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.OutputToString()).To(BeEmpty())
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
It("podman run seccomp test", func() {
session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"})
session.WaitWithDefaultTimeout()
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index ee6da30ec..76caf282b 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -199,9 +199,16 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
local format=$2
run_podman images --sort repository --format "$format"
- _check_line 0 ${aaa_name} ${aaa_tag}
- _check_line 1 "${PODMAN_TEST_IMAGE_REGISTRY}/${PODMAN_TEST_IMAGE_USER}/${PODMAN_TEST_IMAGE_NAME}" "${PODMAN_TEST_IMAGE_TAG}"
- _check_line 2 ${zzz_name} ${zzz_tag}
+
+ line_no=0
+ if [[ $format == table* ]]; then
+ # skip headers from table command
+ line_no=1
+ fi
+
+ _check_line $line_no ${aaa_name} ${aaa_tag}
+ _check_line $((line_no+1)) "${PODMAN_TEST_IMAGE_REGISTRY}/${PODMAN_TEST_IMAGE_USER}/${PODMAN_TEST_IMAGE_NAME}" "${PODMAN_TEST_IMAGE_TAG}"
+ _check_line $((line_no+2)) ${zzz_name} ${zzz_tag}
}
# Begin the test: tag $IMAGE with both the given names
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 8ea9b1c69..272e2ae93 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -28,12 +28,15 @@ verify_iid_and_name() {
@test "podman save to pipe and load" {
# Generate a random name and tag (must be lower-case)
- local random_name=x$(random_string 12 | tr A-Z a-z)
- local random_tag=t$(random_string 7 | tr A-Z a-z)
+ local random_name=x0$(random_string 12 | tr A-Z a-z)
+ local random_tag=t0$(random_string 7 | tr A-Z a-z)
local fqin=localhost/$random_name:$random_tag
run_podman tag $IMAGE $fqin
- archive=$PODMAN_TMPDIR/myimage-$(random_string 8).tar
+ # Believe it or not, 'podman load' would barf if any path element
+ # included a capital letter
+ archive=$PODMAN_TMPDIR/MySubDirWithCaps/MyImage-$(random_string 8).tar
+ mkdir -p $(dirname $archive)
# We can't use run_podman because that uses the BATS 'run' function
# which redirects stdout and stderr. Here we need to guarantee
@@ -51,19 +54,20 @@ verify_iid_and_name() {
run_podman images $fqin --format '{{.Repository}}:{{.Tag}}'
is "$output" "$fqin" "image preserves name across save/load"
- # FIXME: when/if 7337 gets fixed, load with a new tag
- if false; then
- local new_name=x$(random_string 14 | tr A-Z a-z)
- local new_tag=t$(random_string 6 | tr A-Z a-z)
+ # Load with a new tag
+ local new_name=x1$(random_string 14 | tr A-Z a-z)
+ local new_tag=t1$(random_string 6 | tr A-Z a-z)
run_podman rmi $fqin
- fqin=localhost/$new_name:$new_tag
- run_podman load -i $archive $fqin
- run_podman images $fqin --format '{{.Repository}}:{{.Tag}}'
- is "$output" "$fqin" "image can be loaded with new name:tag"
- fi
+
+ new_fqin=localhost/$new_name:$new_tag
+ run_podman load -i $archive $new_fqin
+ run_podman images --format '{{.Repository}}:{{.Tag}}' --sort tag
+ is "${lines[0]}" "$IMAGE" "image is preserved"
+ is "${lines[1]}" "$fqin" "image is reloaded with old fqin"
+ is "${lines[2]}" "$new_fqin" "image is reloaded with new fqin too"
# Clean up
- run_podman rmi $fqin
+ run_podman rmi $fqin $new_fqin
}
diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats
index 142d7dcd9..20fdd068f 100644
--- a/test/system/400-unprivileged-access.bats
+++ b/test/system/400-unprivileged-access.bats
@@ -118,7 +118,7 @@ EOF
/proc/scsi
/sys/firmware
/sys/fs/selinux
- /sys/dev
+ /sys/dev/block
)
# Some of the above may not exist on our host. Find only the ones that do.