Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions quick-start/.env.example

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is different better mode and networadaptordeployment mode'

Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ PROVIDER_SUBSCRIBER_ID=provider.oan.dev
# The address PEERS are told to POST to, published in each registry row. Nothing
# inside this stack resolves it -- routing here is by compose service name -- so
# a wrong value costs nothing locally and everything on a shared network.
#
# In single mode only CONSUMER_BASE_URL is a public host; the other two rows stay
# per tier so a later split to multi needs no new participant ids (ADR-0001).
CONSUMER_BASE_URL=https://consumer.oan.dev
NETWORK_BASE_URL=https://network.oan.dev
PROVIDER_BASE_URL=https://provider.oan.dev
Expand Down Expand Up @@ -211,3 +214,9 @@ POCRA_CAPABILITY=openagrinet:AgricultureFacility
POCRA_BASE_URL=https://middleware-bap-client.mahapocra.gov.in
POCRA_PATH=/search
POCRA_MAPPING_URL=https://raw.githubusercontent.com/OpenAgriNet/helmcharts/0.0.1/quick-start/config/mappings/pocra/agriculture-facility.select.yaml

# single-adapter: network-adapter runs all three tiers; multi-adapter: the network tier plus
# provider- and consumer-adapter. Unset means single-adapter; the shell's value overrides this one.
NETWORK_ADAPTER_DEPLOYMENT_MODE=single-adapter
# Plain `docker compose up -d` follows the mode too: multi-adapter is also the profile.
COMPOSE_PROFILES=${NETWORK_ADAPTER_DEPLOYMENT_MODE:-single-adapter}
4 changes: 4 additions & 0 deletions quick-start/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ config/adapters/experience.yaml
config/adapters/exp.yaml
config/adapters/network.yaml
config/adapters/provider.yaml
config/adapters/single-adapter/network-adapter.yaml
config/adapters/multi-adapter/consumer-adapter.yaml
config/adapters/multi-adapter/network-adapter.yaml
config/adapters/multi-adapter/provider-adapter.yaml

# A local override for the discovery service, if you make one.
config/discovery/instance.yaml
Expand Down
2 changes: 1 addition & 1 deletion quick-start/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# startup order matters, and a good place to make the right order the shortest
# thing to type.
#
# make up the whole stack, in the order it has to start
# make up the whole stack (Network Adapter), in order
# make up-core the same minus the reverse proxy and hyperdx
# make down stop everything, keep the data
# make help the rest
Expand Down
2 changes: 1 addition & 1 deletion quick-start/bin/bootstrap-ubuntu.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ cat <<'NEXT'

Then:

