mirror of
				https://github.com/containers/podman.git
				synced 2025-10-26 02:35:43 +08:00 
			
		
		
		
	top: make output tabular
Make the output of top tabular to be compatible with Docker. Please note, that any user-input for `GetContainerPidInformation(...)` will be ignored until we have found a way to generically and reliably parse ps-1 output or until there is a go-lib to extract all the data from /proc in a ps-1 compatible fashion. Fixes: #458 Signed-off-by: Valentin Rothberg <vrothberg@suse.com> Closes: #939 Approved by: rhatdan
This commit is contained in:
		 Valentin Rothberg
					Valentin Rothberg
				
			
				
					committed by
					
						 Atomic Bot
						Atomic Bot
					
				
			
			
				
	
			
			
			 Atomic Bot
						Atomic Bot
					
				
			
						parent
						
							9e134576e8
						
					
				
				
					commit
					b1e709806d
				
			| @ -2,6 +2,8 @@ package main | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"text/tabwriter" | ||||
|  | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/projectatomic/libpod/cmd/podman/libpodruntime" | ||||
| @ -34,8 +36,7 @@ func topCmd(c *cli.Context) error { | ||||
| 	var container *libpod.Container | ||||
| 	var err error | ||||
| 	args := c.Args() | ||||
| 	var psArgs []string | ||||
| 	psOpts := []string{"-o", "uid,pid,ppid,c,stime,tname,time,cmd"} | ||||
|  | ||||
| 	if len(args) < 1 && !c.Bool("latest") { | ||||
| 		return errors.Errorf("you must provide the name or id of a running container") | ||||
| 	} | ||||
| @ -48,9 +49,6 @@ func topCmd(c *cli.Context) error { | ||||
| 		return errors.Wrapf(err, "error creating libpod runtime") | ||||
| 	} | ||||
| 	defer runtime.Shutdown(false) | ||||
| 	if len(args) > 1 { | ||||
| 		psOpts = args[1:] | ||||
| 	} | ||||
|  | ||||
| 	if c.Bool("latest") { | ||||
| 		container, err = runtime.GetLatestContainer() | ||||
| @ -69,14 +67,15 @@ func topCmd(c *cli.Context) error { | ||||
| 		return errors.Errorf("top can only be used on running containers") | ||||
| 	} | ||||
|  | ||||
| 	psArgs = append(psArgs, psOpts...) | ||||
|  | ||||
| 	psOutput, err := container.GetContainerPidInformation(psArgs) | ||||
| 	psOutput, err := container.GetContainerPidInformation([]string{}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, line := range psOutput { | ||||
| 		fmt.Println(line) | ||||
|  | ||||
| 	w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0) | ||||
| 	for _, proc := range psOutput { | ||||
| 		fmt.Fprintln(w, proc) | ||||
| 	} | ||||
| 	w.Flush() | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| @ -44,8 +44,20 @@ func (c *Container) getContainerPids() ([]string, error) { | ||||
| } | ||||
|  | ||||
| // GetContainerPidInformation calls ps with the appropriate options and returns | ||||
| // the results as a string and the container's PIDs as a []string | ||||
| // the results as a string and the container's PIDs as a []string.  Note that | ||||
| // the ps output columns of each string are separated by a '\t\'.  Currently, | ||||
| // the args argument is overwriten with []string{"-ef"} until there is a | ||||
| // portable library for ps-1 or to parse the procFS to extract all data. | ||||
| func (c *Container) GetContainerPidInformation(args []string) ([]string, error) { | ||||
| 	// XXX(ps-issue): args is overwriten with []{"-ef"} as the ps-1 tool | ||||
| 	// doesn't support a generic way of splitting columns, rendering its | ||||
| 	// output hard to parse.  Docker first deterimes the number of columns | ||||
| 	// and merges all exceeding ones into the last one.  We believe that | ||||
| 	// writing a go library which parses procFS in a ps-compatible way may | ||||
| 	// be more beneficial in the long run.  Until then, args will be | ||||
| 	// ignored. | ||||
| 	args = []string{"-ef"} | ||||
|  | ||||
| 	if !c.batched { | ||||
| 		c.lock.Lock() | ||||
| 		defer c.lock.Unlock() | ||||
| @ -80,7 +92,7 @@ func filterPids(psOutput string, pids []string) ([]string, error) { | ||||
| 	// Pids that don't belong. | ||||
|  | ||||
| 	// append the headers back in | ||||
| 	output = append(output, results[0]) | ||||
| 	output = append(output, strings.Join(headers, "\t")) | ||||
|  | ||||
| 	pidIndex := -1 | ||||
| 	for i, header := range headers { | ||||
| @ -98,7 +110,13 @@ func filterPids(psOutput string, pids []string) ([]string, error) { | ||||
| 		cols := fieldsASCII(l) | ||||
| 		pid := cols[pidIndex] | ||||
| 		if util.StringInSlice(pid, pids) { | ||||
| 			output = append(output, l) | ||||
| 			// XXX(ps-issue): Strip cols down to the header's size | ||||
| 			// and merge exceeding fields. This is required to | ||||
| 			// "merge" the overhanging CMD entries which can | ||||
| 			// contain white spaces. | ||||
| 			out := cols[:len(headers)-1] | ||||
| 			out = append(out, strings.Join(cols[len(headers)-1:], " ")) | ||||
| 			output = append(output, strings.Join(out, "\t")) | ||||
| 		} | ||||
| 	} | ||||
| 	return output, nil | ||||
|  | ||||
| @ -59,7 +59,14 @@ var _ = Describe("Podman top", func() { | ||||
| 		Expect(len(result.OutputToStringArray())).To(BeNumerically(">", 1)) | ||||
| 	}) | ||||
|  | ||||
| 	//      XXX(ps-issue): for the time being, podman-top and the libpod API | ||||
| 	//      GetContainerPidInformation(...) will ignore any arguments passed to ps, | ||||
| 	//      so we have to disable the tests below.  Please refer to | ||||
| 	//      https://github.com/projectatomic/libpod/pull/939 for more background | ||||
| 	//      information. | ||||
|  | ||||
| 	It("podman top with options", func() { | ||||
| 		Skip("podman-top with options: options are temporarily ignored") | ||||
| 		session := podmanTest.Podman([]string{"run", "-d", ALPINE, "top", "-d", "2"}) | ||||
| 		session.WaitWithDefaultTimeout() | ||||
| 		Expect(session.ExitCode()).To(Equal(0)) | ||||
| @ -71,6 +78,7 @@ var _ = Describe("Podman top", func() { | ||||
| 	}) | ||||
|  | ||||
| 	It("podman top on container invalid options", func() { | ||||
| 		Skip("podman-top with invalid options: options are temporarily ignored") | ||||
| 		top := podmanTest.RunTopContainer("") | ||||
| 		top.WaitWithDefaultTimeout() | ||||
| 		Expect(top.ExitCode()).To(Equal(0)) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user