github.com/portworx/docker@v1.12.1/api/client/task/print.go (about)

     1  package task
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  	"text/tabwriter"
     8  	"time"
     9  
    10  	"golang.org/x/net/context"
    11  
    12  	"github.com/docker/docker/api/client"
    13  	"github.com/docker/docker/api/client/idresolver"
    14  	"github.com/docker/engine-api/types/swarm"
    15  	"github.com/docker/go-units"
    16  )
    17  
    18  const (
    19  	psTaskItemFmt = "%s\t%s\t%s\t%s\t%s\t%s %s ago\t%s\n"
    20  	maxErrLength  = 30
    21  )
    22  
    23  type tasksBySlot []swarm.Task
    24  
    25  func (t tasksBySlot) Len() int {
    26  	return len(t)
    27  }
    28  
    29  func (t tasksBySlot) Swap(i, j int) {
    30  	t[i], t[j] = t[j], t[i]
    31  }
    32  
    33  func (t tasksBySlot) Less(i, j int) bool {
    34  	// Sort by slot.
    35  	if t[i].Slot != t[j].Slot {
    36  		return t[i].Slot < t[j].Slot
    37  	}
    38  
    39  	// If same slot, sort by most recent.
    40  	return t[j].Meta.CreatedAt.Before(t[i].CreatedAt)
    41  }
    42  
    43  // Print task information in a table format
    44  func Print(dockerCli *client.DockerCli, ctx context.Context, tasks []swarm.Task, resolver *idresolver.IDResolver) error {
    45  	sort.Stable(tasksBySlot(tasks))
    46  
    47  	writer := tabwriter.NewWriter(dockerCli.Out(), 0, 4, 2, ' ', 0)
    48  
    49  	// Ignore flushing errors
    50  	defer writer.Flush()
    51  	fmt.Fprintln(writer, strings.Join([]string{"ID", "NAME", "IMAGE", "NODE", "DESIRED STATE", "CURRENT STATE", "ERROR"}, "\t"))
    52  
    53  	prevName := ""
    54  	for _, task := range tasks {
    55  		serviceValue, err := resolver.Resolve(ctx, swarm.Service{}, task.ServiceID)
    56  		if err != nil {
    57  			return err
    58  		}
    59  		nodeValue, err := resolver.Resolve(ctx, swarm.Node{}, task.NodeID)
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  		name := serviceValue
    65  		if task.Slot > 0 {
    66  			name = fmt.Sprintf("%s.%d", name, task.Slot)
    67  		}
    68  
    69  		// Indent the name if necessary
    70  		indentedName := name
    71  		if prevName == name {
    72  			indentedName = fmt.Sprintf(" \\_ %s", indentedName)
    73  		}
    74  		prevName = name
    75  
    76  		// Trim and quote the error message.
    77  		taskErr := task.Status.Err
    78  		if len(taskErr) > maxErrLength {
    79  			taskErr = fmt.Sprintf("%s…", taskErr[:maxErrLength-1])
    80  		}
    81  		if len(taskErr) > 0 {
    82  			taskErr = fmt.Sprintf("\"%s\"", taskErr)
    83  		}
    84  
    85  		fmt.Fprintf(
    86  			writer,
    87  			psTaskItemFmt,
    88  			task.ID,
    89  			indentedName,
    90  			task.Spec.ContainerSpec.Image,
    91  			nodeValue,
    92  			client.PrettyPrint(task.DesiredState),
    93  			client.PrettyPrint(task.Status.State),
    94  			strings.ToLower(units.HumanDuration(time.Since(task.Status.Timestamp))),
    95  			taskErr,
    96  		)
    97  	}
    98  
    99  	return nil
   100  }