Skip to content

Commit a1da9db

Browse files
committed
feat: Implement Trino catalog and schema
1 parent ccadaf8 commit a1da9db

7 files changed

Lines changed: 93 additions & 7 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ futures = { version = "0.3" }
2626
hyper = "1.4"
2727
indoc = "2.0"
2828
ldap3 = { version = "0.12", features = ["gssapi", "tls"] }
29+
md5 = "0.7"
2930
moka = { version = "0.12", features = ["future"] }
3031
native-tls = "0.2.12"
3132
pin-project = "1.1"

extra/crds.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ spec:
518518
properties:
519519
entryTimeToLive:
520520
default: 1m
521-
description: How long metadata about each user should be cached for.
521+
description: How long responses should be cached for.
522522
type: string
523523
type: object
524524
type: object
@@ -2449,7 +2449,7 @@ spec:
24492449
properties:
24502450
entryTimeToLive:
24512451
default: 1m
2452-
description: How long metadata about each user should be cached for.
2452+
description: How long responses should be cached for.
24532453
type: string
24542454
type: object
24552455
type: object

rust/operator-binary/src/crd/resource_info_fetcher/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ pub mod versioned {
4545
}
4646
}
4747

48+
// We actually use it as serde(default) value, but Rust fails to see that
49+
#[allow(dead_code)]
4850
fn default_data_hub_env() -> String {
4951
"PROD".to_owned()
5052
}

rust/resource-info-fetcher/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ axum.workspace = true
1717
clap.workspace = true
1818
futures.workspace = true
1919
hyper.workspace = true
20+
md5.workspace = true
2021
moka.workspace = true
2122
reqwest.workspace = true
2223
serde.workspace = true

rust/resource-info-fetcher/src/api.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,21 @@ pub struct ResourceInfoRequest {
2626

2727
#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
2828
#[serde(rename_all = "camelCase")]
29+
// Soon there will be something else than Trino
30+
#[expect(clippy::enum_variant_names)]
2931
pub enum ResourceInfoRequestResource {
3032
TrinoTable {
3133
catalog: String,
3234
schema: String,
3335
table: String,
3436
},
35-
// TrinoSchema {
36-
// catalog: String,
37-
// schema: String,
38-
// },
37+
TrinoSchema {
38+
catalog: String,
39+
schema: String,
40+
},
41+
TrinoCatalog {
42+
catalog: String,
43+
},
3944
}
4045

4146
#[derive(Snafu, Debug)]

rust/resource-info-fetcher/src/backend/data_hub/resource_to_urn_mapping.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use crate::api::{ResourceInfoRequest, ResourceInfoRequestResource};
1+
use std::collections::BTreeMap;
22

3+
use crate::api::{ResourceInfoRequest, ResourceInfoRequestResource};
34

45
pub fn urn_for_request(request: &ResourceInfoRequest, env: &str) -> String {
56
let stacklet = &request.stacklet;
@@ -13,5 +14,74 @@ pub fn urn_for_request(request: &ResourceInfoRequest, env: &str) -> String {
1314
"urn:li:dataset:(urn:li:dataPlatform:{stacklet},{catalog}.{schema}.{table},{env})"
1415
)
1516
}
17+
// Trino catalogs and schemas are modelled as DataHub `Container`s (subtypes `Database` and
18+
// `Schema` respectively). Unlike datasets, their URN is not human-readable but a GUID derived
19+
// from the container key - see `container_urn`.
20+
ResourceInfoRequestResource::TrinoCatalog { catalog } => {
21+
container_urn(&BTreeMap::from([
22+
("platform", stacklet.as_str()),
23+
("instance", env),
24+
("database", catalog.as_str()),
25+
]))
26+
}
27+
ResourceInfoRequestResource::TrinoSchema { catalog, schema } => {
28+
container_urn(&BTreeMap::from([
29+
("platform", stacklet.as_str()),
30+
("instance", env),
31+
("database", catalog.as_str()),
32+
("schema", schema.as_str()),
33+
]))
34+
}
35+
}
36+
}
37+
38+
/// Reproduces DataHub's `datahub_guid`: the container key is serialized to compact, key-sorted JSON
39+
/// and MD5-hashed. A [`BTreeMap`] yields sorted keys and `serde_json` emits no whitespace, which
40+
/// matches Python's `json.dumps(key, sort_keys=True, separators=(",", ":"))`.
41+
///
42+
/// Note that the SQL ingestion source sets `backcompat_env_as_instance`, so the configured `env`
43+
/// (e.g. `PROD`) ends up in the `instance` field and no `env` field is present in the key. The
44+
/// `platform` is the bare platform name (e.g. `trino`), *not* the `urn:li:dataPlatform:` form.
45+
fn container_urn(container_key: &BTreeMap<&str, &str>) -> String {
46+
let key_json =
47+
serde_json::to_string(container_key).expect("serializing a BTreeMap<&str, &str> cannot fail");
48+
format!("urn:li:container:{:x}", md5::compute(key_json.as_bytes()))
49+
}
50+
51+
#[cfg(test)]
52+
mod tests {
53+
use super::*;
54+
55+
/// Verified against a live DataHub: the schema `customer_analytics` in catalog `lakehouse`.
56+
#[test]
57+
fn trino_schema_urn_matches_data_hub() {
58+
let request = ResourceInfoRequest {
59+
stacklet: "trino".to_owned(),
60+
resource: ResourceInfoRequestResource::TrinoSchema {
61+
catalog: "lakehouse".to_owned(),
62+
schema: "customer_analytics".to_owned(),
63+
},
64+
};
65+
66+
assert_eq!(
67+
urn_for_request(&request, "PROD"),
68+
"urn:li:container:c8531e5a52cacf56768d0bf77ca8787c"
69+
);
70+
}
71+
72+
/// Verified against a live DataHub: the catalog `lakehouse`.
73+
#[test]
74+
fn trino_catalog_urn_matches_data_hub() {
75+
let request = ResourceInfoRequest {
76+
stacklet: "trino".to_owned(),
77+
resource: ResourceInfoRequestResource::TrinoCatalog {
78+
catalog: "lakehouse".to_owned(),
79+
},
80+
};
81+
82+
assert_eq!(
83+
urn_for_request(&request, "PROD"),
84+
"urn:li:container:39967cd09b38e2d4736d1eb604cd5247"
85+
);
1686
}
1787
}

0 commit comments

Comments
 (0)