mirror of
https://github.com/scroll-tech/scroll.git
synced 2026-01-10 06:28:04 -05:00
Co-authored-by: Péter Garamvölgyi <peter@scroll.io> Co-authored-by: ChuhanJin <60994121+ChuhanJin@users.noreply.github.com> Co-authored-by: vincent <419436363@qq.com> Co-authored-by: colinlyguo <651734127@qq.com> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
172 lines
3.6 KiB
Go
172 lines
3.6 KiB
Go
package docker
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/big"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/docker/docker/api/types"
|
|
"github.com/scroll-tech/go-ethereum/ethclient"
|
|
|
|
"scroll-tech/common/cmd"
|
|
"scroll-tech/common/utils"
|
|
)
|
|
|
|
// ImgGeth the geth image manager include l1geth and l2geth.
|
|
type ImgGeth struct {
|
|
image string
|
|
name string
|
|
id string
|
|
|
|
volume string
|
|
ipcPath string
|
|
httpPort int
|
|
wsPort int
|
|
chainID *big.Int
|
|
|
|
running bool
|
|
cmd *cmd.Cmd
|
|
}
|
|
|
|
// NewImgGeth return geth img instance.
|
|
func NewImgGeth(image, volume, ipc string, hPort, wPort int) GethImgInstance {
|
|
img := &ImgGeth{
|
|
image: image,
|
|
name: fmt.Sprintf("%s-%d", image, time.Now().Nanosecond()),
|
|
volume: volume,
|
|
ipcPath: ipc,
|
|
httpPort: hPort,
|
|
wsPort: wPort,
|
|
}
|
|
img.cmd = cmd.NewCmd(img.name, img.prepare()...)
|
|
return img
|
|
}
|
|
|
|
// Start run image and check if it is running healthily.
|
|
func (i *ImgGeth) Start() error {
|
|
id := GetContainerID(i.name)
|
|
if id != "" {
|
|
return fmt.Errorf("container already exist, name: %s", i.name)
|
|
}
|
|
i.running = i.isOk()
|
|
if !i.running {
|
|
_ = i.Stop()
|
|
return fmt.Errorf("failed to start image: %s", i.image)
|
|
}
|
|
|
|
// try 10 times to get chainID until is ok.
|
|
utils.TryTimes(10, func() bool {
|
|
client, err := ethclient.Dial(i.Endpoint())
|
|
if err == nil && client != nil {
|
|
i.chainID, err = client.ChainID(context.Background())
|
|
return err == nil && i.chainID != nil
|
|
}
|
|
return false
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
// IsRunning returns docker container's running status.
|
|
func (i *ImgGeth) IsRunning() bool {
|
|
return i.running
|
|
}
|
|
|
|
// Endpoint return the connection endpoint.
|
|
func (i *ImgGeth) Endpoint() string {
|
|
switch true {
|
|
case i.httpPort != 0:
|
|
return fmt.Sprintf("http://127.0.0.1:%d", i.httpPort)
|
|
case i.wsPort != 0:
|
|
return fmt.Sprintf("ws://127.0.0.1:%d", i.wsPort)
|
|
default:
|
|
return i.ipcPath
|
|
}
|
|
}
|
|
|
|
// ChainID return chainID.
|
|
func (i *ImgGeth) ChainID() *big.Int {
|
|
return i.chainID
|
|
}
|
|
|
|
func (i *ImgGeth) isOk() bool {
|
|
keyword := "WebSocket enabled"
|
|
okCh := make(chan struct{}, 1)
|
|
i.cmd.RegistFunc(keyword, func(buf string) {
|
|
if strings.Contains(buf, keyword) {
|
|
select {
|
|
case okCh <- struct{}{}:
|
|
default:
|
|
return
|
|
}
|
|
}
|
|
})
|
|
defer i.cmd.UnRegistFunc(keyword)
|
|
// Start cmd in parallel.
|
|
i.cmd.RunCmd(true)
|
|
|
|
select {
|
|
case <-okCh:
|
|
utils.TryTimes(20, func() bool {
|
|
i.id = GetContainerID(i.name)
|
|
return i.id != ""
|
|
})
|
|
case err := <-i.cmd.ErrChan:
|
|
if err != nil {
|
|
fmt.Printf("failed to start %s, err: %v\n", i.name, err)
|
|
}
|
|
case <-time.After(time.Second * 10):
|
|
return false
|
|
}
|
|
return i.id != ""
|
|
}
|
|
|
|
// Stop the docker container.
|
|
func (i *ImgGeth) Stop() error {
|
|
if !i.running {
|
|
return nil
|
|
}
|
|
i.running = false
|
|
|
|
ctx := context.Background()
|
|
// check if container is running, stop the running container.
|
|
id := GetContainerID(i.name)
|
|
if id != "" {
|
|
timeout := time.Second * 3
|
|
if err := cli.ContainerStop(ctx, id, &timeout); err != nil {
|
|
return err
|
|
}
|
|
i.id = id
|
|
}
|
|
// remove the stopped container.
|
|
return cli.ContainerRemove(ctx, i.id, types.ContainerRemoveOptions{})
|
|
}
|
|
|
|
func (i *ImgGeth) prepare() []string {
|
|
cmds := []string{"docker", "run", "--rm", "--name", i.name}
|
|
var ports []string
|
|
if i.httpPort != 0 {
|
|
ports = append(ports, []string{"-p", strconv.Itoa(i.httpPort) + ":8545"}...)
|
|
}
|
|
if i.wsPort != 0 {
|
|
ports = append(ports, []string{"-p", strconv.Itoa(i.wsPort) + ":8546"}...)
|
|
}
|
|
|
|
var envs []string
|
|
if i.ipcPath != "" {
|
|
envs = append(envs, []string{"-e", fmt.Sprintf("IPC_PATH=%s", i.ipcPath)}...)
|
|
}
|
|
|
|
if i.volume != "" {
|
|
cmds = append(cmds, []string{"-v", fmt.Sprintf("%s:%s", i.volume, i.volume)}...)
|
|
}
|
|
|
|
cmds = append(cmds, ports...)
|
|
cmds = append(cmds, envs...)
|
|
|
|
return append(cmds, i.image)
|
|
}
|