mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 02:11:53 +00:00
fixup after rebase
This commit is contained in:
@@ -12,7 +12,6 @@ use sqlx::Acquire;
|
||||
use crate::{
|
||||
config::hook::ConfigHook,
|
||||
manager::{start_stop::StartStop, Manager},
|
||||
net::keys::Key,
|
||||
};
|
||||
|
||||
use super::try_get_running_ip;
|
||||
@@ -165,26 +164,29 @@ impl OsApi for Manager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_started(&self) {
|
||||
fn set_started(&self) -> Result<(), Report> {
|
||||
self.manage_container
|
||||
.current_state
|
||||
.send(StartStop::Start)
|
||||
.unwrap_or_default()
|
||||
.send_modify(|x| *x = StartStop::Start);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn restart(&self) {
|
||||
self.perform_restart().await
|
||||
async fn restart(&self) -> Result<(), Report> {
|
||||
self.perform_restart().await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn start(&self) {
|
||||
async fn start(&self) -> Result<(), Report> {
|
||||
self.manage_container
|
||||
.wait_for_desired(StartStop::Start)
|
||||
.await
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn stop(&self) {
|
||||
async fn stop(&self) -> Result<(), Report> {
|
||||
self.manage_container
|
||||
.wait_for_desired(StartStop::Stop)
|
||||
.await
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ impl ManageContainer {
|
||||
}
|
||||
|
||||
pub async fn wait_for_desired(&self, new_state: StartStop) {
|
||||
let current_state = self.current_state();
|
||||
let mut current_state = self.current_state();
|
||||
self.to_desired(new_state);
|
||||
while current_state.borrow() != new_state {
|
||||
while *current_state.borrow() != new_state {
|
||||
current_state.changed().await.unwrap_or_default();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ use nix::sys::signal::Signal;
|
||||
use patch_db::DbHandle;
|
||||
use persistent_container::PersistentContainer;
|
||||
use rand::SeedableRng;
|
||||
use serde_json::Value;
|
||||
use sqlx::Connection;
|
||||
use start_stop::StartStop;
|
||||
use tokio::sync::oneshot;
|
||||
|
||||
@@ -52,7 +52,6 @@ pub async fn spawn_persistent_container(
|
||||
let mut send_inserter: Option<oneshot::Sender<Receiver<Arc<UnixRpcClient>>>> = Some(send_inserter);
|
||||
loop {
|
||||
if let Err(e) = async {
|
||||
let generated_certificate = generate_certificate(&*seed).await?;
|
||||
let (mut runtime, inserter) =
|
||||
long_running_docker(&seed, &container).await?;
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ impl From<MainStatus> for StartStop {
|
||||
MainStatus::Stopped => StartStop::Stop,
|
||||
MainStatus::Restarting => StartStop::Start,
|
||||
MainStatus::Stopping => StartStop::Stop,
|
||||
MainStatus::Starting { restarting } => StartStop::Start,
|
||||
MainStatus::Starting => StartStop::Start,
|
||||
MainStatus::Running { started, health } => StartStop::Start,
|
||||
MainStatus::BackingUp { started, health } if started.is_some() => StartStop::Start,
|
||||
MainStatus::BackingUp { started, health } => StartStop::Stop,
|
||||
|
||||
@@ -236,7 +236,7 @@ mod tests {
|
||||
use tokio::sync::watch;
|
||||
|
||||
struct OsApiMock {
|
||||
config_callbacks: (watch::Sender<Vec<Callback>>, watch::Sender<Vec<Callback>>),
|
||||
config_callbacks: watch::Sender<Vec<Callback>>,
|
||||
}
|
||||
impl Default for OsApiMock {
|
||||
fn default() -> Self {
|
||||
@@ -974,7 +974,7 @@ mod tests {
|
||||
continue;
|
||||
}
|
||||
api.config_callbacks.send_modify(|x| {
|
||||
x[0](json!("This is something across the wire!"))
|
||||
x[0].call(vec![json!("This is something across the wire!")])
|
||||
.map_err(|e| format!("Failed call"))
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
@@ -35,7 +35,7 @@ impl Version {
|
||||
#[cfg(test)]
|
||||
fn as_sem_ver(&self) -> emver::Version {
|
||||
match self {
|
||||
Version::LT0_3_4_3(LTWrapper(x)) => x.semver(),
|
||||
Version::LT0_3_4_3(LTWrapper(_, x)) => x.semver(),
|
||||
Version::V0_3_4_3(Wrapper(x)) => x.semver(),
|
||||
Version::V0_4_0(Wrapper(x)) => x.semver(),
|
||||
Version::Other(x) => x.clone(),
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
use super::*;
|
||||
|
||||
const V0_3_0: emver::Version = emver::Version::new(0, 3, 0, 0);
|
||||
lazy_static! {
|
||||
pub static ref V0_3_0_COMPAT: VersionRange = VersionRange::Conj(
|
||||
Box::new(VersionRange::Anchor(
|
||||
emver::GTE,
|
||||
emver::Version::new(0, 3, 0, 0),
|
||||
)),
|
||||
Box::new(VersionRange::Anchor(emver::LTE, Current::new().semver())),
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_0::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_0
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::*;
|
||||
|
||||
const V0_3_0_1: emver::Version = emver::Version::new(0, 3, 0, 1);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_0::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_0_1
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*v0_3_0::V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::*;
|
||||
|
||||
const V0_3_0_2: emver::Version = emver::Version::new(0, 3, 0, 2);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_0_1::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_0_2
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*v0_3_0::V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::*;
|
||||
|
||||
const V0_3_0_3: emver::Version = emver::Version::new(0, 3, 0, 3);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_0_2::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_0_3
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*v0_3_0::V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_1: emver::Version = emver::Version::new(0, 3, 1, 0);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_0_3::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_1
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_1_1: emver::Version = emver::Version::new(0, 3, 1, 1);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_1::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_1_1
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_1_2: emver::Version = emver::Version::new(0, 3, 1, 2);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_1_1::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_1_2
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_2: emver::Version = emver::Version::new(0, 3, 2, 0);
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref DEFAULT_UI: serde_json::Value =serde_json::json!({
|
||||
"name": null,
|
||||
"auto-check-updates": true,
|
||||
"pkg-order": [],
|
||||
"ack-welcome": "0.3.2",
|
||||
"marketplace": {
|
||||
"selected-id": null,
|
||||
"known-hosts": {}
|
||||
},
|
||||
"dev": {},
|
||||
"gaming": {
|
||||
"snake": {
|
||||
"high-score": 0
|
||||
}
|
||||
},
|
||||
"ack-instructions": {}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_1_2::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_2
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
let hostname = legacy::hostname::get_hostname(db).await?;
|
||||
crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.hostname()
|
||||
.put(db, &Some(hostname.0))
|
||||
.await?;
|
||||
crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.id()
|
||||
.put(db, &legacy::hostname::generate_id())
|
||||
.await?;
|
||||
|
||||
legacy::hostname::sync_hostname(db).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
mod legacy {
|
||||
pub mod hostname {
|
||||
use patch_db::DbHandle;
|
||||
use rand::{thread_rng, Rng};
|
||||
use tokio::process::Command;
|
||||
use tracing::instrument;
|
||||
|
||||
use crate::util::Invoke;
|
||||
use crate::{Error, ErrorKind};
|
||||
#[derive(Clone, serde::Deserialize, serde::Serialize, Debug)]
|
||||
pub struct Hostname(pub String);
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref ADJECTIVES: Vec<String> = include_str!("../assets/adjectives.txt").lines().map(|x| x.to_string()).collect();
|
||||
static ref NOUNS: Vec<String> = include_str!("../assets/nouns.txt").lines().map(|x| x.to_string()).collect();
|
||||
}
|
||||
impl AsRef<str> for Hostname {
|
||||
fn as_ref(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_hostname() -> Hostname {
|
||||
let mut rng = thread_rng();
|
||||
let adjective = &ADJECTIVES[rng.gen_range(0..ADJECTIVES.len())];
|
||||
let noun = &NOUNS[rng.gen_range(0..NOUNS.len())];
|
||||
Hostname(format!("embassy-{adjective}-{noun}"))
|
||||
}
|
||||
|
||||
pub fn generate_id() -> String {
|
||||
let id = uuid::Uuid::new_v4();
|
||||
id.to_string()
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_current_hostname() -> Result<Hostname, Error> {
|
||||
let out = Command::new("hostname")
|
||||
.invoke(ErrorKind::ParseSysInfo)
|
||||
.await?;
|
||||
let out_string = String::from_utf8(out)?;
|
||||
Ok(Hostname(out_string.trim().to_owned()))
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn set_hostname(hostname: &Hostname) -> Result<(), Error> {
|
||||
let hostname: &String = &hostname.0;
|
||||
let _out = Command::new("hostnamectl")
|
||||
.arg("set-hostname")
|
||||
.arg(hostname)
|
||||
.invoke(ErrorKind::ParseSysInfo)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub async fn get_id<Db: DbHandle>(handle: &mut Db) -> Result<String, Error> {
|
||||
let id = crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.id()
|
||||
.get(handle)
|
||||
.await?;
|
||||
Ok(id.to_string())
|
||||
}
|
||||
|
||||
pub async fn get_hostname<Db: DbHandle>(handle: &mut Db) -> Result<Hostname, Error> {
|
||||
if let Ok(hostname) = crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.hostname()
|
||||
.get(handle)
|
||||
.await
|
||||
{
|
||||
if let Some(hostname) = hostname.to_owned() {
|
||||
return Ok(Hostname(hostname));
|
||||
}
|
||||
}
|
||||
let id = get_id(handle).await?;
|
||||
if id.len() != 8 {
|
||||
return Ok(generate_hostname());
|
||||
}
|
||||
return Ok(Hostname(format!("embassy-{}", id)));
|
||||
}
|
||||
#[instrument(skip_all)]
|
||||
pub async fn sync_hostname<Db: DbHandle>(handle: &mut Db) -> Result<(), Error> {
|
||||
set_hostname(&get_hostname(handle).await?).await?;
|
||||
Command::new("systemctl")
|
||||
.arg("restart")
|
||||
.arg("avahi-daemon")
|
||||
.invoke(crate::ErrorKind::Network)
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_2_1: emver::Version = emver::Version::new(0, 3, 2, 1);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_2::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_2_1
|
||||
}
|
||||
fn compat(&self) -> &'static emver::VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
use async_trait::async_trait;
|
||||
use emver::VersionRange;
|
||||
use regex::Regex;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
use crate::DEFAULT_MARKETPLACE;
|
||||
|
||||
const V0_3_3: emver::Version = emver::Version::new(0, 3, 3, 0);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_2_1::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_3
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
let mut ui = crate::db::DatabaseModel::new().ui().get_mut(db).await?;
|
||||
|
||||
if let Some(Value::String(selected_url)) =
|
||||
ui["marketplace"]
|
||||
.get("selected-id")
|
||||
.and_then(|selected_id| {
|
||||
if let Value::String(selected_id) = selected_id {
|
||||
return Some(ui["marketplace"]["known-hosts"].get(&selected_id)?);
|
||||
}
|
||||
None
|
||||
})
|
||||
{
|
||||
ui["marketplace"]["selected-url"] = json!(selected_url);
|
||||
}
|
||||
if let Value::Object(ref mut obj) = *ui {
|
||||
obj.remove("pkg-order");
|
||||
obj.remove("auto-check-updates");
|
||||
}
|
||||
let known_hosts = ui["marketplace"]["known-hosts"].take();
|
||||
ui["marketplace"]["known-hosts"] = json!({});
|
||||
if let Value::Object(known_hosts) = known_hosts {
|
||||
for (_id, value) in known_hosts {
|
||||
if let Value::String(url) = &value["url"] {
|
||||
ui["marketplace"]["known-hosts"][ensure_trailing_slashes(url)] = json!({});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui["marketplace"]["known-hosts"]["https://registry.start9.com/"] = json!({});
|
||||
|
||||
if let Some(Value::Object(ref mut obj)) = ui.get_mut("marketplace") {
|
||||
obj.remove("selected-id");
|
||||
}
|
||||
if ui["marketplace"]["selected-url"].is_null() {
|
||||
ui["marketplace"]["selected-url"] = json!(MarketPlaceUrls::Default.url());
|
||||
}
|
||||
ui.save(db).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
let mut ui = crate::db::DatabaseModel::new().ui().get_mut(db).await?;
|
||||
let selected_url = ui["marketplace"]["selected-url"]
|
||||
.as_str()
|
||||
.map(|x| x.to_owned());
|
||||
let known_hosts = ui["marketplace"]["known-hosts"].take();
|
||||
ui["marketplace"]["known-hosts"] = json!({});
|
||||
if let Value::Object(known_hosts) = known_hosts {
|
||||
for (url, obj) in known_hosts {
|
||||
if let Value::String(name) = &obj["name"] {
|
||||
let id = uuid::Uuid::new_v4().to_string();
|
||||
if Some(name) == selected_url.as_ref() {
|
||||
ui["marketplace"]["selected-id"] = Value::String(id.clone());
|
||||
}
|
||||
ui["marketplace"]["known-hosts"][id.as_str()] = json!({
|
||||
"name": name,
|
||||
"url": url
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ui["auto-check-updates"] = Value::Bool(true);
|
||||
ui["pkg-order"] = json!(crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.keys(db)
|
||||
.await?
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<String>>());
|
||||
if let Some(Value::Object(ref mut obj)) = ui.get_mut("marketplace") {
|
||||
obj.remove("selected-url");
|
||||
}
|
||||
ui.save(db).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn ensure_trailing_slashes(url: &str) -> String {
|
||||
lazy_static::lazy_static! {
|
||||
static ref REG: Regex = Regex::new(r".*/$").unwrap();
|
||||
}
|
||||
if REG.is_match(url) {
|
||||
return url.to_string();
|
||||
}
|
||||
format!("{url}/")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ensure_trailing_slashed() {
|
||||
assert_eq!(
|
||||
&ensure_trailing_slashes("http://start9.com"),
|
||||
"http://start9.com/"
|
||||
);
|
||||
assert_eq!(
|
||||
&ensure_trailing_slashes("http://start9.com/"),
|
||||
"http://start9.com/"
|
||||
);
|
||||
assert_eq!(
|
||||
&ensure_trailing_slashes("http://start9.com/a"),
|
||||
"http://start9.com/a/"
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum MarketPlaceUrls {
|
||||
Default,
|
||||
}
|
||||
|
||||
impl MarketPlaceUrls {
|
||||
pub fn url(&self) -> String {
|
||||
let url_string = match self {
|
||||
MarketPlaceUrls::Default => DEFAULT_MARKETPLACE,
|
||||
};
|
||||
format!("{url_string}/")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_that_ui_includes_url() {
|
||||
let ui: Value =
|
||||
serde_json::from_str(include_str!("../../../frontend/patchdb-ui-seed.json")).unwrap();
|
||||
for market_place in [MarketPlaceUrls::Default] {
|
||||
let url = market_place.url();
|
||||
assert!(
|
||||
!ui["marketplace"]["known-hosts"][&url].is_null(),
|
||||
"Should have a market place for {url}"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
use async_trait::async_trait;
|
||||
use emver::VersionRange;
|
||||
use itertools::Itertools;
|
||||
use openssl::hash::MessageDigest;
|
||||
use serde_json::{json, Value};
|
||||
use ssh_key::public::Ed25519PublicKey;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
use crate::account::AccountInfo;
|
||||
use crate::hostname::{generate_hostname, sync_hostname, Hostname};
|
||||
|
||||
const V0_3_4: emver::Version = emver::Version::new(0, 3, 4, 0);
|
||||
|
||||
const COMMUNITY_URL: &str = "https://community-registry.start9.com/";
|
||||
const MAIN_REGISTRY: &str = "https://registry.start9.com/";
|
||||
const COMMUNITY_SERVICES: &[&str] = &[
|
||||
"ipfs",
|
||||
"agora",
|
||||
"lightning-jet",
|
||||
"balanceofsatoshis",
|
||||
"mastodon",
|
||||
"lndg",
|
||||
"robosats",
|
||||
"thunderhub",
|
||||
"syncthing",
|
||||
"sphinx-relay",
|
||||
];
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_3::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_4
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, db: &mut Db, secrets: &PgPool) -> Result<(), Error> {
|
||||
let mut account = AccountInfo::load(secrets).await?;
|
||||
crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.pubkey()
|
||||
.put(
|
||||
db,
|
||||
&ssh_key::PublicKey::from(Ed25519PublicKey::from(&account.key.ssh_key()))
|
||||
.to_openssh()?,
|
||||
)
|
||||
.await?;
|
||||
crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.ca_fingerprint()
|
||||
.put(
|
||||
db,
|
||||
&account
|
||||
.root_ca_cert
|
||||
.digest(MessageDigest::sha256())
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|x| format!("{x:X}"))
|
||||
.join(":"),
|
||||
)
|
||||
.await?;
|
||||
let server_info = crate::db::DatabaseModel::new()
|
||||
.server_info()
|
||||
.get(db)
|
||||
.await?
|
||||
.into_owned();
|
||||
account.hostname = server_info
|
||||
.hostname
|
||||
.map(Hostname)
|
||||
.unwrap_or_else(generate_hostname);
|
||||
account.server_id = server_info.id;
|
||||
account.save(secrets).await?;
|
||||
sync_hostname(&account.hostname).await?;
|
||||
|
||||
let parsed_url = Some(COMMUNITY_URL.parse().unwrap());
|
||||
let mut ui = crate::db::DatabaseModel::new().ui().get_mut(db).await?;
|
||||
ui["marketplace"]["known-hosts"][COMMUNITY_URL] = json!({});
|
||||
ui["marketplace"]["known-hosts"][MAIN_REGISTRY] = json!({});
|
||||
for package_id in crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.keys(db)
|
||||
.await?
|
||||
{
|
||||
if !COMMUNITY_SERVICES.contains(&&*package_id.to_string()) {
|
||||
continue;
|
||||
}
|
||||
crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.idx_model(&package_id)
|
||||
.expect(db)
|
||||
.await?
|
||||
.installed()
|
||||
.expect(db)
|
||||
.await?
|
||||
.marketplace_url()
|
||||
.put(db, &parsed_url)
|
||||
.await?;
|
||||
}
|
||||
ui["theme"] = json!("Dark".to_string());
|
||||
ui["widgets"] = json!([]);
|
||||
ui.save(db).await?;
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
let mut ui = crate::db::DatabaseModel::new().ui().get_mut(db).await?;
|
||||
let parsed_url = Some(MAIN_REGISTRY.parse().unwrap());
|
||||
for package_id in crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.keys(db)
|
||||
.await?
|
||||
{
|
||||
if !COMMUNITY_SERVICES.contains(&&*package_id.to_string()) {
|
||||
continue;
|
||||
}
|
||||
crate::db::DatabaseModel::new()
|
||||
.package_data()
|
||||
.idx_model(&package_id)
|
||||
.expect(db)
|
||||
.await?
|
||||
.installed()
|
||||
.expect(db)
|
||||
.await?
|
||||
.marketplace_url()
|
||||
.put(db, &parsed_url)
|
||||
.await?;
|
||||
}
|
||||
|
||||
if let Value::Object(ref mut obj) = *ui {
|
||||
obj.remove("theme");
|
||||
obj.remove("widgets");
|
||||
}
|
||||
|
||||
ui["marketplace"]["known-hosts"][COMMUNITY_URL].take();
|
||||
ui["marketplace"]["known-hosts"][MAIN_REGISTRY].take();
|
||||
ui.save(db).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use async_trait::async_trait;
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_4_1: emver::Version = emver::Version::new(0, 3, 4, 1);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_4::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_4_1
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
use async_trait::async_trait;
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_4_2: emver::Version = emver::Version::new(0, 3, 4, 2);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
|
||||
#[async_trait]
|
||||
impl VersionT for Version {
|
||||
type Previous = v0_3_4_1::Version;
|
||||
fn new() -> Self {
|
||||
Version
|
||||
}
|
||||
fn semver(&self) -> emver::Version {
|
||||
V0_3_4_2
|
||||
}
|
||||
fn compat(&self) -> &'static VersionRange {
|
||||
&*V0_3_0_COMPAT
|
||||
}
|
||||
async fn up<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
async fn down<Db: DbHandle>(&self, _db: &mut Db, _secrets: &PgPool) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,18 @@
|
||||
use async_trait::async_trait;
|
||||
use emver::VersionRange;
|
||||
|
||||
use super::v0_3_0::V0_3_0_COMPAT;
|
||||
use super::*;
|
||||
|
||||
const V0_3_4_3: emver::Version = emver::Version::new(0, 3, 4, 3);
|
||||
lazy_static! {
|
||||
static ref V0_3_0_COMPAT: VersionRange = VersionRange::Conj(
|
||||
Box::new(VersionRange::Anchor(
|
||||
emver::GTE,
|
||||
emver::Version::new(0, 3, 0, 0)
|
||||
)),
|
||||
Box::new(VersionRange::Anchor(emver::LTE, Current::new().semver())),
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Version;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": null,
|
||||
"ack-welcome": "0.4.0",
|
||||
"ack-welcome": "0.3.4",
|
||||
"marketplace": {
|
||||
"selected-url": "https://registry.start9.com/",
|
||||
"known-hosts": {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use color_eyre::eyre::eyre;
|
||||
use color_eyre::Report;
|
||||
use models::InterfaceId;
|
||||
use models::PackageId;
|
||||
@@ -76,8 +75,8 @@ pub trait OsApi: Send + Sync + 'static {
|
||||
|
||||
async fn unbind_local(&self, id: InterfaceId, external: u16) -> Result<(), Report>;
|
||||
async fn unbind_onion(&self, id: InterfaceId, external: u16) -> Result<(), Report>;
|
||||
fn set_started(&self);
|
||||
async fn restart(&self);
|
||||
async fn start(&self);
|
||||
async fn stop(&self);
|
||||
fn set_started(&self) -> Result<(), Report>;
|
||||
async fn restart(&self) -> Result<(), Report>;
|
||||
async fn start(&self) -> Result<(), Report>;
|
||||
async fn stop(&self) -> Result<(), Report>;
|
||||
}
|
||||
|
||||
@@ -1559,7 +1559,7 @@ mod fns {
|
||||
callback.map(|id| Callback::new(id, sender)),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Couldn't get service config: {e:?}"))
|
||||
.map_err(|e| anyhow!("Couldn't get service config: {e}"))
|
||||
}
|
||||
|
||||
#[op]
|
||||
@@ -1585,7 +1585,7 @@ mod fns {
|
||||
};
|
||||
os.bind_onion(internal_port, address_schema)
|
||||
.await
|
||||
.map_err(|e| anyhow!("{e:?}"))
|
||||
.map_err(|e| anyhow!("{e}"))
|
||||
}
|
||||
#[op]
|
||||
async fn bind_local(
|
||||
@@ -1610,16 +1610,16 @@ mod fns {
|
||||
};
|
||||
os.bind_local(internal_port, address_schema)
|
||||
.await
|
||||
.map_err(|e| anyhow!("{e:?}"))
|
||||
.map_err(|e| anyhow!("{e}"))
|
||||
}
|
||||
|
||||
#[op]
|
||||
fn set_started(state: &mut OpState) {
|
||||
fn set_started(state: &mut OpState) -> Result<(), AnyError> {
|
||||
let os = {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.set_started()
|
||||
os.set_started().map_err(|e| anyhow!("{e}"))
|
||||
}
|
||||
|
||||
#[op]
|
||||
@@ -1639,7 +1639,7 @@ mod fns {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.restart().await;
|
||||
os.restart().await.map_err(|e| anyhow!("{e}"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1661,7 +1661,7 @@ mod fns {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.start().await;
|
||||
os.start().await.map_err(|e| anyhow!("{e}"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -1683,7 +1683,7 @@ mod fns {
|
||||
let ctx = state.borrow::<JsContext>();
|
||||
ctx.os.clone()
|
||||
};
|
||||
os.stop().await;
|
||||
os.stop().await.map_err(|e| anyhow!("{e}"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user