Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update demo/playground scripts #2562

Merged
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
2 changes: 1 addition & 1 deletion demo/playground/Dockerfile.acapy
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.8.1
FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.10.4

USER root

Expand Down
4 changes: 4 additions & 0 deletions demo/playground/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ services:
retries: 5

faber-agent:
image: playground-image
build:
context: .
dockerfile: Dockerfile.acapy
Expand Down Expand Up @@ -110,6 +111,7 @@ services:
retries: 5

alice-agent:
image: playground-image
build:
context: .
dockerfile: Dockerfile.acapy
Expand Down Expand Up @@ -154,6 +156,7 @@ services:
retries: 5

acme-agent:
image: playground-image
build:
context: .
dockerfile: Dockerfile.acapy
Expand Down Expand Up @@ -198,6 +201,7 @@ services:
retries: 5

multi-agent:
image: playground-image
build:
context: .
dockerfile: Dockerfile.acapy
Expand Down
20 changes: 20 additions & 0 deletions demo/playground/examples/Dockerfile.test.runner
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM python:3.9-slim
WORKDIR /usr/src/app

# install poetry
RUN pip3 install --no-cache-dir poetry

# Add docker-compose-wait tool
ENV WAIT_VERSION 2.7.2
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/$WAIT_VERSION/wait /wait
RUN chmod +x /wait

# install dependencies
COPY pyproject.toml .
COPY poetry.lock .
RUN poetry install --only main

