Java Plugin API
The jhelm-plugin-api module lets you extend jhelm by implementing a small Java interface —
no WebAssembly to compile, no subprocess to spawn. Your plugin runs in-process and is
discovered off the classpath, either as a JDK ServiceLoader service (any application) or
as a Spring bean (the jhelm CLI/REST/MCP apps, or your own Spring app embedding jhelm).
|
This is one of three plugin surfaces. See also Helm plugin compatibility
(native Helm plugins as subprocesses) and the WASM |
2. Extension points
All interfaces live in org.alexmond.jhelm.pluginapi and extend JhelmPlugin (which
provides a name() for listings/logs).
- Post-renderer
-
JhelmPostRenderer— transform the rendered manifest (install, upgrade, template).public class BannerPostRenderer implements JhelmPostRenderer { public String postRender(String manifest) { return "# rendered via my plugin\n" + manifest; } } - Chart downloader
-
JhelmChartDownloader— fetch charts for a custom URL scheme (s3://,gs://, …).supports(scheme)selects it;download(url)returns the chart archive bytes. - Lifecycle listener
-
JhelmLifecycleListener— react to release events.onEvent(JhelmReleaseEvent)receives the phase (PRE_INSTALL,POST_INSTALL,PRE_UPGRADE,POST_UPGRADE,PRE_ROLLBACK,POST_ROLLBACK,PRE_UNINSTALL,POST_UNINSTALL), release name, namespace, and metadata. A throwing listener is logged and ignored. - Template functions
-
JhelmTemplateFunctionProvider— contribute Go-template functions callable from any chart.public class MyFunctions implements JhelmTemplateFunctionProvider { public Map<String, JhelmTemplateFunction> functions() { return Map.of("my_greet", args -> "hello, " + args[0]); } }Name your functions distinctively — a name that collides with a built-in overrides it (the cluster-backed
lookupis the one exception, always preserved).
Any method may throw JhelmPluginException; jhelm surfaces the message and aborts the
operation.
3. Registering a plugin
- ServiceLoader (any application)
-
add a file under
META-INF/services/named for the interface, listing your implementation class. For a post-renderer:META-INF/services/org.alexmond.jhelm.pluginapi.JhelmPostRenderercom.example.BannerPostRenderer
- Spring bean (jhelm CLI/REST/MCP, or your Spring app)
-
expose the plugin as a bean:
@Bean JhelmPostRenderer bannerPostRenderer() { return new BannerPostRenderer(); }
jhelm unions both sources and de-duplicates by implementation class (a Spring bean that is also a declared service is registered once, preferring the bean instance).
4. Loading external plugin JARs
The two mechanisms above discover plugins already on the application classpath. To load a
plugin without rebuilding jhelm — dropping a JAR into a directory — point
jhelm.plugins.path at one or more directories:
jhelm:
plugins:
path: /opt/jhelm-plugins # or a comma-separated list of directories
Every *.jar in each directory is loaded in its own class loader (parented on jhelm-core,
so the plugin resolves the jhelm-plugin-api types; isolating each jar tolerates
conflicting transitive dependencies between plugins), and its declared ServiceLoader
services are discovered and merged with the classpath and Spring-bean plugins. This works on
every surface — the CLI, the REST and MCP servers, and an embedded library — and is
independent of how the application is launched. Empty by default, so nothing is scanned
until a directory is configured.
On the CLI, set it with the global --plugin-dir flag, the JHELM_PLUGINS_PATH environment
variable, or the property directly:
jhelm --plugin-dir /opt/jhelm-plugins template my-release ./chart
4.1. Packaging a plugin as a self-contained JAR
Build an ordinary JAR that (1) compiles against jhelm-plugin-api (scope provided — jhelm
supplies it at runtime) and (2) contains a META-INF/services/ file for each extension
point it implements, as in Registering a plugin. Bundle any third-party libraries your
plugin needs into the JAR (a shaded/uber JAR), since only that JAR is added to the plugin’s
class loader. Drop the finished JAR into a jhelm.plugins.path directory.
|
This is jhelm’s own Java plugin store, distinct from the native-Helm plugin store
( |
5. Worked examples
The jhelm-plugin-api-sample module in the source tree implements one plugin of each kind
(post-renderer, downloader, lifecycle listener, template functions) with ServiceLoader
registrations, and an integration test that runs them through jhelm-core end to end.
6. Stability
The plugin API follows the project’s semantic versioning: interfaces are additive within a minor line. New extension points and enum constants may be added; existing method signatures are kept stable within a major version.
7. Relation to the native-Helm and WASM plugin systems
Java plugins run in-process, so — unlike native Helm plugins (arbitrary executables) — they
are not gated on the FULL security posture; they are code you already put on the
classpath. Use a Java plugin when you extend jhelm from Java, a
Helm plugin to reuse an existing Helm plugin, and the WASM .jhp
system for a sandboxed, language-agnostic plugin.