aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/completion.go27
-rw-r--r--cmd/podman/networks/list.go6
-rw-r--r--cmd/podman/secrets/list.go16
-rw-r--r--cmd/podman/volumes/list.go13
-rw-r--r--cmd/podman/volumes/prune.go3
-rw-r--r--docs/source/markdown/podman-secret-ls.1.md13
-rw-r--r--docs/tutorials/mac_win_client.md6
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--pkg/api/handlers/compat/images_build.go8
-rw-r--r--pkg/domain/filters/containers.go18
-rw-r--r--pkg/domain/filters/pods.go20
-rw-r--r--pkg/domain/infra/abi/pods.go2
-rw-r--r--pkg/network/network.go27
-rw-r--r--test/apiv2/10-images.at76
-rw-r--r--test/apiv2/35-networks.at2
-rw-r--r--test/apiv2/README.md6
-rwxr-xr-xtest/apiv2/test-apiv231
-rw-r--r--test/e2e/secret_test.go49
-rw-r--r--test/system/500-networking.bats15
-rw-r--r--utils/utils.go6
-rw-r--r--vendor/modules.txt2
22 files changed, 217 insertions, 134 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index cb3efe592..f1dea4113 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -13,7 +13,6 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
"github.com/containers/podman/v3/pkg/domain/entities"
- "github.com/containers/podman/v3/pkg/network"
"github.com/containers/podman/v3/pkg/rootless"
systemdDefine "github.com/containers/podman/v3/pkg/systemd/define"
"github.com/containers/podman/v3/pkg/util"
@@ -209,7 +208,7 @@ func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellComp
return suggestions, cobra.ShellCompDirectiveNoFileComp
}
-func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
+func getSecrets(cmd *cobra.Command, toComplete string, cType completeType) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
engine, err := setupContainerEngine(cmd)
@@ -224,7 +223,13 @@ func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCom
}
for _, s := range secrets {
- if strings.HasPrefix(s.Spec.Name, toComplete) {
+ // works the same as in getNetworks
+ if ((len(toComplete) > 1 && cType == completeDefault) ||
+ cType == completeIDs) && strings.HasPrefix(s.ID, toComplete) {
+ suggestions = append(suggestions, s.ID[0:12])
+ }
+ // include name in suggestions
+ if cType != completeIDs && strings.HasPrefix(s.Spec.Name, toComplete) {
suggestions = append(suggestions, s.Spec.Name)
}
}
@@ -256,12 +261,11 @@ func getNetworks(cmd *cobra.Command, toComplete string, cType completeType) ([]s
}
for _, n := range networks {
- id := network.GetNetworkID(n.Name)
// include ids in suggestions if cType == completeIDs or
// more then 2 chars are typed and cType == completeDefault
if ((len(toComplete) > 1 && cType == completeDefault) ||
- cType == completeIDs) && strings.HasPrefix(id, toComplete) {
- suggestions = append(suggestions, id[0:12])
+ cType == completeIDs) && strings.HasPrefix(n.ID, toComplete) {
+ suggestions = append(suggestions, n.ID[0:12])
}
// include name in suggestions
if cType != completeIDs && strings.HasPrefix(n.Name, toComplete) {
@@ -470,7 +474,7 @@ func AutocompleteSecrets(cmd *cobra.Command, args []string, toComplete string) (
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
- return getSecrets(cmd, toComplete)
+ return getSecrets(cmd, toComplete, completeDefault)
}
func AutocompleteSecretCreate(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
@@ -1283,6 +1287,15 @@ func AutocompleteVolumeFilters(cmd *cobra.Command, args []string, toComplete str
return completeKeyValues(toComplete, kv)
}
+// AutocompleteSecretFilters - Autocomplete secret ls --filter options.
+func AutocompleteSecretFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+ kv := keyValueCompletion{
+ "name=": func(s string) ([]string, cobra.ShellCompDirective) { return getSecrets(cmd, s, completeNames) },
+ "id=": func(s string) ([]string, cobra.ShellCompDirective) { return getSecrets(cmd, s, completeIDs) },
+ }
+ return completeKeyValues(toComplete, kv)
+}
+
// AutocompleteCheckpointCompressType - Autocomplete checkpoint compress type options.
// -> "gzip", "none", "zstd"
func AutocompleteCheckpointCompressType(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index 6f1a7742a..7ce566225 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -3,6 +3,7 @@ package network
import (
"fmt"
"os"
+ "sort"
"strings"
"github.com/containers/common/pkg/completion"
@@ -73,6 +74,11 @@ func networkList(cmd *cobra.Command, args []string) error {
return err
}
+ // sort the networks to make sure the order is deterministic
+ sort.Slice(responses, func(i, j int) bool {
+ return responses[i].Name < responses[j].Name
+ })
+
switch {
// quiet means we only print the network names
case networkListOptions.Quiet:
diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go
index 255d9ae1a..2074ab973 100644
--- a/cmd/podman/secrets/list.go
+++ b/cmd/podman/secrets/list.go
@@ -8,6 +8,7 @@ import (
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v3/cmd/podman/common"
+ "github.com/containers/podman/v3/cmd/podman/parse"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/pkg/domain/entities"
@@ -32,6 +33,7 @@ var (
type listFlagType struct {
format string
noHeading bool
+ filter []string
}
func init() {
@@ -44,14 +46,26 @@ func init() {
formatFlagName := "format"
flags.StringVar(&listFlag.format, formatFlagName, "{{.ID}}\t{{.Name}}\t{{.Driver}}\t{{.CreatedAt}}\t{{.UpdatedAt}}\t\n", "Format volume output using Go template")
_ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(entities.SecretInfoReport{}))
+ filterFlagName := "filter"
+ flags.StringSliceVarP(&listFlag.filter, filterFlagName, "f", []string{}, "Filter secret output")
+ _ = lsCmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompleteSecretFilters)
flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers")
}
func ls(cmd *cobra.Command, args []string) error {
- responses, err := registry.ContainerEngine().SecretList(context.Background(), entities.SecretListRequest{})
+ var err error
+ lsOpts := entities.SecretListRequest{}
+
+ lsOpts.Filters, err = parse.FilterArgumentsIntoFilters(listFlag.filter)
+ if err != nil {
+ return err
+ }
+
+ responses, err := registry.ContainerEngine().SecretList(context.Background(), lsOpts)
if err != nil {
return err
}
+
listed := make([]*entities.SecretListReport, 0, len(responses))
for _, response := range responses {
listed = append(listed, &entities.SecretListReport{
diff --git a/cmd/podman/volumes/list.go b/cmd/podman/volumes/list.go
index c372527de..97fa2c61f 100644
--- a/cmd/podman/volumes/list.go
+++ b/cmd/podman/volumes/list.go
@@ -4,11 +4,11 @@ import (
"context"
"fmt"
"os"
- "strings"
"github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/report"
"github.com/containers/podman/v3/cmd/podman/common"
+ "github.com/containers/podman/v3/cmd/podman/parse"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/libpod/define"
@@ -64,19 +64,18 @@ func init() {
}
func list(cmd *cobra.Command, args []string) error {
+ var err error
if cliOpts.Quiet && cmd.Flag("format").Changed {
return errors.New("quiet and format flags cannot be used together")
}
if len(cliOpts.Filter) > 0 {
lsOpts.Filter = make(map[string][]string)
}
- for _, f := range cliOpts.Filter {
- filterSplit := strings.SplitN(f, "=", 2)
- if len(filterSplit) < 2 {
- return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
- }
- lsOpts.Filter[filterSplit[0]] = append(lsOpts.Filter[filterSplit[0]], filterSplit[1])
+ lsOpts.Filter, err = parse.FilterArgumentsIntoFilters(cliOpts.Filter)
+ if err != nil {
+ return err
}
+
responses, err := registry.ContainerEngine().VolumeList(context.Background(), lsOpts)
if err != nil {
return err
diff --git a/cmd/podman/volumes/prune.go b/cmd/podman/volumes/prune.go
index 1f3cc6913..43b529768 100644
--- a/cmd/podman/volumes/prune.go
+++ b/cmd/podman/volumes/prune.go
@@ -58,6 +58,9 @@ func prune(cmd *cobra.Command, args []string) error {
return err
}
pruneOptions.Filters, err = parse.FilterArgumentsIntoFilters(filter)
+ if err != nil {
+ return err
+ }
if !force {
reader := bufio.NewReader(os.Stdin)
fmt.Println("WARNING! This will remove all volumes not used by at least one container. The following volumes will be removed:")
diff --git a/docs/source/markdown/podman-secret-ls.1.md b/docs/source/markdown/podman-secret-ls.1.md
index 27576f026..f33ccf41b 100644
--- a/docs/source/markdown/podman-secret-ls.1.md
+++ b/docs/source/markdown/podman-secret-ls.1.md
@@ -20,11 +20,24 @@ Format secret output using Go template.
Omit the table headings from the listing of secrets. .
+#### **--filter**, **-f**=*filter=value*
+
+Filter output based on conditions given.
+Multiple filters can be given with multiple uses of the --filter option.
+
+Valid filters are listed below:
+
+| **Filter** | **Description** |
+| ---------- | ----------------------------------------------------------------- |
+| name | [Name] Secret name (accepts regex) |
+| id | [ID] Full or partial secret ID |
+
## EXAMPLES
```
$ podman secret ls
$ podman secret ls --format "{{.Name}}"
+$ podman secret ls --filter name=confidential
```
## SEE ALSO
diff --git a/docs/tutorials/mac_win_client.md b/docs/tutorials/mac_win_client.md
index 6295eb6b2..159296d5e 100644
--- a/docs/tutorials/mac_win_client.md
+++ b/docs/tutorials/mac_win_client.md
@@ -12,11 +12,11 @@ The remote client uses a client-server model. You need Podman installed on a Lin
### Windows
-Installing the Windows Podman client begins by downloading the Podman windows installer. The windows installer is built with each Podman release and is downloadable from its [release description page](https://github.com/containers/podman/releases/latest). You can also build the installer from source using the `podman.msi` Makefile endpoint.
+Installing the Windows Podman client begins by downloading the Podman Windows installer. The Windows installer is built with each Podman release and is downloadable from its [release description page](https://github.com/containers/podman/releases/latest). The Windows installer file is named `podman-v.#.#.#.msi`, where the `#` symbols represent the version number of Podman. At the time of this writing, the file name is `podman-v3.4.4.msi`. You can also build the installer from source using the `podman.msi` Makefile endpoint.
-Once you have downloaded the installer, simply double click the installer and Podman will be installed. The path is also set to put `podman` in the default user path.
+Once you have downloaded the installer to your Windows host, simply double click the installer and Podman will be installed. The path is also set to put `podman` in the default user path.
-Podman must be run at a command prompt using the Windows ‘cmd” or powershell applications.
+Podman must be run at a command prompt using the Windows Command Prompt (`cmd.exe`) or PowerShell (`pwsh.exe`) applications.
### macOS
diff --git a/go.mod b/go.mod
index e2106eaaf..de320b894 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/digitalocean/go-qemu v0.0.0-20210209191958-152a1535e49f
github.com/docker/distribution v2.7.1+incompatible
- github.com/docker/docker v20.10.11+incompatible
+ github.com/docker/docker v20.10.12+incompatible
github.com/docker/go-connections v0.4.0
github.com/docker/go-plugins-helpers v0.0.0-20200102110956-c9a8a2d92ccc
github.com/docker/go-units v0.4.0
diff --git a/go.sum b/go.sum
index 15b0b5a37..a0d779fdf 100644
--- a/go.sum
+++ b/go.sum
@@ -344,8 +344,9 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker v20.10.11+incompatible h1:OqzI/g/W54LczvhnccGqniFoQghHx3pklbLuhfXpqGo=
github.com/docker/docker v20.10.11+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
+github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U=
+github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index a665be4fb..45e4543a9 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -621,7 +621,8 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Stream string `json:"stream,omitempty"`
Error *jsonmessage.JSONError `json:"errorDetail,omitempty"`
// NOTE: `error` is being deprecated check https://github.com/moby/moby/blob/master/pkg/jsonmessage/jsonmessage.go#L148
- ErrorMessage string `json:"error,omitempty"` // deprecate this slowly
+ ErrorMessage string `json:"error,omitempty"` // deprecate this slowly
+ Aux json.RawMessage `json:"aux,omitempty"`
}{}
select {
@@ -656,6 +657,11 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
case <-runCtx.Done():
if success {
if !utils.IsLibpodRequest(r) && !query.Quiet {
+ m.Aux = []byte(fmt.Sprintf(`{"ID":"sha256:%s"}`, imageID))
+ if err := enc.Encode(m); err != nil {
+ logrus.Warnf("failed to json encode error %v", err)
+ }
+ m.Aux = nil
m.Stream = fmt.Sprintf("Successfully built %12.12s\n", imageID)
if err := enc.Encode(m); err != nil {
logrus.Warnf("Failed to json encode error %v", err)
diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go
index bd5167fa5..60a1efb22 100644
--- a/pkg/domain/filters/containers.go
+++ b/pkg/domain/filters/containers.go
@@ -8,7 +8,6 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/pkg/network"
"github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
)
@@ -210,6 +209,15 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
return false
}, nil
case "network":
+ var inputNetNames []string
+ for _, val := range filterValues {
+ net, err := r.Network().NetworkInspect(val)
+ if err != nil {
+ // ignore not found errors
+ break
+ }
+ inputNetNames = append(inputNetNames, net.Name)
+ }
return func(c *libpod.Container) bool {
networkMode := c.NetworkMode()
// support docker like `--filter network=container:<IDorName>`
@@ -247,12 +255,8 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
return false
}
for _, net := range networks {
- netID := network.GetNetworkID(net)
- for _, val := range filterValues {
- // match by network name or id
- if val == net || val == netID {
- return true
- }
+ if util.StringInSlice(net, inputNetNames) {
+ return true
}
}
return false
diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go
index 59a6d0d78..8231dbc79 100644
--- a/pkg/domain/filters/pods.go
+++ b/pkg/domain/filters/pods.go
@@ -6,7 +6,6 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
- "github.com/containers/podman/v3/pkg/network"
"github.com/containers/podman/v3/pkg/util"
"github.com/pkg/errors"
)
@@ -14,7 +13,7 @@ import (
// GeneratePodFilterFunc takes a filter and filtervalue (key, value)
// and generates a libpod function that can be used to filter
// pods
-func GeneratePodFilterFunc(filter string, filterValues []string) (
+func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runtime) (
func(pod *libpod.Pod) bool, error) {
switch filter {
case "ctr-ids":
@@ -128,6 +127,15 @@ func GeneratePodFilterFunc(filter string, filterValues []string) (
return false
}, nil
case "network":
+ var inputNetNames []string
+ for _, val := range filterValues {
+ net, err := r.Network().NetworkInspect(val)
+ if err != nil {
+ // ignore not found errors
+ break
+ }
+ inputNetNames = append(inputNetNames, net.Name)
+ }
return func(p *libpod.Pod) bool {
infra, err := p.InfraContainer()
// no infra, quick out
@@ -140,12 +148,8 @@ func GeneratePodFilterFunc(filter string, filterValues []string) (
return false
}
for _, net := range networks {
- netID := network.GetNetworkID(net)
- for _, val := range filterValues {
- // match by network name or id
- if val == net || val == netID {
- return true
- }
+ if util.StringInSlice(net, inputNetNames) {
+ return true
}
}
return false
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index c8c7b0d9e..7bda7e994 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -325,7 +325,7 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
filters := make([]libpod.PodFilter, 0, len(options.Filters))
for k, v := range options.Filters {
- f, err := dfilters.GeneratePodFilterFunc(k, v)
+ f, err := dfilters.GeneratePodFilterFunc(k, v, ic.Libpod)
if err != nil {
return nil, err
}
diff --git a/pkg/network/network.go b/pkg/network/network.go
deleted file mode 100644
index 44132ca28..000000000
--- a/pkg/network/network.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package network
-
-import (
- "crypto/sha256"
- "encoding/hex"
- "strings"
-
- "github.com/containernetworking/cni/libcni"
-)
-
-// GetCNIPlugins returns a list of plugins that a given network
-// has in the form of a string
-func GetCNIPlugins(list *libcni.NetworkConfigList) string {
- plugins := make([]string, 0, len(list.Plugins))
- for _, plug := range list.Plugins {
- plugins = append(plugins, plug.Network.Type)
- }
- return strings.Join(plugins, ",")
-}
-
-// GetNetworkID return the network ID for a given name.
-// It is just the sha256 hash but this should be good enough.
-// The caller has to make sure it is only called with the network name.
-func GetNetworkID(name string) string {
- hash := sha256.Sum256([]byte(name))
- return hex.EncodeToString(hash[:])
-}
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 85d4d69ed..f849fc33c 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -171,70 +171,32 @@ function cleanBuildTest() {
}
CONTAINERFILE_TAR="${TMPD}/containerfile.tar"
cat > $TMPD/containerfile << EOF
-FROM quay.io/libpod/alpine_labels:latest
+FROM $IMAGE
EOF
tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null
-curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \
- -H "content-type: application/x-tar" \
- --dump-header "${TMPD}/headers.txt" \
- -o "${TMPD}/response.txt" \
- "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null
-
-BUILD_TEST_ERROR=""
-
-if ! grep -q '200 OK' "${TMPD}/headers.txt"; then
- echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/x-tar)"
- BUILD_TEST_ERROR="1"
-fi
-
-if ! grep -q 'quay.io/libpod/alpine_labels' "${TMPD}/response.txt"; then
- echo -e "${red}NOK: Image build from tar failed image name not in response"
- BUILD_TEST_ERROR="1"
-fi
-
-curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \
- -H "content-type: application/tar" \
- --dump-header "${TMPD}/headers.txt" \
- -o "${TMPD}/response.txt" \
- "http://$HOST:$PORT/v1.40/build?dockerfile=containerfile&q=true" &> /dev/null
-if ! grep -q '200 OK' "${TMPD}/headers.txt"; then
- echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/tar)"
- BUILD_TEST_ERROR="1"
-fi
-if grep -E "\"[0-9a-f]{64}\\\n\"" $(jq .stream "${TMPD}/response.txt"); then
- echo -e "${red} quiet-mode should only send image ID"
- BUILD_TEST_ERROR="1"
-fi
-
-# Yes, this is very un-RESTful re: Content-Type header ignored when compatibility endpoint used
-# See https://github.com/containers/podman/issues/11012
-curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \
- -H "content-type: application/json" \
- --dump-header "${TMPD}/headers.txt" \
- -o /dev/null \
- "http://$HOST:$PORT/v1.40/build?dockerfile=containerfile" &> /dev/null
-if ! grep -q '200 OK' "${TMPD}/headers.txt"; then
- echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/tar)"
- BUILD_TEST_ERROR="1"
-fi
-
-curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \
- -H "content-type: application/json" \
- --dump-header "${TMPD}/headers.txt" \
- -o /dev/null \
- "http://$HOST:$PORT/v1.40/libpod/build?dockerfile=containerfile" &> /dev/null
-if ! grep -q '400 Bad Request' "${TMPD}/headers.txt"; then
- echo -e "${red}NOK: Image build should have failed with 400 (wrong Content-Type)"
- BUILD_TEST_ERROR="1"
-fi
+t POST "libpod/build?dockerfile=containerfile" $CONTAINERFILE_TAR 200 \
+ .stream~"STEP 1/1: FROM $IMAGE"
+
+# With -q, all we should get is image ID. Test both libpod & compat endpoints.
+t POST "libpod/build?dockerfile=containerfile&q=true" $CONTAINERFILE_TAR 200 \
+ .stream~'^[0-9a-f]\{64\}$'
+t POST "build?dockerfile=containerfile&q=true" $CONTAINERFILE_TAR 200 \
+ .stream~'^[0-9a-f]\{64\}$'
+
+# Override content-type and confirm that libpod rejects, but compat accepts
+t POST "libpod/build?dockerfile=containerfile" $CONTAINERFILE_TAR application/json 400 \
+ .cause='Content-Type: application/json is not supported. Should be "application/x-tar"'
+t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR application/json 200 \
+ .stream~"STEP 1/1: FROM $IMAGE"
+
+# PR #12091: output from compat API must now include {"aux":{"ID":"sha..."}}
+t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR 200 \
+ '.aux|select(has("ID")).ID~^sha256:[0-9a-f]\{64\}$'
t POST libpod/images/prune 200
t POST libpod/images/prune 200 length=0 []
cleanBuildTest
-if [[ "${BUILD_TEST_ERROR}" ]]; then
- exit 1
-fi
# vim: filetype=sh
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index 713f677fa..0e2389bd5 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -7,7 +7,7 @@ t GET networks/non-existing-network 404 \
.cause='network not found'
t POST libpod/networks/create name='"network1"' 200 \
- .name=network1
+ .name=network1 \
.created~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \
# --data '{"name":"network2","subnets":[{"subnet":"10.10.254.0/24"}],"Labels":{"abc":"val"}}'
diff --git a/test/apiv2/README.md b/test/apiv2/README.md
index 19727cec7..63d1f5b13 100644
--- a/test/apiv2/README.md
+++ b/test/apiv2/README.md
@@ -60,6 +60,12 @@ of POST parameters in the form 'key=value', separated by spaces:
t POST myentrypoint name=$name badparam='["foo","bar"]' 500 ! etc...
`t` will convert the param list to JSON form for passing to the server.
A numeric status code terminates processing of POST parameters.
+** As a special case, when one POST argument is a string ending in `.tar`,
+`t` will invoke `curl` with `--data-binary @PATH` and
+set `Content-type: application/x-tar`. This is useful for `build` endpoints.
+(To override `Content-type`, simply pass along an extra string argument
+matching `application/*`):
+ t POST myentrypoint /mytmpdir/myfile.tar application/foo 400
* The final arguments are one or more expected string results. If an
argument starts with a dot, `t` will invoke `jq` on the output to
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index c644b9578..47934cca9 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -182,6 +182,7 @@ function t() {
local method=$1; shift
local path=$1; shift
local curl_args
+ local content_type="application/json"
local testname="$method $path"
# POST requests may be followed by one or more key=value pairs.
@@ -190,13 +191,21 @@ function t() {
local -a post_args
for arg; do
case "$arg" in
- *=*) post_args+=("$arg"); shift ;;
+ *=*) post_args+=("$arg");
+ shift;;
+ *.tar) curl_args="--data-binary @$arg" ;
+ content_type="application/x-tar";
+ shift;;
+ application/*) content_type="$arg";
+ shift;;
[1-9][0-9][0-9]) break;;
*) die "Internal error: invalid POST arg '$arg'" ;;
esac
done
- curl_args="-d $(jsonify ${post_args[@]})"
- testname="$testname [$curl_args]"
+ if [[ -z "$curl_args" ]]; then
+ curl_args="-d $(jsonify ${post_args[@]})"
+ testname="$testname [$curl_args]"
+ fi
fi
# entrypoint path can include a descriptive comment; strip it off
@@ -229,7 +238,7 @@ function t() {
rm -f $WORKDIR/curl.*
# -s = silent, but --write-out 'format' gives us important response data
response=$(curl -s -X $method ${curl_args} \
- -H 'Content-type: application/json' \
+ -H "Content-type: $content_type" \
--dump-header $WORKDIR/curl.headers.out \
--write-out '%{http_code}^%{content_type}^%{time_total}' \
-o $WORKDIR/curl.result.out "$url")
@@ -328,10 +337,13 @@ function start_service() {
fi
echo $WORKDIR
- $PODMAN_BIN --root $WORKDIR/server_root --syslog=true \
- system service \
- --time 15 \
- tcp:127.0.0.1:$PORT \
+ # Some tests use shortnames; force registry override to work around
+ # docker.io throttling.
+ env CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf $PODMAN_BIN \
+ --root $WORKDIR/server_root --syslog=true \
+ system service \
+ --time 15 \
+ tcp:127.0.0.1:$PORT \
&> $WORKDIR/server.log &
service_pid=$!
@@ -460,7 +472,8 @@ function wait_for_port() {
############
function podman() {
echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log
- $PODMAN_BIN --root $WORKDIR/server_root "$@" >>$WORKDIR/output.log 2>&1
+ env CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \
+ $PODMAN_BIN --root $WORKDIR/server_root "$@" >>$WORKDIR/output.log 2>&1
}
####################
diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go
index 661ebbdc0..f08638b1b 100644
--- a/test/e2e/secret_test.go
+++ b/test/e2e/secret_test.go
@@ -1,6 +1,7 @@
package integration
import (
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
@@ -145,6 +146,54 @@ var _ = Describe("Podman secret", func() {
})
+ It("podman secret ls with filters", func() {
+ secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
+ err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
+ Expect(err).To(BeNil())
+
+ secret1 := "Secret1"
+ secret2 := "Secret2"
+
+ session := podmanTest.Podman([]string{"secret", "create", secret1, secretFilePath})
+ session.WaitWithDefaultTimeout()
+ secrID1 := session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"secret", "create", secret2, secretFilePath})
+ session.WaitWithDefaultTimeout()
+ secrID2 := session.OutputToString()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"secret", "create", "Secret3", secretFilePath})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ list := podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s", secret1)})
+ list.WaitWithDefaultTimeout()
+ Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secret1))
+
+ list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s", secret2)})
+ list.WaitWithDefaultTimeout()
+ Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secret2))
+
+ list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("id=%s", secrID1)})
+ list.WaitWithDefaultTimeout()
+ Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secrID1))
+
+ list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("id=%s", secrID2)})
+ list.WaitWithDefaultTimeout()
+ Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secrID2))
+
+ list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s,name=%s", secret1, secret2)})
+ list.WaitWithDefaultTimeout()
+ Expect(list).Should(Exit(0))
+ Expect(list.OutputToStringArray()).To(HaveLen(3), ContainSubstring(secret1), ContainSubstring(secret2))
+ })
+
It("podman secret ls with Go template", func() {
secretFilePath := filepath.Join(podmanTest.TempDir, "secret")
err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755)
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index deadfa90a..4d36163d7 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -16,6 +16,21 @@ load helpers
if [[ ${output} = ${heading} ]]; then
die "network ls --noheading did not remove heading: $output"
fi
+
+ # check deterministic list order
+ local net1=a-$(random_string 10)
+ local net2=b-$(random_string 10)
+ local net3=c-$(random_string 10)
+ run_podman network create $net1
+ run_podman network create $net2
+ run_podman network create $net3
+
+ run_podman network ls --quiet
+ # just check the the order of the created networks is correct
+ # we cannot do an exact match since developer and CI systems could contain more networks
+ is "$output" ".*$net1.*$net2.*$net3.*podman.*" "networks sorted alphabetically"
+
+ run_podman network rm $net1 $net2 $net3
}
# Copied from tsweeney's https://github.com/containers/podman/issues/4827
diff --git a/utils/utils.go b/utils/utils.go
index 095370a08..241e361cd 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -11,6 +11,7 @@ import (
"strconv"
"strings"
"sync"
+ "time"
"github.com/containers/common/pkg/cgroups"
"github.com/containers/podman/v3/libpod/define"
@@ -204,8 +205,9 @@ func moveProcessToScope(pidPath, slice, scope string) error {
func MovePauseProcessToScope(pausePidPath string) {
var err error
- for i := 0; i < 3; i++ {
- r := rand.Int()
+ state := rand.New(rand.NewSource(time.Now().UnixNano()))
+ for i := 0; i < 10; i++ {
+ r := state.Int()
err = moveProcessToScope(pausePidPath, "user.slice", fmt.Sprintf("podman-pause-%d.scope", r))
if err == nil {
return
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 3109a6698..1976528fe 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -311,7 +311,7 @@ github.com/docker/distribution/registry/client/auth/challenge
github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory
-# github.com/docker/docker v20.10.11+incompatible
+# github.com/docker/docker v20.10.12+incompatible
## explicit
github.com/docker/docker/api
github.com/docker/docker/api/types