diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index e4f1931fd..c9c3ee786 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -16,6 +16,7 @@ - [Test Configuration](./framework/test_configuration_overrides.md) - [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/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/framework/cmd/docker.go b/framework/cmd/docker.go index ee9de9aad..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 { diff --git a/framework/components/postgres/postgres.go b/framework/components/postgres/postgres.go index 13bb2acd4..c66b26232 100644 --- a/framework/components/postgres/postgres.go +++ b/framework/components/postgres/postgres.go @@ -4,13 +4,11 @@ import ( "context" "fmt" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/api/types/mount" "github.com/docker/go-connections/nat" "github.com/smartcontractkit/chainlink-testing-framework/framework" "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" "os" - "path/filepath" "strings" "time" ) @@ -84,17 +82,19 @@ func NewPostgreSQL(in *Input) (*Output, error) { FileMode: 0644, }, }, + Mounts: testcontainers.ContainerMounts{ + { + Source: testcontainers.GenericVolumeMountSource{ + Name: DatabaseDir, + }, + 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). WithPollInterval(1 * time.Second), } - wd, err := os.Getwd() - if err != nil { - return nil, err - } - _ = os.RemoveAll(filepath.Join(wd, DatabaseDir)) - _ = os.Mkdir(DatabaseDir, os.ModePerm) req.HostConfigModifier = func(h *container.HostConfig) { h.PortBindings = nat.PortMap{ nat.Port(bindPort): []nat.PortBinding{ @@ -104,17 +104,11 @@ func NewPostgreSQL(in *Input) (*Output, error) { }, }, } - h.Mounts = []mount.Mount{ - { - Type: mount.TypeBind, - Source: filepath.Join(wd, DatabaseDir), - Target: "/var/lib/postgresql/data", - }, - } } c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ ContainerRequest: req, Started: true, + Reuse: true, }) if err != nil { return nil, err diff --git a/framework/components/simple_node_set/node_set.go b/framework/components/simple_node_set/node_set.go index 51eef1d9a..1a9d4837b 100644 --- a/framework/components/simple_node_set/node_set.go +++ b/framework/components/simple_node_set/node_set.go @@ -66,13 +66,18 @@ func NewSharedDBNodeSet(in *Input, bcOut *blockchain.Output, fakeUrl string) (*O } func printURLs(out *Output) { - httpURLs, p2pURLs := make([]string, 0), make([]string, 0) + 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) { @@ -137,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, } 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..75cfd790f --- /dev/null +++ b/framework/examples/myproject/reload_test.go @@ -0,0 +1,77 @@ +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) + time.Sleep(20 * time.Second) + + // deploy second time + _, err = chaos.ExecPumba("rm --volumes=false re2:node.*|postgresql.*") + require.NoError(t, err) + + in.NodeSet.NodeSpecs[0].Node.UserConfigOverrides = in.NodeSet.NodeSpecs[0].Node.UserConfigOverrides + ` +[Log] +Level = 'info' +` + in.NodeSet.Out = nil + 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) + } + }) +}