github.com/kobeld/docker@v1.12.0-rc1/daemon/inspect.go (about)

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