automation-tests/cmd/podman/machine/list.go

144 lines
3.6 KiB
Go

// +build amd64,linux arm64,linux amd64,darwin arm64,darwin
package machine
import (
"os"
"sort"
"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/registry"
"github.com/containers/podman/v3/cmd/podman/validate"
"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 managed virtual machines.",
RunE: list,
Args: validate.NoArgs,
ValidArgsFunction: completion.AutocompleteNone,
Example: `podman machine list,
podman machine ls`,
}
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{
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)
flags.BoolVar(&listFlag.noHeading, "noheading", false, "Do not print headers")
}
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 := report.EnforceRange(row)
tmpl, err := report.NewTemplate("list").Parse(format)
if err != nil {
return err
}
w, err := report.NewWriterDefault(os.Stdout)
if err != nil {
return err
}
defer w.Flush()
if cmd.Flags().Changed("format") && !report.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
}