Allow '/' to prefix container names to match Docker

Fixes: https://github.com/containers/podman/issues/16663

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
Daniel J Walsh
2022-12-26 07:37:43 -05:00
parent 4a57cfb926
commit 0c94f61852
31 changed files with 68 additions and 15 deletions

View File

@ -3,6 +3,7 @@ package containers
import ( import (
"errors" "errors"
"os" "os"
"strings"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
@ -75,7 +76,7 @@ func attach(cmd *cobra.Command, args []string) error {
var name string var name string
if len(args) > 0 { if len(args) > 0 {
name = args[0] name = strings.TrimPrefix(args[0], "/")
} }
attachOpts.Stdin = os.Stdin attachOpts.Stdin = os.Stdin
if attachOpts.NoStdin { if attachOpts.NoStdin {

View File

@ -87,6 +87,7 @@ func init() {
func checkpoint(cmd *cobra.Command, args []string) error { func checkpoint(cmd *cobra.Command, args []string) error {
var errs utils.OutputErrors var errs utils.OutputErrors
args = utils.RemoveSlash(args)
podmanStart := time.Now() podmanStart := time.Now()
if cmd.Flags().Changed("compress") { if cmd.Flags().Changed("compress") {
if checkpointOptions.Export == "" { if checkpointOptions.Export == "" {

View File

@ -93,7 +93,7 @@ func init() {
} }
func commit(cmd *cobra.Command, args []string) error { func commit(cmd *cobra.Command, args []string) error {
container := args[0] container := strings.TrimPrefix(args[0], "/")
if len(args) == 2 { if len(args) == 2 {
commitOptions.ImageName = args[1] commitOptions.ImageName = args[1]
} }

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"strings"
"github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
@ -112,7 +113,7 @@ func exec(_ *cobra.Command, args []string) error {
execOpts.Cmd = args execOpts.Cmd = args
if !execOpts.Latest { if !execOpts.Latest {
execOpts.Cmd = args[1:] execOpts.Cmd = args[1:]
nameOrID = args[0] nameOrID = strings.TrimPrefix(args[0], "/")
} }
// Validate given environment variables // Validate given environment variables
execOpts.Envs = make(map[string]string) execOpts.Envs = make(map[string]string)

View File

@ -2,6 +2,7 @@ package containers
import ( import (
"context" "context"
"strings"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
@ -41,7 +42,7 @@ func exists(cmd *cobra.Command, args []string) error {
options := entities.ContainerExistsOptions{ options := entities.ContainerExistsOptions{
External: external, External: external,
} }
response, err := registry.ContainerEngine().ContainerExists(context.Background(), args[0], options) response, err := registry.ContainerEngine().ContainerExists(context.Background(), strings.TrimPrefix(args[0], "/"), options)
if err != nil { if err != nil {
return err return err
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"errors" "errors"
"os" "os"
"strings"
"github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
@ -87,5 +88,5 @@ func export(cmd *cobra.Command, args []string) error {
defer file.Close() defer file.Close()
exportOpts.Output = file exportOpts.Output = file
} }
return registry.ContainerEngine().ContainerExport(context.Background(), args[0], exportOpts) return registry.ContainerEngine().ContainerExport(context.Background(), strings.TrimPrefix(args[0], "/"), exportOpts)
} }

View File

@ -69,6 +69,7 @@ func init() {
func initContainer(cmd *cobra.Command, args []string) error { func initContainer(cmd *cobra.Command, args []string) error {
var errs utils.OutputErrors var errs utils.OutputErrors
args = utils.RemoveSlash(args)
report, err := registry.ContainerEngine().ContainerInit(registry.GetContext(), args, initOptions) report, err := registry.ContainerEngine().ContainerInit(registry.GetContext(), args, initOptions)
if err != nil { if err != nil {
return err return err

View File

@ -86,6 +86,7 @@ func kill(_ *cobra.Command, args []string) error {
err error err error
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
// Check if the signalString provided by the user is valid // Check if the signalString provided by the user is valid
// Invalid signals will return err // Invalid signals will return err
sig, err := signal.ParseSignalNameOrNumber(killOptions.Signal) sig, err := signal.ParseSignalNameOrNumber(killOptions.Signal)

View File

@ -8,6 +8,7 @@ import (
"github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/utils"
"github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/cmd/podman/validate"
"github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/util" "github.com/containers/podman/v4/pkg/util"
@ -122,6 +123,7 @@ func logsFlags(cmd *cobra.Command) {
} }
func logs(_ *cobra.Command, args []string) error { func logs(_ *cobra.Command, args []string) error {
args = utils.RemoveSlash(args)
if logsOptions.SinceRaw != "" { if logsOptions.SinceRaw != "" {
// parse time, error out if something is wrong // parse time, error out if something is wrong
since, err := util.ParseInputTime(logsOptions.SinceRaw, true) since, err := util.ParseInputTime(logsOptions.SinceRaw, true)

View File

@ -85,6 +85,8 @@ func mount(cmd *cobra.Command, args []string) error {
if len(args) > 0 && mountOpts.Latest { if len(args) > 0 && mountOpts.Latest {
return errors.New("--latest and containers cannot be used together") return errors.New("--latest and containers cannot be used together")
} }
args = utils.RemoveSlash(args)
reports, err := registry.ContainerEngine().ContainerMount(registry.GetContext(), args, mountOpts) reports, err := registry.ContainerEngine().ContainerMount(registry.GetContext(), args, mountOpts)
if err != nil { if err != nil {
return err return err

View File

@ -90,6 +90,7 @@ func pause(cmd *cobra.Command, args []string) error {
var ( var (
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
for _, cidFile := range pauseCidFiles { for _, cidFile := range pauseCidFiles {
content, err := os.ReadFile(cidFile) content, err := os.ReadFile(cidFile)

View File

@ -80,7 +80,7 @@ func port(_ *cobra.Command, args []string) error {
return errors.New("you must supply a running container name or id") return errors.New("you must supply a running container name or id")
} }
if !portOpts.Latest && len(args) >= 1 { if !portOpts.Latest && len(args) >= 1 {
container = args[0] container = strings.TrimPrefix(args[0], "/")
} }
port := "" port := ""
if len(args) > 2 { if len(args) > 2 {

View File

@ -46,7 +46,7 @@ func init() {
_ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePruneFilters) _ = pruneCommand.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePruneFilters)
} }
func prune(cmd *cobra.Command, args []string) error { func prune(cmd *cobra.Command, _ []string) error {
var ( var (
pruneOptions = entities.ContainerPruneOptions{} pruneOptions = entities.ContainerPruneOptions{}
err error err error

View File

@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/cmd/podman/utils"
"github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -47,6 +48,7 @@ func rename(cmd *cobra.Command, args []string) error {
if len(args) > 2 { if len(args) > 2 {
return errors.New("must provide at least two arguments to rename") return errors.New("must provide at least two arguments to rename")
} }
args = utils.RemoveSlash(args)
renameOpts := entities.ContainerRenameOptions{ renameOpts := entities.ContainerRenameOptions{
NewName: args[1], NewName: args[1],
} }

View File

@ -99,6 +99,7 @@ func restart(cmd *cobra.Command, args []string) error {
var ( var (
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
if cmd.Flag("time").Changed { if cmd.Flag("time").Changed {
restartOpts.Timeout = &restartTimeout restartOpts.Timeout = &restartTimeout

View File

@ -96,6 +96,8 @@ func restore(cmd *cobra.Command, args []string) error {
e error e error
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
podmanStart := time.Now() podmanStart := time.Now()
if rootless.IsRootless() { if rootless.IsRootless() {
return fmt.Errorf("restoring a container requires root") return fmt.Errorf("restoring a container requires root")

View File

@ -132,7 +132,7 @@ func rm(cmd *cobra.Command, args []string) error {
rmOptions.Depend = true rmOptions.Depend = true
} }
return removeContainers(args, rmOptions, true) return removeContainers(utils.RemoveSlash(args), rmOptions, true)
} }
// removeContainers will remove the specified containers (names or IDs). // removeContainers will remove the specified containers (names or IDs).

View File

@ -3,6 +3,7 @@ package containers
import ( import (
"context" "context"
"os" "os"
"strings"
"github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/completion"
@ -95,5 +96,5 @@ func runlabel(cmd *cobra.Command, args []string) error {
return err return err
} }
} }
return registry.ContainerEngine().ContainerRunlabel(context.Background(), args[0], args[1], args[2:], runlabelOptions.ContainerRunlabelOptions) return registry.ContainerEngine().ContainerRunlabel(context.Background(), strings.TrimPrefix(args[0], "/"), args[1], args[2:], runlabelOptions.ContainerRunlabelOptions)
} }

View File

@ -124,7 +124,7 @@ func start(cmd *cobra.Command, args []string) error {
startOptions.Stdout = os.Stdout startOptions.Stdout = os.Stdout
} }
containers := args containers := utils.RemoveSlash(args)
for _, f := range filters { for _, f := range filters {
split := strings.SplitN(f, "=", 2) split := strings.SplitN(f, "=", 2)
if len(split) < 2 { if len(split) < 2 {

View File

@ -10,6 +10,7 @@ import (
"github.com/containers/common/pkg/report" "github.com/containers/common/pkg/report"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
putils "github.com/containers/podman/v4/cmd/podman/utils"
"github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/cmd/podman/validate"
"github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities"
@ -120,6 +121,7 @@ func stats(cmd *cobra.Command, args []string) error {
Stream: !statsOptions.NoStream, Stream: !statsOptions.NoStream,
Interval: statsOptions.Interval, Interval: statsOptions.Interval,
} }
args = putils.RemoveSlash(args)
statsChan, err := registry.ContainerEngine().ContainerStats(registry.Context(), args, opts) statsChan, err := registry.ContainerEngine().ContainerStats(registry.Context(), args, opts)
if err != nil { if err != nil {
return err return err

View File

@ -101,6 +101,8 @@ func stop(cmd *cobra.Command, args []string) error {
var ( var (
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
if cmd.Flag("time").Changed { if cmd.Flag("time").Changed {
stopOptions.Timeout = &stopTimeout stopOptions.Timeout = &stopTimeout
} }

View File

@ -94,7 +94,7 @@ func top(cmd *cobra.Command, args []string) error {
if topOptions.Latest { if topOptions.Latest {
topOptions.Descriptors = args topOptions.Descriptors = args
} else { } else {
topOptions.NameOrID = args[0] topOptions.NameOrID = strings.TrimPrefix(args[0], "/")
topOptions.Descriptors = args[1:] topOptions.Descriptors = args[1:]
} }

View File

@ -78,6 +78,7 @@ func init() {
func unmount(cmd *cobra.Command, args []string) error { func unmount(cmd *cobra.Command, args []string) error {
var errs utils.OutputErrors var errs utils.OutputErrors
args = utils.RemoveSlash(args)
reports, err := registry.ContainerEngine().ContainerUnmount(registry.GetContext(), args, unmountOpts) reports, err := registry.ContainerEngine().ContainerUnmount(registry.GetContext(), args, unmountOpts)
if err != nil { if err != nil {
return err return err

View File

@ -91,6 +91,8 @@ func unpause(cmd *cobra.Command, args []string) error {
var ( var (
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
if rootless.IsRootless() && !registry.IsRemote() { if rootless.IsRootless() && !registry.IsRemote() {
cgroupv2, _ := cgroups.IsCgroup2UnifiedMode() cgroupv2, _ := cgroups.IsCgroup2UnifiedMode()
if !cgroupv2 { if !cgroupv2 {

View File

@ -3,6 +3,7 @@ package containers
import ( import (
"context" "context"
"fmt" "fmt"
"strings"
"github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
@ -71,7 +72,7 @@ func update(cmd *cobra.Command, args []string) error {
} }
opts := &entities.ContainerUpdateOptions{ opts := &entities.ContainerUpdateOptions{
NameOrID: args[0], NameOrID: strings.TrimPrefix(args[0], "/"),
Specgen: s, Specgen: s,
} }
rep, err := registry.ContainerEngine().ContainerUpdate(context.Background(), opts) rep, err := registry.ContainerEngine().ContainerUpdate(context.Background(), opts)

View File

@ -80,6 +80,7 @@ func wait(cmd *cobra.Command, args []string) error {
err error err error
errs utils.OutputErrors errs utils.OutputErrors
) )
args = utils.RemoveSlash(args)
if waitOptions.Interval, err = time.ParseDuration(waitInterval); err != nil { if waitOptions.Interval, err = time.ParseDuration(waitInterval); err != nil {
var err1 error var err1 error
if waitOptions.Interval, err1 = time.ParseDuration(waitInterval + "ms"); err1 != nil { if waitOptions.Interval, err1 = time.ParseDuration(waitInterval + "ms"); err1 != nil {

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"strings"
"github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/define"
@ -139,3 +140,11 @@ func IsCheckpointImage(ctx context.Context, namesOrIDs []string) (bool, error) {
} }
return true, nil return true, nil
} }
func RemoveSlash(input []string) []string {
output := make([]string, 0, len(input))
for _, in := range input {
output = append(output, strings.TrimPrefix(in, "/"))
}
return output
}

View File

@ -6,6 +6,7 @@ import (
"net" "net"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"syscall" "syscall"
"github.com/containers/buildah/pkg/parse" "github.com/containers/buildah/pkg/parse"
@ -776,6 +777,7 @@ func WithName(name string) CtrCreateOption {
return define.ErrCtrFinalized return define.ErrCtrFinalized
} }
name = strings.TrimPrefix(name, "/")
// Check the name against a regex // Check the name against a regex
if !define.NameRegex.MatchString(name) { if !define.NameRegex.MatchString(name) {
return define.RegexError return define.RegexError

View File

@ -118,6 +118,7 @@ func (r *Runtime) RenameContainer(ctx context.Context, ctr *Container, newName s
return nil, err return nil, err
} }
newName = strings.TrimPrefix(newName, "/")
if newName == "" || !define.NameRegex.MatchString(newName) { if newName == "" || !define.NameRegex.MatchString(newName) {
return nil, define.RegexError return nil, define.RegexError
} }

View File

@ -30,7 +30,11 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
case "name": case "name":
// we only have to match one name // we only have to match one name
return func(c *libpod.Container) bool { return func(c *libpod.Container) bool {
return util.StringMatchRegexSlice(c.Name(), filterValues) var filters []string
for _, f := range filterValues {
filters = append(filters, strings.ReplaceAll(f, "/", ""))
}
return util.StringMatchRegexSlice(c.Name(), filters)
}, nil }, nil
case "exited": case "exited":
var exitCodes []int32 var exitCodes []int32

View File

@ -174,7 +174,7 @@ echo $rand | 0 | $rand
run_podman 1 image exists $NONLOCAL_IMAGE run_podman 1 image exists $NONLOCAL_IMAGE
# Run a container, without --rm; this should block subsequent --rmi # Run a container, without --rm; this should block subsequent --rmi
run_podman run --name keepme $NONLOCAL_IMAGE /bin/true run_podman run --name /keepme $NONLOCAL_IMAGE /bin/true
run_podman image exists $NONLOCAL_IMAGE run_podman image exists $NONLOCAL_IMAGE
# Now try running with --rmi : it should succeed, but not remove the image # Now try running with --rmi : it should succeed, but not remove the image
@ -182,7 +182,7 @@ echo $rand | 0 | $rand
run_podman image exists $NONLOCAL_IMAGE run_podman image exists $NONLOCAL_IMAGE
# Remove the stray container, and run one more time with --rmi. # Remove the stray container, and run one more time with --rmi.
run_podman rm keepme run_podman rm /keepme
run_podman run --rmi --rm $NONLOCAL_IMAGE /bin/true run_podman run --rmi --rm $NONLOCAL_IMAGE /bin/true
run_podman 1 image exists $NONLOCAL_IMAGE run_podman 1 image exists $NONLOCAL_IMAGE
} }
@ -964,4 +964,14 @@ EOF
CONTAINERS_CONF="$containersconf" run_podman 1 run --rm --read-only-tmpfs=false $IMAGE touch /tmp/testro CONTAINERS_CONF="$containersconf" run_podman 1 run --rm --read-only-tmpfs=false $IMAGE touch /tmp/testro
} }
@test "podman run bad --name" {
randomname=$(random_string 30)
run_podman 125 create --name "$randomname/bad" $IMAGE
run_podman create --name "/$randomname" $IMAGE
run_podman ps -a --filter name="^/$randomname$" --format '{{ .Names }}'
is $output "$randomname" "Should be able to find container by name"
run_podman rm "/$randomname"
run_podman 125 create --name "$randomname/" $IMAGE
}
# vim: filetype=sh # vim: filetype=sh