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