# add tests to image
COPY tests/* tests/

ENTRYPOINT ["/bin/sh", "-c", "/wait && poetry run pytest \"$@\"", "--"]
33 changes: 33 additions & 0 deletions demo/playground/examples/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
version: '3'
#***************************************************************
# playground test agents *
#***************************************************************

networks:
app-network:
name: ${APP_NETWORK_NAME:-playgroundnet}
driver: bridge
external: true

services:

tests:
container_name: juggernaut
build:
context: .
dockerfile: Dockerfile.test.runner
environment:
- WAIT_BEFORE_HOSTS=3
- WAIT_HOSTS=faber-agent:9011, alice-agent:9012, acme-agent:9013, multi-agent:9014
- WAIT_HOSTS_TIMEOUT=60
- WAIT_SLEEP_INTERVAL=1
- WAIT_HOST_CONNECT_TIMEOUT=30
# API ADMIN
- FABER=http://faber-agent:9011
- ALICE=http://alice-agent:9012
- ACME=http://acme-agent:9013
- MULTI=http://multi-agent:9014
# ADDITIONAL TEST env vars
- MEDIATOR_INVITATION_URL=${MEDIATOR_INVITATION_URL}
networks:
- app-network
303 changes: 303 additions & 0 deletions demo/playground/examples/poetry.lock

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions demo/playground/examples/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[tool.poetry]
name = "acapy_demos_playground"
version = "0.1.0"
description = ""
authors = ["Jason Sherman <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.9"
pytest = "^7.4.0"
pytest-asyncio = "^0.21.0"
asynctest = "^0.13.0"
requests = "^2.31.0"

[tool.poetry.dev-dependencies]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
222 changes: 222 additions & 0 deletions demo/playground/examples/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# pylint: disable=redefined-outer-name

from functools import wraps
import logging
import os
import time

import pytest
import requests

AUTO_ACCEPT = "false"

FABER = os.getenv("FABER")
ALICE = os.getenv("ALICE")
ACME = os.getenv("ACME")
MULTI = os.getenv("MULTI")

# Create a named logger
logger = logging.getLogger("playground_examples")
logger.setLevel(logging.INFO)
# Create a console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# Set the formatter for the console handler
formatter = logging.Formatter(
"%(asctime)s - %(levelname)s - %(message)s",
)
console_handler.setFormatter(formatter)
# Add the console handler to the logger
logger.addHandler(console_handler)


def get(agent: str, path: str, **kwargs):
"""Get."""
return requests.get(f"{agent}{path}", **kwargs)


def post(agent: str, path: str, **kwargs):
"""Post."""
return requests.post(f"{agent}{path}", **kwargs)


def fail_if_not_ok(message: str):
"""Fail the current test if wrapped call fails with message."""

def _fail_if_not_ok(func):
@wraps(func)
def _wrapper(*args, **kwargs):
response = func(*args, **kwargs)
if not response.ok:
pytest.fail(f"{message}: {response.content}")
return response

return _wrapper

return _fail_if_not_ok


def unwrap_json_response(func):
"""Unwrap a requests response object to json."""

@wraps(func)
def _wrapper(*args, **kwargs) -> dict:
response = func(*args, **kwargs)
return response.json()

return _wrapper


class Agent:
"""Class for interacting with Agent over Admin API"""

def __init__(self, url: str, headers=None):
self.url = url
self._headers = headers

@property
def headers(self):
"""Accessor for the agents http headers.

Returns:
dict or None

"""
return self._headers

@headers.setter
def headers(self, headers):
"""Setter for agent's http headers.

Args:
headers: dict or None

"""
self._headers = headers

@unwrap_json_response
@fail_if_not_ok("Create invitation failed")
def create_invitation(self, json=None, **kwargs):
"""Create invitation."""
return post(
self.url,
"/connections/create-invitation",
params=kwargs,
headers=self._headers,
json=json,
)

@unwrap_json_response
@fail_if_not_ok("Receive invitation failed")
def receive_invite(self, invite: dict, **kwargs):
"""Receive invitation."""
return post(
self.url,
"/connections/receive-invitation",
params=kwargs,
headers=self._headers,
json=invite,
)

@unwrap_json_response
@fail_if_not_ok("Accept invitation failed")
def accept_invite(self, connection_id: str, **kwargs):
"""Accept invitation."""
return post(
self.url,
f"/connections/{connection_id}/accept-invitation",
params=kwargs,
headers=self._headers,
)

@unwrap_json_response
@fail_if_not_ok("Create invitation failed")
def list_connections(self, **kwargs):
"""List connections."""
results = get(self.url, "/connections", params=kwargs, headers=self._headers)
return results

@unwrap_json_response
@fail_if_not_ok("Failed to get connection by id")
def get_connection(self, connection_id: str, **kwargs):
"""Fetch a connection."""
return get(
self.url,
f"/connections/{connection_id}",
params=kwargs,
headers=self._headers,
)

@unwrap_json_response
@fail_if_not_ok("Failed to ping connection")
def ping_connection(self, connection_id: str, alias: str, **kwargs):
"""ping connection."""
return post(
self.url,
f"/connections/{connection_id}/send-ping",
params=kwargs,
headers=self._headers,
json={"comment": f"{alias} pinging..."},
)

@unwrap_json_response
@fail_if_not_ok("Failure requesting mediation")
def request_for_mediation(self, connection_id: str, **kwargs):
"""Request mediation from mediator."""
return post(
self.url,
f"/mediation/request/{connection_id}",
params=kwargs,
headers=self._headers,
json={},
)

@unwrap_json_response
@fail_if_not_ok("Failed to check mediation request")
def get_mediation_request(self, mediation_id: str, **kwargs):
"""Fetch mediation request."""
return get(
self.url,
f"/mediation/requests/{mediation_id}",
params=kwargs,
headers=self._headers,
)

@unwrap_json_response
@fail_if_not_ok("Failure requesting mediation")
def create_tenant(self, wallet_name: str, wallet_key: str, **kwargs):
"""Create a tenant in multitenanted acapy."""
data = {
"key_management_mode": "managed",
"wallet_dispatch_type": "default",
"wallet_name": wallet_name,
"wallet_key": wallet_key,
"label": wallet_name,
"wallet_type": "askar",
"wallet_webhook_urls": [],
}
# multi-agent has no security for base wallet, just call multitenancy/wallet
# to create a new tenant
return post(self.url, "/multitenancy/wallet", headers={}, json=data)

def get(self, path: str, return_json: bool = True, fail_with: str = None, **kwargs):
"""Do get to agent endpoint."""
wrapped_get = get
if fail_with:
wrapped_get = fail_if_not_ok(fail_with)(wrapped_get)
if return_json:
wrapped_get = unwrap_json_response(wrapped_get)

return wrapped_get(self.url, path, **kwargs)

def post(
self, path: str, return_json: bool = True, fail_with: str = None, **kwargs
):
"""Do post to agent endpoint."""
wrapped_post = post
if fail_with:
wrapped_post = fail_if_not_ok(fail_with)(wrapped_post)
if return_json:
wrapped_post = unwrap_json_response(wrapped_post)

return wrapped_post(self.url, path, **kwargs)
Loading