diff options
-rw-r--r-- | cmd/podman/common/create_opts.go | 41 | ||||
-rw-r--r-- | cmd/podman/images/search.go | 10 | ||||
-rw-r--r-- | docs/source/markdown/podman-import.1.md | 3 | ||||
-rw-r--r-- | docs/source/markdown/podman-pull.1.md | 11 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_create.go | 7 | ||||
-rw-r--r-- | pkg/bindings/containers/logs.go | 2 | ||||
-rw-r--r-- | pkg/specgen/container_validate.go | 35 | ||||
-rw-r--r-- | test/e2e/search_test.go | 8 |
8 files changed, 98 insertions, 19 deletions
diff --git a/cmd/podman/common/create_opts.go b/cmd/podman/common/create_opts.go index 05bb9de13..8b2efc988 100644 --- a/cmd/podman/common/create_opts.go +++ b/cmd/podman/common/create_opts.go @@ -7,7 +7,9 @@ import ( "strings" "github.com/containers/podman/v2/pkg/api/handlers" + "github.com/containers/podman/v2/pkg/cgroups" "github.com/containers/podman/v2/pkg/domain/entities" + "github.com/containers/podman/v2/pkg/rootless" "github.com/containers/podman/v2/pkg/specgen" ) @@ -129,7 +131,7 @@ func stringMaptoArray(m map[string]string) []string { // ContainerCreateToContainerCLIOpts converts a compat input struct to cliopts so it can be converted to // a specgen spec. -func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig) (*ContainerCLIOpts, []string, error) { +func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig, cgroupsManager string) (*ContainerCLIOpts, []string, error) { var ( capAdd []string cappDrop []string @@ -346,16 +348,23 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig) (*Cont Systemd: "true", // podman default TmpFS: stringMaptoArray(cc.HostConfig.Tmpfs), TTY: cc.Config.Tty, - //Ulimit: cc.HostConfig.Ulimits, // ask dan, no documented format - Ulimit: []string{"nproc=4194304:4194304"}, - User: cc.Config.User, - UserNS: string(cc.HostConfig.UsernsMode), - UTS: string(cc.HostConfig.UTSMode), - Mount: mounts, - Volume: volumes, - VolumesFrom: cc.HostConfig.VolumesFrom, - Workdir: cc.Config.WorkingDir, - Net: &netInfo, + User: cc.Config.User, + UserNS: string(cc.HostConfig.UsernsMode), + UTS: string(cc.HostConfig.UTSMode), + Mount: mounts, + Volume: volumes, + VolumesFrom: cc.HostConfig.VolumesFrom, + Workdir: cc.Config.WorkingDir, + Net: &netInfo, + } + if !rootless.IsRootless() { + var ulimits []string + if len(cc.HostConfig.Ulimits) > 0 { + for _, ul := range cc.HostConfig.Ulimits { + ulimits = append(ulimits, ul.String()) + } + cliOpts.Ulimit = ulimits + } } if len(cc.HostConfig.BlkioWeightDevice) > 0 { @@ -377,7 +386,11 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig) (*Cont cliOpts.MemoryReservation = strconv.Itoa(int(cc.HostConfig.MemoryReservation)) } - if cc.HostConfig.MemorySwap > 0 { + cgroupsv2, err := cgroups.IsCgroup2UnifiedMode() + if err != nil { + return nil, nil, err + } + if cc.HostConfig.MemorySwap > 0 && (!rootless.IsRootless() || (rootless.IsRootless() && cgroupsv2)) { cliOpts.MemorySwap = strconv.Itoa(int(cc.HostConfig.MemorySwap)) } @@ -401,8 +414,10 @@ func ContainerCreateToContainerCLIOpts(cc handlers.CreateContainerConfig) (*Cont cliOpts.Restart = policy } - if cc.HostConfig.MemorySwappiness != nil { + if cc.HostConfig.MemorySwappiness != nil && (!rootless.IsRootless() || rootless.IsRootless() && cgroupsv2 && cgroupsManager == "systemd") { cliOpts.MemorySwappiness = *cc.HostConfig.MemorySwappiness + } else { + cliOpts.MemorySwappiness = -1 } if cc.HostConfig.OomKillDisable != nil { cliOpts.OOMKillDisable = *cc.HostConfig.OomKillDisable diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index 774b39d3a..7de6a7316 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -1,6 +1,7 @@ package images import ( + "fmt" "os" "text/tabwriter" "text/template" @@ -81,7 +82,7 @@ func init() { // searchFlags set the flags for the pull command. func searchFlags(flags *pflag.FlagSet) { flags.StringSliceVarP(&searchOptions.Filters, "filter", "f", []string{}, "Filter output based on conditions provided (default [])") - flags.StringVar(&searchOptions.Format, "format", "", "Change the output format to a Go template") + flags.StringVar(&searchOptions.Format, "format", "", "Change the output format to JSON or a Go template") flags.IntVar(&searchOptions.Limit, "limit", 0, "Limit the number of results") flags.BoolVar(&searchOptions.NoTrunc, "no-trunc", false, "Do not truncate the output") flags.StringVar(&searchOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") @@ -135,6 +136,13 @@ func imageSearch(cmd *cobra.Command, args []string) error { return errors.Errorf("filters are not applicable to list tags result") } row = "{{.Name}}\t{{.Tag}}\n" + case report.IsJSON(searchOptions.Format): + prettyJSON, err := json.MarshalIndent(searchReport, "", " ") + if err != nil { + return err + } + fmt.Println(string(prettyJSON)) + return nil case cmd.Flags().Changed("format"): renderHeaders = parse.HasTable(searchOptions.Format) row = report.NormalizeFormat(searchOptions.Format) diff --git a/docs/source/markdown/podman-import.1.md b/docs/source/markdown/podman-import.1.md index 946b680dd..b6d88aeac 100644 --- a/docs/source/markdown/podman-import.1.md +++ b/docs/source/markdown/podman-import.1.md @@ -22,6 +22,7 @@ Note: `:` is a restricted character and cannot be part of the file name. Apply the following possible instructions to the created image: **CMD** | **ENTRYPOINT** | **ENV** | **EXPOSE** | **LABEL** | **STOPSIGNAL** | **USER** | **VOLUME** | **WORKDIR** + Can be set multiple times **--message**, **-m**=*message* @@ -55,7 +56,7 @@ db65d991f3bbf7f31ed1064db9a6ced7652e3f8166c4736aa9133dadd3c7acb3 ``` ``` -$ podman import --change "ENTRYPOINT ["/bin/sh","-c","test-image"]" --change LABEL=blue=image test-image.tar image-imported +$ podman import --change 'ENTRYPOINT ["/bin/sh","-c","test-image"]' --change LABEL=blue=image test-image.tar image-imported Getting image source signatures Copying blob e3b0c44298fc skipped: already exists Copying config 1105523502 done diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md index 46beb4c42..9e3911704 100644 --- a/docs/source/markdown/podman-pull.1.md +++ b/docs/source/markdown/podman-pull.1.md @@ -120,6 +120,17 @@ Storing signatures ``` ``` +$ podman pull alpine@sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e +Trying to pull docker.io/library/alpine@sha256:d7342993700f8cd7aba8496c2d0e57be0666e80b4c441925fc6f9361fa81d10e... +Getting image source signatures +Copying blob 188c0c94c7c5 done +Copying config d6e46aa247 done +Writing manifest to image destination +Storing signatures +d6e46aa2470df1d32034c6707c8041158b652f38d2a9ae3d7ad7e7532d22ebe0 +``` + +``` $ podman pull --authfile temp-auths/myauths.json docker://docker.io/umohnani/finaltest Trying to pull docker.io/umohnani/finaltest:latest...Getting image source signatures Copying blob sha256:6d987f6f42797d81a318c40d442369ba3dc124883a0964d40b0c8f4f7561d913 diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go index 24e25f526..4efe770b3 100644 --- a/pkg/api/handlers/compat/containers_create.go +++ b/pkg/api/handlers/compat/containers_create.go @@ -38,6 +38,11 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { utils.Error(w, utils.ErrLinkNotSupport.Error(), http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter")) return } + rtc, err := runtime.GetConfig() + if err != nil { + utils.Error(w, "unable to obtain runtime config", http.StatusInternalServerError, errors.Wrap(err, "unable to get runtime config")) + } + newImage, err := runtime.ImageRuntime().NewFromLocal(input.Image) if err != nil { if errors.Cause(err) == define.ErrNoSuchImage { @@ -53,7 +58,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) { input.Name = query.Name // Take input structure and convert to cliopts - cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(input) + cliOpts, args, err := common.ContainerCreateToContainerCLIOpts(input, rtc.Engine.CgroupManager) if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "make cli opts()")) return diff --git a/pkg/bindings/containers/logs.go b/pkg/bindings/containers/logs.go index 750a6dbe1..a73517bac 100644 --- a/pkg/bindings/containers/logs.go +++ b/pkg/bindings/containers/logs.go @@ -1,7 +1,6 @@ package containers import ( - "bytes" "context" "fmt" "io" @@ -64,7 +63,6 @@ func Logs(ctx context.Context, nameOrID string, opts LogOptions, stdoutChan, std if err != nil { return err } - frame = bytes.Replace(frame[0:l], []byte{13}, []byte{10}, -1) switch fd { case 0: diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go index dc9e6b9d8..a0d36f865 100644 --- a/pkg/specgen/container_validate.go +++ b/pkg/specgen/container_validate.go @@ -1,11 +1,13 @@ package specgen import ( + "strconv" "strings" "github.com/containers/podman/v2/libpod/define" "github.com/containers/podman/v2/pkg/rootless" "github.com/containers/podman/v2/pkg/util" + "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" ) @@ -144,7 +146,38 @@ func (s *SpecGenerator) Validate() error { //default: // return errors.New("unrecognized option for cgroups; supported are 'default', 'disabled', 'no-conmon'") //} - + invalidUlimitFormatError := errors.New("invalid default ulimit definition must be form of type=soft:hard") + //set ulimits if not rootless + if len(s.ContainerResourceConfig.Rlimits) < 1 && !rootless.IsRootless() { + // Containers common defines this as something like nproc=4194304:4194304 + tmpnproc := containerConfig.Ulimits() + var posixLimits []specs.POSIXRlimit + for _, limit := range tmpnproc { + limitSplit := strings.SplitN(limit, "=", 2) + if len(limitSplit) < 2 { + return errors.Wrapf(invalidUlimitFormatError, "missing = in %s", limit) + } + valueSplit := strings.SplitN(limitSplit[1], ":", 2) + if len(valueSplit) < 2 { + return errors.Wrapf(invalidUlimitFormatError, "missing : in %s", limit) + } + hard, err := strconv.Atoi(valueSplit[0]) + if err != nil { + return err + } + soft, err := strconv.Atoi(valueSplit[1]) + if err != nil { + return err + } + posixLimit := specs.POSIXRlimit{ + Type: limitSplit[0], + Hard: uint64(hard), + Soft: uint64(soft), + } + posixLimits = append(posixLimits, posixLimit) + } + s.ContainerResourceConfig.Rlimits = posixLimits + } // Namespaces if err := s.UtsNS.validate(); err != nil { return err diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index 424a191c5..edd2fedad 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -116,6 +116,14 @@ registries = ['{{.Host}}:{{.Port}}']` Expect(search.LineInOutputContains("docker.io/library/alpine")).To(BeTrue()) }) + It("podman search format json", func() { + search := podmanTest.Podman([]string{"search", "--format", "json", "alpine"}) + search.WaitWithDefaultTimeout() + Expect(search.ExitCode()).To(Equal(0)) + Expect(search.IsJSONOutputValid()).To(BeTrue()) + Expect(search.OutputToString()).To(ContainSubstring("docker.io/library/alpine")) + }) + It("podman search no-trunc flag", func() { search := podmanTest.Podman([]string{"search", "--no-trunc", "alpine"}) search.WaitWithDefaultTimeout() |