Skip to content

Commit

Permalink
Fix server cannot start without the configuration file (#1804)
Browse files Browse the repository at this point in the history
Co-authored-by: Twice <[email protected]>
  • Loading branch information
git-hulk and PragmaTwice authored Oct 15, 2023
1 parent 935f32e commit 2b95456
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/config/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ Status Config::Set(Server *svr, std::string key, const std::string &value) {
}

Status Config::Rewrite(const std::map<std::string, std::string> &tokens) {
if (path_.empty()) {
if (!HasConfigFile()) {
return {Status::NotOK, "the server is running without a config file"};
}

Expand Down
1 change: 1 addition & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ struct Config {
void SetMaster(const std::string &host, uint32_t port);
void ClearMaster();
bool IsSlave() const { return !master_host.empty(); }
bool HasConfigFile() const { return !path_.empty(); }

private:
std::string path_;
Expand Down
23 changes: 20 additions & 3 deletions src/server/namespace.cc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ constexpr const char* kErrClusterModeEnabled = "forbidden to add namespace when
constexpr const char* kErrDeleteDefaultNamespace = "forbidden to delete the default namespace";
constexpr const char* kErrAddDefaultNamespace = "forbidden to add the default namespace";
constexpr const char* kErrInvalidToken = "the token is duplicated with requirepass or masterauth";
constexpr const char* kErrCantModifyNamespace =
"modify namespace requires the server is running with a configuration file or enabled namespace replication";

Status IsNamespaceLegal(const std::string& ns) {
if (ns.size() > UINT8_MAX) {
Expand All @@ -43,6 +45,12 @@ Status IsNamespaceLegal(const std::string& ns) {
return Status::OK();
}

bool Namespace::IsAllowModify() const {
auto config = storage_->GetConfig();

return config->HasConfigFile() || config->repl_namespace_enabled;
}

Status Namespace::LoadAndRewrite() {
auto config = storage_->GetConfig();
// Load from the configuration file first
Expand Down Expand Up @@ -100,6 +108,9 @@ Status Namespace::Set(const std::string& ns, const std::string& token) {
if (config->cluster_enabled) {
return {Status::NotOK, kErrClusterModeEnabled};
}
if (!IsAllowModify()) {
return {Status::NotOK, kErrCantModifyNamespace};
}
if (ns == kDefaultNamespace) {
return {Status::NotOK, kErrAddDefaultNamespace};
}
Expand Down Expand Up @@ -142,6 +153,9 @@ Status Namespace::Del(const std::string& ns) {
if (ns == kDefaultNamespace) {
return {Status::NotOK, kErrDeleteDefaultNamespace};
}
if (!IsAllowModify()) {
return {Status::NotOK, kErrCantModifyNamespace};
}

for (const auto& iter : tokens_) {
if (iter.second == ns) {
Expand All @@ -159,9 +173,12 @@ Status Namespace::Del(const std::string& ns) {

Status Namespace::Rewrite() {
auto config = storage_->GetConfig();
auto s = config->Rewrite(tokens_);
if (!s.IsOK()) {
return s;
// Rewrite the configuration file only if it's running with the configuration file
if (config->HasConfigFile()) {
auto s = config->Rewrite(tokens_);
if (!s.IsOK()) {
return s;
}
}

// Don't propagate write to DB if its role is slave to prevent from
Expand Down
1 change: 1 addition & 0 deletions src/server/namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class Namespace {
Status Del(const std::string &ns);
const std::map<std::string, std::string> &List() const { return tokens_; }
Status Rewrite();
bool IsAllowModify() const;

private:
engine::Storage *storage_;
Expand Down
2 changes: 1 addition & 1 deletion tests/gocase/integration/cli_options/cli_options_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
)

func TestCLIOptions(t *testing.T) {
srv := util.StartServerWithCLIOptions(t, map[string]string{}, []string{"--maxclients", "23333"})
srv := util.StartServerWithCLIOptions(t, true, map[string]string{}, []string{"--maxclients", "23333"})
defer srv.Close()

ctx := context.Background()
Expand Down
12 changes: 12 additions & 0 deletions tests/gocase/unit/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,15 @@ func TestConfigSetCompression(t *testing.T) {
}
require.ErrorContains(t, rdb.ConfigSet(ctx, configKey, "unsupported").Err(), "invalid enum option")
}

func TestStartWithoutConfigurationFile(t *testing.T) {
srv := util.StartServerWithCLIOptions(t, false, map[string]string{}, []string{})
defer srv.Close()

ctx := context.Background()
rdb := srv.NewClient()
defer func() { require.NoError(t, rdb.Close()) }()

require.NoError(t, rdb.Do(ctx, "SET", "foo", "bar").Err())
require.Equal(t, "bar", rdb.Do(ctx, "GET", "foo").Val())
}
30 changes: 30 additions & 0 deletions tests/gocase/unit/namespace/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,3 +241,33 @@ func TestNamespaceReplicate(t *testing.T) {
util.ErrorRegexp(t, masterRdb.ConfigSet(ctx, "repl-namespace-enabled", "no").Err(), ".*cannot switch off repl_namespace_enabled when namespaces exist in db.*")
})
}

func TestNamespaceRewrite(t *testing.T) {
password := "pwd"
srv := util.StartServerWithCLIOptions(t, false, map[string]string{
"requirepass": password,
}, []string{})
defer srv.Close()

rdb := srv.NewClientWithOption(&redis.Options{
Password: password,
})
defer func() { require.NoError(t, rdb.Close()) }()
ctx := context.Background()

t.Run("Cannot modify namespace if running without the configuration", func(t *testing.T) {
errMsg := ".*ERR modify namespace requires the server is running with a configuration file or enabled namespace replication.*"
r := rdb.Do(ctx, "NAMESPACE", "ADD", "ns1", "token1")
util.ErrorRegexp(t, r.Err(), errMsg)
r = rdb.Do(ctx, "NAMESPACE", "SET", "ns1", "token1")
util.ErrorRegexp(t, r.Err(), errMsg)
r = rdb.Do(ctx, "NAMESPACE", "DEL", "ns1")
util.ErrorRegexp(t, r.Err(), errMsg)

// Good to go after enabling namespace replication
require.NoError(t, rdb.ConfigSet(ctx, "repl-namespace-enabled", "yes").Err())
require.NoError(t, rdb.Do(ctx, "NAMESPACE", "ADD", "ns1", "token1").Err())
require.NoError(t, rdb.Do(ctx, "NAMESPACE", "SET", "ns1", "token2").Err())
require.NoError(t, rdb.Do(ctx, "NAMESPACE", "DEL", "ns1").Err())
})
}
31 changes: 21 additions & 10 deletions tests/gocase/util/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,16 @@ func StartTLSServer(t testing.TB, configs map[string]string) *KvrocksServer {
}

func StartServer(t testing.TB, configs map[string]string) *KvrocksServer {
return StartServerWithCLIOptions(t, configs, []string{})
return StartServerWithCLIOptions(t, true, configs, []string{})
}

func StartServerWithCLIOptions(t testing.TB, configs map[string]string, options []string) *KvrocksServer {
func StartServerWithCLIOptions(
t testing.TB,
withConfigFile bool,
configs map[string]string,
options []string,
) *KvrocksServer {

b := *binPath
require.NotEmpty(t, b, "please set the binary path by `-binPath`")
cmd := exec.Command(b)
Expand All @@ -215,16 +221,21 @@ func StartServerWithCLIOptions(t testing.TB, configs map[string]string, options
require.NoError(t, err)
configs["dir"] = dir

f, err := os.Create(filepath.Join(dir, "kvrocks.conf"))
require.NoError(t, err)
defer func() { require.NoError(t, f.Close()) }()

for k := range configs {
_, err := f.WriteString(fmt.Sprintf("%s %s\n", k, configs[k]))
if withConfigFile {
f, err := os.Create(filepath.Join(dir, "kvrocks.conf"))
require.NoError(t, err)
}
defer func() { require.NoError(t, f.Close()) }()

cmd.Args = append(cmd.Args, "-c", f.Name())
for k := range configs {
_, err := f.WriteString(fmt.Sprintf("%s %s\n", k, configs[k]))
require.NoError(t, err)
}
cmd.Args = append(cmd.Args, "-c", f.Name())
} else {
for k := range configs {
cmd.Args = append(cmd.Args, fmt.Sprintf("--%s", k), configs[k])
}
}
cmd.Args = append(cmd.Args, options...)

stdout, err := os.Create(filepath.Join(dir, "stdout"))
Expand Down

0 comments on commit 2b95456

Please sign in to comment.