Support --format tables in ps output
- Added tests to help ensure there is no future regressions - Added WaitWithTimeout(int) rather than calling WaitWithDefaultTimeout() multiple times - Exposed DefaultWaitTimeout to allow test to use a multiplier Fixes #2221 Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
		
							parent
							
								
									7e8ce73c15
								
							
						
					
					
						commit
						8453c8ce63
					
				|  | @ -221,7 +221,10 @@ func ps(cmd *cobra.Command, _ []string) error { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	hdrs, format := createPsOut() | 	hdrs, format := createPsOut() | ||||||
|  | 
 | ||||||
|  | 	noHeading, _ := cmd.Flags().GetBool("noheading") | ||||||
| 	if cmd.Flags().Changed("format") { | 	if cmd.Flags().Changed("format") { | ||||||
|  | 		noHeading = noHeading || !report.HasTable(listOpts.Format) | ||||||
| 		format = report.NormalizeFormat(listOpts.Format) | 		format = report.NormalizeFormat(listOpts.Format) | ||||||
| 		format = report.EnforceRange(format) | 		format = report.EnforceRange(format) | ||||||
| 	} | 	} | ||||||
|  | @ -240,8 +243,7 @@ func ps(cmd *cobra.Command, _ []string) error { | ||||||
| 	defer w.Flush() | 	defer w.Flush() | ||||||
| 
 | 
 | ||||||
| 	headers := func() error { return nil } | 	headers := func() error { return nil } | ||||||
| 	noHeading, _ := cmd.Flags().GetBool("noheading") | 	if !noHeading { | ||||||
| 	if !(noHeading || listOpts.Quiet || cmd.Flags().Changed("format")) { |  | ||||||
| 		headers = func() error { | 		headers = func() error { | ||||||
| 			return tmpl.Execute(w, hdrs) | 			return tmpl.Execute(w, hdrs) | ||||||
| 		} | 		} | ||||||
|  | @ -298,9 +300,11 @@ func createPsOut() ([]map[string]string, string) { | ||||||
| 		"IPC":          "ipc", | 		"IPC":          "ipc", | ||||||
| 		"MNT":          "mnt", | 		"MNT":          "mnt", | ||||||
| 		"NET":          "net", | 		"NET":          "net", | ||||||
|  | 		"Networks":     "networks", | ||||||
| 		"PIDNS":        "pidns", | 		"PIDNS":        "pidns", | ||||||
| 		"Pod":          "pod id", | 		"Pod":          "pod id", | ||||||
| 		"PodName":      "podname", // undo camelcase space break
 | 		"PodName":      "podname", // undo camelcase space break
 | ||||||
|  | 		"RunningFor":   "running for", | ||||||
| 		"UTS":          "uts", | 		"UTS":          "uts", | ||||||
| 		"User":         "userns", | 		"User":         "userns", | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ import ( | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"sort" | 	"sort" | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"strings" |  | ||||||
| 
 | 
 | ||||||
| 	. "github.com/containers/podman/v3/test/utils" | 	. "github.com/containers/podman/v3/test/utils" | ||||||
| 	"github.com/containers/storage/pkg/stringid" | 	"github.com/containers/storage/pkg/stringid" | ||||||
|  | @ -187,7 +186,10 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 		Expect(result).Should(Exit(0)) | 		Expect(result).Should(Exit(0)) | ||||||
| 		Expect(result.OutputToString()).To(ContainSubstring("bravo")) | 
 | ||||||
|  | 		actual := result.OutputToString() | ||||||
|  | 		Expect(actual).To(ContainSubstring("bravo")) | ||||||
|  | 		Expect(actual).To(ContainSubstring("NAMES")) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps --filter network=container:<id>", func() { | 	It("podman ps --filter network=container:<id>", func() { | ||||||
|  | @ -206,7 +208,9 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 		Expect(result).Should(Exit(0)) | 		Expect(result).Should(Exit(0)) | ||||||
| 		Expect(result.OutputToString()).To(ContainSubstring("second")) | 		actual := result.OutputToString() | ||||||
|  | 		Expect(actual).To(ContainSubstring("second")) | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring("table")) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps namespace flag", func() { | 	It("podman ps namespace flag", func() { | ||||||
|  | @ -228,7 +232,7 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 		Expect(result).Should(Exit(0)) | 		Expect(result).Should(Exit(0)) | ||||||
| 		// it must contains `::` when some ns is null. If it works normally, it should be "$num1:$num2:$num3"
 | 		// it must contains `::` when some ns is null. If it works normally, it should be "$num1:$num2:$num3"
 | ||||||
| 		Expect(result.OutputToString()).To(Not(ContainSubstring(`::`))) | 		Expect(result.OutputToString()).ToNot(ContainSubstring(`::`)) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps with no containers is valid json format", func() { | 	It("podman ps with no containers is valid json format", func() { | ||||||
|  | @ -285,11 +289,14 @@ var _ = Describe("Podman ps", func() { | ||||||
| 
 | 
 | ||||||
| 		result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.ID}} {{.Image}} {{.ImageID}} {{.Labels}}"}) | 		result := podmanTest.Podman([]string{"ps", "-a", "--format", "table {{.ID}} {{.Image}} {{.ImageID}} {{.Labels}}"}) | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 
 |  | ||||||
| 		Expect(result.OutputToStringArray()[0]).ToNot(ContainSubstring("table")) |  | ||||||
| 		Expect(result.OutputToStringArray()[0]).ToNot(ContainSubstring("ImageID")) |  | ||||||
| 		Expect(result.OutputToStringArray()[0]).To(ContainSubstring("alpine:latest")) |  | ||||||
| 		Expect(result).Should(Exit(0)) | 		Expect(result).Should(Exit(0)) | ||||||
|  | 
 | ||||||
|  | 		Expect(result.OutputToString()).ToNot(ContainSubstring("table")) | ||||||
|  | 
 | ||||||
|  | 		actual := result.OutputToStringArray() | ||||||
|  | 		Expect(actual[0]).To(ContainSubstring("CONTAINER ID")) | ||||||
|  | 		Expect(actual[0]).ToNot(ContainSubstring("ImageID")) | ||||||
|  | 		Expect(actual[1]).To(ContainSubstring("alpine:latest")) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps ancestor filter flag", func() { | 	It("podman ps ancestor filter flag", func() { | ||||||
|  | @ -380,7 +387,9 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		psFilter.WaitWithDefaultTimeout() | 		psFilter.WaitWithDefaultTimeout() | ||||||
| 		Expect(psFilter).Should(Exit(0)) | 		Expect(psFilter).Should(Exit(0)) | ||||||
| 
 | 
 | ||||||
| 		Expect(strings.Contains(psFilter.OutputToString(), ctrName)).To(BeFalse()) | 		actual := psFilter.OutputToString() | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring(ctrName)) | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring("NAMES")) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps mutually exclusive flags", func() { | 	It("podman ps mutually exclusive flags", func() { | ||||||
|  | @ -453,14 +462,13 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		Expect(session).Should(Exit(0)) | 		Expect(session).Should(Exit(0)) | ||||||
| 
 | 
 | ||||||
| 		session = podmanTest.Podman([]string{"ps", "-a", "--sort=command", "--format", "{{.Command}}"}) | 		session = podmanTest.Podman([]string{"ps", "-a", "--sort=command", "--format", "{{.Command}}"}) | ||||||
| 
 |  | ||||||
| 		session.WaitWithDefaultTimeout() | 		session.WaitWithDefaultTimeout() | ||||||
| 		Expect(session).Should(Exit(0)) | 		Expect(session).Should(Exit(0)) | ||||||
| 
 | 
 | ||||||
|  | 		Expect(session.OutputToString()).ToNot(ContainSubstring("COMMAND")) | ||||||
|  | 
 | ||||||
| 		sortedArr := session.OutputToStringArray() | 		sortedArr := session.OutputToStringArray() | ||||||
| 
 |  | ||||||
| 		Expect(sort.SliceIsSorted(sortedArr, func(i, j int) bool { return sortedArr[i] < sortedArr[j] })).To(BeTrue()) | 		Expect(sort.SliceIsSorted(sortedArr, func(i, j int) bool { return sortedArr[i] < sortedArr[j] })).To(BeTrue()) | ||||||
| 
 |  | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman --pod", func() { | 	It("podman --pod", func() { | ||||||
|  | @ -474,7 +482,7 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		session = podmanTest.Podman([]string{"ps", "--no-trunc"}) | 		session = podmanTest.Podman([]string{"ps", "--no-trunc"}) | ||||||
| 		session.WaitWithDefaultTimeout() | 		session.WaitWithDefaultTimeout() | ||||||
| 		Expect(session).Should(Exit(0)) | 		Expect(session).Should(Exit(0)) | ||||||
| 		Expect(session.OutputToString()).To(Not(ContainSubstring(podid))) | 		Expect(session.OutputToString()).ToNot(ContainSubstring(podid)) | ||||||
| 
 | 
 | ||||||
| 		session = podmanTest.Podman([]string{"ps", "--pod", "--no-trunc"}) | 		session = podmanTest.Podman([]string{"ps", "--pod", "--no-trunc"}) | ||||||
| 		session.WaitWithDefaultTimeout() | 		session.WaitWithDefaultTimeout() | ||||||
|  | @ -510,7 +518,11 @@ var _ = Describe("Podman ps", func() { | ||||||
| 
 | 
 | ||||||
| 		session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"}) | 		session = podmanTest.Podman([]string{"ps", "--format", "{{.Ports}}"}) | ||||||
| 		session.WaitWithDefaultTimeout() | 		session.WaitWithDefaultTimeout() | ||||||
| 		Expect(session.OutputToString()).To(ContainSubstring("0.0.0.0:2000-2006")) | 		Expect(session).To(Exit(0)) | ||||||
|  | 
 | ||||||
|  | 		actual := session.OutputToString() | ||||||
|  | 		Expect(actual).To(ContainSubstring("0.0.0.0:2000-2006")) | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring("PORT")) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps test with invalid port range", func() { | 	It("podman ps test with invalid port range", func() { | ||||||
|  | @ -628,7 +640,10 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		result := podmanTest.Podman([]string{"ps", "-a", "--format", "{{.RunningFor}}"}) | 		result := podmanTest.Podman([]string{"ps", "-a", "--format", "{{.RunningFor}}"}) | ||||||
| 		result.WaitWithDefaultTimeout() | 		result.WaitWithDefaultTimeout() | ||||||
| 		Expect(result).Should(Exit(0)) | 		Expect(result).Should(Exit(0)) | ||||||
| 		Expect(result.OutputToString()).To(ContainSubstring("ago")) | 
 | ||||||
|  | 		actual := result.OutputToString() | ||||||
|  | 		Expect(actual).To(ContainSubstring("ago")) | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring("RUNNING FOR")) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps filter test", func() { | 	It("podman ps filter test", func() { | ||||||
|  | @ -823,8 +838,9 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		session = podmanTest.Podman([]string{"ps", "--all", "--no-trunc", "--filter", "network=" + net}) | 		session = podmanTest.Podman([]string{"ps", "--all", "--no-trunc", "--filter", "network=" + net}) | ||||||
| 		session.WaitWithDefaultTimeout() | 		session.WaitWithDefaultTimeout() | ||||||
| 		Expect(session).Should(Exit(0)) | 		Expect(session).Should(Exit(0)) | ||||||
| 		Expect(session.OutputToString()).To(ContainSubstring(ctrWithNet)) | 		actual := session.OutputToString() | ||||||
| 		Expect(session.OutputToString()).To(Not(ContainSubstring(ctrWithoutNet))) | 		Expect(actual).To(ContainSubstring(ctrWithNet)) | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring(ctrWithoutNet)) | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	It("podman ps --format networks", func() { | 	It("podman ps --format networks", func() { | ||||||
|  | @ -835,12 +851,15 @@ var _ = Describe("Podman ps", func() { | ||||||
| 		session = podmanTest.Podman([]string{"ps", "--all", "--format", "{{ .Networks }}"}) | 		session = podmanTest.Podman([]string{"ps", "--all", "--format", "{{ .Networks }}"}) | ||||||
| 		session.WaitWithDefaultTimeout() | 		session.WaitWithDefaultTimeout() | ||||||
| 		Expect(session).Should(Exit(0)) | 		Expect(session).Should(Exit(0)) | ||||||
|  | 
 | ||||||
|  | 		actual := session.OutputToString() | ||||||
|  | 		Expect(actual).ToNot(ContainSubstring("NETWORKS")) | ||||||
| 		if isRootless() { | 		if isRootless() { | ||||||
| 			// rootless container don't have a network by default
 | 			// rootless container don't have a network by default
 | ||||||
| 			Expect(session.OutputToString()).To(Equal("")) | 			Expect(actual).To(BeEmpty()) | ||||||
| 		} else { | 		} else { | ||||||
| 			// default network name is podman
 | 			// default network name is podman
 | ||||||
| 			Expect(session.OutputToString()).To(Equal("podman")) | 			Expect(actual).To(Equal("podman")) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		net1 := stringid.GenerateNonCryptoID() | 		net1 := stringid.GenerateNonCryptoID() | ||||||
|  |  | ||||||
|  | @ -19,7 +19,7 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| var ( | var ( | ||||||
| 	defaultWaitTimeout   = 90 | 	DefaultWaitTimeout   = 90 | ||||||
| 	OSReleasePath        = "/etc/os-release" | 	OSReleasePath        = "/etc/os-release" | ||||||
| 	ProcessOneCgroupPath = "/proc/1/cgroup" | 	ProcessOneCgroupPath = "/proc/1/cgroup" | ||||||
| ) | ) | ||||||
|  | @ -317,15 +317,20 @@ func (s *PodmanSession) IsJSONOutputValid() bool { | ||||||
| 	return true | 	return true | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // WaitWithDefaultTimeout waits for process finished with defaultWaitTimeout
 | // WaitWithDefaultTimeout waits for process finished with DefaultWaitTimeout
 | ||||||
| func (s *PodmanSession) WaitWithDefaultTimeout() { | func (s *PodmanSession) WaitWithDefaultTimeout() { | ||||||
| 	Eventually(s, defaultWaitTimeout).Should(Exit()) | 	s.WaitWithTimeout(DefaultWaitTimeout) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // WaitWithTimeout waits for process finished with DefaultWaitTimeout
 | ||||||
|  | func (s *PodmanSession) WaitWithTimeout(timeout int) { | ||||||
|  | 	Eventually(s, timeout).Should(Exit()) | ||||||
| 	os.Stdout.Sync() | 	os.Stdout.Sync() | ||||||
| 	os.Stderr.Sync() | 	os.Stderr.Sync() | ||||||
| 	fmt.Println("output:", s.OutputToString()) | 	fmt.Println("output:", s.OutputToString()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // CreateTempDirinTempDir create a temp dir with prefix podman_test
 | // CreateTempDirInTempDir create a temp dir with prefix podman_test
 | ||||||
| func CreateTempDirInTempDir() (string, error) { | func CreateTempDirInTempDir() (string, error) { | ||||||
| 	return ioutil.TempDir("", "podman_test") | 	return ioutil.TempDir("", "podman_test") | ||||||
| } | } | ||||||
|  | @ -337,7 +342,7 @@ func SystemExec(command string, args []string) *PodmanSession { | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " "))) | 		Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " "))) | ||||||
| 	} | 	} | ||||||
| 	session.Wait(defaultWaitTimeout) | 	session.Wait(DefaultWaitTimeout) | ||||||
| 	return &PodmanSession{session} | 	return &PodmanSession{session} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue