Skip to content

Commit

Permalink
Add Multi-tenancy single wallet upgrade test (openwallet-foundation#3457
Browse files Browse the repository at this point in the history
)

Signed-off-by: jamshale <[email protected]>
  • Loading branch information
jamshale authored Jan 20, 2025
1 parent 7ef0ba8 commit 9c4805f
Show file tree
Hide file tree
Showing 2 changed files with 182 additions and 29 deletions.
40 changes: 40 additions & 0 deletions scenarios/examples/simple_restart/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,43 @@ services:
wallet-db:
condition: service_healthy

agency:
image: bcgovimages/aries-cloudagent:py3.12_1.0.1
ports:
- "3003:3001"
command: >
start
--label Agency
--inbound-transport http 0.0.0.0 3000
--outbound-transport http
--endpoint http://agency:3000
--admin 0.0.0.0 3001
--admin-insecure-mode
--tails-server-base-url http://tails:6543
--genesis-url http://test.bcovrin.vonx.io/genesis
--wallet-type askar
--wallet-name agency
--wallet-key insecure
--auto-provision
--multitenant
--multitenant-admin
--jwt-secret insecure
--multitenancy-config wallet_type=single-wallet-askar key_derivation_method=RAW
--wallet-storage-type "postgres_storage"
--wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}"
--wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}"
--log-level info
--debug-webhooks
healthcheck:
test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null
start_period: 30s
interval: 7s
timeout: 5s
retries: 5
depends_on:
tails:
condition: service_started

tails:
image: ghcr.io/bcgov/tails-server:latest
ports:
Expand All @@ -112,6 +149,7 @@ services:
- DOCKER_HOST=unix:///var/run/docker.sock
- ALICE=http://alice:3001
- BOB=http://bob:3001
- AGENCY=http://agency:3001
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./example.py:/usr/src/app/example.py:ro,z
Expand All @@ -121,3 +159,5 @@ services:
condition: service_healthy
bob:
condition: service_healthy
agency:
condition: service_healthy
171 changes: 142 additions & 29 deletions scenarios/examples/simple_restart/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,50 @@

import asyncio
from os import getenv
import json
import time

import docker
from docker.errors import NotFound
from docker.models.containers import Container

from acapy_controller import Controller
from acapy_controller.logging import logging_to_stdout
from acapy_controller.models import CreateWalletResponse
from acapy_controller.protocols import (
connection,
didexchange,
indy_anoncred_credential_artifacts,
indy_anoncred_onboard,
indy_anoncreds_publish_revocation,
indy_anoncreds_revoke,
indy_issue_credential_v2,
indy_present_proof_v2,
)

from examples.util import (
healthy,
unhealthy,
wait_until_healthy,
)

import docker

ALICE = getenv("ALICE", "http://alice:3001")
BOB = getenv("BOB", "http://bob:3001")
AGENCY = getenv("AGENCY", "http://agency:3001")


async def main():
"""Test Controller protocols."""
async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob:
# create multitenant issuer tenant
async with Controller(base_url=AGENCY) as agency:
multitenant_issuer_tenant = await agency.post(
"/multitenancy/wallet",
json={
"label": "MultitenantIssuer",
"wallet_type": "askar",
},
response=CreateWalletResponse,
)

async with (
Controller(base_url=ALICE) as alice,
Controller(base_url=BOB) as bob,
Controller(
base_url=AGENCY,
wallet_id=multitenant_issuer_tenant.wallet_id,
subwallet_token=multitenant_issuer_tenant.token,
) as multitenant_issuer,
):
# connect the 2 agents
print(">>> connecting agents ...")
(alice_conn, bob_conn) = await didexchange(alice, bob)
Expand Down Expand Up @@ -74,45 +84,100 @@ async def main():
)
print(">>> Done!")

# connect multitenant issuer to bob
print(">>> connecting agents ...")
(multitenant_issuer_conn, bob_to_mt_conn) = await didexchange(
multitenant_issuer, bob
)

# setup multitenant issuer as an issuer
print(">>> setting up multitenant issuer as issuer ...")
await indy_anoncred_onboard(multitenant_issuer)
schema, cred_def = await indy_anoncred_credential_artifacts(
multitenant_issuer,
["firstname", "lastname"],
support_revocation=True,
)

# Issue a credential
print(">>> issue credential ...")
multitenant_issuer_cred_ex, _ = await indy_issue_credential_v2(
multitenant_issuer,
bob,
multitenant_issuer_conn.connection_id,
bob_to_mt_conn.connection_id,
cred_def.credential_definition_id,
{"firstname": "Bob", "lastname": "Builder"},
)

# Present the the credential's attributes
print(">>> present proof ...")
await indy_present_proof_v2(
bob,
multitenant_issuer,
bob_to_mt_conn.connection_id,
multitenant_issuer_conn.connection_id,
requested_attributes=[{"name": "firstname"}],
)
print(">>> Done!")

