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