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

add subnet alias #1987

Merged
merged 31 commits into from
Aug 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
da96adf
add api for fuji
arturrez Jun 20, 2024
85caa00
put old code back
arturrez Jun 20, 2024
31c4110
add subnet alias
arturrez Jun 20, 2024
9cf03c4
avoid github api if custom version is set
arturrez Jul 2, 2024
5765bfd
add publicAPI to network
arturrez Jul 3, 2024
7a405c2
Merge branch 'main' into fuji-api
arturrez Jul 3, 2024
e2eaf34
fixes
arturrez Jul 3, 2024
07a4e24
fix golang template newline
arturrez Jul 3, 2024
3266cee
switch to host network
arturrez Jul 3, 2024
38cf267
fix template
arturrez Jul 3, 2024
d7c08ee
rm host mode for monitoring
arturrez Jul 3, 2024
2ae0bb5
add e2e support back to template
arturrez Jul 3, 2024
e70c1ba
fix e2e indent
arturrez Jul 3, 2024
d76f0a7
make sure that all API hosts can receive traffic on IP and not localhost
arturrez Jul 10, 2024
d32ddb0
lint
arturrez Jul 10, 2024
6f4f5e6
Merge branch 'main' into fuji-api-alias
arturrez Jul 18, 2024
a549b1b
change subnet-alias implementation after join refactor
arturrez Jul 18, 2024
2e14262
Merge branch 'main' into fuji-api
arturrez Jul 18, 2024
df7095b
mv public access config to clusterconf and address other felipe feedback
arturrez Jul 24, 2024
2eda222
lint
arturrez Jul 24, 2024
c5f0980
Merge branch 'fuji-api' into fuji-api-alias
arturrez Jul 24, 2024
afd065d
check for err
arturrez Jul 25, 2024
dfc7ac4
fix wiz
arturrez Jul 25, 2024
9862694
prepareAvala
arturrez Jul 29, 2024
4584425
additional subnet aliases
arturrez Jul 29, 2024
504698b
Merge branch 'main' into fuji-api-alias
arturrez Jul 30, 2024
76a4b5f
address felipe feedback
arturrez Jul 30, 2024
06dce2b
add helperfunc to template
arturrez Jul 30, 2024
6956f86
fix
arturrez Jul 30, 2024
301d4b0
fix text/template instead of html
arturrez Jul 30, 2024
715fe3d
use text/template
arturrez Jul 30, 2024
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
6 changes: 4 additions & 2 deletions cmd/nodecmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import (
)

var (
subnetOnly bool
avoidChecks bool
subnetOnly bool
avoidChecks bool
subnetAliases []string
)

func newDeployCmd() *cobra.Command {
Expand All @@ -33,6 +34,7 @@ It saves the deploy info both locally and remotely.
}
cmd.Flags().BoolVar(&subnetOnly, "subnet-only", false, "only create a subnet")
cmd.Flags().BoolVar(&avoidChecks, "no-checks", false, "do not check for healthy status or rpc compatibility of nodes against subnet")
cmd.Flags().StringSliceVar(&subnetAliases, "subnet-aliases", nil, "additional subnet aliases to be used for RPC calls in addition to subnet blockchain name")
return cmd
}

Expand Down
13 changes: 13 additions & 0 deletions cmd/nodecmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ You can check the subnet bootstrap status by calling avalanche node status <clus

cmd.Flags().StringSliceVar(&validators, "validators", []string{}, "sync subnet into given comma separated list of validators. defaults to all cluster nodes")
cmd.Flags().BoolVar(&avoidChecks, "no-checks", false, "do not check for bootstrapped/healthy status or rpc compatibility of nodes against subnet")
cmd.Flags().StringSliceVar(&subnetAliases, "subnet-aliases", nil, "subnet alias to be used for RPC calls. defaults to subnet blockchain ID")

