2016-09-08 13:11:39 -04:00
package system
import (
2018-05-03 21:02:44 -04:00
"context"
2016-09-08 13:11:39 -04:00
"fmt"
2017-05-10 16:38:06 -04:00
"io"
2016-11-03 14:23:58 -04:00
"sort"
2016-09-08 13:11:39 -04:00
"strings"
2017-04-17 18:07:56 -04:00
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/debug"
2017-08-08 11:26:24 -04:00
"github.com/docker/cli/templates"
2016-09-08 13:11:39 -04:00
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/go-units"
"github.com/spf13/cobra"
)
type infoOptions struct {
format string
}
// NewInfoCommand creates a new cobra.Command for `docker info`
2017-10-11 12:18:27 -04:00
func NewInfoCommand ( dockerCli command . Cli ) * cobra . Command {
2016-09-08 13:11:39 -04:00
var opts infoOptions
cmd := & cobra . Command {
Use : "info [OPTIONS]" ,
Short : "Display system-wide information" ,
Args : cli . NoArgs ,
RunE : func ( cmd * cobra . Command , args [ ] string ) error {
return runInfo ( dockerCli , & opts )
} ,
}
flags := cmd . Flags ( )
2016-10-18 06:50:11 -04:00
flags . StringVarP ( & opts . format , "format" , "f" , "" , "Format the output using the given Go template" )
2016-09-08 13:11:39 -04:00
return cmd
}
2017-10-11 12:18:27 -04:00
func runInfo ( dockerCli command . Cli , opts * infoOptions ) error {
2016-09-08 13:11:39 -04:00
ctx := context . Background ( )
info , err := dockerCli . Client ( ) . Info ( ctx )
if err != nil {
return err
}
if opts . format == "" {
return prettyPrintInfo ( dockerCli , info )
}
return formatInfo ( dockerCli , info , opts . format )
}
2017-05-02 16:14:43 -04:00
// nolint: gocyclo
2017-08-24 18:42:11 -04:00
func prettyPrintInfo ( dockerCli command . Cli , info types . Info ) error {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Containers:" , info . Containers )
fmt . Fprintln ( dockerCli . Out ( ) , " Running:" , info . ContainersRunning )
fmt . Fprintln ( dockerCli . Out ( ) , " Paused:" , info . ContainersPaused )
fmt . Fprintln ( dockerCli . Out ( ) , " Stopped:" , info . ContainersStopped )
fmt . Fprintln ( dockerCli . Out ( ) , "Images:" , info . Images )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Server Version:" , info . ServerVersion )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Storage Driver:" , info . Driver )
2016-09-08 13:11:39 -04:00
if info . DriverStatus != nil {
for _ , pair := range info . DriverStatus {
fmt . Fprintf ( dockerCli . Out ( ) , " %s: %s\n" , pair [ 0 ] , pair [ 1 ] )
}
}
if info . SystemStatus != nil {
for _ , pair := range info . SystemStatus {
fmt . Fprintf ( dockerCli . Out ( ) , "%s: %s\n" , pair [ 0 ] , pair [ 1 ] )
}
}
2017-08-06 17:23:15 -04:00
fprintlnNonEmpty ( dockerCli . Out ( ) , "Logging Driver:" , info . LoggingDriver )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Cgroup Driver:" , info . CgroupDriver )
2016-09-08 13:11:39 -04:00
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Plugins:" )
fmt . Fprintln ( dockerCli . Out ( ) , " Volume:" , strings . Join ( info . Plugins . Volume , " " ) )
fmt . Fprintln ( dockerCli . Out ( ) , " Network:" , strings . Join ( info . Plugins . Network , " " ) )
2016-09-08 13:11:39 -04:00
if len ( info . Plugins . Authorization ) != 0 {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " Authorization:" , strings . Join ( info . Plugins . Authorization , " " ) )
2016-09-08 13:11:39 -04:00
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " Log:" , strings . Join ( info . Plugins . Log , " " ) )
2017-04-11 17:21:21 -04:00
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Swarm:" , info . Swarm . LocalNodeState )
printSwarmInfo ( dockerCli , info )
2016-09-08 13:11:39 -04:00
if len ( info . Runtimes ) > 0 {
2017-08-06 17:23:15 -04:00
fmt . Fprint ( dockerCli . Out ( ) , "Runtimes:" )
2016-09-08 13:11:39 -04:00
for name := range info . Runtimes {
fmt . Fprintf ( dockerCli . Out ( ) , " %s" , name )
}
fmt . Fprint ( dockerCli . Out ( ) , "\n" )
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Default Runtime:" , info . DefaultRuntime )
2016-09-08 13:11:39 -04:00
}
2016-09-07 14:14:49 -04:00
if info . OSType == "linux" {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Init Binary:" , info . InitBinary )
2016-10-24 18:18:58 -04:00
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 )
}
2017-08-06 17:23:15 -04:00
fmt . Fprint ( dockerCli . Out ( ) , "\n" )
2016-10-24 18:18:58 -04:00
}
2016-09-02 09:20:54 -04:00
if len ( info . SecurityOptions ) != 0 {
2016-11-16 16:30:29 -05:00
kvs , err := types . DecodeSecurityOptions ( info . SecurityOptions )
if err != nil {
return err
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Security Options:" )
2016-11-16 16:30:29 -05:00
for _ , so := range kvs {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " " + so . Name )
2016-11-16 16:30:29 -05:00
for _ , o := range so . Options {
switch o . Key {
case "profile" :
if o . Value != "default" {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Err ( ) , " WARNING: You're not using the default seccomp profile" )
2016-11-16 16:30:29 -05:00
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " Profile:" , o . Value )
2016-09-02 09:20:54 -04:00
}
}
}
}
2016-09-07 14:14:49 -04:00
}
2016-09-08 13:11:39 -04:00
2016-09-07 18:10:00 -04:00
// Isolation only has meaning on a Windows daemon.
if info . OSType == "windows" {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Default Isolation:" , info . Isolation )
2016-09-07 18:10:00 -04:00
}
2017-08-06 17:23:15 -04:00
fprintlnNonEmpty ( dockerCli . Out ( ) , "Kernel Version:" , info . KernelVersion )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Operating System:" , info . OperatingSystem )
fprintlnNonEmpty ( dockerCli . Out ( ) , "OSType:" , info . OSType )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Architecture:" , info . Architecture )
fmt . Fprintln ( dockerCli . Out ( ) , "CPUs:" , info . NCPU )
fmt . Fprintln ( dockerCli . Out ( ) , "Total Memory:" , units . BytesSize ( float64 ( info . MemTotal ) ) )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Name:" , info . Name )
fprintlnNonEmpty ( dockerCli . Out ( ) , "ID:" , info . ID )
fmt . Fprintln ( dockerCli . Out ( ) , "Docker Root Dir:" , info . DockerRootDir )
fmt . Fprintln ( dockerCli . Out ( ) , "Debug Mode (client):" , debug . IsEnabled ( ) )
fmt . Fprintln ( dockerCli . Out ( ) , "Debug Mode (server):" , info . Debug )
2016-09-08 13:11:39 -04:00
if info . Debug {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " File Descriptors:" , info . NFd )
fmt . Fprintln ( dockerCli . Out ( ) , " Goroutines:" , info . NGoroutines )
fmt . Fprintln ( dockerCli . Out ( ) , " System Time:" , info . SystemTime )
fmt . Fprintln ( dockerCli . Out ( ) , " EventsListeners:" , info . NEventsListener )
2016-09-08 13:11:39 -04:00
}
2017-08-06 17:23:15 -04:00
fprintlnNonEmpty ( dockerCli . Out ( ) , "HTTP Proxy:" , info . HTTPProxy )
fprintlnNonEmpty ( dockerCli . Out ( ) , "HTTPS Proxy:" , info . HTTPSProxy )
fprintlnNonEmpty ( dockerCli . Out ( ) , "No Proxy:" , info . NoProxy )
2016-09-08 13:11:39 -04:00
if info . IndexServerAddress != "" {
u := dockerCli . ConfigFile ( ) . AuthConfigs [ info . IndexServerAddress ] . Username
if len ( u ) > 0 {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Username:" , u )
2016-09-08 13:11:39 -04:00
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Registry:" , info . IndexServerAddress )
2016-09-08 13:11:39 -04:00
}
if info . Labels != nil {
fmt . Fprintln ( dockerCli . Out ( ) , "Labels:" )
2017-08-06 17:23:15 -04:00
for _ , lbl := range info . Labels {
fmt . Fprintln ( dockerCli . Out ( ) , " " + lbl )
2016-09-08 13:11:39 -04:00
}
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Experimental:" , info . ExperimentalBuild )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Cluster Store:" , info . ClusterStore )
fprintlnNonEmpty ( dockerCli . Out ( ) , "Cluster Advertise:" , info . ClusterAdvertise )
2016-09-08 13:11:39 -04:00
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 {
2017-06-09 17:42:16 -04:00
if ! registry . Secure {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " " + registry . Name )
2016-09-08 13:11:39 -04:00
}
}
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 {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " " + mirror )
2016-09-08 13:11:39 -04:00
}
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , "Live Restore Enabled:" , info . LiveRestoreEnabled )
2018-08-27 18:33:16 -04:00
if info . ProductLicense != "" {
fmt . Fprintln ( dockerCli . Out ( ) , "Product License:" , info . ProductLicense )
}
2017-08-06 17:23:15 -04:00
fmt . Fprint ( dockerCli . Out ( ) , "\n" )
add d_type warning to docker info, and optimize output
The overlay(2) drivers were moved up in the list of storage drivers,
and are known to have problems if the backing filesystem does not
support d_type.
Commit 2e20e63da2a8a0ffbbb3f2146f87559e17f43046 added a warning,
which is logged in the daemon logs, however, many users do not
check those logs, and may overlook this warning.
This patch adds the same warning to the output of `docker info`
so that the warning is more easily found.
In addition, the output of warnings printed by `docker info` is
optimized, by;
- moving all warnings to the _end_ of the output, instead of
mixing them with the regular output
- wrapping the storage-driver warnings, so that they are more
easily readable
Example output with this patch applied
============================================
devicemapper using loopback devices:
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
overlay2 on xfs without d_type support;
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior.
Reformat the filesystem with ftype=1 to enable d_type support.
Running without d_type support will not be supported in future releases.
WARNING: bridge-nf-call-iptables is disabled
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2017-02-23 07:36:57 -05:00
2018-07-19 13:45:04 -04:00
printWarnings ( dockerCli , info )
2016-09-08 13:11:39 -04:00
return nil
}
2018-07-28 22:44:11 -04:00
// nolint: gocyclo
2017-08-06 17:23:15 -04:00
func printSwarmInfo ( dockerCli command . Cli , info types . Info ) {
if info . Swarm . LocalNodeState == swarm . LocalNodeStateInactive || info . Swarm . LocalNodeState == swarm . LocalNodeStateLocked {
return
}
fmt . Fprintln ( dockerCli . Out ( ) , " NodeID:" , info . Swarm . NodeID )
if info . Swarm . Error != "" {
fmt . Fprintln ( dockerCli . Out ( ) , " Error:" , info . Swarm . Error )
}
fmt . Fprintln ( dockerCli . Out ( ) , " Is Manager:" , info . Swarm . ControlAvailable )
if info . Swarm . Cluster != nil && info . Swarm . ControlAvailable && info . Swarm . Error == "" && info . Swarm . LocalNodeState != swarm . LocalNodeStateError {
fmt . Fprintln ( dockerCli . Out ( ) , " ClusterID:" , info . Swarm . Cluster . ID )
fmt . Fprintln ( dockerCli . Out ( ) , " Managers:" , info . Swarm . Managers )
fmt . Fprintln ( dockerCli . Out ( ) , " Nodes:" , info . Swarm . Nodes )
2018-07-28 22:44:11 -04:00
var strAddrPool strings . Builder
if info . Swarm . Cluster . DefaultAddrPool != nil {
for _ , p := range info . Swarm . Cluster . DefaultAddrPool {
strAddrPool . WriteString ( p + " " )
}
fmt . Fprintln ( dockerCli . Out ( ) , " Default Address Pool:" , strAddrPool . String ( ) )
fmt . Fprintln ( dockerCli . Out ( ) , " SubnetSize:" , info . Swarm . Cluster . SubnetSize )
}
2018-11-26 16:04:39 -05:00
if info . Swarm . Cluster . DataPathPort > 0 {
fmt . Fprintln ( dockerCli . Out ( ) , " Data Path Port:" , info . Swarm . Cluster . DataPathPort )
}
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( dockerCli . Out ( ) , " Orchestration:" )
2018-07-28 22:44:11 -04:00
2017-08-06 17:23:15 -04:00
taskHistoryRetentionLimit := int64 ( 0 )
if info . Swarm . Cluster . Spec . Orchestration . TaskHistoryRetentionLimit != nil {
taskHistoryRetentionLimit = * info . Swarm . Cluster . Spec . Orchestration . TaskHistoryRetentionLimit
}
fmt . Fprintln ( dockerCli . Out ( ) , " Task History Retention Limit:" , taskHistoryRetentionLimit )
fmt . Fprintln ( dockerCli . Out ( ) , " Raft:" )
fmt . Fprintln ( dockerCli . Out ( ) , " Snapshot Interval:" , 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 . Fprintln ( dockerCli . Out ( ) , " Heartbeat Tick:" , info . Swarm . Cluster . Spec . Raft . HeartbeatTick )
fmt . Fprintln ( dockerCli . Out ( ) , " Election Tick:" , info . Swarm . Cluster . Spec . Raft . ElectionTick )
fmt . Fprintln ( dockerCli . Out ( ) , " Dispatcher:" )
fmt . Fprintln ( dockerCli . Out ( ) , " Heartbeat Period:" , units . HumanDuration ( info . Swarm . Cluster . Spec . Dispatcher . HeartbeatPeriod ) )
fmt . Fprintln ( dockerCli . Out ( ) , " CA Configuration:" )
fmt . Fprintln ( dockerCli . Out ( ) , " Expiry Duration:" , units . HumanDuration ( info . Swarm . Cluster . Spec . CAConfig . NodeCertExpiry ) )
fmt . Fprintln ( dockerCli . Out ( ) , " Force Rotate:" , info . Swarm . Cluster . Spec . CAConfig . ForceRotate )
if caCert := strings . TrimSpace ( info . Swarm . Cluster . Spec . CAConfig . SigningCACert ) ; caCert != "" {
fmt . Fprintf ( dockerCli . Out ( ) , " Signing CA Certificate: \n%s\n\n" , caCert )
}
if len ( info . Swarm . Cluster . Spec . CAConfig . ExternalCAs ) > 0 {
fmt . Fprintln ( dockerCli . Out ( ) , " External CAs:" )
for _ , entry := range info . Swarm . Cluster . Spec . CAConfig . ExternalCAs {
fmt . Fprintf ( dockerCli . Out ( ) , " %s: %s\n" , entry . Protocol , entry . URL )
}
}
fmt . Fprintln ( dockerCli . Out ( ) , " Autolock Managers:" , info . Swarm . Cluster . Spec . EncryptionConfig . AutoLockManagers )
fmt . Fprintln ( dockerCli . Out ( ) , " Root Rotation In Progress:" , info . Swarm . Cluster . RootRotationInProgress )
}
fmt . Fprintln ( dockerCli . Out ( ) , " Node Address:" , info . Swarm . NodeAddr )
if len ( info . Swarm . RemoteManagers ) > 0 {
managers := [ ] string { }
for _ , entry := range info . Swarm . RemoteManagers {
managers = append ( managers , entry . Addr )
}
sort . Strings ( managers )
fmt . Fprintln ( dockerCli . Out ( ) , " Manager Addresses:" )
for _ , entry := range managers {
fmt . Fprintf ( dockerCli . Out ( ) , " %s\n" , entry )
}
}
}
2018-07-19 13:45:04 -04:00
func printWarnings ( dockerCli command . Cli , info types . Info ) {
if len ( info . Warnings ) > 0 {
fmt . Fprintln ( dockerCli . Err ( ) , strings . Join ( info . Warnings , "\n" ) )
return
}
// daemon didn't return warnings. Fallback to old behavior
printStorageDriverWarnings ( dockerCli , info )
printWarningsLegacy ( dockerCli , info )
}
// printWarningsLegacy generates warnings based on information returned by the daemon.
// DEPRECATED: warnings are now generated by the daemon, and returned in
// info.Warnings. This function is used to provide backward compatibility with
// daemons that do not provide these warnings. No new warnings should be added
// here.
func printWarningsLegacy ( dockerCli command . Cli , info types . Info ) {
if info . OSType == "windows" {
return
}
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" )
}
}
// printStorageDriverWarnings generates warnings based on storage-driver information
// returned by the daemon.
// DEPRECATED: warnings are now generated by the daemon, and returned in
// info.Warnings. This function is used to provide backward compatibility with
// daemons that do not provide these warnings. No new warnings should be added
// here.
2017-08-24 18:42:11 -04:00
func printStorageDriverWarnings ( dockerCli command . Cli , info types . Info ) {
2018-07-19 13:45:04 -04:00
if info . OSType == "windows" {
return
}
add d_type warning to docker info, and optimize output
The overlay(2) drivers were moved up in the list of storage drivers,
and are known to have problems if the backing filesystem does not
support d_type.
Commit 2e20e63da2a8a0ffbbb3f2146f87559e17f43046 added a warning,
which is logged in the daemon logs, however, many users do not
check those logs, and may overlook this warning.
This patch adds the same warning to the output of `docker info`
so that the warning is more easily found.
In addition, the output of warnings printed by `docker info` is
optimized, by;
- moving all warnings to the _end_ of the output, instead of
mixing them with the regular output
- wrapping the storage-driver warnings, so that they are more
easily readable
Example output with this patch applied
============================================
devicemapper using loopback devices:
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
overlay2 on xfs without d_type support;
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior.
Reformat the filesystem with ftype=1 to enable d_type support.
Running without d_type support will not be supported in future releases.
WARNING: bridge-nf-call-iptables is disabled
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2017-02-23 07:36:57 -05:00
if info . DriverStatus == nil {
return
}
for _ , pair := range info . DriverStatus {
if pair [ 0 ] == "Data loop file" {
2017-05-03 18:14:30 -04:00
fmt . Fprintf ( dockerCli . Err ( ) , "WARNING: %s: usage of loopback devices is " +
"strongly discouraged for production use.\n " +
"Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.\n" , info . Driver )
add d_type warning to docker info, and optimize output
The overlay(2) drivers were moved up in the list of storage drivers,
and are known to have problems if the backing filesystem does not
support d_type.
Commit 2e20e63da2a8a0ffbbb3f2146f87559e17f43046 added a warning,
which is logged in the daemon logs, however, many users do not
check those logs, and may overlook this warning.
This patch adds the same warning to the output of `docker info`
so that the warning is more easily found.
In addition, the output of warnings printed by `docker info` is
optimized, by;
- moving all warnings to the _end_ of the output, instead of
mixing them with the regular output
- wrapping the storage-driver warnings, so that they are more
easily readable
Example output with this patch applied
============================================
devicemapper using loopback devices:
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
overlay2 on xfs without d_type support;
...
Insecure Registries:
127.0.0.0/8
Live Restore Enabled: false
WARNING: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior.
Reformat the filesystem with ftype=1 to enable d_type support.
Running without d_type support will not be supported in future releases.
WARNING: bridge-nf-call-iptables is disabled
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2017-02-23 07:36:57 -05:00
}
if pair [ 0 ] == "Supports d_type" && pair [ 1 ] == "false" {
backingFs := getBackingFs ( info )
msg := fmt . Sprintf ( "WARNING: %s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.\n" , info . Driver , backingFs )
if backingFs == "xfs" {
msg += " Reformat the filesystem with ftype=1 to enable d_type support.\n"
}
msg += " Running without d_type support will not be supported in future releases."
fmt . Fprintln ( dockerCli . Err ( ) , msg )
}
}
}
func getBackingFs ( info types . Info ) string {
if info . DriverStatus == nil {
return ""
}
for _ , pair := range info . DriverStatus {
if pair [ 0 ] == "Backing Filesystem" {
return pair [ 1 ]
}
}
return ""
}
2017-10-11 12:18:27 -04:00
func formatInfo ( dockerCli command . Cli , info types . Info , format string ) error {
2016-09-08 13:11:39 -04:00
tmpl , err := templates . Parse ( format )
if err != nil {
return cli . StatusError { StatusCode : 64 ,
Status : "Template parsing error: " + err . Error ( ) }
}
err = tmpl . Execute ( dockerCli . Out ( ) , info )
dockerCli . Out ( ) . Write ( [ ] byte { '\n' } )
return err
}
2017-05-10 16:38:06 -04:00
2017-08-06 17:23:15 -04:00
func fprintlnNonEmpty ( w io . Writer , label , value string ) {
2017-05-10 16:38:06 -04:00
if value != "" {
2017-08-06 17:23:15 -04:00
fmt . Fprintln ( w , label , value )
2017-05-10 16:38:06 -04:00
}
}