Browse Source

Show network names in "docker service inspect --pretty"

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
Aaron Lehmann 8 years ago
parent
commit
56f1da77c3

+ 25 - 4
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
 }

+ 9 - 1
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

+ 21 - 9
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) {