diff --git a/docker-compose.yaml b/docker-compose.yaml index 46c4de3..cdecdb0 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -21,7 +21,7 @@ services: - TLS=false - MTLS=false - BOOTSTRAP_CLUSTER=false - - ACL_CONFIG=/etc/config/echovault/acl.yml + # - ACL_CONFIG=/etc/config/echovault/acl.yml - REQUIRE_PASS=false - PASSWORD=password1 - FORWARD_COMMAND=false @@ -44,7 +44,7 @@ services: - "7946:7946" - "7999:8000" volumes: - - ./config/acl.yml:/etc/config/echovault/acl.yml + - ./volumes/config/acl.yml:/etc/config/echovault/acl.yml - ./volumes/standalone_node:/var/lib/echovault networks: - testnet @@ -65,7 +65,7 @@ services: - TLS=false - MTLS=false - BOOTSTRAP_CLUSTER=true - - ACL_CONFIG=/etc/config/echovault/acl.yml + # - ACL_CONFIG=/etc/config/echovault/acl.yml - REQUIRE_PASS=false - FORWARD_COMMAND=true - SNAPSHOT_THRESHOLD=1000 @@ -87,7 +87,7 @@ services: - "7945:7946" - "8000:8000" volumes: - - ./config/acl.yml:/etc/config/echovault/acl.yml + - ./volumes/config/acl.yml:/etc/config/echovault/acl.yml - ./volumes/cluster_node_1:/var/lib/echovault networks: - testnet @@ -108,7 +108,7 @@ services: - TLS=false - MTLS=false - BOOTSTRAP_CLUSTER=false - - ACL_CONFIG=/etc/config/echovault/acl.yml + # - ACL_CONFIG=/etc/config/echovault/acl.yml - REQUIRE_PASS=false - FORWARD_COMMAND=true - SNAPSHOT_THRESHOLD=1000 @@ -130,7 +130,7 @@ services: - "7947:7946" - "8001:8000" volumes: - - ./config/acl.yml:/etc/config/echovault/acl.yml + - ./volumes/config/acl.yml:/etc/config/echovault/acl.yml - ./volumes/cluster_node_2:/var/lib/echovault networks: - testnet @@ -151,7 +151,7 @@ services: - TLS=false - MTLS=false - BOOTSTRAP_CLUSTER=false - - ACL_CONFIG=/etc/config/echovault/acl.yml + # - ACL_CONFIG=/etc/config/echovault/acl.yml - REQUIRE_PASS=false - FORWARD_COMMAND=true - SNAPSHOT_THRESHOLD=1000 @@ -173,7 +173,7 @@ services: - "7948:7946" - "8002:8000" volumes: - - ./config/acl.yml:/etc/config/echovault/acl.yml + - ./volumes/config/acl.yml:/etc/config/echovault/acl.yml - ./volumes/cluster_node_3:/var/lib/echovault networks: - testnet @@ -194,7 +194,7 @@ services: - TLS=false - MTLS=false - BOOTSTRAP_CLUSTER=false - - ACL_CONFIG=/etc/config/echovault/acl.yml + # - ACL_CONFIG=/etc/config/echovault/acl.yml - REQUIRE_PASS=false - FORWARD_COMMAND=true - SNAPSHOT_THRESHOLD=1000 @@ -216,7 +216,7 @@ services: - "7949:7946" - "8003:8000" volumes: - - ./config/acl.yml:/etc/config/echovault/acl.yml + - ./volumes/config/acl.yml:/etc/config/echovault/acl.yml - ./volumes/cluster_node_4:/var/lib/echovault networks: - testnet @@ -237,7 +237,7 @@ services: - TLS=false - MTLS=false - BOOTSTRAP_CLUSTER=false - - ACL_CONFIG=/etc/config/echovault/acl.yml + # - ACL_CONFIG=/etc/config/echovault/acl.yml - REQUIRE_PASS=false - FORWARD_COMMAND=true - SNAPSHOT_THRESHOLD=1000 @@ -259,7 +259,7 @@ services: - "7950:7946" - "8004:8000" volumes: - - ./config/acl.yml:/etc/config/echovault/acl.yml + - ./volumes/config/acl.yml:/etc/config/echovault/acl.yml - ./volumes/cluster_node_5:/var/lib/echovault networks: - testnet \ No newline at end of file diff --git a/pkg/echovault/api_admin.go b/pkg/echovault/api_admin.go index 8e248bf..9c730ed 100644 --- a/pkg/echovault/api_admin.go +++ b/pkg/echovault/api_admin.go @@ -14,7 +14,12 @@ package echovault -import "github.com/echovault/echovault/internal" +import ( + "fmt" + "github.com/echovault/echovault/internal" + "github.com/echovault/echovault/pkg/types" + "strings" +) // CommandListOptions modifies the result from the COMMAND_LIST command. // @@ -29,6 +34,17 @@ type CommandListOptions struct { MODULE string } +// TODO: Add description for CommandOptions type +type CommandOptions struct { + Command string + Module string + Categories []string + Description string + Sync bool + KeyExtractionFunc types.PluginKeyExtractionFunc + HandlerFunc types.PluginHandlerFunc +} + // COMMAND_LIST returns the list of commands currently loaded in the EchoVault instance. // // Parameters: @@ -93,3 +109,58 @@ func (server *EchoVault) REWRITEAOF() (string, error) { } return internal.ParseStringResponse(b) } + +// TODO: Add description for ADD_COMMAND method +func (server *EchoVault) ADD_COMMAND(command CommandOptions) error { + // Check if commands already exists + for _, c := range server.commands { + if strings.EqualFold(c.Command, command.Command) { + return fmt.Errorf("command %s already exists", command.Command) + } + } + server.commands = append(server.commands, internal.Command{ + Command: command.Command, + Module: strings.ToLower(command.Module), // Convert module to lower case for uniformity + Categories: func() []string { + // Convert all the categories to lower case for uniformity + cats := make([]string, len(command.Categories)) + for i, cat := range command.Categories { + cats[i] = strings.ToLower(cat) + } + return cats + }(), + Description: command.Description, + Sync: command.Sync, + KeyExtractionFunc: internal.KeyExtractionFunc(func(cmd []string) (internal.AccessKeys, error) { + accessKeys, err := command.KeyExtractionFunc(cmd) + if err != nil { + return internal.AccessKeys{}, err + } + return internal.AccessKeys{ + Channels: []string{}, + ReadKeys: accessKeys.ReadKeys, + WriteKeys: accessKeys.WriteKeys, + }, nil + }), + HandlerFunc: internal.HandlerFunc(func(params internal.HandlerFuncParams) ([]byte, error) { + return command.HandlerFunc(types.PluginHandlerFuncParams{ + Context: params.Context, + Command: params.Command, + Connection: params.Connection, + KeyLock: params.KeyLock, + KeyUnlock: params.KeyUnlock, + KeyRLock: params.KeyRLock, + KeyRUnlock: params.KeyRUnlock, + KeyExists: params.KeyExists, + CreateKeyAndLock: params.CreateKeyAndLock, + GetValue: params.GetValue, + SetValue: params.SetValue, + GetExpiry: params.GetExpiry, + SetExpiry: params.SetExpiry, + RemoveExpiry: params.RemoveExpiry, + DeleteKey: params.DeleteKey, + }) + }), + }) + return nil +} diff --git a/pkg/types/types.go b/pkg/types/types.go index 2b4f46c..4f20a3d 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -16,6 +16,7 @@ package types import ( "context" + "net" "time" ) @@ -33,3 +34,28 @@ type EchoVault interface { RemoveExpiry(ctx context.Context, key string) DeleteKey(ctx context.Context, key string) error } + +type PluginAccessKeys struct { + ReadKeys []string + WriteKeys []string +} +type PluginKeyExtractionFunc func(cmd []string) (PluginAccessKeys, error) + +type PluginHandlerFunc func(params PluginHandlerFuncParams) ([]byte, error) +type PluginHandlerFuncParams struct { + Context context.Context + Command []string + Connection *net.Conn + KeyLock func(ctx context.Context, key string) (bool, error) + KeyUnlock func(ctx context.Context, key string) + KeyRLock func(ctx context.Context, key string) (bool, error) + KeyRUnlock func(ctx context.Context, key string) + KeyExists func(ctx context.Context, key string) bool + CreateKeyAndLock func(ctx context.Context, key string) (bool, error) + GetValue func(ctx context.Context, key string) interface{} + SetValue func(ctx context.Context, key string, value interface{}) error + GetExpiry func(ctx context.Context, key string) time.Time + SetExpiry func(ctx context.Context, key string, expire time.Time, touch bool) + RemoveExpiry func(ctx context.Context, key string) + DeleteKey func(ctx context.Context, key string) error +}