Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions cmd/blockchaincmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ func CallCreate(
customVMRepoURLParam string,
customVMBranchParam string,
customVMBuildScriptParam string,
customVMPath string,
) error {
forceCreate = forceCreateParam
genesisPath = genesisPathParam
Expand All @@ -174,6 +175,7 @@ func CallCreate(
customVMRepoURL = customVMRepoURLParam
customVMBranch = customVMBranchParam
customVMBuildScript = customVMBuildScriptParam
vmFile = customVMPath
return createBlockchainConfig(cmd, []string{blockchainName})
}

Expand Down
53 changes: 45 additions & 8 deletions cmd/nodecmd/load_test_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/ava-labs/avalanche-cli/pkg/ansible"
"github.com/ava-labs/avalanche-cli/pkg/application"
Expand All @@ -29,13 +30,14 @@ import (
)

var (
loadTestRepoURL string
loadTestBuildCmd string
loadTestCmd string
loadTestRepoCommit string
repoDirName string
loadTestHostRegion string
loadTestBranch string
loadTestRepoURL string
loadTestBuildCmd string
loadTestCmd string
loadTestRepoCommit string
repoDirName string
loadTestHostRegion string
loadTestBranch string
loadTestDeployKeyPath string
)

type clusterInfo struct {
Expand Down Expand Up @@ -80,6 +82,7 @@ The command will then run the load test binary based on the provided load test r
cmd.Flags().StringVar(&loadTestCmd, "load-test-cmd", "", "command to run load test")
cmd.Flags().StringVar(&loadTestHostRegion, "region", "", "create load test node in a given region")
cmd.Flags().StringVar(&loadTestBranch, "load-test-branch", "", "load test branch or commit")
cmd.Flags().StringVar(&loadTestDeployKeyPath, "load-test-deploy-key", "", "path to SSH deploy key for private repository access")
return cmd
}

Expand Down Expand Up @@ -357,6 +360,20 @@ func startLoadTest(_ *cobra.Command, args []string) error {
}

ux.Logger.GreenCheckmarkToUser("Load test environment is ready!")

// Setup deploy key for private repository access if provided
if loadTestDeployKeyPath != "" {
ux.Logger.PrintToUser("%s Setting up deploy key for private repository", logging.Green.Wrap(">"))
if err := ssh.RunSSHSetupDeployKey(currentLoadTestHost[0], loadTestDeployKeyPath); err != nil {
return fmt.Errorf("failed to setup deploy key for private repository: %w", err)
}

// Update repository URL to use SSH config if it's a GitHub SSH URL
if strings.HasPrefix(loadTestRepoURL, "git@github.com:") {
loadTestRepoURL = strings.Replace(loadTestRepoURL, "git@github.com:", "git@github.com-avalanche:", 1)
}
}

ux.Logger.PrintToUser("%s Building load test code", logging.Green.Wrap(">"))
if err := ssh.RunSSHBuildLoadTestCode(currentLoadTestHost[0], loadTestRepoURL, loadTestBuildCmd, loadTestRepoCommit, repoDirName, loadTestBranch, checkoutCommit); err != nil {
return err
Expand Down Expand Up @@ -485,7 +502,7 @@ func GetLoadTestScript(app *application.Avalanche) error {
var err error
if loadTestRepoURL != "" {
ux.Logger.PrintToUser("Checking source code repository URL %s", loadTestRepoURL)
if err := prompts.ValidateURL(loadTestRepoURL); err != nil {
if err := validateRepositoryURL(loadTestRepoURL); err != nil {
ux.Logger.PrintToUser("Invalid repository url %s: %s", loadTestRepoURL, err)
loadTestRepoURL = ""
}
Expand Down Expand Up @@ -534,3 +551,23 @@ func getExistingLoadTestInstance(clusterName, loadTestName string) (string, erro
}
return "", nil
}

// validateRepositoryURL validates both HTTP and SSH repository URLs
func validateRepositoryURL(url string) error {
// Check if it's an SSH URL (git@host:path format)
if strings.HasPrefix(url, "git@") && strings.Contains(url, ":") {
// Basic SSH URL validation
parts := strings.Split(url, ":")
if len(parts) != 2 {
return fmt.Errorf("invalid SSH URL format")
}
hostPart := strings.TrimPrefix(parts[0], "git@")
if hostPart == "" || parts[1] == "" {
return fmt.Errorf("invalid SSH URL format")
}
return nil
}

// For HTTP/HTTPS URLs, use the existing validation
return prompts.ValidateURL(url)
}
3 changes: 3 additions & 0 deletions cmd/nodecmd/wiz.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ var (
customVMRepoURL string
customVMBranch string
customVMBuildScript string
customVMPath string
nodeConf string
subnetConf string
chainConf string
Expand Down Expand Up @@ -122,6 +123,7 @@ The node wiz command creates a devnet and deploys, sync and validate a subnet in
cmd.Flags().StringVar(&customVMRepoURL, "custom-vm-repo-url", "", "custom vm repository url")
cmd.Flags().StringVar(&customVMBranch, "custom-vm-branch", "", "custom vm branch or commit")
cmd.Flags().StringVar(&customVMBuildScript, "custom-vm-build-script", "", "custom vm build-script")
cmd.Flags().StringVar(&customVMPath, "custom-vm-path", "", "custom vm branch or commit")
cmd.Flags().StringVar(&customGrafanaDashboardPath, "add-grafana-dashboard", "", "path to additional grafana dashboard json file")
cmd.Flags().StringVar(&nodeConf, "node-config", "", "path to avalanchego node configuration for subnet")
cmd.Flags().StringVar(&subnetConf, "subnet-config", "", "path to the subnet configuration for subnet")
Expand Down Expand Up @@ -210,6 +212,7 @@ func wiz(cmd *cobra.Command, args []string) error {
customVMRepoURL,
customVMBranch,
customVMBuildScript,
customVMPath,
); err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions pkg/models/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type Sidecar struct {
CustomVMRepoURL string
CustomVMBranch string
CustomVMBuildScript string
CustomVMPath string
// ICM related
TeleporterReady bool
TeleporterKey string
Expand Down
28 changes: 20 additions & 8 deletions pkg/node/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,26 @@ func prepareSubnetPlugin(app *application.Avalanche, hosts []*models.Host, block
}
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)
if sc.CustomVMRepoURL == "" && sc.CustomVMPath != "" {
for _, host := range hosts {
wg.Add(1)
go func(nodeResults *models.NodeResults, host *models.Host) {
defer wg.Done()
if err := ssh.RunSSHCopyBinaryFile(host, sc); err != nil {
nodeResults.AddResult(host.NodeID, nil, err)
}
}(&wgResults, host)
}
} else {
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() {
Expand Down
30 changes: 30 additions & 0 deletions pkg/ssh/shell/setupDeployKey.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
# Setup SSH deploy key for private repository access

# Create .ssh directory if it doesn't exist
mkdir -p ~/.ssh

# Set proper permissions
chmod 700 ~/.ssh

# Upload the deploy key (this will be done by the Go code before calling this script)
# The key should already be at ~/.ssh/avalanche-deploy-key

# Set proper permissions for the deploy key
chmod 600 /home/ubuntu/.ssh/avalanche-deploy-key

# Configure SSH to use the deploy key
cat >> ~/.ssh/config <<'EOF'
Host github.com-avalanche
HostName github.com
User git
IdentityFile /home/ubuntu/.ssh/avalanche-deploy-key
IdentitiesOnly yes
StrictHostKeyChecking accept-new
EOF

# Test the SSH connection
echo "Testing SSH connection to GitHub..."
ssh -T github.com-avalanche || true

echo "Deploy key setup completed successfully!"
71 changes: 71 additions & 0 deletions pkg/ssh/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,31 @@ func RunSSHRenderAvalancheNodeConfig(
return host.UploadBytes(nodeConf, remoteconfig.GetRemoteAvalancheNodeConfig(), constants.SSHFileOpsTimeout)
}

func RunSSHCopyBinaryFile(host *models.Host, sc models.Sidecar) error {
vmID, err := sc.GetVMID()
if err != nil {
return err
}
subnetVMBinaryPath := fmt.Sprintf(constants.CloudNodeSubnetEvmBinaryPath, vmID)
ux.Logger.Info("Building Custom VM for %s to %s", host.NodeID, subnetVMBinaryPath)
Copy link
Collaborator

Choose a reason for hiding this comment

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

it is not strictly building

if err := host.Upload(
sc.CustomVMPath,
subnetVMBinaryPath,
constants.SSHFileOpsTimeout,
); err != nil {
return err
}

// set execute permissions
cmd := fmt.Sprintf("chmod +x %s", subnetVMBinaryPath)
ux.Logger.Info("Setting permissions for %s on %s", subnetVMBinaryPath, host.NodeID)
if _, err := host.Command(cmd, nil, constants.SSHScriptTimeout); err != nil {
return err
}

return nil
}

// RunSSHCreatePlugin runs script to create plugin
func RunSSHCreatePlugin(host *models.Host, sc models.Sidecar) error {
vmID, err := sc.GetVMID()
Expand Down Expand Up @@ -795,6 +820,52 @@ func RunSSHBuildLoadTestCode(host *models.Host, loadTestRepo, loadTestPath, load
)
}

// RunSSHSetupDeployKey sets up SSH deploy key for private repository access
func RunSSHSetupDeployKey(host *models.Host, deployKeyPath string) error {
// Expand tilde in the path
expandedPath, err := expandTilde(deployKeyPath)
if err != nil {
return fmt.Errorf("failed to expand deploy key path: %w", err)
}

// Check if the deploy key file exists
if _, err := os.Stat(expandedPath); os.IsNotExist(err) {
return fmt.Errorf("deploy key file not found: %s", expandedPath)
}

// Upload the deploy key first
remoteDeployKeyPath := "/home/ubuntu/.ssh/avalanche-deploy-key"

if err := host.Upload(expandedPath, remoteDeployKeyPath, constants.SSHFileOpsTimeout); err != nil {
return fmt.Errorf("failed to upload deploy key: %w", err)
}

// Run the setup script
return RunOverSSH(
"Setup Deploy Key",
host,
constants.SSHFileOpsTimeout,
"shell/setupDeployKey.sh",
scriptInputs{},
)
}

// expandTilde expands ~ to the user's home directory
func expandTilde(path string) (string, error) {
if strings.HasPrefix(path, "~") {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
// Handle both ~/ and ~ cases
if len(path) == 1 {
return homeDir, nil
}
return filepath.Join(homeDir, path[1:]), nil
}
return path, nil
}

func RunSSHBuildLoadTestDependencies(host *models.Host) error {
return RunOverSSH(
"Build Load Test",
Expand Down
13 changes: 13 additions & 0 deletions pkg/utils/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,19 @@ func GetIndexInSlice[T comparable](list []T, element T) (int, error) {
// Example: https://github.com/ava-labs/hypersdk/pull/772/commits/b88acfb370f5aeb83a000aece2d72f28154410a5
// Should return https://github.com/ava-labs/hypersdk
func GetRepoFromCommitURL(gitRepoURL string) (string, string) {
// Handle SSH URLs (git@host:path format)
if strings.HasPrefix(gitRepoURL, "git@") && strings.Contains(gitRepoURL, ":") {
parts := strings.Split(gitRepoURL, ":")
if len(parts) == 2 {
// Extract repo name from path (remove .git suffix if present)
// For git@github.com:owner/repo.git, we want just "repo"
pathParts := strings.Split(parts[1], "/")
repoName := strings.TrimSuffix(pathParts[len(pathParts)-1], ".git")
return gitRepoURL, repoName
}
}

// Handle HTTP/HTTPS URLs
splitURL := strings.Split(gitRepoURL, "/")
if len(splitURL) > 4 {
// get first five members of splitURL because it will be [ https, ' ', github.com, ava-labs, hypersdk]
Expand Down
3 changes: 3 additions & 0 deletions pkg/vm/create_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ func CreateCustomSidecar(

sc.RPCVersion = rpcVersion
sc.Sovereign = sovereign
if vmPath != "" {
sc.CustomVMPath = vmPath
}
return sc, nil
}

Expand Down
Loading