# play with docker
client = docker.from_env()
containers = client.containers.list(all=True)
docker_containers = {}
for container in containers:
if 'com.docker.compose.service' in container.attrs['Config']['Labels']:
container_name = container.attrs['Config']['Labels']['com.docker.compose.service']
container_id = container.attrs['Id']
container_is_running = container.attrs['State']['Running']
docker_containers[container_name] = {'Id': container_id, 'Running': container_is_running}
if "com.docker.compose.service" in container.attrs["Config"]["Labels"]:
container_name = container.attrs["Config"]["Labels"][
"com.docker.compose.service"
]
container_id = container.attrs["Id"]
container_is_running = container.attrs["State"]["Running"]
docker_containers[container_name] = {
"Id": container_id,
"Running": container_is_running,
}
print(">>> container:", container_name, docker_containers[container_name])

# try to restart a container (stop alice and start alice-upgrade)
alice_docker_container = docker_containers['alice']
alice_container = client.containers.get(alice_docker_container['Id'])
alice_docker_container = docker_containers["alice"]
alice_container = client.containers.get(alice_docker_container["Id"])

# try to restart agency container (stop agency and start agency-upgrade)
agency_docker_container = docker_containers["agency"]
agency_container = client.containers.get(agency_docker_container["Id"])

print(">>> shut down alice ...")
alice_container.stop()

print(">>> shut down agency ...")
agency_container.stop()

print(">>> waiting for alice container to exit ...")
alice_id = alice_container.attrs['Id']
alice_id = agency_container.attrs["Id"]
wait_until_healthy(client, alice_id, is_healthy=False)
alice_container.remove()

print(">>> waiting for agency container to exit ...")
agency_id = agency_container.attrs["Id"]
wait_until_healthy(client, agency_id, is_healthy=False)
agency_container.remove()

# Upgrade alice and perform some tests
new_alice_container = None
alice_id = None
try:
print(">>> start new alice container ...")
new_alice_container = client.containers.run(
'acapy-test',
command=alice_container.attrs['Config']['Cmd'],
"acapy-test",
command=alice_container.attrs["Config"]["Cmd"],
detach=True,
environment={'RUST_LOG': 'aries-askar::log::target=error'},
healthcheck=alice_container.attrs['Config']['Healthcheck'],
name='alice',
network=alice_container.attrs['HostConfig']['NetworkMode'],
ports=alice_container.attrs['NetworkSettings']['Ports'],
environment={"RUST_LOG": "aries-askar::log::target=error"},
healthcheck=alice_container.attrs["Config"]["Healthcheck"],
name="alice",
network=alice_container.attrs["HostConfig"]["NetworkMode"],
ports=alice_container.attrs["NetworkSettings"]["Ports"],
)
alice_id = new_alice_container.attrs['Id']
alice_id = new_alice_container.attrs["Id"]

wait_until_healthy(client, alice_id)
print(">>> new alice container is healthy")
Expand All @@ -138,6 +203,54 @@ async def main():
wait_until_healthy(client, alice_id, is_healthy=False)
alice_container.remove()

# Upgrade agency and perform some tests
new_agency_container = None
agency_id = None
try:
print(">>> start new agency container ...")
new_agency_container = client.containers.run(
"acapy-test",
command=agency_container.attrs["Config"]["Cmd"],
detach=True,
environment={"RUST_LOG": "aries-askar::log::target=error"},
healthcheck=agency_container.attrs["Config"]["Healthcheck"],
name="agency",
network=agency_container.attrs["HostConfig"]["NetworkMode"],
ports=agency_container.attrs["NetworkSettings"]["Ports"],
)
agency_id = new_agency_container.attrs["Id"]

wait_until_healthy(client, agency_id)
print(">>> new agency container is healthy")

# run some more tests ... agency tenant should still be connected to bob ...
async with (
Controller(base_url=BOB) as bob,
Controller(
base_url=AGENCY,
wallet_id=multitenant_issuer_tenant.wallet_id,
subwallet_token=multitenant_issuer_tenant.token,
) as multitenant_issuer,
):
# Present the the credential's attributes
print(">>> present proof ... again ...")
await indy_present_proof_v2(
bob,
multitenant_issuer,
bob_to_mt_conn.connection_id,
multitenant_issuer_conn.connection_id,
requested_attributes=[{"name": "firstname"}],
)
print(">>> Done! (again)")
finally:
if agency_id and new_agency_container:
# cleanup - shut down agency agent (not part of docker compose)
print(">>> shut down agency ...")
agency_container = client.containers.get(agency_id)
agency_container.stop()
wait_until_healthy(client, agency_id, is_healthy=False)
agency_container.remove()


if __name__ == "__main__":
logging_to_stdout()
Expand Down

0 comments on commit 9c4805f

Please sign in to comment.