From 73aace219d12acbc44f72007ed742e256d5ef081 Mon Sep 17 00:00:00 2001 From: Mantas Date: Fri, 16 Feb 2024 18:13:52 +0200 Subject: [PATCH 01/16] wip ingress fix --- internal/actions/ingress_fix.go | 91 ++++++++++++++++++++++++++++ internal/actions/swarm.go | 103 ++++++++++++++++++++++++++++++-- internal/cmd/main.go | 5 ++ 3 files changed, 194 insertions(+), 5 deletions(-) create mode 100644 internal/actions/ingress_fix.go diff --git a/internal/actions/ingress_fix.go b/internal/actions/ingress_fix.go new file mode 100644 index 0000000..413736e --- /dev/null +++ b/internal/actions/ingress_fix.go @@ -0,0 +1,91 @@ +package actions + +import ( + "fmt" + "strconv" + "sync" + "time" + + "github.com/D8-X/d8x-cli/internal/conn" + "github.com/D8-X/d8x-cli/internal/styles" + "github.com/urfave/cli/v2" +) + +func (c *Container) IngressFix(ctx *cli.Context) error { + pwd, err := c.GetPassword(ctx) + if err != nil { + return err + } + + // Remove the ingress on manager + ip, err := c.HostsCfg.GetMangerPublicIp() + if err != nil { + return err + } + managerConn, err := conn.NewSSHConnection(ip, c.DefaultClusterUserName, c.SshKeyPath) + if err != nil { + return err + } + + // Remove the stack and ingress network + fmt.Println("Removing stack and ingress network") + if _, err := managerConn.ExecCommand( + fmt.Sprintf("docker stack rm %s && yes | docker network rm ingress -f", dockerStackName), + ); err != nil { + return fmt.Errorf("removing stack and ingress network: %w", err) + } else { + fmt.Println(styles.SuccessText.Render("Successfully removed stack and ingress network")) + } + + fmt.Println("Recreating ingress network") + time.Sleep(5 * time.Second) + // Recreate ingress + if _, err := managerConn.ExecCommand("docker network create -d overlay --subnet 172.16.1.0/24 --ingress ingress"); err != nil { + return fmt.Errorf("recreating ingress network: %w", err) + } else { + fmt.Println(styles.SuccessText.Render("Successfully recreated ingress network")) + } + + fmt.Println("Restarting docker daemons") + + // Restart the manager's docker + if _, err := managerConn.ExecCommand( + fmt.Sprintf(`echo "%s"| sudo -S systemctl restart docker`, pwd), + ); err != nil { + return fmt.Errorf("restarting manager's docker: %w", err) + } else { + fmt.Println(styles.SuccessText.Render("Successfully restarted docker on manager")) + } + + workerIps, err := c.HostsCfg.GetWorkerIps() + if err != nil { + return err + } + + // Reboot all workers + wg := sync.WaitGroup{} + for n, ip := range workerIps { + n := n + wg.Add(1) + go func(ip string) { + workerNum := n + 1 + defer wg.Done() + workerConn, err := conn.NewSSHConnectionWithBastion(managerConn.GetClient(), ip, c.DefaultClusterUserName, c.SshKeyPath) + if err != nil { + info := fmt.Sprintf("creating ssh connection to worker-%d %s: %s", workerNum, ip, err.Error()) + fmt.Println(styles.ErrorText.Render(info)) + } + + if _, err := workerConn.ExecCommand( + fmt.Sprintf(`echo "%s"| sudo -S systemctl restart docker`, pwd), + ); err != nil { + return + } else { + fmt.Println(styles.SuccessText.Render("Successfully restarted docker on worker-" + strconv.Itoa(workerNum))) + } + }(ip) + } + wg.Wait() + + return nil +} diff --git a/internal/actions/swarm.go b/internal/actions/swarm.go index 8c6840c..f9671c7 100644 --- a/internal/actions/swarm.go +++ b/internal/actions/swarm.go @@ -1,6 +1,7 @@ package actions import ( + "encoding/json" "fmt" "os" "os/exec" @@ -129,6 +130,46 @@ func (c *Container) CopySwarmDeployConfigs() error { func (c *Container) SwarmDeploy(ctx *cli.Context) error { styles.PrintCommandTitle("Starting swarm cluster deployment...") + if err := c.swarmDeploy(ctx, true); err != nil { + return err + } + + // After swarm deployment is completed, check if ingress network is working + // correctly on manager. Repeat for 2 times max + ingressWorks := false + for i := 0; i < 2; i++ { + fmt.Printf("Checking ingress network on manager... (attempt %d/2)\n", i+1) + err := c.CheckSwarmIngressIsCorrect(ctx) + if err != nil { + fmt.Println(styles.ErrorText.Render(err.Error())) + if err := c.IngressFix(ctx); err != nil { + fmt.Println(styles.SuccessText.Render(fmt.Sprintf("Ingress network fix failed: %s\n", err.Error()))) + continue + } + + // Redeploy the swarm after ingress fix + if err := c.swarmDeploy(ctx, false); err != nil { + return err + } + + } else { + fmt.Println(styles.SuccessText.Render("Ingress network is working correctly on manager")) + ingressWorks = true + break + } + } + + if !ingressWorks { + fmt.Println(styles.ErrorText.Render("Ingress network is not working correctly on manager")) + fmt.Println("Automatic fix failed, please try to run fix-ingress and setup swarm-deploy manually") + } + + return nil +} + +// swarmDeploy performs the swarm deployment step +func (c *Container) swarmDeploy(ctx *cli.Context, showConfigConfirmation bool) error { + // Find manager ip before we start collecting data in case manager is not // available. managerIp, err := c.HostsCfg.GetMangerPublicIp() @@ -233,12 +274,14 @@ func (c *Container) SwarmDeploy(ctx *cli.Context) error { return fmt.Errorf("temp storage of keyfile failed: %w", err) } - fmt.Println(styles.AlertImportant.Render("Please verify your .env and configuration files are correct before proceeding.")) - fmt.Println("The following configuration files will be copied to the 'manager node' for the d8x-trader-backend swarm deployment:") - for _, f := range swarmDeployConfigFilesToCopy[:6] { - fmt.Println(f.Dst) + if showConfigConfirmation { + fmt.Println(styles.AlertImportant.Render("Please verify your .env and configuration files are correct before proceeding.")) + fmt.Println("The following configuration files will be copied to the 'manager node' for the d8x-trader-backend swarm deployment:") + for _, f := range swarmDeployConfigFilesToCopy[:6] { + fmt.Println(f.Dst) + } + c.TUI.NewConfirmation("Press enter to confirm that the configuration files listed above are good to go...") } - c.TUI.NewConfirmation("Press enter to confirm that the configuration files listed above are good to go...") pwd, err := c.GetPassword(ctx) if err != nil { @@ -665,3 +708,53 @@ var hostsTpl = []hostnameTuple{ serviceName: configs.D8XServiceCandlesWs, }, } + +type NameIp struct { + Name string `json:"name"` + IP string `json:"IP"` +} + +// CheckSwarmIngressIsCorrect checks if swarm manager's ingress network +// configuration contains worker servers as peers and is in correct state +func (c *Container) CheckSwarmIngressIsCorrect(ctx *cli.Context) error { + // Check if ingress's peers property contains all the workers on manager + managerIp, err := c.HostsCfg.GetMangerPublicIp() + if err != nil { + return err + } + managerConn, err := conn.NewSSHConnection(managerIp, c.DefaultClusterUserName, c.SshKeyPath) + if err != nil { + return err + } + + out, err := managerConn.ExecCommand(`docker network inspect -f "{{json .Peers}}" ingress`) + if err != nil { + return err + } + peers := []NameIp{} + if err := json.Unmarshal([]byte(out), &peers); err != nil { + return fmt.Errorf("parsing docker network inspect output: %w", err) + } + + // Check if all workers are present in peers list + workerIps, err := c.HostsCfg.GetWorkerPrivateIps() + if err != nil { + return err + } + + for _, workerIp := range workerIps { + found := false + for _, peer := range peers { + if workerIp == peer.IP { + found = true + break + } + } + + if !found { + return fmt.Errorf("worker with IP %s is not present in ingress network peers", workerIp) + } + } + + return nil +} diff --git a/internal/cmd/main.go b/internal/cmd/main.go index 8e7ab4f..287fec5 100644 --- a/internal/cmd/main.go +++ b/internal/cmd/main.go @@ -201,6 +201,11 @@ func RunD8XCli() { ArgsUsage: "[local port 5432]", Description: "Create a ssh tunnel to database server. Database credentials are read from d8x.conf.json file.", }, + { + Name: "fix-ingress", + Usage: "Fix faulty ingress network", + Action: container.IngressFix, + }, }, // Global flags accessible to all subcommands Flags: []cli.Flag{ From 844b4c00bb702ad7abc3e91fdd604d8dace642e6 Mon Sep 17 00:00:00 2001 From: Mantas Date: Mon, 19 Feb 2024 14:57:16 +0200 Subject: [PATCH 02/16] add ingress-fix docs --- README.md | 8 ++++++++ internal/actions/ingress_fix.go | 10 +++++++++- internal/actions/swarm.go | 1 + 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a69b79..c643498 100644 --- a/README.md +++ b/README.md @@ -369,6 +369,14 @@ On the broker server, inspect the services with `docker ps` and look at the log files with `cd broker` and `docker compose logs -f`. Redeploy changed configs via `d8x setup broker-deploy` +Sometimes swarm cluster deployment ingress network can get stuck on manager +server. This might result in HTTP 503 errors or `Connection refused` message +when trying to curl swarm services on manager server. To fix this you can re-run +`d8x setup swarm-deploy` command which attempts to fix "broker" ingress network +after deploying swarm services. There is also individual subcommand `d8x +fix-ingress` which does only the ingress network fixing part, but requires to +rerun `swarm-deploy` command afterwards. +
How do I update the swarm server software images to a new version? diff --git a/internal/actions/ingress_fix.go b/internal/actions/ingress_fix.go index 413736e..a6d2ffe 100644 --- a/internal/actions/ingress_fix.go +++ b/internal/actions/ingress_fix.go @@ -11,6 +11,10 @@ import ( "github.com/urfave/cli/v2" ) +// IngressFix fixes non-working ingress network on manager. Steps to fix ingress +// (in order) are: remove any existing stacks; remove ingress on manager; +// recreate ingress on manager; reboot manager's docker; reboot all workers' +// docker. func (c *Container) IngressFix(ctx *cli.Context) error { pwd, err := c.GetPassword(ctx) if err != nil { @@ -39,7 +43,7 @@ func (c *Container) IngressFix(ctx *cli.Context) error { fmt.Println("Recreating ingress network") time.Sleep(5 * time.Second) - // Recreate ingress + // Recreate ingress. Make sure subnet is the same as in setup playbook if _, err := managerConn.ExecCommand("docker network create -d overlay --subnet 172.16.1.0/24 --ingress ingress"); err != nil { return fmt.Errorf("recreating ingress network: %w", err) } else { @@ -87,5 +91,9 @@ func (c *Container) IngressFix(ctx *cli.Context) error { } wg.Wait() + if ctx.Command.Name == "fix-ingress" { + fmt.Println("Make sure you re-run d8x setup swarm-deploy to re-deploy the services") + } + return nil } diff --git a/internal/actions/swarm.go b/internal/actions/swarm.go index f9671c7..286cbee 100644 --- a/internal/actions/swarm.go +++ b/internal/actions/swarm.go @@ -148,6 +148,7 @@ func (c *Container) SwarmDeploy(ctx *cli.Context) error { } // Redeploy the swarm after ingress fix + fmt.Println(styles.ItalicText.Render("Redeploying swarm services after ingress fix...")) if err := c.swarmDeploy(ctx, false); err != nil { return err } From 5192b56db8132ca2ed0162edef8baa095d01a67a Mon Sep 17 00:00:00 2001 From: Mantas Date: Sun, 3 Mar 2024 17:52:47 +0200 Subject: [PATCH 03/16] add berchain configs --- .../embedded/broker-server/chainConfig.json | 7 +++++++ .../configs/embedded/broker-server/rpc.json | 4 ++++ .../configs/embedded/trader-backend/chain.json | 7 +++++++ .../trader-backend/live.referralSettings.json | 17 +++++++++++++++++ .../embedded/trader-backend/rpc.history.json | 11 +++++++++-- .../embedded/trader-backend/rpc.main.json | 5 +++++ .../embedded/trader-backend/rpc.referral.json | 5 +++++ 7 files changed, 54 insertions(+), 2 deletions(-) diff --git a/internal/configs/embedded/broker-server/chainConfig.json b/internal/configs/embedded/broker-server/chainConfig.json index f9b6f74..900657b 100644 --- a/internal/configs/embedded/broker-server/chainConfig.json +++ b/internal/configs/embedded/broker-server/chainConfig.json @@ -33,5 +33,12 @@ "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", "multiPayCtrctAddr": "0x60Eba5B5ba7Bd4694886CC5ecc0642D6178c2c86", "allowedExecutors": [] + }, + { + "chainId": 80085, + "name": "artio", + "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", + "multiPayCtrctAddr": "0xDa7f988605Abe824dF767Aa583d8fD60f09E23D0", + "allowedExecutors": [] } ] diff --git a/internal/configs/embedded/broker-server/rpc.json b/internal/configs/embedded/broker-server/rpc.json index 2a1f744..8d1c013 100644 --- a/internal/configs/embedded/broker-server/rpc.json +++ b/internal/configs/embedded/broker-server/rpc.json @@ -21,5 +21,9 @@ "https://sepolia-rollup.arbitrum.io/rpc", "https://arbitrum-sepolia.blockpi.network/v1/rpc/public" ] + }, + { + "chainId": 80085, + "HTTP": ["https://rpc.ankr.com/berachain_testnet"] } ] diff --git a/internal/configs/embedded/trader-backend/chain.json b/internal/configs/embedded/trader-backend/chain.json index 923f42a..4dc1263 100644 --- a/internal/configs/embedded/trader-backend/chain.json +++ b/internal/configs/embedded/trader-backend/chain.json @@ -34,6 +34,13 @@ "priceServiceWSEndpoint": "wss://hermes.pyth.network/ws", "priceServiceHTTPSEndpoint": "" }, + "80085": { + "type": "mainnet", + "sdkNetwork": "artio", + "priceFeedNetwork": "mainnet", + "priceServiceWSEndpoint": "wss://hermes.pyth.network/ws", + "priceServiceHTTPSEndpoint": "https://odin.quantena.tech/api" + }, "default": { "type": "mainnet", "sdkNetwork": "zkevm", diff --git a/internal/configs/embedded/trader-backend/live.referralSettings.json b/internal/configs/embedded/trader-backend/live.referralSettings.json index d2bcf3d..45a2ac7 100644 --- a/internal/configs/embedded/trader-backend/live.referralSettings.json +++ b/internal/configs/embedded/trader-backend/live.referralSettings.json @@ -83,5 +83,22 @@ [3.75, 10000] ], "brokerPayoutAddr": "0x9d5aaB428e98678d0E645ea4AeBd25f744341a05" + }, + { + "chainId": 80085, + "paymentMaxLookBackDays": 14, + "paymentScheduleCron": "0 08 * * 2", + "multiPayContractAddr": "0xDa7f988605Abe824dF767Aa583d8fD60f09E23D0", + "tokenX": { + "address": "0x9a1E6C2f81bE72Af2C4138Bbec3d9029516f27a6", + "decimals": 18 + }, + "referrerCutPercentForTokenXHolding": [ + [0.2, 0], + [1.5, 100], + [2.5, 1000], + [3.75, 10000] + ], + "brokerPayoutAddr": "0x9d5aaB428e98678d0E645ea4AeBd25f744341a05" } ] diff --git a/internal/configs/embedded/trader-backend/rpc.history.json b/internal/configs/embedded/trader-backend/rpc.history.json index 70cccc9..88816d4 100644 --- a/internal/configs/embedded/trader-backend/rpc.history.json +++ b/internal/configs/embedded/trader-backend/rpc.history.json @@ -16,13 +16,20 @@ }, { "chainId": 2442, - "HTTP": ["https://rpc.cardona.zkevm-rpc.com"] + "HTTP": ["https://rpc.cardona.zkevm-rpc.com"], + "WS": [] }, { "chainId": 421614, "HTTP": [ "https://sepolia-rollup.arbitrum.io/rpc", "https://arbitrum-sepolia.blockpi.network/v1/rpc/public" - ] + ], + "WS": [] + }, + { + "chainId": 80085, + "HTTP": ["https://rpc.ankr.com/berachain_testnet"], + "WS": [] } ] diff --git a/internal/configs/embedded/trader-backend/rpc.main.json b/internal/configs/embedded/trader-backend/rpc.main.json index 70cccc9..318c121 100644 --- a/internal/configs/embedded/trader-backend/rpc.main.json +++ b/internal/configs/embedded/trader-backend/rpc.main.json @@ -24,5 +24,10 @@ "https://sepolia-rollup.arbitrum.io/rpc", "https://arbitrum-sepolia.blockpi.network/v1/rpc/public" ] + }, + { + "chainId": 80085, + "HTTP": ["https://rpc.ankr.com/berachain_testnet"], + "WS": [] } ] diff --git a/internal/configs/embedded/trader-backend/rpc.referral.json b/internal/configs/embedded/trader-backend/rpc.referral.json index 70cccc9..318c121 100644 --- a/internal/configs/embedded/trader-backend/rpc.referral.json +++ b/internal/configs/embedded/trader-backend/rpc.referral.json @@ -24,5 +24,10 @@ "https://sepolia-rollup.arbitrum.io/rpc", "https://arbitrum-sepolia.blockpi.network/v1/rpc/public" ] + }, + { + "chainId": 80085, + "HTTP": ["https://rpc.ankr.com/berachain_testnet"], + "WS": [] } ] From ded0967e8df183430e04fccb2f48319c80367b27 Mon Sep 17 00:00:00 2001 From: Mantas Date: Tue, 12 Mar 2024 11:47:53 +0200 Subject: [PATCH 04/16] sort chain selection --- internal/actions/input.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/actions/input.go b/internal/actions/input.go index 4ac9f14..59782ec 100644 --- a/internal/actions/input.go +++ b/internal/actions/input.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "os/exec" + "sort" "strconv" "strings" @@ -772,6 +773,12 @@ func (c *InputCollector) GetChainId(cfg *configs.D8XConfig, ctx *cli.Context) (u chainSelection = append(chainSelection, chainName) } + // Sort chains by name so we always have consistent order in the + // selection + sort.Slice(chainSelection, func(i, j int) bool { + return chainSelection[i] < chainSelection[j] + }) + chains, err := c.TUI.NewSelection(chainSelection, components.SelectionOptAllowOnlySingleItem(), components.SelectionOptRequireSelection()) if err != nil { return 0, err From 39bb409104f1ca414dfd75cc79aafd24c1fb6395 Mon Sep 17 00:00:00 2001 From: b1674927 <117123379+b1674927@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:02:03 +0800 Subject: [PATCH 05/16] Update live.referralSettings.json correct multipay addr --- .../configs/embedded/trader-backend/live.referralSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configs/embedded/trader-backend/live.referralSettings.json b/internal/configs/embedded/trader-backend/live.referralSettings.json index 45a2ac7..4d12e76 100644 --- a/internal/configs/embedded/trader-backend/live.referralSettings.json +++ b/internal/configs/embedded/trader-backend/live.referralSettings.json @@ -54,7 +54,7 @@ "chainId": 421614, "paymentMaxLookBackDays": 14, "paymentScheduleCron": "0 08 * * 2", - "multiPayContractAddr": "0x60Eba5B5ba7Bd4694886CC5ecc0642D6178c2c86", + "multiPayContractAddr": "0x35672963523bc874f13da5CeED024249794E6a16", "tokenX": { "address": "0x9a1E6C2f81bE72Af2C4138Bbec3d9029516f27a6", "decimals": 18 From b94290720471d1ea9fc94e7b32901d3df66fa5a7 Mon Sep 17 00:00:00 2001 From: b1674927 <117123379+b1674927@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:48:18 +0800 Subject: [PATCH 06/16] Update chainConfig.json fix multipay addr --- internal/configs/embedded/broker-server/chainConfig.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configs/embedded/broker-server/chainConfig.json b/internal/configs/embedded/broker-server/chainConfig.json index 900657b..e103b86 100644 --- a/internal/configs/embedded/broker-server/chainConfig.json +++ b/internal/configs/embedded/broker-server/chainConfig.json @@ -31,7 +31,7 @@ "chainId": 421614, "name": "arbitrumSepolia", "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", - "multiPayCtrctAddr": "0x60Eba5B5ba7Bd4694886CC5ecc0642D6178c2c86", + "multiPayCtrctAddr": "0x35672963523bc874f13da5CeED024249794E6a16", "allowedExecutors": [] }, { From 27841d0ce3fb59acbf607c0ad86bbef6eb413a50 Mon Sep 17 00:00:00 2001 From: Mantas Date: Tue, 12 Mar 2024 13:04:44 +0200 Subject: [PATCH 07/16] add chain id for error msg --- internal/actions/swarm.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/actions/swarm.go b/internal/actions/swarm.go index 286cbee..a3cd767 100644 --- a/internal/actions/swarm.go +++ b/internal/actions/swarm.go @@ -262,9 +262,10 @@ func (c *Container) swarmDeploy(ctx *cli.Context, showConfigConfirmation bool) e } } if !matchFound { + // Allowed executor was either different or not found for selected chain fmt.Println( styles.ErrorText.Render( - "provided referral executor address did not match any allowedExecutor address in ./broker-server/chainConfig.json", + "provided referral executor address did not match any allowedExecutor address for chain id" + strconv.Itoa(int(cfg.ChainId)) + " in ./broker-server/chainConfig.json", ), ) } From 1586c88f735080db078070ec2e2fc157a9210487 Mon Sep 17 00:00:00 2001 From: Mantas Date: Wed, 13 Mar 2024 11:07:02 +0200 Subject: [PATCH 08/16] add update runbook --- UPDATE_RUNBOOK.md | 97 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 UPDATE_RUNBOOK.md diff --git a/UPDATE_RUNBOOK.md b/UPDATE_RUNBOOK.md new file mode 100644 index 0000000..8f98260 --- /dev/null +++ b/UPDATE_RUNBOOK.md @@ -0,0 +1,97 @@ +# Updating your d8x services + +When updating your d8x swarm and broker services, we recommend performing a +database backup before running the actual updates. If you make a backup, if something goes wrong, you will still have the database that can be used to restore the state of your previous deployments. Making a backup is also useful when significant contract changes are introduced, for example changes in events (around beginning of March in 2024). + +The following runbook will guide how to perform a database backup and update your services. + +Follow this runbook from top to bottom. + +## Running the database backup + +Refer to the [Database Backups](./README.md#database-backups) on more details about how to perform a database backup. + +First, you should run the `d8x backup-db` command: + +```bash +d8x backup-db +``` + +Will result with output similar to the following: +```bash +┌──────────────────────────┐ +│ ____ ___ __ __ │ +│ | _ \ ( _ ) \ \/ / │ +│ | | | | / _ \ \ / │ +│ | |_| | | (_) | / \ │ +│ |____/ \___/ /_/\_\ │ +│ │ +└──────────────────────────┘ +Backing up database... + +Determining postgres version +Postgres server at lin-55017-35110-pgsql-primary-private.servers.linodedb.net version: 14.6 +Ensuring pg_dump is installed on manager server (postgresql-client-16) +Creating database testing_db backup +Backup file size: 0.023752 MB +Database testing_db backup file was downloaded and copied to /home/mantas/work/d8x-cli/build/backup-d8x-cluster-testing-linode-2024-03-12-17-36-36.dump.sql +Removing backup file from server +``` + +Make sure you securely store the backup file. + +## Running the update for specific or all services + +Refer to [Readme](./README.md) for more information about the `d8x update` command. + +Run `d8x update` and select the service(s) you want to update. Depending on +which services are updated, you might be asked to enter private keys or other +information. + +```bash +d8x update +``` + +```bash +Updating swarm services... + +Select swarm services to update + + [x] api + [ ] candles-pyth-client + [ ] candles-ws-server + [x] history + [ ] referral +╭────────╮ +│ OK │ +╰────────╯ +Select broker-server services to update + + [ ] broker + [ ] executorws +╭────────╮ +│ OK │ +╰────────╯ +Pruning unused resources on worker servers... +Running docker prune on worker-1: +<...> +Updating service api +Choose which image reference to update to + + [ ] ghcr.io/d8-x/d8x-trader-main:main@sha256:ac06805f6be51a83e21dfa78d9d27ec425d169623f16ffa43484792a48d8a016 + [x] ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 + [ ] Enter image reference manually +╭────────╮ +│ OK │ +╰────────╯ +Using image: ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 +Updating api to ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 +stack_api +overall progress: 2 out of 2 tasks +1/2: running +2/2: running +verify: Service converged +Service api updated successfully +<...> +``` + From cb61a4526689047ef17daab28ebcf6ba8aa261f3 Mon Sep 17 00:00:00 2001 From: Mantas Date: Thu, 14 Mar 2024 00:10:37 +0200 Subject: [PATCH 09/16] more efficient svc update --- internal/actions/svc_update.go | 131 +++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 55 deletions(-) diff --git a/internal/actions/svc_update.go b/internal/actions/svc_update.go index 5e61e21..cdf4b63 100644 --- a/internal/actions/svc_update.go +++ b/internal/actions/svc_update.go @@ -6,6 +6,7 @@ import ( "net/http" "sort" "strings" + "sync" "time" "github.com/D8-X/d8x-cli/internal/components" @@ -81,51 +82,46 @@ func (c *Container) updateSwarmServices(ctx *cli.Context, selectedSwarmServicesT return nil } - workerIps, err := c.HostsCfg.GetWorkerIps() - if err != nil { - return err - } - - fmt.Println("Pruning unused resources on worker servers...") - if err := c.PurgeWorkers(workerIps); err != nil { - return err + // Collect the sha hashes for selected services + svcTagsWithShaHashes := map[string][]string{} + wg := sync.WaitGroup{} + for _, svcToUpdate := range selectedSwarmServicesToUpdate { + wg.Add(1) + go func(svcToUpdate string) { + fmt.Println("Fetching image tags with sha hashes for service " + svcToUpdate) + img := services[svcToUpdate].Image + tags, err := getTagsWithHashes(svcToUpdate, img) + // Just print the error if tags cannot be fetched/parsed + if err != nil { + fmt.Println(styles.ErrorText.Render(fmt.Sprintf("Could not get tags for %s: %s", img, err.Error()))) + } else { + fmt.Println(styles.SuccessText.Render(fmt.Sprintf("Image tags fetched for service %s", img))) + svcTagsWithShaHashes[svcToUpdate] = tags + } + wg.Done() + }(svcToUpdate) } + wg.Wait() - password, err := c.GetPassword(ctx) - if err != nil { - return err - } - managerIp, err := c.HostsCfg.GetMangerPublicIp() - if err != nil { - return err - } - sshConn, err := conn.NewSSHConnection(managerIp, c.DefaultClusterUserName, c.SshKeyPath) - if err != nil { - return err - } + // Prompt user to enter referral executor key whenever we update referral + // service. + referralExecutorKey := "" + // Prompt user to select the tags to use for updating services. Use image + // tags with hashes fetched from github but also allow to enter the image + // reference manually + enterManuallyOption := "Enter image reference manually" + selectedImageReferenceForUpdate := map[string]string{} for _, svcToUpdate := range selectedSwarmServicesToUpdate { - fmt.Printf("Updating service %s\n", svcToUpdate) - img := services[svcToUpdate].Image - tags, err := getTagsWithHashes(svcToUpdate, img) - // If tags cannot be fetched - show error, but do not exit the update - // process, since this is only local error on users' machine - if err != nil { - fmt.Println(styles.ErrorText.Render(fmt.Sprintf("Could not get tags for %s: %s\n", img, err.Error()))) - tags = []string{} - } - - // Show selection of available tags (with latest sha hashes whenever - // possible) to update to - enterManuallyOption := "Enter image reference manually" - imagesSelection := make([]string, len(tags)) - for i, tag := range tags { - imagesSelection[i] = img + ":" + tag + imagesSelection := svcTagsWithShaHashes[svcToUpdate] + // Append the image url + for i, tagHash := range imagesSelection { + imagesSelection[i] = img + ":" + tagHash } - // Manual entry option imagesSelection = append(imagesSelection, enterManuallyOption) - fmt.Println("Choose which image reference to update to") + + fmt.Printf("\nChoose which image reference to update %s service to\n", svcToUpdate) selectedImageToUpdate, err := c.TUI.NewSelection( imagesSelection, components.SelectionOptAllowOnlySingleItem(), @@ -136,9 +132,8 @@ func (c *Container) updateSwarmServices(ctx *cli.Context, selectedSwarmServicesT } imgToUse := selectedImageToUpdate[0] - if imgToUse != enterManuallyOption { - fmt.Printf("Using image: %s\n", selectedImageToUpdate[0]) + fmt.Printf("Service %s will be updated to %s\n", svcToUpdate, imgToUse) } else { fmt.Printf("Provide a full path to image with tag (or optionally sha256 hash) to update to\n") info := "When providing a specific sha version, follow the following format:\nghcr.io/d8-x/@sha256:\n" @@ -157,12 +152,51 @@ func (c *Container) updateSwarmServices(ctx *cli.Context, selectedSwarmServicesT imgToUse = enteredImage } + selectedImageReferenceForUpdate[svcToUpdate] = imgToUse + + // Collect private key for referral service + if svcToUpdate == "referral" { + executorkey, _, err := c.Input.CollectAndValidatePrivateKey("Enter your referral payment executor private key:") + if err != nil { + return err + } + referralExecutorKey = "0x" + strings.TrimPrefix(executorkey, "0x") + } + + } + + workerIps, err := c.HostsCfg.GetWorkerIps() + if err != nil { + return err + } + + fmt.Println("Pruning unused resources on worker servers...") + if err := c.PurgeWorkers(workerIps); err != nil { + return err + } + + password, err := c.GetPassword(ctx) + if err != nil { + return err + } + managerIp, err := c.HostsCfg.GetMangerPublicIp() + if err != nil { + return err + } + sshConn, err := conn.NewSSHConnection(managerIp, c.DefaultClusterUserName, c.SshKeyPath) + if err != nil { + return err + } + + for _, svcToUpdate := range selectedSwarmServicesToUpdate { + imgToUse := selectedImageReferenceForUpdate[svcToUpdate] + fmt.Printf("Updating %s to %s\n", svcToUpdate, imgToUse) + // For referral system - we need to update the referral executor private // key, since the new version will have different encryption key and // keyfile.txt will be reencrypted // var oldKeyfile string = "" if svcToUpdate == "referral" { - // Remove existing referral service fmt.Println("Scaling down referral service") if err := sshConn.ExecCommandPiped( @@ -179,19 +213,8 @@ func (c *Container) updateSwarmServices(ctx *cli.Context, selectedSwarmServicesT if err != nil { return err } - - fmt.Println("Enter your referral payment executor private key:") - executorkey, err := c.TUI.NewInput( - components.TextInputOptPlaceholder(""), - components.TextInputOptMasked(), - ) - if err != nil { - return err - } - executorkey = "0x" + strings.TrimPrefix(executorkey, "0x") - // Write new keyfile - out, err := sshConn.ExecCommand(fmt.Sprintf(`echo '%s' | sudo -S bash -c "echo -n '%s' > /var/nfs/general/keyfile.txt"`, password, executorkey)) + out, err := sshConn.ExecCommand(fmt.Sprintf(`echo '%s' | sudo -S bash -c "echo -n '%s' > /var/nfs/general/keyfile.txt"`, password, referralExecutorKey)) if err != nil { fmt.Println(string(out)) return fmt.Errorf("updating executor private key file: %w", err) @@ -201,8 +224,6 @@ func (c *Container) updateSwarmServices(ctx *cli.Context, selectedSwarmServicesT // Append stack name for service svcStackName := dockerStackName + "_" + svcToUpdate - fmt.Printf("Updating %s to %s\n", svcToUpdate, imgToUse) - t := time.NewTimer(time.Minute * 2) done := make(chan struct{}) go func() { From 1fea21f4d489c4102e569ede40a087adf47afd4a Mon Sep 17 00:00:00 2001 From: Mantas Date: Thu, 14 Mar 2024 13:25:50 +0200 Subject: [PATCH 10/16] include update runbook in readme --- README.md | 3 ++ UPDATE_RUNBOOK.md | 124 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 110 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index c643498..1fc8a04 100644 --- a/README.md +++ b/README.md @@ -425,6 +425,9 @@ swarm-manager for which you can get the ip with `d8x ip manager`). docker service update --image "ghcr.io/d8-x/d8x-trader-main:dev@sha256:aea8e56d6077c733a1d553b4291149712c022b8bd72571d2a852a5478e1ec559" stack_api ``` +See the [Update Runbook](./UPDATE_RUNBOOK.md) for more guidelines and more +details how updating services works. +
diff --git a/UPDATE_RUNBOOK.md b/UPDATE_RUNBOOK.md index 8f98260..26c7da8 100644 --- a/UPDATE_RUNBOOK.md +++ b/UPDATE_RUNBOOK.md @@ -1,15 +1,21 @@ # Updating your d8x services When updating your d8x swarm and broker services, we recommend performing a -database backup before running the actual updates. If you make a backup, if something goes wrong, you will still have the database that can be used to restore the state of your previous deployments. Making a backup is also useful when significant contract changes are introduced, for example changes in events (around beginning of March in 2024). +database backup before running the actual updates. If you make a backup, if +something goes wrong, you will still have the database that can be used to +restore the state of your previous deployments. Making a backup is also useful +when significant contract changes are introduced, for example changes in events +(around beginning of March in 2024). -The following runbook will guide how to perform a database backup and update your services. +The following runbook will guide on how to perform a database backup and update +your services. Follow this runbook from top to bottom. ## Running the database backup -Refer to the [Database Backups](./README.md#database-backups) on more details about how to perform a database backup. +Refer to the [Database Backups](./README.md#database-backups) on more details +about how to perform a database backup. First, you should run the `d8x backup-db` command: @@ -53,39 +59,123 @@ d8x update ``` ```bash +┌──────────────────────────┐ +│ ____ ___ __ __ │ +│ | _ \ ( _ ) \ \/ / │ +│ | | | | / _ \ \ / │ +│ | |_| | | (_) | / \ │ +│ |____/ \___/ /_/\_\ │ +│ │ +└──────────────────────────┘ Updating swarm services... Select swarm services to update [x] api - [ ] candles-pyth-client - [ ] candles-ws-server + [x] candles-pyth-client + [x] candles-ws-server [x] history - [ ] referral + [x] referral ╭────────╮ │ OK │ ╰────────╯ Select broker-server services to update - [ ] broker - [ ] executorws + [x] broker + [x] executorws ╭────────╮ │ OK │ ╰────────╯ -Pruning unused resources on worker servers... -Running docker prune on worker-1: -<...> -Updating service api -Choose which image reference to update to +Fetching image tags with sha hashes for service referral +Fetching image tags with sha hashes for service candles-pyth-client +Fetching image tags with sha hashes for service candles-ws-server +Fetching image tags with sha hashes for service api +Fetching image tags with sha hashes for service history +Image tags fetched for service ghcr.io/d8-x/d8x-candles-pyth-client +Image tags fetched for service ghcr.io/d8-x/d8x-trader-main +Image tags fetched for service ghcr.io/d8-x/d8x-trader-history +Image tags fetched for service ghcr.io/d8-x/d8x-candles-ws-server +Image tags fetched for service ghcr.io/d8-x/d8x-referral-system + +Choose which image reference to update api service to + + [x] ghcr.io/d8-x/d8x-trader-main:main@sha256:ac06805f6be51a83e21dfa78d9d27ec425d169623f16ffa43484792a48d8a016 + [ ] ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 + [ ] Enter image reference manually +╭────────╮ +│ OK │ +╰────────╯ +Service api will be updated to ghcr.io/d8-x/d8x-trader-main:main@sha256:ac06805f6be51a83e21dfa78d9d27ec425d169623f16ffa43484792a48d8a016 + +Choose which image reference to update candles-pyth-client service to + + [x] ghcr.io/d8-x/d8x-candles-pyth-client:main + [ ] ghcr.io/d8-x/d8x-candles-pyth-client:dev@sha256:5373e33c382f72773d50e3ac7b47f739ca95b05ae6d0f11e1eac9ce800877f3a + [ ] Enter image reference manually +╭────────╮ +│ OK │ +╰────────╯ +Service candles-pyth-client will be updated to ghcr.io/d8-x/d8x-candles-pyth-client:main + +Choose which image reference to update candles-ws-server service to - [ ] ghcr.io/d8-x/d8x-trader-main:main@sha256:ac06805f6be51a83e21dfa78d9d27ec425d169623f16ffa43484792a48d8a016 - [x] ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 + [x] ghcr.io/d8-x/d8x-candles-ws-server:main + [ ] ghcr.io/d8-x/d8x-candles-ws-server:dev@sha256:081eb98ec939d0bfa7e58637fb541c985e36ab0092eca7dd5dc7396f1f5e89ef [ ] Enter image reference manually ╭────────╮ │ OK │ ╰────────╯ -Using image: ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 -Updating api to ghcr.io/d8-x/d8x-trader-main:dev@sha256:2f306c1342d6f7aecc440fd8d841479cb63afa3e0e9b61dceb384a3118000928 +Service candles-ws-server will be updated to ghcr.io/d8-x/d8x-candles-ws-server:main + +Choose which image reference to update history service to + + [x] ghcr.io/d8-x/d8x-trader-history:main@sha256:001704f5249a88cbd93272da705cd92c933837190653b1ad02e7b63add4a24df + [ ] ghcr.io/d8-x/d8x-trader-history:dev@sha256:4e14361b0033ea1917971bd9293a017b0791edf34e7025a344cb091d223c7830 + [ ] Enter image reference manually +╭────────╮ +│ OK │ +╰────────╯ +Service history will be updated to ghcr.io/d8-x/d8x-trader-history:main@sha256:001704f5249a88cbd93272da705cd92c933837190653b1ad02e7b63add4a24df + +Choose which image reference to update referral service to + + [x] ghcr.io/d8-x/d8x-referral-system:main@sha256:5c38fc8938f9cc85a4168386a684930a97cbe1bcdf06e51df1cf7f34b247cfcd + [ ] ghcr.io/d8-x/d8x-referral-system:dev@sha256:cd1925abdcbb17fb063e17370bb3b376d5f85f395e9233873db7e05217098992 + [ ] Enter image reference manually +╭────────╮ +│ OK │ +╰────────╯ +Service referral will be updated to ghcr.io/d8-x/d8x-referral-system:main@sha256:5c38fc8938f9cc85a4168386a684930a97cbe1bcdf06e51df1cf7f34b247cfcd +Enter your referral payment executor private key: +> **************************************************************** + +Wallet address of entered private key: 0xAc35CA4cC617CFf4143A1471151a904FE535F0c6 +Is this the correct address? + +╭─────────╮ ╭────────╮ +│ yes │ │ no │ +╰─────────╯ ╰────────╯ + +Pruning unused resources on worker servers... +Running docker prune on worker-1: +Deleted Containers: +aefad8dbc219ec4a17a9c5a86f3b56e00937ee2a8627db8a9908d377b5473dc4 +fc1a21466bb6de3572ee6d6b8f8cde2dfb31d0d3bace9ea69d7924f0c60a0b27 + +Total reclaimed space: 0B +Total reclaimed space: 0B + +Docker prune on worker 1 completed successfully +Running docker prune on worker-2: +Deleted Containers: +6e251b1f07c935d7b2ac61a0c6ae49fe44abf90bdcda8e3c3125bc54e0d96b9f +205a6f00d081dc3937e4cd3e5907dab50ca6b34eff49609a90e14a25f1e43e84 + +Total reclaimed space: 0B +Total reclaimed space: 0B + +Docker prune on worker 2 completed successfully +Updating api to ghcr.io/d8-x/d8x-trader-main:main@sha256:ac06805f6be51a83e21dfa78d9d27ec425d169623f16ffa43484792a48d8a016 stack_api overall progress: 2 out of 2 tasks 1/2: running From 62006a24671e067631ee2e7916f6c781cb0005dc Mon Sep 17 00:00:00 2001 From: Mantas Date: Thu, 14 Mar 2024 15:17:02 +0200 Subject: [PATCH 11/16] collect broker update info before running updates --- internal/actions/svc_update.go | 97 ++++++++++++++++++---------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/internal/actions/svc_update.go b/internal/actions/svc_update.go index cdf4b63..5f5f3c1 100644 --- a/internal/actions/svc_update.go +++ b/internal/actions/svc_update.go @@ -66,10 +66,58 @@ func (c *Container) ServiceUpdate(ctx *cli.Context) error { return err } + // Collect broker services related information whenever needed + brokerRedisPassword := "" + brokerFeeTBPS := "" + brokerPrivateKey := "" + if len(selectedBrokerServicesToUpdate) > 0 { + cfg, err := c.ConfigRWriter.Read() + if err != nil { + return err + } + + // Ask for private key + pk, _, err := c.CollectAndValidatePrivateKey("Enter your broker private key:") + if err != nil { + return err + } + brokerPrivateKey = pk + + if !cfg.BrokerDeployed { + fmt.Println(styles.ErrorText.Render("Broker server configuration not found, make sure you have deployed the broker server first (d8x setup broker-deploy), otherwise the update might fail.")) + fmt.Println("Enter your broker redis password:") + pwd, err := c.TUI.NewInput( + components.TextInputOptPlaceholder(""), + ) + if err != nil { + return err + } + brokerRedisPassword = pwd + + fee, err := c.Input.CollectBrokerFee() + if err != nil { + return err + } + brokerFeeTBPS = fee + + // Store these in the config once entered + cfg.BrokerServerConfig = configs.D8XBrokerServerConfig{ + FeeTBPS: brokerFeeTBPS, + RedisPassword: brokerRedisPassword, + } + if err := c.ConfigRWriter.Write(cfg); err != nil { + return err + } + } else { + brokerRedisPassword = cfg.BrokerServerConfig.RedisPassword + brokerFeeTBPS = cfg.BrokerServerConfig.FeeTBPS + } + } + if err := c.updateSwarmServices(ctx, selectedSwarmServicesToUpdate, services); err != nil { return err } - if err := c.updateBrokerServerServices(selectedBrokerServicesToUpdate, brokerServices); err != nil { + if err := c.updateBrokerServerServices(selectedBrokerServicesToUpdate, brokerPrivateKey, brokerRedisPassword, brokerFeeTBPS); err != nil { return err } @@ -271,16 +319,11 @@ func (c *Container) updateSwarmServices(ctx *cli.Context, selectedSwarmServicesT // updateBrokerServerServices performs broker-server services update on broker // server. Broker-server update involves uploading the key to a new volume. -func (c *Container) updateBrokerServerServices(selectedSwarmServicesToUpdate []string, services map[string]configs.DockerService) error { +func (c *Container) updateBrokerServerServices(selectedSwarmServicesToUpdate []string, pk, redisPassword, feeTBPS string) error { if len(selectedSwarmServicesToUpdate) == 0 { return nil } - cfg, err := c.ConfigRWriter.Read() - if err != nil { - return err - } - // See broker.go for broker server setup directory brokerDir := "./broker" @@ -301,46 +344,6 @@ func (c *Container) updateBrokerServerServices(selectedSwarmServicesToUpdate []s } fmt.Println(styles.SuccessText.Render("Docker prune on broker server completed successfully")) - // Ask for private key - pk, _, err := c.CollectAndValidatePrivateKey("Enter your broker private key:") - if err != nil { - return err - } - - // Check if we have broker services configuration information and prompt - // user to enter it otherwise - redisPassword := "" - feeTBPS := "" - if !cfg.BrokerDeployed { - fmt.Println(styles.ErrorText.Render("Broker server configuration not found, make sure you have deployed the broker server first (d8x setup broker-deploy), otherwise the update might fail.")) - fmt.Println("Enter your broker redis password:") - pwd, err := c.TUI.NewInput( - components.TextInputOptPlaceholder(""), - ) - if err != nil { - return err - } - redisPassword = pwd - - fee, err := c.Input.CollectBrokerFee() - if err != nil { - return err - } - feeTBPS = fee - - // Store these in the config - cfg.BrokerServerConfig = configs.D8XBrokerServerConfig{ - FeeTBPS: feeTBPS, - RedisPassword: redisPassword, - } - if err := c.ConfigRWriter.Write(cfg); err != nil { - return err - } - } else { - redisPassword = cfg.BrokerServerConfig.RedisPassword - feeTBPS = cfg.BrokerServerConfig.FeeTBPS - } - fmt.Printf("Using BROKER_FEE_TBPS=%s REDIS_PW=%s\n", feeTBPS, redisPassword) for _, svcToUpdate := range selectedSwarmServicesToUpdate { From 19bced7bdda491cdf8bf9d007387394a98617bab Mon Sep 17 00:00:00 2001 From: Mantas Date: Thu, 14 Mar 2024 17:10:12 +0200 Subject: [PATCH 12/16] cleanup update logging --- internal/actions/svc_update.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/actions/svc_update.go b/internal/actions/svc_update.go index 5f5f3c1..3f40f01 100644 --- a/internal/actions/svc_update.go +++ b/internal/actions/svc_update.go @@ -338,8 +338,9 @@ func (c *Container) updateBrokerServerServices(selectedSwarmServicesToUpdate []s fmt.Println("Pruning unused resources on broker server...") out, err := dockerPrune(sshConn) - fmt.Println(string(out)) if err != nil { + // Print out the output only on error + fmt.Println(string(out)) return fmt.Errorf("docker prune on broker server failed: %w", err) } fmt.Println(styles.SuccessText.Render("Docker prune on broker server completed successfully")) @@ -547,8 +548,8 @@ func (c *Container) PurgeWorkers(workersIps []string) error { } output, err := dockerPrune(worker) - fmt.Println(string(output)) if err != nil { + fmt.Println(string(output)) return fmt.Errorf("docker prune on worker %d failed: %w", workerIndex+1, err) } else { fmt.Println(styles.SuccessText.Render(fmt.Sprintf("Docker prune on worker %d completed successfully", workerIndex+1))) From ff7507561617ba41d50efbb216fc25d9a4a3b354 Mon Sep 17 00:00:00 2001 From: Mantas Date: Fri, 15 Mar 2024 13:56:10 +0200 Subject: [PATCH 13/16] remove proxy address from chainConfig.json --- internal/configs/embedded/broker-server/chainConfig.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/internal/configs/embedded/broker-server/chainConfig.json b/internal/configs/embedded/broker-server/chainConfig.json index e103b86..9456587 100644 --- a/internal/configs/embedded/broker-server/chainConfig.json +++ b/internal/configs/embedded/broker-server/chainConfig.json @@ -2,42 +2,36 @@ { "chainId": 195, "name": "x1", - "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", "multiPayCtrctAddr": "0x3594D0eAAaC82D3AFA7347d098bc4a39A71e918c", "allowedExecutors": [] }, { "chainId": 1442, "name": "zkEVM Testnet", - "perpetualManagerProxyAddr": "0x0e23619704556945B1C7CB550Dee6D428f7d2E2B", "multiPayCtrctAddr": "0xfCBE2f332b1249cDE226DFFE8b2435162426AfE5", "allowedExecutors": [] }, { "chainId": 1101, "name": "zkEVM Mainnet", - "perpetualManagerProxyAddr": "0xaB7794EcD2c8e9Decc6B577864b40eBf9204720f", "multiPayCtrctAddr": "0x5a1e7BBCf0A02a84C5BcE8865aC88668FC6389fE", "allowedExecutors": [] }, { "chainId": 2442, "name": "cardona", - "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", "multiPayCtrctAddr": "0xF08A1E0d5E5a0b90D082e218f5CA2416916C5e8c", "allowedExecutors": [] }, { "chainId": 421614, "name": "arbitrumSepolia", - "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", - "multiPayCtrctAddr": "0x35672963523bc874f13da5CeED024249794E6a16", + "multiPayCtrctAddr": "0x60Eba5B5ba7Bd4694886CC5ecc0642D6178c2c86", "allowedExecutors": [] }, { "chainId": 80085, "name": "artio", - "perpetualManagerProxyAddr": "0x70212F1E2eB66C82990312FA5AB3f851706fD1E1", "multiPayCtrctAddr": "0xDa7f988605Abe824dF767Aa583d8fD60f09E23D0", "allowedExecutors": [] } From 83fafe560dfd6ea3df3a1f5fcbe4d6fa091717c9 Mon Sep 17 00:00:00 2001 From: Mantas Date: Fri, 15 Mar 2024 18:23:12 +0200 Subject: [PATCH 14/16] add priceServiceHTTPSEndpoint for cardona --- internal/configs/embedded/trader-backend/chain.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/configs/embedded/trader-backend/chain.json b/internal/configs/embedded/trader-backend/chain.json index 4dc1263..c5e1fbb 100644 --- a/internal/configs/embedded/trader-backend/chain.json +++ b/internal/configs/embedded/trader-backend/chain.json @@ -25,7 +25,7 @@ "sdkNetwork": "cardona", "priceFeedNetwork": "mainnet", "priceServiceWSEndpoint": "wss://hermes.pyth.network/ws", - "priceServiceHTTPSEndpoint": "" + "priceServiceHTTPSEndpoint": "https://odin.quantena.tech/api" }, "421614": { "type": "testnet", From 6ada6df5dcb65ebdcac83919900f9e1cb109f38f Mon Sep 17 00:00:00 2001 From: Mantas Date: Mon, 18 Mar 2024 09:41:57 +0200 Subject: [PATCH 15/16] do not limit referral restarts --- internal/configs/embedded/docker-swarm-stack.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/configs/embedded/docker-swarm-stack.yml b/internal/configs/embedded/docker-swarm-stack.yml index 830e096..b395fd0 100644 --- a/internal/configs/embedded/docker-swarm-stack.yml +++ b/internal/configs/embedded/docker-swarm-stack.yml @@ -82,7 +82,8 @@ services: restart_policy: condition: any delay: 60s - max_attempts: 20 + # Do not limit referral restart attempts + # max_attempts: 20 # Do not wait to verify restart window: 0s environment: From 46868a8c26fda706212e09de6395fd9e3e01901d Mon Sep 17 00:00:00 2001 From: Mantas Date: Mon, 18 Mar 2024 14:22:42 +0200 Subject: [PATCH 16/16] backup old config --- internal/actions/setup.go | 18 +++++++++++++++++- internal/configs/d8x.go | 21 +++++++++++++++++++++ internal/mocks/configs.go | 28 ++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/internal/actions/setup.go b/internal/actions/setup.go index 99eaa13..09b88b3 100644 --- a/internal/actions/setup.go +++ b/internal/actions/setup.go @@ -33,8 +33,24 @@ func (c *Container) Setup(ctx *cli.Context) error { return err } if !keepConfig { - if err := c.ConfigRWriter.Write(&configs.D8XConfig{}); err != nil { + // Print out a warning one more time to prevent accidental deletion + // of config + fmt.Println( + styles.AlertImportant.Render("Warning! Existing configuration will be completely removed!"), + ) + if yes, err := c.TUI.NewPrompt("Are you sure you want to continue?", false); err != nil { return err + } else if yes { + // Make a backup of the existing config just in case + backup := c.ConfigRWriter.GetPath() + ".backup-" + time.Now().Format("2006-01-02_15:04:05") + if err := c.ConfigRWriter.WriteTo(backup, cfg); err != nil { + return err + } + fmt.Printf("Backup of the existing configuration was saved to %s\n\n", backup) + + if err := c.ConfigRWriter.Write(&configs.D8XConfig{}); err != nil { + return err + } } } } diff --git a/internal/configs/d8x.go b/internal/configs/d8x.go index c52688f..b46708e 100644 --- a/internal/configs/d8x.go +++ b/internal/configs/d8x.go @@ -222,6 +222,12 @@ type D8XConfigReadWriter interface { // Write writes given D8XConfig to underlying storage system Write(*D8XConfig) error + + // GetPath returns the full path of config file + GetPath() string + + // WriteTo writes the contents of cfg to the provided filePath + WriteTo(filePath string, cfg *D8XConfig) error } func NewFileBasedD8XConfigRW(filePath string) D8XConfigReadWriter { @@ -236,6 +242,10 @@ type d8xConfigFileReadWriter struct { warningShown bool } +func (d *d8xConfigFileReadWriter) GetPath() string { + return d.filePath +} + func (d *d8xConfigFileReadWriter) Read() (*D8XConfig, error) { cfg := NewD8XConfig() if contents, err := os.ReadFile(d.filePath); err != nil { @@ -281,6 +291,17 @@ func (d *d8xConfigFileReadWriter) Write(cfg *D8XConfig) error { return nil } +func (d *d8xConfigFileReadWriter) WriteTo(filePath string, cfg *D8XConfig) error { + if buf, err := json.MarshalIndent(cfg, "", "\t"); err != nil { + return err + } else { + if err := os.WriteFile(filePath, buf, 0666); err != nil { + return err + } + } + return nil +} + func (c *D8XConfig) SuggestSubdomain(svc D8XServiceName, chainName string, chainId uint) string { if c.SetupDomain == "" { return "" diff --git a/internal/mocks/configs.go b/internal/mocks/configs.go index 202a009..4a3ce17 100644 --- a/internal/mocks/configs.go +++ b/internal/mocks/configs.go @@ -34,6 +34,20 @@ func (m *MockD8XConfigReadWriter) EXPECT() *MockD8XConfigReadWriterMockRecorder return m.recorder } +// GetPath mocks base method. +func (m *MockD8XConfigReadWriter) GetPath() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPath") + ret0, _ := ret[0].(string) + return ret0 +} + +// GetPath indicates an expected call of GetPath. +func (mr *MockD8XConfigReadWriterMockRecorder) GetPath() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPath", reflect.TypeOf((*MockD8XConfigReadWriter)(nil).GetPath)) +} + // Read mocks base method. func (m *MockD8XConfigReadWriter) Read() (*configs.D8XConfig, error) { m.ctrl.T.Helper() @@ -62,3 +76,17 @@ func (mr *MockD8XConfigReadWriterMockRecorder) Write(arg0 interface{}) *gomock.C mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Write", reflect.TypeOf((*MockD8XConfigReadWriter)(nil).Write), arg0) } + +// WriteTo mocks base method. +func (m *MockD8XConfigReadWriter) WriteTo(arg0 string, arg1 *configs.D8XConfig) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WriteTo", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// WriteTo indicates an expected call of WriteTo. +func (mr *MockD8XConfigReadWriterMockRecorder) WriteTo(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WriteTo", reflect.TypeOf((*MockD8XConfigReadWriter)(nil).WriteTo), arg0, arg1) +}