Skip to content

Platform & transport

This is the API reference for the platform × transport runtime model: the Platform and Transport enums, the PlatformProfile / ResolvedProfile / ResolverInputs types, the pure resolver functions, the profile-helper functions, and the platform-profile constants. Signatures are shown as they appear in source, in each of the four SDKs.

For the conceptual narrative (the two axes, auto-detection, precedence) see Platforms & transports; for the command-line flags that feed this resolver see the CLI contract. You rarely call the resolver yourself — the builder parses the flags and runs it for you — but the types below are the public surface, and the constants are the source of truth for the env vars and tokens the model keys off.

SDK Module / package
Java com.mbreissi.ggcommons.platform (the resolver, enums, and profile types); com.mbreissi.ggcommons.GGCommons (the parser entry point processArgs).
Python ggcommons.platform — submodules platform (the Platform enum), transport (the Transport enum), and resolver (everything else).
Rust ggcommons::platform (enums, profile types, resolver fns); ggcommons::cli (the parse_from entry point).
TypeScript the ggcommons package root re-exports from platform.ts and cli.ts.

The primary axis — where the component runs. Three variants; auto is a CLI token only (it is not an enum member — it maps to “no explicit platform”, i.e. auto-detect). The CLI token parses case-insensitively.

package com.mbreissi.ggcommons.platform;
public enum Platform {
GREENGRASS, // on a Greengrass v2 Nucleus: IPC transport, Nucleus-managed config/identity
HOST, // a plain host (Docker / bare host without a Nucleus): MQTT transport
KUBERNETES // a pod: MQTT transport, ConfigMap-mounted config/identity
}

The secondary axis — how it talks. IPC is valid only on GREENGRASS (the IPC lock, enforced by validate); MQTT (the dual-MQTT provider) is valid on every platform.

package com.mbreissi.ggcommons.platform;
public enum Transport {
IPC, // Greengrass Nucleus IPC (domain socket) — requires GREENGRASS
MQTT // dual-MQTT (local broker + AWS IoT Core)
}

The per-platform table of subsystem defaults — pure data the resolver (and the subsystem init sites) consult for any setting the caller did not set explicitly. All four carry the same seven fields. The fields beyond transport and configSource are middle-tier defaults: e.g. credentialsKeyProvider only changes the default key-provider type when a credentials section is already present; it never auto-enables a subsystem.

public record PlatformProfile(
Transport transport, // default messaging transport
String configSource, // default -c/--config source token
String loggingFormat, // default logging.<lang>_format, or null
boolean healthEnabled, // start the HTTP health endpoint by default?
String metricTarget, // default metricEmission.target, or null
String credentialsKeyProvider, // default vault keyProvider.type, or null
String metricLogPath // default metric-log file path, or null
) {}

The resolver’s output — the fully resolved runtime settings every subsystem initializer consumes.

public record ResolvedProfile(
Platform platform,
Transport transport,
String[] configSource, // [SOURCE, args...]
String identity, // resolved IoT Thing name, never empty
String messagingConfigPath // resolved --transport MQTT <path>, or null (Java-only field)
) {}

The parse-time inputs to the resolver. Any field may be null/None/undefined, meaning “not specified — fall back to detection / the profile default”.

// Nested in PlatformResolver. Field 5 (messagingConfigPath) is Java-only.
public record ResolverInputs(
Platform platform, Transport transport, String[] configArgs,
String thing, String messagingConfigPath
) {
// Convenience ctor: equivalent to passing null for messagingConfigPath.
public ResolverInputs(Platform platform, Transport transport,
String[] configArgs, String thing) { /* ... */ }
}

The pure resolver: it maps ResolverInputs + the process environment to a ResolvedProfile, with no I/O beyond an injectable filesystem probe (used only to detect the Kubernetes service-account token). Signatures below.

public final class PlatformResolver {
// explicit flag ▸ platform-profile default ▸ library default
public static ResolvedProfile resolveProfile(ResolverInputs inputs, Map<String,String> env);
public static Platform detectPlatform(Map<String,String> env);
static Platform detectPlatform(Map<String,String> env, Predicate<String> fileExists);
// throws IllegalArgumentException when transport == IPC && platform != GREENGRASS
public static void validate(Platform platform, Transport transport);
public static String resolveIdentity(String thing, Platform platform, Map<String,String> env);
// the profile-default table, keyed by Platform
public static final Map<Platform, PlatformProfile> PROFILES;
}

