[#466] adm: Allow to download contracts from Gitea

Signed-off-by: Olga Konstantinova <kola43843@gmail.com>
This commit is contained in:
Olga Konstantinova 2024-02-03 20:17:12 +03:00 committed by okonstantinova
parent 805862f4b7
commit 80b581d499
6 changed files with 108 additions and 7 deletions

View file

@ -0,0 +1,81 @@
package morph
import (
"context"
"errors"
"fmt"
"io"
"net"
"net/http"
"strings"
"time"
"code.gitea.io/sdk/gitea"
"github.com/spf13/cobra"
)
func downloadContracts(cmd *cobra.Command, url string) (io.ReadCloser, error) {
cmd.Printf("Downloading contracts archive from '%s'\n", url)
// HTTP client with connect timeout
client := http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 10 * time.Second,
}).DialContext,
},
}
ctx, cancel := context.WithTimeout(cmd.Context(), 60*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return nil, fmt.Errorf("can't create request: %w", err)
}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("can't fetch contracts archive: %w", err)
}
return resp.Body, nil
}
func downloadContractsFromRepository(cmd *cobra.Command) (io.ReadCloser, error) {
client, err := gitea.NewClient("https://git.frostfs.info")
if err != nil {
return nil, fmt.Errorf("can't initialize repository client: %w", err)
}
releases, _, err := client.ListReleases("TrueCloudLab", "frostfs-contract", gitea.ListReleasesOptions{})
if err != nil {
return nil, fmt.Errorf("can't fetch release information: %w", err)
}
var latestRelease *gitea.Release
for _, r := range releases {
if !r.IsDraft && !r.IsPrerelease {
latestRelease = r
break
}
}
if latestRelease == nil {
return nil, fmt.Errorf("attempt to fetch contracts archive from the offitial repository failed: no releases found")
}
cmd.Printf("Found release %s (%s)\n", latestRelease.TagName, latestRelease.Title)
var url string
for _, a := range latestRelease.Attachments {
if strings.HasPrefix(a.Name, "frostfs-contract") {
url = a.DownloadURL
break
}
}
if url == "" {
return nil, errors.New("can't find contracts archive in the latest release")
}
return downloadContracts(cmd, url)
}

View file

