summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/source/markdown/podman-create.1.md5
-rw-r--r--docs/source/markdown/podman-run.1.md5
-rw-r--r--docs/source/markdown/podman-secret-rm.1.md6
-rw-r--r--pkg/api/handlers/compat/auth.go59
-rw-r--r--pkg/api/handlers/compat/volumes.go34
-rw-r--r--pkg/api/handlers/libpod/networks.go2
-rw-r--r--pkg/api/handlers/libpod/swagger.go2
-rw-r--r--pkg/api/server/register_auth.go24
-rw-r--r--pkg/api/server/swagger.go9
-rw-r--r--pkg/bindings/network/network.go3
-rw-r--r--pkg/domain/entities/system.go11
-rw-r--r--test/apiv2/30-volumes.at4
-rw-r--r--test/apiv2/35-networks.at4
-rw-r--r--test/apiv2/44-mounts.at9
-rw-r--r--test/apiv2/60-auth.at24
-rw-r--r--test/apiv2/rest_api/test_rest_v2_0_0.py11
-rw-r--r--test/system/065-cp.bats1
-rw-r--r--test/system/070-build.bats69
-rw-r--r--test/system/120-load.bats3
-rw-r--r--test/system/700-play.bats16
20 files changed, 233 insertions, 68 deletions
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index d6b90e17a..5c53f8601 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -833,6 +833,11 @@ A secret is a blob of sensitive data which a container needs at runtime but
should not be stored in the image or in source control, such as usernames and passwords,
TLS certificates and keys, SSH keys or other important generic strings or binary content (up to 500 kb in size).
+Secrets are copied and mounted into the container when a container is created. If a secret is deleted using
+`podman secret rm`, the container will still have access to the secret. If a secret is deleted and
+another secret is created with the same name, the secret inside the container will not change; the old
+secret value will still remain.
+
Secrets are managed using the `podman secret` command.
#### **--security-opt**=*option*
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 78b036cee..f61344099 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -885,6 +885,11 @@ A secret is a blob of sensitive data which a container needs at runtime but
should not be stored in the image or in source control, such as usernames and passwords,
TLS certificates and keys, SSH keys or other important generic strings or binary content (up to 500 kb in size).
+Secrets are copied and mounted into the container when a container is created. If a secret is deleted using
+`podman secret rm`, the container will still have access to the secret. If a secret is deleted and
+another secret is created with the same name, the secret inside the container will not change; the old
+secret value will still remain.
+
Secrets are managed using the `podman secret` command
#### **--security-opt**=*option*
diff --git a/docs/source/markdown/podman-secret-rm.1.md b/docs/source/markdown/podman-secret-rm.1.md
index 5169626dc..c6f5079ba 100644
--- a/docs/source/markdown/podman-secret-rm.1.md
+++ b/docs/source/markdown/podman-secret-rm.1.md
@@ -10,6 +10,12 @@ podman\-secret\-rm - Remove one or more secrets
Removes one or more secrets.
+`podman secret rm` is safe to use on secrets that are in use by a container.
+The created container will still have access to the secret data because secrets are
+copied and mounted into the container when a container is created. If a secret is deleted and
+another secret is created with the same name, the secret inside the container will not change;
+the old secret value will still remain.
+
## OPTIONS
#### **--all**, **-a**
diff --git a/pkg/api/handlers/compat/auth.go b/pkg/api/handlers/compat/auth.go
new file mode 100644
index 000000000..2c152fbc2
--- /dev/null
+++ b/pkg/api/handlers/compat/auth.go
@@ -0,0 +1,59 @@
+package compat
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+
+ DockerClient "github.com/containers/image/v5/docker"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/podman/v3/pkg/api/handlers/utils"
+ "github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/containers/podman/v3/pkg/registries"
+ docker "github.com/docker/docker/api/types"
+ "github.com/pkg/errors"
+)
+
+func stripAddressOfScheme(address string) string {
+ for _, s := range []string{"https", "http"} {
+ address = strings.TrimPrefix(address, s+"://")
+ }
+ return address
+}
+
+func Auth(w http.ResponseWriter, r *http.Request) {
+ var authConfig docker.AuthConfig
+ err := json.NewDecoder(r.Body).Decode(&authConfig)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse request"))
+ return
+ }
+
+ skipTLS := types.NewOptionalBool(false)
+ if strings.HasPrefix(authConfig.ServerAddress, "https://localhost/") || strings.HasPrefix(authConfig.ServerAddress, "https://localhost:") || strings.HasPrefix(authConfig.ServerAddress, "localhost:") {
+ // support for local testing
+ skipTLS = types.NewOptionalBool(true)
+ }
+
+ fmt.Println("Authenticating with existing credentials...")
+ sysCtx := types.SystemContext{
+ AuthFilePath: "",
+ DockerCertPath: "",
+ DockerInsecureSkipTLSVerify: skipTLS,
+ SystemRegistriesConfPath: registries.SystemRegistriesConfPath(),
+ }
+ registry := stripAddressOfScheme(authConfig.ServerAddress)
+ if err := DockerClient.CheckAuth(context.Background(), &sysCtx, authConfig.Username, authConfig.Password, registry); err == nil {
+ utils.WriteResponse(w, http.StatusOK, entities.AuthReport{
+ IdentityToken: "",
+ Status: "Login Succeeded",
+ })
+ } else {
+ utils.WriteResponse(w, http.StatusBadRequest, entities.AuthReport{
+ IdentityToken: "",
+ Status: "login attempt to " + authConfig.ServerAddress + " failed with status: " + err.Error(),
+ })
+ }
+}
diff --git a/pkg/api/handlers/compat/volumes.go b/pkg/api/handlers/compat/volumes.go
index 28fb67102..d2febc615 100644
--- a/pkg/api/handlers/compat/volumes.go
+++ b/pkg/api/handlers/compat/volumes.go
@@ -5,6 +5,7 @@ import (
"encoding/json"
"net/http"
"net/url"
+ "strings"
"time"
"github.com/containers/podman/v3/libpod"
@@ -31,7 +32,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -40,7 +41,7 @@ func ListVolumes(w http.ResponseWriter, r *http.Request) {
// happily parse them for us.
for filter := range query.Filters {
if filter == "opts" {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
errors.Errorf("unsupported libpod filters passed to docker endpoint"))
return
}
@@ -90,7 +91,7 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
/* No query string data*/
query := struct{}{}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -218,7 +219,7 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
@@ -263,25 +264,24 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
func PruneVolumes(w http.ResponseWriter, r *http.Request) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
- decoder = r.Context().Value("decoder").(*schema.Decoder)
)
- // For some reason the prune filters are query parameters even though this
- // is a POST endpoint
- query := struct {
- Filters map[string][]string `schema:"filters"`
- }{
- // override any golang type defaults
- }
-
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
+ filtersList, err := filtersFromRequest(r)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
+ filterMap := map[string][]string{}
+ for _, filter := range filtersList {
+ split := strings.SplitN(filter, "=", 2)
+ if len(split) > 1 {
+ filterMap[split[0]] = append(filterMap[split[0]], split[1])
+ }
+ }
- f := (url.Values)(query.Filters)
+ f := (url.Values)(filterMap)
filterFuncs, err := filters.GenerateVolumeFilters(f)
if err != nil {
- utils.Error(w, "Something when wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse filters for %s", f.Encode()))
+ utils.Error(w, "Something when wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse filters for %s", f.Encode()))
return
}
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index a6c4f6d64..48cd37994 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -128,7 +128,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusOK, reports)
+ utils.WriteResponse(w, http.StatusOK, reports[0])
}
// Connect adds a container to a network
diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go
index 1bececa1a..2631f19ac 100644
--- a/pkg/api/handlers/libpod/swagger.go
+++ b/pkg/api/handlers/libpod/swagger.go
@@ -102,7 +102,7 @@ type swagNetworkRmReport struct {
// swagger:response NetworkInspectReport
type swagNetworkInspectReport struct {
// in:body
- Body []entities.NetworkInspectReport
+ Body entities.NetworkInspectReport
}
// Network list
diff --git a/pkg/api/server/register_auth.go b/pkg/api/server/register_auth.go
index 1e5474462..56e115e30 100644
--- a/pkg/api/server/register_auth.go
+++ b/pkg/api/server/register_auth.go
@@ -1,13 +1,33 @@
package server
import (
+ "net/http"
+
"github.com/containers/podman/v3/pkg/api/handlers/compat"
"github.com/gorilla/mux"
)
func (s *APIServer) registerAuthHandlers(r *mux.Router) error {
- r.Handle(VersionedPath("/auth"), s.APIHandler(compat.UnsupportedHandler))
+ // swagger:operation POST /auth compat auth
+ // ---
+ // summary: Check auth configuration
+ // tags:
+ // - system (compat)
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: body
+ // name: authConfig
+ // description: Authentication to check
+ // schema:
+ // $ref: "#/definitions/AuthConfig"
+ // responses:
+ // 200:
+ // $ref: "#/responses/SystemAuthResponse"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.Handle(VersionedPath("/auth"), s.APIHandler(compat.Auth)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
- r.Handle("/auth", s.APIHandler(compat.UnsupportedHandler))
+ r.Handle("/auth", s.APIHandler(compat.Auth)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 92efb8ef3..12fd083bb 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -226,3 +226,12 @@ type swagSystemPruneReport struct {
entities.SystemPruneReport
}
}
+
+// Auth response
+// swagger:response SystemAuthResponse
+type swagSystemAuthResponse struct {
+ // in:body
+ Body struct {
+ entities.AuthReport
+ }
+}
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index 46a3719fe..6f3aa8594 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -40,6 +40,7 @@ func Create(ctx context.Context, options *CreateOptions) (*entities.NetworkCreat
// Inspect returns low level information about a CNI network configuration
func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) ([]entities.NetworkInspectReport, error) {
var reports []entities.NetworkInspectReport
+ reports = append(reports, entities.NetworkInspectReport{})
if options == nil {
options = new(InspectOptions)
}
@@ -52,7 +53,7 @@ func Inspect(ctx context.Context, nameOrID string, options *InspectOptions) ([]e
if err != nil {
return nil, err
}
- return reports, response.Process(&reports)
+ return reports, response.Process(&reports[0])
}
// Remove deletes a defined CNI network configuration by name. The optional force boolean
diff --git a/pkg/domain/entities/system.go b/pkg/domain/entities/system.go
index a1cfb4481..4b8383613 100644
--- a/pkg/domain/entities/system.go
+++ b/pkg/domain/entities/system.go
@@ -107,3 +107,14 @@ type ComponentVersion struct {
type ListRegistriesReport struct {
Registries []string
}
+
+// swagger:model AuthConfig
+type AuthConfig struct {
+ types.AuthConfig
+}
+
+// AuthReport describes the response for authentication check
+type AuthReport struct {
+ IdentityToken string
+ Status string
+}
diff --git a/test/apiv2/30-volumes.at b/test/apiv2/30-volumes.at
index c27c638bb..1a40b3cdf 100644
--- a/test/apiv2/30-volumes.at
+++ b/test/apiv2/30-volumes.at
@@ -86,6 +86,10 @@ t DELETE libpod/volumes/foo1 404 \
.message~.* \
.response=404
+# Prune volumes - bad filter input
+t POST volumes/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+
## Prune volumes with label matching 'testlabel1=testonly'
t POST libpod/volumes/prune?filters='{"label":["testlabel1=testonly"]}' 200
t GET libpod/volumes/json?filters='{"label":["testlabel1=testonly"]}' 200 length=0
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index 98786e914..ce7ca628a 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -30,6 +30,10 @@ t GET libpod/networks/json?filters='{"name":["network1"]}' 200 \
.[0].Name=network1
t GET networks 200
+#inspect network
+t GET libpod/networks/network1/json 200 \
+ .name="network1"
+
#network list docker endpoint
t GET networks?filters='{"name":["network1","network2"]}' 200 \
length=2
diff --git a/test/apiv2/44-mounts.at b/test/apiv2/44-mounts.at
index 901245da6..d54669e7d 100644
--- a/test/apiv2/44-mounts.at
+++ b/test/apiv2/44-mounts.at
@@ -6,7 +6,7 @@ podman pull $IMAGE &>/dev/null
tmpfs_name="/mytmpfs"
t POST containers/create?name=hostconfig_test \
Image=$IMAGE \
- Cmd='["df"]' \
+ Cmd='["df","-P","'$tmpfs_name'"]' \
HostConfig='{"Binds":["/tmp/doesnotexist:/test1"]' \
TmpFs="{\"$tmpfs_name\":\"rw\"}}" \
201 \
@@ -22,5 +22,10 @@ t POST containers/${cid}/start 204
t POST containers/${cid}/wait 200
t GET containers/${cid}/logs?stdout=true 200
-like "$(<$WORKDIR/curl.result.out)" ".* ${tmpfs_name}" \
+# /logs returns application/octet-stream, which our test helper saves in
+# an outfile rather than returning in $output. That's why we can't test
+# this directly in the /logs test above; instead, we rely on knowing the
+# path to the stored results. The 'tr' is needed because there may be
+# null bytes in the outfile.
+like "$(tr -d \\0 <$WORKDIR/curl.result.out)" ".* ${tmpfs_name}" \
"'df' output includes tmpfs name"
diff --git a/test/apiv2/60-auth.at b/test/apiv2/60-auth.at
index 378955cd7..cfde519c1 100644
--- a/test/apiv2/60-auth.at
+++ b/test/apiv2/60-auth.at
@@ -5,25 +5,19 @@
start_registry
-# FIXME FIXME FIXME: remove the 'if false' for use with PR 9589
-if false; then
-
-# FIXME FIXME: please forgive the horrible POST params format; I have an
-# upcoming PR which should fix that.
-
# Test with wrong password. Confirm bad status and appropriate error message
-t POST /v1.40/auth "\"username\":\"${REGISTRY_USERNAME}\",\"password\":\"WrOnGPassWord\",\"serveraddress\":\"localhost:$REGISTRY_PORT/\"" \
+t POST /v1.40/auth username=$REGISTRY_USERNAME password=WrOnGPassWord serveraddress=localhost:$REGISTRY_PORT/ \
400 \
.Status~'.* invalid username/password'
-# Test with the right password. Confirm status message and reasonable token
-t POST /v1.40/auth "\"username\":\"${REGISTRY_USERNAME}\",\"password\":\"${REGISTRY_PASSWORD}\",\"serveraddress\":\"localhost:$REGISTRY_PORT/\"" \
+# Test with the right password. Confirm status message
+t POST /v1.40/auth username=$REGISTRY_USERNAME password=$REGISTRY_PASSWORD serveraddress=localhost:$REGISTRY_PORT/ \
200 \
.Status="Login Succeeded" \
- .IdentityToken~[a-zA-Z0-9]
-
-# FIXME: now what? Try something-something using that token?
-token=$(jq -r .IdentityToken <<<"$output")
-# ...
+ .IdentityToken=""
-fi # FIXME FIXME FIXME: remove when working
+# Same test with url scheme provided
+t POST /v1.40/auth username=$REGISTRY_USERNAME password=$REGISTRY_PASSWORD serveraddress=https://localhost:$REGISTRY_PORT/ \
+ 200 \
+ .Status="Login Succeeded" \
+ .IdentityToken=""
diff --git a/test/apiv2/rest_api/test_rest_v2_0_0.py b/test/apiv2/rest_api/test_rest_v2_0_0.py
index c0b61ea85..d7910f555 100644
--- a/test/apiv2/rest_api/test_rest_v2_0_0.py
+++ b/test/apiv2/rest_api/test_rest_v2_0_0.py
@@ -555,17 +555,6 @@ class TestApi(unittest.TestCase):
self.assertIn(name, payload["VolumesDeleted"])
self.assertGreater(payload["SpaceReclaimed"], 0)
- def test_auth_compat(self):
- r = requests.post(
- PODMAN_URL + "/v1.40/auth",
- json={
- "username": "bozo",
- "password": "wedontneednopasswords",
- "serveraddress": "https://localhost/v1.40/",
- },
- )
- self.assertEqual(r.status_code, 404, r.content)
-
def test_version(self):
r = requests.get(PODMAN_URL + "/v1.40/version")
self.assertEqual(r.status_code, 200, r.content)
diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats
index 73e807843..679cdc209 100644
--- a/test/system/065-cp.bats
+++ b/test/system/065-cp.bats
@@ -370,6 +370,7 @@ load helpers
is "${lines[0]}" "${randomcontent[0]}" "eval symlink - created container"
is "${lines[1]}" "${randomcontent[1]}" "eval symlink - created container"
run_podman rm -f cpcontainer
+ run_podman rmi $cpimage
}
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index d413b0c10..8f6cdb46b 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -241,11 +241,21 @@ EOF
build_arg_implicit+="=$arg_implicit_value"
fi
+ # FIXME FIXME FIXME: 2021-03-15: workaround for #9567 (slow ubuntu 2004):
+ # we're seeing lots of timeouts in CI. Until/unless #9567 gets fixed,
+ # let's get CI passing by extending the timeout when remote on ubuntu
+ local localtimeout=${PODMAN_TIMEOUT}
+ if is_remote; then
+ if grep -qi ubuntu /etc/os-release; then
+ localtimeout=$(( 2 * $localtimeout ))
+ fi
+ fi
+
# cd to the dir, so we test relative paths (important for podman-remote)
cd $PODMAN_TMPDIR
export arg_explicit="THIS SHOULD BE OVERRIDDEN BY COMMAND LINE!"
export arg_implicit=${arg_implicit_value}
- run_podman ${MOUNTS_CONF} build \
+ PODMAN_TIMEOUT=$localtimeout run_podman ${MOUNTS_CONF} build \
--build-arg arg_explicit=${arg_explicit_value} \
$build_arg_implicit \
--dns-search $nosuchdomain \
@@ -594,34 +604,46 @@ EOF
run_podman rmi -a --force
}
+# Caveat lector: this test was mostly copy-pasted from buildah in #9275.
+# It's not entirely clear what it's testing, or if the 'mount' section is
+# necessary.
@test "build with copy-from referencing the base image" {
- skip_if_rootless "cannot mount as rootless"
- target=busybox-derived
- target_mt=busybox-mt-derived
+ target=derived
+ target_mt=derived-mt
tmpdir=$PODMAN_TMPDIR/build-test
mkdir -p $tmpdir
+
containerfile1=$tmpdir/Containerfile1
- cat >$containerfile1 <<EOF
-FROM quay.io/libpod/busybox AS build
-RUN rm -f /bin/paste
+ cat >$containerfile1 <<EOF
+FROM $IMAGE AS build
+RUN rm -f /etc/issue
USER 1001
-COPY --from=quay.io/libpod/busybox /bin/paste /test/
+COPY --from=$IMAGE /etc/issue /test/
EOF
+
containerfile2=$tmpdir/Containerfile2
- cat >$containerfile2 <<EOF
-FROM quay.io/libpod/busybox AS test
-RUN rm -f /bin/nl
+ cat >$containerfile2 <<EOF
+FROM $IMAGE AS test
+RUN rm -f /etc/alpine-release
FROM quay.io/libpod/alpine AS final
-COPY --from=quay.io/libpod/busybox /bin/nl /test/
+COPY --from=$IMAGE /etc/alpine-release /test/
EOF
- run_podman build -t ${target} -f ${containerfile1} ${tmpdir}
- run_podman build --jobs 4 -t ${target} -f ${containerfile1} ${tmpdir}
- run_podman build -t ${target} -f ${containerfile2} ${tmpdir}
+ # Before the build, $IMAGE's base image should not be present
+ local base_image=quay.io/libpod/alpine:latest
+ run_podman 1 image exists $base_image
+
+ run_podman build --jobs 1 -t ${target} -f ${containerfile2} ${tmpdir}
run_podman build --no-cache --jobs 4 -t ${target_mt} -f ${containerfile2} ${tmpdir}
+ # After the build, the base image should exist
+ run_podman image exists $base_image
+
# (can only test locally; podman-remote has no image mount command)
- if ! is_remote; then
+ # (can also only test as root; mounting under rootless podman is too hard)
+ # We perform the test as a conditional, not a 'skip', because there's
+ # value in testing the above 'build' commands even remote & rootless.
+ if ! is_remote && ! is_rootless; then
run_podman image mount ${target}
root_single_job=$output
@@ -629,8 +651,21 @@ EOF
root_multi_job=$output
# Check that both the version with --jobs 1 and --jobs=N have the same number of files
- test $(find $root_single_job -type f | wc -l) = $(find $root_multi_job -type f | wc -l)
+ nfiles_single=$(find $root_single_job -type f | wc -l)
+ nfiles_multi=$(find $root_multi_job -type f | wc -l)
+ run_podman image umount ${target_mt}
+ run_podman image umount ${target}
+
+ is "$nfiles_single" "$nfiles_multi" \
+ "Number of files (--jobs=1) == (--jobs=4)"
+
+ # Make sure the number is reasonable
+ test "$nfiles_single" -gt 50
fi
+
+ # Clean up
+ run_podman rmi ${target_mt} ${target} ${base_image}
+ run_podman image prune -f
}
@test "podman build --logfile test" {
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 936449bdb..95113c4a6 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -31,6 +31,9 @@ verify_iid_and_name() {
invalid=$PODMAN_TMPDIR/invalid
echo "I am an invalid file and should cause a podman-load error" > $invalid
run_podman 125 load -i $invalid
+ # podman and podman-remote emit different messages; this is a common string
+ is "$output" ".*error pulling image: unable to pull .*" \
+ "load -i INVALID fails with expected diagnostic"
}
@test "podman save to pipe and load" {
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index e7904f59f..8fa96741c 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -5,6 +5,20 @@
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
+}
+
testYaml="
apiVersion: v1
kind: Pod
@@ -24,7 +38,7 @@ spec:
value: xterm
- name: container
value: podman
- image: quay.io/libpod/alpine:latest
+ image: $IMAGE
name: test
resources: {}
securityContext: