summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/containers/create.go4
-rw-r--r--cmd/podman/containers/rm.go2
-rw-r--r--cmd/podman/networks/inspect.go28
-rw-r--r--cmd/podman/networks/list.go13
-rw-r--r--completions/bash/podman5
-rw-r--r--docs/source/markdown/podman-network-inspect.1.md14
-rw-r--r--docs/source/markdown/podman-network-ls.1.md18
-rw-r--r--pkg/bindings/images/images.go2
-rw-r--r--pkg/domain/entities/network.go2
-rw-r--r--pkg/domain/infra/abi/network.go37
-rw-r--r--pkg/domain/infra/tunnel/images.go1
-rw-r--r--pkg/domain/infra/tunnel/manifest.go31
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/create_test.go4
-rw-r--r--test/e2e/images_test.go10
-rw-r--r--test/e2e/kill_test.go2
-rw-r--r--test/e2e/manifest_test.go4
-rw-r--r--test/e2e/network_test.go39
-rw-r--r--test/e2e/pause_test.go3
-rw-r--r--test/e2e/save_test.go1
-rw-r--r--test/e2e/stop_test.go1
-rw-r--r--test/e2e/untag_test.go2
-rw-r--r--test/system/200-pod-top.bats40
-rw-r--r--test/system/200-pod.bats174
24 files changed, 347 insertions, 92 deletions
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 5058cdfe5..bb6cb5fdd 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -6,6 +6,8 @@ import (
"os"
"strings"
+ "github.com/containers/libpod/libpod/define"
+
"github.com/containers/common/pkg/config"
"github.com/containers/libpod/cmd/podman/common"
"github.com/containers/libpod/cmd/podman/registry"
@@ -203,7 +205,7 @@ func pullImage(imageName string) error {
}
if !br.Value || pullPolicy == config.PullImageAlways {
if pullPolicy == config.PullImageNever {
- return errors.New("unable to find a name and tag match for busybox in repotags: no such image")
+ return errors.Wrapf(define.ErrNoSuchImage, "unable to find a name and tag match for %s in repotags", imageName)
}
_, pullErr := registry.ImageEngine().Pull(registry.GetContext(), imageName, entities.ImagePullOptions{
Authfile: cliVals.Authfile,
diff --git a/cmd/podman/containers/rm.go b/cmd/podman/containers/rm.go
index 5ef2e23be..f01462447 100644
--- a/cmd/podman/containers/rm.go
+++ b/cmd/podman/containers/rm.go
@@ -128,5 +128,7 @@ func setExitCode(err error) {
registry.SetExitCode(1)
case cause == define.ErrCtrStateInvalid:
registry.SetExitCode(2)
+ case strings.Contains(cause.Error(), define.ErrCtrStateInvalid.Error()):
+ registry.SetExitCode(2)
}
}
diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go
index 60cede894..1b2e89909 100644
--- a/cmd/podman/networks/inspect.go
+++ b/cmd/podman/networks/inspect.go
@@ -3,6 +3,10 @@ package network
import (
"encoding/json"
"fmt"
+ "html/template"
+ "io"
+ "os"
+ "strings"
"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities"
@@ -24,12 +28,18 @@ var (
}
)
+var (
+ networkInspectOptions entities.NetworkInspectOptions
+)
+
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: networkinspectCommand,
Parent: networkCmd,
})
+ flags := networkinspectCommand.Flags()
+ flags.StringVarP(&networkInspectOptions.Format, "format", "f", "", "Pretty-print network to JSON or using a Go template")
}
func networkInspect(cmd *cobra.Command, args []string) error {
@@ -41,6 +51,22 @@ func networkInspect(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
- fmt.Println(string(b))
+ if strings.ToLower(networkInspectOptions.Format) == "json" || networkInspectOptions.Format == "" {
+ fmt.Println(string(b))
+ } else {
+ var w io.Writer = os.Stdout
+ //There can be more than 1 in the inspect output.
+ format := "{{range . }}" + networkInspectOptions.Format + "{{end}}"
+ tmpl, err := template.New("inspectNetworks").Parse(format)
+ if err != nil {
+ return err
+ }
+ if err := tmpl.Execute(w, responses); err != nil {
+ return err
+ }
+ if flusher, ok := w.(interface{ Flush() error }); ok {
+ return flusher.Flush()
+ }
+ }
return nil
}
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 1c0528e5c..24604c055 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -40,8 +40,9 @@ var (
func networkListFlags(flags *pflag.FlagSet) {
// TODO enable filters based on something
//flags.StringSliceVarP(&networklistCommand.Filter, "filter", "f", []string{}, "Pause all running containers")
- flags.StringVarP(&networkListOptions.Format, "format", "f", "", "Pretty-print containers to JSON or using a Go template")
+ flags.StringVarP(&networkListOptions.Format, "format", "f", "", "Pretty-print networks to JSON or using a Go template")
flags.BoolVarP(&networkListOptions.Quiet, "quiet", "q", false, "display only names")
+ flags.StringVarP(&networkListOptions.Filter, "filter", "", "", "Provide filter values (e.g. 'name=podman')")
}
func init() {
@@ -59,6 +60,14 @@ func networkList(cmd *cobra.Command, args []string) error {
nlprs []NetworkListPrintReports
)
+ // validate the filter pattern.
+ if len(networkListOptions.Filter) > 0 {
+ tokens := strings.Split(networkListOptions.Filter, "=")
+ if len(tokens) != 2 {
+ return fmt.Errorf("invalid filter syntax : %s", networkListOptions.Filter)
+ }
+ }
+
responses, err := registry.ContainerEngine().NetworkList(registry.Context(), networkListOptions)
if err != nil {
return err
@@ -69,7 +78,7 @@ func networkList(cmd *cobra.Command, args []string) error {
return quietOut(responses)
}
- if networkListOptions.Format == "json" {
+ if strings.ToLower(networkListOptions.Format) == "json" {
return jsonOut(responses)
}
diff --git a/completions/bash/podman b/completions/bash/podman
index 5dbd179ce..9baf7901e 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -1024,6 +1024,8 @@ _podman_network_inspect() {
local boolean_options="
--help
-h
+ --format
+ -f
"
_complete_ "$options_with_args" "$boolean_options"
@@ -1042,6 +1044,9 @@ _podman_network_ls() {
-h
--quiet
-q
+ --format
+ -f
+ -- filter
"
_complete_ "$options_with_args" "$boolean_options"
diff --git a/docs/source/markdown/podman-network-inspect.1.md b/docs/source/markdown/podman-network-inspect.1.md
index dfa7e4b0c..ca6875d18 100644
--- a/docs/source/markdown/podman-network-inspect.1.md
+++ b/docs/source/markdown/podman-network-inspect.1.md
@@ -9,6 +9,15 @@ podman\-network\-inspect - Displays the raw CNI network configuration for one or
## DESCRIPTION
Display the raw (JSON format) network configuration. This command is not available for rootless users.
+## OPTIONS
+**--quiet**, **-q**
+
+The `quiet` option will restrict the output to only the network names.
+
+**--format**, **-f**
+
+Pretty-print networks to JSON or using a Go template.
+
## EXAMPLE
Inspect the default podman network
@@ -43,6 +52,11 @@ Inspect the default podman network
]
```
+```
+# podman network inspect podman --format '{{(index .plugins 0).ipam.ranges}}'
+[[map[gateway:10.88.0.1 subnet:10.88.0.0/16]]]
+```
+
## SEE ALSO
podman(1), podman-network(1), podman-network-ls(1)
diff --git a/docs/source/markdown/podman-network-ls.1.md b/docs/source/markdown/podman-network-ls.1.md
index 46e424593..7b20cf5e0 100644
--- a/docs/source/markdown/podman-network-ls.1.md
+++ b/docs/source/markdown/podman-network-ls.1.md
@@ -12,7 +12,15 @@ Displays a list of existing podman networks. This command is not available for r
## OPTIONS
**--quiet**, **-q**
-The `quiet` option will restrict the output to only the network names
+The `quiet` option will restrict the output to only the network names.
+
+**--format**, **-f**
+
+Pretty-print networks to JSON or using a Go template.
+
+**--filter**
+
+Provide filter values (e.g. 'name=podman').
## EXAMPLE
@@ -36,6 +44,14 @@ outside
podman9
```
+Display name of network which support bridge plugin
+```
+# podman network ls --filter plugin=portmap --format {{.Name}}
+podman
+podman2
+podman9
+```
+
## SEE ALSO
podman(1), podman-network(1), podman-network-inspect(1)
diff --git a/pkg/bindings/images/images.go b/pkg/bindings/images/images.go
index a15ce56e5..69b9e9bbf 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -146,7 +146,7 @@ func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, c
_, err = io.Copy(w, response.Body)
return err
}
- return nil
+ return response.Process(nil)
}
// Prune removes unused images from local storage. The optional filters can be used to further
diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go
index d001553e0..9beeeb042 100644
--- a/pkg/domain/entities/network.go
+++ b/pkg/domain/entities/network.go
@@ -10,6 +10,7 @@ import (
type NetworkListOptions struct {
Format string
Quiet bool
+ Filter string
}
// NetworkListReport describes the results from listing networks
@@ -19,6 +20,7 @@ type NetworkListReport struct {
// NetworkInspectOptions describes options for inspect networks
type NetworkInspectOptions struct {
+ Format string
}
// NetworkInspectReport describes the results from inspect networks
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index dfde3a939..8e3515824 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -6,7 +6,9 @@ import (
"fmt"
"io/ioutil"
"path/filepath"
+ "strings"
+ "github.com/containernetworking/cni/libcni"
cniversion "github.com/containernetworking/cni/pkg/version"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/domain/entities"
@@ -28,8 +30,19 @@ 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 {
- reports = append(reports, &entities.NetworkListReport{NetworkConfigList: n})
+ if ifPassesFilterTest(n, tokens) {
+ reports = append(reports, &entities.NetworkListReport{NetworkConfigList: n})
+ }
}
return reports, nil
}
@@ -255,3 +268,25 @@ func createMacVLAN(r *libpod.Runtime, name string, options entities.NetworkCreat
err = ioutil.WriteFile(cniPathName, b, 0644)
return cniPathName, err
}
+
+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
+}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 5a849d362..4d00d331b 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -190,7 +190,6 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string,
f *os.File
err error
)
-
switch options.Format {
case "oci-dir", "docker-dir":
f, err = ioutil.TempFile("", "podman_save")
diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go
index 9c1f5349a..beac378fe 100644
--- a/pkg/domain/infra/tunnel/manifest.go
+++ b/pkg/domain/infra/tunnel/manifest.go
@@ -57,46 +57,21 @@ func (ir *ImageEngine) ManifestAdd(ctx context.Context, opts entities.ManifestAd
}
manifestAddOpts.Annotation = annotations
}
- listID, err := manifests.Add(ctx, opts.Images[1], manifestAddOpts)
+ listID, err := manifests.Add(ir.ClientCxt, opts.Images[1], manifestAddOpts)
if err != nil {
return listID, errors.Wrapf(err, "error adding to manifest list %s", opts.Images[1])
}
return listID, nil
}
-// FIXME There is no endpoint for annotate and therefor this code is currently invalid
// ManifestAnnotate updates an entry of the manifest list
func (ir *ImageEngine) ManifestAnnotate(ctx context.Context, names []string, opts entities.ManifestAnnotateOptions) (string, error) {
return "", errors.New("not implemented")
- // manifestAnnotateOpts := image.ManifestAnnotateOpts{
- // Arch: opts.Arch,
- // Features: opts.Features,
- // OS: opts.OS,
- // OSFeatures: opts.OSFeatures,
- // OSVersion: opts.OSVersion,
- // Variant: opts.Variant,
- // }
- // if len(opts.Annotation) > 0 {
- // annotations := make(map[string]string)
- // for _, annotationSpec := range opts.Annotation {
- // spec := strings.SplitN(annotationSpec, "=", 2)
- // if len(spec) != 2 {
- // return "", errors.Errorf("no value given for annotation %q", spec[0])
- // }
- // annotations[spec[0]] = spec[1]
- // }
- // manifestAnnotateOpts.Annotation = annotations
- // }
- // updatedListID, err := manifests.Annotate(ctx, names[0], names[1], manifestAnnotateOpts)
- // if err != nil {
- // return updatedListID, errors.Wrapf(err, "error annotating %s of manifest list %s", names[1], names[0])
- // }
- // return fmt.Sprintf("%s :%s", updatedListID, names[1]), nil
}
// ManifestRemove removes the digest from manifest list
func (ir *ImageEngine) ManifestRemove(ctx context.Context, names []string) (string, error) {
- updatedListID, err := manifests.Remove(ctx, names[0], names[1])
+ updatedListID, err := manifests.Remove(ir.ClientCxt, names[0], names[1])
if err != nil {
return updatedListID, errors.Wrapf(err, "error removing from manifest %s", names[0])
}
@@ -105,6 +80,6 @@ func (ir *ImageEngine) ManifestRemove(ctx context.Context, names []string) (stri
// ManifestPush pushes a manifest list or image index to the destination
func (ir *ImageEngine) ManifestPush(ctx context.Context, names []string, opts entities.ManifestPushOptions) error {
- _, err := manifests.Push(ctx, names[0], &names[1], &opts.All)
+ _, err := manifests.Push(ir.ClientCxt, names[0], &names[1], &opts.All)
return err
}
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 6d6f1762d..80ee83f44 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -35,7 +35,7 @@ var (
INTEGRATION_ROOT string
CGROUP_MANAGER = "systemd"
ARTIFACT_DIR = "/tmp/.artifacts"
- RESTORE_IMAGES = []string{ALPINE, BB}
+ RESTORE_IMAGES = []string{ALPINE, BB, nginx}
defaultWaitTimeout = 90
)
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 9cdbe6287..7d4858551 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -235,11 +235,11 @@ var _ = Describe("Podman create", func() {
})
It("podman create --pull", func() {
- session := podmanTest.PodmanNoCache([]string{"create", "--pull", "never", "--name=foo", "nginx"})
+ session := podmanTest.PodmanNoCache([]string{"create", "--pull", "never", "--name=foo", "debian"})
session.WaitWithDefaultTimeout()
Expect(session).To(ExitWithError())
- session = podmanTest.PodmanNoCache([]string{"create", "--pull", "always", "--name=foo", "nginx"})
+ session = podmanTest.PodmanNoCache([]string{"create", "--pull", "always", "--name=foo", "debian"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index 542f7f1e1..cd281e3c7 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -90,7 +90,7 @@ var _ = Describe("Podman images", func() {
session = podmanTest.PodmanNoCache([]string{"images", "-qn"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 2))
+ Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 3))
})
It("podman images with digests", func() {
@@ -164,13 +164,13 @@ var _ = Describe("Podman images", func() {
retapline := podmanTest.PodmanNoCache([]string{"images", "-f", "reference=a*pine"})
retapline.WaitWithDefaultTimeout()
Expect(retapline).Should(Exit(0))
- Expect(len(retapline.OutputToStringArray())).To(Equal(2))
+ Expect(len(retapline.OutputToStringArray())).To(Equal(3))
Expect(retapline.LineInOutputContains("alpine")).To(BeTrue())
retapline = podmanTest.PodmanNoCache([]string{"images", "-f", "reference=alpine"})
retapline.WaitWithDefaultTimeout()
Expect(retapline).Should(Exit(0))
- Expect(len(retapline.OutputToStringArray())).To(Equal(2))
+ Expect(len(retapline.OutputToStringArray())).To(Equal(3))
Expect(retapline.LineInOutputContains("alpine")).To(BeTrue())
retnone := podmanTest.PodmanNoCache([]string{"images", "-q", "-f", "reference=bogus"})
@@ -321,12 +321,12 @@ ENV foo=bar
session := podmanTest.PodmanNoCache([]string{"images"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(4))
+ Expect(len(session.OutputToStringArray())).To(Equal(5))
session2 := podmanTest.PodmanNoCache([]string{"images", "--all"})
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
- Expect(len(session2.OutputToStringArray())).To(Equal(6))
+ Expect(len(session2.OutputToStringArray())).To(Equal(7))
})
It("podman images filter by label", func() {
diff --git a/test/e2e/kill_test.go b/test/e2e/kill_test.go
index b0f9cd900..3f192fb55 100644
--- a/test/e2e/kill_test.go
+++ b/test/e2e/kill_test.go
@@ -100,7 +100,7 @@ var _ = Describe("Podman kill", func() {
})
It("podman kill latest container", func() {
- Skip(v2remotefail)
+ SkipIfRemote()
session := podmanTest.RunTopContainer("")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go
index a1decde7d..c47e20276 100644
--- a/test/e2e/manifest_test.go
+++ b/test/e2e/manifest_test.go
@@ -28,7 +28,6 @@ var _ = Describe("Podman manifest", func() {
)
BeforeEach(func() {
- Skip(v2remotefail)
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -103,6 +102,7 @@ var _ = Describe("Podman manifest", func() {
})
It("podman manifest annotate", func() {
+ SkipIfRemote()
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -155,6 +155,7 @@ var _ = Describe("Podman manifest", func() {
})
It("podman manifest push", func() {
+ Skip(v2remotefail)
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -184,6 +185,7 @@ var _ = Describe("Podman manifest", func() {
})
It("podman manifest push purge", func() {
+ Skip(v2remotefail)
session := podmanTest.Podman([]string{"manifest", "create", "foo"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index 8d575d7f9..e293876b9 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -105,6 +105,32 @@ var _ = Describe("Podman network", func() {
Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
})
+ It("podman network list --filter success", func() {
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "ls", "--filter", "plugin=bridge"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("podman-integrationtest")).To(BeTrue())
+ })
+
+ It("podman network list --filter failure", func() {
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "ls", "--filter", "plugin=test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("podman-integrationtest")).To(BeFalse())
+ })
+
It("podman network rm no args", func() {
session := podmanTest.Podman([]string{"network", "rm"})
session.WaitWithDefaultTimeout()
@@ -152,6 +178,19 @@ var _ = Describe("Podman network", func() {
Expect(session.IsJSONOutputValid()).To(BeTrue())
})
+ It("podman network inspect", func() {
+ // Setup, use uuid to prevent conflict with other tests
+ uuid := stringid.GenerateNonCryptoID()
+ secondPath := filepath.Join(cniPath, fmt.Sprintf("%s.conflist", uuid))
+ writeConf([]byte(secondConf), secondPath)
+ defer removeConf(secondPath)
+
+ session := podmanTest.Podman([]string{"network", "inspect", "podman-integrationtest", "--format", "{{.cniVersion}}"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.LineInOutputContains("0.3.0")).To(BeTrue())
+ })
+
It("podman inspect container single CNI network", func() {
netName := "testNetSingleCNI"
network := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.50.0/24", netName})
diff --git a/test/e2e/pause_test.go b/test/e2e/pause_test.go
index 162138a43..2faa4bc3f 100644
--- a/test/e2e/pause_test.go
+++ b/test/e2e/pause_test.go
@@ -132,7 +132,6 @@ var _ = Describe("Podman pause", func() {
})
It("podman remove a paused container by id without force", func() {
- Skip(v2remotefail)
session := podmanTest.RunTopContainer("")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -175,7 +174,6 @@ var _ = Describe("Podman pause", func() {
})
It("podman stop a paused container by id", func() {
- Skip(v2remotefail)
session := podmanTest.RunTopContainer("")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -272,7 +270,6 @@ var _ = Describe("Podman pause", func() {
})
It("Pause a bunch of running containers", func() {
- Skip(v2remotefail)
for i := 0; i < 3; i++ {
name := fmt.Sprintf("test%d", i)
run := podmanTest.Podman([]string{"run", "-dt", "--name", name, nginx})
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index 69454f6a9..aaa5ae180 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -68,7 +68,6 @@ var _ = Describe("Podman save", func() {
})
It("podman save bogus image", func() {
- Skip(v2remotefail)
outfile := filepath.Join(podmanTest.TempDir, "alpine.tar")
save := podmanTest.PodmanNoCache([]string{"save", "-o", outfile, "FOOBAR"})
diff --git a/test/e2e/stop_test.go b/test/e2e/stop_test.go
index 8c845e90a..8e49e3bd0 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -198,7 +198,6 @@ var _ = Describe("Podman stop", func() {
})
It("podman stop all containers with one stopped", func() {
- Skip(v2remotefail)
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/untag_test.go b/test/e2e/untag_test.go
index c61f57a9c..43b874d47 100644
--- a/test/e2e/untag_test.go
+++ b/test/e2e/untag_test.go
@@ -59,7 +59,7 @@ var _ = Describe("Podman untag", func() {
results := podmanTest.PodmanNoCache([]string{"images"})
results.WaitWithDefaultTimeout()
Expect(results.ExitCode()).To(Equal(0))
- Expect(results.OutputToStringArray()).To(HaveLen(5))
+ Expect(results.OutputToStringArray()).To(HaveLen(6))
Expect(results.LineInOuputStartsWith("docker.io/library/alpine")).To(BeTrue())
Expect(results.LineInOuputStartsWith("localhost/foo")).To(BeTrue())
Expect(results.LineInOuputStartsWith("localhost/bar")).To(BeTrue())
diff --git a/test/system/200-pod-top.bats b/test/system/200-pod-top.bats
deleted file mode 100644
index bba1e8d14..000000000
--- a/test/system/200-pod-top.bats
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/usr/bin/env bats
-
-load helpers
-
-@test "podman pod top - containers in different PID namespaces" {
- skip_if_remote "podman-pod does not work with podman-remote"
-
- # With infra=false, we don't get a /pause container (we also
- # don't pull k8s.gcr.io/pause )
- no_infra='--infra=false'
- run_podman pod create $no_infra
- podid="$output"
-
- # Start two containers...
- run_podman run -d --pod $podid $IMAGE top -d 2
- cid1="$output"
- run_podman run -d --pod $podid $IMAGE top -d 2
- cid2="$output"
-
- # ...and wait for them to actually start.
- wait_for_output "PID \+PPID \+USER " $cid1
- wait_for_output "PID \+PPID \+USER " $cid2
-
- # Both containers have emitted at least one top-like line.
- # Now run 'pod top', and expect two 'top -d 2' processes running.
- run_podman pod top $podid
- is "$output" ".*root.*top -d 2.*root.*top -d 2" "two 'top' containers"
-
- # By default (podman pod create w/ default --infra) there should be
- # a /pause container.
- if [ -z "$no_infra" ]; then
- is "$output" ".*0 \+1 \+0 \+[0-9. ?s]\+/pause" "there is a /pause container"
- fi
-
- # Clean up
- run_podman pod rm -f $podid
-}
-
-
-# vim: filetype=sh
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
new file mode 100644
index 000000000..f3d278826
--- /dev/null
+++ b/test/system/200-pod.bats
@@ -0,0 +1,174 @@
+#!/usr/bin/env bats
+
+load helpers
+
+# This is a long ugly way to clean up pods and remove the pause image
+function teardown() {
+ run_podman pod rm -f -a
+ run_podman rm -f -a
+ run_podman image list --format '{{.ID}} {{.Repository}}'
+ while read id name; do
+ if [[ "$name" =~ /pause ]]; then
+ run_podman rmi $id
+ fi
+ done <<<"$output"
+
+ basic_teardown
+}
+
+
+@test "podman pod top - containers in different PID namespaces" {
+ skip_if_remote "podman-pod does not work with podman-remote"
+
+ # With infra=false, we don't get a /pause container (we also
+ # don't pull k8s.gcr.io/pause )
+ no_infra='--infra=false'
+ run_podman pod create $no_infra
+ podid="$output"
+
+ # Start two containers...
+ run_podman run -d --pod $podid $IMAGE top -d 2
+ cid1="$output"
+ run_podman run -d --pod $podid $IMAGE top -d 2
+ cid2="$output"
+
+ # ...and wait for them to actually start.
+ wait_for_output "PID \+PPID \+USER " $cid1
+ wait_for_output "PID \+PPID \+USER " $cid2
+
+ # Both containers have emitted at least one top-like line.
+ # Now run 'pod top', and expect two 'top -d 2' processes running.
+ run_podman pod top $podid
+ is "$output" ".*root.*top -d 2.*root.*top -d 2" "two 'top' containers"
+
+ # By default (podman pod create w/ default --infra) there should be
+ # a /pause container.
+ if [ -z "$no_infra" ]; then
+ is "$output" ".*0 \+1 \+0 \+[0-9. ?s]\+/pause" "there is a /pause container"
+ fi
+
+ # Clean up
+ run_podman pod rm -f $podid
+}
+
+
+@test "podman pod - communicating between pods" {
+ skip_if_remote "podman-pod does not work with podman-remote"
+
+ podname=pod$(random_string)
+ run_podman pod create --infra=true --name=$podname
+
+ # Randomly-assigned port in the 5xxx range
+ for port in $(shuf -i 5000-5999);do
+ if ! { exec 3<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then
+ break
+ fi
+ done
+
+ # Listener. This will exit as soon as it receives a message.
+ run_podman run -d --pod $podname $IMAGE nc -l -p $port
+ cid1="$output"
+
+ # Talker: send the message via common port on localhost
+ message=$(random_string 15)
+ run_podman run --rm --pod $podname $IMAGE \
+ sh -c "echo $message | nc 127.0.0.1 $port"
+
+ # Back to the first (listener) container. Make sure message was received.
+ run_podman logs $cid1
+ is "$output" "$message" "message sent from one container to another"
+
+ # Clean up. First the nc -l container...
+ run_podman rm $cid1
+
+ # ...then, from pause container, find the image ID of the pause image...
+ # FIXME: if #6283 gets implemented, use 'inspect --format ...'
+ run_podman pod inspect $podname
+ pause_cid=$(jq -r '.Containers[0].Id' <<<"$output")
+ run_podman container inspect --format '{{.Image}}' $pause_cid
+ pause_iid="$output"
+
+ # ...then rm the pod, then rmi the pause image so we don't leave strays.
+ run_podman pod rm $podname
+ run_podman rmi $pause_iid
+}
+
+# Random byte
+function octet() {
+ echo $(( $RANDOM & 255 ))
+}
+
+# random MAC address: convention seems to be that 2nd lsb=1, lsb=0
+# (i.e. 0bxxxxxx10) in the first octet guarantees a private space.
+# FIXME: I can't find a definitive reference for this though
+# Generate the address IN CAPS (A-F), but we will test it in lowercase.
+function random_mac() {
+ local mac=$(printf "%02X" $(( $(octet) & 242 | 2 )) )
+ for i in $(seq 2 6); do
+ mac+=$(printf ":%02X" $(octet))
+ done
+
+ echo $mac
+}
+
+# Random RFC1918 IP address
+function random_ip() {
+ local ip="172.20"
+ for i in 1 2;do
+ ip+=$(printf ".%d" $(octet))
+ done
+ echo $ip
+}
+
+@test "podman pod create - hashtag AllTheOptions" {
+ mac=$(random_mac)
+ add_host_ip=$(random_ip)
+ add_host_n=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).xyz
+
+ dns_server=$(random_ip)
+ dns_opt="ndots:$(octet)"
+ dns_search=$(random_string 15 | tr A-Z a-z).abc
+
+ hostname=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).net
+
+ pod_id_file=${PODMAN_TMPDIR}/pod-id-file
+
+ # Create a pod with all the desired options
+ # FIXME: --ip=$ip fails:
+ # Error adding network: failed to allocate all requested IPs
+ run_podman pod create --name=mypod \
+ --pod-id-file=$pod_id_file \
+ --mac-address=$mac \
+ --hostname=$hostname \
+ --add-host "$add_host_n:$add_host_ip" \
+ --dns "$dns_server" \
+ --dns-search "$dns_search" \
+ --dns-opt "$dns_opt"
+ pod_id="$output"
+
+ # Check --pod-id-file
+ # FIXME: broken in master; reenable once #6292 is fixed
+ #is "$(<$pod_id_file)" "$pod_id" "contents of pod-id-file"
+
+ # Check each of the options
+ if ! is_rootless; then
+ run_podman run --rm --pod mypod $IMAGE ip link show
+ # 'ip' outputs hex in lower-case, ${expr,,} converts UC to lc
+ is "$output" ".* link/ether ${mac,,} " "requested MAC address was set"
+ fi
+
+ run_podman run --rm --pod mypod $IMAGE hostname
+ is "$output" "$hostname" "--hostname set the hostname"
+
+ run_podman run --rm --pod $pod_id $IMAGE cat /etc/hosts
+ is "$output" ".*$add_host_ip $add_host_n" "--add-host was added"
+ is "$output" ".* $hostname" "--hostname is in /etc/hosts"
+ # ^^^^ this must be a tab, not a space
+
+ run_podman run --rm --pod mypod $IMAGE cat /etc/resolv.conf
+ is "$output" ".*nameserver $dns_server" "--dns [server] was added"
+ is "$output" ".*search $dns_search" "--dns-search was added"
+ is "$output" ".*options $dns_opt" "--dns-opt was added"
+}
+
+# vim: filetype=sh