Provisioning from the Shell

Table of Contents

Everything the browser's setup journeys do, the shell can do too. This chapter covers the same ground from the command line, where a complete system can be set up with three commands — or with one script, run end to end from a file. It sets out the bootstrap setup, provision tenant and provision party commands, the supporting commands they are built from, the script library that ties them together, and two complete worked examples — the fast Acme Corporation path and the GLEIF path — showing that scripted provisioning is repeatable: the same script against a fresh installation always produces the same system.

1. Overview

The chapter advances the argument that provisioning a complete system from the command line means understanding the client that runs the commands, then each provisioning command in the order it must be run, then the smaller commands they are built from, and finally how to tie them together into a repeatable script — and it proceeds in that order. It begins by establishing the client and the rules it enforces in The shell and provisioning, which explains how the shell speaks to the backend and why provisioning follows a fixed sequence; this is the premise the rest of the chapter builds on. From there it walks the sequence one stage at a time — Setting up the system, then Provisioning a tenant, then Provisioning a party — each command sending one provision request and following the run that request starts. It then opens up the machinery in The supporting commands, the smaller commands a run can be inspected or recovered with, before showing in Scripts how the shell runs those commands unattended from a file. Finally A complete example runs the fast Acme Corporation path from a single shipped script, and A custom example: your own organisation points to the equivalent script for building your own house instead, before the Conclusion draws these steps together.

2. The shell and provisioning

ores.shell is ORE Studio's interactive command-line client. Like the browser it speaks to the backend services over the message bus, so anything it does respects the same validation, audit trail, and permissions. Start it, connect, and type help to see the available commands; every command described here also explains its own arguments through the shell's built-in help.

Provisioning from the shell follows the same sequence as the browser's setup journeys — system, then tenant, then party. The session is refreshed by a logout and a login between the stages where the administrator changes, because a session created before a tenant exists does not see it. Each stage is one command: the command sends one provision request, which answers with a workflow instance id, and then follows the run through the same progress read the browser's journey renders. The command holds no sequence of its own beyond the order the two clients share, and the starting point it runs from is a flag naming a registered row rather than a profile the shell knows anything about.

3. Setting up the system

bootstrap setup is the first-run act. It is registered in the generated bootstrap menu, beside status and create-initial-admin, because it is what brings the installation to life. It requires bootstrap mode and no login.

bootstrap setup super_admin Secure-Password-123 super_admin@localhost.com --tenant-admin-password Secure-Password-123 --tenant-code default --tenant-name "Default Tenant" --tenant-hostname localhost --profile empty_operational --param counterparty_size=small
logout
exit

The administrator's password is the only value the command requires: it offers no default it could invent. It reads the installation's bootstrap answer, creates the system administrator, signs in as it, and accepts the terms of every public source as they stand, printing one line a source. It then sends one provision request for the first tenant and follows the run to its end.

A new system fetches no public rates until each public source's terms are accepted. The shell does not show the terms' text: running the command accepts each source's terms as they stand at that moment. The acceptance is recorded under the administrator's account, with the time the server records it. To leave the terms for the administrator to read and accept, add --no-accept-terms; accept them later on the Public rates screen, or all at once with provider_terms_operations accept-all.

Tenant code default, name Default Tenant, hostname localhost and administrator tenant_admin are the tenant defaults; the administrator's e-mail address defaults to admin@<code>.com. Override any of them with --tenant-code, --tenant-name, --tenant-hostname, --tenant-description, --tenant-admin and --tenant-admin-email. --profile names the starting point (default empty_operational) and --param name=value supplies one parameter the starting point declares; the flag is repeatable. --timeout is how long the command follows the run (default 3600 seconds).

The command refuses to run when you are already logged in or the system is not in bootstrap mode, and on success prints the login for the next stage:

./projects/ores.compass/compass.sh shell << 'EOF'
<<shellprov-setup>>
EOF
✓ Connected to nats://localhost:42222
⚠ WARNING: System is in BOOTSTRAP MODE
ores-shell> [1/3] Creating initial admin account 'super_admin'...
  Account created (ID: b88d04ec-ac25-4137-981a-ddefb1d92592).
[2/3] Logging in as 'super_admin'...
✓ Login successful!
[3/3] Provisioning tenant 'default' from 'empty_operational'...
  Run started: 7c059b7f-...
  [1/3] publish_bundle: completed
  [2/3] import_lei_hierarchy: completed
  [3/3] provision_party: completed
✓ All 3 step(s) completed.
✓ System provisioned. Tenant 'Default Tenant'.
Next: logout, then: login tenant_admin@localhost <password>  — the tenant is ready to work in.
ores-shell> ✓ Logged out successfully.
ores-shell> Bye!

Note the login principal is the username at the tenant's hostname (tenant_admin@localhost above), not its display name.

4. Provisioning a tenant

