Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix monitor in integration test #378

Open
wants to merge 8 commits into
base: update-monitoring
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/integration-tests-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ jobs:
mkdir -p -m 777 target/debug artifacts
make build_contracts

- name: Run Cosmos monitor dependencies
run: |
cd ops/monitoring
docker-compose up -d

- name: Run Test
env:
CORE_IMAGE: 'local_chainlink'
Expand Down
74 changes: 66 additions & 8 deletions cmd/monitoring/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,67 @@
# On-chain monitor

## Example of running the monitor locally
## Local development

- Start the monitor's third party dependencies using [docker-compose](https://docs.docker.com/compose/).
Use the docker-compose.yml file in `./ops`:

```sh
docker-compose up
```

- Start an http server that mimics weiwatchers locally. Note: this isn't required to run integration tests as it these are created automatically in the test. It needs to export a json configuration file for feeds:

```json
[
{
"name": "LINK / USD",
"path": "link-usd",
"symbol": "$",
"heartbeat": 0,
"contract_type": "numerical_median_feed",
"status": "testing",
"contract_address": "<CONTRACT_ADDRESS>",
"multiply": "100000000",
"proxy_address": "<PROXY_ADDRESS>"
}
]
```

It also needs to export a json configuration for for node operators:

```json
[
{
"id": "noop",
"nodeAddress": [<NODE_OPERATOR_ADDRESS>]
}
]
```

One option is to create a folder `/tmp/configs` and add two files `feeds.json` and `nodes.json` with the configs from above, then:

```bash
python3 -m http.server 4000
```

- Start the monitor locally. You will need the tendermint url and the address of the LINK token.

```bash
COSMOS_TENDERMINT_URL="<some terra url>" \
COSMOS_FCD_URL="https://fcd.cosmos.dev/" \
COSMOS_TENDERMINT_URL="<tendermint url>" \
COSMOS_NETWORK_NAME="cosmos-devnet" \
COSMOS_NETWORK_ID="cosmos-devnet" \
COSMOS_CHAIN_ID="1" \
COSMOS_READ_TIMEOUT="15s" \
COSMOS_POLL_INTERVAL="5s" \
COSMOS_LINK_TOKEN_ADDRESS="terra1eq0xqc88ceuvw2ztz2a08200he8lrgvnplrcst" \
COSMOS_LINK_TOKEN_ADDRESS="wasm12fykm2xhg5ces2vmf4q2aem8c958exv3v0wmvrspa8zucrdwjedsjax9ms" \
COSMOS_BECH32_PREFIX="wasm" \
COSMOS_GAS_TOKEN="ucosm" \
KAFKA_BROKERS="localhost:29092" \
KAFKA_CLIENT_ID=“terra” \
KAFKA_SECURITY_PROTOCOL="PLAINTEXT" \
KAFKA_CLIENT_ID="cosmos" \
KAFKA_SECURITY_PROTOCOL="SASL_PLAINTEXT" \
KAFKA_SASL_MECHANISM="PLAIN" \
KAFKA_SASL_USERNAME="" \
KAFKA_SASL_PASSWORD="" \
KAFKA_SASL_USERNAME="user" \
KAFKA_SASL_PASSWORD="pass" \
KAFKA_TRANSMISSION_TOPIC="transmission_topic" \
KAFKA_CONFIG_SET_SIMPLIFIED_TOPIC="config_set_simplified" \
SCHEMA_REGISTRY_URL="http://localhost:8989" \
Expand All @@ -27,6 +72,19 @@ FEEDS_URL="http://localhost:4000/feeds.json" \
go run ./cmd/monitoring/main.go
```

- Check the output for the Prometheus scraper

```bash
curl http://localhost:3000/metrics
```