@ -50,6 +50,7 @@ type initializeContext struct {
Contracts map[string]*contractState Contracts map[string]*contractState
Command *cobra.Command Command *cobra.Command
ContractPath string ContractPath string
ContractURL string
} }
var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", maxAlphabetNodes) var ErrTooManyAlphabetNodes = fmt.Errorf("too many alphabet nodes (maximum allowed is %d)", maxAlphabetNodes)
@ -152,6 +153,11 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
return nil, err return nil, err
} }
var ctrURL string
if needContracts {
ctrURL, _ = cmd.Flags().GetString(contractsURLFlag)
}
if err := checkNotaryEnabled(c); err != nil { if err := checkNotaryEnabled(c); err != nil {
return nil, err return nil, err
} }
@ -176,6 +182,7 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
Command: cmd, Command: cmd,
Contracts: make(map[string]*contractState), Contracts: make(map[string]*contractState),
ContractPath: ctrPath, ContractPath: ctrPath,
ContractURL: ctrURL,
} }
if needContracts { if needContracts {

View file

@ -399,10 +399,14 @@ func (c *initializeContext) readContracts(names []string) error {
} }
} else { } else {
var r io.ReadCloser var r io.ReadCloser
if c.ContractPath == "" { if c.ContractPath != "" {
return errors.New("contracts flag is missing") r, err = os.Open(c.ContractPath)
} else if c.ContractURL != "" {
r, err = downloadContracts(c.Command, c.ContractURL)
} else {
r, err = downloadContractsFromRepository(c.Command)
} }
r, err = os.Open(c.ContractPath)
if err != nil { if err != nil {
return fmt.Errorf("can't open contracts archive: %w", err) return fmt.Errorf("can't open contracts archive: %w", err)
} }

View file

@ -17,6 +17,9 @@ const (
storageGasCLIFlag = "initial-gas" storageGasCLIFlag = "initial-gas"
storageGasConfigFlag = "storage.initial_gas" storageGasConfigFlag = "storage.initial_gas"
contractsInitFlag = "contracts" contractsInitFlag = "contracts"
contractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)"
contractsURLFlag = "contracts-url"
contractsURLFlagDesc = "URL to archive with compiled FrostFS contracts"
maxObjectSizeInitFlag = "network.max_object_size" maxObjectSizeInitFlag = "network.max_object_size"
maxObjectSizeCLIFlag = "max-object-size" maxObjectSizeCLIFlag = "max-object-size"
epochDurationInitFlag = "network.epoch_duration" epochDurationInitFlag = "network.epoch_duration"
@ -370,8 +373,9 @@ func initUpdateContractsCmd() {
RootCmd.AddCommand(updateContractsCmd) RootCmd.AddCommand(updateContractsCmd)
updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) updateContractsCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc)
updateContractsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) updateContractsCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc)
updateContractsCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts") updateContractsCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc)
_ = updateContractsCmd.MarkFlagRequired(contractsInitFlag) updateContractsCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc)
updateContractsCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag)
} }
func initDumpBalancesCmd() { func initDumpBalancesCmd() {
@ -441,8 +445,8 @@ func initInitCmd() {
RootCmd.AddCommand(initCmd) RootCmd.AddCommand(initCmd)
initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc) initCmd.Flags().String(alphabetWalletsFlag, "", alphabetWalletsFlagDesc)
initCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc) initCmd.Flags().StringP(endpointFlag, endpointFlagShort, "", endpointFlagDesc)
initCmd.Flags().String(contractsInitFlag, "", "Path to archive with compiled FrostFS contracts") initCmd.Flags().String(contractsInitFlag, "", contractsInitFlagDesc)
_ = initCmd.MarkFlagRequired(contractsInitFlag) initCmd.Flags().String(contractsURLFlag, "", contractsURLFlagDesc)
initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch") initCmd.Flags().Uint(epochDurationCLIFlag, 240, "Amount of side chain blocks in one FrostFS epoch")
initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes") initCmd.Flags().Uint(maxObjectSizeCLIFlag, 67108864, "Max single object size in bytes")
initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing") initCmd.Flags().Bool(homomorphicHashDisabledCLIFlag, false, "Disable object homomorphic hashing")
@ -451,6 +455,7 @@ func initInitCmd() {
initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee") initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "Container alias fee")
initCmd.Flags().String(protoConfigPath, "", "Path to the consensus node configuration") initCmd.Flags().String(protoConfigPath, "", "Path to the consensus node configuration")
initCmd.Flags().String(localDumpFlag, "", "Path to the blocks dump file") initCmd.Flags().String(localDumpFlag, "", "Path to the blocks dump file")
initCmd.MarkFlagsMutuallyExclusive(contractsInitFlag, contractsURLFlag)
} }
func initGenerateAlphabetCmd() { func initGenerateAlphabetCmd() {

4
go.mod
View file

@ -3,6 +3,7 @@ module git.frostfs.info/TrueCloudLab/frostfs-node
go 1.20 go 1.20
require ( require (
code.gitea.io/sdk/gitea v0.17.1
git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c git.frostfs.info/TrueCloudLab/frostfs-api-go/v2 v2.16.1-0.20240112150928-72885aae835c
git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa git.frostfs.info/TrueCloudLab/frostfs-contract v0.18.1-0.20240115082915-f2a82aa635aa
git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65 git.frostfs.info/TrueCloudLab/frostfs-observability v0.0.0-20231101111734-b3ad3335ff65
@ -61,8 +62,10 @@ require (
github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect github.com/consensys/gnark-crypto v0.12.2-0.20231222162921-eb75782795d2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
@ -71,6 +74,7 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 // indirect
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.0.1 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/uint256 v1.2.4 // indirect github.com/holiman/uint256 v1.2.4 // indirect

BIN
go.sum

Binary file not shown.