Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove remote cli dependency for CLI #2026

Merged
merged 25 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 1 addition & 9 deletions cmd/nodecmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -60,7 +59,6 @@ var (
useLatestAvalanchegoPreReleaseVersion bool
useCustomAvalanchegoVersion string
useAvalanchegoVersionFromSubnet string
remoteCLIVersion string
cmdLineGCPCredentialsPath string
cmdLineGCPProjectName string
cmdLineAlternativeKeyPairName string
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -175,11 +172,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")
}
Expand Down Expand Up @@ -693,7 +685,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
Expand Down
4 changes: 4 additions & 0 deletions cmd/nodecmd/create_devnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{}
Expand Down
59 changes: 47 additions & 12 deletions cmd/nodecmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@

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/utils"
"github.com/ava-labs/avalanche-cli/pkg/ux"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -41,6 +40,10 @@
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
}
Expand All @@ -66,7 +69,10 @@
return err
}
}
untrackedNodes, err := trackSubnet(hosts, clusterName, subnetName)
if err := prepareSubnetPlugin(hosts, subnetName); err != nil {
return err
}
untrackedNodes, err := trackSubnet(hosts, clusterName, clusterConfig.Network, subnetName)
if err != nil {
return err
}
Expand All @@ -78,34 +84,63 @@
return nil
}

// prepareSubnetPlugin creates subnet plugin to all nodes in the cluster
func prepareSubnetPlugin(hosts []*models.Host, subnetName string) error {
sc, err := app.LoadSidecar(subnetName)
if err != nil {
return err
}
ux.Logger.Info("Creating subnet %s plugin for hosts: %s", subnetName, hosts)

Check failure on line 93 in cmd/nodecmd/sync.go

View workflow job for this annotation

GitHub Actions / Golang Unit Tests v1.21.7 (ubuntu-20.04)

(*github.com/ava-labs/avalanche-cli/pkg/ux.UserLog).Info format %s has arg hosts of wrong type []*github.com/ava-labs/avalanche-cli/pkg/models.Host

Check failure on line 93 in cmd/nodecmd/sync.go

View workflow job for this annotation

GitHub Actions / Lint

printf: (*github.com/ava-labs/avalanche-cli/pkg/ux.UserLog).Info format %s has arg hosts of wrong type []*github.com/ava-labs/avalanche-cli/pkg/models.Host (govet)
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.RunSSHCreatePlugin(host, sc); 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 <subnetName> command)
func trackSubnet(
hosts []*models.Host,
clusterName string,
network models.Network,
subnetName string,
) ([]string, error) {
subnetPath := "/tmp/" + subnetName + constants.ExportSubnetSuffix
networkFlag := "--cluster " + clusterName
if err := subnetcmd.CallExportSubnet(subnetName, subnetPath); err != nil {
// 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()
subnetExportPath := filepath.Join("/tmp", filepath.Base(subnetPath))
if err := ssh.RunSSHExportSubnet(host, subnetPath, subnetExportPath); err != nil {
if err := ssh.RunSSHStopNode(host); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
return
}
if err := ssh.RunSSHUploadClustersConfig(host, app.GetClustersConfigPath()); err != nil {
if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, network, allSubnets); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}

if err := ssh.RunSSHTrackSubnet(host, subnetName, subnetExportPath, networkFlag); 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 {
nodeResults.AddResult(host.NodeID, nil, err)
return
}
Expand Down
30 changes: 20 additions & 10 deletions cmd/nodecmd/updateSubnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@ 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/utils"
"github.com/ava-labs/avalanche-cli/pkg/ux"
"github.com/spf13/cobra"
)
Expand All @@ -38,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
}
Expand All @@ -55,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, subnetName)
if err != nil {
return err
}
Expand All @@ -71,27 +74,34 @@ func updateSubnet(_ *cobra.Command, args []string) error {
// restart tracking the specified subnet (similar to avalanche subnet join <subnetName> command)
func doUpdateSubnet(
hosts []*models.Host,
clusterName string,
network models.Network,
subnetName string,
) ([]string, error) {
subnetPath := "/tmp/" + subnetName + constants.ExportSubnetSuffix
if err := subnetcmd.CallExportSubnet(subnetName, subnetPath); err != nil {
// 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()
subnetExportPath := filepath.Join("/tmp", filepath.Base(subnetPath))
if err := ssh.RunSSHExportSubnet(host, subnetPath, subnetExportPath); err != nil {
if err := ssh.RunSSHStopNode(host); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}
if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, network, allSubnets); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
return
}
if err := ssh.RunSSHUploadClustersConfig(host, app.GetClustersConfigPath()); err != nil {
if err := ssh.RunSSHSyncSubnetData(app, host, network, subnetName); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}
if err := ssh.RunSSHUpdateSubnet(host, subnetName, subnetExportPath); err != nil {
if err := ssh.RunSSHStartNode(host); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
return
}
Expand Down
7 changes: 5 additions & 2 deletions cmd/nodecmd/wiz.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ var (
deployTeleporterMessenger bool
deployTeleporterRegistry bool
replaceKeyPair bool
depricatedRemoteCLIVersion string
Copy link
Collaborator

@sukantoraymond sukantoraymond Jul 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets just delete this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would force us to update hypersdk example for morpheusVM

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya I'll just delete it in the script once this PR is merged

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

k. will do

)

func newWizCmd() *cobra.Command {
Expand All @@ -99,7 +100,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")
Expand All @@ -124,7 +124,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")
Expand All @@ -141,6 +140,7 @@ 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
}

Expand All @@ -162,6 +162,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"))
Expand Down
1 change: 1 addition & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/"
Expand Down
2 changes: 1 addition & 1 deletion pkg/docker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

func prepareAvalanchegoConfig(host *models.Host, networkID string) (string, string, error) {
avagoConf := remoteconfig.DefaultCliAvalancheConfig(host.IP, networkID)
avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, networkID, nil)
nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf)
if err != nil {
return "", "", err
Expand Down
13 changes: 12 additions & 1 deletion pkg/remoteconfig/avalanche.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bytes"
"html/template"
"path/filepath"
"strings"

"github.com/ava-labs/avalanche-cli/pkg/constants"
)
Expand All @@ -21,9 +22,13 @@ type AvalancheConfigInputs struct {
PublicIP string
StateSyncEnabled bool
PruningEnabled bool
TrackSubnets string
BootstrapIDs string
BootstrapIPs string
GenesisPath string
}

