diff --git a/pkg/services/ldap/settings.go b/pkg/services/ldap/settings.go index 90f3732b235..5d30e53c138 100644 --- a/pkg/services/ldap/settings.go +++ b/pkg/services/ldap/settings.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "sync" + "time" "github.com/BurntSushi/toml" @@ -93,7 +94,11 @@ var loadingMutex = &sync.Mutex{} // We need to define in this space so `GetConfig` fn // could be defined as singleton -var config *ServersConfig +var cachedConfig struct { + config *ServersConfig + filePath string + fileModified time.Time +} func GetLDAPConfig(cfg *setting.Cfg) *Config { return &Config{ @@ -117,15 +122,27 @@ func GetConfig(cfg *Config) (*ServersConfig, error) { return nil, nil } - // Make it a singleton - if config != nil { - return config, nil + configFileStats, err := os.Stat(cfg.ConfigFilePath) + if err != nil { + return nil, err + } + configFileModified := configFileStats.ModTime() + + // return the config from cache if the config file hasn't been modified + if cachedConfig.config != nil && cachedConfig.filePath == cfg.ConfigFilePath && cachedConfig.fileModified.Equal(configFileModified) { + return cachedConfig.config, nil } loadingMutex.Lock() defer loadingMutex.Unlock() - return readConfig(cfg.ConfigFilePath) + cachedConfig.config, err = readConfig(cfg.ConfigFilePath) + if err == nil { + cachedConfig.filePath = cfg.ConfigFilePath + cachedConfig.fileModified = configFileModified + } + + return cachedConfig.config, err } func readConfig(configFile string) (*ServersConfig, error) { diff --git a/pkg/services/ldap/settings_test.go b/pkg/services/ldap/settings_test.go index b1562afe513..2ca8c5025e4 100644 --- a/pkg/services/ldap/settings_test.go +++ b/pkg/services/ldap/settings_test.go @@ -25,3 +25,28 @@ func TestReadingLDAPSettingsWithEnvVariable(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, "MySecret", config.Servers[0].BindPassword) } + +func TestReadingLDAPSettingsUsingCache(t *testing.T) { + cfg := &Config{ + Enabled: true, + ConfigFilePath: "testdata/ldap.toml", + } + + // cache is empty initially + assert.Nil(t, cachedConfig.config) + + firstConfig, err := GetConfig(cfg) + + // cache has been initialized + assert.NotNil(t, cachedConfig.config) + assert.EqualValues(t, *firstConfig, *cachedConfig.config) + assert.Nil(t, err) + assert.EqualValues(t, "127.0.0.1", cachedConfig.config.Servers[0].Host) + + // make sure the cached config is returned on subsequent calls + config := cachedConfig.config + secondConfig, err := GetConfig(cfg) + + assert.Equal(t, config, secondConfig) + assert.Nil(t, err) +}