Modules & Plugins Overview¶
Cresco is assembled from a fixed set of OSGi bundles (io.cresco.*) hosted inside a single Apache Felix container. This page explains the module/plugin model — how the bundles are packaged, how the agent uber-jar bootstraps them, and the distinction between the controller (the fabric brain) and the functional plugins that run on top of it.
The OSGi bundle model¶
Every Cresco module is an OSGi bundle: a JAR whose manifest carries a Bundle-SymbolicName, an Export-Package list, and (for most modules) an Embed-Dependency set that packages third-party libraries inside the bundle. The symbolic name of each module is io.cresco.<artifactId> (group id io.cresco).
The bundle:bundle build gotcha
Each module declares <packaging>jar</packaging>, but the artifact must be a real OSGi bundle or Felix cannot start it. The maven-bundle-plugin only rewrites the JAR when its goal is invoked explicitly:
A plain mvn package/mvn install produces a non-bundle JAR that the framework rejects. See Installation & Build.
Bundles fall into three roles:
| Role | Bundles | Loaded |
|---|---|---|
| Host | agent |
The executable uber-jar; boots Felix and installs everything else. |
| Framework services | logger, library, core |
Installed and started at boot, before the controller. |
| The controller | controller |
The fabric brain — installed and started at boot. |
| Functional plugins | repo, filerepo, sysinfo, wsapi, stunnel, executor |
Embedded in the uber-jar but installed at runtime by the controller, not at boot. |
How the agent uber-jar bootstraps the bundles¶
The agent is not itself an OSGi bundle — it is the Felix host jar with Main-Class io.cresco.main.AgentEngine. The component JARs are embedded inside the agent uber-jar under src/main/resources/ and installed from the classpath by HostApplication. The boot sequence installs and starts a fixed ordered set:
configadmin → logger → (metatype, scr, gogo, healthcheck.api) → library → core → controller
(+ optional Jetty web console when enable_console=true)
healthcheck.api is installed but not started at boot (the controller drives the Felix Health Check subsystem itself). Once the controller reaches ACTIVE, it brings up the fabric — the embedded ActiveMQ broker, the embedded Apache Derby state database, TCP/UDP discovery, the data plane, the health subsystem — and only then loads the functional plugins. See agent for the full boot detail.
Controller vs. functional plugins¶
The controller is fundamentally different from the other plugins. It implements the AgentService that every plugin depends on, owns the messaging fabric, the state machine, discovery, persistence, and the three role tiers (agent / region / global). It is the host environment that all functional plugins run inside.
A functional plugin is a much thinner thing: an OSGi @Component implementing PluginService (scope=PROTOTYPE, configurationPolicy=REQUIRE), holding a @Reference AgentService. Each registers an Executor that handles only the MsgEvent types it uses (all others return null). Plugins reach the mesh exclusively through the PluginBuilder API defined by library.
Plugin lifecycle¶
The controller's StaticPluginLoader (see controller) waits for the controller to become active, then loads the enabled system plugins and restarts any persisted ones. Lifecycle is driven by PluginAdmin:
- Resolve the plugin JAR (bundle / absolute path / local cache / embedded / remote repo), MD5-verified.
- Install & start the OSGi bundle.
- Register a
PluginNode(in-memory record + Derby row) and poll for thePluginServiceto appear. - Run — the plugin reports a status code;
10= working, which the controller'sPluginHealthCheckrolls into thepluginsverdict. In addition, each functional plugin registers its ownlocal-tagged Felix Health Check (executor/filerepo/repo/sysinfo/wsapi/stunnel), discovered byCrescoHealthExecutoralongside the controller's built-in checks and queryable viagethealthinventory. See Health & State. - Stop — the bundle is stopped and the
PluginNodepruned.
Plugins are identified by a generated pluginID (e.g. system-<UUID> for system plugins) and addressed on the mesh via their region/agent/plugin tuple.
Module summary¶
| Module | Bundle symbolic name | Purpose | Page |
|---|---|---|---|
| agent | (host jar — not a bundle) | OSGi host bootstrap + uber-jar (Main-Class io.cresco.main.AgentEngine). |
agent |
| library | io.cresco.library |
Shared plugin & controller API plus embedded runtime dependencies. | library |
| core | io.cresco.core |
CoreState service — stop/restart/update the controller & JVM. |
core |
| logger | io.cresco.logger |
Logging bootstrap (Pax Logging / log4j2 via ConfigAdmin). | logger |
| controller | io.cresco.controller |
The fabric brain — state machine, messaging, discovery, persistence, health, roles. | controller |
| repo | io.cresco.repo |
Plugin/JAR repository — stores, reports, and serves plugins (MD5-verified). | repo |
| filerepo | io.cresco.filerepo |
Distributed file/artifact repository — catalog + any-size transfer/streaming/sync. | filerepo |
| sysinfo | io.cresco.sysinfo |
Host metrics (OSHI) + on-demand SciMark2 CPU benchmark. | sysinfo |
| wsapi | io.cresco.wsapi |
WebSocket/HTTPS API — external client entrypoint over wss://…:8282. |
wsapi |
| stunnel | io.cresco.stunnel |
Netty TCP tunnels over the data plane. | stunnel |
| executor | io.cresco.executor |
Process/shell execution — dataplane-attached stdio + per-process metrics. | executor |
See also¶
- Architecture Overview
- Library API — the surface plugins are written against.
- MsgEvent — the universal wire message.
- Configuration — the
-D/CRESCO_*/agent.iniinputs each module reads.