github.com/fabiokung/docker@v0.11.2-0.20170222101415-4534dcd49497/cli/command/formatter/task.go (about)

     1  package formatter
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"github.com/docker/distribution/reference"
     9  	"github.com/docker/docker/api/types/swarm"
    10  	"github.com/docker/docker/cli/command"
    11  	"github.com/docker/docker/pkg/stringid"
    12  	"github.com/docker/go-units"
    13  )
    14  
    15  const (
    16  	defaultTaskTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Node}}\t{{.DesiredState}}\t{{.CurrentState}}\t{{.Error}}\t{{.Ports}}"
    17  
    18  	nodeHeader         = "NODE"
    19  	taskIDHeader       = "ID"
    20  	desiredStateHeader = "DESIRED STATE"
    21  	currentStateHeader = "CURRENT STATE"
    22  	errorHeader        = "ERROR"
    23  
    24  	maxErrLength = 30
    25  )
    26  
    27  // NewTaskFormat returns a Format for rendering using a task Context
    28  func NewTaskFormat(source string, quiet bool) Format {
    29  	switch source {
    30  	case TableFormatKey:
    31  		if quiet {
    32  			return defaultQuietFormat
    33  		}
    34  		return defaultTaskTableFormat
    35  	case RawFormatKey:
    36  		if quiet {
    37  			return `id: {{.ID}}`
    38  		}
    39  		return `id: {{.ID}}\nname: {{.Name}}\nimage: {{.Image}}\nnode: {{.Node}}\ndesired_state: {{.DesiredState}}\ncurrent_state: {{.CurrentState}}\nerror: {{.Error}}\nports: {{.Ports}}\n`
    40  	}
    41  	return Format(source)
    42  }
    43  
    44  // TaskWrite writes the context
    45  func TaskWrite(ctx Context, tasks []swarm.Task, names map[string]string, nodes map[string]string) error {
    46  	render := func(format func(subContext subContext) error) error {
    47  		for _, task := range tasks {
    48  			taskCtx := &taskContext{trunc: ctx.Trunc, task: task, name: names[task.ID], node: nodes[task.ID]}
    49  			if err := format(taskCtx); err != nil {
    50  				return err
    51  			}
    52  		}
    53  		return nil
    54  	}
    55  	return ctx.Write(&taskContext{}, render)
    56  }
    57  
    58  type taskContext struct {
    59  	HeaderContext
    60  	trunc bool
    61  	task  swarm.Task
    62  	name  string
    63  	node  string
    64  }
    65  
    66  func (c *taskContext) MarshalJSON() ([]byte, error) {
    67  	return marshalJSON(c)
    68  }
    69  
    70  func (c *taskContext) ID() string {
    71  	c.AddHeader(taskIDHeader)
    72  	if c.trunc {
    73  		return stringid.TruncateID(c.task.ID)
    74  	}
    75  	return c.task.ID
    76  }
    77  
    78  func (c *taskContext) Name() string {
    79  	c.AddHeader(nameHeader)
    80  	return c.name
    81  }
    82  
    83  func (c *taskContext) Image() string {
    84  	c.AddHeader(imageHeader)
    85  	image := c.task.Spec.ContainerSpec.Image
    86  	if c.trunc {
    87  		ref, err := reference.ParseNormalizedNamed(image)
    88  		if err == nil {
    89  			// update image string for display, (strips any digest)
    90  			if nt, ok := ref.(reference.NamedTagged); ok {
    91  				if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
    92  					image = reference.FamiliarString(namedTagged)
    93  				}
    94  			}
    95  		}
    96  	}
    97  	return image
    98  }
    99  
   100  func (c *taskContext) Node() string {
   101  	c.AddHeader(nodeHeader)
   102  	return c.node
   103  }
   104  
   105  func (c *taskContext) DesiredState() string {
   106  	c.AddHeader(desiredStateHeader)
   107  	return command.PrettyPrint(c.task.DesiredState)
   108  }
   109  
   110  func (c *taskContext) CurrentState() string {
   111  	c.AddHeader(currentStateHeader)
   112  	return fmt.Sprintf("%s %s ago",
   113  		command.PrettyPrint(c.task.Status.State),
   114  		strings.ToLower(units.HumanDuration(time.Since(c.task.Status.Timestamp))),
   115  	)
   116  }
   117  
   118  func (c *taskContext) Error() string {
   119  	c.AddHeader(errorHeader)
   120  	// Trim and quote the error message.
   121  	taskErr := c.task.Status.Err
   122  	if c.trunc && len(taskErr) > maxErrLength {
   123  		taskErr = fmt.Sprintf("%s…", taskErr[:maxErrLength-1])
   124  	}
   125  	if len(taskErr) > 0 {
   126  		taskErr = fmt.Sprintf("\"%s\"", taskErr)
   127  	}
   128  	return taskErr
   129  }
   130  
   131  func (c *taskContext) Ports() string {
   132  	c.AddHeader(portsHeader)
   133  	if len(c.task.Status.PortStatus.Ports) == 0 {
   134  		return ""
   135  	}
   136  	ports := []string{}
   137  	for _, pConfig := range c.task.Status.PortStatus.Ports {
   138  		ports = append(ports, fmt.Sprintf("*:%d->%d/%s",
   139  			pConfig.PublishedPort,
   140  			pConfig.TargetPort,
   141  			pConfig.Protocol,
   142  		))
   143  	}
   144  	return strings.Join(ports, ",")
   145  }