From cec9dcfee876eb76c71930fb020d41fd5df87c31 Mon Sep 17 00:00:00 2001 From: Frank Schroeder Date: Fri, 30 Jun 2017 22:37:20 +0200 Subject: [PATCH] agent: fix pending data races between localState and agent This patch creates a local config structure for the local state which is independent from the agent but populated from its configuration. This avoids data races between the agent configuration which can change during tests and concurrent go routines using the configuraiton at the same time. --- agent/local.go | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/agent/local.go b/agent/local.go index e4b8cdc359..e3d30135fc 100644 --- a/agent/local.go +++ b/agent/local.go @@ -27,6 +27,21 @@ type syncStatus struct { inSync bool // Is this in sync with the server } +// localStateConfig is the configuration for the localState. It is +// popuplated during NewLocalAgent from the agent configuration to avoid +// race conditions with the agent configuration. +type localStateConfig struct { + ACLToken string + AEInterval time.Duration + AdvertiseAddr string + CheckUpdateInterval time.Duration + Datacenter string + NodeID types.NodeID + NodeName string + TaggedAddresses map[string]string + TokenForAgent string +} + // localState is used to represent the node's services, // and checks. We used it to perform anti-entropy with the // catalog representation @@ -39,7 +54,7 @@ type localState struct { logger *log.Logger // Config is the agent config - config *Config + config localStateConfig // delegate is the consul interface to use for keeping in sync delegate delegate @@ -76,8 +91,23 @@ type localState struct { // NewLocalState creates a is used to initialize the local state func NewLocalState(c *Config, lg *log.Logger) *localState { + lc := localStateConfig{ + ACLToken: c.ACLToken, + AEInterval: c.AEInterval, + AdvertiseAddr: c.AdvertiseAddr, + CheckUpdateInterval: c.CheckUpdateInterval, + Datacenter: c.Datacenter, + NodeID: c.NodeID, + NodeName: c.NodeName, + TaggedAddresses: map[string]string{}, + TokenForAgent: c.GetTokenForAgent(), + } + for k, v := range c.TaggedAddresses { + lc.TaggedAddresses[k] = v + } + return &localState{ - config: c, + config: lc, logger: lg, services: make(map[string]*structs.NodeService), serviceStatus: make(map[string]syncStatus), @@ -413,7 +443,7 @@ func (l *localState) setSyncState() error { req := structs.NodeSpecificRequest{ Datacenter: l.config.Datacenter, Node: l.config.NodeName, - QueryOptions: structs.QueryOptions{Token: l.config.GetTokenForAgent()}, + QueryOptions: structs.QueryOptions{Token: l.config.TokenForAgent}, } var out1 structs.IndexedNodeServices var out2 structs.IndexedHealthChecks @@ -744,7 +774,7 @@ func (l *localState) syncNodeInfo() error { Address: l.config.AdvertiseAddr, TaggedAddresses: l.config.TaggedAddresses, NodeMeta: l.metadata, - WriteRequest: structs.WriteRequest{Token: l.config.GetTokenForAgent()}, + WriteRequest: structs.WriteRequest{Token: l.config.TokenForAgent}, } var out struct{} err := l.delegate.RPC("Catalog.Register", &req, &out)