[wip] universal workers

This commit is contained in:
2026-03-21 07:32:11 -05:00
parent 0782675a2b
commit 8ba7e3bb84
59 changed files with 4971 additions and 34 deletions

View File

@@ -677,6 +677,15 @@ impl Default for PackRegistryConfig {
}
}
/// Agent binary distribution configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AgentConfig {
/// Directory containing agent binary files
pub binary_dir: String,
/// Optional bootstrap token for authenticating agent binary downloads
pub bootstrap_token: Option<String>,
}
/// Executor service configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ExecutorConfig {
@@ -770,6 +779,9 @@ pub struct Config {
/// Executor configuration (optional, for executor service)
pub executor: Option<ExecutorConfig>,
/// Agent configuration (optional, for agent binary distribution)
pub agent: Option<AgentConfig>,
}
fn default_service_name() -> String {
@@ -1066,6 +1078,7 @@ mod tests {
notifier: None,
pack_registry: PackRegistryConfig::default(),
executor: None,
agent: None,
};
assert_eq!(config.service_name, "attune");
@@ -1144,6 +1157,7 @@ mod tests {
notifier: None,
pack_registry: PackRegistryConfig::default(),
executor: None,
agent: None,
};
assert!(config.validate().is_ok());

View File

@@ -780,6 +780,8 @@ pub mod runtime {
pub installation: Option<JsonDict>,
pub installers: JsonDict,
pub execution_config: JsonDict,
pub auto_detected: bool,
pub detection_config: JsonDict,
pub created: DateTime<Utc>,
pub updated: DateTime<Utc>,
}

View File

@@ -374,6 +374,7 @@ impl PackEnvironmentManager {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
WHERE id = $1

View File

@@ -418,6 +418,7 @@ impl<'a> PackComponentLoader<'a> {
None => Patch::Clear,
}),
execution_config: Some(execution_config),
..Default::default()
};
match RuntimeRepository::update(self.pool, existing.id, update_input).await {
@@ -448,6 +449,8 @@ impl<'a> PackComponentLoader<'a> {
distributions,
installation,
execution_config,
auto_detected: false,
detection_config: serde_json::json!({}),
};
match RuntimeRepository::create(self.pool, input).await {

View File

@@ -23,6 +23,13 @@ impl Repository for RuntimeRepository {
}
}
/// Columns selected for all Runtime queries. Centralised here so that
/// schema changes only need one update.
pub const SELECT_COLUMNS: &str = "id, ref, pack, pack_ref, description, name, \
distributions, installation, installers, execution_config, \
auto_detected, detection_config, \
created, updated";
/// Input for creating a new runtime
#[derive(Debug, Clone)]
pub struct CreateRuntimeInput {
@@ -34,6 +41,8 @@ pub struct CreateRuntimeInput {
pub distributions: JsonDict,
pub installation: Option<JsonDict>,
pub execution_config: JsonDict,
pub auto_detected: bool,
pub detection_config: JsonDict,
}
/// Input for updating a runtime
@@ -44,6 +53,8 @@ pub struct UpdateRuntimeInput {
pub distributions: Option<JsonDict>,
pub installation: Option<Patch<JsonDict>>,
pub execution_config: Option<JsonDict>,
pub auto_detected: Option<bool>,
pub detection_config: Option<JsonDict>,
}
#[async_trait::async_trait]
@@ -56,6 +67,7 @@ impl FindById for RuntimeRepository {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
WHERE id = $1
@@ -79,6 +91,7 @@ impl FindByRef for RuntimeRepository {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
WHERE ref = $1
@@ -102,6 +115,7 @@ impl List for RuntimeRepository {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
ORDER BY ref ASC
@@ -125,10 +139,12 @@ impl Create for RuntimeRepository {
let runtime = sqlx::query_as::<_, Runtime>(
r#"
INSERT INTO runtime (ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
distributions, installation, installers, execution_config,
auto_detected, detection_config)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
RETURNING id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
"#,
)
@@ -141,6 +157,8 @@ impl Create for RuntimeRepository {
.bind(&input.installation)
.bind(serde_json::json!({}))
.bind(&input.execution_config)
.bind(input.auto_detected)
.bind(&input.detection_config)
.fetch_one(executor)
.await?;
@@ -209,6 +227,24 @@ impl Update for RuntimeRepository {
has_updates = true;
}
if let Some(auto_detected) = input.auto_detected {
if has_updates {
query.push(", ");
}
query.push("auto_detected = ");
query.push_bind(auto_detected);
has_updates = true;
}
if let Some(detection_config) = &input.detection_config {
if has_updates {
query.push(", ");
}
query.push("detection_config = ");
query.push_bind(detection_config);
has_updates = true;
}
if !has_updates {
// No updates requested, fetch and return existing entity
return Self::get_by_id(executor, id).await;
@@ -218,7 +254,9 @@ impl Update for RuntimeRepository {
query.push_bind(id);
query.push(
" RETURNING id, ref, pack, pack_ref, description, name, \
distributions, installation, installers, execution_config, created, updated",
distributions, installation, installers, execution_config, \
auto_detected, detection_config, \
created, updated",
);
let runtime = query
@@ -255,6 +293,7 @@ impl RuntimeRepository {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
WHERE pack = $1
@@ -277,6 +316,7 @@ impl RuntimeRepository {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
WHERE LOWER(name) = LOWER($1)

View File

@@ -42,6 +42,11 @@ pub fn normalize_runtime_name(name: &str) -> &str {
"python" | "python3" => "python",
"bash" | "sh" | "shell" => "shell",
"native" | "builtin" | "standalone" => "native",
"ruby" | "rb" => "ruby",
"go" | "golang" => "go",
"java" | "jdk" | "openjdk" => "java",
"perl" | "perl5" => "perl",
"r" | "rscript" => "r",
other => other,
}
}
@@ -160,6 +165,7 @@ impl RuntimeDetector {
r#"
SELECT id, ref, pack, pack_ref, description, name,
distributions, installation, installers, execution_config,
auto_detected, detection_config,
created, updated
FROM runtime
ORDER BY ref
@@ -363,6 +369,37 @@ mod tests {
assert_eq!(normalize_runtime_name("standalone"), "native");
}
#[test]
fn test_normalize_runtime_name_ruby_variants() {
assert_eq!(normalize_runtime_name("ruby"), "ruby");
assert_eq!(normalize_runtime_name("rb"), "ruby");
}
#[test]
fn test_normalize_runtime_name_go_variants() {
assert_eq!(normalize_runtime_name("go"), "go");
assert_eq!(normalize_runtime_name("golang"), "go");
}
#[test]
fn test_normalize_runtime_name_java_variants() {
assert_eq!(normalize_runtime_name("java"), "java");
assert_eq!(normalize_runtime_name("jdk"), "java");
assert_eq!(normalize_runtime_name("openjdk"), "java");
}
#[test]
fn test_normalize_runtime_name_perl_variants() {
assert_eq!(normalize_runtime_name("perl"), "perl");
assert_eq!(normalize_runtime_name("perl5"), "perl");
}
#[test]
fn test_normalize_runtime_name_r_variants() {
assert_eq!(normalize_runtime_name("r"), "r");
assert_eq!(normalize_runtime_name("rscript"), "r");
}
#[test]
fn test_normalize_runtime_name_passthrough() {
assert_eq!(normalize_runtime_name("custom_runtime"), "custom_runtime");
@@ -390,6 +427,12 @@ mod tests {
assert!(runtime_matches_filter("python", "Python"));
assert!(runtime_matches_filter("Shell", "shell"));
assert!(runtime_matches_filter("NODEJS", "node"));
assert!(runtime_matches_filter("Ruby", "ruby"));
assert!(runtime_matches_filter("ruby", "rb"));
assert!(runtime_matches_filter("Go", "golang"));
assert!(runtime_matches_filter("R", "rscript"));
assert!(runtime_matches_filter("Java", "jdk"));
assert!(runtime_matches_filter("Perl", "perl5"));
assert!(!runtime_matches_filter("Python", "node"));
}

View File

@@ -964,6 +964,8 @@ impl RuntimeFixture {
distributions: self.distributions,
installation: self.installation,
execution_config: self.execution_config,
auto_detected: false,
detection_config: serde_json::json!({}),
};
RuntimeRepository::create(pool, input).await

View File

@@ -79,6 +79,8 @@ impl RuntimeFixture {
"file_extension": ".py"
}
}),
auto_detected: false,
detection_config: json!({}),
}
}
@@ -102,6 +104,8 @@ impl RuntimeFixture {
"file_extension": ".sh"
}
}),
auto_detected: false,
detection_config: json!({}),
}
}
}
@@ -268,6 +272,7 @@ async fn test_update_runtime() {
"method": "npm"
}))),
execution_config: None,
..Default::default()
};
let updated = RuntimeRepository::update(&pool, created.id, update_input.clone())
@@ -299,6 +304,7 @@ async fn test_update_runtime_partial() {
distributions: None,
installation: None,
execution_config: None,
..Default::default()
};
let updated = RuntimeRepository::update(&pool, created.id, update_input.clone())

View File

@@ -583,6 +583,8 @@ async fn test_worker_with_runtime() {
"file_extension": ".sh"
}
}),
auto_detected: false,
detection_config: json!({}),
};
let runtime = RuntimeRepository::create(&pool, runtime_input)