Skip to content

Commit

Permalink
feat: Add command to run dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
fmoura authored and gligneul committed Jan 24, 2024
1 parent 3ba7ff0 commit bd31565
Show file tree
Hide file tree
Showing 7 changed files with 295 additions and 0 deletions.
65 changes: 65 additions & 0 deletions cmd/cartesi-rollups-cli/root/deps/deps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package deps

import (
"context"
"os/signal"
"syscall"

"github.com/cartesi/rollups-node/internal/config"
"github.com/cartesi/rollups-node/internal/deps"
"github.com/spf13/cobra"
)

var Cmd = &cobra.Command{
Use: "run-deps",
Short: "Run node dependencies with Docker",
Example: examples,
Run: run,
}

const examples = `# Run all deps:
cartesi-rollups-cli run-deps`

var depsConfig = deps.NewDefaultDepsConfig()

func init() {
Cmd.Flags().StringVar(&depsConfig.PostgresDockerImage, "postgres-docker-image",
deps.DefaultPostgresDockerImage,
"Postgress docker image name")

Cmd.Flags().StringVar(&depsConfig.PostgresPort, "postgres-mapped-port",
deps.DefaultPostgresPort,
"Postgres local listening port number")

Cmd.Flags().StringVar(&depsConfig.PostgresPassword, "postgres-password",
deps.DefaultPostgresPassword,
"Postgres password")

Cmd.Flags().StringVar(&depsConfig.DevnetDockerImage, "devnet-docker-image",
deps.DefaultDevnetDockerImage,
"Devnet docker image name")

Cmd.Flags().StringVar(&depsConfig.DevnetPort, "devnet-mapped-port",
deps.DefaultDevnetPort,
"devnet local listening port number")
}

func run(cmd *cobra.Command, args []string) {

ctx, cancel := signal.NotifyContext(cmd.Context(), syscall.SIGINT, syscall.SIGTERM)
defer cancel()

depsContainers, err := deps.Run(ctx, *depsConfig)
cobra.CheckErr(err)

config.InfoLogger.Println("all deps are up")

<-ctx.Done()

err = deps.Terminate(context.Background(), depsContainers)
cobra.CheckErr(err)

}
2 changes: 2 additions & 0 deletions cmd/cartesi-rollups-cli/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package root

