mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-31 04:23:40 +00:00
appmgr: minor fixes
This commit is contained in:
@@ -11,7 +11,6 @@ keywords = [
|
|||||||
"full-node",
|
"full-node",
|
||||||
"lightning",
|
"lightning",
|
||||||
]
|
]
|
||||||
license = "Start9 Personal Use License v1.0"
|
|
||||||
name = "embassy-os"
|
name = "embassy-os"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://github.com/Start9Labs/embassy-os"
|
repository = "https://github.com/Start9Labs/embassy-os"
|
||||||
|
|||||||
22
appmgr/deny.toml
Normal file
22
appmgr/deny.toml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[licenses]
|
||||||
|
unlicensed = "warn"
|
||||||
|
allow-osi-fsf-free = "neither"
|
||||||
|
copyleft = "deny"
|
||||||
|
confidence-threshold = 0.93
|
||||||
|
allow = [
|
||||||
|
"Apache-2.0",
|
||||||
|
"Apache-2.0 WITH LLVM-exception",
|
||||||
|
"MIT",
|
||||||
|
"ISC",
|
||||||
|
"MPL-2.0",
|
||||||
|
"CC0-1.0",
|
||||||
|
"BSD-2-Clause",
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"LGPL-3.0",
|
||||||
|
"OpenSSL",
|
||||||
|
]
|
||||||
|
|
||||||
|
clarify = [
|
||||||
|
{ name = "webpki", expression = "ISC", license-files = [ { path = "LICENSE", hash = 0x001c7e6c } ] },
|
||||||
|
{ name = "ring", expression = "OpenSSL", license-files = [ { path = "LICENSE", hash = 0xbd0eed23 } ] },
|
||||||
|
]
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::path::Path;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use embassy::context::{EitherContext, RpcContext};
|
use embassy::context::{EitherContext, RpcContext};
|
||||||
@@ -14,9 +15,8 @@ fn status_fn(_: i32) -> StatusCode {
|
|||||||
StatusCode::OK
|
StatusCode::OK
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn inner_main() -> Result<(), Error> {
|
async fn inner_main(cfg_path: Option<&str>) -> Result<(), Error> {
|
||||||
simple_logging::log_to_stderr(log::LevelFilter::Info);
|
let rpc_ctx = RpcContext::init(cfg_path).await?;
|
||||||
let rpc_ctx = RpcContext::init().await?;
|
|
||||||
if !rpc_ctx.db.exists(&<JsonPointer>::default()).await? {
|
if !rpc_ctx.db.exists(&<JsonPointer>::default()).await? {
|
||||||
rpc_ctx
|
rpc_ctx
|
||||||
.db
|
.db
|
||||||
@@ -24,7 +24,12 @@ async fn inner_main() -> Result<(), Error> {
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
let ctx = EitherContext::Rpc(rpc_ctx.clone());
|
let ctx = EitherContext::Rpc(rpc_ctx.clone());
|
||||||
let server = rpc_server!(embassy::main_api, ctx, status_fn);
|
let server = rpc_server!({
|
||||||
|
command: embassy::main_api,
|
||||||
|
context: ctx,
|
||||||
|
status: status_fn,
|
||||||
|
|
||||||
|
});
|
||||||
let status_ctx = rpc_ctx.clone();
|
let status_ctx = rpc_ctx.clone();
|
||||||
let status_daemon = daemon(
|
let status_daemon = daemon(
|
||||||
move || {
|
move || {
|
||||||
@@ -70,8 +75,32 @@ async fn inner_main() -> Result<(), Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let matches = clap::App::new("embassyd")
|
||||||
|
.arg(
|
||||||
|
clap::Arg::with_name("config")
|
||||||
|
.short("c")
|
||||||
|
.long("config")
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
clap::Arg::with_name("verbosity")
|
||||||
|
.short("v")
|
||||||
|
.multiple(true)
|
||||||
|
.takes_value(false),
|
||||||
|
)
|
||||||
|
.get_matches();
|
||||||
|
|
||||||
|
simple_logging::log_to_stderr(match matches.occurrences_of("verbosity") {
|
||||||
|
0 => log::LevelFilter::Off,
|
||||||
|
1 => log::LevelFilter::Error,
|
||||||
|
2 => log::LevelFilter::Warn,
|
||||||
|
3 => log::LevelFilter::Info,
|
||||||
|
4 => log::LevelFilter::Debug,
|
||||||
|
_ => log::LevelFilter::Trace,
|
||||||
|
});
|
||||||
|
let cfg_path = matches.value_of("config");
|
||||||
let rt = tokio::runtime::Runtime::new().expect("failed to initialize runtime");
|
let rt = tokio::runtime::Runtime::new().expect("failed to initialize runtime");
|
||||||
match rt.block_on(inner_main()) {
|
match rt.block_on(inner_main(cfg_path)) {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
drop(rt);
|
drop(rt);
|
||||||
|
|||||||
@@ -238,7 +238,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct WithDescription<T> {
|
pub struct WithDescription<T> {
|
||||||
#[serde(flatten)]
|
#[serde(flatten)]
|
||||||
pub inner: T,
|
pub inner: T,
|
||||||
@@ -497,7 +497,7 @@ impl DefaultableWith for ValueSpecBoolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct ValueSpecEnum {
|
pub struct ValueSpecEnum {
|
||||||
pub values: IndexSet<String>,
|
pub values: IndexSet<String>,
|
||||||
pub value_names: IndexMap<String, String>,
|
pub value_names: IndexMap<String, String>,
|
||||||
@@ -505,7 +505,7 @@ pub struct ValueSpecEnum {
|
|||||||
impl<'de> serde::de::Deserialize<'de> for ValueSpecEnum {
|
impl<'de> serde::de::Deserialize<'de> for ValueSpecEnum {
|
||||||
fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct _ValueSpecEnum {
|
pub struct _ValueSpecEnum {
|
||||||
pub values: IndexSet<String>,
|
pub values: IndexSet<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -944,7 +944,7 @@ impl DefaultableWith for ValueSpecNumber {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct ValueSpecObject {
|
pub struct ValueSpecObject {
|
||||||
pub spec: ConfigSpec,
|
pub spec: ConfigSpec,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -1120,7 +1120,7 @@ impl ConfigSpec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct Pattern {
|
pub struct Pattern {
|
||||||
#[serde(with = "util::serde_regex")]
|
#[serde(with = "util::serde_regex")]
|
||||||
pub pattern: Regex,
|
pub pattern: Regex,
|
||||||
@@ -1254,7 +1254,7 @@ impl Entropy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct UnionTag {
|
pub struct UnionTag {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@@ -1263,7 +1263,7 @@ pub struct UnionTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize)]
|
#[derive(Clone, Debug, Serialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct ValueSpecUnion {
|
pub struct ValueSpecUnion {
|
||||||
pub tag: UnionTag,
|
pub tag: UnionTag,
|
||||||
pub variants: IndexMap<String, ConfigSpec>,
|
pub variants: IndexMap<String, ConfigSpec>,
|
||||||
@@ -1274,14 +1274,14 @@ pub struct ValueSpecUnion {
|
|||||||
impl<'de> serde::de::Deserialize<'de> for ValueSpecUnion {
|
impl<'de> serde::de::Deserialize<'de> for ValueSpecUnion {
|
||||||
fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum _UnionTag {
|
pub enum _UnionTag {
|
||||||
Old(String),
|
Old(String),
|
||||||
New(UnionTag),
|
New(UnionTag),
|
||||||
}
|
}
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct _ValueSpecUnion {
|
pub struct _ValueSpecUnion {
|
||||||
pub variants: IndexMap<String, ConfigSpec>,
|
pub variants: IndexMap<String, ConfigSpec>,
|
||||||
pub tag: _UnionTag,
|
pub tag: _UnionTag,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
use std::ops::{Bound, RangeBounds, RangeInclusive};
|
use std::ops::{Bound, RangeBounds, RangeInclusive};
|
||||||
|
|
||||||
use rand::distributions::Distribution;
|
use rand::distributions::Distribution;
|
||||||
@@ -311,8 +312,8 @@ impl<'de> serde::de::Deserialize<'de> for UniqueBy {
|
|||||||
mut map: A,
|
mut map: A,
|
||||||
) -> Result<Self::Value, A::Error> {
|
) -> Result<Self::Value, A::Error> {
|
||||||
let mut variant = None;
|
let mut variant = None;
|
||||||
while let Some(key) = map.next_key()? {
|
while let Some(key) = map.next_key::<Cow<str>>()? {
|
||||||
match key {
|
match key.as_ref() {
|
||||||
"any" => {
|
"any" => {
|
||||||
return Ok(UniqueBy::Any(map.next_value()?));
|
return Ok(UniqueBy::Any(map.next_value()?));
|
||||||
}
|
}
|
||||||
@@ -325,7 +326,7 @@ impl<'de> serde::de::Deserialize<'de> for UniqueBy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(serde::de::Error::unknown_variant(
|
Err(serde::de::Error::unknown_variant(
|
||||||
variant.unwrap_or_default(),
|
variant.unwrap_or_default().as_ref(),
|
||||||
&["any", "all"],
|
&["any", "all"],
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ impl CliContext {
|
|||||||
} else {
|
} else {
|
||||||
CliContextConfig::default()
|
CliContextConfig::default()
|
||||||
};
|
};
|
||||||
if let Some(bind) = base.server_config.bind {
|
if let Some(bind) = base.server_config.bind_rpc {
|
||||||
if base.host.is_none() {
|
if base.host.is_none() {
|
||||||
base.host = Some(match bind.ip() {
|
base.host = Some(match bind.ip() {
|
||||||
IpAddr::V4(a) => Host::Ipv4(a),
|
IpAddr::V4(a) => Host::Ipv4(a),
|
||||||
|
|||||||
@@ -11,38 +11,48 @@ use serde::Deserialize;
|
|||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
|
|
||||||
use crate::util::{from_yaml_async_reader, AsyncFileExt};
|
use crate::net::mdns::LanHandle;
|
||||||
|
use crate::util::{from_toml_async_reader, AsyncFileExt, Container};
|
||||||
use crate::{Error, ResultExt};
|
use crate::{Error, ResultExt};
|
||||||
|
|
||||||
#[derive(Debug, Default, Deserialize)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct RpcContextConfig {
|
pub struct RpcContextConfig {
|
||||||
pub bind: Option<SocketAddr>,
|
pub bind_rpc: Option<SocketAddr>,
|
||||||
|
pub bind_ws: Option<SocketAddr>,
|
||||||
pub db: Option<PathBuf>,
|
pub db: Option<PathBuf>,
|
||||||
pub secret_store: Option<PathBuf>,
|
pub secret_store: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RpcContextSeed {
|
pub struct RpcContextSeed {
|
||||||
pub bind: SocketAddr,
|
pub bind_rpc: SocketAddr,
|
||||||
|
pub bind_ws: SocketAddr,
|
||||||
pub db: PatchDb,
|
pub db: PatchDb,
|
||||||
pub secret_store: SqlitePool,
|
pub secret_store: SqlitePool,
|
||||||
pub docker: Docker,
|
pub docker: Docker,
|
||||||
|
// pub lan_handle: Container<LanHandle>,
|
||||||
|
// pub
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RpcContext(Arc<RpcContextSeed>);
|
pub struct RpcContext(Arc<RpcContextSeed>);
|
||||||
impl RpcContext {
|
impl RpcContext {
|
||||||
pub async fn init() -> Result<Self, Error> {
|
pub async fn init<P: AsRef<Path>>(cfg_path: Option<P>) -> Result<Self, Error> {
|
||||||
let cfg_path = Path::new(crate::CONFIG_PATH);
|
let cfg_path = cfg_path
|
||||||
|
.as_ref()
|
||||||
|
.map(|p| p.as_ref())
|
||||||
|
.unwrap_or(Path::new(crate::CONFIG_PATH));
|
||||||
let base = if let Some(f) = File::maybe_open(cfg_path)
|
let base = if let Some(f) = File::maybe_open(cfg_path)
|
||||||
.await
|
.await
|
||||||
.with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))?
|
.with_ctx(|_| (crate::ErrorKind::Filesystem, cfg_path.display().to_string()))?
|
||||||
{
|
{
|
||||||
from_yaml_async_reader(f).await?
|
from_toml_async_reader(f).await?
|
||||||
} else {
|
} else {
|
||||||
RpcContextConfig::default()
|
RpcContextConfig::default()
|
||||||
};
|
};
|
||||||
let seed = Arc::new(RpcContextSeed {
|
let seed = Arc::new(RpcContextSeed {
|
||||||
bind: base.bind.unwrap_or(([127, 0, 0, 1], 5959).into()),
|
bind_rpc: base.bind_rpc.unwrap_or(([127, 0, 0, 1], 5959).into()),
|
||||||
|
bind_ws: base.bind_ws.unwrap_or(([127, 0, 0, 1], 5960).into()),
|
||||||
db: PatchDb::open(
|
db: PatchDb::open(
|
||||||
base.db
|
base.db
|
||||||
.unwrap_or_else(|| Path::new("/mnt/embassy-os/embassy.db").to_owned()),
|
.unwrap_or_else(|| Path::new("/mnt/embassy-os/embassy.db").to_owned()),
|
||||||
@@ -62,13 +72,13 @@ impl RpcContext {
|
|||||||
}
|
}
|
||||||
impl Context for RpcContext {
|
impl Context for RpcContext {
|
||||||
fn host(&self) -> Host<&str> {
|
fn host(&self) -> Host<&str> {
|
||||||
match self.0.bind.ip() {
|
match self.0.bind_rpc.ip() {
|
||||||
IpAddr::V4(a) => Host::Ipv4(a),
|
IpAddr::V4(a) => Host::Ipv4(a),
|
||||||
IpAddr::V6(a) => Host::Ipv6(a),
|
IpAddr::V6(a) => Host::Ipv6(a),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn port(&self) -> u16 {
|
fn port(&self) -> u16 {
|
||||||
self.0.bind.port()
|
self.0.bind_rpc.port()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Deref for RpcContext {
|
impl Deref for RpcContext {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tokio::fs::File;
|
use tokio::fs::File;
|
||||||
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadBuf};
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use crate::{Error, ResultExt as _};
|
use crate::{Error, ResultExt as _};
|
||||||
|
|
||||||
@@ -145,6 +146,29 @@ where
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn from_toml_async_reader<T, R>(mut reader: R) -> Result<T, crate::Error>
|
||||||
|
where
|
||||||
|
T: for<'de> serde::Deserialize<'de>,
|
||||||
|
R: AsyncRead + Unpin,
|
||||||
|
{
|
||||||
|
let mut buffer = Vec::new();
|
||||||
|
reader.read_to_end(&mut buffer).await?;
|
||||||
|
serde_toml::from_slice(&buffer)
|
||||||
|
.map_err(anyhow::Error::from)
|
||||||
|
.with_kind(crate::ErrorKind::Deserialization)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn to_toml_async_writer<T, W>(mut writer: W, value: &T) -> Result<(), crate::Error>
|
||||||
|
where
|
||||||
|
T: serde::Serialize,
|
||||||
|
W: AsyncWrite + Unpin,
|
||||||
|
{
|
||||||
|
let mut buffer = serde_toml::to_vec(value).with_kind(crate::ErrorKind::Serialization)?;
|
||||||
|
buffer.extend_from_slice(b"\n");
|
||||||
|
writer.write_all(&buffer).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn from_cbor_async_reader<T, R>(mut reader: R) -> Result<T, crate::Error>
|
pub async fn from_cbor_async_reader<T, R>(mut reader: R) -> Result<T, crate::Error>
|
||||||
where
|
where
|
||||||
T: for<'de> serde::Deserialize<'de>,
|
T: for<'de> serde::Deserialize<'de>,
|
||||||
@@ -771,3 +795,13 @@ pub fn parse_duration(arg: &str, matches: &ArgMatches<'_>) -> Result<Duration, E
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Container<T>(RwLock<Option<T>>);
|
||||||
|
impl<T> Container<T> {
|
||||||
|
pub async fn set(&self, value: T) {
|
||||||
|
*self.0.write().await = Some(value);
|
||||||
|
}
|
||||||
|
pub async fn drop(&self) {
|
||||||
|
*self.0.write().await = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user