The same call in all four SDKs — forcing HOST with a FILE config source and an explicit thing name. Leaving platform unset (null/None/undefined) auto-detects; leaving transport unset derives it from the platform (HOST → MQTT).

import com.mbreissi.ggcommons.platform.*;
import java.util.Map;
ResolvedProfile resolved = PlatformResolver.resolveProfile(
// 4-arg convenience ctor (messagingConfigPath defaults to null)
new PlatformResolver.ResolverInputs(
Platform.HOST, // null = auto-detect
null, // null = derive (→ MQTT)
new String[]{"FILE", "config.json"}, // null = profile default
"my-thing"), // null = resolve from env
System.getenv());
resolved.platform(); // HOST
resolved.transport(); // MQTT
resolved.identity(); // "my-thing"

Convenience lookups into the profile table — the middle precedence tier consumed by each subsystem’s init site (explicit config value ▸ this profile default ▸ library default). They are pure lookups (no I/O), keyed only on the resolved platform.

public static String profileLoggingFormat(Platform platform); // "json" on KUBERNETES, else null
public static boolean profileHealthEnabled(Platform platform); // true on KUBERNETES, else false
public static String profileMetricTarget(Platform platform); // "prometheus" on KUBERNETES, else null
public static String profileMetricLogPath(Platform platform); // local path on HOST/KUBERNETES, else null
public static String profileCredentialsKeyProvider(Platform platform); // "env" on KUBERNETES, else null

The contents of PROFILES (Java/Python/TypeScript) / profile() (Rust), identical across all four SDKs. Cells marked (library default) mean the profile carries no override, so the library’s own default applies downstream.

Default GREENGRASS HOST KUBERNETES
transport IPC MQTT MQTT
configSource GG_CONFIG FILE CONFIGMAP
loggingFormat console/text (library default) console/text (library default) json (stdout-JSON sink)
metricTarget log (library default) log (library default) prometheus (pull-based /metrics)
metricLogPath /greengrass/v2/logs (library default) ./logs/{ComponentFullName}.metric.log ./logs/{ComponentFullName}.metric.log
credentialsKeyProvider file (library default) file (library default) env (base64 KEK from env/Secret)
healthEnabled false false true

When you name a config source but omit its argument (-c <SOURCE> with no extra positionals), these apply:

  • FILEconfig.json
  • ENV → reads the CONFIG variable
  • GG_CONFIG → key ComponentConfig
  • CONFIGMAP → mount dir /etc/ggcommons, key config.json

Under MQTT + CONFIGMAP with no explicit --transport MQTT <path>, the messaging-config path defaults to that same mounted ConfigMap file (FR-MSG-1) — one file serves as both component config and MQTT broker config. An explicit path always wins; HOST (which uses FILE) still requires an explicit path. Java computes this in PlatformResolver.resolveMessagingConfigPath; Python, Rust, and TypeScript compute it in their CLI layer.

These constant names and values are identical in all four SDKs (public static final String in Java, module-level in Python, pub const in Rust, export const in TypeScript).

Constant Value Role
ENV_GG_IPC_SOCKET AWS_GG_NUCLEUS_DOMAIN_SOCKET_FILEPATH_FOR_COMPONENT Definitive GREENGRASS auto-detect signal.
ENV_GG_SVCUID SVCUID Definitive GREENGRASS auto-detect signal.
ENV_THING_NAME AWS_IOT_THING_NAME Identity probe (Greengrass / platform-supplied).
ENV_K8S_SERVICE_HOST KUBERNETES_SERVICE_HOST Confirming (secondary) Kubernetes signal.
K8S_SA_TOKEN_PATH /var/run/secrets/kubernetes.io/serviceaccount/token Primary, definitive Kubernetes signal (a file probe).
ENV_K8S_THING_NAME GGCOMMONS_THING_NAME Kubernetes Downward-API identity (primary k8s tier).
ENV_K8S_POD_NAME POD_NAME Kubernetes Downward-API identity (secondary k8s tier).
ENV_K8S_POD_NAMESPACE POD_NAMESPACE Logging-correlation field (best-effort).
ENV_K8S_NODE_NAME NODE_NAME Logging-correlation field (best-effort).
DEFAULT_IDENTITY NOT_GREENGRASS Library fallback identity when nothing resolves.

