From fbd50145fcde7ce95388c731c50a810aa10286f3 Mon Sep 17 00:00:00 2001 From: lash Date: Thu, 3 Apr 2025 03:03:26 +0100 Subject: [PATCH] Add state cloner --- cmd/africastalking/main.go | 8 ++-- cmd/async/main.go | 8 ++-- cmd/http/main.go | 8 ++-- cmd/ssh/main.go | 8 ++-- config/config.go | 3 +- devtools/admin/main.go | 7 ++- internal/cmd/cmd.go | 88 +++++++++++++++++++++++++++++++++----- profile/profile_test.go | 6 +-- ssh/ssh.go | 4 +- 9 files changed, 102 insertions(+), 38 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 3f7e372..a1f4a0e 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -77,10 +77,10 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), - MenuSeparator: menuSeparator, + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: menuSeparator, ResetOnEmptyInput: true, } diff --git a/cmd/async/main.go b/cmd/async/main.go index 9a064a6..f131605 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -92,10 +92,10 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), - MenuSeparator: menuSeparator, + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: menuSeparator, ResetOnEmptyInput: true, } diff --git a/cmd/http/main.go b/cmd/http/main.go index 13ef408..303684d 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -78,10 +78,10 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), - MenuSeparator: menuSeparator, + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), + MenuSeparator: menuSeparator, ResetOnEmptyInput: true, } diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go index 96dd150..7588531 100644 --- a/cmd/ssh/main.go +++ b/cmd/ssh/main.go @@ -38,7 +38,7 @@ func main() { var stateDebug bool var host string var port uint - + flag.StringVar(&override.DbConn, "c", "?", "default connection string (replaces all unspecified strings)") flag.StringVar(&override.ResourceConn, "resource", "?", "resource connection string") flag.StringVar(&override.UserConn, "userdata", "?", "userdata store connection string") @@ -81,9 +81,9 @@ func main() { pfp := path.Join(scriptDir, "pp.csv") cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(128), + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(128), ResetOnEmptyInput: true, } if stateDebug { diff --git a/config/config.go b/config/config.go index 863e418..cf33ffe 100644 --- a/config/config.go +++ b/config/config.go @@ -25,7 +25,7 @@ const ( defaultSSHHost string = "127.0.0.1" defaultSSHPort uint = 7122 defaultHTTPHost string = "127.0.0.1" - defaultHTTPPort uint = 7123 + defaultHTTPPort uint = 7123 defaultDomain = "sarafu.local" ) @@ -52,7 +52,6 @@ func SearchDomains() []string { return ParsedDomains } - func Language() string { return viseconfig.DefaultLanguage } diff --git a/devtools/admin/main.go b/devtools/admin/main.go index 7d42584..8c81609 100644 --- a/devtools/admin/main.go +++ b/devtools/admin/main.go @@ -7,8 +7,8 @@ import ( "os" "path" - "git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/engine" + "git.defalsify.org/vise.git/logging" "git.grassecon.net/grassrootseconomics/sarafu-vise/config" "git.grassecon.net/grassrootseconomics/sarafu-vise/handlers/application" @@ -17,8 +17,8 @@ import ( ) var ( - logg = logging.NewVanilla().WithContextKey("SessionId") - scriptDir = path.Join("services", "registration") + logg = logging.NewVanilla().WithContextKey("SessionId") + scriptDir = path.Join("services", "registration") menuSeparator = ": " ) @@ -87,5 +87,4 @@ func main() { fmt.Fprintf(os.Stderr, "cmd exec error: %v\n", err) os.Exit(1) } - } diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 5c550ea..255e270 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -3,9 +3,11 @@ package cmd import ( "context" "fmt" + "regexp" - "git.defalsify.org/vise.git/logging" + "git.defalsify.org/vise.git/db" "git.defalsify.org/vise.git/engine" + "git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" @@ -16,21 +18,24 @@ import ( var argc map[string]int = map[string]int{ "reset": 0, "admin": 1, + "clone": 1, } var ( - logg = logging.NewVanilla().WithDomain("cmd").WithContextKey("SessionId") + logg = logging.NewVanilla().WithDomain("cmd").WithContextKey("SessionId") + cloneTargetRegex = `^\+000` ) type Cmd struct { - sessionId string - conn storage.ConnData - flagParser *application.FlagManager - cmd int - enable bool - exec func(ctx context.Context, ss storage.StorageService) error - engineConfig *engine.Config - st *state.State + sessionId string + conn storage.ConnData + flagParser *application.FlagManager + cmd int + enable bool + param string + exec func(ctx context.Context, ss storage.StorageService) error + engineConfig *engine.Config + st *state.State } func NewCmd(sessionId string, flagParser *application.FlagManager) *Cmd { @@ -70,6 +75,50 @@ func (c *Cmd) engine(ctx context.Context, rs resource.Resource, pe *persist.Pers return en, nil } +func (c *Cmd) execClone(ctx context.Context, ss storage.StorageService) error { + re := regexp.MustCompile(cloneTargetRegex) + if !re.MatchString(c.param) { + return fmt.Errorf("Clone sessionId must match target: %s", c.param) + } + + pe, err := ss.GetPersister(ctx) + if err != nil { + return fmt.Errorf("get persister error: %v", err) + } + err = pe.Load(c.engineConfig.SessionId) + if err != nil { + return fmt.Errorf("persister load error: %v", err) + } + + /// TODO consider DRY with devtools/store/dump + store, err := ss.GetUserdataDb(ctx) + if err != nil { + return fmt.Errorf("store retrieve error: %v", err) + } + + store.SetSession(c.engineConfig.SessionId) + store.SetPrefix(db.DATATYPE_USERDATA) + dmp, err := store.Dump(ctx, []byte("")) + if err != nil { + return fmt.Errorf("store dump fail: %v\n", err.Error()) + } + + for true { + store.SetSession(c.engineConfig.SessionId) + k, v := dmp.Next(ctx) + if k == nil { + break + } + store.SetSession(c.param) + err = store.Put(ctx, k, v) + if err != nil { + return fmt.Errorf("user data store clone failed on key: %x", k) + } + } + + return pe.Save(c.param) +} + func (c *Cmd) execReset(ctx context.Context, ss storage.StorageService) error { pe, err := ss.GetPersister(ctx) if err != nil { @@ -157,6 +206,16 @@ func (c *Cmd) parseCmdReset(cmd string, param string, more []string) (bool, erro return false, nil } +func (c *Cmd) parseCmdClone(cmd string, param string, more []string) (bool, error) { + if cmd == "clone" { + c.enable = false + c.param = param + c.exec = c.execClone + return true, nil + } + return false, nil +} + func (c *Cmd) Parse(args []string) error { var param string if len(args) < 1 { @@ -169,7 +228,7 @@ func (c *Cmd) Parse(args []string) error { return fmt.Errorf("invalid command: %v", cmd) } if n > 0 { - if len(args) < n + 1 { + if len(args) < n+1 { return fmt.Errorf("Wrong number of arguments, need: %d", n) } param = args[1] @@ -192,6 +251,13 @@ func (c *Cmd) Parse(args []string) error { return nil } + r, err = c.parseCmdClone(cmd, param, args) + if err != nil { + return err + } + if r { + return nil + } return fmt.Errorf("unknown subcommand: %s", cmd) } diff --git a/profile/profile_test.go b/profile/profile_test.go index a210646..e8fe1b0 100644 --- a/profile/profile_test.go +++ b/profile/profile_test.go @@ -10,9 +10,9 @@ import ( func TestInsertOrShift(t *testing.T) { tests := []struct { name string - profile Profile - index int - value string + profile Profile + index int + value string expected []string }{ { diff --git a/ssh/ssh.go b/ssh/ssh.go index bab538a..f6d1dbb 100644 --- a/ssh/ssh.go +++ b/ssh/ssh.go @@ -181,8 +181,8 @@ func (s *SshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) { accountService := services.New(ctx, menuStorageService) _, err = lhs.GetHandler(accountService) if err != nil { - fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err) - os.Exit(1) + fmt.Fprintf(os.Stderr, "get accounts service handler: %v\n", err) + os.Exit(1) } en := lhs.GetEngine(lhs.Cfg, rs, pe) closer := func() {