github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/daemon/inspect.go (about)

     1  package daemon
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/docker/docker/api/types"
     8  	"github.com/docker/docker/api/types/backend"
     9  	networktypes "github.com/docker/docker/api/types/network"
    10  	"github.com/docker/docker/api/types/versions"
    11  	"github.com/docker/docker/api/types/versions/v1p20"
    12  	"github.com/docker/docker/container"
    13  	"github.com/docker/docker/daemon/network"
    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 string) (interface{}, error) {
    20  	switch {
    21  	case versions.LessThan(version, "1.20"):
    22  		return daemon.containerInspectPre120(name)
    23  	case versions.Equal(version, "1.20"):
    24  		return daemon.containerInspect120(name)
    25  	}
    26  	return daemon.ContainerInspectCurrent(name, size)
    27  }
    28  
    29  // ContainerInspectCurrent returns low-level information about a
    30  // container in a most recent api version.
    31  func (daemon *Daemon) ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error) {
    32  	container, err := daemon.GetContainer(name)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	container.Lock()
    38  	defer container.Unlock()
    39  
    40  	base, err := daemon.getInspectData(container, size)
    41  	if err != nil {
    42  		return nil, err
    43  	}
    44  
    45  	apiNetworks := make(map[string]*networktypes.EndpointSettings)
    46  	for name, epConf := range container.NetworkSettings.Networks {
    47  		if epConf.EndpointSettings != nil {
    48  			apiNetworks[name] = epConf.EndpointSettings
    49  		}
    50  	}
    51  
    52  	mountPoints := addMountPoints(container)
    53  	networkSettings := &types.NetworkSettings{
    54  		NetworkSettingsBase: types.NetworkSettingsBase{
    55  			Bridge:                 container.NetworkSettings.Bridge,
    56  			SandboxID:              container.NetworkSettings.SandboxID,
    57  			HairpinMode:            container.NetworkSettings.HairpinMode,
    58  			LinkLocalIPv6Address:   container.NetworkSettings.LinkLocalIPv6Address,
    59  			LinkLocalIPv6PrefixLen: container.NetworkSettings.LinkLocalIPv6PrefixLen,
    60  			Ports:                  container.NetworkSettings.Ports,
    61  			SandboxKey:             container.NetworkSettings.SandboxKey,
    62  			SecondaryIPAddresses:   container.NetworkSettings.SecondaryIPAddresses,
    63  			SecondaryIPv6Addresses: container.NetworkSettings.SecondaryIPv6Addresses,
    64  		},
    65  		DefaultNetworkSettings: daemon.getDefaultNetworkSettings(container.NetworkSettings.Networks),
    66  		Networks:               apiNetworks,
    67  	}
    68  
    69  	return &types.ContainerJSON{
    70  		ContainerJSONBase: base,
    71  		Mounts:            mountPoints,
    72  		Config:            container.Config,
    73  		NetworkSettings:   networkSettings,
    74  	}, nil
    75  }
    76  
    77  // containerInspect120 serializes the master version of a container into a json type.
    78  func (daemon *Daemon) containerInspect120(name string) (*v1p20.ContainerJSON, error) {
    79  	container, err := daemon.GetContainer(name)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  
    84  	container.Lock()
    85  	defer container.Unlock()
    86  
    87  	base, err := daemon.getInspectData(container, false)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	mountPoints := addMountPoints(container)
    93  	config := &v1p20.ContainerConfig{
    94  		Config:          container.Config,
    95  		MacAddress:      container.Config.MacAddress,
    96  		NetworkDisabled: container.Config.NetworkDisabled,
    97  		ExposedPorts:    container.Config.ExposedPorts,
    98  		VolumeDriver:    container.HostConfig.VolumeDriver,
    99  	}
   100  	networkSettings := daemon.getBackwardsCompatibleNetworkSettings(container.NetworkSettings)
   101  
   102  	return &v1p20.ContainerJSON{
   103  		ContainerJSONBase: base,
   104  		Mounts:            mountPoints,
   105  		Config:            config,
   106  		NetworkSettings:   networkSettings,
   107  	}, nil
   108  }
   109  
   110  func (daemon *Daemon) getInspectData(container *container.Container, size bool) (*types.ContainerJSONBase, error) {
   111      fmt.Println("daemon/inspect.go  getInspectData()")
   112  	// make a copy to play with
   113  	hostConfig := *container.HostConfig
   114  
   115  	children := daemon.children(container)
   116  	hostConfig.Links = nil // do not expose the internal structure
   117  	for linkAlias, child := range children {
   118  		hostConfig.Links = append(hostConfig.Links, fmt.Sprintf("%s:%s", child.Name, linkAlias))
   119  	}
   120  
   121  	// We merge the Ulimits from hostConfig with daemon default
   122  	daemon.mergeUlimits(&hostConfig)
   123  
   124  	var containerHealth *types.Health
   125  	if container.State.Health != nil {
   126  		containerHealth = &types.Health{
   127  			Status:        container.State.Health.Status,
   128  			FailingStreak: container.State.Health.FailingStreak,
   129  			Log:           append([]*types.HealthcheckResult{}, container.State.Health.Log...),
   130  		}
   131  	}
   132  
   133  	containerState := &types.ContainerState{
   134  		Status:     container.State.StateString(),
   135  		Running:    container.State.Running,
   136  		Paused:     container.State.Paused,
   137  		Restarting: container.State.Restarting,
   138  		OOMKilled:  container.State.OOMKilled,
   139  		Dead:       container.State.Dead,
   140  		Pid:        container.State.Pid,
   141  		ExitCode:   container.State.ExitCode(),
   142  		Error:      container.State.Error(),
   143  		StartedAt:  container.State.StartedAt.Format(time.RFC3339Nano),
   144  		FinishedAt: container.State.FinishedAt.Format(time.RFC3339Nano),
   145  		Health:     containerHealth,
   146  	}
   147  
   148  	contJSONBase := &types.ContainerJSONBase{
   149  		ID:           container.ID,
   150  		Created:      container.Created.Format(time.RFC3339Nano),
   151  		Path:         container.Path,
   152  		Args:         container.Args,
   153  		State:        containerState,
   154  		Image:        container.ImageID.String(),
   155  		LogPath:      container.LogPath,
   156  		Name:         container.Name,
   157  		RestartCount: container.RestartCount,
   158  		Driver:       container.Driver,
   159  		MountLabel:   container.MountLabel,
   160  		ProcessLabel: container.ProcessLabel,
   161  		ExecIDs:      container.GetExecIDs(),
   162  		HostConfig:   &hostConfig,
   163  	}
   164  
   165  	var (
   166  		sizeRw     int64
   167  		sizeRootFs int64
   168  	)
   169  	if size {
   170  		sizeRw, sizeRootFs = daemon.getSize(container)
   171  		contJSONBase.SizeRw = &sizeRw
   172  		contJSONBase.SizeRootFs = &sizeRootFs
   173  	}
   174  
   175  	// Now set any platform-specific fields
   176  	contJSONBase = setPlatformSpecificContainerFields(container, contJSONBase)
   177  
   178  	contJSONBase.GraphDriver.Name = container.Driver
   179  
   180  	graphDriverData, err := container.RWLayer.Metadata()
   181  	// If container is marked as Dead, the container's graphdriver metadata
   182  	// could have been removed, it will cause error if we try to get the metadata,
   183  	// we can ignore the error if the container is dead.
   184  	if err != nil && !container.Dead {
   185  		return nil, err
   186  	}
   187  	contJSONBase.GraphDriver.Data = graphDriverData
   188  
   189  	return contJSONBase, nil
   190  }
   191  
   192  // ContainerExecInspect returns low-level information about the exec
   193  // command. An error is returned if the exec cannot be found.
   194  func (daemon *Daemon) ContainerExecInspect(id string) (*backend.ExecInspect, error) {
   195  	e, err := daemon.getExecConfig(id)
   196  	if err != nil {
   197  		return nil, err
   198  	}
   199  
   200  	pc := inspectExecProcessConfig(e)
   201  
   202  	return &backend.ExecInspect{
   203  		ID:            e.ID,
   204  		Running:       e.Running,
   205  		ExitCode:      e.ExitCode,
   206  		ProcessConfig: pc,
   207  		OpenStdin:     e.OpenStdin,
   208  		OpenStdout:    e.OpenStdout,
   209  		OpenStderr:    e.OpenStderr,
   210  		CanRemove:     e.CanRemove,
   211  		ContainerID:   e.ContainerID,
   212  		DetachKeys:    e.DetachKeys,
   213  		Pid:           e.Pid,
   214  	}, nil
   215  }
   216  
   217  // VolumeInspect looks up a volume by name. An error is returned if
   218  // the volume cannot be found.
   219  func (daemon *Daemon) VolumeInspect(name string) (*types.Volume, error) {
   220  	v, err := daemon.volumes.Get(name)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	apiV := volumeToAPIType(v)
   225  	apiV.Mountpoint = v.Path()
   226  	apiV.Status = v.Status()
   227  	return apiV, nil
   228  }
   229  
   230  func (daemon *Daemon) getBackwardsCompatibleNetworkSettings(settings *network.Settings) *v1p20.NetworkSettings {
   231  	result := &v1p20.NetworkSettings{
   232  		NetworkSettingsBase: types.NetworkSettingsBase{
   233  			Bridge:                 settings.Bridge,
   234  			SandboxID:              settings.SandboxID,
   235  			HairpinMode:            settings.HairpinMode,
   236  			LinkLocalIPv6Address:   settings.LinkLocalIPv6Address,
   237  			LinkLocalIPv6PrefixLen: settings.LinkLocalIPv6PrefixLen,
   238  			Ports:                  settings.Ports,
   239  			SandboxKey:             settings.SandboxKey,
   240  			SecondaryIPAddresses:   settings.SecondaryIPAddresses,
   241  			SecondaryIPv6Addresses: settings.SecondaryIPv6Addresses,
   242  		},
   243  		DefaultNetworkSettings: daemon.getDefaultNetworkSettings(settings.Networks),
   244  	}
   245  
   246  	return result
   247  }
   248  
   249  // getDefaultNetworkSettings creates the deprecated structure that holds the information
   250  // about the bridge network for a container.
   251  func (daemon *Daemon) getDefaultNetworkSettings(networks map[string]*network.EndpointSettings) types.DefaultNetworkSettings {
   252  	var settings types.DefaultNetworkSettings
   253  
   254  	if defaultNetwork, ok := networks["bridge"]; ok && defaultNetwork.EndpointSettings != nil {
   255  		settings.EndpointID = defaultNetwork.EndpointID
   256  		settings.Gateway = defaultNetwork.Gateway
   257  		settings.GlobalIPv6Address = defaultNetwork.GlobalIPv6Address
   258  		settings.GlobalIPv6PrefixLen = defaultNetwork.GlobalIPv6PrefixLen
   259  		settings.IPAddress = defaultNetwork.IPAddress
   260  		settings.IPPrefixLen = defaultNetwork.IPPrefixLen
   261  		settings.IPv6Gateway = defaultNetwork.IPv6Gateway
   262  		settings.MacAddress = defaultNetwork.MacAddress
   263  	}
   264  	return settings
   265  }