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

Node status API dockerfile and env vars #4986

Merged
merged 9 commits into from
Oct 18, 2024
Merged
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
55 changes: 55 additions & 0 deletions .github/workflows/push-node-status-api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Build and upload Node Status API container to harbor.nymte.ch
on:
workflow_dispatch:

env:
WORKING_DIRECTORY: "nym-node-status-api"
CONTAINER_NAME: "node-status-api"

jobs:
build-container:
runs-on: arc-ubuntu-22.04-dind
steps:
- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: harbor.nymte.ch
username: ${{ secrets.HARBOR_ROBOT_USERNAME }}
password: ${{ secrets.HARBOR_ROBOT_SECRET }}

- name: Checkout repo
uses: actions/checkout@v4

- name: Configure git identity
run: |
git config --global user.email "[email protected]"
git config --global user.name "Lawrence Stalder"

- name: Get version from cargo.toml
uses: mikefarah/[email protected]
id: get_version
with:
cmd: yq -oy '.package.version' ${{ env.WORKING_DIRECTORY }}/Cargo.toml

- name: Check if tag exists
run: |
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
echo "Tag ${{ steps.get_version.outputs.result }} already exists"
fi

- name: Remove existing tag if exists
run: |
if git rev-parse ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} >/dev/null 2>&1; then
git push --delete origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
git tag -d ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}
fi

- name: Create tag
run: |
git tag -a ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }} -m "Version ${{ steps.get_version.outputs.result }}"
git push origin ${{ env.WORKING_DIRECTORY }}-${{ steps.get_version.outputs.result }}

- name: BuildAndPushImageOnHarbor
run: |
docker build -f ${{ env.WORKING_DIRECTORY }}/Dockerfile . -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:${{ steps.get_version.outputs.result }} -t harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }}:latest
docker push harbor.nymte.ch/nym/${{ env.CONTAINER_NAME }} --all-tags
6 changes: 3 additions & 3 deletions envs/mainnet.env
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ COCONUT_DKG_CONTRACT_ADDRESS=n19604yflqggs9mk2z26mqygq43q2kr3n932egxx630svywd5mp

REWARDING_VALIDATOR_ADDRESS=n10yyd98e2tuwu0f7ypz9dy3hhjw7v772q6287gy
STATISTICS_SERVICE_DOMAIN_ADDRESS="https://mainnet-stats.nymte.ch:8090"
NYXD="https://rpc.nymtech.net"
NYM_API="https://validator.nymtech.net/api/"
NYXD=https://rpc.nymtech.net
NYM_API=https://validator.nymtech.net/api/
NYXD_WS="wss://rpc.nymtech.net/websocket"
EXPLORER_API="https://explorer.nymtech.net/api/"
EXPLORER_API=https://explorer.nymtech.net/api/
NYM_VPN_API="https://nymvpn.com/api"
11 changes: 8 additions & 3 deletions nym-node-status-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ rust-version.workspace = true
anyhow = { workspace = true }
axum = { workspace = true, features = ["tokio"] }
chrono = { workspace = true }
clap = { workspace = true, features = ["cargo", "derive"] }
clap = { workspace = true, features = ["cargo", "derive", "env", "string"] }
cosmwasm-std = { workspace = true }
envy = { workspace = true }
futures-util = { workspace = true }
Expand Down Expand Up @@ -53,5 +53,10 @@ utoipauto = { workspace = true }

