From c99909c47243ab86ff859628a04b6d6518680ae9 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 4 Jul 2024 15:35:12 -0700 Subject: [PATCH 01/24] rm deprecated code after research --- cmd/nodecmd/sync.go | 8 -------- cmd/nodecmd/updateSubnet.go | 7 ------- pkg/ssh/ssh.go | 32 -------------------------------- 3 files changed, 47 deletions(-) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index 84af07e2b..8318fcc50 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -97,14 +97,6 @@ func trackSubnet( go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() subnetExportPath := filepath.Join("/tmp", filepath.Base(subnetPath)) - if err := ssh.RunSSHExportSubnet(host, subnetPath, subnetExportPath); err != nil { - nodeResults.AddResult(host.NodeID, nil, err) - return - } - if err := ssh.RunSSHUploadClustersConfig(host, app.GetClustersConfigPath()); err != nil { - nodeResults.AddResult(host.NodeID, nil, err) - } - if err := ssh.RunSSHTrackSubnet(host, subnetName, subnetExportPath, networkFlag); err != nil { nodeResults.AddResult(host.NodeID, nil, err) return diff --git a/cmd/nodecmd/updateSubnet.go b/cmd/nodecmd/updateSubnet.go index 3823212ad..91c175fd8 100644 --- a/cmd/nodecmd/updateSubnet.go +++ b/cmd/nodecmd/updateSubnet.go @@ -84,13 +84,6 @@ func doUpdateSubnet( go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() subnetExportPath := filepath.Join("/tmp", filepath.Base(subnetPath)) - if err := ssh.RunSSHExportSubnet(host, subnetPath, subnetExportPath); err != nil { - nodeResults.AddResult(host.NodeID, nil, err) - return - } - if err := ssh.RunSSHUploadClustersConfig(host, app.GetClustersConfigPath()); err != nil { - nodeResults.AddResult(host.NodeID, nil, err) - } if err := ssh.RunSSHUpdateSubnet(host, subnetName, subnetExportPath); err != nil { nodeResults.AddResult(host.NodeID, nil, err) return diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 072746272..fa5073bfc 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -457,22 +457,6 @@ func RunSSHSetupDevNet(host *models.Host, nodeInstanceDirPath string) error { return docker.StartDockerCompose(host, constants.SSHLongRunningScriptTimeout) } -func RunSSHUploadClustersConfig(host *models.Host, localClustersConfigPath string) error { - remoteNodesDir := filepath.Join(constants.CloudNodeCLIConfigBasePath, constants.NodesDir) - if err := host.MkdirAll( - remoteNodesDir, - constants.SSHDirOpsTimeout, - ); err != nil { - return err - } - remoteClustersConfigPath := filepath.Join(remoteNodesDir, constants.ClustersConfigFileName) - return host.Upload( - localClustersConfigPath, - remoteClustersConfigPath, - constants.SSHFileOpsTimeout, - ) -} - // RunSSHUploadStakingFiles uploads staking files to a remote host via SSH. func RunSSHUploadStakingFiles(host *models.Host, nodeInstanceDirPath string) error { if err := host.MkdirAll( @@ -502,21 +486,8 @@ func RunSSHUploadStakingFiles(host *models.Host, nodeInstanceDirPath string) err ) } -// RunSSHExportSubnet exports deployed Subnet from local machine to cloud server -func RunSSHExportSubnet(host *models.Host, exportPath, cloudServerSubnetPath string) error { - // name: copy exported subnet VM spec to cloud server - return host.Upload( - exportPath, - cloudServerSubnetPath, - constants.SSHFileOpsTimeout, - ) -} - // RunSSHTrackSubnet enables tracking of specified subnet func RunSSHTrackSubnet(host *models.Host, subnetName, importPath, networkFlag string) error { - if _, err := host.Command(fmt.Sprintf("/home/ubuntu/bin/avalanche subnet import file %s --force", importPath), nil, constants.SSHScriptTimeout); err != nil { - return err - } if err := docker.StopDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout); err != nil { return err } @@ -531,9 +502,6 @@ func RunSSHUpdateSubnet(host *models.Host, subnetName, importPath string) error if err := docker.StopDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout); err != nil { return err } - if _, err := host.Command(fmt.Sprintf("/home/ubuntu/bin/avalanche subnet import file %s --force", importPath), nil, constants.SSHScriptTimeout); err != nil { - return err - } if _, err := host.Command(fmt.Sprintf("/home/ubuntu/bin/avalanche subnet join %s --fuji --avalanchego-config /home/ubuntu/.avalanchego/configs/node.json --plugin-dir /home/ubuntu/.avalanchego/plugins --force-write", subnetName), nil, constants.SSHScriptTimeout); err != nil { return err } From 86dde62f598e4489507f8a892881eef99de4233d Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 4 Jul 2024 15:43:14 -0700 Subject: [PATCH 02/24] more cleanup --- cmd/nodecmd/sync.go | 9 +-------- cmd/nodecmd/updateSubnet.go | 9 +-------- pkg/ssh/ssh.go | 8 ++++++-- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index 8318fcc50..21f97cf08 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -4,13 +4,11 @@ package nodecmd import ( "fmt" - "path/filepath" "sync" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/ansible" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/ssh" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -85,19 +83,14 @@ func trackSubnet( clusterName string, subnetName string, ) ([]string, error) { - subnetPath := "/tmp/" + subnetName + constants.ExportSubnetSuffix networkFlag := "--cluster " + clusterName - if err := subnetcmd.CallExportSubnet(subnetName, subnetPath); err != nil { - return nil, err - } wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { wg.Add(1) go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() - subnetExportPath := filepath.Join("/tmp", filepath.Base(subnetPath)) - if err := ssh.RunSSHTrackSubnet(host, subnetName, subnetExportPath, networkFlag); err != nil { + if err := ssh.RunSSHTrackSubnet(host, subnetName, networkFlag); err != nil { nodeResults.AddResult(host.NodeID, nil, err) return } diff --git a/cmd/nodecmd/updateSubnet.go b/cmd/nodecmd/updateSubnet.go index 91c175fd8..91a73e3e6 100644 --- a/cmd/nodecmd/updateSubnet.go +++ b/cmd/nodecmd/updateSubnet.go @@ -4,13 +4,11 @@ package nodecmd import ( "fmt" - "path/filepath" "sync" "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/ansible" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/ssh" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -73,18 +71,13 @@ func doUpdateSubnet( hosts []*models.Host, subnetName string, ) ([]string, error) { - subnetPath := "/tmp/" + subnetName + constants.ExportSubnetSuffix - if err := subnetcmd.CallExportSubnet(subnetName, subnetPath); err != nil { - return nil, err - } wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { wg.Add(1) go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() - subnetExportPath := filepath.Join("/tmp", filepath.Base(subnetPath)) - if err := ssh.RunSSHUpdateSubnet(host, subnetName, subnetExportPath); err != nil { + if err := ssh.RunSSHUpdateSubnet(host, subnetName); err != nil { nodeResults.AddResult(host.NodeID, nil, err) return } diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index fa5073bfc..474d4086c 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -486,8 +486,12 @@ func RunSSHUploadStakingFiles(host *models.Host, nodeInstanceDirPath string) err ) } +func RunSSHJoinSubnet(host *models.Host, subnetName, networkFlag string) error { + +} + // RunSSHTrackSubnet enables tracking of specified subnet -func RunSSHTrackSubnet(host *models.Host, subnetName, importPath, networkFlag string) error { +func RunSSHTrackSubnet(host *models.Host, subnetName, networkFlag string) error { if err := docker.StopDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout); err != nil { return err } @@ -498,7 +502,7 @@ func RunSSHTrackSubnet(host *models.Host, subnetName, importPath, networkFlag st } // RunSSHUpdateSubnet runs avalanche subnet join in cloud server using update subnet info -func RunSSHUpdateSubnet(host *models.Host, subnetName, importPath string) error { +func RunSSHUpdateSubnet(host *models.Host, subnetName string) error { if err := docker.StopDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout); err != nil { return err } From d3da6ac820577725823767e19be525b9f976ba06 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Fri, 5 Jul 2024 14:46:21 -0700 Subject: [PATCH 03/24] deprecate cli join in terms of the infra --- cmd/nodecmd/sync.go | 28 +++- cmd/nodecmd/updateSubnet.go | 28 +++- pkg/docker/config.go | 2 +- pkg/remoteconfig/avalanche.go | 8 +- .../templates/avalanche-node.tmpl | 3 + pkg/ssh/ssh.go | 138 ++++++++++++++++-- 6 files changed, 188 insertions(+), 19 deletions(-) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index 21f97cf08..cdafc4a2a 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/ssh" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/spf13/cobra" ) @@ -39,6 +40,10 @@ func syncSubnet(_ *cobra.Command, args []string) error { if err := checkCluster(clusterName); err != nil { return err } + clusterConfig, err := app.GetClusterConfig(clusterName) + if err != nil { + return err + } if _, err := subnetcmd.ValidateSubnetNameAndGetChains([]string{subnetName}); err != nil { return err } @@ -64,7 +69,7 @@ func syncSubnet(_ *cobra.Command, args []string) error { return err } } - untrackedNodes, err := trackSubnet(hosts, clusterName, subnetName) + untrackedNodes, err := trackSubnet(hosts, clusterName, clusterConfig.Network.NetworkIDFlagValue(), subnetName) if err != nil { return err } @@ -81,16 +86,33 @@ func syncSubnet(_ *cobra.Command, args []string) error { func trackSubnet( hosts []*models.Host, clusterName string, + networkID string, subnetName string, ) ([]string, error) { - networkFlag := "--cluster " + clusterName + // load cluster config + clusterConf, err := app.GetClusterConfig(clusterName) + if err != nil { + return nil, err + } + // and get list of subnets + allSubnets := utils.Unique(append(clusterConf.Subnets, subnetName)) + wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { wg.Add(1) go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() - if err := ssh.RunSSHTrackSubnet(host, subnetName, networkFlag); err != nil { + if err := ssh.RunSSHStopNode(host); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, networkID, allSubnets); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + if err := ssh.RunSSHSyncSubnetData(app, host, networkID, subnetName); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + if err := ssh.RunSSHStartNode(host); err != nil { nodeResults.AddResult(host.NodeID, nil, err) return } diff --git a/cmd/nodecmd/updateSubnet.go b/cmd/nodecmd/updateSubnet.go index 91a73e3e6..9b6c3db03 100644 --- a/cmd/nodecmd/updateSubnet.go +++ b/cmd/nodecmd/updateSubnet.go @@ -11,6 +11,7 @@ import ( "github.com/ava-labs/avalanche-cli/pkg/cobrautils" "github.com/ava-labs/avalanche-cli/pkg/models" "github.com/ava-labs/avalanche-cli/pkg/ssh" + "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" "github.com/spf13/cobra" ) @@ -36,6 +37,10 @@ func updateSubnet(_ *cobra.Command, args []string) error { if err := checkCluster(clusterName); err != nil { return err } + clusterConfig, err := app.GetClusterConfig(clusterName) + if err != nil { + return err + } if _, err := subnetcmd.ValidateSubnetNameAndGetChains([]string{subnetName}); err != nil { return err } @@ -53,7 +58,7 @@ func updateSubnet(_ *cobra.Command, args []string) error { if err := checkHostsAreRPCCompatible(hosts, subnetName); err != nil { return err } - nonUpdatedNodes, err := doUpdateSubnet(hosts, subnetName) + nonUpdatedNodes, err := doUpdateSubnet(hosts, clusterName, clusterConfig.Network.NetworkIDFlagValue(), subnetName) if err != nil { return err } @@ -69,15 +74,34 @@ func updateSubnet(_ *cobra.Command, args []string) error { // restart tracking the specified subnet (similar to avalanche subnet join command) func doUpdateSubnet( hosts []*models.Host, + clusterName string, + networkID string, subnetName string, ) ([]string, error) { + // load cluster config + clusterConf, err := app.GetClusterConfig(clusterName) + if err != nil { + return nil, err + } + // and get list of subnets + allSubnets := utils.Unique(append(clusterConf.Subnets, subnetName)) + wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { wg.Add(1) go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() - if err := ssh.RunSSHUpdateSubnet(host, subnetName); err != nil { + if err := ssh.RunSSHStopNode(host); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, networkID, allSubnets); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + if err := ssh.RunSSHSyncSubnetData(app, host, networkID, subnetName); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + if err := ssh.RunSSHStartNode(host); err != nil { nodeResults.AddResult(host.NodeID, nil, err) return } diff --git a/pkg/docker/config.go b/pkg/docker/config.go index e5b5412c5..dbbefd7d6 100644 --- a/pkg/docker/config.go +++ b/pkg/docker/config.go @@ -12,7 +12,7 @@ import ( ) func prepareAvalanchegoConfig(host *models.Host, networkID string) (string, string, error) { - avagoConf := remoteconfig.DefaultCliAvalancheConfig(host.IP, networkID) + avagoConf := remoteconfig.DefaultCliAvalancheConfig(host.IP, networkID, nil) nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf) if err != nil { return "", "", err diff --git a/pkg/remoteconfig/avalanche.go b/pkg/remoteconfig/avalanche.go index e0aec807b..aa09ca5ea 100644 --- a/pkg/remoteconfig/avalanche.go +++ b/pkg/remoteconfig/avalanche.go @@ -21,9 +21,10 @@ type AvalancheConfigInputs struct { PublicIP string StateSyncEnabled bool PruningEnabled bool + TrackSubents []string } -func DefaultCliAvalancheConfig(publicIP string, networkID string) AvalancheConfigInputs { +func DefaultCliAvalancheConfig(publicIP string, networkID string, subnets []string) AvalancheConfigInputs { return AvalancheConfigInputs{ HTTPHost: "0.0.0.0", NetworkID: networkID, @@ -32,6 +33,7 @@ func DefaultCliAvalancheConfig(publicIP string, networkID string) AvalancheConfi PublicIP: publicIP, StateSyncEnabled: true, PruningEnabled: false, + TrackSubents: subnets, } } @@ -77,6 +79,10 @@ func GetRemoteAvalancheCChainConfig() string { return filepath.Join(constants.CloudNodeConfigPath, "chains", "C", "config.json") } +func GetRemoteAvalancheGenesis() string { + return filepath.Join(constants.CloudNodeConfigPath, "genesis.json") +} + func AvalancheFolderToCreate() []string { return []string{ "/home/ubuntu/.avalanchego/db", diff --git a/pkg/remoteconfig/templates/avalanche-node.tmpl b/pkg/remoteconfig/templates/avalanche-node.tmpl index ef0ffbd24..a74b907f6 100644 --- a/pkg/remoteconfig/templates/avalanche-node.tmpl +++ b/pkg/remoteconfig/templates/avalanche-node.tmpl @@ -10,4 +10,7 @@ {{- else -}} "public-ip-resolution-service": "opendns" {{- end -}} +{{- if .TrackSubnets }} + "track-subnets": "{{ join .TrackSubnets ", " }}" +{{- end }} } diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 474d4086c..7047e2892 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -5,6 +5,7 @@ package ssh import ( "bytes" "embed" + "errors" "fmt" "net/url" "os" @@ -14,11 +15,13 @@ import ( "text/template" "time" + "github.com/ava-labs/avalanche-cli/pkg/application" "github.com/ava-labs/avalanche-cli/pkg/docker" "github.com/ava-labs/avalanche-cli/pkg/monitoring" "github.com/ava-labs/avalanche-cli/pkg/remoteconfig" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" @@ -486,30 +489,141 @@ func RunSSHUploadStakingFiles(host *models.Host, nodeInstanceDirPath string) err ) } -func RunSSHJoinSubnet(host *models.Host, subnetName, networkFlag string) error { +// RunSSHRenderAvalancheNodeConfig renders avalanche node config to a remote host via SSH. +func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Host, networkID string, trackSubnets []string) error { + // get subnet ids + subnetIDs, err := utils.MapWithError(trackSubnets, func(subnetName string) (string, error) { + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return "", err + } else { + return sc.Networks[networkID].SubnetID.String(), nil + } + }) + if err != nil { + return err + } -} + nodeConfFile, err := os.CreateTemp("", "avalanchecli-node-*.yml") + if err != nil { + return err + } + defer os.Remove(nodeConfFile.Name()) -// RunSSHTrackSubnet enables tracking of specified subnet -func RunSSHTrackSubnet(host *models.Host, subnetName, networkFlag string) error { - if err := docker.StopDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout); err != nil { + avagoConf := remoteconfig.DefaultCliAvalancheConfig(host.IP, networkID, subnetIDs) + nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf) + if err != nil { return err } - if _, err := host.Command(fmt.Sprintf("/home/ubuntu/bin/avalanche subnet join %s %s --avalanchego-config /home/ubuntu/.avalanchego/configs/node.json --plugin-dir /home/ubuntu/.avalanchego/plugins --force-write", subnetName, networkFlag), nil, constants.SSHScriptTimeout); err != nil { + if err := os.WriteFile(nodeConfFile.Name(), nodeConf, constants.WriteReadUserOnlyPerms); err != nil { return err } - return docker.StartDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout) + return host.Upload(nodeConfFile.Name(), remoteconfig.GetRemoteAvalancheNodeConfig(), constants.SSHFileOpsTimeout) } -// RunSSHUpdateSubnet runs avalanche subnet join in cloud server using update subnet info -func RunSSHUpdateSubnet(host *models.Host, subnetName string) error { - if err := docker.StopDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout); err != nil { +// RunSSHSyncSubnetData syncs subnet data required +func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, networkID string, subnetName string) error { + sc, err := app.LoadSidecar(subnetName) + if err != nil { return err } - if _, err := host.Command(fmt.Sprintf("/home/ubuntu/bin/avalanche subnet join %s --fuji --avalanchego-config /home/ubuntu/.avalanchego/configs/node.json --plugin-dir /home/ubuntu/.avalanchego/plugins --force-write", subnetName), nil, constants.SSHScriptTimeout); err != nil { + subnetID := sc.Networks[networkID].SubnetID + if subnetID == ids.Empty { + return errors.New("subnet id is empty") + } + subnetIDStr := subnetID.String() + blockchainID := sc.Networks[networkID].BlockchainID + // genesis config + genData, err := app.LoadRawGenesis(subnetName) + if err != nil { return err } - return docker.StartDockerComposeService(host, utils.GetRemoteComposeFile(), "avalanchego", constants.SSHLongRunningScriptTimeout) + genesisFile, err := os.CreateTemp("", "avalanchecli-genesis-*.json") + if err != nil { + return err + } + defer os.Remove(genesisFile.Name()) + if err := os.WriteFile(genesisFile.Name(), genData, constants.WriteReadUserOnlyPerms); err != nil { + return err + } + if err := host.Upload(genesisFile.Name(), remoteconfig.GetRemoteAvalancheGenesis(), constants.SSHFileOpsTimeout); err != nil { + return err + } + // end genesis config + // subnet config + if app.AvagoSubnetConfigExists(subnetName) { + subnetConfig, err := app.LoadRawAvagoSubnetConfig(subnetName) + if err != nil { + return err + } + subnetConfigFile, err := os.CreateTemp("", "avalanchecli-subnet-*.json") + if err != nil { + return err + } + defer os.Remove(subnetConfigFile.Name()) + if err := os.WriteFile(subnetConfigFile.Name(), subnetConfig, constants.WriteReadUserOnlyPerms); err != nil { + return err + } + + subnetConfigPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", subnetIDStr+".json") + if err := host.MkdirAll(filepath.Base(subnetConfigPath), constants.SSHDirOpsTimeout); err != nil { + return err + } + if err := host.Upload(subnetConfigFile.Name(), subnetConfigPath, constants.SSHFileOpsTimeout); err != nil { + return err + } + } + // end subnet config + + // chain config + if blockchainID != ids.Empty && app.ChainConfigExists(subnetName) { + chainConfigFile, err := os.CreateTemp("", "avalanchecli-chain-*.json") + if err != nil { + return err + } + defer os.Remove(chainConfigFile.Name()) + chainConfig, err := app.LoadRawChainConfig(subnetName) + if err != nil { + return err + } + if err := os.WriteFile(chainConfigFile.Name(), chainConfig, constants.WriteReadUserOnlyPerms); err != nil { + return err + } + chainConfigPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", "chains", blockchainID.String(), "config.json") + if err := host.MkdirAll(filepath.Base(chainConfigPath), constants.SSHDirOpsTimeout); err != nil { + return err + } + if err := host.Upload(chainConfigFile.Name(), chainConfigPath, constants.SSHFileOpsTimeout); err != nil { + return err + } + } + // end chain config + + // network upgrade + if app.NetworkUpgradeExists(subnetName) { + networkUpgradesFile, err := os.CreateTemp("", "avalanchecli-network-*.json") + if err != nil { + return err + } + defer os.Remove(networkUpgradesFile.Name()) + networkUpgrades, err := app.LoadRawNetworkUpgrades(subnetName) + if err != nil { + return err + } + if err := os.WriteFile(networkUpgradesFile.Name(), networkUpgrades, constants.WriteReadUserOnlyPerms); err != nil { + return err + } + networkUpgradesPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", "chains", blockchainID.String(), "upgrade.json") + if err := host.MkdirAll(filepath.Base(networkUpgradesPath), constants.SSHDirOpsTimeout); err != nil { + return err + } + if err := host.Upload(networkUpgradesFile.Name(), networkUpgradesPath, constants.SSHFileOpsTimeout); err != nil { + return err + } + } + // end network upgrade + + return nil } func RunSSHBuildLoadTestCode(host *models.Host, loadTestRepo, loadTestPath, loadTestGitCommit, repoDirName, loadTestBranch string, checkoutCommit bool) error { From c8efd31ffb13e9c8b198b6d6b76ad5ffcedf7f01 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Fri, 5 Jul 2024 15:53:31 -0700 Subject: [PATCH 04/24] add prepare subnet plugin --- cmd/nodecmd/sync.go | 33 +++++++++++++++++++++++++++++++++ pkg/constants/constants.go | 1 + 2 files changed, 34 insertions(+) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index cdafc4a2a..57cf6ae7b 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -9,7 +9,9 @@ import ( "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/ansible" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" + "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" + "github.com/ava-labs/avalanche-cli/pkg/plugins" "github.com/ava-labs/avalanche-cli/pkg/ssh" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -69,6 +71,9 @@ func syncSubnet(_ *cobra.Command, args []string) error { return err } } + if err := prepareSubnetPlugin(hosts, subnetName); err != nil { + return err + } untrackedNodes, err := trackSubnet(hosts, clusterName, clusterConfig.Network.NetworkIDFlagValue(), subnetName) if err != nil { return err @@ -81,6 +86,34 @@ func syncSubnet(_ *cobra.Command, args []string) error { return nil } +func prepareSubnetPlugin(hosts []*models.Host, subnetName string) error { + pluginDir := app.GetTmpPluginDir() + sc, err := app.LoadSidecar(subnetName) + if err != nil { + return err + } + vmPath, err := plugins.CreatePlugin(app, sc.Name, pluginDir) + if err != nil { + return err + } + wg := sync.WaitGroup{} + wgResults := models.NodeResults{} + for _, host := range hosts { + wg.Add(1) + go func(nodeResults *models.NodeResults, host *models.Host) { + defer wg.Done() + if err := host.Upload(vmPath, constants.CloudNodePluginsPath, constants.SSHFileOpsTimeout); err != nil { + nodeResults.AddResult(host.NodeID, nil, err) + } + }(&wgResults, host) + } + wg.Wait() + if wgResults.HasErrors() { + return fmt.Errorf("failed to upload plugin to node(s) %s", wgResults.GetErrorHostMap()) + } + return nil +} + // trackSubnet exports deployed subnet in user's local machine to cloud server and calls node to // start tracking the specified subnet (similar to avalanche subnet join command) func trackSubnet( diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 1df0996e9..220c6e9d7 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -216,6 +216,7 @@ const ( CloudNodeSubnetEvmBinaryPath = "/home/ubuntu/.avalanchego/plugins/%s" CloudNodeStakingPath = "/home/ubuntu/.avalanchego/staking/" CloudNodeConfigPath = "/home/ubuntu/.avalanchego/configs/" + CloudNodePluginsPath = "/home/ubuntu/.avalanchego/plugins/" DockerNodeConfigPath = "/.avalanchego/configs/" CloudNodePrometheusConfigPath = "/etc/prometheus/prometheus.yml" CloudNodeCLIConfigBasePath = "/home/ubuntu/.avalanche-cli/" From 9b7bbe104458acab75d987d57ea5ceb1b0f5ae97 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Tue, 9 Jul 2024 10:47:04 -0700 Subject: [PATCH 05/24] fixes --- pkg/docker/config.go | 2 +- pkg/remoteconfig/avalanche.go | 7 ++++--- pkg/remoteconfig/templates/avalanche-node.tmpl | 2 +- pkg/ssh/ssh.go | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/pkg/docker/config.go b/pkg/docker/config.go index dbbefd7d6..125e43b2f 100644 --- a/pkg/docker/config.go +++ b/pkg/docker/config.go @@ -12,7 +12,7 @@ import ( ) func prepareAvalanchegoConfig(host *models.Host, networkID string) (string, string, error) { - avagoConf := remoteconfig.DefaultCliAvalancheConfig(host.IP, networkID, nil) + avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, networkID, nil) nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf) if err != nil { return "", "", err diff --git a/pkg/remoteconfig/avalanche.go b/pkg/remoteconfig/avalanche.go index aa09ca5ea..ba758c99e 100644 --- a/pkg/remoteconfig/avalanche.go +++ b/pkg/remoteconfig/avalanche.go @@ -7,6 +7,7 @@ import ( "bytes" "html/template" "path/filepath" + "strings" "github.com/ava-labs/avalanche-cli/pkg/constants" ) @@ -21,10 +22,10 @@ type AvalancheConfigInputs struct { PublicIP string StateSyncEnabled bool PruningEnabled bool - TrackSubents []string + TrackSubnets string } -func DefaultCliAvalancheConfig(publicIP string, networkID string, subnets []string) AvalancheConfigInputs { +func PrepareAvalancheConfig(publicIP string, networkID string, subnets []string) AvalancheConfigInputs { return AvalancheConfigInputs{ HTTPHost: "0.0.0.0", NetworkID: networkID, @@ -33,7 +34,7 @@ func DefaultCliAvalancheConfig(publicIP string, networkID string, subnets []stri PublicIP: publicIP, StateSyncEnabled: true, PruningEnabled: false, - TrackSubents: subnets, + TrackSubnets: strings.Join(subnets, ","), } } diff --git a/pkg/remoteconfig/templates/avalanche-node.tmpl b/pkg/remoteconfig/templates/avalanche-node.tmpl index a74b907f6..fd2a8c7c4 100644 --- a/pkg/remoteconfig/templates/avalanche-node.tmpl +++ b/pkg/remoteconfig/templates/avalanche-node.tmpl @@ -11,6 +11,6 @@ "public-ip-resolution-service": "opendns" {{- end -}} {{- if .TrackSubnets }} - "track-subnets": "{{ join .TrackSubnets ", " }}" + "track-subnets": "{{ .TrackSubnets }}" {{- end }} } diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 7047e2892..7f6f32e24 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -510,7 +510,7 @@ func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Ho } defer os.Remove(nodeConfFile.Name()) - avagoConf := remoteconfig.DefaultCliAvalancheConfig(host.IP, networkID, subnetIDs) + avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, networkID, subnetIDs) nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf) if err != nil { return err From b134a47f08eb7d980221e0c390c5d287f3f3e5d3 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Wed, 10 Jul 2024 16:31:46 -0700 Subject: [PATCH 06/24] ready for testing --- cmd/nodecmd/sync.go | 10 +--- pkg/ssh/installer.go | 28 ++++++++++ pkg/ssh/shell/buildCustomVM.sh | 16 ++++++ pkg/ssh/shell/buildLoadTest.sh | 2 +- pkg/ssh/shell/getNewSubnetEVMRelease.sh | 2 +- pkg/ssh/shell/upgradeSubnetEVM.sh | 4 ++ pkg/ssh/ssh.go | 70 ++++++++++++++++++++++++- 7 files changed, 120 insertions(+), 12 deletions(-) create mode 100644 pkg/ssh/installer.go create mode 100644 pkg/ssh/shell/buildCustomVM.sh create mode 100644 pkg/ssh/shell/upgradeSubnetEVM.sh diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index 57cf6ae7b..29e645d22 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -9,9 +9,7 @@ import ( "github.com/ava-labs/avalanche-cli/cmd/subnetcmd" "github.com/ava-labs/avalanche-cli/pkg/ansible" "github.com/ava-labs/avalanche-cli/pkg/cobrautils" - "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" - "github.com/ava-labs/avalanche-cli/pkg/plugins" "github.com/ava-labs/avalanche-cli/pkg/ssh" "github.com/ava-labs/avalanche-cli/pkg/utils" "github.com/ava-labs/avalanche-cli/pkg/ux" @@ -86,23 +84,19 @@ func syncSubnet(_ *cobra.Command, args []string) error { return nil } +// prepareSubnetPlugin creates subnet plugin to all nodes in the cluster func prepareSubnetPlugin(hosts []*models.Host, subnetName string) error { - pluginDir := app.GetTmpPluginDir() sc, err := app.LoadSidecar(subnetName) if err != nil { return err } - vmPath, err := plugins.CreatePlugin(app, sc.Name, pluginDir) - if err != nil { - return err - } wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { wg.Add(1) go func(nodeResults *models.NodeResults, host *models.Host) { defer wg.Done() - if err := host.Upload(vmPath, constants.CloudNodePluginsPath, constants.SSHFileOpsTimeout); err != nil { + if err := ssh.RunSSHCreatePlugin(host, sc); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } }(&wgResults, host) diff --git a/pkg/ssh/installer.go b/pkg/ssh/installer.go new file mode 100644 index 000000000..57d6b7c86 --- /dev/null +++ b/pkg/ssh/installer.go @@ -0,0 +1,28 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package ssh + +import ( + "github.com/ava-labs/avalanche-cli/pkg/constants" + "github.com/ava-labs/avalanche-cli/pkg/models" +) + +type HostInstaller struct { + Host *models.Host +} + +func NewHostInstaller(host *models.Host) *HostInstaller { + return &HostInstaller{Host: host} +} + +func (h *HostInstaller) GetArch() (string, string) { + goArhBytes, err := h.Host.Command("go env GOARCH", nil, constants.SSHScriptTimeout) + if err != nil { + return "", "" + } + goOSBytes, err := h.Host.Command("go env GOOS", nil, constants.SSHScriptTimeout) + if err != nil { + return "", "" + } + return string(goArhBytes), string(goOSBytes) +} diff --git a/pkg/ssh/shell/buildCustomVM.sh b/pkg/ssh/shell/buildCustomVM.sh new file mode 100644 index 000000000..3c4afde0a --- /dev/null +++ b/pkg/ssh/shell/buildCustomVM.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +if [ -d {{ .CustomVMRepoDir }} ]; then + rm -rf {{ .LoadTestRepoDir }} +fi + +cd {{ .CustomVMRepoDir }} +git remote init -q +git remote add origin {{ .CustomVMRepoURL }} +git fetch --depth 1 origin {{ .CustomVMBranch }} -q +git checkout {{ .CustomVMBranch }} +chmod +x {{ .CustomVMBuildScript }} +./{{ .CustomVMBuildScript }} {{ .CustomVMPath }} +echo {{ .CustomVMPath }} [ok] + + diff --git a/pkg/ssh/shell/buildLoadTest.sh b/pkg/ssh/shell/buildLoadTest.sh index 5569c25ac..ed610a73b 100644 --- a/pkg/ssh/shell/buildLoadTest.sh +++ b/pkg/ssh/shell/buildLoadTest.sh @@ -2,7 +2,7 @@ # delete existing repo directory if it exists # choosing to delete and re-clone to avoid merge conflicts if [ -d {{ .LoadTestRepoDir }} ]; then - rm -r {{ .LoadTestRepoDir }} + rm -rf {{ .LoadTestRepoDir }} fi git clone {{ .LoadTestRepo }} echo "getting load test repo ..." diff --git a/pkg/ssh/shell/getNewSubnetEVMRelease.sh b/pkg/ssh/shell/getNewSubnetEVMRelease.sh index 76072e39a..caecedb7b 100644 --- a/pkg/ssh/shell/getNewSubnetEVMRelease.sh +++ b/pkg/ssh/shell/getNewSubnetEVMRelease.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -e #name:TASK [download new subnet EVM release] -wget -N "{{ .SubnetEVMReleaseURL }}" +busybox wget "{{ .SubnetEVMReleaseURL }}" -O "{{ .SubnetEVMArchive }}" #name:TASK [unpack new subnet EVM release] tar xvf "{{ .SubnetEVMArchive}}" diff --git a/pkg/ssh/shell/upgradeSubnetEVM.sh b/pkg/ssh/shell/upgradeSubnetEVM.sh new file mode 100644 index 000000000..05ba3634e --- /dev/null +++ b/pkg/ssh/shell/upgradeSubnetEVM.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +set -e +#name:TASK [upgrade avalanchego version] +cp -f subnet-evm {{ .VMBinaryPath }} diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 7f6f32e24..de1010dff 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -16,6 +16,7 @@ import ( "time" "github.com/ava-labs/avalanche-cli/pkg/application" + "github.com/ava-labs/avalanche-cli/pkg/binutils" "github.com/ava-labs/avalanche-cli/pkg/docker" "github.com/ava-labs/avalanche-cli/pkg/monitoring" "github.com/ava-labs/avalanche-cli/pkg/remoteconfig" @@ -38,7 +39,7 @@ type scriptInputs struct { IsDevNet bool IsE2E bool NetworkFlag string - SubnetEVMBinaryPath string + VMBinaryPath string SubnetEVMReleaseURL string SubnetEVMArchive string MonitoringDashboardPath string @@ -51,6 +52,10 @@ type scriptInputs struct { CheckoutCommit bool LoadTestResultFile string GrafanaPkg string + CustomVMRepoDir string + CustomVMRepoURL string + CustomVMBranch string + CustomVMBuildScript string } //go:embed shell/*.sh @@ -219,7 +224,7 @@ func RunSSHUpgradeSubnetEVM(host *models.Host, subnetEVMBinaryPath string) error host, constants.SSHScriptTimeout, "shell/upgradeSubnetEVM.sh", - scriptInputs{SubnetEVMBinaryPath: subnetEVMBinaryPath}, + scriptInputs{VMBinaryPath: subnetEVMBinaryPath}, ) } @@ -521,6 +526,67 @@ func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Ho return host.Upload(nodeConfFile.Name(), remoteconfig.GetRemoteAvalancheNodeConfig(), constants.SSHFileOpsTimeout) } +// RunSSHCreatePlugin runs script to create plugin +func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error { + vmID, err := sc.GetVMID() + if err != nil { + return err + } + subnetVMBinaryPath := fmt.Sprintf(constants.CloudNodeSubnetEvmBinaryPath, vmID) + hostInstaller := NewHostInstaller(host) + tmpDir, err := host.CreateTempDir() + if err != nil { + return err + } + defer func(h *models.Host) { + _ = h.Remove(tmpDir, true) + }(host) + switch { + case sc.VM == models.CustomVM: + if err := RunOverSSH( + "Build CustomVMe", + host, + constants.SSHLongRunningScriptTimeout, + "shell/buildCustomVM.sh", + scriptInputs{ + CustomVMRepoDir: tmpDir, + CustomVMRepoURL: sc.CustomVMRepoURL, + CustomVMBranch: sc.CustomVMBranch, + CustomVMBuildScript: sc.CustomVMBuildScript, + VMBinaryPath: subnetVMBinaryPath, + }, + ); err != nil { + return err + } + + case sc.VM == models.SubnetEvm: + dl := binutils.NewSubnetEVMDownloader() + installURL, _, err := dl.GetDownloadURL(sc.VMVersion, hostInstaller) // extension is tar.gz + if err != nil { + return err + } + + archiveName := "subnet-evm.tar.gz" + archiveFullPath := filepath.Join(tmpDir, archiveName) + + // download and install subnet evm + if _, err := host.Command(fmt.Sprintf("%s %s -O %s", "busybox wget", installURL, archiveFullPath), nil, constants.SSHLongRunningScriptTimeout); err != nil { + return err + } + if _, err := host.Command(fmt.Sprintf("tar -xzf %s -C %s", archiveFullPath, tmpDir), nil, constants.SSHLongRunningScriptTimeout); err != nil { + return err + } + + if _, err := host.Command(fmt.Sprintf("mv -f %s/subnet-evm %s", tmpDir, subnetVMBinaryPath), nil, constants.SSHLongRunningScriptTimeout); err != nil { + return err + } + default: + return fmt.Errorf("unexpected error: unsupported VM type: %s", sc.VM) + } + + return nil +} + // RunSSHSyncSubnetData syncs subnet data required func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, networkID string, subnetName string) error { sc, err := app.LoadSidecar(subnetName) From 3249c358f71cf86c14691967b1db98a1a8d45d1d Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 11:47:20 -0700 Subject: [PATCH 07/24] fix --- pkg/ssh/installer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/ssh/installer.go b/pkg/ssh/installer.go index 57d6b7c86..9c4b10b65 100644 --- a/pkg/ssh/installer.go +++ b/pkg/ssh/installer.go @@ -3,6 +3,8 @@ package ssh import ( + "strings" + "github.com/ava-labs/avalanche-cli/pkg/constants" "github.com/ava-labs/avalanche-cli/pkg/models" ) @@ -24,5 +26,5 @@ func (h *HostInstaller) GetArch() (string, string) { if err != nil { return "", "" } - return string(goArhBytes), string(goOSBytes) + return strings.TrimSpace(string(goArhBytes)), strings.TrimSpace(string(goOSBytes)) } From 004e704a17b12e437f61030ddda50228728fac3d Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 12:20:56 -0700 Subject: [PATCH 08/24] fix template comma --- pkg/remoteconfig/templates/avalanche-node.tmpl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/remoteconfig/templates/avalanche-node.tmpl b/pkg/remoteconfig/templates/avalanche-node.tmpl index fd2a8c7c4..85d9d8e0c 100644 --- a/pkg/remoteconfig/templates/avalanche-node.tmpl +++ b/pkg/remoteconfig/templates/avalanche-node.tmpl @@ -3,14 +3,14 @@ "api-admin-enabled": {{.APIAdminEnabled}}, "index-enabled": {{.IndexEnabled}}, "network-id": "{{if .NetworkID}}{{.NetworkID}}{{else}}fuji{{end}}", - "db-dir": "{{.DBDir}}", - "log-dir": "{{.LogDir}}", -{{- if .PublicIP -}} - "public-ip": "{{.PublicIP}}" -{{- else -}} - "public-ip-resolution-service": "opendns" -{{- end -}} +{{- if .PublicIP }} + "public-ip": "{{.PublicIP}}", +{{- else }} + "public-ip-resolution-service": "opendns", +{{- end }} {{- if .TrackSubnets }} - "track-subnets": "{{ .TrackSubnets }}" -{{- end }} + "track-subnets": "{{ .TrackSubnets }}", +{{- end }} + "db-dir": "{{.DBDir}}", + "log-dir": "{{.LogDir}}" } From 06a551058d698f97a91e07510ecfa7d453dc993b Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 12:39:58 -0700 Subject: [PATCH 09/24] models.Network --- cmd/nodecmd/sync.go | 8 ++++---- cmd/nodecmd/updateSubnet.go | 8 ++++---- pkg/remoteconfig/templates/avalanche-node.tmpl | 2 +- pkg/ssh/ssh.go | 17 ++++++++--------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index 29e645d22..a5928ae60 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -72,7 +72,7 @@ func syncSubnet(_ *cobra.Command, args []string) error { if err := prepareSubnetPlugin(hosts, subnetName); err != nil { return err } - untrackedNodes, err := trackSubnet(hosts, clusterName, clusterConfig.Network.NetworkIDFlagValue(), subnetName) + untrackedNodes, err := trackSubnet(hosts, clusterName, clusterConfig.Network, subnetName) if err != nil { return err } @@ -113,7 +113,7 @@ func prepareSubnetPlugin(hosts []*models.Host, subnetName string) error { func trackSubnet( hosts []*models.Host, clusterName string, - networkID string, + network models.Network, subnetName string, ) ([]string, error) { // load cluster config @@ -133,10 +133,10 @@ func trackSubnet( if err := ssh.RunSSHStopNode(host); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } - if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, networkID, allSubnets); err != nil { + if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, network, allSubnets); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } - if err := ssh.RunSSHSyncSubnetData(app, host, networkID, subnetName); err != nil { + if err := ssh.RunSSHSyncSubnetData(app, host, network, subnetName); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } if err := ssh.RunSSHStartNode(host); err != nil { diff --git a/cmd/nodecmd/updateSubnet.go b/cmd/nodecmd/updateSubnet.go index 9b6c3db03..d51f06538 100644 --- a/cmd/nodecmd/updateSubnet.go +++ b/cmd/nodecmd/updateSubnet.go @@ -58,7 +58,7 @@ func updateSubnet(_ *cobra.Command, args []string) error { if err := checkHostsAreRPCCompatible(hosts, subnetName); err != nil { return err } - nonUpdatedNodes, err := doUpdateSubnet(hosts, clusterName, clusterConfig.Network.NetworkIDFlagValue(), subnetName) + nonUpdatedNodes, err := doUpdateSubnet(hosts, clusterName, clusterConfig.Network, subnetName) if err != nil { return err } @@ -75,7 +75,7 @@ func updateSubnet(_ *cobra.Command, args []string) error { func doUpdateSubnet( hosts []*models.Host, clusterName string, - networkID string, + network models.Network, subnetName string, ) ([]string, error) { // load cluster config @@ -95,10 +95,10 @@ func doUpdateSubnet( if err := ssh.RunSSHStopNode(host); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } - if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, networkID, allSubnets); err != nil { + if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, network, allSubnets); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } - if err := ssh.RunSSHSyncSubnetData(app, host, networkID, subnetName); err != nil { + if err := ssh.RunSSHSyncSubnetData(app, host, network, subnetName); err != nil { nodeResults.AddResult(host.NodeID, nil, err) } if err := ssh.RunSSHStartNode(host); err != nil { diff --git a/pkg/remoteconfig/templates/avalanche-node.tmpl b/pkg/remoteconfig/templates/avalanche-node.tmpl index 85d9d8e0c..98acdb047 100644 --- a/pkg/remoteconfig/templates/avalanche-node.tmpl +++ b/pkg/remoteconfig/templates/avalanche-node.tmpl @@ -4,7 +4,7 @@ "index-enabled": {{.IndexEnabled}}, "network-id": "{{if .NetworkID}}{{.NetworkID}}{{else}}fuji{{end}}", {{- if .PublicIP }} - "public-ip": "{{.PublicIP}}", + "public-ip": "{{.PublicIP}}", {{- else }} "public-ip-resolution-service": "opendns", {{- end }} diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index de1010dff..e7c893b1a 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -5,7 +5,6 @@ package ssh import ( "bytes" "embed" - "errors" "fmt" "net/url" "os" @@ -495,14 +494,14 @@ func RunSSHUploadStakingFiles(host *models.Host, nodeInstanceDirPath string) err } // RunSSHRenderAvalancheNodeConfig renders avalanche node config to a remote host via SSH. -func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Host, networkID string, trackSubnets []string) error { +func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Host, network models.Network, trackSubnets []string) error { // get subnet ids subnetIDs, err := utils.MapWithError(trackSubnets, func(subnetName string) (string, error) { sc, err := app.LoadSidecar(subnetName) if err != nil { return "", err } else { - return sc.Networks[networkID].SubnetID.String(), nil + return sc.Networks[network.Name()].SubnetID.String(), nil } }) if err != nil { @@ -515,7 +514,7 @@ func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Ho } defer os.Remove(nodeConfFile.Name()) - avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, networkID, subnetIDs) + avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, network.NetworkIDFlagValue(), subnetIDs) nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf) if err != nil { return err @@ -588,17 +587,17 @@ func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error { } // RunSSHSyncSubnetData syncs subnet data required -func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, networkID string, subnetName string) error { +func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network models.Network, subnetName string) error { sc, err := app.LoadSidecar(subnetName) if err != nil { return err } - subnetID := sc.Networks[networkID].SubnetID - if subnetID == ids.Empty { + subnetID := sc.Networks[network.Name()].SubnetID + /*if subnetID == ids.Empty { return errors.New("subnet id is empty") - } + }*/ subnetIDStr := subnetID.String() - blockchainID := sc.Networks[networkID].BlockchainID + blockchainID := sc.Networks[network.Name()].BlockchainID // genesis config genData, err := app.LoadRawGenesis(subnetName) if err != nil { From 266093d6a594b8c4afdadeda68352ed9d944c9a0 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 13:26:31 -0700 Subject: [PATCH 10/24] add bootstrap data and genesis to remote config --- pkg/remoteconfig/avalanche.go | 3 ++ .../templates/avalanche-node.tmpl | 9 ++++ pkg/ssh/ssh.go | 42 +++++++++++++++++++ pkg/utils/common.go | 8 ++++ 4 files changed, 62 insertions(+) diff --git a/pkg/remoteconfig/avalanche.go b/pkg/remoteconfig/avalanche.go index ba758c99e..9c980c8e4 100644 --- a/pkg/remoteconfig/avalanche.go +++ b/pkg/remoteconfig/avalanche.go @@ -23,6 +23,9 @@ type AvalancheConfigInputs struct { StateSyncEnabled bool PruningEnabled bool TrackSubnets string + BootstrapIDs string + BootstrapIPs string + GenesisPath string } func PrepareAvalancheConfig(publicIP string, networkID string, subnets []string) AvalancheConfigInputs { diff --git a/pkg/remoteconfig/templates/avalanche-node.tmpl b/pkg/remoteconfig/templates/avalanche-node.tmpl index 98acdb047..c5704fd1f 100644 --- a/pkg/remoteconfig/templates/avalanche-node.tmpl +++ b/pkg/remoteconfig/templates/avalanche-node.tmpl @@ -3,6 +3,15 @@ "api-admin-enabled": {{.APIAdminEnabled}}, "index-enabled": {{.IndexEnabled}}, "network-id": "{{if .NetworkID}}{{.NetworkID}}{{else}}fuji{{end}}", +{{- if .BootstrapIDs }} + "bootstrap-ids": "{{ .BootstrapIDs }}", +{{- end }} +{{- if .BootstrapIPs }} + "bootstrap-ips": "{{ .BootstrapIPs }}", +{{- end }} +{{- if .GenesisPath }} + "genesis-file": "{{ .GenesisPath }}", +{{- end }} {{- if .PublicIP }} "public-ip": "{{.PublicIP}}", {{- else }} diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index e7c893b1a..9b2cb2821 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -5,6 +5,7 @@ package ssh import ( "bytes" "embed" + "encoding/json" "fmt" "net/url" "os" @@ -515,6 +516,19 @@ func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Ho defer os.Remove(nodeConfFile.Name()) avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, network.NetworkIDFlagValue(), subnetIDs) + // make sure that genesis and bootstrap data is preserved + if genesisFileExists(host) { + avagoConf.GenesisPath = filepath.Join(constants.CloudNodeConfigPath, constants.GenesisFileName) + } + remoteAvagoConfFile, err := getAvalancheGoConfigData(host) + if err != nil { + return err + } + bootstrapIDs, _ := utils.GetValueString(remoteAvagoConfFile, "bootstrap-ids") + bootstrapIPs, _ := utils.GetValueString(remoteAvagoConfFile, "bootstrap-ips") + avagoConf.BootstrapIDs = bootstrapIDs + avagoConf.BootstrapIPs = bootstrapIPs + // ready to render node config nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf) if err != nil { return err @@ -853,3 +867,31 @@ func composeFileExists(host *models.Host) bool { composeFileExists, _ := host.FileExists(utils.GetRemoteComposeFile()) return composeFileExists } + +func genesisFileExists(host *models.Host) bool { + genesisFileExists, _ := host.FileExists(filepath.Join(constants.CloudNodeConfigPath, constants.GenesisFileName)) + return genesisFileExists +} + +func getAvalancheGoConfigData(host *models.Host) (map[string]interface{}, error) { + //get remote node.json file + nodeJSONPath := filepath.Join(constants.CloudNodeConfigPath, constants.NodeFileName) + tmpFile, err := os.CreateTemp("", "avalanchecli-node-*.json") + if err != nil { + return nil, err + } + defer os.Remove(tmpFile.Name()) + if err := host.Download(nodeJSONPath, tmpFile.Name(), constants.SSHFileOpsTimeout); err != nil { + return nil, err + } + //parse node.json file + nodeJSON, err := os.ReadFile(tmpFile.Name()) + if err != nil { + return nil, err + } + var avagoConfig map[string]interface{} + if err := json.Unmarshal(nodeJSON, &avagoConfig); err != nil { + return nil, err + } + return avagoConfig, nil +} diff --git a/pkg/utils/common.go b/pkg/utils/common.go index 0380056aa..d4ba63b6b 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -559,3 +559,11 @@ func Command(cmdLine string, params ...string) *exec.Cmd { c.Env = os.Environ() return c } + +// GetValueString returns the value of a key in a map as a string. +func GetValueString(data map[string]interface{}, key string) (string, error) { + if value, ok := data[key]; ok { + return fmt.Sprintf("%v", value), nil + } + return "", fmt.Errorf("key %s not found", key) +} From bca0821928204c6589ab8e05378980412892b427 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 13:26:53 -0700 Subject: [PATCH 11/24] lint --- pkg/ssh/ssh.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 9b2cb2821..b383d0fcd 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -874,7 +874,7 @@ func genesisFileExists(host *models.Host) bool { } func getAvalancheGoConfigData(host *models.Host) (map[string]interface{}, error) { - //get remote node.json file + // get remote node.json file nodeJSONPath := filepath.Join(constants.CloudNodeConfigPath, constants.NodeFileName) tmpFile, err := os.CreateTemp("", "avalanchecli-node-*.json") if err != nil { @@ -884,7 +884,7 @@ func getAvalancheGoConfigData(host *models.Host) (map[string]interface{}, error) if err := host.Download(nodeJSONPath, tmpFile.Name(), constants.SSHFileOpsTimeout); err != nil { return nil, err } - //parse node.json file + // parse node.json file nodeJSON, err := os.ReadFile(tmpFile.Name()) if err != nil { return nil, err From 3404f3c520dbbc3b6cbccec5fbba2b689641c291 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 14:02:39 -0700 Subject: [PATCH 12/24] fix genesis --- pkg/ssh/ssh.go | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index b383d0fcd..41f956f41 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -6,6 +6,7 @@ import ( "bytes" "embed" "encoding/json" + "errors" "fmt" "net/url" "os" @@ -518,7 +519,7 @@ func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Ho avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, network.NetworkIDFlagValue(), subnetIDs) // make sure that genesis and bootstrap data is preserved if genesisFileExists(host) { - avagoConf.GenesisPath = filepath.Join(constants.CloudNodeConfigPath, constants.GenesisFileName) + avagoConf.GenesisPath = filepath.Join(constants.DockerNodeConfigPath, constants.GenesisFileName) } remoteAvagoConfFile, err := getAvalancheGoConfigData(host) if err != nil { @@ -607,25 +608,14 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } subnetID := sc.Networks[network.Name()].SubnetID - /*if subnetID == ids.Empty { + if subnetID == ids.Empty { return errors.New("subnet id is empty") - }*/ + } subnetIDStr := subnetID.String() blockchainID := sc.Networks[network.Name()].BlockchainID // genesis config - genData, err := app.LoadRawGenesis(subnetName) - if err != nil { - return err - } - genesisFile, err := os.CreateTemp("", "avalanchecli-genesis-*.json") - if err != nil { - return err - } - defer os.Remove(genesisFile.Name()) - if err := os.WriteFile(genesisFile.Name(), genData, constants.WriteReadUserOnlyPerms); err != nil { - return err - } - if err := host.Upload(genesisFile.Name(), remoteconfig.GetRemoteAvalancheGenesis(), constants.SSHFileOpsTimeout); err != nil { + genesisFilename := filepath.Join(constants.CloudNodeConfigPath, constants.GenesisFileName) + if err := host.Upload(genesisFilename, remoteconfig.GetRemoteAvalancheGenesis(), constants.SSHFileOpsTimeout); err != nil { return err } // end genesis config @@ -643,7 +633,6 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network if err := os.WriteFile(subnetConfigFile.Name(), subnetConfig, constants.WriteReadUserOnlyPerms); err != nil { return err } - subnetConfigPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", subnetIDStr+".json") if err := host.MkdirAll(filepath.Base(subnetConfigPath), constants.SSHDirOpsTimeout); err != nil { return err From 50b4aa30f936eb7f13c4d689ca3f3759de36981f Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 14:13:09 -0700 Subject: [PATCH 13/24] fix local genesis name --- pkg/ssh/ssh.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 41f956f41..cdd860712 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -614,7 +614,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network subnetIDStr := subnetID.String() blockchainID := sc.Networks[network.Name()].BlockchainID // genesis config - genesisFilename := filepath.Join(constants.CloudNodeConfigPath, constants.GenesisFileName) + genesisFilename := filepath.Join(app.GetNodesDir(), host.GetCloudID(), constants.GenesisFileName) if err := host.Upload(genesisFilename, remoteconfig.GetRemoteAvalancheGenesis(), constants.SSHFileOpsTimeout); err != nil { return err } From edae2e252c69f14c726113a644ddc19c7feacb5e Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 14:19:42 -0700 Subject: [PATCH 14/24] make sure that subnet folder has latest genesis file on disk --- cmd/nodecmd/create_devnet.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/nodecmd/create_devnet.go b/cmd/nodecmd/create_devnet.go index fb7360dc6..1582867a9 100644 --- a/cmd/nodecmd/create_devnet.go +++ b/cmd/nodecmd/create_devnet.go @@ -204,6 +204,10 @@ func setupDevnet(clusterName string, hosts []*models.Host, apiNodeIPMap map[stri if err != nil { return err } + // make sure that custom genesis is saved to the subnet dir + if err := os.WriteFile(app.GetGenesisPath(subnetName), genesisBytes, constants.WriteReadReadPerms); err != nil { + return err + } // create avalanchego conf node.json at each node dir bootstrapIPs := []string{} From aebf6714473c71773bef1c5047b1e4c3a8dec0ab Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 14:48:17 -0700 Subject: [PATCH 15/24] fix custom VM path --- pkg/ssh/shell/buildCustomVM.sh | 4 ++-- pkg/ssh/ssh.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/ssh/shell/buildCustomVM.sh b/pkg/ssh/shell/buildCustomVM.sh index 3c4afde0a..cbeb79e91 100644 --- a/pkg/ssh/shell/buildCustomVM.sh +++ b/pkg/ssh/shell/buildCustomVM.sh @@ -10,7 +10,7 @@ git remote add origin {{ .CustomVMRepoURL }} git fetch --depth 1 origin {{ .CustomVMBranch }} -q git checkout {{ .CustomVMBranch }} chmod +x {{ .CustomVMBuildScript }} -./{{ .CustomVMBuildScript }} {{ .CustomVMPath }} -echo {{ .CustomVMPath }} [ok] +./{{ .CustomVMBuildScript }} {{ .VMBinaryPath }} +echo {{ .VMBinaryPath }} [ok] diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index cdd860712..5ec3085c0 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -558,7 +558,7 @@ func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error { switch { case sc.VM == models.CustomVM: if err := RunOverSSH( - "Build CustomVMe", + "Build CustomVM", host, constants.SSHLongRunningScriptTimeout, "shell/buildCustomVM.sh", From b9a6d93ba7fd02e211852c86552ed855872a4f2b Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 15:12:25 -0700 Subject: [PATCH 16/24] better error messages --- pkg/ssh/ssh.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 5ec3085c0..ec1d70d70 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -616,14 +616,14 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network // genesis config genesisFilename := filepath.Join(app.GetNodesDir(), host.GetCloudID(), constants.GenesisFileName) if err := host.Upload(genesisFilename, remoteconfig.GetRemoteAvalancheGenesis(), constants.SSHFileOpsTimeout); err != nil { - return err + return fmt.Errorf("error uploading genesis config to %s: %w", remoteconfig.GetRemoteAvalancheGenesis(), err } // end genesis config // subnet config if app.AvagoSubnetConfigExists(subnetName) { subnetConfig, err := app.LoadRawAvagoSubnetConfig(subnetName) if err != nil { - return err + return fmt.Errorf("error loading subnet config: %w", err) } subnetConfigFile, err := os.CreateTemp("", "avalanchecli-subnet-*.json") if err != nil { @@ -638,7 +638,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } if err := host.Upload(subnetConfigFile.Name(), subnetConfigPath, constants.SSHFileOpsTimeout); err != nil { - return err + return fmt.Errorf("error uploading subnet config to %s: %w", subnetConfigPath, err) } } // end subnet config @@ -652,7 +652,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network defer os.Remove(chainConfigFile.Name()) chainConfig, err := app.LoadRawChainConfig(subnetName) if err != nil { - return err + return fmt.Errorf("error loading chain config: %w", err) } if err := os.WriteFile(chainConfigFile.Name(), chainConfig, constants.WriteReadUserOnlyPerms); err != nil { return err @@ -662,7 +662,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } if err := host.Upload(chainConfigFile.Name(), chainConfigPath, constants.SSHFileOpsTimeout); err != nil { - return err + return fmt.Errorf("error uploading chain config to %s: %w", chainConfigPath, err) } } // end chain config @@ -676,7 +676,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network defer os.Remove(networkUpgradesFile.Name()) networkUpgrades, err := app.LoadRawNetworkUpgrades(subnetName) if err != nil { - return err + return fmt.Errorf("error loading network upgrades: %w", err) } if err := os.WriteFile(networkUpgradesFile.Name(), networkUpgrades, constants.WriteReadUserOnlyPerms); err != nil { return err @@ -686,7 +686,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } if err := host.Upload(networkUpgradesFile.Name(), networkUpgradesPath, constants.SSHFileOpsTimeout); err != nil { - return err + return fmt.Errorf("error uploading network upgrades to %s: %w", networkUpgradesPath, err) } } // end network upgrade From 24cda0e841bc47279a875e9164a82d386bf0dcb0 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 15:14:02 -0700 Subject: [PATCH 17/24] typo --- pkg/ssh/ssh.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index ec1d70d70..dcd7d60bc 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -616,7 +616,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network // genesis config genesisFilename := filepath.Join(app.GetNodesDir(), host.GetCloudID(), constants.GenesisFileName) if err := host.Upload(genesisFilename, remoteconfig.GetRemoteAvalancheGenesis(), constants.SSHFileOpsTimeout); err != nil { - return fmt.Errorf("error uploading genesis config to %s: %w", remoteconfig.GetRemoteAvalancheGenesis(), err + return fmt.Errorf("error uploading genesis config to %s: %w", remoteconfig.GetRemoteAvalancheGenesis(), err) } // end genesis config // subnet config From 3f6380fc3e3eb2cacd7652f607cb1ac3a6fde360 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 15:19:47 -0700 Subject: [PATCH 18/24] add "/home/ubuntu/.avalanchego/configs/subnets/" to folders to create for avago --- pkg/remoteconfig/avalanche.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/remoteconfig/avalanche.go b/pkg/remoteconfig/avalanche.go index 9c980c8e4..d4e1c12d6 100644 --- a/pkg/remoteconfig/avalanche.go +++ b/pkg/remoteconfig/avalanche.go @@ -92,6 +92,7 @@ func AvalancheFolderToCreate() []string { "/home/ubuntu/.avalanchego/db", "/home/ubuntu/.avalanchego/logs", "/home/ubuntu/.avalanchego/configs", + "/home/ubuntu/.avalanchego/configs/subnets/", "/home/ubuntu/.avalanchego/configs/chains/C", "/home/ubuntu/.avalanchego/staking", "/home/ubuntu/.avalanchego/plugins", From be67a3b5c2aee1c0ea9de5527d7ab4055f0e455d Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 18:32:51 -0700 Subject: [PATCH 19/24] correct filepath func --- pkg/ssh/ssh.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index dcd7d60bc..197fb33c6 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -634,7 +634,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } subnetConfigPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", subnetIDStr+".json") - if err := host.MkdirAll(filepath.Base(subnetConfigPath), constants.SSHDirOpsTimeout); err != nil { + if err := host.MkdirAll(filepath.Dir(subnetConfigPath), constants.SSHDirOpsTimeout); err != nil { return err } if err := host.Upload(subnetConfigFile.Name(), subnetConfigPath, constants.SSHFileOpsTimeout); err != nil { @@ -658,7 +658,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } chainConfigPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", "chains", blockchainID.String(), "config.json") - if err := host.MkdirAll(filepath.Base(chainConfigPath), constants.SSHDirOpsTimeout); err != nil { + if err := host.MkdirAll(filepath.Dir(chainConfigPath), constants.SSHDirOpsTimeout); err != nil { return err } if err := host.Upload(chainConfigFile.Name(), chainConfigPath, constants.SSHFileOpsTimeout); err != nil { @@ -682,7 +682,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return err } networkUpgradesPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", "chains", blockchainID.String(), "upgrade.json") - if err := host.MkdirAll(filepath.Base(networkUpgradesPath), constants.SSHDirOpsTimeout); err != nil { + if err := host.MkdirAll(filepath.Dir(networkUpgradesPath), constants.SSHDirOpsTimeout); err != nil { return err } if err := host.Upload(networkUpgradesFile.Name(), networkUpgradesPath, constants.SSHFileOpsTimeout); err != nil { From 3ec4dfa76dedcf0344113b05b45fd9096db52597 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 11 Jul 2024 19:09:17 -0700 Subject: [PATCH 20/24] depricate remote cli --- cmd/nodecmd/create.go | 10 +--------- cmd/nodecmd/wiz.go | 1 - pkg/ssh/shell/setupNode.sh | 7 ------- pkg/ssh/ssh.go | 5 ++--- 4 files changed, 3 insertions(+), 20 deletions(-) diff --git a/cmd/nodecmd/create.go b/cmd/nodecmd/create.go index 8abeac736..7e07d21db 100644 --- a/cmd/nodecmd/create.go +++ b/cmd/nodecmd/create.go @@ -38,7 +38,6 @@ import ( "github.com/spf13/cobra" "golang.org/x/exp/maps" "golang.org/x/exp/slices" - "golang.org/x/mod/semver" ) const ( @@ -60,7 +59,6 @@ var ( useLatestAvalanchegoPreReleaseVersion bool useCustomAvalanchegoVersion string useAvalanchegoVersionFromSubnet string - remoteCLIVersion string cmdLineGCPCredentialsPath string cmdLineGCPProjectName string cmdLineAlternativeKeyPairName string @@ -113,7 +111,6 @@ will apply to all nodes in the cluster`, cmd.Flags().BoolVar(&useLatestAvalanchegoPreReleaseVersion, "latest-avalanchego-pre-release-version", false, "install latest avalanchego pre-release version on node/s") cmd.Flags().StringVar(&useCustomAvalanchegoVersion, "custom-avalanchego-version", "", "install given avalanchego version on node/s") cmd.Flags().StringVar(&useAvalanchegoVersionFromSubnet, "avalanchego-version-from-subnet", "", "install latest avalanchego version, that is compatible with the given subnet, on node/s") - cmd.Flags().StringVar(&remoteCLIVersion, "remote-cli-version", "", "install given CLI version on remote nodes. defaults to latest CLI release") cmd.Flags().StringVar(&cmdLineGCPCredentialsPath, "gcp-credentials", "", "use given GCP credentials") cmd.Flags().StringVar(&cmdLineGCPProjectName, "gcp-project", "", "use given GCP project") cmd.Flags().StringVar(&cmdLineAlternativeKeyPairName, "alternative-key-pair-name", "", "key pair name to use if default one generates conflicts") @@ -174,11 +171,6 @@ func preCreateChecks(clusterName string) error { } } } - if remoteCLIVersion != "" { - if !semver.IsValid(remoteCLIVersion) { - return fmt.Errorf("invalid semantic version for CLI on hosts") - } - } if customGrafanaDashboardPath != "" && !utils.FileExists(utils.ExpandHome(customGrafanaDashboardPath)) { return fmt.Errorf("custom grafana dashboard file does not exist") } @@ -692,7 +684,7 @@ func createNodes(cmd *cobra.Command, args []string) error { return } spinner := spinSession.SpinToUser(utils.ScriptLog(host.NodeID, "Setup Node")) - if err := ssh.RunSSHSetupNode(host, app.Conf.GetConfigPath(), remoteCLIVersion); err != nil { + if err := ssh.RunSSHSetupNode(host, app.Conf.GetConfigPath()); err != nil { nodeResults.AddResult(host.NodeID, nil, err) ux.SpinFailWithError(spinner, "", err) return diff --git a/cmd/nodecmd/wiz.go b/cmd/nodecmd/wiz.go index b8ed4e78b..2184d0c19 100644 --- a/cmd/nodecmd/wiz.go +++ b/cmd/nodecmd/wiz.go @@ -123,7 +123,6 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in cmd.Flags().BoolVar(&useLatestAvalanchegoReleaseVersion, "latest-avalanchego-version", false, "install latest avalanchego release version on node/s") cmd.Flags().BoolVar(&useLatestAvalanchegoPreReleaseVersion, "latest-avalanchego-pre-release-version", false, "install latest avalanchego pre-release version on node/s") cmd.Flags().StringVar(&useCustomAvalanchegoVersion, "custom-avalanchego-version", "", "install given avalanchego version on node/s") - cmd.Flags().StringVar(&remoteCLIVersion, "remote-cli-version", "", "install given CLI version on remote nodes. defaults to latest CLI release") cmd.Flags().StringSliceVar(&validators, "validators", []string{}, "deploy subnet into given comma separated list of validators. defaults to all cluster nodes") cmd.Flags().BoolVar(&addMonitoring, enableMonitoringFlag, false, " set up Prometheus monitoring for created nodes. Please note that this option creates a separate monitoring instance and incures additional cost") cmd.Flags().IntSliceVar(&numAPINodes, "num-apis", []int{}, "number of API nodes(nodes without stake) to create in the new Devnet") diff --git a/pkg/ssh/shell/setupNode.sh b/pkg/ssh/shell/setupNode.sh index 25d2e5ed6..5ee84424b 100644 --- a/pkg/ssh/shell/setupNode.sh +++ b/pkg/ssh/shell/setupNode.sh @@ -1,7 +1,6 @@ #!/usr/bin/env bash {{ if .IsE2E }} echo "E2E detected" -echo "CLI Version: {{ .CLIVersion }}" export DEBIAN_FRONTEND=noninteractive sudo apt-get -y update && sudo apt-get -y install busybox-static software-properties-common sudo add-apt-repository -y ppa:longsleep/golang-backports @@ -13,10 +12,4 @@ sudo usermod -aG docker ubuntu sudo chgrp ubuntu /var/run/docker.sock sudo chmod +rw /var/run/docker.sock {{ end }} -export PATH=$PATH:~/go/bin mkdir -p ~/.avalanche-cli -rm -vf install.sh && busybox wget -q -nd https://raw.githubusercontent.com/ava-labs/avalanche-cli/main/scripts/install.sh -#name:TASK [modify permissions] -chmod 755 install.sh -#name:TASK [run install script] -./install.sh {{ .CLIVersion }} diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index 197fb33c6..e54692eb2 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -31,7 +31,6 @@ import ( type scriptInputs struct { AvalancheGoVersion string - CLIVersion string SubnetExportFileName string SubnetName string ClusterName string @@ -111,13 +110,13 @@ func PostOverSSH(host *models.Host, path string, requestBody string) ([]byte, er } // RunSSHSetupNode runs script to setup node -func RunSSHSetupNode(host *models.Host, configPath, cliVersion string) error { +func RunSSHSetupNode(host *models.Host, configPath string) error { if err := RunOverSSH( "Setup Node", host, constants.SSHLongRunningScriptTimeout, "shell/setupNode.sh", - scriptInputs{CLIVersion: cliVersion, IsE2E: utils.IsE2E()}, + scriptInputs{IsE2E: utils.IsE2E()}, ); err != nil { return err } From 350f5c62cc0eb57f6077e35d622785257ff5c8dd Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Fri, 12 Jul 2024 12:00:14 -0700 Subject: [PATCH 21/24] support node-config for subnet --- cmd/nodecmd/wiz.go | 7 ++++- pkg/ssh/ssh.go | 49 +++++++++++++++++++++++++++++- pkg/utils/json.go | 11 +++++++ pkg/utils/json_test.go | 67 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 pkg/utils/json_test.go diff --git a/cmd/nodecmd/wiz.go b/cmd/nodecmd/wiz.go index 2184d0c19..2fbfbbd30 100644 --- a/cmd/nodecmd/wiz.go +++ b/cmd/nodecmd/wiz.go @@ -72,6 +72,7 @@ var ( teleporterRegistryBydecodePath string deployTeleporterMessenger bool deployTeleporterRegistry bool + depricatedRemoteCLIVersion string ) func newWizCmd() *cobra.Command { @@ -98,7 +99,6 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in cmd.Flags().StringVar(&cmdLineAlternativeKeyPairName, "alternative-key-pair-name", "", "key pair name to use if default one generates conflicts") cmd.Flags().StringVar(&awsProfile, "aws-profile", constants.AWSDefaultCredential, "aws profile to use") cmd.Flags().BoolVar(&defaultValidatorParams, "default-validator-params", false, "use default weight/start/duration params for subnet validator") - cmd.Flags().BoolVar(&forceSubnetCreate, "force-subnet-create", false, "overwrite the existing subnet configuration if one exists") cmd.Flags().StringVar(&subnetGenesisFile, "subnet-genesis", "", "file path of the subnet genesis") cmd.Flags().BoolVar(&teleporterReady, "teleporter", false, "generate a teleporter-ready vm") @@ -138,6 +138,8 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in cmd.Flags().StringVar(&teleporterRegistryBydecodePath, "teleporter-registry-bytecode-path", "", "path to a teleporter registry bytecode file") cmd.Flags().BoolVar(&deployTeleporterMessenger, "deploy-teleporter-messenger", true, "deploy Teleporter Messenger") cmd.Flags().BoolVar(&deployTeleporterRegistry, "deploy-teleporter-registry", true, "deploy Teleporter Registry") + + cmd.Flags().StringVar(&depricatedRemoteCLIVersion, "remote-cli-version", "", "[depricated] install given CLI version on remote nodes.") return cmd } @@ -159,6 +161,9 @@ func wiz(cmd *cobra.Command, args []string) error { if clusterAlreadyExists && subnetName == "" { return fmt.Errorf("expecting to add subnet to existing cluster but no subnet-name was provided") } + if depricatedRemoteCLIVersion != "" { + ux.Logger.PrintToUser("remote-cli-version flag is depricated and will be removed in future releases. Ignoring it.") + } if subnetName != "" && (!app.SidecarExists(subnetName) || forceSubnetCreate) { ux.Logger.PrintToUser("") ux.Logger.PrintToUser(logging.Green.Wrap("Creating the subnet")) diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index e54692eb2..a12523261 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -600,6 +600,46 @@ func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error { return nil } +// RunSSHMergeSubnetNodeConfig merges subnet node config to the node config on the remote host +func mergeSubnetNodeConfig(host *models.Host, subnetNodeConfigPath string) error { + if subnetNodeConfigPath == "" { + return fmt.Errorf("subnet node config path is empty") + } + tmpFile, err := os.CreateTemp("", "avalanchecli-subnet-node-*.yml") + if err != nil { + return err + } + defer os.Remove(tmpFile.Name()) + if err := host.Download(remoteconfig.GetRemoteAvalancheNodeConfig(), tmpFile.Name(), constants.SSHFileOpsTimeout); err != nil { + return err + } + remoteNodeConfigBytes, err := os.ReadFile(tmpFile.Name()) + if err != nil { + return fmt.Errorf("error reading remote node config: %w", err) + } + var remoteNodeConfig map[string]interface{} + if err := json.Unmarshal(remoteNodeConfigBytes, &remoteNodeConfig); err != nil { + return fmt.Errorf("error unmarshalling remote node config: %w", err) + } + subnetNodeConfigBytes, err := os.ReadFile(subnetNodeConfigPath) + if err != nil { + return fmt.Errorf("error reading subnet node config: %w", err) + } + var subnetNodeConfig map[string]interface{} + if err := json.Unmarshal(subnetNodeConfigBytes, &subnetNodeConfig); err != nil { + return fmt.Errorf("error unmarshalling subnet node config: %w", err) + } + mergedNodeConfig := utils.MergeJSONMaps(remoteNodeConfig, subnetNodeConfig) + mergedNodeConfigBytes, err := json.Marshal(mergedNodeConfig) + if err != nil { + return fmt.Errorf("error creating merged node config: %w", err) + } + if err := os.WriteFile(tmpFile.Name(), mergedNodeConfigBytes, constants.WriteReadUserOnlyPerms); err != nil { + return err + } + return host.Upload(tmpFile.Name(), remoteconfig.GetRemoteAvalancheNodeConfig(), constants.SSHFileOpsTimeout) +} + // RunSSHSyncSubnetData syncs subnet data required func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network models.Network, subnetName string) error { sc, err := app.LoadSidecar(subnetName) @@ -618,6 +658,13 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network return fmt.Errorf("error uploading genesis config to %s: %w", remoteconfig.GetRemoteAvalancheGenesis(), err) } // end genesis config + // subnet node config + subnetNodeConfigPath := app.GetAvagoNodeConfigPath(subnetName) + if utils.FileExists(subnetNodeConfigPath) { + if err := mergeSubnetNodeConfig(host, subnetNodeConfigPath); err != nil { + return err + } + } // subnet config if app.AvagoSubnetConfigExists(subnetName) { subnetConfig, err := app.LoadRawAvagoSubnetConfig(subnetName) @@ -656,7 +703,7 @@ func RunSSHSyncSubnetData(app *application.Avalanche, host *models.Host, network if err := os.WriteFile(chainConfigFile.Name(), chainConfig, constants.WriteReadUserOnlyPerms); err != nil { return err } - chainConfigPath := filepath.Join(constants.CloudNodeConfigPath, "subnets", "chains", blockchainID.String(), "config.json") + chainConfigPath := filepath.Join(constants.CloudNodeConfigPath, "chains", blockchainID.String(), "config.json") if err := host.MkdirAll(filepath.Dir(chainConfigPath), constants.SSHDirOpsTimeout); err != nil { return err } diff --git a/pkg/utils/json.go b/pkg/utils/json.go index d35b7eb30..cad2a773e 100644 --- a/pkg/utils/json.go +++ b/pkg/utils/json.go @@ -25,3 +25,14 @@ func ValidateJSON(path string) ([]byte, error) { return contentBytes, nil } + +// MergeJsonMaps merges two maps of type map[string]interface{} +func MergeJSONMaps(a, b map[string]interface{}) map[string]interface{} { + for k, v := range b { + if _, ok := a[k]; !ok { + a[k] = v + } + // skip if key already exists in a + } + return a +} diff --git a/pkg/utils/json_test.go b/pkg/utils/json_test.go new file mode 100644 index 000000000..419295c1a --- /dev/null +++ b/pkg/utils/json_test.go @@ -0,0 +1,67 @@ +// Copyright (C) 2022, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. +package utils + +import ( + "reflect" + "testing" +) + +func TestMergeJsonMaps(t *testing.T) { + tests := []struct { + name string + a map[string]interface{} + b map[string]interface{} + expected map[string]interface{} + }{ + { + name: "no conflict", + a: map[string]interface{}{"key1": "value1"}, + b: map[string]interface{}{"key2": "value2"}, + expected: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + }, + { + name: "with conflict", + a: map[string]interface{}{"key1": "value1"}, + b: map[string]interface{}{"key1": "new_value1", "key2": "value2"}, + expected: map[string]interface{}{ + "key1": "value1", + "key2": "value2", + }, + }, + { + name: "empty map a", + a: map[string]interface{}{}, + b: map[string]interface{}{"key1": "value1"}, + expected: map[string]interface{}{ + "key1": "value1", + }, + }, + { + name: "empty map b", + a: map[string]interface{}{"key1": "value1"}, + b: map[string]interface{}{}, + expected: map[string]interface{}{ + "key1": "value1", + }, + }, + { + name: "both maps empty", + a: map[string]interface{}{}, + b: map[string]interface{}{}, + expected: map[string]interface{}{}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := MergeJSONMaps(tt.a, tt.b) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("MergeJsonMaps(%v, %v) = %v; expected %v", tt.a, tt.b, result, tt.expected) + } + }) + } +} From 9d46ce850e36463941eb701393fe9f38676709bf Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Fri, 12 Jul 2024 12:56:57 -0700 Subject: [PATCH 22/24] logging for custom vm build --- cmd/nodecmd/sync.go | 1 + pkg/ssh/ssh.go | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index a5928ae60..75c177a53 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -90,6 +90,7 @@ func prepareSubnetPlugin(hosts []*models.Host, subnetName string) error { if err != nil { return err } + ux.Logger.Info("Creating subnet %s plugin for hosts: %s", subnetName, hosts) wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { diff --git a/pkg/ssh/ssh.go b/pkg/ssh/ssh.go index a12523261..212fd0414 100644 --- a/pkg/ssh/ssh.go +++ b/pkg/ssh/ssh.go @@ -556,6 +556,8 @@ func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error { }(host) switch { case sc.VM == models.CustomVM: + ux.Logger.Info("Building Custom VM for %s to %s", host.NodeID, subnetVMBinaryPath) + ux.Logger.Info("Custom VM Params: repo %s branch %s via %s", sc.CustomVMRepoURL, sc.CustomVMBranch, sc.CustomVMBuildScript) if err := RunOverSSH( "Build CustomVM", host, @@ -573,6 +575,7 @@ func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error { } case sc.VM == models.SubnetEvm: + ux.Logger.Info("Installing Subnet EVM for %s", host.NodeID) dl := binutils.NewSubnetEVMDownloader() installURL, _, err := dl.GetDownloadURL(sc.VMVersion, hostInstaller) // extension is tar.gz if err != nil { @@ -630,7 +633,7 @@ func mergeSubnetNodeConfig(host *models.Host, subnetNodeConfigPath string) error return fmt.Errorf("error unmarshalling subnet node config: %w", err) } mergedNodeConfig := utils.MergeJSONMaps(remoteNodeConfig, subnetNodeConfig) - mergedNodeConfigBytes, err := json.Marshal(mergedNodeConfig) + mergedNodeConfigBytes, err := json.MarshalIndent(mergedNodeConfig, "", " ") if err != nil { return fmt.Errorf("error creating merged node config: %w", err) } From 84494a0f81a30b5d75f44024d214f2289d55702f Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Fri, 12 Jul 2024 13:07:27 -0700 Subject: [PATCH 23/24] typo --- pkg/ssh/shell/buildCustomVM.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/ssh/shell/buildCustomVM.sh b/pkg/ssh/shell/buildCustomVM.sh index cbeb79e91..ad813e6f1 100644 --- a/pkg/ssh/shell/buildCustomVM.sh +++ b/pkg/ssh/shell/buildCustomVM.sh @@ -1,11 +1,11 @@ #!/usr/bin/env bash if [ -d {{ .CustomVMRepoDir }} ]; then - rm -rf {{ .LoadTestRepoDir }} + rm -rf {{ .CustomVMRepoDir }} fi cd {{ .CustomVMRepoDir }} -git remote init -q +git init -q git remote add origin {{ .CustomVMRepoURL }} git fetch --depth 1 origin {{ .CustomVMBranch }} -q git checkout {{ .CustomVMBranch }} From 7b48f35efba4dec7391e62a807002bc3980e5600 Mon Sep 17 00:00:00 2001 From: Artur Reznikov Date: Thu, 18 Jul 2024 12:41:15 -0700 Subject: [PATCH 24/24] address raymond feedback --- cmd/nodecmd/sync.go | 1 - cmd/nodecmd/wiz.go | 5 ----- 2 files changed, 6 deletions(-) diff --git a/cmd/nodecmd/sync.go b/cmd/nodecmd/sync.go index 75c177a53..a5928ae60 100644 --- a/cmd/nodecmd/sync.go +++ b/cmd/nodecmd/sync.go @@ -90,7 +90,6 @@ func prepareSubnetPlugin(hosts []*models.Host, subnetName string) error { if err != nil { return err } - ux.Logger.Info("Creating subnet %s plugin for hosts: %s", subnetName, hosts) wg := sync.WaitGroup{} wgResults := models.NodeResults{} for _, host := range hosts { diff --git a/cmd/nodecmd/wiz.go b/cmd/nodecmd/wiz.go index ddbddd501..40747ca65 100644 --- a/cmd/nodecmd/wiz.go +++ b/cmd/nodecmd/wiz.go @@ -73,7 +73,6 @@ var ( deployTeleporterMessenger bool deployTeleporterRegistry bool replaceKeyPair bool - depricatedRemoteCLIVersion string ) func newWizCmd() *cobra.Command { @@ -140,7 +139,6 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in cmd.Flags().BoolVar(&deployTeleporterMessenger, "deploy-teleporter-messenger", true, "deploy Teleporter Messenger") cmd.Flags().BoolVar(&deployTeleporterRegistry, "deploy-teleporter-registry", true, "deploy Teleporter Registry") cmd.Flags().BoolVar(&replaceKeyPair, "auto-replace-keypair", false, "automatically replaces key pair to access node if previous key pair is not found") - cmd.Flags().StringVar(&depricatedRemoteCLIVersion, "remote-cli-version", "", "[depricated] install given CLI version on remote nodes.") return cmd } @@ -162,9 +160,6 @@ func wiz(cmd *cobra.Command, args []string) error { if clusterAlreadyExists && subnetName == "" { return fmt.Errorf("expecting to add subnet to existing cluster but no subnet-name was provided") } - if depricatedRemoteCLIVersion != "" { - ux.Logger.PrintToUser("remote-cli-version flag is depricated and will be removed in future releases. Ignoring it.") - } if subnetName != "" && (!app.SidecarExists(subnetName) || forceSubnetCreate) { ux.Logger.PrintToUser("") ux.Logger.PrintToUser(logging.Green.Wrap("Creating the subnet"))