diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000000..f1650dcb21 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,5 @@ +# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.134.0/containers/python-3/.devcontainer/base.Dockerfile +ARG VARIANT="3.9" +FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT} + +# if we need to enhance this image we can do it in this dockerfile or the post-install.sh script diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000000..46f3969472 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,57 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/python +{ + "name": "aries_cloudagent", + "build": { + "dockerfile": "Dockerfile", + "context": "..", + "args": { + "VARIANT": "3.9-bullseye" + } + }, + "customizations": { + "vscode": { + "extensions": [ + "ms-python.python", + "ms-python.vscode-pylance" + ], + "settings": { + "python.testing.pytestArgs": [ + ".", + "--no-cov" + ], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true, + "python.testing.pytestPath": "pytest", + "editor.defaultFormatter": null, + "editor.formatOnSave": false, // enable per language + "[python]": { + "editor.formatOnSave": true + }, + "python.formatting.provider": "black", + "python.formatting.blackPath": "/usr/local/py-utils/bin/black", + "python.formatting.blackArgs": [] + } + } + }, + + "features": { + "docker-in-docker": "latest", + }, + + // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode", + + "remoteEnv": { + //"PATH": "${containerEnv:PATH}:${workspaceRoot}/.venv/bin" + }, + + "mounts": [], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 9060, + 9061 + ], + "postCreateCommand": "bash ./.devcontainer/post-install.sh" + +} \ No newline at end of file diff --git a/.devcontainer/post-install.sh b/.devcontainer/post-install.sh new file mode 100644 index 0000000000..28a32368da --- /dev/null +++ b/.devcontainer/post-install.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -ex + +# Convenience workspace directory for later use +WORKSPACE_DIR=$(pwd) + +# install all ACA-Py requirements +python -m pip install --upgrade pip +pip3 install -r requirements.txt -r requirements.askar.txt -r requirements.bbs.txt -r requirements.dev.txt -r requirements.indy.txt + +# install black for formatting +pip3 install black \ No newline at end of file diff --git a/.vscode-sample/launch.json b/.vscode-sample/launch.json new file mode 100644 index 0000000000..f3af717a1b --- /dev/null +++ b/.vscode-sample/launch.json @@ -0,0 +1,97 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Run/Debug ACA-Py", + "type": "python", + "request": "launch", + "module": "aries_cloudagent", + "justMyCode": true, + "args": [ + "start", + "--arg-file=${workspaceRoot}/.vscode/multitenant.yml" + ] + }, + { + "name": "flake8 - aries_cloudagent", + "type": "python", + "request": "launch", + "module": "flake8", + "console": "integratedTerminal", + "justMyCode": true, + "cwd": "${workspaceFolder}/aries_cloudagent", + "args": [ + "--max-line-length=90", + "--exclude=*/tests/**", + "--extend-ignore=D202,W503", + "--per-file-ignores=*/__init__.py:D104" + ], + }, + { + "name": "flake8 - current file", + "type": "python", + "request": "launch", + "module": "flake8", + "console": "integratedTerminal", + "justMyCode": true, + "args": [ + "--max-line-length=90", + "--exclude=*/tests/**", + "--extend-ignore=D202,W503", + "--per-file-ignores=*/__init__.py:D104", + "${file}" + ], + }, + { + "name": "black (check) - aries_cloudagent", + "type": "python", + "request": "launch", + "module": "black", + "console": "integratedTerminal", + "justMyCode": true, + "cwd": "${workspaceFolder}/aries_cloudagent", + "args": [ + ".", + "--check" + ], + }, + { + "name": "black (check) - current file", + "type": "python", + "request": "launch", + "module": "black", + "console": "integratedTerminal", + "justMyCode": true, + "args": [ + "${file}", + "--check" + ], + }, + { + "name": "black (format) - aries_cloudagent", + "type": "python", + "request": "launch", + "module": "black", + "console": "integratedTerminal", + "justMyCode": true, + "cwd": "${workspaceFolder}/aries_cloudagent", + "args": [ + "." + ], + }, + { + "name": "black (format) - current file", + "type": "python", + "request": "launch", + "module": "black", + "console": "integratedTerminal", + "justMyCode": true, + "args": [ + "${file}", + ], + }, + ] +} \ No newline at end of file diff --git a/.vscode-sample/multitenant.yml b/.vscode-sample/multitenant.yml new file mode 100644 index 0000000000..68888a5bb2 --- /dev/null +++ b/.vscode-sample/multitenant.yml @@ -0,0 +1,32 @@ +auto-provision: true +label: vscode + +inbound-transport: + - [http, 0.0.0.0, 9060] + +outbound-transport: http + +emit-new-didcomm-prefix: true +wallet-type: askar +wallet-storage-type: default + +admin-insecure-mode: true + +admin: [0.0.0.0, 9061] + +endpoint: http://host.docker.internal:9060 + +genesis-url: http://test.bcovrin.vonx.io/genesis + +# Connections +debug-connections: true +auto-accept-invites: true +auto-accept-requests: true +auto-ping-connection: true + +# multitenant +multitenant: true +multitenant-admin: true +jwt-secret: changeme + +log-level: info diff --git a/.vscode-sample/settings.json b/.vscode-sample/settings.json new file mode 100644 index 0000000000..cd0a79cb6a --- /dev/null +++ b/.vscode-sample/settings.json @@ -0,0 +1,3 @@ +{ + "python.testing.pytestArgs": ["--no-cov"], +} \ No newline at end of file diff --git a/devcontainer.md b/devcontainer.md new file mode 100644 index 0000000000..d3aed89483 --- /dev/null +++ b/devcontainer.md @@ -0,0 +1,130 @@ +For information on running demos and tests using provided shell scripts, see [DevReadMe](/DevReadMe.md) readme. + +# ACA-Py Development with Dev Container +The following guide will get you up and running and developing/debugging ACA-Py as quickly as possible. +We provide a [`devcontainer`](https://containers.dev) and will use [`VS Code`](https://code.visualstudio.com) to illustrate. + +By no means is ACA-Py limited to these tools; they are merely examples. + +## Caveats + +The primary use case for this `devcontainer` is for developing, debugging and unit testing (pytest) the [aries_cloudagent](./aries_cloudagent) source code. + +There are limitations running this devcontainer, such as all networking is within this container. This container has [docker-in-docker](https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md) which allows running demos, building docker images, running `docker compose` all within this container. + +### Files +The `.devcontainer` folder contains the `devcontainer.json` file which defines this container. We are using a `Dockerfile` and `post-install.sh` to build and configure the container run image. The `Dockerfile` is simple but in place for simplifying image enhancements (ex. adding `poetry` to the image). The `post-install.sh` will install all the ACA-Py requirements and any additional steps (ex. adding additional development libraries). + +### Running docker-in-docker demos +The following is an example of running the demos in this container using a local [von-network](https://github.com/bcgov/von-network/tree/main). You will have to connect to the local von-network using `host.docker.internal` not `localhost`. + +Assumes von-network is running outside of VS Code and this container at the default port (9000). + +```sh +# open a terminal in VS Code... +cd demo +LEDGER_URL=http://host.docker.internal:9000 ./run_demo faber +# open a second terminal in VS Code... +cd demo +LEDGER_URL=http://host.docker.internal:9000 ./run_demo alice +# follow the script... +``` + + +## Further Reading and Links + +* Development Containers (devcontainers): [https://containers.dev](https://containers.dev) +* Visual Studio Code: [https://code.visualstudio.com](https://code.visualstudio.com) +* Dev Containers Extension: [marketplace.visualstudio.com](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +* Docker: [https://www.docker.com](https://www.docker.com) +* Docker Compose: [https://docs.docker.com/compose/](https://docs.docker.com/compose/) + + +## Devcontainer + +> What are Development Containers? +> +> A Development Container (or Dev Container for short) allows you to use a container as a full-featured development environment. It can be used to run an application, to separate tools, libraries, or runtimes needed for working with a codebase, and to aid in continuous integration and testing. Dev containers can be run locally or remotely, in a private or public cloud. + +see [https://containers.dev](https://containers.dev). + +In this guide, we will use [Docker](https://www.docker.com) and [Visual Studio Code](https://code.visualstudio.com) with the [Dev Containers Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) installed, please set your machine up with those. As of writing, we used the following: + +- Docker Version: 20.10.24 +- VS Code Version: 1.79.0 +- Dev Container Extension Version: v0.295.0 + +### Open ACA-Py in the devcontainer + +To open ACA-Py in a devcontainer, we open the *root* of this repository. We can open in 2 ways: + +1. Open Visual Studio Code, and use the Command Palette and use `Dev Containers: Open Folder in Container...` +2. Open Visual Studio Code and `File|Open Folder...`, you should be prompted to `Reopen in Container`. + +*NOTE* follow any prompts to install `Python Extension` or reload window for `Pylance` when first building the container. + +#### devcontainer.json + +When the [.devcontainer/devcontainer.json](.devcontainer/devcontainer.json) is opened, you will see it building... it is building a Python 3.9 image (bash shell) and loading it with all the ACA-Py requirements (and black). Since this is a Docker container, we will also open ports `9060` and `9061`, allowing you to run/debug ACA-Py with those ports available to your `localhost` (more on those later). We also load a few Visual Studio settings (for running Pytests and formatting with Flake and Black). + +In VS Code, open a Terminal, you should be able to run the following commands: + +``` +python -m aries_cloudagent -v +cd aries_cloudagent +flake8 --max-line-length=90 --exclude=*/tests/** --extend-ignore=D202,W503 --per-file-ignores=*/__init__.py:D104 +black . --check +``` + +The first command should show you that `aries_cloudagent` module is loaded (ACA-Py). The others are examples of code quality checks that ACA-Py does on commits (if you have [`precommit`](https://pre-commit.com) installed) and Pull Requests. + +## Debugging + +To better illustrate debugging pytests and ACA-Py runtime code, let's add some run/debug configurations to VS Code. If you have your own `launch.json` and `settings.json`, please cut and paste what you want/need. + +``` +cp -R .vscode-sample .vscode +``` + +This will add a `launch.json`, `settings.json` and an ACA-Py configuration file: `multitenant.yml`. + +### Pytest + +Pytest is installed and almost ready; however, we must build the test list. In the Command Palette, `Test: Refresh Tests` will scan and find the tests. + +See [Python Testing](https://code.visualstudio.com/docs/python/testing) for more details, and [Test Commands](https://code.visualstudio.com/docs/python/testing#_test-commands) for usage. + +*IMPORTANT*: our pytests include coverage, which will prevent the [debugger from working](https://code.visualstudio.com/docs/python/testing#_debug-tests). One way around this would be to have a `.vscode/settings.json` that says not to use coverage (see above). This will allow you to set breakpoints in the pytest and code under test and use commands such as `Test: Debug Tests in Current File` to start debugging. + + +### ACA-Py + +Above, we added some run/debug configurations, one of which is to run our ACA-Py source code so we can debug it. + +In `launch.json` you will see: + +``` + { + "name": "Run/Debug ACA-Py", + "type": "python", + "request": "launch", + "module": "aries_cloudagent", + "justMyCode": true, + "args": [ + "start", + "--arg-file=${workspaceRoot}/.vscode/multitenant.yml" + ] + }, +``` + +To run your ACA-Py code in debug mode, go to the `Run and Debug` view, select "Run/Debug ACA-Py" and click `Start Debugging (F5)`. + +This will start your source code as a running ACA-Py instance, all configuration is in the `multitenant.yml` file. This is just a sample of a configuration, and we chose multi-tenancy so we can easily create multiple wallets/agents and have them interact. Note that we are not using a database and are joining the ` http://test.bcovrin.vonx.io` ledger. Feel free to change to a local VON Network (by default, it would be `http://host.docker.internal:9000`) or another ledger. This is purposefully a very simple configuration. + +Remember those ports we exposed in `devcontainer`? You can open a browser to `http://localhost:9061/api/doc` and see your Admin Console Swagger. Set some breakpoints and hit some endpoints, and start debugging your source code. + +For example, open `aries_cloudagent/admin/server.py` and set a breakpoint in `async def status_handler(self, request: web.BaseRequest):`, then call [`GET /status`](http://localhost:9061/api/doc#/server/get_status) in the Admin Console and hit your breakpoint. + +## Next Steps + +At this point, you now have a development environment where you can add pytests, add ACA-Py code and run and debug it all. Be aware there are limitations with `devcontainer` and other docker networks. You may need to adjust other docker-compose files not to start their own networks, and you may need to reference containers using `host.docker.internal`. This isn't a panacea but should get you going in the right direction and provide you with some development tools.