Skip to content

Commit

Permalink
[reconstruction] change configFilterChain from public sigleton to pri…
Browse files Browse the repository at this point in the history
…vate owned by ConfigClient (#700)

* change configFilterChain from public sigleton to private owned by ConfigClient

* fix up encryptedDataKey cache

* tiny fix

* tiny fix

* change mse endpoint

* add using localDiskCache test case

* add using localDiskCache test case

* add using localDiskCache test case
  • Loading branch information
robynron authored Dec 22, 2023
1 parent 7178ed3 commit 89c5ab6
Show file tree
Hide file tree
Showing 16 changed files with 556 additions and 323 deletions.
11 changes: 11 additions & 0 deletions clients/cache/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package cache

type ConfigCachedFileType string

const (
ConfigContent ConfigCachedFileType = "Config Content"
ConfigEncryptedDataKey ConfigCachedFileType = "Config Encrypted Data Key"

ENCRYPTED_DATA_KEY_FILE_NAME = "encrypted-data-key"
FAILOVER_FILE_SUFFIX = "_failover"
)
114 changes: 99 additions & 15 deletions clients/cache/disk_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,43 @@ package cache

import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"
"syscall"

"github.com/nacos-group/nacos-sdk-go/v2/common/constant"
"github.com/nacos-group/nacos-sdk-go/v2/common/file"
"github.com/nacos-group/nacos-sdk-go/v2/common/logger"
"github.com/nacos-group/nacos-sdk-go/v2/model"
"github.com/nacos-group/nacos-sdk-go/v2/util"
"github.com/pkg/errors"
)

