-
Notifications
You must be signed in to change notification settings - Fork 516
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Aca-Py test scenario including a container restart (with aca-py versi…
…on upgrade) (#3400) * Fix for demo initial cred_type override Signed-off-by: Ian Costanzo <[email protected]> * Initial version of a scenario test with restart Signed-off-by: Ian Costanzo <[email protected]> * WIP container restart example Signed-off-by: Ian Costanzo <[email protected]> * Make docker network explicit Signed-off-by: Ian Costanzo <[email protected]> * Add some agent activity to the restart test Signed-off-by: Ian Costanzo <[email protected]> * Test cleanup Signed-off-by: Ian Costanzo <[email protected]> * Remove unused env var Signed-off-by: Ian Costanzo <[email protected]> --------- Signed-off-by: Ian Costanzo <[email protected]>
- Loading branch information
Showing
4 changed files
with
1,104 additions
and
575 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
services: | ||
wallet-db: | ||
image: postgres:12 | ||
environment: | ||
- POSTGRES_USER=DB_USER | ||
- POSTGRES_PASSWORD=DB_PASSWORD | ||
ports: | ||
- 5433:5432 | ||
healthcheck: | ||
test: ["CMD-SHELL", "pg_isready -U DB_USER"] | ||
interval: 10s | ||
retries: 5 | ||
start_period: 30s | ||
timeout: 10s | ||
|
||
alice: | ||
image: bcgovimages/aries-cloudagent:py3.12_1.0.1 | ||
ports: | ||
- "3001:3001" | ||
environment: | ||
RUST_LOG: 'aries-askar::log::target=error' | ||
command: > | ||
start | ||
--label Alice | ||
--inbound-transport http 0.0.0.0 3000 | ||
--outbound-transport http | ||
--endpoint http://alice: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 alice | ||
--wallet-key insecure | ||
--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\"}" | ||
--auto-provision | ||
--log-level debug | ||
--debug-webhooks | ||
--preserve-exchange-records | ||
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 | ||
wallet-db: | ||
condition: service_healthy | ||
|
||
bob: | ||
image: acapy-test | ||
ports: | ||
- "3002:3001" | ||
environment: | ||
RUST_LOG: 'aries-askar::log::target=error' | ||
command: > | ||
start | ||
--label Bob | ||
--inbound-transport http 0.0.0.0 3000 | ||
--outbound-transport http | ||
--endpoint http://bob: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 bob | ||
--wallet-key insecure | ||
--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\"}" | ||
--auto-provision | ||
--log-level debug | ||
--debug-webhooks | ||
--monitor-revocation-notification | ||
--preserve-exchange-records | ||
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 | ||
wallet-db: | ||
condition: service_healthy | ||
|
||
tails: | ||
image: ghcr.io/bcgov/tails-server:latest | ||
ports: | ||
- 6543:6543 | ||
environment: | ||
- GENESIS_URL=http://test.bcovrin.vonx.io/genesis | ||
command: > | ||
tails-server | ||
--host 0.0.0.0 | ||
--port 6543 | ||
--storage-path /tmp/tails-files | ||
--log-level INFO | ||
example: | ||
container_name: controller | ||
privileged: true | ||
build: | ||
context: ../.. | ||
environment: | ||
- DOCKER_HOST=unix:///var/run/docker.sock | ||
- ALICE=http://alice:3001 | ||
- BOB=http://bob:3001 | ||
volumes: | ||
- /var/run/docker.sock:/var/run/docker.sock | ||
- ./example.py:/usr/src/app/example.py:ro,z | ||
command: python -m example | ||
depends_on: | ||
alice: | ||
condition: service_healthy | ||
bob: | ||
condition: service_healthy |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
"""Minimal reproducible example script. | ||
This script is for you to use to reproduce a bug or demonstrate a feature. | ||
""" | ||
|
||
import asyncio | ||
from os import getenv | ||
import json | ||
import time | ||
|
||
import docker | ||
from docker.errors import NotFound | ||
from docker.models.containers import Container | ||
from docker.models.networks import Network | ||
|
||
from acapy_controller import Controller | ||
from acapy_controller.logging import logging_to_stdout | ||
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, | ||
) | ||
|
||
ALICE = getenv("ALICE", "http://alice:3001") | ||
BOB = getenv("BOB", "http://bob:3001") | ||
|
||
|
||
def healthy(container: Container) -> bool: | ||
"""Check if container is healthy.""" | ||
inspect_results = container.attrs | ||
return inspect_results["State"]["Running"] and inspect_results["State"]["Health"]["Status"] == "healthy" | ||
|
||
|
||
def unhealthy(container: Container) -> bool: | ||
"""Check if container is unhealthy.""" | ||
inspect_results = container.attrs | ||
return not inspect_results["State"]["Running"] | ||
|
||
|
||
def wait_until_healthy(client, container_id: str, attempts: int = 350, is_healthy=True): | ||
"""Wait until container is healthy.""" | ||
container = client.containers.get(container_id) | ||
print((container.name, container.status)) | ||
for _ in range(attempts): | ||
if (is_healthy and healthy(container)) or unhealthy(container): | ||
return | ||
else: | ||
time.sleep(1) | ||
container = client.containers.get(container_id) | ||
raise TimeoutError("Timed out waiting for container") | ||
|
||
|
||
async def main(): | ||
"""Test Controller protocols.""" | ||
async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: | ||
# connect the 2 agents | ||
print(">>> connecting agents ...") | ||
(alice_conn, bob_conn) = await didexchange(alice, bob) | ||
|
||
# setup alice as an issuer | ||
print(">>> setting up alice as issuer ...") | ||
await indy_anoncred_onboard(alice) | ||
schema, cred_def = await indy_anoncred_credential_artifacts( | ||
alice, | ||
["firstname", "lastname"], | ||
support_revocation=True, | ||
) | ||
|
||
# Issue a credential | ||
print(">>> issue credential ...") | ||
alice_cred_ex, _ = await indy_issue_credential_v2( | ||
alice, | ||
bob, | ||
alice_conn.connection_id, | ||
bob_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, | ||
alice, | ||
bob_conn.connection_id, | ||
alice_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} | ||
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']) | ||
|
||
print(">>> shut down alice ...") | ||
alice_container.stop() | ||
|
||
print(">>> waiting for alice container to exit ...") | ||
alice_id = alice_container.attrs['Id'] | ||
wait_until_healthy(client, alice_id, is_healthy=False) | ||
alice_container.remove() | ||
|
||
print(">>> start new alice container ...") | ||
new_alice_container = client.containers.run( | ||
'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'], | ||
) | ||
print(">>> new container:", 'alice', json.dumps(new_alice_container.attrs)) | ||
alice_id = new_alice_container.attrs['Id'] | ||
|
||
try: | ||
wait_until_healthy(client, alice_id) | ||
print(">>> new alice container is healthy") | ||
|
||
# run some more tests ... alice should still be connected to bob for example ... | ||
async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: | ||
# Present the the credential's attributes | ||
print(">>> present proof ... again ...") | ||
await indy_present_proof_v2( | ||
bob, | ||
alice, | ||
bob_conn.connection_id, | ||
alice_conn.connection_id, | ||
requested_attributes=[{"name": "firstname"}], | ||
) | ||
print(">>> Done! (again)") | ||
finally: | ||
# cleanup - shut down alice agent (not part of docker compose) | ||
print(">>> shut down alice ...") | ||
alice_container = client.containers.get(alice_id) | ||
alice_container.stop() | ||
wait_until_healthy(client, alice_id, is_healthy=False) | ||
alice_container.remove() | ||
|
||
|
||
if __name__ == "__main__": | ||
logging_to_stdout() | ||
asyncio.run(main()) |
Oops, something went wrong.