provision tenant creates a tenant under the tenant the signed-in administrator works in. Every tenant is created the same way, the first included; the only difference from bootstrap setup is that the administrator and the session already exist. Log in as an administrator and run:

login super_admin Secure-Password-123
provision tenant --tenant-code example --tenant-name "Example Corp" --tenant-hostname example --tenant-admin-password Secure-Password-123 --profile empty_operational --param counterparty_size=small
logout
exit
./projects/ores.compass/compass.sh shell << 'EOF'
<<shellprov-tenant>>
EOF
ores-shell> ✓ Login successful!
ores-shell> Provisioning tenant 'example' from 'empty_operational'...
  Run started: 3a9d2c1e-...
  [1/3] publish_bundle: completed
  [2/3] import_lei_hierarchy: completed
  [3/3] provision_party: completed
✓ All 3 step(s) completed.
✓ Tenant 'Example Corp' provisioned.
Next: logout, then: login tenant_admin@example <password>  — the tenant is ready to work in.
ores-shell> ✓ Logged out successfully.
ores-shell> Bye!

The new tenant administrator's password is the only value the command requires. The command prints the login for the new tenant when the run completes.

A starting point ("seed profile") is registered data: a row naming the tenant's type, the ordered steps, and the parameters its form declares. The shell holds no profile of its own, so a new starting point is a row rather than a shell change. Three starting points ship today:

  • empty_operational (the default) — the production starting point. It publishes the base reference data and the counterparty set, takes a GLEIF root LEI, and creates no test data.
  • gleif_entity — a tenant built around a public registry hierarchy. The root LEI names the parent legal entity whose hierarchy becomes the tenant's parties.
  • acme_demo — the demonstration, the Acme Corporation holding group with its legal entities, staff, books and market data.
  • northwind is a second demonstration tenant, the fictional Northwind Traders. It has one legal entity, nine staff, six portfolios and seven books, and its own report documents. It is lighter than acme_demo. A deployment uses it to exercise more than one tenant at once.

--profile names the starting point and --param name=value supplies one parameter it declares, for example --param root_lei=<lei> or --param counterparty_size=small. The flag is repeatable. The counterparty set is published once for the tenant. --timeout is how long the command follows the run (default 3600 seconds).

The request answers with a workflow instance id at once, and the command follows the run through the progress read the browser's journey renders. On failure the run stops on the failing step, and the workflow commands read it by the instance id the command prints.

After the run completes, log out and back in as the new tenant's administrator so the session picks up the now-active tenant.

5. Provisioning a party

provision party runs the party stage against one party of the signed-in tenant. It publishes the bundles the starting point orders for a party, activates the party, marks its onboarding complete, and joins the administrator who asked to it. The party is named by its identifier or its exact full name; parties list shows the candidates:

login tenant_admin@barclays_plc Secure-Password-123
provision party "BARCLAYS PLC"
logout
exit
./projects/ores.compass/compass.sh shell << 'EOF'
<<shellprov-party>>
EOF
ores-shell> ✓ Login successful!
ores-shell> Provisioning party 'BARCLAYS PLC' from 'empty_operational'...
  Run started: 5f6e1b02-...
  [1/1] provision_party: completed
✓ All 1 step(s) completed.
✓ Party 'BARCLAYS PLC' provisioned.
Next: accounts set-default-party "BARCLAYS PLC" to work in it.
ores-shell> ✓ Logged out successfully.
ores-shell> Bye!

--profile names the starting point (default empty_operational) and --timeout is how long the command follows the run (default 3600 seconds). The counterparties a party works against are the tenant's, published once by the tenant's starting point and not here. The run's last step marks the party's onboarding complete.

6. The supporting commands

The provision commands send one request each, and the server orchestrates the work, so these smaller commands are not steps the provision commands call in sequence. They remain useful on their own — to inspect the system, to recover when a step fails, or to assemble a custom flow. A failed run names the step it stopped on, and the workflow commands read that run by the instance id the provision command printed.

Command Purpose
dataset_bundles list The reference data catalogues available for publication.
bundles publish <code> [--wait] Publish a catalogue; --wait blocks until the backend finishes.
workflow wait <instance_id> [--timeout <seconds>] [--expect-steps <n>] [--expect-state <state>] Follow a run, or assert the terminal state a run that is meant to fail must reach.
workflow_steps by-workflow-id <id> Read a run's steps by the instance id the provision command printed.
lei countries / lei_entity_summary search-lei-entities <text> [--country_filter <code>] Browse the GLEIF registry for a root LEI.
parties list List the parties of the signed-in tenant.
accounts set-default-party <party-uuid-or-full-name> Set the logged-in account's default party.
report_definition_template list-dq-report-definition-templates [--bundle_code <code>] The standard report definitions seeded in a bundle.

The reads that come from generated units print their response as JSON, where the hand-written commands they replace printed aligned rows. search-lei-entities <text> matches a legal name anywhere in it, or an LEI from its start, and states for each match how many parties importing its hierarchy would create. It replaces both the old cross-country search and the per-country name filter.