func GetFileName(cacheKey string, cacheDir string) string {
var (
fileNotExistError = errors.New("file not exist")
)

func GetFileName(cacheKey, cacheDir string) string {
return cacheDir + string(os.PathSeparator) + cacheKey
}

func GetEncryptedDataKeyDir(cacheDir string) string {
return cacheDir + string(os.PathSeparator) + ENCRYPTED_DATA_KEY_FILE_NAME
}

func GetConfigEncryptedDataKeyFileName(cacheKey, cacheDir string) string {
return GetEncryptedDataKeyDir(cacheDir) + string(os.PathSeparator) + cacheKey
}

func GetConfigFailOverContentFileName(cacheKey, cacheDir string) string {
return GetFileName(cacheKey, cacheDir) + FAILOVER_FILE_SUFFIX
}

func GetConfigFailOverEncryptedDataKeyFileName(cacheKey, cacheDir string) string {
return GetConfigEncryptedDataKeyFileName(cacheKey, cacheDir) + FAILOVER_FILE_SUFFIX
}

func WriteServicesToFile(service *model.Service, cacheKey, cacheDir string) {
err := file.MkdirIfNecessary(cacheDir)
if err != nil {
Expand Down Expand Up @@ -76,43 +98,105 @@ func ReadServicesFromFile(cacheDir string) map[string]model.Service {
return serviceMap
}

func WriteConfigToFile(cacheKey string, cacheDir string, content string) {
file.MkdirIfNecessary(cacheDir)
fileName := GetFileName(cacheKey, cacheDir)
if len(content) == 0 {
func WriteConfigToFile(cacheKey string, cacheDir string, content string) error {
err := file.MkdirIfNecessary(cacheDir)
if err != nil {
errMsg := fmt.Sprintf("make dir failed, dir path %s, err: %v.", cacheDir, err)
logger.Error(errMsg)
return errors.New(errMsg)
}
err = writeConfigToFile(GetFileName(cacheKey, cacheDir), content, ConfigContent)
if err != nil {
logger.Error(err)
return err
}
return nil
}

func WriteEncryptedDataKeyToFile(cacheKey string, cacheDir string, content string) error {
err := file.MkdirIfNecessary(GetEncryptedDataKeyDir(cacheDir))
if err != nil {
errMsg := fmt.Sprintf("make dir failed, dir path %s, err: %v.", cacheDir, err)
logger.Error(errMsg)
return errors.New(errMsg)
}
err = writeConfigToFile(GetConfigEncryptedDataKeyFileName(cacheKey, cacheDir), content, ConfigEncryptedDataKey)
if err != nil {
logger.Error(err)
return err
}
return nil
}

func writeConfigToFile(fileName string, content string, fileType ConfigCachedFileType) error {
if len(strings.TrimSpace(content)) == 0 {
// delete config snapshot
if err := os.Remove(fileName); err != nil {
logger.Errorf("failed to delete config file,cache:%s ,value:%s ,err:%v", fileName, content, err)
if err != syscall.ENOENT {
logger.Debug(fmt.Sprintf("no need to delete %s cache file, file path %s, file doesn't exist.", fileType, fileName))
return nil
}
errMsg := fmt.Sprintf("failed to delete %s cache file, file path %s, err:%v", fileType, fileName, err)
return errors.New(errMsg)
}
return
}
err := os.WriteFile(fileName, []byte(content), 0666)
if err != nil {
logger.Errorf("failed to write config cache:%s ,value:%s ,err:%v", fileName, content, err)
errMsg := fmt.Sprintf("failed to write %s cache file, file name: %s, value: %s, err:%v", fileType, fileName, content, err)
return errors.New(errMsg)
}
return nil
}

func ReadEncryptedDataKeyFromFile(cacheKey string, cacheDir string) (string, error) {
content, err := readConfigFromFile(GetConfigEncryptedDataKeyFileName(cacheKey, cacheDir), ConfigEncryptedDataKey)
if err != nil {
if errors.Is(err, fileNotExistError) {
logger.Warn(err)
return "", nil
}
}
return content, nil
}

func ReadConfigFromFile(cacheKey string, cacheDir string) (string, error) {
fileName := GetFileName(cacheKey, cacheDir)
return readConfigFromFile(GetFileName(cacheKey, cacheDir), ConfigEncryptedDataKey)
}

func readConfigFromFile(fileName string, fileType ConfigCachedFileType) (string, error) {
if !file.IsExistFile(fileName) {
errMsg := fmt.Sprintf("read cache file %s failed. cause file doesn't exist, file path: %s.", fileType, fileName)
return "", errors.Wrap(fileNotExistError, errMsg)
}
b, err := os.ReadFile(fileName)
if err != nil {
logger.Errorf("get config from cache, cacheKey:%s, cacheDir:%s, error:%v ", cacheKey, cacheDir, err)
return "", errors.Errorf("failed to read config cache file:%s, cacheDir:%s, err:%v ", fileName, cacheDir, err)
errMsg := fmt.Sprintf("get %s from cache failed, filePath:%s, error:%v ", fileType, fileName, err)
return "", errors.New(errMsg)
}
return string(b), nil
}

// GetFailover , get failover content
func GetFailover(key, dir string) string {
filePath := dir + string(os.PathSeparator) + key + constant.FAILOVER_FILE_SUFFIX
filePath := GetConfigFailOverContentFileName(key, dir)
return getFailOverConfig(filePath, ConfigContent)
}

func GetFailoverEncryptedDataKey(key, dir string) string {
filePath := GetConfigFailOverEncryptedDataKeyFileName(key, dir)
return getFailOverConfig(filePath, ConfigEncryptedDataKey)
}

func getFailOverConfig(filePath string, fileType ConfigCachedFileType) string {
if !file.IsExistFile(filePath) {
errMsg := fmt.Sprintf("read %s failed. cause file doesn't exist, file path: %s.", fileType, filePath)
logger.Error(errMsg)
return ""
}
logger.Warnf("reading failover content from path:%s", filePath)
logger.Warnf("reading failover %s from path:%s", fileType, filePath)
fileContent, err := os.ReadFile(filePath)
if err != nil {
logger.Errorf("fail to read failover content from %s", filePath)
logger.Errorf("fail to read failover %s from %s", fileType, filePath)
return ""
}
return string(fileContent)
Expand Down
92 changes: 91 additions & 1 deletion clients/cache/disk_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,107 @@ package cache

import (
"fmt"
"github.com/nacos-group/nacos-sdk-go/v2/util"
"math/rand"
"os"
"strconv"
"testing"

"github.com/stretchr/testify/assert"

"github.com/nacos-group/nacos-sdk-go/v2/common/file"
)

var (
dir = file.GetCurrentPath()
group = "FILE_GROUP"
ns = "chasu"
)

func TestWriteAndGetConfigToFile(t *testing.T) {
dataIdSuffix := strconv.Itoa(rand.Intn(1000))
t.Run("write and get config content", func(t *testing.T) {
dataId := "config_content" + dataIdSuffix
cacheKey := util.GetConfigCacheKey(dataId, group, ns)
configContent := "config content"

err := WriteConfigToFile(cacheKey, dir, "")
assert.Nil(t, err)

configFromFile, err := ReadConfigFromFile(cacheKey, dir)
assert.NotNil(t, err)
assert.Equal(t, configFromFile, "")

err = WriteConfigToFile(cacheKey, dir, configContent)
assert.Nil(t, err)

fromFile, err := ReadConfigFromFile(cacheKey, dir)
assert.Nil(t, err)
assert.Equal(t, fromFile, configContent)

err = WriteConfigToFile(cacheKey, dir, "")
assert.Nil(t, err)

configFromFile, err = ReadConfigFromFile(cacheKey, dir)
assert.Nil(t, err)
assert.Equal(t, configFromFile, "")
})

t.Run("write and get config encryptedDataKey", func(t *testing.T) {
dataId := "config_encryptedDataKey" + dataIdSuffix
cacheKey := util.GetConfigCacheKey(dataId, group, ns)
configContent := "config encrypted data key"

err := WriteEncryptedDataKeyToFile(cacheKey, dir, "")
assert.Nil(t, err)

configFromFile, err := ReadEncryptedDataKeyFromFile(cacheKey, dir)
assert.Nil(t, err)
assert.Equal(t, configFromFile, "")

err = WriteEncryptedDataKeyToFile(cacheKey, dir, configContent)
assert.Nil(t, err)

fromFile, err := ReadEncryptedDataKeyFromFile(cacheKey, dir)
assert.Nil(t, err)
assert.Equal(t, fromFile, configContent)

err = WriteEncryptedDataKeyToFile(cacheKey, dir, "")
assert.Nil(t, err)

configFromFile, err = ReadEncryptedDataKeyFromFile(cacheKey, dir)
assert.Nil(t, err)
assert.Equal(t, configFromFile, "")
})
t.Run("double write config file", func(t *testing.T) {
dataId := "config_encryptedDataKey" + dataIdSuffix
cacheKey := util.GetConfigCacheKey(dataId, group, ns)
configContent := "config encrypted data key"

err := WriteConfigToFile(cacheKey, dir, configContent)
assert.Nil(t, err)

err = WriteConfigToFile(cacheKey, dir, configContent)
assert.Nil(t, err)

fromFile, err := ReadConfigFromFile(cacheKey, dir)
assert.Nil(t, err)
assert.Equal(t, fromFile, configContent)
})
t.Run("read doesn't existed config file", func(t *testing.T) {
dataId := "config_encryptedDataKey" + dataIdSuffix + strconv.Itoa(rand.Intn(1000))
cacheKey := util.GetConfigCacheKey(dataId, group, ns)

_, err := ReadConfigFromFile(cacheKey, dir)
assert.NotNil(t, err)

_, err = ReadEncryptedDataKeyFromFile(cacheKey, dir)
assert.Nil(t, err)
})
}

func TestGetFailover(t *testing.T) {
cacheKey := "test_failOver"
dir := file.GetCurrentPath()
fileContent := "test_failover"
t.Run("writeContent", func(t *testing.T) {
filepath := dir + string(os.PathSeparator) + cacheKey + "_failover"
Expand Down
Loading

0 comments on commit 89c5ab6

Please sign in to comment.