diff --git a/.github/workflows/framework-golden-tests.yml b/.github/workflows/framework-golden-tests.yml
index 32070633e..ce1f114fd 100644
--- a/.github/workflows/framework-golden-tests.yml
+++ b/.github/workflows/framework-golden-tests.yml
@@ -1,9 +1,6 @@
name: Framework Golden Tests Examples
on:
push:
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}-framework-golden-examples
- cancel-in-progress: true
jobs:
test:
@@ -18,6 +15,7 @@ jobs:
id-token: write
contents: read
strategy:
+ fail-fast: false
matrix:
test:
- name: TestSmoke
@@ -32,6 +30,10 @@ jobs:
config: chaos.toml
count: 1
timeout: 10m
+ - name: TestReload
+ config: reload.toml
+ count: 1
+ timeout: 10m
steps:
- name: Checkout repo
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
@@ -62,9 +64,10 @@ jobs:
path: |
~/.cache/go-build
~/go/pkg/mod
- key: go-modules-${{ hashFiles('**/go.sum') }}-${{ runner.os }}-framework-golden-examples
+ key: go-modules-${{ hashFiles('framework/examples/myproject/go.sum') }}-${{ runner.os }}-framework-golden-examples
restore-keys: |
- go-modules-${{ hashFiles('**/go.sum') }}-${{ runner.os }}-framework-golden-examples
+ go-modules-${{ runner.os }}-framework-golden-examples
+ go-modules-${{ runner.os }}
- name: Install dependencies
run: go mod download
- name: Run Docker Component Tests
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index e4f1931fd..430f6b351 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -14,8 +14,10 @@
- [CLI](./framework/cli.md)
- [Configuration](./framework/configuration.md)
- [Test Configuration](./framework/test_configuration_overrides.md)
- - [Caching](framework/components/caching.md)
+ - [Components Persistence](framework/components/state.md)
+ - [Components Caching](framework/components/caching.md)
- [Secrets]()
+ - [Docker](framework/docker.md)
- [Observability Stack](framework/observability/observability_stack.md)
- [Metrics](framework/observability/metrics.md)
- [Logs](framework/observability/logs.md)
diff --git a/book/src/ci/ci.md b/book/src/ci/ci.md
index 98c2a2333..b78499159 100644
--- a/book/src/ci/ci.md
+++ b/book/src/ci/ci.md
@@ -2,8 +2,6 @@
Here we describe our good practices for structuring different types of tests in Continuous Integration (GitHub Actions).
-The simplest flow can look like:
-
Set up secrets in your GitHub repository
```
gh secret set CTF_SIMULATED_KEY_1 --body "..."
@@ -11,22 +9,58 @@ gh secret set CTF_SIMULATED_KEY_1 --body "..."
Add a workflow
```yaml
-name: Run E2E tests
-
+name: Framework Golden Tests Examples
on:
push:
jobs:
test:
- runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: framework/examples/myproject
env:
- CTF_CONFIGS: smoke.toml
- CTF_LOG_LEVEL: info
- CTF_LOKI_STREAM: "false"
- PRIVATE_KEY: ${{ secrets.CTF_SIMULATED_KEY_1 }}
+ LOKI_TENANT_ID: promtail
+ LOKI_URL: http://localhost:3030/loki/api/v1/push
+ runs-on: ubuntu-latest
+ permissions:
+ id-token: write
+ contents: read
+ strategy:
+ fail-fast: false
+ matrix:
+ test:
+ - name: TestSmoke
+ config: smoke.toml
+ count: 1
+ timeout: 10m
+ - name: TestLoad
+ config: load.toml
+ count: 1
+ timeout: 10m
+ - name: TestChaos
+ config: chaos.toml
+ count: 1
+ timeout: 10m
steps:
- - name: Check out code
- uses: actions/checkout@v3
+ - name: Checkout repo
+ uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
+ - name: Configure AWS credentials using OIDC
+ uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
+ with:
+ role-to-assume: ${{ secrets.PUBLIC_AWS_ECR_ROLE }}
+ aws-region: us-east-1
+ - name: Authenticate to ECR Public
+ id: login-ecr-public
+ uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1
+ with:
+ registry-type: public
+ - name: Check for changes in Framework
+ uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ id: changes
+ with:
+ filters: |
+ src:
+ - 'framework/**'
- name: Set up Go
uses: actions/setup-go@v4
with:
@@ -37,14 +71,18 @@ jobs:
path: |
~/.cache/go-build
~/go/pkg/mod
- key: go-modules-${{ hashFiles('**/go.sum') }}-${{ runner.os }}
+ key: go-modules-${{ hashFiles('framework/examples/myproject/go.sum') }}-${{ runner.os }}-framework-golden-examples
restore-keys: |
- go-modules-${{ hashFiles('**/go.sum') }}-${{ runner.os }}
+ go-modules-${{ runner.os }}-framework-golden-examples
+ go-modules-${{ runner.os }}
- name: Install dependencies
run: go mod download
- - name: Run tests
- working-directory: e2e/capabilities
- run: go test -v -run TestDON
+ - name: Run Docker Component Tests
+ if: steps.changes.outputs.src == 'true'
+ env:
+ CTF_CONFIGS: ${{ matrix.test.config }}
+ run: |
+ go test -timeout ${{ matrix.test.timeout }} -v -count ${{ matrix.test.count }} -run ${{ matrix.test.name }}
```
If you need to structure a lot of different end-to-end tests follow [this](https://github.com/smartcontractkit/.github/tree/main/.github/workflows) guide.
\ No newline at end of file
diff --git a/book/src/framework/components/caching.md b/book/src/framework/components/caching.md
index 4700a68fc..c6900be1f 100644
--- a/book/src/framework/components/caching.md
+++ b/book/src/framework/components/caching.md
@@ -1,6 +1,6 @@
## Component caching
-We use component caching to accelerate test development and enforce idempotent test actions.
+We use component caching to accelerate test development and enforce idempotent test actions development.
Each component is isolated by means of inputs and outputs.
diff --git a/book/src/framework/components/chainlink/nodeset.md b/book/src/framework/components/chainlink/nodeset.md
index 2696b1ac0..19d523747 100644
--- a/book/src/framework/components/chainlink/nodeset.md
+++ b/book/src/framework/components/chainlink/nodeset.md
@@ -48,6 +48,11 @@ Then configure NodeSet
# defines how we override configs, either we apply first node fields to all of them
# or we define each node custom configuration (used in compatibility testing)
override_mode = "all"
+ # HTTP API port range start, each new node get port incremented (host machine)
+ http_port_range_start = 10000
+ # P2P API port range start, each new node get port incremented (host machine)
+ p2p_port_range_start = 12000
+
[[nodeset.node_specs]]
# Optional URL for fake data provider URL
@@ -59,6 +64,8 @@ Then configure NodeSet
image = "postgres:15.6"
# Pulls the image every time if set to 'true', used like that in CI. Can be set to 'false' to speed up local runs
pull_image = true
+ # PostgreSQL volume name
+ volume_name = ""
[nodeset.node_specs.node]
# A list of paths to capability binaries
diff --git a/book/src/framework/components/databases/pg.md b/book/src/framework/components/databases/pg.md
new file mode 100644
index 000000000..9892a29dc
--- /dev/null
+++ b/book/src/framework/components/databases/pg.md
@@ -0,0 +1 @@
+# PostgreSQL
\ No newline at end of file
diff --git a/book/src/framework/components/state.md b/book/src/framework/components/state.md
new file mode 100644
index 000000000..1a42412f8
--- /dev/null
+++ b/book/src/framework/components/state.md
@@ -0,0 +1,37 @@
+# Components Persistence
+
+We use static port ranges and volumes for all components to simplify Docker port management for developers.
+
+This approach allows us to apply chaos testing to any container, ensuring it reconnects and retains the data needed for your tests.
+
+When deploying a component, you can explicitly configure port ranges if the default ports don’t meet your needs.
+
+Defaults are:
+- [NodeSet](../components/chainlink/nodeset.md) (Node HTTP API): `10000..100XX`
+- [NodeSet](../components/chainlink/nodeset.md) (Node P2P API): `12000..120XX`
+```
+[nodeset]
+ # HTTP API port range start, each new node get port incremented (host machine)
+ http_port_range_start = 10000
+ # P2P API port range start, each new node get port incremented (host machine)
+ p2p_port_range_start = 12000
+```
+- [PostgreSQL](../components/chainlink/nodeset.md): `13000` (we do not allow to have multiple databases for now, for simplicity)
+```
+ [nodeset.node_specs.db]
+ # PostgreSQL volume name
+ volume_name = "a"
+ # PostgreSQL port (host machine)
+ port = 13000
+```
+
+When you run `ctf d rm` database volume will be **removed**.
+
+
+
+One node set is enough for any kind of testing, if you need more nodes consider extending your existing node set:
+```
+[nodeset]
+ nodes = 10
+```
+
diff --git a/book/src/framework/docker.md b/book/src/framework/docker.md
new file mode 100644
index 000000000..c102010cb
--- /dev/null
+++ b/book/src/framework/docker.md
@@ -0,0 +1,7 @@
+# Docker
+
+We are not removing volumes and images when you are working locally to allow you to debug, however, to clean up some space use:
+```
+docker volume prune -f
+docker system prune -f
+```
diff --git a/book/src/framework/first_test.md b/book/src/framework/first_test.md
index d651ac172..f30c3155b 100644
--- a/book/src/framework/first_test.md
+++ b/book/src/framework/first_test.md
@@ -55,6 +55,6 @@ Summary:
- We defined configuration for `BlockchainNetwork`
- We've used one CTF component in test and checked if it's working
-You can learn more about [component design](./components/overview.md) or proceed with another example of [connecting Chainlink node](./connecting_chainlink_node.md)
+Now let's connect the [Chainlink](./connecting_chainlink_node.md) node!
Learn more about [anvil](./components/blockchains/anvil.md) component.
\ No newline at end of file
diff --git a/book/src/framework/nodeset_environment.md b/book/src/framework/nodeset_environment.md
index ce0588d57..d6eca5c21 100644
--- a/book/src/framework/nodeset_environment.md
+++ b/book/src/framework/nodeset_environment.md
@@ -72,13 +72,9 @@ Run it
CTF_CONFIGS=smoke.toml go test -v -run TestNodeSet
```
-You'll see something like, use any URL to access CL node
+Check the logs to access the UI
```bash
-6:14PM INF Chainlink node url URL=http://127.0.0.1:34041
-6:14PM INF Chainlink node url URL=http://127.0.0.1:34045
-6:14PM INF Chainlink node url URL=http://127.0.0.1:34044
-6:14PM INF Chainlink node url URL=http://127.0.0.1:34042
-6:14PM INF Chainlink node url URL=http://127.0.0.1:34043
+12:41AM INF UI=["http://127.0.0.1:10000","http://127.0.0.1:10001", ...]
```
Use credentials to authorize:
diff --git a/framework/.changeset/v0.1.11.md b/framework/.changeset/v0.1.11.md
new file mode 100644
index 000000000..714889248
--- /dev/null
+++ b/framework/.changeset/v0.1.11.md
@@ -0,0 +1,3 @@
+- Static port ranges for easy chaos testing
+- SharedDBNodeSet config update method
+- Example of rebooting nodes to apply configuration
\ No newline at end of file
diff --git a/framework/chaos/chaos.go b/framework/chaos/chaos.go
index b18637b04..56ec1b7a7 100644
--- a/framework/chaos/chaos.go
+++ b/framework/chaos/chaos.go
@@ -9,9 +9,13 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/framework"
"github.com/testcontainers/testcontainers-go"
"strings"
+ "time"
)
-func ExecPumba(command string) (func(), error) {
+// ExecPumba executes Pumba (https://github.com/alexei-led/pumba) command
+// since handling various docker race conditions is hard and there is no easy API for that
+// for now you can provide time to wait until chaos is applied
+func ExecPumba(command string, wait time.Duration) (func(), error) {
ctx := context.Background()
cmd := strings.Split(command, " ")
pumbaReq := testcontainers.ContainerRequest{
@@ -38,7 +42,9 @@ func ExecPumba(command string) (func(), error) {
if err != nil {
return nil, fmt.Errorf("failed to start pumba chaos container: %w", err)
}
- framework.L.Info().Msg("Pumba chaos started")
+ framework.L.Info().Str("Cmd", command).Msg("Pumba chaos has started")
+ time.Sleep(wait)
+ framework.L.Info().Msg("Pumba chaos has finished")
return func() {
_ = pumbaContainer.Terminate(ctx)
}, nil
diff --git a/framework/cmd/blockscout.go b/framework/cmd/blockscout.go
index ef77f2749..20385bc34 100644
--- a/framework/cmd/blockscout.go
+++ b/framework/cmd/blockscout.go
@@ -18,7 +18,6 @@ func blockscoutUp() error {
if err != nil {
return err
}
- framework.L.Info().Msg("Done")
fmt.Println()
framework.L.Info().Msgf("Blockscout is up at: %s", "http://localhost")
return nil
@@ -40,6 +39,5 @@ func blockscoutDown() error {
rm -rf redis-data && \
rm -rf stats-db-data
`, filepath.Join("blockscout", "services")))
- framework.L.Info().Msg("Done")
return nil
}
diff --git a/framework/cmd/docker.go b/framework/cmd/docker.go
index 181ea8c88..bf503f6e8 100644
--- a/framework/cmd/docker.go
+++ b/framework/cmd/docker.go
@@ -14,7 +14,8 @@ func cleanDockerResources() error {
// Bash command for removing Docker containers and networks with "framework=ctf" label
cmd := exec.Command("bash", "-c", `
docker ps -aq --filter "label=framework=ctf" | xargs -r docker rm -f && \
- docker network ls --filter "label=framework=ctf" -q | xargs -r docker network rm
+ docker network ls --filter "label=framework=ctf" -q | xargs -r docker network rm && \
+ docker volume rm postgresql_data
`)
framework.L.Debug().Msg("Running command")
if framework.L.GetLevel() == zerolog.DebugLevel {
@@ -24,7 +25,6 @@ func cleanDockerResources() error {
if err != nil {
return fmt.Errorf("error running clean command: %s", string(output))
}
- framework.L.Info().Msgf("Done")
return nil
}
diff --git a/framework/cmd/interactive.go b/framework/cmd/interactive.go
index ff907cec7..61ae06a8b 100644
--- a/framework/cmd/interactive.go
+++ b/framework/cmd/interactive.go
@@ -131,14 +131,14 @@ Docker Desktop (https://www.docker.com/products/docker-desktop/)
Options(
huh.NewOption("Anvil", "anvil"),
).
- Value(&f.Network), // stores the selected network
+ Value(&f.Network),
huh.NewSelect[int]().
Title("How many nodes do you need?").
Options(
huh.NewOption("5", 5),
).
- Value(&f.Nodes), // stores the selected number of nodes
+ Value(&f.Nodes),
huh.NewSelect[string]().
Title("Choose Chainlink node version").
@@ -147,11 +147,11 @@ Docker Desktop (https://www.docker.com/products/docker-desktop/)
Value(&f.CLVersion),
huh.NewConfirm().
Title("Do you need to spin up an observability stack?").
- Value(&f.Observability), // stores the observability option
+ Value(&f.Observability),
huh.NewConfirm().
Title("Do you need to spin up a Blockscout stack?").
- Value(&f.Blockscout), // stores the Blockscout option
+ Value(&f.Blockscout),
),
)
@@ -167,13 +167,12 @@ Docker Desktop (https://www.docker.com/products/docker-desktop/)
signal.Notify(sigs, os.Interrupt, syscall.SIGTERM)
go func() {
<-sigs
- fmt.Println("\nReceived Ctrl+C, starting custom cleanup...")
err := cleanup(f)
if err != nil {
panic(err)
}
os.Exit(0)
}()
- framework.L.Info().Msg("Press Ctrl+C to remove the stack..")
+ framework.L.Info().Msg("Services are up! Press Ctrl+C to remove them..")
select {}
}
diff --git a/framework/cmd/observability.go b/framework/cmd/observability.go
index 039851b76..7a42dc666 100644
--- a/framework/cmd/observability.go
+++ b/framework/cmd/observability.go
@@ -17,11 +17,8 @@ func observabilityUp() error {
if err != nil {
return err
}
- framework.L.Info().Msg("Done")
fmt.Println()
framework.L.Info().Msgf("Loki: %s", LocalLogsURL)
- framework.L.Info().Msgf("All logs: %s", "{job=\"ctf\"}")
- framework.L.Info().Msgf("By log level: %s", "{job=\"ctf\", container=~\"node.*\"} |= \"WARN|INFO|DEBUG\"")
framework.L.Info().Msgf("Pyroscope: %s", LocalPyroScopeURL)
return nil
}
@@ -35,6 +32,5 @@ func observabilityDown() error {
if err != nil {
return err
}
- framework.L.Info().Msg("Done")
return nil
}
diff --git a/framework/components/clnode/clnode.go b/framework/components/clnode/clnode.go
index 9131828a4..cdd69f759 100644
--- a/framework/components/clnode/clnode.go
+++ b/framework/components/clnode/clnode.go
@@ -263,24 +263,6 @@ func newNode(in *Input, pgOut *postgres.Output) (*NodeOut, error) {
if err != nil {
return nil, err
}
- //var (
- // mp nat.Port
- // mpP2P nat.Port
- //)
- //if in.Node.HTTPPort != 0 && in.Node.P2PPort != 0 {
- // mp = nat.Port(fmt.Sprintf("%d/tcp", in.Node.HTTPPort))
- // mpP2P = nat.Port(fmt.Sprintf("%d/udp", in.Node.P2PPort))
- //}
- //else {
- // mp, err = c.MappedPort(ctx, nat.Port(httpPort))
- // if err != nil {
- // return nil, err
- // }
- // mpP2P, err = c.MappedPort(ctx, nat.Port(p2pPort))
- // if err != nil {
- // return nil, err
- // }
- //}
mp := nat.Port(fmt.Sprintf("%d/tcp", in.Node.HTTPPort))
mpP2P := nat.Port(fmt.Sprintf("%d/udp", in.Node.P2PPort))
diff --git a/framework/components/clnode/clnode_test.go b/framework/components/clnode/clnode_test.go
index 3c35ac688..d2fac58e4 100644
--- a/framework/components/clnode/clnode_test.go
+++ b/framework/components/clnode/clnode_test.go
@@ -33,7 +33,9 @@ func TestDockerNodeWithSharedDB(t *testing.T) {
input: &clnode.Input{
DataProviderURL: "http://example.com",
DbInput: &postgres.Input{
- Image: "postgres:15.6",
+ Image: "postgres:15.6",
+ Port: 16000,
+ VolumeName: "a",
},
Node: &clnode.NodeInput{
Image: "public.ecr.aws/chainlink/chainlink:v2.17.0",
@@ -67,7 +69,9 @@ func TestDockerNodeWithDB(t *testing.T) {
input: &clnode.Input{
DataProviderURL: "http://example.com",
DbInput: &postgres.Input{
- Image: "postgres:15.6",
+ Image: "postgres:15.6",
+ Port: 15000,
+ VolumeName: "b",
},
Node: &clnode.NodeInput{
Image: "public.ecr.aws/chainlink/chainlink:v2.17.0",
diff --git a/framework/components/postgres/postgres.go b/framework/components/postgres/postgres.go
index 33670d8dc..9b5fb957e 100644
--- a/framework/components/postgres/postgres.go
+++ b/framework/components/postgres/postgres.go
@@ -3,6 +3,7 @@ package postgres
import (
"context"
"fmt"
+ "github.com/docker/docker/api/types/container"
"github.com/docker/go-connections/nat"
"github.com/smartcontractkit/chainlink-testing-framework/framework"
"github.com/testcontainers/testcontainers-go"
@@ -13,17 +14,21 @@ import (
)
const (
- User = "chainlink"
- Password = "thispasswordislongenough"
- Port = "5432"
- Database = "chainlink"
- Databases = 5
+ User = "chainlink"
+ Password = "thispasswordislongenough"
+ Port = "5432"
+ ExposedStaticPort = 13000
+ Database = "chainlink"
+ DBVolumeName = "postgresql_data"
)
type Input struct {
- Image string `toml:"image" validate:"required"`
- PullImage bool `toml:"pull_image"`
- Out *Output `toml:"out"`
+ Image string `toml:"image" validate:"required"`
+ Port int `toml:"port"`
+ VolumeName string `toml:"volume_name"`
+ Databases int `toml:"databases"`
+ PullImage bool `toml:"pull_image"`
+ Out *Output `toml:"out"`
}
type Output struct {
@@ -35,11 +40,10 @@ func NewPostgreSQL(in *Input) (*Output, error) {
ctx := context.Background()
bindPort := fmt.Sprintf("%s/tcp", Port)
-
containerName := framework.DefaultTCName("postgresql")
var sqlCommands []string
- for i := 0; i <= Databases; i++ {
+ for i := 0; i <= in.Databases; i++ {
sqlCommands = append(sqlCommands, fmt.Sprintf("CREATE DATABASE db_%d;", i))
}
sqlCommands = append(sqlCommands, "ALTER USER chainlink WITH SUPERUSER;")
@@ -80,13 +84,39 @@ func NewPostgreSQL(in *Input) (*Output, error) {
FileMode: 0644,
},
},
+ Mounts: testcontainers.ContainerMounts{
+ {
+ Source: testcontainers.GenericVolumeMountSource{
+ Name: fmt.Sprintf("%s%s", DBVolumeName, in.VolumeName),
+ },
+ Target: "/var/lib/postgresql/data",
+ },
+ },
WaitingFor: tcwait.ForExec([]string{"psql", "-h", "127.0.0.1",
"-U", User, "-p", Port, "-c", "select", "1", "-d", Database}).
- WithStartupTimeout(20 * time.Second),
+ WithStartupTimeout(20 * time.Second).
+ WithPollInterval(1 * time.Second),
+ }
+ var portToExpose int
+ if in.Port != 0 {
+ portToExpose = in.Port
+ } else {
+ portToExpose = ExposedStaticPort
+ }
+ req.HostConfigModifier = func(h *container.HostConfig) {
+ h.PortBindings = nat.PortMap{
+ nat.Port(bindPort): []nat.PortBinding{
+ {
+ HostIP: "0.0.0.0",
+ HostPort: fmt.Sprintf("%d/tcp", portToExpose),
+ },
+ },
+ }
}
c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
+ Reuse: true,
})
if err != nil {
return nil, err
@@ -95,10 +125,6 @@ func NewPostgreSQL(in *Input) (*Output, error) {
if err != nil {
return nil, err
}
- mp, err := c.MappedPort(ctx, nat.Port(bindPort))
- if err != nil {
- return nil, err
- }
return &Output{
DockerInternalURL: fmt.Sprintf(
"postgresql://%s:%s@%s:%s/%s?sslmode=disable",
@@ -109,11 +135,11 @@ func NewPostgreSQL(in *Input) (*Output, error) {
Database,
),
Url: fmt.Sprintf(
- "postgresql://%s:%s@%s:%s/%s?sslmode=disable",
+ "postgresql://%s:%s@%s:%d/%s?sslmode=disable",
User,
Password,
host,
- mp.Port(),
+ portToExpose,
Database,
),
}, nil
diff --git a/framework/components/simple_node_set/node_set.go b/framework/components/simple_node_set/node_set.go
index c51b36f0c..1a9d4837b 100644
--- a/framework/components/simple_node_set/node_set.go
+++ b/framework/components/simple_node_set/node_set.go
@@ -7,6 +7,7 @@ import (
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/clnode"
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/postgres"
"golang.org/x/sync/errgroup"
+ "slices"
"strings"
"sync"
)
@@ -16,20 +17,24 @@ const (
DefaultP2PStaticRangeStart = 12000
)
+// Input is a node set configuration input
type Input struct {
Nodes int `toml:"nodes" validate:"required"`
HTTPPortRangeStart int `toml:"http_port_range_start"`
P2PPortRangeStart int `toml:"p2p_port_range_start"`
OverrideMode string `toml:"override_mode" validate:"required,oneof=all each"`
- NodeSpecs []*clnode.Input `toml:"node_specs"`
+ NodeSpecs []*clnode.Input `toml:"node_specs" validate:"required"`
Out *Output `toml:"out"`
}
+// Output is a node set configuration output, used for caching or external components
type Output struct {
UseCache bool `toml:"use_cache"`
CLNodes []*clnode.Output `toml:"cl_nodes"`
}
+// NewSharedDBNodeSet create a new node set with a shared database instance
+// all the nodes have their own isolated database
func NewSharedDBNodeSet(in *Input, bcOut *blockchain.Output, fakeUrl string) (*Output, error) {
if in.Out != nil && in.Out.UseCache {
return in.Out, nil
@@ -39,6 +44,7 @@ func NewSharedDBNodeSet(in *Input, bcOut *blockchain.Output, fakeUrl string) (*O
err error
)
defer func() {
+ printURLs(out)
in.Out = out
}()
if len(in.NodeSpecs) != in.Nodes && in.OverrideMode == "each" {
@@ -56,23 +62,34 @@ func NewSharedDBNodeSet(in *Input, bcOut *blockchain.Output, fakeUrl string) (*O
return nil, err
}
}
- printOut(out)
return out, nil
}
-func printOut(out *Output) {
- for i, n := range out.CLNodes {
- framework.L.Info().Str(fmt.Sprintf("Node-%d", i), n.Node.HostURL).Msg("Chainlink node url")
+func printURLs(out *Output) {
+ if out == nil {
+ return
}
+ httpURLs, p2pURLs, pgURLs := make([]string, 0), make([]string, 0), make([]string, 0)
+ for _, n := range out.CLNodes {
+ httpURLs = append(httpURLs, n.Node.HostURL)
+ p2pURLs = append(p2pURLs, n.Node.HostP2PURL)
+ pgURLs = append(pgURLs, n.PostgreSQL.Url)
+ }
+ framework.L.Info().Any("UI", httpURLs).Send()
+ framework.L.Debug().Any("P2P", p2pURLs).Send()
+ framework.L.Debug().Any("DB", pgURLs).Send()
}
func sharedDBSetup(in *Input, bcOut *blockchain.Output, fakeUrl string, overrideEach bool) (*Output, error) {
+ in.NodeSpecs[0].DbInput.Databases = in.Nodes
dbOut, err := postgres.NewPostgreSQL(in.NodeSpecs[0].DbInput)
if err != nil {
return nil, err
}
nodeOuts := make([]*clnode.Output, 0)
+ // to make it easier for chaos testing we use static ports
+ // there is no need to check them in advance since testcontainers-go returns a nice error
var (
httpPortRangeStart = DefaultHTTPPortStaticRangeStart
p2pPortRangeStart = DefaultP2PStaticRangeStart
@@ -125,9 +142,10 @@ func sharedDBSetup(in *Input, bcOut *blockchain.Output, fakeUrl string, override
},
}
+ dbURLHost := strings.Replace(dbOut.Url, "/chainlink?sslmode=disable", fmt.Sprintf("/db_%d?sslmode=disable", i), -1)
dbURL := strings.Replace(dbOut.DockerInternalURL, "/chainlink?sslmode=disable", fmt.Sprintf("/db_%d?sslmode=disable", i), -1)
dbSpec := &postgres.Output{
- Url: dbOut.Url,
+ Url: dbURLHost,
DockerInternalURL: dbURL,
}
@@ -144,8 +162,21 @@ func sharedDBSetup(in *Input, bcOut *blockchain.Output, fakeUrl string, override
if err := eg.Wait(); err != nil {
return nil, err
}
+ sortNodeOutsByHostPort(nodeOuts)
return &Output{
UseCache: true,
CLNodes: nodeOuts,
}, nil
}
+
+func sortNodeOutsByHostPort(nodes []*clnode.Output) {
+ slices.SortFunc[[]*clnode.Output, *clnode.Output](nodes, func(a, b *clnode.Output) int {
+ aa := strings.Split(a.Node.HostURL, ":")
+ bb := strings.Split(b.Node.HostURL, ":")
+ if aa[len(aa)-1] < bb[len(bb)-1] {
+ return -1
+ } else {
+ return 1
+ }
+ })
+}
diff --git a/framework/components/simple_node_set/nodeset_test.go b/framework/components/simple_node_set/nodeset_test.go
index f0aa9860b..98d604568 100644
--- a/framework/components/simple_node_set/nodeset_test.go
+++ b/framework/components/simple_node_set/nodeset_test.go
@@ -87,6 +87,7 @@ func TestDockerNodeSetSharedDB(t *testing.T) {
DataProviderURL: "http://example.com",
DbInput: &postgres.Input{
Image: "postgres:15.6",
+ Port: 14000,
},
Node: &clnode.NodeInput{
Image: "public.ecr.aws/chainlink/chainlink:v2.17.0",
diff --git a/framework/components/simple_node_set/reload.go b/framework/components/simple_node_set/reload.go
new file mode 100644
index 000000000..9180defa5
--- /dev/null
+++ b/framework/components/simple_node_set/reload.go
@@ -0,0 +1,8 @@
+package simple_node_set
+
+// UpdateNodeConfigs updates nodes configuration TOML files
+// this API is discouraged, however, you can use it if nodes require restart or configuration updates, temporarily!
+func UpdateNodeConfigs(in *Input, cfg string) {
+ in.NodeSpecs[0].Node.UserConfigOverrides = in.NodeSpecs[0].Node.UserConfigOverrides + cfg
+ in.Out = nil
+}
diff --git a/framework/examples/.gitignore b/framework/examples/.gitignore
index 8184ab7cb..ea2f8193b 100644
--- a/framework/examples/.gitignore
+++ b/framework/examples/.gitignore
@@ -33,3 +33,5 @@ promtail-config.yml
**/blockscout
**/blockscout/*
**/*cache.toml
+**/postgresql_data
+**/postgresql_data/*
diff --git a/framework/examples/myproject/.envrc b/framework/examples/myproject/.envrc
index 2bc67310e..3e3bc940a 100644
--- a/framework/examples/myproject/.envrc
+++ b/framework/examples/myproject/.envrc
@@ -3,4 +3,5 @@ export PRIVATE_KEY="..."
# load test
export LOKI_TENANT_ID=promtail
export LOKI_URL=http://localhost:3030/loki/api/v1/push
-export RESTY_DEBUG=true
\ No newline at end of file
+#export RESTY_DEBUG=true
+export CTF_LOG_LEVEL=debug
\ No newline at end of file
diff --git a/framework/examples/myproject/chaos_test.go b/framework/examples/myproject/chaos_test.go
index 6a3baee42..4c2df3149 100644
--- a/framework/examples/myproject/chaos_test.go
+++ b/framework/examples/myproject/chaos_test.go
@@ -9,6 +9,7 @@ import (
ns "github.com/smartcontractkit/chainlink-testing-framework/framework/components/simple_node_set"
"github.com/stretchr/testify/require"
"testing"
+ "time"
)
type CfgChaos struct {
@@ -35,7 +36,7 @@ func TestChaos(t *testing.T) {
// example commands for Pumba:
// stop --duration=1s --restart re2:node0 # stop one container for 1s and restart
// netem --tc-image=gaiadocker/iproute2 --duration=1m delay --time=300 re2:node.* # slow network
- _, err = chaos.ExecPumba("stop --duration=1s --restart re2:node0")
+ _, err = chaos.ExecPumba("stop --duration=1s --restart re2:node0", 1*time.Second)
require.NoError(t, err)
_, _, err = c[0].ReadBridges()
require.NoError(t, err)
diff --git a/framework/examples/myproject/go.mod b/framework/examples/myproject/go.mod
index f458d7773..6a2d21569 100644
--- a/framework/examples/myproject/go.mod
+++ b/framework/examples/myproject/go.mod
@@ -9,7 +9,7 @@ replace (
)
require (
- github.com/smartcontractkit/chainlink-testing-framework/framework v0.1.9
+ github.com/smartcontractkit/chainlink-testing-framework/framework v0.1.10
github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2
github.com/stretchr/testify v1.9.0
)
@@ -28,6 +28,7 @@ require (
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
+ github.com/atotto/clipboard v0.1.4 // indirect
github.com/aws/aws-sdk-go v1.45.25 // indirect
github.com/aws/aws-sdk-go-v2 v1.31.0 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.39 // indirect
@@ -43,6 +44,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.27.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.31.3 // indirect
github.com/aws/smithy-go v1.21.0 // indirect
+ github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
@@ -50,9 +52,18 @@ require (
github.com/bytedance/sonic/loader v0.2.0 // indirect
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b // indirect
github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 // indirect
+ github.com/catppuccin/go v0.2.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
+ github.com/charmbracelet/bubbles v0.20.0 // indirect
+ github.com/charmbracelet/bubbletea v1.1.1 // indirect
+ github.com/charmbracelet/huh v0.6.0 // indirect
+ github.com/charmbracelet/huh/spinner v0.0.0-20241028115900-20a4d21717a8 // indirect
+ github.com/charmbracelet/lipgloss v0.13.0 // indirect
+ github.com/charmbracelet/x/ansi v0.2.3 // indirect
+ github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 // indirect
+ github.com/charmbracelet/x/term v0.2.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/coder/websocket v1.8.12 // indirect
@@ -62,6 +73,7 @@ require (
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpuguy83/dockercfg v0.3.1 // indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dennwc/varint v1.0.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@@ -72,6 +84,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
+ github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/ethereum/go-ethereum v1.14.11 // indirect
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect
github.com/fatih/color v1.16.0 // indirect
@@ -143,14 +156,18 @@ require (
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
+ github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
+ github.com/mattn/go-localereader v0.0.1 // indirect
+ github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/mitchellh/copystructure v1.0.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
+ github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
@@ -161,6 +178,9 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
+ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
+ github.com/muesli/cancelreader v0.2.2 // indirect
+ github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/oklog/ulid v1.3.1 // indirect
@@ -170,6 +190,7 @@ require (
github.com/opentracing-contrib/go-stdlib v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
+ github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
github.com/pkg/errors v0.9.1 // indirect
@@ -183,7 +204,9 @@ require (
github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 // indirect
+ github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/zerolog v1.33.0 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect
github.com/sercand/kuberesolver/v5 v5.1.1 // indirect
github.com/shirou/gopsutil/v3 v3.23.12 // indirect
@@ -203,7 +226,9 @@ require (
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
+ github.com/urfave/cli/v2 v2.27.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
+ github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.etcd.io/etcd/api/v3 v3.5.7 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect
diff --git a/framework/examples/myproject/go.sum b/framework/examples/myproject/go.sum
index 70537bae5..a39037ab9 100644
--- a/framework/examples/myproject/go.sum
+++ b/framework/examples/myproject/go.sum
@@ -105,6 +105,8 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
+github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
+github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4=
github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
@@ -136,6 +138,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.31.3 h1:VzudTFrDCIDakXtemR7l6Qzt2+JY
github.com/aws/aws-sdk-go-v2/service/sts v1.31.3/go.mod h1:yMWe0F+XG0DkRZK5ODZhG7BEFYhLXi2dqGsv6tX0cgI=
github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA=
github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
+github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
+github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -154,6 +158,8 @@ github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdS
github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8 h1:SjZ2GvvOononHOpK84APFuMvxqsk3tEIaKH/z4Rpu3g=
github.com/c9s/goprocinfo v0.0.0-20210130143923-c95fcf8c64a8/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE=
+github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
+github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -162,6 +168,22 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE=
+github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU=
+github.com/charmbracelet/bubbletea v1.1.1 h1:KJ2/DnmpfqFtDNVTvYZ6zpPFL9iRCRr0qqKOCvppbPY=
+github.com/charmbracelet/bubbletea v1.1.1/go.mod h1:9Ogk0HrdbHolIKHdjfFpyXJmiCzGwy+FesYkZr7hYU4=
+github.com/charmbracelet/huh v0.6.0 h1:mZM8VvZGuE0hoDXq6XLxRtgfWyTI3b2jZNKh0xWmax8=
+github.com/charmbracelet/huh v0.6.0/go.mod h1:GGNKeWCeNzKpEOh/OJD8WBwTQjV3prFAtQPpLv+AVwU=
+github.com/charmbracelet/huh/spinner v0.0.0-20241028115900-20a4d21717a8 h1:g+Bz64hsMLTf3lAgUqI6Rj1YEAlm/HN39IuhyneCokc=
+github.com/charmbracelet/huh/spinner v0.0.0-20241028115900-20a4d21717a8/go.mod h1:Cxhgl8N0sX9A+EQxedzzGZAalaF8fUVL+JP/pSOW8cI=
+github.com/charmbracelet/lipgloss v0.13.0 h1:4X3PPeoWEDCMvzDvGmTajSyYPcZM4+y8sCA/SsA3cjw=
+github.com/charmbracelet/lipgloss v0.13.0/go.mod h1:nw4zy0SBX/F/eAO1cWdcvy6qnkDUxr8Lw7dvFrAIbbY=
+github.com/charmbracelet/x/ansi v0.2.3 h1:VfFN0NUpcjBRd4DnKfRaIRo53KRgey/nhOoEqosGDEY=
+github.com/charmbracelet/x/ansi v0.2.3/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw=
+github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0 h1:qko3AQ4gK1MTS/de7F5hPGx6/k1u0w4TeYmBFwzYVP4=
+github.com/charmbracelet/x/exp/strings v0.0.0-20240722160745-212f7b056ed0/go.mod h1:pBhA0ybfXv6hDjQUZ7hk1lVxBiUbupdw5R31yPUViVQ=
+github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0=
+github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -189,6 +211,8 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E=
github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
+github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
+github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0=
github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@@ -226,6 +250,8 @@ github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnv
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
+github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
+github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/ethereum/go-ethereum v1.14.11 h1:8nFDCUUE67rPc6AKxFj7JKaOa2W/W1Rse3oS6LvvxEY=
github.com/ethereum/go-ethereum v1.14.11/go.mod h1:+l/fr42Mma+xBnhefL/+z11/hcmJ2egl+ScIVPjhc7E=
github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb h1:IT4JYU7k4ikYg1SCxNI1/Tieq/NFvh6dzLdgi7eu0tM=
@@ -572,6 +598,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YUw=
github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ=
+github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
+github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
@@ -599,6 +627,10 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
+github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
+github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
+github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
@@ -611,6 +643,8 @@ github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFW
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
+github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
+github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@@ -639,6 +673,12 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
+github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
+github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
+github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
+github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
+github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg=
+github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -674,6 +714,8 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
+github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
+github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
@@ -728,6 +770,9 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 h1:6ksZ7t1hNOzGPPs8DK7SvXQf6UfWzi+W5Z7PCBl8gx4=
github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510/go.mod h1:UC0TwJiF90m2T3iYPQBKnGu8gv3s55dF/EgpTq8gyvo=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
+github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
@@ -736,6 +781,9 @@ github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
+github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.20 h1:a9hSJdJcd16e0HoMsnFvaHvxB3pxSD+SC7+CISp7xY0=
@@ -811,6 +859,9 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/urfave/cli v1.22.12 h1:igJgVw1JdKH+trcLWLeLwZjU9fEfPesQ+9/e4MQ44S8=
+github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
+github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs=
github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
@@ -822,6 +873,8 @@ github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3k
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
+github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
+github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -1051,6 +1104,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/framework/examples/myproject/reload.toml b/framework/examples/myproject/reload.toml
new file mode 100644
index 000000000..acbac497d
--- /dev/null
+++ b/framework/examples/myproject/reload.toml
@@ -0,0 +1,23 @@
+
+[blockchain_a]
+ chain_id = "31337"
+ image = "f4hrenh9it/foundry:latest"
+ port = "8545"
+ type = "anvil"
+
+[data_provider]
+ port = 9111
+
+[nodeset]
+ nodes = 5
+ override_mode = "all"
+
+ [[nodeset.node_specs]]
+
+ [nodeset.node_specs.db]
+ image = "postgres:15.6"
+ pull_image = true
+
+ [nodeset.node_specs.node]
+ image = "public.ecr.aws/chainlink/chainlink:v2.17.0"
+ pull_image = false
diff --git a/framework/examples/myproject/reload_test.go b/framework/examples/myproject/reload_test.go
new file mode 100644
index 000000000..9e9732b5c
--- /dev/null
+++ b/framework/examples/myproject/reload_test.go
@@ -0,0 +1,74 @@
+package examples
+
+import (
+ "fmt"
+ "github.com/smartcontractkit/chainlink-testing-framework/framework"
+ "github.com/smartcontractkit/chainlink-testing-framework/framework/chaos"
+ "github.com/smartcontractkit/chainlink-testing-framework/framework/clclient"
+ "github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
+ "github.com/smartcontractkit/chainlink-testing-framework/framework/components/fake"
+ ns "github.com/smartcontractkit/chainlink-testing-framework/framework/components/simple_node_set"
+ "github.com/stretchr/testify/require"
+ "testing"
+ "time"
+)
+
+type CfgReload struct {
+ BlockchainA *blockchain.Input `toml:"blockchain_a" validate:"required"`
+ MockerDataProvider *fake.Input `toml:"data_provider" validate:"required"`
+ NodeSet *ns.Input `toml:"nodeset" validate:"required"`
+}
+
+func TestReload(t *testing.T) {
+ in, err := framework.Load[CfgReload](t)
+ require.NoError(t, err)
+
+ bc, err := blockchain.NewBlockchainNetwork(in.BlockchainA)
+ require.NoError(t, err)
+ dp, err := fake.NewFakeDataProvider(in.MockerDataProvider)
+ require.NoError(t, err)
+
+ // deploy first time
+ out, err := ns.NewSharedDBNodeSet(in.NodeSet, bc, dp.BaseURLDocker)
+ require.NoError(t, err)
+
+ c, err := clclient.NewCLDefaultClients(out.CLNodes, framework.L)
+ require.NoError(t, err)
+ _, _, err = c[0].CreateJobRaw(`
+ type = "cron"
+ schemaVersion = 1
+ schedule = "CRON_TZ=UTC */10 * * * * *" # every 10 secs
+ observationSource = """
+ // data source 2
+ fetch [type=http method=GET url="https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"];
+ parse [type=jsonparse path="RAW,ETH,USD,PRICE"];
+ multiply [type="multiply" input="$(parse)" times=100]
+ encode_tx [type="ethabiencode"
+ abi="submit(uint256 value)"
+ data="{ \\"value\\": $(multiply) }"]
+ submit_tx [type="ethtx" to="0x859AAa51961284C94d970B47E82b8771942F1980" data="$(encode_tx)"]
+
+ fetch -> parse -> multiply -> encode_tx -> submit_tx
+ """`)
+ require.NoError(t, err)
+
+ // deploy second time
+ _, err = chaos.ExecPumba("rm --volumes=false re2:node.*|postgresql.*", 5*time.Second)
+ require.NoError(t, err)
+ ns.UpdateNodeConfigs(in.NodeSet, `
+[Log]
+level = 'info'
+`)
+ out, err = ns.NewSharedDBNodeSet(in.NodeSet, bc, dp.BaseURLDocker)
+ require.NoError(t, err)
+ jobs, _, err := c[0].ReadJobs()
+ require.NoError(t, err)
+ fmt.Println(jobs)
+
+ t.Run("test something", func(t *testing.T) {
+ for _, n := range out.CLNodes {
+ require.NotEmpty(t, n.Node.HostURL)
+ require.NotEmpty(t, n.Node.HostP2PURL)
+ }
+ })
+}