Skip to content

Commit

Permalink
781 rework api logic (#811)
Browse files Browse the repository at this point in the history
  • Loading branch information
mbround18 authored Apr 29, 2024
1 parent 5605d03 commit c7c58a3
Show file tree
Hide file tree
Showing 10 changed files with 558 additions and 184 deletions.
488 changes: 349 additions & 139 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Dockerfile.odin
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ RUN cargo chef prepare --recipe-path recipe.json
# ------------------ #
FROM lukemathwalker/cargo-chef:latest-rust-${RUST_VERSION} as cacher
WORKDIR /data/odin
RUN apt-get update && apt-get install -y cmake
COPY --from=planner /data/odin/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

Expand All @@ -23,6 +24,7 @@ RUN cargo chef cook --release --recipe-path recipe.json
# ------------------ #
FROM rust:${RUST_VERSION} as builder
WORKDIR /data/odin
RUN apt-get update && apt-get install -y cmake
COPY . .
# Copy over the cached dependencies
COPY --from=cacher /data/odin/target target
Expand Down
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Makefile

.PHONY: setup member_format member_clippy docker-build docker-up docker-down docker-push start start-dev build-dev access access-admin release-odin release-http-server release
.PHONY: setup member_format member_clippy docker-build docker-up docker-down docker-push start start-dev build-dev access access-admin release-odin release-http-server release test docker-dev

setup:
@if [ ! -f "$$PWD/docker-compose.dev.yml" ]; then \
Expand All @@ -11,6 +11,9 @@ setup:
lint: member_format
docker run --rm -v "$$PWD:/app" -w /app node:lts sh -c 'npx -y prettier --write .'

test:
cargo test

member_format:
cargo fmt

Expand All @@ -28,6 +31,8 @@ docker-down: setup

docker-push: setup
docker compose -f ./docker-compose.dev.yml push
docker-dev: setup
docker compose -f ./docker-compose.dev.yml up --build

start: member_format member_clippy docker-up

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
<a href="https://github.com/mbround18/valheim-docker/actions/workflows/docker-release.yml"><img src="https://img.shields.io/github/actions/workflow/status/mbround18/valheim-docker/docker-release.yml?label=Docker&style=for-the-badge" alt=""></a>

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->

[![All Contributors](https://img.shields.io/badge/all_contributors-14-orange.svg?style=flat-square)](#contributors-)

<!-- ALL-CONTRIBUTORS-BADGE:END -->

## Table of Contents
Expand Down
7 changes: 5 additions & 2 deletions src/odin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,22 @@ tar = "0.4"
flate2 = "1.0"
inflections = "1.1.1"
md5 = "0.7"
reqwest = { version = "0.11", default_features = false, features = ["blocking", "json", "rustls-tls"] }
reqwest = { version = "0.12.4", default_features = false, features = ["blocking", "json", "rustls-tls"] }
chrono = "0.4"
zip = { version = "0.6" }
zip = { version = "1.1.1" }
fs_extra = "1.3"
glob = "0.3"
a2s = "0.5"
serde_with = "3"
regex = "1"


[dev-dependencies]
once_cell = "1"
rand = "0.8"
serial_test = "3"
mockito = "1.4.0"
lazy_static = "1.4.0"

[dev-dependencies.cargo-husky]
version = "1.5.0"
Expand Down
5 changes: 2 additions & 3 deletions src/odin/commands/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ pub fn invoke(output_json: bool, use_local: bool, supplied_address: Option<Strin
let address = if use_local {
String::from("127.0.0.1:2457")
} else {
env::var("ADDRESS").unwrap_or_else(|_| {
supplied_address.unwrap_or_else(|| fetch_public_address().unwrap().to_string())
})
env::var("ADDRESS")
.unwrap_or_else(|_| supplied_address.unwrap_or_else(|| fetch_public_address().to_string()))
};
let parsed_address = parse_address(&address);
let server_info = ServerInfo::from(parsed_address);
Expand Down
8 changes: 4 additions & 4 deletions src/odin/mods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ impl ZipExt for ZipArchive<File> {
fn extract_sub_dir_custom<P: AsRef<Path>>(&mut self, dst_dir: P, sub_dir: &str) -> ZipResult<()> {
for i in 0..self.len() {
let mut file = self.by_index(i)?;
let filepath = match file
let enclosed_name = file
.enclosed_name()
.ok_or(ZipError::InvalidArchive("Invalid file path"))?
.strip_prefix(sub_dir)
{
.ok_or(ZipError::InvalidArchive("Invalid file path"))?;

let filepath = match enclosed_name.strip_prefix(sub_dir) {
Ok(path) => path,
Err(_) => continue,
};
Expand Down
9 changes: 2 additions & 7 deletions src/odin/notifications/enums/notification_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,8 @@ fn is_webhook_include_public_ip() -> bool {

pub fn parse_server_name_for_notification() -> String {
if is_webhook_include_public_ip() {
let public_address = fetch_public_address().unwrap();
format!(
"{} - {}:{}",
get_server_name(),
public_address.ip(),
public_address.port() - 1
)
let ip = fetch_public_address();
format!("{} - {}:{}", get_server_name(), &ip.ip, &ip.port)
} else {
get_server_name()
}
Expand Down
203 changes: 186 additions & 17 deletions src/odin/utils/fetch_public_ip_address.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,190 @@
use crate::utils::environment::fetch_var;
use std::env;
use std::net::{AddrParseError, SocketAddrV4};
use std::str::FromStr;
use log::{debug, error};
use reqwest::blocking::Client;
use std::env::VarError;
use std::{env, fmt};

// Standardized way of fetching public address
pub fn fetch_public_address() -> Result<SocketAddrV4, AddrParseError> {
let current_port: u16 = fetch_var("PORT", "2456").parse().unwrap();
let current_ip = match env::var("ADDRESS") {
Ok(found_address) => found_address,
Err(_) => {
// Make request
match reqwest::blocking::get("https://api.ipify.org") {
Ok(result) => String::from(&result.text().unwrap()),
// Fallback to local IP address
Err(_) => String::from("127.0.0.1"),
#[derive(Debug, serde::Deserialize, serde::Serialize)]
struct IPResponse {
ip: String,
}

pub struct IPConfig {
pub(crate) ip: String,
pub(crate) port: u16,
}

impl fmt::Display for IPConfig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", self.ip, self.port)
}
}

impl IPConfig {
fn new(ip: String, port: u16) -> IPConfig {
IPConfig { ip, port }
}

fn default() -> IPConfig {
IPConfig::new("127.0.0.1".to_string(), 2456)
}

fn get_ip_from_env(&self) -> Result<String, VarError> {
env::var("ADDRESS")
}

fn get_port_from_env(&self) -> Result<u16, VarError> {
env::var("PORT").map(|port| port.parse().unwrap())
}

pub fn to_string_from_env(&self) -> Result<IPConfig, VarError> {
match self.get_ip_from_env() {
Ok(ip) => match self.get_port_from_env() {
Ok(port) => {
if ip.is_empty() {
error!("IP address is empty");
Err(VarError::NotPresent)
} else if port.to_string().is_empty() {
error!("Port is empty");
Err(VarError::NotPresent)
} else {
Ok(IPConfig::new(ip, port))
}
}
Err(e) => Err(e),
},
Err(e) => Err(e),
}
}

pub fn fetch_ip_from_api(&self, client: &Client) -> Result<String, Box<dyn std::error::Error>> {
let urls = [
"https://api.ipify.org?format=json",
"https://api.seeip.org/jsonip?",
"https://ipinfo.io",
];

for url in urls {
match client.get(url).send() {
Ok(response) => match response.json::<IPResponse>() {
Ok(json) => return Ok(json.ip.to_string()),
Err(e) => {
debug!("Failed to parse JSON: {}", e);
continue;
}
},
Err(e) => {
debug!("Request failed: {}", e);
continue;
}
}
}
};
SocketAddrV4::from_str(&format!("{}:{}", current_ip, current_port + 1))

Err(Box::new(std::io::Error::new(
std::io::ErrorKind::NotFound,
"All IP fetch attempts failed",
)))
}
}

// Standardized way of fetching public address
pub fn fetch_public_address() -> IPConfig {
let client = Client::new();
let mut ip_config = IPConfig::default();
debug!("Checking for address in env");
match ip_config.to_string_from_env() {
Ok(ip) => {
debug!("Fetched IP: {}", ip);
ip
}
Err(_) => match ip_config.fetch_ip_from_api(&client) {
Ok(ip) => {
debug!("Fetched IP: {}", ip);
ip_config.ip = ip;
ip_config
}
Err(e) => {
debug!("Failed to fetch IP: {}", e);
ip_config
}
},
}
}

#[cfg(test)]
mod tests {
use super::*;
use lazy_static::lazy_static;
use std::env;
use std::sync::Mutex;

lazy_static! {
static ref ENV_LOCK: Mutex<()> = Mutex::new(());
}

#[test]
fn test_new() {
let ip_config = IPConfig::new("192.168.1.1".to_string(), 3000);
assert_eq!(ip_config.ip, "192.168.1.1");
assert_eq!(ip_config.port, 3000);
}

#[test]
fn test_default() {
let ip_config = IPConfig::default();
assert_eq!(ip_config.ip, "127.0.0.1");
assert_eq!(ip_config.port, 2456);
}

#[test]
fn test_get_ip_from_env() {
let _guard = ENV_LOCK.lock().unwrap();
env::set_var("ADDRESS", "192.168.1.1");

let ip_config = IPConfig::default();
let result = ip_config.get_ip_from_env();
assert_eq!(result.unwrap(), "192.168.1.1");

env::remove_var("ADDRESS");
}

#[test]
fn test_get_port_from_env() {
let _guard = ENV_LOCK.lock().unwrap();
env::set_var("PORT", "3000");

let ip_config = IPConfig::default();
let result = ip_config.get_port_from_env();
assert_eq!(result.unwrap(), 3000);

env::remove_var("PORT");
}

#[test]
fn test_to_string_from_env() {
let _guard = ENV_LOCK.lock().unwrap();
env::set_var("ADDRESS", "192.168.1.1");
env::set_var("PORT", "3000");

let ip_config = IPConfig::default();
let result = ip_config.to_string_from_env().unwrap();
assert_eq!(result.ip, "192.168.1.1");
assert_eq!(result.port, 3000);

env::remove_var("ADDRESS");
env::remove_var("PORT");
}

#[test]
fn test_fetch_ip_from_api() {
let client = Client::new();
let ip_config = IPConfig::default();
let result = ip_config.fetch_ip_from_api(&client);
assert!(result.is_ok());
}

#[test]
fn test_display_for_ip_config() {
let ip_config = IPConfig::new("192.168.1.1".to_string(), 3000);
assert_eq!(ip_config.to_string(), "192.168.1.1:3000");
}
}
11 changes: 0 additions & 11 deletions test.sh

This file was deleted.

0 comments on commit c7c58a3

Please sign in to comment.