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 }