in agentconfig/agentconfig.go [436:502]
func WatchConfig(ctx context.Context) error {
var md []byte
var webError error
// Max watch time, after this WatchConfig will return.
timeout := time.After(osConfigWatchConfigTimeout)
// Min watch loop time.
loopTicker := time.NewTicker(5 * time.Second)
defer loopTicker.Stop()
eTag := lEtag.get()
webErrorCount := 0
unmarshalErrorCount := 0
for {
md, eTag, webError = getMetadata(fmt.Sprintf("?recursive=true&alt=json&wait_for_change=true&last_etag=%s&timeout_sec=%d", lEtag.get(), osConfigMetadataPollTimeout))
if webError == nil && eTag != lEtag.get() {
var metadataConfig metadataJSON
if err := json.Unmarshal(md, &metadataConfig); err != nil {
// Try up to three times (with 5s sleep) to get and unmarshal metadata.
// Most unmarshal errors are transient read issues with the metadata server
// so we should retry without logging the error.
if unmarshalErrorCount >= 3 {
return err
}
unmarshalErrorCount++
select {
case <-timeout:
return err
case <-ctx.Done():
return nil
case <-loopTicker.C:
continue
}
}
unmarshalErrorCount = 0
lEtag.set(eTag)
newAgentConfig := createConfigFromMetadata(metadataConfig)
agentConfigMx.Lock()
if agentConfig.asSha256() != newAgentConfig.asSha256() {
agentConfig = newAgentConfig
agentConfigMx.Unlock()
break
}
agentConfigMx.Unlock()
}
// Try up to 12 times (60s) to wait for slow network initialization, after
// that resort to using defaults and returning the error.
if webError != nil {
if webErrorCount == 12 {
return formatMetadataError(webError)
}
webErrorCount++
}
select {
case <-timeout:
return webError
case <-ctx.Done():
return nil
case <-loopTicker.C:
continue
}
}
return webError
}