import (
"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/deps"
"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/increasetime"
"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/inspect"
"github.com/cartesi/rollups-node/cmd/cartesi-rollups-cli/root/read"
Expand All @@ -27,5 +28,6 @@ func init() {
Cmd.AddCommand(inspect.Cmd)
Cmd.AddCommand(increasetime.Cmd)
Cmd.AddCommand(validate.Cmd)
Cmd.AddCommand(deps.Cmd)
Cmd.DisableAutoGenTag = true
}
1 change: 1 addition & 0 deletions docs/cartesi-rollups-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Cartesi Rollups node.
* [cartesi-rollups-cli increase-time](cartesi-rollups-cli_increase-time.md) - Increases evm time of the current machine
* [cartesi-rollups-cli inspect](cartesi-rollups-cli_inspect.md) - Calls inspect API
* [cartesi-rollups-cli read](cartesi-rollups-cli_read.md) - Read the node state from the GraphQL API
* [cartesi-rollups-cli run-deps](cartesi-rollups-cli_run-deps.md) - Run node dependencies with Docker
* [cartesi-rollups-cli save-snapshot](cartesi-rollups-cli_save-snapshot.md) - Saves the testing Cartesi machine snapshot to the designated folder
* [cartesi-rollups-cli send](cartesi-rollups-cli_send.md) - Send a rollups input to the Ethereum node
* [cartesi-rollups-cli validate](cartesi-rollups-cli_validate.md) - Validates a notice
Expand Down
15 changes: 15 additions & 0 deletions docs/cartesi-rollups-cli_deps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## cartesi-rollups-cli deps

Read the node state from the GraphQL API

### Options

```
-h, --help help for deps
```

### SEE ALSO

* [cartesi-rollups-cli](cartesi-rollups-cli.md) - Command line interface for Cartesi Rollups
* [cartesi-rollups-cli deps start](cartesi-rollups-cli_deps_start.md) - start all deps

30 changes: 30 additions & 0 deletions docs/cartesi-rollups-cli_deps_start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## cartesi-rollups-cli deps start

start all deps

```
cartesi-rollups-cli deps start [flags]
```

### Examples

```
# Start all deps:
cartesi-rollups-cli deps start
```

### Options

```
--devnet-docker-image string Devnet docker image name
--devnet-mapped-port string devnet local listening port number
-h, --help help for start
--postgres-docker-image string Postgress docker image name
--postgres-mapped-port string Postgres local listening port number
--postgres-password string Postgres password
```

### SEE ALSO

* [cartesi-rollups-cli deps](cartesi-rollups-cli_deps.md) - Read the node state from the GraphQL API

30 changes: 30 additions & 0 deletions docs/cartesi-rollups-cli_run-deps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## cartesi-rollups-cli run-deps

Run node dependencies with Docker

```
cartesi-rollups-cli run-deps [flags]
```

### Examples

```
# Run all deps:
cartesi-rollups-cli run-deps
```

### Options

```
--devnet-docker-image string Devnet docker image name (default "cartesi/rollups-devnet:devel")
--devnet-mapped-port string devnet local listening port number (default "8545")
-h, --help help for run-deps
--postgres-docker-image string Postgress docker image name (default "postgres:16-alpine")
--postgres-mapped-port string Postgres local listening port number (default "5432")
--postgres-password string Postgres password (default "password")
```

### SEE ALSO

* [cartesi-rollups-cli](cartesi-rollups-cli.md) - Command line interface for Cartesi Rollups

152 changes: 152 additions & 0 deletions internal/deps/deps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

// Package deps provides mechanisms to run Node dependencies using docker
package deps

import (
"context"
"strings"
"sync"
"time"

"github.com/cartesi/rollups-node/internal/config"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)

const (
DefaultPostgresDockerImage = "postgres:16-alpine"
DefaultPostgresPort = "5432"
DefaultPostgresPassword = "password"
DefaultDevnetDockerImage = "cartesi/rollups-devnet:devel"
DefaultDevnetPort = "8545"

numPostgresCheckReadyAttempts = 2
pollInterval = 5 * time.Second
)

// Struct to hold Node dependencies containers configurations
type DepsConfig struct {
PostgresDockerImage string
PostgresPort string
PostgresPassword string
DevnetDockerImage string
DevnetPort string
}

// Builds a DepsConfig struct with default values
func NewDefaultDepsConfig() *DepsConfig {
return &DepsConfig{
DefaultPostgresDockerImage,
DefaultPostgresPort,
DefaultPostgresPassword,
DefaultDevnetDockerImage,
DefaultDevnetPort,
}
}

// Struct to represent the Node dependencies containers
type DepsContainers struct {
containers []testcontainers.Container
//Literal copies lock value from waitGroup as sync.WaitGroup contains sync.noCopy
waitGroup *sync.WaitGroup
}

// A dummy Logging to write all Test Containers logs with DEBUG priority
type debugLogging struct{}

func (debug debugLogging) Printf(format string, v ...interface{}) {
config.DebugLogger.Printf(format, v...)
}

func createHook(containerName string,
waitGroup *sync.WaitGroup) []testcontainers.ContainerLifecycleHooks {
return []testcontainers.ContainerLifecycleHooks{
{
PostTerminates: []testcontainers.ContainerHook{
func(ctx context.Context, container testcontainers.Container) error {
waitGroup.Done()
return nil
},
},
},
}

}

// Run starts the Node dependencies containers.
// The returned DepContainers struct can be used to gracefully
// terminate the containers using the Terminate method
func Run(ctx context.Context, depsConfig DepsConfig) (*DepsContainers, error) {
nolog := debugLogging{}
var waitGroup sync.WaitGroup

// wait strategy copied from testcontainers docs
postgresWaitStrategy := wait.ForLog("database system is ready to accept connections").
WithOccurrence(numPostgresCheckReadyAttempts).
WithPollInterval(pollInterval)

postgresReq := testcontainers.ContainerRequest{
Image: depsConfig.PostgresDockerImage,
ExposedPorts: []string{strings.Join([]string{
depsConfig.PostgresPort, ":5432/tcp"}, "")},
WaitingFor: postgresWaitStrategy,
Name: "rollups-node-dep-postgres",
Env: map[string]string{
"POSTGRES_PASSWORD": depsConfig.PostgresPassword,
},
LifecycleHooks: createHook("rollups-node-dep-postgres", &waitGroup),
}

postgres, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: postgresReq,
Started: true,
Logger: nolog,
})

if err != nil {
return nil, err
}
waitGroup.Add(1)

devNetReq := testcontainers.ContainerRequest{
Image: depsConfig.DevnetDockerImage,
ExposedPorts: []string{strings.Join([]string{depsConfig.DevnetPort, ":8545/tcp"}, "")},
WaitingFor: wait.ForLog("Listening on 0.0.0.0:8545"),
Name: "rollups-node-dep-devnet",
Env: map[string]string{
"ANVIL_IP_ADDR": "0.0.0.0",
},
LifecycleHooks: createHook("rollups-node-dep-devnet", &waitGroup),
}

devnet, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: devNetReq,
Started: true,
Logger: nolog,
})
if err != nil {
return nil, err
}

waitGroup.Add(1)

containers := []testcontainers.Container{postgres, devnet}

return &DepsContainers{containers, &waitGroup}, nil
}

// Terminate terminates all dependencies containers. This method waits for all the containers
// to terminate or gives an error if it fails to terminate one of the containers
func Terminate(ctx context.Context, depContainers *DepsContainers) error {

for _, depContainer := range depContainers.containers {
terr := depContainer.Terminate(ctx)
if terr != nil {
return terr
}
}
depContainers.waitGroup.Wait()
return nil
}

0 comments on commit bd31565

Please sign in to comment.