Skip to content

Commit 9c4805f

Browse files
authored
Add Multi-tenancy single wallet upgrade test (openwallet-foundation#3457)
Signed-off-by: jamshale <[email protected]>
1 parent 7ef0ba8 commit 9c4805f

File tree

2 files changed

+182
-29
lines changed

2 files changed

+182
-29
lines changed

scenarios/examples/simple_restart/docker-compose.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,43 @@ services:
9090
wallet-db:
9191
condition: service_healthy
9292

93+
agency:
94+
image: bcgovimages/aries-cloudagent:py3.12_1.0.1
95+
ports:
96+
- "3003:3001"
97+
command: >
98+
start
99+
--label Agency
100+
--inbound-transport http 0.0.0.0 3000
101+
--outbound-transport http
102+
--endpoint http://agency:3000
103+
--admin 0.0.0.0 3001
104+
--admin-insecure-mode
105+
--tails-server-base-url http://tails:6543
106+
--genesis-url http://test.bcovrin.vonx.io/genesis
107+
--wallet-type askar
108+
--wallet-name agency
109+
--wallet-key insecure
110+
--auto-provision
111+
--multitenant
112+
--multitenant-admin
113+
--jwt-secret insecure
114+
--multitenancy-config wallet_type=single-wallet-askar key_derivation_method=RAW
115+
--wallet-storage-type "postgres_storage"
116+
--wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}"
117+
--wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}"
118+
--log-level info
119+
--debug-webhooks
120+
healthcheck:
121+
test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null
122+
start_period: 30s
123+
interval: 7s
124+
timeout: 5s
125+
retries: 5
126+
depends_on:
127+
tails:
128+
condition: service_started
129+
93130
tails:
94131
image: ghcr.io/bcgov/tails-server:latest
95132
ports:
@@ -112,6 +149,7 @@ services:
112149
- DOCKER_HOST=unix:///var/run/docker.sock
113150
- ALICE=http://alice:3001
114151
- BOB=http://bob:3001
152+
- AGENCY=http://agency:3001
115153
volumes:
116154
- /var/run/docker.sock:/var/run/docker.sock
117155
- ./example.py:/usr/src/app/example.py:ro,z
@@ -121,3 +159,5 @@ services:
121159
condition: service_healthy
122160
bob:
123161
condition: service_healthy
162+
agency:
163+
condition: service_healthy

scenarios/examples/simple_restart/example.py

Lines changed: 142 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,50 @@
55

66
import asyncio
77
from os import getenv
8-
import json
9-
import time
10-
11-
import docker
12-
from docker.errors import NotFound
13-
from docker.models.containers import Container
148

159
from acapy_controller import Controller
1610
from acapy_controller.logging import logging_to_stdout
11+
from acapy_controller.models import CreateWalletResponse
1712
from acapy_controller.protocols import (
18-
connection,
1913
didexchange,
2014
indy_anoncred_credential_artifacts,
2115
indy_anoncred_onboard,
22-
indy_anoncreds_publish_revocation,
23-
indy_anoncreds_revoke,
2416
indy_issue_credential_v2,
2517
indy_present_proof_v2,
2618
)
27-
2819
from examples.util import (
29-
healthy,
30-
unhealthy,
3120
wait_until_healthy,
3221
)
3322

23+
import docker
3424

3525
ALICE = getenv("ALICE", "http://alice:3001")
3626
BOB = getenv("BOB", "http://bob:3001")
27+
AGENCY = getenv("AGENCY", "http://agency:3001")
3728

3829

3930
async def main():
4031
"""Test Controller protocols."""
41-
async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob:
32+
# create multitenant issuer tenant
33+
async with Controller(base_url=AGENCY) as agency:
34+
multitenant_issuer_tenant = await agency.post(
35+
"/multitenancy/wallet",
36+
json={
37+
"label": "MultitenantIssuer",
38+
"wallet_type": "askar",
39+
},
40+
response=CreateWalletResponse,
41+
)
42+
43+
async with (
44+
Controller(base_url=ALICE) as alice,
45+
Controller(base_url=BOB) as bob,
46+
Controller(
47+
base_url=AGENCY,
48+
wallet_id=multitenant_issuer_tenant.wallet_id,
49+
subwallet_token=multitenant_issuer_tenant.token,
50+
) as multitenant_issuer,
51+
):
4252
# connect the 2 agents
4353
print(">>> connecting agents ...")
4454
(alice_conn, bob_conn) = await didexchange(alice, bob)
@@ -74,45 +84,100 @@ async def main():
7484
)
7585
print(">>> Done!")
7686

