diff --git a/libnetwork/controller.go b/libnetwork/controller.go index f6d4d52665..7aef771d45 100644 --- a/libnetwork/controller.go +++ b/libnetwork/controller.go @@ -656,7 +656,7 @@ addToStore: // end up with a datastore containing a network and not an epCnt, // in case of an ungraceful shutdown during this function call. epCnt := &endpointCnt{n: nw} - if err := c.updateToStore(epCnt); err != nil { + if err := c.updateToStore(context.TODO(), epCnt); err != nil { return nil, err } defer func() { @@ -668,7 +668,7 @@ addToStore: }() nw.epCnt = epCnt - if err := c.updateToStore(nw); err != nil { + if err := c.updateToStore(context.TODO(), nw); err != nil { return nil, err } defer func() { @@ -967,7 +967,7 @@ func (c *Controller) NewSandbox(ctx context.Context, containerID string, options } }() - if err := sb.storeUpdate(); err != nil { + if err := sb.storeUpdate(ctx); err != nil { return nil, fmt.Errorf("failed to update the store state of sandbox: %v", err) } diff --git a/libnetwork/drivers/bridge/bridge_linux.go b/libnetwork/drivers/bridge/bridge_linux.go index c79c957454..d0ffa1a809 100644 --- a/libnetwork/drivers/bridge/bridge_linux.go +++ b/libnetwork/drivers/bridge/bridge_linux.go @@ -750,7 +750,7 @@ func (d *driver) CreateNetwork(id string, option map[string]interface{}, nInfo d return err } - return d.storeUpdate(config) + return d.storeUpdate(context.TODO(), config) } func (d *driver) checkConflict(config *networkConfiguration) error { @@ -1183,7 +1183,7 @@ func (d *driver) CreateEndpoint(ctx context.Context, nid, eid string, ifInfo dri } } - if err = d.storeUpdate(endpoint); err != nil { + if err = d.storeUpdate(ctx, endpoint); err != nil { return fmt.Errorf("failed to save bridge endpoint %.7s to store: %v", endpoint.id, err) } @@ -1443,7 +1443,7 @@ func (d *driver) ProgramExternalConnectivity(ctx context.Context, nid, eid strin // be bound to the local proxy, or to the host (for UDP packets), and won't be redirected to the new endpoints. clearConntrackEntries(d.nlh, endpoint) - if err = d.storeUpdate(endpoint); err != nil { + if err = d.storeUpdate(ctx, endpoint); err != nil { return fmt.Errorf("failed to update bridge endpoint %.7s to store: %v", endpoint.id, err) } @@ -1481,7 +1481,7 @@ func (d *driver) RevokeExternalConnectivity(nid, eid string) error { // to bad NATing. clearConntrackEntries(d.nlh, endpoint) - if err = d.storeUpdate(endpoint); err != nil { + if err = d.storeUpdate(context.TODO(), endpoint); err != nil { return fmt.Errorf("failed to update bridge endpoint %.7s to store: %v", endpoint.id, err) } diff --git a/libnetwork/drivers/bridge/bridge_store.go b/libnetwork/drivers/bridge/bridge_store.go index 77e3893cea..e2b509f7fe 100644 --- a/libnetwork/drivers/bridge/bridge_store.go +++ b/libnetwork/drivers/bridge/bridge_store.go @@ -12,6 +12,9 @@ import ( "github.com/docker/docker/libnetwork/datastore" "github.com/docker/docker/libnetwork/netlabel" "github.com/docker/docker/libnetwork/types" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" ) const ( @@ -95,9 +98,13 @@ func (d *driver) populateEndpoints() error { return nil } -func (d *driver) storeUpdate(kvObject datastore.KVObject) error { +func (d *driver) storeUpdate(ctx context.Context, kvObject datastore.KVObject) error { + ctx, span := otel.Tracer("").Start(ctx, "libnetwork.drivers.bridge.storeUpdate", trace.WithAttributes( + attribute.String("kvObject", fmt.Sprintf("%+v", kvObject.Key())))) + defer span.End() + if d.store == nil { - log.G(context.TODO()).Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...)) + log.G(ctx).Warnf("bridge store not initialized. kv object %s is not added to the store", datastore.Key(kvObject.Key()...)) return nil } diff --git a/libnetwork/endpoint.go b/libnetwork/endpoint.go index 93b8a660a2..335f3f70b9 100644 --- a/libnetwork/endpoint.go +++ b/libnetwork/endpoint.go @@ -562,7 +562,7 @@ func (ep *Endpoint) sbJoin(ctx context.Context, sb *Sandbox, options ...Endpoint return errdefs.System(err) } - if err = n.getController().updateToStore(ep); err != nil { + if err = n.getController().updateToStore(ctx, ep); err != nil { return err } @@ -646,7 +646,7 @@ func (ep *Endpoint) rename(name string) error { ep.mu.Unlock() // Update the store with the updated name - if err := ep.getNetwork().getController().updateToStore(ep); err != nil { + if err := ep.getNetwork().getController().updateToStore(context.TODO(), ep); err != nil { return err } @@ -682,7 +682,7 @@ func (ep *Endpoint) UpdateDNSNames(dnsNames []string) error { } // Update the store with the updated name - if err := c.updateToStore(ep); err != nil { + if err := c.updateToStore(context.TODO(), ep); err != nil { return err } @@ -777,7 +777,7 @@ func (ep *Endpoint) sbLeave(sb *Sandbox, force bool) error { // spurious logs when cleaning up the sandbox when the daemon // ungracefully exits and restarts before completing sandbox // detach but after store has been updated. - if err := n.getController().updateToStore(ep); err != nil { + if err := n.getController().updateToStore(context.TODO(), ep); err != nil { return err } @@ -860,7 +860,7 @@ func (ep *Endpoint) Delete(force bool) error { defer func() { if err != nil && !force { ep.dbExists = false - if e := n.getController().updateToStore(ep); e != nil { + if e := n.getController().updateToStore(context.WithoutCancel(context.TODO()), ep); e != nil { log.G(context.TODO()).Warnf("failed to recreate endpoint in store %s : %v", name, e) } } diff --git a/libnetwork/endpoint_cnt.go b/libnetwork/endpoint_cnt.go index a5b5dd6585..43e48f86ef 100644 --- a/libnetwork/endpoint_cnt.go +++ b/libnetwork/endpoint_cnt.go @@ -1,6 +1,7 @@ package libnetwork import ( + "context" "encoding/json" "fmt" "sync" @@ -110,7 +111,7 @@ func (ec *endpointCnt) updateStore() error { count := ec.EndpointCnt() n := ec.n for { - if err := c.updateToStore(ec); err == nil || err != datastore.ErrKeyModified { + if err := c.updateToStore(context.TODO(), ec); err == nil || err != datastore.ErrKeyModified { return err } if err := c.store.GetObject(ec); err != nil { @@ -148,7 +149,7 @@ retry: } ec.Unlock() - if err := ec.n.getController().updateToStore(ec); err != nil { + if err := ec.n.getController().updateToStore(context.TODO(), ec); err != nil { if err == datastore.ErrKeyModified { if err := store.GetObject(ec); err != nil { return fmt.Errorf("could not update the kvobject to latest when trying to atomic add endpoint count: %v", err) diff --git a/libnetwork/network.go b/libnetwork/network.go index c037646dad..00316fb439 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -1016,7 +1016,7 @@ func (n *Network) delete(force bool, rmLBEndpoint bool) error { // Mark the network for deletion n.inDelete = true - if err = c.updateToStore(n); err != nil { + if err = c.updateToStore(context.TODO(), n); err != nil { return fmt.Errorf("error marking network %s (%s) for deletion: %v", n.Name(), n.ID(), err) } @@ -1211,7 +1211,7 @@ func (n *Network) createEndpoint(ctx context.Context, name string, options ...En // We should perform updateToStore call right after addEndpoint // in order to have iface properly configured - if err = n.getController().updateToStore(ep); err != nil { + if err = n.getController().updateToStore(ctx, ep); err != nil { return nil, err } defer func() { diff --git a/libnetwork/sandbox.go b/libnetwork/sandbox.go index 3a3c274d2f..17e093d7ec 100644 --- a/libnetwork/sandbox.go +++ b/libnetwork/sandbox.go @@ -638,7 +638,7 @@ func (sb *Sandbox) clearNetworkResources(origEp *Endpoint) error { // not bother updating the store. The sandbox object will be // deleted anyway if !inDelete { - return sb.storeUpdate() + return sb.storeUpdate(context.TODO()) } return nil diff --git a/libnetwork/sandbox_linux.go b/libnetwork/sandbox_linux.go index 7ac25d09d0..91b12d3925 100644 --- a/libnetwork/sandbox_linux.go +++ b/libnetwork/sandbox_linux.go @@ -375,7 +375,7 @@ func (sb *Sandbox) populateNetworkResources(ctx context.Context, ep *Endpoint) e // not bother updating the store. The sandbox object will be // deleted anyway if !inDelete { - return sb.storeUpdate() + return sb.storeUpdate(ctx) } return nil diff --git a/libnetwork/sandbox_store.go b/libnetwork/sandbox_store.go index aebf1735dc..66661241aa 100644 --- a/libnetwork/sandbox_store.go +++ b/libnetwork/sandbox_store.go @@ -122,7 +122,7 @@ func (sbs *sbState) CopyTo(o datastore.KVObject) error { return nil } -func (sb *Sandbox) storeUpdate() error { +func (sb *Sandbox) storeUpdate(ctx context.Context) error { sbs := &sbState{ c: sb.controller, ID: sb.id, @@ -146,7 +146,7 @@ retry: }) } - err := sb.controller.updateToStore(sbs) + err := sb.controller.updateToStore(ctx, sbs) if err == datastore.ErrKeyModified { // When we get ErrKeyModified it is sufficient to just // go back and retry. No need to get the object from diff --git a/libnetwork/store.go b/libnetwork/store.go index 2982462947..7d0e03e778 100644 --- a/libnetwork/store.go +++ b/libnetwork/store.go @@ -8,6 +8,7 @@ import ( "github.com/containerd/log" "github.com/docker/docker/libnetwork/datastore" "github.com/docker/docker/libnetwork/scope" + "go.opentelemetry.io/otel" ) func (c *Controller) getNetworkFromStore(nid string) (*Network, error) { @@ -114,7 +115,10 @@ func (n *Network) getEndpointsFromStore() ([]*Endpoint, error) { return epl, nil } -func (c *Controller) updateToStore(kvObject datastore.KVObject) error { +func (c *Controller) updateToStore(ctx context.Context, kvObject datastore.KVObject) error { + ctx, span := otel.Tracer("").Start(ctx, "libnetwork.Controller.updateToStore") + defer span.End() + if err := c.store.PutObjectAtomic(kvObject); err != nil { if err == datastore.ErrKeyModified { return err