Declare module settings
A module’s settings are the choices its owner makes for it: a VM size, a threshold, a word its runners read. From core
2.9 a module declares each one as a key with a type, a scope and constraints; the core validates every value, shows
each key in the console with where its value comes from, and hands each process exactly the keys meant for it. Node
settings, required settings and campaign overrides need requires.core >= 2.9. The contract is
manifest.md; this page shows the steps.
Declare the keys
Section titled “Declare the keys”-
Point the manifest at a JSON Schema file:
[requires]core = ">=2.9,<3"[settings]schema = "schemas/settings.schema.json" -
Write one property per setting:
{"$schema": "https://json-schema.org/draft/2020-12/schema","type": "object","properties": {"vm_mem_gb": {"type": "number", "minimum": 2, "maximum": 64, "default": 8,"title": "VM memory", "description": "Memory the module's VM gets on a node.","x-oarbank": {"scope": "node", "unit": "GB"}},"batch_size": {"type": "integer", "minimum": 1, "maximum": 4096, "default": 64,"title": "Batch size", "description": "Items per job.","x-oarbank": {"campaign": true}},"upstream_url": {"type": "string", "format": "uri","title": "Upstream feed", "description": "Where the ingestion stage reads from.","x-oarbank": {"required": true}}}}The property is the contract. Its
type(boolean,integer,number,string,arrayorobject, optionally with"null") and every constraint on it (minimum,maximum,enum,pattern,maxLength,items,format, …) are what the core checks each value against, on every write.defaultmust itself be valid.titleis the label the owner reads (at most 80 characters) anddescriptionits one line of help (at most 500). A name is lower-case letters, digits and_, starting with a letter, at most 64 characters; a schema declares at most 128 settings. -
Say how the core treats each key in
x-oarbank:Field Default Meaning Needs scope"fleet"fleet: one value for the fleet, read by the module’s coordinator side.node: a value the owner sets for the fleet, a node group or one node (the most specific wins), delivered to the module’s runners, doctor and services on each nodenode: core 2.9requiredfalseThe owner must set it. Until a value exists, the module’s work waits with SETTINGS_NOT_SETand its readiness checklist shows Required settings. A required key has nodefault. The schema’s ownrequiredlist counts toocore 2.9 unitnone A short word shown beside the value ( GB,s,items)advancedfalseShown under the module’s Advanced disclosure campaignfalseA campaign of the module may override it while it runs (Campaign overrides) core 2.9 -
Check it:
Terminal window oarbank-sdk check . # refuses a schema the core would not readoarbank-sdk check,bundle buildandbundle verifyrefuse an invalid schema (an unknownx-oarbankfield, an invalid default, a required key with a default, a bad name), so an installed bundle always registers.checkwarns about a property named like a core key (enabled,pipeline,replica_rate,services) or like a credential.
Credentials are never settings. Settings are stored and shown in clear. A property with writeOnly, x-secret or
x-oarbank.secret is refused, and a name that looks like a credential (token, password, api_key, …) gets a
warning. Declare credentials in [[secrets]] (Use secrets and signed container images).
Read the values
Section titled “Read the values”On a node. A runner, doctor and services get the module’s node keys resolved for their node: the owner’s value
for the fleet, a group or the node, else the key’s default (a key with neither is absent), and no fleet keys, in
OARBANK_SETTINGS_FILE:
from oarbank_sdk import settingsmem = settings.read().get("vm_mem_gb", 8) # {} outside a node process, or when the file is missingBootstrap jobs get {}. A change to another module’s settings never touches your file, and a change to yours reaches
the node with its next heartbeat.
On the coordinator. The module’s coordinator side gets every key at fleet scope the same way: ctx.settings in a
verb (from initialize), or host.settings.get:
threshold = ctx.settings.get("batch_size", 64)From the module’s own operations. An operation changes the module’s settings at fleet scope with the
module_settings.update effect, {key: value}, where null resets a key to inherit. Each key must be declared and
each value valid, or the whole effect is refused (bad_settings):
from oarbank_sdk import module_protocol as mpreturn mp.OpApplyResult(effects=[mp.Effect(kind="module_settings.update", args={"batch_size": 128})])The toy module’s Set the favorite n operation does exactly this (examples/toy).
The owner sets values in the module’s Settings tab, or with
oarbank settings set vm_mem_gb 12 --module <module> [--node N | --group G]
(Settings).
Campaign overrides
Section titled “Campaign overrides”A key marked "x-oarbank": {"campaign": true} may be overridden by a campaign of the module while that campaign runs:
by the module itself, or by the owner on the campaign’s page. The campaign’s value reaches that campaign’s jobs only.
-
Check that the host supports it (core 2.9), if the module also runs on older cores:
if ctx.host_has(mp.HOST_CAMPAIGN_SETTINGS):... -
Set overrides when you create the campaign, or change them later (
Noneresets a key):from oarbank_sdk import effects as fxfx.campaign_create("c_big", "Big batches", settings={"batch_size": 1024})fx.campaign_settings("c_big", {"batch_size": None})Besides its own campaign keys, a campaign may override the core keys
replica_rate,jobs,run_on_batteryanduser_present_slots, which may only tighten (a value looser than the fleet’s is refused). A key the owner locked, an undeclared key or an invalid value refuses the whole effect (bad_settings). -
Read them:
campaign.tickcarriescampaign.settings, every key at fleet scope with the campaign’s overrides on top. A campaign’s override of anodekey reaches its jobs’ runners inOARBANK_SETTINGS_FILE.
The host capability is campaign_settings.v1 (module-protocol.md).
New versions and old values
Section titled “New versions and old values”The core reads the schema of the module’s current version (before it is enabled, the newest installed one):
- a key a new version no longer declares keeps its values, unused, until the owner deletes them or a later version declares it again;
- a value the new version’s schema no longer accepts (its type or range changed, or a
nodekey becamefleetwhile a value was set below the fleet) is dropped, and the module’s event names it.
So change a key’s type or meaning under a new name.
Test them
Section titled “Test them”In conformance.json, settings holds the owner’s values. The kit checks them against your keys, gives runs, doctor
and services the node keys (a fixture value, else the default) in OARBANK_SETTINGS_FILE, and gives the coordinator
side every key (conformance.md):
{"settings": {"vm_mem_gb": 4, "upstream_url": "https://feed.example.org/v1"}}Move a module from SDK 1.5
Section titled “Move a module from SDK 1.5”Before core 2.9 the core stored a module’s settings as one opaque object. To move a module:
- Declare every key the module reads or writes in its settings schema.
- Mark the keys its runners or services need on a node
"x-oarbank": {"scope": "node"}: only those reachOARBANK_SETTINGS_FILE. - Move any credential to
[[secrets]]. - Drop a
pipelineproperty: the core’s ownpipelinesetting replaces it. - Set
requires.core = ">=2.9,<3"if you usescope = "node",requiredorcampaign.
An undeclared key in module_settings.update is refused. When a fleet upgrades to core 2.9, the values its owner had
set are kept only for keys the module declares and whose schema accepts them.
Source: docs/module-settings.md in the oarbank-sdk repository