func DefaultCliAvalancheConfig(publicIP string, networkID string) AvalancheConfigInputs {
func PrepareAvalancheConfig(publicIP string, networkID string, subnets []string) AvalancheConfigInputs {
return AvalancheConfigInputs{
HTTPHost: "0.0.0.0",
NetworkID: networkID,
Expand All @@ -32,6 +37,7 @@ func DefaultCliAvalancheConfig(publicIP string, networkID string) AvalancheConfi
PublicIP: publicIP,
StateSyncEnabled: true,
PruningEnabled: false,
TrackSubnets: strings.Join(subnets, ","),
}
}

Expand Down Expand Up @@ -77,11 +83,16 @@ 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",
"/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",
Expand Down
24 changes: 18 additions & 6 deletions pkg/remoteconfig/templates/avalanche-node.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@
"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 }}
"public-ip-resolution-service": "opendns",
{{- end }}
{{- if .TrackSubnets }}
"track-subnets": "{{ .TrackSubnets }}",
{{- end }}
"db-dir": "{{.DBDir}}",
"log-dir": "{{.LogDir}}",
{{- if .PublicIP -}}
"public-ip": "{{.PublicIP}}"
{{- else -}}
"public-ip-resolution-service": "opendns"
{{- end -}}
"log-dir": "{{.LogDir}}"
}
Loading
Loading