From 88c6d2ec81178ca083d292b31d8b04725ee04957 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Mon, 16 Dec 2024 18:46:25 +0100 Subject: [PATCH] Container polling speedup, move Promtail to CLI, Delve debugger entrypoint (#1484) move promtail, speedup, delve --- book/src/framework/components/debug.md | 33 ++----------------- book/src/framework/components/state.md | 1 + framework/.changeset/v0.3.8.md | 3 ++ framework/cmd/interactive.go | 3 -- framework/cmd/observability.go | 3 ++ framework/components/blockchain/anvil.go | 2 +- framework/components/blockchain/besu.go | 2 +- framework/components/blockchain/geth.go | 2 +- framework/components/clnode/clnode.go | 32 ++++++++++++++---- framework/components/postgres/postgres.go | 4 +-- .../components/simple_node_set/node_set.go | 6 ++++ .../simple_node_set/nodeset_test.go | 1 + framework/config.go | 4 --- framework/examples/myproject/smoke.toml | 6 ++-- framework/promtail.go | 4 +-- 15 files changed, 52 insertions(+), 54 deletions(-) create mode 100644 framework/.changeset/v0.3.8.md diff --git a/book/src/framework/components/debug.md b/book/src/framework/components/debug.md index d0f703b9c..aa2af79ae 100644 --- a/book/src/framework/components/debug.md +++ b/book/src/framework/components/debug.md @@ -10,35 +10,6 @@ Use `RESTY_DEBUG=true` to debug any API calls. Use `SETH_LOG_LEVEL=trace|debug|info|warn` to debug [Seth](../../libs/seth.md). -## Using Delve (TBD) - -You can use [Delve]() inside your containers to debug aplications. - -Build them with `go build -gcflags="all=-N -l" -o myapp` and use an example `Dockerfile`: -``` -FROM golang:1.20 - -# Install Delve -RUN go install github.com/go-delve/delve/cmd/dlv@latest - -# Set working directory -WORKDIR /app - -# Copy the application binary and source code (if needed for debugging) -COPY myapp /app/myapp -COPY . /app - -# Expose the port for Delve -EXPOSE 40000 - -# Start Delve in headless mode for remote debugging -ENTRYPOINT ["dlv", "exec", "./myapp", "--headless", "--listen=:40000", "--api-version=2", "--accept-multiclient"] - -``` - -Adding `Delve` to all our components is WIP right now. - -To expose `Delve` port follow this [guide](state.md). - - +## Using Delve Debugger +If you are using `Chainlink` image with [Delve](https://github.com/go-delve/delve) available in path you can use ports `40000..400XX` to connect to any node. diff --git a/book/src/framework/components/state.md b/book/src/framework/components/state.md index 240549f14..841594a15 100644 --- a/book/src/framework/components/state.md +++ b/book/src/framework/components/state.md @@ -9,6 +9,7 @@ When deploying a component, you can explicitly configure port ranges if the defa Defaults are: - [NodeSet](../components/chainlink/nodeset.md) (Node HTTP API): `10000..100XX` - [NodeSet](../components/chainlink/nodeset.md) (Node P2P API): `12000..120XX` +- [NodeSet](../components/chainlink/nodeset.md) (Delve debugger): `40000..400XX` (if you are using debug image) - Shared `PostgreSQL` volume is called `postgresql_data` ``` [nodeset] diff --git a/framework/.changeset/v0.3.8.md b/framework/.changeset/v0.3.8.md new file mode 100644 index 000000000..7cc327059 --- /dev/null +++ b/framework/.changeset/v0.3.8.md @@ -0,0 +1,3 @@ +- Move promtail to CLI +- Speed up container polling +- Allow debug entrypoint for dlv \ No newline at end of file diff --git a/framework/cmd/interactive.go b/framework/cmd/interactive.go index 5c685a9fa..b9d619576 100644 --- a/framework/cmd/interactive.go +++ b/framework/cmd/interactive.go @@ -75,9 +75,6 @@ func createComponentsFromForm(form *nodeSetForm) error { } switch form.Observability { case true: - if err = framework.NewPromtail(); err != nil { - return err - } if err := observabilityUp(); err != nil { return err } diff --git a/framework/cmd/observability.go b/framework/cmd/observability.go index 7a42dc666..e77c71d2b 100644 --- a/framework/cmd/observability.go +++ b/framework/cmd/observability.go @@ -10,6 +10,9 @@ func observabilityUp() error { if err := extractAllFiles("observability"); err != nil { return err } + if err := framework.NewPromtail(); err != nil { + return err + } err := runCommand("bash", "-c", fmt.Sprintf(` cd %s && \ docker compose up -d diff --git a/framework/components/blockchain/anvil.go b/framework/components/blockchain/anvil.go index 6618befda..174cc1355 100644 --- a/framework/components/blockchain/anvil.go +++ b/framework/components/blockchain/anvil.go @@ -53,7 +53,7 @@ func newAnvil(in *Input) (*Output, error) { NetworkAliases: map[string][]string{ framework.DefaultNetworkName: {containerName}, }, - WaitingFor: wait.ForListeningPort(nat.Port(in.Port)).WithStartupTimeout(10 * time.Second), + WaitingFor: wait.ForListeningPort(nat.Port(in.Port)).WithStartupTimeout(10 * time.Second).WithPollInterval(200 * time.Millisecond), Entrypoint: entryPoint, } c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ diff --git a/framework/components/blockchain/besu.go b/framework/components/blockchain/besu.go index 4da19d5a4..c47b035de 100644 --- a/framework/components/blockchain/besu.go +++ b/framework/components/blockchain/besu.go @@ -82,7 +82,7 @@ func newBesu(in *Input) (*Output, error) { }, } }, - WaitingFor: wait.ForListeningPort(nat.Port(in.Port)).WithStartupTimeout(15 * time.Second), + WaitingFor: wait.ForListeningPort(nat.Port(in.Port)).WithStartupTimeout(15 * time.Second).WithPollInterval(200 * time.Millisecond), Cmd: entryPoint, } diff --git a/framework/components/blockchain/geth.go b/framework/components/blockchain/geth.go index e9d9a0f53..7b51f951f 100644 --- a/framework/components/blockchain/geth.go +++ b/framework/components/blockchain/geth.go @@ -191,7 +191,7 @@ func newGeth(in *Input) (*Output, error) { FileMode: 0644, }, }, - WaitingFor: wait.ForListeningPort(nat.Port(in.Port)).WithStartupTimeout(15 * time.Second), + WaitingFor: wait.ForListeningPort(nat.Port(in.Port)).WithStartupTimeout(15 * time.Second).WithPollInterval(200 * time.Millisecond), Cmd: entryPoint, } c, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{ diff --git a/framework/components/clnode/clnode.go b/framework/components/clnode/clnode.go index 8ca9a3e7c..fa429a58a 100644 --- a/framework/components/clnode/clnode.go +++ b/framework/components/clnode/clnode.go @@ -7,6 +7,7 @@ import ( "fmt" "os" "path/filepath" + "strconv" "strings" "sync" "text/template" @@ -23,6 +24,7 @@ import ( const ( DefaultHTTPPort = "6688" DefaultP2PPort = "6690" + DefaultDebuggerPort = 40000 TmpImageName = "chainlink-tmp:latest" CustomPortSeparator = ":" ) @@ -54,6 +56,7 @@ type NodeInput struct { HTTPPort int `toml:"port"` P2PPort int `toml:"p2p_port"` CustomPorts []string `toml:"custom_ports"` + DebuggerPort int `toml:"debugger_port"` } // Output represents Chainlink node output, nodes and databases connection URLs @@ -114,11 +117,25 @@ func NewNode(in *Input, pgOut *postgres.Output) (*Output, error) { return out, nil } +func generateEntryPoint() []string { + entrypoint := []string{ + "/bin/sh", "-c", + } + if os.Getenv("CTF_CLNODE_DLV") == "true" { + entrypoint = append(entrypoint, "dlv exec /usr/local/bin/chainlink --continue --listen=0.0.0.0:40000 --headless=true --api-version=2 --accept-multiclient -- -c /config/config -c /config/overrides -c /config/user-overrides -s /config/secrets -s /config/secrets-overrides -s /config/user-secrets-overrides node start -d -p /config/node_password -a /config/apicredentials") + } else { + entrypoint = append(entrypoint, "chainlink -c /config/config -c /config/overrides -c /config/user-overrides -s /config/secrets -s /config/secrets-overrides -s /config/user-secrets-overrides node start -d -p /config/node_password -a /config/apicredentials") + } + return entrypoint +} + // generatePortBindings generates exposed ports and port bindings // exposes default CL node port // exposes custom_ports in format "host:docker" or map 1-to-1 if only "host" port is provided func generatePortBindings(in *Input) ([]string, nat.PortMap, error) { httpPort := fmt.Sprintf("%s/tcp", DefaultHTTPPort) + innerDebuggerPort := fmt.Sprintf("%d/tcp", DefaultDebuggerPort) + debuggerPort := fmt.Sprintf("%d/tcp", in.Node.DebuggerPort) portBindings := nat.PortMap{ nat.Port(httpPort): []nat.PortBinding{ { @@ -126,6 +143,12 @@ func generatePortBindings(in *Input) ([]string, nat.PortMap, error) { HostPort: fmt.Sprintf("%d/tcp", in.Node.HTTPPort), }, }, + nat.Port(innerDebuggerPort): []nat.PortBinding{ + { + HostIP: "0.0.0.0", + HostPort: debuggerPort, + }, + }, } customPorts := make([]string, 0) for _, p := range in.Node.CustomPorts { @@ -157,7 +180,7 @@ func generatePortBindings(in *Input) ([]string, nat.PortMap, error) { } } } - exposedPorts := []string{httpPort} + exposedPorts := []string{httpPort, strconv.Itoa(DefaultDebuggerPort)} exposedPorts = append(exposedPorts, customPorts...) return exposedPorts, portBindings, nil } @@ -219,11 +242,8 @@ func newNode(in *Input, pgOut *postgres.Output) (*NodeOut, error) { framework.DefaultNetworkName: {containerName}, }, ExposedPorts: exposedPorts, - Entrypoint: []string{ - "/bin/sh", "-c", - "chainlink -c /config/config -c /config/overrides -c /config/user-overrides -s /config/secrets -s /config/secrets-overrides -s /config/user-secrets-overrides node start -d -p /config/node_password -a /config/apicredentials", - }, - WaitingFor: wait.ForHTTP("/").WithPort(DefaultHTTPPort).WithStartupTimeout(2 * time.Minute), + Entrypoint: generateEntryPoint(), + WaitingFor: wait.ForHTTP("/").WithPort(DefaultHTTPPort).WithStartupTimeout(1 * time.Minute).WithPollInterval(200 * time.Millisecond), } if in.Node.HTTPPort != 0 && in.Node.P2PPort != 0 { req.HostConfigModifier = func(h *container.HostConfig) { diff --git a/framework/components/postgres/postgres.go b/framework/components/postgres/postgres.go index 46ac97557..3d44ecf0b 100644 --- a/framework/components/postgres/postgres.go +++ b/framework/components/postgres/postgres.go @@ -107,8 +107,8 @@ func NewPostgreSQL(in *Input) (*Output, error) { }, 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), + WithStartupTimeout(15 * time.Second). + WithPollInterval(200 * time.Millisecond), } var portToExpose int if in.Port != 0 { diff --git a/framework/components/simple_node_set/node_set.go b/framework/components/simple_node_set/node_set.go index 73e7c5d67..7ee3ca866 100644 --- a/framework/components/simple_node_set/node_set.go +++ b/framework/components/simple_node_set/node_set.go @@ -23,6 +23,7 @@ type Input struct { Nodes int `toml:"nodes" validate:"required"` HTTPPortRangeStart int `toml:"http_port_range_start"` P2PPortRangeStart int `toml:"p2p_port_range_start"` + DlvPortRangeStart int `toml:"dlv_port_range_start"` OverrideMode string `toml:"override_mode" validate:"required,oneof=all each"` DbInput *postgres.Input `toml:"db" validate:"required"` NodeSpecs []*clnode.Input `toml:"node_specs" validate:"required"` @@ -88,6 +89,7 @@ func sharedDBSetup(in *Input, bcOut *blockchain.Output) (*Output, error) { var ( httpPortRangeStart = DefaultHTTPPortStaticRangeStart p2pPortRangeStart = DefaultP2PStaticRangeStart + dlvPortStart = clnode.DefaultDebuggerPort ) if in.HTTPPortRangeStart != 0 { httpPortRangeStart = in.HTTPPortRangeStart @@ -95,6 +97,9 @@ func sharedDBSetup(in *Input, bcOut *blockchain.Output) (*Output, error) { if in.P2PPortRangeStart != 0 { p2pPortRangeStart = in.P2PPortRangeStart } + if in.DlvPortRangeStart != 0 { + dlvPortStart = in.DlvPortRangeStart + } eg := &errgroup.Group{} mu := &sync.Mutex{} @@ -129,6 +134,7 @@ func sharedDBSetup(in *Input, bcOut *blockchain.Output) (*Output, error) { Node: &clnode.NodeInput{ HTTPPort: httpPortRangeStart + i, P2PPort: p2pPortRangeStart + i, + DebuggerPort: dlvPortStart + i, CustomPorts: in.NodeSpecs[overrideIdx].Node.CustomPorts, Image: in.NodeSpecs[overrideIdx].Node.Image, Name: nodeName, diff --git a/framework/components/simple_node_set/nodeset_test.go b/framework/components/simple_node_set/nodeset_test.go index a398b688f..5fc63e5c3 100644 --- a/framework/components/simple_node_set/nodeset_test.go +++ b/framework/components/simple_node_set/nodeset_test.go @@ -78,6 +78,7 @@ func TestComponentDockerNodeSetSharedDB(t *testing.T) { OverrideMode: "each", HTTPPortRangeStart: 20000, P2PPortRangeStart: 22000, + DlvPortRangeStart: 45000, DbInput: &postgres.Input{ Image: "postgres:12.0", Port: 14000, diff --git a/framework/config.go b/framework/config.go index 3637b7ccf..f60fc71fd 100644 --- a/framework/config.go +++ b/framework/config.go @@ -144,10 +144,6 @@ func Load[X any](t *testing.T) (*X, error) { //} err = DefaultNetwork(once) require.NoError(t, err) - if os.Getenv(EnvVarCI) != "true" { - err = NewPromtail() - require.NoError(t, err) - } return input, nil } diff --git a/framework/examples/myproject/smoke.toml b/framework/examples/myproject/smoke.toml index a8074d14b..f73ac540c 100644 --- a/framework/examples/myproject/smoke.toml +++ b/framework/examples/myproject/smoke.toml @@ -1,9 +1,9 @@ [blockchain_a] # choose "anvil", "geth" or "besu" - # uncomment the second line for "anvil" - type = "besu" -# docker_cmd_params = ["-b", "1"] + # use docker_cmd_params = ["-b", "1"] for "anvil" + type = "anvil" + docker_cmd_params = ["-b", "1"] [data_provider] port = 9111 diff --git a/framework/promtail.go b/framework/promtail.go index e1b5246ae..adaf4aeba 100644 --- a/framework/promtail.go +++ b/framework/promtail.go @@ -59,7 +59,7 @@ scrape_configs: lokiTenantID := os.Getenv("LOKI_TENANT_ID") if lokiURL == "" { - lokiURL = "http://host.docker.internal:3030/loki/api/v1/push" + lokiURL = "http://host.docker.internal:3100/loki/api/v1/push" } if lokiTenantID == "" { lokiTenantID = "promtail" @@ -108,7 +108,7 @@ scrape_configs: } func NewPromtail() error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Minute) defer cancel() pcn, err := promtailConfig()