8000 refactor: add&use chaincmdrunner package by ilgooz · Pull Request #612 · ignite/cli · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

refactor: add&use chaincmdrunner package #612

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

Merged
merged 5 commits into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


8000
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ require (
golang.org/x/mod v0.4.0
golang.org/x/net v0.0.0-20201021035429-f5854403a974 // indirect
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect
golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 // indirect
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154 // indirect
google.golang.org/grpc v1.33.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -928,8 +928,8 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo=
golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210105210732-16f7687f5001 h1:/dSxr6gT0FNI1MO5WLJo8mTmItROeOKTkDn+7OwWBos=
golang.org/x/sys v0.0.0-20210105210732-16f7687f5001/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf h1:MZ2shdL+ZM/XzY3ZGOnh4Nlpnxz5GSOhOmtHo3iPU6M=
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
19 changes: 16 additions & 3 deletions starport/pkg/chaincmd/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ func WithChainID(chainID string) Option {
}
}

// WithKeyrinBackend provides a specific keyring backend for the commands that accept this option
func WithKeyrinBackend(keyringBackend KeyringBackend) Option {
// WithKeyringBackend provides a specific keyring backend for the commands that accept this option
func WithKeyringBackend(keyringBackend KeyringBackend) Option {
return func(c *ChainCmd) {
c.keyringBackend = keyringBackend
}
Expand Down Expand Up @@ -152,6 +152,19 @@ func (c ChainCmd) ShowKeyAddressCommand(accountName string) step.Option {
return c.cliCommand(command)
}

// ListKeysCommand returns the command to print the list of a keys in the chain keyring
func (c ChainCmd) ListKeysCommand() step.Option {
command := []string{
commandKeys,
"list",
optionOutput,
constJSON,
}
command = c.attachKeyringBackend(command)

return c.cliCommand(command)
}

// AddGenesisAccountCommand returns the command to add a new account in the genesis file of the chain
func (c ChainCmd) AddGenesisAccountCommand(address string, coins string) step.Option {
command := []string{
Expand All @@ -162,7 +175,7 @@ func (c ChainCmd) AddGenesisAccountCommand(address string, coins string) step.Op
return c.daemonCommand(command)
}

// Options for the GentxCommand
// GentxOption for the GentxCommand
type GentxOption func([]string) []string

// GentxWithMoniker provides moniker option for the gentx command
Expand Down
92 changes: 92 additions & 0 deletions starport/pkg/chaincmd/runner/account.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package chaincmdrunner

import (
"bytes"
"context"
"encoding/json"
"errors"
"strings"

"github.com/tendermint/starport/starport/pkg/cmdrunner/step"
)

// AddAccount creates a new account or imports an account when mnemonic is provided.
// returns with an error if the operation went unsuccessful or an account with the provided name
// already exists.
func (r Runner) AddAccount(ctx context.Context, name, mnemonic string) (Account, error) {
b := &bytes.Buffer{}

// check if account already exists.
var accounts []Account
if err := r.run(ctx, runOptions{stdout: b}, r.cc.ListKeysCommand()); err != nil {
return Account{}, err
}
if err := json.NewDecoder(b).Decode(&accounts); err != nil {
return Account{}, err
}
for _, account := range accounts {
if account.Name == name {
return Account{}, errors.New("account already exists")
}
}
b.Reset()

account := Account{
Name: name,
Mnemonic: mnemonic,
}

// import the account when mnemonic is provided, otherwise create a new one.
if mnemonic != "" {
if err := r.run(
ctx,
runOptions{},
r.cc.ImportKeyCommand(name),
step.Write([]byte(mnemonic+"\n")),
); err != nil {
return Account{}, err
}
} else {
// note that, launchpad prints account output from stderr.
if err := r.run(ctx, runOptions{stdout: b, stderr: b}, r.cc.AddKeyCommand(name)); err != nil {
return Account{}, err
}
if err := json.NewDecoder(b).Decode(&account); err != nil {
return Account{}, err
}

b.Reset()
}

// get full details of the account.
if err := r.run(ctx, runOptions{stdout: b}, r.cc.ShowKeyAddressCommand(name)); err != nil {
return Account{}, err
}
account.Address = strings.TrimSpace(b.String())

return account, nil
}

// Account represents a user account.
type Account struct {
Name string `json:"name"`
Address string `json:"address"`
Mnemonic string `json:"mnemonic,omitempty"`
}

// ShowAccount shows details of an account.
func (r Runner) ShowAccount(ctx context.Context, name string) (Account, error) {
b := &bytes.Buffer{}
if err := r.run(ctx, runOptions{stdout: b}, r.cc.ShowKeyAddressCommand(name)); err != nil {
return Account{}, err
}
return Account{
Name: name,
Address: strings.TrimSpace(b.String()),
}, nil
}

// AddGenesisAccount adds account to genesis by its address.
func (r Runner) AddGenesisAccount(ctx context.Context, address, coins string) error {
return r.run(ctx, runOptions{}, r.cc.AddGenesisAccountCommand(address, coins))
}
78 changes: 78 additions & 0 deletions starport/pkg/chaincmd/runner/chain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package chaincmdrunner

import (
"bytes"
"context"
"regexp"
"strings"

"github.com/tendermint/starport/starport/pkg/chaincmd"
)

// Start starts the blockchain.
func (r Runner) Start(ctx context.Context, args ...string) error {
return r.run(ctx, runOptions{longRunning: true}, r.cc.StartCommand(args...))
}

// LaunchpadStartRestServer start launchpad rest server.
func (r Runner) LaunchpadStartRestServer(ctx context.Context, apiAddress, rpcAddress string) error {
return r.run(ctx, runOptions{longRunning: true}, r.cc.LaunchpadRestServerCommand(apiAddress, rpcAddress))
}

// Init inits the blockchain.
func (r Runner) Init(ctx context.Context, moniker string) error {
return r.run(ctx, runOptions{}, r.cc.InitCommand(moniker))
}

// KV holds a key, value pair.
type KV struct {
key string
value string
}

// NewKV returns a new key, value pair.
func NewKV(key, value string) KV {
return KV{key, value}
}

// LaunchpadSetConfigs updates configurations for a launchpad app.
func (r Runner) LaunchpadSetConfigs(ctx context.Context, kvs ...KV) error {
for _, kv := range kvs {
if err := r.run(ctx, runOptions{}, r.cc.LaunchpadSetConfigCommand(kv.key, kv.value)); err != nil {
return err
}
}
return nil
}

var gentxRe = regexp.MustCompile(`(?m)"(.+?)"`)

// Gentx generates a genesis tx carrying a self delegation.
func (r Runner) Gentx(ctx context.Context, validatorName, selfDelegation string, options ...chaincmd.GentxOption) (gentxPath string, err error) {
b := &bytes.Buffer{}

// note: launchpad outputs from stderr.
if err := r.run(ctx, runOptions{stdout: b, stderr: b}, r.cc.GentxCommand(validatorName, selfDelegation, options...)); err != nil {
return "", err
}

return gentxRe.FindStringSubmatch(b.String())[1], nil
}

// CollectGentxs collects gentxs.
func (r Runner) CollectGentxs(ctx context.Context) error {
return r.run(ctx, runOptions{}, r.cc.CollectGentxsCommand())
}

// ValidateGenesis validates genesis.
func (r Runner) ValidateGenesis(ctx context.Context) error {
return r.run(ctx, runOptions{}, r.cc.ValidateGenesisCommand())
}

// ShowNodeID shows node id.
func (r Runner) ShowNodeID(ctx context.Context) (nodeID string, err error) {
b := &bytes.Buffer{}
err = r.run(ctx, runOptions{stdout: b}, r.cc.ShowNodeIDCommand())
nodeID = strings.TrimSpace(b.String())
return
}
120 changes: 120 additions & 0 deletions starport/pkg/chaincmd/runner/runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Package chaincmdrunner provides a high level access to a blockchain's commands.
package chaincmdrunner

import (
"bytes"
"context"
"io"
"io/ioutil"

"github.com/pkg/errors"
"github.com/tendermint/starport/starport/pkg/chaincmd"
"github.com/tendermint/starport/starport/pkg/cmdrunner"
"github.com/tendermint/starport/starport/pkg/cmdrunner/step"
"github.com/tendermint/starport/starport/pkg/lineprefixer"
)

// Runner provides a high level access to a blockchain's commands.
type Runner struct {
cc chaincmd.ChainCmd
stdout, stderr io.Writer
daemonLogPrefix, cliLogPrefix string
}

// Option configures Runner.
type Option func(r *Runner)

// Stdout sets stdout for executed commands.
func Stdout(w io.Writer) Option {
return func(r *Runner) {
r.stdout = w
}
}

// DaemonLogPrefix is a prefix added to app's daemon logs.
func DaemonLogPrefix(prefix string) Option {
return func(r *Runner) {
r.daemonLogPrefix = prefix
}
}

// CLILogPrefix is a prefix added to app's cli logs.
func CLILogPrefix(prefix string) Option {
return func(r *Runner) {
r.cliLogPrefix = prefix
}
}

// Stderr sets stderr for executed commands.
func Stderr(w io.Writer) Option {
return func(r *Runner) {
r.stderr = w
}
}

// New creates a new Runner with cc and options.
func New(cc chaincmd.ChainCmd, options ...Option) Runner {
r := Runner{
cc: cc,
stdout: ioutil.Discard,
stderr: ioutil.Discard,
}

applyOptions(&r, options)

return r
}

func applyOptions(r *Runner, options []Option) {
for _, apply := range options {
apply(r)
}
}

// Copy makes a copy of runner by overwriting its options with given options.
func (r Runner) Copy(options ...Option) Runner {
applyOptions(&r, options)

return r
}

type runOptions struct {
// longRunning indicates that command expected to run for a long period of time.
longRunning bool

// stdout and stderr used to collect a copy of command's outputs.
stdout, stderr io.Writer
}

// run executes a command.
func (r Runner) run(ctx context.Context, roptions runOptions, soptions ...step.Option) error {
var (
errb = &bytes.Buffer{}

// add optional prefixes to output streams.
stdout io.Writer = lineprefixer.NewWriter(r.stdout, func() string { return r.daemonLogPrefix })
stderr io.Writer = lineprefixer.NewWriter(r.stderr, func() string { return r.cliLogPrefix })
)

if roptions.stdout != nil {
stdout = io.MultiWriter(stdout, roptions.stdout)
}
if roptions.stderr != nil {
stderr = io.MultiWriter(stderr, roptions.stderr)
}

if !roptions.longRunning {
stderr = io.MultiWriter(stderr, errb)
}

rnoptions := []cmdrunner.Option{
cmdrunner.DefaultStdout(stdout),
cmdrunner.DefaultStderr(stderr),
}

err := cmdrunner.
New(rnoptions...).
Run(ctx, step.New(soptions...))

return errors.Wrap(err, errb.String())
}
Loading
0