git clone -b feat/4-docker-compose https://github.com/OpenAgriNet/helmcharts.git
git clone -b development https://github.com/OpenAgriNet/helmcharts.git
cd helmcharts/quick-start
cp .env.example .env && nano .env # change every credential
make up
Expand Down
39 changes: 22 additions & 17 deletions quick-start/bin/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -565,17 +565,24 @@ def render(identities):
vistaar_binding = (f"{env('VISTAAR_PARTICIPANT_ID')}"
f"|{env('VISTAAR_CAPABILITY')}")
pocra_binding = f"{env('POCRA_PARTICIPANT_ID')}|{env('POCRA_CAPABILITY')}"
for role in ROLES:
identity = identities[role]
template = (ADAPTERS / f"{role}.yaml.tmpl").read_text()
prefix = role.upper()
# The three tier configs (multi-adapter/), then single-adapter/network-adapter,
# which carries all three tiers' identities.
for name in (*ROLES, "network-adapter"):
folder = "single-adapter" if name == "network-adapter" else "multi-adapter"
fname = name if name == "network-adapter" else f"{name}-adapter"
template = (ADAPTERS / folder / f"{fname}.yaml.tmpl").read_text()
for role in (ROLES if name == "network-adapter" else (name,)):
identity = identities[role]
prefix = role.upper()
for placeholder, value in (
(f"__{prefix}_SUBSCRIBER_ID__", identity["participantId"]),
(f"__{prefix}_KEY_ID__", identity["keyOsid"]),
(f"__{prefix}_SIGNING_PRIVATE__", identity["signingPrivate"]),
(f"__{prefix}_SIGNING_PUBLIC__", identity["signingPublic"]),
(f"__{prefix}_ENCR_PRIVATE__", identity["encrPrivate"]),
(f"__{prefix}_ENCR_PUBLIC__", identity["encrPublic"])):
template = template.replace(placeholder, value)
for placeholder, value in (
(f"__{prefix}_SUBSCRIBER_ID__", identity["participantId"]),
(f"__{prefix}_KEY_ID__", identity["keyOsid"]),
(f"__{prefix}_SIGNING_PRIVATE__", identity["signingPrivate"]),
(f"__{prefix}_SIGNING_PUBLIC__", identity["signingPublic"]),
(f"__{prefix}_ENCR_PRIVATE__", identity["encrPrivate"]),
(f"__{prefix}_ENCR_PUBLIC__", identity["encrPublic"]),
("__MAUSAMGRAM_BINDING_KEY__", mausamgram_binding),
("__AGMARKNET_BINDING_KEY__", agmarknet_binding),
("__VISTAAR_BINDING_KEY__", vistaar_binding),
Expand All @@ -601,8 +608,8 @@ def render(identities):
("__OTEL_ENVIRONMENT__", env("OTEL_ENVIRONMENT", "dev"))):
template = template.replace(placeholder, value)
if "__" in template:
sys.exit(f"setup: {role}.yaml still has unrendered placeholders")
out = ADAPTERS / f"{role}.yaml"
sys.exit(f"setup: {name}.yaml still has unrendered placeholders")
out = ADAPTERS / folder / f"{fname}.yaml"
# A bare `docker compose up -d` before this script runs starts the
# adapters too, and Docker creates a DIRECTORY at a bind-mount source
# that does not exist. Writing would then fail with a bare
Expand All @@ -613,11 +620,11 @@ def render(identities):
f" Docker created it, which means the adapters were started before this\n"
f" script ran. Bring them down, remove the empty directories and retry:\n"
f" docker compose down\n"
f" rmdir config/adapters/*.yaml\n"
f" rmdir config/adapters/*/*.yaml\n"
f" make up")
out.write_text(template)
out.chmod(0o600) # holds a private key
print(f" config/adapters/{role}.yaml")
print(f" config/adapters/{folder}/{fname}.yaml")


if __name__ == "__main__":
Expand Down Expand Up @@ -659,9 +666,7 @@ def render(identities):
happens from here.

Next: `make up` continues to step 3 and starts the adapters. If you ran this
on its own, the adapters need recreating to pick up the rendered configs:

docker compose up -d --force-recreate provider-adapter network-adapter consumer-adapter
on its own, run `make up` (or `NETWORK_ADAPTER_DEPLOYMENT_MODE=multi-adapter make up`) to pick up the rendered configs.

Then import ../api-collection/ -- both files, the collection and the
environment -- and run it. Eighteen requests across the four capabilities,
Expand Down
104 changes: 91 additions & 13 deletions quick-start/bin/stack.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,55 @@ set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

# Both optional profiles, named explicitly. This matters for `down`: compose
# only acts on services whose profile is active, so a plain `docker compose
# down` leaves the gateway and hyperdx containers running and then reports
# success. Naming them on teardown is what makes "down" mean down.
PROFILES=(--profile reverse-proxy --profile observability)
# Every optional profile, named so `down` also stops profiled services
# (the gateway, hyperdx, provider- and consumer-adapter).
PROFILES=(--profile reverse-proxy --profile observability --profile multi-adapter)

# Deployment mode for `up`: NETWORK_ADAPTER_DEPLOYMENT_MODE from the shell, else .env, else
# single-adapter (ADR-0001).
# Other commands keep the running mode so depends_on never swaps network-adapter's config.