return cmd
}
Expand Down Expand Up @@ -124,15 +125,27 @@ func trackSubnet(
// and get list of subnets
allSubnets := utils.Unique(append(clusterConf.Subnets, subnetName))

// load sidecar to get subnet blockchain ID
sc, err := app.LoadSidecar(subnetName)
if err != nil {
return nil, err
}
blockchainID := sc.Networks[network.Name()].BlockchainID

wg := sync.WaitGroup{}
wgResults := models.NodeResults{}
subnetAliases := append([]string{subnetName}, subnetAliases...)
for _, host := range hosts {
wg.Add(1)
go func(nodeResults *models.NodeResults, host *models.Host) {
defer wg.Done()
if err := ssh.RunSSHStopNode(host); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}

if err := ssh.RunSSHRenderAvagoAliasConfigFile(host, blockchainID.String(), subnetAliases); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}
if err := ssh.RunSSHRenderAvalancheNodeConfig(app, host, network, allSubnets); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}
Expand Down
1 change: 1 addition & 0 deletions cmd/nodecmd/wiz.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in
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")
cmd.Flags().StringSliceVar(&subnetAliases, "subnet-aliases", nil, "additional subnet aliases to be used for RPC calls in addition to subnet blockchain name")
return cmd
}

Expand Down
1 change: 1 addition & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const (
SuffixSeparator = "_"
SidecarFileName = "sidecar.json"
GenesisFileName = "genesis.json"
AliasesFileName = "aliases.json"
SidecarSuffix = SuffixSeparator + SidecarFileName
GenesisSuffix = SuffixSeparator + GenesisFileName
NodeFileName = "node.json"
Expand Down
2 changes: 1 addition & 1 deletion pkg/docker/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (
"bytes"
"embed"
"fmt"
"html/template"
"os"
"path/filepath"
"strings"
"text/template"
"time"

"github.com/ava-labs/avalanche-cli/pkg/constants"
Expand Down
27 changes: 23 additions & 4 deletions pkg/remoteconfig/avalanche.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ package remoteconfig

import (
"bytes"
"html/template"
"path/filepath"
"strings"
"text/template"

"github.com/ava-labs/avalanche-cli/pkg/constants"
)
Expand All @@ -22,6 +22,8 @@ type AvalancheConfigInputs struct {
PublicIP string
StateSyncEnabled bool
PruningEnabled bool
Aliases []string
BlockChainID string
TrackSubnets string
BootstrapIDs string
BootstrapIPs string
Expand All @@ -38,6 +40,8 @@ func PrepareAvalancheConfig(publicIP string, networkID string, subnets []string)
StateSyncEnabled: true,
PruningEnabled: false,
TrackSubnets: strings.Join(subnets, ","),
Aliases: nil,
BlockChainID: "",
}
}

Expand All @@ -46,7 +50,10 @@ func RenderAvalancheTemplate(templateName string, config AvalancheConfigInputs)
if err != nil {
return nil, err
}
tmpl, err := template.New("config").Parse(string(templateBytes))
helperFuncs := template.FuncMap{
"join": strings.Join,
}
tmpl, err := template.New("config").Funcs(helperFuncs).Parse(string(templateBytes))
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -75,16 +82,28 @@ func RenderAvalancheCChainConfig(config AvalancheConfigInputs) ([]byte, error) {
}
}

func RenderAvalancheAliasesConfig(config AvalancheConfigInputs) ([]byte, error) {
if output, err := RenderAvalancheTemplate("templates/avalanche-aliases.tmpl", config); err != nil {
return nil, err
} else {
return output, nil
}
}

func GetRemoteAvalancheNodeConfig() string {
return filepath.Join(constants.CloudNodeConfigPath, "node.json")
return filepath.Join(constants.CloudNodeConfigPath, constants.NodeFileName)
}

func GetRemoteAvalancheCChainConfig() string {
return filepath.Join(constants.CloudNodeConfigPath, "chains", "C", "config.json")
}

func GetRemoteAvalancheGenesis() string {
return filepath.Join(constants.CloudNodeConfigPath, "genesis.json")
return filepath.Join(constants.CloudNodeConfigPath, constants.GenesisFileName)
}

func GetRemoteAvalancheAliasesConfig() string {
return filepath.Join(constants.CloudNodeConfigPath, "chains", constants.AliasesFileName)
}

