Bugfix/sdk misc (#2847)

* misc sdk fixes

* version bump

* formatting

* add missing dependency to root

* alpha.16 and beta.17

* beta.18
This commit is contained in:
Aiden McClelland
2025-03-16 09:04:10 -06:00
committed by GitHub
parent e662b2f393
commit 05162ca350
50 changed files with 756 additions and 442 deletions

View File

@@ -14,7 +14,7 @@ keywords = [
name = "start-os"
readme = "README.md"
repository = "https://github.com/Start9Labs/start-os"
version = "0.3.6-alpha.15" # VERSION_BUMP
version = "0.3.6-alpha.16" # VERSION_BUMP
license = "MIT"
[lib]

View File

@@ -1021,6 +1021,15 @@ impl ListenerMap {
fn poll_accept(&self, cx: &mut std::task::Context<'_>) -> Poll<Result<Accepted, Error>> {
for (bind_addr, listener) in self.listeners.iter() {
if let Poll::Ready((stream, addr)) = listener.0.poll_accept(cx)? {
if let Err(e) = socket2::SockRef::from(&stream).set_tcp_keepalive(
&socket2::TcpKeepalive::new()
.with_time(Duration::from_secs(900))
.with_interval(Duration::from_secs(60))
.with_retries(5),
) {
tracing::error!("Failed to set tcp keepalive: {e}");
tracing::debug!("{e:?}");
}
return Poll::Ready(Ok(Accepted {
stream,
peer: addr,

View File

@@ -258,16 +258,6 @@ impl VHostServer {
}
}
if let Err(e) = socket2::SockRef::from(&accepted.stream).set_tcp_keepalive(
&socket2::TcpKeepalive::new()
.with_time(Duration::from_secs(900))
.with_interval(Duration::from_secs(60))
.with_retries(5),
) {
tracing::error!("Failed to set tcp keepalive: {e}");
tracing::debug!("{e:?}");
}
tokio::spawn(async move {
let bind = accepted.bind;
if let Err(e) =

View File

@@ -36,6 +36,25 @@ impl<'a, T: Clone> Expected<'a, T> {
))
}
}
pub fn check_dir(&mut self, path: impl AsRef<Path>) -> Result<(), Error> {
if let Some(dir) = self
.dir
.get_path(path.as_ref())
.and_then(|e| e.as_directory())
{
for entry in dir.file_paths(path.as_ref()) {
if !entry.to_string_lossy().ends_with("/") {
self.keep.insert_path(entry, Entry::file(()))?;
}
}
Ok(())
} else {
Err(Error::new(
eyre!("directory {} missing from archive", path.as_ref().display()),
ErrorKind::ParseS9pk,
))
}
}
pub fn check_stem(
&mut self,
path: impl AsRef<Path>,

View File

@@ -129,25 +129,16 @@ impl S9pk<TmpSource<PackSource>> {
tokio_tar::Archive::new(reader.assets().await?)
.unpack(&asset_dir)
.await?;
for (asset_id, _) in manifest
.volumes
.iter()
.filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("assets"))
{
let assets_path = asset_dir.join(&asset_id);
let sqfs_path = assets_path.with_extension("squashfs");
Command::new("mksquashfs")
.arg(&assets_path)
.arg(&sqfs_path)
.invoke(ErrorKind::Filesystem)
.await?;
archive.insert_path(
Path::new("assets")
.join(&asset_id)
.with_extension("squashfs"),
Entry::file(TmpSource::new(tmp_dir.clone(), PackSource::File(sqfs_path))),
)?;
}
let sqfs_path = asset_dir.with_extension("squashfs");
Command::new("mksquashfs")
.arg(&asset_dir)
.arg(&sqfs_path)
.invoke(ErrorKind::Filesystem)
.await?;
archive.insert_path(
"assets.squashfs",
Entry::file(TmpSource::new(tmp_dir.clone(), PackSource::File(sqfs_path))),
)?;
// javascript
let js_dir = tmp_dir.join("javascript");
@@ -217,12 +208,6 @@ impl TryFrom<ManifestV1> for Manifest {
donation_url: value.donation_url,
description: value.description,
images: BTreeMap::new(),
assets: value
.volumes
.iter()
.filter(|(_, v)| v.get("type").and_then(|v| v.as_str()) == Some("assets"))
.map(|(id, _)| id.clone())
.collect(),
volumes: value
.volumes
.iter()

View File

@@ -53,7 +53,6 @@ pub struct Manifest {
pub donation_url: Option<Url>,
pub description: Description,
pub images: BTreeMap<ImageId, ImageConfig>,
pub assets: BTreeSet<VolumeId>, // TODO: AssetsId
pub volumes: BTreeSet<VolumeId>,
#[serde(default)]
pub alerts: Alerts,
@@ -93,8 +92,11 @@ impl Manifest {
.map_or(false, |mime| mime.starts_with("image/"))
});
}
for assets in &self.assets {
expected.check_file(Path::new("assets").join(assets).with_extension("squashfs"))?;
if let Err(e) = expected.check_file(Path::new("assets.squashfs")) {
// backwards compatibility for alpha s9pks - remove eventually
if expected.check_dir("assets").is_err() {
return Err(e);
}
}
for (image_id, config) in &self.images {
let mut check_arch = |arch: &str| {

View File

@@ -60,7 +60,7 @@ fn priority(s: &str) -> Option<usize> {
"instructions.md" => Some(3),
"dependencies" => Some(4),
"javascript.squashfs" => Some(5),
"assets" => Some(6),
"assets.squashfs" => Some(6),
"images" => Some(7),
_ => None,
}

View File

@@ -694,18 +694,13 @@ pub async fn pack(ctx: CliContext, params: PackParams) -> Result<(), Error> {
.await?;
let assets_dir = params.assets();
for assets in s9pk.as_manifest().assets.clone() {
s9pk.as_archive_mut().contents_mut().insert_path(
Path::new("assets").join(&assets).with_extension("squashfs"),
Entry::file(TmpSource::new(
tmp_dir.clone(),
PackSource::Squashfs(Arc::new(SqfsDir::new(
assets_dir.join(&assets),
tmp_dir.clone(),
))),
)),
)?;
}
s9pk.as_archive_mut().contents_mut().insert_path(
"assets.squashfs",
Entry::file(TmpSource::new(
tmp_dir.clone(),
PackSource::Squashfs(Arc::new(SqfsDir::new(assets_dir, tmp_dir.clone()))),
)),
)?;
s9pk.load_images(tmp_dir.clone()).await?;
@@ -816,9 +811,7 @@ pub async fn list_ingredients(_: CliContext, params: PackParams) -> Result<Vec<P
}
let assets_dir = params.assets();
for assets in manifest.assets {
ingredients.push(assets_dir.join(assets));
}
ingredients.push(assets_dir);
for image in manifest.images.values() {
ingredients.extend(image.source.ingredients());

View File

@@ -106,7 +106,7 @@ pub struct PersistentContainer {
// procedures: Mutex<Vec<(ProcedureName, ProcedureId)>>,
js_mount: MountGuard,
volumes: BTreeMap<VolumeId, MountGuard>,
assets: BTreeMap<VolumeId, MountGuard>,
assets: Vec<MountGuard>,
pub(super) images: BTreeMap<ImageId, Arc<MountGuard>>,
pub(super) subcontainers: Arc<Mutex<BTreeMap<Guid, Subcontainer>>>,
pub(super) state: Arc<watch::Sender<ServiceState>>,
@@ -168,35 +168,63 @@ impl PersistentContainer {
.await?;
volumes.insert(volume.clone(), mount);
}
let mut assets = BTreeMap::new();
for asset in &s9pk.as_manifest().assets {
let mountpoint = lxc_container
.rootfs_dir()
.join("media/startos/assets")
.join(asset);
tokio::fs::create_dir_all(&mountpoint).await?;
Command::new("chown")
.arg("100000:100000")
.arg(&mountpoint)
.invoke(crate::ErrorKind::Filesystem)
.await?;
let s9pk_asset_path = Path::new("assets").join(asset).with_extension("squashfs");
let sqfs = s9pk
.as_archive()
.contents()
.get_path(&s9pk_asset_path)
.and_then(|e| e.as_file())
.or_not_found(s9pk_asset_path.display())?;
assets.insert(
asset.clone(),
let mountpoint = lxc_container.rootfs_dir().join("media/startos/assets");
tokio::fs::create_dir_all(&mountpoint).await?;
Command::new("chown")
.arg("100000:100000")
.arg(&mountpoint)
.invoke(crate::ErrorKind::Filesystem)
.await?;
let assets = if let Some(sqfs) = s9pk
.as_archive()
.contents()
.get_path("assets.squashfs")
.and_then(|e| e.as_file())
{
vec![
MountGuard::mount(
&IdMapped::new(LoopDev::from(&**sqfs), 0, 100000, 65536),
mountpoint,
MountType::ReadWrite,
)
.await?,
);
}
]
} else if let Some(dir) = s9pk
.as_archive()
.contents()
.get_path("assets")
.and_then(|e| e.as_directory())
{
// backwards compatibility for alpha s9pks - remove eventually
let mut assets = Vec::new();
for (asset, entry) in &**dir {
let mountpoint = lxc_container
.rootfs_dir()
.join("media/startos/assets")
.join(Path::new(asset).with_extension(""));
tokio::fs::create_dir_all(&mountpoint).await?;
Command::new("chown")
.arg("100000:100000")
.arg(&mountpoint)
.invoke(crate::ErrorKind::Filesystem)
.await?;
let Some(sqfs) = entry.as_file() else {
continue;
};
assets.push(
MountGuard::mount(
&IdMapped::new(LoopDev::from(&**sqfs), 0, 100000, 65536),
mountpoint,
MountType::ReadWrite,
)
.await?,
);
}
assets
} else {
Vec::new()
};
let mut images = BTreeMap::new();
let image_path = lxc_container.rootfs_dir().join("media/startos/images");
@@ -432,7 +460,7 @@ impl PersistentContainer {
for (_, volume) in volumes {
errs.handle(volume.unmount(true).await);
}
for (_, assets) in assets {
for assets in assets {
errs.handle(assets.unmount(true).await);
}
for (_, overlay) in std::mem::take(&mut *subcontainers.lock().await) {

View File

@@ -35,8 +35,9 @@ mod v0_3_6_alpha_12;
mod v0_3_6_alpha_13;
mod v0_3_6_alpha_14;
mod v0_3_6_alpha_15;
mod v0_3_6_alpha_16;
pub type Current = v0_3_6_alpha_15::Version; // VERSION_BUMP
pub type Current = v0_3_6_alpha_16::Version; // VERSION_BUMP
impl Current {
#[instrument(skip(self, db))]
@@ -133,7 +134,8 @@ enum Version {
V0_3_6_alpha_12(Wrapper<v0_3_6_alpha_12::Version>),
V0_3_6_alpha_13(Wrapper<v0_3_6_alpha_13::Version>),
V0_3_6_alpha_14(Wrapper<v0_3_6_alpha_14::Version>),
V0_3_6_alpha_15(Wrapper<v0_3_6_alpha_15::Version>), // VERSION_BUMP
V0_3_6_alpha_15(Wrapper<v0_3_6_alpha_15::Version>),
V0_3_6_alpha_16(Wrapper<v0_3_6_alpha_16::Version>), // VERSION_BUMP
Other(exver::Version),
}
@@ -172,7 +174,8 @@ impl Version {
Self::V0_3_6_alpha_12(v) => DynVersion(Box::new(v.0)),
Self::V0_3_6_alpha_13(v) => DynVersion(Box::new(v.0)),
Self::V0_3_6_alpha_14(v) => DynVersion(Box::new(v.0)),
Self::V0_3_6_alpha_15(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
Self::V0_3_6_alpha_15(v) => DynVersion(Box::new(v.0)),
Self::V0_3_6_alpha_16(v) => DynVersion(Box::new(v.0)), // VERSION_BUMP
Self::Other(v) => {
return Err(Error::new(
eyre!("unknown version {v}"),
@@ -203,7 +206,8 @@ impl Version {
Version::V0_3_6_alpha_12(Wrapper(x)) => x.semver(),
Version::V0_3_6_alpha_13(Wrapper(x)) => x.semver(),
Version::V0_3_6_alpha_14(Wrapper(x)) => x.semver(),
Version::V0_3_6_alpha_15(Wrapper(x)) => x.semver(), // VERSION_BUMP
Version::V0_3_6_alpha_15(Wrapper(x)) => x.semver(),
Version::V0_3_6_alpha_16(Wrapper(x)) => x.semver(), // VERSION_BUMP
Version::Other(x) => x.clone(),
}
}

View File

@@ -0,0 +1,36 @@
use exver::{PreReleaseSegment, VersionRange};
use super::v0_3_5::V0_3_0_COMPAT;
use super::{v0_3_6_alpha_15, VersionT};
use crate::prelude::*;
lazy_static::lazy_static! {
static ref V0_3_6_alpha_16: exver::Version = exver::Version::new(
[0, 3, 6],
[PreReleaseSegment::String("alpha".into()), 16.into()]
);
}
#[derive(Clone, Copy, Debug, Default)]
pub struct Version;
impl VersionT for Version {
type Previous = v0_3_6_alpha_15::Version;
type PreUpRes = ();
async fn pre_up(self) -> Result<Self::PreUpRes, Error> {
Ok(())
}
fn semver(self) -> exver::Version {
V0_3_6_alpha_16.clone()
}
fn compat(self) -> &'static VersionRange {
&V0_3_0_COMPAT
}
fn up(self, _db: &mut Value, _: Self::PreUpRes) -> Result<(), Error> {
Ok(())
}
fn down(self, _db: &mut Value) -> Result<(), Error> {
Ok(())
}
}