Skip to content

Commit fc9a8dd

Browse files
committed
Initial commit
1 parent 0723d31 commit fc9a8dd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1937
-1
lines changed

.idea/.gitignore

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1818
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21-
SOFTWARE.
21+
SOFTWARE.

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Webhook forwarder
2+
3+
This app allows forwarding of HTTP payloads to one or more endpoints.
4+
5+
See [documentation](./documentation/index.md) for more information

common-services.yml

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
version: '3.7'
2+
3+
services:
4+
5+
django:
6+
env_file:
7+
- ./.env.django
8+
user: '${UID}:${GID}'
9+
command: python manage.py runserver 0.0.0.0:8000
10+
volumes:
11+
- ./src/backend/:/home/app/django/
12+
- ./logs:/home/app/logs
13+
- .:/srv/project_root/
14+
15+
django-dramatiq-worker:
16+
env_file:
17+
- ./.env.django
18+
user: '${UID}:${GID}'
19+
volumes:
20+
- ./src/backend/:/home/app/django/
21+
- ./logs:/home/app/logs
22+
command: python manage.py rundramatiq --processes 2 --threads 1
23+
24+
django-periodiq-worker:
25+
env_file:
26+
- ./.env.django
27+
user: '${UID}:${GID}'
28+
volumes:
29+
- ./src/backend/:/home/app/django/
30+
- ./logs:/home/app/logs
31+
command: python manage.py runperiodiq
32+
33+
postgres:
34+
image: postgres:16-alpine
35+
env_file:
36+
- ./.env.django.db
37+
volumes:
38+
- postgres_data:/var/lib/postgresql/data/
39+
40+
pg-backups:
41+
image: prodrigestivill/postgres-backup-local
42+
env_file:
43+
- ./.env.django.db
44+
restart: always
45+
healthcheck:
46+
test: ['CMD', 'curl', '--fail', 'http://localhost:8080/']
47+
interval: 10s
48+
timeout: 10s
49+
retries: 5
50+
volumes:
51+
- ./pgbackups:/backups
52+
environment:
53+
POSTGRES_HOST: postgres
54+
POSTGRES_EXTRA_OPTS: -Z6 --schema=public --blobs
55+
BACKUP_KEEP_MONTHS: 2
56+
57+
rabbitmq:
58+
image: rabbitmq:3.11
59+
healthcheck:
60+
test: ['CMD', 'rabbitmq-diagnostics', '-q', 'ping']
61+
volumes:
62+
- rabbitmq_data:/data
63+
64+
# nginx:
65+
# image: nginx:1.23.0
66+
# volumes:
67+
# - ./nginx-templates:/etc/nginx/templates
68+
# environment:
69+
# - COMPOSE_PROJECT_NAME=${COMPOSE_PROJECT_NAME}
70+
71+
volumes:
72+
postgres_data:
73+
rabbitmq_data:

docker-compose.deployment.yml

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Config for deployment (tst/acc/prd)
2+
services:
3+
_django-image_build:
4+
image: django-deployment-image
5+
env_file:
6+
- ./.env.django
7+
user: '${UID}:${GID}'
8+
build:
9+
context: ./src/backend
10+
dockerfile: Dockerfile.deployment
11+
args:
12+
- UID=${UID}
13+
- GID=${GID}
14+
15+
command: [ 'echo', 'build completed' ] # any linux command which directly terminates.
16+
17+
django:
18+
image: django-deployment-image
19+
extends:
20+
file: common-services.yml
21+
service: django
22+
command: gunicorn wsgi:application --bind 0.0.0.0:8000
23+
restart: unless-stopped
24+
depends_on:
25+
- _django-image_build
26+
- postgres
27+
- rabbitmq
28+
ports:
29+
- ${DJANGO_HTTP_PORT:-8000}:8000
30+
volumes:
31+
- ./data/staticfiles:/home/app/staticfiles
32+
- ./data/mediafiles:/home/app/mediafiles
33+
34+
django-dramatiq-worker:
35+
image: django-deployment-image
36+
extends:
37+
file: common-services.yml
38+
service: django-dramatiq-worker
39+
restart: unless-stopped
40+
depends_on:
41+
- postgres
42+
- _django-image_build
43+
- rabbitmq
44+
45+
postgres:
46+
extends:
47+
file: common-services.yml
48+
service: postgres
49+
restart: unless-stopped
50+
51+
pg-backups:
52+
extends:
53+
file: common-services.yml
54+
service: pg-backups
55+
links:
56+
- postgres
57+
depends_on:
58+
- postgres
59+
environment:
60+
POSTGRES_HOST: postgres
61+
BACKUP_KEEP_DAYS: 7
62+
BACKUP_KEEP_WEEKS: 2
63+
BACKUP_KEEP_MONTHS: 1
64+
65+
rabbitmq:
66+
hostname: rabbitmq
67+
extends:
68+
file: common-services.yml
69+
service: rabbitmq
70+
restart: unless-stopped
71+
ulimits:
72+
nofile:
73+
soft: 65536
74+
hard: 65536
75+
76+
77+
78+
volumes:
79+
postgres_data:
80+
rabbitmq_data:

