123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 |
- package formatter
- import (
- "fmt"
- "strings"
- "time"
- "github.com/docker/distribution/reference"
- "github.com/docker/docker/api/types/swarm"
- "github.com/docker/docker/cli/command"
- "github.com/docker/docker/pkg/stringid"
- "github.com/docker/go-units"
- )
- const (
- defaultTaskTableFormat = "table {{.ID}}\t{{.Name}}\t{{.Image}}\t{{.Node}}\t{{.DesiredState}}\t{{.CurrentState}}\t{{.Error}}\t{{.Ports}}"
- nodeHeader = "NODE"
- taskIDHeader = "ID"
- desiredStateHeader = "DESIRED STATE"
- currentStateHeader = "CURRENT STATE"
- errorHeader = "ERROR"
- maxErrLength = 30
- )
- // NewTaskFormat returns a Format for rendering using a task Context
- func NewTaskFormat(source string, quiet bool) Format {
- switch source {
- case TableFormatKey:
- if quiet {
- return defaultQuietFormat
- }
- return defaultTaskTableFormat
- case RawFormatKey:
- if quiet {
- return `id: {{.ID}}`
- }
- return `id: {{.ID}}\nname: {{.Name}}\nimage: {{.Image}}\nnode: {{.Node}}\ndesired_state: {{.DesiredState}}\ncurrent_state: {{.CurrentState}}\nerror: {{.Error}}\nports: {{.Ports}}\n`
- }
- return Format(source)
- }
- // TaskWrite writes the context
- func TaskWrite(ctx Context, tasks []swarm.Task, names map[string]string, nodes map[string]string) error {
- render := func(format func(subContext subContext) error) error {
- for _, task := range tasks {
- taskCtx := &taskContext{trunc: ctx.Trunc, task: task, name: names[task.ID], node: nodes[task.ID]}
- if err := format(taskCtx); err != nil {
- return err
- }
- }
- return nil
- }
- return ctx.Write(&taskContext{}, render)
- }
- type taskContext struct {
- HeaderContext
- trunc bool
- task swarm.Task
- name string
- node string
- }
- func (c *taskContext) MarshalJSON() ([]byte, error) {
- return marshalJSON(c)
- }
- func (c *taskContext) ID() string {
- c.AddHeader(taskIDHeader)
- if c.trunc {
- return stringid.TruncateID(c.task.ID)
- }
- return c.task.ID
- }
- func (c *taskContext) Name() string {
- c.AddHeader(nameHeader)
- return c.name
- }
- func (c *taskContext) Image() string {
- c.AddHeader(imageHeader)
- image := c.task.Spec.ContainerSpec.Image
- if c.trunc {
- ref, err := reference.ParseNormalizedNamed(image)
- if err == nil {
- // update image string for display, (strips any digest)
- if nt, ok := ref.(reference.NamedTagged); ok {
- if namedTagged, err := reference.WithTag(reference.TrimNamed(nt), nt.Tag()); err == nil {
- image = reference.FamiliarString(namedTagged)
- }
- }
- }
- }
- return image
- }
- func (c *taskContext) Node() string {
- c.AddHeader(nodeHeader)
- return c.node
- }
- func (c *taskContext) DesiredState() string {
- c.AddHeader(desiredStateHeader)
- return command.PrettyPrint(c.task.DesiredState)
- }
- func (c *taskContext) CurrentState() string {
- c.AddHeader(currentStateHeader)
- return fmt.Sprintf("%s %s ago",
- command.PrettyPrint(c.task.Status.State),
- strings.ToLower(units.HumanDuration(time.Since(c.task.Status.Timestamp))),
- )
- }
- func (c *taskContext) Error() string {
- c.AddHeader(errorHeader)
- // Trim and quote the error message.
- taskErr := c.task.Status.Err
- if c.trunc && len(taskErr) > maxErrLength {
- taskErr = fmt.Sprintf("%s…", taskErr[:maxErrLength-1])
- }
- if len(taskErr) > 0 {
- taskErr = fmt.Sprintf("\"%s\"", taskErr)
- }
- return taskErr
- }
- func (c *taskContext) Ports() string {
- c.AddHeader(portsHeader)
- if len(c.task.Status.PortStatus.Ports) == 0 {
- return ""
- }
- ports := []string{}
- for _, pConfig := range c.task.Status.PortStatus.Ports {
- ports = append(ports, fmt.Sprintf("*:%d->%d/%s",
- pConfig.PublishedPort,
- pConfig.TargetPort,
- pConfig.Protocol,
- ))
- }
- return strings.Join(ports, ",")
- }
|