Enable pod ps integration tests

Enable integration tests for pod ps.

In addition, fixed bug where output was still using slice go template routines and would fail when no infra container was present.  Added integration test to prevent future regressions.

Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
Brent Baude 2020-04-25 13:11:08 -05:00
parent 2afe579c06
commit 942a3ef588
3 changed files with 112 additions and 23 deletions

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"sort"
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"text/template" "text/template"
@ -32,7 +33,7 @@ var (
var ( var (
defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED" defaultHeaders string = "POD ID\tNAME\tSTATUS\tCREATED"
inputFilters string inputFilters []string
noTrunc bool noTrunc bool
psInput entities.PodPSOptions psInput entities.PodPSOptions
) )
@ -48,7 +49,7 @@ func init() {
flags.BoolVar(&psInput.CtrIds, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated") flags.BoolVar(&psInput.CtrIds, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated")
flags.BoolVar(&psInput.CtrStatus, "ctr-status", false, "Display the container status") flags.BoolVar(&psInput.CtrStatus, "ctr-status", false, "Display the container status")
// TODO should we make this a [] ? // TODO should we make this a [] ?
flags.StringVarP(&inputFilters, "filter", "f", "", "Filter output based on conditions given") flags.StringSliceVarP(&inputFilters, "filter", "f", []string{}, "Filter output based on conditions given")
flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template") flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template")
flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod") flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod")
@ -67,8 +68,13 @@ func pods(cmd *cobra.Command, args []string) error {
row string row string
lpr []ListPodReporter lpr []ListPodReporter
) )
if psInput.Quiet && len(psInput.Format) > 0 {
return errors.New("quiet and format cannot be used together")
}
if cmd.Flag("filter").Changed { if cmd.Flag("filter").Changed {
for _, f := range strings.Split(inputFilters, ",") { psInput.Filters = make(map[string][]string)
for _, f := range inputFilters {
split := strings.Split(f, "=") split := strings.Split(f, "=")
if len(split) < 2 { if len(split) < 2 {
return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f) return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
@ -81,6 +87,10 @@ func pods(cmd *cobra.Command, args []string) error {
return err return err
} }
if err := sortPodPsOutput(psInput.Sort, responses); err != nil {
return err
}
if psInput.Format == "json" { if psInput.Format == "json" {
b, err := json.MarshalIndent(responses, "", " ") b, err := json.MarshalIndent(responses, "", " ")
if err != nil { if err != nil {
@ -95,11 +105,7 @@ func pods(cmd *cobra.Command, args []string) error {
} }
headers, row := createPodPsOut() headers, row := createPodPsOut()
if psInput.Quiet { if psInput.Quiet {
if noTrunc { row = "{{.Id}}\n"
row = "{{.Id}}\n"
} else {
row = "{{slice .Id 0 12}}\n"
}
} }
if cmd.Flag("format").Changed { if cmd.Flag("format").Changed {
row = psInput.Format row = psInput.Format
@ -130,11 +136,7 @@ func pods(cmd *cobra.Command, args []string) error {
func createPodPsOut() (string, string) { func createPodPsOut() (string, string) {
var row string var row string
headers := defaultHeaders headers := defaultHeaders
if noTrunc { row += "{{.Id}}"
row += "{{.Id}}"
} else {
row += "{{slice .Id 0 12}}"
}
row += "\t{{.Name}}\t{{.Status}}\t{{.Created}}" row += "\t{{.Name}}\t{{.Status}}\t{{.Created}}"
@ -160,11 +162,7 @@ func createPodPsOut() (string, string) {
} }
headers += "\tINFRA ID\n" headers += "\tINFRA ID\n"
if noTrunc { row += "\t{{.InfraId}}\n"
row += "\t{{.InfraId}}\n"
} else {
row += "\t{{slice .InfraId 0 12}}\n"
}
return headers, row return headers, row
} }
@ -184,6 +182,19 @@ func (l ListPodReporter) NumberOfContainers() int {
return len(l.Containers) return len(l.Containers)
} }
// ID is a wrapper to Id for compat, typos
func (l ListPodReporter) ID() string {
return l.Id()
}
// Id returns the Pod id
func (l ListPodReporter) Id() string {
if noTrunc {
return l.ListPodsReport.Id
}
return l.ListPodsReport.Id[0:12]
}
// Added for backwards compatibility with podmanv1 // Added for backwards compatibility with podmanv1
func (l ListPodReporter) InfraID() string { func (l ListPodReporter) InfraID() string {
return l.InfraId() return l.InfraId()
@ -192,6 +203,9 @@ func (l ListPodReporter) InfraID() string {
// InfraId returns the infra container id for the pod // InfraId returns the infra container id for the pod
// depending on trunc // depending on trunc
func (l ListPodReporter) InfraId() string { func (l ListPodReporter) InfraId() string {
if len(l.ListPodsReport.InfraId) == 0 {
return ""
}
if noTrunc { if noTrunc {
return l.ListPodsReport.InfraId return l.ListPodsReport.InfraId
} }
@ -225,3 +239,52 @@ func (l ListPodReporter) ContainerStatuses() string {
} }
return strings.Join(statuses, ",") return strings.Join(statuses, ",")
} }
func sortPodPsOutput(sortBy string, lprs []*entities.ListPodsReport) error {
switch sortBy {
case "created":
sort.Sort(podPsSortedCreated{lprs})
case "id":
sort.Sort(podPsSortedId{lprs})
case "name":
sort.Sort(podPsSortedName{lprs})
case "number":
sort.Sort(podPsSortedNumber{lprs})
case "status":
sort.Sort(podPsSortedStatus{lprs})
default:
return errors.Errorf("invalid option for --sort, options are: id, names, or number")
}
return nil
}
type lprSort []*entities.ListPodsReport
func (a lprSort) Len() int { return len(a) }
func (a lprSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
type podPsSortedCreated struct{ lprSort }
func (a podPsSortedCreated) Less(i, j int) bool {
return a.lprSort[i].Created.After(a.lprSort[j].Created)
}
type podPsSortedId struct{ lprSort }
func (a podPsSortedId) Less(i, j int) bool { return a.lprSort[i].Id < a.lprSort[j].Id }
type podPsSortedNumber struct{ lprSort }
func (a podPsSortedNumber) Less(i, j int) bool {
return len(a.lprSort[i].Containers) < len(a.lprSort[j].Containers)
}
type podPsSortedName struct{ lprSort }
func (a podPsSortedName) Less(i, j int) bool { return a.lprSort[i].Name < a.lprSort[j].Name }
type podPsSortedStatus struct{ lprSort }
func (a podPsSortedStatus) Less(i, j int) bool {
return a.lprSort[i].Status < a.lprSort[j].Status
}

View File

@ -292,9 +292,12 @@ func (ic *ContainerEngine) PodTop(ctx context.Context, options entities.PodTopOp
func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) { func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOptions) ([]*entities.ListPodsReport, error) {
var ( var (
err error
filters []libpod.PodFilter filters []libpod.PodFilter
pds []*libpod.Pod
reports []*entities.ListPodsReport reports []*entities.ListPodsReport
) )
for k, v := range options.Filters { for k, v := range options.Filters {
for _, filter := range v { for _, filter := range v {
f, err := lpfilters.GeneratePodFilterFunc(k, filter) f, err := lpfilters.GeneratePodFilterFunc(k, filter)
@ -305,10 +308,19 @@ func (ic *ContainerEngine) PodPs(ctx context.Context, options entities.PodPSOpti
} }
} }
pds, err := ic.Libpod.Pods(filters...) if options.Latest {
if err != nil { pod, err := ic.Libpod.GetLatestPod()
return nil, err if err != nil {
return nil, err
}
pds = append(pds, pod)
} else {
pds, err = ic.Libpod.Pods(filters...)
if err != nil {
return nil, err
}
} }
for _, p := range pds { for _, p := range pds {
var lpcs []*entities.ListPodContainer var lpcs []*entities.ListPodContainer
status, err := p.GetPodStatus() status, err := p.GetPodStatus()

View File

@ -18,7 +18,6 @@ var _ = Describe("Podman ps", func() {
) )
BeforeEach(func() { BeforeEach(func() {
Skip(v2fail)
tempdir, err = CreateTempDirInTempDir() tempdir, err = CreateTempDirInTempDir()
if err != nil { if err != nil {
os.Exit(1) os.Exit(1)
@ -96,6 +95,7 @@ var _ = Describe("Podman ps", func() {
Expect(result.OutputToString()).To(ContainSubstring(podid2)) Expect(result.OutputToString()).To(ContainSubstring(podid2))
Expect(result.OutputToString()).To(Not(ContainSubstring(podid1))) Expect(result.OutputToString()).To(Not(ContainSubstring(podid1)))
}) })
It("podman pod ps id filter flag", func() { It("podman pod ps id filter flag", func() {
_, ec, podid := podmanTest.CreatePod("") _, ec, podid := podmanTest.CreatePod("")
Expect(ec).To(Equal(0)) Expect(ec).To(Equal(0))
@ -143,7 +143,7 @@ var _ = Describe("Podman ps", func() {
_, ec, _ = podmanTest.RunLsContainerInPod("test2", podid) _, ec, _ = podmanTest.RunLsContainerInPod("test2", podid)
Expect(ec).To(Equal(0)) Expect(ec).To(Equal(0))
session = podmanTest.Podman([]string{"pod", "ps", "--format={{.ContainerInfo}}", "--ctr-names"}) session = podmanTest.Podman([]string{"pod", "ps", "--format={{.ContainerNames}}", "--ctr-names"})
session.WaitWithDefaultTimeout() session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0)) Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("test1")) Expect(session.OutputToString()).To(ContainSubstring("test1"))
@ -228,4 +228,18 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(ContainSubstring(podid2)) Expect(session.OutputToString()).To(ContainSubstring(podid2))
Expect(session.OutputToString()).To(Not(ContainSubstring(podid3))) Expect(session.OutputToString()).To(Not(ContainSubstring(podid3)))
}) })
It("pod no infra should ps", func() {
session := podmanTest.Podman([]string{"pod", "create", "--infra=false"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ps := podmanTest.Podman([]string{"pod", "ps"})
ps.WaitWithDefaultTimeout()
Expect(ps.ExitCode()).To(Equal(0))
infra := podmanTest.Podman([]string{"pod", "ps", "--format", "{{.InfraId}}"})
infra.WaitWithDefaultTimeout()
Expect(len(infra.OutputToString())).To(BeZero())
})
}) })