Skip to content

feat: Add resource-info-fetcher - #863

Open
sbernauer wants to merge 36 commits into
mainfrom
spike/rif
Open

feat: Add resource-info-fetcher#863
sbernauer wants to merge 36 commits into
mainfrom
spike/rif

Conversation

@sbernauer

@sbernauer sbernauer commented Jul 21, 2026

Copy link
Copy Markdown
Member

Description

Part of #848

Yes, the diff looks big, but most of it are lockfiles and kuttl tests

CRD change

Basically the same as for the user-info-fetcher. The only difference is the env field, which is DataHub specific.

Look at extra/crds.yaml for the concrete CRD change

  clusterConfig:
    resourceInfo: # <1>
      backend:
        dataHub:
          hostname: datahub-gms.my-namespace.svc.cluster.local
          port: 8080
          rootPath: / # optional, defaults to /
          tls:
            verification:
              server:
                caCert:
                  secretClass: tls # <2>
          credentialsSecretName: resource-info-fetcher-credentials # <3>
          env: PROD # <4>
      cache: # optional, enabled by default
        entryTimeToLive: 60s # optional, defaults to 60s
---
apiVersion: v1
kind: Secret
metadata:
  name: resource-info-fetcher-credentials
stringData:
  token: <datahub-personal-access-token> # <3>

API of RIF

The rego rules and HTTP API of RIF: https://github.com/stackabletech/opa-operator/blob/spike/rif/docs/modules/opa/pages/usage-guide/resource-info-fetcher.adoc

Definition of Done Checklist

  • Not all of these items are applicable to all PRs, the author should update this template to only leave the boxes in that are relevant
  • Please make sure all these things are done and tick the boxes

Author

  • Changes are OpenShift compatible
  • CRD changes approved
  • CRD documentation for all fields, following the style guide.
  • Helm chart can be installed and deployed operator works
  • Integration tests passed (for non trivial changes)
  • Changes need to be "offline" compatible
  • Links to generated (nightly) docs added
  • Release note snippet added

Reviewer

  • Code contains useful comments
  • Code contains useful logging statements
  • (Integration-)Test cases added
  • Documentation added or updated. Follows the style guide.
  • Changelog updated
  • Cargo.toml only contains references to git tags (not specific commits or branches)

Acceptance

  • Feature Tracker has been updated
  • Proper release label has been added
  • Links to generated (nightly) docs added
  • Release note snippet added
  • Add type/deprecation label & add to the deprecation schedule
  • Add type/experimental label & add to the experimental features tracker

Release notes

Added
  • Add an initial version of resource-info-fetcher, which is similar to user-info-fetcher, but allows to fetch additional metadata about resource information from a data catalog.
    For now only DataHub is supported.
    Also, a rego-rule library has been added to make it easier to call resource-info-fetcher from within OPA.
    The API (especially the response) might change in the future once more data catalogs are supported

Nightly docs

As soon as this PR is merged the docs will show up at https://docs.stackable.tech/home/nightly/opa/usage-guide/resource-info-fetcher/

@sbernauer
sbernauer marked this pull request as ready for review July 30, 2026 13:49
@lfrancke

Copy link
Copy Markdown
Member

Because we had it yesterday with OpenLineage: I believe it could make sense to add a "path" or "endpoint" field. Just in case DataHub is deployed behind some proxy. ://

@sbernauer

Copy link
Copy Markdown
Member Author

I believe it could make sense to add a "path" or "endpoint" field

Good point! For consistency reasons with UIF and AuthenticationClass I went with rootPath in 215d4b9. Feel free to have a look

@sbernauer sbernauer self-assigned this Jul 31, 2026
@sbernauer
sbernauer requested a review from Maleware July 31, 2026 08:53
@sbernauer sbernauer moved this to Development: Waiting for Review in Stackable Engineering Jul 31, 2026

@Maleware Maleware left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just two typos, thanks you! Test passes locally, thus LTGTM otherwise.

}

/// Generates the trivial `From<Params> for ResourceInfoRequest` conversions, so each HTTP handler
/// can turn its deserialized query parameters into a [`ResourceInfoRequest`] via `.into()`. Adding a

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// can turn its deserialized query parameters into a [`ResourceInfoRequest`] via `.into()`. Adding a
/// can turn its deserialized query parameters into a [`ResourceInfoRequest`] via `.from()`. Adding a

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://doc.rust-lang.org/std/convert/trait.From.html
From automatically implements Into, so the caller can pick.
In

P: DeserializeOwned + Into<ResourceInfoRequest>,
we actually use Into<ResourceInfoRequest>. In general I feel in this situation a into feels more natural than a from

Comment thread rust/resource-info-fetcher/src/main.rs Outdated
Co-authored-by: Maximilian Wittich <56642549+Maleware@users.noreply.github.com>
@sbernauer
sbernauer requested a review from Maleware August 5, 2026 05:56
@sbernauer

Copy link
Copy Markdown
Member Author

Please vote on the CRD change as well as the rego rule API on this comment. Feel free to also look at the JSON API, but I'd say that's an implementation detail we are allowed to change in the future

@maltesander
maltesander self-requested a review August 5, 2026 06:26

@maltesander maltesander left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First round, did not check docs etc. properly yet and not testing yet.

Comment on lines +183 to +187
let mut client_builder = ClientBuilder::new();
client_builder = utils::tls::configure_reqwest(&config.tls, client_builder)
.await
.context(ConfigureTlsSnafu)?;
let http_client = client_builder.build().context(ConstructHttpClientSnafu)?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses request client builder and does not have any timeouts set.
Check the UIF backends and please use utils::http::client_builder() instead.

Comment on lines +142 to +147
let resource_info_cache = {
Cache::builder()
.name("resource-info")
.time_to_live(*config.cache.entry_time_to_live)
.build()
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sidecar has 128MB memory and this cache can grow forever. UIF is limited/keyed on usernames from a directory, so this is limited. Set a max capacity (or make it configurable)?

Comment on lines +174 to +175
// Trim trailing whitespace/newlines so the value is safe to use in an HTTP header.
let token = tokio::fs::read_to_string(&token_path)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is never refreshed? Will go stale and produce 401 until restart?

fragment ResourceInfo on Entity {
# DataHub has no direct "dataProduct" field on assets; membership is a graph edge that points from
# the data product to its assets. From the asset's side it is therefore an INCOMING relationship.
dataProducts: relationships(input: {types: ["DataProductContains"], direction: INCOMING, count: 10}) {

@maltesander maltesander Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there is something belonging to 11 data products? Why limit to 10? This will hard fail policies that should succeed. Can we paginate that or warn (if a much higher limit than 10 (e.g. 1000)) is reached somehow?

@@ -0,0 +1,179 @@
= Resource info fetcher

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not referenced in nav.adoc?

xref:opa:usage-guide/resource-info-fetcher.adoc[]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, bf85e53

///
/// [`urn_for_request`]: crate::backend::data_hub::resource_to_urn_mapping::urn_for_request
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ResourceInfoRequest {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The instance is always required. Datahub (defaults) leave that out and a trino table will become e.g. urn:li:dataset:(urn:li:dataPlatform:trino,tpch.sf1.customer,PROD) and the tableResourceInfo always builds {instance}.tpch.sf1.customer which will be empty and therefore fail a correct rego?

Can we make instance optional and skip?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Development: Waiting for Review

Development

Successfully merging this pull request may close these issues.

4 participants