merge 036, everything broken

This commit is contained in:
Matt Hill
2024-03-20 13:32:57 -06:00
parent f4fadd366e
commit 5e6a7e134f
429 changed files with 42285 additions and 27221 deletions

View File

@@ -15,6 +15,7 @@ emver = { version = "0.1", git = "https://github.com/Start9Labs/emver-rs.git", f
"serde",
] }
ipnet = "2.8.0"
num_enum = "0.7.1"
openssl = { version = "0.10.57", features = ["vendored"] }
patch-db = { version = "*", path = "../../patch-db/patch-db", features = [
"trace",
@@ -31,8 +32,9 @@ sqlx = { version = "0.7.2", features = [
"postgres",
] }
ssh-key = "0.6.2"
ts-rs = "7"
thiserror = "1.0"
tokio = { version = "1", features = ["full"] }
torut = "0.2.1"
torut = { git = "https://github.com/Start9Labs/torut.git", branch = "update/dependencies" }
tracing = "0.1.39"
yasi = "0.1.5"

View File

@@ -1,14 +1,19 @@
use std::fmt::Display;
use std::fmt::{Debug, Display};
use color_eyre::eyre::eyre;
use num_enum::TryFromPrimitive;
use patch_db::Revision;
use rpc_toolkit::hyper::http::uri::InvalidUri;
use rpc_toolkit::reqwest;
use rpc_toolkit::yajrc::RpcError;
use rpc_toolkit::yajrc::{
RpcError, INVALID_PARAMS_ERROR, INVALID_REQUEST_ERROR, METHOD_NOT_FOUND_ERROR, PARSE_ERROR,
};
use serde::{Deserialize, Serialize};
use crate::InvalidId;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, TryFromPrimitive)]
#[repr(i32)]
pub enum ErrorKind {
Unknown = 1,
Filesystem = 2,
@@ -81,6 +86,8 @@ pub enum ErrorKind {
CpuSettings = 69,
Firmware = 70,
Timeout = 71,
Lxc = 72,
Cancelled = 73,
}
impl ErrorKind {
pub fn as_str(&self) -> &'static str {
@@ -157,6 +164,8 @@ impl ErrorKind {
CpuSettings => "CPU Settings Error",
Firmware => "Firmware Error",
Timeout => "Timeout Error",
Lxc => "LXC Error",
Cancelled => "Cancelled",
}
}
}
@@ -186,6 +195,22 @@ impl Error {
revision: None,
}
}
pub fn clone_output(&self) -> Self {
Error {
source: ErrorData {
details: format!("{}", self.source),
debug: format!("{:?}", self.source),
}
.into(),
kind: self.kind,
revision: self.revision.clone(),
}
}
}
impl From<std::convert::Infallible> for Error {
fn from(value: std::convert::Infallible) -> Self {
match value {}
}
}
impl From<InvalidId> for Error {
fn from(err: InvalidId) -> Self {
@@ -300,6 +325,53 @@ impl From<patch_db::value::Error> for Error {
}
}
#[derive(Clone, Deserialize, Serialize)]
pub struct ErrorData {
pub details: String,
pub debug: String,
}
impl Display for ErrorData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.details, f)
}
}
impl Debug for ErrorData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Display::fmt(&self.debug, f)
}
}
impl std::error::Error for ErrorData {}
impl From<&RpcError> for ErrorData {
fn from(value: &RpcError) -> Self {
Self {
details: value
.data
.as_ref()
.and_then(|d| {
d.as_object()
.and_then(|d| {
d.get("details")
.and_then(|d| d.as_str().map(|s| s.to_owned()))
})
.or_else(|| d.as_str().map(|s| s.to_owned()))
})
.unwrap_or_else(|| value.message.clone().into_owned()),
debug: value
.data
.as_ref()
.and_then(|d| {
d.as_object()
.and_then(|d| {
d.get("debug")
.and_then(|d| d.as_str().map(|s| s.to_owned()))
})
.or_else(|| d.as_str().map(|s| s.to_owned()))
})
.unwrap_or_else(|| value.message.clone().into_owned()),
}
}
}
impl From<Error> for RpcError {
fn from(e: Error) -> Self {
let mut data_object = serde_json::Map::with_capacity(3);
@@ -318,10 +390,40 @@ impl From<Error> for RpcError {
RpcError {
code: e.kind as i32,
message: e.kind.as_str().into(),
data: Some(data_object.into()),
data: Some(
match serde_json::to_value(&ErrorData {
details: format!("{}", e.source),
debug: format!("{:?}", e.source),
}) {
Ok(a) => a,
Err(e) => {
tracing::warn!("Error serializing revision for Error object: {}", e);
serde_json::Value::Null
}
},
),
}
}
}
impl From<RpcError> for Error {
fn from(e: RpcError) -> Self {
Error::new(
ErrorData::from(&e),
if let Ok(kind) = e.code.try_into() {
kind
} else if e.code == METHOD_NOT_FOUND_ERROR.code {
ErrorKind::NotFound
} else if e.code == PARSE_ERROR.code
|| e.code == INVALID_PARAMS_ERROR.code
|| e.code == INVALID_REQUEST_ERROR.code
{
ErrorKind::Deserialization
} else {
ErrorKind::Unknown
},
)
}
}
#[derive(Debug, Default)]
pub struct ErrorCollection(Vec<Error>);
@@ -377,10 +479,7 @@ where
Self: Sized,
{
fn with_kind(self, kind: ErrorKind) -> Result<T, Error>;
fn with_ctx<F: FnOnce(&E) -> (ErrorKind, D), D: Display + Send + Sync + 'static>(
self,
f: F,
) -> Result<T, Error>;
fn with_ctx<F: FnOnce(&E) -> (ErrorKind, D), D: Display>(self, f: F) -> Result<T, Error>;
}
impl<T, E> ResultExt<T, E> for Result<T, E>
where
@@ -394,10 +493,7 @@ where
})
}
fn with_ctx<F: FnOnce(&E) -> (ErrorKind, D), D: Display + Send + Sync + 'static>(
self,
f: F,
) -> Result<T, Error> {
fn with_ctx<F: FnOnce(&E) -> (ErrorKind, D), D: Display>(self, f: F) -> Result<T, Error> {
self.map_err(|e| {
let (kind, ctx) = f(&e);
let source = color_eyre::eyre::Error::from(e);
@@ -411,6 +507,29 @@ where
})
}
}
impl<T> ResultExt<T, Error> for Result<T, Error> {
fn with_kind(self, kind: ErrorKind) -> Result<T, Error> {
self.map_err(|e| Error {
source: e.source,
kind,
revision: e.revision,
})
}
fn with_ctx<F: FnOnce(&Error) -> (ErrorKind, D), D: Display>(self, f: F) -> Result<T, Error> {
self.map_err(|e| {
let (kind, ctx) = f(&e);
let source = e.source;
let ctx = format!("{}: {}", ctx, source);
let source = source.wrap_err(ctx);
Error {
kind,
source,
revision: e.revision,
}
})
}
}
pub trait OptionExt<T>
where

