WIP on implementing redirect
Refactors brain connection logic to use custom endpoint while runtime Implements redirect handling in the `create_vm` function to gracefully handle server moves by reconnecting to the new URL
This commit is contained in:
parent
51d50ff496
commit
41d9bd104f
@ -309,20 +309,22 @@ impl Config {
|
|||||||
|
|
||||||
pub fn get_brain_info() -> (String, String) {
|
pub fn get_brain_info() -> (String, String) {
|
||||||
match Self::init_config().network.as_str() {
|
match Self::init_config().network.as_str() {
|
||||||
"staging" => ("https://184.107.169.199:49092".to_string(), "staging-brain".to_string()),
|
"staging" => ("https://10.254.254.8:31337".to_string(), "staging-brain".to_string()),
|
||||||
"localhost" => ("https://localhost:31337".to_string(), "staging-brain".to_string()),
|
"localhost" => ("https://localhost:31337".to_string(), "staging-brain".to_string()),
|
||||||
_ => ("https://173.234.17.2:39477".to_string(), "testnet-brain".to_string()),
|
_ => ("https://173.234.17.2:39477".to_string(), "testnet-brain".to_string()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_brain_channel() -> Result<tonic::transport::Channel, Error> {
|
pub async fn connect_brain_channel(
|
||||||
let (brain_url, brain_san) = Self::get_brain_info();
|
brain_url: String,
|
||||||
|
) -> Result<tonic::transport::Channel, Error> {
|
||||||
use hyper_rustls::HttpsConnectorBuilder;
|
use hyper_rustls::HttpsConnectorBuilder;
|
||||||
use rustls::pki_types::pem::PemObject;
|
use rustls::pki_types::pem::PemObject;
|
||||||
use rustls::pki_types::CertificateDer;
|
use rustls::pki_types::CertificateDer;
|
||||||
use rustls::{ClientConfig, RootCertStore};
|
use rustls::{ClientConfig, RootCertStore};
|
||||||
|
|
||||||
|
let brain_san = Config::get_brain_info().1;
|
||||||
|
|
||||||
let mut detee_root_ca_store = RootCertStore::empty();
|
let mut detee_root_ca_store = RootCertStore::empty();
|
||||||
detee_root_ca_store
|
detee_root_ca_store
|
||||||
.add(CertificateDer::from_pem_file(Config::get_root_ca_path()?).map_err(|e| {
|
.add(CertificateDer::from_pem_file(Config::get_root_ca_path()?).map_err(|e| {
|
||||||
|
@ -1 +1,2 @@
|
|||||||
pub const HRATLS_APP_PORT: u32 = 34500;
|
pub const HRATLS_APP_PORT: u32 = 34500;
|
||||||
|
pub const MAX_REDIRECTS: u16 = 3;
|
||||||
|
@ -35,7 +35,8 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn client() -> Result<BrainGeneralCliClient<Channel>, Error> {
|
async fn client() -> Result<BrainGeneralCliClient<Channel>, Error> {
|
||||||
Ok(BrainGeneralCliClient::new(Config::get_brain_channel().await?))
|
let default_brain_url = Config::get_brain_info().0;
|
||||||
|
Ok(BrainGeneralCliClient::new(Config::connect_brain_channel(default_brain_url).await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_balance(account: &str) -> Result<AccountBalance, Error> {
|
pub async fn get_balance(account: &str) -> Result<AccountBalance, Error> {
|
||||||
|
@ -66,7 +66,8 @@ impl crate::HumanOutput for AppContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn client() -> Result<BrainAppCliClient<Channel>> {
|
async fn client() -> Result<BrainAppCliClient<Channel>> {
|
||||||
Ok(BrainAppCliClient::new(Config::get_brain_channel().await?))
|
let default_brain_url = Config::get_brain_info().0;
|
||||||
|
Ok(BrainAppCliClient::new(Config::connect_brain_channel(default_brain_url).await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_app(app_deploy_config: AppDeployConfig) -> Result<NewAppRes> {
|
pub async fn new_app(app_deploy_config: AppDeployConfig) -> Result<NewAppRes> {
|
||||||
|
@ -4,6 +4,7 @@ pub mod proto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
use crate::constants::MAX_REDIRECTS;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
use proto::{
|
use proto::{
|
||||||
@ -41,6 +42,8 @@ pub enum Error {
|
|||||||
CorruptedRootCa(#[from] std::io::Error),
|
CorruptedRootCa(#[from] std::io::Error),
|
||||||
#[error("Internal app error: could not parse Brain URL")]
|
#[error("Internal app error: could not parse Brain URL")]
|
||||||
CorruptedBrainUrl,
|
CorruptedBrainUrl,
|
||||||
|
#[error("Max redirects exceeded: {0}")]
|
||||||
|
MaxRedirectsExceeded(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl crate::HumanOutput for VmContract {
|
impl crate::HumanOutput for VmContract {
|
||||||
@ -84,7 +87,14 @@ impl crate::HumanOutput for VmNodeListResp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn client() -> Result<BrainVmCliClient<Channel>, Error> {
|
async fn client() -> Result<BrainVmCliClient<Channel>, Error> {
|
||||||
Ok(BrainVmCliClient::new(Config::get_brain_channel().await?))
|
let default_brain_url = Config::get_brain_info().0;
|
||||||
|
Ok(BrainVmCliClient::new(Config::connect_brain_channel(default_brain_url).await?))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn client_from_endpoint(
|
||||||
|
reconnect_endpoint: String,
|
||||||
|
) -> Result<BrainVmCliClient<Channel>, Error> {
|
||||||
|
Ok(BrainVmCliClient::new(Config::connect_brain_channel(reconnect_endpoint).await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sign_request<T: std::fmt::Debug>(req: T) -> Result<Request<T>, Error> {
|
fn sign_request<T: std::fmt::Debug>(req: T) -> Result<Request<T>, Error> {
|
||||||
@ -130,10 +140,28 @@ pub async fn get_one_node(req: VmNodeFilters) -> Result<VmNodeListResp, Error> {
|
|||||||
pub async fn create_vm(req: NewVmReq) -> Result<NewVmResp, Error> {
|
pub async fn create_vm(req: NewVmReq) -> Result<NewVmResp, Error> {
|
||||||
let mut client = client().await?;
|
let mut client = client().await?;
|
||||||
debug!("Sending NewVmReq to brain: {req:?}");
|
debug!("Sending NewVmReq to brain: {req:?}");
|
||||||
match client.new_vm(sign_request(req)?).await {
|
for attempt in 0..MAX_REDIRECTS {
|
||||||
Ok(resp) => Ok(resp.into_inner()),
|
match client.new_vm(sign_request(req.clone())?).await {
|
||||||
Err(e) => Err(e.into()),
|
Ok(resp) => return Ok(resp.into_inner()),
|
||||||
|
Err(status)
|
||||||
|
if status.code() == tonic::Code::Unavailable
|
||||||
|
&& status.message() == "moved"
|
||||||
|
&& status.metadata().contains_key("location") =>
|
||||||
|
{
|
||||||
|
let redirect_url = status
|
||||||
|
.metadata()
|
||||||
|
.get("location")
|
||||||
|
.and_then(|v| v.to_str().ok().map(|s| format!("https://{s}")))
|
||||||
|
.unwrap_or_default();
|
||||||
|
// TODO: change this println to log::info!()
|
||||||
|
println!("{attempt}) server moved to a different URL, trying to reconnect... ({redirect_url})");
|
||||||
|
client = client_from_endpoint(redirect_url).await?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Err(e) => return Err(e.into()),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Err(Error::MaxRedirectsExceeded(MAX_REDIRECTS.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_contracts(req: ListVmContractsReq) -> Result<Vec<VmContract>, Error> {
|
pub async fn list_contracts(req: ListVmContractsReq) -> Result<Vec<VmContract>, Error> {
|
||||||
|
Loading…
Reference in New Issue
Block a user