docker-compose.yml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Config for development
2+
services:
3+
_django-image_build:
4+
image: django-dev-image
5+
build:
6+
context: ./src/backend
7+
command: ['echo', 'build completed'] # any linux command which directly terminates.
8+
9+
django:
10+
image: django-dev-image
11+
extends:
12+
file: common-services.yml
13+
service: django
14+
command: sleep infinity
15+
# command: gunicorn wsgi:application --bind 0.0.0.0:8000
16+
depends_on:
17+
- postgres
18+
- _django-image_build
19+
- rabbitmq
20+
ports:
21+
- ${DJANGO_HTTP_PORT:-8000}:8000
22+
23+
postgres:
24+
extends:
25+
file: common-services.yml
26+
service: postgres
27+
ports:
28+
- 127.0.0.1:${POSTGRES_PORT:-5432}:5432
29+
restart: unless-stopped
30+
31+
rabbitmq:
32+
extends:
33+
file: common-services.yml
34+
service: rabbitmq
35+
restart: unless-stopped
36+
ports:
37+
- 5672:5672
38+
39+
volumes:
40+
postgres_data:
41+
rabbitmq_data:

documentation/development.md

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Deployment on test or production environments
2+
3+
## Development in docker container
4+
5+
Copy env templates:
6+
7+
- Copy `.env-template` to `.env`
8+
- Copy `.env.django-template` to `.env.django`
9+
- Copy `.env.django.db-template` to `.env.django.db`
10+
11+
Adjust settings in env files as needed.
12+
13+
Run the docker development container:
14+
15+
docker-compose up -d
16+
17+
(You can use `--build` to force rebuilding the docker container)
18+
19+
There are two ways to debug django inside the container.
20+
21+
1: Debug using by connecting to the remote docker and just debug a django project as usual.
22+
E.g. in Visual Studio Code: install extension: Visual Studio Code Remote - Containers
23+
Then connect to the remote md-api-dvl_django_1 container.
24+
You can now start a debugging session as usual
25+
26+
Note that you can add the /srv/project_root folder as workspace folder so you can use
27+
the git functionality in the IDE as well
28+
29+
2: The one that isn't all that great uses debugpy. You can read more about it here:
30+
To debug a running container, see: [Debugging a Containerized Django App in VS Code](https://testdriven.io/blog/django-debugging-vs-code/)
31+
32+
## Development in using local python
33+
34+
Set-up and enable [pyenv](https://github.com/pyenv/pyenv#getting-pyenv) and
35+
[pyenv-virtual-env](https://github.com/pyenv/pyenv-virtualenv#installation):
36+
37+
pyenv install --list
38+
pyenv install 3.11.7
39+
pyenv virtualenv 3.11.7 webhook_forwarder
40+
pyenv local webhook_forwarder__3.11.7
41+
42+
Clone git repo. For any other env than development make sure ssh agent
43+
forwarding is enabled.
44+
45+
git clone [email protected]:pu/webhook_forwarder.git
46+
cd webhook_forwarder/src
47+
48+
Create `.env` file based on `.env-sample`
49+
50+
## Seting up dev env
51+
52+
When django is used locally (not in a docker env) the `.env` file is used by Django.
53+
54+
Rename `.env-template` to `.env` and adjust settings as needed.
55+
56+
Install dependencies:
57+
58+
pip install -r requirements/dev.txt
59+
60+
Run migrations to initialize the database:
61+
62+
python manage.py migrate
63+
64+
Start development server:
65+
66+
python manage.py runserver
67+
68+
### Dramatiq message queue / RabbitMQ
69+
70+
First start rabbitmq in a docker container:
71+
72+
docker-compose up -d rabbitmq
73+
74+
Start the dramatiq worker:
75+
76+
./manage.py rundramatiq --threads 2 --processes 1 --reload
77+
78+
Start the periodiq (cron replacement) scheduler:
79+
80+
./manage.py runperiodiq
81+
82+
Task queue progress is available in Django admin
83+
[http://localhost:8000/admin/django_dramatiq/task/](http://localhost:8000/admin/django_dramatiq/task/).
84+
85+

documentation/how-to-use.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# How to use this app
2+
3+
This webhook forwarder can be used to forward webhook payloads to multiple endpoints.
4+
This can be useful when developing and testing. For example when a payment provider has the
5+
limitation that only one webhook can be set for testing. Use an URL from this app to forward
6+
the webhook payload to both the test enviroment and development environment (using a local tunnel).
7+
8+
## Set-up in Django admin
9+
10+
First add a 'webhook identifier'. For example if this webhook will be used for the sandbox environment
11+
for Acme Payments, name it `Acme Payments (sandbox env)`.
12+
13+
In the same form when adding or editing a 'webhook identifier', one or more URLs can be added to which
14+
the webhook payload should be forwarded. To test you could use a URL from https://webhook.site.
15+
16+
The name enetered earlier will be converted to a slug. The URL path will look like:
17+
18+
/api/forwarder/1.0/webhooks/acme-payments-sandbox-env
19+
20+
Finally, add the URL to the service which fires the webhook. When a request is sent to the above, the
21+
app will forward the request to the URLs set in the webhook identifier.
22+
23+
## Open API docs caveat
24+
25+
Open API docs are available at `/api/docs`. However it is not possible to set a http payload via
26+
this interface. As Django Ninja is geared towards JSON and plain-text data schemas are not possible.
27+
28+
## Local tunnel
29+
30+
A tunnelling solution can be used to set-up a local tunnel from your development env to this app.
31+
32+
For example using local tunnel:
33+
34+
npm install -g localtunnel
35+
36+
lt --port 8000 --subdomain example-subdomain
37+
38+
Or any of the tunneling solutions listed here: https://github.com/anderspitman/awesome-tunneling

documentation/index.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# PU Multipass Documentation
2+
3+
Django app to forward webhook payloads to one or more endpoints
4+
5+
## Table of contents
6+
7+
- [Development](./development.md)
8+
- [How to use](./how-to-use.md)
9+

env-template

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#--- Docker compose settings ---------------------------------------------------
2+
# As we are using rootless docker, default UID/GID to 0
3+
UID=0
4+
GID=0
5+
6+
DJANGO_HTTP_PORT=8080
7+
8+
#--- Enable below for local development ----------------
9+
# Using postgres container, but without django container
10+
DATABASE_URL=postgres://postgres:[email protected]:5488/postgres
11+
POSTGRES_PORT=5488
12+
SECRET_KEY=supersecret
13+
DJANGO_DEBUG=True
14+
15+
#--- Enable below for test or production ---------------------------------------
16+
17+
# COMPOSE_FILE=docker-compose.deployment.yml
18+
COMPOSE_PROJECT_NAME=multipass-[dev|tst|acc|prd]

env.django-template

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#--- Settings for Django Docker container -------------------------------------
2+
3+
ENVIRONMENT=production
4+
5+
DJANGO_SETTINGS_MODULE="settings.deployment"
6+
DJANGO_DEBUG=False
7+
8+
ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0,example.com
9+
CSRF_TRUSTED_ORIGINS=http://localhost:8080,http://127.0.0.1:8080,http://0.0.0.0:8080,https://example.com
10+
11+
# import secrets; print(secrets.token_hex(25))
12+
SECRET_KEY=my-secret-key
13+
SENTRY_URL=
14+
15+
# Host (`postgres:5342`) must stay the same, as this points to postgres
16+
# container which is only internally (within docker compose) available on
17+
# the `postgres` hostname
18+
DATABASE_URL=postgres://postgres:postgres@postgres:5432/postgres
19+
20+
# Host (`rabbitmq:5672`) must stay the same
21+
DRAMATIQ_BROKER_URL=amqp://rabbitmq:5672?heartbeat=0
22+
23+
24+

0 commit comments

Comments
 (0)