7. Scripts

The shell runs scripts with the load command: one command per line, # starts a comment, and blank lines are ignored. A script stops at the first command that fails — so a run that reaches the end has genuinely succeeded — and reports the failing line and command. When you want a script to press on regardless, for example while exploring, pass --continue-on-error:

load my_script.ores
load my_script.ores --continue-on-error

ORE Studio ships a small library of provisioning scripts in projects/ores.shell/scripts/library/provisioning/. Each .ores script in the library is generated from a recipe under doc/recipes/shell/provisioning/ that explains, step by step, what the script does and what it expects of the system — read that file before running a script for the first time. Treat the shipped scripts as templates: copy one and adjust the copy rather than editing the original, which the build regenerates.

8. A complete example

The library's how_do_i_provision_the_system_with_acme_corporation_holding_group.ores sets up a complete system from a fresh installation. It runs bootstrap setup with the demonstration starting point, acme_demo, which imports the Acme Corporation hierarchy, publishes each party's data, attaches the staff photographs and starts the market feeds, server-side in one run. The script then publishes the vendored compute packages and logs out. It is the quickest way to a fully populated installation and the recommended starting point for exploring ORE Studio; see the Acme Corporation chapter for what it produces. It expects a fresh installation in bootstrap mode, all services running, and a connected, logged-out session.

load projects/ores.shell/scripts/library/provisioning/how_do_i_provision_the_system_with_acme_corporation_holding_group.ores
exit

An error-free run ends with all four legal entities active:

./projects/ores.compass/compass.sh shell << 'EOF'
<<shellprov-acme>>
EOF
ores-shell> Loading script: .../how_do_i_provision_the_system_with_acme_corporation_holding_group.ores
> connect $ORES_NATS_URL
> bootstrap setup super_admin Secure-Password-123 super_admin@localhost.com --tenant-admin-password Secure-Password-123 --tenant-code acme_corporation --tenant-name "Acme Corporation" --tenant-hostname acme_corporation --profile acme_demo
[1/3] Creating initial admin account 'super_admin'...
  Account created (ID: ...).
[2/3] Logging in as 'super_admin'...
✓ Login successful!
[3/3] Provisioning tenant 'acme_corporation' from 'acme_demo'...
  Run started: ...
  [1/6] publish_bundle: completed
  [2/6] import_lei_hierarchy: completed
  [3/6] provision_party: completed
  [4/6] load_staff: completed
  [5/6] attach_photos: completed
  [6/6] subscribe_market_data: completed
✓ All 6 step(s) completed.
✓ System provisioned. Tenant 'Acme Corporation'.
Next: logout, then: login tenant_admin@acme_corporation <password>  — the tenant is ready to work in.
> compute publish-package ORE ...
> compute publish-package ORE ...
> logout
✓ Logged out successfully.
Script complete: 5 commands executed.

The starting point handles every one of Acme's four legal entities inside its own run — there is no per-party stage to call separately — and the same script against a fresh installation always produces the same system.

Log in — from the shell or the browser — as tenant_admin@acme_corporation, select one of the four operating companies, and daily use begins, just as at the end of the previous chapter.

9. A custom example: your own organisation

Where the Acme Corporation script above is the fast path, building your own house from scratch — modelling a real organisation — uses the generic sequence Setting up the system through Provisioning a party set out earlier: bootstrap setup with the GLEIF starting point, then provision party for each party that needs its own reference data. The library's barclays_system_provision.ores is the worked example of this path — a tenant built around a real GLEIF hierarchy — and follows the same load=/logout/login shape as the Acme example above, just with a party stage for the hierarchy's root after the tenant stage. The library's =tenant_provision.ores covers the tenant stage on its own, for adding a tenant to a system that is already set up, and party_provision.ores covers the party stage on its own.

10. Conclusion

The chapter set out to show that a complete system can be provisioned from the command line by understanding the client, the provisioning commands in sequence, the supporting commands beneath them, and the scripts that tie them together, and it has traced exactly that path. The shell speaks to the same backend services as the browser, so it enforces the same validation, audit trail, and permissions, and provisioning follows the same sequence — system, then tenant, then party — with the logout and login between stages that refresh the session's view of the system. bootstrap setup sets up an empty installation, provision tenant creates every tenant after the first, and provision party runs the party stage; each sends one provision request and follows the run through the progress read the browser's journey renders. A starting point is registered data, so the shell holds no profile of its own, and the shipped script library showed both paths executing end to end from a fresh installation: acme_demo for the fast, fully populated Acme Corporation tenant, and gleif_entity for building a house around a real GLEIF hierarchy. Because the same script against the same starting point always produces the same system, scripted provisioning is the natural tool for development environments, testing, and automation — everything the browser's setup journeys do, reproducibly and without the browser.

Emacs 29.3 (Org mode 9.6.15)