Merge pull request #14 from getamis/feature/refactor-environment-config-with-docker

core, container: refactor environment config with docker
This commit is contained in:
bailantaotao 2017-08-14 14:20:12 +08:00 committed by GitHub
commit c7abc22f26
6 changed files with 72 additions and 63 deletions

View File

@ -32,7 +32,7 @@ import (
"github.com/docker/go-connections/nat"
"github.com/getamis/go-ethereum/cmd/utils"
"github.com/getamis/go-ethereum/ethclient"
"github.com/getamis/istanbul-tools/core"
"github.com/getamis/istanbul-tools/core/genesis"
)
const (
@ -46,14 +46,9 @@ type Ethereum interface {
Stop() error
}
func NewEthereum(options ...Option) *ethereum {
client, err := client.NewEnvClient()
if err != nil {
log.Fatalf("Cannot connect to Docker daemon, err: %v", err)
}
func NewEthereum(c *client.Client, options ...Option) *ethereum {
geth := &ethereum{
client: client,
client: c,
}
for _, opt := range options {
@ -106,12 +101,12 @@ func (eth *ethereum) Init(genesisFile string) error {
"init",
"--" + utils.DataDirFlag.Name,
eth.dataDir,
filepath.Join("/", core.GenesisJson),
filepath.Join("/", genesis.FileName),
},
},
&container.HostConfig{
Binds: []string{
genesisFile + ":" + filepath.Join("/", core.GenesisJson),
genesisFile + ":" + filepath.Join("/", genesis.FileName),
eth.hostDataDir + ":" + eth.dataDir,
},
}, nil, "")

View File

@ -22,11 +22,11 @@ import (
"testing"
"github.com/getamis/istanbul-tools/core"
"github.com/getamis/istanbul-tools/core/genesis"
)
func TestEthereumContainer(t *testing.T) {
keys := core.GenerateClusterKeys(1)
envs := core.SetupEnv(keys)
envs := core.SetupEnv(1)
defer core.Teardown(envs)
err := core.SetupNodes(envs)
if err != nil {
@ -35,10 +35,11 @@ func TestEthereumContainer(t *testing.T) {
for _, env := range envs {
geth := NewEthereum(
env.Client,
ImageName("quay.io/maicoin/ottoman_geth:istanbul_develop"),
HostDataDir(env.DataDir),
DataDir("/data"),
Port(fmt.Sprintf("%d", env.HttpPort)),
Port(fmt.Sprintf("%d", env.P2PPort)),
RPC(),
RPCAddress("0.0.0.0"),
RPCAPI("eth,net,web3,personal"),
@ -46,7 +47,7 @@ func TestEthereumContainer(t *testing.T) {
Logging(true),
)
err := geth.Init(filepath.Join(env.DataDir, core.GenesisJson))
err := geth.Init(filepath.Join(env.DataDir, genesis.FileName))
if err != nil {
t.Error(err)
}

View File

@ -23,49 +23,36 @@ import (
"io/ioutil"
"log"
"net"
"net/url"
"os"
"path/filepath"
"github.com/docker/docker/client"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/getamis/istanbul-tools/core/genesis"
"github.com/satori/go.uuid"
)
const (
defaultBaseRpcPort = uint16(8545)
defaultHttpPort = uint16(30303)
defaultP2PPort = uint16(30303)
defaultLocalDir = "/tmp/gdata"
datadirPrivateKey = "nodekey"
clientIdentifier = "geth"
staticNodeJson = "static-nodes.json"
GenesisJson = "genesis.json"
)
var (
defaultIP = net.IPv4(127, 0, 0, 1)
)
func GenerateClusterKeys(numbers int) []*ecdsa.PrivateKey {
keys := make([]*ecdsa.PrivateKey, numbers)
for i := 0; i < len(keys); i++ {
key, err := crypto.GenerateKey()
if err != nil {
panic("couldn't generate key: " + err.Error())
}
keys[i] = key
}
return keys
}
type Env struct {
GethID int
HttpPort uint16
RpcPort uint16
DataDir string
Key *ecdsa.PrivateKey
GethID int
P2PPort uint16
RpcPort uint16
DataDir string
Key *ecdsa.PrivateKey
Client *client.Client
}
func Teardown(envs []*Env) {
@ -74,43 +61,54 @@ func Teardown(envs []*Env) {
}
}
func SetupEnv(prvKeys []*ecdsa.PrivateKey) []*Env {
envs := make([]*Env, len(prvKeys))
func SetupEnv(numbers int) []*Env {
envs := make([]*Env, numbers)
rpcPort := defaultBaseRpcPort
httpPort := defaultHttpPort
p2pPort := defaultP2PPort
for i := 0; i < len(envs); i++ {
dataDir, err := saveNodeKey(prvKeys[i])
client, err := client.NewEnvClient()
if err != nil {
panic("Failed to save node key")
log.Fatalf("Cannot connect to Docker daemon, err: %v", err)
}
key, err := crypto.GenerateKey()
if err != nil {
log.Fatalf("couldn't generate key: " + err.Error())
}
dataDir, err := saveNodeKey(key)
if err != nil {
log.Fatalf("Failed to save node key")
}
envs[i] = &Env{
GethID: i,
HttpPort: httpPort,
RpcPort: rpcPort,
DataDir: dataDir,
Key: prvKeys[i],
GethID: i,
P2PPort: p2pPort,
RpcPort: rpcPort,
DataDir: dataDir,
Key: key,
Client: client,
}
rpcPort = rpcPort + 1
httpPort = httpPort + 1
p2pPort = p2pPort + 1
}
return envs
}
func SetupNodes(envs []*Env) error {
nodes := transformToStaticNodes(envs)
nodes := toStaticNodes(envs)
for _, env := range envs {
if err := saveStaticNode(env.DataDir, nodes); err != nil {
return err
}
}
addrs := transformToAddress(envs)
genesis := GenerateGenesis(addrs)
addrs := toAddress(envs)
g := genesis.New(addrs)
for _, env := range envs {
if err := saveGenesis(env.DataDir, genesis); err != nil {
if err := genesis.Save(env.DataDir, g); err != nil {
return err
}
}
@ -155,17 +153,27 @@ func saveStaticNode(dataDir string, nodes []string) error {
return ioutil.WriteFile(keyPath, raw, 0600)
}
func transformToStaticNodes(envs []*Env) []string {
func toStaticNodes(envs []*Env) []string {
nodes := make([]string, len(envs))
for i, env := range envs {
daemonHost := env.Client.DaemonHost()
url, err := url.Parse(daemonHost)
if err != nil {
log.Fatalf("Failed to parse daemon host, err: %v", err)
}
host, _, err := net.SplitHostPort(url.Host)
if err != nil {
log.Fatalf("Failed to split host and port, err: %v", err)
}
nodeID := discover.PubkeyID(&env.Key.PublicKey)
nodes[i] = discover.NewNode(nodeID, defaultIP, 0, env.HttpPort).String()
nodes[i] = discover.NewNode(nodeID, net.ParseIP(host), 0, env.P2PPort).String()
}
return nodes
}
func transformToAddress(envs []*Env) []common.Address {
func toAddress(envs []*Env) []common.Address {
addrs := make([]common.Address, len(envs))
for i, env := range envs {

View File

@ -22,12 +22,12 @@ import (
)
func TestWriteFile(t *testing.T) {
keys := GenerateClusterKeys(4)
envs := SetupEnv(keys)
envs := SetupEnv(4)
err := SetupNodes(envs)
if err != nil {
t.Fatal("failed to setup nodes", err)
}
defer Teardown(envs)
for _, env := range envs {
fmt.Println(fmt.Sprintf("%s%d%s%s", "geth ID:", env.GethID, ", dataDir:", env.DataDir))
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package core
package genesis
import (
"encoding/json"
@ -23,6 +23,7 @@ import (
"math/big"
"path/filepath"
"time"
"log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@ -33,10 +34,14 @@ import (
"github.com/getamis/istanbul-tools/cmd/istanbul/extradata"
)
func GenerateGenesis(addrs []common.Address) *core.Genesis {
const (
FileName = "genesis.json"
)
func New(addrs []common.Address) *core.Genesis {
extraData, err := extradata.Encode("0x00", addrs)
if err != nil {
panic(fmt.Sprintf("%s%s", "Failed to generate genesis", err))
log.Fatalf("Failed to generate genesis, err:%s", err)
}
return &core.Genesis{
@ -59,8 +64,8 @@ func GenerateGenesis(addrs []common.Address) *core.Genesis {
}
}
func saveGenesis(dataDir string, genesis *core.Genesis) error {
filePath := filepath.Join(dataDir, GenesisJson)
func Save(dataDir string, genesis *core.Genesis) error {
filePath := filepath.Join(dataDir, FileName)
raw, err := json.Marshal(genesis)
if err != nil {

View File

@ -53,7 +53,7 @@ var _ = Describe("4 validators Istanbul", func() {
container.ImageName("quay.io/maicoin/ottoman_geth:istanbul_develop"),
container.HostDataDir(env.DataDir),
container.DataDir("/data"),
container.Port(fmt.Sprintf("%d", env.HttpPort)),
container.Port(fmt.Sprintf("%d", env.P2PPort)),
container.RPC(),
container.RPCAddress("0.0.0.0"),
container.RPCAPI("eth,net,web3,personal"),