[build-dependencies]
anyhow = { workspace = true }
tokio = { workspace = true, features = ["macros" ] }
sqlx = { workspace = true, features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
tokio = { workspace = true, features = ["macros"] }
sqlx = { workspace = true, features = [
"runtime-tokio-rustls",
"sqlite",
"macros",
"migrate",
] }
15 changes: 15 additions & 0 deletions nym-node-status-api/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM rust:latest AS builder

COPY ./ /usr/src/nym
WORKDIR /usr/src/nym/nym-node-status-api

RUN cargo build --release

FROM ubuntu:24.04

RUN apt-get update && apt-get install -y ca-certificates

WORKDIR /nym

COPY --from=builder /usr/src/nym/target/release/nym-node-status-api ./
ENTRYPOINT [ "/nym/nym-node-status-api" ]
14 changes: 11 additions & 3 deletions nym-node-status-api/launch_node_status_api.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,15 @@ set -e

export RUST_LOG=${RUST_LOG:-debug}

export NYM_API_CLIENT_TIMEOUT=60;
export EXPLORER_CLIENT_TIMEOUT=60;
export NYM_API_CLIENT_TIMEOUT=60
export EXPLORER_CLIENT_TIMEOUT=60
#export NYXD=https://rpc.nymtech.net
#export NYM_API=https://validator.nymtech.net/api/
#export EXPLORER_API=https://explorer.nymtech.net/api/
#export NETWORK_NAME=mainnet

cargo run --package nym-node-status-api --release -- --config-env-file ../envs/mainnet.env
#cargo run --package nym-node-status-api --release -- --connection-url "sqlite://node-status-api.sqlite?mode=rwc"

cd ..
docker build -t node-status-api -f nym-node-status-api/Dockerfile .
docker run --env-file envs/mainnet.env -e NYM_NODE_STATUS_API_CONNECTION_URL="sqlite://node-status-api.sqlite?mode=rwc" node-status-api
62 changes: 57 additions & 5 deletions nym-node-status-api/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,69 @@
use clap::Parser;
use nym_bin_common::bin_info;
use std::sync::OnceLock;
use reqwest::Url;
use std::{sync::OnceLock, time::Duration};

// Helper for passing LONG_VERSION to clap
fn pretty_build_info_static() -> &'static str {
static PRETTY_BUILD_INFORMATION: OnceLock<String> = OnceLock::new();
PRETTY_BUILD_INFORMATION.get_or_init(|| bin_info!().pretty_print())
}

#[derive(Parser, Debug)]
#[derive(Clone, Debug, Parser)]
#[clap(author = "Nymtech", version, long_version = pretty_build_info_static(), about)]
pub(crate) struct Cli {
/// Path pointing to an env file that configures the Nym API.
#[clap(short, long)]
pub(crate) config_env_file: Option<std::path::PathBuf>,
/// Network name for the network to which we're connecting.
#[clap(long, env = "NETWORK_NAME")]
pub(crate) network_name: String,

/// Explorer api url.
#[clap(short, long, env = "EXPLORER_API")]
pub(crate) explorer_api: String,

/// Nym api url.
#[clap(short, long, env = "NYM_API")]
pub(crate) nym_api: String,

/// TTL for the http cache.
#[clap(
long,
default_value_t = 30,
env = "NYM_NODE_STATUS_API_NYM_HTTP_CACHE_TTL"
)]
pub(crate) nym_http_cache_ttl: u64,

/// HTTP port on which to run node status api.
#[clap(long, default_value_t = 8000, env = "NYM_NODE_STATUS_API_HTTP_PORT")]
pub(crate) http_port: u16,

/// Nyxd address.
#[clap(long, env = "NYXD")]
pub(crate) nyxd_addr: Url,

/// Nym api client timeout.
#[clap(
long,
default_value = "15",
env = "NYM_NODE_STATUS_API_NYM_API_CLIENT_TIMEOUT"
)]
#[arg(value_parser = parse_duration)]
pub(crate) nym_api_client_timeout: Duration,

/// Explorer api client timeout.
#[clap(
long,
default_value = "15",
env = "NYM_NODE_STATUS_API_EXPLORER_CLIENT_TIMEOUT"
)]
#[arg(value_parser = parse_duration)]
pub(crate) explorer_client_timeout: Duration,

/// Connection url for the database.
#[clap(long, env = "NYM_NODE_STATUS_API_CONNECTION_URL")]
pub(crate) connection_url: String,
}

fn parse_duration(arg: &str) -> Result<std::time::Duration, std::num::ParseIntError> {
let seconds = arg.parse()?;
Ok(std::time::Duration::from_secs(seconds))
}
72 changes: 0 additions & 72 deletions nym-node-status-api/src/config.rs

This file was deleted.

5 changes: 1 addition & 4 deletions nym-node-status-api/src/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use std::str::FromStr;

use crate::read_env_var;
use anyhow::{anyhow, Result};
use sqlx::{migrate::Migrator, sqlite::SqliteConnectOptions, ConnectOptions, SqlitePool};

pub(crate) mod models;
pub(crate) mod queries;

pub(crate) const DATABASE_URL_ENV_VAR: &str = "DATABASE_URL";
static MIGRATOR: Migrator = sqlx::migrate!("./migrations");

pub(crate) type DbPool = SqlitePool;
Expand All @@ -17,8 +15,7 @@ pub(crate) struct Storage {
}

