greentic-distributor-client 0.4.9

WIT-based client for the greentic:distributor-api@1.0.0 distributor resolver.
Documentation

greentic-distributor-client

WIT-based client for the greentic:distributor-api@1.0.0 world. Provides:

  • DistributorClient async trait for resolving components, querying pack status, and warming packs.
  • WitDistributorClient adapter that translates DTOs to greentic-interfaces-guest distributor-api bindings; use GeneratedDistributorApiBindings on WASM targets to call the distributor imports.
  • Optional HTTP runtime client behind the http-runtime feature for JSON endpoints that mirror the runtime API.

Uses DTOs from greentic-types.

Usage

use greentic_distributor_client::{
    DistributorApiBindings, DistributorClient, DistributorEnvironmentId, EnvId,
    GeneratedDistributorApiBindings, ResolveComponentRequest, TenantCtx, TenantId,
    WitDistributorClient,
};
use serde_json::json;

let bindings = GeneratedDistributorApiBindings::default();
let client = WitDistributorClient::new(bindings);
let resp = client.resolve_component(ResolveComponentRequest {
    tenant: TenantCtx::new(
        EnvId::try_from("prod").unwrap(),
        TenantId::try_from("tenant-a").unwrap(),
    ),
    environment_id: DistributorEnvironmentId::from("env-1"),
    pack_id: "pack-123".into(),
    component_id: "component-x".into(),
    version: "1.0.0".into(),
    extra: json!({}),
}).await?;
println!("artifact: {:?}", resp.artifact);
if let Some(reqs) = resp.secret_requirements.as_ref() {
    println!("secret requirements: {:?}", reqs);
}

GeneratedDistributorApiBindings calls the distributor imports on WASM targets. On non-WASM targets it returns an error; consumers can provide their own bindings implementation for testing.

secret_requirements is present when talking to distributor versions that support it; otherwise it is None. When requirements are returned, run greentic-secrets init --pack <pack-id> ahead of time so secrets are available to the runtime.

HTTP runtime client (feature http-runtime)

Enable the feature and construct HttpDistributorClient:

[dependencies]
greentic-distributor-client = { version = "0.4", features = ["http-runtime"] }
use greentic_distributor_client::{
    DistributorClient, DistributorClientConfig, DistributorEnvironmentId, EnvId, HttpDistributorClient,
    ResolveComponentRequest, TenantCtx, TenantId,
};
use serde_json::json;

let config = DistributorClientConfig {
    base_url: Some("https://distributor.example.com".into()),
    environment_id: DistributorEnvironmentId::from("env-1"),
    tenant: TenantCtx::new(EnvId::try_from("prod").unwrap(), TenantId::try_from("tenant-a").unwrap()),
    auth_token: Some("token123".into()),
    extra_headers: None,
    request_timeout: None,
};
let client = HttpDistributorClient::new(config)?;
let resp = client.resolve_component(ResolveComponentRequest {
    tenant: TenantCtx::new(
        EnvId::try_from("prod").unwrap(),
        TenantId::try_from("tenant-a").unwrap(),
    ),
    environment_id: DistributorEnvironmentId::from("env-1"),
    pack_id: "pack-123".into(),
    component_id: "component-x".into(),
    version: "1.0.0".into(),
    extra: json!({}),
}).await?;
println!("artifact: {:?}", resp.artifact);
if let Some(reqs) = resp.secret_requirements.as_ref() {
    println!("secret requirements: {:?}", reqs);
}

Fetch typed pack status (includes secret requirements):

let status = client
    .get_pack_status_v2(
        &TenantCtx::new(EnvId::try_from("prod")?, TenantId::try_from("tenant-a")?),
        &DistributorEnvironmentId::from("env-1"),
        "pack-123",
    )
    .await?;
println!(
    "status: {}, secrets: {:?}",
    status.status, status.secret_requirements
);

Using greentic-config-types (host-resolved config)

Resolve configuration in your host binary with greentic-config and map it into the distributor client with DistributorClientConfig::from_greentic:

use greentic_config_types::GreenticConfig;
use greentic_distributor_client::{DistributorClientConfig, DistributorEnvironmentId, DistributorClient, TenantCtx, TenantId};

let cfg: GreenticConfig = /* resolved in the host via greentic-config */;
let tenant = TenantCtx::new(cfg.environment.env_id.clone(), TenantId::try_from("tenant-a")?);
let mut client_cfg = DistributorClientConfig::from_greentic(&cfg, tenant)
    .with_base_url("https://distributor.example.com"); // host still provides the endpoint/auth
// pass client_cfg to your chosen DistributorClient implementation

Local dev distributor

Use the companion greentic-distributor-dev crate to serve packs/components from a local directory, useful for greentic-dev and conformance tests:

use greentic_distributor_client::{ChainedDistributorSource, DistributorSource, PackId, Version};
use greentic_distributor_dev::{DevConfig, DevDistributorSource};

let dev_source = DevDistributorSource::new(DevConfig::default());
let sources = ChainedDistributorSource::new(vec![Box::new(dev_source)]);

let pack_bytes = sources.fetch_pack(&PackId::try_from("dev.local.hello-flow")?, &Version::parse("0.1.0")?);
println!("Loaded {} bytes", pack_bytes.len());

Repo maintenance

  • Enable GitHub's "Allow auto-merge" setting for the repository.
  • Configure branch protection with the required checks you want enforced before merges.