diff options
31 files changed, 154 insertions, 89 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index c29218d01..285cab1b9 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -7,6 +7,7 @@ import ( "reflect" "strconv" "strings" + "unicode" libimageDefine "github.com/containers/common/libimage/define" "github.com/containers/common/libnetwork/types" @@ -17,6 +18,7 @@ import ( "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/rootless" + "github.com/containers/podman/v4/pkg/signal" systemdDefine "github.com/containers/podman/v4/pkg/systemd/define" "github.com/containers/podman/v4/pkg/util" "github.com/spf13/cobra" @@ -601,7 +603,9 @@ func AutocompleteRunlabelCommand(cmd *cobra.Command, args []string, toComplete s return nil, cobra.ShellCompDirectiveNoFileComp } if len(args) == 0 { - // FIXME: What labels can we recommend here? + // This is unfortunate because the argument order is label followed by image. + // If it would be the other way around we could inspect the first arg and get + // all labels from it to suggest them. return nil, cobra.ShellCompDirectiveNoFileComp } if len(args) == 1 { @@ -806,8 +810,7 @@ func AutocompleteLogDriver(cmd *cobra.Command, args []string, toComplete string) // AutocompleteLogOpt - Autocomplete log-opt options. // -> "path=", "tag=" func AutocompleteLogOpt(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // FIXME: are these the only one? the man page states these but in the current shell completion they are more options - logOptions := []string{"path=", "tag="} + logOptions := []string{"path=", "tag=", "max-size="} if strings.HasPrefix(toComplete, "path=") { return nil, cobra.ShellCompDirectiveDefault } @@ -846,10 +849,26 @@ func AutocompleteSecurityOption(cmd *cobra.Command, args []string, toComplete st } // AutocompleteStopSignal - Autocomplete stop signal options. -// -> "SIGHUP", "SIGINT", "SIGKILL", "SIGTERM" +// Autocompletes signals both lower or uppercase depending on the user input. func AutocompleteStopSignal(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - // FIXME: add more/different signals? - stopSignals := []string{"SIGHUP", "SIGINT", "SIGKILL", "SIGTERM"} + // convertCase will convert a string to lowercase only if the user input is lowercase + convertCase := func(s string) string { return s } + if len(toComplete) > 0 && unicode.IsLower(rune(toComplete[0])) { + convertCase = strings.ToLower + } + + prefix := "" + // if input starts with "SI" we have to add SIG in front + // since the signal map does not have this prefix but the option + // allows signals with and without SIG prefix + if strings.HasPrefix(toComplete, convertCase("SI")) { + prefix = "SIG" + } + + stopSignals := make([]string, 0, len(signal.SignalMap)) + for sig := range signal.SignalMap { + stopSignals = append(stopSignals, convertCase(prefix+sig)) + } return stopSignals, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 29e138e30..c62ddd6eb 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -9,6 +9,7 @@ import ( "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/image/v5/transports/alltransports" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/cmd/podman/common" @@ -116,7 +117,7 @@ func create(cmd *cobra.Command, args []string) error { if !cmd.Flags().Changed("pod") { return errors.New("must specify pod value with init-ctr") } - if !util.StringInSlice(initctr, []string{define.AlwaysInitContainer, define.OneShotInitContainer}) { + if !cutil.StringInSlice(initctr, []string{define.AlwaysInitContainer, define.OneShotInitContainer}) { return errors.Errorf("init-ctr value must be '%s' or '%s'", define.AlwaysInitContainer, define.OneShotInitContainer) } cliVals.InitContainerType = initctr diff --git a/cmd/podman/images/save.go b/cmd/podman/images/save.go index 3394c2e99..d85d688ee 100644 --- a/cmd/podman/images/save.go +++ b/cmd/podman/images/save.go @@ -6,12 +6,12 @@ import ( "strings" "github.com/containers/common/pkg/completion" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/parse" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/term" diff --git a/cmd/podman/images/trust_set.go b/cmd/podman/images/trust_set.go index fff035d12..f4ff0cffc 100644 --- a/cmd/podman/images/trust_set.go +++ b/cmd/podman/images/trust_set.go @@ -5,10 +5,10 @@ import ( "regexp" "github.com/containers/common/pkg/completion" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" "github.com/spf13/cobra" ) diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go index 1275e65dc..a89448275 100644 --- a/cmd/podman/pods/ps.go +++ b/cmd/podman/pods/ps.go @@ -24,7 +24,7 @@ var ( // Command: podman pod _ps_ psCmd = &cobra.Command{ - Use: "ps [options]", + Use: "ps [options]", Aliases: []string{"ls", "list"}, Short: "List pods", Long: psDescription, diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 2bd4fa723..1892ff9f7 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -423,7 +423,7 @@ func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { // -s is deprecated due to conflict with -s on subcommands storageDriverFlagName := "storage-driver" pFlags.StringVar(&opts.StorageDriver, storageDriverFlagName, "", "Select which storage driver is used to manage storage of images and containers") - _ = cmd.RegisterFlagCompletionFunc(storageDriverFlagName, completion.AutocompleteNone) //TODO: what can we recommend here? + _ = cmd.RegisterFlagCompletionFunc(storageDriverFlagName, completion.AutocompleteNone) tmpdirFlagName := "tmpdir" pFlags.StringVar(&opts.Engine.TmpDir, tmpdirFlagName, "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n") diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index d7683cce9..82e5fa992 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -36,6 +36,7 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/subscriptions" "github.com/containers/common/pkg/umask" + cutil "github.com/containers/common/pkg/util" is "github.com/containers/image/v5/storage" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" @@ -393,7 +394,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { overrides := c.getUserOverrides() execUser, err := lookup.GetUserGroupInfo(c.state.Mountpoint, c.config.User, overrides) if err != nil { - if util.StringInSlice(c.config.User, c.config.HostUsers) { + if cutil.StringInSlice(c.config.User, c.config.HostUsers) { execUser, err = lookupHostUser(c.config.User) } if err != nil { @@ -2389,7 +2390,7 @@ func (c *Container) generateResolvConf() error { } if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 { - if !util.StringInSlice(".", c.config.DNSSearch) { + if !cutil.StringInSlice(".", c.config.DNSSearch) { search = append(search, c.runtime.config.Containers.DNSSearches...) search = append(search, c.config.DNSSearch...) } diff --git a/libpod/kube.go b/libpod/kube.go index 5a5fe9d35..20c4612d1 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -14,6 +14,7 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/env" v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" @@ -515,7 +516,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod, podDNS.Nameservers = make([]string, 0) } for _, s := range servers { - if !util.StringInSlice(s, podDNS.Nameservers) { // only append if it does not exist + if !cutil.StringInSlice(s, podDNS.Nameservers) { // only append if it does not exist podDNS.Nameservers = append(podDNS.Nameservers, s) } } @@ -526,7 +527,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod, podDNS.Searches = make([]string, 0) } for _, d := range domains { - if !util.StringInSlice(d, podDNS.Searches) { // only append if it does not exist + if !cutil.StringInSlice(d, podDNS.Searches) { // only append if it does not exist podDNS.Searches = append(podDNS.Searches, d) } } @@ -543,7 +544,7 @@ func simplePodWithV1Containers(ctx context.Context, ctrs []*Container) (*v1.Pod, podName := removeUnderscores(ctrs[0].Name()) // Check if the pod name and container name will end up conflicting // Append -pod if so - if util.StringInSlice(podName, ctrNames) { + if cutil.StringInSlice(podName, ctrNames) { podName += "-pod" } @@ -824,7 +825,7 @@ func libpodMountsToKubeVolumeMounts(c *Container) ([]v1.VolumeMount, []v1.Volume // generateKubePersistentVolumeClaim converts a ContainerNamedVolume to a Kubernetes PersistentVolumeClaim func generateKubePersistentVolumeClaim(v *ContainerNamedVolume) (v1.VolumeMount, v1.Volume) { - ro := util.StringInSlice("ro", v.Options) + ro := cutil.StringInSlice("ro", v.Options) // To avoid naming conflicts with any host path mounts, add a unique suffix to the volume's name. name := v.Name + "-pvc" @@ -857,7 +858,7 @@ func generateKubeVolumeMount(m specs.Mount) (v1.VolumeMount, v1.Volume, error) { name += "-host" vm.Name = name vm.MountPath = m.Destination - if util.StringInSlice("ro", m.Options) { + if cutil.StringInSlice("ro", m.Options) { vm.ReadOnly = true } @@ -915,7 +916,7 @@ func determineCapAddDropFromCapabilities(defaultCaps, containerCaps []string) *v // Find caps in the defaultCaps but not in the container's // those indicate a dropped cap for _, capability := range defaultCaps { - if !util.StringInSlice(capability, containerCaps) { + if !cutil.StringInSlice(capability, containerCaps) { if _, ok := dedupDrop[capability]; !ok { drop = append(drop, v1.Capability(capability)) dedupDrop[capability] = true @@ -925,7 +926,7 @@ func determineCapAddDropFromCapabilities(defaultCaps, containerCaps []string) *v // Find caps in the container but not in the defaults; those indicate // an added cap for _, capability := range containerCaps { - if !util.StringInSlice(capability, defaultCaps) { + if !cutil.StringInSlice(capability, defaultCaps) { if _, ok := dedupAdd[capability]; !ok { add = append(add, v1.Capability(capability)) dedupAdd[capability] = true diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 0c124cf0b..73e64530e 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -25,13 +25,13 @@ import ( "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/machine" "github.com/containers/common/pkg/netns" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/pkg/namespaces" "github.com/containers/podman/v4/pkg/resolvconf" "github.com/containers/podman/v4/pkg/rootless" - "github.com/containers/podman/v4/pkg/util" "github.com/containers/podman/v4/utils" "github.com/containers/storage/pkg/lockfile" spec "github.com/opencontainers/runtime-spec/specs-go" diff --git a/libpod/options.go b/libpod/options.go index feb89510f..a02c05537 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -12,6 +12,7 @@ import ( nettypes "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/secrets" + cutil "github.com/containers/common/pkg/util" "github.com/containers/image/v5/manifest" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/libpod/define" @@ -605,7 +606,7 @@ func WithSdNotifyMode(mode string) CtrCreateOption { } // verify values - if len(mode) > 0 && !util.StringInSlice(strings.ToLower(mode), SdNotifyModeValues) { + if len(mode) > 0 && !cutil.StringInSlice(strings.ToLower(mode), SdNotifyModeValues) { return errors.Wrapf(define.ErrInvalidArg, "--sdnotify values must be one of %q", strings.Join(SdNotifyModeValues, ", ")) } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 2eaa77572..bdfc102ba 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -13,6 +13,7 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/libpod/events" "github.com/containers/podman/v4/libpod/shutdown" @@ -246,7 +247,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai for _, opts := range ctr.config.Networks { if opts.InterfaceName != "" { // check that no name is assigned to more than network - if util.StringInSlice(opts.InterfaceName, usedIfNames) { + if cutil.StringInSlice(opts.InterfaceName, usedIfNames) { return nil, errors.Errorf("network interface name %q is already assigned to another network", opts.InterfaceName) } usedIfNames = append(usedIfNames, opts.InterfaceName) @@ -262,7 +263,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai if opts.InterfaceName == "" { for i < 100000 { ifName := fmt.Sprintf("eth%d", i) - if !util.StringInSlice(ifName, usedIfNames) { + if !cutil.StringInSlice(ifName, usedIfNames) { opts.InterfaceName = ifName usedIfNames = append(usedIfNames, ifName) break diff --git a/libpod/runtime_pod.go b/libpod/runtime_pod.go index dca0ffc8a..ee3d40484 100644 --- a/libpod/runtime_pod.go +++ b/libpod/runtime_pod.go @@ -4,8 +4,8 @@ import ( "context" "time" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" ) diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index bcd102901..0a1bc941d 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -674,15 +674,17 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { enc := json.NewEncoder(body) enc.SetEscapeHTML(true) + var stepErrors []string for { - m := struct { + type BuildResponse struct { 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 Aux json.RawMessage `json:"aux,omitempty"` - }{} + } + m := BuildResponse{} select { case e := <-stdout.Chan(): @@ -698,12 +700,27 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } flush() case e := <-auxout.Chan(): - m.Stream = string(e) - if err := enc.Encode(m); err != nil { - stderr.Write([]byte(err.Error())) + if !query.Quiet { + m.Stream = string(e) + if err := enc.Encode(m); err != nil { + stderr.Write([]byte(err.Error())) + } + flush() + } else { + stepErrors = append(stepErrors, string(e)) } - flush() case e := <-stderr.Chan(): + // Docker-API Compat parity : Build failed so + // output all step errors irrespective of quiet + // flag. + for _, stepError := range stepErrors { + t := BuildResponse{} + t.Stream = stepError + if err := enc.Encode(t); err != nil { + stderr.Write([]byte(err.Error())) + } + flush() + } m.ErrorMessage = string(e) m.Error = &jsonmessage.JSONError{ Message: m.ErrorMessage, diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 3e5b9cad9..e2ab8d70c 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -6,6 +6,7 @@ import ( "strings" "time" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/util" @@ -257,7 +258,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo return false } for _, net := range networks { - if util.StringInSlice(net, inputNetNames) { + if cutil.StringInSlice(net, inputNetNames) { return true } } diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go index e22480006..c2ed359f5 100644 --- a/pkg/domain/filters/pods.go +++ b/pkg/domain/filters/pods.go @@ -4,6 +4,7 @@ import ( "strconv" "strings" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/util" @@ -57,7 +58,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti }, nil case "ctr-status": for _, filterValue := range filterValues { - if !util.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { + if !cutil.StringInSlice(filterValue, []string{"created", "running", "paused", "stopped", "exited", "unknown"}) { return nil, errors.Errorf("%s is not a valid status", filterValue) } } @@ -94,7 +95,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti }, nil case "status": for _, filterValue := range filterValues { - if !util.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { + if !cutil.StringInSlice(filterValue, []string{"stopped", "running", "paused", "exited", "dead", "created", "degraded"}) { return nil, errors.Errorf("%s is not a valid pod status", filterValue) } } @@ -150,7 +151,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti return false } for _, net := range networks { - if util.StringInSlice(net, inputNetNames) { + if cutil.StringInSlice(net, inputNetNames) { return true } } diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go index 910008fc7..47f7917f4 100644 --- a/pkg/domain/infra/abi/network.go +++ b/pkg/domain/infra/abi/network.go @@ -5,9 +5,9 @@ import ( "github.com/containers/common/libnetwork/types" netutil "github.com/containers/common/libnetwork/util" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" ) diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index 10f3e70b1..2ce190464 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -10,6 +10,7 @@ import ( "github.com/containers/common/pkg/cgroups" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/domain/entities/reports" @@ -307,7 +308,7 @@ func (ic *ContainerEngine) SystemDf(ctx context.Context, options entities.System reclaimableSize += volSize } for _, viu := range inUse { - if util.StringInSlice(viu, runningContainers) { + if cutil.StringInSlice(viu, runningContainers) { consInUse++ } } diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go index 0bc867047..1c8c6ac81 100644 --- a/pkg/machine/e2e/list_test.go +++ b/pkg/machine/e2e/list_test.go @@ -3,7 +3,7 @@ package e2e import ( "strings" - "github.com/containers/buildah/util" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/cmd/podman/machine" jsoniter "github.com/json-iterator/go" . "github.com/onsi/ginkgo" diff --git a/pkg/signal/signal_common.go b/pkg/signal/signal_common.go index 5ea67843a..fe5a76dae 100644 --- a/pkg/signal/signal_common.go +++ b/pkg/signal/signal_common.go @@ -17,7 +17,7 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) { } return syscall.Signal(s), nil } - sig, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] + sig, ok := SignalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")] if !ok { return -1, fmt.Errorf("invalid signal: %s", rawSignal) } @@ -32,7 +32,7 @@ func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) { if err == nil { return s, nil } - for k, v := range signalMap { + for k, v := range SignalMap { if k == strings.ToUpper(basename) { return v, nil } diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index 21e09c9fe..a114ea019 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -23,8 +23,8 @@ const ( SIGWINCH = syscall.SIGWINCH // For cross-compilation with Windows ) -// signalMap is a map of Linux signals. -var signalMap = map[string]syscall.Signal{ +// SignalMap is a map of Linux signals. +var SignalMap = map[string]syscall.Signal{ "ABRT": unix.SIGABRT, "ALRM": unix.SIGALRM, "BUS": unix.SIGBUS, @@ -94,8 +94,8 @@ var signalMap = map[string]syscall.Signal{ // CatchAll catches all signals and relays them to the specified channel. func CatchAll(sigc chan os.Signal) { - handledSigs := make([]os.Signal, 0, len(signalMap)) - for _, s := range signalMap { + handledSigs := make([]os.Signal, 0, len(SignalMap)) + for _, s := range SignalMap { handledSigs = append(handledSigs, s) } signal.Notify(sigc, handledSigs...) diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go index 52b07aaf4..9021a10e7 100644 --- a/pkg/signal/signal_linux_mipsx.go +++ b/pkg/signal/signal_linux_mipsx.go @@ -24,8 +24,8 @@ const ( SIGWINCH = syscall.SIGWINCH ) -// signalMap is a map of Linux signals. -var signalMap = map[string]syscall.Signal{ +// SignalMap is a map of Linux signals. +var SignalMap = map[string]syscall.Signal{ "ABRT": unix.SIGABRT, "ALRM": unix.SIGALRM, "BUS": unix.SIGBUS, @@ -95,8 +95,8 @@ var signalMap = map[string]syscall.Signal{ // CatchAll catches all signals and relays them to the specified channel. func CatchAll(sigc chan os.Signal) { - handledSigs := make([]os.Signal, 0, len(signalMap)) - for _, s := range signalMap { + handledSigs := make([]os.Signal, 0, len(SignalMap)) + for _, s := range SignalMap { handledSigs = append(handledSigs, s) } signal.Notify(sigc, handledSigs...) diff --git a/pkg/signal/signal_unix.go b/pkg/signal/signal_unix.go index c0aa62d21..0f43e21b7 100644 --- a/pkg/signal/signal_unix.go +++ b/pkg/signal/signal_unix.go @@ -16,12 +16,12 @@ const ( SIGWINCH = syscall.SIGWINCH ) -// signalMap is a map of Linux signals. +// SignalMap is a map of Linux signals. // These constants are sourced from the Linux version of golang.org/x/sys/unix // (I don't see much risk of this changing). // This should work as long as Podman only runs containers on Linux, which seems // a safe assumption for now. -var signalMap = map[string]syscall.Signal{ +var SignalMap = map[string]syscall.Signal{ "ABRT": syscall.Signal(0x6), "ALRM": syscall.Signal(0xe), "BUS": syscall.Signal(0x7), diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index d8bba7c90..9d0cee317 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -16,12 +16,12 @@ const ( SIGWINCH = syscall.Signal(0xff) ) -// signalMap is a map of Linux signals. +// SignalMap is a map of Linux signals. // These constants are sourced from the Linux version of golang.org/x/sys/unix // (I don't see much risk of this changing). // This should work as long as Podman only runs containers on Linux, which seems // a safe assumption for now. -var signalMap = map[string]syscall.Signal{ +var SignalMap = map[string]syscall.Signal{ "ABRT": syscall.Signal(0x6), "ALRM": syscall.Signal(0xe), "BUS": syscall.Signal(0x7), diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index 355fbc368..532a2094f 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -4,9 +4,9 @@ import ( "strconv" "strings" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" - "github.com/containers/podman/v4/pkg/util" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index f37d79798..689c740f0 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -16,6 +16,7 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/parse" "github.com/containers/common/pkg/secrets" + cutil "github.com/containers/common/pkg/util" "github.com/containers/image/v5/manifest" "github.com/containers/podman/v4/libpod/define" ann "github.com/containers/podman/v4/pkg/annotations" @@ -356,7 +357,7 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener // a selinux mount option exists for it for k, v := range opts.Annotations { // Make sure the z/Z option is not already there (from editing the YAML) - if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !util.StringInSlice("z", options) && !util.StringInSlice("Z", options) { + if strings.Replace(k, define.BindMountPrefix, "", 1) == volumeSource.Source && !cutil.StringInSlice("z", options) && !cutil.StringInSlice("Z", options) { options = append(options, v) } } diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go index bec548d3b..4243630e2 100644 --- a/pkg/specgen/generate/ports.go +++ b/pkg/specgen/generate/ports.go @@ -10,9 +10,9 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/podman/v4/utils" + "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/pkg/specgen" "github.com/containers/podman/v4/pkg/specgenutil" - "github.com/containers/podman/v4/pkg/util" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go index ec52164ab..7268ec318 100644 --- a/pkg/specgen/generate/security.go +++ b/pkg/specgen/generate/security.go @@ -7,6 +7,7 @@ import ( "github.com/containers/common/pkg/apparmor" "github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/config" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/specgen" @@ -120,7 +121,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, // capabilities, required to run the container. var capsRequiredRequested []string for key, val := range s.Labels { - if util.StringInSlice(key, capabilities.ContainerImageLabels) { + if cutil.StringInSlice(key, capabilities.ContainerImageLabels) { capsRequiredRequested = strings.Split(val, ",") } } @@ -132,7 +133,7 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator, } // Verify all capRequired are in the capList for _, cap := range capsRequired { - if !util.StringInSlice(cap, caplist) { + if !cutil.StringInSlice(cap, caplist) { privCapsRequired = append(privCapsRequired, cap) } } diff --git a/pkg/specgen/namespaces.go b/pkg/specgen/namespaces.go index 7a7ca2706..5a3b94ca4 100644 --- a/pkg/specgen/namespaces.go +++ b/pkg/specgen/namespaces.go @@ -8,6 +8,7 @@ import ( "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/cgroups" + cutil "github.com/containers/common/pkg/util" "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/rootless" "github.com/containers/podman/v4/pkg/util" @@ -472,7 +473,7 @@ func ParseNetworkFlag(networks []string) (Namespace, map[string]types.PerNetwork if parts[0] == "" { return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "network name cannot be empty") } - if util.StringInSlice(parts[0], []string{string(Bridge), string(Slirp), string(FromPod), string(NoNetwork), + if cutil.StringInSlice(parts[0], []string{string(Bridge), string(Slirp), string(FromPod), string(NoNetwork), string(Default), string(Private), string(Path), string(FromContainer), string(Host)}) { return toReturn, nil, nil, errors.Wrapf(define.ErrInvalidArg, "can only set extra network names, selected mode %s conflicts with bridge", parts[0]) } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index a0bf8b50d..1b7663330 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -17,6 +17,7 @@ import ( "github.com/BurntSushi/toml" "github.com/containers/common/pkg/config" + "github.com/containers/common/pkg/util" "github.com/containers/image/v5/types" "github.com/containers/podman/v4/pkg/errorhandling" "github.com/containers/podman/v4/pkg/namespaces" @@ -78,14 +79,9 @@ func ParseRegistryCreds(creds string) (*types.DockerAuthConfig, error) { }, nil } -// StringInSlice determines if a string is in a string slice, returns bool +// StringInSlice is depracated, use containers/common/pkg/util/StringInSlice func StringInSlice(s string, sl []string) bool { - for _, i := range sl { - if i == s { - return true - } - } - return false + return util.StringInSlice(s, sl) } // StringMatchRegexSlice determines if a given string matches one of the given regexes, returns bool diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index fd04e3f1b..13aaea317 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -225,6 +225,18 @@ t POST "images/load" ${TMPD}/test.tar 200 \ t GET libpod/images/quay.io/libpod/alpine:latest/exists 204 t GET libpod/images/quay.io/libpod/busybox:latest/exists 204 +CONTAINERFILE_WITH_ERR_TAR="${TMPD}/containerfile.tar" +cat > $TMPD/containerfile << EOF +FROM quay.io/fedora/fedora +RUN echo 'some error' >&2 +EOF +tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_WITH_ERR_TAR} containerfile &> /dev/null +t POST "build?q=1&dockerfile=containerfile" $CONTAINERFILE_WITH_ERR_TAR 200 +response_output=$(cat "$WORKDIR/curl.result.out") +if [[ ${response_output} == *"some error"* ]];then + _show_ok 0 "compat quiet build" "~ $response_output" "found output from stderr in API" +fi + cleanBuildTest # vim: filetype=sh diff --git a/test/system/015-help.bats b/test/system/015-help.bats index 5757d51dc..1356c99a0 100644 --- a/test/system/015-help.bats +++ b/test/system/015-help.bats @@ -34,10 +34,16 @@ function check_help() { # has no ' [options]' is "$usage " " $command_string .*" "Usage string matches command" + # Strip off the leading command string; we no longer need it + usage=$(sed -e "s/^ $command_string \?//" <<<"$usage") + # If usage ends in '[command]', recurse into subcommands - if expr "$usage" : '.*\[command\]$' >/dev/null; then + if expr "$usage" : '\[command\]' >/dev/null; then found[subcommands]=1 - check_help "$@" $cmd + # (except for 'podman help', which is a special case) + if [[ $cmd != "help" ]]; then + check_help "$@" $cmd + fi continue fi @@ -49,10 +55,26 @@ function check_help() { assert "$usage" !~ '[A-Z].*\[option' \ "'options' must precede arguments in usage" + # Strip off '[options]' but remember if we've seen it. + local has_options= + if [[ $usage =~ \[options\] ]]; then + has_options=1 + usage=$(sed -e 's/^\[options\] \?//' <<<"$usage") + fi + + # From this point on, remaining argument descriptions must be UPPER CASE + # e.g., 'podman cmd [options] arg' or 'podman cmd [arg]' are invalid. + assert "$usage" !~ '[a-z]' \ + "$command_string: argument names must be UPPER CASE" + + # It makes no sense to have an optional arg followed by a mandatory one + assert "$usage" !~ '\[.*\] [A-Z]' \ + "$command_string: optional args must be _after_ required ones" + # Cross-check: if usage includes '[options]', there must be a # longer 'Options:' section in the full --help output; vice-versa, # if 'Options:' is in full output, usage line must have '[options]'. - if expr "$usage" : '.*\[option' >/dev/null; then + if [[ $has_options ]]; then if ! expr "$full_help" : ".*Options:" >/dev/null; then die "$command_string: Usage includes '[options]' but has no 'Options:' subsection" fi @@ -95,9 +117,7 @@ function check_help() { fi # If usage has required arguments, try running without them. - # The expression here is 'first capital letter is not in [BRACKETS]'. - # It is intended to handle 'podman foo [options] ARG' but not ' [ARG]'. - if expr "$usage" : '[^A-Z]\+ [A-Z]' >/dev/null; then + if expr "$usage" : '[A-Z]' >/dev/null; then # Exceptions: these commands don't work rootless if is_rootless; then # "pause is not supported for rootless containers" @@ -126,25 +146,15 @@ function check_help() { # the required args, then invoke with one extra. We should get a # usage error. if ! expr "$usage" : ".*\.\.\."; then - # "podman help" can take infinite args, so skip that one - if [ "$cmd" != "help" ]; then - # Get the args part of the command line; this should be - # everything from the first CAPITAL LETTER onward. We - # don't actually care about the letter itself, so just - # make it 'X'. And we don't care about [OPTIONAL] brackets - # either. What we do care about is stuff like 'IMAGE | CTR' - # which is actually one argument; convert to 'IMAGE-or-CTR' - local rhs=$(sed -e 's/^[^A-Z]\+[A-Z]/X/' -e 's/ | /-or-/g' <<<"$usage") - local n_args=$(wc -w <<<"$rhs") - - run_podman '?' "$@" $cmd $(seq --format='x%g' 0 $n_args) - is "$status" 125 \ - "'$usage' indicates a maximum of $n_args args. I invoked it with more, and expected this exit status" - is "$output" "Error:.* \(takes no arguments\|requires exactly $n_args arg\|accepts at most\|too many arguments\|accepts $n_args arg(s), received\|accepts between .* and .* arg(s), received \)" \ - "'$usage' indicates a maximum of $n_args args. I invoked it with more, and expected one of these error messages" + local n_args=$(wc -w <<<"$usage") - found[fixed_args]=1 - fi + run_podman '?' "$@" $cmd $(seq --format='x%g' 0 $n_args) + is "$status" 125 \ + "'$usage' indicates a maximum of $n_args args. I invoked it with more, and expected this exit status" + is "$output" "Error:.* \(takes no arguments\|requires exactly $n_args arg\|accepts at most\|too many arguments\|accepts $n_args arg(s), received\|accepts between .* and .* arg(s), received \)" \ + "'$usage' indicates a maximum of $n_args args. I invoked it with more, and expected one of these error messages" + + found[fixed_args]=1 fi count=$(expr $count + 1) |