# A key's value in .env (quotes, inline comment and CR stripped); empty if absent.
dotenv_get() {
local v
v=$(grep -E "^$1=" .env 2>/dev/null | tail -1 | cut -d= -f2-) || true
v=${v%%#*}
printf '%s' "$v" | tr -d '"'"'"' \t\r'
}

# Running mode, from the config network-adapter mounts; empty if not running.
running_mode() {
[ "$(docker inspect -f '{{.State.Running}}' network-adapter 2>/dev/null)" = true ] || return 0
case "$(docker inspect -f '{{range .Mounts}}{{if eq .Destination "/app/config/adapter.yaml"}}{{.Source}}{{end}}{{end}}' network-adapter 2>/dev/null)" in
*/multi-adapter/*) echo multi-adapter ;;
*) echo single-adapter ;;
esac
}

MODE="${NETWORK_ADAPTER_DEPLOYMENT_MODE:-$(dotenv_get NETWORK_ADAPTER_DEPLOYMENT_MODE)}"
MODE="${MODE:-single-adapter}"
case "$MODE" in single|multi) MODE="$MODE-adapter" ;; esac # old values still accepted
RUNNING_MODE="$(running_mode)"

# compose mounts config/adapters/<mode>/network-adapter.yaml from this variable.
export NETWORK_ADAPTER_DEPLOYMENT_MODE="${RUNNING_MODE:-$MODE}"
check_mode() {
case "$MODE" in single-adapter|multi-adapter) ;; *) die "NETWORK_ADAPTER_DEPLOYMENT_MODE must be single-adapter or multi-adapter, not '$MODE'" ;; esac
}

adapters_for() { # $1 mode
case "$1" in
single-adapter) echo network-adapter ;;
multi-adapter) echo provider-adapter network-adapter consumer-adapter ;;
esac
}
# The rendered config files (config/adapters/<path>.yaml) a deployment mode mounts.
configs_for() { # $1 mode
case "$1" in
single-adapter) echo single-adapter/network-adapter ;;
multi-adapter) echo multi-adapter/provider-adapter multi-adapter/network-adapter multi-adapter/consumer-adapter ;;
esac
}

# ------------------------------------------------------------------ output

Expand Down Expand Up @@ -74,6 +118,7 @@ preflight() {
# `up-core` below is the same thing minus steps 4 and 5, for when you want
# neither a public port nor ClickHouse's memory.
up() {
check_mode
preflight
up_registry_tier 5
up_setup 5
Expand All @@ -97,6 +142,7 @@ up() {
# 16 GB -- this is the stack you can actually exercise, which is the reason the
# profiles exist in the first place.
up_core() {
check_mode
preflight
up_registry_tier 3
up_setup 3
Expand Down Expand Up @@ -125,7 +171,7 @@ up_registry_tier() {
}

# Generates the adapter keypairs, registers the three adapter identities, and
# renders config/adapters/{provider,network,consumer}.yaml from the .tmpl files
# renders config/adapters/{multi-adapter,single-adapter}/*.yaml from the .tmpl files
# beside them. Safe to re-run: keys come from keys/keys.json once it exists,
# and participants already registered are left alone.
up_setup() {
Expand All @@ -142,8 +188,33 @@ up_adapters() {
# debugging a mapping without the real credentials -- but that also needs a
# new participant id and base URL in .env plus a setup.py re-run, because
# the registry cannot repoint an existing row.
step 3 "$1" "adapters (provider, network, consumer)"
docker compose up -d provider-adapter network-adapter consumer-adapter
check_mode
local f
# `up` starts the requested mode, not the running one.
NETWORK_ADAPTER_DEPLOYMENT_MODE="$MODE"
step 3 "$1" "adapters, mode $MODE ($(adapters_for "$MODE"))"
# A pre-merge stack's network-adapter container (service network-adapter-layer)
# is unknown to compose and would clash by name.
if [ "$(docker inspect -f '{{index .Config.Labels "com.docker.compose.service"}}' network-adapter 2>/dev/null)" = network-adapter-layer ]; then
docker rm -f network-adapter >/dev/null
fi
# Single runs network-adapter alone: remove the multi-only adapters.
if [ "$MODE" = single-adapter ]; then
docker compose --profile multi-adapter rm -sf provider-adapter consumer-adapter >/dev/null 2>&1 || true
fi
# Never let compose create a directory where a bind-mounted config belongs.
for f in $(configs_for "$MODE"); do
[ -f "config/adapters/$f.yaml" ] \
|| die "config/adapters/$f.yaml was not rendered (a directory there? rm -r it, then re-run)"
done
# shellcheck disable=SC2046
docker compose --profile multi-adapter up -d --force-recreate $(adapters_for "$MODE")
# NPM resolves adapter names when nginx loads and caches the addresses, so
# a recreated or switched adapter 502s through it until it restarts.
if [ "$(docker inspect -f '{{.State.Running}}' nginx-proxy-manager 2>/dev/null)" = true ]; then
info "restarting nginx-proxy-manager so it re-resolves the adapter addresses"
docker compose --profile reverse-proxy restart nginx-proxy-manager >/dev/null
fi
}

done_banner() {
Expand Down Expand Up @@ -282,7 +353,6 @@ NEXT
# It also excludes nginx-proxy-manager, whose routing table lives in a SQLite
# database rather than in anything a restart would re-read. `restart-edge` is
# the separate target for the one case that does need it.
APP_SERVICES=(registry discovery provider-adapter network-adapter consumer-adapter)

# `restart`, not `up -d --force-recreate`. A restart keeps the container and
# therefore its address, so NPM's cached proxy_pass targets stay valid -- a
Expand All @@ -294,10 +364,13 @@ APP_SERVICES=(registry discovery provider-adapter network-adapter consumer-adapt
# up is a changed image or a changed environment, both of which need the
# container recreated -- use `make up` for those.
restart_app() {
step 1 1 "restarting registry, discovery and the three adapters"
[ -n "$RUNNING_MODE" ] && MODE=$RUNNING_MODE
check_mode
step 1 1 "restarting registry, discovery and the $MODE-mode adapters"
info "keycloak, both databases and the edge are left alone"
docker compose restart "${APP_SERVICES[@]}"
docker compose ps --format 'table {{.Service}}\t{{.Status}}'
# shellcheck disable=SC2046
docker compose --profile multi-adapter restart sunbird-registry-service discovery-service $(adapters_for "$MODE")
docker compose --profile multi-adapter ps --format 'table {{.Service}}\t{{.Status}}'
}

# ----------------------------------------------------------------- misc
Expand All @@ -324,9 +397,12 @@ usage() {
cat <<'USAGE'
bin/stack.sh <command>

up the whole stack: registry+discovery -> setup.py -> adapters
up the whole stack, Network Adapter Layer (default):
registry+discovery -> setup.py -> network-adapter (Network Adapter Layer)
-> gateway (public, 80/443) -> hyperdx (wants 16 GB)
up-core steps 1-3 only. Nothing public, no ClickHouse.
(without a flag: MODE, else NETWORK_ADAPTER_DEPLOYMENT_MODE in
.env, else single-adapter; restart follows the running mode)
down stop everything, keep the data
destroy stop everything and DELETE every volume
setup re-run bin/setup.py only
Expand All @@ -341,6 +417,8 @@ bin/stack.sh <command>
USAGE
}

# Every command takes no arguments except logs; an extra one is a mistake, not a mode.
[ $# -le 1 ] || [ "${1:-}" = logs ] || { usage; die "unexpected argument: $2"; }
case "${1:-}" in
up) up ;;
up-core) up_core ;;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# OAN consumer adapter. The caller: routes by action -- discovery to the
# network layer, transactions straight to the provider adapter.
# Use only in multi-adapter deployment mode: the consumer adapter,
# the caller: routes discovery to the network layer, transactions to the provider.
appName: "consumer-adapter"

log:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# OAN network adapter. The network layer: hands discovery to the discovery
# service and re-signs as itself on the way out.
# Use only in multi-adapter deployment mode: the network adapter,
# the network layer: hands discovery to the discovery service, re-signs as itself.
appName: "network-adapter"

log:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# OAN provider adapter. Answers Beckn actions synchronously: resolve the
# capability's call plan, call the provider, return the mapped result.
# Use only in multi-adapter deployment mode: the provider adapter,
# answers Beckn actions from the provider APIs and publishes the catalogue.
appName: "provider-adapter"

log:
Expand Down
Loading