| Branch | Status |
|---|---|
| develop | |
| master |
A Microservice which stores drawings that are created in the mapviewer on s3. A detailed descriptions of the endpoints can be found in the OpenAPI Spec.
| Environments | URL |
|---|---|
| DEV | https://sys-public.dev.bgdi.ch/api/kml/ |
| INT | https://sys-public.int.bgdi.ch/api/kml/ |
| PROD | https://public.geo.admin.ch/api/kml/ |
This service uses SemVer as versioning scheme. The versioning is automatically handled by .github/workflows/main.yml file.
See also Git Flow - Versioning for more information on the versioning guidelines.
The Make targets assume you have python3.11, pipenv, bash, curl, tar, docker and docker-compose-plugin installed.
First, you'll need to clone the repo
git clone git@github.com:geoadmin/service-kmlIf needed create and adapt your local copy of .env.default to your needs. Afterwards source it (otherwise default values will be used by the service) and let ENV_FILE point to your local env file:
cp .env.default .env.local
source .env.local
export ENV_FILE=.env.localThen, you can run the setup target to ensure you have everything needed to develop, test and serve locally
make setupThe other services that are used (DynamoDB local and MinIO as local S3 replacement) are wrapped in a docker compose.
Starting DynamoDB local and MinIO is done with a simple
docker compose upin the source root folder. Make sure to run make dev before to ensure the necessary folders .volumes/* are in place. These folders are mounted in the services and allow data persistency over restarts of the containers.
That's it, you're ready to work.
In order to have a consistent code style the code should be formatted using yapf. Also to avoid syntax errors and non
pythonic idioms code, the project uses the pylint linter. Both formatting and linter can be manually run using the
following command:
make format-lintFormatting and linting should be at best integrated inside the IDE, for this look at Integrate yapf and pylint into IDE
Testing if what you developed work is made simple. You have four targets at your disposal. test, serve, gunicornserve, dockerrun
make testThis command run the integration and unit tests.
make serveThis will serve the application through Flask without any wsgi in front.
make gunicornserveThis serve the application using gunicorn and with the path prefix set to /api/kml.
make dockerrunThis will serve the application with the wsgi server, inside a container with the /api/kml path prefix.
Here some curl examples
Note if you run the server with Flask make serve then you need to remove the /api/kml path prefix
# post a kml
curl -X POST http://localhost:5000/api/kml/admin -F kml="@./tests/samples/valid-kml.xml; type=application/vnd.google-earth.kml+xml" -F author="test" -H "Origin: map.geo.admin.ch"
# get the kml metadata
curl http://localhost:5000/api/kml/admin/${KML_ID} -H "Origin: map.geo.admin.ch"
# update the kml file
curl -X PUT http://localhost:5000/api/kml/admin/${KML_ID} -F admin_id=${ADMIN_ID} -F kml="@./tests/samples/updated-kml.xml; type=application/vnd.google-earth.kml+xml" -H "Origin: map.geo.admin.ch"
# delete the kml
curl -X DELETE http://localhost:5000/api/kml/admin/${KML_ID} -F admin_id=${ADMIN_ID} -H "Origin: map.geo.admin.ch"From each github PR that is merged into master or into develop, one Docker image is built and pushed on AWS ECR with the following tag:
vX.X.Xfor tags on mastervX.X.X-beta.Xfor tags on develop
Each image contains the following metadata:
- author
- git.branch
- git.hash
- git.dirty
- version
These metadata can be read with the following command
make dockerlogin
docker pull 974517877189.dkr.ecr.eu-central-1.amazonaws.com/service-kml:develop.latest
# NOTE: jq is only used for pretty printing the json output,
# you can install it with `apt install jq` or simply enter the command without it
docker image inspect --format='{{json .Config.Labels}}' 974517877189.dkr.ecr.eu-central-1.amazonaws.com/service-kml:develop.latest | jqYou can also check these metadata on a running container as follows
docker ps --format="table {{.ID}}\t{{.Image}}\t{{.Labels}}"To build a local docker image tagged as service-kml:local-${USER}-${GIT_HASH_SHORT} you can
use
make dockerbuildTo push the image on the ECR repository use the following two commands
make dockerlogin
make dockerpushThis service is to be deployed to the Kubernetes cluster. See geoadmin/infra-kubernetes/services/service-kml/README.md.
The service is configured by Environment Variable:
| Env | Default | Description |
|---|---|---|
| LOGGING_CFG | logging-cfg-local.yml | Logging configuration file |
| AWS_S3_BUCKET_NAME | AWS S3 bucket name used to save and serve KML files | |
| AWS_S3_REGION_NAME | AWS region name of the S3 service | |
| AWS_S3_ENDPOINT_URL | None |
AWS S3 Endpoint URL. This can be used to use another S3 service as the one from AWS (e.g. local minio) |
| AWS_DB_REGION_NAME | AWS DynamoDB region name | |
| AWS_DB_TABLE_NAME | AWS DynamoDB table name | |
| AWS_DB_ENDPOINT_URL | None |
AWS DynamoDB Endpoint URL. This can be used to use another DynamoDB service as the one from AWS (e.g. local DynamoDB) |
| KML_STORAGE_HOST_URL | None |
KML storage host. This can be used if the S3 storage is not on the same host as the service (e.g. local development where service runs on localhost:5000 and storage on localhost:9090 |
| KML_MAX_SIZE | 2 * 1024 * 1024 |
KML max size file allowed in bytes |
| ALLOWED_DOMAINS | .* |
Comma separated of domain pattern allowed in Origin header |
| KML_FILE_CACHE_CONTROL | no-store, max-age=0 |
Cache Control header set in answer when serving the KML file. |
| FORWARED_ALLOW_IPS | * |
Sets the gunicorn forwarded_allow_ips. See Gunicorn Doc. This setting is required in order to secure_scheme_headers to work. |
| FORWARDED_PROTO_HEADER_NAME | X-Forwarded-Proto |
Sets gunicorn secure_scheme_headers parameter to {${FORWARDED_PROTO_HEADER_NAME}: 'https'}. This settings is required in order to generate correct URLs in the service responses. See Gunicorn Doc. |
| SCRIPT_NAME | '' |
If the service is behind a reverse proxy and not served at the root, the route prefix must be set in SCRIPT_NAME. |
| CACHE_CONTROL | no-cache, no-store, must-revalidate |
Cache Control header value of the GET endpoint(s) |
| CACHE_CONTROL_4XX | public, max-age=3600 |
Cache Control header for 4XX responses |
| GUNICORN_WORKER_TMP_DIR | /tmp/gunicorn_workers |
Gunicorn worker tmp directory. |
| GUNICORN_KEEPALIVE | 2 |
The keepalive setting passed to gunicorn. |