Skip to content

Commit

Permalink
Fuji api (#1986)
Browse files Browse the repository at this point in the history
* add api for fuji

* put old code back

* avoid github api if custom version is set

* add publicAPI to network

* fixes

* fix golang template newline

* switch to host network

* fix template

* rm host mode for monitoring

* add e2e support back to template

* fix e2e indent

* make sure that all API hosts can receive traffic on IP and not localhost

* lint

* mv public access config to clusterconf and address other felipe feedback

* lint

* fix wiz

* fix check. we should be able to deploy validators without api

* fix check

* Visibility -> HTTPAccess
  • Loading branch information
arturrez authored Jul 29, 2024
1 parent d76ac0d commit c391d07
Show file tree
Hide file tree
Showing 17 changed files with 85 additions and 62 deletions.
30 changes: 19 additions & 11 deletions cmd/nodecmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,9 @@ var (
versionComments = map[string]string{
"v1.11.0-fuji": " (recommended for fuji durango)",
}
grafanaPkg string
wizSubnet string
grafanaPkg string
wizSubnet string
publicHTTPPortAccess bool
)

func newCreateCmd() *cobra.Command {
Expand Down Expand Up @@ -126,6 +127,7 @@ will apply to all nodes in the cluster`,
cmd.Flags().StringVar(&volumeType, "aws-volume-type", "gp3", "AWS volume type")
cmd.Flags().IntVar(&volumeSize, "aws-volume-size", constants.CloudServerStorageSize, "AWS volume size in GB")
cmd.Flags().BoolVar(&replaceKeyPair, "auto-replace-keypair", false, "automatically replaces key pair to access node if previous key pair is not found")
cmd.Flags().BoolVar(&publicHTTPPortAccess, "public-http-port", false, "allow public access to avalanchego HTTP port")
return cmd
}

Expand Down Expand Up @@ -159,10 +161,10 @@ func preCreateChecks(clusterName string) error {
if useSSHAgent && !utils.IsSSHAgentAvailable() {
return fmt.Errorf("ssh agent is not available")
}
if len(numAPINodes) > 0 && !globalNetworkFlags.UseDevnet {
return fmt.Errorf("API nodes can only be created in Devnet")
if len(numAPINodes) > 0 && !(globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji) {
return fmt.Errorf("API nodes can only be created in Devnet/Fuji(Testnet)")
}
if globalNetworkFlags.UseDevnet && len(numAPINodes) > 0 && len(numAPINodes) != len(numValidatorsNodes) {
if (globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji) && len(numAPINodes) > 0 && len(numAPINodes) != len(numValidatorsNodes) {
return fmt.Errorf("API nodes and Validator nodes must be deployed to same number of regions")
}
if len(numAPINodes) > 0 {
Expand Down Expand Up @@ -255,7 +257,6 @@ func createNodes(cmd *cobra.Command, args []string) error {
return err
}
network = models.NewNetworkFromCluster(network, clusterName)

globalNetworkFlags.UseDevnet = network.Kind == models.Devnet // set globalNetworkFlags.UseDevnet to true if network is devnet for further use
avalancheGoVersion, err := getAvalancheGoVersion()
if err != nil {
Expand Down Expand Up @@ -403,14 +404,14 @@ func createNodes(cmd *cobra.Command, args []string) error {
if existingMonitoringInstance == "" {
monitoringHostRegion = regions[0]
}
cloudConfigMap, err = createAWSInstances(ec2SvcMap, nodeType, numNodesMap, regions, ami, false)
cloudConfigMap, err = createAWSInstances(ec2SvcMap, nodeType, numNodesMap, regions, ami, false, publicHTTPPortAccess)
if err != nil {
return err
}
monitoringEc2SvcMap := make(map[string]*awsAPI.AwsCloud)
if addMonitoring && existingMonitoringInstance == "" {
monitoringEc2SvcMap[monitoringHostRegion] = ec2SvcMap[monitoringHostRegion]
monitoringCloudConfig, err := createAWSInstances(monitoringEc2SvcMap, nodeType, map[string]NumNodes{monitoringHostRegion: {1, 0}}, []string{monitoringHostRegion}, ami, true)
monitoringCloudConfig, err := createAWSInstances(monitoringEc2SvcMap, nodeType, map[string]NumNodes{monitoringHostRegion: {1, 0}}, []string{monitoringHostRegion}, ami, true, publicHTTPPortAccess)
if err != nil {
return err
}
Expand Down Expand Up @@ -712,7 +713,9 @@ func createNodes(cmd *cobra.Command, args []string) error {
ux.SpinComplete(spinner)
}
spinner = spinSession.SpinToUser(utils.ScriptLog(host.NodeID, "Setup AvalancheGo"))
if err := docker.ComposeSSHSetupNode(host, network, avalancheGoVersion, addMonitoring); err != nil {
// check if host is a API host
publicAccessToHTTPPort := slices.Contains(cloudConfigMap.GetAllAPIInstanceIDs(), host.GetCloudID()) || publicHTTPPortAccess
if err := docker.ComposeSSHSetupNode(host, network, avalancheGoVersion, addMonitoring, publicAccessToHTTPPort); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
ux.SpinFailWithError(spinner, "", err)
return
Expand Down Expand Up @@ -900,6 +903,7 @@ func addNodeToClustersConfig(network models.Network, nodeID, clusterName string,
if network != models.UndefinedNetwork {
clusterConfig.Network = network
}
clusterConfig.HTTPAccess = constants.HTTPAccess(publicHTTPPortAccess)
if clusterConfig.LoadTestInstance == nil {
clusterConfig.LoadTestInstance = make(map[string]string)
}
Expand Down Expand Up @@ -987,6 +991,10 @@ func provideStakingCertAndKey(host *models.Host) error {
// or if they want to use the newest Avalanche Go Version that is still compatible with Subnet EVM
// version of their choice
func getAvalancheGoVersion() (string, error) {
// skip this logic if custom-avalanchego-version flag is set
if useCustomAvalanchegoVersion != "" {
return useCustomAvalanchegoVersion, nil
}
latestReleaseVersion, err := app.Downloader.GetLatestReleaseVersion(binutils.GetGithubLatestReleaseURL(
constants.AvaLabsOrg,
constants.AvalancheGoRepoName,
Expand Down Expand Up @@ -1367,7 +1375,7 @@ func getRegionsNodeNum(cloudName string) (
if err != nil {
return nil, err
}
if globalNetworkFlags.UseDevnet {
if globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji {
numAPINodes, err = app.Prompt.CaptureUint32(fmt.Sprintf("How many API nodes (nodes without stake) do you want to set up in %s %s?", userRegion, supportedClouds[cloudName].locationName))
if err != nil {
return nil, err
Expand All @@ -1378,7 +1386,7 @@ func getRegionsNodeNum(cloudName string) (
}
nodes[userRegion] = NumNodes{int(numNodes), int(numAPINodes)}
var currentInput []string
if globalNetworkFlags.UseDevnet {
if globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji {
currentInput = utils.Map(maps.Keys(nodes), func(region string) string {
return fmt.Sprintf("[%s]: %d validator(s) %d api(s)", region, nodes[region].numValidators, nodes[region].numAPI)
})
Expand Down
27 changes: 22 additions & 5 deletions cmd/nodecmd/create_aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ func getAWSCloudConfig(awsProfile string, singleNode bool, clusterSgRegions []st
switch {
case len(numValidatorsNodes) != len(utils.Unique(cmdLineRegion)):
return nil, nil, nil, fmt.Errorf("number of nodes and regions should be the same")
case globalNetworkFlags.UseDevnet && len(numAPINodes) != len(utils.Unique(cmdLineRegion)):
case (globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji) && len(numAPINodes) != len(utils.Unique(cmdLineRegion)):
return nil, nil, nil, fmt.Errorf("number of api nodes and regions should be the same")
case globalNetworkFlags.UseDevnet && len(numAPINodes) != len(numValidatorsNodes):
case (globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji) && len(numAPINodes) != len(numValidatorsNodes):
return nil, nil, nil, fmt.Errorf("number of api nodes and validator nodes should be the same")
case len(cmdLineRegion) == 0 && len(numValidatorsNodes) == 0 && len(numAPINodes) == 0:
var err error
Expand All @@ -128,7 +128,7 @@ func getAWSCloudConfig(awsProfile string, singleNode bool, clusterSgRegions []st
}
default:
for i, region := range cmdLineRegion {
if globalNetworkFlags.UseDevnet {
if globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji {
finalRegions[region] = NumNodes{numValidatorsNodes[i], numAPINodes[i]}
} else {
finalRegions[region] = NumNodes{numValidatorsNodes[i], 0}
Expand Down Expand Up @@ -193,6 +193,7 @@ func createEC2Instances(ec2Svc map[string]*awsAPI.AwsCloud,
regions []string,
regionConf map[string]models.RegionConfig,
forMonitoring bool,
publicHTTPPortAccess bool,
) (map[string][]string, map[string][]string, map[string]string, map[string]string, error) {
if !forMonitoring {
ux.Logger.PrintToUser("Creating new EC2 instance(s) on AWS...")
Expand Down Expand Up @@ -299,6 +300,12 @@ func createEC2Instances(ec2Svc map[string]*awsAPI.AwsCloud,
} else {
sgID = newSGID
}
// allow public access to API avalanchego port
if publicHTTPPortAccess {
if err := ec2Svc[region].AddSecurityGroupRule(sgID, "ingress", "tcp", "0.0.0.0/0", constants.AvalanchegoAPIPort); err != nil {
return instanceIDs, elasticIPs, sshCertPath, keyPairName, err
}
}
} else {
sgID = *sg.GroupId
ux.Logger.PrintToUser(fmt.Sprintf("Using existing security group %s in AWS[%s]", securityGroupName, region))
Expand Down Expand Up @@ -333,6 +340,15 @@ func createEC2Instances(ec2Svc map[string]*awsAPI.AwsCloud,
return instanceIDs, elasticIPs, sshCertPath, keyPairName, err
}
}
// check for public access to API port if flag is set
if publicHTTPPortAccess {
ipInPublicAPI := awsAPI.CheckIPInSg(&sg, "0.0.0.0/0", constants.AvalanchegoAPIPort)
if !ipInPublicAPI {
if err := ec2Svc[region].AddSecurityGroupRule(sgID, "ingress", "tcp", "0.0.0.0/0", constants.AvalanchegoAPIPort); err != nil {
return instanceIDs, elasticIPs, sshCertPath, keyPairName, err
}
}
}
}
sshCertPath[region] = privKey
if instanceIDs[region], err = ec2Svc[region].CreateEC2Instances(
Expand Down Expand Up @@ -482,7 +498,8 @@ func createAWSInstances(
numNodes map[string]NumNodes,
regions []string,
ami map[string]string,
forMonitoring bool) (
forMonitoring bool,
publicHTTPPortAccess bool) (
models.CloudConfig, error,
) {
regionConf := map[string]models.RegionConfig{}
Expand All @@ -501,7 +518,7 @@ func createAWSInstances(
}
}
// Create new EC2 instances
instanceIDs, elasticIPs, certFilePath, keyPairName, err := createEC2Instances(ec2Svc, regions, regionConf, forMonitoring)
instanceIDs, elasticIPs, certFilePath, keyPairName, err := createEC2Instances(ec2Svc, regions, regionConf, forMonitoring, publicHTTPPortAccess)
if err != nil {
if err.Error() == constants.EIPLimitErr {
ux.Logger.PrintToUser("Failed to create AWS cloud server(s), please try creating again in a different region")
Expand Down
2 changes: 1 addition & 1 deletion cmd/nodecmd/create_gcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func getGCPConfig(singleNode bool) (*gcpAPI.GcpCloud, map[string]NumNodes, strin
}
}
default:
if globalNetworkFlags.UseDevnet {
if globalNetworkFlags.UseDevnet || globalNetworkFlags.UseFuji {
for i, region := range cmdLineRegion {
finalRegions[region] = NumNodes{numValidatorsNodes[i], numAPINodes[i]}
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/nodecmd/loadtestStart.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func startLoadTest(_ *cobra.Command, args []string) error {
}
separateHostRegion = loadTestHostRegion
loadTestEc2SvcMap[separateHostRegion] = ec2SvcMap[separateHostRegion]
loadTestCloudConfig, err = createAWSInstances(loadTestEc2SvcMap, nodeType, map[string]NumNodes{separateHostRegion: {1, 0}}, []string{separateHostRegion}, ami, true)
loadTestCloudConfig, err = createAWSInstances(loadTestEc2SvcMap, nodeType, map[string]NumNodes{separateHostRegion: {1, 0}}, []string{separateHostRegion}, ami, true, false)
if err != nil {
return err
}
Expand Down
7 changes: 5 additions & 2 deletions cmd/nodecmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ func upgrade(_ *cobra.Command, args []string) error {
for host, upgradeInfo := range toUpgradeNodesMap {
if upgradeInfo.AvalancheGoVersion != "" {
spinner := spinSession.SpinToUser(utils.ScriptLog(host.NodeID, fmt.Sprintf("Upgrading avalanchego to version %s...", upgradeInfo.AvalancheGoVersion)))
if err := upgradeAvalancheGo(host, network, upgradeInfo.AvalancheGoVersion); err != nil {
// check if host is API host
publicAccessToHTTPPort := clusterConfig.IsAPIHost(host.GetCloudID()) || clusterConfig.HTTPAccess == constants.PublicAccess
if err := upgradeAvalancheGo(host, network, upgradeInfo.AvalancheGoVersion, publicAccessToHTTPPort); err != nil {
ux.SpinFailWithError(spinner, "", err)
return err
}
Expand Down Expand Up @@ -216,8 +218,9 @@ func upgradeAvalancheGo(
host *models.Host,
network models.Network,
avaGoVersionToUpdateTo string,
publicAccessToHTTPPort bool,
) error {
if err := ssh.RunSSHUpgradeAvalanchego(host, network, avaGoVersionToUpdateTo); err != nil {
if err := ssh.RunSSHUpgradeAvalanchego(host, network, avaGoVersionToUpdateTo, publicAccessToHTTPPort); err != nil {
return err
}
return nil
Expand Down
1 change: 1 addition & 0 deletions cmd/nodecmd/wiz.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,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().BoolVar(&publicHTTPPortAccess, "public-http-port", false, "allow public access to avalanchego HTTP port")
return cmd
}

Expand Down
8 changes: 6 additions & 2 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"time"
)

type HTTPAccess bool

const (
DefaultPerms755 = 0o755
WriteReadReadPerms = 0o644
Expand Down Expand Up @@ -70,8 +72,10 @@ const (

OperateOfflineEnvVarName = "CLIOFFLINE"

FujiAPIEndpoint = "https://api.avax-test.network"
MainnetAPIEndpoint = "https://api.avax.network"
PublicAccess HTTPAccess = true
PrivateAccess HTTPAccess = false
FujiAPIEndpoint = "https://api.avax-test.network"
MainnetAPIEndpoint = "https://api.avax.network"

// this depends on bootstrap snapshot
LocalAPIEndpoint = "http://127.0.0.1:9650"
Expand Down
8 changes: 6 additions & 2 deletions pkg/docker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ import (
"github.com/ava-labs/avalanche-cli/pkg/constants"
"github.com/ava-labs/avalanche-cli/pkg/models"
"github.com/ava-labs/avalanche-cli/pkg/remoteconfig"
"github.com/ava-labs/avalanche-cli/pkg/utils"
)

func prepareAvalanchegoConfig(host *models.Host, networkID string) (string, string, error) {
avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, networkID, nil)
func prepareAvalanchegoConfig(host *models.Host, network models.Network, publicAccess bool) (string, string, error) {
avagoConf := remoteconfig.PrepareAvalancheConfig(host.IP, network.NetworkIDFlagValue(), nil)
if publicAccess || utils.IsE2E() {
avagoConf.HTTPHost = "0.0.0.0"
}
nodeConf, err := remoteconfig.RenderAvalancheNodeConfig(avagoConf)
if err != nil {
return "", "", err
Expand Down
9 changes: 2 additions & 7 deletions pkg/docker/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func ValidateComposeFile(host *models.Host, composeFile string, timeout time.Dur
}

// ComposeSSHSetupNode sets up an AvalancheGo node and dependencies on a remote host over SSH.
func ComposeSSHSetupNode(host *models.Host, network models.Network, avalancheGoVersion string, withMonitoring bool) error {
func ComposeSSHSetupNode(host *models.Host, network models.Network, avalancheGoVersion string, withMonitoring bool, publicAccessToHTTPPort bool) error {
startTime := time.Now()
folderStructure := remoteconfig.RemoteFoldersToCreateAvalanchego()
for _, dir := range folderStructure {
Expand All @@ -34,19 +34,14 @@ func ComposeSSHSetupNode(host *models.Host, network models.Network, avalancheGoV
}
}
ux.Logger.Info("avalancheCLI folder structure created on remote host %s after %s", folderStructure, time.Since(startTime))
// configs
networkID := network.NetworkIDFlagValue()
if network.Kind == models.Local || network.Kind == models.Devnet {
networkID = fmt.Sprintf("%d", network.ID)
}

avagoDockerImage := fmt.Sprintf("%s:%s", constants.AvalancheGoDockerImage, avalancheGoVersion)
ux.Logger.Info("Preparing AvalancheGo Docker image %s on %s[%s]", avagoDockerImage, host.NodeID, host.IP)
if err := PrepareDockerImageWithRepo(host, avagoDockerImage, constants.AvalancheGoGitRepo, avalancheGoVersion); err != nil {
return err
}
ux.Logger.Info("AvalancheGo Docker image %s ready on %s[%s] after %s", avagoDockerImage, host.NodeID, host.IP, time.Since(startTime))
nodeConfFile, cChainConfFile, err := prepareAvalanchegoConfig(host, networkID)
nodeConfFile, cChainConfFile, err := prepareAvalanchegoConfig(host, network, publicAccessToHTTPPort)
if err != nil {
return err
}
Expand Down
14 changes: 3 additions & 11 deletions pkg/docker/templates/avalanchego.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ services:
ports:
- "9650:9650"
- "9651:9651"
networks:
- avalanchego_net
network_mode: "host"
{{ end }}
{{ end }}

{{if .WithMonitoring}}
promtail:
image: grafana/promtail:3.0.0
Expand All @@ -48,8 +48,6 @@ services:
volumes:
- /home/ubuntu/.avalanchego/logs:/logs:ro
- /home/ubuntu/.avalanche-cli/services/promtail:/etc/promtail:ro
networks:
- avalanchego_net
{{ end }}
node-exporter:
image: prom/node-exporter:v1.7.0
Expand All @@ -68,20 +66,14 @@ services:
{{if .E2E }}
networks:
- avalanchego_net_{{.E2ESuffix}}
{{ else }}
networks:
- avalanchego_net
{{ end }}
{{ end }}
{{end}}

{{if .E2E }}
volumes:
avalanchego_data_{{.E2ESuffix}}:
avalanchego_logs_{{.E2ESuffix}}:
networks:
avalanchego_net_{{.E2ESuffix}}:
{{ else }}
networks:
avalanchego_net:
{{ end }}

5 changes: 1 addition & 4 deletions pkg/docker/templates/awmrelayer.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ services:
container_name: awm-relayer
restart: unless-stopped
user: "1000:1000" # ubuntu user
networks:
- avalanchego_net
network_mode: "host"
volumes:
- /home/ubuntu/.avalanche-cli/services/awm-relayer:/.awm-relayer:rw
command: 'awm-relayer --config-file /.awm-relayer/awm-relayer-config.json'
networks:
avalanchego_net:
11 changes: 0 additions & 11 deletions pkg/docker/templates/monitoring.docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ services:
- '--storage.tsdb.path=/var/lib/prometheus'
links:
- node-exporter
networks:
- monitoring_net

grafana:
image: grafana/grafana:10.4.1
Expand All @@ -31,8 +29,6 @@ services:
links:
- prometheus
- loki
networks:
- monitoring_net

loki:
image: grafana/loki:3.0.0
Expand All @@ -45,21 +41,14 @@ services:
volumes:
- /home/ubuntu/.avalanche-cli/services/loki:/etc/loki:ro
- /home/ubuntu/.avalanche-cli/services/loki/data:/var/lib/loki:rw
networks:
- monitoring_net

node-exporter:
image: prom/node-exporter:v1.7.0
container_name: node-exporter
restart: unless-stopped
ports:
- "9100:9100"
networks:
- monitoring_net
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro

networks:
monitoring_net:
Loading

0 comments on commit c391d07

Please sign in to comment.