-
Notifications
You must be signed in to change notification settings - Fork 80
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
public archive sdk #2426
public archive sdk #2426
Changes from all commits
1ba4d47
d2618b3
eb1359d
fd5ec0c
167a623
20907d5
9ae7c69
710408c
6f9cee2
a531f62
d4e03c9
c48bc75
ef97841
dcb2780
8592aba
a92819f
10b4d47
6066e3a
24102cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,6 +7,8 @@ import ( | |
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"regexp" | ||
"sort" | ||
"strconv" | ||
|
@@ -24,8 +26,11 @@ import ( | |
"github.com/ava-labs/avalanche-cli/pkg/utils" | ||
"github.com/ava-labs/avalanche-cli/pkg/ux" | ||
"github.com/ava-labs/avalanche-cli/pkg/vm" | ||
"github.com/ava-labs/avalanche-cli/sdk/network" | ||
"github.com/ava-labs/avalanche-cli/sdk/publicarchive" | ||
"github.com/ava-labs/avalanche-network-runner/rpcpb" | ||
"github.com/ava-labs/avalanchego/api/info" | ||
"github.com/ava-labs/avalanchego/utils/logging" | ||
"github.com/ava-labs/avalanchego/utils/set" | ||
) | ||
|
||
|
@@ -555,3 +560,75 @@ func GetNodeData(endpoint string) ( | |
"0x" + hex.EncodeToString(proofOfPossession.ProofOfPossession[:]), | ||
nil | ||
} | ||
|
||
func DownloadPublicArchive( | ||
clusterNetwork models.Network, | ||
rootDir string, | ||
nodeNames []string, | ||
) error { | ||
// only fuji is supported for now | ||
if clusterNetwork.Kind != models.Fuji { | ||
return fmt.Errorf("unsupported network: %s", clusterNetwork.Name()) | ||
} | ||
network := network.FujiNetwork() | ||
ux.Logger.Info("downloading public archive for network %s", clusterNetwork.Name()) | ||
publicArcDownloader, err := publicarchive.NewDownloader(network, logging.NewLogger("public-archive-downloader", logging.NewWrappedCore(logging.Off, os.Stdout, logging.JSON.ConsoleEncoder()))) // off as we run inside of the spinner | ||
if err != nil { | ||
return fmt.Errorf("failed to create public archive downloader for network %s: %w", clusterNetwork.Name(), err) | ||
} | ||
|
||
if err := publicArcDownloader.Download(); err != nil { | ||
return fmt.Errorf("failed to download public archive: %w", err) | ||
} | ||
defer publicArcDownloader.CleanUp() | ||
if path, err := publicArcDownloader.GetFilePath(); err != nil { | ||
return fmt.Errorf("failed to get downloaded file path: %w", err) | ||
} else { | ||
ux.Logger.Info("public archive downloaded to %s", path) | ||
} | ||
|
||
wg := sync.WaitGroup{} | ||
mu := sync.Mutex{} | ||
var firstErr error | ||
|
||
for _, nodeName := range nodeNames { | ||
target := filepath.Join(rootDir, nodeName, "db") | ||
ux.Logger.Info("unpacking public archive to %s", target) | ||
|
||
// Skip if target already exists | ||
if _, err := os.Stat(target); err == nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we override data instead of skip? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no we should skip as data is already there |
||
ux.Logger.Info("data folder already exists at %s. Skipping...", target) | ||
continue | ||
} | ||
wg.Add(1) | ||
go func(target string) { | ||
defer wg.Done() | ||
|
||
if err := publicArcDownloader.UnpackTo(target); err != nil { | ||
// Capture the first error encountered | ||
mu.Lock() | ||
if firstErr == nil { | ||
firstErr = fmt.Errorf("failed to unpack public archive: %w", err) | ||
_ = cleanUpClusterNodeData(rootDir, nodeNames) | ||
} | ||
mu.Unlock() | ||
} | ||
}(target) | ||
} | ||
wg.Wait() | ||
|
||
if firstErr != nil { | ||
return firstErr | ||
} | ||
ux.Logger.PrintToUser("Public archive unpacked to: %s", rootDir) | ||
return nil | ||
} | ||
|
||
func cleanUpClusterNodeData(rootDir string, nodesNames []string) error { | ||
for _, nodeName := range nodesNames { | ||
if err := os.RemoveAll(filepath.Join(rootDir, nodeName)); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -427,6 +427,14 @@ func StartLocalNode( | |
ux.Logger.PrintToUser("Starting local avalanchego node using root: %s ...", rootDir) | ||
spinSession := ux.NewUserSpinner() | ||
spinner := spinSession.SpinToUser("Booting Network. Wait until healthy...") | ||
// preseed nodes data from public archive. ignore errors | ||
nodeNames := []string{} | ||
for i := 1; i <= int(numNodes); i++ { | ||
nodeNames = append(nodeNames, fmt.Sprintf("node%d", i)) | ||
} | ||
err := DownloadPublicArchive(network, rootDir, nodeNames) | ||
ux.Logger.Info("seeding public archive data finished with error: %v. Ignored if any", err) | ||
|
||
if _, err := cli.Start(ctx, avalancheGoBinPath, anrOpts...); err != nil { | ||
ux.SpinFailWithError(spinner, "", err) | ||
_ = DestroyLocalNode(app, clusterName) | ||
|
@@ -490,6 +498,9 @@ func UpsizeLocalNode( | |
nodeConfig = map[string]interface{}{} | ||
} | ||
nodeConfig[config.NetworkAllowPrivateIPsKey] = true | ||
if network.Kind == models.Fuji { | ||
nodeConfig[config.IndexEnabledKey] = false // disable index for Fuji | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what does it mean if this flag is disabled? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dataset for avalanchego created with index and without are not interchangeable |
||
} | ||
nodeConfigBytes, err := json.Marshal(nodeConfig) | ||
if err != nil { | ||
return "", err | ||
|
@@ -586,6 +597,8 @@ func UpsizeLocalNode( | |
|
||
spinSession := ux.NewUserSpinner() | ||
spinner := spinSession.SpinToUser("Creating new node with name %s on local machine", newNodeName) | ||
err = DownloadPublicArchive(network, rootDir, []string{newNodeName}) | ||
ux.Logger.Info("seeding public archive data finished with error: %v. Ignored if any", err) | ||
// add new local node | ||
if _, err := cli.AddNode(ctx, newNodeName, avalancheGoBinPath, anrOpts...); err != nil { | ||
ux.SpinFailWithError(spinner, "", err) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Public Archive Downloader SDK | ||
|
||
This Go package provides a utility to download and extract tar archives from public URLs. It's tailored for downloading Avalanche network archives but can be adapted for other use cases. | ||
|
||
|
||
## Features | ||
|
||
* Downloads files from predefined URLs. | ||
* Tracks download progress and logs status updates. | ||
* Safely unpacks .tar archives to a target directory. | ||
* Includes security checks to prevent path traversal and manage large files. | ||
|
||
## Usage example | ||
|
||
``` | ||
// Copyright (C) 2024, Ava Labs, Inc. All rights reserved | ||
// See the file LICENSE for licensing terms. | ||
|
||
``` | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/ava-labs/avalanche-cli/sdk/network" | ||
"github.com/ava-labs/avalanchego/utils/constants" | ||
"github.com/ava-labs/avalanchego/utils/logging" | ||
"github.com/your-repo-name/publicarchive" | ||
) | ||
|
||
func main() { | ||
// Initialize the downloader | ||
downloader, err := publicarchive.NewDownloader(network.FujiNetwork(), logging.Debug) | ||
if err != nil { | ||
fmt.Printf("Failed to create downloader: %v\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
// Start downloading | ||
if err := downloader.Download(); err != nil { | ||
fmt.Printf("Download failed: %v\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
// Specify the target directory for unpacking | ||
targetDir := "./extracted_files" | ||
if err := downloader.UnpackTo(targetDir); err != nil { | ||
fmt.Printf("Failed to unpack archive: %v\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
fmt.Printf("Files successfully unpacked to %s\n", targetDir) | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should rename this err var
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
err is used in
so it should be some other name