diff --git a/cmd/synchronizer/flag_set_validation_error_test.go b/cmd/synchronizer/flag_set_validation_error_test.go new file mode 100644 index 00000000..54de97f7 --- /dev/null +++ b/cmd/synchronizer/flag_set_validation_error_test.go @@ -0,0 +1,30 @@ +package main + +import ( + "fmt" + "github.com/splitio/go-split-commons/v5/flagsets" + "golang.org/x/exp/slices" + "strings" + "testing" +) + +func TestFlagSetValidationError(t *testing.T) { + flagSets, err := flagsets.SanitizeMany([]string{"Flagset1", " flagset2 ", "123#@flagset"}) + if err == nil { + t.Error("errors should not be nil") + } + if len(err) != 3 { + t.Error("Unexpected Amount of errors. Should be 3. Was", len(err)) + } + if len(flagSets) != 2 { + t.Error("Unexpected amount of flagsets. Should be 2. Was", len(flagSets)) + } + if !slices.Contains(flagSets, "flagset1") || !slices.Contains(flagSets, "flagset2") { + t.Error("Missing flagsets.") + } + fsvError := flagSetValidationError{wrapped: err}.Error() + if !strings.Contains(fsvError, "Flagset1") || !strings.Contains(fsvError, "flagset2") || !strings.Contains(fsvError, "123#@flagset") { + t.Error("Missing errors on flagSetValidation.") + } + fmt.Printf("Flagsets: %#v", flagSets) +} diff --git a/cmd/synchronizer/main.go b/cmd/synchronizer/main.go index a19742ec..07c56efa 100644 --- a/cmd/synchronizer/main.go +++ b/cmd/synchronizer/main.go @@ -3,7 +3,9 @@ package main import ( "errors" "fmt" + "github.com/splitio/go-split-commons/v5/flagsets" "os" + "strings" "github.com/splitio/split-synchronizer/v5/splitio" "github.com/splitio/split-synchronizer/v5/splitio/common" @@ -22,6 +24,18 @@ func parseCliArgs() *cconf.CliFlags { return cconf.ParseCliArgs(&conf.Main{}) } +type flagSetValidationError struct { + wrapped []error +} + +func (f flagSetValidationError) Error() string { + var errors []string + for _, err := range f.wrapped { + errors = append(errors, err.Error()) + } + return strings.Join(errors, ".|| ") +} + func setupConfig(cliArgs *cconf.CliFlags) (*conf.Main, error) { syncConf := conf.Main{} cconf.PopulateDefaults(&syncConf) @@ -34,7 +48,16 @@ func setupConfig(cliArgs *cconf.CliFlags) (*conf.Main, error) { } cconf.PopulateFromArguments(&syncConf, cliArgs.RawConfig) - return &syncConf, nil + + var err error + sanitizedFlagSets, fsErr := flagsets.SanitizeMany(syncConf.FlagSetsFilter) + if fsErr != nil { + err = flagSetValidationError{wrapped: fsErr} + } + if sanitizedFlagSets != nil { + syncConf.FlagSetsFilter = sanitizedFlagSets + } + return &syncConf, err } func main() { @@ -57,8 +80,13 @@ func main() { cfg, err := setupConfig(cliArgs) if err != nil { - fmt.Println("error processing config: ", err) - os.Exit(exitCodeConfigError) + var fsErr flagSetValidationError + if errors.As(err, &fsErr) { + fmt.Println("error processing flagset: ", err.Error()) + } else { + fmt.Println("error processing config: ", err) + os.Exit(exitCodeConfigError) + } } logger := log.BuildFromConfig(&cfg.Logging, "Split-Sync", &cfg.Integrations.Slack) diff --git a/splitio/producer/initialization_test.go b/splitio/producer/initialization_test.go index d03c6e22..df7f58c3 100644 --- a/splitio/producer/initialization_test.go +++ b/splitio/producer/initialization_test.go @@ -6,6 +6,8 @@ import ( "net/http" "net/http/httptest" "os" + "strconv" + "strings" "testing" config "github.com/splitio/go-split-commons/v5/conf" @@ -198,6 +200,58 @@ func TestSanitizeRedisWithRedisDifferentApiKey(t *testing.T) { redisClient.Del("SPLITIO.test1") } +func TestSanitizeRedisWithForcedCleanupByFlagSets(t *testing.T) { + cfg := getDefaultConf() + cfg.Apikey = "983564etyrudhijfgknf9i08euh" + cfg.Initialization.ForceFreshStartup = true + cfg.FlagSetsFilter = []string{"flagset1", "flagset2"} + + hash := util.HashAPIKey(cfg.Apikey + strings.Join(cfg.FlagSetsFilter, "::")) + + logger := logging.NewLogger(nil) + + redisClient, err := predis.NewRedisClient(&config.RedisConfig{ + Host: "localhost", + Port: 6379, + Prefix: "some_prefix", + Database: 1, + }, logger) + if err != nil { + t.Error("It should be nil") + } + + err = redisClient.Set("SPLITIO.test1", "123", 0) + redisClient.Set("SPLITIO.hash", hash, 0) + if err != nil { + t.Error("It should be nil") + } + value, err := redisClient.Get("SPLITIO.test1") + if value != "123" { + t.Error("Value should have been set properly") + } + + cfg.FlagSetsFilter = []string{"flagset7"} + miscStorage := predis.NewMiscStorage(redisClient, logger) + value, err = redisClient.Get("SPLITIO.test1") + err = sanitizeRedis(cfg, miscStorage, logger) + if err != nil { + t.Error("It should be nil", err) + } + + value, _ = redisClient.Get("SPLITIO.test1") + if value != "" { + t.Error("Value should have been removed.") + } + + val, _ := redisClient.Get("SPLITIO.hash") + parsedHash, _ := strconv.ParseUint(val, 10, 64) + if uint32(parsedHash) == hash { + t.Error("ApiHash should have been updated.") + } + redisClient.Del("SPLITIO.hash") + redisClient.Del("SPLITIO.test1") +} + func getDefaultConf() *conf.Main { var c conf.Main cconf.PopulateDefaults(&c) diff --git a/splitio/producer/util.go b/splitio/producer/util.go index c0f24f69..f7cda7f2 100644 --- a/splitio/producer/util.go +++ b/splitio/producer/util.go @@ -124,7 +124,7 @@ func sanitizeRedis(cfg *conf.Main, miscStorage *redis.MiscStorage, logger loggin if miscStorage == nil { return errors.New("Could not sanitize redis") } - currentHash := util.HashAPIKey(cfg.Apikey) + currentHash := util.HashAPIKey(cfg.Apikey + strings.Join(cfg.FlagSetsFilter, "::")) currentHashAsStr := strconv.Itoa(int(currentHash)) defer miscStorage.SetApikeyHash(currentHashAsStr)