From 56f1da77c33dcc5e752dce2694887878f93ffea6 Mon Sep 17 00:00:00 2001 From: Aaron Lehmann Date: Fri, 7 Apr 2017 16:37:03 -0700 Subject: [PATCH] Show network names in "docker service inspect --pretty" Signed-off-by: Aaron Lehmann --- cli/command/formatter/service.go | 29 ++++++++++++++++++++++++---- cli/command/service/inspect.go | 10 +++++++++- cli/command/service/inspect_test.go | 30 ++++++++++++++++++++--------- 3 files changed, 55 insertions(+), 14 deletions(-) diff --git a/cli/command/formatter/service.go b/cli/command/formatter/service.go index f5eb1aeaf7..8f57af22d9 100644 --- a/cli/command/formatter/service.go +++ b/cli/command/formatter/service.go @@ -6,6 +6,7 @@ import ( "time" "github.com/docker/distribution/reference" + "github.com/docker/docker/api/types" mounttypes "github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/cli/command/inspect" @@ -137,8 +138,20 @@ func NewServiceFormat(source string) Format { } } +func resolveNetworks(service swarm.Service, getNetwork inspect.GetRefFunc) map[string]string { + networkNames := make(map[string]string) + for _, network := range service.Spec.TaskTemplate.Networks { + if resolved, _, err := getNetwork(network.Target); err == nil { + if resolvedNetwork, ok := resolved.(types.NetworkResource); ok { + networkNames[resolvedNetwork.ID] = resolvedNetwork.Name + } + } + } + return networkNames +} + // ServiceInspectWrite renders the context for a list of services -func ServiceInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) error { +func ServiceInspectWrite(ctx Context, refs []string, getRef, getNetwork inspect.GetRefFunc) error { if ctx.Format != serviceInspectPrettyTemplate { return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) } @@ -152,7 +165,7 @@ func ServiceInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) if !ok { return errors.Errorf("got wrong object to inspect") } - if err := format(&serviceInspectContext{Service: service}); err != nil { + if err := format(&serviceInspectContext{Service: service, networkNames: resolveNetworks(service, getNetwork)}); err != nil { return err } } @@ -164,6 +177,10 @@ func ServiceInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc) type serviceInspectContext struct { swarm.Service subContext + + // networkNames is a map from network IDs (as found in + // Networks[x].Target) to network names. + networkNames map[string]string } func (ctx *serviceInspectContext) MarshalJSON() ([]byte, error) { @@ -383,8 +400,12 @@ func (ctx *serviceInspectContext) ResourceLimitMemory() string { func (ctx *serviceInspectContext) Networks() []string { var out []string - for _, n := range ctx.Service.Spec.Networks { - out = append(out, n.Target) + for _, n := range ctx.Service.Spec.TaskTemplate.Networks { + if name, ok := ctx.networkNames[n.Target]; ok { + out = append(out, name) + } else { + out = append(out, n.Target) + } } return out } diff --git a/cli/command/service/inspect.go b/cli/command/service/inspect.go index 8247d45afa..8a8b51cd0e 100644 --- a/cli/command/service/inspect.go +++ b/cli/command/service/inspect.go @@ -58,6 +58,14 @@ func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { return nil, nil, errors.Errorf("Error: no such service: %s", ref) } + getNetwork := func(ref string) (interface{}, []byte, error) { + network, _, err := client.NetworkInspectWithRaw(ctx, ref, false) + if err == nil || !apiclient.IsErrNetworkNotFound(err) { + return network, nil, err + } + return nil, nil, errors.Errorf("Error: no such network: %s", ref) + } + f := opts.format if len(f) == 0 { f = "raw" @@ -77,7 +85,7 @@ func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error { Format: formatter.NewServiceFormat(f), } - if err := formatter.ServiceInspectWrite(serviceCtx, opts.refs, getRef); err != nil { + if err := formatter.ServiceInspectWrite(serviceCtx, opts.refs, getRef, getNetwork); err != nil { return cli.StatusError{StatusCode: 1, Status: err.Error()} } return nil diff --git a/cli/command/service/inspect_test.go b/cli/command/service/inspect_test.go index 94c96cc164..44d9df9176 100644 --- a/cli/command/service/inspect_test.go +++ b/cli/command/service/inspect_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/cli/command/formatter" "github.com/docker/docker/pkg/testutil/assert" @@ -43,18 +44,18 @@ func formatServiceInspect(t *testing.T, format formatter.Format, now time.Time) ContainerSpec: swarm.ContainerSpec{ Image: "foo/bar@sha256:this_is_a_test", }, + Networks: []swarm.NetworkAttachmentConfig{ + { + Target: "5vpyomhb6ievnk0i0o60gcnei", + Aliases: []string{"web"}, + }, + }, }, Mode: swarm.ServiceMode{ Replicated: &swarm.ReplicatedService{ Replicas: &two, }, }, - Networks: []swarm.NetworkAttachmentConfig{ - { - Target: "5vpyomhb6ievnk0i0o60gcnei", - Aliases: []string{"web"}, - }, - }, EndpointSpec: endpointSpec, }, Endpoint: swarm.Endpoint{ @@ -84,9 +85,17 @@ func formatServiceInspect(t *testing.T, format formatter.Format, now time.Time) Format: format, } - err := formatter.ServiceInspectWrite(ctx, []string{"de179gar9d0o7ltdybungplod"}, func(ref string) (interface{}, []byte, error) { - return s, nil, nil - }) + err := formatter.ServiceInspectWrite(ctx, []string{"de179gar9d0o7ltdybungplod"}, + func(ref string) (interface{}, []byte, error) { + return s, nil, nil + }, + func(ref string) (interface{}, []byte, error) { + return types.NetworkResource{ + ID: "5vpyomhb6ievnk0i0o60gcnei", + Name: "mynetwork", + }, nil, nil + }, + ) if err != nil { t.Fatal(err) } @@ -98,6 +107,9 @@ func TestPrettyPrintWithNoUpdateConfig(t *testing.T) { if strings.Contains(s, "UpdateStatus") { t.Fatal("Pretty print failed before parsing UpdateStatus") } + if !strings.Contains(s, "mynetwork") { + t.Fatal("network name not found in inspect output") + } } func TestJSONFormatWithNoUpdateConfig(t *testing.T) {