The token values are identical across SDKs; the constant identifiers differ. The metric-log path also differs in its filename suffix (see the caution above) and Rust inlines the three selector strings rather than naming constants for them.

Token value Java / Python identifier Rust identifier TypeScript identifier
json LOGGING_FORMAT_JSON (inline "json") JSON_LOG_FORMAT
prometheus METRIC_TARGET_PROMETHEUS (inline "prometheus") PROMETHEUS_METRIC_TARGET
env CREDENTIALS_KEY_PROVIDER_ENV (inline "env") ENV_KEY_PROVIDER
./logs/{ComponentFullName}.metric.log METRIC_LOG_PATH_LOCAL METRIC_LOG_PATH_LOCAL LOCAL_METRIC_LOG_PATH

The token value shown for METRIC_LOG_PATH_LOCAL is the Java/Rust/TypeScript form; Python’s value uses an underscore (./logs/{ComponentFullName}_metric.log) — see the caution above.

ConfigMap defaults (Java names them CONFIGMAP_DEFAULT_MOUNT_DIR / CONFIGMAP_DEFAULT_KEY): mount dir /etc/ggcommons, key config.json.

These three behaviors are summarized here for the API surface; the Platforms & transports page covers them in depth.

  • detectPlatform — first match wins, order is load-bearing: (1) GREENGRASS if ENV_GG_IPC_SOCKET or ENV_GG_SVCUID is set non-empty; (2) KUBERNETES if the K8S_SA_TOKEN_PATH file exists or ENV_K8S_SERVICE_HOST is set; (3) HOST otherwise. An empty env value is not a signal; GREENGRASS wins when both signal sets are present.
  • validate — rejects transport == IPC && platform != GREENGRASS (the IPC lock). Java raises IllegalArgumentException, Python raises ValueError, Rust returns GgError::Cli, TypeScript throws a GgError of kind Cli.
  • resolveIdentity — precedence: explicit -t/--thing ▸ (only on KUBERNETES: ENV_K8S_THING_NAMEENV_K8S_POD_NAME) ▸ ENV_THING_NAMEDEFAULT_IDENTITY. Empty env values are ignored; the returned value is raw (sanitized later wherever {ThingName} is interpolated).

The fully resolved value of any setting follows a four-tier rule:

explicit flag ▸ explicit config value ▸ platform-profile default ▸ library default

It splits across two layers: the resolver applies explicit flag ▸ profile default ▸ library default to the runtime axes (transport, config source, identity), while each subsystem’s init site applies explicit config value ▸ profile default ▸ library default to the subsystem settings (logging format, metric target, metric-log path, credentials key provider, health endpoint).

Relevant only if you inspect the resolver types or the parsed-args result directly:

  • ResolvedProfile / ResolverInputs field counts. Java is five fields (it threads messagingConfigPath through the resolver); Python, Rust, and TypeScript are four (the ConfigMap-default messaging path is computed in the CLI layer).
  • Enum casing (Rust). Rust uses Platform::{Greengrass, Host, Kubernetes} and Transport::{Ipc, Mqtt} (PascalCase); the others use the uppercase token names. All four parse the CLI token case-insensitively.
  • Logging-format helper. Java, Python, and TypeScript expose a profileLoggingFormat helper; Rust has none — read profile(platform).logging_format instead.
  • The profile table accessor. Java/Python/TypeScript expose a PROFILES map; Rust exposes profile(platform) -> Option<PlatformProfile> plus profiled_platforms() -> [Platform; 3].
  • validate name in TypeScript. Re-exported from the package root as validatePlatformTransport.

See the CLI contract for the parser entry points (processArgs / parse_from / parseArgs) and the ParsedCommandLine / ParsedArgs result types, including the thing-vs-resolved-identity distinction.