diff options
-rw-r--r-- | cmd/podman/common/create.go | 12 | ||||
-rw-r--r-- | cmd/podman/containers/create.go | 5 | ||||
-rw-r--r-- | cmd/podman/containers/run.go | 4 | ||||
-rw-r--r-- | docs/source/markdown/podman-create.1.md | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 4 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_prune.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_top.go | 10 | ||||
-rw-r--r-- | pkg/bindings/connection.go | 32 | ||||
-rw-r--r-- | pkg/bindings/test/containers_test.go | 15 | ||||
-rw-r--r-- | pkg/domain/filters/containers.go | 37 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 2 | ||||
-rw-r--r-- | pkg/machine/fcos_arm64.go | 16 | ||||
-rw-r--r-- | pkg/machine/qemu/machine.go | 4 | ||||
-rw-r--r-- | test/apiv2/20-containers.at | 18 | ||||
-rw-r--r-- | test/apiv2/25-containersMore.at | 3 |
15 files changed, 113 insertions, 53 deletions
diff --git a/cmd/podman/common/create.go b/cmd/podman/common/create.go index d1170710b..dda709ecd 100644 --- a/cmd/podman/common/create.go +++ b/cmd/podman/common/create.go @@ -765,11 +765,15 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) { ) _ = cmd.RegisterFlagCompletionFunc(mountFlagName, AutocompleteMountFlag) + volumeDesciption := "Bind mount a volume into the container" + if registry.IsRemote() { + volumeDesciption = "Bind mount a volume into the container. Volume src will be on the server machine, not the client" + } volumeFlagName := "volume" createFlags.StringArrayVarP( &cf.Volume, volumeFlagName, "v", volumes(), - "Bind mount a volume into the container", + volumeDesciption, ) _ = cmd.RegisterFlagCompletionFunc(volumeFlagName, AutocompleteVolumeFlag) @@ -804,4 +808,10 @@ func DefineCreateFlags(cmd *cobra.Command, cf *ContainerCLIOpts) { "Configure cgroup v2 (key=value)", ) _ = cmd.RegisterFlagCompletionFunc(cgroupConfFlagName, completion.AutocompleteNone) + + _ = createFlags.MarkHidden("signature-policy") + if registry.IsRemote() { + _ = createFlags.MarkHidden("env-host") + _ = createFlags.MarkHidden("http-proxy") + } } diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index af9278ce1..2da9aaf5e 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -63,11 +63,6 @@ func createFlags(cmd *cobra.Command) { common.DefineNetFlags(cmd) flags.SetNormalizeFunc(utils.AliasFlags) - - _ = flags.MarkHidden("signature-policy") - if registry.IsRemote() { - _ = flags.MarkHidden("http-proxy") - } } func init() { diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index db7180ca9..1a9fa2f0f 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -76,13 +76,11 @@ func runFlags(cmd *cobra.Command) { detachKeysFlagName := "detach-keys" flags.StringVar(&runOpts.DetachKeys, detachKeysFlagName, containerConfig.DetachKeys(), "Override the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-<value>`, where `<value>` is one of: `a-cf`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") _ = cmd.RegisterFlagCompletionFunc(detachKeysFlagName, common.AutocompleteDetachKeys) - - _ = flags.MarkHidden("signature-policy") if registry.IsRemote() { - _ = flags.MarkHidden("http-proxy") _ = flags.MarkHidden("preserve-fds") } } + func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 9ae4ab207..f56319cf3 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -1029,7 +1029,7 @@ Create a bind mount. If you specify, ` -v /HOST-DIR:/CONTAINER-DIR`, Podman bind mounts `/HOST-DIR` in the host to `/CONTAINER-DIR` in the Podman container. Similarly, `-v SOURCE-VOLUME:/CONTAINER-DIR` will mount the volume in the host to the container. If no such named volume exists, Podman will -create one. The `OPTIONS` are a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup> +create one. The `OPTIONS` are a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup> (Note when using the remote client, the volumes will be mounted from the remote server, not necessarly the client machine.) The _options_ is a comma delimited list and can be: diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 6d9d5ba28..fcb5a13ec 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -744,7 +744,7 @@ If a container is run within a pod, and the pod has an infra-container, the infr #### **\-\-preserve-fds**=*N* Pass down to the process N additional file descriptors (in addition to 0, 1, 2). -The total FDs will be 3+N. +The total FDs will be 3+N. (This option is not available with the remote Podman client) #### **\-\-privileged**=**true**|**false** @@ -1104,7 +1104,7 @@ Create a bind mount. If you specify _/HOST-DIR_:_/CONTAINER-DIR_, Podman bind mounts _host-dir_ in the host to _CONTAINER-DIR_ in the Podman container. Similarly, _SOURCE-VOLUME_:_/CONTAINER-DIR_ will mount the volume in the host to the container. If no such named volume exists, Podman will -create one. +create one. (Note when using the remote client, the volumes will be mounted from the remote server, not necessarly the client machine.) The _options_ is a comma delimited list and can be: <sup>[[1]](#Footnote1)</sup> diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go index e37929d27..61ea7a89e 100644 --- a/pkg/api/handlers/compat/containers_prune.go +++ b/pkg/api/handlers/compat/containers_prune.go @@ -23,7 +23,7 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) { filterFuncs := make([]libpod.ContainerFilter, 0, len(*filtersMap)) for k, v := range *filtersMap { - generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime) + generatedFunc, err := filters.GeneratePruneContainerFilterFuncs(k, v, runtime) if err != nil { utils.InternalServerError(w, err) return diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go index ab9f613af..cae044a89 100644 --- a/pkg/api/handlers/compat/containers_top.go +++ b/pkg/api/handlers/compat/containers_top.go @@ -46,8 +46,16 @@ func TopContainer(w http.ResponseWriter, r *http.Request) { var body = handlers.ContainerTopOKBody{} if len(output) > 0 { body.Titles = strings.Split(output[0], "\t") + for i := range body.Titles { + body.Titles[i] = strings.TrimSpace(body.Titles[i]) + } + for _, line := range output[1:] { - body.Processes = append(body.Processes, strings.Split(line, "\t")) + process := strings.Split(line, "\t") + for i := range process { + process[i] = strings.TrimSpace(process[i]) + } + body.Processes = append(body.Processes, process) } } utils.WriteJSON(w, http.StatusOK, body) diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go index 21a8e7a8b..fd93c5ac7 100644 --- a/pkg/bindings/connection.go +++ b/pkg/bindings/connection.go @@ -22,14 +22,6 @@ import ( "golang.org/x/crypto/ssh/agent" ) -var ( - BasePath = &url.URL{ - Scheme: "http", - Host: "d", - Path: "/v" + version.APIVersion[version.Libpod][version.CurrentAPI].String() + "/libpod", - } -) - type APIResponse struct { *http.Response Request *http.Request @@ -318,16 +310,24 @@ func (c *Connection) DoRequest(httpBody io.Reader, httpMethod, endpoint string, err error response *http.Response ) - safePathValues := make([]interface{}, len(pathValues)) - // Make sure path values are http url safe + + params := make([]interface{}, len(pathValues)+3) + + // Including the semver suffices breaks older services... so do not include them + v := version.APIVersion[version.Libpod][version.CurrentAPI] + params[0] = v.Major + params[1] = v.Minor + params[2] = v.Patch for i, pv := range pathValues { - safePathValues[i] = url.PathEscape(pv) + // url.URL lacks the semantics for escaping embedded path parameters... so we manually + // escape each one and assume the caller included the correct formatting in "endpoint" + params[i+3] = url.PathEscape(pv) } - // Lets eventually use URL for this which might lead to safer - // usage - safeEndpoint := fmt.Sprintf(endpoint, safePathValues...) - e := BasePath.String() + safeEndpoint - req, err := http.NewRequest(httpMethod, e, httpBody) + + uri := fmt.Sprintf("http://d/v%d.%d.%d/libpod"+endpoint, params...) + logrus.Debugf("DoRequest Method: %s URI: %v", httpMethod, uri) + + req, err := http.NewRequest(httpMethod, uri, httpBody) if err != nil { return nil, err } diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go index b0ddc7862..cb9e0721b 100644 --- a/pkg/bindings/test/containers_test.go +++ b/pkg/bindings/test/containers_test.go @@ -550,21 +550,28 @@ var _ = Describe("Podman containers ", func() { filtersIncorrect := map[string][]string{ "status": {"dummy"}, } - pruneResponse, err := containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filtersIncorrect)) + _, err = containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filtersIncorrect)) + Expect(err).ToNot(BeNil()) + + // List filter params should not work with prune. + filtersIncorrect = map[string][]string{ + "name": {"top"}, + } + _, err = containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filtersIncorrect)) Expect(err).ToNot(BeNil()) // Mismatched filter params no container should be pruned. filtersIncorrect = map[string][]string{ - "name": {"r"}, + "label": {"xyz"}, } - pruneResponse, err = containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filtersIncorrect)) + pruneResponse, err := containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filtersIncorrect)) Expect(err).To(BeNil()) Expect(len(reports.PruneReportsIds(pruneResponse))).To(Equal(0)) Expect(len(reports.PruneReportsErrs(pruneResponse))).To(Equal(0)) // Valid filter params container should be pruned now. filters := map[string][]string{ - "name": {"top"}, + "until": {"0s"}, } pruneResponse, err = containers.Prune(bt.conn, new(containers.PruneOptions).WithFilters(filters)) Expect(err).To(BeNil()) diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go index 84cf03764..19d704da1 100644 --- a/pkg/domain/filters/containers.go +++ b/pkg/domain/filters/containers.go @@ -165,16 +165,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo return false }, nil case "until": - until, err := util.ComputeUntilTimestamp(filterValues) - if err != nil { - return nil, err - } - return func(c *libpod.Container) bool { - if !until.IsZero() && c.CreatedTime().After((until)) { - return true - } - return false - }, nil + return prepareUntilFilterFunc(filterValues) case "pod": var pods []*libpod.Pod for _, podNameOrID := range filterValues { @@ -226,3 +217,29 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo } return nil, errors.Errorf("%s is an invalid filter", filter) } + +// GeneratePruneContainerFilterFuncs return ContainerFilter functions based of filter for prune operation +func GeneratePruneContainerFilterFuncs(filter string, filterValues []string, r *libpod.Runtime) (func(container *libpod.Container) bool, error) { + switch filter { + case "label": + return func(c *libpod.Container) bool { + return util.MatchLabelFilters(filterValues, c.Labels()) + }, nil + case "until": + return prepareUntilFilterFunc(filterValues) + } + return nil, errors.Errorf("%s is an invalid filter", filter) +} + +func prepareUntilFilterFunc(filterValues []string) (func(container *libpod.Container) bool, error) { + until, err := util.ComputeUntilTimestamp(filterValues) + if err != nil { + return nil, err + } + return func(c *libpod.Container) bool { + if !until.IsZero() && c.CreatedTime().After((until)) { + return true + } + return false + }, nil +} diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 637531ee9..24261e5ed 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -194,7 +194,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) ([]*reports.PruneReport, error) { filterFuncs := make([]libpod.ContainerFilter, 0, len(options.Filters)) for k, v := range options.Filters { - generatedFunc, err := dfilters.GenerateContainerFilterFuncs(k, v, ic.Libpod) + generatedFunc, err := dfilters.GeneratePruneContainerFilterFuncs(k, v, ic.Libpod) if err != nil { return nil, err } diff --git a/pkg/machine/fcos_arm64.go b/pkg/machine/fcos_arm64.go index 4d7e4e4db..f5cd5a505 100644 --- a/pkg/machine/fcos_arm64.go +++ b/pkg/machine/fcos_arm64.go @@ -2,9 +2,9 @@ package machine import ( "encoding/json" - "fmt" "io/ioutil" "net/http" + url2 "net/url" "github.com/sirupsen/logrus" ) @@ -14,9 +14,7 @@ const aarchBaseURL = "https://fedorapeople.org/groups/fcos-images/builds/latest/ // Total hack until automation is possible. // We need a proper json file at least to automate func getFCOSDownload() (*fcosDownloadInfo, error) { - meta := Build{} - fmt.Println(aarchBaseURL + "meta.json") resp, err := http.Get(aarchBaseURL + "meta.json") if err != nil { return nil, err @@ -33,8 +31,18 @@ func getFCOSDownload() (*fcosDownloadInfo, error) { if err := json.Unmarshal(body, &meta); err != nil { return nil, err } + pathURL, err := url2.Parse(meta.BuildArtifacts.Qemu.Path) + if err != nil { + return nil, err + } + + baseURL, err := url2.Parse(aarchBaseURL) + if err != nil { + return nil, err + } + pullURL := baseURL.ResolveReference(pathURL) return &fcosDownloadInfo{ - Location: aarchBaseURL + "/" + meta.BuildArtifacts.Qemu.Path, + Location: pullURL.String(), Release: "", Sha256Sum: meta.BuildArtifacts.Qemu.Sha256, }, nil diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index 58486fc73..b4427f160 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -83,7 +83,7 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) { return nil, err } vm.QMPMonitor = monitor - cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address + ",server,nowait"}...) + cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address + ",server=on,wait=off"}...) // Add network cmd = append(cmd, "-nic", "user,model=virtio,hostfwd=tcp::"+strconv.Itoa(vm.Port)+"-:22") @@ -96,7 +96,7 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) { // Add serial port for readiness cmd = append(cmd, []string{ "-device", "virtio-serial", - "-chardev", "socket,path=" + virtualSocketPath + ",server,nowait,id=" + vm.Name + "_ready", + "-chardev", "socket,path=" + virtualSocketPath + ",server=on,wait=off,id=" + vm.Name + "_ready", "-device", "virtserialport,chardev=" + vm.Name + "_ready" + ",name=org.fedoraproject.port.0"}...) vm.CmdLine = cmd return vm, nil diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 9030f0095..58b2dff0a 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -298,7 +298,7 @@ t POST containers/prune?filters='garb1age}' 500 \ t POST libpod/containers/prune?filters='garb1age}' 500 \ .cause="invalid character 'g' looking for beginning of value" -## Prune containers with illformed label +# Prune containers with illformed label t POST containers/prune?filters='{"label":["tes' 500 \ .cause="unexpected end of JSON input" t POST libpod/containers/prune?filters='{"label":["tes' 500 \ @@ -306,6 +306,22 @@ t POST libpod/containers/prune?filters='{"label":["tes' 500 \ t GET libpod/containers/json?filters='{"label":["testlabel"]}' 200 length=0 +# libpod api: do not use list filters for prune +t POST libpod/containers/prune?filters='{"name":["anyname"]}' 500 \ + .cause="name is an invalid filter" +t POST libpod/containers/prune?filters='{"id":["anyid"]}' 500 \ + .cause="id is an invalid filter" +t POST libpod/containers/prune?filters='{"network":["anynetwork"]}' 500 \ + .cause="network is an invalid filter" + +# compat api: do not use list filters for prune +t POST containers/prune?filters='{"name":["anyname"]}' 500 \ + .cause="name is an invalid filter" +t POST containers/prune?filters='{"id":["anyid"]}' 500 \ + .cause="id is an invalid filter" +t POST containers/prune?filters='{"network":["anynetwork"]}' 500 \ + .cause="network is an invalid filter" + # Test CPU limit (NanoCPUs) t POST containers/create Image=$IMAGE HostConfig='{"NanoCpus":500000}' 201 \ .Id~[0-9a-f]\\{64\\} diff --git a/test/apiv2/25-containersMore.at b/test/apiv2/25-containersMore.at index 39bfa2e32..0a049d869 100644 --- a/test/apiv2/25-containersMore.at +++ b/test/apiv2/25-containersMore.at @@ -38,7 +38,8 @@ t GET libpod/containers/foo/json 200 \ # List processes of the container t GET libpod/containers/foo/top 200 \ - length=2 + length=2 \ + .Processes[0][7]="top" # List processes of none such t GET libpod/containers/nonesuch/top 404 |