github.com/uriddle/docker@v0.0.0-20210926094723-4072e6aeb013/daemon/inspect.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/docker/docker/container"
     8  	"github.com/docker/docker/daemon/exec"
     9  	"github.com/docker/docker/daemon/network"
    10  	"github.com/docker/docker/pkg/version"
    11  	"github.com/docker/engine-api/types"
    12  	networktypes "github.com/docker/engine-api/types/network"
    13  	"github.com/docker/engine-api/types/versions/v1p20"
    14  )
    15  
    16  // ContainerInspect returns low-level information about a
    17  // container. Returns an error if the container cannot be found, or if
    18  // there is an error getting the data.
    19  func (daemon *Daemon) ContainerInspect(name string, size bool, version version.Version) (interface{}, error) {
    20  	switch {
    21  	case version.LessThan("1.20"):
    22  		return daemon.containerInspectPre120(name)
    23  	case version.Equal("1.20"):
    24  		return daemon.containerInspect120(name)
    25  	}
    26  	return daemon.containerInspectCurrent(name, size)
    27  }
    28  
    29  func (daemon *Daemon) containerInspectCurrent(name string, size bool) (*types.ContainerJSON, error) {
    30  	container, err := daemon.GetContainer(name)
    31  	if err != nil {
    32  		return nil, err
    33  	}
    34  
    35  	container.Lock()
    36  	defer container.Unlock()
    37  
    38  	base, err := daemon.getInspectData(container, size)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  
    43  	mountPoints := addMountPoints(container)
    44  	networkSettings := &types.NetworkSettings{
    45  		NetworkSettingsBase: types.NetworkSettingsBase{
    46  			Bridge:                 container.NetworkSettings.Bridge,
    47  			SandboxID:              container.NetworkSettings.SandboxID,
    48  			HairpinMode:            container.NetworkSettings.HairpinMode,
    49  			LinkLocalIPv6Address:   container.NetworkSettings.LinkLocalIPv6Address,
    50  			LinkLocalIPv6PrefixLen: container.NetworkSettings.LinkLocalIPv6PrefixLen,
    51  			Ports:                  container.NetworkSettings.Ports,
    52  			SandboxKey:             container.NetworkSettings.SandboxKey,
    53  			SecondaryIPAddresses:   container.NetworkSettings.SecondaryIPAddresses,
    54  			SecondaryIPv6Addresses: container.NetworkSettings.SecondaryIPv6Addresses,
    55  		},
    56  		DefaultNetworkSettings: daemon.getDefaultNetworkSettings(container.NetworkSettings.Networks),
    57  		Networks:               container.NetworkSettings.Networks,
    58  	}
    59  
    60  	return &types.ContainerJSON{
    61  		ContainerJSONBase: base,
    62  		Mounts:            mountPoints,
    63  		Config:            container.Config,
    64  		NetworkSettings:   networkSettings,
    65  	}, nil
    66  }
    67  
    68  // containerInspect120 serializes the master version of a container into a json type.
    69  func (daemon *Daemon) containerInspect120(name string) (*v1p20.ContainerJSON, error) {
    70  	container, err := daemon.GetContainer(name)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	container.Lock()
    76  	defer container.Unlock()
    77  
    78  	base, err := daemon.getInspectData(container, false)
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  
    83  	mountPoints := addMountPoints(container)
    84  	config := &v1p20.ContainerConfig{
    85  		Config:          container.Config,
    86  		MacAddress:      container.Config.MacAddress,
    87  		NetworkDisabled: container.Config.NetworkDisabled,
    88  		ExposedPorts:    container.Config.ExposedPorts,
    89  		VolumeDriver:    container.HostConfig.VolumeDriver,
    90  	}
    91  	networkSettings := daemon.getBackwardsCompatibleNetworkSettings(container.NetworkSettings)
    92  
    93  	return &v1p20.ContainerJSON{
    94  		ContainerJSONBase: base,
    95  		Mounts:            mountPoints,
    96  		Config:            config,
    97  		NetworkSettings:   networkSettings,
    98  	}, nil
    99  }
   100  
   101  func (daemon *Daemon) getInspectData(container *container.Container, size bool) (*types.ContainerJSONBase, error) {
   102  	// make a copy to play with
   103  	hostConfig := *container.HostConfig
   104  
   105  	children := daemon.children(container)
   106  	hostConfig.Links = nil // do not expose the internal structure
   107  	for linkAlias, child := range children {
   108  		hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
   109  	}
   110  
   111  	// we need this trick to preserve empty log driver, so
   112  	// container will use daemon defaults even if daemon change them
   113  	if hostConfig.LogConfig.Type == "" {
   114  		hostConfig.LogConfig.Type = daemon.defaultLogConfig.Type
   115  	}
   116  
   117  	if len(hostConfig.LogConfig.Config) == 0 {
   118  		hostConfig.LogConfig.Config = daemon.defaultLogConfig.Config
   119  	}
   120  
   121  	containerState := &types.ContainerState{
   122  		Status:     container.State.StateString(),
   123  		Running:    container.State.Running,
   124  		Paused:     container.State.Paused,
   125  		Restarting: container.State.Restarting,
   126  		OOMKilled:  container.State.OOMKilled,
   127  		Dead:       container.State.Dead,
   128  		Pid:        container.State.Pid,
   129  		ExitCode:   container.State.ExitCode,
   130  		Error:      container.State.Error,
   131  		StartedAt:  container.State.StartedAt.Format(time.RFC3339Nano),
   132  		FinishedAt: container.State.FinishedAt.Format(time.RFC3339Nano),
   133  	}
   134  
   135  	contJSONBase := &types.ContainerJSONBase{
   136  		ID:           container.ID,
   137  		Created:      container.Created.Format(time.RFC3339Nano),
   138  		Path:         container.Path,
   139  		Args:         container.Args,
   140  		State:        containerState,
   141  		Image:        container.ImageID.String(),
   142  		LogPath:      container.LogPath,
   143  		Name:         container.Name,
   144  		RestartCount: container.RestartCount,
   145  		Driver:       container.Driver,
   146  		MountLabel:   container.MountLabel,
   147  		ProcessLabel: container.ProcessLabel,
   148  		ExecIDs:      container.GetExecIDs(),
   149  		HostConfig:   &hostConfig,
   150  	}
   151  
   152  	var (
   153  		sizeRw     int64
   154  		sizeRootFs int64
   155  	)
   156  	if size {
   157  		sizeRw, sizeRootFs = daemon.getSize(container)
   158  		contJSONBase.SizeRw = &sizeRw
   159  		contJSONBase.SizeRootFs = &sizeRootFs
   160  	}
   161  
   162  	// Now set any platform-specific fields
   163  	contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
   164  
   165  	contJSONBase.GraphDriver.Name = container.Driver
   166  
   167  	graphDriverData, err := container.RWLayer.Metadata()
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	contJSONBase.GraphDriver.Data = graphDriverData
   172  
   173  	return contJSONBase, nil
   174  }
   175  
   176  // ContainerExecInspect returns low-level information about the exec
   177  // command. An error is returned if the exec cannot be found.
   178  func (daemon *Daemon) ContainerExecInspect(id string) (*exec.Config, error) {
   179  	eConfig, err := daemon.getExecConfig(id)
   180  	if err != nil {
   181  		return nil, err
   182  	}
   183  	return eConfig, nil
   184  }
   185  
   186  // VolumeInspect looks up a volume by name. An error is returned if
   187  // the volume cannot be found.
   188  func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) {
   189  	v, err := daemon.volumes.Get(name)
   190  	if err != nil {
   191  		return nil, err
   192  	}
   193  	return volumeToAPIType(v), nil
   194  }
   195  
   196  func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings {
   197  	result := &v1p20.NetworkSettings{
   198  		NetworkSettingsBase: types.NetworkSettingsBase{
   199  			Bridge:                 settings.Bridge,
   200  			SandboxID:              settings.SandboxID,
   201  			HairpinMode:            settings.HairpinMode,
   202  			LinkLocalIPv6Address:   settings.LinkLocalIPv6Address,
   203  			LinkLocalIPv6PrefixLen: settings.LinkLocalIPv6PrefixLen,
   204  			Ports:                  settings.Ports,
   205  			SandboxKey:             settings.SandboxKey,
   206  			SecondaryIPAddresses:   settings.SecondaryIPAddresses,
   207  			SecondaryIPv6Addresses: settings.SecondaryIPv6Addresses,
   208  		},
   209  		DefaultNetworkSettings: daemon.getDefaultNetworkSettings(settings.Networks),
   210  	}
   211  
   212  	return result
   213  }
   214  
   215  // getDefaultNetworkSettings creates the deprecated structure that holds the information
   216  // about the bridge network for a container.
   217  func (daemon *Daemon) getDefaultNetworkSettings(networks map[string]*networktypes.EndpointSettings) types.DefaultNetworkSettings {
   218  	var settings types.DefaultNetworkSettings
   219  
   220  	if defaultNetwork, ok := networks["bridge"]; ok {
   221  		settings.EndpointID = defaultNetwork.EndpointID
   222  		settings.Gateway = defaultNetwork.Gateway
   223  		settings.GlobalIPv6Address = defaultNetwork.GlobalIPv6Address
   224  		settings.GlobalIPv6PrefixLen = defaultNetwork.GlobalIPv6PrefixLen
   225  		settings.IPAddress = defaultNetwork.IPAddress
   226  		settings.IPPrefixLen = defaultNetwork.IPPrefixLen
   227  		settings.IPv6Gateway = defaultNetwork.IPv6Gateway
   228  		settings.MacAddress = defaultNetwork.MacAddress
   229  	}
   230  	return settings
   231  }