Skip to content
2 changes: 1 addition & 1 deletion framework/docker/container/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import (
"time"

"github.com/containerd/errdefs"
"github.com/moby/moby/api/pkg/stdcopy"
"github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/mount"
"github.com/moby/moby/api/types/network"
"github.com/moby/moby/api/pkg/stdcopy"
"github.com/moby/moby/client"
"go.uber.org/zap"
)
Expand Down
27 changes: 16 additions & 11 deletions framework/docker/container/lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,25 @@ func (c *Lifecycle) CreateContainer(
}
}

containerCfg := &container.Config{
Image: imageRef,

Entrypoint: entrypoint,
Cmd: cmd,
Env: env,
Hostname: hostName,
Labels: map[string]string{consts.CleanupLabel: c.client.CleanupLabel()},
ExposedPorts: pS,
}
if image.UIDGID != "" {
containerCfg.User = image.UIDGID
}

cc, err := c.client.ContainerCreate(
ctx,
client.ContainerCreateOptions{
Name: c.containerName,
Config: &container.Config{
Image: imageRef,

Entrypoint: entrypoint,
Cmd: cmd,
Env: env,
Hostname: hostName,
Labels: map[string]string{consts.CleanupLabel: c.client.CleanupLabel()},
ExposedPorts: pS,
},
Name: c.containerName,
Config: containerCfg,
HostConfig: &container.HostConfig{
Binds: volumeBinds,
PortBindings: pb,
Expand Down
1 change: 1 addition & 0 deletions framework/docker/container/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func (n *Node) Exec(ctx context.Context, logger *zap.Logger, cmd []string, env [
opts := Options{
Env: env,
Binds: n.Bind(),
User: n.Image.UIDGID,
}
res := job.Run(ctx, cmd, opts)
if res.Err != nil {
Expand Down
28 changes: 19 additions & 9 deletions framework/docker/cosmos/chain_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ type ChainBuilder struct {
// blockWaitTimeout is the timeout for waiting for blocks after starting the chain.
// If zero, defaults to 120 seconds.
blockWaitTimeout time.Duration
// homeDir overrides the default home directory inside the container
homeDir string
}

// NewChainBuilder initializes and returns a new ChainBuilder with default values for testing purposes.
Expand Down Expand Up @@ -315,6 +317,12 @@ func (b *ChainBuilder) WithImage(image container.Image) *ChainBuilder {
return b
}

// WithHomeDir overrides the default home directory inside the container.
func (b *ChainBuilder) WithHomeDir(homeDir string) *ChainBuilder {
b.homeDir = homeDir
return b
}

// WithAdditionalStartArgs sets the default additional start arguments for all nodes in the chain
func (b *ChainBuilder) WithAdditionalStartArgs(args ...string) *ChainBuilder {
b.additionalStartArgs = args
Expand Down Expand Up @@ -441,11 +449,11 @@ func (b *ChainBuilder) Build(ctx context.Context) (*Chain, error) {
Env: b.env,
GenesisFileBz: b.genesisBz,
},
t: b.t,
Validators: validators,
FullNodes: fullNodes,
cdc: cdc,
log: b.logger,
t: b.t,
Validators: validators,
FullNodes: fullNodes,
cdc: cdc,
log: b.logger,
faucetWallet: b.faucetWallet,
skipInit: b.skipInit,
blockWaitTimeout: b.blockWaitTimeout,
Expand Down Expand Up @@ -494,10 +502,12 @@ func (b *ChainBuilder) newChainNode(
}

func (b *ChainBuilder) newDockerChainNode(log *zap.Logger, nodeConfig ChainNodeConfig, index int) *ChainNode {
// use a default home directory if name is not set
homeDir := "/var/cosmos-chain"
if b.name != "" {
homeDir = path.Join("/var/cosmos-chain", b.name)
homeDir := b.homeDir
if homeDir == "" {
homeDir = "/var/cosmos-chain"
if b.name != "" {
homeDir = path.Join("/var/cosmos-chain", b.name)
}
}

chainParams := ChainNodeParams{
Expand Down
138 changes: 69 additions & 69 deletions framework/docker/da_network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,75 +124,75 @@ func TestDANetworkCreation(t *testing.T) {
// TestDANetworkStopAndRestart ensures a DA network can be stopped and then restarted,
// and nodes continue to respond to RPC after restart.
func TestDANetworkStopAndRestart(t *testing.T) {
if testing.Short() {
t.Skip("skipping due to short mode")
}
t.Parallel()
configureBech32PrefixOnce()

// Setup isolated docker environment for this test
testCfg := setupDockerTest(t)

chain, err := testCfg.ChainBuilder.Build(testCfg.Ctx)
require.NoError(t, err)

err = chain.Start(testCfg.Ctx)
require.NoError(t, err)
defer func() { _ = chain.Remove(testCfg.Ctx) }()

// Default image for the DA network
defaultImage := container.Image{
Repository: "ghcr.io/celestiaorg/celestia-node",
Version: "v0.26.4",
UIDGID: "10001:10001",
}

// Create bridge node config
bridgeNodeConfig := da.NewNodeBuilder().
WithNodeType(types.BridgeNode).
Build()

// Create DA network with a single bridge node
daNetwork, err := testCfg.DANetworkBuilder.
WithChainID(chain.GetChainID()).
WithImage(defaultImage).
WithNodes(bridgeNodeConfig).
Build(testCfg.Ctx)
require.NoError(t, err)

// Start the bridge node
bridgeNode := daNetwork.GetBridgeNodes()[0]

chainNetworkInfo, err := chain.GetNodes()[0].GetNetworkInfo(testCfg.Ctx)
require.NoError(t, err, "failed to get network info")
hostname := chainNetworkInfo.Internal.Hostname

chainID := chain.GetChainID()
genesisHash, err := getGenesisHash(testCfg.Ctx, chain)
require.NoError(t, err)

require.NoError(t, bridgeNode.Start(testCfg.Ctx,
da.WithChainID(chainID),
da.WithAdditionalStartArguments("--p2p.network", chainID, "--core.ip", hostname, "--rpc.addr", "0.0.0.0"),
da.WithEnvironmentVariables(map[string]string{
"CELESTIA_CUSTOM": types.BuildCelestiaCustomEnvVar(chainID, genesisHash, ""),
"P2P_NETWORK": chainID,
}),
))

// Verify it is responding
_, err = bridgeNode.GetP2PInfo(testCfg.Ctx)
require.NoError(t, err, "failed to get bridge node p2p info before stop")

// Stop the entire DA network
require.NoError(t, daNetwork.Stop(testCfg.Ctx))

// Start the entire DA network again
require.NoError(t, daNetwork.Start(testCfg.Ctx))

// Verify RPC works after restart
_, err = bridgeNode.GetP2PInfo(testCfg.Ctx)
require.NoError(t, err, "failed to get bridge node p2p info after restart")
if testing.Short() {
t.Skip("skipping due to short mode")
}
t.Parallel()
configureBech32PrefixOnce()

// Setup isolated docker environment for this test
testCfg := setupDockerTest(t)

chain, err := testCfg.ChainBuilder.Build(testCfg.Ctx)
require.NoError(t, err)

err = chain.Start(testCfg.Ctx)
require.NoError(t, err)
defer func() { _ = chain.Remove(testCfg.Ctx) }()

// Default image for the DA network
defaultImage := container.Image{
Repository: "ghcr.io/celestiaorg/celestia-node",
Version: "v0.26.4",
UIDGID: "10001:10001",
}

// Create bridge node config
bridgeNodeConfig := da.NewNodeBuilder().
WithNodeType(types.BridgeNode).
Build()

// Create DA network with a single bridge node
daNetwork, err := testCfg.DANetworkBuilder.
WithChainID(chain.GetChainID()).
WithImage(defaultImage).
WithNodes(bridgeNodeConfig).
Build(testCfg.Ctx)
require.NoError(t, err)

// Start the bridge node
bridgeNode := daNetwork.GetBridgeNodes()[0]

chainNetworkInfo, err := chain.GetNodes()[0].GetNetworkInfo(testCfg.Ctx)
require.NoError(t, err, "failed to get network info")
hostname := chainNetworkInfo.Internal.Hostname

chainID := chain.GetChainID()
genesisHash, err := getGenesisHash(testCfg.Ctx, chain)
require.NoError(t, err)

require.NoError(t, bridgeNode.Start(testCfg.Ctx,
da.WithChainID(chainID),
da.WithAdditionalStartArguments("--p2p.network", chainID, "--core.ip", hostname, "--rpc.addr", "0.0.0.0"),
da.WithEnvironmentVariables(map[string]string{
"CELESTIA_CUSTOM": types.BuildCelestiaCustomEnvVar(chainID, genesisHash, ""),
"P2P_NETWORK": chainID,
}),
))

// Verify it is responding
_, err = bridgeNode.GetP2PInfo(testCfg.Ctx)
require.NoError(t, err, "failed to get bridge node p2p info before stop")

// Stop the entire DA network
require.NoError(t, daNetwork.Stop(testCfg.Ctx))

// Start the entire DA network again
require.NoError(t, daNetwork.Start(testCfg.Ctx))

// Verify RPC works after restart
_, err = bridgeNode.GetP2PInfo(testCfg.Ctx)
require.NoError(t, err, "failed to get bridge node p2p info after restart")
}

// TestModifyConfigFileDANetwork ensures modification of config files is possible by
Expand Down
7 changes: 7 additions & 0 deletions framework/docker/dataavailability/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,11 @@ type Config struct {
Image container.Image
// AdditionalStartArgs are additional arguments passed to all nodes when starting
AdditionalStartArgs []string
// HomeDir is the home directory inside the container. Defaults to DefaultHomeDir().
HomeDir string
}

// DefaultHomeDir returns the default home directory for DA node containers.
func DefaultHomeDir() string {
return "/home/celestia"
}
56 changes: 28 additions & 28 deletions framework/docker/dataavailability/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (n *Network) GetBridgeNodes() []*Node {

// GetLightNodes returns only the light nodes in the network.
func (n *Network) GetLightNodes() []*Node {
return n.GetNodesByType(types.LightNode)
return n.GetNodesByType(types.LightNode)
}

// AddNodes adds one or more nodes to the DA network with the given configurations.
Expand Down Expand Up @@ -151,41 +151,41 @@ func (n *Network) RemoveNodes(ctx context.Context, nodeNames ...string) error {

// Stop stops all nodes in the data availability network without removing them.
func (n *Network) Stop(ctx context.Context) error {
nodes := n.GetNodes()
var eg errgroup.Group
for _, nd := range nodes {
nd := nd
eg.Go(func() error {
return nd.Stop(ctx)
})
}
return eg.Wait()
nodes := n.GetNodes()
var eg errgroup.Group
for _, nd := range nodes {
nd := nd
eg.Go(func() error {
return nd.Stop(ctx)
})
}
return eg.Wait()
}

// Remove stops and removes all nodes in the data availability network.
// Matches the semantics of cosmos.Chain.Remove by operating on all components concurrently.
func (n *Network) Remove(ctx context.Context, opts ...types.RemoveOption) error {
nodes := n.GetNodes()
var eg errgroup.Group
for _, nd := range nodes {
nd := nd
eg.Go(func() error {
return nd.Remove(ctx, opts...)
})
}
return eg.Wait()
nodes := n.GetNodes()
var eg errgroup.Group
for _, nd := range nodes {
nd := nd
eg.Go(func() error {
return nd.Remove(ctx, opts...)
})
}
return eg.Wait()
}

// Start starts all nodes in the data availability network.
// If nodes were previously initialized and only stopped, this will only start their containers.
func (n *Network) Start(ctx context.Context) error {
nodes := n.GetNodes()
var eg errgroup.Group
for _, nd := range nodes {
nd := nd
eg.Go(func() error {
return nd.Start(ctx)
})
}
return eg.Wait()
nodes := n.GetNodes()
var eg errgroup.Group
for _, nd := range nodes {
nd := nd
eg.Go(func() error {
return nd.Start(ctx)
})
}
return eg.Wait()
}
9 changes: 9 additions & 0 deletions framework/docker/dataavailability/network_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type NetworkBuilder struct {
chainID string
// binaryName is the name of the Node binary executable (e.g., "celestia")
binaryName string
// homeDir overrides the default home directory inside the container
homeDir string
}

// NewNetworkBuilder initializes and returns a new NetworkBuilder with default values for testing purposes
Expand Down Expand Up @@ -108,6 +110,12 @@ func (b *NetworkBuilder) WithDockerNetworkID(networkID string) *NetworkBuilder {
return b
}

// WithHomeDir overrides the default home directory inside the container.
func (b *NetworkBuilder) WithHomeDir(homeDir string) *NetworkBuilder {
b.homeDir = homeDir
return b
}

// WithImage sets the default Docker image for all nodes in the network
func (b *NetworkBuilder) WithImage(image container.Image) *NetworkBuilder {
b.dockerImage = &image
Expand Down Expand Up @@ -214,6 +222,7 @@ func (b *NetworkBuilder) newNode(ctx context.Context, nodeConfig NodeConfig, ind
ChainID: b.chainID,
Bin: b.binaryName,
Image: imageToUse,
HomeDir: b.homeDir,
// Env and AdditionalStartArgs provide default set of values for all nodes, but can
// be individually overridden by nodeConfig.
Env: b.env,
Expand Down
6 changes: 5 additions & 1 deletion framework/docker/dataavailability/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ type Node struct {
}

func NewNode(cfg Config, testName string, image container.Image, index int, nodeConfig NodeConfig) *Node {
homeDir := cfg.HomeDir
if homeDir == "" {
homeDir = DefaultHomeDir()
}
logger := cfg.Logger.With(
zap.String("node_type", nodeConfig.NodeType.String()),
)
Expand All @@ -86,7 +90,7 @@ func NewNode(cfg Config, testName string, image container.Image, index int, node
additionalStartArgs: nodeConfig.AdditionalStartArgs,
configModifications: nodeConfig.ConfigModifications,
internalPorts: initializeDANodePorts(nodeConfig.InternalPorts),
Node: container.NewNode(cfg.DockerNetworkID, cfg.DockerClient, testName, image, "/home/celestia", index, nodeConfig.NodeType, logger),
Node: container.NewNode(cfg.DockerNetworkID, cfg.DockerClient, testName, image, homeDir, index, nodeConfig.NodeType, logger),
}

node.SetContainerLifecycle(container.NewLifecycle(cfg.Logger, cfg.DockerClient, node.Name()))
Expand Down
Loading
Loading