github.com/sld880311/docker@v0.0.0-20200524143708-d5593973a475/cli/command/formatter/service.go (about) 1 package formatter 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 mounttypes "github.com/docker/docker/api/types/mount" 9 "github.com/docker/docker/api/types/swarm" 10 "github.com/docker/docker/cli/command/inspect" 11 units "github.com/docker/go-units" 12 ) 13 14 const serviceInspectPrettyTemplate Format = ` 15 ID: {{.ID}} 16 Name: {{.Name}} 17 {{- if .Labels }} 18 Labels: 19 {{- range $k, $v := .Labels }} 20 {{ $k }}{{if $v }}={{ $v }}{{ end }} 21 {{- end }}{{ end }} 22 Service Mode: 23 {{- if .IsModeGlobal }} Global 24 {{- else if .IsModeReplicated }} Replicated 25 {{- if .ModeReplicatedReplicas }} 26 Replicas: {{ .ModeReplicatedReplicas }} 27 {{- end }}{{ end }} 28 {{- if .HasUpdateStatus }} 29 UpdateStatus: 30 State: {{ .UpdateStatusState }} 31 Started: {{ .UpdateStatusStarted }} 32 {{- if .UpdateIsCompleted }} 33 Completed: {{ .UpdateStatusCompleted }} 34 {{- end }} 35 Message: {{ .UpdateStatusMessage }} 36 {{- end }} 37 Placement: 38 {{- if .TaskPlacementConstraints -}} 39 Contraints: {{ .TaskPlacementConstraints }} 40 {{- end }} 41 {{- if .HasUpdateConfig }} 42 UpdateConfig: 43 Parallelism: {{ .UpdateParallelism }} 44 {{- if .HasUpdateDelay}} 45 Delay: {{ .UpdateDelay }} 46 {{- end }} 47 On failure: {{ .UpdateOnFailure }} 48 {{- if .HasUpdateMonitor}} 49 Monitoring Period: {{ .UpdateMonitor }} 50 {{- end }} 51 Max failure ratio: {{ .UpdateMaxFailureRatio }} 52 {{- end }} 53 ContainerSpec: 54 Image: {{ .ContainerImage }} 55 {{- if .ContainerArgs }} 56 Args: {{ range $arg := .ContainerArgs }}{{ $arg }} {{ end }} 57 {{- end -}} 58 {{- if .ContainerEnv }} 59 Env: {{ range $env := .ContainerEnv }}{{ $env }} {{ end }} 60 {{- end -}} 61 {{- if .ContainerWorkDir }} 62 Dir: {{ .ContainerWorkDir }} 63 {{- end -}} 64 {{- if .ContainerUser }} 65 User: {{ .ContainerUser }} 66 {{- end }} 67 {{- if .ContainerMounts }} 68 Mounts: 69 {{- end }} 70 {{- range $mount := .ContainerMounts }} 71 Target = {{ $mount.Target }} 72 Source = {{ $mount.Source }} 73 ReadOnly = {{ $mount.ReadOnly }} 74 Type = {{ $mount.Type }} 75 {{- end -}} 76 {{- if .HasResources }} 77 Resources: 78 {{- if .HasResourceReservations }} 79 Reservations: 80 {{- if gt .ResourceReservationNanoCPUs 0.0 }} 81 CPU: {{ .ResourceReservationNanoCPUs }} 82 {{- end }} 83 {{- if .ResourceReservationMemory }} 84 Memory: {{ .ResourceReservationMemory }} 85 {{- end }}{{ end }} 86 {{- if .HasResourceLimits }} 87 Limits: 88 {{- if gt .ResourceLimitsNanoCPUs 0.0 }} 89 CPU: {{ .ResourceLimitsNanoCPUs }} 90 {{- end }} 91 {{- if .ResourceLimitMemory }} 92 Memory: {{ .ResourceLimitMemory }} 93 {{- end }}{{ end }}{{ end }} 94 {{- if .Networks }} 95 Networks: 96 {{- range $network := .Networks }} {{ $network }}{{ end }} {{ end }} 97 Endpoint Mode: {{ .EndpointMode }} 98 {{- if .Ports }} 99 Ports: 100 {{- range $port := .Ports }} 101 PublishedPort {{ $port.PublishedPort }} 102 Protocol = {{ $port.Protocol }} 103 TargetPort = {{ $port.TargetPort }} 104 {{- end }} {{ end -}} 105 ` 106 107 // NewServiceFormat returns a Format for rendering using a Context 108 func NewServiceFormat(source string) Format { 109 switch source { 110 case PrettyFormatKey: 111 return serviceInspectPrettyTemplate 112 default: 113 return Format(strings.TrimPrefix(source, RawFormatKey)) 114 } 115 } 116 117 // ServiceInspectWrite renders the context for a list of services 118 func ServiceInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) error { 119 if ctx.Format != serviceInspectPrettyTemplate { 120 return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) 121 } 122 render := func(format func(subContext subContext) error) error { 123 for _, ref := range refs { 124 serviceI, _, err := getRef(ref) 125 if err != nil { 126 return err 127 } 128 service, ok := serviceI.(swarm.Service) 129 if !ok { 130 return fmt.Errorf("got wrong object to inspect") 131 } 132 if err := format(&serviceInspectContext{Service: service}); err != nil { 133 return err 134 } 135 } 136 return nil 137 } 138 return ctx.Write(&serviceInspectContext{}, render) 139 } 140 141 type serviceInspectContext struct { 142 swarm.Service 143 subContext 144 } 145 146 func (ctx *serviceInspectContext) MarshalJSON() ([]byte, error) { 147 return marshalJSON(ctx) 148 } 149 150 func (ctx *serviceInspectContext) ID() string { 151 return ctx.Service.ID 152 } 153 154 func (ctx *serviceInspectContext) Name() string { 155 return ctx.Service.Spec.Name 156 } 157 158 func (ctx *serviceInspectContext) Labels() map[string]string { 159 return ctx.Service.Spec.Labels 160 } 161 162 func (ctx *serviceInspectContext) IsModeGlobal() bool { 163 return ctx.Service.Spec.Mode.Global != nil 164 } 165 166 func (ctx *serviceInspectContext) IsModeReplicated() bool { 167 return ctx.Service.Spec.Mode.Replicated != nil 168 } 169 170 func (ctx *serviceInspectContext) ModeReplicatedReplicas() *uint64 { 171 return ctx.Service.Spec.Mode.Replicated.Replicas 172 } 173 174 func (ctx *serviceInspectContext) HasUpdateStatus() bool { 175 return ctx.Service.UpdateStatus.State != "" 176 } 177 178 func (ctx *serviceInspectContext) UpdateStatusState() swarm.UpdateState { 179 return ctx.Service.UpdateStatus.State 180 } 181 182 func (ctx *serviceInspectContext) UpdateStatusStarted() string { 183 return units.HumanDuration(time.Since(ctx.Service.UpdateStatus.StartedAt)) 184 } 185 186 func (ctx *serviceInspectContext) UpdateIsCompleted() bool { 187 return ctx.Service.UpdateStatus.State == swarm.UpdateStateCompleted 188 } 189 190 func (ctx *serviceInspectContext) UpdateStatusCompleted() string { 191 return units.HumanDuration(time.Since(ctx.Service.UpdateStatus.CompletedAt)) 192 } 193 194 func (ctx *serviceInspectContext) UpdateStatusMessage() string { 195 return ctx.Service.UpdateStatus.Message 196 } 197 198 func (ctx *serviceInspectContext) TaskPlacementConstraints() []string { 199 if ctx.Service.Spec.TaskTemplate.Placement != nil { 200 return ctx.Service.Spec.TaskTemplate.Placement.Constraints 201 } 202 return nil 203 } 204 205 func (ctx *serviceInspectContext) HasUpdateConfig() bool { 206 return ctx.Service.Spec.UpdateConfig != nil 207 } 208 209 func (ctx *serviceInspectContext) UpdateParallelism() uint64 { 210 return ctx.Service.Spec.UpdateConfig.Parallelism 211 } 212 213 func (ctx *serviceInspectContext) HasUpdateDelay() bool { 214 return ctx.Service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 215 } 216 217 func (ctx *serviceInspectContext) UpdateDelay() time.Duration { 218 return ctx.Service.Spec.UpdateConfig.Delay 219 } 220 221 func (ctx *serviceInspectContext) UpdateOnFailure() string { 222 return ctx.Service.Spec.UpdateConfig.FailureAction 223 } 224 225 func (ctx *serviceInspectContext) HasUpdateMonitor() bool { 226 return ctx.Service.Spec.UpdateConfig.Monitor.Nanoseconds() > 0 227 } 228 229 func (ctx *serviceInspectContext) UpdateMonitor() time.Duration { 230 return ctx.Service.Spec.UpdateConfig.Monitor 231 } 232 233 func (ctx *serviceInspectContext) UpdateMaxFailureRatio() float32 { 234 return ctx.Service.Spec.UpdateConfig.MaxFailureRatio 235 } 236 237 func (ctx *serviceInspectContext) ContainerImage() string { 238 return ctx.Service.Spec.TaskTemplate.ContainerSpec.Image 239 } 240 241 func (ctx *serviceInspectContext) ContainerArgs() []string { 242 return ctx.Service.Spec.TaskTemplate.ContainerSpec.Args 243 } 244 245 func (ctx *serviceInspectContext) ContainerEnv() []string { 246 return ctx.Service.Spec.TaskTemplate.ContainerSpec.Env 247 } 248 249 func (ctx *serviceInspectContext) ContainerWorkDir() string { 250 return ctx.Service.Spec.TaskTemplate.ContainerSpec.Dir 251 } 252 253 func (ctx *serviceInspectContext) ContainerUser() string { 254 return ctx.Service.Spec.TaskTemplate.ContainerSpec.User 255 } 256 257 func (ctx *serviceInspectContext) ContainerMounts() []mounttypes.Mount { 258 return ctx.Service.Spec.TaskTemplate.ContainerSpec.Mounts 259 } 260 261 func (ctx *serviceInspectContext) HasResources() bool { 262 return ctx.Service.Spec.TaskTemplate.Resources != nil 263 } 264 265 func (ctx *serviceInspectContext) HasResourceReservations() bool { 266 if ctx.Service.Spec.TaskTemplate.Resources == nil || ctx.Service.Spec.TaskTemplate.Resources.Reservations == nil { 267 return false 268 } 269 return ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs > 0 || ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes > 0 270 } 271 272 func (ctx *serviceInspectContext) ResourceReservationNanoCPUs() float64 { 273 if ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs == 0 { 274 return float64(0) 275 } 276 return float64(ctx.Service.Spec.TaskTemplate.Resources.Reservations.NanoCPUs) / 1e9 277 } 278 279 func (ctx *serviceInspectContext) ResourceReservationMemory() string { 280 if ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes == 0 { 281 return "" 282 } 283 return units.BytesSize(float64(ctx.Service.Spec.TaskTemplate.Resources.Reservations.MemoryBytes)) 284 } 285 286 func (ctx *serviceInspectContext) HasResourceLimits() bool { 287 if ctx.Service.Spec.TaskTemplate.Resources == nil || ctx.Service.Spec.TaskTemplate.Resources.Limits == nil { 288 return false 289 } 290 return ctx.Service.Spec.TaskTemplate.Resources.Limits.NanoCPUs > 0 || ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes > 0 291 } 292 293 func (ctx *serviceInspectContext) ResourceLimitsNanoCPUs() float64 { 294 return float64(ctx.Service.Spec.TaskTemplate.Resources.Limits.NanoCPUs) / 1e9 295 } 296 297 func (ctx *serviceInspectContext) ResourceLimitMemory() string { 298 if ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes == 0 { 299 return "" 300 } 301 return units.BytesSize(float64(ctx.Service.Spec.TaskTemplate.Resources.Limits.MemoryBytes)) 302 } 303 304 func (ctx *serviceInspectContext) Networks() []string { 305 var out []string 306 for _, n := range ctx.Service.Spec.Networks { 307 out = append(out, n.Target) 308 } 309 return out 310 } 311 312 func (ctx *serviceInspectContext) EndpointMode() string { 313 if ctx.Service.Spec.EndpointSpec == nil { 314 return "" 315 } 316 317 return string(ctx.Service.Spec.EndpointSpec.Mode) 318 } 319 320 func (ctx *serviceInspectContext) Ports() []swarm.PortConfig { 321 return ctx.Service.Endpoint.Ports 322 }