diff --git a/.devcontainer/.vscode/launch.json b/.devcontainer/.vscode/launch.json new file mode 100644 index 00000000..8aa448c3 --- /dev/null +++ b/.devcontainer/.vscode/launch.json @@ -0,0 +1,100 @@ +{ + // 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": "GeoNode", + "type": "debugpy", + "request": "launch", + "args": [ + "runserver", + "0.0.0.0:8000" + ], + "env": { + "ASYNC_SIGNALS": "True", + }, + "django": true, + "autoStartBrowser": false, + "program": "${workspaceFolder}/project/manage.py", + "justMyCode": false + }, + { + "name": "Celery Worker", + "type": "debugpy", + "request": "launch", + "args": [ + "-A", + "geonode.celery_app:app", + "worker", + "--loglevel=DEBUG", + "--without-mingle", + "--without-gossip", + "-Ofair", + "-E", + "--statedb=worker.state", + "--concurrency=2", + "-n", + "worker@%h", + "-X", + "harvesting" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}/project:/usr/src/django-geonode-mapstore-client" + }, + "cwd": "${workspaceFolder}", + "autoStartBrowser": false, + "program": "${workspaceFolder}/venv/bin/celery", + "justMyCode": false + }, + { + "name": "Celery Beat", + "type": "debugpy", + "request": "launch", + "args": [ + "-A", + "geonode.celery_app:app", + "beat", + "--loglevel=DEBUG", + "--scheduler=celery.beat:PersistentScheduler", + "--pidfile=/tmp/celerybeat.pid" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}/project:/usr/src/django-geonode-mapstore-client" + }, + "cwd": "${workspaceFolder}", + "autoStartBrowser": false, + "program": "${workspaceFolder}/venv/bin/celery", + "justMyCode": false + }, + { + "name": "Celery Harvesters", + "type": "debugpy", + "request": "launch", + "args": [ + "-A", + "geonode.celery_app:app", + "worker", + "--loglevel=DEBUG", + "--without-mingle", + "--without-gossip", + "-Ofair", + "-E", + "--concurrency=2", + "-n", + "harvesting_worker@%h", + "-Q", + "harvesting" + ], + "env": { + "PYTHONPATH": "${workspaceFolder}/project:/usr/src/django-geonode-mapstore-client" + }, + "cwd": "${workspaceFolder}", + "autoStartBrowser": false, + "program": "${workspaceFolder}/venv/bin/celery", + "justMyCode": false + } + ] +} \ No newline at end of file diff --git a/.devcontainer/.vscode/settings.json b/.devcontainer/.vscode/settings.json new file mode 100644 index 00000000..654d48e5 --- /dev/null +++ b/.devcontainer/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "python.defaultInterpreterPath": "/usr/src/venv/bin/python", + "python.analysis.extraPaths": [ + "${workspaceFolder}/project", + "${workspaceFolder}/geonode", + "${workspaceFolder}/geonode_mapstore_client", + ] +} \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..3e8f2452 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,60 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: +// https://github.com/microsoft/vscode-dev-containers/tree/v0.194.0/containers/docker-existing-docker-compose +// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. +{ + "name": "Django Container", + + // Update the 'dockerComposeFile' list if you have more compose files or use different names. + // The .devcontainer/docker-compose.yml file contains any overrides you need/want to make. + "dockerComposeFile": [ + "../docker-compose.yml", + "./docker-compose.yml" + ], + + // The 'service' property is the name of the service for the container that VS Code should + // use. Update this value and .devcontainer/docker-compose.yml to the real service name. + "service": "django", + + // The optional 'workspaceFolder' property is the path VS Code should open by default when + // connected. This is typically a file mount in .devcontainer/docker-compose.yml + "workspaceFolder": "/usr/src", + + // Set *default* container specific settings.json values on container create. + "customizations": { + "vscode": { + "settings": { + "terminal.integrated.profiles.linux": { + "/bin/bash": { + "path": "/bin/bash", + "args": [ + "-l" + ] + } + }, + "terminal.integrated.defaultProfile.linux": "bash", + "python.defaultInterpreterPath": "/usr/src/venv/bin/python", + "python.terminal.activateEnvironment": true, + "python.formatting.provider": "black" + }, + + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-python.python" + ] + } + } + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + + // Uncomment the next line if you want start specific services in your Docker Compose config. + // "runServices": [], + + // Uncomment the next line if you want to keep your containers running after VS Code shuts down. + // "shutdownAction": "none", + + // Uncomment the next line to run commands after the container is created - for example installing curl. + // "postCreateCommand": "apt-get update && apt-get install -y curl", + + // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root. + // "remoteUser": "vscode" +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..4522b9e8 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,18 @@ +services: + + django: + volumes: + - './src:/usr/src/project' + - './.devcontainer/.vscode:/usr/src/.vscode' + - statics:/mnt/volumes/statics + - geoserver-data-dir:/geoserver_data/data + - backup-restore:/backup_restore + - data:/data + - tmp:/tmp + healthcheck: + test: "echo 'Alive'" + entrypoint: ["/usr/src/project/entrypoint.sh"] + command: sleep infinity + celery: + entrypoint: ["/usr/src/project/entrypoint.sh"] + command: sleep infinity diff --git a/.devcontainer/docker.sh b/.devcontainer/docker.sh new file mode 100755 index 00000000..9f53030f --- /dev/null +++ b/.devcontainer/docker.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -o allexport +source ../.env +set +o allexport +docker compose -f ../docker-compose.yml -f ./docker-compose.yml "$@" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 4137f8f4..041e4c0a 100644 --- a/.gitignore +++ b/.gitignore @@ -66,7 +66,7 @@ development.db-journal local_settings.py .idea/ -.vscode/ +/.vscode/ .vagrant/ Vagrantfile /.env diff --git a/README.md b/README.md index cc1ceca7..d8bf8796 100644 --- a/README.md +++ b/README.md @@ -215,3 +215,47 @@ POSTGRESQL_MAX_CONNECTIONS=200 ``` In this case PostgreSQL will run accepting 200 maximum connections. + +## Developing with Dev Containers in VS Code + +This repo includes a .devcontainer folder with the condigurations to run Django and Celery inside a VS Code Dev Container. +A `docker.sh` script aliases the `docker compose` command with the pre-configured arguments to use the customized compose files. + +You can run the Dev Container with the following commands: + +```bash +cd .devcontainer +chmod +x docker.sh +./docker.sh build +.docker.sh up -d +``` + +The Django and the Celery containers will be started **without** running the Django and Celery processes. They can be started manually inside the dev container. The container is autopopulated with VS Code development extensions for Python and a list of pre-configured luanch configurations (for Django and Celery). + +Within VS Code open the command palette with `Ctrl+P` and run `Dev Container: Reopen in Container`. VS Code will recognize the presence of the two dev container, and will allow to reopen the current window inside the container's workspace. +Wait a few seconds to let VS Code setup the dev extensions, then you should see the launch configurations. + +To simplify the debugging of GeoNode and the GeoNode client, these modules can be installed as editable (PEP-660) with the following commands: + +```bash +pip install -e git+https://github.com/GeoNode/geonode.git@master#egg=geonode --src=/usr/src +pip install -e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client --src=/usr/src +``` + +The modules will be isntalled under `/usr/src` and so at te root of the VS Code workspace. +Notice that at the time of writing Pylance can't resolve PEP-660 editable installs. For this reason the `.vscode/settings.py` contain extrPaths for the modules. + +### Running Django +The `GeoNode` launch configuration for Django sets the `ASYNC_SIGNALS` env variable to False. This way GeoNode can be developed and debugged in sync mode, without Celery. +If you want to test Django in async mode, you can switch this variable to `True` and tun Celery (see below). + +Running the Debug sessions for Django will start Django with its internal development server. + +### Running Celery +Celery exectutions requires luanching three Debug processes: + + - `Celery Worker`: the generic worker process + - `Celery Beat`: the scheduler + - `Celery Harvesters`: The worker dedicated to the harvesters + +You can also remove the `-X harvesting` argument inside the Celery Worker launch configuration to have also the harvesters running in the same worker. this way you don't need to run the Beat and the Celery Harvesters processes.