refactor(cli): remove lasuite from workflows

This commit is contained in:
2026-04-07 19:25:59 +01:00
parent bfbc391e7f
commit 7c64093342
5 changed files with 52 additions and 90 deletions

View File

@@ -325,8 +325,8 @@ impl StepBody for ConfigureOIDC {
}
// Create new OIDC auth source
let oidc_id = k::kube_get_secret_field("lasuite", "oidc-gitea", "CLIENT_ID").await;
let oidc_secret = k::kube_get_secret_field("lasuite", "oidc-gitea", "CLIENT_SECRET").await;
let oidc_id = k::kube_get_secret_field("devtools", "oidc-gitea", "CLIENT_ID").await;
let oidc_secret = k::kube_get_secret_field("devtools", "oidc-gitea", "CLIENT_SECRET").await;
match (oidc_id, oidc_secret) {
(Ok(oidc_id), Ok(oidc_sec)) => {

View File

@@ -26,58 +26,14 @@ pub fn all_service_configs() -> Vec<Value> {
{"key":"admin-username","generator":"gitea_admin"},
{"key":"admin-password","generator":"rand_token"}
]}),
json!({"service":"hive","fields":[
{"key":"oidc-client-id","generator":"static:hive-local"},
{"key":"oidc-client-secret","generator":"rand_token"}
]}),
json!({"service":"livekit","fields":[
{"key":"api-key","generator":"static:devkey"},
{"key":"api-secret","generator":"rand_token"}
]}),
json!({"service":"people","fields":[
{"key":"django-secret-key","generator":"rand_token"}
]}),
json!({"service":"login-ui","fields":[
{"key":"cookie-secret","generator":"rand_token"},
{"key":"csrf-cookie-secret","generator":"rand_token"}
]}),
json!({"service":"docs","fields":[
{"key":"django-secret-key","generator":"rand_token"},
{"key":"collaboration-secret","generator":"rand_token"}
]}),
json!({"service":"meet","fields":[
{"key":"django-secret-key","generator":"rand_token"},
{"key":"application-jwt-secret-key","generator":"rand_token"}
]}),
json!({"service":"drive","fields":[
{"key":"django-secret-key","generator":"rand_token"}
]}),
json!({"service":"projects","fields":[
{"key":"secret-key","generator":"rand_token"}
]}),
json!({"service":"calendars","fields":[
{"key":"django-secret-key","generator":"rand_token_50"},
{"key":"salt-key","generator":"rand_token"},
{"key":"caldav-inbound-api-key","generator":"rand_token"},
{"key":"caldav-outbound-api-key","generator":"rand_token"},
{"key":"caldav-internal-api-key","generator":"rand_token"}
]}),
json!({"service":"messages","fields":[
{"key":"django-secret-key","generator":"rand_token"},
{"key":"salt-key","generator":"rand_token"},
{"key":"mda-api-secret","generator":"rand_token"},
{"key":"oidc-refresh-token-key","generator":"fernet_key"},
{"key":"dkim-private-key","generator":"dkim_private"},
{"key":"dkim-public-key","generator":"dkim_public"},
{"key":"rspamd-password","generator":"rand_token"},
{"key":"socks-proxy-users","generator":"socks_proxy"},
{"key":"mta-out-smtp-username","generator":"static:sunbeam"},
{"key":"mta-out-smtp-password","generator":"rand_token"}
]}),
json!({"service":"collabora","fields":[
{"key":"username","generator":"static:admin"},
{"key":"password","generator":"rand_token"}
]}),
json!({"service":"tuwunel","fields":[
{"key":"oidc-client-id","generator":"static:"},
{"key":"oidc-client-secret","generator":"static:"},
@@ -117,10 +73,17 @@ pub fn kratos_admin_config() -> Value {
/// All service names (for WriteKVPath branches).
pub fn all_service_names() -> Vec<&'static str> {
vec![
"hydra", "kratos", "seaweedfs", "gitea", "hive", "livekit",
"people", "login-ui", "kratos-admin", "docs", "meet", "drive",
"projects", "calendars", "messages", "collabora", "tuwunel",
"grafana", "scaleway-s3", "headscale",
"hydra",
"kratos",
"seaweedfs",
"gitea",
"livekit",
"login-ui",
"kratos-admin",
"tuwunel",
"grafana",
"scaleway-s3",
"headscale",
]
}
@@ -132,22 +95,28 @@ mod tests {
fn all_configs_have_service_and_fields() {
for cfg in all_service_configs() {
assert!(cfg.get("service").is_some(), "missing service in {cfg}");
assert!(cfg.get("fields").and_then(|f| f.as_array()).is_some(), "missing fields in {cfg}");
assert!(
cfg.get("fields").and_then(|f| f.as_array()).is_some(),
"missing fields in {cfg}"
);
}
}
#[test]
fn service_count() {
// 19 independent + 1 kratos-admin (dependent)
assert_eq!(all_service_configs().len(), 19);
assert_eq!(all_service_names().len(), 20);
// 10 independent + 1 kratos-admin (dependent)
assert_eq!(all_service_configs().len(), 10);
assert_eq!(all_service_names().len(), 11);
}
#[test]
fn kratos_admin_has_from_creds() {
let cfg = kratos_admin_config();
let fields = cfg["fields"].as_array().unwrap();
let s3_field = fields.iter().find(|f| f["key"] == "s3-access-key").unwrap();
let s3_field = fields
.iter()
.find(|f| f["key"] == "s3-access-key")
.unwrap();
assert!(s3_field["generator"].as_str().unwrap().starts_with("from_creds:"));
}
}

View File

@@ -206,8 +206,8 @@ mod tests {
let db_steps: Vec<_> = def.steps.iter()
.filter(|s| s.step_type.contains("CreatePGDatabase"))
.collect();
assert_eq!(role_steps.len(), 16, "should have 16 CreatePGRole steps");
assert_eq!(db_steps.len(), 16, "should have 16 CreatePGDatabase steps");
assert_eq!(role_steps.len(), 7, "should have 7 CreatePGRole steps");
assert_eq!(db_steps.len(), 7, "should have 7 CreatePGDatabase steps");
}
#[test]

View File

@@ -32,15 +32,16 @@ fn json_str(data: &serde_json::Value, key: &str) -> Option<String> {
/// Build the user to database mapping used by EnsurePGRolesAndDatabases.
pub(crate) fn pg_db_map() -> HashMap<&'static str, &'static str> {
[
("kratos", "kratos_db"), ("hydra", "hydra_db"), ("gitea", "gitea_db"),
("hive", "hive_db"), ("docs", "docs_db"), ("meet", "meet_db"),
("drive", "drive_db"), ("messages", "messages_db"),
("conversations", "conversations_db"), ("people", "people_db"),
("find", "find_db"), ("calendars", "calendars_db"), ("projects", "projects_db"),
("kratos", "kratos_db"),
("hydra", "hydra_db"),
("gitea", "gitea_db"),
("penpot", "penpot_db"),
("stalwart", "stalwart_db"),
("headscale", "headscale_db"),
].into_iter().collect()
("wfe", "wfe_db"),
]
.into_iter()
.collect()
}
/// SQL to idempotently create a postgres user if it does not exist.
@@ -219,7 +220,7 @@ mod tests {
#[test]
fn test_pg_db_map_contains_all_users() {
let map = pg_db_map();
assert_eq!(map.len(), 16);
assert_eq!(map.len(), 7);
for user in crate::secrets::PG_USERS {
assert!(map.contains_key(user), "pg_db_map missing key for: {user}");
}

View File

@@ -102,7 +102,7 @@ pub fn build() -> WorkflowDefinition {
.name("write-vso-role")
.config(json!({"mount": "kubernetes", "role": "vso", "config": {
"bound_service_account_names": "default",
"bound_service_account_namespaces": "ory,devtools,storage,lasuite,stalwart,matrix,media,data,monitoring,cert-manager",
"bound_service_account_namespaces": "ory,devtools,storage,stalwart,matrix,media,data,monitoring,cert-manager,vpn,wfe",
"policies": "vso-reader",
"ttl": "1h"
}}))
@@ -159,6 +159,17 @@ pub fn build() -> WorkflowDefinition {
b.add_step_typed::<ApplyManifest>("apply-media",
Some(json!({"namespace": "media"})));
})
.branch(|b| {
b.add_step_typed::<ApplyManifest>("apply-stalwart",
Some(json!({"namespace": "stalwart"})));
})
.branch(|b| {
// VPN bootstrap path — headscale needs cert-manager + the
// headscale_db postgres role from Phase 4. Both are done by
// the time this branch fires.
b.add_step_typed::<ApplyManifest>("apply-vpn",
Some(json!({"namespace": "vpn"})));
})
)
// ── Phase 6: K8s secrets (parallel by namespace) ──────────────
@@ -211,27 +222,6 @@ pub fn build() -> WorkflowDefinition {
b.wire_outcome(ns, s1, None);
b.wire_outcome(s1, s2, None);
})
.branch(|b| {
let ns = b.add_step_typed::<EnsureNamespace>("ensure-ns-lasuite",
Some(json!({"namespace": "lasuite"})));
let s1 = b.add_step_typed::<CreateK8sSecret>("secret-lasuite-s3",
Some(json!({"namespace":"lasuite","name":"seaweedfs-s3-credentials","data":{
"S3_ACCESS_KEY":"s3-access-key",
"S3_SECRET_KEY":"s3-secret-key"
}})));
let s2 = b.add_step_typed::<CreateK8sSecret>("secret-hive-oidc",
Some(json!({"namespace":"lasuite","name":"hive-oidc","data":{
"client-id":"hive-oidc-client-id",
"client-secret":"hive-oidc-client-secret"
}})));
let s3 = b.add_step_typed::<CreateK8sSecret>("secret-people-django",
Some(json!({"namespace":"lasuite","name":"people-django-secret","data":{
"DJANGO_SECRET_KEY":"people-django-secret"
}})));
b.wire_outcome(ns, s1, None);
b.wire_outcome(s1, s2, None);
b.wire_outcome(s2, s3, None);
})
.branch(|b| {
b.add_step_typed::<EnsureNamespace>("ensure-ns-matrix",
Some(json!({"namespace": "matrix"})));
@@ -253,14 +243,16 @@ pub fn build() -> WorkflowDefinition {
// ── Phase 7: Application manifests ────────────────────────────
.parallel(|p| p
.branch(|b| {
b.add_step_typed::<ApplyManifest>("apply-lasuite",
Some(json!({"namespace": "lasuite"})));
})
.branch(|b| {
b.add_step_typed::<ApplyManifest>("apply-matrix",
Some(json!({"namespace": "matrix"})));
})
.branch(|b| {
// wfe-server pulls its image from src.DOMAIN_SUFFIX (built
// locally), so it has to come *after* gitea bootstrap.
b.add_step_typed::<ApplyManifest>("apply-wfe",
Some(json!({"namespace": "wfe"})));
})
)
// ── Phase 8: Core rollouts + OpenSearch ML (parallel) ─────────