refactor(cli): remove lasuite from workflows
This commit is contained in:
@@ -325,8 +325,8 @@ impl StepBody for ConfigureOIDC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create new OIDC auth source
|
// Create new OIDC auth source
|
||||||
let oidc_id = k::kube_get_secret_field("lasuite", "oidc-gitea", "CLIENT_ID").await;
|
let oidc_id = k::kube_get_secret_field("devtools", "oidc-gitea", "CLIENT_ID").await;
|
||||||
let oidc_secret = k::kube_get_secret_field("lasuite", "oidc-gitea", "CLIENT_SECRET").await;
|
let oidc_secret = k::kube_get_secret_field("devtools", "oidc-gitea", "CLIENT_SECRET").await;
|
||||||
|
|
||||||
match (oidc_id, oidc_secret) {
|
match (oidc_id, oidc_secret) {
|
||||||
(Ok(oidc_id), Ok(oidc_sec)) => {
|
(Ok(oidc_id), Ok(oidc_sec)) => {
|
||||||
|
|||||||
@@ -26,58 +26,14 @@ pub fn all_service_configs() -> Vec<Value> {
|
|||||||
{"key":"admin-username","generator":"gitea_admin"},
|
{"key":"admin-username","generator":"gitea_admin"},
|
||||||
{"key":"admin-password","generator":"rand_token"}
|
{"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":[
|
json!({"service":"livekit","fields":[
|
||||||
{"key":"api-key","generator":"static:devkey"},
|
{"key":"api-key","generator":"static:devkey"},
|
||||||
{"key":"api-secret","generator":"rand_token"}
|
{"key":"api-secret","generator":"rand_token"}
|
||||||
]}),
|
]}),
|
||||||
json!({"service":"people","fields":[
|
|
||||||
{"key":"django-secret-key","generator":"rand_token"}
|
|
||||||
]}),
|
|
||||||
json!({"service":"login-ui","fields":[
|
json!({"service":"login-ui","fields":[
|
||||||
{"key":"cookie-secret","generator":"rand_token"},
|
{"key":"cookie-secret","generator":"rand_token"},
|
||||||
{"key":"csrf-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":[
|
json!({"service":"tuwunel","fields":[
|
||||||
{"key":"oidc-client-id","generator":"static:"},
|
{"key":"oidc-client-id","generator":"static:"},
|
||||||
{"key":"oidc-client-secret","generator":"static:"},
|
{"key":"oidc-client-secret","generator":"static:"},
|
||||||
@@ -117,10 +73,17 @@ pub fn kratos_admin_config() -> Value {
|
|||||||
/// All service names (for WriteKVPath branches).
|
/// All service names (for WriteKVPath branches).
|
||||||
pub fn all_service_names() -> Vec<&'static str> {
|
pub fn all_service_names() -> Vec<&'static str> {
|
||||||
vec![
|
vec![
|
||||||
"hydra", "kratos", "seaweedfs", "gitea", "hive", "livekit",
|
"hydra",
|
||||||
"people", "login-ui", "kratos-admin", "docs", "meet", "drive",
|
"kratos",
|
||||||
"projects", "calendars", "messages", "collabora", "tuwunel",
|
"seaweedfs",
|
||||||
"grafana", "scaleway-s3", "headscale",
|
"gitea",
|
||||||
|
"livekit",
|
||||||
|
"login-ui",
|
||||||
|
"kratos-admin",
|
||||||
|
"tuwunel",
|
||||||
|
"grafana",
|
||||||
|
"scaleway-s3",
|
||||||
|
"headscale",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,22 +95,28 @@ mod tests {
|
|||||||
fn all_configs_have_service_and_fields() {
|
fn all_configs_have_service_and_fields() {
|
||||||
for cfg in all_service_configs() {
|
for cfg in all_service_configs() {
|
||||||
assert!(cfg.get("service").is_some(), "missing service in {cfg}");
|
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]
|
#[test]
|
||||||
fn service_count() {
|
fn service_count() {
|
||||||
// 19 independent + 1 kratos-admin (dependent)
|
// 10 independent + 1 kratos-admin (dependent)
|
||||||
assert_eq!(all_service_configs().len(), 19);
|
assert_eq!(all_service_configs().len(), 10);
|
||||||
assert_eq!(all_service_names().len(), 20);
|
assert_eq!(all_service_names().len(), 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn kratos_admin_has_from_creds() {
|
fn kratos_admin_has_from_creds() {
|
||||||
let cfg = kratos_admin_config();
|
let cfg = kratos_admin_config();
|
||||||
let fields = cfg["fields"].as_array().unwrap();
|
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:"));
|
assert!(s3_field["generator"].as_str().unwrap().starts_with("from_creds:"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,8 +206,8 @@ mod tests {
|
|||||||
let db_steps: Vec<_> = def.steps.iter()
|
let db_steps: Vec<_> = def.steps.iter()
|
||||||
.filter(|s| s.step_type.contains("CreatePGDatabase"))
|
.filter(|s| s.step_type.contains("CreatePGDatabase"))
|
||||||
.collect();
|
.collect();
|
||||||
assert_eq!(role_steps.len(), 16, "should have 16 CreatePGRole steps");
|
assert_eq!(role_steps.len(), 7, "should have 7 CreatePGRole steps");
|
||||||
assert_eq!(db_steps.len(), 16, "should have 16 CreatePGDatabase steps");
|
assert_eq!(db_steps.len(), 7, "should have 7 CreatePGDatabase steps");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -32,15 +32,16 @@ fn json_str(data: &serde_json::Value, key: &str) -> Option<String> {
|
|||||||
/// Build the user to database mapping used by EnsurePGRolesAndDatabases.
|
/// Build the user to database mapping used by EnsurePGRolesAndDatabases.
|
||||||
pub(crate) fn pg_db_map() -> HashMap<&'static str, &'static str> {
|
pub(crate) fn pg_db_map() -> HashMap<&'static str, &'static str> {
|
||||||
[
|
[
|
||||||
("kratos", "kratos_db"), ("hydra", "hydra_db"), ("gitea", "gitea_db"),
|
("kratos", "kratos_db"),
|
||||||
("hive", "hive_db"), ("docs", "docs_db"), ("meet", "meet_db"),
|
("hydra", "hydra_db"),
|
||||||
("drive", "drive_db"), ("messages", "messages_db"),
|
("gitea", "gitea_db"),
|
||||||
("conversations", "conversations_db"), ("people", "people_db"),
|
|
||||||
("find", "find_db"), ("calendars", "calendars_db"), ("projects", "projects_db"),
|
|
||||||
("penpot", "penpot_db"),
|
("penpot", "penpot_db"),
|
||||||
("stalwart", "stalwart_db"),
|
("stalwart", "stalwart_db"),
|
||||||
("headscale", "headscale_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.
|
/// SQL to idempotently create a postgres user if it does not exist.
|
||||||
@@ -219,7 +220,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_pg_db_map_contains_all_users() {
|
fn test_pg_db_map_contains_all_users() {
|
||||||
let map = pg_db_map();
|
let map = pg_db_map();
|
||||||
assert_eq!(map.len(), 16);
|
assert_eq!(map.len(), 7);
|
||||||
for user in crate::secrets::PG_USERS {
|
for user in crate::secrets::PG_USERS {
|
||||||
assert!(map.contains_key(user), "pg_db_map missing key for: {user}");
|
assert!(map.contains_key(user), "pg_db_map missing key for: {user}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ pub fn build() -> WorkflowDefinition {
|
|||||||
.name("write-vso-role")
|
.name("write-vso-role")
|
||||||
.config(json!({"mount": "kubernetes", "role": "vso", "config": {
|
.config(json!({"mount": "kubernetes", "role": "vso", "config": {
|
||||||
"bound_service_account_names": "default",
|
"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",
|
"policies": "vso-reader",
|
||||||
"ttl": "1h"
|
"ttl": "1h"
|
||||||
}}))
|
}}))
|
||||||
@@ -159,6 +159,17 @@ pub fn build() -> WorkflowDefinition {
|
|||||||
b.add_step_typed::<ApplyManifest>("apply-media",
|
b.add_step_typed::<ApplyManifest>("apply-media",
|
||||||
Some(json!({"namespace": "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) ──────────────
|
// ── Phase 6: K8s secrets (parallel by namespace) ──────────────
|
||||||
@@ -211,27 +222,6 @@ pub fn build() -> WorkflowDefinition {
|
|||||||
b.wire_outcome(ns, s1, None);
|
b.wire_outcome(ns, s1, None);
|
||||||
b.wire_outcome(s1, s2, 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| {
|
.branch(|b| {
|
||||||
b.add_step_typed::<EnsureNamespace>("ensure-ns-matrix",
|
b.add_step_typed::<EnsureNamespace>("ensure-ns-matrix",
|
||||||
Some(json!({"namespace": "matrix"})));
|
Some(json!({"namespace": "matrix"})));
|
||||||
@@ -253,14 +243,16 @@ pub fn build() -> WorkflowDefinition {
|
|||||||
|
|
||||||
// ── Phase 7: Application manifests ────────────────────────────
|
// ── Phase 7: Application manifests ────────────────────────────
|
||||||
.parallel(|p| p
|
.parallel(|p| p
|
||||||
.branch(|b| {
|
|
||||||
b.add_step_typed::<ApplyManifest>("apply-lasuite",
|
|
||||||
Some(json!({"namespace": "lasuite"})));
|
|
||||||
})
|
|
||||||
.branch(|b| {
|
.branch(|b| {
|
||||||
b.add_step_typed::<ApplyManifest>("apply-matrix",
|
b.add_step_typed::<ApplyManifest>("apply-matrix",
|
||||||
Some(json!({"namespace": "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) ─────────
|
// ── Phase 8: Core rollouts + OpenSearch ML (parallel) ─────────
|
||||||
|
|||||||
Reference in New Issue
Block a user