Skip to content

Commit

Permalink
feat(swarm)!: allow swarm to override public urls (#1295)
Browse files Browse the repository at this point in the history
Description
---
feat(swarm): allow swarm to override public urls
Better and more descriptive names for cli and config options

Motivation and Context
---
Public deployments of swarm need to specify the full URL for public
services. Mainly for https:// purposes.

How Has This Been Tested?
---
Manually, only tested that it still works as before in a non-public
context

What process can a PR reviewer use to test or verify this change?
---


Breaking Changes
---

- [ ] None
- [ ] Requires data directory to be deleted
- [x] Other - Please specify

BREAKING CHANGES: config names and cli flags relating to public urls
have changed
  • Loading branch information
sdbondi authored Feb 18, 2025
1 parent 9a0747d commit be3a03b
Show file tree
Hide file tree
Showing 22 changed files with 119 additions and 85 deletions.
10 changes: 5 additions & 5 deletions applications/tari_dan_wallet_daemon/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ pub struct Cli {
pub common: CommonCliArgs,
#[clap(long, alias = "endpoint", env = "JRPC_ENDPOINT")]
pub json_rpc_address: Option<SocketAddr>,
#[clap(long, env = "TARI_DAN_WALLET_UI_CONNECT_ADDRESS")]
pub ui_connect_address: Option<String>,
#[clap(long, env = "TARI_WALLET_WEB_UI_JSON_RPC_PUBLIC_URL")]
pub web_ui_public_json_rpc_url: Option<String>,
#[clap(long, env = "SIGNALING_SERVER_ADDRESS")]
pub signaling_server_address: Option<SocketAddr>,
#[clap(long, short = 'i', alias = "indexer-url")]
Expand All @@ -62,10 +62,10 @@ impl ConfigOverrideProvider for Cli {
json_rpc_address.to_string(),
));
}
if let Some(ref ui_connect_address) = self.ui_connect_address {
if let Some(ref json_rpc_url) = self.web_ui_public_json_rpc_url {
overrides.push((
"dan_wallet_daemon.ui_connect_address".to_string(),
ui_connect_address.to_string(),
"dan_wallet_daemon.web_ui_public_json_rpc_url".to_string(),
json_rpc_url.to_string(),
));
}
if let Some(ref signaling_server_address) = self.signaling_server_address {
Expand Down
7 changes: 3 additions & 4 deletions applications/tari_dan_wallet_daemon/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,8 @@ pub struct WalletDaemonConfig {
pub network: Network,
/// The wallet daemon listening address
pub json_rpc_address: Option<SocketAddr>,
/// The jrpc address where the UI should connect (it can be the same as the json_rpc_addr, but doesn't have to be),
/// if this will be None, then the listen_addr will be used.
pub ui_connect_address: Option<String>,
/// The public URL to JSON-RPC server used by the web UI. If not specified, the json_rpc_address is used.
pub web_ui_public_json_rpc_url: Option<String>,
/// The signaling server address for the webrtc
pub signaling_server_address: Option<SocketAddr>,
/// The indexer JSON-RPC url
Expand All @@ -85,7 +84,7 @@ impl Default for WalletDaemonConfig {
override_from: None,
network: Network::Igor,
json_rpc_address: Some(SocketAddr::from(([127u8, 0, 0, 1], 9000))),
ui_connect_address: None,
web_ui_public_json_rpc_url: None,
signaling_server_address: Some(SocketAddr::from(([127u8, 0, 0, 1], 9100))),
indexer_json_rpc_url: "http://127.0.0.1:18300/json_rpc"
.parse()
Expand Down
12 changes: 6 additions & 6 deletions applications/tari_dan_wallet_daemon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,16 +91,16 @@ pub async fn run_tari_dan_wallet_daemon(

// Run the http ui
if let Some(web_listener_address) = config.dan_wallet_daemon.web_ui_address {
let mut public_jrpc_address = config
let mut public_jrpc_url = config
.dan_wallet_daemon
.ui_connect_address
.web_ui_public_json_rpc_url
.unwrap_or_else(|| jrpc_address.to_string());
if !public_jrpc_address.starts_with("http://") && !public_jrpc_address.starts_with("https://") {
public_jrpc_address = format!("http://{}", public_jrpc_address);
if !public_jrpc_url.starts_with("http://") && !public_jrpc_url.starts_with("https://") {
public_jrpc_url = format!("http://{}", public_jrpc_url);
}

let public_jrpc_address = url::Url::parse(&public_jrpc_address)?;
task::spawn(run_http_ui_server(web_listener_address, public_jrpc_address));
let public_jrpc_url = url::Url::parse(&public_jrpc_url)?;
task::spawn(run_http_ui_server(web_listener_address, public_jrpc_url));
}

if let Err(e) = fs::write(config.common.base_path.join("pid"), process::id().to_string()) {
Expand Down
11 changes: 7 additions & 4 deletions applications/tari_indexer/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ pub struct Cli {
#[clap(long)]
pub disable_mdns: bool,
/// Public address of the Web UI
#[clap(long, env = "TARI_INDEXER_UI_CONNECT_ADDRESS")]
pub ui_connect_address: Option<String>,
#[clap(long, env = "TARI_INDEXER_WEB_UI_PUBLIC_JSON_RPC_URL")]
pub web_ui_public_json_rpc_url: Option<String>,
}

impl Cli {
Expand Down Expand Up @@ -90,8 +90,11 @@ impl ConfigOverrideProvider for Cli {
if let Some(seconds) = self.dan_layer_scanning_internal {
overrides.push(("indexer.dan_layer_scanning_interval".to_string(), seconds.to_string()));
}
if let Some(ref ui_connect_address) = self.ui_connect_address {
overrides.push(("indexer.ui_connect_address".to_string(), ui_connect_address.to_string()));
if let Some(ref json_rpc_url) = self.web_ui_public_json_rpc_url {
overrides.push((
"indexer.web_ui_public_json_rpc_url".to_string(),
json_rpc_url.to_string(),
));
}
if let Some(reachability) = self.reachability {
overrides.push(("indexer.p2p.reachability_mode".to_string(), reachability.to_string()));
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_indexer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub struct IndexerConfig {
pub web_ui_address: Option<SocketAddr>,
/// The jrpc address where the UI should connect (it can be the same as the json_rpc_address, but doesn't have to
/// be), if this will be None, then the listen_addr will be used.
pub ui_connect_address: Option<String>,
pub web_ui_public_json_rpc_url: Option<String>,
/// How often do we want to scan the second layer for new versions
#[serde(with = "serializers::seconds")]
pub dan_layer_scanning_internal: Duration,
Expand Down Expand Up @@ -130,7 +130,7 @@ impl Default for IndexerConfig {
json_rpc_address: Some("127.0.0.1:18300".parse().unwrap()),
graphql_address: Some("127.0.0.1:18301".parse().unwrap()),
web_ui_address: Some("127.0.0.1:15000".parse().unwrap()),
ui_connect_address: None,
web_ui_public_json_rpc_url: None,
dan_layer_scanning_internal: Duration::from_secs(10),
templates: TemplateConfig::default(),
sidechain_id: None,
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_indexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,14 @@ pub async fn run_indexer(config: ApplicationConfig, mut shutdown_signal: Shutdow
if let Some(address) = config.indexer.web_ui_address {
let mut public_jrpc_address = config
.indexer
.ui_connect_address
.web_ui_public_json_rpc_url
.unwrap_or_else(|| jrpc_address.to_string());
if !public_jrpc_address.starts_with("http://") && !public_jrpc_address.starts_with("https://") {
public_jrpc_address = format!("http://{}", public_jrpc_address);
}

let public_jrpc_address = url::Url::parse(&public_jrpc_address)
.map_err(|err| ExitError::new(ExitCode::ConfigError, format!("Invalid ui_connect_address: {err}")))?;
.map_err(|err| ExitError::new(ExitCode::ConfigError, format!("Invalid public JSON-rpc url: {err}")))?;
task::spawn(run_http_ui_server(address, public_jrpc_address));
}
}
Expand Down
7 changes: 2 additions & 5 deletions applications/tari_swarm_daemon/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ pub struct Config {
pub base_dir: PathBuf,
pub start_port: u16,
pub network: Network,
pub settings: Option<HashMap<String, String>>,
#[serde(default)]
pub settings: HashMap<String, String>,
pub webserver: WebserverConfig,
#[serde(flatten)]
pub processes: ProcessesConfig,
Expand Down Expand Up @@ -64,10 +65,6 @@ impl Config {
Ok(())
}

pub fn get_public_ip(&self) -> IpAddr {
self.public_ip.unwrap_or_else(|| [127, 0, 0, 1].into())
}

fn overrides_from_cli(&mut self, cli: &Cli) {
if let Commands::Start(ref overrides) = cli.command {
self.skip_registration = overrides.skip_registration;
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_swarm_daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ fn get_base_config(cli: &Cli) -> anyhow::Result<Config> {
Ok(Config {
skip_registration: false,
network: cli.common.network.unwrap_or(Network::LocalNet),
settings: Some(HashMap::new()),
settings: HashMap::new(),
start_port: 12000,
base_dir: base_dir
.canonicalize()
Expand Down
19 changes: 19 additions & 0 deletions applications/tari_swarm_daemon/src/process_definitions/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use std::{collections::HashMap, net::IpAddr, path::PathBuf};

use tari_common::configuration::Network;
use url::Url;

use crate::process_manager::{
AllocatedPorts,
Expand Down Expand Up @@ -79,6 +80,24 @@ impl<'a> ProcessContext<'a> {
self.settings.get(key).map(|s| s.as_str())
}

pub fn get_public_json_rpc_url(&self) -> Url {
match self.settings.get("public_json_rpc_url") {
Some(url) => url.parse().expect("Invalid JSON RPC URL"),
None => {
let public_ip = self
.settings
.get("public_ip")
.map(|s| s.as_str())
.unwrap_or("127.0.0.1");
let port = self
.port_allocator
.get("jrpc")
.expect("JSON-rpc port must be allocated before calling get_public_json_rpc_url");
format!("http://{public_ip}:{port}").parse().expect("Invalid web URL")
},
}
}

pub async fn get_free_port(&mut self, name: &'static str) -> anyhow::Result<u16> {
Ok(self.port_allocator.get_or_next_port(name).await)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ impl ProcessDefinition for Indexer {
let jrpc_port = context.get_free_port("jrpc").await?;
let web_ui_port = context.get_free_port("web").await?;
let listen_ip = context.listen_ip();
let public_ip = context.get_setting("public_ip").unwrap_or("127.0.0.1");

let json_rpc_public_address = format!("{public_ip}:{jrpc_port}");
let json_rpc_public_url = context.get_public_json_rpc_url();
let json_rpc_listener_address = format!("{listen_ip}:{jrpc_port}");
let web_ui_listener_address = format!("{listen_ip}:{web_ui_port}");

Expand All @@ -54,7 +53,7 @@ impl ProcessDefinition for Indexer {
))
.arg(format!("-pindexer.json_rpc_address={json_rpc_listener_address}"))
.arg(format!("-pindexer.web_ui_address={web_ui_listener_address}"))
.arg(format!("-pindexer.ui_connect_address={json_rpc_public_address}"))
.arg(format!("-pindexer.web_ui_public_json_rpc_url={json_rpc_public_url}"))
.arg("-pepoch_oracle.base_layer.scanning_interval=1");

Ok(command)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,9 @@ impl ProcessDefinition for ValidatorNode {
let jrpc_port = context.get_free_port("jrpc").await?;
let web_ui_port = context.get_free_port("web").await?;
let listen_ip = context.listen_ip();
let public_ip = context.get_setting("public_ip").unwrap_or("127.0.0.1");

let json_rpc_address = format!("{listen_ip}:{jrpc_port}");
let json_rpc_public_address = format!("{public_ip}:{jrpc_port}");
let json_rpc_public_url = context.get_public_json_rpc_url();
let web_ui_address = format!("{listen_ip}:{web_ui_port}");

let base_node = context
Expand Down Expand Up @@ -60,7 +59,7 @@ impl ProcessDefinition for ValidatorNode {
.arg(context.base_path())
.arg("--network")
.arg(context.network().to_string())
.arg(format!("--json-rpc-public-address={json_rpc_public_address}"))
.arg(format!("--json-rpc-public-url={json_rpc_public_url}"))
.arg(format!(
"-pepoch_oracle.base_layer.base_node_grpc_url={base_node_grpc_url}"
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,8 @@ impl ProcessDefinition for WalletDaemon {
let jrpc_port = context.get_free_port("jrpc").await?;
let web_ui_port = context.get_free_port("web").await?;
let listen_ip = context.listen_ip();
let public_ip = context.get_setting("public_ip").unwrap_or("127.0.0.1");

let json_rpc_public_address = format!("{public_ip}:{jrpc_port}");
let json_rpc_public_url = context.get_public_json_rpc_url();
let json_rpc_address = format!("{listen_ip}:{jrpc_port}");
let web_ui_address = format!("{listen_ip}:{web_ui_port}");

Expand All @@ -52,7 +51,7 @@ impl ProcessDefinition for WalletDaemon {
.arg(context.network().to_string())
.arg(format!("--json-rpc-address={json_rpc_address}"))
.arg(format!("--indexer-url={indexer_url}"))
.arg(format!("--ui-connect-address={json_rpc_public_address}"))
.arg(format!("--web-ui-public-json-rpc-url={json_rpc_public_url}"))
.arg(format!("-pdan_wallet_daemon.web_ui_address={web_ui_address}"));

// A signaling server is not required for startup of the wallet daemon,
Expand Down
38 changes: 38 additions & 0 deletions applications/tari_swarm_daemon/src/process_manager/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,46 @@ pub struct InstanceInfo {
pub ports: AllocatedPorts,
pub base_path: PathBuf,
pub instance_type: InstanceType,
pub settings: HashMap<String, String>,
pub is_running: bool,
}

impl InstanceInfo {
pub fn get_public_web_url(&self) -> Url {
match self.settings.get("public_web_url") {
Some(url) => url.parse().expect("Invalid web URL"),
None => {
let public_ip = self
.settings
.get("public_ip")
.map(|s| s.as_str())
.unwrap_or("127.0.0.1");
let web_port = self.ports.get("web").expect("web port not found");
format!("http://{public_ip}:{web_port}")
.parse()
.expect("Invalid web URL")
},
}
}

pub fn get_public_json_rpc_url(&self) -> Url {
match self.settings.get("public_json_rpc_url") {
Some(url) => url.parse().expect("Invalid JSON RPC URL"),
None => {
let public_ip = self
.settings
.get("public_ip")
.map(|s| s.as_str())
.unwrap_or("127.0.0.1");
let web_port = self.ports.get("jrpc").expect("jrpc port not found");
format!("http://{public_ip}:{web_port}/json_rpc")
.parse()
.expect("Invalid web URL")
},
}
}
}

impl From<&Instance> for InstanceInfo {
fn from(instance: &Instance) -> Self {
Self {
Expand All @@ -87,6 +124,7 @@ impl From<&Instance> for InstanceInfo {
ports: instance.allocated_ports().clone(),
base_path: instance.base_path().clone(),
instance_type: instance.instance_type(),
settings: instance.settings().clone(),
is_running: instance.is_running(),
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl ProcessManager {
pub fn new(config: &Config, shutdown_signal: ShutdownSignal) -> (Self, ProcessManagerHandle) {
let (tx_request, rx_request) = mpsc::channel(1);

let mut global_settings = config.settings.clone().unwrap_or_default();
let mut global_settings = config.settings.clone();
if let Some(public_ip) = config.public_ip {
global_settings.insert("public_ip".to_string(), public_ip.to_string());
}
Expand Down
16 changes: 5 additions & 11 deletions applications/tari_swarm_daemon/src/webserver/rpc/dan_wallets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

use std::collections::HashMap;

use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::{config::InstanceType, process_manager::InstanceId, webserver::context::HandlerContext};

Expand All @@ -20,8 +20,8 @@ pub struct ListDanWalletsResponse {
pub struct DanWalletInfo {
pub instance_id: InstanceId,
pub name: String,
pub web: String,
pub jrpc: String,
pub web: Url,
pub jrpc: Url,
pub is_running: bool,
}

Expand All @@ -30,18 +30,12 @@ pub async fn list(
_req: ListDanWalletsRequest,
) -> Result<ListDanWalletsResponse, anyhow::Error> {
let instances = context.process_manager().list_wallet_daemons().await?;
let public_ip = context.config().get_public_ip();

let nodes = instances
.into_iter()
.map(|instance| {
let web_port = instance.ports.get("web").ok_or_else(|| anyhow!("web port not found"))?;
let json_rpc_port = instance
.ports
.get("jrpc")
.ok_or_else(|| anyhow!("jrpc port not found"))?;
let web = format!("http://{public_ip}:{web_port}");
let jrpc = format!("http://{public_ip}:{json_rpc_port}");
let web = instance.get_public_web_url();
let jrpc = instance.get_public_json_rpc_url();

Ok(DanWalletInfo {
instance_id: instance.id,
Expand Down
16 changes: 5 additions & 11 deletions applications/tari_swarm_daemon/src/webserver/rpc/indexers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

use std::collections::HashMap;

use anyhow::anyhow;
use serde::{Deserialize, Serialize};
use url::Url;

use crate::{config::InstanceType, process_manager::InstanceId, webserver::context::HandlerContext};

Expand All @@ -20,25 +20,19 @@ pub struct ListIndexersResponse {
pub struct IndexerInfo {
pub instance_id: InstanceId,
pub name: String,
pub web: String,
pub jrpc: String,
pub web: Url,
pub jrpc: Url,
pub is_running: bool,
}

pub async fn list(context: &HandlerContext, _req: ListIndexersRequest) -> Result<ListIndexersResponse, anyhow::Error> {
let instances = context.process_manager().list_indexers().await?;
let public_ip = context.config().get_public_ip();

let nodes = instances
.into_iter()
.map(|instance| {
let web_port = instance.ports.get("web").ok_or_else(|| anyhow!("web port not found"))?;
let json_rpc_port = instance
.ports
.get("jrpc")
.ok_or_else(|| anyhow!("jrpc port not found"))?;
let web = format!("http://{public_ip}:{web_port}");
let jrpc = format!("http://{public_ip}:{json_rpc_port}");
let jrpc = instance.get_public_json_rpc_url();
let web = instance.get_public_web_url();

Ok(IndexerInfo {
instance_id: instance.id,
Expand Down
Loading

0 comments on commit be3a03b

Please sign in to comment.