From cb603b8a3e4a4a1da194ed020caf270fa85f6f5b Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Wed, 15 Jul 2020 16:33:24 -0400 Subject: Support default profile for apparmor Currently you can not apply an ApparmorProfile if you specify --privileged. This patch will allow both to be specified simultaniosly. By default Apparmor should be disabled if the user specifies --privileged, but if the user specifies --security apparmor:PROFILE, with --privileged, we should do both. Added e2e run_apparmor_test.go Signed-off-by: Daniel J Walsh --- cmd/podman/common/create.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index ee7f957cc..3f2d7b2b0 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -395,7 +395,7 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { ) createFlags.StringArrayVar( &cf.SecurityOpt, - "security-opt", containerConfig.SecurityOptions(), + "security-opt", []string{}, "Security Options", ) createFlags.String( -- cgit v1.2.3-54-g00ecf From a5f5e45c4b08f2c74409194836d6fb7aa05fa4c1 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Tue, 21 Jul 2020 10:12:03 -0400 Subject: Add noop function disable-content-trust People who use docker scripts with Podman see failures if they use disable-content-trust flag. This flag already existed for podman build, adding it to pull/push/create/run. Signed-off-by: Daniel J Walsh --- cmd/podman/common/create.go | 4 ++++ cmd/podman/images/pull.go | 1 + cmd/podman/images/push.go | 1 + docs/source/markdown/podman-create.1.md | 6 ++++++ docs/source/markdown/podman-pull.1.md | 6 ++++++ docs/source/markdown/podman-push.1.md | 6 ++++++ docs/source/markdown/podman-run.1.md | 6 ++++++ 7 files changed, 30 insertions(+) (limited to 'cmd') diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index 3f2d7b2b0..5f3198ed6 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -154,6 +154,10 @@ func GetCreateFlags(cf *ContainerCLIOpts) *pflag.FlagSet { "device-write-iops", []string{}, "Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000)", ) + createFlags.Bool( + "disable-content-trust", false, + "This is a Docker specific option and is a NOOP", + ) createFlags.String("entrypoint", "", "Overwrite the default ENTRYPOINT of the image", ) diff --git a/cmd/podman/images/pull.go b/cmd/podman/images/pull.go index 83bb186df..c10a351d8 100644 --- a/cmd/podman/images/pull.go +++ b/cmd/podman/images/pull.go @@ -82,6 +82,7 @@ func pullFlags(flags *pflag.FlagSet) { flags.StringVar(&pullOptions.CredentialsCLI, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") flags.StringVar(&pullOptions.OverrideArch, "override-arch", "", "Use `ARCH` instead of the architecture of the machine for choosing images") flags.StringVar(&pullOptions.OverrideOS, "override-os", "", "Use `OS` instead of the running OS for choosing images") + flags.Bool("disable-content-trust", false, "This is a Docker specific option and is a NOOP") flags.BoolVarP(&pullOptions.Quiet, "quiet", "q", false, "Suppress output information when pulling images") flags.StringVar(&pullOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.BoolVar(&pullOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go index fd91ab0ab..c25c33784 100644 --- a/cmd/podman/images/push.go +++ b/cmd/podman/images/push.go @@ -77,6 +77,7 @@ func pushFlags(flags *pflag.FlagSet) { flags.BoolVar(&pushOptions.Compress, "compress", false, "Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type as source)") flags.StringVar(&pushOptions.CredentialsCLI, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry") flags.StringVar(&pushOptions.DigestFile, "digestfile", "", "Write the digest of the pushed image to the specified file") + flags.Bool("disable-content-trust", false, "This is a Docker specific option and is a NOOP") flags.StringVarP(&pushOptions.Format, "format", "f", "", "Manifest type (oci, v2s1, or v2s2) to use when pushing an image using the 'dir' transport (default is manifest type of source)") flags.BoolVarP(&pushOptions.Quiet, "quiet", "q", false, "Suppress output information when pushing images") flags.BoolVar(&pushOptions.RemoveSignatures, "remove-signatures", false, "Discard any pre-existing signatures in the image") diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 6d8686d24..d7e5861e7 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -231,6 +231,12 @@ Limit write rate (bytes per second) to a device (e.g. --device-write-bps=/dev/sd Limit write rate (IO per second) to a device (e.g. --device-write-iops=/dev/sda:1000) +**--disable-content-trust** + +This is a Docker specific option to disable image verification to a Docker +registry and is not supported by Podman. This flag is a NOOP and provided +solely for scripting compatibility. + **--dns**=*dns* Set custom DNS servers. Invalid if using **--dns** and **--network** that is set to 'none' or 'container:'. diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md index 5d941219a..201b10aa6 100644 --- a/docs/source/markdown/podman-pull.1.md +++ b/docs/source/markdown/podman-pull.1.md @@ -73,6 +73,12 @@ The [username[:password]] to use to authenticate with the registry if required. If one or both values are not supplied, a command line prompt will appear and the value can be entered. The password is entered without echo. +**--disable-content-trust** + +This is a Docker specific option to disable image verification to a Docker +registry and is not supported by Podman. This flag is a NOOP and provided +solely for scripting compatibility. + **--override-os**=*OS* Use OS instead of the running OS for choosing images diff --git a/docs/source/markdown/podman-push.1.md b/docs/source/markdown/podman-push.1.md index f029c8db1..fffd76801 100644 --- a/docs/source/markdown/podman-push.1.md +++ b/docs/source/markdown/podman-push.1.md @@ -71,6 +71,12 @@ Note: This flag can only be set when using the **dir** transport After copying the image, write the digest of the resulting image to the file. (Not available for remote commands) +**--disable-content-trust** + +This is a Docker specific option to disable image verification to a Docker +registry and is not supported by Podman. This flag is a NOOP and provided +solely for scripting compatibility. + **--format**, **-f**=*format* Manifest Type (oci, v2s1, or v2s2) to use when pushing an image to a directory using the 'dir:' transport (default is manifest type of source) diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 6632ac2d1..0cbb54780 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -245,6 +245,12 @@ Limit write rate (in bytes per second) to a device (e.g. **--device-write-bps=/d Limit write rate (in IO operations per second) to a device (e.g. **--device-write-iops=/dev/sda:1000**). +**--disable-content-trust** + +This is a Docker specific option to disable image verification to a Docker +registry and is not supported by Podman. This flag is a NOOP and provided +solely for scripting compatibility. + **--dns**=*ipaddr* Set custom DNS servers. Invalid if using **--dns** with **--network** that is set to **none** or **container:**_id_. -- cgit v1.2.3-54-g00ecf From 92186cbd28df57bda027c90eb3715c8a636c1037 Mon Sep 17 00:00:00 2001 From: Parker Van Roy Date: Mon, 13 Jul 2020 15:26:41 -0400 Subject: Used reference package with errors for parsing tag Signed-off-by: Parker Van Roy --- cmd/podman/images/list.go | 53 +++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 18 deletions(-) (limited to 'cmd') diff --git a/cmd/podman/images/list.go b/cmd/podman/images/list.go index 8d50986d5..94d03bd6f 100644 --- a/cmd/podman/images/list.go +++ b/cmd/podman/images/list.go @@ -1,7 +1,6 @@ package images import ( - "errors" "fmt" "os" "sort" @@ -11,9 +10,11 @@ import ( "time" "unicode" + "github.com/containers/image/v5/docker/reference" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/docker/go-units" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" ) @@ -98,7 +99,10 @@ func images(cmd *cobra.Command, args []string) error { return err } - imgs := sortImages(summaries) + imgs, err := sortImages(summaries) + if err != nil { + return err + } switch { case listFlag.quiet: return writeID(imgs) @@ -170,14 +174,18 @@ func writeTemplate(imgs []imageReporter) error { return tmpl.Execute(w, imgs) } -func sortImages(imageS []*entities.ImageSummary) []imageReporter { +func sortImages(imageS []*entities.ImageSummary) ([]imageReporter, error) { imgs := make([]imageReporter, 0, len(imageS)) + var err error for _, e := range imageS { var h imageReporter if len(e.RepoTags) > 0 { for _, tag := range e.RepoTags { h.ImageSummary = *e - h.Repository, h.Tag = tokenRepoTag(tag) + h.Repository, h.Tag, err = tokenRepoTag(tag) + if err != nil { + return nil, errors.Wrapf(err, "error parsing repository tag %q:", tag) + } imgs = append(imgs, h) } } else { @@ -189,23 +197,32 @@ func sortImages(imageS []*entities.ImageSummary) []imageReporter { } sort.Slice(imgs, sortFunc(listFlag.sort, imgs)) - return imgs + return imgs, err } -func tokenRepoTag(tag string) (string, string) { - tokens := strings.Split(tag, ":") - switch len(tokens) { - case 0: - return tag, "" - case 1: - return tokens[0], "" - case 2: - return tokens[0], tokens[1] - case 3: - return tokens[0] + ":" + tokens[1], tokens[2] - default: - return "", "" +func tokenRepoTag(ref string) (string, string, error) { + + if ref == ":" { + return "", "", nil + } + + repo, err := reference.Parse(ref) + if err != nil { + return "", "", err + } + + named, ok := repo.(reference.Named) + if !ok { + return ref, "", nil } + + tagged, ok := repo.(reference.Tagged) + if !ok { + return named.Name(), "", nil + } + + return named.Name(), tagged.Tag(), nil + } func sortFunc(key string, data []imageReporter) func(i, j int) bool { -- cgit v1.2.3-54-g00ecf From e21a6368f9308292641ed5ce58321b1cd46abdc9 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 17 Jul 2020 13:58:22 +0200 Subject: abi: set default umask and rlimits the code got lost in the migration to podman 2.0, reintroduce it. Closes: https://github.com/containers/podman/issues/6989 Signed-off-by: Giuseppe Scrivano Signed-off-by: Matthew Heon --- cmd/podman/early_init_linux.go | 39 ++++++++++++++++++++++++++++++++++++ cmd/podman/early_init_unsupported.go | 6 ++++++ cmd/podman/root.go | 1 + libpod/define/config.go | 10 +++++++++ pkg/domain/infra/abi/system.go | 22 -------------------- pkg/spec/spec.go | 15 +++++++------- pkg/specgen/generate/oci.go | 15 +++++++------- 7 files changed, 70 insertions(+), 38 deletions(-) create mode 100644 cmd/podman/early_init_linux.go create mode 100644 cmd/podman/early_init_unsupported.go (limited to 'cmd') diff --git a/cmd/podman/early_init_linux.go b/cmd/podman/early_init_linux.go new file mode 100644 index 000000000..b43450a7f --- /dev/null +++ b/cmd/podman/early_init_linux.go @@ -0,0 +1,39 @@ +package main + +import ( + "fmt" + "os" + "syscall" + + "github.com/containers/libpod/v2/libpod/define" + "github.com/pkg/errors" +) + +func setRLimits() error { + rlimits := new(syscall.Rlimit) + rlimits.Cur = define.RLimitDefaultValue + rlimits.Max = define.RLimitDefaultValue + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { + return errors.Wrapf(err, "error getting rlimits") + } + rlimits.Cur = rlimits.Max + if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { + return errors.Wrapf(err, "error setting new rlimits") + } + } + return nil +} + +func setUMask() { + // Be sure we can create directories with 0755 mode. + syscall.Umask(0022) +} + +func earlyInitHook() { + if err := setRLimits(); err != nil { + fmt.Fprint(os.Stderr, "Failed to set rlimits: "+err.Error()) + } + + setUMask() +} diff --git a/cmd/podman/early_init_unsupported.go b/cmd/podman/early_init_unsupported.go new file mode 100644 index 000000000..4e748559f --- /dev/null +++ b/cmd/podman/early_init_unsupported.go @@ -0,0 +1,6 @@ +// +build !linux + +package main + +func earlyInitHook() { +} diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 7c54da91a..b2c9f9c2c 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -77,6 +77,7 @@ func init() { cobra.OnInitialize( loggingHook, syslogHook, + earlyInitHook, ) rootFlags(rootCmd, registry.PodmanConfig()) diff --git a/libpod/define/config.go b/libpod/define/config.go index 900a363d8..64b24d9e2 100644 --- a/libpod/define/config.go +++ b/libpod/define/config.go @@ -75,3 +75,13 @@ const JSONLogging = "json-file" // NoLogging is the string conmon expects when specifying to use no log driver whatsoever const NoLogging = "none" + +// Strings used for --sdnotify option to podman +const ( + SdNotifyModeContainer = "container" + SdNotifyModeConmon = "conmon" + SdNotifyModeIgnore = "ignore" +) + +// DefaultRlimitValue is the value set by default for nofile and nproc +const RLimitDefaultValue = uint64(1048576) diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go index be14f52b8..435902ded 100644 --- a/pkg/domain/infra/abi/system.go +++ b/pkg/domain/infra/abi/system.go @@ -8,7 +8,6 @@ import ( "os/exec" "path/filepath" "strconv" - "syscall" "github.com/containers/common/pkg/config" "github.com/containers/libpod/v2/libpod/define" @@ -146,27 +145,6 @@ func movePauseProcessToScope() error { return utils.RunUnderSystemdScope(int(pid), "user.slice", "podman-pause.scope") } -func setRLimits() error { // nolint:deadcode,unused - rlimits := new(syscall.Rlimit) - rlimits.Cur = 1048576 - rlimits.Max = 1048576 - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { - if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { - return errors.Wrapf(err, "error getting rlimits") - } - rlimits.Cur = rlimits.Max - if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil { - return errors.Wrapf(err, "error setting new rlimits") - } - } - return nil -} - -func setUMask() { // nolint:deadcode,unused - // Be sure we can create directories with 0755 mode. - syscall.Umask(0022) -} - // checkInput can be used to verify any of the globalopt values func checkInput() error { // nolint:deadcode,unused return nil diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 6f52b88b1..b974772d5 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -505,10 +505,9 @@ func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, g *generate. func addRlimits(config *CreateConfig, g *generate.Generator) error { var ( - kernelMax uint64 = 1048576 - isRootless = rootless.IsRootless() - nofileSet = false - nprocSet = false + isRootless = rootless.IsRootless() + nofileSet = false + nprocSet = false ) for _, u := range config.Resources.Ulimit { @@ -538,8 +537,8 @@ func addRlimits(config *CreateConfig, g *generate.Generator) error { // files and number of processes to the maximum they can be set to // (without overriding a sysctl) if !nofileSet { - max := kernelMax - current := kernelMax + max := define.RLimitDefaultValue + current := define.RLimitDefaultValue if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil { @@ -555,8 +554,8 @@ func addRlimits(config *CreateConfig, g *generate.Generator) error { g.AddProcessRlimits("RLIMIT_NOFILE", max, current) } if !nprocSet { - max := kernelMax - current := kernelMax + max := define.RLimitDefaultValue + current := define.RLimitDefaultValue if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil { diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index f770b0582..b62e851b3 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -20,10 +20,9 @@ import ( func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error { var ( - kernelMax uint64 = 1048576 - isRootless = rootless.IsRootless() - nofileSet = false - nprocSet = false + isRootless = rootless.IsRootless() + nofileSet = false + nprocSet = false ) if s.Rlimits == nil { @@ -45,8 +44,8 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error { // files and number of processes to the maximum they can be set to // (without overriding a sysctl) if !nofileSet { - max := kernelMax - current := kernelMax + max := define.RLimitDefaultValue + current := define.RLimitDefaultValue if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil { @@ -62,8 +61,8 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) error { g.AddProcessRlimits("RLIMIT_NOFILE", max, current) } if !nprocSet { - max := kernelMax - current := kernelMax + max := define.RLimitDefaultValue + current := define.RLimitDefaultValue if isRootless { var rlimit unix.Rlimit if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil { -- cgit v1.2.3-54-g00ecf From 0030dd3f75aa2f5877fa599a325f19b9e4140209 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Fri, 10 Jul 2020 11:37:30 -0400 Subject: Ensure sig-proxy default is propagated in start We properly determined what sig-proxy should be set to, but we never passed that along to the backend. As such, cases where the default swapped (mostly when `--attach` was specified but the `--sig-proxy` flag was not) were not handled correctly Fixes #6928 Signed-off-by: Matthew Heon --- cmd/podman/containers/start.go | 1 + 1 file changed, 1 insertion(+) (limited to 'cmd') diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index 941588137..21f22b986 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -82,6 +82,7 @@ func start(cmd *cobra.Command, args []string) error { if cmd.Flag("sig-proxy").Changed { sigProxy = startOptions.SigProxy } + startOptions.SigProxy = sigProxy if sigProxy && !startOptions.Attach { return errors.Wrapf(define.ErrInvalidArg, "you cannot use sig-proxy without --attach") -- cgit v1.2.3-54-g00ecf From 0630d19b34c6cea674fc5f830fe308b8a1206259 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 7 Jul 2020 17:19:59 -0400 Subject: Fix container and pod create commands for remote create In `podman inspect` output for containers and pods, we include the command that was used to create the container. This is also used by `podman generate systemd --new` to generate unit files. With remote podman, the generated create commands were incorrect since we sourced directly from os.Args on the server side, which was guaranteed to be `podman system service` (or some variant thereof). The solution is to pass the command along in the Specgen or PodSpecgen, where we can source it from the client's os.Args. This will still be VERY iffy for mixed local/remote use (doing a `podman --remote run ...` on a remote client then a `podman generate systemd --new` on the server on the same container will not work, because the `--remote` flag will slip in) but at the very least the output of `podman inspect` will be correct. We can look into properly handling `--remote` (parsing it out would be a little iffy) in a future PR. Signed-off-by: Matthew Heon Signed-off-by: Matthew Heon --- cmd/podman/common/specgen.go | 3 +++ cmd/podman/pods/create.go | 2 ++ libpod/options.go | 8 ++++---- pkg/domain/entities/pods.go | 2 ++ pkg/spec/createconfig.go | 4 ---- pkg/specgen/generate/container_create.go | 4 +++- pkg/specgen/generate/pod_create.go | 4 +++- pkg/specgen/podspecgen.go | 6 ++++++ pkg/specgen/specgen.go | 7 +++++++ pkg/varlinkapi/create.go | 4 ---- 10 files changed, 30 insertions(+), 14 deletions(-) (limited to 'cmd') diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index b4f786da2..3722d45b2 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -378,6 +378,9 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } var command []string + // Include the command used to create the container. + s.ContainerCreateCommand = os.Args + // Build the command // If we have an entry point, it goes first if c.Entrypoint != nil { diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index 0e2a085fd..d57a2f2f7 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -149,6 +149,8 @@ func create(cmd *cobra.Command, args []string) error { } } + createOptions.CreateCommand = os.Args + if replace { if err := replacePod(createOptions.Name); err != nil { return err diff --git a/libpod/options.go b/libpod/options.go index 3120a35d7..bff3f3c18 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1371,12 +1371,12 @@ func WithHealthCheck(healthCheck *manifest.Schema2HealthConfig) CtrCreateOption // WithCreateCommand adds the full command plus arguments of the current // process to the container config. -func WithCreateCommand() CtrCreateOption { +func WithCreateCommand(cmd []string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { return define.ErrCtrFinalized } - ctr.config.CreateCommand = os.Args + ctr.config.CreateCommand = cmd return nil } } @@ -1553,12 +1553,12 @@ func WithPodHostname(hostname string) PodCreateOption { // WithPodCreateCommand adds the full command plus arguments of the current // process to the pod config. -func WithPodCreateCommand() PodCreateOption { +func WithPodCreateCommand(createCmd []string) PodCreateOption { return func(pod *Pod) error { if pod.valid { return define.ErrPodFinalized } - pod.config.CreateCommand = os.Args + pod.config.CreateCommand = createCmd return nil } } diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 8023034ef..9e9b834ef 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -104,6 +104,7 @@ type PodRmReport struct { type PodCreateOptions struct { CGroupParent string + CreateCommand []string Hostname string Infra bool InfraImage string @@ -133,6 +134,7 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) { } s.InfraImage = p.InfraImage s.SharedNamespaces = p.Share + s.PodCreateCommand = p.CreateCommand // Networking config s.NetNS = p.Net.Network diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 879c66895..55c3238d2 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -406,10 +406,6 @@ func CreateContainerFromCreateConfig(ctx context.Context, r *libpod.Runtime, cre return nil, err } - // Set the CreateCommand explicitly. Some (future) consumers of libpod - // might not want to set it. - options = append(options, libpod.WithCreateCommand()) - ctr, err := r.NewContainer(ctx, runtimeSpec, options...) if err != nil { return nil, err diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index daf7f84d4..be1e3b48e 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -78,7 +78,9 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener } options := []libpod.CtrCreateOption{} - options = append(options, libpod.WithCreateCommand()) + if s.ContainerCreateCommand != nil { + options = append(options, libpod.WithCreateCommand(s.ContainerCreateCommand)) + } var newImage *image.Image if s.Rootfs != "" { diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 690651a23..4fe1b6435 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -93,7 +93,9 @@ func createPodOptions(p *specgen.PodSpecGenerator) ([]libpod.PodCreateOption, er options = append(options, libpod.WithInfraContainerPorts(ports)) } options = append(options, libpod.WithPodCgroups()) - options = append(options, libpod.WithPodCreateCommand()) + if p.PodCreateCommand != nil { + options = append(options, libpod.WithPodCreateCommand(p.PodCreateCommand)) + } if len(p.InfraConmonPidFile) > 0 { options = append(options, libpod.WithInfraConmonPidFile(p.InfraConmonPidFile)) } diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index 600d27004..3c32ec365 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -49,6 +49,12 @@ type PodBasicConfig struct { // Conflicts with NoInfra=true. // Optional. SharedNamespaces []string `json:"shared_namespaces,omitempty"` + // PodCreateCommand is the command used to create this pod. + // This will be shown in the output of Inspect() on the pod, and may + // also be used by some tools that wish to recreate the pod + // (e.g. `podman generate systemd --new`). + // Optional. + PodCreateCommand []string `json:"pod_create_command,omitempty"` } // PodNetworkConfig contains networking configuration for a pod. diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 91bc36709..bd738f5a7 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -131,6 +131,13 @@ type ContainerBasicConfig struct { // Remove indicates if the container should be removed once it has been started // and exits Remove bool `json:"remove,omitempty"` + // ContainerCreateCommand is the command that was used to create this + // container. + // This will be shown in the output of Inspect() on the container, and + // may also be used by some tools that wish to recreate the container + // (e.g. `podman generate systemd --new`). + // Optional. + ContainerCreateCommand []string `json:"containerCreateCommand,omitempty"` } // ContainerStorageConfig contains information on the storage configuration of a diff --git a/pkg/varlinkapi/create.go b/pkg/varlinkapi/create.go index 5c5f075f7..ac93939d9 100644 --- a/pkg/varlinkapi/create.go +++ b/pkg/varlinkapi/create.go @@ -915,10 +915,6 @@ func CreateContainerFromCreateConfig(ctx context.Context, r *libpod.Runtime, cre return nil, err } - // Set the CreateCommand explicitly. Some (future) consumers of libpod - // might not want to set it. - options = append(options, libpod.WithCreateCommand()) - ctr, err := r.NewContainer(ctx, runtimeSpec, options...) if err != nil { return nil, err -- cgit v1.2.3-54-g00ecf From 1fb32b9b2f1196f02fdd0aba8f55e18684e9e932 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Fri, 10 Jul 2020 15:22:39 +0200 Subject: version/info: format: allow more json variants Allow more variants to yield json output for `podman version` and `podman info`. Instead of comparing strings, use a regex and add unit and e2e tests. Fixes: #6927 Signed-off-by: Valentin Rothberg --- cmd/podman/parse/json.go | 9 +++++++++ cmd/podman/parse/json_test.go | 30 ++++++++++++++++++++++++++++++ cmd/podman/system/info.go | 3 ++- cmd/podman/system/version.go | 3 ++- test/e2e/info_test.go | 30 +++++++++++++++++++++++++----- test/e2e/version_test.go | 34 +++++++++++++++++++++++----------- 6 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 cmd/podman/parse/json.go create mode 100644 cmd/podman/parse/json_test.go (limited to 'cmd') diff --git a/cmd/podman/parse/json.go b/cmd/podman/parse/json.go new file mode 100644 index 000000000..95a6633b8 --- /dev/null +++ b/cmd/podman/parse/json.go @@ -0,0 +1,9 @@ +package parse + +import "regexp" + +var jsonFormatRegex = regexp.MustCompile(`^(\s*json\s*|\s*{{\s*json\s*\.\s*}}\s*)$`) + +func MatchesJSONFormat(s string) bool { + return jsonFormatRegex.Match([]byte(s)) +} diff --git a/cmd/podman/parse/json_test.go b/cmd/podman/parse/json_test.go new file mode 100644 index 000000000..5cad185fd --- /dev/null +++ b/cmd/podman/parse/json_test.go @@ -0,0 +1,30 @@ +package parse + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMatchesJSONFormat(t *testing.T) { + tests := []struct { + input string + expected bool + }{ + {"json", true}, + {" json", true}, + {"json ", true}, + {" json ", true}, + {"{{json .}}", true}, + {"{{ json .}}", true}, + {"{{json . }}", true}, + {" {{ json . }} ", true}, + {"{{json }}", false}, + {"{{json .", false}, + {"json . }}", false}, + } + + for _, tt := range tests { + assert.Equal(t, tt.expected, MatchesJSONFormat(tt.input)) + } +} diff --git a/cmd/podman/system/info.go b/cmd/podman/system/info.go index 699f7b55c..410b3455a 100644 --- a/cmd/podman/system/info.go +++ b/cmd/podman/system/info.go @@ -5,6 +5,7 @@ import ( "os" "text/template" + "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" @@ -68,7 +69,7 @@ func info(cmd *cobra.Command, args []string) error { return err } - if inFormat == "json" { + if parse.MatchesJSONFormat(inFormat) { b, err := json.MarshalIndent(info, "", " ") if err != nil { return err diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go index 5aac34699..9b70bc9f4 100644 --- a/cmd/podman/system/version.go +++ b/cmd/podman/system/version.go @@ -8,6 +8,7 @@ import ( "text/tabwriter" "github.com/containers/buildah/pkg/formats" + "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/libpod/define" @@ -41,7 +42,7 @@ func version(cmd *cobra.Command, args []string) error { } switch { - case versionFormat == "json", versionFormat == "{{ json .}}": + case parse.MatchesJSONFormat(versionFormat): s, err := json.MarshalToString(versions) if err != nil { return err diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go index e38ace53f..8aa9712fd 100644 --- a/test/e2e/info_test.go +++ b/test/e2e/info_test.go @@ -11,6 +11,7 @@ import ( . "github.com/containers/libpod/v2/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" ) var _ = Describe("Podman Info", func() { @@ -35,11 +36,30 @@ var _ = Describe("Podman Info", func() { processTestResult(f) }) - It("podman info json output", func() { - session := podmanTest.Podman([]string{"info", "--format=json"}) - session.WaitWithDefaultTimeout() - Expect(session.ExitCode()).To(Equal(0)) - + It("podman info --format json", func() { + tests := []struct { + input string + success bool + exitCode int + }{ + {"json", true, 0}, + {" json", true, 0}, + {"json ", true, 0}, + {" json ", true, 0}, + {"{{json .}}", true, 0}, + {"{{ json .}}", true, 0}, + {"{{json . }}", true, 0}, + {" {{ json . }} ", true, 0}, + {"{{json }}", false, 125}, + {"{{json .", false, 125}, + {"json . }}", false, 0}, // Note: this does NOT fail but produces garbage + } + for _, tt := range tests { + session := podmanTest.Podman([]string{"info", "--format", tt.input}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(tt.exitCode)) + Expect(session.IsJSONOutputValid()).To(Equal(tt.success)) + } }) It("podman info --format GO template", func() { diff --git a/test/e2e/version_test.go b/test/e2e/version_test.go index 775be6511..eb1d1b733 100644 --- a/test/e2e/version_test.go +++ b/test/e2e/version_test.go @@ -55,17 +55,29 @@ var _ = Describe("Podman version", func() { }) It("podman version --format json", func() { - session := podmanTest.Podman([]string{"version", "--format", "json"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - Expect(session.IsJSONOutputValid()).To(BeTrue()) - }) - - It("podman version --format json", func() { - session := podmanTest.Podman([]string{"version", "--format", "{{ json .}}"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - Expect(session.IsJSONOutputValid()).To(BeTrue()) + tests := []struct { + input string + success bool + exitCode int + }{ + {"json", true, 0}, + {" json", true, 0}, + {"json ", true, 0}, + {" json ", true, 0}, + {"{{json .}}", true, 0}, + {"{{ json .}}", true, 0}, + {"{{json . }}", true, 0}, + {" {{ json . }} ", true, 0}, + {"{{json }}", false, 125}, + {"{{json .", false, 125}, + {"json . }}", false, 0}, // Note: this does NOT fail but produces garbage + } + for _, tt := range tests { + session := podmanTest.Podman([]string{"version", "--format", tt.input}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(tt.exitCode)) + Expect(session.IsJSONOutputValid()).To(Equal(tt.success)) + } }) It("podman version --format GO template", func() { -- cgit v1.2.3-54-g00ecf From 4d7626cc897d821bd8c931d1dde1fa0ab236f4f9 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Tue, 14 Jul 2020 13:05:25 -0400 Subject: Fix handling of entrypoint If a user specifies an entrypoint of "" then we should not use the images entrypoint. Signed-off-by: Daniel J Walsh --- cmd/podman/common/specgen.go | 12 +++++------- pkg/api/handlers/compat/containers_create.go | 2 +- pkg/specgen/generate/oci.go | 2 +- test/e2e/run_entrypoint_test.go | 5 +++++ 4 files changed, 12 insertions(+), 9 deletions(-) (limited to 'cmd') diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 3722d45b2..aa8669e7a 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -365,9 +365,10 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string s.Annotations = annotations s.WorkDir = c.Workdir - entrypoint := []string{} userCommand := []string{} + var command []string if c.Entrypoint != nil { + entrypoint := []string{} if ep := *c.Entrypoint; len(ep) > 0 { // Check if entrypoint specified is json if err := json.Unmarshal([]byte(*c.Entrypoint), &entrypoint); err != nil { @@ -375,17 +376,14 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string } } s.Entrypoint = entrypoint + // Build the command + // If we have an entry point, it goes first + command = entrypoint } - var command []string // Include the command used to create the container. s.ContainerCreateCommand = os.Args - // Build the command - // If we have an entry point, it goes first - if c.Entrypoint != nil { - command = entrypoint - } if len(inputCommand) > 0 { // User command overrides data CMD command = append(command, inputCommand...) diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 031e30b7e..cbee8a8b6 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -81,7 +81,7 @@ func makeCreateConfig(ctx context.Context, containerConfig *config.Config, input workDir = input.WorkingDir } - if len(input.Entrypoint) == 0 { + if input.Entrypoint == nil { entrypointSlice, err := newImage.Entrypoint(ctx) if err != nil { return createconfig.CreateConfig{}, err diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go index b33fe0e25..f279aac1c 100644 --- a/pkg/specgen/generate/oci.go +++ b/pkg/specgen/generate/oci.go @@ -86,7 +86,7 @@ func makeCommand(ctx context.Context, s *specgen.SpecGenerator, img *image.Image finalCommand := []string{} entrypoint := s.Entrypoint - if len(entrypoint) == 0 && img != nil { + if entrypoint == nil && img != nil { newEntry, err := img.Entrypoint(ctx) if err != nil { return nil, err diff --git a/test/e2e/run_entrypoint_test.go b/test/e2e/run_entrypoint_test.go index c947fa863..e6604a21e 100644 --- a/test/e2e/run_entrypoint_test.go +++ b/test/e2e/run_entrypoint_test.go @@ -101,6 +101,11 @@ ENTRYPOINT ["grep", "Alpine", "/etc/os-release"] session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) Expect(session.LineInOuputStartsWith("Linux")).To(BeTrue()) + + session = podmanTest.Podman([]string{"run", "--entrypoint", "", "foobar.com/entrypoint:latest", "uname"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.LineInOuputStartsWith("Linux")).To(BeTrue()) }) It("podman run user entrypoint with command overrides image entrypoint and image cmd", func() { -- cgit v1.2.3-54-g00ecf