diff options
-rw-r--r-- | cmd/podman/create.go | 47 | ||||
-rw-r--r-- | cmd/podman/ps.go | 142 | ||||
-rw-r--r-- | libpod/container.go | 24 | ||||
-rw-r--r-- | libpod/container_inspect.go | 3 | ||||
-rw-r--r-- | libpod/oci.go | 3 | ||||
-rw-r--r-- | libpod/runtime_img.go | 28 | ||||
-rw-r--r-- | test/podman_import.bats | 102 | ||||
-rw-r--r-- | test/podman_networking.bats | 9 |
8 files changed, 183 insertions, 175 deletions
diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 28bd0a60e..e0825566a 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -299,15 +299,26 @@ func isPortInPortBindings(pb map[nat.Port][]nat.PortBinding, port nat.Port) bool } func exposedPorts(c *cli.Context, imageExposedPorts map[string]struct{}) (map[nat.Port]struct{}, map[nat.Port][]nat.PortBinding, error) { - // TODO Handle exposed ports from image - // Currently ignoring imageExposedPorts + var exposedPorts []string var ports map[nat.Port]struct{} ports = make(map[nat.Port]struct{}) _, portBindings, err := nat.ParsePortSpecs(c.StringSlice("publish")) if err != nil { return nil, nil, err } - for _, e := range c.StringSlice("expose") { + + // Parse the ports from the image itself + for i := range imageExposedPorts { + fields := strings.Split(i, "/") + if len(fields) > 2 { + return nil, nil, errors.Errorf("invalid exposed port format in image") + } + exposedPorts = append(exposedPorts, fields[0]) + } + + // Add the ports from the image to the ports from the user + exposedPorts = append(exposedPorts, c.StringSlice("expose")...) + for _, e := range exposedPorts { // Merge in exposed ports to the map of published ports if strings.Contains(e, ":") { return nil, nil, fmt.Errorf("invalid port format for --expose: %s", e) @@ -359,10 +370,13 @@ func exposedPorts(c *cli.Context, imageExposedPorts map[string]struct{}) (map[na // default container runtime data out of it. imageData returns the data // to the caller. Example Data: Entrypoint, Env, WorkingDir, Labels ... func imageData(c *cli.Context, runtime *libpod.Runtime, image string) (string, string, *libpod.ImageData, error) { - var err error + var ( + err error + imageName, imageID string + ) // Deal with the image after all the args have been checked createImage := runtime.NewImage(image) - createImage.LocalName, _ = createImage.GetLocalImageName() + imageName, imageID, _ = createImage.GetLocalImageName() if createImage.LocalName == "" { // The image wasnt found by the user input'd name or its fqname // Pull the image @@ -373,31 +387,14 @@ func imageData(c *cli.Context, runtime *libpod.Runtime, image string) (string, s createImage.Pull(writer) } - var imageName string - if createImage.LocalName != "" { - nameIsID, err := runtime.IsImageID(createImage.LocalName) - if err != nil { - return "", "", nil, err - } - if nameIsID { - // If the input from the user is an ID, then we need to get the image - // name for cstorage - createImage.LocalName, err = createImage.GetNameByID() - if err != nil { - return "", "", nil, err - } - } - imageName = createImage.LocalName - } else { + createImage.LocalName = imageName + if imageName == "" { imageName, err = createImage.GetFQName() + _, imageID, _ = createImage.GetLocalImageName() } if err != nil { return "", "", nil, err } - imageID, err := createImage.GetImageID() - if err != nil { - return "", "", nil, err - } storageImage, err := runtime.GetImage(imageName) if err != nil { return "", "", nil, errors.Wrapf(err, "error getting storage image %q", image) diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index 9ac64f0c8..be6c5aef5 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "fmt" "os" "path/filepath" @@ -10,15 +11,19 @@ import ( "strings" "time" + "github.com/cri-o/ocicni/pkg/ocicni" "github.com/docker/go-units" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" "github.com/projectatomic/libpod/cmd/podman/formats" "github.com/projectatomic/libpod/libpod" + "github.com/sirupsen/logrus" "github.com/urfave/cli" "k8s.io/apimachinery/pkg/fields" ) +const mountTruncLength = 12 + type psOptions struct { all bool filter string @@ -62,12 +67,13 @@ type psJSONParams struct { ID string `json:"id"` Image string `json:"image"` ImageID string `json:"image_id"` - Command string `json:"command"` + Command []string `json:"command"` CreatedAt time.Time `json:"createdAt"` RunningFor time.Duration `json:"runningFor"` Status string `json:"status"` Ports map[string]struct{} `json:"ports"` - Size uint `json:"size"` + RootFsSize int64 `json:"rootFsSize"` + RWSize int64 `json:"rwSize"` Names string `json:"names"` Labels fields.Set `json:"labels"` Mounts []specs.Mount `json:"mounts"` @@ -241,7 +247,7 @@ func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Ru switch filter { case "id": return func(c *libpod.Container) bool { - return c.ID() == filterValue + return strings.Contains(c.ID(), filterValue) }, nil case "label": return func(c *libpod.Container) bool { @@ -254,7 +260,7 @@ func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Ru }, nil case "name": return func(c *libpod.Container) bool { - return c.Name() == filterValue + return strings.Contains(c.Name(), filterValue) }, nil case "exited": exitCode, err := strconv.ParseInt(filterValue, 10, 32) @@ -277,14 +283,18 @@ func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Ru if err != nil { return false } - return status.String() == filterValue + state := status.String() + if status == libpod.ContainerStateConfigured { + state = "created" + } + return state == filterValue }, nil case "ancestor": // This needs to refine to match docker // - ancestor=(<image-name>[:tag]|<image-id>| ⟨image@digest⟩) - containers created from an image or a descendant. return func(c *libpod.Container) bool { containerConfig := c.Config() - if containerConfig.RootfsImageID == filterValue || containerConfig.RootfsImageName == filterValue { + if strings.Contains(containerConfig.RootfsImageID, filterValue) || strings.Contains(containerConfig.RootfsImageName, filterValue) { return true } return false @@ -315,8 +325,21 @@ func generateContainerFilterFuncs(filter, filterValue string, runtime *libpod.Ru //- volume=(<volume-name>|<mount-point-destination>) return func(c *libpod.Container) bool { containerConfig := c.Config() - //TODO We need to still lookup against volumes too - return containerConfig.MountLabel == filterValue + var dest string + arr := strings.Split(filterValue, ":") + source := arr[0] + if len(arr) == 2 { + dest = arr[1] + } + for _, mount := range containerConfig.Spec.Mounts { + if dest != "" && (mount.Source == source && mount.Destination == dest) { + return true + } + if dest == "" && mount.Source == source { + return true + } + } + return false }, nil } return nil, errors.Errorf("%s is an invalid filter", filter) @@ -408,15 +431,32 @@ func getTemplateOutput(containers []*libpod.Container, opts psOptions) ([]psTemp runningFor := units.HumanDuration(time.Since(conConfig.CreatedTime)) createdAt := runningFor + " ago" imageName := conConfig.RootfsImageName + rootFsSize, err := ctr.RootFsSize() + if err != nil { + logrus.Errorf("error getting root fs size for %q: %v", ctr.ID(), err) + } + rwSize, err := ctr.RWSize() + if err != nil { + logrus.Errorf("error getting rw size for %q: %v", ctr.ID(), err) + } + + var createArtifact createConfig + artifact, err := ctr.GetArtifact("create-config") + if err == nil { + if err := json.Unmarshal(artifact, &createArtifact); err != nil { + return nil, err + } + } else { + logrus.Errorf("couldn't get some ps information, error getting artifact %q: %v", ctr.ID(), err) + } // TODO We currently dont have the ability to get many of // these data items. Uncomment as progress is made - //command := getStrFromSquareBrackets(ctr.ImageCreatedBy) command := strings.Join(ctr.Spec().Process.Args, " ") - //mounts := getMounts(ctr.Mounts, opts.noTrunc) - //ports := getPorts(ctr.Config.ExposedPorts) - //size := units.HumanSize(float64(ctr.SizeRootFs)) + ports := getPorts(ctr.Config().PortMappings) + mounts := getMounts(createArtifact.Volumes, opts.noTrunc) + size := units.HumanSizeWithPrecision(float64(rwSize), 3) + " (virtual " + units.HumanSizeWithPrecision(float64(rootFsSize), 3) + ")" labels := formatLabels(ctr.Labels()) ns := getNamespaces(pid) @@ -448,19 +488,19 @@ func getTemplateOutput(containers []*libpod.Container, opts psOptions) ([]psTemp CreatedAt: createdAt, RunningFor: runningFor, Status: status, - //Ports: ports, - //Size: size, - Names: ctr.Name(), - Labels: labels, - //Mounts: mounts, - PID: pid, - Cgroup: ns.Cgroup, - IPC: ns.IPC, - MNT: ns.MNT, - NET: ns.NET, - PIDNS: ns.PID, - User: ns.User, - UTS: ns.UTS, + Ports: ports, + Size: size, + Names: ctr.Name(), + Labels: labels, + Mounts: mounts, + PID: pid, + Cgroup: ns.Cgroup, + IPC: ns.IPC, + MNT: ns.MNT, + NET: ns.NET, + PIDNS: ns.PID, + User: ns.User, + UTS: ns.UTS, } psOutput = append(psOutput, params) } @@ -514,19 +554,28 @@ func getJSONOutput(containers []*libpod.Container, nSpace bool) ([]psJSONParams, if err != nil { return psOutput, errors.Wrapf(err, "unable to obtain container state for JSON output") } + rootFsSize, err := ctr.RootFsSize() + if err != nil { + logrus.Errorf("error getting root fs size for %q: %v", ctr.ID(), err) + } + rwSize, err := ctr.RWSize() + if err != nil { + logrus.Errorf("error getting rw size for %q: %v", ctr.ID(), err) + } + params := psJSONParams{ // TODO When we have ability to obtain the commented out data, we need // TODO to add it - ID: ctr.ID(), - Image: cc.RootfsImageName, - ImageID: cc.RootfsImageID, - //Command: getStrFromSquareBrackets(ctr.ImageCreatedBy), - Command: strings.Join(ctr.Spec().Process.Args, " "), + ID: ctr.ID(), + Image: cc.RootfsImageName, + ImageID: cc.RootfsImageID, + Command: ctr.Spec().Process.Args, CreatedAt: cc.CreatedTime, RunningFor: time.Since(cc.CreatedTime), Status: conState.String(), //Ports: cc.Spec.Linux.Resources.Network. - //Size: ctr.SizeRootFs, + RootFsSize: rootFsSize, + RWSize: rwSize, Names: cc.Name, Labels: cc.Labels, Mounts: cc.Spec.Mounts, @@ -585,37 +634,36 @@ func formatLabels(labels map[string]string) string { return "" } -/* // getMounts converts the volumes mounted to a string of the form "mount1, mount2" // it truncates it if noTrunc is false -func getMounts(mounts []specs.Mount, noTrunc bool) string { +func getMounts(mounts []string, noTrunc bool) string { var arr []string if len(mounts) == 0 { return "" } for _, mount := range mounts { - if noTrunc { - arr = append(arr, mount.Source) + splitArr := strings.Split(mount, ":") + if len(splitArr[0]) > mountTruncLength && !noTrunc { + arr = append(arr, splitArr[0][:mountTruncLength]+"...") continue } - tempArr := strings.SplitAfter(mount.Source, "/") - if len(tempArr) >= 3 { - arr = append(arr, strings.Join(tempArr[:3], "")) - } else { - arr = append(arr, mount.Source) - } + arr = append(arr, splitArr[0]) } return strings.Join(arr, ",") } + // getPorts converts the ports used to a string of the from "port1, port2" -func getPorts(ports map[string]struct{}) string { - var arr []string +func getPorts(ports []ocicni.PortMapping) string { + var portDisplay []string if len(ports) == 0 { return "" } - for key := range ports { - arr = append(arr, key) + for _, v := range ports { + hostIP := v.HostIP + if hostIP == "" { + hostIP = "0.0.0.0" + } + portDisplay = append(portDisplay, fmt.Sprintf("%s:%d->%d/%s", hostIP, v.HostPort, v.ContainerPort, v.Protocol)) } - return strings.Join(arr, ",") + return strings.Join(portDisplay, ", ") } -*/ diff --git a/libpod/container.go b/libpod/container.go index 4170ea443..27042de39 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -515,3 +515,27 @@ func (c *Container) CGroupPath() cgroups.Path { func (c *Container) StopTimeout() uint { return c.config.StopTimeout } + +// RootFsSize returns the root FS size of the container +func (c *Container) RootFsSize() (int64, error) { + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return -1, errors.Wrapf(err, "error updating container %s state", c.ID()) + } + } + return c.rootFsSize() +} + +// RWSize returns the rw size of the container +func (c *Container) RWSize() (int64, error) { + if !c.locked { + c.lock.Lock() + defer c.lock.Unlock() + if err := c.syncContainer(); err != nil { + return -1, errors.Wrapf(err, "error updating container %s state", c.ID()) + } + } + return c.rwSize() +} diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 0bb45cedd..78dd00c16 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -4,7 +4,6 @@ import ( "github.com/cri-o/ocicni/pkg/ocicni" "github.com/projectatomic/libpod/libpod/driver" "github.com/sirupsen/logrus" - "github.com/ulule/deepcopier" ) func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) (*ContainerInspectData, error) { @@ -77,7 +76,7 @@ func (c *Container) getContainerInspectData(size bool, driverData *driver.Data) // Copy port mappings into network settings if config.PortMappings != nil { - deepcopier.Copy(config.PortMappings).To(data.NetworkSettings.Ports) + data.NetworkSettings.Ports = config.PortMappings } // Get information on the container's network namespace (if present) diff --git a/libpod/oci.go b/libpod/oci.go index c122071e3..155b23640 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -232,11 +232,8 @@ func (r *OCIRuntime) createContainer(ctr *Container, cgroupParent string) (err e if err != nil { logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err) } else { - // XXX: this defer does nothing as the cgroup can't be deleted cause - // it contains the conmon pid in tasks // we need to remove this defer and delete the cgroup once conmon exits // maybe need a conmon monitor? - defer control.Delete() if err := control.Add(cgroups.Process{Pid: cmd.Process.Pid}); err != nil { logrus.Warnf("Failed to add conmon to cgroupfs sandbox cgroup: %v", err) } diff --git a/libpod/runtime_img.go b/libpod/runtime_img.go index 671e08c19..882174856 100644 --- a/libpod/runtime_img.go +++ b/libpod/runtime_img.go @@ -342,27 +342,23 @@ func getTags(nameInput string) (reference.NamedTagged, bool, error) { return tagged, isTagged, nil } -// GetLocalImageName returns the name of the image if it is local. -// It will return an empty string and error if not found. -func (k *Image) GetLocalImageName() (string, error) { - _, err := k.runtime.GetImage(k.Name) +// GetLocalImageName returns the name of the image if it is local as well +// as the image's ID. It will return an empty strings and error if not found. +func (k *Image) GetLocalImageName() (string, string, error) { + localImage, err := k.runtime.GetImage(k.Name) if err == nil { k.LocalName = k.Name - return k.Name, nil + return k.Name, localImage.ID, nil } localImages, err := k.runtime.GetImages(&ImageFilterParams{}) if err != nil { - return "", errors.Wrapf(err, "unable to find local images") + return "", "", errors.Wrapf(err, "unable to find local images") } _, isTagged, err := getTags(k.Name) if err != nil { - return "", err + return "", "", err } for _, image := range localImages { - if strings.HasPrefix(image.ID, k.Name) { - k.ID = image.ID - return image.ID, nil - } for _, name := range image.Names { imgRef, err := reference.Parse(name) if err != nil { @@ -382,22 +378,22 @@ func (k *Image) GetLocalImageName() (string, error) { if imageName == k.Name { k.LocalName = name - return name, nil + return name, image.ID, nil } imageSplit := strings.Split(imageName, "/") baseName := imageSplit[len(imageSplit)-1] if baseName == k.Name { k.LocalName = name - return name, nil + return name, image.ID, nil } } } - return "", errors.Wrapf(storage.ErrImageUnknown, "unable to find image locally") + return "", "", errors.Wrapf(storage.ErrImageUnknown, "unable to find image locally") } // HasLatest determines if we have the latest image local func (k *Image) HasLatest() (bool, error) { - localName, err := k.GetLocalImageName() + localName, _, err := k.GetLocalImageName() if err != nil { return false, err } @@ -434,7 +430,7 @@ func (k *Image) Pull(writer io.Writer) error { func (k *Image) Remove(force bool) (string, error) { if k.LocalName == "" { // This populates the images local name - _, err := k.GetLocalImageName() + _, _, err := k.GetLocalImageName() if err != nil { return "", errors.Wrapf(err, "unable to find %s locally", k.Name) } diff --git a/test/podman_import.bats b/test/podman_import.bats index 6303141c9..69c704a68 100644 --- a/test/podman_import.bats +++ b/test/podman_import.bats @@ -2,8 +2,6 @@ load helpers -IMAGE="redis:alpine" - function teardown() { cleanup_test } @@ -13,133 +11,73 @@ function setup() { } @test "podman import with source and reference" { - skip "Test needs to be converted to podman run bash -c" - start_crio - run bash -c crioctl pod run bash -c --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run bash -c crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run bash -c crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d $ALPINE sleep 60" echo "$output" [ "$status" -eq 0 ] ctr_id="$output" - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} import container.tar imported-image + run bash -cp "${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar $ctr_id" echo "$output" [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} images + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} import container.tar imported-image" echo "$output" [ "$status" -eq 0 ] - images="$output" - run bash -c grep "imported-image" <<< "$images" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} images" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio + [[ "$output" == *"imported-image"* ]] rm -f container.tar } @test "podman import without reference" { - skip "Test needs to be converted to podman run bash -c" - start_crio - run bash -c crioctl pod run bash -c --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run bash -c crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run bash -c crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d $ALPINE sleep 60" echo "$output" [ "$status" -eq 0 ] ctr_id="$output" - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} import container.tar + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar $ctr_id" echo "$output" [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} images + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} import container.tar" echo "$output" [ "$status" -eq 0 ] - images="$output" - run bash -c grep "<none>" <<< "$images" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} images" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio + [[ "$output" == *"<none>"* ]] rm -f container.tar } @test "podman import with message flag" { - skip "Test needs to be converted to podman run bash -c" - start_crio - run bash -c crioctl pod run bash -c --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run bash -c crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run bash -c crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d $ALPINE sleep 60" echo "$output" [ "$status" -eq 0 ] ctr_id="$output" - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} import --message "importing container test message" container.tar imported-image + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar $ctr_id" echo "$output" [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} history imported-image + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} import --message 'importing container test message' container.tar imported-image" echo "$output" [ "$status" -eq 0 ] - history="$output" - run bash -c grep "importing container test message" <<< "$history" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} history imported-image" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio + [[ "$output" == *"importing container test message"* ]] rm -f container.tar } @test "podman import with change flag" { - skip "Test needs to be converted to podman run bash -c" - start_crio - run bash -c crioctl pod run bash -c --config "$TESTDATA"/sandbox_config.json - echo "$output" - [ "$status" -eq 0 ] - pod_id="$output" - run bash -c crioctl image pull "$IMAGE" - echo "$output" - [ "$status" -eq 0 ] - run bash -c crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} run -d $ALPINE sleep 60" echo "$output" [ "$status" -eq 0 ] ctr_id="$output" - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar "$ctr_id" - echo "$output" - [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} import --change "CMD=/bin/bash" container.tar imported-image + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} export -o container.tar $ctr_id" echo "$output" [ "$status" -eq 0 ] - run bash -c ${PODMAN_BINARY} ${PODMAN_OPTIONS} inspect imported-image + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} import --change 'CMD=/bin/bash' container.tar imported-image" echo "$output" [ "$status" -eq 0 ] - inspect="$output" - run bash -c grep "/bin/bash" <<< "$inspect" + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} inspect imported-image" echo "$output" [ "$status" -eq 0 ] - cleanup_ctrs - cleanup_pods - stop_crio + [[ "$output" == *"/bin/bash"* ]] rm -f container.tar } diff --git a/test/podman_networking.bats b/test/podman_networking.bats index b2196b4bc..b27c16634 100644 --- a/test/podman_networking.bats +++ b/test/podman_networking.bats @@ -48,3 +48,12 @@ function setup() { echo "$output" [ "$status" -eq 0 ] } + +@test "expose ports in image" { + run ${PODMAN_BINARY} ${PODMAN_OPTIONS} run -dt -P docker.io/library/nginx:latest + echo "$output" + [ "$status" -eq 0 ] + run bash -c "${PODMAN_BINARY} ${PODMAN_OPTIONS} inspect -l | grep ': 80,'" + echo "$output" + [ "$status" -eq 0 ] +} |