func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) { fmt.Fprintf(out, " Image:\t\t%s\n", containerSpec.Image) if len(containerSpec.Command) > 0 { fmt.Fprintf(out, " Command:\t%s\n", strings.Join(containerSpec.Command, " ")) } if len(containerSpec.Args) > 0 { fmt.Fprintf(out, " Args:\t%s\n", strings.Join(containerSpec.Args, " ")) } if len(containerSpec.Env) > 0 { fmt.Fprintf(out, " Env:\t\t%s\n", strings.Join(containerSpec.Env, " ")) } ioutils.FprintfIfNotEmpty(out, " Dir\t\t%s\n", containerSpec.Dir) ioutils.FprintfIfNotEmpty(out, " User\t\t%s\n", containerSpec.User) }
func printContainerSpec(out io.Writer, containerSpec swarm.ContainerSpec) { fmt.Fprintf(out, " Image:\t\t%s\n", containerSpec.Image) if len(containerSpec.Args) > 0 { fmt.Fprintf(out, " Args:\t\t%s\n", strings.Join(containerSpec.Args, " ")) } if len(containerSpec.Env) > 0 { fmt.Fprintf(out, " Env:\t\t%s\n", strings.Join(containerSpec.Env, " ")) } ioutils.FprintfIfNotEmpty(out, " Dir\t\t%s\n", containerSpec.Dir) ioutils.FprintfIfNotEmpty(out, " User\t\t%s\n", containerSpec.User) if len(containerSpec.Mounts) > 0 { fmt.Fprintln(out, " Mounts:") for _, v := range containerSpec.Mounts { fmt.Fprintf(out, " Target = %s\n", v.Target) fmt.Fprintf(out, " Source = %s\n", v.Source) fmt.Fprintf(out, " ReadOnly = %v\n", v.ReadOnly) fmt.Fprintf(out, " Type = %v\n", v.Type) } } }
// CmdInfo displays system-wide information. // // Usage: docker info func (cli *DockerCli) CmdInfo(args ...string) error { cmd := cli.Subcmd("info", nil, "Display system-wide information", true) cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) rdr, _, _, err := cli.call("GET", "/info", nil, nil) if err != nil { return err } defer rdr.Close() info := &types.Info{} if err := json.NewDecoder(rdr).Decode(info); err != nil { return fmt.Errorf("Error reading remote info: %v", err) } fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers) fmt.Fprintf(cli.out, "Images: %d\n", info.Images) ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver) if info.DriverStatus != nil { for _, pair := range info.DriverStatus { fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1]) } } ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver) ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver) ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion) ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem) fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU) fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name) ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID) if info.Debug { fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug) fmt.Fprintf(cli.out, "File Descriptors: %d\n", info.NFd) fmt.Fprintf(cli.out, "Goroutines: %d\n", info.NGoroutines) fmt.Fprintf(cli.out, "System Time: %s\n", info.SystemTime) fmt.Fprintf(cli.out, "EventsListeners: %d\n", info.NEventsListener) fmt.Fprintf(cli.out, "Init SHA1: %s\n", info.InitSha1) fmt.Fprintf(cli.out, "Init Path: %s\n", info.InitPath) fmt.Fprintf(cli.out, "Docker Root Dir: %s\n", info.DockerRootDir) } ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HttpProxy) ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HttpsProxy) ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy) if info.IndexServerAddress != "" { u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username if len(u) > 0 { fmt.Fprintf(cli.out, "Username: %v\n", u) fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress) } } if !info.MemoryLimit { fmt.Fprintf(cli.err, "WARNING: No memory limit support\n") } if !info.SwapLimit { fmt.Fprintf(cli.err, "WARNING: No swap limit support\n") } if !info.IPv4Forwarding { fmt.Fprintf(cli.err, "WARNING: IPv4 forwarding is disabled.\n") } if !info.BridgeNfIptables { fmt.Fprintf(cli.err, "WARNING: bridge-nf-call-iptables is disabled\n") } if !info.BridgeNfIp6tables { fmt.Fprintf(cli.err, "WARNING: bridge-nf-call-ip6tables is disabled\n") } if info.Labels != nil { fmt.Fprintln(cli.out, "Labels:") for _, attribute := range info.Labels { fmt.Fprintf(cli.out, " %s\n", attribute) } } if info.ExperimentalBuild { fmt.Fprintf(cli.out, "Experimental: true\n") } return nil }
func prettyPrintInfo(dockerCli *client.DockerCli, info types.Info) error { fmt.Fprintf(dockerCli.Out(), "Containers: %d\n", info.Containers) fmt.Fprintf(dockerCli.Out(), " Running: %d\n", info.ContainersRunning) fmt.Fprintf(dockerCli.Out(), " Paused: %d\n", info.ContainersPaused) fmt.Fprintf(dockerCli.Out(), " Stopped: %d\n", info.ContainersStopped) fmt.Fprintf(dockerCli.Out(), "Images: %d\n", info.Images) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Server Version: %s\n", info.ServerVersion) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Storage Driver: %s\n", info.Driver) if info.DriverStatus != nil { for _, pair := range info.DriverStatus { fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1]) // print a warning if devicemapper is using a loopback file if pair[0] == "Data loop file" { fmt.Fprintln(dockerCli.Err(), " WARNING: Usage of loopback devices is strongly discouraged for production use. Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.") } } } if info.SystemStatus != nil { for _, pair := range info.SystemStatus { fmt.Fprintf(dockerCli.Out(), "%s: %s\n", pair[0], pair[1]) } } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Logging Driver: %s\n", info.LoggingDriver) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Cgroup Driver: %s\n", info.CgroupDriver) fmt.Fprintf(dockerCli.Out(), "Plugins: \n") fmt.Fprintf(dockerCli.Out(), " Volume:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Volume, " ")) fmt.Fprintf(dockerCli.Out(), "\n") fmt.Fprintf(dockerCli.Out(), " Network:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Network, " ")) fmt.Fprintf(dockerCli.Out(), "\n") if len(info.Plugins.Authorization) != 0 { fmt.Fprintf(dockerCli.Out(), " Authorization:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Authorization, " ")) fmt.Fprintf(dockerCli.Out(), "\n") } fmt.Fprintf(dockerCli.Out(), "Swarm: %v\n", info.Swarm.LocalNodeState) if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive { fmt.Fprintf(dockerCli.Out(), " NodeID: %s\n", info.Swarm.NodeID) if info.Swarm.Error != "" { fmt.Fprintf(dockerCli.Out(), " Error: %v\n", info.Swarm.Error) } fmt.Fprintf(dockerCli.Out(), " Is Manager: %v\n", info.Swarm.ControlAvailable) if info.Swarm.ControlAvailable { fmt.Fprintf(dockerCli.Out(), " ClusterID: %s\n", info.Swarm.Cluster.ID) fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers) fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes) fmt.Fprintf(dockerCli.Out(), " Orchestration:\n") fmt.Fprintf(dockerCli.Out(), " Task History Retention Limit: %d\n", info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit) fmt.Fprintf(dockerCli.Out(), " Raft:\n") fmt.Fprintf(dockerCli.Out(), " Snapshot Interval: %d\n", info.Swarm.Cluster.Spec.Raft.SnapshotInterval) fmt.Fprintf(dockerCli.Out(), " Heartbeat Tick: %d\n", info.Swarm.Cluster.Spec.Raft.HeartbeatTick) fmt.Fprintf(dockerCli.Out(), " Election Tick: %d\n", info.Swarm.Cluster.Spec.Raft.ElectionTick) fmt.Fprintf(dockerCli.Out(), " Dispatcher:\n") fmt.Fprintf(dockerCli.Out(), " Heartbeat Period: %s\n", units.HumanDuration(time.Duration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))) fmt.Fprintf(dockerCli.Out(), " CA Configuration:\n") fmt.Fprintf(dockerCli.Out(), " Expiry Duration: %s\n", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry)) if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 { fmt.Fprintf(dockerCli.Out(), " External CAs:\n") for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs { fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL) } } } fmt.Fprintf(dockerCli.Out(), " Node Address: %s\n", info.Swarm.NodeAddr) } if len(info.Runtimes) > 0 { fmt.Fprintf(dockerCli.Out(), "Runtimes:") for name := range info.Runtimes { fmt.Fprintf(dockerCli.Out(), " %s", name) } fmt.Fprint(dockerCli.Out(), "\n") fmt.Fprintf(dockerCli.Out(), "Default Runtime: %s\n", info.DefaultRuntime) } fmt.Fprintf(dockerCli.Out(), "Security Options:") ioutils.FprintfIfNotEmpty(dockerCli.Out(), " %s", strings.Join(info.SecurityOptions, " ")) fmt.Fprintf(dockerCli.Out(), "\n") ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Kernel Version: %s\n", info.KernelVersion) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Operating System: %s\n", info.OperatingSystem) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "OSType: %s\n", info.OSType) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Architecture: %s\n", info.Architecture) fmt.Fprintf(dockerCli.Out(), "CPUs: %d\n", info.NCPU) fmt.Fprintf(dockerCli.Out(), "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Name: %s\n", info.Name) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "ID: %s\n", info.ID) fmt.Fprintf(dockerCli.Out(), "Docker Root Dir: %s\n", info.DockerRootDir) fmt.Fprintf(dockerCli.Out(), "Debug Mode (client): %v\n", utils.IsDebugEnabled()) fmt.Fprintf(dockerCli.Out(), "Debug Mode (server): %v\n", info.Debug) if info.Debug { fmt.Fprintf(dockerCli.Out(), " File Descriptors: %d\n", info.NFd) fmt.Fprintf(dockerCli.Out(), " Goroutines: %d\n", info.NGoroutines) fmt.Fprintf(dockerCli.Out(), " System Time: %s\n", info.SystemTime) fmt.Fprintf(dockerCli.Out(), " EventsListeners: %d\n", info.NEventsListener) } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Http Proxy: %s\n", info.HTTPProxy) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Https Proxy: %s\n", info.HTTPSProxy) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "No Proxy: %s\n", info.NoProxy) if info.IndexServerAddress != "" { u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username if len(u) > 0 { fmt.Fprintf(dockerCli.Out(), "Username: %v\n", u) } fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress) } // Only output these warnings if the server does not support these features if info.OSType != "windows" { if !info.MemoryLimit { fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support") } if !info.SwapLimit { fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support") } if !info.KernelMemory { fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support") } if !info.OomKillDisable { fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support") } if !info.CPUCfsQuota { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support") } if !info.CPUCfsPeriod { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support") } if !info.CPUShares { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support") } if !info.CPUSet { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support") } if !info.IPv4Forwarding { fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled") } if !info.BridgeNfIptables { fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled") } if !info.BridgeNfIP6tables { fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled") } } if info.Labels != nil { fmt.Fprintln(dockerCli.Out(), "Labels:") for _, attribute := range info.Labels { fmt.Fprintf(dockerCli.Out(), " %s\n", attribute) } } ioutils.FprintfIfTrue(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild) if info.ClusterStore != "" { fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore) } if info.ClusterAdvertise != "" { fmt.Fprintf(dockerCli.Out(), "Cluster Advertise: %s\n", info.ClusterAdvertise) } if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) { fmt.Fprintln(dockerCli.Out(), "Insecure Registries:") for _, registry := range info.RegistryConfig.IndexConfigs { if registry.Secure == false { fmt.Fprintf(dockerCli.Out(), " %s\n", registry.Name) } } for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs { mask, _ := registry.Mask.Size() fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask) } } if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 { fmt.Fprintln(dockerCli.Out(), "Registry Mirrors:") for _, mirror := range info.RegistryConfig.Mirrors { fmt.Fprintf(dockerCli.Out(), " %s\n", mirror) } } fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n", info.LiveRestoreEnabled) return nil }
// TODO: use a template func printNode(out io.Writer, node swarm.Node) { fmt.Fprintf(out, "ID:\t\t\t%s\n", node.ID) ioutils.FprintfIfNotEmpty(out, "Name:\t\t\t%s\n", node.Spec.Name) if node.Spec.Labels != nil { fmt.Fprintln(out, "Labels:") for k, v := range node.Spec.Labels { fmt.Fprintf(out, " - %s = %s\n", k, v) } } ioutils.FprintfIfNotEmpty(out, "Hostname:\t\t%s\n", node.Description.Hostname) fmt.Fprintln(out, "Status:") fmt.Fprintf(out, " State:\t\t\t%s\n", client.PrettyPrint(node.Status.State)) ioutils.FprintfIfNotEmpty(out, " Message:\t\t%s\n", client.PrettyPrint(node.Status.Message)) fmt.Fprintf(out, " Availability:\t\t%s\n", client.PrettyPrint(node.Spec.Availability)) if node.ManagerStatus != nil { fmt.Fprintln(out, "Manager Status:") fmt.Fprintf(out, " Address:\t\t%s\n", node.ManagerStatus.Addr) fmt.Fprintf(out, " Raft Status:\t\t%s\n", client.PrettyPrint(node.ManagerStatus.Reachability)) leader := "No" if node.ManagerStatus.Leader { leader = "Yes" } fmt.Fprintf(out, " Leader:\t\t%s\n", leader) } fmt.Fprintln(out, "Platform:") fmt.Fprintf(out, " Operating System:\t%s\n", node.Description.Platform.OS) fmt.Fprintf(out, " Architecture:\t\t%s\n", node.Description.Platform.Architecture) fmt.Fprintln(out, "Resources:") fmt.Fprintf(out, " CPUs:\t\t\t%d\n", node.Description.Resources.NanoCPUs/1e9) fmt.Fprintf(out, " Memory:\t\t%s\n", units.BytesSize(float64(node.Description.Resources.MemoryBytes))) var pluginTypes []string pluginNamesByType := map[string][]string{} for _, p := range node.Description.Engine.Plugins { // append to pluginTypes only if not done previously if _, ok := pluginNamesByType[p.Type]; !ok { pluginTypes = append(pluginTypes, p.Type) } pluginNamesByType[p.Type] = append(pluginNamesByType[p.Type], p.Name) } if len(pluginTypes) > 0 { fmt.Fprintln(out, "Plugins:") sort.Strings(pluginTypes) // ensure stable output for _, pluginType := range pluginTypes { fmt.Fprintf(out, " %s:\t\t%s\n", pluginType, strings.Join(pluginNamesByType[pluginType], ", ")) } } fmt.Fprintf(out, "Engine Version:\t\t%s\n", node.Description.Engine.EngineVersion) if len(node.Description.Engine.Labels) != 0 { fmt.Fprintln(out, "Engine Labels:") for k, v := range node.Description.Engine.Labels { fmt.Fprintf(out, " - %s = %s", k, v) } } }
func runInfo(dockerCli *client.DockerCli) error { info, err := dockerCli.Client().Info(context.Background()) if err != nil { return err } fmt.Fprintf(dockerCli.Out(), "Containers: %d\n", info.Containers) fmt.Fprintf(dockerCli.Out(), " Running: %d\n", info.ContainersRunning) fmt.Fprintf(dockerCli.Out(), " Paused: %d\n", info.ContainersPaused) fmt.Fprintf(dockerCli.Out(), " Stopped: %d\n", info.ContainersStopped) fmt.Fprintf(dockerCli.Out(), "Images: %d\n", info.Images) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Server Version: %s\n", info.ServerVersion) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Storage Driver: %s\n", info.Driver) if info.DriverStatus != nil { for _, pair := range info.DriverStatus { fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1]) // print a warning if devicemapper is using a loopback file if pair[0] == "Data loop file" { fmt.Fprintln(dockerCli.Err(), " WARNING: Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.") } } } if info.SystemStatus != nil { for _, pair := range info.SystemStatus { fmt.Fprintf(dockerCli.Out(), "%s: %s\n", pair[0], pair[1]) } } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Execution Driver: %s\n", info.ExecutionDriver) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Logging Driver: %s\n", info.LoggingDriver) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Cgroup Driver: %s\n", info.CgroupDriver) fmt.Fprintf(dockerCli.Out(), "Plugins: \n") fmt.Fprintf(dockerCli.Out(), " Volume:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Volume, " ")) fmt.Fprintf(dockerCli.Out(), "\n") fmt.Fprintf(dockerCli.Out(), " Network:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Network, " ")) fmt.Fprintf(dockerCli.Out(), "\n") if len(info.Plugins.Authorization) != 0 { fmt.Fprintf(dockerCli.Out(), " Authorization:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Authorization, " ")) fmt.Fprintf(dockerCli.Out(), "\n") } fmt.Fprintf(dockerCli.Out(), "Swarm: %v\n", info.Swarm.LocalNodeState) if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive { fmt.Fprintf(dockerCli.Out(), " NodeID: %s\n", info.Swarm.NodeID) if info.Swarm.Error != "" { fmt.Fprintf(dockerCli.Out(), " Error: %v\n", info.Swarm.Error) } if info.Swarm.ControlAvailable { fmt.Fprintf(dockerCli.Out(), " IsManager: Yes\n") fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers) fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes) ioutils.FprintfIfNotEmpty(dockerCli.Out(), " CACertHash: %s\n", info.Swarm.CACertHash) } else { fmt.Fprintf(dockerCli.Out(), " IsManager: No\n") } } if len(info.Runtimes) > 0 { fmt.Fprintf(dockerCli.Out(), "Runtimes:") for name := range info.Runtimes { fmt.Fprintf(dockerCli.Out(), " %s", name) } fmt.Fprint(dockerCli.Out(), "\n") fmt.Fprintf(dockerCli.Out(), "Default Runtime: %s\n", info.DefaultRuntime) } fmt.Fprintf(dockerCli.Out(), "Security Options:") ioutils.FprintfIfNotEmpty(dockerCli.Out(), " %s", strings.Join(info.SecurityOptions, " ")) fmt.Fprintf(dockerCli.Out(), "\n") ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Kernel Version: %s\n", info.KernelVersion) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Operating System: %s\n", info.OperatingSystem) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "OSType: %s\n", info.OSType) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Architecture: %s\n", info.Architecture) fmt.Fprintf(dockerCli.Out(), "CPUs: %d\n", info.NCPU) fmt.Fprintf(dockerCli.Out(), "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Name: %s\n", info.Name) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "ID: %s\n", info.ID) fmt.Fprintf(dockerCli.Out(), "Docker Root Dir: %s\n", info.DockerRootDir) fmt.Fprintf(dockerCli.Out(), "Debug Mode (client): %v\n", utils.IsDebugEnabled()) fmt.Fprintf(dockerCli.Out(), "Debug Mode (server): %v\n", info.Debug) if info.Debug { fmt.Fprintf(dockerCli.Out(), " File Descriptors: %d\n", info.NFd) fmt.Fprintf(dockerCli.Out(), " Goroutines: %d\n", info.NGoroutines) fmt.Fprintf(dockerCli.Out(), " System Time: %s\n", info.SystemTime) fmt.Fprintf(dockerCli.Out(), " EventsListeners: %d\n", info.NEventsListener) } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Http Proxy: %s\n", info.HTTPProxy) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Https Proxy: %s\n", info.HTTPSProxy) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "No Proxy: %s\n", info.NoProxy) if info.IndexServerAddress != "" { u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username if len(u) > 0 { fmt.Fprintf(dockerCli.Out(), "Username: %v\n", u) } fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress) } // Only output these warnings if the server does not support these features if info.OSType != "windows" { if !info.MemoryLimit { fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support") } if !info.SwapLimit { fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support") } if !info.KernelMemory { fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support") } if !info.OomKillDisable { fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support") } if !info.CPUCfsQuota { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support") } if !info.CPUCfsPeriod { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support") } if !info.CPUShares { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support") } if !info.CPUSet { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support") } if !info.IPv4Forwarding { fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled") } if !info.BridgeNfIptables { fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled") } if !info.BridgeNfIP6tables { fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled") } } if info.Labels != nil { fmt.Fprintln(dockerCli.Out(), "Labels:") for _, attribute := range info.Labels { fmt.Fprintf(dockerCli.Out(), " %s\n", attribute) } } ioutils.FprintfIfTrue(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild) if info.ClusterStore != "" { fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore) } if info.ClusterAdvertise != "" { fmt.Fprintf(dockerCli.Out(), "Cluster Advertise: %s\n", info.ClusterAdvertise) } if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) { fmt.Fprintln(dockerCli.Out(), "Insecure Registries:") for _, registry := range info.RegistryConfig.IndexConfigs { if registry.Secure == false { fmt.Fprintf(dockerCli.Out(), " %s\n", registry.Name) } } for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs { mask, _ := registry.Mask.Size() fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask) } } return nil }
func prettyPrintInfo(dockerCli *command.DockerCli, info types.Info) error { fmt.Fprintf(dockerCli.Out(), "Containers: %d\n", info.Containers) fmt.Fprintf(dockerCli.Out(), " Running: %d\n", info.ContainersRunning) fmt.Fprintf(dockerCli.Out(), " Paused: %d\n", info.ContainersPaused) fmt.Fprintf(dockerCli.Out(), " Stopped: %d\n", info.ContainersStopped) fmt.Fprintf(dockerCli.Out(), "Images: %d\n", info.Images) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Server Version: %s\n", info.ServerVersion) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Storage Driver: %s\n", info.Driver) if info.DriverStatus != nil { for _, pair := range info.DriverStatus { fmt.Fprintf(dockerCli.Out(), " %s: %s\n", pair[0], pair[1]) // print a warning if devicemapper is using a loopback file if pair[0] == "Data loop file" { fmt.Fprintln(dockerCli.Err(), " WARNING: Usage of loopback devices is strongly discouraged for production use. Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.") } } } if info.SystemStatus != nil { for _, pair := range info.SystemStatus { fmt.Fprintf(dockerCli.Out(), "%s: %s\n", pair[0], pair[1]) } } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Logging Driver: %s\n", info.LoggingDriver) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Cgroup Driver: %s\n", info.CgroupDriver) fmt.Fprintf(dockerCli.Out(), "Plugins: \n") fmt.Fprintf(dockerCli.Out(), " Volume:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Volume, " ")) fmt.Fprintf(dockerCli.Out(), "\n") fmt.Fprintf(dockerCli.Out(), " Network:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Network, " ")) fmt.Fprintf(dockerCli.Out(), "\n") if len(info.Plugins.Authorization) != 0 { fmt.Fprintf(dockerCli.Out(), " Authorization:") fmt.Fprintf(dockerCli.Out(), " %s", strings.Join(info.Plugins.Authorization, " ")) fmt.Fprintf(dockerCli.Out(), "\n") } fmt.Fprintf(dockerCli.Out(), "Swarm: %v\n", info.Swarm.LocalNodeState) if info.Swarm.LocalNodeState != swarm.LocalNodeStateInactive && info.Swarm.LocalNodeState != swarm.LocalNodeStateLocked { fmt.Fprintf(dockerCli.Out(), " NodeID: %s\n", info.Swarm.NodeID) if info.Swarm.Error != "" { fmt.Fprintf(dockerCli.Out(), " Error: %v\n", info.Swarm.Error) } fmt.Fprintf(dockerCli.Out(), " Is Manager: %v\n", info.Swarm.ControlAvailable) if info.Swarm.ControlAvailable { fmt.Fprintf(dockerCli.Out(), " ClusterID: %s\n", info.Swarm.Cluster.ID) fmt.Fprintf(dockerCli.Out(), " Managers: %d\n", info.Swarm.Managers) fmt.Fprintf(dockerCli.Out(), " Nodes: %d\n", info.Swarm.Nodes) fmt.Fprintf(dockerCli.Out(), " Orchestration:\n") taskHistoryRetentionLimit := int64(0) if info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit != nil { taskHistoryRetentionLimit = *info.Swarm.Cluster.Spec.Orchestration.TaskHistoryRetentionLimit } fmt.Fprintf(dockerCli.Out(), " Task History Retention Limit: %d\n", taskHistoryRetentionLimit) fmt.Fprintf(dockerCli.Out(), " Raft:\n") fmt.Fprintf(dockerCli.Out(), " Snapshot Interval: %d\n", info.Swarm.Cluster.Spec.Raft.SnapshotInterval) if info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots != nil { fmt.Fprintf(dockerCli.Out(), " Number of Old Snapshots to Retain: %d\n", *info.Swarm.Cluster.Spec.Raft.KeepOldSnapshots) } fmt.Fprintf(dockerCli.Out(), " Heartbeat Tick: %d\n", info.Swarm.Cluster.Spec.Raft.HeartbeatTick) fmt.Fprintf(dockerCli.Out(), " Election Tick: %d\n", info.Swarm.Cluster.Spec.Raft.ElectionTick) fmt.Fprintf(dockerCli.Out(), " Dispatcher:\n") fmt.Fprintf(dockerCli.Out(), " Heartbeat Period: %s\n", units.HumanDuration(time.Duration(info.Swarm.Cluster.Spec.Dispatcher.HeartbeatPeriod))) fmt.Fprintf(dockerCli.Out(), " CA Configuration:\n") fmt.Fprintf(dockerCli.Out(), " Expiry Duration: %s\n", units.HumanDuration(info.Swarm.Cluster.Spec.CAConfig.NodeCertExpiry)) if len(info.Swarm.Cluster.Spec.CAConfig.ExternalCAs) > 0 { fmt.Fprintf(dockerCli.Out(), " External CAs:\n") for _, entry := range info.Swarm.Cluster.Spec.CAConfig.ExternalCAs { fmt.Fprintf(dockerCli.Out(), " %s: %s\n", entry.Protocol, entry.URL) } } } fmt.Fprintf(dockerCli.Out(), " Node Address: %s\n", info.Swarm.NodeAddr) managers := []string{} for _, entry := range info.Swarm.RemoteManagers { managers = append(managers, entry.Addr) } if len(managers) > 0 { sort.Strings(managers) fmt.Fprintf(dockerCli.Out(), " Manager Addresses:\n") for _, entry := range managers { fmt.Fprintf(dockerCli.Out(), " %s\n", entry) } } } if len(info.Runtimes) > 0 { fmt.Fprintf(dockerCli.Out(), "Runtimes:") for name := range info.Runtimes { fmt.Fprintf(dockerCli.Out(), " %s", name) } fmt.Fprint(dockerCli.Out(), "\n") fmt.Fprintf(dockerCli.Out(), "Default Runtime: %s\n", info.DefaultRuntime) } if info.OSType == "linux" { fmt.Fprintf(dockerCli.Out(), "Init Binary: %v\n", info.InitBinary) for _, ci := range []struct { Name string Commit types.Commit }{ {"containerd", info.ContainerdCommit}, {"runc", info.RuncCommit}, {"init", info.InitCommit}, } { fmt.Fprintf(dockerCli.Out(), "%s version: %s", ci.Name, ci.Commit.ID) if ci.Commit.ID != ci.Commit.Expected { fmt.Fprintf(dockerCli.Out(), " (expected: %s)", ci.Commit.Expected) } fmt.Fprintf(dockerCli.Out(), "\n") } if len(info.SecurityOptions) != 0 { fmt.Fprintf(dockerCli.Out(), "Security Options:\n") for _, o := range info.SecurityOptions { switch o.Key { case "Name": fmt.Fprintf(dockerCli.Out(), " %s\n", o.Value) case "Profile": if o.Value != "default" { fmt.Fprintf(dockerCli.Err(), " WARNING: You're not using the default seccomp profile\n") } fmt.Fprintf(dockerCli.Out(), " %s: %s\n", o.Key, o.Value) } } } } // Isolation only has meaning on a Windows daemon. if info.OSType == "windows" { fmt.Fprintf(dockerCli.Out(), "Default Isolation: %v\n", info.Isolation) } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Kernel Version: %s\n", info.KernelVersion) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Operating System: %s\n", info.OperatingSystem) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "OSType: %s\n", info.OSType) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Architecture: %s\n", info.Architecture) fmt.Fprintf(dockerCli.Out(), "CPUs: %d\n", info.NCPU) fmt.Fprintf(dockerCli.Out(), "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Name: %s\n", info.Name) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "ID: %s\n", info.ID) fmt.Fprintf(dockerCli.Out(), "Docker Root Dir: %s\n", info.DockerRootDir) fmt.Fprintf(dockerCli.Out(), "Debug Mode (client): %v\n", utils.IsDebugEnabled()) fmt.Fprintf(dockerCli.Out(), "Debug Mode (server): %v\n", info.Debug) if info.Debug { fmt.Fprintf(dockerCli.Out(), " File Descriptors: %d\n", info.NFd) fmt.Fprintf(dockerCli.Out(), " Goroutines: %d\n", info.NGoroutines) fmt.Fprintf(dockerCli.Out(), " System Time: %s\n", info.SystemTime) fmt.Fprintf(dockerCli.Out(), " EventsListeners: %d\n", info.NEventsListener) } ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Http Proxy: %s\n", info.HTTPProxy) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "Https Proxy: %s\n", info.HTTPSProxy) ioutils.FprintfIfNotEmpty(dockerCli.Out(), "No Proxy: %s\n", info.NoProxy) if info.IndexServerAddress != "" { u := dockerCli.ConfigFile().AuthConfigs[info.IndexServerAddress].Username if len(u) > 0 { fmt.Fprintf(dockerCli.Out(), "Username: %v\n", u) } fmt.Fprintf(dockerCli.Out(), "Registry: %v\n", info.IndexServerAddress) } // Only output these warnings if the server does not support these features if info.OSType != "windows" { if !info.MemoryLimit { fmt.Fprintln(dockerCli.Err(), "WARNING: No memory limit support") } if !info.SwapLimit { fmt.Fprintln(dockerCli.Err(), "WARNING: No swap limit support") } if !info.KernelMemory { fmt.Fprintln(dockerCli.Err(), "WARNING: No kernel memory limit support") } if !info.OomKillDisable { fmt.Fprintln(dockerCli.Err(), "WARNING: No oom kill disable support") } if !info.CPUCfsQuota { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs quota support") } if !info.CPUCfsPeriod { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu cfs period support") } if !info.CPUShares { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpu shares support") } if !info.CPUSet { fmt.Fprintln(dockerCli.Err(), "WARNING: No cpuset support") } if !info.IPv4Forwarding { fmt.Fprintln(dockerCli.Err(), "WARNING: IPv4 forwarding is disabled") } if !info.BridgeNfIptables { fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-iptables is disabled") } if !info.BridgeNfIP6tables { fmt.Fprintln(dockerCli.Err(), "WARNING: bridge-nf-call-ip6tables is disabled") } } if info.Labels != nil { fmt.Fprintln(dockerCli.Out(), "Labels:") for _, attribute := range info.Labels { fmt.Fprintf(dockerCli.Out(), " %s\n", attribute) } // TODO: Engine labels with duplicate keys has been deprecated in 1.13 and will be error out // after 3 release cycles (1.16). For now, a WARNING will be generated. The following will // be removed eventually. labelMap := map[string]string{} for _, label := range info.Labels { stringSlice := strings.SplitN(label, "=", 2) if len(stringSlice) > 1 { // If there is a conflict we will throw out an warning if v, ok := labelMap[stringSlice[0]]; ok && v != stringSlice[1] { fmt.Fprintln(dockerCli.Err(), "WARNING: labels with duplicate keys and conflicting values have been deprecated") break } labelMap[stringSlice[0]] = stringSlice[1] } } } fmt.Fprintf(dockerCli.Out(), "Experimental: %v\n", info.ExperimentalBuild) if info.ClusterStore != "" { fmt.Fprintf(dockerCli.Out(), "Cluster Store: %s\n", info.ClusterStore) } if info.ClusterAdvertise != "" { fmt.Fprintf(dockerCli.Out(), "Cluster Advertise: %s\n", info.ClusterAdvertise) } if info.RegistryConfig != nil && (len(info.RegistryConfig.InsecureRegistryCIDRs) > 0 || len(info.RegistryConfig.IndexConfigs) > 0) { fmt.Fprintln(dockerCli.Out(), "Insecure Registries:") for _, registry := range info.RegistryConfig.IndexConfigs { if registry.Secure == false { fmt.Fprintf(dockerCli.Out(), " %s\n", registry.Name) } } for _, registry := range info.RegistryConfig.InsecureRegistryCIDRs { mask, _ := registry.Mask.Size() fmt.Fprintf(dockerCli.Out(), " %s/%d\n", registry.IP.String(), mask) } } if info.RegistryConfig != nil && len(info.RegistryConfig.Mirrors) > 0 { fmt.Fprintln(dockerCli.Out(), "Registry Mirrors:") for _, mirror := range info.RegistryConfig.Mirrors { fmt.Fprintf(dockerCli.Out(), " %s\n", mirror) } } fmt.Fprintf(dockerCli.Out(), "Live Restore Enabled: %v\n", info.LiveRestoreEnabled) return nil }
// CmdInfo displays system-wide information. // // Usage: docker info func (cli *DockerCli) CmdInfo(args ...string) error { cmd := Cli.Subcmd("info", nil, Cli.DockerCommands["info"].Description, true) cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) info, err := cli.client.Info() if err != nil { return err } fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers) fmt.Fprintf(cli.out, "Images: %d\n", info.Images) ioutils.FprintfIfNotEmpty(cli.out, "Server Version: %s\n", info.ServerVersion) ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver) if info.DriverStatus != nil { for _, pair := range info.DriverStatus { fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1]) // print a warning if devicemapper is using a loopback file if pair[0] == "Data loop file" { fmt.Fprintln(cli.err, " WARNING: Usage of loopback devices is strongly discouraged for production use. Either use `--storage-opt dm.thinpooldev` or use `--storage-opt dm.no_warn_on_loop_devices=true` to suppress this warning.") } } } ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver) ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver) fmt.Fprintf(cli.out, "Plugins: \n") fmt.Fprintf(cli.out, " Volume:") for _, driver := range info.Plugins.Volume { fmt.Fprintf(cli.out, " %s", driver) } fmt.Fprintf(cli.out, "\n") fmt.Fprintf(cli.out, " Network:") for _, driver := range info.Plugins.Network { fmt.Fprintf(cli.out, " %s", driver) } fmt.Fprintf(cli.out, "\n") ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion) ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem) ioutils.FprintfIfNotEmpty(cli.out, "OSType: %s\n", info.OSType) ioutils.FprintfIfNotEmpty(cli.out, "Architecture: %s\n", info.Architecture) fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU) fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name) ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID) if info.Debug { fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug) fmt.Fprintf(cli.out, " File Descriptors: %d\n", info.NFd) fmt.Fprintf(cli.out, " Goroutines: %d\n", info.NGoroutines) fmt.Fprintf(cli.out, " System Time: %s\n", info.SystemTime) fmt.Fprintf(cli.out, " EventsListeners: %d\n", info.NEventsListener) fmt.Fprintf(cli.out, " Init SHA1: %s\n", info.InitSha1) fmt.Fprintf(cli.out, " Init Path: %s\n", info.InitPath) fmt.Fprintf(cli.out, " Docker Root Dir: %s\n", info.DockerRootDir) } ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HTTPProxy) ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HTTPSProxy) ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy) if info.IndexServerAddress != "" { u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username if len(u) > 0 { fmt.Fprintf(cli.out, "Username: %v\n", u) fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress) } } // Only output these warnings if the server does not support these features if info.OSType != "windows" { if !info.MemoryLimit { fmt.Fprintln(cli.err, "WARNING: No memory limit support") } if !info.SwapLimit { fmt.Fprintln(cli.err, "WARNING: No swap limit support") } if !info.OomKillDisable { fmt.Fprintln(cli.err, "WARNING: No oom kill disable support") } if !info.CPUCfsQuota { fmt.Fprintln(cli.err, "WARNING: No cpu cfs quota support") } if !info.CPUCfsPeriod { fmt.Fprintln(cli.err, "WARNING: No cpu cfs period support") } if !info.CPUShares { fmt.Fprintln(cli.err, "WARNING: No cpu shares support") } if !info.CPUSet { fmt.Fprintln(cli.err, "WARNING: No cpuset support") } if !info.IPv4Forwarding { fmt.Fprintln(cli.err, "WARNING: IPv4 forwarding is disabled") } if !info.BridgeNfIptables { fmt.Fprintln(cli.err, "WARNING: bridge-nf-call-iptables is disabled") } if !info.BridgeNfIP6tables { fmt.Fprintln(cli.err, "WARNING: bridge-nf-call-ip6tables is disabled") } } if info.Labels != nil { fmt.Fprintln(cli.out, "Labels:") for _, attribute := range info.Labels { fmt.Fprintf(cli.out, " %s\n", attribute) } } ioutils.FprintfIfTrue(cli.out, "Experimental: %v\n", info.ExperimentalBuild) if info.ClusterStore != "" { fmt.Fprintf(cli.out, "Cluster store: %s\n", info.ClusterStore) } if info.ClusterAdvertise != "" { fmt.Fprintf(cli.out, "Cluster advertise: %s\n", info.ClusterAdvertise) } return nil }
// CmdInfo displays system-wide information. // // Usage: docker info func (cli *DockerCli) CmdInfo(args ...string) error { cmd := Cli.Subcmd("info", nil, Cli.DockerCommands["info"].Description, true) cmd.Require(flag.Exact, 0) cmd.ParseFlags(args, true) serverResp, err := cli.call("GET", "/info", nil, nil) if err != nil { return err } defer serverResp.body.Close() info := &types.Info{} if err := json.NewDecoder(serverResp.body).Decode(info); err != nil { return fmt.Errorf("Error reading remote info: %v", err) } fmt.Fprintf(cli.out, "Containers: %d\n", info.Containers) fmt.Fprintf(cli.out, "Images: %d\n", info.Images) ioutils.FprintfIfNotEmpty(cli.out, "Server Version: %s\n", info.ServerVersion) ioutils.FprintfIfNotEmpty(cli.out, "Storage Driver: %s\n", info.Driver) if info.DriverStatus != nil { for _, pair := range info.DriverStatus { fmt.Fprintf(cli.out, " %s: %s\n", pair[0], pair[1]) } } ioutils.FprintfIfNotEmpty(cli.out, "Execution Driver: %s\n", info.ExecutionDriver) ioutils.FprintfIfNotEmpty(cli.out, "Logging Driver: %s\n", info.LoggingDriver) ioutils.FprintfIfNotEmpty(cli.out, "Kernel Version: %s\n", info.KernelVersion) ioutils.FprintfIfNotEmpty(cli.out, "Operating System: %s\n", info.OperatingSystem) fmt.Fprintf(cli.out, "CPUs: %d\n", info.NCPU) fmt.Fprintf(cli.out, "Total Memory: %s\n", units.BytesSize(float64(info.MemTotal))) ioutils.FprintfIfNotEmpty(cli.out, "Name: %s\n", info.Name) ioutils.FprintfIfNotEmpty(cli.out, "ID: %s\n", info.ID) if info.Debug { fmt.Fprintf(cli.out, "Debug mode (server): %v\n", info.Debug) fmt.Fprintf(cli.out, " File Descriptors: %d\n", info.NFd) fmt.Fprintf(cli.out, " Goroutines: %d\n", info.NGoroutines) fmt.Fprintf(cli.out, " System Time: %s\n", info.SystemTime) fmt.Fprintf(cli.out, " EventsListeners: %d\n", info.NEventsListener) fmt.Fprintf(cli.out, " Init SHA1: %s\n", info.InitSha1) fmt.Fprintf(cli.out, " Init Path: %s\n", info.InitPath) fmt.Fprintf(cli.out, " Docker Root Dir: %s\n", info.DockerRootDir) } ioutils.FprintfIfNotEmpty(cli.out, "Http Proxy: %s\n", info.HTTPProxy) ioutils.FprintfIfNotEmpty(cli.out, "Https Proxy: %s\n", info.HTTPSProxy) ioutils.FprintfIfNotEmpty(cli.out, "No Proxy: %s\n", info.NoProxy) if info.IndexServerAddress != "" { u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username if len(u) > 0 { fmt.Fprintf(cli.out, "Username: %v\n", u) fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress) } } // Only output these warnings if the server does not support these features if h, err := httputils.ParseServerHeader(serverResp.header.Get("Server")); err == nil { if h.OS != "windows" { if !info.MemoryLimit { fmt.Fprintf(cli.err, "WARNING: No memory limit support\n") } if !info.SwapLimit { fmt.Fprintf(cli.err, "WARNING: No swap limit support\n") } if !info.IPv4Forwarding { fmt.Fprintf(cli.err, "WARNING: IPv4 forwarding is disabled\n") } if !info.BridgeNfIptables { fmt.Fprintf(cli.err, "WARNING: bridge-nf-call-iptables is disabled\n") } if !info.BridgeNfIP6tables { fmt.Fprintf(cli.err, "WARNING: bridge-nf-call-ip6tables is disabled\n") } } } if info.Labels != nil { fmt.Fprintln(cli.out, "Labels:") for _, attribute := range info.Labels { fmt.Fprintf(cli.out, " %s\n", attribute) } } ioutils.FprintfIfTrue(cli.out, "Experimental: %v\n", info.ExperimentalBuild) if info.ClusterStore != "" { fmt.Fprintf(cli.out, "Cluster store: %s\n", info.ClusterStore) } if info.ClusterAdvertise != "" { fmt.Fprintf(cli.out, "Cluster advertise: %s\n", info.ClusterAdvertise) } return nil }
// TODO: use a template func printService(out io.Writer, service swarm.Service) { fmt.Fprintf(out, "ID:\t\t%s\n", service.ID) fmt.Fprintf(out, "Name:\t\t%s\n", service.Spec.Name) if service.Spec.Labels != nil { fmt.Fprintln(out, "Labels:") for k, v := range service.Spec.Labels { fmt.Fprintf(out, " - %s=%s\n", k, v) } } if service.Spec.Mode.Global != nil { fmt.Fprintln(out, "Mode:\t\tGlobal") } else { fmt.Fprintln(out, "Mode:\t\tReplicated") if service.Spec.Mode.Replicated.Replicas != nil { fmt.Fprintf(out, " Replicas:\t%d\n", *service.Spec.Mode.Replicated.Replicas) } } if service.UpdateStatus.State != "" { fmt.Fprintln(out, "Update status:") fmt.Fprintf(out, " State:\t\t%s\n", service.UpdateStatus.State) fmt.Fprintf(out, " Started:\t%s ago\n", strings.ToLower(units.HumanDuration(time.Since(service.UpdateStatus.StartedAt)))) if service.UpdateStatus.State == swarm.UpdateStateCompleted { fmt.Fprintf(out, " Completed:\t%s ago\n", strings.ToLower(units.HumanDuration(time.Since(service.UpdateStatus.CompletedAt)))) } fmt.Fprintf(out, " Message:\t%s\n", service.UpdateStatus.Message) } fmt.Fprintln(out, "Placement:") if service.Spec.TaskTemplate.Placement != nil && len(service.Spec.TaskTemplate.Placement.Constraints) > 0 { ioutils.FprintfIfNotEmpty(out, " Constraints\t: %s\n", strings.Join(service.Spec.TaskTemplate.Placement.Constraints, ", ")) } fmt.Fprintf(out, "UpdateConfig:\n") fmt.Fprintf(out, " Parallelism:\t%d\n", service.Spec.UpdateConfig.Parallelism) if service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 { fmt.Fprintf(out, " Delay:\t\t%s\n", service.Spec.UpdateConfig.Delay) } fmt.Fprintf(out, " On failure:\t%s\n", service.Spec.UpdateConfig.FailureAction) fmt.Fprintf(out, "ContainerSpec:\n") printContainerSpec(out, service.Spec.TaskTemplate.ContainerSpec) resources := service.Spec.TaskTemplate.Resources if resources != nil { fmt.Fprintln(out, "Resources:") printResources := func(out io.Writer, requirement string, r *swarm.Resources) { if r == nil || (r.MemoryBytes == 0 && r.NanoCPUs == 0) { return } fmt.Fprintf(out, " %s:\n", requirement) if r.NanoCPUs != 0 { fmt.Fprintf(out, " CPU:\t\t%g\n", float64(r.NanoCPUs)/1e9) } if r.MemoryBytes != 0 { fmt.Fprintf(out, " Memory:\t%s\n", units.BytesSize(float64(r.MemoryBytes))) } } printResources(out, "Reservations", resources.Reservations) printResources(out, "Limits", resources.Limits) } if len(service.Spec.Networks) > 0 { fmt.Fprintf(out, "Networks:") for _, n := range service.Spec.Networks { fmt.Fprintf(out, " %s", n.Target) } } if len(service.Endpoint.Ports) > 0 { fmt.Fprintln(out, "Ports:") for _, port := range service.Endpoint.Ports { ioutils.FprintfIfNotEmpty(out, " Name = %s\n", port.Name) fmt.Fprintf(out, " Protocol = %s\n", port.Protocol) fmt.Fprintf(out, " TargetPort = %d\n", port.TargetPort) fmt.Fprintf(out, " PublishedPort = %d\n", port.PublishedPort) } } }
// TODO: use a template func printService(out io.Writer, service swarm.Service) { fmt.Fprintf(out, "ID:\t\t%s\n", service.ID) fmt.Fprintf(out, "Name:\t\t%s\n", service.Spec.Name) if service.Spec.Labels != nil { fmt.Fprintln(out, "Labels:") for k, v := range service.Spec.Labels { fmt.Fprintf(out, " - %s=%s\n", k, v) } } if service.Spec.Mode.Global != nil { fmt.Fprintln(out, "Mode:\t\tGlobal") } else { fmt.Fprintln(out, "Mode:\t\tReplicated") if service.Spec.Mode.Replicated.Replicas != nil { fmt.Fprintf(out, " Replicas:\t%d\n", *service.Spec.Mode.Replicated.Replicas) } } fmt.Fprintln(out, "Placement:") fmt.Fprintln(out, " Strategy:\tSpread") if service.Spec.TaskTemplate.Placement != nil && len(service.Spec.TaskTemplate.Placement.Constraints) > 0 { ioutils.FprintfIfNotEmpty(out, " Constraints\t: %s\n", strings.Join(service.Spec.TaskTemplate.Placement.Constraints, ", ")) } fmt.Fprintf(out, "UpdateConfig:\n") fmt.Fprintf(out, " Parallelism:\t%d\n", service.Spec.UpdateConfig.Parallelism) if service.Spec.UpdateConfig.Delay.Nanoseconds() > 0 { fmt.Fprintf(out, " Delay:\t\t%s\n", service.Spec.UpdateConfig.Delay) } fmt.Fprintf(out, "ContainerSpec:\n") printContainerSpec(out, service.Spec.TaskTemplate.ContainerSpec) if service.Spec.TaskTemplate.Resources != nil { fmt.Fprintln(out, "Resources:") printResources := func(out io.Writer, r *swarm.Resources) { if r.NanoCPUs != 0 { fmt.Fprintf(out, " CPU:\t\t%g\n", float64(r.NanoCPUs)/1e9) } if r.MemoryBytes != 0 { fmt.Fprintf(out, " Memory:\t\t%s\n", units.BytesSize(float64(r.MemoryBytes))) } } if service.Spec.TaskTemplate.Resources.Reservations != nil { fmt.Fprintln(out, "Reservations:") printResources(out, service.Spec.TaskTemplate.Resources.Reservations) } if service.Spec.TaskTemplate.Resources.Limits != nil { fmt.Fprintln(out, "Limits:") printResources(out, service.Spec.TaskTemplate.Resources.Limits) } } if len(service.Spec.Networks) > 0 { fmt.Fprintf(out, "Networks:") for _, n := range service.Spec.Networks { fmt.Fprintf(out, " %s", n.Target) } } if len(service.Endpoint.Ports) > 0 { fmt.Fprintln(out, "Ports:") for _, port := range service.Endpoint.Ports { fmt.Fprintf(out, " Name = %s\n", port.Name) fmt.Fprintf(out, " Protocol = %s\n", port.Protocol) fmt.Fprintf(out, " TargetPort = %d\n", port.TargetPort) fmt.Fprintf(out, " PublishedPort = %d\n", port.PublishedPort) } } }