mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-07 08:02:40 +00:00
* feat: Handle `pip install` by `uv` Dirty and untested, but already something working * Integrate with NSJAIL and prepare fallbacks * Refactor fallback no_uv disable compile and install where no_uv_install and no_uv_compile are a bit more specific * Remove `--disable-pip-version-check` Reason: warning: pip's `--disable-pip-version-check` has no effect * Fix backend compilation error * Pip fallback overwrite UV's cache * Initially refactor cache (No S3) * Support S3 * Remove unused import * Handle flags for NSJAIL * Return deleted flag * Remove verbose mode and enable link-mode=copy * Granural migration of lockfiles Before i realized we dont need it :) * Initial draft (not-working) * Add fallback * Fix bug preventing uv from installing deps '\n' - Love it * Add verbosity indicator * Iterate on feature - Added instance python version - Rework logic * Fix EE build error error[E0599]: no method named `iter` found for tuple `(PyVersion, std::vec::Vec<std::string::String>)` in the current scope * Support S3 * Support NSJAIL * Refactor `get_python` * Make NSJAIL work [Unsafe] config file missed /proc mount causing install phase to fail * Trigger CI * Clean up * Make Actions build it * Trigger CI #2 * Update Dockerfile and clean up * Change fallbacks now there is only no_uv and NOUV * Expose INSTANCE_PYTHON_VERSION through env variable * Change namings * Include py-version to requirements.in Also add comments and make code much cleaner * Use const for python installation dir It was hardcoded before * Pin preinstalled version * Update python_executor.rs * Up to date branch * Create PYCACHE dirs TODO: PY_TAR_DIRS * Fix after merge * Make it safer * Implement USE_SYSTEM_PYTHON * Implement latest_stable option * Load INSTANCE_PYTHON_VERSION on startup * Check for multiple annotations used * Fix Latest Stable button not pressed if selected * Proper error handling for conflict on multiple annotations * Fix merge conflicts * Preinstall 3.11 and Latest Stable * Preinstall latest stable in non-blocking manner * Fix Warning * Gate preinstall logic behind "python" feature * Handle raw_deps properly * Make it work with nsjail * Revert docker-image.yml * Revert Dockerfile * Cleanup + Fixing * Add windows support --------- Co-authored-by: Ruben Fiszel <ruben@windmill.dev>
144 lines
4.2 KiB
Rust
144 lines
4.2 KiB
Rust
// #[cfg(feature = "enterprise")]
|
|
// use rand::Rng;
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet"))]
|
|
use tokio::time::Instant;
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet", unix))]
|
|
use object_store::ObjectStore;
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet"))]
|
|
use windmill_common::error;
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet", unix))]
|
|
use std::sync::Arc;
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet", unix))]
|
|
pub async fn build_tar_and_push(
|
|
s3_client: Arc<dyn ObjectStore>,
|
|
folder: String,
|
|
// python_311
|
|
python_xyz: String,
|
|
no_uv: bool,
|
|
) -> error::Result<()> {
|
|
use object_store::path::Path;
|
|
|
|
use crate::{TAR_PIP_CACHE_DIR, TAR_PYBASE_CACHE_DIR};
|
|
|
|
tracing::info!("Started building and pushing piptar {folder}");
|
|
let start = Instant::now();
|
|
|
|
// e.g. tiny==1.0.0
|
|
let folder_name = folder.split("/").last().unwrap();
|
|
|
|
let prefix = if no_uv {
|
|
TAR_PIP_CACHE_DIR
|
|
} else {
|
|
&format!("{TAR_PYBASE_CACHE_DIR}/{}", python_xyz)
|
|
};
|
|
let tar_path = format!("{prefix}/{folder_name}_tar.tar",);
|
|
|
|
let tar_file = std::fs::File::create(&tar_path)?;
|
|
let mut tar = tar::Builder::new(tar_file);
|
|
tar.append_dir_all(".", &folder)?;
|
|
|
|
let tar_metadata = tokio::fs::metadata(&tar_path).await;
|
|
if tar_metadata.is_err() || tar_metadata.as_ref().unwrap().len() == 0 {
|
|
tracing::info!("Failed to tar cache: {folder}");
|
|
return Err(error::Error::ExecutionErr(format!(
|
|
"Failed to tar cache: {folder}"
|
|
)));
|
|
}
|
|
|
|
// let s3_settings = S3_CACHE_SETTINGS.read().await;
|
|
// let s3_client = s3_settings.as_ref().ok_or_else(|| {
|
|
// error::Error::ExecutionErr("Failed to read s3 cache settings".to_string())
|
|
// })?;
|
|
if let Err(e) = s3_client
|
|
.put(
|
|
&Path::from(format!(
|
|
"/tar/{}/{folder_name}.tar",
|
|
if no_uv { "pip" } else { &python_xyz }
|
|
)),
|
|
std::fs::read(&tar_path)?.into(),
|
|
)
|
|
.await
|
|
{
|
|
tracing::info!("Failed to put tar to s3: {tar_path}. Error: {:?}", e);
|
|
return Err(error::Error::ExecutionErr(format!(
|
|
"Failed to put tar to s3: {tar_path}"
|
|
)));
|
|
}
|
|
|
|
tokio::fs::remove_file(&tar_path).await.map_err(|e| {
|
|
tracing::error!("Failed to remove piptar {folder_name}. Error: {:?}", e);
|
|
e
|
|
})?;
|
|
|
|
tracing::info!(
|
|
"Finished copying piptar {folder} to bucket as tar, took: {:?}s. Size of tar: {}",
|
|
start.elapsed().as_secs(),
|
|
tar_metadata.unwrap().len(),
|
|
);
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet", unix))]
|
|
pub async fn pull_from_tar(
|
|
client: Arc<dyn ObjectStore>,
|
|
folder: String,
|
|
// python_311
|
|
python_xyz: String,
|
|
no_uv: bool,
|
|
) -> error::Result<()> {
|
|
use windmill_common::s3_helpers::attempt_fetch_bytes;
|
|
|
|
let folder_name = folder.split("/").last().unwrap();
|
|
|
|
tracing::info!("Attempting to pull piptar {folder_name} from bucket");
|
|
|
|
let start = Instant::now();
|
|
|
|
let tar_path = format!(
|
|
"tar/{}/{folder_name}.tar",
|
|
if no_uv { "pip".to_owned() } else { python_xyz }
|
|
);
|
|
let bytes = attempt_fetch_bytes(client, &tar_path).await?;
|
|
|
|
extract_tar(bytes, &folder).await.map_err(|e| {
|
|
tracing::error!("Failed to extract piptar {folder_name}. Error: {:?}", e);
|
|
e
|
|
})?;
|
|
|
|
tracing::info!(
|
|
"Finished pulling and extracting {folder_name}. Took {:?}ms",
|
|
start.elapsed().as_millis()
|
|
);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(all(feature = "enterprise", feature = "parquet"))]
|
|
pub async fn extract_tar(tar: bytes::Bytes, folder: &str) -> error::Result<()> {
|
|
use bytes::Buf;
|
|
use tokio::fs::{self};
|
|
|
|
let start: Instant = Instant::now();
|
|
fs::create_dir_all(&folder).await?;
|
|
|
|
let mut ar = tar::Archive::new(tar.reader());
|
|
|
|
if let Err(e) = ar.unpack(folder) {
|
|
tracing::info!("Failed to untar to {folder}. Error: {:?}", e);
|
|
fs::remove_dir_all(&folder).await?;
|
|
return Err(error::Error::ExecutionErr(format!(
|
|
"Failed to untar tar {folder}"
|
|
)));
|
|
}
|
|
tracing::info!(
|
|
"Finished extracting tar to {folder}. Took {}ms",
|
|
start.elapsed().as_millis(),
|
|
);
|
|
Ok(())
|
|
}
|