func AvalancheFolderToCreate() []string {
Expand Down
3 changes: 3 additions & 0 deletions pkg/remoteconfig/templates/avalanche-aliases.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"{{.BlockChainID}}": ["{{join .Aliases "\", \""}}"]
}
65 changes: 64 additions & 1 deletion pkg/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,51 @@ func RunSSHUploadStakingFiles(host *models.Host, nodeInstanceDirPath string) err
)
}

// RunSSHRenderAvagoAliasConfigFile renders avalanche alias config to a remote host via SSH.
func RunSSHRenderAvagoAliasConfigFile(
host *models.Host,
blockchainID string,
subnetAliases []string,
) error {
aliasConf, err := remoteconfig.RenderAvalancheAliasesConfig(remoteconfig.AvalancheConfigInputs{
BlockChainID: blockchainID,
Aliases: subnetAliases,
})
if err != nil {
return err
}
// merge alias config into remote config
if aliasConfigFileExists(host) {
// read remote aliases
remoteAliases, err := getAvalancheGoAliasData(host)
if err != nil {
return err
}
localAliases := make(map[string]interface{})
if err := json.Unmarshal(aliasConf, &localAliases); err != nil {
return err
}
// merge with local aliases presedence. Result is in remoteAliases
maps.Copy(remoteAliases, localAliases)
aliasConf, err = json.MarshalIndent(remoteAliases, "", " ")
if err != nil {
return err
}
}
aliasConfFile, err := os.CreateTemp("", "avalanchecli-alias-*.yml")
if err != nil {
return err
}
defer os.Remove(aliasConfFile.Name())
if err := os.WriteFile(aliasConfFile.Name(), aliasConf, constants.DefaultPerms755); err != nil {
return err
}
if err := host.Upload(aliasConfFile.Name(), remoteconfig.GetRemoteAvalancheAliasesConfig(), constants.SSHFileOpsTimeout); err != nil {
return err
}
return nil
}

// RunSSHRenderAvalancheNodeConfig renders avalanche node config to a remote host via SSH.
func RunSSHRenderAvalancheNodeConfig(app *application.Avalanche, host *models.Host, network models.Network, trackSubnets []string) error {
// get subnet ids
Expand Down Expand Up @@ -851,9 +896,14 @@ func nodeConfigFileExists(host *models.Host) bool {
return nodeConfigFileExists
}

func aliasConfigFileExists(host *models.Host) bool {
aliasConfigFileExists, _ := host.FileExists(remoteconfig.GetRemoteAvalancheAliasesConfig())
return aliasConfigFileExists
}

func getAvalancheGoConfigData(host *models.Host) (map[string]interface{}, error) {
// get remote node.json file
nodeJSONPath := filepath.Join(constants.CloudNodeConfigPath, constants.NodeFileName)
nodeJSONPath := filepath.Join(constants.CloudNodeConfigPath, constants.NodeConfigJSONFile)
// parse node.json file
nodeJSON, err := host.ReadFileBytes(nodeJSONPath, constants.SSHFileOpsTimeout)
if err != nil {
Expand All @@ -865,3 +915,16 @@ func getAvalancheGoConfigData(host *models.Host) (map[string]interface{}, error)
}
return avagoConfig, nil
}

func getAvalancheGoAliasData(host *models.Host) (map[string]interface{}, error) {
// parse aliases.json file
aliasesJSON, err := host.ReadFileBytes(remoteconfig.GetRemoteAvalancheAliasesConfig(), constants.SSHFileOpsTimeout)
if err != nil {
return nil, err
}
var aliases map[string]interface{}
if err := json.Unmarshal(aliasesJSON, &aliases); err != nil {
return nil, err
}
return aliases, nil
}
2 changes: 1 addition & 1 deletion pkg/utils/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import (
"bytes"
"encoding/base64"
"fmt"
"html/template"
"os"
"os/exec"
"regexp"
"strings"
"text/template"

"github.com/ava-labs/avalanche-cli/pkg/constants"
)
Expand Down
Loading