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

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
Aaron Lehmann 2017-04-07 16:37:03 -07:00
parent f804f893b6
commit 008f6d1b3f
3 changed files with 55 additions and 14 deletions

View File

@ -6,6 +6,7 @@ import (
"time" "time"
"github.com/docker/distribution/reference" "github.com/docker/distribution/reference"
"github.com/docker/docker/api/types"
mounttypes "github.com/docker/docker/api/types/mount" mounttypes "github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command/inspect" "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 // 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 { if ctx.Format != serviceInspectPrettyTemplate {
return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef) 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 { if !ok {
return errors.Errorf("got wrong object to inspect") 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 return err
} }
} }
@ -164,6 +177,10 @@ func ServiceInspectWrite(ctx Context, refs []string, getRef inspect.GetRefFunc)
type serviceInspectContext struct { type serviceInspectContext struct {
swarm.Service swarm.Service
subContext 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) { func (ctx *serviceInspectContext) MarshalJSON() ([]byte, error) {
@ -383,9 +400,13 @@ func (ctx *serviceInspectContext) ResourceLimitMemory() string {
func (ctx *serviceInspectContext) Networks() []string { func (ctx *serviceInspectContext) Networks() []string {
var out []string var out []string
for _, n := range ctx.Service.Spec.Networks { 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) out = append(out, n.Target)
} }
}
return out return out
} }

View File

@ -58,6 +58,14 @@ func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
return nil, nil, errors.Errorf("Error: no such service: %s", ref) 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 f := opts.format
if len(f) == 0 { if len(f) == 0 {
f = "raw" f = "raw"
@ -77,7 +85,7 @@ func runInspect(dockerCli *command.DockerCli, opts inspectOptions) error {
Format: formatter.NewServiceFormat(f), 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 cli.StatusError{StatusCode: 1, Status: err.Error()}
} }
return nil return nil

View File

@ -7,6 +7,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/cli/command/formatter" "github.com/docker/docker/cli/command/formatter"
"github.com/docker/docker/pkg/testutil/assert" "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{ ContainerSpec: swarm.ContainerSpec{
Image: "foo/bar@sha256:this_is_a_test", Image: "foo/bar@sha256:this_is_a_test",
}, },
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &two,
},
},
Networks: []swarm.NetworkAttachmentConfig{ Networks: []swarm.NetworkAttachmentConfig{
{ {
Target: "5vpyomhb6ievnk0i0o60gcnei", Target: "5vpyomhb6ievnk0i0o60gcnei",
Aliases: []string{"web"}, Aliases: []string{"web"},
}, },
}, },
},
Mode: swarm.ServiceMode{
Replicated: &swarm.ReplicatedService{
Replicas: &two,
},
},
EndpointSpec: endpointSpec, EndpointSpec: endpointSpec,
}, },
Endpoint: swarm.Endpoint{ Endpoint: swarm.Endpoint{
@ -84,9 +85,17 @@ func formatServiceInspect(t *testing.T, format formatter.Format, now time.Time)
Format: format, Format: format,
} }
err := formatter.ServiceInspectWrite(ctx, []string{"de179gar9d0o7ltdybungplod"}, func(ref string) (interface{}, []byte, error) { err := formatter.ServiceInspectWrite(ctx, []string{"de179gar9d0o7ltdybungplod"},
func(ref string) (interface{}, []byte, error) {
return s, nil, nil return s, nil, nil
}) },
func(ref string) (interface{}, []byte, error) {
return types.NetworkResource{
ID: "5vpyomhb6ievnk0i0o60gcnei",
Name: "mynetwork",
}, nil, nil
},
)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -98,6 +107,9 @@ func TestPrettyPrintWithNoUpdateConfig(t *testing.T) {
if strings.Contains(s, "UpdateStatus") { if strings.Contains(s, "UpdateStatus") {
t.Fatal("Pretty print failed before parsing 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) { func TestJSONFormatWithNoUpdateConfig(t *testing.T) {