87+
# connect multitenant issuer to bob
88+
print(">>> connecting agents ...")
89+
(multitenant_issuer_conn, bob_to_mt_conn) = await didexchange(
90+
multitenant_issuer, bob
91+
)
92+
93+
# setup multitenant issuer as an issuer
94+
print(">>> setting up multitenant issuer as issuer ...")
95+
await indy_anoncred_onboard(multitenant_issuer)
96+
schema, cred_def = await indy_anoncred_credential_artifacts(
97+
multitenant_issuer,
98+
["firstname", "lastname"],
99+
support_revocation=True,
100+
)
101+
102+
# Issue a credential
103+
print(">>> issue credential ...")
104+
multitenant_issuer_cred_ex, _ = await indy_issue_credential_v2(
105+
multitenant_issuer,
106+
bob,
107+
multitenant_issuer_conn.connection_id,
108+
bob_to_mt_conn.connection_id,
109+
cred_def.credential_definition_id,
110+
{"firstname": "Bob", "lastname": "Builder"},
111+
)
112+
113+
# Present the the credential's attributes
114+
print(">>> present proof ...")
115+
await indy_present_proof_v2(
116+
bob,
117+
multitenant_issuer,
118+
bob_to_mt_conn.connection_id,
119+
multitenant_issuer_conn.connection_id,
120+
requested_attributes=[{"name": "firstname"}],
121+
)
122+
print(">>> Done!")
123+
77124
# play with docker
78125
client = docker.from_env()
79126
containers = client.containers.list(all=True)
80127
docker_containers = {}
81128
for container in containers:
82-
if 'com.docker.compose.service' in container.attrs['Config']['Labels']:
83-
container_name = container.attrs['Config']['Labels']['com.docker.compose.service']
84-
container_id = container.attrs['Id']
85-
container_is_running = container.attrs['State']['Running']
86-
docker_containers[container_name] = {'Id': container_id, 'Running': container_is_running}
129+
if "com.docker.compose.service" in container.attrs["Config"]["Labels"]:
130+
container_name = container.attrs["Config"]["Labels"][
131+
"com.docker.compose.service"
132+
]
133+
container_id = container.attrs["Id"]
134+
container_is_running = container.attrs["State"]["Running"]
135+
docker_containers[container_name] = {
136+
"Id": container_id,
137+
"Running": container_is_running,
138+
}
87139
print(">>> container:", container_name, docker_containers[container_name])
88140

89141
# try to restart a container (stop alice and start alice-upgrade)
90-
alice_docker_container = docker_containers['alice']
91-
alice_container = client.containers.get(alice_docker_container['Id'])
142+
alice_docker_container = docker_containers["alice"]
143+
alice_container = client.containers.get(alice_docker_container["Id"])
144+
145+
# try to restart agency container (stop agency and start agency-upgrade)
146+
agency_docker_container = docker_containers["agency"]
147+
agency_container = client.containers.get(agency_docker_container["Id"])
92148

93149
print(">>> shut down alice ...")
94150
alice_container.stop()
95151

152+
print(">>> shut down agency ...")
153+
agency_container.stop()
154+
96155
print(">>> waiting for alice container to exit ...")
97-
alice_id = alice_container.attrs['Id']
156+
alice_id = agency_container.attrs["Id"]
98157
wait_until_healthy(client, alice_id, is_healthy=False)
99158
alice_container.remove()
100159

160+
print(">>> waiting for agency container to exit ...")
161+
agency_id = agency_container.attrs["Id"]
162+
wait_until_healthy(client, agency_id, is_healthy=False)
163+
agency_container.remove()
164+
165+
# Upgrade alice and perform some tests
101166
new_alice_container = None
102167
alice_id = None
103168
try:
104169
print(">>> start new alice container ...")
105170
new_alice_container = client.containers.run(
106-
'acapy-test',
107-
command=alice_container.attrs['Config']['Cmd'],
171+
"acapy-test",
172+
command=alice_container.attrs["Config"]["Cmd"],
108173
detach=True,
109-
environment={'RUST_LOG': 'aries-askar::log::target=error'},
110-
healthcheck=alice_container.attrs['Config']['Healthcheck'],
111-
name='alice',
112-
network=alice_container.attrs['HostConfig']['NetworkMode'],
113-
ports=alice_container.attrs['NetworkSettings']['Ports'],
174+
environment={"RUST_LOG": "aries-askar::log::target=error"},
175+
healthcheck=alice_container.attrs["Config"]["Healthcheck"],
176+
name="alice",
177+
network=alice_container.attrs["HostConfig"]["NetworkMode"],
178+
ports=alice_container.attrs["NetworkSettings"]["Ports"],
114179
)
115-
alice_id = new_alice_container.attrs['Id']
180+
alice_id = new_alice_container.attrs["Id"]
116181

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

206+
# Upgrade agency and perform some tests
207+
new_agency_container = None
208+
agency_id = None
209+
try:
210+
print(">>> start new agency container ...")
211+
new_agency_container = client.containers.run(
212+
"acapy-test",
213+
command=agency_container.attrs["Config"]["Cmd"],
214+
detach=True,
215+
environment={"RUST_LOG": "aries-askar::log::target=error"},
216+
healthcheck=agency_container.attrs["Config"]["Healthcheck"],
217+
name="agency",
218+
network=agency_container.attrs["HostConfig"]["NetworkMode"],
219+
ports=agency_container.attrs["NetworkSettings"]["Ports"],
220+
)
221+
agency_id = new_agency_container.attrs["Id"]
222+
223+
wait_until_healthy(client, agency_id)
224+
print(">>> new agency container is healthy")
225+
226+
# run some more tests ... agency tenant should still be connected to bob ...
227+
async with (
228+
Controller(base_url=BOB) as bob,
229+
Controller(
230+
base_url=AGENCY,
231+
wallet_id=multitenant_issuer_tenant.wallet_id,
232+
subwallet_token=multitenant_issuer_tenant.token,
233+
) as multitenant_issuer,
234+
):
235+
# Present the the credential's attributes
236+
print(">>> present proof ... again ...")
237+
await indy_present_proof_v2(
238+
bob,
239+
multitenant_issuer,
240+
bob_to_mt_conn.connection_id,
241+
multitenant_issuer_conn.connection_id,
242+
requested_attributes=[{"name": "firstname"}],
243+
)
244+
print(">>> Done! (again)")
245+
finally:
246+
if agency_id and new_agency_container:
247+
# cleanup - shut down agency agent (not part of docker compose)
248+
print(">>> shut down agency ...")
249+
agency_container = client.containers.get(agency_id)
250+
agency_container.stop()
251+
wait_until_healthy(client, agency_id, is_healthy=False)
252+
agency_container.remove()
253+
141254

142255
if __name__ == "__main__":
143256
logging_to_stdout()

0 commit comments

Comments
 (0)