I was trying to find out why `docker info` was sometimes slow so
plumbing a context through to propagate trace data through.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -27,8 +27,8 @@ type DiskUsageOptions struct {
|
| 27 | 27 |
// Backend is the methods that need to be implemented to provide |
| 28 | 28 |
// system specific functionality. |
| 29 | 29 |
type Backend interface {
|
| 30 |
- SystemInfo() *system.Info |
|
| 31 |
- SystemVersion() types.Version |
|
| 30 |
+ SystemInfo(context.Context) (*system.Info, error) |
|
| 31 |
+ SystemVersion(context.Context) (types.Version, error) |
|
| 32 | 32 |
SystemDiskUsage(ctx context.Context, opts DiskUsageOptions) (*types.DiskUsage, error) |
| 33 | 33 |
SubscribeToEvents(since, until time.Time, ef filters.Args) ([]events.Message, chan interface{})
|
| 34 | 34 |
UnsubscribeFromEvents(chan interface{})
|
| ... | ... |
@@ -38,7 +38,7 @@ type Backend interface {
|
| 38 | 38 |
// ClusterBackend is all the methods that need to be implemented |
| 39 | 39 |
// to provide cluster system specific functionality. |
| 40 | 40 |
type ClusterBackend interface {
|
| 41 |
- Info() swarm.Info |
|
| 41 |
+ Info(context.Context) swarm.Info |
|
| 42 | 42 |
} |
| 43 | 43 |
|
| 44 | 44 |
// StatusProvider provides methods to get the swarm status of the current node. |
| ... | ... |
@@ -60,10 +60,13 @@ func (s *systemRouter) swarmStatus() string {
|
| 60 | 60 |
func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 61 | 61 |
version := httputils.VersionFromContext(ctx) |
| 62 | 62 |
info, _, _ := s.collectSystemInfo.Do(ctx, version, func(ctx context.Context) (*system.Info, error) {
|
| 63 |
- info := s.backend.SystemInfo() |
|
| 63 |
+ info, err := s.backend.SystemInfo(ctx) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return nil, err |
|
| 66 |
+ } |
|
| 64 | 67 |
|
| 65 | 68 |
if s.cluster != nil {
|
| 66 |
- info.Swarm = s.cluster.Info() |
|
| 69 |
+ info.Swarm = s.cluster.Info(ctx) |
|
| 67 | 70 |
info.Warnings = append(info.Warnings, info.Swarm.Warnings...) |
| 68 | 71 |
} |
| 69 | 72 |
|
| ... | ... |
@@ -97,7 +100,10 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht |
| 97 | 97 |
} |
| 98 | 98 |
|
| 99 | 99 |
func (s *systemRouter) getVersion(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
|
| 100 |
- info := s.backend.SystemVersion() |
|
| 100 |
+ info, err := s.backend.SystemVersion(ctx) |
|
| 101 |
+ if err != nil {
|
|
| 102 |
+ return err |
|
| 103 |
+ } |
|
| 101 | 104 |
|
| 102 | 105 |
return httputils.WriteJSON(w, http.StatusOK, info) |
| 103 | 106 |
} |
| ... | ... |
@@ -249,8 +249,8 @@ func (c *Cluster) newNodeRunner(conf nodeStartConfig) (*nodeRunner, error) {
|
| 249 | 249 |
return nr, nil |
| 250 | 250 |
} |
| 251 | 251 |
|
| 252 |
-func (c *Cluster) getRequestContext() (context.Context, func()) { // TODO: not needed when requests don't block on qourum lost
|
|
| 253 |
- return context.WithTimeout(context.Background(), swarmRequestTimeout) |
|
| 252 |
+func (c *Cluster) getRequestContext(ctx context.Context) (context.Context, func()) { // TODO: not needed when requests don't block on qourum lost
|
|
| 253 |
+ return context.WithTimeout(ctx, swarmRequestTimeout) |
|
| 254 | 254 |
} |
| 255 | 255 |
|
| 256 | 256 |
// IsManager returns true if Cluster is participating as a manager. |
| ... | ... |
@@ -443,7 +443,8 @@ func (c *Cluster) lockedManagerAction(fn func(ctx context.Context, state nodeSta |
| 443 | 443 |
return c.errNoManager(state) |
| 444 | 444 |
} |
| 445 | 445 |
|
| 446 |
- ctx, cancel := c.getRequestContext() |
|
| 446 |
+ ctx := context.TODO() |
|
| 447 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 447 | 448 |
defer cancel() |
| 448 | 449 |
|
| 449 | 450 |
return fn(ctx, state) |
| ... | ... |
@@ -41,7 +41,9 @@ func (c *Cluster) GetConfigs(options apitypes.ConfigListOptions) ([]types.Config |
| 41 | 41 |
if err != nil {
|
| 42 | 42 |
return nil, err |
| 43 | 43 |
} |
| 44 |
- ctx, cancel := c.getRequestContext() |
|
| 44 |
+ |
|
| 45 |
+ ctx := context.TODO() |
|
| 46 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 45 | 47 |
defer cancel() |
| 46 | 48 |
|
| 47 | 49 |
r, err := state.controlClient.ListConfigs(ctx, |
| ... | ... |
@@ -53,7 +53,7 @@ type Backend interface {
|
| 53 | 53 |
SetContainerDependencyStore(name string, store exec.DependencyGetter) error |
| 54 | 54 |
SetContainerSecretReferences(name string, refs []*swarm.SecretReference) error |
| 55 | 55 |
SetContainerConfigReferences(name string, refs []*swarm.ConfigReference) error |
| 56 |
- SystemInfo() *system.Info |
|
| 56 |
+ SystemInfo(context.Context) (*system.Info, error) |
|
| 57 | 57 |
Containers(ctx context.Context, config *container.ListOptions) ([]*types.Container, error) |
| 58 | 58 |
SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error |
| 59 | 59 |
DaemonJoinsCluster(provider cluster.Provider) |
| ... | ... |
@@ -58,7 +58,10 @@ func NewExecutor(b executorpkg.Backend, p plugin.Backend, i executorpkg.ImageBac |
| 58 | 58 |
|
| 59 | 59 |
// Describe returns the underlying node description from the docker client. |
| 60 | 60 |
func (e *executor) Describe(ctx context.Context) (*api.NodeDescription, error) {
|
| 61 |
- info := e.backend.SystemInfo() |
|
| 61 |
+ info, err := e.backend.SystemInfo(ctx) |
|
| 62 |
+ if err != nil {
|
|
| 63 |
+ return nil, err |
|
| 64 |
+ } |
|
| 62 | 65 |
|
| 63 | 66 |
plugins := map[api.PluginDescription]struct{}{}
|
| 64 | 67 |
addPlugins := func(typ string, names []string) {
|
| ... | ... |
@@ -12,6 +12,7 @@ import ( |
| 12 | 12 |
"github.com/docker/docker/daemon/cluster/convert" |
| 13 | 13 |
internalnetwork "github.com/docker/docker/daemon/network" |
| 14 | 14 |
"github.com/docker/docker/errdefs" |
| 15 |
+ "github.com/docker/docker/internal/compatcontext" |
|
| 15 | 16 |
"github.com/docker/docker/runconfig" |
| 16 | 17 |
swarmapi "github.com/moby/swarmkit/v2/api" |
| 17 | 18 |
"github.com/pkg/errors" |
| ... | ... |
@@ -68,7 +69,8 @@ func (c *Cluster) getNetworks(filters *swarmapi.ListNetworksRequest_Filters) ([] |
| 68 | 68 |
return nil, c.errNoManager(state) |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
- ctx, cancel := c.getRequestContext() |
|
| 71 |
+ ctx := context.TODO() |
|
| 72 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 72 | 73 |
defer cancel() |
| 73 | 74 |
|
| 74 | 75 |
r, err := state.controlClient.ListNetworks(ctx, &swarmapi.ListNetworksRequest{Filters: filters})
|
| ... | ... |
@@ -203,7 +205,8 @@ func (c *Cluster) AttachNetwork(target string, containerID string, addresses []s |
| 203 | 203 |
} |
| 204 | 204 |
c.mu.Unlock() |
| 205 | 205 |
|
| 206 |
- ctx, cancel := c.getRequestContext() |
|
| 206 |
+ ctx := context.TODO() |
|
| 207 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 207 | 208 |
defer cancel() |
| 208 | 209 |
|
| 209 | 210 |
taskID, err := agent.ResourceAllocator().AttachNetwork(ctx, containerID, target, addresses) |
| ... | ... |
@@ -222,7 +225,8 @@ func (c *Cluster) AttachNetwork(target string, containerID string, addresses []s |
| 222 | 222 |
log.G(ctx).Debugf("Successfully attached to network %s with task id %s", target, taskID)
|
| 223 | 223 |
|
| 224 | 224 |
release := func() {
|
| 225 |
- ctx, cancel := c.getRequestContext() |
|
| 225 |
+ ctx := compatcontext.WithoutCancel(ctx) |
|
| 226 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 226 | 227 |
defer cancel() |
| 227 | 228 |
if err := agent.ResourceAllocator().DetachNetwork(ctx, taskID); err != nil {
|
| 228 | 229 |
log.G(ctx).Errorf("Failed remove network attachment %s to network %s on allocation failure: %v",
|
| ... | ... |
@@ -26,7 +26,8 @@ func (c *Cluster) GetNodes(options apitypes.NodeListOptions) ([]types.Node, erro |
| 26 | 26 |
return nil, err |
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 |
- ctx, cancel := c.getRequestContext() |
|
| 29 |
+ ctx := context.TODO() |
|
| 30 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 30 | 31 |
defer cancel() |
| 31 | 32 |
|
| 32 | 33 |
r, err := state.controlClient.ListNodes( |
| ... | ... |
@@ -72,7 +73,8 @@ func (c *Cluster) UpdateNode(input string, version uint64, spec types.NodeSpec) |
| 72 | 72 |
return errdefs.InvalidParameter(err) |
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 |
- ctx, cancel := c.getRequestContext() |
|
| 75 |
+ ctx := context.TODO() |
|
| 76 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 76 | 77 |
defer cancel() |
| 77 | 78 |
|
| 78 | 79 |
currentNode, err := getNode(ctx, state.controlClient, input) |
| ... | ... |
@@ -41,7 +41,9 @@ func (c *Cluster) GetSecrets(options apitypes.SecretListOptions) ([]types.Secret |
| 41 | 41 |
if err != nil {
|
| 42 | 42 |
return nil, err |
| 43 | 43 |
} |
| 44 |
- ctx, cancel := c.getRequestContext() |
|
| 44 |
+ |
|
| 45 |
+ ctx := context.TODO() |
|
| 46 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 45 | 47 |
defer cancel() |
| 46 | 48 |
|
| 47 | 49 |
r, err := state.controlClient.ListSecrets(ctx, |
| ... | ... |
@@ -21,6 +21,7 @@ import ( |
| 21 | 21 |
timetypes "github.com/docker/docker/api/types/time" |
| 22 | 22 |
"github.com/docker/docker/daemon/cluster/convert" |
| 23 | 23 |
"github.com/docker/docker/errdefs" |
| 24 |
+ "github.com/docker/docker/internal/compatcontext" |
|
| 24 | 25 |
runconfigopts "github.com/docker/docker/runconfig/opts" |
| 25 | 26 |
gogotypes "github.com/gogo/protobuf/types" |
| 26 | 27 |
swarmapi "github.com/moby/swarmkit/v2/api" |
| ... | ... |
@@ -65,7 +66,8 @@ func (c *Cluster) GetServices(options types.ServiceListOptions) ([]swarm.Service |
| 65 | 65 |
Runtimes: options.Filters.Get("runtime"),
|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 |
- ctx, cancel := c.getRequestContext() |
|
| 68 |
+ ctx := context.TODO() |
|
| 69 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 69 | 70 |
defer cancel() |
| 70 | 71 |
|
| 71 | 72 |
r, err := state.controlClient.ListServices( |
| ... | ... |
@@ -263,7 +265,8 @@ func (c *Cluster) CreateService(s swarm.ServiceSpec, encodedAuth string, queryRe |
| 263 | 263 |
// "ctx" could make it impossible to create a service |
| 264 | 264 |
// if the registry is slow or unresponsive. |
| 265 | 265 |
var cancel func() |
| 266 |
- ctx, cancel = c.getRequestContext() |
|
| 266 |
+ ctx = compatcontext.WithoutCancel(ctx) |
|
| 267 |
+ ctx, cancel = c.getRequestContext(ctx) |
|
| 267 | 268 |
defer cancel() |
| 268 | 269 |
} |
| 269 | 270 |
|
| ... | ... |
@@ -378,7 +381,8 @@ func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec swa |
| 378 | 378 |
// "ctx" could make it impossible to update a service |
| 379 | 379 |
// if the registry is slow or unresponsive. |
| 380 | 380 |
var cancel func() |
| 381 |
- ctx, cancel = c.getRequestContext() |
|
| 381 |
+ ctx = compatcontext.WithoutCancel(ctx) |
|
| 382 |
+ ctx, cancel = c.getRequestContext(ctx) |
|
| 382 | 383 |
defer cancel() |
| 383 | 384 |
} |
| 384 | 385 |
} |
| ... | ... |
@@ -429,7 +429,7 @@ func (c *Cluster) Leave(ctx context.Context, force bool) error {
|
| 429 | 429 |
} |
| 430 | 430 |
|
| 431 | 431 |
// Info returns information about the current cluster state. |
| 432 |
-func (c *Cluster) Info() types.Info {
|
|
| 432 |
+func (c *Cluster) Info(ctx context.Context) types.Info {
|
|
| 433 | 433 |
info := types.Info{
|
| 434 | 434 |
NodeAddr: c.GetAdvertiseAddress(), |
| 435 | 435 |
} |
| ... | ... |
@@ -442,7 +442,7 @@ func (c *Cluster) Info() types.Info {
|
| 442 | 442 |
info.Error = state.err.Error() |
| 443 | 443 |
} |
| 444 | 444 |
|
| 445 |
- ctx, cancel := c.getRequestContext() |
|
| 445 |
+ ctx, cancel := c.getRequestContext(ctx) |
|
| 446 | 446 |
defer cancel() |
| 447 | 447 |
|
| 448 | 448 |
if state.IsActiveManager() {
|
| ... | ... |
@@ -76,8 +76,8 @@ func (i *ImageService) DistributionServices() images.DistributionServices {
|
| 76 | 76 |
|
| 77 | 77 |
// CountImages returns the number of images stored by ImageService |
| 78 | 78 |
// called from info.go |
| 79 |
-func (i *ImageService) CountImages() int {
|
|
| 80 |
- imgs, err := i.client.ListImages(context.TODO()) |
|
| 79 |
+func (i *ImageService) CountImages(ctx context.Context) int {
|
|
| 80 |
+ imgs, err := i.client.ListImages(ctx) |
|
| 81 | 81 |
if err != nil {
|
| 82 | 82 |
return 0 |
| 83 | 83 |
} |
| ... | ... |
@@ -1175,7 +1175,10 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S |
| 1175 | 1175 |
} |
| 1176 | 1176 |
close(d.startupDone) |
| 1177 | 1177 |
|
| 1178 |
- info := d.SystemInfo() |
|
| 1178 |
+ info, err := d.SystemInfo(ctx) |
|
| 1179 |
+ if err != nil {
|
|
| 1180 |
+ return nil, err |
|
| 1181 |
+ } |
|
| 1179 | 1182 |
for _, w := range info.Warnings {
|
| 1180 | 1183 |
log.G(ctx).Warn(w) |
| 1181 | 1184 |
} |
| ... | ... |
@@ -1349,7 +1352,7 @@ func (daemon *Daemon) Subnets() ([]net.IPNet, []net.IPNet) {
|
| 1349 | 1349 |
var v4Subnets []net.IPNet |
| 1350 | 1350 |
var v6Subnets []net.IPNet |
| 1351 | 1351 |
|
| 1352 |
- for _, managedNetwork := range daemon.netController.Networks() {
|
|
| 1352 |
+ for _, managedNetwork := range daemon.netController.Networks(context.TODO()) {
|
|
| 1353 | 1353 |
v4infos, v6infos := managedNetwork.IpamInfo() |
| 1354 | 1354 |
for _, info := range v4infos {
|
| 1355 | 1355 |
if info.IPAMData.Pool != nil {
|
| ... | ... |
@@ -247,8 +247,10 @@ func (daemon *Daemon) initNetworkController(daemonCfg *config.Config, activeSand |
| 247 | 247 |
return err |
| 248 | 248 |
} |
| 249 | 249 |
|
| 250 |
+ ctx := context.TODO() |
|
| 251 |
+ |
|
| 250 | 252 |
// Remove networks not present in HNS |
| 251 |
- for _, v := range daemon.netController.Networks() {
|
|
| 253 |
+ for _, v := range daemon.netController.Networks(ctx) {
|
|
| 252 | 254 |
hnsid := v.DriverOptions()[winlibnetwork.HNSID] |
| 253 | 255 |
found := false |
| 254 | 256 |
|
| ... | ... |
@@ -68,7 +68,7 @@ func (daemon *Daemon) LogNetworkEventWithAttributes(nw *libnetwork.Network, acti |
| 68 | 68 |
// LogDaemonEventWithAttributes generates an event related to the daemon itself with specific given attributes. |
| 69 | 69 |
func (daemon *Daemon) LogDaemonEventWithAttributes(action events.Action, attributes map[string]string) {
|
| 70 | 70 |
if daemon.EventsService != nil {
|
| 71 |
- if name := hostName(); name != "" {
|
|
| 71 |
+ if name := hostName(context.TODO()); name != "" {
|
|
| 72 | 72 |
attributes["name"] = name |
| 73 | 73 |
} |
| 74 | 74 |
daemon.EventsService.Log(action, events.DaemonEventType, events.Actor{
|
| ... | ... |
@@ -36,7 +36,7 @@ type ImageService interface {
|
| 36 | 36 |
LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error |
| 37 | 37 |
Images(ctx context.Context, opts types.ImageListOptions) ([]*imagetype.Summary, error) |
| 38 | 38 |
LogImageEvent(imageID, refName string, action events.Action) |
| 39 |
- CountImages() int |
|
| 39 |
+ CountImages(ctx context.Context) int |
|
| 40 | 40 |
ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error) |
| 41 | 41 |
ImportImage(ctx context.Context, ref reference.Named, platform *ocispec.Platform, msg string, layerReader io.Reader, changes []string) (image.ID, error) |
| 42 | 42 |
TagImage(ctx context.Context, imageID image.ID, newTag reference.Named) error |
| ... | ... |
@@ -102,7 +102,7 @@ func (i *ImageService) DistributionServices() DistributionServices {
|
| 102 | 102 |
|
| 103 | 103 |
// CountImages returns the number of images stored by ImageService |
| 104 | 104 |
// called from info.go |
| 105 |
-func (i *ImageService) CountImages() int {
|
|
| 105 |
+func (i *ImageService) CountImages(ctx context.Context) int {
|
|
| 106 | 106 |
return i.imageStore.Len() |
| 107 | 107 |
} |
| 108 | 108 |
|
| ... | ... |
@@ -8,6 +8,7 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"time" |
| 10 | 10 |
|
| 11 |
+ "github.com/containerd/containerd/tracing" |
|
| 11 | 12 |
"github.com/containerd/log" |
| 12 | 13 |
"github.com/docker/docker/api" |
| 13 | 14 |
"github.com/docker/docker/api/types" |
| ... | ... |
@@ -27,8 +28,19 @@ import ( |
| 27 | 27 |
"github.com/opencontainers/selinux/go-selinux" |
| 28 | 28 |
) |
| 29 | 29 |
|
| 30 |
+func doWithTrace[T any](ctx context.Context, name string, f func() T) T {
|
|
| 31 |
+ _, span := tracing.StartSpan(ctx, name) |
|
| 32 |
+ defer span.End() |
|
| 33 |
+ return f() |
|
| 34 |
+} |
|
| 35 |
+ |
|
| 30 | 36 |
// SystemInfo returns information about the host server the daemon is running on. |
| 31 |
-func (daemon *Daemon) SystemInfo() *system.Info {
|
|
| 37 |
+// |
|
| 38 |
+// The only error this should return is due to context cancellation/deadline. |
|
| 39 |
+// Anything else should be logged and ignored because this is looking up |
|
| 40 |
+// multiple things and is often used for debugging. |
|
| 41 |
+// The only case valid early return is when the caller doesn't want the result anymore (ie context cancelled). |
|
| 42 |
+func (daemon *Daemon) SystemInfo(ctx context.Context) (*system.Info, error) {
|
|
| 32 | 43 |
defer metrics.StartTimer(hostInfoFunctions.WithValues("system_info"))()
|
| 33 | 44 |
|
| 34 | 45 |
sysInfo := daemon.RawSysInfo() |
| ... | ... |
@@ -36,22 +48,22 @@ func (daemon *Daemon) SystemInfo() *system.Info {
|
| 36 | 36 |
|
| 37 | 37 |
v := &system.Info{
|
| 38 | 38 |
ID: daemon.id, |
| 39 |
- Images: daemon.imageService.CountImages(), |
|
| 39 |
+ Images: daemon.imageService.CountImages(ctx), |
|
| 40 | 40 |
IPv4Forwarding: !sysInfo.IPv4ForwardingDisabled, |
| 41 | 41 |
BridgeNfIptables: !sysInfo.BridgeNFCallIPTablesDisabled, |
| 42 | 42 |
BridgeNfIP6tables: !sysInfo.BridgeNFCallIP6TablesDisabled, |
| 43 |
- Name: hostName(), |
|
| 43 |
+ Name: hostName(ctx), |
|
| 44 | 44 |
SystemTime: time.Now().Format(time.RFC3339Nano), |
| 45 | 45 |
LoggingDriver: daemon.defaultLogConfig.Type, |
| 46 |
- KernelVersion: kernelVersion(), |
|
| 47 |
- OperatingSystem: operatingSystem(), |
|
| 48 |
- OSVersion: osVersion(), |
|
| 46 |
+ KernelVersion: kernelVersion(ctx), |
|
| 47 |
+ OperatingSystem: operatingSystem(ctx), |
|
| 48 |
+ OSVersion: osVersion(ctx), |
|
| 49 | 49 |
IndexServerAddress: registry.IndexServer, |
| 50 | 50 |
OSType: runtime.GOOS, |
| 51 | 51 |
Architecture: platform.Architecture, |
| 52 |
- RegistryConfig: daemon.registryService.ServiceConfig(), |
|
| 53 |
- NCPU: sysinfo.NumCPU(), |
|
| 54 |
- MemTotal: memInfo().MemTotal, |
|
| 52 |
+ RegistryConfig: doWithTrace(ctx, "registry.ServiceConfig", daemon.registryService.ServiceConfig), |
|
| 53 |
+ NCPU: doWithTrace(ctx, "sysinfo.NumCPU", sysinfo.NumCPU), |
|
| 54 |
+ MemTotal: memInfo(ctx).MemTotal, |
|
| 55 | 55 |
GenericResources: daemon.genericResources, |
| 56 | 56 |
DockerRootDir: cfg.Root, |
| 57 | 57 |
Labels: cfg.Labels, |
| ... | ... |
@@ -66,24 +78,31 @@ func (daemon *Daemon) SystemInfo() *system.Info {
|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 | 68 |
daemon.fillContainerStates(v) |
| 69 |
- daemon.fillDebugInfo(v) |
|
| 69 |
+ daemon.fillDebugInfo(ctx, v) |
|
| 70 | 70 |
daemon.fillAPIInfo(v, &cfg.Config) |
| 71 | 71 |
// Retrieve platform specific info |
| 72 |
- daemon.fillPlatformInfo(v, sysInfo, cfg) |
|
| 72 |
+ if err := daemon.fillPlatformInfo(ctx, v, sysInfo, cfg); err != nil {
|
|
| 73 |
+ return nil, err |
|
| 74 |
+ } |
|
| 73 | 75 |
daemon.fillDriverInfo(v) |
| 74 |
- daemon.fillPluginsInfo(v, &cfg.Config) |
|
| 76 |
+ daemon.fillPluginsInfo(ctx, v, &cfg.Config) |
|
| 75 | 77 |
daemon.fillSecurityOptions(v, sysInfo, &cfg.Config) |
| 76 | 78 |
daemon.fillLicense(v) |
| 77 |
- daemon.fillDefaultAddressPools(v, &cfg.Config) |
|
| 79 |
+ daemon.fillDefaultAddressPools(ctx, v, &cfg.Config) |
|
| 78 | 80 |
|
| 79 |
- return v |
|
| 81 |
+ return v, nil |
|
| 80 | 82 |
} |
| 81 | 83 |
|
| 82 | 84 |
// SystemVersion returns version information about the daemon. |
| 83 |
-func (daemon *Daemon) SystemVersion() types.Version {
|
|
| 85 |
+// |
|
| 86 |
+// The only error this should return is due to context cancellation/deadline. |
|
| 87 |
+// Anything else should be logged and ignored because this is looking up |
|
| 88 |
+// multiple things and is often used for debugging. |
|
| 89 |
+// The only case valid early return is when the caller doesn't want the result anymore (ie context cancelled). |
|
| 90 |
+func (daemon *Daemon) SystemVersion(ctx context.Context) (types.Version, error) {
|
|
| 84 | 91 |
defer metrics.StartTimer(hostInfoFunctions.WithValues("system_version"))()
|
| 85 | 92 |
|
| 86 |
- kernelVersion := kernelVersion() |
|
| 93 |
+ kernelVersion := kernelVersion(ctx) |
|
| 87 | 94 |
cfg := daemon.config() |
| 88 | 95 |
|
| 89 | 96 |
v := types.Version{
|
| ... | ... |
@@ -120,8 +139,10 @@ func (daemon *Daemon) SystemVersion() types.Version {
|
| 120 | 120 |
|
| 121 | 121 |
v.Platform.Name = dockerversion.PlatformName |
| 122 | 122 |
|
| 123 |
- daemon.fillPlatformVersion(&v, cfg) |
|
| 124 |
- return v |
|
| 123 |
+ if err := daemon.fillPlatformVersion(ctx, &v, cfg); err != nil {
|
|
| 124 |
+ return v, err |
|
| 125 |
+ } |
|
| 126 |
+ return v, nil |
|
| 125 | 127 |
} |
| 126 | 128 |
|
| 127 | 129 |
func (daemon *Daemon) fillDriverInfo(v *system.Info) {
|
| ... | ... |
@@ -140,10 +161,10 @@ WARNING: The %s storage-driver is deprecated, and will be removed in a future re |
| 140 | 140 |
fillDriverWarnings(v) |
| 141 | 141 |
} |
| 142 | 142 |
|
| 143 |
-func (daemon *Daemon) fillPluginsInfo(v *system.Info, cfg *config.Config) {
|
|
| 143 |
+func (daemon *Daemon) fillPluginsInfo(ctx context.Context, v *system.Info, cfg *config.Config) {
|
|
| 144 | 144 |
v.Plugins = system.PluginsInfo{
|
| 145 | 145 |
Volume: daemon.volumes.GetDriverList(), |
| 146 |
- Network: daemon.GetNetworkDriverList(), |
|
| 146 |
+ Network: daemon.GetNetworkDriverList(ctx), |
|
| 147 | 147 |
|
| 148 | 148 |
// The authorization plugins are returned in the order they are |
| 149 | 149 |
// used as they constitute a request/response modification chain. |
| ... | ... |
@@ -198,9 +219,9 @@ func (daemon *Daemon) fillContainerStates(v *system.Info) {
|
| 198 | 198 |
// this information optional (cli to request "with debugging information"), or |
| 199 | 199 |
// only collect it if the daemon has debug enabled. For the CLI code, see |
| 200 | 200 |
// https://github.com/docker/cli/blob/v20.10.12/cli/command/system/info.go#L239-L244 |
| 201 |
-func (daemon *Daemon) fillDebugInfo(v *system.Info) {
|
|
| 201 |
+func (daemon *Daemon) fillDebugInfo(ctx context.Context, v *system.Info) {
|
|
| 202 | 202 |
v.Debug = debug.IsEnabled() |
| 203 |
- v.NFd = fileutils.GetTotalUsedFds() |
|
| 203 |
+ v.NFd = fileutils.GetTotalUsedFds(ctx) |
|
| 204 | 204 |
v.NGoroutines = runtime.NumGoroutine() |
| 205 | 205 |
v.NEventsListener = daemon.EventsService.SubscribersCount() |
| 206 | 206 |
} |
| ... | ... |
@@ -228,7 +249,9 @@ func (daemon *Daemon) fillAPIInfo(v *system.Info, cfg *config.Config) {
|
| 228 | 228 |
} |
| 229 | 229 |
} |
| 230 | 230 |
|
| 231 |
-func (daemon *Daemon) fillDefaultAddressPools(v *system.Info, cfg *config.Config) {
|
|
| 231 |
+func (daemon *Daemon) fillDefaultAddressPools(ctx context.Context, v *system.Info, cfg *config.Config) {
|
|
| 232 |
+ _, span := tracing.StartSpan(ctx, "fillDefaultAddressPools") |
|
| 233 |
+ defer span.End() |
|
| 232 | 234 |
for _, pool := range cfg.DefaultAddressPools.Value() {
|
| 233 | 235 |
v.DefaultAddressPools = append(v.DefaultAddressPools, system.NetworkAddressPool{
|
| 234 | 236 |
Base: pool.Base, |
| ... | ... |
@@ -237,45 +260,56 @@ func (daemon *Daemon) fillDefaultAddressPools(v *system.Info, cfg *config.Config |
| 237 | 237 |
} |
| 238 | 238 |
} |
| 239 | 239 |
|
| 240 |
-func hostName() string {
|
|
| 240 |
+func hostName(ctx context.Context) string {
|
|
| 241 |
+ ctx, span := tracing.StartSpan(ctx, "hostName") |
|
| 242 |
+ defer span.End() |
|
| 241 | 243 |
hostname := "" |
| 242 | 244 |
if hn, err := os.Hostname(); err != nil {
|
| 243 |
- log.G(context.TODO()).Warnf("Could not get hostname: %v", err)
|
|
| 245 |
+ log.G(ctx).Warnf("Could not get hostname: %v", err)
|
|
| 244 | 246 |
} else {
|
| 245 | 247 |
hostname = hn |
| 246 | 248 |
} |
| 247 | 249 |
return hostname |
| 248 | 250 |
} |
| 249 | 251 |
|
| 250 |
-func kernelVersion() string {
|
|
| 252 |
+func kernelVersion(ctx context.Context) string {
|
|
| 253 |
+ ctx, span := tracing.StartSpan(ctx, "kernelVersion") |
|
| 254 |
+ defer span.End() |
|
| 255 |
+ |
|
| 251 | 256 |
var kernelVersion string |
| 252 | 257 |
if kv, err := kernel.GetKernelVersion(); err != nil {
|
| 253 |
- log.G(context.TODO()).Warnf("Could not get kernel version: %v", err)
|
|
| 258 |
+ log.G(ctx).Warnf("Could not get kernel version: %v", err)
|
|
| 254 | 259 |
} else {
|
| 255 | 260 |
kernelVersion = kv.String() |
| 256 | 261 |
} |
| 257 | 262 |
return kernelVersion |
| 258 | 263 |
} |
| 259 | 264 |
|
| 260 |
-func memInfo() *meminfo.Memory {
|
|
| 265 |
+func memInfo(ctx context.Context) *meminfo.Memory {
|
|
| 266 |
+ ctx, span := tracing.StartSpan(ctx, "memInfo") |
|
| 267 |
+ defer span.End() |
|
| 268 |
+ |
|
| 261 | 269 |
memInfo, err := meminfo.Read() |
| 262 | 270 |
if err != nil {
|
| 263 |
- log.G(context.TODO()).Errorf("Could not read system memory info: %v", err)
|
|
| 271 |
+ log.G(ctx).Errorf("Could not read system memory info: %v", err)
|
|
| 264 | 272 |
memInfo = &meminfo.Memory{}
|
| 265 | 273 |
} |
| 266 | 274 |
return memInfo |
| 267 | 275 |
} |
| 268 | 276 |
|
| 269 |
-func operatingSystem() (operatingSystem string) {
|
|
| 277 |
+func operatingSystem(ctx context.Context) (operatingSystem string) {
|
|
| 278 |
+ ctx, span := tracing.StartSpan(ctx, "operatingSystem") |
|
| 279 |
+ defer span.End() |
|
| 280 |
+ |
|
| 270 | 281 |
defer metrics.StartTimer(hostInfoFunctions.WithValues("operating_system"))()
|
| 271 | 282 |
|
| 272 | 283 |
if s, err := operatingsystem.GetOperatingSystem(); err != nil {
|
| 273 |
- log.G(context.TODO()).Warnf("Could not get operating system name: %v", err)
|
|
| 284 |
+ log.G(ctx).Warnf("Could not get operating system name: %v", err)
|
|
| 274 | 285 |
} else {
|
| 275 | 286 |
operatingSystem = s |
| 276 | 287 |
} |
| 277 | 288 |
if inContainer, err := operatingsystem.IsContainerized(); err != nil {
|
| 278 |
- log.G(context.TODO()).Errorf("Could not determine if daemon is containerized: %v", err)
|
|
| 289 |
+ log.G(ctx).Errorf("Could not determine if daemon is containerized: %v", err)
|
|
| 279 | 290 |
operatingSystem += " (error determining if containerized)" |
| 280 | 291 |
} else if inContainer {
|
| 281 | 292 |
operatingSystem += " (containerized)" |
| ... | ... |
@@ -284,12 +318,15 @@ func operatingSystem() (operatingSystem string) {
|
| 284 | 284 |
return operatingSystem |
| 285 | 285 |
} |
| 286 | 286 |
|
| 287 |
-func osVersion() (version string) {
|
|
| 287 |
+func osVersion(ctx context.Context) (version string) {
|
|
| 288 |
+ ctx, span := tracing.StartSpan(ctx, "osVersion") |
|
| 289 |
+ defer span.End() |
|
| 290 |
+ |
|
| 288 | 291 |
defer metrics.StartTimer(hostInfoFunctions.WithValues("os_version"))()
|
| 289 | 292 |
|
| 290 | 293 |
version, err := operatingsystem.GetOperatingSystemVersion() |
| 291 | 294 |
if err != nil {
|
| 292 |
- log.G(context.TODO()).Warnf("Could not get operating system version: %v", err)
|
|
| 295 |
+ log.G(ctx).Warnf("Could not get operating system version: %v", err)
|
|
| 293 | 296 |
} |
| 294 | 297 |
|
| 295 | 298 |
return version |
| ... | ... |
@@ -16,6 +16,7 @@ import ( |
| 16 | 16 |
containertypes "github.com/docker/docker/api/types/container" |
| 17 | 17 |
"github.com/docker/docker/api/types/system" |
| 18 | 18 |
"github.com/docker/docker/daemon/config" |
| 19 |
+ "github.com/docker/docker/errdefs" |
|
| 19 | 20 |
"github.com/docker/docker/pkg/rootless" |
| 20 | 21 |
"github.com/docker/docker/pkg/sysinfo" |
| 21 | 22 |
"github.com/pkg/errors" |
| ... | ... |
@@ -23,7 +24,7 @@ import ( |
| 23 | 23 |
) |
| 24 | 24 |
|
| 25 | 25 |
// fillPlatformInfo fills the platform related info. |
| 26 |
-func (daemon *Daemon) fillPlatformInfo(v *system.Info, sysInfo *sysinfo.SysInfo, cfg *configStore) {
|
|
| 26 |
+func (daemon *Daemon) fillPlatformInfo(ctx context.Context, v *system.Info, sysInfo *sysinfo.SysInfo, cfg *configStore) error {
|
|
| 27 | 27 |
v.CgroupDriver = cgroupDriver(&cfg.Config) |
| 28 | 28 |
v.CgroupVersion = "1" |
| 29 | 29 |
if sysInfo.CgroupUnified {
|
| ... | ... |
@@ -57,36 +58,20 @@ func (daemon *Daemon) fillPlatformInfo(v *system.Info, sysInfo *sysinfo.SysInfo, |
| 57 | 57 |
v.ContainerdCommit.ID = "N/A" |
| 58 | 58 |
v.InitCommit.ID = "N/A" |
| 59 | 59 |
|
| 60 |
- if _, _, commit, err := parseDefaultRuntimeVersion(&cfg.Runtimes); err != nil {
|
|
| 61 |
- log.G(context.TODO()).Warnf(err.Error()) |
|
| 62 |
- } else {
|
|
| 63 |
- v.RuncCommit.ID = commit |
|
| 60 |
+ if err := populateRuncCommit(&v.RuncCommit, cfg); err != nil {
|
|
| 61 |
+ log.G(ctx).WithError(err).Warn("Failed to retrieve default runtime version")
|
|
| 64 | 62 |
} |
| 65 | 63 |
|
| 66 |
- if rv, err := daemon.containerd.Version(context.Background()); err == nil {
|
|
| 67 |
- v.ContainerdCommit.ID = rv.Revision |
|
| 68 |
- } else {
|
|
| 69 |
- log.G(context.TODO()).Warnf("failed to retrieve containerd version: %v", err)
|
|
| 64 |
+ if err := daemon.populateContainerdCommit(ctx, &v.ContainerdCommit); err != nil {
|
|
| 65 |
+ return err |
|
| 70 | 66 |
} |
| 71 | 67 |
|
| 72 |
- v.InitBinary = cfg.GetInitPath() |
|
| 73 |
- if initBinary, err := cfg.LookupInitPath(); err != nil {
|
|
| 74 |
- log.G(context.TODO()).Warnf("failed to find docker-init: %s", err)
|
|
| 75 |
- } else if rv, err := exec.Command(initBinary, "--version").Output(); err == nil {
|
|
| 76 |
- if _, commit, err := parseInitVersion(string(rv)); err != nil {
|
|
| 77 |
- log.G(context.TODO()).Warnf("failed to parse %s version: %s", initBinary, err)
|
|
| 78 |
- } else {
|
|
| 79 |
- v.InitCommit.ID = commit |
|
| 80 |
- } |
|
| 81 |
- } else {
|
|
| 82 |
- log.G(context.TODO()).Warnf("failed to retrieve %s version: %s", initBinary, err)
|
|
| 68 |
+ if err := daemon.populateInitCommit(ctx, v, cfg); err != nil {
|
|
| 69 |
+ return err |
|
| 83 | 70 |
} |
| 84 | 71 |
|
| 85 | 72 |
// Set expected and actual commits to the same value to prevent the client |
| 86 | 73 |
// showing that the version does not match the "expected" version/commit. |
| 87 |
- v.RuncCommit.Expected = v.RuncCommit.ID |
|
| 88 |
- v.ContainerdCommit.Expected = v.ContainerdCommit.ID |
|
| 89 |
- v.InitCommit.Expected = v.InitCommit.ID |
|
| 90 | 74 |
|
| 91 | 75 |
if v.CgroupDriver == cgroupNoneDriver {
|
| 92 | 76 |
if v.CgroupVersion == "2" {
|
| ... | ... |
@@ -171,65 +156,79 @@ func (daemon *Daemon) fillPlatformInfo(v *system.Info, sysInfo *sysinfo.SysInfo, |
| 171 | 171 |
if !v.BridgeNfIP6tables {
|
| 172 | 172 |
v.Warnings = append(v.Warnings, "WARNING: bridge-nf-call-ip6tables is disabled") |
| 173 | 173 |
} |
| 174 |
+ return nil |
|
| 174 | 175 |
} |
| 175 | 176 |
|
| 176 |
-func (daemon *Daemon) fillPlatformVersion(v *types.Version, cfg *configStore) {
|
|
| 177 |
- if rv, err := daemon.containerd.Version(context.Background()); err == nil {
|
|
| 178 |
- v.Components = append(v.Components, types.ComponentVersion{
|
|
| 179 |
- Name: "containerd", |
|
| 180 |
- Version: rv.Version, |
|
| 181 |
- Details: map[string]string{
|
|
| 182 |
- "GitCommit": rv.Revision, |
|
| 183 |
- }, |
|
| 184 |
- }) |
|
| 177 |
+func (daemon *Daemon) fillPlatformVersion(ctx context.Context, v *types.Version, cfg *configStore) error {
|
|
| 178 |
+ if err := daemon.populateContainerdVersion(ctx, v); err != nil {
|
|
| 179 |
+ return err |
|
| 185 | 180 |
} |
| 186 | 181 |
|
| 187 |
- if _, ver, commit, err := parseDefaultRuntimeVersion(&cfg.Runtimes); err != nil {
|
|
| 188 |
- log.G(context.TODO()).Warnf(err.Error()) |
|
| 189 |
- } else {
|
|
| 190 |
- v.Components = append(v.Components, types.ComponentVersion{
|
|
| 191 |
- Name: cfg.Runtimes.Default, |
|
| 192 |
- Version: ver, |
|
| 193 |
- Details: map[string]string{
|
|
| 194 |
- "GitCommit": commit, |
|
| 195 |
- }, |
|
| 196 |
- }) |
|
| 197 |
- } |
|
| 198 |
- |
|
| 199 |
- if initBinary, err := cfg.LookupInitPath(); err != nil {
|
|
| 200 |
- log.G(context.TODO()).Warnf("failed to find docker-init: %s", err)
|
|
| 201 |
- } else if rv, err := exec.Command(initBinary, "--version").Output(); err == nil {
|
|
| 202 |
- if ver, commit, err := parseInitVersion(string(rv)); err != nil {
|
|
| 203 |
- log.G(context.TODO()).Warnf("failed to parse %s version: %s", initBinary, err)
|
|
| 204 |
- } else {
|
|
| 205 |
- v.Components = append(v.Components, types.ComponentVersion{
|
|
| 206 |
- Name: filepath.Base(initBinary), |
|
| 207 |
- Version: ver, |
|
| 208 |
- Details: map[string]string{
|
|
| 209 |
- "GitCommit": commit, |
|
| 210 |
- }, |
|
| 211 |
- }) |
|
| 182 |
+ if err := populateRuncVersion(cfg, v); err != nil {
|
|
| 183 |
+ log.G(ctx).WithError(err).Warn("Failed to retrieve default runtime version")
|
|
| 184 |
+ } |
|
| 185 |
+ |
|
| 186 |
+ if err := populateInitVersion(ctx, cfg, v); err != nil {
|
|
| 187 |
+ return err |
|
| 188 |
+ } |
|
| 189 |
+ |
|
| 190 |
+ if err := daemon.fillRootlessVersion(ctx, v); err != nil {
|
|
| 191 |
+ if errdefs.IsContext(err) {
|
|
| 192 |
+ return err |
|
| 212 | 193 |
} |
| 213 |
- } else {
|
|
| 214 |
- log.G(context.TODO()).Warnf("failed to retrieve %s version: %s", initBinary, err)
|
|
| 194 |
+ log.G(ctx).WithError(err).Warn("Failed to fill rootless version")
|
|
| 215 | 195 |
} |
| 196 |
+ return nil |
|
| 197 |
+} |
|
| 216 | 198 |
|
| 217 |
- daemon.fillRootlessVersion(v) |
|
| 199 |
+func populateRuncCommit(v *system.Commit, cfg *configStore) error {
|
|
| 200 |
+ _, _, commit, err := parseDefaultRuntimeVersion(&cfg.Runtimes) |
|
| 201 |
+ if err != nil {
|
|
| 202 |
+ return err |
|
| 203 |
+ } |
|
| 204 |
+ v.ID = commit |
|
| 205 |
+ v.Expected = commit |
|
| 206 |
+ return nil |
|
| 218 | 207 |
} |
| 219 | 208 |
|
| 220 |
-func (daemon *Daemon) fillRootlessVersion(v *types.Version) {
|
|
| 209 |
+func (daemon *Daemon) populateInitCommit(ctx context.Context, v *system.Info, cfg *configStore) error {
|
|
| 210 |
+ v.InitBinary = cfg.GetInitPath() |
|
| 211 |
+ initBinary, err := cfg.LookupInitPath() |
|
| 212 |
+ if err != nil {
|
|
| 213 |
+ log.G(ctx).WithError(err).Warnf("Failed to find docker-init")
|
|
| 214 |
+ return nil |
|
| 215 |
+ } |
|
| 216 |
+ |
|
| 217 |
+ rv, err := exec.CommandContext(ctx, initBinary, "--version").Output() |
|
| 218 |
+ if err != nil {
|
|
| 219 |
+ if errdefs.IsContext(err) {
|
|
| 220 |
+ return err |
|
| 221 |
+ } |
|
| 222 |
+ log.G(ctx).WithError(err).Warnf("Failed to retrieve %s version", initBinary)
|
|
| 223 |
+ return nil |
|
| 224 |
+ } |
|
| 225 |
+ |
|
| 226 |
+ _, commit, err := parseInitVersion(string(rv)) |
|
| 227 |
+ if err != nil {
|
|
| 228 |
+ log.G(ctx).WithError(err).Warnf("failed to parse %s version", initBinary)
|
|
| 229 |
+ return nil |
|
| 230 |
+ } |
|
| 231 |
+ v.InitCommit.ID = commit |
|
| 232 |
+ v.InitCommit.Expected = v.InitCommit.ID |
|
| 233 |
+ return nil |
|
| 234 |
+} |
|
| 235 |
+ |
|
| 236 |
+func (daemon *Daemon) fillRootlessVersion(ctx context.Context, v *types.Version) error {
|
|
| 221 | 237 |
if !rootless.RunningWithRootlessKit() {
|
| 222 |
- return |
|
| 238 |
+ return nil |
|
| 223 | 239 |
} |
| 224 | 240 |
rlc, err := getRootlessKitClient() |
| 225 | 241 |
if err != nil {
|
| 226 |
- log.G(context.TODO()).Warnf("failed to create RootlessKit client: %v", err)
|
|
| 227 |
- return |
|
| 242 |
+ return errors.Wrap(err, "failed to create RootlessKit client") |
|
| 228 | 243 |
} |
| 229 |
- rlInfo, err := rlc.Info(context.TODO()) |
|
| 244 |
+ rlInfo, err := rlc.Info(ctx) |
|
| 230 | 245 |
if err != nil {
|
| 231 |
- log.G(context.TODO()).Warnf("failed to retrieve RootlessKit version: %v", err)
|
|
| 232 |
- return |
|
| 246 |
+ return errors.Wrap(err, "failed to retrieve RootlessKit version") |
|
| 233 | 247 |
} |
| 234 | 248 |
v.Components = append(v.Components, types.ComponentVersion{
|
| 235 | 249 |
Name: "rootlesskit", |
| ... | ... |
@@ -244,31 +243,54 @@ func (daemon *Daemon) fillRootlessVersion(v *types.Version) {
|
| 244 | 244 |
|
| 245 | 245 |
switch rlInfo.NetworkDriver.Driver {
|
| 246 | 246 |
case "slirp4netns": |
| 247 |
- if rv, err := exec.Command("slirp4netns", "--version").Output(); err == nil {
|
|
| 248 |
- if _, ver, commit, err := parseRuntimeVersion(string(rv)); err != nil {
|
|
| 249 |
- log.G(context.TODO()).Warnf("failed to parse slirp4netns version: %v", err)
|
|
| 250 |
- } else {
|
|
| 251 |
- v.Components = append(v.Components, types.ComponentVersion{
|
|
| 252 |
- Name: "slirp4netns", |
|
| 253 |
- Version: ver, |
|
| 254 |
- Details: map[string]string{
|
|
| 255 |
- "GitCommit": commit, |
|
| 256 |
- }, |
|
| 257 |
- }) |
|
| 247 |
+ err = func() error {
|
|
| 248 |
+ rv, err := exec.CommandContext(ctx, "slirp4netns", "--version").Output() |
|
| 249 |
+ if err != nil {
|
|
| 250 |
+ if errdefs.IsContext(err) {
|
|
| 251 |
+ return err |
|
| 252 |
+ } |
|
| 253 |
+ log.G(ctx).WithError(err).Warn("Failed to retrieve slirp4netns version")
|
|
| 254 |
+ return nil |
|
| 258 | 255 |
} |
| 259 |
- } else {
|
|
| 260 |
- log.G(context.TODO()).Warnf("failed to retrieve slirp4netns version: %v", err)
|
|
| 256 |
+ |
|
| 257 |
+ _, ver, commit, err := parseRuntimeVersion(string(rv)) |
|
| 258 |
+ if err != nil {
|
|
| 259 |
+ log.G(ctx).WithError(err).Warn("Failed to parse slirp4netns version")
|
|
| 260 |
+ return nil |
|
| 261 |
+ } |
|
| 262 |
+ v.Components = append(v.Components, types.ComponentVersion{
|
|
| 263 |
+ Name: "slirp4netns", |
|
| 264 |
+ Version: ver, |
|
| 265 |
+ Details: map[string]string{
|
|
| 266 |
+ "GitCommit": commit, |
|
| 267 |
+ }, |
|
| 268 |
+ }) |
|
| 269 |
+ return nil |
|
| 270 |
+ }() |
|
| 271 |
+ if err != nil {
|
|
| 272 |
+ return err |
|
| 261 | 273 |
} |
| 262 | 274 |
case "vpnkit": |
| 263 |
- if rv, err := exec.Command("vpnkit", "--version").Output(); err == nil {
|
|
| 275 |
+ err = func() error {
|
|
| 276 |
+ out, err := exec.CommandContext(ctx, "vpnkit", "--version").Output() |
|
| 277 |
+ if err != nil {
|
|
| 278 |
+ if errdefs.IsContext(err) {
|
|
| 279 |
+ return err |
|
| 280 |
+ } |
|
| 281 |
+ log.G(ctx).WithError(err).Warn("Failed to retrieve vpnkit version")
|
|
| 282 |
+ return nil |
|
| 283 |
+ } |
|
| 264 | 284 |
v.Components = append(v.Components, types.ComponentVersion{
|
| 265 | 285 |
Name: "vpnkit", |
| 266 |
- Version: strings.TrimSpace(string(rv)), |
|
| 286 |
+ Version: strings.TrimSpace(strings.TrimSpace(string(out))), |
|
| 267 | 287 |
}) |
| 268 |
- } else {
|
|
| 269 |
- log.G(context.TODO()).Warnf("failed to retrieve vpnkit version: %v", err)
|
|
| 288 |
+ return nil |
|
| 289 |
+ }() |
|
| 290 |
+ if err != nil {
|
|
| 291 |
+ return err |
|
| 270 | 292 |
} |
| 271 | 293 |
} |
| 294 |
+ return nil |
|
| 272 | 295 |
} |
| 273 | 296 |
|
| 274 | 297 |
// getRootlessKitClient returns RootlessKit client |
| ... | ... |
@@ -384,3 +406,83 @@ func Rootless(cfg *config.Config) bool {
|
| 384 | 384 |
func noNewPrivileges(cfg *config.Config) bool {
|
| 385 | 385 |
return cfg.NoNewPrivileges |
| 386 | 386 |
} |
| 387 |
+ |
|
| 388 |
+func (daemon *Daemon) populateContainerdCommit(ctx context.Context, v *system.Commit) error {
|
|
| 389 |
+ rv, err := daemon.containerd.Version(ctx) |
|
| 390 |
+ if err != nil {
|
|
| 391 |
+ if errdefs.IsContext(err) {
|
|
| 392 |
+ return err |
|
| 393 |
+ } |
|
| 394 |
+ log.G(ctx).WithError(err).Warnf("Failed to retrieve containerd version")
|
|
| 395 |
+ return nil |
|
| 396 |
+ } |
|
| 397 |
+ v.ID = rv.Revision |
|
| 398 |
+ v.Expected = rv.Revision |
|
| 399 |
+ return nil |
|
| 400 |
+} |
|
| 401 |
+ |
|
| 402 |
+func (daemon *Daemon) populateContainerdVersion(ctx context.Context, v *types.Version) error {
|
|
| 403 |
+ rv, err := daemon.containerd.Version(ctx) |
|
| 404 |
+ if err != nil {
|
|
| 405 |
+ if errdefs.IsContext(err) {
|
|
| 406 |
+ return err |
|
| 407 |
+ } |
|
| 408 |
+ log.G(ctx).WithError(err).Warn("Failed to retrieve containerd version")
|
|
| 409 |
+ return nil |
|
| 410 |
+ } |
|
| 411 |
+ |
|
| 412 |
+ v.Components = append(v.Components, types.ComponentVersion{
|
|
| 413 |
+ Name: "containerd", |
|
| 414 |
+ Version: rv.Version, |
|
| 415 |
+ Details: map[string]string{
|
|
| 416 |
+ "GitCommit": rv.Revision, |
|
| 417 |
+ }, |
|
| 418 |
+ }) |
|
| 419 |
+ return nil |
|
| 420 |
+} |
|
| 421 |
+ |
|
| 422 |
+func populateRuncVersion(cfg *configStore, v *types.Version) error {
|
|
| 423 |
+ _, ver, commit, err := parseDefaultRuntimeVersion(&cfg.Runtimes) |
|
| 424 |
+ if err != nil {
|
|
| 425 |
+ return err |
|
| 426 |
+ } |
|
| 427 |
+ v.Components = append(v.Components, types.ComponentVersion{
|
|
| 428 |
+ Name: cfg.Runtimes.Default, |
|
| 429 |
+ Version: ver, |
|
| 430 |
+ Details: map[string]string{
|
|
| 431 |
+ "GitCommit": commit, |
|
| 432 |
+ }, |
|
| 433 |
+ }) |
|
| 434 |
+ return nil |
|
| 435 |
+} |
|
| 436 |
+ |
|
| 437 |
+func populateInitVersion(ctx context.Context, cfg *configStore, v *types.Version) error {
|
|
| 438 |
+ initBinary, err := cfg.LookupInitPath() |
|
| 439 |
+ if err != nil {
|
|
| 440 |
+ log.G(ctx).WithError(err).Warn("Failed to find docker-init")
|
|
| 441 |
+ return nil |
|
| 442 |
+ } |
|
| 443 |
+ |
|
| 444 |
+ rv, err := exec.CommandContext(ctx, initBinary, "--version").Output() |
|
| 445 |
+ if err != nil {
|
|
| 446 |
+ if errdefs.IsContext(err) {
|
|
| 447 |
+ return err |
|
| 448 |
+ } |
|
| 449 |
+ log.G(ctx).WithError(err).Warnf("Failed to retrieve %s version", initBinary)
|
|
| 450 |
+ return nil |
|
| 451 |
+ } |
|
| 452 |
+ |
|
| 453 |
+ ver, commit, err := parseInitVersion(string(rv)) |
|
| 454 |
+ if err != nil {
|
|
| 455 |
+ log.G(ctx).WithError(err).Warnf("failed to parse %s version", initBinary)
|
|
| 456 |
+ return nil |
|
| 457 |
+ } |
|
| 458 |
+ v.Components = append(v.Components, types.ComponentVersion{
|
|
| 459 |
+ Name: filepath.Base(initBinary), |
|
| 460 |
+ Version: ver, |
|
| 461 |
+ Details: map[string]string{
|
|
| 462 |
+ "GitCommit": commit, |
|
| 463 |
+ }, |
|
| 464 |
+ }) |
|
| 465 |
+ return nil |
|
| 466 |
+} |
| ... | ... |
@@ -1,6 +1,8 @@ |
| 1 | 1 |
package daemon // import "github.com/docker/docker/daemon" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "context" |
|
| 5 |
+ |
|
| 4 | 6 |
"github.com/docker/docker/api/types" |
| 5 | 7 |
"github.com/docker/docker/api/types/system" |
| 6 | 8 |
"github.com/docker/docker/daemon/config" |
| ... | ... |
@@ -8,10 +10,13 @@ import ( |
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
// fillPlatformInfo fills the platform related info. |
| 11 |
-func (daemon *Daemon) fillPlatformInfo(v *system.Info, sysInfo *sysinfo.SysInfo, cfg *configStore) {
|
|
| 11 |
+func (daemon *Daemon) fillPlatformInfo(ctx context.Context, v *system.Info, sysInfo *sysinfo.SysInfo, cfg *configStore) error {
|
|
| 12 |
+ return nil |
|
| 12 | 13 |
} |
| 13 | 14 |
|
| 14 |
-func (daemon *Daemon) fillPlatformVersion(v *types.Version, cfg *configStore) {}
|
|
| 15 |
+func (daemon *Daemon) fillPlatformVersion(ctx context.Context, v *types.Version, cfg *configStore) error {
|
|
| 16 |
+ return nil |
|
| 17 |
+} |
|
| 15 | 18 |
|
| 16 | 19 |
func fillDriverWarnings(v *system.Info) {
|
| 17 | 20 |
} |
| ... | ... |
@@ -139,7 +139,8 @@ func (daemon *Daemon) getAllNetworks() []*libnetwork.Network {
|
| 139 | 139 |
if c == nil {
|
| 140 | 140 |
return nil |
| 141 | 141 |
} |
| 142 |
- return c.Networks() |
|
| 142 |
+ ctx := context.TODO() |
|
| 143 |
+ return c.Networks(ctx) |
|
| 143 | 144 |
} |
| 144 | 145 |
|
| 145 | 146 |
type ingressJob struct {
|
| ... | ... |
@@ -465,7 +466,7 @@ func (daemon *Daemon) DisconnectContainerFromNetwork(containerName string, netwo |
| 465 | 465 |
|
| 466 | 466 |
// GetNetworkDriverList returns the list of plugins drivers |
| 467 | 467 |
// registered for network. |
| 468 |
-func (daemon *Daemon) GetNetworkDriverList() []string {
|
|
| 468 |
+func (daemon *Daemon) GetNetworkDriverList(ctx context.Context) []string {
|
|
| 469 | 469 |
if !daemon.NetworkControllerEnabled() {
|
| 470 | 470 |
return nil |
| 471 | 471 |
} |
| ... | ... |
@@ -483,7 +484,7 @@ func (daemon *Daemon) GetNetworkDriverList() []string {
|
| 483 | 483 |
pluginMap[plugin] = true |
| 484 | 484 |
} |
| 485 | 485 |
|
| 486 |
- networks := daemon.netController.Networks() |
|
| 486 |
+ networks := daemon.netController.Networks(ctx) |
|
| 487 | 487 |
|
| 488 | 488 |
for _, nw := range networks {
|
| 489 | 489 |
if !pluginMap[nw.Type()] {
|
| ... | ... |
@@ -1,5 +1,10 @@ |
| 1 | 1 |
package errdefs |
| 2 | 2 |
|
| 3 |
+import ( |
|
| 4 |
+ "context" |
|
| 5 |
+ "errors" |
|
| 6 |
+) |
|
| 7 |
+ |
|
| 3 | 8 |
type causer interface {
|
| 4 | 9 |
Cause() error |
| 5 | 10 |
} |
| ... | ... |
@@ -105,3 +110,8 @@ func IsDataLoss(err error) bool {
|
| 105 | 105 |
_, ok := getImplementer(err).(ErrDataLoss) |
| 106 | 106 |
return ok |
| 107 | 107 |
} |
| 108 |
+ |
|
| 109 |
+// IsContext returns if the passed in error is due to context cancellation or deadline exceeded. |
|
| 110 |
+func IsContext(err error) bool {
|
|
| 111 |
+ return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) |
|
| 112 |
+} |
| ... | ... |
@@ -820,10 +820,10 @@ func (c *Controller) addNetwork(n *Network) error {
|
| 820 | 820 |
} |
| 821 | 821 |
|
| 822 | 822 |
// Networks returns the list of Network(s) managed by this controller. |
| 823 |
-func (c *Controller) Networks() []*Network {
|
|
| 823 |
+func (c *Controller) Networks(ctx context.Context) []*Network {
|
|
| 824 | 824 |
var list []*Network |
| 825 | 825 |
|
| 826 |
- for _, n := range c.getNetworksFromStore() {
|
|
| 826 |
+ for _, n := range c.getNetworksFromStore(ctx) {
|
|
| 827 | 827 |
if n.inDelete {
|
| 828 | 828 |
continue |
| 829 | 829 |
} |
| ... | ... |
@@ -835,7 +835,7 @@ func (c *Controller) Networks() []*Network {
|
| 835 | 835 |
|
| 836 | 836 |
// WalkNetworks uses the provided function to walk the Network(s) managed by this controller. |
| 837 | 837 |
func (c *Controller) WalkNetworks(walker NetworkWalker) {
|
| 838 |
- for _, n := range c.Networks() {
|
|
| 838 |
+ for _, n := range c.Networks(context.TODO()) {
|
|
| 839 | 839 |
if walker(n) {
|
| 840 | 840 |
return |
| 841 | 841 |
} |
| ... | ... |
@@ -538,7 +538,8 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
|
| 538 | 538 |
t.Fatal(err) |
| 539 | 539 |
} |
| 540 | 540 |
|
| 541 |
- current := len(controller.Networks()) |
|
| 541 |
+ ctx := context.TODO() |
|
| 542 |
+ current := len(controller.Networks(ctx)) |
|
| 542 | 543 |
|
| 543 | 544 |
// Create network 2 |
| 544 | 545 |
netOption = options.Generic{
|
| ... | ... |
@@ -558,7 +559,7 @@ func TestNetworkEndpointsWalkers(t *testing.T) {
|
| 558 | 558 |
}() |
| 559 | 559 |
|
| 560 | 560 |
// Test Networks method |
| 561 |
- if len(controller.Networks()) != current+1 {
|
|
| 561 |
+ if len(controller.Networks(ctx)) != current+1 {
|
|
| 562 | 562 |
t.Fatalf("Did not find the expected number of networks")
|
| 563 | 563 |
} |
| 564 | 564 |
|
| ... | ... |
@@ -34,7 +34,7 @@ func (c *Controller) getStore() *datastore.Store {
|
| 34 | 34 |
} |
| 35 | 35 |
|
| 36 | 36 |
func (c *Controller) getNetworkFromStore(nid string) (*Network, error) {
|
| 37 |
- for _, n := range c.getNetworksFromStore() {
|
|
| 37 |
+ for _, n := range c.getNetworksFromStore(context.TODO()) {
|
|
| 38 | 38 |
if n.id == nid {
|
| 39 | 39 |
return n, nil |
| 40 | 40 |
} |
| ... | ... |
@@ -77,21 +77,21 @@ func (c *Controller) getNetworks() ([]*Network, error) {
|
| 77 | 77 |
return nl, nil |
| 78 | 78 |
} |
| 79 | 79 |
|
| 80 |
-func (c *Controller) getNetworksFromStore() []*Network { // FIXME: unify with c.getNetworks()
|
|
| 80 |
+func (c *Controller) getNetworksFromStore(ctx context.Context) []*Network { // FIXME: unify with c.getNetworks()
|
|
| 81 | 81 |
var nl []*Network |
| 82 | 82 |
|
| 83 | 83 |
store := c.getStore() |
| 84 | 84 |
kvol, err := store.List(datastore.Key(datastore.NetworkKeyPrefix), &Network{ctrlr: c})
|
| 85 | 85 |
if err != nil {
|
| 86 | 86 |
if err != datastore.ErrKeyNotFound {
|
| 87 |
- log.G(context.TODO()).Debugf("failed to get networks from store: %v", err)
|
|
| 87 |
+ log.G(ctx).Debugf("failed to get networks from store: %v", err)
|
|
| 88 | 88 |
} |
| 89 | 89 |
return nil |
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 | 92 |
kvep, err := store.Map(datastore.Key(epCntKeyPrefix), &endpointCnt{})
|
| 93 | 93 |
if err != nil && err != datastore.ErrKeyNotFound {
|
| 94 |
- log.G(context.TODO()).Warnf("failed to get endpoint_count map from store: %v", err)
|
|
| 94 |
+ log.G(ctx).Warnf("failed to get endpoint_count map from store: %v", err)
|
|
| 95 | 95 |
} |
| 96 | 96 |
|
| 97 | 97 |
for _, kvo := range kvol {
|
| ... | ... |
@@ -185,7 +185,7 @@ retry: |
| 185 | 185 |
} |
| 186 | 186 |
|
| 187 | 187 |
func (c *Controller) networkCleanup() {
|
| 188 |
- for _, n := range c.getNetworksFromStore() {
|
|
| 188 |
+ for _, n := range c.getNetworksFromStore(context.TODO()) {
|
|
| 189 | 189 |
if n.inDelete {
|
| 190 | 190 |
log.G(context.TODO()).Infof("Removing stale network %s (%s)", n.Name(), n.ID())
|
| 191 | 191 |
if err := n.delete(true, true); err != nil {
|
| ... | ... |
@@ -6,13 +6,17 @@ import ( |
| 6 | 6 |
"io" |
| 7 | 7 |
"os" |
| 8 | 8 |
|
| 9 |
+ "github.com/containerd/containerd/tracing" |
|
| 9 | 10 |
"github.com/containerd/log" |
| 10 | 11 |
"golang.org/x/sys/unix" |
| 11 | 12 |
) |
| 12 | 13 |
|
| 13 | 14 |
// GetTotalUsedFds Returns the number of used File Descriptors by |
| 14 | 15 |
// reading it via /proc filesystem. |
| 15 |
-func GetTotalUsedFds() int {
|
|
| 16 |
+func GetTotalUsedFds(ctx context.Context) int {
|
|
| 17 |
+ ctx, span := tracing.StartSpan(ctx, "GetTotalUsedFds") |
|
| 18 |
+ defer span.End() |
|
| 19 |
+ |
|
| 16 | 20 |
name := fmt.Sprintf("/proc/%d/fd", os.Getpid())
|
| 17 | 21 |
|
| 18 | 22 |
// Fast-path for Linux 6.2 (since [f1f1f2569901ec5b9d425f2e91c09a0e320768f3]). |
| ... | ... |
@@ -30,19 +34,26 @@ func GetTotalUsedFds() int {
|
| 30 | 30 |
|
| 31 | 31 |
f, err := os.Open(name) |
| 32 | 32 |
if err != nil {
|
| 33 |
- log.G(context.TODO()).WithError(err).Error("Error listing file descriptors")
|
|
| 33 |
+ log.G(ctx).WithError(err).Error("Error listing file descriptors")
|
|
| 34 | 34 |
return -1 |
| 35 | 35 |
} |
| 36 | 36 |
defer f.Close() |
| 37 | 37 |
|
| 38 | 38 |
var fdCount int |
| 39 | 39 |
for {
|
| 40 |
+ select {
|
|
| 41 |
+ case <-ctx.Done(): |
|
| 42 |
+ log.G(ctx).WithError(ctx.Err()).Error("Context cancelled while counting file descriptors")
|
|
| 43 |
+ return -1 |
|
| 44 |
+ default: |
|
| 45 |
+ } |
|
| 46 |
+ |
|
| 40 | 47 |
names, err := f.Readdirnames(100) |
| 41 | 48 |
fdCount += len(names) |
| 42 | 49 |
if err == io.EOF {
|
| 43 | 50 |
break |
| 44 | 51 |
} else if err != nil {
|
| 45 |
- log.G(context.TODO()).WithError(err).Error("Error listing file descriptors")
|
|
| 52 |
+ log.G(ctx).WithError(err).Error("Error listing file descriptors")
|
|
| 46 | 53 |
return -1 |
| 47 | 54 |
} |
| 48 | 55 |
} |
| ... | ... |
@@ -1,6 +1,7 @@ |
| 1 | 1 |
package fileutils // import "github.com/docker/docker/pkg/fileutils" |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ "context" |
|
| 4 | 5 |
"errors" |
| 5 | 6 |
"os" |
| 6 | 7 |
"path" |
| ... | ... |
@@ -242,8 +243,9 @@ func TestCreateIfNotExistsFile(t *testing.T) {
|
| 242 | 242 |
} |
| 243 | 243 |
|
| 244 | 244 |
func BenchmarkGetTotalUsedFds(b *testing.B) {
|
| 245 |
+ ctx := context.Background() |
|
| 245 | 246 |
b.ReportAllocs() |
| 246 | 247 |
for i := 0; i < b.N; i++ {
|
| 247 |
- _ = GetTotalUsedFds() |
|
| 248 |
+ _ = GetTotalUsedFds(ctx) |
|
| 248 | 249 |
} |
| 249 | 250 |
} |
| ... | ... |
@@ -1,7 +1,9 @@ |
| 1 | 1 |
package fileutils // import "github.com/docker/docker/pkg/fileutils" |
| 2 | 2 |
|
| 3 |
+import "context" |
|
| 4 |
+ |
|
| 3 | 5 |
// GetTotalUsedFds Returns the number of used File Descriptors. Not supported |
| 4 | 6 |
// on Windows. |
| 5 |
-func GetTotalUsedFds() int {
|
|
| 7 |
+func GetTotalUsedFds(ctx context.Context) int {
|
|
| 6 | 8 |
return -1 |
| 7 | 9 |
} |