From 3aa5e4681dc4475727f2167db253cc1e1f2e8c7c Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Thu, 11 Jan 2024 10:19:56 -0600 Subject: [PATCH] golangci-lint: add noctx, sqlclosecheck; rm redundant revive.toml (#11362) * golangci-lint: add noctx, sqlclosecheck; rm redundant revive.toml * sqlclosecheck * noctx --- .golangci.yml | 2 + core/bridges/orm.go | 2 + core/cmd/admin_commands.go | 17 +++--- core/cmd/blocks_commands.go | 2 +- core/cmd/bridge_commands.go | 6 +-- core/cmd/cosmos_transaction_commands.go | 2 +- core/cmd/csa_keys_commands.go | 8 +-- core/cmd/eth_keys_commands.go | 12 ++--- core/cmd/evm_transaction_commands.go | 4 +- core/cmd/forwarders_commands.go | 4 +- core/cmd/jobs_commands.go | 8 +-- core/cmd/keys_commands.go | 10 ++-- core/cmd/ocr2_keys_commands.go | 10 ++-- core/cmd/ocr_keys_commands.go | 10 ++-- core/cmd/p2p_keys_commands.go | 10 ++-- core/cmd/shell.go | 42 +++++++-------- core/cmd/shell_local.go | 6 ++- core/cmd/shell_remote.go | 22 ++++---- core/cmd/shell_remote_test.go | 23 ++++---- core/cmd/shell_test.go | 8 +-- core/cmd/solana_transaction_commands.go | 2 +- core/cmd/vrf_keys_commands.go | 10 ++-- core/internal/cltest/cltest.go | 17 +++--- core/internal/cltest/mocks.go | 2 +- core/scripts/chaincli/handler/bootstrap.go | 10 ++-- core/scripts/chaincli/handler/debug.go | 17 +++--- core/scripts/chaincli/handler/handler.go | 26 ++++----- core/scripts/chaincli/handler/jobs.go | 8 +-- core/scripts/chaincli/handler/keeper.go | 7 +-- .../chaincli/handler/keeper_deployer.go | 19 +++---- .../scripts/chaincli/handler/keeper_launch.go | 28 +++++----- .../chaincli/handler/scrape_node_config.go | 18 +++---- .../gateway/network/httpserver_test.go | 2 +- .../services/gateway/network/wsserver_test.go | 2 +- core/services/health_test.go | 5 +- core/services/keystore/p2p_test.go | 1 + core/services/ocr/database.go | 4 +- core/services/ocr2/database.go | 2 +- .../ocr2/plugins/dkg/persistence/db_test.go | 3 ++ .../services/ocrcommon/discoverer_database.go | 16 +++--- core/services/pg/q.go | 1 + core/services/pipeline/orm.go | 1 + core/services/pipeline/orm_test.go | 3 +- core/services/relay/evm/request_round_db.go | 1 + core/services/webhook/delegate.go | 10 +++- .../webhook/external_initiator_manager.go | 25 ++++----- .../external_initiator_manager_test.go | 12 +++-- .../mocks/external_initiator_manager.go | 23 ++++---- core/utils/http/http_test.go | 3 +- core/web/auth/auth_test.go | 22 +++++--- core/web/auth/gql_test.go | 4 +- core/web/build_info_controller_test.go | 7 ++- core/web/gui_assets_test.go | 24 ++++++--- core/web/jobs_controller_test.go | 12 +++-- core/web/log_controller_test.go | 4 +- core/web/ping_controller_test.go | 9 ++-- core/web/router_test.go | 37 ++++++++----- core/web/sessions_controller_test.go | 17 ++++-- revive.toml | 53 ------------------- tools/flakeytests/cmd/runner/main.go | 15 ++++-- tools/flakeytests/reporter.go | 9 ++-- tools/flakeytests/runner.go | 7 +-- tools/flakeytests/runner_test.go | 25 +++++---- 63 files changed, 384 insertions(+), 347 deletions(-) delete mode 100644 revive.toml diff --git a/.golangci.yml b/.golangci.yml index f9d06ad471c..00541302f08 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -10,6 +10,8 @@ linters: - misspell - rowserrcheck - errorlint + - sqlclosecheck + - noctx linters-settings: exhaustive: default-signifies-exhaustive: true diff --git a/core/bridges/orm.go b/core/bridges/orm.go index cfad1da836e..8ae6b855c88 100644 --- a/core/bridges/orm.go +++ b/core/bridges/orm.go @@ -150,6 +150,7 @@ func (o *orm) CreateBridgeType(bt *BridgeType) error { if err != nil { return err } + defer stmt.Close() return stmt.Get(bt, bt) }) if err == nil { @@ -222,6 +223,7 @@ func (o *orm) CreateExternalInitiator(externalInitiator *ExternalInitiator) (err if err != nil { return errors.Wrap(err, "failed to prepare named stmt") } + defer stmt.Close() return errors.Wrap(stmt.Get(externalInitiator, externalInitiator), "failed to load external_initiator") }) return errors.Wrap(err, "CreateExternalInitiator failed") diff --git a/core/cmd/admin_commands.go b/core/cmd/admin_commands.go index a0e69867e71..799709ad205 100644 --- a/core/cmd/admin_commands.go +++ b/core/cmd/admin_commands.go @@ -180,7 +180,7 @@ func (ps AdminUsersPresenters) RenderTable(rt RendererTable) error { // ListUsers renders all API users and their roles func (s *Shell) ListUsers(_ *cli.Context) (err error) { - resp, err := s.HTTP.Get("/v2/users/", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/users/", nil) if err != nil { return s.errorOut(err) } @@ -195,7 +195,7 @@ func (s *Shell) ListUsers(_ *cli.Context) (err error) { // CreateUser creates a new user by prompting for email, password, and role func (s *Shell) CreateUser(c *cli.Context) (err error) { - resp, err := s.HTTP.Get("/v2/users/", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/users/", nil) if err != nil { return s.errorOut(err) } @@ -234,7 +234,7 @@ func (s *Shell) CreateUser(c *cli.Context) (err error) { } buf := bytes.NewBuffer(requestData) - response, err := s.HTTP.Post("/v2/users", buf) + response, err := s.HTTP.Post(s.ctx(), "/v2/users", buf) if err != nil { return s.errorOut(err) } @@ -263,7 +263,7 @@ func (s *Shell) ChangeRole(c *cli.Context) (err error) { } buf := bytes.NewBuffer(requestData) - response, err := s.HTTP.Patch("/v2/users", buf) + response, err := s.HTTP.Patch(s.ctx(), "/v2/users", buf) if err != nil { return s.errorOut(err) } @@ -283,7 +283,7 @@ func (s *Shell) DeleteUser(c *cli.Context) (err error) { return s.errorOut(errors.New("email flag is empty, must specify an email")) } - response, err := s.HTTP.Delete(fmt.Sprintf("/v2/users/%s", email)) + response, err := s.HTTP.Delete(s.ctx(), fmt.Sprintf("/v2/users/%s", email)) if err != nil { return s.errorOut(err) } @@ -297,8 +297,8 @@ func (s *Shell) DeleteUser(c *cli.Context) (err error) { } // Status will display the health of various services -func (s *Shell) Status(_ *cli.Context) error { - resp, err := s.HTTP.Get("/health?full=1", nil) +func (s *Shell) Status(c *cli.Context) error { + resp, err := s.HTTP.Get(s.ctx(), "/health?full=1", nil) if err != nil { return s.errorOut(err) } @@ -313,6 +313,7 @@ func (s *Shell) Status(_ *cli.Context) error { // Profile will collect pprof metrics and store them in a folder. func (s *Shell) Profile(c *cli.Context) error { + ctx := s.ctx() seconds := c.Uint("seconds") baseDir := c.String("output_dir") @@ -342,7 +343,7 @@ func (s *Shell) Profile(c *cli.Context) error { go func(vt string) { defer wgPprof.Done() uri := fmt.Sprintf("/v2/debug/pprof/%s?seconds=%d", vt, seconds) - resp, err := s.HTTP.Get(uri) + resp, err := s.HTTP.Get(ctx, uri) if err != nil { errs <- fmt.Errorf("error collecting %s: %w", vt, err) return diff --git a/core/cmd/blocks_commands.go b/core/cmd/blocks_commands.go index 29c9e7642a5..72b0523e18d 100644 --- a/core/cmd/blocks_commands.go +++ b/core/cmd/blocks_commands.go @@ -52,7 +52,7 @@ func (s *Shell) ReplayFromBlock(c *cli.Context) (err error) { } buf := bytes.NewBufferString("{}") - resp, err := s.HTTP.Post( + resp, err := s.HTTP.Post(s.ctx(), fmt.Sprintf( "/v2/replay_from_block/%v?%s", blockNumber, diff --git a/core/cmd/bridge_commands.go b/core/cmd/bridge_commands.go index 8389d548c79..398d466c43a 100644 --- a/core/cmd/bridge_commands.go +++ b/core/cmd/bridge_commands.go @@ -91,7 +91,7 @@ func (s *Shell) ShowBridge(c *cli.Context) (err error) { return s.errorOut(errors.New("must pass the name of the bridge to be shown")) } bridgeName := c.Args().First() - resp, err := s.HTTP.Get("/v2/bridge_types/" + bridgeName) + resp, err := s.HTTP.Get(s.ctx(), "/v2/bridge_types/"+bridgeName) if err != nil { return s.errorOut(err) } @@ -115,7 +115,7 @@ func (s *Shell) CreateBridge(c *cli.Context) (err error) { return s.errorOut(err) } - resp, err := s.HTTP.Post("/v2/bridge_types", buf) + resp, err := s.HTTP.Post(s.ctx(), "/v2/bridge_types", buf) if err != nil { return s.errorOut(err) } @@ -134,7 +134,7 @@ func (s *Shell) RemoveBridge(c *cli.Context) (err error) { return s.errorOut(errors.New("must pass the name of the bridge to be removed")) } bridgeName := c.Args().First() - resp, err := s.HTTP.Delete("/v2/bridge_types/" + bridgeName) + resp, err := s.HTTP.Delete(s.ctx(), "/v2/bridge_types/"+bridgeName) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/cosmos_transaction_commands.go b/core/cmd/cosmos_transaction_commands.go index 7c53d1ff1da..576a64adfb0 100644 --- a/core/cmd/cosmos_transaction_commands.go +++ b/core/cmd/cosmos_transaction_commands.go @@ -115,7 +115,7 @@ func (s *Shell) CosmosSendNativeToken(c *cli.Context) (err error) { buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Post("/v2/transfers/cosmos", buf) + resp, err := s.HTTP.Post(s.ctx(), "/v2/transfers/cosmos", buf) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/csa_keys_commands.go b/core/cmd/csa_keys_commands.go index c2ab3697b18..1c0fe54ab09 100644 --- a/core/cmd/csa_keys_commands.go +++ b/core/cmd/csa_keys_commands.go @@ -108,7 +108,7 @@ func (ps CSAKeyPresenters) RenderTable(rt RendererTable) error { // ListCSAKeys retrieves a list of all CSA keys func (s *Shell) ListCSAKeys(_ *cli.Context) (err error) { - resp, err := s.HTTP.Get("/v2/keys/csa", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/keys/csa", nil) if err != nil { return s.errorOut(err) } @@ -123,7 +123,7 @@ func (s *Shell) ListCSAKeys(_ *cli.Context) (err error) { // CreateCSAKey creates a new CSA key func (s *Shell) CreateCSAKey(_ *cli.Context) (err error) { - resp, err := s.HTTP.Post("/v2/keys/csa", nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/csa", nil) if err != nil { return s.errorOut(err) } @@ -165,7 +165,7 @@ func (s *Shell) ImportCSAKey(c *cli.Context) (err error) { query.Set("oldpassword", normalizePassword(string(oldPassword))) exportUrl.RawQuery = query.Encode() - resp, err := s.HTTP.Post(exportUrl.String(), bytes.NewReader(keyJSON)) + resp, err := s.HTTP.Post(s.ctx(), exportUrl.String(), bytes.NewReader(keyJSON)) if err != nil { return s.errorOut(err) } @@ -208,7 +208,7 @@ func (s *Shell) ExportCSAKey(c *cli.Context) (err error) { query.Set("newpassword", normalizePassword(string(newPassword))) exportUrl.RawQuery = query.Encode() - resp, err := s.HTTP.Post(exportUrl.String(), nil) + resp, err := s.HTTP.Post(s.ctx(), exportUrl.String(), nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } diff --git a/core/cmd/eth_keys_commands.go b/core/cmd/eth_keys_commands.go index 4fb3044ecb6..5adac3b382b 100644 --- a/core/cmd/eth_keys_commands.go +++ b/core/cmd/eth_keys_commands.go @@ -176,7 +176,7 @@ func (ps EthKeyPresenters) RenderTable(rt RendererTable) error { // ListETHKeys renders the active account address with its ETH & LINK balance func (s *Shell) ListETHKeys(_ *cli.Context) (err error) { - resp, err := s.HTTP.Get("/v2/keys/evm") + resp, err := s.HTTP.Get(s.ctx(), "/v2/keys/evm") if err != nil { return s.errorOut(err) @@ -206,7 +206,7 @@ func (s *Shell) CreateETHKey(c *cli.Context) (err error) { } createUrl.RawQuery = query.Encode() - resp, err := s.HTTP.Post(createUrl.String(), nil) + resp, err := s.HTTP.Post(s.ctx(), createUrl.String(), nil) if err != nil { return s.errorOut(err) } @@ -231,7 +231,7 @@ func (s *Shell) DeleteETHKey(c *cli.Context) (err error) { return nil } - resp, err := s.HTTP.Delete("/v2/keys/evm/" + address) + resp, err := s.HTTP.Delete(s.ctx(), "/v2/keys/evm/"+address) if err != nil { return s.errorOut(err) } @@ -290,7 +290,7 @@ func (s *Shell) ImportETHKey(c *cli.Context) (err error) { } importUrl.RawQuery = query.Encode() - resp, err := s.HTTP.Post(importUrl.String(), bytes.NewReader(keyJSON)) + resp, err := s.HTTP.Post(s.ctx(), importUrl.String(), bytes.NewReader(keyJSON)) if err != nil { return s.errorOut(err) } @@ -332,7 +332,7 @@ func (s *Shell) ExportETHKey(c *cli.Context) (err error) { query.Set("newpassword", strings.TrimSpace(string(newPassword))) exportUrl.RawQuery = query.Encode() - resp, err := s.HTTP.Post(exportUrl.String(), nil) + resp, err := s.HTTP.Post(s.ctx(), exportUrl.String(), nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } @@ -385,7 +385,7 @@ func (s *Shell) UpdateChainEVMKey(c *cli.Context) (err error) { } chainURL.RawQuery = query.Encode() - resp, err := s.HTTP.Post(chainURL.String(), nil) + resp, err := s.HTTP.Post(s.ctx(), chainURL.String(), nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } diff --git a/core/cmd/evm_transaction_commands.go b/core/cmd/evm_transaction_commands.go index 76628944a6c..28a4fa23a3b 100644 --- a/core/cmd/evm_transaction_commands.go +++ b/core/cmd/evm_transaction_commands.go @@ -117,7 +117,7 @@ func (s *Shell) ShowTransaction(c *cli.Context) (err error) { return s.errorOut(errors.New("must pass the hash of the transaction")) } hash := c.Args().First() - resp, err := s.HTTP.Get("/v2/transactions/evm/" + hash) + resp, err := s.HTTP.Get(s.ctx(), "/v2/transactions/evm/"+hash) if err != nil { return s.errorOut(err) } @@ -198,7 +198,7 @@ func (s *Shell) SendEther(c *cli.Context) (err error) { buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Post("/v2/transfers/evm", buf) + resp, err := s.HTTP.Post(s.ctx(), "/v2/transfers/evm", buf) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/forwarders_commands.go b/core/cmd/forwarders_commands.go index a870d4714c7..2445be5bfec 100644 --- a/core/cmd/forwarders_commands.go +++ b/core/cmd/forwarders_commands.go @@ -102,7 +102,7 @@ func (s *Shell) DeleteForwarder(c *cli.Context) (err error) { if !c.Args().Present() { return s.errorOut(errors.New("must pass the forwarder id to be archived")) } - resp, err := s.HTTP.Delete("/v2/nodes/evm/forwarders/" + c.Args().First()) + resp, err := s.HTTP.Delete(s.ctx(), "/v2/nodes/evm/forwarders/"+c.Args().First()) if err != nil { return s.errorOut(err) } @@ -143,7 +143,7 @@ func (s *Shell) TrackForwarder(c *cli.Context) (err error) { return s.errorOut(err) } - resp, err := s.HTTP.Post("/v2/nodes/evm/forwarders/track", bytes.NewReader(request)) + resp, err := s.HTTP.Post(s.ctx(), "/v2/nodes/evm/forwarders/track", bytes.NewReader(request)) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/jobs_commands.go b/core/cmd/jobs_commands.go index d6e752e1a10..1f9ca33c78e 100644 --- a/core/cmd/jobs_commands.go +++ b/core/cmd/jobs_commands.go @@ -212,7 +212,7 @@ func (s *Shell) ShowJob(c *cli.Context) (err error) { return s.errorOut(errors.New("must provide the id of the job")) } id := c.Args().First() - resp, err := s.HTTP.Get("/v2/jobs/" + id) + resp, err := s.HTTP.Get(s.ctx(), "/v2/jobs/"+id) if err != nil { return s.errorOut(err) } @@ -244,7 +244,7 @@ func (s *Shell) CreateJob(c *cli.Context) (err error) { return s.errorOut(err) } - resp, err := s.HTTP.Post("/v2/jobs", bytes.NewReader(request)) + resp, err := s.HTTP.Post(s.ctx(), "/v2/jobs", bytes.NewReader(request)) if err != nil { return s.errorOut(err) } @@ -273,7 +273,7 @@ func (s *Shell) DeleteJob(c *cli.Context) error { if !c.Args().Present() { return s.errorOut(errors.New("must pass the job id to be archived")) } - resp, err := s.HTTP.Delete("/v2/jobs/" + c.Args().First()) + resp, err := s.HTTP.Delete(s.ctx(), "/v2/jobs/"+c.Args().First()) if err != nil { return s.errorOut(err) } @@ -291,7 +291,7 @@ func (s *Shell) TriggerPipelineRun(c *cli.Context) error { if !c.Args().Present() { return s.errorOut(errors.New("Must pass the job id to trigger a run")) } - resp, err := s.HTTP.Post("/v2/jobs/"+c.Args().First()+"/runs", nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/jobs/"+c.Args().First()+"/runs", nil) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/keys_commands.go b/core/cmd/keys_commands.go index 07340c9cf08..7408d168887 100644 --- a/core/cmd/keys_commands.go +++ b/core/cmd/keys_commands.go @@ -105,7 +105,7 @@ func newKeysClient[K keystore.Key, P TableRenderer, P2 ~[]P](typ string, s *Shel // ListKeys retrieves a list of all keys func (cli *keysClient[K, P, P2]) ListKeys(_ *cli.Context) (err error) { - resp, err := cli.HTTP.Get(cli.path, nil) + resp, err := cli.HTTP.Get(cli.ctx(), cli.path, nil) if err != nil { return cli.errorOut(err) } @@ -121,7 +121,7 @@ func (cli *keysClient[K, P, P2]) ListKeys(_ *cli.Context) (err error) { // CreateKey creates a new key func (cli *keysClient[K, P, P2]) CreateKey(_ *cli.Context) (err error) { - resp, err := cli.HTTP.Post(cli.path, nil) + resp, err := cli.HTTP.Post(cli.ctx(), cli.path, nil) if err != nil { return cli.errorOut(err) } @@ -152,7 +152,7 @@ func (cli *keysClient[K, P, P2]) DeleteKey(c *cli.Context) (err error) { queryStr = "?hard=true" } - resp, err := cli.HTTP.Delete(fmt.Sprintf(cli.path+"/%s%s", id, queryStr)) + resp, err := cli.HTTP.Delete(cli.ctx(), fmt.Sprintf(cli.path+"/%s%s", id, queryStr)) if err != nil { return cli.errorOut(err) } @@ -189,7 +189,7 @@ func (cli *keysClient[K, P, P2]) ImportKey(c *cli.Context) (err error) { } normalizedPassword := normalizePassword(string(oldPassword)) - resp, err := cli.HTTP.Post(cli.path+"/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) + resp, err := cli.HTTP.Post(cli.ctx(), cli.path+"/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) if err != nil { return cli.errorOut(err) } @@ -227,7 +227,7 @@ func (cli *keysClient[K, P, P2]) ExportKey(c *cli.Context) (err error) { ID := c.Args().Get(0) normalizedPassword := normalizePassword(string(newPassword)) - resp, err := cli.HTTP.Post(cli.path+"/export/"+ID+"?newpassword="+normalizedPassword, nil) + resp, err := cli.HTTP.Post(cli.ctx(), cli.path+"/export/"+ID+"?newpassword="+normalizedPassword, nil) if err != nil { return cli.errorOut(errors.Wrap(err, "Could not make HTTP request")) } diff --git a/core/cmd/ocr2_keys_commands.go b/core/cmd/ocr2_keys_commands.go index ad4b30df4c2..1d469024878 100644 --- a/core/cmd/ocr2_keys_commands.go +++ b/core/cmd/ocr2_keys_commands.go @@ -127,7 +127,7 @@ func (ps OCR2KeyBundlePresenters) RenderTable(rt RendererTable) error { // ListOCR2KeyBundles lists the available OCR2 Key Bundles func (s *Shell) ListOCR2KeyBundles(_ *cli.Context) error { - resp, err := s.HTTP.Get("/v2/keys/ocr2", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/keys/ocr2", nil) if err != nil { return s.errorOut(err) } @@ -149,7 +149,7 @@ func (s *Shell) CreateOCR2KeyBundle(c *cli.Context) error { ) } chainType := c.Args().Get(0) - resp, err := s.HTTP.Post(fmt.Sprintf("/v2/keys/ocr2/%s", chainType), nil) + resp, err := s.HTTP.Post(s.ctx(), fmt.Sprintf("/v2/keys/ocr2/%s", chainType), nil) if err != nil { return s.errorOut(err) } @@ -182,7 +182,7 @@ func (s *Shell) DeleteOCR2KeyBundle(c *cli.Context) error { queryStr = "?hard=true" } - resp, err := s.HTTP.Delete(fmt.Sprintf("/v2/keys/ocr2/%s%s", id, queryStr)) + resp, err := s.HTTP.Delete(s.ctx(), fmt.Sprintf("/v2/keys/ocr2/%s%s", id, queryStr)) if err != nil { return s.errorOut(err) } @@ -218,7 +218,7 @@ func (s *Shell) ImportOCR2Key(c *cli.Context) (err error) { } normalizedPassword := normalizePassword(string(oldPassword)) - resp, err := s.HTTP.Post("/v2/keys/ocr2/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/ocr2/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) if err != nil { return s.errorOut(err) } @@ -255,7 +255,7 @@ func (s *Shell) ExportOCR2Key(c *cli.Context) (err error) { ID := c.Args().Get(0) normalizedPassword := normalizePassword(string(newPassword)) - resp, err := s.HTTP.Post("/v2/keys/ocr2/export/"+ID+"?newpassword="+normalizedPassword, nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/ocr2/export/"+ID+"?newpassword="+normalizedPassword, nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } diff --git a/core/cmd/ocr_keys_commands.go b/core/cmd/ocr_keys_commands.go index 2628cd9b270..399333bba93 100644 --- a/core/cmd/ocr_keys_commands.go +++ b/core/cmd/ocr_keys_commands.go @@ -108,7 +108,7 @@ type OCRKeyBundlePresenters []OCRKeyBundlePresenter // ListOCRKeyBundles lists the available OCR Key Bundles func (s *Shell) ListOCRKeyBundles(_ *cli.Context) error { - resp, err := s.HTTP.Get("/v2/keys/ocr", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/keys/ocr", nil) if err != nil { return s.errorOut(err) } @@ -141,7 +141,7 @@ func (ps OCRKeyBundlePresenters) RenderTable(rt RendererTable) error { // CreateOCR2KeyBundle creates an OCR key bundle and saves it to the keystore func (s *Shell) CreateOCRKeyBundle(_ *cli.Context) error { - resp, err := s.HTTP.Post("/v2/keys/ocr", nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/ocr", nil) if err != nil { return s.errorOut(err) } @@ -174,7 +174,7 @@ func (s *Shell) DeleteOCRKeyBundle(c *cli.Context) error { queryStr = "?hard=true" } - resp, err := s.HTTP.Delete(fmt.Sprintf("/v2/keys/ocr/%s%s", id, queryStr)) + resp, err := s.HTTP.Delete(s.ctx(), fmt.Sprintf("/v2/keys/ocr/%s%s", id, queryStr)) if err != nil { return s.errorOut(err) } @@ -210,7 +210,7 @@ func (s *Shell) ImportOCRKey(c *cli.Context) (err error) { } normalizedPassword := normalizePassword(string(oldPassword)) - resp, err := s.HTTP.Post("/v2/keys/ocr/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/ocr/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) if err != nil { return s.errorOut(err) } @@ -247,7 +247,7 @@ func (s *Shell) ExportOCRKey(c *cli.Context) (err error) { ID := c.Args().Get(0) normalizedPassword := normalizePassword(string(newPassword)) - resp, err := s.HTTP.Post("/v2/keys/ocr/export/"+ID+"?newpassword="+normalizedPassword, nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/ocr/export/"+ID+"?newpassword="+normalizedPassword, nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } diff --git a/core/cmd/p2p_keys_commands.go b/core/cmd/p2p_keys_commands.go index 4ec03da96ca..da3bf412a04 100644 --- a/core/cmd/p2p_keys_commands.go +++ b/core/cmd/p2p_keys_commands.go @@ -125,7 +125,7 @@ func (ps P2PKeyPresenters) RenderTable(rt RendererTable) error { // ListP2PKeys retrieves a list of all P2P keys func (s *Shell) ListP2PKeys(_ *cli.Context) (err error) { - resp, err := s.HTTP.Get("/v2/keys/p2p", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/keys/p2p", nil) if err != nil { return s.errorOut(err) } @@ -140,7 +140,7 @@ func (s *Shell) ListP2PKeys(_ *cli.Context) (err error) { // CreateP2PKey creates a new P2P key func (s *Shell) CreateP2PKey(_ *cli.Context) (err error) { - resp, err := s.HTTP.Post("/v2/keys/p2p", nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/p2p", nil) if err != nil { return s.errorOut(err) } @@ -170,7 +170,7 @@ func (s *Shell) DeleteP2PKey(c *cli.Context) (err error) { queryStr = "?hard=true" } - resp, err := s.HTTP.Delete(fmt.Sprintf("/v2/keys/p2p/%s%s", id, queryStr)) + resp, err := s.HTTP.Delete(s.ctx(), fmt.Sprintf("/v2/keys/p2p/%s%s", id, queryStr)) if err != nil { return s.errorOut(err) } @@ -206,7 +206,7 @@ func (s *Shell) ImportP2PKey(c *cli.Context) (err error) { } normalizedPassword := normalizePassword(string(oldPassword)) - resp, err := s.HTTP.Post("/v2/keys/p2p/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/p2p/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) if err != nil { return s.errorOut(err) } @@ -243,7 +243,7 @@ func (s *Shell) ExportP2PKey(c *cli.Context) (err error) { ID := c.Args().Get(0) normalizedPassword := normalizePassword(string(newPassword)) - resp, err := s.HTTP.Post("/v2/keys/p2p/export/"+ID+"?newpassword="+normalizedPassword, nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/p2p/export/"+ID+"?newpassword="+normalizedPassword, nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } diff --git a/core/cmd/shell.go b/core/cmd/shell.go index 547de67210f..b2298ab399d 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -473,11 +473,11 @@ func createServer(handler *gin.Engine, addr string, requestTimeout time.Duration // HTTPClient encapsulates all methods used to interact with a chainlink node API. type HTTPClient interface { - Get(string, ...map[string]string) (*http.Response, error) - Post(string, io.Reader) (*http.Response, error) - Put(string, io.Reader) (*http.Response, error) - Patch(string, io.Reader, ...map[string]string) (*http.Response, error) - Delete(string) (*http.Response, error) + Get(context.Context, string, ...map[string]string) (*http.Response, error) + Post(context.Context, string, io.Reader) (*http.Response, error) + Put(context.Context, string, io.Reader) (*http.Response, error) + Patch(context.Context, string, io.Reader, ...map[string]string) (*http.Response, error) + Delete(context.Context, string) (*http.Response, error) } type authenticatedHTTPClient struct { @@ -511,31 +511,31 @@ func newHttpClient(lggr logger.Logger, insecureSkipVerify bool) *http.Client { } // Get performs an HTTP Get using the authenticated HTTP client's cookie. -func (h *authenticatedHTTPClient) Get(path string, headers ...map[string]string) (*http.Response, error) { - return h.doRequest("GET", path, nil, headers...) +func (h *authenticatedHTTPClient) Get(ctx context.Context, path string, headers ...map[string]string) (*http.Response, error) { + return h.doRequest(ctx, "GET", path, nil, headers...) } // Post performs an HTTP Post using the authenticated HTTP client's cookie. -func (h *authenticatedHTTPClient) Post(path string, body io.Reader) (*http.Response, error) { - return h.doRequest("POST", path, body) +func (h *authenticatedHTTPClient) Post(ctx context.Context, path string, body io.Reader) (*http.Response, error) { + return h.doRequest(ctx, "POST", path, body) } // Put performs an HTTP Put using the authenticated HTTP client's cookie. -func (h *authenticatedHTTPClient) Put(path string, body io.Reader) (*http.Response, error) { - return h.doRequest("PUT", path, body) +func (h *authenticatedHTTPClient) Put(ctx context.Context, path string, body io.Reader) (*http.Response, error) { + return h.doRequest(ctx, "PUT", path, body) } // Patch performs an HTTP Patch using the authenticated HTTP client's cookie. -func (h *authenticatedHTTPClient) Patch(path string, body io.Reader, headers ...map[string]string) (*http.Response, error) { - return h.doRequest("PATCH", path, body, headers...) +func (h *authenticatedHTTPClient) Patch(ctx context.Context, path string, body io.Reader, headers ...map[string]string) (*http.Response, error) { + return h.doRequest(ctx, "PATCH", path, body, headers...) } // Delete performs an HTTP Delete using the authenticated HTTP client's cookie. -func (h *authenticatedHTTPClient) Delete(path string) (*http.Response, error) { - return h.doRequest("DELETE", path, nil) +func (h *authenticatedHTTPClient) Delete(ctx context.Context, path string) (*http.Response, error) { + return h.doRequest(ctx, "DELETE", path, nil) } -func (h *authenticatedHTTPClient) doRequest(verb, path string, body io.Reader, headerArgs ...map[string]string) (*http.Response, error) { +func (h *authenticatedHTTPClient) doRequest(ctx context.Context, verb, path string, body io.Reader, headerArgs ...map[string]string) (*http.Response, error) { var headers map[string]string if len(headerArgs) > 0 { headers = headerArgs[0] @@ -543,7 +543,7 @@ func (h *authenticatedHTTPClient) doRequest(verb, path string, body io.Reader, h headers = map[string]string{} } - request, err := http.NewRequest(verb, h.remoteNodeURL.String()+path, body) + request, err := http.NewRequestWithContext(ctx, verb, h.remoteNodeURL.String()+path, body) if err != nil { return nil, err } @@ -565,7 +565,7 @@ func (h *authenticatedHTTPClient) doRequest(verb, path string, body io.Reader, h } if response.StatusCode == http.StatusUnauthorized && (h.sessionRequest.Email != "" || h.sessionRequest.Password != "") { var cookieerr error - cookie, cookieerr = h.cookieAuth.Authenticate(h.sessionRequest) + cookie, cookieerr = h.cookieAuth.Authenticate(ctx, h.sessionRequest) if cookieerr != nil { return response, err } @@ -583,7 +583,7 @@ func (h *authenticatedHTTPClient) doRequest(verb, path string, body io.Reader, h // future HTTP requests. type CookieAuthenticator interface { Cookie() (*http.Cookie, error) - Authenticate(sessions.SessionRequest) (*http.Cookie, error) + Authenticate(context.Context, sessions.SessionRequest) (*http.Cookie, error) Logout() error } @@ -612,14 +612,14 @@ func (t *SessionCookieAuthenticator) Cookie() (*http.Cookie, error) { } // Authenticate retrieves a session ID via a cookie and saves it to disk. -func (t *SessionCookieAuthenticator) Authenticate(sessionRequest sessions.SessionRequest) (*http.Cookie, error) { +func (t *SessionCookieAuthenticator) Authenticate(ctx context.Context, sessionRequest sessions.SessionRequest) (*http.Cookie, error) { b := new(bytes.Buffer) err := json.NewEncoder(b).Encode(sessionRequest) if err != nil { return nil, err } url := t.config.RemoteNodeURL.String() + "/sessions" - req, err := http.NewRequest("POST", url, b) + req, err := http.NewRequestWithContext(ctx, "POST", url, b) if err != nil { return nil, err } diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 69b7373ed70..b970b516413 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -1006,9 +1006,8 @@ func (s *Shell) CleanupChainTables(c *cli.Context) error { rows, err := db.Query(tablesToDeleteFromQuery, "evm_chain_id") if err != nil { return err - } else if rows.Err() != nil { - return rows.Err() } + defer rows.Close() var tablesToDeleteFrom []string for rows.Next() { @@ -1019,6 +1018,9 @@ func (s *Shell) CleanupChainTables(c *cli.Context) error { } tablesToDeleteFrom = append(tablesToDeleteFrom, schema+"."+name) } + if rows.Err() != nil { + return rows.Err() + } for _, tableName := range tablesToDeleteFrom { query := fmt.Sprintf(`DELETE FROM %s WHERE "evm_chain_id"=$1;`, tableName) diff --git a/core/cmd/shell_remote.go b/core/cmd/shell_remote.go index bc4620d0732..aab4a94da6f 100644 --- a/core/cmd/shell_remote.go +++ b/core/cmd/shell_remote.go @@ -110,7 +110,7 @@ func (s *Shell) CreateExternalInitiator(c *cli.Context) (err error) { } buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Post("/v2/external_initiators", buf) + resp, err := s.HTTP.Post(s.ctx(), "/v2/external_initiators", buf) if err != nil { return s.errorOut(err) } @@ -131,7 +131,7 @@ func (s *Shell) DeleteExternalInitiator(c *cli.Context) (err error) { return s.errorOut(errors.New("Must pass the name of the external initiator to delete")) } - resp, err := s.HTTP.Delete("/v2/external_initiators/" + c.Args().First()) + resp, err := s.HTTP.Delete(s.ctx(), "/v2/external_initiators/"+c.Args().First()) if err != nil { return s.errorOut(err) } @@ -155,7 +155,7 @@ func (s *Shell) getPage(requestURI string, page int, model interface{}) (err err } uri.RawQuery = q.Encode() - resp, err := s.HTTP.Get(uri.String()) + resp, err := s.HTTP.Get(s.ctx(), uri.String()) if err != nil { return s.errorOut(err) } @@ -180,7 +180,7 @@ func (s *Shell) RemoteLogin(c *cli.Context) error { if err != nil { return s.errorOut(err) } - _, err = s.CookieAuthenticator.Authenticate(sessionRequest) + _, err = s.CookieAuthenticator.Authenticate(s.ctx(), sessionRequest) if err != nil { return s.errorOut(err) } @@ -194,7 +194,7 @@ func (s *Shell) RemoteLogin(c *cli.Context) error { // Logout removes local and remote session. func (s *Shell) Logout(_ *cli.Context) (err error) { - resp, err := s.HTTP.Delete("/sessions") + resp, err := s.HTTP.Delete(s.ctx(), "/sessions") if err != nil { return s.errorOut(err) } @@ -224,7 +224,7 @@ func (s *Shell) ChangePassword(_ *cli.Context) (err error) { } buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Patch("/v2/user/password", buf) + resp, err := s.HTTP.Patch(s.ctx(), "/v2/user/password", buf) if err != nil { return s.errorOut(err) } @@ -313,7 +313,7 @@ func (s *Shell) ConfigV2(c *cli.Context) error { } func (s *Shell) configV2Str(userOnly bool) (string, error) { - resp, err := s.HTTP.Get(fmt.Sprintf("/v2/config/v2?userOnly=%t", userOnly)) + resp, err := s.HTTP.Get(s.ctx(), fmt.Sprintf("/v2/config/v2?userOnly=%t", userOnly)) if err != nil { return "", s.errorOut(err) } @@ -351,7 +351,7 @@ func (s *Shell) SetLogLevel(c *cli.Context) (err error) { } buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Patch("/v2/log", buf) + resp, err := s.HTTP.Patch(s.ctx(), "/v2/log", buf) if err != nil { return s.errorOut(err) } @@ -383,7 +383,7 @@ func (s *Shell) SetLogSQL(c *cli.Context) (err error) { } buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Patch("/v2/log", buf) + resp, err := s.HTTP.Patch(s.ctx(), "/v2/log", buf) if err != nil { return s.errorOut(err) } @@ -476,7 +476,7 @@ func parseResponse(resp *http.Response) ([]byte, error) { } func (s *Shell) checkRemoteBuildCompatibility(lggr logger.Logger, onlyWarn bool, cliVersion, cliSha string) error { - resp, err := s.HTTP.Get("/v2/build_info") + resp, err := s.HTTP.Get(s.ctx(), "/v2/build_info") if err != nil { lggr.Warnw("Got error querying for version. Remote node version is unknown and CLI may behave in unexpected ways.", "err", err) return nil @@ -517,7 +517,7 @@ func (s *Shell) Health(c *cli.Context) error { if c.Bool("json") { mime = gin.MIMEJSON } - resp, err := s.HTTP.Get("/health", map[string]string{"Accept": mime}) + resp, err := s.HTTP.Get(s.ctx(), "/health", map[string]string{"Accept": mime}) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index ed675d8ee9e..dbd9968daab 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "errors" "flag" "fmt" @@ -383,7 +384,7 @@ type mockHTTPClient struct { mockSha string } -func (h *mockHTTPClient) Get(path string, headers ...map[string]string) (*http.Response, error) { +func (h *mockHTTPClient) Get(ctx context.Context, path string, headers ...map[string]string) (*http.Response, error) { if path == "/v2/build_info" { // Return mocked response here json := fmt.Sprintf(`{"version":"%s","commitSHA":"%s"}`, h.mockVersion, h.mockSha) @@ -393,23 +394,23 @@ func (h *mockHTTPClient) Get(path string, headers ...map[string]string) (*http.R Body: r, }, nil } - return h.HTTP.Get(path, headers...) + return h.HTTP.Get(ctx, path, headers...) } -func (h *mockHTTPClient) Post(path string, body io.Reader) (*http.Response, error) { - return h.HTTP.Post(path, body) +func (h *mockHTTPClient) Post(ctx context.Context, path string, body io.Reader) (*http.Response, error) { + return h.HTTP.Post(ctx, path, body) } -func (h *mockHTTPClient) Put(path string, body io.Reader) (*http.Response, error) { - return h.HTTP.Put(path, body) +func (h *mockHTTPClient) Put(ctx context.Context, path string, body io.Reader) (*http.Response, error) { + return h.HTTP.Put(ctx, path, body) } -func (h *mockHTTPClient) Patch(path string, body io.Reader, headers ...map[string]string) (*http.Response, error) { - return h.HTTP.Patch(path, body, headers...) +func (h *mockHTTPClient) Patch(ctx context.Context, path string, body io.Reader, headers ...map[string]string) (*http.Response, error) { + return h.HTTP.Patch(ctx, path, body, headers...) } -func (h *mockHTTPClient) Delete(path string) (*http.Response, error) { - return h.HTTP.Delete(path) +func (h *mockHTTPClient) Delete(ctx context.Context, path string) (*http.Response, error) { + return h.HTTP.Delete(ctx, path) } func TestShell_ChangePassword(t *testing.T) { @@ -700,7 +701,7 @@ func (FailingAuthenticator) Cookie() (*http.Cookie, error) { } // Authenticate retrieves a session ID via a cookie and saves it to disk. -func (FailingAuthenticator) Authenticate(sessionRequest sessions.SessionRequest) (*http.Cookie, error) { +func (FailingAuthenticator) Authenticate(context.Context, sessions.SessionRequest) (*http.Cookie, error) { return nil, errors.New("no luck") } diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index ade14aa0d8a..ec9606e0ac6 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -38,6 +38,7 @@ import ( func TestTerminalCookieAuthenticator_AuthenticateWithoutSession(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) u := cltest.NewUserWithSession(t, app.AuthenticationProvider()) @@ -54,7 +55,7 @@ func TestTerminalCookieAuthenticator_AuthenticateWithoutSession(t *testing.T) { sr := sessions.SessionRequest{Email: test.email, Password: test.pwd} store := &cmd.MemoryCookieStore{} tca := cmd.NewSessionCookieAuthenticator(cmd.ClientOpts{}, store, logger.TestLogger(t)) - cookie, err := tca.Authenticate(sr) + cookie, err := tca.Authenticate(ctx, sr) assert.Error(t, err) assert.Nil(t, cookie) @@ -68,8 +69,9 @@ func TestTerminalCookieAuthenticator_AuthenticateWithoutSession(t *testing.T) { func TestTerminalCookieAuthenticator_AuthenticateWithSession(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) u := cltest.NewUserWithSession(t, app.AuthenticationProvider()) @@ -87,7 +89,7 @@ func TestTerminalCookieAuthenticator_AuthenticateWithSession(t *testing.T) { sr := sessions.SessionRequest{Email: test.email, Password: test.pwd} store := &cmd.MemoryCookieStore{} tca := cmd.NewSessionCookieAuthenticator(app.NewClientOpts(), store, logger.TestLogger(t)) - cookie, err := tca.Authenticate(sr) + cookie, err := tca.Authenticate(ctx, sr) if test.wantError { assert.Error(t, err) diff --git a/core/cmd/solana_transaction_commands.go b/core/cmd/solana_transaction_commands.go index c92cc3e29dd..23e94eee50b 100644 --- a/core/cmd/solana_transaction_commands.go +++ b/core/cmd/solana_transaction_commands.go @@ -105,7 +105,7 @@ func (s *Shell) SolanaSendSol(c *cli.Context) (err error) { buf := bytes.NewBuffer(requestData) - resp, err := s.HTTP.Post("/v2/transfers/solana", buf) + resp, err := s.HTTP.Post(s.ctx(), "/v2/transfers/solana", buf) if err != nil { return s.errorOut(err) } diff --git a/core/cmd/vrf_keys_commands.go b/core/cmd/vrf_keys_commands.go index 1a04ef37c3e..32d32334af5 100644 --- a/core/cmd/vrf_keys_commands.go +++ b/core/cmd/vrf_keys_commands.go @@ -118,7 +118,7 @@ func (ps VRFKeyPresenters) RenderTable(rt RendererTable) error { // CreateVRFKey creates a key in the VRF keystore, protected by the password in // the vrf password file provided when starting the chainlink node. func (s *Shell) CreateVRFKey(_ *cli.Context) error { - resp, err := s.HTTP.Post("/v2/keys/vrf", nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/vrf", nil) if err != nil { return s.errorOut(err) } @@ -154,7 +154,7 @@ func (s *Shell) ImportVRFKey(c *cli.Context) error { } normalizedPassword := normalizePassword(string(oldPassword)) - resp, err := s.HTTP.Post("/v2/keys/vrf/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/vrf/import?oldpassword="+normalizedPassword, bytes.NewReader(keyJSON)) if err != nil { return s.errorOut(err) } @@ -195,7 +195,7 @@ func (s *Shell) ExportVRFKey(c *cli.Context) error { } normalizedPassword := normalizePassword(string(newPassword)) - resp, err := s.HTTP.Post("/v2/keys/vrf/export/"+pk.String()+"?newpassword="+normalizedPassword, nil) + resp, err := s.HTTP.Post(s.ctx(), "/v2/keys/vrf/export/"+pk.String()+"?newpassword="+normalizedPassword, nil) if err != nil { return s.errorOut(errors.Wrap(err, "Could not make HTTP request")) } @@ -248,7 +248,7 @@ func (s *Shell) DeleteVRFKey(c *cli.Context) error { queryStr = "?hard=true" } - resp, err := s.HTTP.Delete(fmt.Sprintf("/v2/keys/vrf/%s%s", id, queryStr)) + resp, err := s.HTTP.Delete(s.ctx(), fmt.Sprintf("/v2/keys/vrf/%s%s", id, queryStr)) if err != nil { return s.errorOut(err) } @@ -276,7 +276,7 @@ func getPublicKey(c *cli.Context) (secp256k1.PublicKey, error) { // ListKeys Lists the keys in the db func (s *Shell) ListVRFKeys(_ *cli.Context) error { - resp, err := s.HTTP.Get("/v2/keys/vrf", nil) + resp, err := s.HTTP.Get(s.ctx(), "/v2/keys/vrf", nil) if err != nil { return s.errorOut(err) } diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index dcd16b8e59c..c7abfb31a2a 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -692,27 +692,27 @@ type HTTPClientCleaner struct { } func (r *HTTPClientCleaner) Get(path string, headers ...map[string]string) (*http.Response, func()) { - resp, err := r.HTTPClient.Get(path, headers...) + resp, err := r.HTTPClient.Get(testutils.Context(r.t), path, headers...) return bodyCleaner(r.t, resp, err) } func (r *HTTPClientCleaner) Post(path string, body io.Reader) (*http.Response, func()) { - resp, err := r.HTTPClient.Post(path, body) + resp, err := r.HTTPClient.Post(testutils.Context(r.t), path, body) return bodyCleaner(r.t, resp, err) } func (r *HTTPClientCleaner) Put(path string, body io.Reader) (*http.Response, func()) { - resp, err := r.HTTPClient.Put(path, body) + resp, err := r.HTTPClient.Put(testutils.Context(r.t), path, body) return bodyCleaner(r.t, resp, err) } func (r *HTTPClientCleaner) Patch(path string, body io.Reader, headers ...map[string]string) (*http.Response, func()) { - resp, err := r.HTTPClient.Patch(path, body, headers...) + resp, err := r.HTTPClient.Patch(testutils.Context(r.t), path, body, headers...) return bodyCleaner(r.t, resp, err) } func (r *HTTPClientCleaner) Delete(path string) (*http.Response, func()) { - resp, err := r.HTTPClient.Delete(path) + resp, err := r.HTTPClient.Delete(testutils.Context(r.t), path) return bodyCleaner(r.t, resp, err) } @@ -872,10 +872,7 @@ func CreateExternalInitiatorViaWeb( t.Helper() client := app.NewHTTPClient(nil) - resp, cleanup := client.Post( - "/v2/external_initiators", - bytes.NewBufferString(payload), - ) + resp, cleanup := client.Post("/v2/external_initiators", bytes.NewBufferString(payload)) defer cleanup() AssertServerResponse(t, resp, http.StatusCreated) ei := &webpresenters.ExternalInitiatorAuthentication{} @@ -1125,7 +1122,7 @@ func unauthenticatedHTTP(t testing.TB, method string, url string, body io.Reader t.Helper() client := clhttptest.NewTestLocalOnlyHTTPClient() - request, err := http.NewRequest(method, url, body) + request, err := http.NewRequestWithContext(testutils.Context(t), method, url, body) require.NoError(t, err) request.Header.Set("Content-Type", "application/json") for key, value := range headers { diff --git a/core/internal/cltest/mocks.go b/core/internal/cltest/mocks.go index 073b3ba246c..fbfd820309a 100644 --- a/core/internal/cltest/mocks.go +++ b/core/internal/cltest/mocks.go @@ -355,7 +355,7 @@ func (m MockCookieAuthenticator) Cookie() (*http.Cookie, error) { return MustGenerateSessionCookie(m.t, m.SessionID), m.Error } -func (m MockCookieAuthenticator) Authenticate(sessions.SessionRequest) (*http.Cookie, error) { +func (m MockCookieAuthenticator) Authenticate(context.Context, sessions.SessionRequest) (*http.Cookie, error) { return MustGenerateSessionCookie(m.t, m.SessionID), m.Error } diff --git a/core/scripts/chaincli/handler/bootstrap.go b/core/scripts/chaincli/handler/bootstrap.go index 4cc19299cca..bf79f5698dc 100644 --- a/core/scripts/chaincli/handler/bootstrap.go +++ b/core/scripts/chaincli/handler/bootstrap.go @@ -47,17 +47,17 @@ func (h *baseHandler) StartBootstrapNode(ctx context.Context, addr string, uiPor lggr.Fatal("Failed to launch chainlink node, ", err) } - cl, err := authenticate(urlRaw, defaultChainlinkNodeLogin, defaultChainlinkNodePassword, lggr) + cl, err := authenticate(ctx, urlRaw, defaultChainlinkNodeLogin, defaultChainlinkNodePassword, lggr) if err != nil { lggr.Fatal("Authentication failed, ", err) } - p2pKeyID, err := getP2PKeyID(cl) + p2pKeyID, err := getP2PKeyID(ctx, cl) if err != nil { lggr.Fatal("Failed to get P2P key ID, ", err) } - if err = h.createBootstrapJob(cl, addr); err != nil { + if err = h.createBootstrapJob(ctx, cl, addr); err != nil { lggr.Fatal("Failed to create keeper job: ", err) } @@ -68,7 +68,7 @@ func (h *baseHandler) StartBootstrapNode(ctx context.Context, addr string, uiPor } // createBootstrapJob creates a bootstrap job in the chainlink node by the given address -func (h *baseHandler) createBootstrapJob(client cmd.HTTPClient, contractAddr string) error { +func (h *baseHandler) createBootstrapJob(ctx context.Context, client cmd.HTTPClient, contractAddr string) error { request, err := json.Marshal(web.CreateJobRequest{ TOML: fmt.Sprintf(bootstrapJobSpec, contractAddr, h.cfg.ChainID), }) @@ -76,7 +76,7 @@ func (h *baseHandler) createBootstrapJob(client cmd.HTTPClient, contractAddr str return fmt.Errorf("failed to marshal request: %s", err) } - resp, err := client.Post("/v2/jobs", bytes.NewReader(request)) + resp, err := client.Post(ctx, "/v2/jobs", bytes.NewReader(request)) if err != nil { return fmt.Errorf("failed to create bootstrap job: %s", err) } diff --git a/core/scripts/chaincli/handler/debug.go b/core/scripts/chaincli/handler/debug.go index 9782f5b72fe..c317edcac37 100644 --- a/core/scripts/chaincli/handler/debug.go +++ b/core/scripts/chaincli/handler/debug.go @@ -150,7 +150,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failUnknown("failed to pack raw checkUpkeep call", err) } - addLink("checkUpkeep simulation", tenderlySimLink(k.cfg, chainID, 0, rawCall, registryAddress)) + addLink("checkUpkeep simulation", tenderlySimLink(ctx, k.cfg, chainID, 0, rawCall, registryAddress)) } else if triggerType == LogTrigger { // validate inputs message("upkeep identified as log trigger") @@ -243,9 +243,9 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failUnknown("failed to pack raw checkUpkeep call", err) } - addLink("checkUpkeep simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, registryAddress)) + addLink("checkUpkeep simulation", tenderlySimLink(ctx, k.cfg, chainID, blockNum, rawCall, registryAddress)) rawCall = append(core.ILogAutomationABI.Methods["checkLog"].ID, triggerData...) - addLink("checkLog (direct) simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, upkeepInfo.Target)) + addLink("checkLog (direct) simulation", tenderlySimLink(ctx, k.cfg, chainID, blockNum, rawCall, upkeepInfo.Target)) } else { resolveIneligible(fmt.Sprintf("invalid trigger type: %d", triggerType)) } @@ -334,12 +334,12 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failUnknown("failed to pack raw checkCallback call", err) } - addLink("checkCallback simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, registryAddress)) + addLink("checkCallback simulation", tenderlySimLink(ctx, k.cfg, chainID, blockNum, rawCall, registryAddress)) rawCall, err = core.StreamsCompatibleABI.Pack("checkCallback", values, streamsLookup.ExtraData) if err != nil { failUnknown("failed to pack raw checkCallback (direct) call", err) } - addLink("checkCallback (direct) simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, upkeepInfo.Target)) + addLink("checkCallback (direct) simulation", tenderlySimLink(ctx, k.cfg, chainID, blockNum, rawCall, upkeepInfo.Target)) } else { message("did not revert with StreamsLookup error") } @@ -358,7 +358,7 @@ func (k *Keeper) Debug(ctx context.Context, args []string) { if err != nil { failUnknown("failed to pack raw simulatePerformUpkeep call", err) } - addLink("simulatePerformUpkeep simulation", tenderlySimLink(k.cfg, chainID, blockNum, rawCall, registryAddress)) + addLink("simulatePerformUpkeep simulation", tenderlySimLink(ctx, k.cfg, chainID, blockNum, rawCall, registryAddress)) if simulateResult.Success { resolveEligible() @@ -536,7 +536,7 @@ type TenderlyAPIResponse struct { } } -func tenderlySimLink(cfg *config.Config, chainID int64, blockNumber uint64, input []byte, contractAddress gethcommon.Address) string { +func tenderlySimLink(ctx context.Context, cfg *config.Config, chainID int64, blockNumber uint64, input []byte, contractAddress gethcommon.Address) string { errResult := "" if cfg.TenderlyAccountName == "" || cfg.TenderlyKey == "" || cfg.TenderlyProjectName == "" { warning("tenderly credentials not properly configured - this is optional but helpful") @@ -558,7 +558,8 @@ func tenderlySimLink(cfg *config.Config, chainID int64, blockNumber uint64, inpu warning(fmt.Sprintf("unable to marshal tenderly request data: %v", err)) return errResult } - request, err := http.NewRequest( + request, err := http.NewRequestWithContext( + ctx, "POST", fmt.Sprintf("https://api.tenderly.co/api/v1/account/%s/project/%s/simulate", cfg.TenderlyAccountName, cfg.TenderlyProjectName), bytes.NewBuffer(jsonData), diff --git a/core/scripts/chaincli/handler/handler.go b/core/scripts/chaincli/handler/handler.go index 6423df3aa23..591431555a9 100644 --- a/core/scripts/chaincli/handler/handler.go +++ b/core/scripts/chaincli/handler/handler.go @@ -399,7 +399,7 @@ func (h *baseHandler) launchChainlinkNode(ctx context.Context, port int, contain addr := fmt.Sprintf("http://localhost:%s", portStr) log.Println("Node docker container successfully created and started: ", nodeContainerResp.ID, addr) - if err = waitForNodeReady(addr); err != nil { + if err = waitForNodeReady(ctx, addr); err != nil { log.Fatal(err, nodeContainerResp.ID) } log.Println("Node ready: ", nodeContainerResp.ID) @@ -477,13 +477,13 @@ func checkAndRemoveContainer(ctx context.Context, dockerClient *client.Client, c return nil } -func waitForNodeReady(addr string) error { +func waitForNodeReady(ctx context.Context, addr string) error { client := &http.Client{} defer client.CloseIdleConnections() const timeout = 120 startTime := time.Now().Unix() for { - req, err := http.NewRequest("GET", fmt.Sprintf("%s/health", addr), nil) + req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("%s/health", addr), nil) if err != nil { return err } @@ -503,7 +503,7 @@ func waitForNodeReady(addr string) error { } // authenticate creates a http client with URL, email and password -func authenticate(urlStr, email, password string, lggr logger.Logger) (cmd.HTTPClient, error) { +func authenticate(ctx context.Context, urlStr, email, password string, lggr logger.Logger) (cmd.HTTPClient, error) { remoteNodeURL, err := url.Parse(urlStr) if err != nil { return nil, err @@ -514,7 +514,7 @@ func authenticate(urlStr, email, password string, lggr logger.Logger) (cmd.HTTPC store := &cmd.MemoryCookieStore{} tca := cmd.NewSessionCookieAuthenticator(c, store, lggr) - if _, err = tca.Authenticate(sr); err != nil { + if _, err = tca.Authenticate(ctx, sr); err != nil { log.Println("failed to authenticate: ", err) return nil, err } @@ -522,8 +522,8 @@ func authenticate(urlStr, email, password string, lggr logger.Logger) (cmd.HTTPC return cmd.NewAuthenticatedHTTPClient(lggr, c, tca, sr), nil } -func nodeRequest(client cmd.HTTPClient, path string) ([]byte, error) { - resp, err := client.Get(path) +func nodeRequest(ctx context.Context, client cmd.HTTPClient, path string) ([]byte, error) { + resp, err := client.Get(ctx, path) if err != nil { return []byte{}, fmt.Errorf("GET error from client: %w", err) } @@ -551,8 +551,8 @@ func nodeRequest(client cmd.HTTPClient, path string) ([]byte, error) { } // getNodeAddress returns chainlink node's wallet address -func getNodeAddress(client cmd.HTTPClient) (string, error) { - resp, err := nodeRequest(client, ethKeysEndpoint) +func getNodeAddress(ctx context.Context, client cmd.HTTPClient) (string, error) { + resp, err := nodeRequest(ctx, client, ethKeysEndpoint) if err != nil { return "", fmt.Errorf("failed to get ETH keys: %w", err) } @@ -566,8 +566,8 @@ func getNodeAddress(client cmd.HTTPClient) (string, error) { } // getNodeOCR2Config returns chainlink node's OCR2 bundle key ID -func getNodeOCR2Config(client cmd.HTTPClient) (*cmd.OCR2KeyBundlePresenter, error) { - resp, err := nodeRequest(client, ocr2KeysEndpoint) +func getNodeOCR2Config(ctx context.Context, client cmd.HTTPClient) (*cmd.OCR2KeyBundlePresenter, error) { + resp, err := nodeRequest(ctx, client, ocr2KeysEndpoint) if err != nil { return nil, fmt.Errorf("failed to get OCR2 keys: %w", err) } @@ -589,8 +589,8 @@ func getNodeOCR2Config(client cmd.HTTPClient) (*cmd.OCR2KeyBundlePresenter, erro } // getP2PKeyID returns chainlink node's P2P key ID -func getP2PKeyID(client cmd.HTTPClient) (string, error) { - resp, err := nodeRequest(client, p2pKeysEndpoint) +func getP2PKeyID(ctx context.Context, client cmd.HTTPClient) (string, error) { + resp, err := nodeRequest(ctx, client, p2pKeysEndpoint) if err != nil { return "", fmt.Errorf("failed to get P2P keys: %w", err) } diff --git a/core/scripts/chaincli/handler/jobs.go b/core/scripts/chaincli/handler/jobs.go index 9787d7fc175..89f1a3ea5bc 100644 --- a/core/scripts/chaincli/handler/jobs.go +++ b/core/scripts/chaincli/handler/jobs.go @@ -8,10 +8,10 @@ import ( ) func (k *Keeper) CreateJob(ctx context.Context) { - k.createJobs() + k.createJobs(ctx) } -func (k *Keeper) createJobs() { +func (k *Keeper) createJobs(ctx context.Context) { lggr, closeLggr := logger.NewLogger() logger.Sugared(lggr).ErrorIfFn(closeLggr, "Failed to close logger") @@ -27,12 +27,12 @@ func (k *Keeper) createJobs() { pwd = defaultChainlinkNodePassword } - cl, err := authenticate(url, email, pwd, lggr) + cl, err := authenticate(ctx, url, email, pwd, lggr) if err != nil { log.Fatal(err) } - if err = k.createKeeperJob(cl, k.cfg.RegistryAddress, keeperAddr); err != nil { + if err = k.createKeeperJob(ctx, cl, k.cfg.RegistryAddress, keeperAddr); err != nil { log.Fatal(err) } } diff --git a/core/scripts/chaincli/handler/keeper.go b/core/scripts/chaincli/handler/keeper.go index a5fb505adb4..1f56eb14080 100644 --- a/core/scripts/chaincli/handler/keeper.go +++ b/core/scripts/chaincli/handler/keeper.go @@ -77,13 +77,13 @@ func (k *Keeper) DeployKeepers(ctx context.Context) { pwd = defaultChainlinkNodePassword } - cl, err := authenticate(url, email, pwd, lggr) + cl, err := authenticate(ctx, url, email, pwd, lggr) if err != nil { log.Fatal(err) } cls[i] = cl - if err = k.createKeeperJob(cl, k.cfg.RegistryAddress, keeperAddr); err != nil { + if err = k.createKeeperJob(ctx, cl, k.cfg.RegistryAddress, keeperAddr); err != nil { log.Fatal(err) } } @@ -753,7 +753,8 @@ func (k *Keeper) deployUpkeeps(ctx context.Context, registryAddr common.Address, func (k *Keeper) setKeepers(ctx context.Context, cls []cmd.HTTPClient, deployer keepersDeployer, keepers, owners []common.Address) { if len(keepers) > 0 { log.Println("Set keepers...") - setKeepersTx, err := deployer.SetKeepers(k.buildTxOpts(ctx), cls, keepers, owners) + opts := k.buildTxOpts(ctx) + setKeepersTx, err := deployer.SetKeepers(ctx, opts, cls, keepers, owners) if err != nil { log.Fatal("SetKeepers failed: ", err) } diff --git a/core/scripts/chaincli/handler/keeper_deployer.go b/core/scripts/chaincli/handler/keeper_deployer.go index 7c532753426..118cbbb0ff9 100644 --- a/core/scripts/chaincli/handler/keeper_deployer.go +++ b/core/scripts/chaincli/handler/keeper_deployer.go @@ -1,6 +1,7 @@ package handler import ( + "context" "crypto/ed25519" "encoding/hex" "encoding/json" @@ -48,14 +49,14 @@ type upkeepDeployer interface { type keepersDeployer interface { canceller upkeepDeployer - SetKeepers(opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) + SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) } type v11KeeperDeployer struct { registry11.KeeperRegistryInterface } -func (d *v11KeeperDeployer) SetKeepers(opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { +func (d *v11KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { return d.KeeperRegistryInterface.SetKeepers(opts, keepers, payees) } @@ -71,7 +72,7 @@ type v12KeeperDeployer struct { registry12.KeeperRegistryInterface } -func (d *v12KeeperDeployer) SetKeepers(opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { +func (d *v12KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, _ []cmd.HTTPClient, keepers []common.Address, payees []common.Address) (*types.Transaction, error) { return d.KeeperRegistryInterface.SetKeepers(opts, keepers, payees) } @@ -88,7 +89,7 @@ type v20KeeperDeployer struct { cfg *config.Config } -func (d *v20KeeperDeployer) SetKeepers(opts *bind.TransactOpts, cls []cmd.HTTPClient, keepers []common.Address, _ []common.Address) (*types.Transaction, error) { +func (d *v20KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, cls []cmd.HTTPClient, keepers []common.Address, _ []common.Address) (*types.Transaction, error) { S := make([]int, len(cls)) oracleIdentities := make([]ocr2config.OracleIdentityExtra, len(cls)) sharedSecretEncryptionPublicKeys := make([]ocr2types.ConfigEncryptionPublicKey, len(cls)) @@ -98,12 +99,12 @@ func (d *v20KeeperDeployer) SetKeepers(opts *bind.TransactOpts, cls []cmd.HTTPCl go func(i int, cl cmd.HTTPClient) { defer wg.Done() - ocr2Config, err := getNodeOCR2Config(cl) + ocr2Config, err := getNodeOCR2Config(ctx, cl) if err != nil { panic(err) } - p2pKeyID, err := getP2PKeyID(cl) + p2pKeyID, err := getP2PKeyID(ctx, cl) if err != nil { panic(err) } @@ -228,7 +229,7 @@ type v21KeeperDeployer struct { cfg *config.Config } -func (d *v21KeeperDeployer) SetKeepers(opts *bind.TransactOpts, cls []cmd.HTTPClient, keepers []common.Address, _ []common.Address) (*types.Transaction, error) { +func (d *v21KeeperDeployer) SetKeepers(ctx context.Context, opts *bind.TransactOpts, cls []cmd.HTTPClient, keepers []common.Address, _ []common.Address) (*types.Transaction, error) { S := make([]int, len(cls)) oracleIdentities := make([]ocr2config.OracleIdentityExtra, len(cls)) sharedSecretEncryptionPublicKeys := make([]ocr2types.ConfigEncryptionPublicKey, len(cls)) @@ -238,12 +239,12 @@ func (d *v21KeeperDeployer) SetKeepers(opts *bind.TransactOpts, cls []cmd.HTTPCl go func(i int, cl cmd.HTTPClient) { defer wg.Done() - ocr2Config, err := getNodeOCR2Config(cl) + ocr2Config, err := getNodeOCR2Config(ctx, cl) if err != nil { panic(err) } - p2pKeyID, err := getP2PKeyID(cl) + p2pKeyID, err := getP2PKeyID(ctx, cl) if err != nil { panic(err) } diff --git a/core/scripts/chaincli/handler/keeper_launch.go b/core/scripts/chaincli/handler/keeper_launch.go index e8be82a4bb7..25af77f1d5c 100644 --- a/core/scripts/chaincli/handler/keeper_launch.go +++ b/core/scripts/chaincli/handler/keeper_launch.go @@ -92,7 +92,7 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, // Create authenticated client var cl cmd.HTTPClient var err error - cl, err = authenticate(startedNode.url, defaultChainlinkNodeLogin, defaultChainlinkNodePassword, lggr) + cl, err = authenticate(ctx, startedNode.url, defaultChainlinkNodeLogin, defaultChainlinkNodePassword, lggr) if err != nil { log.Fatal("Authentication failed, ", err) } @@ -101,13 +101,13 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, if len(k.cfg.KeeperKeys) > 0 { // import key if exists - nodeAddrHex, err = k.addKeyToKeeper(cl, k.cfg.KeeperKeys[i]) + nodeAddrHex, err = k.addKeyToKeeper(ctx, cl, k.cfg.KeeperKeys[i]) if err != nil { log.Fatal("could not add key to keeper", err) } } else { // get node's default wallet address - nodeAddrHex, err = getNodeAddress(cl) + nodeAddrHex, err = getNodeAddress(ctx, cl) if err != nil { log.Println("Failed to get node addr: ", err) continue @@ -117,7 +117,7 @@ func (k *Keeper) LaunchAndTest(ctx context.Context, withdraw, printLogs, force, nodeAddr := common.HexToAddress(nodeAddrHex) // Create keepers - if err = k.createKeeperJob(cl, registryAddr.Hex(), nodeAddr.Hex()); err != nil { + if err = k.createKeeperJob(ctx, cl, registryAddr.Hex(), nodeAddr.Hex()); err != nil { log.Println("Failed to create keeper job: ", err) continue } @@ -291,12 +291,12 @@ func (k *Keeper) cancelAndWithdrawUpkeeps(ctx context.Context, upkeepCount *big. } // createKeeperJob creates a keeper job in the chainlink node by the given address -func (k *Keeper) createKeeperJob(client cmd.HTTPClient, registryAddr, nodeAddr string) error { +func (k *Keeper) createKeeperJob(ctx context.Context, client cmd.HTTPClient, registryAddr, nodeAddr string) error { var err error if k.cfg.OCR2Keepers { - err = k.createOCR2KeeperJob(client, registryAddr, nodeAddr) + err = k.createOCR2KeeperJob(ctx, client, registryAddr, nodeAddr) } else { - err = k.createLegacyKeeperJob(client, registryAddr, nodeAddr) + err = k.createLegacyKeeperJob(ctx, client, registryAddr, nodeAddr) } if err != nil { return err @@ -308,7 +308,7 @@ func (k *Keeper) createKeeperJob(client cmd.HTTPClient, registryAddr, nodeAddr s } // createLegacyKeeperJob creates a legacy keeper job in the chainlink node by the given address -func (k *Keeper) createLegacyKeeperJob(client cmd.HTTPClient, registryAddr, nodeAddr string) error { +func (k *Keeper) createLegacyKeeperJob(ctx context.Context, client cmd.HTTPClient, registryAddr, nodeAddr string) error { request, err := json.Marshal(web.CreateJobRequest{ TOML: testspecs.GenerateKeeperSpec(testspecs.KeeperSpecParams{ Name: fmt.Sprintf("keeper job - registry %s", registryAddr), @@ -321,7 +321,7 @@ func (k *Keeper) createLegacyKeeperJob(client cmd.HTTPClient, registryAddr, node return fmt.Errorf("failed to marshal request: %s", err) } - resp, err := client.Post("/v2/jobs", bytes.NewReader(request)) + resp, err := client.Post(ctx, "/v2/jobs", bytes.NewReader(request)) if err != nil { return fmt.Errorf("failed to create keeper job: %s", err) } @@ -363,8 +363,8 @@ contractVersion = "%s" mercuryCredentialName = "%s"` // createOCR2KeeperJob creates an ocr2keeper job in the chainlink node by the given address -func (k *Keeper) createOCR2KeeperJob(client cmd.HTTPClient, contractAddr, nodeAddr string) error { - ocr2KeyConfig, err := getNodeOCR2Config(client) +func (k *Keeper) createOCR2KeeperJob(ctx context.Context, client cmd.HTTPClient, contractAddr, nodeAddr string) error { + ocr2KeyConfig, err := getNodeOCR2Config(ctx, client) if err != nil { return fmt.Errorf("failed to get node OCR2 key bundle ID: %s", err) } @@ -390,7 +390,7 @@ func (k *Keeper) createOCR2KeeperJob(client cmd.HTTPClient, contractAddr, nodeAd return fmt.Errorf("failed to marshal request: %s", err) } - resp, err := client.Post("/v2/jobs", bytes.NewReader(request)) + resp, err := client.Post(ctx, "/v2/jobs", bytes.NewReader(request)) if err != nil { return fmt.Errorf("failed to create ocr2keeper job: %s", err) } @@ -409,7 +409,7 @@ func (k *Keeper) createOCR2KeeperJob(client cmd.HTTPClient, contractAddr, nodeAd } // addKeyToKeeper imports the provided ETH sending key to the keeper -func (k *Keeper) addKeyToKeeper(client cmd.HTTPClient, privKeyHex string) (string, error) { +func (k *Keeper) addKeyToKeeper(ctx context.Context, client cmd.HTTPClient, privKeyHex string) (string, error) { privkey, err := crypto.HexToECDSA(hex.TrimPrefix(privKeyHex)) if err != nil { log.Fatalf("Failed to decode priv key %s: %v", privKeyHex, err) @@ -429,7 +429,7 @@ func (k *Keeper) addKeyToKeeper(client cmd.HTTPClient, privKeyHex string) (strin query.Set("evmChainID", fmt.Sprint(k.cfg.ChainID)) importUrl.RawQuery = query.Encode() - resp, err := client.Post(importUrl.String(), bytes.NewReader(keyJSON)) + resp, err := client.Post(ctx, importUrl.String(), bytes.NewReader(keyJSON)) if err != nil { log.Fatalf("Failed to import priv key %s: %v", privKeyHex, err) } diff --git a/core/scripts/chaincli/handler/scrape_node_config.go b/core/scripts/chaincli/handler/scrape_node_config.go index aaaf5d26477..6525a4794d0 100644 --- a/core/scripts/chaincli/handler/scrape_node_config.go +++ b/core/scripts/chaincli/handler/scrape_node_config.go @@ -114,7 +114,7 @@ func (h *baseHandler) scrapeNodes(ctx context.Context, log logger.Logger) { pwd = defaultChainlinkNodePassword } - cl, err := authenticate(url, email, pwd, log) + cl, err := authenticate(ctx, url, email, pwd, log) if err != nil { log.Fatal(err) } @@ -125,7 +125,7 @@ func (h *baseHandler) scrapeNodes(ctx context.Context, log logger.Logger) { var wg sync.WaitGroup for i, cl := range cls { wg.Add(1) - go h.scrapeNodeInfo(&wg, i, cl, nodes, log) + go h.scrapeNodeInfo(ctx, &wg, i, cl, nodes, log) } wg.Wait() @@ -184,8 +184,8 @@ func (h *baseHandler) fetchNodeInfosFromWeiwatchers(ctx context.Context, log log return nodeInfos } -func (h *baseHandler) fetchNodeInfosFromNodes(i int, cl cmd.HTTPClient, log logger.Logger) ([]string, *cmd.OCR2KeyBundlePresenter, string, *cmd.CSAKeyPresenters) { - resp, err := nodeRequest(cl, ethKeysEndpoint) +func (h *baseHandler) fetchNodeInfosFromNodes(ctx context.Context, i int, cl cmd.HTTPClient, log logger.Logger) ([]string, *cmd.OCR2KeyBundlePresenter, string, *cmd.CSAKeyPresenters) { + resp, err := nodeRequest(ctx, cl, ethKeysEndpoint) if err != nil { log.Fatalf("failed to get ETH keys: %s", err) } @@ -204,17 +204,17 @@ func (h *baseHandler) fetchNodeInfosFromNodes(i int, cl cmd.HTTPClient, log logg log.Warnf("%d th node has more than 1 node addresses. is this a multi-chain node? or this node used to serve another chain?", i) } - ocr2Config, err := getNodeOCR2Config(cl) + ocr2Config, err := getNodeOCR2Config(ctx, cl) if err != nil { log.Fatalf("failed to get node OCR2 config: %s", err) } - peerId, err := getP2PKeyID(cl) + peerId, err := getP2PKeyID(ctx, cl) if err != nil { log.Fatalf("failed to get p2p keys: %s", err) } - resp, err = nodeRequest(cl, csaKeysEndpoint) + resp, err = nodeRequest(ctx, cl, csaKeysEndpoint) if err != nil { log.Fatalf("failed to get CSA keys: %s", err) } @@ -232,10 +232,10 @@ func (h *baseHandler) fetchNodeInfosFromNodes(i int, cl cmd.HTTPClient, log logg return nodeAddresses, ocr2Config, peerId, &csaKeys } -func (h *baseHandler) scrapeNodeInfo(wg *sync.WaitGroup, i int, cl cmd.HTTPClient, nodes map[string]*NodeInfo, log logger.Logger) { +func (h *baseHandler) scrapeNodeInfo(ctx context.Context, wg *sync.WaitGroup, i int, cl cmd.HTTPClient, nodes map[string]*NodeInfo, log logger.Logger) { defer wg.Done() - nodeAddresses, ocr2Config, peerId, csaKeys := h.fetchNodeInfosFromNodes(i, cl, log) + nodeAddresses, ocr2Config, peerId, csaKeys := h.fetchNodeInfosFromNodes(ctx, i, cl, log) // this assumes the nodes are not multichain nodes and have only 1 node address assigned. // for a multichain node, we can pass in a chain id and filter `ethKeys` array based on the chain id diff --git a/core/services/gateway/network/httpserver_test.go b/core/services/gateway/network/httpserver_test.go index 92215245e20..dac00df2a12 100644 --- a/core/services/gateway/network/httpserver_test.go +++ b/core/services/gateway/network/httpserver_test.go @@ -47,7 +47,7 @@ func startNewServer(t *testing.T, maxRequestBytes int64, readTimeoutMillis uint3 } func sendRequest(t *testing.T, url string, body []byte) *http.Response { - req, err := http.NewRequest("POST", url, bytes.NewBuffer(body)) + req, err := http.NewRequestWithContext(testutils.Context(t), "POST", url, bytes.NewBuffer(body)) require.NoError(t, err) client := &http.Client{} resp, err := client.Do(req) diff --git a/core/services/gateway/network/wsserver_test.go b/core/services/gateway/network/wsserver_test.go index 1a4c04787b4..0b24dbe6614 100644 --- a/core/services/gateway/network/wsserver_test.go +++ b/core/services/gateway/network/wsserver_test.go @@ -49,7 +49,7 @@ func startNewWSServer(t *testing.T, readTimeoutMillis uint32) (server network.We } func sendRequestWithHeader(t *testing.T, url string, headerName string, headerValue string) *http.Response { - req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte{})) + req, err := http.NewRequestWithContext(testutils.Context(t), "POST", url, bytes.NewBuffer([]byte{})) require.NoError(t, err) req.Header.Set(headerName, headerValue) diff --git a/core/services/health_test.go b/core/services/health_test.go index 3bd0e5d39b2..b95b266ca19 100644 --- a/core/services/health_test.go +++ b/core/services/health_test.go @@ -8,6 +8,7 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services" ) @@ -20,7 +21,9 @@ func TestNewInBackupHealthReport(t *testing.T) { require.Eventually(t, func() bool { return observed.Len() >= 1 }, time.Second*5, time.Millisecond*100) require.Equal(t, "Starting InBackupHealthReport", observed.TakeAll()[0].Message) - res, err := http.Get("http://localhost:1234/health") + req, err := http.NewRequestWithContext(tests.Context(t), "GET", "http://localhost:1234/health", nil) + require.NoError(t, err) + res, err := http.DefaultClient.Do(req) require.NoError(t, err) require.Equal(t, http.StatusNoContent, res.StatusCode) diff --git a/core/services/keystore/p2p_test.go b/core/services/keystore/p2p_test.go index 4e9ca75c456..4dc44651473 100644 --- a/core/services/keystore/p2p_test.go +++ b/core/services/keystore/p2p_test.go @@ -177,6 +177,7 @@ func Test_P2PKeyStore_E2E(t *testing.T) { RETURNING *;`, p2pTableName) stmt, err := db.PrepareNamed(sql) require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, stmt.Close()) }) require.NoError(t, stmt.Get(&p2pPeer1, &p2pPeer1)) require.NoError(t, stmt.Get(&p2pPeer2, &p2pPeer2)) cltest.AssertCount(t, db, p2pTableName, 2) diff --git a/core/services/ocr/database.go b/core/services/ocr/database.go index cec9596bb91..977c371c15d 100644 --- a/core/services/ocr/database.go +++ b/core/services/ocr/database.go @@ -207,6 +207,7 @@ func (d *db) StorePendingTransmission(ctx context.Context, k ocrtypes.ReportTime } func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtypes.ConfigDigest) (map[ocrtypes.ReportTimestamp]ocrtypes.PendingTransmission, error) { + //nolint sqlclosecheck false positive rows, err := d.q.QueryContext(ctx, ` SELECT config_digest, @@ -317,6 +318,7 @@ LIMIT 1 if err != nil { return rr, errors.Wrap(err, "LoadLatestRoundRequested failed to query rows") } + defer func() { err = multierr.Combine(err, rows.Close()) }() for rows.Next() { var configDigest []byte @@ -337,7 +339,5 @@ LIMIT 1 return } - err = multierr.Combine(err, rows.Close()) - return } diff --git a/core/services/ocr2/database.go b/core/services/ocr2/database.go index 5591f33fd40..1d449047578 100644 --- a/core/services/ocr2/database.go +++ b/core/services/ocr2/database.go @@ -279,7 +279,7 @@ func (d *db) PendingTransmissionsWithConfigDigest(ctx context.Context, cd ocrtyp FROM ocr2_pending_transmissions WHERE ocr2_oracle_spec_id = $1 AND config_digest = $2 ` - rows, err := d.q.QueryxContext(ctx, stmt, d.oracleSpecID, cd) + rows, err := d.q.QueryxContext(ctx, stmt, d.oracleSpecID, cd) //nolint sqlclosecheck false positive if err != nil { return nil, errors.Wrap(err, "PendingTransmissionsWithConfigDigest failed to query rows") } diff --git a/core/services/ocr2/plugins/dkg/persistence/db_test.go b/core/services/ocr2/plugins/dkg/persistence/db_test.go index b4fa000cb99..53a5ae26758 100644 --- a/core/services/ocr2/plugins/dkg/persistence/db_test.go +++ b/core/services/ocr2/plugins/dkg/persistence/db_test.go @@ -55,6 +55,7 @@ func TestShareDB_WriteShareRecords(t *testing.T) { rows, err := db.Query(`SELECT COUNT(*) AS count FROM dkg_shares`) require.NoError(tt, err) + t.Cleanup(func() { assert.NoError(t, rows.Close()) }) var count int for rows.Next() { @@ -84,6 +85,7 @@ func TestShareDB_WriteShareRecords(t *testing.T) { rows, err := db.Query(`SELECT COUNT(*) AS count FROM dkg_shares`) require.NoError(tt, err) + t.Cleanup(func() { assert.NoError(t, rows.Close()) }) var count int for rows.Next() { @@ -122,6 +124,7 @@ func TestShareDB_WriteShareRecords(t *testing.T) { // no rows should have been inserted rows, err := db.Query(`SELECT COUNT(*) AS count FROM dkg_shares`) require.NoError(tt, err) + t.Cleanup(func() { assert.NoError(t, rows.Close()) }) var count int for rows.Next() { diff --git a/core/services/ocrcommon/discoverer_database.go b/core/services/ocrcommon/discoverer_database.go index 6468a910a65..9413b11ad07 100644 --- a/core/services/ocrcommon/discoverer_database.go +++ b/core/services/ocrcommon/discoverer_database.go @@ -39,27 +39,25 @@ updated_at = EXCLUDED.updated_at // ReadAnnouncements returns one serialized announcement (if available) for each of the peerIDs in the form of a map // keyed by each announcement's corresponding peer ID. -func (d *DiscovererDatabase) ReadAnnouncements(ctx context.Context, peerIDs []string) (map[string][]byte, error) { +func (d *DiscovererDatabase) ReadAnnouncements(ctx context.Context, peerIDs []string) (results map[string][]byte, err error) { rows, err := d.db.QueryContext(ctx, ` SELECT remote_peer_id, ann FROM ocr_discoverer_announcements WHERE remote_peer_id = ANY($1) AND local_peer_id = $2`, pq.Array(peerIDs), d.peerID) if err != nil { return nil, errors.Wrap(err, "DiscovererDatabase failed to ReadAnnouncements") } - results := make(map[string][]byte) + defer func() { err = multierr.Combine(err, rows.Close()) }() + results = make(map[string][]byte) for rows.Next() { var peerID string var ann []byte - err := rows.Scan(&peerID, &ann) + err = rows.Scan(&peerID, &ann) if err != nil { - return nil, multierr.Combine(err, rows.Close()) + return } results[peerID] = ann } - if err := rows.Err(); err != nil { - return nil, err - } - if err := rows.Close(); err != nil { - return nil, errors.WithStack(err) + if err = rows.Err(); err != nil { + return } return results, nil } diff --git a/core/services/pg/q.go b/core/services/pg/q.go index e69e16ec48f..ba2627fa745 100644 --- a/core/services/pg/q.go +++ b/core/services/pg/q.go @@ -154,6 +154,7 @@ func PrepareQueryRowx(q Queryer, sql string, dest interface{}, arg interface{}) if err != nil { return errors.Wrap(err, "error preparing named statement") } + defer stmt.Close() return errors.Wrap(stmt.QueryRowx(arg).Scan(dest), "error querying row") } diff --git a/core/services/pipeline/orm.go b/core/services/pipeline/orm.go index eb242e62765..70ff244ab3c 100644 --- a/core/services/pipeline/orm.go +++ b/core/services/pipeline/orm.go @@ -346,6 +346,7 @@ RETURNING id if errQ != nil { return errors.Wrap(errQ, "inserting finished pipeline runs") } + defer rows.Close() var runIDs []int64 for rows.Next() { diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 638977863d6..5578bdcd4ca 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -291,7 +291,7 @@ func Test_PipelineORM_StoreRun_DetectsRestarts(t *testing.T) { ds1_id := uuid.New() // insert something for this pipeline_run to trigger an early resume while the pipeline is running - _, err = db.NamedQuery(` + rows, err := db.NamedQuery(` INSERT INTO pipeline_task_runs (pipeline_run_id, id, type, index, output, error, dot_id, created_at, finished_at) VALUES (:pipeline_run_id, :id, :type, :index, :output, :error, :dot_id, :created_at, :finished_at) `, pipeline.TaskRun{ @@ -304,6 +304,7 @@ func Test_PipelineORM_StoreRun_DetectsRestarts(t *testing.T) { FinishedAt: null.TimeFrom(now), }) require.NoError(t, err) + t.Cleanup(func() { assert.NoError(t, rows.Close()) }) run.PipelineTaskRuns = []pipeline.TaskRun{ // pending task diff --git a/core/services/relay/evm/request_round_db.go b/core/services/relay/evm/request_round_db.go index 331d663918a..b3a5b01bc2c 100644 --- a/core/services/relay/evm/request_round_db.go +++ b/core/services/relay/evm/request_round_db.go @@ -61,6 +61,7 @@ LIMIT 1 if err != nil { return rr, errors.Wrap(err, "LoadLatestRoundRequested failed to query rows") } + defer rows.Close() for rows.Next() { var configDigest []byte diff --git a/core/services/webhook/delegate.go b/core/services/webhook/delegate.go index 237245b81c9..7e6aab0bb07 100644 --- a/core/services/webhook/delegate.go +++ b/core/services/webhook/delegate.go @@ -21,6 +21,7 @@ type ( webhookJobRunner *webhookJobRunner externalInitiatorManager ExternalInitiatorManager lggr logger.Logger + stopCh services.StopChan } JobRunner interface { @@ -36,6 +37,7 @@ func NewDelegate(runner pipeline.Runner, externalInitiatorManager ExternalInitia externalInitiatorManager: externalInitiatorManager, webhookJobRunner: newWebhookJobRunner(runner, lggr), lggr: lggr, + stopCh: make(services.StopChan), } } @@ -49,7 +51,9 @@ func (d *Delegate) JobType() job.Type { func (d *Delegate) BeforeJobCreated(spec job.Job) {} func (d *Delegate) AfterJobCreated(jb job.Job) { - err := d.externalInitiatorManager.Notify(*jb.WebhookSpecID) + ctx, cancel := d.stopCh.NewCtx() + defer cancel() + err := d.externalInitiatorManager.Notify(ctx, *jb.WebhookSpecID) if err != nil { d.lggr.Errorw("Webhook delegate AfterJobCreated errored", "err", err, @@ -59,7 +63,9 @@ func (d *Delegate) AfterJobCreated(jb job.Job) { } func (d *Delegate) BeforeJobDeleted(spec job.Job) { - err := d.externalInitiatorManager.DeleteJob(*spec.WebhookSpecID) + ctx, cancel := d.stopCh.NewCtx() + defer cancel() + err := d.externalInitiatorManager.DeleteJob(ctx, *spec.WebhookSpecID) if err != nil { d.lggr.Errorw("Webhook delegate OnDeleteJob errored", "err", err, diff --git a/core/services/webhook/external_initiator_manager.go b/core/services/webhook/external_initiator_manager.go index 01edf82b114..0c035abde7a 100644 --- a/core/services/webhook/external_initiator_manager.go +++ b/core/services/webhook/external_initiator_manager.go @@ -2,6 +2,7 @@ package webhook import ( "bytes" + "context" "encoding/json" "fmt" "net/http" @@ -24,8 +25,8 @@ import ( // ExternalInitiatorManager manages HTTP requests to remote external initiators type ExternalInitiatorManager interface { - Notify(webhookSpecID int32) error - DeleteJob(webhookSpecID int32) error + Notify(ctx context.Context, webhookSpecID int32) error + DeleteJob(ctx context.Context, webhookSpecID int32) error FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) } @@ -52,7 +53,7 @@ func NewExternalInitiatorManager(db *sqlx.DB, httpclient HTTPClient, lggr logger // Notify sends a POST notification to the External Initiator // responsible for initiating the Job Spec. -func (m externalInitiatorManager) Notify(webhookSpecID int32) error { +func (m externalInitiatorManager) Notify(ctx context.Context, webhookSpecID int32) error { eiWebhookSpecs, jobID, err := m.Load(webhookSpecID) if err != nil { return err @@ -71,7 +72,7 @@ func (m externalInitiatorManager) Notify(webhookSpecID int32) error { if err != nil { return errors.Wrap(err, "new Job Spec notification") } - req, err := newNotifyHTTPRequest(buf, ei) + req, err := newNotifyHTTPRequest(ctx, buf, ei) if err != nil { return errors.Wrap(err, "creating notify HTTP request") } @@ -136,7 +137,7 @@ func (m externalInitiatorManager) eagerLoadExternalInitiator(q pg.Queryer, txs [ return nil } -func (m externalInitiatorManager) DeleteJob(webhookSpecID int32) error { +func (m externalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID int32) error { eiWebhookSpecs, jobID, err := m.Load(webhookSpecID) if err != nil { return err @@ -147,7 +148,7 @@ func (m externalInitiatorManager) DeleteJob(webhookSpecID int32) error { continue } - req, err := newDeleteJobFromExternalInitiatorHTTPRequest(ei, jobID) + req, err := newDeleteJobFromExternalInitiatorHTTPRequest(ctx, ei, jobID) if err != nil { return errors.Wrap(err, "creating delete HTTP request") } @@ -178,8 +179,8 @@ type JobSpecNotice struct { Params models.JSON `json:"params,omitempty"` } -func newNotifyHTTPRequest(buf []byte, ei bridges.ExternalInitiator) (*http.Request, error) { - req, err := http.NewRequest(http.MethodPost, ei.URL.String(), bytes.NewBuffer(buf)) +func newNotifyHTTPRequest(ctx context.Context, buf []byte, ei bridges.ExternalInitiator) (*http.Request, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodPost, ei.URL.String(), bytes.NewBuffer(buf)) if err != nil { return nil, err } @@ -187,10 +188,10 @@ func newNotifyHTTPRequest(buf []byte, ei bridges.ExternalInitiator) (*http.Reque return req, nil } -func newDeleteJobFromExternalInitiatorHTTPRequest(ei bridges.ExternalInitiator, jobID uuid.UUID) (*http.Request, error) { +func newDeleteJobFromExternalInitiatorHTTPRequest(ctx context.Context, ei bridges.ExternalInitiator, jobID uuid.UUID) (*http.Request, error) { url := fmt.Sprintf("%s/%s", ei.URL.String(), jobID) - req, err := http.NewRequest(http.MethodDelete, url, nil) + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil) if err != nil { return nil, err } @@ -208,8 +209,8 @@ type NullExternalInitiatorManager struct{} var _ ExternalInitiatorManager = (*NullExternalInitiatorManager)(nil) -func (NullExternalInitiatorManager) Notify(int32) error { return nil } -func (NullExternalInitiatorManager) DeleteJob(int32) error { return nil } +func (NullExternalInitiatorManager) Notify(context.Context, int32) error { return nil } +func (NullExternalInitiatorManager) DeleteJob(context.Context, int32) error { return nil } func (NullExternalInitiatorManager) FindExternalInitiatorByName(name string) (bridges.ExternalInitiator, error) { return bridges.ExternalInitiator{}, nil } diff --git a/core/services/webhook/external_initiator_manager_test.go b/core/services/webhook/external_initiator_manager_test.go index 568008c2117..553455ebe63 100644 --- a/core/services/webhook/external_initiator_manager_test.go +++ b/core/services/webhook/external_initiator_manager_test.go @@ -12,7 +12,9 @@ import ( "github.com/stretchr/testify/require" "github.com/tidwall/gjson" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" _ "github.com/smartcontractkit/chainlink/v2/core/services/pg" @@ -57,6 +59,7 @@ func Test_ExternalInitiatorManager_Load(t *testing.T) { } func Test_ExternalInitiatorManager_Notify(t *testing.T) { + ctx := tests.Context(t) db := pgtest.NewSqlxDB(t) cfg := pgtest.NewQConfig(true) borm := newBridgeORM(t, db, cfg) @@ -78,7 +81,7 @@ func Test_ExternalInitiatorManager_Notify(t *testing.T) { eim := webhook.NewExternalInitiatorManager(db, client, logger.TestLogger(t), cfg) // Does nothing with no EI - require.NoError(t, eim.Notify(webhookSpecNoEIs.ID)) + require.NoError(t, eim.Notify(ctx, webhookSpecNoEIs.ID)) client.On("Do", mock.MatchedBy(func(r *http.Request) bool { body, err := r.GetBody() @@ -92,10 +95,11 @@ func Test_ExternalInitiatorManager_Notify(t *testing.T) { return r.Method == "POST" && r.URL.String() == eiWithURL.URL.String() && r.Header["Content-Type"][0] == "application/json" && r.Header["X-Chainlink-Ea-Accesskey"][0] == "token" && r.Header["X-Chainlink-Ea-Secret"][0] == "secret" })).Once().Return(&http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader(""))}, nil) - require.NoError(t, eim.Notify(webhookSpecTwoEIs.ID)) + require.NoError(t, eim.Notify(ctx, webhookSpecTwoEIs.ID)) } func Test_ExternalInitiatorManager_DeleteJob(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) cfg := pgtest.NewQConfig(true) borm := newBridgeORM(t, db, cfg) @@ -117,11 +121,11 @@ func Test_ExternalInitiatorManager_DeleteJob(t *testing.T) { eim := webhook.NewExternalInitiatorManager(db, client, logger.TestLogger(t), cfg) // Does nothing with no EI - require.NoError(t, eim.DeleteJob(webhookSpecNoEIs.ID)) + require.NoError(t, eim.DeleteJob(ctx, webhookSpecNoEIs.ID)) client.On("Do", mock.MatchedBy(func(r *http.Request) bool { expectedURL := fmt.Sprintf("%s/%s", eiWithURL.URL.String(), jb.ExternalJobID.String()) return r.Method == "DELETE" && r.URL.String() == expectedURL && r.Header["Content-Type"][0] == "application/json" && r.Header["X-Chainlink-Ea-Accesskey"][0] == "token" && r.Header["X-Chainlink-Ea-Secret"][0] == "secret" })).Once().Return(&http.Response{StatusCode: 200, Body: io.NopCloser(strings.NewReader(""))}, nil) - require.NoError(t, eim.DeleteJob(webhookSpecTwoEIs.ID)) + require.NoError(t, eim.DeleteJob(ctx, webhookSpecTwoEIs.ID)) } diff --git a/core/services/webhook/mocks/external_initiator_manager.go b/core/services/webhook/mocks/external_initiator_manager.go index 6c061f5412d..010b6f8db0a 100644 --- a/core/services/webhook/mocks/external_initiator_manager.go +++ b/core/services/webhook/mocks/external_initiator_manager.go @@ -3,7 +3,10 @@ package mocks import ( + context "context" + bridges "github.com/smartcontractkit/chainlink/v2/core/bridges" + mock "github.com/stretchr/testify/mock" ) @@ -12,17 +15,17 @@ type ExternalInitiatorManager struct { mock.Mock } -// DeleteJob provides a mock function with given fields: webhookSpecID -func (_m *ExternalInitiatorManager) DeleteJob(webhookSpecID int32) error { - ret := _m.Called(webhookSpecID) +// DeleteJob provides a mock function with given fields: ctx, webhookSpecID +func (_m *ExternalInitiatorManager) DeleteJob(ctx context.Context, webhookSpecID int32) error { + ret := _m.Called(ctx, webhookSpecID) if len(ret) == 0 { panic("no return value specified for DeleteJob") } var r0 error - if rf, ok := ret.Get(0).(func(int32) error); ok { - r0 = rf(webhookSpecID) + if rf, ok := ret.Get(0).(func(context.Context, int32) error); ok { + r0 = rf(ctx, webhookSpecID) } else { r0 = ret.Error(0) } @@ -58,17 +61,17 @@ func (_m *ExternalInitiatorManager) FindExternalInitiatorByName(name string) (br return r0, r1 } -// Notify provides a mock function with given fields: webhookSpecID -func (_m *ExternalInitiatorManager) Notify(webhookSpecID int32) error { - ret := _m.Called(webhookSpecID) +// Notify provides a mock function with given fields: ctx, webhookSpecID +func (_m *ExternalInitiatorManager) Notify(ctx context.Context, webhookSpecID int32) error { + ret := _m.Called(ctx, webhookSpecID) if len(ret) == 0 { panic("no return value specified for Notify") } var r0 error - if rf, ok := ret.Get(0).(func(int32) error); ok { - r0 = rf(webhookSpecID) + if rf, ok := ret.Get(0).(func(context.Context, int32) error); ok { + r0 = rf(ctx, webhookSpecID) } else { r0 = ret.Error(0) } diff --git a/core/utils/http/http_test.go b/core/utils/http/http_test.go index db7a593a8cd..7ef2f1523ab 100644 --- a/core/utils/http/http_test.go +++ b/core/utils/http/http_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/utils/http" ) @@ -20,7 +21,7 @@ func TestUnrestrictedHTTPClient(t *testing.T) { assert.True(t, client.Transport.(*netHttp.Transport).DisableCompression) client.Transport = newMockTransport() - netReq, err := netHttp.NewRequest("GET", "http://localhost", bytes.NewReader([]byte{})) + netReq, err := netHttp.NewRequestWithContext(testutils.Context(t), "GET", "http://localhost", bytes.NewReader([]byte{})) assert.NoError(t, err) req := &http.HTTPRequest{ diff --git a/core/web/auth/auth_test.go b/core/web/auth/auth_test.go index f0b4e5068fb..2ac6473ed2e 100644 --- a/core/web/auth/auth_test.go +++ b/core/web/auth/auth_test.go @@ -2,6 +2,7 @@ package auth_test import ( "fmt" + "io" "net/http" "net/http/httptest" "testing" @@ -75,7 +76,7 @@ func TestAuthenticateByToken_Success(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) req.Header.Set(webauth.APIKey, key) req.Header.Set(webauth.APISecret, secret) router.ServeHTTP(w, req) @@ -96,7 +97,7 @@ func TestAuthenticateByToken_AuthFailed(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) req.Header.Set(webauth.APIKey, "bad-key") req.Header.Set(webauth.APISecret, "bad-secret") router.ServeHTTP(w, req) @@ -122,7 +123,7 @@ func TestAuthenticateByToken_RejectsBlankAccessKey(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) req.Header.Set(webauth.APIKey, key) req.Header.Set(webauth.APISecret, secret) router.ServeHTTP(w, req) @@ -143,7 +144,7 @@ func TestRequireAuth_NoneRequired(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) router.ServeHTTP(w, req) assert.True(t, called) @@ -161,7 +162,7 @@ func TestRequireAuth_AuthFailed(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) router.ServeHTTP(w, req) assert.False(t, called) @@ -179,7 +180,7 @@ func TestRequireAuth_LastAuthSuccess(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) router.ServeHTTP(w, req) assert.True(t, called) @@ -197,7 +198,7 @@ func TestRequireAuth_Error(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) router.ServeHTTP(w, req) assert.False(t, called) @@ -504,3 +505,10 @@ func TestRBAC_Routemap_ViewOnly(t *testing.T) { }) } } + +func mustRequest(t *testing.T, method, url string, body io.Reader) *http.Request { + ctx := testutils.Context(t) + req, err := http.NewRequestWithContext(ctx, method, url, body) + require.NoError(t, err) + return req +} diff --git a/core/web/auth/gql_test.go b/core/web/auth/gql_test.go index 4f3f8e27baf..f3d085c71f8 100644 --- a/core/web/auth/gql_test.go +++ b/core/web/auth/gql_test.go @@ -37,7 +37,7 @@ func Test_AuthenticateGQL_Unauthenticated(t *testing.T) { }) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) r.ServeHTTP(w, req) } @@ -63,7 +63,7 @@ func Test_AuthenticateGQL_Authenticated(t *testing.T) { sessionORM.On("AuthorizedUserWithSession", sessionID).Return(clsessions.User{Email: cltest.APIEmailAdmin, Role: clsessions.UserRoleAdmin}, nil) w := httptest.NewRecorder() - req, _ := http.NewRequest("GET", "/", nil) + req := mustRequest(t, "GET", "/", nil) cookie := cltest.MustGenerateSessionCookie(t, sessionID) req.AddCookie(cookie) diff --git a/core/web/build_info_controller_test.go b/core/web/build_info_controller_test.go index e2d2cb0e631..5a2b88fa0dc 100644 --- a/core/web/build_info_controller_test.go +++ b/core/web/build_info_controller_test.go @@ -32,12 +32,15 @@ func TestBuildInfoController_Show_APICredentials(t *testing.T) { func TestBuildInfoController_Show_NoCredentials(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := clhttptest.NewTestLocalOnlyHTTPClient() url := app.Server.URL + "/v2/build_info" - resp, err := client.Get(url) + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + require.NoError(t, err) + resp, err := client.Do(req) require.NoError(t, err) require.Equal(t, http.StatusUnauthorized, resp.StatusCode) } diff --git a/core/web/gui_assets_test.go b/core/web/gui_assets_test.go index 137b1231984..810aa40ca05 100644 --- a/core/web/gui_assets_test.go +++ b/core/web/gui_assets_test.go @@ -44,7 +44,9 @@ func TestGuiAssets_DefaultIndexHtml_OK(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - resp, err := client.Get(app.Server.URL + tc.path) + req, err := http.NewRequestWithContext(testutils.Context(t), "GET", app.Server.URL+tc.path, nil) + require.NoError(t, err) + resp, err := client.Do(req) require.NoError(t, err) cltest.AssertServerResponse(t, resp, http.StatusOK) }) @@ -75,7 +77,9 @@ func TestGuiAssets_DefaultIndexHtml_NotFound(t *testing.T) { t.Run(tc.name, func(t *testing.T) { t.Parallel() - resp, err := client.Get(app.Server.URL + tc.path) + req, err := http.NewRequestWithContext(testutils.Context(t), "GET", app.Server.URL+tc.path, nil) + require.NoError(t, err) + resp, err := client.Do(req) require.NoError(t, err) cltest.AssertServerResponse(t, resp, http.StatusNotFound) }) @@ -94,13 +98,17 @@ func TestGuiAssets_DefaultIndexHtml_RateLimited(t *testing.T) { // Make calls equal to the rate limit rateLimit := 20 for i := 0; i < rateLimit; i++ { - resp, err := client.Get(app.Server.URL + "/") + req, err := http.NewRequestWithContext(testutils.Context(t), "GET", app.Server.URL+"/", nil) + require.NoError(t, err) + resp, err := client.Do(req) require.NoError(t, err) cltest.AssertServerResponse(t, resp, http.StatusOK) } // Last request fails - resp, err := client.Get(app.Server.URL + "/") + req, err := http.NewRequestWithContext(testutils.Context(t), "GET", app.Server.URL+"/", nil) + require.NoError(t, err) + resp, err := client.Do(req) require.NoError(t, err) assert.Equal(t, http.StatusTooManyRequests, resp.StatusCode) } @@ -115,7 +123,7 @@ func TestGuiAssets_AssetsFS(t *testing.T) { recorder := httptest.NewRecorder() c, _ := gin.CreateTestContext(recorder) var err error - c.Request, err = http.NewRequest("GET", "http://localhost:6688/fixtures/operator_ui/assets/main.js", nil) + c.Request, err = http.NewRequestWithContext(c, "GET", "http://localhost:6688/fixtures/operator_ui/assets/main.js", nil) require.NoError(t, err) handler(c) @@ -123,7 +131,7 @@ func TestGuiAssets_AssetsFS(t *testing.T) { recorder = httptest.NewRecorder() c, _ = gin.CreateTestContext(recorder) - c.Request, err = http.NewRequest("GET", "http://localhost:6688/fixtures/operator_ui/assets/kinda_main.js", nil) + c.Request, err = http.NewRequestWithContext(c, "GET", "http://localhost:6688/fixtures/operator_ui/assets/kinda_main.js", nil) require.NoError(t, err) handler(c) @@ -134,7 +142,7 @@ func TestGuiAssets_AssetsFS(t *testing.T) { recorder := httptest.NewRecorder() c, _ := gin.CreateTestContext(recorder) var err error - c.Request, err = http.NewRequest("GET", "http://localhost:6688/fixtures/operator_ui/assets/main.js", nil) + c.Request, err = http.NewRequestWithContext(c, "GET", "http://localhost:6688/fixtures/operator_ui/assets/main.js", nil) require.NoError(t, err) c.Request.Header.Set("Accept-Encoding", "gzip") handler(c) @@ -144,7 +152,7 @@ func TestGuiAssets_AssetsFS(t *testing.T) { recorder = httptest.NewRecorder() c, _ = gin.CreateTestContext(recorder) - c.Request, err = http.NewRequest("GET", "http://localhost:6688/fixtures/operator_ui/assets/kinda_main.js", nil) + c.Request, err = http.NewRequestWithContext(c, "GET", "http://localhost:6688/fixtures/operator_ui/assets/kinda_main.js", nil) require.NoError(t, err) c.Request.Header.Set("Accept-Encoding", "gzip") handler(c) diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 83c4fc30db0..eec58c30571 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -600,6 +600,7 @@ func TestJobsController_Update_HappyPath(t *testing.T) { } func TestJobsController_Update_NonExistentID(t *testing.T) { + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.OCR.Enabled = ptr(true) c.P2P.V2.Enabled = ptr(true) @@ -609,7 +610,7 @@ func TestJobsController_Update_NonExistentID(t *testing.T) { app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}, app.GetConfig().Database()) _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}, app.GetConfig().Database()) @@ -629,7 +630,7 @@ func TestJobsController_Update_NonExistentID(t *testing.T) { require.NoError(t, err) jb.OCROracleSpec = &ocrSpec jb.OCROracleSpec.TransmitterAddress = &app.Keys[0].EIP55Address - err = app.AddJobV2(testutils.Context(t), &jb) + err = app.AddJobV2(ctx, &jb) require.NoError(t, err) // test Calling update on the job id with changed values should succeed. @@ -712,6 +713,7 @@ func setupEthClientForControllerTests(t *testing.T) *evmclimocks.Client { } func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication, cltest.HTTPClientCleaner, job.Job, int32, job.Job, int32) { + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.OCR.Enabled = ptr(true) c.P2P.V2.Enabled = ptr(true) @@ -721,7 +723,7 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}, app.GetConfig().Database()) _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}, app.GetConfig().Database()) @@ -737,7 +739,7 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication require.NoError(t, err) jb.OCROracleSpec = &ocrSpec jb.OCROracleSpec.TransmitterAddress = &app.Keys[0].EIP55Address - err = app.AddJobV2(testutils.Context(t), &jb) + err = app.AddJobV2(ctx, &jb) require.NoError(t, err) drSpec := fmt.Sprintf(` @@ -758,7 +760,7 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication erejb, err := directrequest.ValidatedDirectRequestSpec(drSpec) require.NoError(t, err) - err = app.AddJobV2(testutils.Context(t), &erejb) + err = app.AddJobV2(ctx, &erejb) require.NoError(t, err) return app, client, jb, jb.ID, erejb, erejb.ID diff --git a/core/web/log_controller_test.go b/core/web/log_controller_test.go index dbb95361b98..28c54b72450 100644 --- a/core/web/log_controller_test.go +++ b/core/web/log_controller_test.go @@ -43,8 +43,8 @@ func TestLogController_GetLogConfig(t *testing.T) { client := app.NewHTTPClient(nil) - resp, err := client.HTTPClient.Get("/v2/log") - require.NoError(t, err) + resp, clean := client.Get("/v2/log") + t.Cleanup(clean) svcLogConfig := presenters.ServiceLogConfigResource{} cltest.AssertServerResponse(t, resp, http.StatusOK) diff --git a/core/web/ping_controller_test.go b/core/web/ping_controller_test.go index 8e1862cd8c7..aa528ced534 100644 --- a/core/web/ping_controller_test.go +++ b/core/web/ping_controller_test.go @@ -55,7 +55,7 @@ func TestPingController_Show_ExternalInitiatorCredentials(t *testing.T) { require.NoError(t, err) url := app.Server.URL + "/v2/ping" - request, err := http.NewRequest("GET", url, nil) + request, err := http.NewRequestWithContext(testutils.Context(t), "GET", url, nil) require.NoError(t, err) request.Header.Set("Content-Type", web.MediaType) request.Header.Set("X-Chainlink-EA-AccessKey", eia.AccessKey) @@ -74,12 +74,15 @@ func TestPingController_Show_ExternalInitiatorCredentials(t *testing.T) { func TestPingController_Show_NoCredentials(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := clhttptest.NewTestLocalOnlyHTTPClient() url := app.Server.URL + "/v2/ping" - resp, err := client.Get(url) + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + require.NoError(t, err) + resp, err := client.Do(req) require.NoError(t, err) require.Equal(t, http.StatusUnauthorized, resp.StatusCode) } diff --git a/core/web/router_test.go b/core/web/router_test.go index 18177a1ac28..bb371318468 100644 --- a/core/web/router_test.go +++ b/core/web/router_test.go @@ -20,14 +20,18 @@ import ( ) func TestTokenAuthRequired_NoCredentials(t *testing.T) { + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) router := web.Router(t, app, nil) ts := httptest.NewServer(router) defer ts.Close() - resp, err := http.Post(ts.URL+"/v2/jobs/", web.MediaType, bytes.NewBufferString("{}")) + req, err := http.NewRequestWithContext(ctx, "POST", ts.URL+"/v2/jobs/", bytes.NewBufferString("{}")) + require.NoError(t, err) + req.Header.Set("Content-Type", web.MediaType) + resp, err := http.DefaultClient.Do(req) require.NoError(t, err) assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) @@ -49,8 +53,9 @@ func TestTokenAuthRequired_SessionCredentials(t *testing.T) { } func TestTokenAuthRequired_TokenCredentials(t *testing.T) { + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) router := web.Router(t, app, nil) ts := httptest.NewServer(router) @@ -67,7 +72,7 @@ func TestTokenAuthRequired_TokenCredentials(t *testing.T) { err = app.BridgeORM().CreateExternalInitiator(ea) require.NoError(t, err) - request, err := http.NewRequest("GET", ts.URL+"/v2/ping/", bytes.NewBufferString("{}")) + request, err := http.NewRequestWithContext(ctx, "GET", ts.URL+"/v2/ping/", bytes.NewBufferString("{}")) require.NoError(t, err) request.Header.Set("Content-Type", web.MediaType) request.Header.Set("X-Chainlink-EA-AccessKey", eia.AccessKey) @@ -81,8 +86,9 @@ func TestTokenAuthRequired_TokenCredentials(t *testing.T) { } func TestTokenAuthRequired_BadTokenCredentials(t *testing.T) { + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) router := web.Router(t, app, nil) ts := httptest.NewServer(router) @@ -99,7 +105,7 @@ func TestTokenAuthRequired_BadTokenCredentials(t *testing.T) { err = app.BridgeORM().CreateExternalInitiator(ea) require.NoError(t, err) - request, err := http.NewRequest("GET", ts.URL+"/v2/ping/", bytes.NewBufferString("{}")) + request, err := http.NewRequestWithContext(ctx, "GET", ts.URL+"/v2/ping/", bytes.NewBufferString("{}")) require.NoError(t, err) request.Header.Set("Content-Type", web.MediaType) request.Header.Set("X-Chainlink-EA-AccessKey", eia.AccessKey) @@ -113,8 +119,9 @@ func TestTokenAuthRequired_BadTokenCredentials(t *testing.T) { } func TestSessions_RateLimited(t *testing.T) { + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) router := web.Router(t, app, nil) ts := httptest.NewServer(router) @@ -124,7 +131,7 @@ func TestSessions_RateLimited(t *testing.T) { input := `{"email":"brute@force.com", "password": "wrongpassword"}` for i := 0; i < 5; i++ { - request, err := http.NewRequest("POST", ts.URL+"/sessions", bytes.NewBufferString(input)) + request, err := http.NewRequestWithContext(ctx, "POST", ts.URL+"/sessions", bytes.NewBufferString(input)) require.NoError(t, err) resp, err := client.Do(request) @@ -132,7 +139,7 @@ func TestSessions_RateLimited(t *testing.T) { assert.Equal(t, http.StatusUnauthorized, resp.StatusCode) } - request, err := http.NewRequest("POST", ts.URL+"/sessions", bytes.NewBufferString(input)) + request, err := http.NewRequestWithContext(ctx, "POST", ts.URL+"/sessions", bytes.NewBufferString(input)) require.NoError(t, err) resp, err := client.Do(request) @@ -141,8 +148,9 @@ func TestSessions_RateLimited(t *testing.T) { } func TestRouter_LargePOSTBody(t *testing.T) { + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) router := web.Router(t, app, nil) ts := httptest.NewServer(router) @@ -151,7 +159,7 @@ func TestRouter_LargePOSTBody(t *testing.T) { client := clhttptest.NewTestLocalOnlyHTTPClient() body := string(make([]byte, 70000)) - request, err := http.NewRequest("POST", ts.URL+"/sessions", bytes.NewBufferString(body)) + request, err := http.NewRequestWithContext(ctx, "POST", ts.URL+"/sessions", bytes.NewBufferString(body)) require.NoError(t, err) resp, err := client.Do(request) @@ -160,13 +168,16 @@ func TestRouter_LargePOSTBody(t *testing.T) { } func TestRouter_GinHelmetHeaders(t *testing.T) { + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) router := web.Router(t, app, nil) ts := httptest.NewServer(router) defer ts.Close() - res, err := http.Get(ts.URL) + req, err := http.NewRequestWithContext(ctx, "GET", ts.URL, nil) + require.NoError(t, err) + res, err := http.DefaultClient.Do(req) require.NoError(t, err) for _, tt := range []struct { HelmetName string diff --git a/core/web/sessions_controller_test.go b/core/web/sessions_controller_test.go index c2950caf3d1..9f883ef54b8 100644 --- a/core/web/sessions_controller_test.go +++ b/core/web/sessions_controller_test.go @@ -22,6 +22,7 @@ import ( func TestSessionsController_Create(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) @@ -44,7 +45,7 @@ func TestSessionsController_Create(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { body := fmt.Sprintf(`{"email":"%s","password":"%s"}`, test.email, test.password) - request, err := http.NewRequest("POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) + request, err := http.NewRequestWithContext(ctx, "POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) assert.NoError(t, err) resp, err := client.Do(request) assert.NoError(t, err) @@ -86,8 +87,9 @@ func mustInsertSession(t *testing.T, q pg.Q, session *sessions.Session) { func TestSessionsController_Create_ReapSessions(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) user := cltest.MustRandomUser(t) require.NoError(t, app.AuthenticationProvider().CreateUser(&user)) @@ -99,7 +101,10 @@ func TestSessionsController_Create_ReapSessions(t *testing.T) { mustInsertSession(t, q, &staleSession) body := fmt.Sprintf(`{"email":"%s","password":"%s"}`, user.Email, cltest.Password) - resp, err := http.Post(app.Server.URL+"/sessions", "application/json", bytes.NewBufferString(body)) + req, err := http.NewRequestWithContext(ctx, "POST", app.Server.URL+"/sessions", bytes.NewBufferString(body)) + assert.NoError(t, err) + req.Header.Set("Content-Type", "application/json") + resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) defer func() { assert.NoError(t, resp.Body.Close()) }() @@ -119,6 +124,7 @@ func TestSessionsController_Create_ReapSessions(t *testing.T) { func TestSessionsController_Destroy(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) @@ -143,7 +149,7 @@ func TestSessionsController_Destroy(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { cookie := cltest.MustGenerateSessionCookie(t, test.sessionID) - request, err := http.NewRequest("DELETE", app.Server.URL+"/sessions", nil) + request, err := http.NewRequestWithContext(ctx, "DELETE", app.Server.URL+"/sessions", nil) assert.NoError(t, err) request.AddCookie(cookie) @@ -163,6 +169,7 @@ func TestSessionsController_Destroy(t *testing.T) { func TestSessionsController_Destroy_ReapSessions(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) client := clhttptest.NewTestLocalOnlyHTTPClient() app := cltest.NewApplicationEVMDisabled(t) @@ -183,7 +190,7 @@ func TestSessionsController_Destroy_ReapSessions(t *testing.T) { staleSession.LastUsed = time.Now().Add(-cltest.MustParseDuration(t, "241h")) mustInsertSession(t, q, &staleSession) - request, err := http.NewRequest("DELETE", app.Server.URL+"/sessions", nil) + request, err := http.NewRequestWithContext(ctx, "DELETE", app.Server.URL+"/sessions", nil) assert.NoError(t, err) request.AddCookie(cookie) diff --git a/revive.toml b/revive.toml deleted file mode 100644 index daa62cd5487..00000000000 --- a/revive.toml +++ /dev/null @@ -1,53 +0,0 @@ -ignoreGeneratedHeader = false -severity = "warning" -confidence = 0.8 -errorCode = 0 -warningCode = 0 - -[rule.blank-imports] -[rule.context-as-argument] -[rule.context-keys-type] -[rule.dot-imports] -[rule.error-return] -[rule.error-strings] -[rule.error-naming] -[rule.exported] -Disabled = true -[rule.if-return] -[rule.increment-decrement] -[rule.var-naming] -Disabled = true -[rule.var-declaration] -[rule.package-comments] -[rule.range] -[rule.receiver-naming] -[rule.time-naming] -[rule.unexported-return] -Disabled = true -[rule.indent-error-flow] -[rule.errorf] -[rule.empty-block] -[rule.superfluous-else] -[rule.unused-parameter] -Disabled = true -[rule.unreachable-code] -[rule.redefines-builtin-id] -[rule.waitgroup-by-value] -[rule.unconditional-recursion] -[rule.struct-tag] -# [rule.string-format] -[rule.string-of-int] -# [rule.range-val-address] -[rule.range-val-in-closure] -[rule.modifies-value-receiver] -[rule.modifies-parameter] -[rule.identical-branches] -[rule.get-return] -# [rule.flag-parameter] -# [rule.early-return] -[rule.defer] -[rule.constant-logical-expr] -# [rule.confusing-naming] -# [rule.confusing-results] -[rule.bool-literal-in-expr] -[rule.atomic] diff --git a/tools/flakeytests/cmd/runner/main.go b/tools/flakeytests/cmd/runner/main.go index f38179f502b..0f36ab25ef9 100644 --- a/tools/flakeytests/cmd/runner/main.go +++ b/tools/flakeytests/cmd/runner/main.go @@ -1,10 +1,12 @@ package main import ( + "context" "flag" "io" "log" "os" + "os/signal" "strings" "github.com/smartcontractkit/chainlink/v2/tools/flakeytests" @@ -13,6 +15,13 @@ import ( const numReruns = 2 func main() { + ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt) + go func() { + <-ctx.Done() + stop() // restore default exit behavior + log.Println("Cancelling... interrupt again to exit") + }() + grafanaHost := flag.String("grafana_host", "", "grafana host URL") grafanaAuth := flag.String("grafana_auth", "", "grafana basic auth for Loki API") command := flag.String("command", "", "test command being rerun; used to tag metrics") @@ -48,10 +57,10 @@ func main() { readers = append(readers, r) } - ctx := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID) - rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *command, ctx) + meta := flakeytests.GetGithubMetadata(*ghRepo, *ghEventName, *ghSHA, *ghEventPath, *ghRunID) + rep := flakeytests.NewLokiReporter(*grafanaHost, *grafanaAuth, *command, meta) r := flakeytests.NewRunner(readers, rep, numReruns) - err := r.Run() + err := r.Run(ctx) if err != nil { log.Fatalf("Error re-running flakey tests: %s", err) } diff --git a/tools/flakeytests/reporter.go b/tools/flakeytests/reporter.go index f17a44ef9f1..b7c7f66698f 100644 --- a/tools/flakeytests/reporter.go +++ b/tools/flakeytests/reporter.go @@ -2,6 +2,7 @@ package flakeytests import ( "bytes" + "context" "encoding/base64" "encoding/json" "fmt" @@ -138,14 +139,14 @@ func (l *LokiReporter) createRequest(report *Report) (pushRequest, error) { return pr, nil } -func (l *LokiReporter) makeRequest(pushReq pushRequest) error { +func (l *LokiReporter) makeRequest(ctx context.Context, pushReq pushRequest) error { body, err := json.Marshal(pushReq) if err != nil { return err } u := url.URL{Scheme: "https", Host: l.host, Path: "loki/api/v1/push"} - req, err := http.NewRequest("POST", u.String(), bytes.NewReader(body)) + req, err := http.NewRequestWithContext(ctx, "POST", u.String(), bytes.NewReader(body)) if err != nil { return err } @@ -167,13 +168,13 @@ func (l *LokiReporter) makeRequest(pushReq pushRequest) error { return err } -func (l *LokiReporter) Report(report *Report) error { +func (l *LokiReporter) Report(ctx context.Context, report *Report) error { pushReq, err := l.createRequest(report) if err != nil { return err } - return l.makeRequest(pushReq) + return l.makeRequest(ctx, pushReq) } func NewLokiReporter(host, auth, command string, ctx Context) *LokiReporter { diff --git a/tools/flakeytests/runner.go b/tools/flakeytests/runner.go index 97402633f38..88ab647e7c1 100644 --- a/tools/flakeytests/runner.go +++ b/tools/flakeytests/runner.go @@ -3,6 +3,7 @@ package flakeytests import ( "bufio" "bytes" + "context" "encoding/json" "errors" "fmt" @@ -33,7 +34,7 @@ type tester interface { } type reporter interface { - Report(r *Report) error + Report(ctx context.Context, r *Report) error } type parseFn func(readers ...io.Reader) (*Report, error) @@ -297,7 +298,7 @@ func dedupeEntries(report *Report) (*Report, error) { return out, nil } -func (r *Runner) Run() error { +func (r *Runner) Run(ctx context.Context) error { parseReport, err := r.parse(r.readers...) if err != nil { return err @@ -323,5 +324,5 @@ func (r *Runner) Run() error { return err } - return r.reporter.Report(report) + return r.reporter.Report(ctx, report) } diff --git a/tools/flakeytests/runner_test.go b/tools/flakeytests/runner_test.go index 64e2a6c968a..ee069a1655d 100644 --- a/tools/flakeytests/runner_test.go +++ b/tools/flakeytests/runner_test.go @@ -1,6 +1,7 @@ package flakeytests import ( + "context" "io" "os" "os/exec" @@ -9,13 +10,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" ) type mockReporter struct { report *Report } -func (m *mockReporter) Report(report *Report) error { +func (m *mockReporter) Report(_ context.Context, report *Report) error { m.report = report return nil } @@ -120,7 +123,7 @@ func TestRunner_WithFlake(t *testing.T) { // This will report a flake since we've mocked the rerun // to only report one failure (not two as expected). - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) assert.Len(t, m.report.tests, 1) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] @@ -155,7 +158,7 @@ func TestRunner_WithFailedPackage(t *testing.T) { // This will report a flake since we've mocked the rerun // to only report one failure (not two as expected). - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) assert.Len(t, m.report.tests, 1) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] @@ -181,7 +184,7 @@ func TestRunner_AllFailures(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) assert.Len(t, m.report.tests, 0) } @@ -207,7 +210,7 @@ func TestRunner_RerunSuccessful(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) @@ -229,7 +232,7 @@ func TestRunner_RootLevelTest(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/"]["TestConfigDocs"] assert.True(t, ok) @@ -256,7 +259,7 @@ func TestRunner_RerunFailsWithNonzeroExitCode(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets"]["TestLink"] assert.True(t, ok) @@ -293,7 +296,7 @@ func TestRunner_RerunWithNonZeroExitCodeDoesntStopCommand(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) calls := index assert.Equal(t, 4, calls) @@ -366,7 +369,7 @@ func TestIntegration_DealsWithSubtests(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) expectedTests := map[string]map[string]int{ "github.com/smartcontractkit/chainlink/v2/tools/flakeytests/": { @@ -402,7 +405,7 @@ func TestIntegration_ParsesPanics(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/tools/flakeytests"]["TestSkippedForTests"] assert.False(t, ok) @@ -433,7 +436,7 @@ func TestIntegration(t *testing.T) { reporter: m, } - err := r.Run() + err := r.Run(tests.Context(t)) require.NoError(t, err) _, ok := m.report.tests["github.com/smartcontractkit/chainlink/v2/tools/flakeytests"]["TestSkippedForTests_Success"] assert.False(t, ok)