- To check the output for Kafka, you need to install [kcat](https://github.com/edenhill/kcat). After you install, run:

```bash
kcat -b localhost:29092 -t config_set_simplified
kcat -b localhost:29092 -t transmission_topic
```

## Example of feed configurations returned by weiwatchers.com

```json
Expand Down
23 changes: 17 additions & 6 deletions cmd/monitoring/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package main
import (
"context"
"log"
"os"

"github.com/smartcontractkit/chainlink-relay/pkg/logger"

"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
"github.com/smartcontractkit/chainlink-cosmos/pkg/monitoring"
"github.com/smartcontractkit/chainlink-relay/pkg/logger"
)

func main() {
Expand All @@ -22,17 +24,26 @@ func main() {
}
}()

bech32Prefix := "wasm"
gasToken := "ucosm"
if value, isPresent := os.LookupEnv("COSMOS_BECH32_PREFIX"); isPresent {
bech32Prefix = value
}
if value, isPresent := os.LookupEnv("COSMOS_GAS_TOKEN"); isPresent {
gasToken = value
}
// note: need to register bech32 prefix before parsing config to ensure AccAddressFromBech32 returns a correctly prefixed address
params.InitCosmosSdk(
bech32Prefix,
gasToken,
)

cosmosConfig, err := monitoring.ParseCosmosConfig()
if err != nil {
l.Fatalw("failed to parse cosmos specific configuration", "error", err)
return
}

params.InitCosmosSdk(
cosmosConfig.Bech32Prefix,
cosmosConfig.GasToken,
)

monitor, err := monitoring.NewCosmosMonitor(ctx, cosmosConfig, l)
if err != nil {
l.Fatalw("failed to create new cosmos monitor", "error", err)
Expand Down
21 changes: 11 additions & 10 deletions integration-tests/common/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,33 @@ import (

"github.com/google/uuid"
"github.com/lib/pq"
"github.com/rs/zerolog/log"
"github.com/rs/zerolog"
"gopkg.in/guregu/null.v4"

"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
"github.com/smartcontractkit/chainlink-env/environment"
"github.com/smartcontractkit/chainlink/integration-tests/client"
"github.com/smartcontractkit/chainlink/v2/core/services/job"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"

"github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/params"
)

type ChainlinkClient struct {
bech32Prefix string
ChainlinkNodes []*client.ChainlinkClient
NodeKeys []client.NodeKeysBundle
bTypeAttr *client.BridgeTypeAttributes
// bTypeAttr *client.BridgeTypeAttributes
bootstrapPeers []client.P2PData
}

// TODO: Remove env. See https://github.com/smartcontractkit/chainlink-cosmos/pull/350#discussion_r1298071289
// CreateKeys Creates node keys and defines chain and nodes for each node
func NewChainlinkClient(env *environment.Environment, nodeName string, chainId string, tendermintURL string, bech32Prefix string) (*ChainlinkClient, error) {
nodes, err := connectChainlinkNodes(env)
func NewChainlinkClient(env *environment.Environment, nodeName string, chainId string, tendermintURL string, bech32Prefix string, logger zerolog.Logger) (*ChainlinkClient, error) {
nodes, err := connectChainlinkNodes(env, logger)
if err != nil {
return nil, err
}
if nodes == nil || len(nodes) == 0 {
if len(nodes) == 0 {
return nil, errors.New("No connected nodes")
}

Expand All @@ -42,7 +43,7 @@ func NewChainlinkClient(env *environment.Environment, nodeName string, chainId s
return nil, err
}

if nodeKeys == nil || len(nodeKeys) == 0 {
if len(nodeKeys) == 0 {
return nil, errors.New("No node keys")
}

Expand Down Expand Up @@ -185,19 +186,19 @@ func (cc *ChainlinkClient) CreateJobsForContract(chainId, nodeName, p2pPort, moc
// connectChainlinkNodes creates a chainlink client for each node in the environment
// This is a non k8s version of the function in chainlink_k8s.go
// https://github.com/smartcontractkit/chainlink/blob/cosmos-test-keys/integration-tests/client/chainlink_k8s.go#L77
func connectChainlinkNodes(e *environment.Environment) ([]*client.ChainlinkClient, error) {
func connectChainlinkNodes(e *environment.Environment, logger zerolog.Logger) ([]*client.ChainlinkClient, error) {
var clients []*client.ChainlinkClient
for _, nodeDetails := range e.ChainlinkNodeDetails {
c, err := client.NewChainlinkClient(&client.ChainlinkConfig{
URL: nodeDetails.LocalIP,
Email: "[email protected]",
Password: "fj293fbBnlQ!f9vNs",
InternalIP: parseHostname(nodeDetails.InternalIP),
})
}, logger)
if err != nil {
return nil, err
}
log.Debug().
logger.Debug().
Str("URL", c.Config.URL).
Str("Internal IP", c.Config.InternalIP).
Str("Chart Name", nodeDetails.ChartName).
Expand Down
4 changes: 2 additions & 2 deletions integration-tests/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ func NewCommon(t *testing.T) *Common {
Enabled = true
ChainID = '%s'
Bech32Prefix = 'wasm'
FeeToken = 'ucosm'
GasToken = 'ucosm'

[[Cosmos.Nodes]]
Name = 'primary'
Expand Down Expand Up @@ -168,7 +168,7 @@ HTTPSPort = 0
TTL: getTTL(),
TestDuration: getTestDuration(),
NodeUrl: nodeUrl,
MockUrl: "http://172.17.0.1:6060",
MockUrl: "http://host.docker.internal:6060",
Mnemonic: getEnv("MNEMONIC"),
ObservationSource: observationSource,
JuelsPerFeeCoinSource: juelsPerFeeCoinSource,
Expand Down
11 changes: 8 additions & 3 deletions integration-tests/common/monitor_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"log"
"net/http"
"testing"
"time"

"github.com/stretchr/testify/require"
)

func RunHTTPServer(t *testing.T, serverName, serverAddress string, responses map[string][]byte) *http.Server {
Expand All @@ -13,13 +16,15 @@ func RunHTTPServer(t *testing.T, serverName, serverAddress string, responses map
handler.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s received request for %s\n", serverName, path)
w.Header().Set("Content-Type", "application/octet-stream")
w.Write(response)
_, err := w.Write(response)
require.NoError(t, err, "failed to write response")
})
}

server := &http.Server{
Addr: serverAddress,
Handler: handler,
Addr: serverAddress,
Handler: handler,
ReadHeaderTimeout: 10 * time.Second,
}

go func() {
Expand Down
Loading