Testing plugins locally
Run a plugin against the local platform: the platform stores its definition, a sandbox cluster runs it, the console shows it.
k3d-fundament (platform) k3d-fundament-plugin (sandbox)┌─────────────────────────────┐ ┌─────────────────────────────┐│ marketplace-registry-api │◄──────┤ just plugins publish ││ │ │ ││ marketplace-catalog-api ├──────►│ plugin-controller ││ relay :38080 │ runs plugin-<org>--<name> ││ kube-api-proxy │ │ ││ plugin-proxy ├──────►│ (console reads the sandbox) ││ Secret plugin-sandbox-kubeconfig │└─────────────────────────────┘ └─────────────────────────────┘ registry localhost:5111 registry localhost:5112- Requires the platform from Getting started. Run the
justcommands from the fundament repository root. - Example: cert-manager runs every step for one plugin.
- Plugin-specific steps (extra images,
spec.config, test recipes) are in each plugin’splugins/<path>/README.md.
1. Create the sandbox
Section titled “1. Create the sandbox”just plugins cluster-createjust plugins deploycluster-createcreatesk3d-fundament-pluginand switches the kubectl context to it.deploybuilds plugin-controller from source and deploys it.
2. Connect the clusters
Section titled “2. Connect the clusters”just plugin-sandbox-kubeconfigjust plugins sandbox-catalog- kube-api-proxy is proxying to the sandbox (mock disabled)- marketplace-catalog-api reachable from the sandbox at http://host.k3d.internal:380803. Log in with functl
Section titled “3. Log in with functl”In the console, log in as an admin of the publishing organization and create a key under API keys (API keys). Then:
| Organization | ID | Admin |
|---|---|---|
system (first-party plugins) |
019b4000-0000-7000-8000-000000000000 |
platform-admin@fundament.io |
acme-corp |
019b4000-0000-7000-8000-000000000001 |
alice@acme-corp.com |
Plugin in this repository: just functl uses the local endpoints from mise.toml.
just functl auth login <API_KEY>just functl org set <organization-id>Plugin in its own project: point functl at the local endpoints; without them it talks to fundament-poc.nl.
export FUNCTL_API_ENDPOINT=https://organization.fundament.localhost:8443export FUNCTL_AUTHN_URL=https://authn.fundament.localhost:8443export FUNCTL_REGISTRY_URL=https://marketplace-registry-api.fundament.localhost:8443functl auth login <API_KEY>functl org set <organization-id>4. Publish
Section titled “4. Publish”Plugin in this repository:
PLUGIN_REGISTRY=localhost:5112 just plugins publish <path><path>is the plugin directory underplugins/, e.g.gateway-api/envoy-gateway.- Builds the image with the repository root as build context, pushes it and publishes
plugins/<path>/definition.yaml. - Extra flags go to
functl plugin publish.
Plugin in its own project, from the project directory (names from the scaffolded my-plugin):
just docker v0.1.0docker tag my-plugin-plugin:v0.1.0 localhost:5112/my-plugin:v0.1.0docker push localhost:5112/my-plugin:v0.1.0functl plugin publish definition.yaml --image=localhost:5112/my-plugin@sha256:<digest from push> --createBoth print:
published plugin=<name> version=<version> hash=sha256:… id=… version_id=… status=SUBMISSION_STATUS_DRAFT--createreserves the listing on the first publish; without it functl answersno listing named "<name>" in this organization — pass --create to reserve it.--submitopens the review: see Marketplace route.- Step 5 needs
versionandhash. - Versions are create-only: bump
metadata.versionto publish changed content.
5. Install
Section titled “5. Install”kubectl --context k3d-fundament-plugin apply -f - <<'YAML'apiVersion: plugins.fundament.io/v1kind: PluginInstallationmetadata: name: <organizationName>--<pluginName>spec: definitionRef: organizationName: <organizationName> pluginName: <pluginName> pluginVersion: "<version from step 4>" definitionHash: "<hash printed by publish>" # includes the sha256: prefixYAML- Draft and pending versions install this way.
- The image comes from the published definition; the CR carries none. Field reference: PluginInstallation CRD.
spec.configsets the plugin’sFUNP_values without the prefix, e.g.OPERATOR_IMAGE: <ref>.definitionRefis immutable: to change the version, uninstall and install again.
6. Verify
Section titled “6. Verify”just plugins statusjust plugins logs <organizationName>--<pluginName>NAME PLUGIN ORGANIZATION PHASE READY<organization>--<name> <name> <organization> Running trueIn the console, log in as a member of an organization with a cluster (alice@acme-corp.com) and open the project: the plugin’s section appears under its display name.
First-party plugins
Section titled “First-party plugins”Each first-party plugin documents its flow from step 4, its config and its recipes in plugins/<path>/README.md: see plugins/. ceph-rook: Example: Ceph Storage (Rook).
Marketplace route
Section titled “Marketplace route”- Publish with
--submit(step 4): the version becomes Pending review. - https://marketplace-registry.fundament.localhost:8443 (console session) lists it under My plugins.
- https://marketplace-admin.fundament.localhost:8443 (DCIM login): Review queue → Review → approve.
- https://marketplace.fundament.localhost:8443 lists the approved plugin.
- Console Plugins page, as a member of an organization with a cluster: install it on the cluster.
After a platform deploy
Section titled “After a platform deploy”Every platform deploy resets its databases: API keys, published definitions and the cluster’s ready state are gone. Installed plugins keep running; a new install reports fetch definition: GetPluginDefinition RPC: not_found: plugin definition not found. Repeat:
just plugin-sandbox-kubeconfig- step 3 with a new API key
- step 4. The hash stays the same while the image content is unchanged. If it differs from the installation’s
definitionHash, uninstall and repeat step 5.
Remove
Section titled “Remove”just plugins uninstall <organizationName>--<pluginName>just plugins cluster-deleteA plugin whose pod keeps failing takes minutes to uninstall.
Example: cert-manager
Section titled “Example: cert-manager”Log in to the console as platform-admin@fundament.io (password password) and create an API key under API keys. Then:
just plugins cluster-createjust plugins deployjust plugin-sandbox-kubeconfigjust plugins sandbox-catalog
just functl auth login <API_KEY>just functl org set 019b4000-0000-7000-8000-000000000000
PLUGIN_REGISTRY=localhost:5112 just plugins publish cert-manager
kubectl --context k3d-fundament-plugin apply -f - <<'YAML'apiVersion: plugins.fundament.io/v1kind: PluginInstallationmetadata: name: system--cert-managerspec: definitionRef: organizationName: system pluginName: cert-manager pluginVersion: "1.17.2" definitionHash: "<hash printed by publish>" # includes the sha256: prefixYAML
just plugins statusjust plugins cert-manager testpublishprintspublished plugin=cert-manager version=1.17.2 hash=sha256:…; the listing exists, so no--create.statusshowssystem--cert-manager cert-manager system Running true;testends withtest-cert True test-cert-tls.just plugins logs system--cert-managerstreams the plugin log:cert-manager is running.- In the console as
alice@acme-corp.com: acme-project → Cert Manager → Certificates liststest-certinfundament, Ready.
Remove:
just plugins cert-manager test-cleanupjust plugins uninstall system--cert-managerjust plugins cluster-delete