summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/create.go12
-rw-r--r--cmd/podman/containers/create.go5
-rw-r--r--cmd/podman/containers/run.go4
-rw-r--r--cmd/podman/machine/list.go143
-rw-r--r--docs/README.md (renamed from docs/Readme.md)16
-rw-r--r--docs/source/machine.rst1
-rw-r--r--docs/source/markdown/links/podman-machine-ls.11
-rw-r--r--docs/source/markdown/podman-create.1.md2
-rw-r--r--docs/source/markdown/podman-machine-list.1.md50
-rw-r--r--docs/source/markdown/podman-machine.1.md11
-rw-r--r--docs/source/markdown/podman-run.1.md4
-rw-r--r--pkg/api/handlers/compat/containers_prune.go2
-rw-r--r--pkg/api/handlers/compat/containers_top.go10
-rw-r--r--pkg/bindings/connection.go32
-rw-r--r--pkg/bindings/test/containers_test.go15
-rw-r--r--pkg/domain/filters/containers.go37
-rw-r--r--pkg/domain/infra/abi/containers.go2
-rw-r--r--pkg/machine/config.go11
-rw-r--r--pkg/machine/fcos_arm64.go16
-rw-r--r--pkg/machine/qemu/machine.go54
-rw-r--r--test/apiv2/20-containers.at18
-rw-r--r--test/apiv2/25-containersMore.at3
22 files changed, 391 insertions, 58 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/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
new file mode 100644
index 000000000..3c8368c6b
--- /dev/null
+++ b/cmd/podman/machine/list.go
@@ -0,0 +1,143 @@
+// +build amd64,linux arm64,linux amd64,darwin arm64,darwin
+
+package machine
+
+import (
+ "os"
+ "sort"
+ "text/tabwriter"
+ "text/template"
+ "time"
+
+ "github.com/containers/common/pkg/completion"
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/common/pkg/report"
+ "github.com/containers/podman/v3/cmd/podman/parse"
+ "github.com/containers/podman/v3/cmd/podman/registry"
+ "github.com/containers/podman/v3/cmd/podman/validate"
+ "github.com/containers/podman/v3/pkg/domain/entities"
+ "github.com/containers/podman/v3/pkg/machine"
+ "github.com/containers/podman/v3/pkg/machine/qemu"
+ "github.com/docker/go-units"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ lsCmd = &cobra.Command{
+ Use: "list [options]",
+ Aliases: []string{"ls"},
+ Short: "List machines",
+ Long: "List Podman managed virtual machines.",
+ RunE: list,
+ Args: validate.NoArgs,
+ Example: `podman machine list,
+ podman machine ls`,
+ ValidArgsFunction: completion.AutocompleteNone,
+ }
+ listFlag = listFlagType{}
+)
+
+type listFlagType struct {
+ format string
+ noHeading bool
+}
+
+type machineReporter struct {
+ Name string
+ Created string
+ LastUp string
+ VMType string
+}
+
+func init() {
+ registry.Commands = append(registry.Commands, registry.CliCommand{
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
+ Command: lsCmd,
+ Parent: machineCmd,
+ })
+
+ flags := lsCmd.Flags()
+ formatFlagName := "format"
+ flags.StringVar(&listFlag.format, formatFlagName, "{{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\n", "Format volume output using Go template")
+ _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, completion.AutocompleteNone)
+}
+
+func list(cmd *cobra.Command, args []string) error {
+ var opts machine.ListOptions
+ // We only have qemu VM's for now
+ listResponse, err := qemu.List(opts)
+ if err != nil {
+ return errors.Wrap(err, "error listing vms")
+ }
+
+ // Sort by last run
+ sort.Slice(listResponse, func(i, j int) bool {
+ return listResponse[i].LastUp.After(listResponse[j].LastUp)
+ })
+ // Bring currently running machines to top
+ sort.Slice(listResponse, func(i, j int) bool {
+ return listResponse[i].Running
+ })
+ machineReporter, err := toHumanFormat(listResponse)
+ if err != nil {
+ return err
+ }
+
+ return outputTemplate(cmd, machineReporter)
+}
+
+func outputTemplate(cmd *cobra.Command, responses []*machineReporter) error {
+ headers := report.Headers(machineReporter{}, map[string]string{
+ "LastUp": "LAST UP",
+ "VmType": "VM TYPE",
+ })
+
+ row := report.NormalizeFormat(listFlag.format)
+ format := parse.EnforceRange(row)
+
+ tmpl, err := template.New("list machines").Parse(format)
+ if err != nil {
+ return err
+ }
+ w := tabwriter.NewWriter(os.Stdout, 12, 2, 2, ' ', 0)
+ defer w.Flush()
+
+ if cmd.Flags().Changed("format") && !parse.HasTable(listFlag.format) {
+ listFlag.noHeading = true
+ }
+
+ if !listFlag.noHeading {
+ if err := tmpl.Execute(w, headers); err != nil {
+ return errors.Wrapf(err, "failed to write report column headers")
+ }
+ }
+ return tmpl.Execute(w, responses)
+}
+
+func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
+ cfg, err := config.ReadCustomConfig()
+ if err != nil {
+ return nil, err
+ }
+
+ humanResponses := make([]*machineReporter, 0, len(vms))
+ for _, vm := range vms {
+ response := new(machineReporter)
+ if vm.Name == cfg.Engine.ActiveService {
+ response.Name = vm.Name + "*"
+ } else {
+ response.Name = vm.Name
+ }
+ if vm.Running {
+ response.LastUp = "Currently running"
+ } else {
+ response.LastUp = units.HumanDuration(time.Since(vm.LastUp)) + " ago"
+ }
+ response.Created = units.HumanDuration(time.Since(vm.CreatedAt)) + " ago"
+ response.VMType = vm.VMType
+
+ humanResponses = append(humanResponses, response)
+ }
+ return humanResponses, nil
+}
diff --git a/docs/Readme.md b/docs/README.md
index e0918cd54..83f5c79a3 100644
--- a/docs/Readme.md
+++ b/docs/README.md
@@ -52,3 +52,19 @@ likely caused by broken metadata needed to protect clients from cross-site-scrip
style attacks. Please [notify a maintainer](https://github.com/containers/podman#communications)
so they may investigate how/why the `swagger.yaml` file's CORS-metadata is
incorrect, or the file isn't accessible for some other reason.
+
+## Local Testing
+
+Assuming that you have the [dependencies](https://podman.io/getting-started/installation#build-and-run-dependencies)
+installed, then also install (showing Fedora in the example):
+
+```
+# dnf install python3-sphinx python3-recommonmark
+# pip install sphinx-markdown-tables
+```
+After that completes, cd to the `docs` directory in your Podman sandbox and then do `make html`.
+
+You can then preview the html files in `docs/build/html` with:
+```
+python -m http.server 8000 --directory build/html
+```
diff --git a/docs/source/machine.rst b/docs/source/machine.rst
index be9ef1e95..16c042173 100644
--- a/docs/source/machine.rst
+++ b/docs/source/machine.rst
@@ -3,6 +3,7 @@ Machine
:doc:`init <markdown/podman-machine-init.1>` Initialize a new virtual machine
+:doc:`list <markdown/podman-machine-list.1>` List virtual machines
:doc:`rm <markdown/podman-machine-rm.1>` Remove a virtual machine
:doc:`ssh <markdown/podman-machine-ssh.1>` SSH into a virtual machine
:doc:`start <markdown/podman-machine-start.1>` Start a virtual machine
diff --git a/docs/source/markdown/links/podman-machine-ls.1 b/docs/source/markdown/links/podman-machine-ls.1
new file mode 100644
index 000000000..f6acb7f74
--- /dev/null
+++ b/docs/source/markdown/links/podman-machine-ls.1
@@ -0,0 +1 @@
+.so man1/podman-machine-list.1
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-machine-list.1.md b/docs/source/markdown/podman-machine-list.1.md
new file mode 100644
index 000000000..bd5608258
--- /dev/null
+++ b/docs/source/markdown/podman-machine-list.1.md
@@ -0,0 +1,50 @@
+% podman-machine-ls(1)
+
+## NAME
+podman\-machine\-list - List virtual machines
+
+## SYNOPSIS
+**podman machine list** [*options*]
+
+**podman machine ls** [*options*]
+
+## DESCRIPTION
+
+List Podman managed virtual machines.
+
+Podman on macOS requires a virtual machine. This is because containers are Linux -
+containers do not run on any other OS because containers' core functionality is
+tied to the Linux kernel.
+
+## OPTIONS
+
+#### **\-\-format**=*format*
+
+Format list output using a Go template.
+
+Valid placeholders for the Go template are listed below:
+
+| **Placeholder** | **Description** |
+| --------------- | ------------------------------- |
+| .Name | VM name |
+| .Created | Time since VM creation |
+| .LastUp | Time since the VM was last run |
+| .VMType | VM type |
+
+#### **\-\-help**
+
+Print usage statement.
+
+## EXAMPLES
+
+```
+$ podman machine list
+
+$ podman machine ls --format {{.Name}}\t{{.VMType}}\t{{.Created}}\t{{.LastUp}}\n
+```
+
+## SEE ALSO
+podman-machine(1)
+
+## HISTORY
+March 2021, Originally compiled by Ashley Cui <acui@redhat.com>
diff --git a/docs/source/markdown/podman-machine.1.md b/docs/source/markdown/podman-machine.1.md
index a5d3b78df..693f42fe3 100644
--- a/docs/source/markdown/podman-machine.1.md
+++ b/docs/source/markdown/podman-machine.1.md
@@ -14,13 +14,14 @@ podman\-machine - Manage Podman's virtual machine
| Command | Man Page | Description |
| ------- | ------------------------------------------------------- | --------------------------------- |
| init | [podman-machine-init(1)](podman-machine-init.1.md) | Initialize a new virtual machine |
-| rm | [podman-machine-rm(1)](podman-machine-rm.1.md)| Remove a virtual machine |
-| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
-| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
-| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
+| list | [podman-machine-list(1)](podman-machine-list.1.md) | List virtual machines |
+| rm | [podman-machine-rm(1)](podman-machine-rm.1.md) | Remove a virtual machine |
+| ssh | [podman-machine-ssh(1)](podman-machine-ssh.1.md) | SSH into a virtual machine |
+| start | [podman-machine-start(1)](podman-machine-start.1.md) | Start a virtual machine |
+| stop | [podman-machine-stop(1)](podman-machine-stop.1.md) | Stop a virtual machine |
## SEE ALSO
-podman(1)
+podman(1), podman-machine-init(1), podman-machine-list(1), podman-machine-rm(1), podman-machine-ssh(1), podman-machine-start(1), podman-machine-stop(1)
## HISTORY
March 2021, Originally compiled by Ashley Cui <acui@redhat.com>
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/config.go b/pkg/machine/config.go
index 273deca00..554ea7c97 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -5,6 +5,7 @@ import (
"net/url"
"os"
"path/filepath"
+ "time"
"github.com/containers/storage/pkg/homedir"
"github.com/pkg/errors"
@@ -44,6 +45,16 @@ type Download struct {
VMName string
}
+type ListOptions struct{}
+
+type ListResponse struct {
+ Name string
+ CreatedAt time.Time
+ LastUp time.Time
+ Running bool
+ VMType string
+}
+
type SSHOptions struct {
Execute bool
Args []string
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 426d46208..b48926524 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"strconv"
+ "strings"
"time"
"github.com/containers/podman/v3/pkg/machine"
@@ -78,7 +79,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")
@@ -91,7 +92,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
@@ -443,3 +444,52 @@ func getDiskSize(path string) (uint64, error) {
}
return tmpInfo.VirtualSize, nil
}
+
+// List lists all vm's that use qemu virtualization
+func List(opts machine.ListOptions) ([]*machine.ListResponse, error) {
+ vmConfigDir, err := machine.GetConfDir(vmtype)
+ if err != nil {
+ return nil, err
+ }
+
+ var listed []*machine.ListResponse
+
+ if err = filepath.Walk(vmConfigDir, func(path string, info os.FileInfo, err error) error {
+ vm := new(MachineVM)
+ if strings.HasSuffix(info.Name(), ".json") {
+ fullPath := filepath.Join(vmConfigDir, info.Name())
+ b, err := ioutil.ReadFile(fullPath)
+ if err != nil {
+ return err
+ }
+ err = json.Unmarshal(b, vm)
+ if err != nil {
+ return err
+ }
+ listEntry := new(machine.ListResponse)
+
+ listEntry.Name = vm.Name
+ listEntry.VMType = "qemu"
+ fi, err := os.Stat(fullPath)
+ if err != nil {
+ return err
+ }
+ listEntry.CreatedAt = fi.ModTime()
+
+ fi, err = os.Stat(vm.ImagePath)
+ if err != nil {
+ return err
+ }
+ listEntry.LastUp = fi.ModTime()
+ if vm.isRunning() {
+ listEntry.Running = true
+ }
+
+ listed = append(listed, listEntry)
+ }
+ return nil
+ }); err != nil {
+ return nil, err
+ }
+ return listed, err
+}
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