View File

@@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
use crate::{Id, InvalidId};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, ts_rs::TS)]
pub struct ActionId(Id);
impl FromStr for ActionId {
type Err = InvalidId;

View File

@@ -1,16 +1,23 @@
use std::path::Path;
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize};
use crate::Id;
use crate::{Id, InvalidId};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, ts_rs::TS)]
pub struct HealthCheckId(Id);
impl std::fmt::Display for HealthCheckId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.0)
}
}
impl FromStr for HealthCheckId {
type Err = InvalidId;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Id::from_str(s).map(HealthCheckId)
}
}
impl AsRef<str> for HealthCheckId {
fn as_ref(&self) -> &str {
self.0.as_ref()

View File

@@ -2,52 +2,63 @@ use std::path::Path;
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize};
use yasi::InternedString;
use crate::{Id, InvalidId};
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
pub struct InterfaceId(Id);
impl FromStr for InterfaceId {
pub struct HostId(Id);
impl FromStr for HostId {
type Err = InvalidId;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(Id::try_from(s.to_owned())?))
}
}
impl From<Id> for InterfaceId {
impl From<Id> for HostId {
fn from(id: Id) -> Self {
Self(id)
}
}
impl std::fmt::Display for InterfaceId {
impl From<HostId> for Id {
fn from(value: HostId) -> Self {
value.0
}
}
impl From<HostId> for InternedString {
fn from(value: HostId) -> Self {
value.0.into()
}
}
impl std::fmt::Display for HostId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.0)
}
}
impl std::ops::Deref for InterfaceId {
impl std::ops::Deref for HostId {
type Target = str;
fn deref(&self) -> &Self::Target {
&*self.0
}
}
impl AsRef<str> for InterfaceId {
impl AsRef<str> for HostId {
fn as_ref(&self) -> &str {
self.0.as_ref()
}
}
impl<'de> Deserialize<'de> for InterfaceId {
impl<'de> Deserialize<'de> for HostId {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
Ok(InterfaceId(Deserialize::deserialize(deserializer)?))
Ok(HostId(Deserialize::deserialize(deserializer)?))
}
}
impl AsRef<Path> for InterfaceId {
impl AsRef<Path> for HostId {
fn as_ref(&self) -> &Path {
self.0.as_ref().as_ref()
}
}
impl<'q> sqlx::Encode<'q, sqlx::Postgres> for InterfaceId {
impl<'q> sqlx::Encode<'q, sqlx::Postgres> for HostId {
fn encode_by_ref(
&self,
buf: &mut <sqlx::Postgres as sqlx::database::HasArguments<'q>>::ArgumentBuffer,
@@ -55,7 +66,7 @@ impl<'q> sqlx::Encode<'q, sqlx::Postgres> for InterfaceId {
<&str as sqlx::Encode<'q, sqlx::Postgres>>::encode_by_ref(&&**self, buf)
}
}
impl sqlx::Type<sqlx::Postgres> for InterfaceId {
impl sqlx::Type<sqlx::Postgres> for HostId {
fn type_info() -> sqlx::postgres::PgTypeInfo {
<&str as sqlx::Type<sqlx::Postgres>>::type_info()
}

View File

@@ -1,12 +1,18 @@
use std::fmt::Debug;
use std::path::Path;
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize};
use crate::{Id, InvalidId, PackageId, Version};
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, ts_rs::TS)]
pub struct ImageId(Id);
impl AsRef<Path> for ImageId {
fn as_ref(&self) -> &Path {
self.0.as_ref().as_ref()
}
}
impl std::fmt::Display for ImageId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", &self.0)

View File

@@ -1,4 +1,5 @@
use std::borrow::Borrow;
use std::str::FromStr;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
@@ -7,8 +8,8 @@ use yasi::InternedString;
mod action;
mod address;
mod health_check;
mod host;
mod image;
mod interface;
mod invalid_id;
mod package;
mod volume;
@@ -16,8 +17,8 @@ mod volume;
pub use action::ActionId;
pub use address::AddressId;
pub use health_check::HealthCheckId;
pub use host::HostId;
pub use image::ImageId;
pub use interface::InterfaceId;
pub use invalid_id::InvalidId;
pub use package::{PackageId, SYSTEM_PACKAGE_ID};
pub use volume::VolumeId;
@@ -27,12 +28,12 @@ lazy_static::lazy_static! {
pub static ref SYSTEM_ID: Id = Id(InternedString::intern("x_system"));
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Id(InternedString);
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default, ts_rs::TS)]
pub struct Id(#[ts(type = "string")] InternedString);
impl TryFrom<InternedString> for Id {
type Error = InvalidId;
fn try_from(value: InternedString) -> Result<Self, Self::Error> {
if ID_REGEX.is_match(&*value) {
if ID_REGEX.is_match(&value) {
Ok(Id(value))
} else {
Err(InvalidId)
@@ -52,17 +53,28 @@ impl TryFrom<String> for Id {
impl TryFrom<&str> for Id {
type Error = InvalidId;
fn try_from(value: &str) -> Result<Self, Self::Error> {
if ID_REGEX.is_match(&value) {
if ID_REGEX.is_match(value) {
Ok(Id(InternedString::intern(value)))
} else {
Err(InvalidId)
}
}
}
impl FromStr for Id {
type Err = InvalidId;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::try_from(s)
}
}
impl From<Id> for InternedString {
fn from(value: Id) -> Self {
value.0
}
}
impl std::ops::Deref for Id {
type Target = str;
fn deref(&self) -> &Self::Target {
&*self.0
&self.0
}
}
impl std::fmt::Display for Id {
@@ -72,7 +84,7 @@ impl std::fmt::Display for Id {
}
impl AsRef<str> for Id {
fn as_ref(&self) -> &str {
&*self.0
&self.0
}
}
impl Borrow<str> for Id {
@@ -94,7 +106,7 @@ impl Serialize for Id {
where
Ser: Serializer,
{
serializer.serialize_str(&*self)
serializer.serialize_str(self)
}
}
impl<'q> sqlx::Encode<'q, sqlx::Postgres> for Id {

View File

@@ -3,13 +3,15 @@ use std::path::Path;
use std::str::FromStr;
use serde::{Deserialize, Serialize, Serializer};
use ts_rs::TS;
use yasi::InternedString;
use crate::{Id, InvalidId, SYSTEM_ID};
lazy_static::lazy_static! {
pub static ref SYSTEM_PACKAGE_ID: PackageId = PackageId(SYSTEM_ID.clone());
}
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, TS)]
pub struct PackageId(Id);
impl FromStr for PackageId {
type Err = InvalidId;
@@ -22,10 +24,20 @@ impl From<Id> for PackageId {
PackageId(id)
}
}
impl From<PackageId> for Id {
fn from(value: PackageId) -> Self {
value.0
}
}
impl From<PackageId> for InternedString {
fn from(value: PackageId) -> Self {
value.0.into()
}
}
impl std::ops::Deref for PackageId {
type Target = str;
fn deref(&self) -> &Self::Target {
&*self.0
&self.0
}
}
impl AsRef<PackageId> for PackageId {

View File

@@ -1,57 +1,40 @@
use serde::{Deserialize, Serialize};
use crate::{ActionId, HealthCheckId, PackageId};
use crate::ActionId;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ProcedureName {
Main, // Usually just run container
CreateBackup,
RestoreBackup,
StartMain,
StopMain,
GetConfig,
SetConfig,
Migration,
Properties,
LongRunning,
Check(PackageId),
AutoConfig(PackageId),
Health(HealthCheckId),
Action(ActionId),
Signal,
CreateBackup,
RestoreBackup,
ActionMetadata,
RunAction(ActionId),
GetAction(ActionId),
QueryDependency(ActionId),
UpdateDependency(ActionId),
Init,
Uninit,
}
impl ProcedureName {
pub fn docker_name(&self) -> Option<String> {
pub fn js_function_name(&self) -> String {
match self {
ProcedureName::Main => None,
ProcedureName::LongRunning => None,
ProcedureName::CreateBackup => Some("CreateBackup".to_string()),
ProcedureName::RestoreBackup => Some("RestoreBackup".to_string()),
ProcedureName::GetConfig => Some("GetConfig".to_string()),
ProcedureName::SetConfig => Some("SetConfig".to_string()),
ProcedureName::Migration => Some("Migration".to_string()),
ProcedureName::Properties => Some(format!("Properties-{}", rand::random::<u64>())),
ProcedureName::Health(id) => Some(format!("{}Health", id)),
ProcedureName::Action(id) => Some(format!("{}Action", id)),
ProcedureName::Check(_) => None,
ProcedureName::AutoConfig(_) => None,
ProcedureName::Signal => None,
}
}
pub fn js_function_name(&self) -> Option<String> {
match self {
ProcedureName::Main => Some("/main".to_string()),
ProcedureName::LongRunning => None,
ProcedureName::CreateBackup => Some("/createBackup".to_string()),
ProcedureName::RestoreBackup => Some("/restoreBackup".to_string()),
ProcedureName::GetConfig => Some("/getConfig".to_string()),
ProcedureName::SetConfig => Some("/setConfig".to_string()),
ProcedureName::Migration => Some("/migration".to_string()),
ProcedureName::Properties => Some("/properties".to_string()),
ProcedureName::Health(id) => Some(format!("/health/{}", id)),
ProcedureName::Action(id) => Some(format!("/action/{}", id)),
ProcedureName::Check(id) => Some(format!("/dependencies/{}/check", id)),
ProcedureName::AutoConfig(id) => Some(format!("/dependencies/{}/autoConfigure", id)),
ProcedureName::Signal => Some("/handleSignal".to_string()),
ProcedureName::Init => "/init".to_string(),
ProcedureName::Uninit => "/uninit".to_string(),
ProcedureName::StartMain => "/main/start".to_string(),
ProcedureName::StopMain => "/main/stop".to_string(),
ProcedureName::SetConfig => "/config/set".to_string(),
ProcedureName::GetConfig => "/config/get".to_string(),
ProcedureName::CreateBackup => "/backup/create".to_string(),
ProcedureName::RestoreBackup => "/backup/restore".to_string(),
ProcedureName::ActionMetadata => "/actions/metadata".to_string(),
ProcedureName::RunAction(id) => format!("/actions/{}/run", id),
ProcedureName::GetAction(id) => format!("/actions/{}/get", id),
ProcedureName::QueryDependency(id) => format!("/dependencies/{}/query", id),
ProcedureName::UpdateDependency(id) => format!("/dependencies/{}/update", id),
}
}
}