mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-24 00:00:46 +00:00
@@ -38,13 +38,10 @@ use windmill_common::{
|
||||
db::{UserDB, UserDbWithAuthed, UserDbWithOptAuthed},
|
||||
error::{self, Error, JsonResult, Result},
|
||||
get_database_url, parse_postgres_url,
|
||||
utils::{
|
||||
get_custom_pg_instance_password, not_found_if_none, paginate, require_admin, Pagination,
|
||||
StripPath,
|
||||
},
|
||||
utils::get_custom_pg_instance_password,
|
||||
utils::{not_found_if_none, paginate, require_admin, Pagination, StripPath},
|
||||
variables,
|
||||
worker::{CLOUD_HOSTED, TMP_DIR},
|
||||
workspaces::{get_datatable_from_db_unchecked, DataTableCatalogResourceType},
|
||||
};
|
||||
|
||||
pub fn workspaced_service() -> Router {
|
||||
@@ -472,25 +469,6 @@ pub async fn get_resource_value_interpolated_internal(
|
||||
token: &str,
|
||||
allow_cache: bool,
|
||||
) -> Result<Option<serde_json::Value>> {
|
||||
let (user_db, path) = if let Some(name) = path.strip_prefix("datatable://") {
|
||||
let datatable = get_datatable_from_db_unchecked(db, workspace, name).await?;
|
||||
if datatable.database.resource_type == DataTableCatalogResourceType::Instance {
|
||||
let pg_creds = parse_postgres_url(&get_database_url().await?.as_str().await)?;
|
||||
return Ok(Some(serde_json::json!({
|
||||
"dbname": datatable.database.resource_path,
|
||||
"host": pg_creds.host,
|
||||
"port": pg_creds.port,
|
||||
"user": "custom_instance_user",
|
||||
"sslmode": pg_creds.ssl_mode,
|
||||
"password": get_custom_pg_instance_password(&db).await?,
|
||||
})));
|
||||
} else {
|
||||
(None, datatable.database.resource_path)
|
||||
}
|
||||
} else {
|
||||
(user_db, path.to_string())
|
||||
};
|
||||
|
||||
// This is a special syntax to help debugging custom instance databases
|
||||
if let Some(dbname) = path.strip_prefix("CUSTOM_INSTANCE_DB/") {
|
||||
require_super_admin(db, &authed.email).await?;
|
||||
@@ -521,10 +499,10 @@ pub async fn get_resource_value_interpolated_internal(
|
||||
.await?;
|
||||
tx.commit().await?;
|
||||
if value_o.is_none() {
|
||||
explain_resource_perm_error(&path, workspace, db, &authed).await?;
|
||||
explain_resource_perm_error(path, workspace, db, &authed).await?;
|
||||
}
|
||||
|
||||
let value = not_found_if_none(value_o, "Resource", &path)?;
|
||||
let value = not_found_if_none(value_o, "Resource", path)?;
|
||||
if let Some(value) = value {
|
||||
let r = transform_json_value(
|
||||
authed,
|
||||
|
||||
@@ -170,24 +170,6 @@ pub enum DataTableCatalogResourceType {
|
||||
Instance,
|
||||
}
|
||||
|
||||
pub async fn get_datatable_from_db_unchecked(db: &DB, w_id: &str, name: &str) -> Result<DataTable> {
|
||||
let datatable = sqlx::query_scalar!(
|
||||
r#"
|
||||
SELECT ws.datatable->'datatables'->$2 AS config
|
||||
FROM workspace_settings ws
|
||||
WHERE ws.workspace_id = $1
|
||||
"#,
|
||||
&w_id,
|
||||
name
|
||||
)
|
||||
.fetch_one(db)
|
||||
.await
|
||||
.map_err(|err| Error::internal_err(format!("getting datatable {name}: {err}")))?
|
||||
.ok_or_else(|| Error::internal_err(format!("datatable {name} not found")))?;
|
||||
let datatable = serde_json::from_value::<DataTable>(datatable)?;
|
||||
Ok(datatable)
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub struct Ducklake {
|
||||
pub catalog: DucklakeCatalog,
|
||||
|
||||
@@ -127,7 +127,7 @@ pub async fn write_file_binary(dir: &str, path: &str, content: &[u8]) -> error::
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref RE_RES_VAR: Regex = Regex::new(r#"(?:\$var|\$res|\$encrypted|datatable|CUSTOM_INSTANCE_DB)\:"#).unwrap();
|
||||
static ref RE_RES_VAR: Regex = Regex::new(r#"\$(?:var|res|encrypted)\:"#).unwrap();
|
||||
}
|
||||
|
||||
pub async fn transform_json<'a>(
|
||||
@@ -137,7 +137,14 @@ pub async fn transform_json<'a>(
|
||||
job: &MiniPulledJob,
|
||||
db: &Connection,
|
||||
) -> error::Result<Option<HashMap<String, Box<RawValue>>>> {
|
||||
let has_match = vs.iter().any(|(_, v)| (*RE_RES_VAR).is_match(v.get()));
|
||||
let mut has_match = false;
|
||||
for (_, v) in vs {
|
||||
let inner_vs = v.get();
|
||||
if (*RE_RES_VAR).is_match(inner_vs) {
|
||||
has_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !has_match {
|
||||
return Ok(None);
|
||||
}
|
||||
@@ -236,24 +243,15 @@ pub async fn transform_json_value(
|
||||
)));
|
||||
}
|
||||
client
|
||||
.get_resource_value_interpolated(path, Some(job.id.to_string()))
|
||||
.get_resource_value_interpolated::<serde_json::Value>(
|
||||
path,
|
||||
Some(job.id.to_string()),
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
Error::NotFound(format!("Resource {path} not found for `{name}`: {e:#}"))
|
||||
})
|
||||
}
|
||||
Value::String(ref path)
|
||||
if path.starts_with("CUSTOM_INSTANCE_DB://") || path.starts_with("datatable://") =>
|
||||
{
|
||||
client
|
||||
.get_resource_value_interpolated(path, Some(job.id.to_string()))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
Error::NotFound(format!(
|
||||
"Custom database {path} not found for `{name}`: {e:#}"
|
||||
))
|
||||
})
|
||||
}
|
||||
Value::String(y) if y.starts_with("$encrypted:") => {
|
||||
match conn {
|
||||
Connection::Sql(db) => {
|
||||
|
||||
Reference in New Issue
Block a user