diff options
25 files changed, 123 insertions, 28 deletions
@@ -4,10 +4,8 @@ approvers: - giuseppe - jwhonce - mheon - - mrunalp - rhatdan - TomSweeneyRedHat - - umohnani8 - vrothberg reviewers: - baude @@ -15,8 +13,8 @@ reviewers: - giuseppe - jwhonce - mheon - - mrunalp - rhatdan - TomSweeneyRedHat - - umohnani8 - vrothberg + - ashley-cui + - QiWang19 diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 795b56d6a..96d94dc00 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -111,7 +111,9 @@ func create(cmd *cobra.Command, args []string) error { } imageName := args[0] + rawImageName := "" if !cliVals.RootFS { + rawImageName = args[0] name, err := pullImage(args[0]) if err != nil { return err @@ -122,6 +124,7 @@ func create(cmd *cobra.Command, args []string) error { if err := common.FillOutSpecGen(s, &cliVals, args); err != nil { return err } + s.RawImageName = rawImageName if _, err := createPodIfNecessary(s, cliVals.Net); err != nil { return err diff --git a/cmd/podman/containers/logs.go b/cmd/podman/containers/logs.go index 21c00505f..acc2ab1aa 100644 --- a/cmd/podman/containers/logs.go +++ b/cmd/podman/containers/logs.go @@ -37,7 +37,7 @@ var ( case registry.IsRemote() && len(args) > 1: return errors.New(cmd.Name() + " does not support multiple containers when run remotely") case logsOptions.Latest && len(args) > 0: - return errors.New("no containers can be specified when using 'latest'") + return errors.New("--latest and containers cannot be used together") case !logsOptions.Latest && len(args) < 1: return errors.New("specify at least one container name or ID to log") } diff --git a/cmd/podman/containers/mount.go b/cmd/podman/containers/mount.go index 1c358f4a2..f2df5e99e 100644 --- a/cmd/podman/containers/mount.go +++ b/cmd/podman/containers/mount.go @@ -78,6 +78,9 @@ func mount(_ *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) + if len(args) > 0 && mountOpts.Latest { + return errors.Errorf("--latest and containers cannot be used together") + } reports, err := registry.ContainerEngine().ContainerMount(registry.GetContext(), args, mountOpts) if err != nil { return err diff --git a/cmd/podman/containers/restart.go b/cmd/podman/containers/restart.go index d02097f0e..5f6f9c35c 100644 --- a/cmd/podman/containers/restart.go +++ b/cmd/podman/containers/restart.go @@ -80,6 +80,9 @@ func restart(cmd *cobra.Command, args []string) error { if len(args) < 1 && !restartOptions.Latest && !restartOptions.All { return errors.Wrapf(define.ErrInvalidArg, "you must provide at least one container name or ID") } + if len(args) > 0 && restartOptions.Latest { + return errors.Wrapf(define.ErrInvalidArg, "--latest and containers cannot be used together") + } if cmd.Flag("time").Changed { restartOptions.Timeout = &restartTimeout diff --git a/cmd/podman/containers/restore.go b/cmd/podman/containers/restore.go index 413bcbc87..c996144e3 100644 --- a/cmd/podman/containers/restore.go +++ b/cmd/podman/containers/restore.go @@ -80,7 +80,7 @@ func restore(_ *cobra.Command, args []string) error { } } if (restoreOptions.All || restoreOptions.Latest) && argLen > 0 { - return errors.Errorf("no arguments are needed with --all or --latest") + return errors.Errorf("--all or --latest and containers cannot be used together") } if argLen < 1 && !restoreOptions.All && !restoreOptions.Latest && restoreOptions.Import == "" { return errors.Errorf("you must provide at least one name or id") diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index ce144a32d..8052b033e 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -131,7 +131,9 @@ func run(cmd *cobra.Command, args []string) error { } imageName := args[0] + rawImageName := "" if !cliVals.RootFS { + rawImageName = args[0] name, err := pullImage(args[0]) if err != nil { return err @@ -178,6 +180,7 @@ func run(cmd *cobra.Command, args []string) error { if err := common.FillOutSpecGen(s, &cliVals, args); err != nil { return err } + s.RawImageName = rawImageName runOpts.Spec = s if _, err := createPodIfNecessary(s, cliVals.Net); err != nil { diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index ccbe80317..1e58498b6 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -74,6 +74,9 @@ func start(cmd *cobra.Command, args []string) error { if len(args) == 0 && !startOptions.Latest { return errors.New("start requires at least one argument") } + if len(args) > 0 && startOptions.Latest { + return errors.Errorf("--latest and containers cannot be used together") + } if len(args) > 1 && startOptions.Attach { return errors.Errorf("you cannot start and attach multiple containers at once") } diff --git a/cmd/podman/containers/wait.go b/cmd/podman/containers/wait.go index 9bb39e978..4bc3d20e2 100644 --- a/cmd/podman/containers/wait.go +++ b/cmd/podman/containers/wait.go @@ -78,7 +78,7 @@ func wait(cmd *cobra.Command, args []string) error { return errors.Errorf("%q requires a name, id, or the \"--latest\" flag", cmd.CommandPath()) } if waitOptions.Latest && len(args) > 0 { - return errors.New("--latest and containers are not allowed") + return errors.New("--latest and containers cannot be used together") } waitOptions.Condition, err = define.StringToContainerStatus(waitCondition) diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index 13c6544bb..f29527412 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -93,7 +93,7 @@ func (i *inspector) inspect(namesOrIDs []string) error { tmpType := i.options.Type if i.options.Latest { if len(namesOrIDs) > 0 { - return errors.New("latest and containers are not allowed") + return errors.New("--latest and containers cannot be used together") } tmpType = ContainerType // -l works with --type=all } diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go index 8f5aa6062..bc20352b0 100644 --- a/cmd/podman/pods/inspect.go +++ b/cmd/podman/pods/inspect.go @@ -46,6 +46,9 @@ func inspect(cmd *cobra.Command, args []string) error { if len(args) < 1 && !inspectOptions.Latest { return errors.Errorf("you must provide the name or id of a running pod") } + if len(args) > 0 && inspectOptions.Latest { + return errors.Errorf("--latest and containers cannot be used together") + } if !inspectOptions.Latest { inspectOptions.NameOrID = args[0] diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go index aacb41e69..ab6460e93 100644 --- a/cmd/podman/validate/args.go +++ b/cmd/podman/validate/args.go @@ -37,6 +37,9 @@ func IDOrLatestArgs(cmd *cobra.Command, args []string) error { if len(args) == 0 && !given { return fmt.Errorf("%q requires a name, id, or the \"--latest\" flag", cmd.CommandPath()) } + if len(args) > 0 && given { + return fmt.Errorf("--latest and containers cannot be used together") + } } return nil } @@ -83,7 +86,7 @@ func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool if argLen > 0 { if specifiedLatest { - return errors.Errorf("no arguments are needed with --latest") + return errors.Errorf("--latest and containers cannot be used together") } else if cidfile && (specifiedLatest || specifiedCIDFile) { return errors.Errorf("no arguments are needed with --latest or --cidfile") } @@ -138,7 +141,7 @@ func CheckAllLatestAndPodIDFile(c *cobra.Command, args []string, ignoreArgLen bo if argLen > 0 { if specifiedLatest { - return errors.Errorf("no arguments are needed with --latest") + return errors.Errorf("--latest and pods cannot be used together") } else if withIDFile && (specifiedLatest || specifiedPodIDFile) { return errors.Errorf("no arguments are needed with --latest or --pod-id-file") } diff --git a/docs/source/markdown/podman-remote.1.md b/docs/source/markdown/podman-remote.1.md index 3dcfae606..b621c846a 100644 --- a/docs/source/markdown/podman-remote.1.md +++ b/docs/source/markdown/podman-remote.1.md @@ -39,6 +39,11 @@ Path to ssh identity file. If the identity file has been encrypted, Podman promp If no identity file is provided and no user is given, Podman defaults to the user running the podman command. Podman prompts for the login password on the remote server. +Identity value resolution precedence: + - command line value + - environment variable `CONTAINER_SSHKEY`, if `CONTAINER_HOST` is found + - `containers.conf` + **--log-level**=*level* Log messages above specified level: debug, info, warn, error (default), fatal or panic @@ -47,6 +52,21 @@ Log messages above specified level: debug, info, warn, error (default), fatal or URL to access Podman service (default from `containers.conf`, rootless "unix://run/user/$UID/podman/podman.sock" or as root "unix://run/podman/podman.sock). + - `CONTAINER_HOST` is of the format `<schema>://[<user[:<password>]@]<host>[:<port>][<path>]` + +Details: + - `user` will default to either `root` or current running user + - `password` has no default + - `host` must be provided and is either the IP or name of the machine hosting the Podman service + - `port` defaults to 22 + - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/<uid>/podman/podman.sock` if running rootless. + +URL value resolution precedence: + - command line value + - environment variable `CONTAINER_HOST` + - `containers.conf` + - `unix://run/podman/podman.sock` + **--version** Print the version @@ -124,3 +144,15 @@ the exit codes follow the `chroot` standard, see below: | [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. | | [podman-version(1)](podman-version.1.md) | Display the Podman version information. | | [podman-volume(1)](podman-volume.1.md) | Manage Volumes. | +## FILES + +**containers.conf** (`$HOME/.config/containers/containers.conf`) + +Podman has builtin defaults for command line options. These defaults can be overridden using the containers.conf configuration files. + +Users can modify defaults by creating the `$HOME/.config/containers/containers.conf` file. Podman merges its builtin defaults with the specified fields from this file, if it exists. Fields specified in the users file override the built-in defaults. + +Podman uses builtin defaults if no containers.conf file is found. + +## SEE ALSO +`containers.conf(5)` diff --git a/docs/source/markdown/podman.1.md b/docs/source/markdown/podman.1.md index 2dc6b13bf..555486562 100644 --- a/docs/source/markdown/podman.1.md +++ b/docs/source/markdown/podman.1.md @@ -67,6 +67,11 @@ Path to ssh identity file. If the identity file has been encrypted, podman promp If no identity file is provided and no user is given, podman defaults to the user running the podman command. Podman prompts for the login password on the remote server. +Identity value resolution precedence: + - command line value + - environment variable `CONTAINER_SSHKEY`, if `CONTAINER_HOST` is found + - `containers.conf` + **--log-level**=*level* Log messages above specified level: debug, info, warn, error (default), fatal or panic (default: "error") @@ -83,7 +88,22 @@ Path to the command binary to use for setting up a network. It is currently onl Access Podman service will be remote **--url**=*value* -URL to access Podman service (default from `containers.conf`, rootless "unix://run/user/$UID/podman/podman.sock" or as root "unix://run/podman/podman.sock). +URL to access Podman service (default from `containers.conf`, rootless `unix://run/user/$UID/podman/podman.sock` or as root `unix://run/podman/podman.sock`). + + - `CONTAINER_HOST` is of the format `<schema>://[<user[:<password>]@]<host>[:<port>][<path>]` + +Details: + - `user` will default to either `root` or current running user + - `password` has no default + - `host` must be provided and is either the IP or name of the machine hosting the Podman service + - `port` defaults to 22 + - `path` defaults to either `/run/podman/podman.sock`, or `/run/user/<uid>/podman/podman.sock` if running rootless. + +URL value resolution precedence: + - command line value + - environment variable `CONTAINER_HOST` + - `containers.conf` + - `unix://run/podman/podman.sock` **--root**=*value* diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 3bdf28e8c..dde7cafb1 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -635,7 +635,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro Destination: "/sys/fs/cgroup/systemd", Type: "bind", Source: "/sys/fs/cgroup/systemd", - Options: []string{"bind", "nodev", "nosuid", "rprivate"}, + Options: []string{"bind", "nodev", "noexec", "nosuid", "rprivate"}, } g.AddMount(systemdMnt) g.AddLinuxMaskedPaths("/sys/fs/cgroup/systemd/release_agent") diff --git a/pkg/api/handlers/compat/ping.go b/pkg/api/handlers/compat/ping.go index eb7eed5b6..06150bb63 100644 --- a/pkg/api/handlers/compat/ping.go +++ b/pkg/api/handlers/compat/ping.go @@ -5,7 +5,6 @@ import ( "net/http" "github.com/containers/buildah" - "github.com/containers/podman/v2/pkg/api/handlers/utils" ) // Ping returns headers to client about the service @@ -14,13 +13,12 @@ import ( // Clients will use the Header availability to test which backend engine is in use. // Note: Additionally handler supports GET and HEAD methods func Ping(w http.ResponseWriter, r *http.Request) { - w.Header().Set("API-Version", utils.APIVersion[utils.CompatTree][utils.CurrentAPIVersion].String()) + // Note API-Version and Libpod-API-Version are set in handler_api.go w.Header().Set("BuildKit-Version", "") w.Header().Set("Docker-Experimental", "true") w.Header().Set("Cache-Control", "no-cache") w.Header().Set("Pragma", "no-cache") - w.Header().Set("Libpod-API-Version", utils.APIVersion[utils.LibpodTree][utils.CurrentAPIVersion].String()) w.Header().Set("Libpod-Buildha-Version", buildah.Version) w.WriteHeader(http.StatusOK) diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go index e12c7cefa..92900b75d 100644 --- a/pkg/api/handlers/compat/version.go +++ b/pkg/api/handlers/compat/version.go @@ -30,6 +30,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "Failed to obtain system memory info")) return } + components := []docker.ComponentVersion{{ Name: "Podman Engine", Version: versionInfo.Version, @@ -46,6 +47,9 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { }, }} + apiVersion := utils.APIVersion[utils.CompatTree][utils.CurrentAPIVersion] + minVersion := utils.APIVersion[utils.CompatTree][utils.MinimalAPIVersion] + utils.WriteResponse(w, http.StatusOK, entities.ComponentVersion{ Version: docker.Version{ Platform: struct { @@ -53,7 +57,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { }{ Name: fmt.Sprintf("%s/%s/%s-%s", goRuntime.GOOS, goRuntime.GOARCH, infoData.Host.Distribution.Distribution, infoData.Host.Distribution.Version), }, - APIVersion: components[0].Details["APIVersion"], + APIVersion: fmt.Sprintf("%d.%d", apiVersion.Major, apiVersion.Minor), Arch: components[0].Details["Arch"], BuildTime: components[0].Details["BuildTime"], Components: components, @@ -61,7 +65,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { GitCommit: components[0].Details["GitCommit"], GoVersion: components[0].Details["GoVersion"], KernelVersion: components[0].Details["KernelVersion"], - MinAPIVersion: components[0].Details["MinAPIVersion"], + MinAPIVersion: fmt.Sprintf("%d.%d", minVersion.Major, minVersion.Minor), Os: components[0].Details["Os"], Version: components[0].Version, }}) diff --git a/pkg/api/handlers/utils/handler.go b/pkg/api/handlers/utils/handler.go index 62fdc05dd..517dccad0 100644 --- a/pkg/api/handlers/utils/handler.go +++ b/pkg/api/handlers/utils/handler.go @@ -43,8 +43,8 @@ var ( // clients to shop for the Version they wish to support APIVersion = map[VersionTree]map[VersionLevel]semver.Version{ LibpodTree: { - CurrentAPIVersion: semver.MustParse("1.0.0"), - MinimalAPIVersion: semver.MustParse("1.0.0"), + CurrentAPIVersion: semver.MustParse("2.0.0"), + MinimalAPIVersion: semver.MustParse("2.0.0"), }, CompatTree: { CurrentAPIVersion: semver.MustParse("1.40.0"), diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go index e47b66bb4..f2ce0301b 100644 --- a/pkg/api/server/handler_api.go +++ b/pkg/api/server/handler_api.go @@ -40,6 +40,10 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc { c = context.WithValue(c, "idletracker", s.idleTracker) //nolint r = r.WithContext(c) + v := utils.APIVersion[utils.CompatTree][utils.CurrentAPIVersion] + w.Header().Set("API-Version", fmt.Sprintf("%d.%d", v.Major, v.Minor)) + w.Header().Set("Libpod-API-Version", utils.APIVersion[utils.LibpodTree][utils.CurrentAPIVersion].String()) + h(w, r) } fn(w, r) diff --git a/pkg/api/server/register_archive.go b/pkg/api/server/register_archive.go index 5931c2fc9..b2d2543c4 100644 --- a/pkg/api/server/register_archive.go +++ b/pkg/api/server/register_archive.go @@ -9,7 +9,7 @@ import ( ) func (s *APIServer) registerAchiveHandlers(r *mux.Router) error { - // swagger:operation POST /containers/{name}/archive compat putArchive + // swagger:operation PUT /containers/{name}/archive compat putArchive // --- // summary: Put files into a container // description: Put a tar archive of files into a container @@ -84,9 +84,9 @@ func (s *APIServer) registerAchiveHandlers(r *mux.Router) error { // $ref: "#/responses/NoSuchContainer" // 500: // $ref: "#/responses/InternalError" - r.HandleFunc(VersionedPath("/containers/{name}/archive"), s.APIHandler(compat.Archive)).Methods(http.MethodGet, http.MethodPost) + r.HandleFunc(VersionedPath("/containers/{name}/archive"), s.APIHandler(compat.Archive)).Methods(http.MethodGet, http.MethodPut, http.MethodHead) // Added non version path to URI to support docker non versioned paths - r.HandleFunc("/containers/{name}/archive", s.APIHandler(compat.Archive)).Methods(http.MethodGet, http.MethodPost) + r.HandleFunc("/containers/{name}/archive", s.APIHandler(compat.Archive)).Methods(http.MethodGet, http.MethodPut, http.MethodHead) /* Libpod diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index fda4c098c..2ac3b376f 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -95,7 +95,7 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener if len(names) > 0 { imgName = names[0] } - options = append(options, libpod.WithRootFSFromImage(newImage.ID(), imgName, s.Image)) + options = append(options, libpod.WithRootFSFromImage(newImage.ID(), imgName, s.RawImageName)) } if err := s.Validate(); err != nil { return nil, errors.Wrap(err, "invalid config provided") diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index cca05eddb..b8f37ec7a 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -89,6 +89,9 @@ type ContainerBasicConfig struct { // If not given, a default location will be used. // Optional. ConmonPidFile string `json:"conmon_pid_file,omitempty"` + // RawImageName is the user-specified and unprocessed input referring + // to a local or a remote image. + RawImageName string `json:"raw_image_name,omitempty"` // RestartPolicy is the container's restart policy - an action which // will be taken when the container exits. // If not given, the default policy, which does nothing, will be used. diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at index 96b6aef7c..541d8cbf1 100644 --- a/test/apiv2/01-basic.at +++ b/test/apiv2/01-basic.at @@ -18,11 +18,11 @@ t HEAD libpod/_ping 200 for i in /version version; do t GET $i 200 \ .Components[0].Name="Podman Engine" \ - .Components[0].Details.APIVersion=1.0.0 \ - .Components[0].Details.MinAPIVersion=1.0.0 \ + .Components[0].Details.APIVersion=2.0.0 \ + .Components[0].Details.MinAPIVersion=2.0.0 \ .Components[0].Details.Os=linux \ - .ApiVersion=1.0.0 \ - .MinAPIVersion=1.0.0 \ + .ApiVersion=1.40 \ + .MinAPIVersion=1.24 \ .Os=linux done diff --git a/test/system/015-help.bats b/test/system/015-help.bats index 4a3781012..651fdcd09 100644 --- a/test/system/015-help.bats +++ b/test/system/015-help.bats @@ -86,6 +86,20 @@ function check_help() { found[takes_no_args]=1 fi + # If command lists "-l, --latest" in help output, combine -l with arg. + # This should be disallowed with a clear message. + if expr "$full_help" : ".*-l, --latest" >/dev/null; then + local nope="exec list port ps top" # these can't be tested + if is_rootless; then + nope="$nope mount restore" # these don't work rootless + fi + if ! grep -wq "$cmd" <<<$nope; then + run_podman 125 "$@" $cmd -l nonexistent-container + is "$output" "Error: .*--latest and \(containers\|pods\|arguments\) cannot be used together" \ + "'$command_string' with both -l and container" + fi + 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 [flags] ARG' but not ' [ARG]'. diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats index bbb5a10fb..9bd3e15a1 100644 --- a/test/system/250-systemd.bats +++ b/test/system/250-systemd.bats @@ -41,7 +41,8 @@ function teardown() { fi cname=$(random_string) - run_podman create --name $cname --label "io.containers.autoupdate=image" --detach $IMAGE top + # See #7407 for --pull=always. + run_podman create --pull=always --name $cname --label "io.containers.autoupdate=image" --detach $IMAGE top run_podman generate systemd --new $cname echo "$output" > "$UNIT_FILE" |