From e0dccdeaea942746c533a0358f0de0300a19a6b5 Mon Sep 17 00:00:00 2001 From: AnieeG Date: Fri, 27 Sep 2024 15:40:13 -0700 Subject: [PATCH 1/5] env changes --- .../deployment/ccip/add_chain_test.go | 8 +- .../deployment/ccip/add_lane_test.go | 2 +- .../ccip/changeset/2_initial_deploy_test.go | 6 +- .../deployment/ccip/test_helpers.go | 134 +++-- integration-tests/deployment/devenv/don.go | 48 +- integration-tests/deployment/devenv/jd.go | 44 +- .../deployment/memory/job_client.go | 9 + integration-tests/smoke/ccip_test.go | 59 +- integration-tests/web/sdk/client/client.go | 64 +- .../web/sdk/internal/generated/generated.go | 555 +++++++++++++++++- .../web/sdk/internal/genqlient.graphql | 40 +- 11 files changed, 834 insertions(+), 135 deletions(-) diff --git a/integration-tests/deployment/ccip/add_chain_test.go b/integration-tests/deployment/ccip/add_chain_test.go index dbe86b85368..fc39bddcd93 100644 --- a/integration-tests/deployment/ccip/add_chain_test.go +++ b/integration-tests/deployment/ccip/add_chain_test.go @@ -24,8 +24,7 @@ import ( func TestAddChainInbound(t *testing.T) { // 4 chains where the 4th is added after initial deployment. - e := NewEnvironmentWithCRAndJobs(t, logger.TestLogger(t), 4) - require.Equal(t, len(e.Nodes), 5) + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 4) state, err := LoadOnchainState(e.Env, e.Ab) require.NoError(t, err) // Take first non-home chain as the new chain. @@ -127,6 +126,9 @@ func TestAddChainInbound(t *testing.T) { ExecuteProposal(t, e.Env, chainInboundExec, state, sel) } + replayBlocks, err := LatestBlocksByChain(testcontext.Get(t), e.Env.Chains) + require.NoError(t, err) + // Now configure the new chain using deployer key (not transferred to timelock yet). var offRampEnables []offramp.OffRampSourceChainConfigArgs for _, source := range initialDeploy { @@ -167,7 +169,7 @@ func TestAddChainInbound(t *testing.T) { } // Ensure job related logs are up to date. time.Sleep(30 * time.Second) - require.NoError(t, ReplayAllLogs(e.Nodes, e.Env.Chains)) + ReplayLogs(t, e.Env.Offchain, replayBlocks) // TODO: Send via all inbound lanes and use parallel helper // Now that the proposal has been executed we expect to be able to send traffic to this new 4th chain. diff --git a/integration-tests/deployment/ccip/add_lane_test.go b/integration-tests/deployment/ccip/add_lane_test.go index 3da74ec11a8..540b5dded54 100644 --- a/integration-tests/deployment/ccip/add_lane_test.go +++ b/integration-tests/deployment/ccip/add_lane_test.go @@ -16,7 +16,7 @@ func TestAddLane(t *testing.T) { // TODO: The offchain code doesn't yet support partial lane // enablement, need to address then re-enable this test. t.Skip() - e := NewEnvironmentWithCRAndJobs(t, logger.TestLogger(t), 3) + e := NewMemoryEnvironmentWithJobs(t, logger.TestLogger(t), 3) // Here we have CR + nodes set up, but no CCIP contracts deployed. state, err := LoadOnchainState(e.Env, e.Ab) require.NoError(t, err) diff --git a/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go b/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go index 8dc363b0cbb..5744dfbea95 100644 --- a/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go +++ b/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go @@ -20,10 +20,8 @@ import ( func Test0002_InitialDeploy(t *testing.T) { lggr := logger.TestLogger(t) ctx := ccdeploy.Context(t) - tenv := ccdeploy.NewEnvironmentWithCRAndFeeds(t, lggr, 3) + tenv := ccdeploy.NewMemoryEnvironment(t, lggr, 3) e := tenv.Env - nodes := tenv.Nodes - chains := e.Chains state, err := ccdeploy.LoadOnchainState(tenv.Env, tenv.Ab) require.NoError(t, err) @@ -52,7 +50,7 @@ func Test0002_InitialDeploy(t *testing.T) { require.NoError(t, err) // Ensure capreg logs are up to date. - require.NoError(t, ccdeploy.ReplayAllLogs(nodes, chains)) + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) // Apply the jobs. for nodeID, jobs := range output.JobSpecs { diff --git a/integration-tests/deployment/ccip/test_helpers.go b/integration-tests/deployment/ccip/test_helpers.go index c306ba4fd6a..c9ced060e2b 100644 --- a/integration-tests/deployment/ccip/test_helpers.go +++ b/integration-tests/deployment/ccip/test_helpers.go @@ -9,6 +9,7 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/pkg/errors" "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" @@ -64,11 +65,43 @@ type DeployedEnv struct { Env deployment.Environment HomeChainSel uint64 FeedChainSel uint64 + ReplayBlocks map[uint64]uint64 } -type DeployedTestEnvironment struct { - DeployedEnv - Nodes map[string]memory.Node +func (e *DeployedEnv) SetupJobs(t *testing.T) { + ctx := testcontext.Get(t) + jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) + require.NoError(t, err) + for nodeID, jobs := range jbs { + for _, job := range jobs { + // Note these auto-accept + _, err := e.Env.Offchain.ProposeJob(ctx, + &jobv1.ProposeJobRequest{ + NodeId: nodeID, + Spec: job, + }) + require.NoError(t, err) + } + } + // Wait for plugins to register filters? + // TODO: Investigate how to avoid. + time.Sleep(30 * time.Second) + ReplayLogs(t, e.Env.Offchain, e.ReplayBlocks) +} + +func ReplayLogs(t *testing.T, oc deployment.OffchainClient, replayBlocks map[uint64]uint64) { + switch oc.(type) { + case *memory.JobClient: + jobclient, ok := oc.(*memory.JobClient) + require.True(t, ok) + require.NoError(t, jobclient.ReplayLogs(replayBlocks)) + case *devenv.JobDistributor: + jobclient, ok := oc.(*devenv.JobDistributor) + require.True(t, ok) + require.NoError(t, jobclient.ReplayLogs(replayBlocks)) + default: + t.Fatalf("unsupported offchain client type %T", oc) + } } func SetUpHomeAndFeedChains(t *testing.T, lggr logger.Logger, homeChainSel, feedChainSel uint64, chains map[uint64]deployment.Chain) (deployment.AddressBook, deployment.CapabilityRegistryConfig) { @@ -85,11 +118,24 @@ func SetUpHomeAndFeedChains(t *testing.T, lggr logger.Logger, homeChainSel, feed } } -// NewEnvironmentWithCRAndFeeds creates a new CCIP environment +func LatestBlocksByChain(ctx context.Context, chains map[uint64]deployment.Chain) (map[uint64]uint64, error) { + latestBlocks := make(map[uint64]uint64) + for _, chain := range chains { + latesthdr, err := chain.Client.HeaderByNumber(ctx, nil) + if err != nil { + return nil, errors.Wrapf(err, "failed to get latest header for chain %d", chain.Selector) + } + block := latesthdr.Number.Uint64() + latestBlocks[chain.Selector] = block + } + return latestBlocks, nil +} + +// NewMemoryEnvironment creates a new CCIP environment // with capreg, feeds and nodes set up. -func NewEnvironmentWithCRAndFeeds(t *testing.T, lggr logger.Logger, numChains int) DeployedTestEnvironment { +func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, numChains int) DeployedEnv { require.GreaterOrEqual(t, numChains, 2, "numChains must be at least 2 for home and feed chains") - ctx := Context(t) + ctx := testcontext.Get(t) chains := memory.NewMemoryChains(t, numChains) // Lower chainSel is home chain. var chainSels []uint64 @@ -103,6 +149,8 @@ func NewEnvironmentWithCRAndFeeds(t *testing.T, lggr logger.Logger, numChains in // Take lowest for determinism. homeChainSel := chainSels[HomeChainIndex] feedSel := chainSels[FeedChainIndex] + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) ab, capReg := SetUpHomeAndFeedChains(t, lggr, homeChainSel, feedSel, chains) nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, 4, 1, capReg) @@ -114,55 +162,21 @@ func NewEnvironmentWithCRAndFeeds(t *testing.T, lggr logger.Logger, numChains in } e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) - return DeployedTestEnvironment{ - DeployedEnv: DeployedEnv{ - Ab: ab, - Env: e, - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - }, - Nodes: nodes, + return DeployedEnv{ + Ab: ab, + Env: e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, } } -func NewEnvironmentWithCRAndJobs(t *testing.T, lggr logger.Logger, numChains int) DeployedTestEnvironment { - ctx := Context(t) - e := NewEnvironmentWithCRAndFeeds(t, lggr, numChains) - jbs, err := NewCCIPJobSpecs(e.Env.NodeIDs, e.Env.Offchain) - require.NoError(t, err) - for nodeID, jobs := range jbs { - for _, job := range jobs { - // Note these auto-accept - _, err := e.Env.Offchain.ProposeJob(ctx, - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - require.NoError(t, err) - } - } - // Wait for plugins to register filters? - // TODO: Investigate how to avoid. - time.Sleep(30 * time.Second) - - // Ensure job related logs are up to date. - require.NoError(t, ReplayAllLogs(e.Nodes, e.Env.Chains)) +func NewMemoryEnvironmentWithJobs(t *testing.T, lggr logger.Logger, numChains int) DeployedEnv { + e := NewMemoryEnvironment(t, lggr, numChains) + e.SetupJobs(t) return e } -func ReplayAllLogs(nodes map[string]memory.Node, chains map[uint64]deployment.Chain) error { - blockBySel := make(map[uint64]uint64) - for sel := range chains { - blockBySel[sel] = 1 - } - for _, node := range nodes { - if err := node.ReplayLogs(blockBySel); err != nil { - return err - } - } - return nil -} - func SendRequest(t *testing.T, e deployment.Environment, state CCIPOnChainState, src, dest uint64, testRouter bool) uint64 { msg := router.ClientEVM2AnyMessage{ Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), @@ -228,8 +242,8 @@ func (d DeployedLocalDevEnvironment) RestartChainlinkNodes(t *testing.T) error { return errGrp.Wait() } -func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLocalDevEnvironment { - ctx := Context(t) +func NewLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedEnv { + ctx := testcontext.Get(t) // create a local docker environment with simulated chains and job-distributor // we cannot create the chainlink nodes yet as we need to deploy the capability registry first envConfig, testEnv, cfg := devenv.CreateDockerEnv(t) @@ -243,6 +257,8 @@ func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLo require.NotEmpty(t, homeChainSel, "homeChainSel should not be empty") feedSel := envConfig.FeedChainSelector require.NotEmpty(t, feedSel, "feedSel should not be empty") + replayBlocks, err := LatestBlocksByChain(ctx, chains) + require.NoError(t, err) ab, capReg := SetUpHomeAndFeedChains(t, lggr, homeChainSel, feedSel, chains) // start the chainlink nodes with the CR address @@ -252,20 +268,16 @@ func NewDeployedLocalDevEnvironment(t *testing.T, lggr logger.Logger) DeployedLo e, don, err := devenv.NewEnvironment(ctx, lggr, *envConfig) require.NoError(t, err) require.NotNil(t, e) - require.NotNil(t, don) zeroLogLggr := logging.GetTestLogger(t) // fund the nodes devenv.FundNodes(t, zeroLogLggr, testEnv, cfg, don.PluginNodes()) - return DeployedLocalDevEnvironment{ - DeployedEnv: DeployedEnv{ - Ab: ab, - Env: *e, - HomeChainSel: homeChainSel, - FeedChainSel: feedSel, - }, - DON: don, - testEnv: testEnv, + return DeployedEnv{ + Ab: ab, + Env: *e, + HomeChainSel: homeChainSel, + FeedChainSel: feedSel, + ReplayBlocks: replayBlocks, } } diff --git a/integration-tests/deployment/devenv/don.go b/integration-tests/deployment/devenv/don.go index 9478b729f29..15f67df31c5 100644 --- a/integration-tests/deployment/devenv/don.go +++ b/integration-tests/deployment/devenv/don.go @@ -160,7 +160,7 @@ type Node struct { // It expects bootstrap nodes to have label with key "type" and value as "bootstrap". // It fetches the account address, peer id, and OCR2 key bundle id and creates the JobDistributorChainConfig. func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainConfig, jd JobDistributor) error { - for _, chain := range chains { + for i, chain := range chains { chainId := strconv.FormatUint(chain.ChainID, 10) accountAddr, err := n.gqlClient.FetchAccountAddress(ctx, chainId) if err != nil { @@ -198,10 +198,11 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainC } // JD silently fails to update nodeChainConfig. Therefore, we fetch the node config and // if it's not updated , we retry creating the chain config. - // as a workaround, we keep trying creating the chain config for 3 times until it's created + // as a workaround, we keep trying creating the chain config for 5 times until it's created retryCount := 1 - for retryCount < 3 { - err = n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ + created := false + for retryCount < 5 { + chainConfigId, err := n.gqlClient.CreateJobDistributorChainConfig(ctx, client.JobDistributorChainConfigInput{ JobDistributorID: n.JDId, ChainID: chainId, ChainType: chain.ChainType, @@ -225,22 +226,51 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainC if err != nil { return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) } - if nodeChainConfigs != nil && len(nodeChainConfigs.ChainConfigs) > 0 { + if nodeChainConfigs != nil && len(nodeChainConfigs.ChainConfigs) == i+1 { + created = true break } + // delete the node chain config if it's not updated properly + err = n.gqlClient.DeleteJobDistributorChainConfig(ctx, chainConfigId) + if err != nil { + return fmt.Errorf("failed to delete job distributor chain config for node %s: %w", n.Name, err) + } retryCount++ } + if !created { + return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s", n.Name) + } } return nil } -func (n *Node) AcceptJob(ctx context.Context, id string) error { - spec, err := n.gqlClient.ApproveJobProposalSpec(ctx, id, false) +// AcceptJob accepts the job proposal for the given job proposal spec +func (n *Node) AcceptJob(ctx context.Context, spec string) error { + // fetch JD to get the job proposals + jd, err := n.gqlClient.GetJobDistributor(ctx, n.JDId) + if err != nil { + return err + } + if jd.GetJobProposals() == nil { + return fmt.Errorf("no job proposals found for node %s", n.Name) + } + // locate the job proposal id for the given job spec + var idToAccept string + for _, jp := range jd.JobProposals { + if jp.LatestSpec.Definition == spec { + idToAccept = jp.Id + break + } + } + if idToAccept == "" { + return fmt.Errorf("no job proposal found for job spec %s", spec) + } + aaprovedSpec, err := n.gqlClient.ApproveJobProposalSpec(ctx, idToAccept, false) if err != nil { return err } - if spec == nil { - return fmt.Errorf("no job proposal spec found for job id %s", id) + if aaprovedSpec == nil { + return fmt.Errorf("no job proposal spec found for job id %s", idToAccept) } return nil } diff --git a/integration-tests/deployment/devenv/jd.go b/integration-tests/deployment/devenv/jd.go index 671e6e4cea3..3b96058e9aa 100644 --- a/integration-tests/deployment/devenv/jd.go +++ b/integration-tests/deployment/devenv/jd.go @@ -15,9 +15,10 @@ import ( ) type JDConfig struct { - GRPC string - WSRPC string - creds credentials.TransportCredentials + GRPC string + WSRPC string + creds credentials.TransportCredentials + nodeInfo []NodeInfo } func NewJDConnection(cfg JDConfig) (*grpc.ClientConn, error) { @@ -43,19 +44,25 @@ type JobDistributor struct { nodev1.NodeServiceClient jobv1.JobServiceClient csav1.CSAServiceClient + don *DON } -func NewJDClient(cfg JDConfig) (deployment.OffchainClient, error) { +func NewJDClient(ctx context.Context, cfg JDConfig) (deployment.OffchainClient, error) { conn, err := NewJDConnection(cfg) if err != nil { return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) } - return JobDistributor{ + jd := JobDistributor{ WSRPC: cfg.WSRPC, NodeServiceClient: nodev1.NewNodeServiceClient(conn), JobServiceClient: jobv1.NewJobServiceClient(conn), CSAServiceClient: csav1.NewCSAServiceClient(conn), - }, err + } + jd.don, err = NewRegisteredDON(ctx, cfg.nodeInfo, jd) + if err != nil { + return nil, fmt.Errorf("failed to create registered DON: %w", err) + } + return jd, err } func (jd JobDistributor) GetCSAPublicKey(ctx context.Context) (string, error) { @@ -69,3 +76,28 @@ func (jd JobDistributor) GetCSAPublicKey(ctx context.Context) (string, error) { csakey := keypairs.Keypairs[0].PublicKey return csakey, nil } + +func (jd JobDistributor) ReplayLogs(selectorToBlock map[uint64]uint64) error { + return jd.don.ReplayAllLogs(selectorToBlock) +} + +// ProposeJob proposes jobs through the jobService and accepts the proposed job on selected node based on ProposeJobRequest.NodeId +func (jd JobDistributor) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, opts ...grpc.CallOption) (*jobv1.ProposeJobResponse, error) { + res, err := jd.JobServiceClient.ProposeJob(ctx, in, opts...) + if err != nil { + return nil, fmt.Errorf("failed to propose job. err: %w", err) + } + if res.Proposal == nil { + return nil, fmt.Errorf("failed to propose job. err: proposal is nil") + } + for _, node := range jd.don.Nodes { + if node.NodeId != in.NodeId { + continue + } + // TODO : is there a way to accept the job with proposal id? + if err := node.AcceptJob(ctx, res.Proposal.Spec); err != nil { + return nil, fmt.Errorf("failed to accept job. err: %w", err) + } + } + return res, nil +} diff --git a/integration-tests/deployment/memory/job_client.go b/integration-tests/deployment/memory/job_client.go index 25fec711d81..16dbfc2b828 100644 --- a/integration-tests/deployment/memory/job_client.go +++ b/integration-tests/deployment/memory/job_client.go @@ -156,6 +156,15 @@ func (j JobClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, op panic("implement me") } +func (j JobClient) ReplayLogs(selectorToBlock map[uint64]uint64) error { + for _, node := range j.Nodes { + if err := node.ReplayLogs(selectorToBlock); err != nil { + return err + } + } + return nil +} + func NewMemoryJobClient(nodesByPeerID map[string]Node) *JobClient { return &JobClient{nodesByPeerID} } diff --git a/integration-tests/smoke/ccip_test.go b/integration-tests/smoke/ccip_test.go index 02c8435c222..b4961113131 100644 --- a/integration-tests/smoke/ccip_test.go +++ b/integration-tests/smoke/ccip_test.go @@ -1,7 +1,6 @@ package smoke import ( - "strconv" "testing" "github.com/stretchr/testify/require" @@ -11,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" - ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" + ccdeploy "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip/changeset" jobv1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/job/v1" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -19,65 +18,54 @@ import ( func Test0002_InitialDeployOnLocal(t *testing.T) { lggr := logger.TestLogger(t) - ctx := ccipdeployment.Context(t) - tenv := ccipdeployment.NewDeployedLocalDevEnvironment(t, lggr) + ctx := ccdeploy.Context(t) + tenv := ccdeploy.NewLocalDevEnvironment(t, lggr) e := tenv.Env - don := tenv.DON - state, err := ccipdeployment.LoadOnchainState(tenv.Env, tenv.Ab) + state, err := ccdeploy.LoadOnchainState(tenv.Env, tenv.Ab) require.NoError(t, err) feeds := state.Chains[tenv.FeedChainSel].USDFeeds - tokenConfig := ccipdeployment.NewTokenConfig() - tokenConfig.UpsertTokenInfo(ccipdeployment.LinkSymbol, + tokenConfig := ccdeploy.NewTokenConfig() + tokenConfig.UpsertTokenInfo(ccdeploy.LinkSymbol, pluginconfig.TokenInfo{ - AggregatorAddress: feeds[ccipdeployment.LinkSymbol].Address().String(), - Decimals: ccipdeployment.LinkDecimals, + AggregatorAddress: feeds[ccdeploy.LinkSymbol].Address().String(), + Decimals: ccdeploy.LinkDecimals, DeviationPPB: cciptypes.NewBigIntFromInt64(1e9), }, ) // Apply migration - output, err := changeset.Apply0002(tenv.Env, ccipdeployment.DeployCCIPContractConfig{ + output, err := changeset.Apply0002(tenv.Env, ccdeploy.DeployCCIPContractConfig{ HomeChainSel: tenv.HomeChainSel, FeedChainSel: tenv.FeedChainSel, - TokenConfig: tokenConfig, ChainsToDeploy: tenv.Env.AllChainSelectors(), - // Capreg/config already exist. + TokenConfig: tokenConfig, + // Capreg/config and feeds already exist. CCIPOnChainState: state, }) require.NoError(t, err) // Get new state after migration. - state, err = ccipdeployment.LoadOnchainState(e, output.AddressBook) + state, err = ccdeploy.LoadOnchainState(e, output.AddressBook) require.NoError(t, err) + // Ensure capreg logs are up to date. + ccdeploy.ReplayLogs(t, e.Offchain, tenv.ReplayBlocks) + // Apply the jobs. - nodeIdToJobIds := make(map[string][]string) for nodeID, jobs := range output.JobSpecs { - nodeIdToJobIds[nodeID] = make([]string, 0, len(jobs)) for _, job := range jobs { - res, err := e.Offchain.ProposeJob(ctx, + // Note these auto-accept + _, err := e.Offchain.ProposeJob(ctx, &jobv1.ProposeJobRequest{ NodeId: nodeID, Spec: job, }) require.NoError(t, err) - require.NotNil(t, res.Proposal) - nodeIdToJobIds[nodeID] = append(nodeIdToJobIds[nodeID], res.Proposal.JobId) - } - } - - // Accept all the jobs for this node. - for _, n := range don.Nodes { - jobsToAccept, exists := nodeIdToJobIds[n.NodeId] - require.True(t, exists, "node %s has no jobs to accept", n.NodeId) - for i, jobID := range jobsToAccept { - require.NoError(t, n.AcceptJob(ctx, strconv.Itoa(i+1)), "node -%s failed to accept job %s", n.Name, jobID) } } - t.Log("Jobs accepted") // Add all lanes - require.NoError(t, ccipdeployment.AddLanesForAll(e, state)) + require.NoError(t, ccdeploy.AddLanesForAll(e, state)) // Need to keep track of the block number for each chain so that event subscription can be done from that block. startBlocks := make(map[uint64]*uint64) // Send a message from each chain to every other chain. @@ -91,13 +79,13 @@ func Test0002_InitialDeployOnLocal(t *testing.T) { require.NoError(t, err) block := latesthdr.Number.Uint64() startBlocks[dest] = &block - seqNum := ccipdeployment.SendRequest(t, e, state, src, dest, false) + seqNum := ccdeploy.SendRequest(t, e, state, src, dest, false) expectedSeqNum[dest] = seqNum } } // Wait for all commit reports to land. - ccipdeployment.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmCommitForAllWithExpectedSeqNums(t, e, state, expectedSeqNum, startBlocks) // After commit is reported on all chains, token prices should be updated in FeeQuoter. for dest := range e.Chains { @@ -105,8 +93,11 @@ func Test0002_InitialDeployOnLocal(t *testing.T) { feeQuoter := state.Chains[dest].FeeQuoter timestampedPrice, err := feeQuoter.GetTokenPrice(nil, linkAddress) require.NoError(t, err) - require.Equal(t, ccipdeployment.MockLinkPrice, timestampedPrice.Value) + require.Equal(t, ccdeploy.MockLinkPrice, timestampedPrice.Value) } + // Wait for all exec reports to land - ccipdeployment.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + ccdeploy.ConfirmExecWithSeqNrForAll(t, e, state, expectedSeqNum, startBlocks) + + // TODO: Apply the proposal. } diff --git a/integration-tests/web/sdk/client/client.go b/integration-tests/web/sdk/client/client.go index 783a8a88565..e633bf04c15 100644 --- a/integration-tests/web/sdk/client/client.go +++ b/integration-tests/web/sdk/client/client.go @@ -21,12 +21,13 @@ type Client interface { FetchOCR2KeyBundleID(ctx context.Context, chainType string) (string, error) GetJob(ctx context.Context, id string) (*generated.GetJobResponse, error) ListJobs(ctx context.Context, offset, limit int) (*generated.ListJobsResponse, error) - GetJobDistributor(ctx context.Context, id string) (*generated.GetFeedsManagerResponse, error) + GetJobDistributor(ctx context.Context, id string) (generated.FeedsManagerParts, error) ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) CreateJobDistributor(ctx context.Context, cmd JobDistributorInput) (string, error) UpdateJobDistributor(ctx context.Context, id string, cmd JobDistributorInput) error - CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) error - GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalResponse, error) + CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) (string, error) + DeleteJobDistributorChainConfig(ctx context.Context, id string) error + GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) CancelJobProposalSpec(ctx context.Context, id string) (*generated.CancelJobProposalSpecResponse, error) RejectJobProposalSpec(ctx context.Context, id string) (*generated.RejectJobProposalSpecResponse, error) @@ -142,8 +143,18 @@ func (c *client) ListBridges(ctx context.Context, offset, limit int) (*generated return generated.ListBridges(ctx, c.gqlClient, offset, limit) } -func (c *client) GetJobDistributor(ctx context.Context, id string) (*generated.GetFeedsManagerResponse, error) { - return generated.GetFeedsManager(ctx, c.gqlClient, id) +func (c *client) GetJobDistributor(ctx context.Context, id string) (generated.FeedsManagerParts, error) { + res, err := generated.GetFeedsManager(ctx, c.gqlClient, id) + if err != nil { + return generated.FeedsManagerParts{}, err + } + if res == nil { + return generated.FeedsManagerParts{}, fmt.Errorf("no feeds manager found") + } + if success, ok := res.GetFeedsManager().(*generated.GetFeedsManagerFeedsManager); ok { + return success.FeedsManagerParts, nil + } + return generated.FeedsManagerParts{}, fmt.Errorf("failed to get feeds manager") } func (c *client) ListJobDistributors(ctx context.Context) (*generated.ListFeedsManagersResponse, error) { @@ -178,18 +189,51 @@ func (c *client) UpdateJobDistributor(ctx context.Context, id string, in JobDist return err } -func (c *client) CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) error { +func (c *client) CreateJobDistributorChainConfig(ctx context.Context, in JobDistributorChainConfigInput) (string, error) { var cmd generated.CreateFeedsManagerChainConfigInput err := DecodeInput(in, &cmd) + if err != nil { + return "", err + } + res, err := generated.CreateFeedsManagerChainConfig(ctx, c.gqlClient, cmd) + if err != nil { + return "", err + } + if res == nil { + return "", fmt.Errorf("failed to create feeds manager chain config") + } + if success, ok := res.GetCreateFeedsManagerChainConfig().(*generated.CreateFeedsManagerChainConfigCreateFeedsManagerChainConfigCreateFeedsManagerChainConfigSuccess); ok { + return success.ChainConfig.Id, nil + } + return "", fmt.Errorf("failed to create feeds manager chain config") +} + +func (c *client) DeleteJobDistributorChainConfig(ctx context.Context, id string) error { + res, err := generated.DeleteFeedsManagerChainConfig(ctx, c.gqlClient, id) if err != nil { return err } - _, err = generated.CreateFeedsManagerChainConfig(ctx, c.gqlClient, cmd) - return err + if res == nil { + return fmt.Errorf("failed to delete feeds manager chain config") + } + if _, ok := res.GetDeleteFeedsManagerChainConfig().(*generated.DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess); ok { + return nil + } + return fmt.Errorf("failed to delete feeds manager chain config") } -func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalResponse, error) { - return generated.GetJobProposal(ctx, c.gqlClient, id) +func (c *client) GetJobProposal(ctx context.Context, id string) (*generated.GetJobProposalJobProposal, error) { + proposal, err := generated.GetJobProposal(ctx, c.gqlClient, id) + if err != nil { + return nil, err + } + if proposal == nil { + return nil, fmt.Errorf("no job proposal found") + } + if success, ok := proposal.GetJobProposal().(*generated.GetJobProposalJobProposal); ok { + return success, nil + } + return nil, fmt.Errorf("failed to get job proposal") } func (c *client) ApproveJobProposalSpec(ctx context.Context, id string, force bool) (*JobProposalApprovalSuccessSpec, error) { diff --git a/integration-tests/web/sdk/internal/generated/generated.go b/integration-tests/web/sdk/internal/generated/generated.go index 8efde4c453f..68ab3e48e4f 100644 --- a/integration-tests/web/sdk/internal/generated/generated.go +++ b/integration-tests/web/sdk/internal/generated/generated.go @@ -1194,6 +1194,11 @@ func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManag return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -1231,6 +1236,8 @@ type __premarshalCreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFe IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManager) MarshalJSON() ([]byte, error) { @@ -1250,6 +1257,7 @@ func (v *CreateFeedsManagerCreateFeedsManagerCreateFeedsManagerSuccessFeedsManag retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -1425,6 +1433,200 @@ func (v *CreateFeedsManagerResponse) __premarshalJSON() (*__premarshalCreateFeed return &retval, nil } +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload includes the requested fields of the GraphQL interface DeleteFeedsManagerChainConfigPayload. +// +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload is implemented by the following types: +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload interface { + implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() + // GetTypename returns the receiver's concrete GraphQL type-name (see interface doc for possible values). + GetTypename() string +} + +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() { +} +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) implementsGraphQLInterfaceDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload() { +} + +func __unmarshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload(b []byte, v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload) error { + if string(b) == "null" { + return nil + } + + var tn struct { + TypeName string `json:"__typename"` + } + err := json.Unmarshal(b, &tn) + if err != nil { + return err + } + + switch tn.TypeName { + case "DeleteFeedsManagerChainConfigSuccess": + *v = new(DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) + return json.Unmarshal(b, *v) + case "NotFoundError": + *v = new(DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) + return json.Unmarshal(b, *v) + case "": + return fmt.Errorf( + "response was missing DeleteFeedsManagerChainConfigPayload.__typename") + default: + return fmt.Errorf( + `unexpected concrete type for DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload: "%v"`, tn.TypeName) + } +} + +func __marshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload(v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload) ([]byte, error) { + + var typename string + switch v := (*v).(type) { + case *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess: + typename = "DeleteFeedsManagerChainConfigSuccess" + + result := struct { + TypeName string `json:"__typename"` + *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess + }{typename, v} + return json.Marshal(result) + case *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError: + typename = "NotFoundError" + + result := struct { + TypeName string `json:"__typename"` + *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError + }{typename, v} + return json.Marshal(result) + case nil: + return []byte("null"), nil + default: + return nil, fmt.Errorf( + `unexpected concrete type for DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload: "%T"`, v) + } +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess includes the requested fields of the GraphQL type DeleteFeedsManagerChainConfigSuccess. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess struct { + Typename string `json:"__typename"` + ChainConfig DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig `json:"chainConfig"` +} + +// GetTypename returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess.Typename, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) GetTypename() string { + return v.Typename +} + +// GetChainConfig returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess.ChainConfig, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccess) GetChainConfig() DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig { + return v.ChainConfig +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig includes the requested fields of the GraphQL type FeedsManagerChainConfig. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig struct { + Id string `json:"id"` +} + +// GetId returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig.Id, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigSuccessChainConfigFeedsManagerChainConfig) GetId() string { + return v.Id +} + +// DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError includes the requested fields of the GraphQL type NotFoundError. +type DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError struct { + Typename string `json:"__typename"` + Message string `json:"message"` + Code ErrorCode `json:"code"` +} + +// GetTypename returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Typename, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetTypename() string { + return v.Typename +} + +// GetMessage returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Message, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetMessage() string { + return v.Message +} + +// GetCode returns DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError.Code, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigNotFoundError) GetCode() ErrorCode { + return v.Code +} + +// DeleteFeedsManagerChainConfigResponse is returned by DeleteFeedsManagerChainConfig on success. +type DeleteFeedsManagerChainConfigResponse struct { + DeleteFeedsManagerChainConfig DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload `json:"-"` +} + +// GetDeleteFeedsManagerChainConfig returns DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig, and is useful for accessing the field via an interface. +func (v *DeleteFeedsManagerChainConfigResponse) GetDeleteFeedsManagerChainConfig() DeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload { + return v.DeleteFeedsManagerChainConfig +} + +func (v *DeleteFeedsManagerChainConfigResponse) UnmarshalJSON(b []byte) error { + + if string(b) == "null" { + return nil + } + + var firstPass struct { + *DeleteFeedsManagerChainConfigResponse + DeleteFeedsManagerChainConfig json.RawMessage `json:"deleteFeedsManagerChainConfig"` + graphql.NoUnmarshalJSON + } + firstPass.DeleteFeedsManagerChainConfigResponse = v + + err := json.Unmarshal(b, &firstPass) + if err != nil { + return err + } + + { + dst := &v.DeleteFeedsManagerChainConfig + src := firstPass.DeleteFeedsManagerChainConfig + if len(src) != 0 && string(src) != "null" { + err = __unmarshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload( + src, dst) + if err != nil { + return fmt.Errorf( + "unable to unmarshal DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig: %w", err) + } + } + } + return nil +} + +type __premarshalDeleteFeedsManagerChainConfigResponse struct { + DeleteFeedsManagerChainConfig json.RawMessage `json:"deleteFeedsManagerChainConfig"` +} + +func (v *DeleteFeedsManagerChainConfigResponse) MarshalJSON() ([]byte, error) { + premarshaled, err := v.__premarshalJSON() + if err != nil { + return nil, err + } + return json.Marshal(premarshaled) +} + +func (v *DeleteFeedsManagerChainConfigResponse) __premarshalJSON() (*__premarshalDeleteFeedsManagerChainConfigResponse, error) { + var retval __premarshalDeleteFeedsManagerChainConfigResponse + + { + + dst := &retval.DeleteFeedsManagerChainConfig + src := v.DeleteFeedsManagerChainConfig + var err error + *dst, err = __marshalDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigDeleteFeedsManagerChainConfigPayload( + &src) + if err != nil { + return nil, fmt.Errorf( + "unable to marshal DeleteFeedsManagerChainConfigResponse.DeleteFeedsManagerChainConfig: %w", err) + } + } + return &retval, nil +} + type ErrorCode string const ( @@ -1435,12 +1637,13 @@ const ( // FeedsManagerParts includes the GraphQL fields of FeedsManager requested by the fragment FeedsManagerParts. type FeedsManagerParts struct { - Id string `json:"id"` - Name string `json:"name"` - Uri string `json:"uri"` - PublicKey string `json:"publicKey"` - IsConnectionActive bool `json:"isConnectionActive"` - CreatedAt string `json:"createdAt"` + Id string `json:"id"` + Name string `json:"name"` + Uri string `json:"uri"` + PublicKey string `json:"publicKey"` + IsConnectionActive bool `json:"isConnectionActive"` + CreatedAt string `json:"createdAt"` + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } // GetId returns FeedsManagerParts.Id, and is useful for accessing the field via an interface. @@ -1461,6 +1664,137 @@ func (v *FeedsManagerParts) GetIsConnectionActive() bool { return v.IsConnection // GetCreatedAt returns FeedsManagerParts.CreatedAt, and is useful for accessing the field via an interface. func (v *FeedsManagerParts) GetCreatedAt() string { return v.CreatedAt } +// GetJobProposals returns FeedsManagerParts.JobProposals, and is useful for accessing the field via an interface. +func (v *FeedsManagerParts) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.JobProposals +} + +// FeedsManagerPartsJobProposalsJobProposal includes the requested fields of the GraphQL type JobProposal. +type FeedsManagerPartsJobProposalsJobProposal struct { + Id string `json:"id"` + Status JobProposalStatus `json:"status"` + RemoteUUID string `json:"remoteUUID"` + ExternalJobID string `json:"externalJobID"` + JobID string `json:"jobID"` + Specs []FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec `json:"specs"` + LatestSpec FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec `json:"latestSpec"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposal.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetId() string { return v.Id } + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposal.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetStatus() JobProposalStatus { return v.Status } + +// GetRemoteUUID returns FeedsManagerPartsJobProposalsJobProposal.RemoteUUID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetRemoteUUID() string { return v.RemoteUUID } + +// GetExternalJobID returns FeedsManagerPartsJobProposalsJobProposal.ExternalJobID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetExternalJobID() string { return v.ExternalJobID } + +// GetJobID returns FeedsManagerPartsJobProposalsJobProposal.JobID, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetJobID() string { return v.JobID } + +// GetSpecs returns FeedsManagerPartsJobProposalsJobProposal.Specs, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetSpecs() []FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec { + return v.Specs +} + +// GetLatestSpec returns FeedsManagerPartsJobProposalsJobProposal.LatestSpec, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposal) GetLatestSpec() FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec { + return v.LatestSpec +} + +// FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetId() string { + return v.Id +} + +// GetDefinition returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalLatestSpecJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + +// FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec includes the requested fields of the GraphQL type JobProposalSpec. +type FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec struct { + Id string `json:"id"` + Definition string `json:"definition"` + Version int `json:"version"` + Status SpecStatus `json:"status"` + StatusUpdatedAt string `json:"statusUpdatedAt"` + CreatedAt string `json:"createdAt"` + UpdatedAt string `json:"updatedAt"` +} + +// GetId returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Id, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetId() string { return v.Id } + +// GetDefinition returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Definition, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetDefinition() string { + return v.Definition +} + +// GetVersion returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Version, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetVersion() int { + return v.Version +} + +// GetStatus returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.Status, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetStatus() SpecStatus { + return v.Status +} + +// GetStatusUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.StatusUpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetStatusUpdatedAt() string { + return v.StatusUpdatedAt +} + +// GetCreatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.CreatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetCreatedAt() string { + return v.CreatedAt +} + +// GetUpdatedAt returns FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec.UpdatedAt, and is useful for accessing the field via an interface. +func (v *FeedsManagerPartsJobProposalsJobProposalSpecsJobProposalSpec) GetUpdatedAt() string { + return v.UpdatedAt +} + // FetchAccountsEthKeysEthKeysPayload includes the requested fields of the GraphQL type EthKeysPayload. type FetchAccountsEthKeysEthKeysPayload struct { Results []FetchAccountsEthKeysEthKeysPayloadResultsEthKey `json:"results"` @@ -1929,6 +2263,11 @@ func (v *GetFeedsManagerFeedsManager) GetIsConnectionActive() bool { // GetCreatedAt returns GetFeedsManagerFeedsManager.CreatedAt, and is useful for accessing the field via an interface. func (v *GetFeedsManagerFeedsManager) GetCreatedAt() string { return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns GetFeedsManagerFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *GetFeedsManagerFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *GetFeedsManagerFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -1968,6 +2307,8 @@ type __premarshalGetFeedsManagerFeedsManager struct { IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *GetFeedsManagerFeedsManager) MarshalJSON() ([]byte, error) { @@ -1988,6 +2329,7 @@ func (v *GetFeedsManagerFeedsManager) __premarshalJSON() (*__premarshalGetFeedsM retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -2465,6 +2807,11 @@ func (v *GetJobProposalJobProposalFeedsManager) GetCreatedAt() string { return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns GetJobProposalJobProposalFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *GetJobProposalJobProposalFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *GetJobProposalJobProposalFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -2502,6 +2849,8 @@ type __premarshalGetJobProposalJobProposalFeedsManager struct { IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *GetJobProposalJobProposalFeedsManager) MarshalJSON() ([]byte, error) { @@ -2521,6 +2870,7 @@ func (v *GetJobProposalJobProposalFeedsManager) __premarshalJSON() (*__premarsha retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -3650,6 +4000,11 @@ func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -3687,6 +4042,8 @@ type __premarshalListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsM IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) MarshalJSON() ([]byte, error) { @@ -3706,6 +4063,7 @@ func (v *ListFeedsManagersFeedsManagersFeedsManagersPayloadResultsFeedsManager) retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -4469,6 +4827,11 @@ func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManag return v.FeedsManagerParts.CreatedAt } +// GetJobProposals returns UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager.JobProposals, and is useful for accessing the field via an interface. +func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) GetJobProposals() []FeedsManagerPartsJobProposalsJobProposal { + return v.FeedsManagerParts.JobProposals +} + func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) UnmarshalJSON(b []byte) error { if string(b) == "null" { @@ -4506,6 +4869,8 @@ type __premarshalUpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFe IsConnectionActive bool `json:"isConnectionActive"` CreatedAt string `json:"createdAt"` + + JobProposals []FeedsManagerPartsJobProposalsJobProposal `json:"jobProposals"` } func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManager) MarshalJSON() ([]byte, error) { @@ -4525,6 +4890,7 @@ func (v *UpdateFeedsManagerUpdateFeedsManagerUpdateFeedsManagerSuccessFeedsManag retval.PublicKey = v.FeedsManagerParts.PublicKey retval.IsConnectionActive = v.FeedsManagerParts.IsConnectionActive retval.CreatedAt = v.FeedsManagerParts.CreatedAt + retval.JobProposals = v.FeedsManagerParts.JobProposals return &retval, nil } @@ -4803,6 +5169,14 @@ type __CreateFeedsManagerInput struct { // GetInput returns __CreateFeedsManagerInput.Input, and is useful for accessing the field via an interface. func (v *__CreateFeedsManagerInput) GetInput() CreateFeedsManagerInput { return v.Input } +// __DeleteFeedsManagerChainConfigInput is used internally by genqlient +type __DeleteFeedsManagerChainConfigInput struct { + Id string `json:"id"` +} + +// GetId returns __DeleteFeedsManagerChainConfigInput.Id, and is useful for accessing the field via an interface. +func (v *__DeleteFeedsManagerChainConfigInput) GetId() string { return v.Id } + // __GetBridgeInput is used internally by genqlient type __GetBridgeInput struct { Id string `json:"id"` @@ -5033,6 +5407,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5142,6 +5541,50 @@ func CreateFeedsManagerChainConfig( return &data_, err_ } +// The query or mutation executed by DeleteFeedsManagerChainConfig. +const DeleteFeedsManagerChainConfig_Operation = ` +mutation DeleteFeedsManagerChainConfig ($id: ID!) { + deleteFeedsManagerChainConfig(id: $id) { + __typename + ... on DeleteFeedsManagerChainConfigSuccess { + chainConfig { + id + } + } + ... on NotFoundError { + message + code + } + } +} +` + +func DeleteFeedsManagerChainConfig( + ctx_ context.Context, + client_ graphql.Client, + id string, +) (*DeleteFeedsManagerChainConfigResponse, error) { + req_ := &graphql.Request{ + OpName: "DeleteFeedsManagerChainConfig", + Query: DeleteFeedsManagerChainConfig_Operation, + Variables: &__DeleteFeedsManagerChainConfigInput{ + Id: id, + }, + } + var err_ error + + var data_ DeleteFeedsManagerChainConfigResponse + resp_ := &graphql.Response{Data: &data_} + + err_ = client_.MakeRequest( + ctx_, + req_, + resp_, + ) + + return &data_, err_ +} + // The query or mutation executed by FetchAccounts. const FetchAccounts_Operation = ` query FetchAccounts { @@ -5357,6 +5800,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5514,6 +5982,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5610,6 +6103,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` @@ -5796,6 +6314,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } ` diff --git a/integration-tests/web/sdk/internal/genqlient.graphql b/integration-tests/web/sdk/internal/genqlient.graphql index cd1912b88cf..06baf4f7913 100644 --- a/integration-tests/web/sdk/internal/genqlient.graphql +++ b/integration-tests/web/sdk/internal/genqlient.graphql @@ -212,6 +212,31 @@ fragment FeedsManagerParts on FeedsManager { publicKey isConnectionActive createdAt + jobProposals { + id + status + remoteUUID + externalJobID + jobID + specs { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + latestSpec { + id + definition + version + status + statusUpdatedAt + createdAt + updatedAt + } + } } query GetFeedsManager($id: ID!) { @@ -328,6 +353,19 @@ mutation CreateFeedsManagerChainConfig($input: CreateFeedsManagerChainConfigInpu } } +mutation DeleteFeedsManagerChainConfig($id: ID!) { + deleteFeedsManagerChainConfig(id: $id) { + ... on DeleteFeedsManagerChainConfigSuccess { + chainConfig { + id + } + } + ... on NotFoundError { + message + code + } + } +} ##################### # Job Proposals @@ -418,4 +456,4 @@ mutation UpdateJobProposalSpecDefinition( code } } -} +} \ No newline at end of file From 4324af7e69def56e4dbaccc481d1755bdc471dc9 Mon Sep 17 00:00:00 2001 From: AnieeG Date: Fri, 27 Sep 2024 17:08:38 -0700 Subject: [PATCH 2/5] changes --- .../deployment/devenv/build_env.go | 33 ++++++++++++++++++- .../deployment/devenv/environment.go | 15 ++++----- integration-tests/deployment/devenv/jd.go | 4 +-- .../deployment/memory/environment.go | 17 ---------- 4 files changed, 41 insertions(+), 28 deletions(-) diff --git a/integration-tests/deployment/devenv/build_env.go b/integration-tests/deployment/devenv/build_env.go index a36a6f51a69..dfd43abd934 100644 --- a/integration-tests/deployment/devenv/build_env.go +++ b/integration-tests/deployment/devenv/build_env.go @@ -11,10 +11,13 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" + "github.com/pkg/errors" "github.com/rs/zerolog" chainselectors "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/stretchr/testify/require" "github.com/subosito/gotenv" + "golang.org/x/sync/errgroup" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink-testing-framework/seth" @@ -207,7 +210,10 @@ func StartChainlinkNodes( InternalIP: n.API.InternalIP(), } } - envConfig.nodeInfo = nodeInfo + if envConfig == nil { + envConfig = &EnvironmentConfig{} + } + envConfig.JDConfig.nodeInfo = nodeInfo return nil } @@ -345,3 +351,28 @@ func CreateChainConfigFromNetworks( } return chains } + +// RestartChainlinkNodes restarts the chainlink nodes in the test environment +// ignore lint +// nolint:usage +func RestartChainlinkNodes(t *testing.T, env *test_env.CLClusterTestEnv) error { + errGrp := errgroup.Group{} + if env == nil || env.ClCluster == nil { + return errors.Wrap(errors.New("no testenv or clcluster found "), "error restarting node") + } + for _, n := range env.ClCluster.Nodes { + n := n + errGrp.Go(func() error { + if err := n.Container.Terminate(testcontext.Get(t)); err != nil { + return err + } + err := n.RestartContainer() + if err != nil { + return err + } + return nil + }) + + } + return errGrp.Wait() +} diff --git a/integration-tests/deployment/devenv/environment.go b/integration-tests/deployment/devenv/environment.go index 74cde258cc3..6e25518d54a 100644 --- a/integration-tests/deployment/devenv/environment.go +++ b/integration-tests/deployment/devenv/environment.go @@ -26,25 +26,24 @@ func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentC if err != nil { return nil, nil, fmt.Errorf("failed to create chains: %w", err) } - offChain, err := NewJDClient(config.JDConfig) + offChain, err := NewJDClient(ctx, config.JDConfig) if err != nil { return nil, nil, fmt.Errorf("failed to create JD client: %w", err) } - jd, ok := offChain.(JobDistributor) + jd, ok := offChain.(*JobDistributor) if !ok { return nil, nil, fmt.Errorf("offchain client does not implement JobDistributor") } - don, err := NewRegisteredDON(ctx, config.nodeInfo, jd) - if err != nil { - return nil, nil, fmt.Errorf("failed to create registered DON: %w", err) + if jd == nil || jd.don == nil { + return nil, nil, fmt.Errorf("offchain client does not have a DON") } - nodeIDs := don.NodeIds() - err = don.CreateSupportedChains(ctx, config.Chains, jd) + err = jd.don.CreateSupportedChains(ctx, config.Chains, *jd) if err != nil { return nil, nil, err } + nodeIDs := jd.don.NodeIds() return &deployment.Environment{ Name: DevEnv, @@ -52,5 +51,5 @@ func NewEnvironment(ctx context.Context, lggr logger.Logger, config EnvironmentC NodeIDs: nodeIDs, Chains: chains, Logger: lggr, - }, don, nil + }, jd.don, nil } diff --git a/integration-tests/deployment/devenv/jd.go b/integration-tests/deployment/devenv/jd.go index 3b96058e9aa..7a8183f04aa 100644 --- a/integration-tests/deployment/devenv/jd.go +++ b/integration-tests/deployment/devenv/jd.go @@ -52,13 +52,13 @@ func NewJDClient(ctx context.Context, cfg JDConfig) (deployment.OffchainClient, if err != nil { return nil, fmt.Errorf("failed to connect Job Distributor service. Err: %w", err) } - jd := JobDistributor{ + jd := &JobDistributor{ WSRPC: cfg.WSRPC, NodeServiceClient: nodev1.NewNodeServiceClient(conn), JobServiceClient: jobv1.NewJobServiceClient(conn), CSAServiceClient: csav1.NewCSAServiceClient(conn), } - jd.don, err = NewRegisteredDON(ctx, cfg.nodeInfo, jd) + jd.don, err = NewRegisteredDON(ctx, cfg.nodeInfo, *jd) if err != nil { return nil, fmt.Errorf("failed to create registered DON: %w", err) } diff --git a/integration-tests/deployment/memory/environment.go b/integration-tests/deployment/memory/environment.go index 409e8d3a816..2b68d5666fa 100644 --- a/integration-tests/deployment/memory/environment.go +++ b/integration-tests/deployment/memory/environment.go @@ -112,23 +112,6 @@ func NewMemoryEnvironmentFromChainsNodes(t *testing.T, } } -//func NewMemoryEnvironmentExistingChains(t *testing.T, lggr logger.Logger, -// chains map[uint64]deployment.Chain, config MemoryEnvironmentConfig) deployment.Environment { -// nodes := NewNodes(t, chains, config.Nodes, config.Bootstraps, config.CapabilityRegistryConfig) -// var nodeIDs []string -// for id := range nodes { -// nodeIDs = append(nodeIDs, id) -// } -// return deployment.Environment{ -// Name: Memory, -// Offchain: NewMemoryJobClient(nodes), -// // Note these have the p2p_ prefix. -// NodeIDs: nodeIDs, -// Chains: chains, -// Logger: lggr, -// } -//} - // To be used by tests and any kind of deployment logic. func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { chains := NewMemoryChains(t, config.Chains) From 4f6538f583e6ec5c9c5ccb5b149dc857fc7715b2 Mon Sep 17 00:00:00 2001 From: AnieeG Date: Mon, 30 Sep 2024 08:15:16 -0700 Subject: [PATCH 3/5] lint --- integration-tests/deployment/ccip/test_helpers.go | 10 +++------- integration-tests/deployment/devenv/build_env.go | 5 ++--- integration-tests/deployment/devenv/environment.go | 1 - 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/integration-tests/deployment/ccip/test_helpers.go b/integration-tests/deployment/ccip/test_helpers.go index c9ced060e2b..59eecae4f29 100644 --- a/integration-tests/deployment/ccip/test_helpers.go +++ b/integration-tests/deployment/ccip/test_helpers.go @@ -90,15 +90,11 @@ func (e *DeployedEnv) SetupJobs(t *testing.T) { } func ReplayLogs(t *testing.T, oc deployment.OffchainClient, replayBlocks map[uint64]uint64) { - switch oc.(type) { + switch oc := oc.(type) { case *memory.JobClient: - jobclient, ok := oc.(*memory.JobClient) - require.True(t, ok) - require.NoError(t, jobclient.ReplayLogs(replayBlocks)) + require.NoError(t, oc.ReplayLogs(replayBlocks)) case *devenv.JobDistributor: - jobclient, ok := oc.(*devenv.JobDistributor) - require.True(t, ok) - require.NoError(t, jobclient.ReplayLogs(replayBlocks)) + require.NoError(t, oc.ReplayLogs(replayBlocks)) default: t.Fatalf("unsupported offchain client type %T", oc) } diff --git a/integration-tests/deployment/devenv/build_env.go b/integration-tests/deployment/devenv/build_env.go index dfd43abd934..3e5af0866fa 100644 --- a/integration-tests/deployment/devenv/build_env.go +++ b/integration-tests/deployment/devenv/build_env.go @@ -14,11 +14,12 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog" chainselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/stretchr/testify/require" "github.com/subosito/gotenv" "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink-testing-framework/seth" @@ -353,8 +354,6 @@ func CreateChainConfigFromNetworks( } // RestartChainlinkNodes restarts the chainlink nodes in the test environment -// ignore lint -// nolint:usage func RestartChainlinkNodes(t *testing.T, env *test_env.CLClusterTestEnv) error { errGrp := errgroup.Group{} if env == nil || env.ClCluster == nil { diff --git a/integration-tests/deployment/devenv/environment.go b/integration-tests/deployment/devenv/environment.go index 6e25518d54a..e06b69769f8 100644 --- a/integration-tests/deployment/devenv/environment.go +++ b/integration-tests/deployment/devenv/environment.go @@ -17,7 +17,6 @@ type EnvironmentConfig struct { Chains []ChainConfig HomeChainSelector uint64 FeedChainSelector uint64 - nodeInfo []NodeInfo JDConfig JDConfig } From 32018950a79f31643158af37dcf5d61fb04f32ca Mon Sep 17 00:00:00 2001 From: AnieeG Date: Mon, 30 Sep 2024 08:48:53 -0700 Subject: [PATCH 4/5] jd changes --- integration-tests/deployment/devenv/don.go | 29 ++++++++++++++-------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/integration-tests/deployment/devenv/don.go b/integration-tests/deployment/devenv/don.go index 15f67df31c5..957f9508962 100644 --- a/integration-tests/deployment/devenv/don.go +++ b/integration-tests/deployment/devenv/don.go @@ -5,10 +5,12 @@ import ( "fmt" "strconv" "strings" + "time" "github.com/AlekSi/pointer" "github.com/hashicorp/go-multierror" "github.com/rs/zerolog" + "github.com/sethvargo/go-retry" chainsel "github.com/smartcontractkit/chain-selectors" clclient "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -218,23 +220,30 @@ func (n *Node) CreateCCIPOCRSupportedChains(ctx context.Context, chains []ChainC if err != nil { return fmt.Errorf("failed to create CCIPOCR2SupportedChains for node %s: %w", n.Name, err) } - - nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ - Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeIds: []string{n.NodeId}, - }}) - if err != nil { - return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) - } - if nodeChainConfigs != nil && len(nodeChainConfigs.ChainConfigs) == i+1 { + // JD doesn't update the node chain config immediately, so we need to wait for it to be updated + err = retry.Do(ctx, retry.WithMaxRetries(3, retry.NewFibonacci(1*time.Second)), func(ctx context.Context) error { + nodeChainConfigs, err := jd.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{ + Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ + NodeIds: []string{n.NodeId}, + }}) + if err != nil { + return fmt.Errorf("failed to list node chain configs for node %s: %w", n.Name, err) + } + if nodeChainConfigs != nil && len(nodeChainConfigs.ChainConfigs) == i+1 { + return nil + } + return fmt.Errorf("node chain config not updated properly") + }) + if err == nil { created = true break } - // delete the node chain config if it's not updated properly + // delete the node chain config if it's not updated properly and retry err = n.gqlClient.DeleteJobDistributorChainConfig(ctx, chainConfigId) if err != nil { return fmt.Errorf("failed to delete job distributor chain config for node %s: %w", n.Name, err) } + retryCount++ } if !created { From 0f96cd338898850f025063f7cc629f0e5914cd26 Mon Sep 17 00:00:00 2001 From: AnieeG Date: Mon, 30 Sep 2024 08:58:23 -0700 Subject: [PATCH 5/5] fix typo --- integration-tests/deployment/devenv/don.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration-tests/deployment/devenv/don.go b/integration-tests/deployment/devenv/don.go index 957f9508962..0b10bd091a8 100644 --- a/integration-tests/deployment/devenv/don.go +++ b/integration-tests/deployment/devenv/don.go @@ -274,11 +274,11 @@ func (n *Node) AcceptJob(ctx context.Context, spec string) error { if idToAccept == "" { return fmt.Errorf("no job proposal found for job spec %s", spec) } - aaprovedSpec, err := n.gqlClient.ApproveJobProposalSpec(ctx, idToAccept, false) + approvedSpec, err := n.gqlClient.ApproveJobProposalSpec(ctx, idToAccept, false) if err != nil { return err } - if aaprovedSpec == nil { + if approvedSpec == nil { return fmt.Errorf("no job proposal spec found for job id %s", idToAccept) } return nil