impl Storage {
pub async fn init() -> Result<Self> {
let connection_url = read_env_var(DATABASE_URL_ENV_VAR)?;
pub async fn init(connection_url: String) -> Result<Self> {
let connect_options = {
let connect_options = SqliteConnectOptions::from_str(&connection_url)?;
let mut connect_options = connect_options.create_if_missing(true);
Expand Down
26 changes: 8 additions & 18 deletions nym-node-status-api/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
use clap::Parser;
use nym_network_defaults::setup_env;
use nym_task::signal::wait_for_signal;

use crate::config::read_env_var;

mod cli;
mod config;
mod db;
mod http;
mod logging;
Expand All @@ -16,33 +12,27 @@ async fn main() -> anyhow::Result<()> {
logging::setup_tracing_logger();

let args = cli::Cli::parse();
// if dotenv file is present, load its values
// otherwise, default to mainnet
setup_env(args.config_env_file.as_ref());
tracing::debug!("{:?}", read_env_var("NETWORK_NAME"));
tracing::debug!("{:?}", read_env_var("EXPLORER_API"));
tracing::debug!("{:?}", read_env_var("NYM_API"));

let conf = config::Config::from_env()?;
tracing::debug!("Using config:\n{:#?}", conf);
let connection_url = args.connection_url.clone();
tracing::debug!("Using config:\n{:#?}", args);

let storage = db::Storage::init().await?;
let storage = db::Storage::init(connection_url).await?;
let db_pool = storage.pool_owned().await;
let conf_clone = conf.clone();
let args_clone = args.clone();
tokio::spawn(async move {
monitor::spawn_in_background(db_pool, conf_clone).await;
monitor::spawn_in_background(db_pool, args_clone).await;
});
tracing::info!("Started monitor task");

let shutdown_handles = http::server::start_http_api(
storage.pool_owned().await,
conf.http_port(),
conf.nym_http_cache_ttl(),
args.http_port,
args.nym_http_cache_ttl,
)
.await
.expect("Failed to start server");

tracing::info!("Started HTTP server on port {}", conf.http_port());
tracing::info!("Started HTTP server on port {}", args.http_port);

wait_for_signal().await;

Expand Down
14 changes: 6 additions & 8 deletions nym-node-status-api/src/monitor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::config::Config;
use crate::cli::Cli;
use crate::db::models::{
gateway, mixnode, GatewayRecord, MixnodeRecord, NetworkSummary, GATEWAYS_BLACKLISTED_COUNT,
GATEWAYS_BONDED_COUNT, GATEWAYS_EXPLORER_COUNT, GATEWAYS_HISTORICAL_COUNT,
Expand Down Expand Up @@ -29,7 +29,7 @@ static DELEGATION_PROGRAM_WALLET: &str = "n1rnxpdpx3kldygsklfft0gech7fhfcux4zst5

// TODO dz: query many NYM APIs:
// multiple instances running directory cache, ask sachin
pub(crate) async fn spawn_in_background(db_pool: DbPool, config: Config) -> JoinHandle<()> {
pub(crate) async fn spawn_in_background(db_pool: DbPool, config: Cli) -> JoinHandle<()> {
let network_defaults = nym_network_defaults::NymNetworkDetails::new_from_env();

loop {
Expand All @@ -54,7 +54,7 @@ pub(crate) async fn spawn_in_background(db_pool: DbPool, config: Config) -> Join
async fn run(
pool: &DbPool,
network_details: &NymNetworkDetails,
config: &Config,
config: &Cli,
) -> anyhow::Result<()> {
let default_api_url = network_details
.endpoints
Expand All @@ -70,10 +70,8 @@ async fn run(

let default_explorer_url =
default_explorer_url.expect("explorer url missing in network config");
let explorer_client = ExplorerClient::new_with_timeout(
default_explorer_url,
config.nym_explorer_client_timeout(),
)?;
let explorer_client =
ExplorerClient::new_with_timeout(default_explorer_url, config.explorer_client_timeout)?;
let explorer_gateways = explorer_client
.get_gateways()
.await
Expand Down Expand Up @@ -126,7 +124,7 @@ async fn run(
.await
.log_error("get_active_mixnodes")?;
let delegation_program_members =
get_delegation_program_details(network_details, config.nyxd_addr()).await?;
get_delegation_program_details(network_details, &config.nyxd_addr).await?;

// keep stats for later
let count_bonded_mixnodes = mixnodes.len();
Expand Down