diff --git a/.env.sample b/.env.sample index bbf9cc10..3a86310a 100644 --- a/.env.sample +++ b/.env.sample @@ -1,4 +1,31 @@ -COMPOSE_PROJECT_NAME={{project_name}} +COMPOSE_PROJECT_NAME=geonode + + +## +## DOCKER CONFIGURATION + +# (optional) URL with trailing slash +DOCKER_REGISTRY= +# (optional) with trailing slash e.g. sample/ or orga/ +DOCKER_REPOSITORY= +PROJECT_VERSION="1.0" +GEONODE_BASE_IMAGE_VERSION="4.1.2" +# version should make transparent which GeoNode version +# it can be used in, e.g. '4.1.2-1.25.1' +NGINX_BASE_IMAGE_VERSION="1.25.1" +# TODO Please point to a proper base version here +LETSENCRYPT_BASE_IMAGE_VERSION=latest +# version should make transparent which GeoNode version +# it can be used in, e.g. '4.1.2-2.23.0' +GEOSERVER_BASE_IMAGE_VERSION="2.23.0" +# version should make transparent which GeoNode version +# it can be used in, e.g. '4.1.2-2.23.0' +GEOSERVER_DATA_BASE_IMAGE_VERSION="2.23.0" +# version should make transparent which GeoNode version +# it can be used in, e.g. '4.1.2-13' +POSTGRES_BASE_IMAGE_VERSION="13" + + # See https://github.com/containers/podman/issues/13889 # DOCKER_BUILDKIT=0 DOCKER_ENV=production @@ -14,7 +41,7 @@ INVOKE_LOG_STDOUT=true # LANGUAGE_CODE=it-it # LANGUAGES=(('en-us','English'),('it-it','Italiano')) -DJANGO_SETTINGS_MODULE={{project_name}}.settings +DJANGO_SETTINGS_MODULE=geonode.settings GEONODE_INSTANCE_NAME=geonode # ################# @@ -22,18 +49,18 @@ GEONODE_INSTANCE_NAME=geonode # ################# POSTGRES_USER=postgres POSTGRES_PASSWORD={pgpwd} -GEONODE_DATABASE={{project_name}} -GEONODE_DATABASE_USER={{project_name}} +GEONODE_DATABASE=geonode +GEONODE_DATABASE_USER=geonode GEONODE_DATABASE_PASSWORD={dbpwd} -GEONODE_GEODATABASE={{project_name}}_data -GEONODE_GEODATABASE_USER={{project_name}}_data +GEONODE_GEODATABASE=geonode_data +GEONODE_GEODATABASE_USER=geonode_data GEONODE_GEODATABASE_PASSWORD={geodbpwd} GEONODE_DATABASE_SCHEMA=public GEONODE_GEODATABASE_SCHEMA=public DATABASE_HOST=db DATABASE_PORT=5432 -DATABASE_URL=postgis://{{project_name}}:{dbpwd}@db:5432/{{project_name}} -GEODATABASE_URL=postgis://{{project_name}}_data:{geodbpwd}@db:5432/{{project_name}}_data +DATABASE_URL=postgis://geonode:{dbpwd}@db:5432/geonode +GEODATABASE_URL=postgis://geonode_data:{geodbpwd}@db:5432/geonode_data GEONODE_DB_CONN_MAX_AGE=0 GEONODE_DB_CONN_TOUT=5 DEFAULT_BACKEND_DATASTORE=datastore diff --git a/.override_dev_env.sample b/.override_dev_env.sample deleted file mode 100644 index b2d46103..00000000 --- a/.override_dev_env.sample +++ /dev/null @@ -1,103 +0,0 @@ -export DEBUG=True - -export SECRET_KEY="myv-y4#7j-d*p-__@j#*3z@!y24fz8%^z2v6atuy4bo9vqr1_a" - -export SITEURL=http://localhost:8000/ -export ALLOWED_HOSTS="['localhost',]" - -export GEONODE_INSTANCE_NAME=geonode -export DJANGO_SETTINGS_MODULE={{project_name}}.settings -export GEONODE_DATABASE={{project_name}} -export GEONODE_DATABASE_PASSWORD=geonode -export GEONODE_GEODATABASE={{project_name}}_data -export GEONODE_GEODATABASE_PASSWORD=geonode - -export DATABASE_URL=postgis://{{project_name}}:geonode@localhost:5432/{{project_name}} -export GEODATABASE_URL=postgis://{{project_name}}_data:geonode@localhost:5432/{{project_name}}_data -export DEFAULT_BACKEND_DATASTORE=datastore - -export GEOSERVER_WEB_UI_LOCATION=http://localhost:8080/geoserver/ -export GEOSERVER_PUBLIC_LOCATION=http://localhost:8080/geoserver/ -export GEOSERVER_LOCATION=http://localhost:8080/geoserver/ -export GEOSERVER_ADMIN_USER=admin -export GEOSERVER_ADMIN_PASSWORD=geoserver - -export OGC_REQUEST_TIMEOUT=30 -export OGC_REQUEST_MAX_RETRIES=1 -export OGC_REQUEST_BACKOFF_FACTOR=0.3 -export OGC_REQUEST_POOL_MAXSIZE=10 -export OGC_REQUEST_POOL_CONNECTIONS=10 - -export DEFAULT_BACKEND_UPLOADER=geonode.importer -export TIME_ENABLED=True -export MOSAIC_ENABLED=False - -export ADMIN_PASSWORD=admin -export ADMIN_EMAIL=admin@localhost - -export EMAIL_ENABLE=False -export DJANGO_EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend -export DJANGO_EMAIL_HOST=localhost -export DJANGO_EMAIL_PORT=25 -export DJANGO_EMAIL_HOST_USER= -export DJANGO_EMAIL_HOST_PASSWORD= -export DJANGO_EMAIL_USE_TLS=False -export DJANGO_EMAIL_USE_SSL=False -export DEFAULT_FROM_EMAIL="GeoNode " - -export LOCKDOWN_GEONODE=False -export X_FRAME_OPTIONS=SAMEORIGIN -export SESSION_EXPIRED_CONTROL_ENABLED=True -export DEFAULT_ANONYMOUS_VIEW_PERMISSION=True -export DEFAULT_ANONYMOUS_DOWNLOAD_PERMISSION=True - -export CORS_ALLOW_ALL_ORIGINS=True -export GEOSERVER_CORS_ENABLED=True -export GEOSERVER_CORS_ALLOWED_ORIGINS=* -export GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS -export GEOSERVER_CORS_ALLOWED_HEADERS=* - -export ACCOUNT_OPEN_SIGNUP=True -export ACCOUNT_EMAIL_REQUIRED=True -export ACCOUNT_APPROVAL_REQUIRED=False -export ACCOUNT_CONFIRM_EMAIL_ON_GET=False -export ACCOUNT_EMAIL_VERIFICATION=none -export ACCOUNT_EMAIL_CONFIRMATION_EMAIL=False -export ACCOUNT_EMAIL_CONFIRMATION_REQUIRED=False -export ACCOUNT_AUTHENTICATION_METHOD=username_email - -export OAUTH2_API_KEY= -export OAUTH2_CLIENT_ID=Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV -export OAUTH2_CLIENT_SECRET=rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3 - -export API_LOCKDOWN=False -export TASTYPIE_APIKEY= - -export CACHE_BUSTING_STATIC_ENABLED=False - -export MAX_DOCUMENT_SIZE=2 -export CLIENT_RESULTS_LIMIT=5 -export API_LIMIT_PER_PAGE=1000 - -export GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY=mapstore -export MAPBOX_ACCESS_TOKEN= -export BING_API_KEY= -export GOOGLE_API_KEY= - -export MONITORING_ENABLED=False -export MONITORING_DATA_TTL=365 -export USER_ANALYTICS_ENABLED=True -export USER_ANALYTICS_GZIP=True -export CENTRALIZED_DASHBOARD_ENABLED=False -export MONITORING_SERVICE_NAME=local-geonode -export MONITORING_HOST_NAME=geonode - -export MODIFY_TOPICCATEGORY=True -export AVATAR_GRAVATAR_SSL=True -export AVATAR_PROVIDERS='avatar.providers.PrimaryAvatarProvider','avatar.providers.GravatarAvatarProvider','avatar.providers.DefaultAvatarProvider' -export EXIF_ENABLED=True -export CREATE_LAYER=True -export FAVORITE_ENABLED=True - -export DEFAULT_MAX_UPLOAD_SIZE=5368709120 -export DEFAULT_MAX_PARALLEL_UPLOADS_PER_USER=5 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index d22dab9a..00000000 --- a/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -FROM geonode/geonode-base:latest-ubuntu-22.10 -LABEL GeoNode development team - -RUN mkdir -p /usr/src/{{project_name}} - -# add bower and grunt command -COPY src /usr/src/{{project_name}}/ -WORKDIR /usr/src/{{project_name}} - -#COPY src/monitoring-cron /etc/cron.d/monitoring-cron -#RUN chmod 0644 /etc/cron.d/monitoring-cron -#RUN crontab /etc/cron.d/monitoring-cron -#RUN touch /var/log/cron.log -#RUN service cron start - -COPY src/wait-for-databases.sh /usr/bin/wait-for-databases -RUN chmod +x /usr/bin/wait-for-databases -RUN chmod +x /usr/src/{{project_name}}/tasks.py \ - && chmod +x /usr/src/{{project_name}}/entrypoint.sh - -COPY src/celery.sh /usr/bin/celery-commands -RUN chmod +x /usr/bin/celery-commands - -COPY src/celery-cmd /usr/bin/celery-cmd -RUN chmod +x /usr/bin/celery-cmd - -# # Install "geonode-contribs" apps -# RUN cd /usr/src; git clone https://github.com/GeoNode/geonode-contribs.git -b master -# # Install logstash and centralized dashboard dependencies -# RUN cd /usr/src/geonode-contribs/geonode-logstash; pip install --upgrade -e . \ -# cd /usr/src/geonode-contribs/ldap; pip install --upgrade -e . - -RUN yes w | pip install --src /usr/src -r requirements.txt &&\ - yes w | pip install -e . - -# Cleanup apt update lists -RUN apt-get autoremove --purge &&\ - apt-get clean &&\ - rm -rf /var/lib/apt/lists/* - -# Export ports -EXPOSE 8000 - -# We provide no command or entrypoint as this image can be used to serve the django project or run celery tasks -# ENTRYPOINT /usr/src/{{project_name}}/entrypoint.sh diff --git a/README.md b/README.md index cc09139c..dcc9e92a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -# {{ project_name|title }} +# My Custom GeoNode Project -GeoNode template project. Generates a django project with GeoNode support. +GeoNode project setup using Docker. +Makes use of pre-built Docker images and prepared for your customizations. ## Table of Contents @@ -18,17 +19,9 @@ GeoNode template project. Generates a django project with GeoNode support. ## Quick Docker Start ```bash - python3.10 -m venv ~/.venvs/project_name - source ~/.venvs/{{ project_name }}/bin/activate - - pip install Django==3.2.* - - mkdir ~/project_name - - GN_VERSION=master - django-admin startproject --template=https://github.com/GeoNode/geonode-project/archive/refs/tags/$GN_VERSION.zip -e py,sh,md,rst,json,yml,ini,env,sample,properties -n monitoring-cron -n Dockerfile project_name ~/project_name + git clone https://github.com/GeoNode/geonode-project/ - cd ~/project_name + cd ~/geonode-project python create-envfile.py ``` `create-envfile.py` accepts the following arguments: @@ -47,12 +40,14 @@ GeoNode template project. Generates a django project with GeoNode support. - `--geodbpwd`: GeoNode data DB user role's password. A random value is set if left empty - `--clientid`: Client id of Geoserver's GeoNode Oauth2 client. A random value is set if left empty - `--clientsecret`: Client secret of Geoserver's GeoNode Oauth2 client. A random value is set if left empty + ```bash docker compose build docker compose up -d ``` -In case you want to customize the Docker images for Geoserver, Nginx, PostGIS, Letsencrypt or the data-dir setup, you can use the `docker-compose-local-builds.yml` override, which builds the images from the `./docker/*` subfolders +In case you want to customize the Docker images for Geoserver, Nginx, PostGIS, Letsencrypt or the data-dir setup, make your changes under `docker//Dockerfile`. +You can also mount your changes via Docker volumes in the `docker-componse.yml` file. ## Developer Workshop diff --git a/Vagrantfile b/Vagrantfile deleted file mode 100644 index 89ca3946..00000000 --- a/Vagrantfile +++ /dev/null @@ -1,70 +0,0 @@ -$geonode_source_path='.' - -$script1 = <<-'SCRIPT' -#!/bin/bash - -export DEBIAN_FRONTEND="noninteractive" - -if [ ! -f '/usr/local/bin/docker-compose' ]; then - sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose -fi - -sudo apt-get install -y \ - apt-transport-https \ - ca-certificates \ - curl \ - gnupg \ - lsb-release -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null -sudo apt-get update -sudo apt-get -y install docker-ce docker-ce-cli containerd.io pwgen python3-pip python3-virtualenv virtualenvwrapper -sudo adduser vagrant docker -SCRIPT - -$script2 = <<-'SCRIPT' -#!/bin/bash -if [ -d "/home/vagrant/generated-project" ]; then - cd /home/vagrant/generated-project - docker-compose down - cd .. - rm -rf /home/vagrant/generated-project - docker volume prune -f -fi -rm -rf /home/vagrant/geonode-project -SCRIPT - -$script3 = <<-'SCRIPT' -sudo reboot -SCRIPT - - -Vagrant.configure(2) do |config| - boxes = { - 'geonode-compose' => 'ubuntu/focal64' - } - machine_id = 0 - - - boxes.each do | key, value | - config.vm.network "forwarded_port", guest: 80, host: 8000 - config.vm.provider "virtualbox" do |v| - v.memory = 8132 - v.cpus = 4 - v.name = "geonode-vm" - end - config.vm.box = "#{value}" - machine_id = machine_id + 1 - config.vm.define "#{key}" do |node| - node.vm.hostname = "#{key}" - config.vm.provision "shell", inline: $script1, privileged: false - config.vm.provision "shell", inline: $script2, run: 'always', privileged: true - config.vm.provision "file", source: $geonode_source_path, destination: "$HOME/geonode-project", run: 'always' - config.vm.provision :shell, path: "generated-project-vagrant-compose.sh", run: 'always', privileged: false - config.vm.provision "shell", inline: $script3, run: 'always', privileged: false - end - end -end \ No newline at end of file diff --git a/Vagrantfile.stack b/Vagrantfile.stack deleted file mode 100644 index f917d3e6..00000000 --- a/Vagrantfile.stack +++ /dev/null @@ -1,58 +0,0 @@ -$geonode_source_path='.' - -$script1 = <<-'SCRIPT' -sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose -sudo chmod +x /usr/local/bin/docker-compose -sudo apt-get -f install \ - apt-transport-https \ - ca-certificates \ - curl \ - gnupg \ - lsb-release -curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -echo \ - "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ - $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null -sudo apt-get update -sudo apt-get -y install docker-ce docker-ce-cli containerd.io pwgen python3-pip python3-virtualenv virtualenvwrapper -sudo adduser vagrant docker -SCRIPT - -$script2 = <<-'SCRIPT' -if [ -d "/home/vagrant/generated-project" ]; then - cd /home/vagrant/generated-project - docker service rm geonode-stack - cd .. - rm -rf /home/vagrant/generated-project -fi -rm -rf /home/vagrant/geonode-project -SCRIPT - -$script4 = <<-'SCRIPT' -sudo reboot -SCRIPT - -Vagrant.configure(2) do |config| - boxes = { - 'geonode-swarm' => 'ubuntu/focal64' - } - machine_id = 0 - boxes.each do | key, value | - config.vm.network "forwarded_port", guest: 80, host: 8888 - config.vm.provider "virtualbox" do |v| - v.memory = 8132 - v.cpus = 4 - v.name = "geonode-vm" - end - config.vm.box = "#{value}" - machine_id = machine_id + 1 - config.vm.define "#{key}" do |node| - node.vm.hostname = "#{key}" - config.vm.provision "shell", inline: $script1, privileged: false - config.vm.provision "shell", inline: $script2, run: 'always', privileged: true - config.vm.provision "file", source: $geonode_source_path, destination: "$HOME/geonode-project", run: 'always' - config.vm.provision :shell, path: "generated-project-vagrant-swarm.sh", run: 'always', privileged: false - config.vm.provision "shell", inline: $script3, run: 'always', privileged: false - end - end -end \ No newline at end of file diff --git a/create-envfile.py b/create-envfile.py old mode 100644 new mode 100755 index e061201a..2fa0f52c --- a/create-envfile.py +++ b/create-envfile.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # -*- coding: utf-8 -*- ######################################################################### # diff --git a/dev_config.yml b/dev_config.yml deleted file mode 100644 index 3fa02cd7..00000000 --- a/dev_config.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geoserver.war" -DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geonode-geoserver-ext-web-app-data.zip" -JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" -WINDOWS: - py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe" - pyproj: "https://pyproj.googlecode.com/files/pyproj-1.9.3.win32-py2.7.exe" - lxml: "https://pypi.python.org/packages/2.7/l/lxml/lxml-3.6.0.win32-py2.7.exe" diff --git a/docker-build.sh b/docker-build.sh deleted file mode 100755 index 64fba5a1..00000000 --- a/docker-build.sh +++ /dev/null @@ -1 +0,0 @@ -docker-compose build --no-cache; docker-compose stop; docker-compose up -d; docker system prune -a \ No newline at end of file diff --git a/docker-compose-local-builds.yml b/docker-compose-local-builds.yml deleted file mode 100644 index 127b5379..00000000 --- a/docker-compose-local-builds.yml +++ /dev/null @@ -1,20 +0,0 @@ -version: '3.9' - - # Nginx is serving django static and media files and proxies to django and geonode - geonode: - build: ./docker/nginx/ - - # Gets and installs letsencrypt certificates - letsencrypt: - build: ./docker/letsencrypt/ - - # Geoserver backend - geoserver: - build: ./docker/geoserver/ - - data-dir-conf: - build: ./docker/data_dir_conf/ - - # PostGIS database. - db: - build: ./docker/postgis/ diff --git a/docker-compose.yml b/docker-compose.yml index 023235c1..012464ec 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,17 +3,25 @@ version: '3.9' # Common Django template for GeoNode and Celery services below x-common-django: &default-common-django - image: ${COMPOSE_PROJECT_NAME}_django:latest + image: ${DOCKER_REGISTRY}${DOCKER_REPOSITORY}${COMPOSE_PROJECT_NAME}_django:${GEONODE_BASE_IMAGE_VERSION}-${PROJECT_VERSION} + build: + context: ./docker/geonode + dockerfile: Dockerfile + args: + - BASE_IMAGE_VERSION=${GEONODE_BASE_IMAGE_VERSION} restart: unless-stopped env_file: - .env volumes: - # - './src:/usr/src/{{project_name}}' + - ./geonode/settings.py:/usr/src/geonode/geonode/settings_override.py + - ./geonode/fixtures:/usr/src/geonode/geonode/fixtures - statics:/mnt/volumes/statics - geoserver-data-dir:/geoserver_data/data - backup-restore:/backup_restore - data:/data - tmp:/tmp + environment: + - DJANGO_SETTINGS_MODULE=geonode.settings_override depends_on: db: condition: service_healthy @@ -23,37 +31,37 @@ services: # Our custom django application. It includes Geonode. django: << : *default-common-django - build: - context: ./ - dockerfile: Dockerfile container_name: django4${COMPOSE_PROJECT_NAME} healthcheck: - test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://django:8000/" + test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://localhost:8000/" start_period: 60s interval: 60s timeout: 10s retries: 2 environment: - IS_CELERY=False - entrypoint: ["/usr/src/{{project_name}}/entrypoint.sh"] - command: "uwsgi --ini /usr/src/{{project_name}}/uwsgi.ini" + entrypoint: ["/usr/src/geonode/entrypoint.sh"] + command: "uwsgi --ini /usr/src/geonode/uwsgi.ini" # Celery worker that executes celery tasks created by Django. celery: << : *default-common-django - image: ${COMPOSE_PROJECT_NAME}_django:latest container_name: celery4${COMPOSE_PROJECT_NAME} depends_on: django: condition: service_healthy environment: - IS_CELERY=True - entrypoint: ["/usr/src/{{project_name}}/entrypoint.sh"] + entrypoint: ["/usr/src/geonode/entrypoint.sh"] command: "celery-cmd" # Nginx is serving django static and media files and proxies to django and geonode geonode: - image: geonode/nginx:1.25.1 + build: + context: ./docker/nginx + dockerfile: Dockerfile + args: + - BASE_IMAGE_VERSION=${NGINX_BASE_IMAGE_VERSION} container_name: nginx4${COMPOSE_PROJECT_NAME} env_file: - .env @@ -63,24 +71,31 @@ services: - "${HTTP_PORT}:80" - "${HTTPS_PORT}:443" volumes: - - nginx-confd:/etc/nginx - nginx-certificates:/geonode-certificates - statics:/mnt/volumes/statics restart: unless-stopped # Gets and installs letsencrypt certificates - letsencrypt: - image: geonode/letsencrypt:latest - container_name: letsencrypt4${COMPOSE_PROJECT_NAME} - env_file: - - .env - volumes: - - nginx-certificates:/geonode-certificates - restart: unless-stopped + # letsencrypt: + # build: + # context: ./docker/letsencrypt + # dockerfile: Dockerfile + # args: + # - BASE_IMAGE_VERSION=${LETSENCRYPT_BASE_IMAGE_VERSION} + # container_name: letsencrypt4${COMPOSE_PROJECT_NAME} + # env_file: + # - .env + # volumes: + # - nginx-certificates:/geonode-certificates + # restart: on-failure # Geoserver backend geoserver: - image: geonode/geoserver:2.23.0 + build: + context: ./docker/geoserver + dockerfile: Dockerfile + args: + - BASE_IMAGE_VERSION=${GEOSERVER_BASE_IMAGE_VERSION} container_name: geoserver4${COMPOSE_PROJECT_NAME} healthcheck: test: "curl -m 10 --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://geoserver:8080/geoserver/ows" @@ -106,7 +121,11 @@ services: condition: service_healthy data-dir-conf: - image: geonode/geoserver_data:2.23.0 + build: + context: ./docker/geoserver_data + dockerfile: Dockerfile + args: + - BASE_IMAGE_VERSION=${GEOSERVER_DATA_BASE_IMAGE_VERSION} container_name: gsconf4${COMPOSE_PROJECT_NAME} entrypoint: sleep infinity volumes: @@ -117,8 +136,11 @@ services: # PostGIS database. db: - # use geonode official postgis 15 image - image: geonode/postgis:15 + build: + context: ./docker/postgresql + dockerfile: Dockerfile + args: + - BASE_IMAGE_VERSION=${POSTGRES_BASE_IMAGE_VERSION} command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" container_name: db4${COMPOSE_PROJECT_NAME} env_file: @@ -144,8 +166,6 @@ services: volumes: statics: name: ${COMPOSE_PROJECT_NAME}-statics - nginx-confd: - name: ${COMPOSE_PROJECT_NAME}-nginxconfd nginx-certificates: name: ${COMPOSE_PROJECT_NAME}-nginxcerts geoserver-data-dir: diff --git a/docker-purge.sh b/docker-purge.sh deleted file mode 100755 index f66271f9..00000000 --- a/docker-purge.sh +++ /dev/null @@ -1,2 +0,0 @@ -docker kill $(docker ps -q); docker rm $(docker ps -a -q); docker rmi $(docker images -q); docker volume ls -qf dangling=true | xargs -r docker volume rm; docker system prune -a -docker volume prune diff --git a/docker/data_dir_conf/Dockerfile b/docker/data_dir_conf/Dockerfile deleted file mode 100644 index 7d95c825..00000000 --- a/docker/data_dir_conf/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM alpine:latest -LABEL GeoNode development team - -# Install curl in alpine 3.3+ -RUN apk --no-cache add curl - -# Download required files -RUN mkdir -p /tmp/geonode/downloaded -ENV TEMP_DOWNLOADED /tmp/geonode/downloaded -WORKDIR ${TEMP_DOWNLOADED} - -ENV GEOSERVER_VERSION=2.23.0 - -ADD download.sh ${TEMP_DOWNLOADED} -RUN chmod +x ${TEMP_DOWNLOADED}/download.sh -RUN ${TEMP_DOWNLOADED}/download.sh $GEOSERVER_VERSION $TEMP_DOWNLOADED - -# for debugging -RUN ls -lart - -# preparing the volume -ENV BASE_GEOSERVER_DATA_DIR /geoserver_data -RUN mkdir -p ${BASE_GEOSERVER_DATA_DIR} -RUN cp -r ${TEMP_DOWNLOADED}/data ${BASE_GEOSERVER_DATA_DIR} -VOLUME ${BASE_GEOSERVER_DATA_DIR}/data diff --git a/docker/data_dir_conf/README.rst b/docker/data_dir_conf/README.rst deleted file mode 100644 index 3cc26686..00000000 --- a/docker/data_dir_conf/README.rst +++ /dev/null @@ -1,192 +0,0 @@ -***************************** -How to start with data-docker -***************************** - -What you can do with this docker container -========================================== - -The **data-docker** project can be your base data container volume to add data from scratch to GeoServer and PostGIS and then make them persisted when you want to stop your current containers. - -Quick introduction on creating persisted storage in Docker -========================================================== - -Data persistence strategies ---------------------------- - -The most commonly used approches in `Docker`_ are `Data volumes`_ and `Data volume containers`_ which essentially create a file system data volume rather than a dedicated data volume container. - -.. _Docker: https://www.docker.com/technologies/overview - -.. warning:: If you want to follow this readme and run the docker command you have to make sure that your docker host environment has been already set and your docker default machine has been started. - -.. note:: This is required by all developers who are using `Docker-Machine`_ for running containers. Those use native linux or vm like `Docker for Mac`_ and `Docker for Windows`_ don't need these checks. - -.. _Docker-Machine: https://docs.docker.com/machine/ -.. _Docker for Mac: https://www.docker.com/docker-mac -.. _Docker for Windows: https://www.docker.com/docker-windows - -Docker-Machine --------------- - -In order to verify base prerequirements please run this commands below: - -.. code-block:: console - - $ docker-machine env - -which should output something similar: - -.. code-block:: console - - export DOCKER_TLS_VERIFY="1" - export DOCKER_HOST="tcp://192.168.99.100:2376" - export DOCKER_CERT_PATH="/.docker/machine/machines/default" - export DOCKER_MACHINE_NAME="default" - -and then configure your shell environment - -.. code-block:: console - - $ eval $(docker-machine env) - -Data volumes ------------- - -You can easily add a data volume to a container using the option `-v` with the command `run` as the example below: - -.. code-block:: console - - $ docker run -d -P --name geonode-data-container -v /data geonode/geonode-data touch /data/test.txt - -Which creates a data volume within the new container in the `/data` directory. Data volumes are very useful because can be shared and included into other containers. It can be also remarked that the volume created will persist the `test.txt` file. - -Host data volumes -^^^^^^^^^^^^^^^^^ - -You can also mount a directory from your Docker daemon’s host into a container and this could be very useful for testing but even for production in case your host machine can share a storage mount point like a network file system (*NFS*). This approach despite its ease to implement nature has actually an heavy constraint that you have to pre-configure the mount point in your docker host. -This breaks two of the biggest Docker advantages: **container portability** and **applications run anywhere**. - -.. code-block:: console - - $ docker run -d -P --name geonode-data-container -v /geonode_data/data:/data geonode/geonode-data touch /data/test.txt - -In case of the GeoNode *data* for example you cannot start from scratch in development like you actually do with - -.. code-block:: console - - (venv)$ paver reset_hard - -Data volume containers ----------------------- -A data volume container is essentially a docker image that defines storage space. The container itself just defines a place inside docker's virtual file system where data is stored. The container doesn’t run a process and in fact *stops* immediately after `docker run` is called as the container exists in a stopped state, so along with its data. - -So let's create a dedicated container that holds all of GeoNode persistent shareable data resources, mounting the data inside of it and then eventually into other containers once created and setup: - -.. code-block:: console - - $ docker create -v /geonode-store --name geonode-data-container geonode/geonode-data /bin/true - -.. note:: `/bin/true` returns a `0` and does nothing if the command was successful. - -And the with the option `--volumes-from` you can mount the created volume `/geonode-store` within other containers by running: - -.. code-block:: console - - $ docker run -d --volumes-from geonode-data-container --name geoserver geonode/geoserver - -.. hint:: Notice that if you remove containers that mount volumes, the volume store and its data will not be deleted since docker preserves that. - -To completely delete a volume from the file system you have to run: - -.. code-block:: console - - $ docker rm -v geoserver - -How to start with docker-compose for geonode data volume container -================================================================== - -Start the creation of a volume with the **GEOSERVER_DATA_DIR** in the directory `/geoserver_data/data`: - -.. code-block:: console - - $ docker-compose up - -Run a geoserver container with such created volume: - -.. code-block:: console - - $ docker run -d --volumes-from geoserver_data_dir --name geoserver geonode/geoserver - -Verify that the preloaded `GeoServer Data Directory for GeoServer 2.18.3`_ build from Jenkins is actually there: - -.. _GeoServer Data Directory for GeoServer 2.18.3: https://www.dropbox.com/s/cd20is9ddjz7ti5/data-2.18.3.zip - -.. code-block:: console - - $ docker exec -it geoserver ls -lart /geoserver_data/data/ - -The output should be something similar: - -.. code-block:: console - - total 76 - drwxr-xr-x 3 root root 4096 Aug 27 16:51 workspaces - -rw-r--r-- 1 root root 1547 Aug 27 16:51 wms.xml - -rw-r--r-- 1 root root 2013 Aug 27 16:51 wfs.xml - -rw-r--r-- 1 root root 1285 Aug 27 16:51 wcs.xml - drwxr-xr-x 2 root root 4096 Aug 27 16:51 styles - drwxr-xr-x 8 root root 4096 Aug 27 16:51 security - drwxr-xr-x 2 root root 4096 Aug 27 16:51 printing - drwxr-xr-x 2 root root 4096 Aug 27 16:51 plugIns - drwxr-xr-x 2 root root 4096 Aug 27 16:51 palettes - drwxr-xr-x 2 root root 4096 Aug 27 16:51 logs - -rw-r--r-- 1 root root 144 Aug 27 16:51 logging.xml - drwxr-xr-x 2 root root 4096 Aug 27 16:51 images - -rw-r--r-- 1 root root 1111 Aug 27 16:51 gwc-gs.xml - -rw-r--r-- 1 root root 1374 Aug 27 16:51 global.xml - drwxr-xr-x 2 root root 4096 Aug 27 16:51 geonode - drwxr-xr-x 2 root root 4096 Aug 27 16:51 demo - -rw-r--r-- 1 root root 184 Aug 27 16:51 README.rst - drwxr-xr-x 12 root root 4096 Aug 27 16:51 . - drwxr-xr-x 7 root root 4096 Aug 27 17:08 .. - -How to define a docker-compose that uses data-docker ----------------------------------------------------- - -A docker-compose.yml can be defined in such a way with a service that mounts this data directory from a `tag of Docker Hub builds`_, in this case the version for `GeoServer-GeoNode 2.18.3`_: - -.. _tag of Docker Hub builds: https://hub.docker.com/r/geonode/geoserver_data/builds/ - -.. _GeoServer-GeoNode 2.18.3: https://github.com/GeoNode/geoserver-geonode-ext/tree/2.18.3 - -.. code-block:: yaml - - version: '2' - - services: - geoserver: - build: . - ports: - - "8888:8080" - volumes_from: - # reference to the service which has the volume with the preloaded geoserver_data_dir - - data_dir_conf - data_dir_conf: - image: geonode/geoserver_data:2.18.3 - container_name: geoserver_data_dir # named data container - command: /bin/true - volumes: - - /geoserver_data/data - - volumes: - # reference to the named data container that holds the preloaded geoserver data directory - geoserver_data_dir: - - -Available tags --------------- - -There are several different tags from the `Docker Hub builds`_: - -.. _Docker Hub builds: https://cloud.docker.com/u/geonode/repository/registry-1.docker.io/geonode/geoserver_data/builds/ - diff --git a/docker/data_dir_conf/docker-compose.yml b/docker/data_dir_conf/docker-compose.yml deleted file mode 100644 index 11dea36d..00000000 --- a/docker/data_dir_conf/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: '2' - -services: - data_dir_conf: - build: . - image: geonode/geoserver_data:2.23.0 - container_name: geoserver_data_dir - command: /bin/true - volumes: - - /geoserver_data/data - -volumes: - # reference to the named data container that holds the preloaded geoserver data directory - geoserver_data_dir: \ No newline at end of file diff --git a/docker/data_dir_conf/download.sh b/docker/data_dir_conf/download.sh deleted file mode 100644 index 04dcea61..00000000 --- a/docker/data_dir_conf/download.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env sh - -# Wait for version to come up before downloading it -# args $1 - version -# args $2 - temp directory - -echo "GeoServer Data Dir version is $1" -echo "-----------------------------------------------------------------------------------------------" -echo "Archive temporary directory is $2" - -GEOSERVER_VERSION=$1 -TEMP_DOWNLOADED=$2 - -echo "GeoServer Data Directory is going to be downloaded" -artifact_url="https://artifacts.geonode.org/geoserver/$GEOSERVER_VERSION/geonode-geoserver-ext-web-app-data.zip" -echo "Downloading: $artifact_url" -curl -k -L "$artifact_url" --output data.zip && unzip -x -d ${TEMP_DOWNLOADED} data.zip -echo "GeoServer Data Directory download has been completed" diff --git a/docker/geonode/Dockerfile b/docker/geonode/Dockerfile new file mode 100644 index 00000000..8ca9fecf --- /dev/null +++ b/docker/geonode/Dockerfile @@ -0,0 +1,2 @@ +ARG BASE_IMAGE_VERSION +FROM geonode/geonode:${BASE_IMAGE_VERSION} diff --git a/docker/geonode/README.md b/docker/geonode/README.md new file mode 100644 index 00000000..c081d373 --- /dev/null +++ b/docker/geonode/README.md @@ -0,0 +1,6 @@ +# Building GeoNode Image + +* Base image is built here: https:// +* Customizations can be done by + * option a + * option b \ No newline at end of file diff --git a/docker/geoserver/Dockerfile b/docker/geoserver/Dockerfile index f1451c33..ea638a84 100644 --- a/docker/geoserver/Dockerfile +++ b/docker/geoserver/Dockerfile @@ -1,63 +1,2 @@ -ARG IMAGE_VERSION=9.0-jdk11-openjdk-slim-bullseye -ARG JAVA_HOME=/usr/local/openjdk-11 -FROM tomcat:$IMAGE_VERSION -LABEL GeoNode Development Team - -ARG GEOSERVER_CORS_ENABLED=False -ARG GEOSERVER_CORS_ALLOWED_ORIGINS=* -ARG GEOSERVER_CORS_ALLOWED_METHODS=GET,POST,PUT,DELETE,HEAD,OPTIONS -ARG GEOSERVER_CORS_ALLOWED_HEADERS=* -# -# Set GeoServer version and data directory -# -ENV GEOSERVER_VERSION=2.23.0 -ENV GEOSERVER_DATA_DIR="/geoserver_data/data" -ENV GEOSERVER_CORS_ENABLED=$GEOSERVER_CORS_ENABLED -ENV GEOSERVER_CORS_ALLOWED_ORIGINS=$GEOSERVER_CORS_ALLOWED_ORIGINS -ENV GEOSERVER_CORS_ALLOWED_METHODS=$GEOSERVER_CORS_ALLOWED_METHODS -ENV GEOSERVER_CORS_ALLOWED_HEADERS=$GEOSERVER_CORS_ALLOWED_HEADERS -# -# Download and install GeoServer -# -RUN apt-get update -y && apt-get install curl wget unzip -y -RUN cd /usr/local/tomcat/webapps \ - && wget --no-check-certificate --progress=bar:force:noscroll https://artifacts.geonode.org/geoserver/${GEOSERVER_VERSION}/geoserver.war -O geoserver.war \ - && unzip -q geoserver.war -d geoserver \ - && rm geoserver.war \ - && mkdir -p $GEOSERVER_DATA_DIR - -VOLUME $GEOSERVER_DATA_DIR - -# added by simonelanucara https://github.com/simonelanucara -# Optionally add JAI, ImageIO and Marlin Render for improved Geoserver performance -WORKDIR /tmp - -RUN wget --no-check-certificate https://repo1.maven.org/maven2/org/postgis/postgis-jdbc/1.3.3/postgis-jdbc-1.3.3.jar -O postgis-jdbc-1.3.3.jar && \ - wget --no-check-certificate https://maven.geo-solutions.it/org/hibernatespatial/hibernate-spatial-postgis/1.1.3.2/hibernate-spatial-postgis-1.1.3.2.jar -O hibernate-spatial-postgis-1.1.3.2.jar && \ - rm /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/hibernate-spatial-h2-geodb-1.1.3.2.jar && \ - mv hibernate-spatial-postgis-1.1.3.2.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ && \ - mv postgis-jdbc-1.3.3.jar /usr/local/tomcat/webapps/geoserver/WEB-INF/lib/ - - -# copy the script and perform the run of scripts from entrypoint.sh -RUN mkdir -p /usr/local/tomcat/tmp -WORKDIR /usr/local/tomcat/tmp -COPY set_geoserver_auth.sh /usr/local/tomcat/tmp -COPY entrypoint.sh /usr/local/tomcat/tmp -COPY tasks.py /usr/local/tomcat/tmp -COPY ./templates /templates -COPY multidump.sh /usr/local/tomcat/tmp -COPY multidump-alt.sh /usr/local/tomcat/tmp - -RUN chmod +x /usr/local/tomcat/tmp/set_geoserver_auth.sh \ - && chmod +x /usr/local/tomcat/tmp/entrypoint.sh - -RUN apt-get update \ - && apt-get install -y procps less \ - && apt-get install -y python3 python3-pip python3-dev - -RUN pip install j2cli invoke==2.2.0 requests==2.31.0 - -ENV JAVA_OPTS="-Djava.awt.headless=true -Dgwc.context.suffix=gwc -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=/var/log/jvm.log -XX:MaxPermSize=512m -XX:PermSize=256m -Xms512m -Xmx2048m -XX:+UseConcMarkSweepGC -XX:ParallelGCThreads=4 -Dfile.encoding=UTF8 -Djavax.servlet.request.encoding=UTF-8 -Djavax.servlet.response.encoding=UTF-8 -Duser.timezone=GMT -Dorg.geotools.shapefile.datetime=false -DGS-SHAPEFILE-CHARSET=UTF-8 -DGEOSERVER_CSRF_DISABLED=true -DPRINT_BASE_URL=http://geoserver:8080/geoserver/pdf -Xbootclasspath/a:/usr/local/tomcat/webapps/geoserver/WEB-INF/lib/marlin-0.9.3.jar -Dsun.java2d.renderer=org.marlin.pisces.MarlinRenderingEngine" - -CMD ["/usr/local/tomcat/tmp/entrypoint.sh"] +ARG BASE_IMAGE_VERSION +FROM geonode/geoserver:${BASE_IMAGE_VERSION} \ No newline at end of file diff --git a/docker/geoserver/README.md b/docker/geoserver/README.md index 352ccb25..71f09699 100644 --- a/docker/geoserver/README.md +++ b/docker/geoserver/README.md @@ -1,128 +1,6 @@ -# geoserver-docker +# Building GeoServer Image -[GeoServer](http://geoserver.org) is an open source server for sharing geospatial data. -This is a docker image that eases setting up a GeoServer running specifically for [GeoNode](https://github.com/GeoNode/geoserver-geonode-ext) with an additional separated data directory. - -The image is based on the official Tomcat 9 image - -## Installation - -This image is available as a [trusted build on the docker hub](https://registry.hub.docker.com/r/geonode/geoserver/), and is the recommended method of installation. -Simple pull the image from the docker hub. - -```bash -$ docker pull geonode/geoserver -``` - -Alternatively you can build the image locally - -```bash -$ git clone https://github.com/geonode/geoserver-docker.git -$ cd geoserver-docker -$ docker build -t "geonode/geoserver" . -``` - -## Quick start - -You can quick start the image using the command line - -```bash -$ docker run --name "geoserver" -v /var/run/docker.sock:/var/run/docker.sock -d -p 8080:8080 geonode/geoserver -``` - -Point your browser to `http://localhost:8080/geoserver` and login using GeoServer's default username and password: - -* Username: admin -* Password: geoserver - -## How to use different versions - -There are mainly two different versions of this image which are useful for running **GeoNode** with different authentication system types. These versions are released as specific tags for two authentication mechanisms: - -**Cookie based authn**: -- [geonode/geoserver:2.9.x](https://hub.docker.com/r/geonode/geoserver/builds/bx7ydhghnlrfnsppduyva73/) - -**Oauth2 based authn**: -- [geonode/geoserver:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver/builds/bwca5rtexeoegzgroavftdr/) -- [geonode/geoserver:2.10.x](https://hub.docker.com/r/geonode/geoserver/builds/bjohcnc29vm69acqjrvndxf/) -- [geonode/geoserver:2.12.x](https://hub.docker.com/r/geonode/geoserver/builds/bh7pyw5atmkcljurwsnzbs7/) -- [geonode/geoserver:2.13.x](https://hub.docker.com/r/geonode/geoserver/builds/btmjctbuvrjfnnrxrs4wyrs/) -- [geonode/geoserver:2.14.x](https://hub.docker.com/r/geonode/geoserver/builds/bj53pi8he8uksz6ggvrs3wc/) - -You can declare what version to use along with the data directory tag which corresponds to the same version. - -## Configuration - -### Data volume - -This GeoServer container keeps its configuration data at `/geoserver_data/data` which is exposed as volume in the dockerfile. -The volume allows for stopping and starting new containers from the same image without losing all the data and custom configuration. - -You may want to map this volume to a directory on the host. It will also ease the upgrade process in the future. Volumes can be mounted by passing the `-v` flag to the docker run command: - -```bash --v /your/host/data/path:/geoserver_data/data -``` - -### Data volume container - -In case you are running Compose for automatically having GeoServer up and running then a data volume container will be mounted with a default preloaded *GEOSERVER_DATA_DIR* at the configuration data directory of the container. -Make sure that the image from the repository [data-docker](https://github.com/GeoNode/data-docker) is available from the [GeoNode Docker Hub](https://hub.docker.com/u/geonode/) or has been built locally: - -```bash -docker build -t geonode/geoserver_data . -``` - -#### Persistance behavior - -If you run: - -```bash -docker-compose stop -``` - -Data are retained in the *GEOSERVER_DATA_DIR* and can then be mounted in a new GeoServer instance by running again: - -```bash -docker-compose up -``` - -If you run: - -```bash -docker-compose down -``` - -Data are completely gone but you can ever start from the base GeoServer Data Directory built for Geonode. - -#### Data directory versions - -There has to be a correspondence one-to-one between the data directory version and the tag of the GeoServer image used in the Docker compose file. So at the end you can consume these images below: - -* **2.9.x**: [geonode/geoserver_data:2.9.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bsus6alnddg4bc7icwymevp/) -* **2.9.x-oauth2**: [geonode/geoserver_data:2.9.x-oauth2](https://hub.docker.com/r/geonode/geoserver_data/builds/bwkxcupsunvuitzusi9gsnt/) -* **2.10.x**: [geonode/geoserver_data:2.10.x](https://hub.docker.com/r/geonode/geoserver_data/builds/b5jqhpzapkqxzyevjizccug/) -* **2.12.x**: [geonode/geoserver_data:2.12.x](https://hub.docker.com/r/geonode/geoserver_data/builds/byaaalw3lnasunpveyg3x4i/) -* **2.13.x**: [geonode/geoserver_data:2.13.x](https://hub.docker.com/r/geonode/geoserver_data/builds/bunuqzq7a7dk65iumjhkbtc/) -* **2.14.x**: [geonode/geoserver_data:2.14.x](https://hub.docker.com/r/geonode/geoserver_data/builds/blpdjzkrv7pm3stunzpn4pp/) - -### Database - -GeoServer recommends the usage of a spatial database - -#### PostGIS container (PostgreSQL + GIS Extension) - -If you want to use a [PostGIS](http://postgis.org/) container, you can link it to this image. You're free to use any PostGIS container. -An example with [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/) image: - -```bash -$ docker run -d --name="postgis" kartoza/postgis -``` - -For further information see [kartooza/postgis](https://registry.hub.docker.com/u/kartoza/postgis/). - -Now start the GeoServer instance by adding the `--link` option to the docker run command: - -```bash ---link postgis:postgis -``` +* Base image is built here: https:// +* Customizations can be done by + * option a + * option b \ No newline at end of file diff --git a/docker/geoserver/docker-compose.yml b/docker/geoserver/docker-compose.yml deleted file mode 100644 index d14b5006..00000000 --- a/docker/geoserver/docker-compose.yml +++ /dev/null @@ -1,53 +0,0 @@ -version: '3.9' - -services: - - postgis: - image: geonode/postgis:13 - ports: - - "25432:5432" - volumes: - - /srv/docker/geoserver/postgis:/var/lib/postgresql - #volumes_from: - #- pgstore - healthcheck: - test: "pg_isready -d postgres -U postgres" - restart: on-failure - - geoserver: - image: geonode/geoserver:2.23.0 - build: - context: . - links: - - postgis - ports: - - "8080:8080" - volumes: - - /geoserver_data/data - environment: - - NGINX_BASE_URL=http://localhost - depends_on: - postgis: - condition: service_completed_successfully - data-dir-conf: - condition: service_healthy - healthcheck: - test: curl --fail -s http://localhost:8080/geoserver/rest/workspaces/geonode.html || exit 1 - interval: 1m30s - timeout: 10s - retries: 3 - restart: on-failure - - data-dir-conf: - image: geonode/geoserver_data:2.23.0 - container_name: geoserver_data_dir # named data container - entrypoint: sleep infinity - volumes: - - /geoserver_data/data - healthcheck: - test: "ls -A '/geoserver_data/data' | wc -l" - restart: on-failure - -volumes: - # reference to the named data container that holds the preloaded geoserver data directory - geoserver_data_dir: diff --git a/docker/geoserver/entrypoint.sh b/docker/geoserver/entrypoint.sh deleted file mode 100644 index ce10e11a..00000000 --- a/docker/geoserver/entrypoint.sh +++ /dev/null @@ -1,227 +0,0 @@ -#!/bin/bash -set -e - -source /root/.bashrc - - -INVOKE_LOG_STDOUT=${INVOKE_LOG_STDOUT:-TRUE} -invoke () { - if [ $INVOKE_LOG_STDOUT = 'true' ] || [ $INVOKE_LOG_STDOUT = 'True' ] - then - /usr/local/bin/invoke $@ - else - /usr/local/bin/invoke $@ > /usr/src/geonode/invoke.log 2>&1 - fi - echo "$@ tasks done" -} - -# control the values of LB settings if present -if [ -n "$GEONODE_LB_HOST_IP" ]; -then - echo "GEONODE_LB_HOST_IP is defined and not empty with the value '$GEONODE_LB_HOST_IP' \n" - echo export GEONODE_LB_HOST_IP=${GEONODE_LB_HOST_IP} >> /root/.override_env -else - echo "GEONODE_LB_HOST_IP is either not defined or empty setting the value to 'django' \n" - echo export GEONODE_LB_HOST_IP=django >> /root/.override_env - export GEONODE_LB_HOST_IP=django -fi - -if [ -n "$GEONODE_LB_PORT" ]; -then - echo "GEONODE_LB_HOST_IP is defined and not empty with the value '$GEONODE_LB_PORT' \n" - echo export GEONODE_LB_PORT=${GEONODE_LB_PORT} >> /root/.override_env -else - echo "GEONODE_LB_PORT is either not defined or empty setting the value to '8000' \n" - echo export GEONODE_LB_PORT=8000 >> /root/.override_env - export GEONODE_LB_PORT=8000 -fi - -if [ -n "$GEOSERVER_LB_HOST_IP" ]; -then - echo "GEOSERVER_LB_HOST_IP is defined and not empty with the value '$GEOSERVER_LB_HOST_IP' \n" - echo export GEOSERVER_LB_HOST_IP=${GEOSERVER_LB_HOST_IP} >> /root/.override_env -else - echo "GEOSERVER_LB_HOST_IP is either not defined or empty setting the value to 'geoserver' \n" - echo export GEOSERVER_LB_HOST_IP=geoserver >> /root/.override_env - export GEOSERVER_LB_HOST_IP=geoserver -fi - -if [ -n "$GEOSERVER_LB_PORT" ]; -then - echo "GEOSERVER_LB_PORT is defined and not empty with the value '$GEOSERVER_LB_PORT' \n" - echo export GEOSERVER_LB_PORT=${GEOSERVER_LB_PORT} >> /root/.override_env -else - echo "GEOSERVER_LB_PORT is either not defined or empty setting the value to '8000' \n" - echo export GEOSERVER_LB_PORT=8080 >> /root/.override_env - export GEOSERVER_LB_PORT=8080 -fi - -# If DATABASE_HOST is not set in the environment, use the default value -if [ -n "$DATABASE_HOST" ]; -then - echo "DATABASE_HOST is defined and not empty with the value '$DATABASE_HOST' \n" - echo export DATABASE_HOST=${DATABASE_HOST} >> /root/.override_env -else - echo "DATABASE_HOST is either not defined or empty setting the value to 'db' \n" - echo export DATABASE_HOST=db >> /root/.override_env - export DATABASE_HOST=db -fi - -# If DATABASE_PORT is not set in the environment, use the default value -if [ -n "$DATABASE_PORT" ]; -then - echo "DATABASE_PORT is defined and not empty with the value '$DATABASE_PORT' \n" - echo export DATABASE_HOST=${DATABASE_PORT} >> /root/.override_env -else - echo "DATABASE_PORT is either not defined or empty setting the value to '5432' \n" - echo export DATABASE_PORT=5432 >> /root/.override_env - export DATABASE_PORT=5432 -fi - -# If GEONODE_GEODATABASE_USER is not set in the environment, use the default value -if [ -n "$GEONODE_GEODATABASE_USER" ]; -then - echo "GEONODE_GEODATABASE_USER is defined and not empty with the value '$GEONODE_GEODATABASE_USER' \n" - echo export GEONODE_GEODATABASE_USER=${GEONODE_GEODATABASE_USER} >> /root/.override_env -else - echo "GEONODE_GEODATABASE_USER is either not defined or empty setting the value '$GEONODE_GEODATABASE' \n" - echo export GEONODE_GEODATABASE_USER=${GEONODE_GEODATABASE} >> /root/.override_env - export GEONODE_GEODATABASE_USER=${GEONODE_GEODATABASE} -fi - -# If GEONODE_GEODATABASE_SCHEMA is not set in the environment, use the default value -if [ -n "$GEONODE_GEODATABASE_SCHEMA" ]; -then - echo "GEONODE_GEODATABASE_SCHEMA is defined and not empty with the value '$GEONODE_GEODATABASE_SCHEMA' \n" - echo export GEONODE_GEODATABASE_SCHEMA=${GEONODE_GEODATABASE_SCHEMA} >> /root/.override_env -else - echo "GEONODE_GEODATABASE_SCHEMA is either not defined or empty setting the value to 'public' \n" - echo export GEONODE_GEODATABASE_SCHEMA=public >> /root/.override_env - export GEONODE_GEODATABASE_SCHEMA=public -fi - -if [ ! -z "${GEOSERVER_JAVA_OPTS}" ] -then - echo "GEOSERVER_JAVA_OPTS is filled so I replace the value of '$JAVA_OPTS' with '$GEOSERVER_JAVA_OPTS' \n" - export JAVA_OPTS=${GEOSERVER_JAVA_OPTS} -fi - -# control the value of NGINX_BASE_URL variable -if [ -z `echo ${NGINX_BASE_URL} | sed 's/http:\/\/\([^:]*\).*/\1/'` ] -then - echo "NGINX_BASE_URL is empty so I'll use the default Geoserver location \n" - echo "Setting GEOSERVER_LOCATION='${GEOSERVER_PUBLIC_LOCATION}' \n" - echo export GEOSERVER_LOCATION=${GEOSERVER_PUBLIC_LOCATION} >> /root/.override_env -else - echo "NGINX_BASE_URL is filled so GEOSERVER_LOCATION='${NGINX_BASE_URL}' \n" - echo "Setting GEOSERVER_LOCATION='${NGINX_BASE_URL}' \n" - echo export GEOSERVER_LOCATION=${NGINX_BASE_URL} >> /root/.override_env -fi - -if [ -n "$SUBSTITUTION_URL" ]; -then - echo "SUBSTITUTION_URL is defined and not empty with the value '$SUBSTITUTION_URL' \n" - echo "Setting GEONODE_LOCATION='${SUBSTITUTION_URL}' \n" - echo export GEONODE_LOCATION=${SUBSTITUTION_URL} >> /root/.override_env -else - echo "SUBSTITUTION_URL is either not defined or empty so I'll use the default GeoNode location \n" - echo "Setting GEONODE_LOCATION='http://${GEONODE_LB_HOST_IP}:${GEONODE_LB_PORT}' \n" - echo export GEONODE_LOCATION=http://${GEONODE_LB_HOST_IP}:${GEONODE_LB_PORT} >> /root/.override_env -fi - -# set basic tagname -TAGNAME=( "baseUrl" "authApiKey" ) - -if ! [ -f ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ] -then - echo "Configuration file '$GEOSERVER_DATA_DIR'/security/auth/geonodeAuthProvider/config.xml is not available so it is gone to skip \n" -else - # backup geonodeAuthProvider config.xml - cp ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml.orig - # run the setting script for geonodeAuthProvider - /usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/config.xml ${GEOSERVER_DATA_DIR}/security/auth/geonodeAuthProvider/ ${TAGNAME[@]} > /dev/null 2>&1 -fi - -# backup geonode REST role service config.xml -cp "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml.orig" -# run the setting script for geonode REST role service -/usr/local/tomcat/tmp/set_geoserver_auth.sh "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/config.xml" "${GEOSERVER_DATA_DIR}/security/role/geonode REST role service/" ${TAGNAME[@]} > /dev/null 2>&1 - -# set oauth2 filter tagname -TAGNAME=( "cliendId" "clientSecret" "accessTokenUri" "userAuthorizationUri" "redirectUri" "checkTokenEndpointUrl" "logoutUri" ) - -# backup geonode-oauth2 config.xml -cp ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml.orig -# run the setting script for geonode-oauth2 -/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/config.xml ${GEOSERVER_DATA_DIR}/security/filter/geonode-oauth2/ "${TAGNAME[@]}" > /dev/null 2>&1 - -# set global tagname -TAGNAME=( "proxyBaseUrl" ) - -# backup global.xml -cp ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/global.xml.orig -# run the setting script for global configuration -/usr/local/tomcat/tmp/set_geoserver_auth.sh ${GEOSERVER_DATA_DIR}/global.xml ${GEOSERVER_DATA_DIR}/ ${TAGNAME[@]} > /dev/null 2>&1 - -# set correct amqp broker url -sed -i -e 's/localhost/rabbitmq/g' ${GEOSERVER_DATA_DIR}/notifier/notifier.xml - -# exclude wrong dependencies -sed -i -e 's/xom-\*\.jar/xom-\*\.jar,bcprov\*\.jar/g' /usr/local/tomcat/conf/catalina.properties - -# J2 templating for this docker image we should also do it for other configuration files in /usr/local/tomcat/tmp - -declare -a geoserver_datadir_template_dirs=("geofence") - -for template in in ${geoserver_datadir_template_dirs[*]}; do - #Geofence templates - if [ "$template" == "geofence" ]; then - cp -R /templates/$template/* ${GEOSERVER_DATA_DIR}/geofence - - for f in $(find ${GEOSERVER_DATA_DIR}/geofence/ -type f -name "*.j2"); do - echo -e "Evaluating template\n\tSource: $f\n\tDest: ${f%.j2}" - /usr/local/bin/j2 $f > ${f%.j2} - rm -f $f - done - - fi -done - -# configure CORS (inspired by https://github.com/oscarfonts/docker-geoserver) -# if enabled, this will add the filter definitions -# to the end of the web.xml -# (this will only happen if our filter has not yet been added before) -if [ "${GEOSERVER_CORS_ENABLED}" = "true" ] || [ "${GEOSERVER_CORS_ENABLED}" = "True" ]; then - if ! grep -q DockerGeoServerCorsFilter "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; then - echo "Enable CORS for $CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml" - sed -i "\::i\\ - \n\ - DockerGeoServerCorsFilter\n\ - org.apache.catalina.filters.CorsFilter\n\ - \n\ - cors.allowed.origins\n\ - ${GEOSERVER_CORS_ALLOWED_ORIGINS}\n\ - \n\ - \n\ - cors.allowed.methods\n\ - ${GEOSERVER_CORS_ALLOWED_METHODS}\n\ - \n\ - \n\ - cors.allowed.headers\n\ - ${GEOSERVER_CORS_ALLOWED_HEADERS}\n\ - \n\ - \n\ - \n\ - DockerGeoServerCorsFilter\n\ - /*\n\ - " "$CATALINA_HOME/webapps/geoserver/WEB-INF/web.xml"; - fi -fi - -if [ ${FORCE_REINIT} = "true" ] || [ ${FORCE_REINIT} = "True" ] || [ ! -e "${GEOSERVER_DATA_DIR}/geoserver_init.lock" ]; then - # Run async configuration, it needs Geoserver to be up and running - nohup sh -c "invoke configure-geoserver" & -fi - -# start tomcat -exec env JAVA_OPTS="${JAVA_OPTS}" catalina.sh run diff --git a/docker/geoserver/multidump-alt.sh b/docker/geoserver/multidump-alt.sh deleted file mode 100644 index cc237e17..00000000 --- a/docker/geoserver/multidump-alt.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -if [ $# -ne 3 ]; then - echo "Usage: $0 pid interval count" - exit 1 -fi - -PID=$1 -INTERVAL=$2 -COUNT=$3 - -top -bH -d $INTERVAL -n $COUNT -p $PID >> top.out 2>&1 & -for i in `seq $COUNT`; do - kill -3 $PID - sleep $INTERVAL -done diff --git a/docker/geoserver/multidump.sh b/docker/geoserver/multidump.sh deleted file mode 100644 index 21dfd2ba..00000000 --- a/docker/geoserver/multidump.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -if [ $# -ne 3 ]; then - echo "Usage: $0 pid interval count" - exit 1 -fi - -PID=$1 -INTERVAL=$2 -COUNT=$3 - -top -bH -d $INTERVAL -n $COUNT -p $PID >> top.out 2>&1 & -for i in `seq $COUNT`; do - echo "stack trace $i of $COUNT" >> jstack.out - jstack -l $PID >> jstack.out - echo "--------------------" >> jstack.out - sleep $INTERVAL -done diff --git a/docker/geoserver/set_geoserver_auth.sh b/docker/geoserver/set_geoserver_auth.sh deleted file mode 100644 index 8402e2c8..00000000 --- a/docker/geoserver/set_geoserver_auth.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -auth_conf_source="$1" -auth_conf_target="$2" -# Creating a temporary file for sed to write the changes to -temp_file="xml.tmp" -touch $temp_file - -source /root/.bashrc -source /root/.override_env - -test -z "$auth_conf_source" && echo "You must specify a source file" && exit 1 -test -z "$auth_conf_target" && echo "You must specify a target conf directory" && exit 1 - -test ! -f "$auth_conf_source" && echo "Source $auth_conf_source does not exist or is not a file" && exit 1 -test ! -d "$auth_conf_target" && echo "Target directory $auth_conf_target does not exist or is not a directory" && exit 1 - -# for debugging -echo -e "OAUTH2_API_KEY=$OAUTH2_API_KEY\n" -echo -e "OAUTH2_CLIENT_ID=$OAUTH2_CLIENT_ID\n" -echo -e "OAUTH2_CLIENT_SECRET=$OAUTH2_CLIENT_SECRET\n" -echo -e "GEOSERVER_LOCATION=$GEOSERVER_LOCATION\n" -echo -e "GEONODE_LOCATION=$GEONODE_LOCATION\n" -echo -e "auth_conf_source=$auth_conf_source\n" -echo -e "auth_conf_target=$auth_conf_target\n" - -# Elegance is the key -> adding an empty last line for Mr. “sed” to pick up -echo " " >> "$auth_conf_source" - -cat "$auth_conf_source" - -tagname=( ${@:3:7} ) - -# for debugging -for i in "${tagname[@]}" -do - echo "tagname=<$i>" -done - -echo "DEBUG: Starting... [Ok]\n" - -for i in "${tagname[@]}" -do - echo "DEBUG: Working on '$auth_conf_source' for tagname <$i>" - # Extracting the value from the <$tagname> element - # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n - tagvalue=`grep "<$i>.*<.$i>" "$auth_conf_source" | sed -e "s/^.*<$i/<$i/" | cut -f2 -d">"| cut -f1 -d"<"` - - echo "DEBUG: Found the current value for the element <$i> - '$tagvalue'" - - # Setting new substituted value - case $i in - authApiKey) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$OAUTH2_API_KEY'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@.*@$OAUTH2_API_KEY@"`;; - cliendId) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$OAUTH2_CLIENT_ID'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@.*@$OAUTH2_CLIENT_ID@"`;; - clientSecret) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$OAUTH2_CLIENT_SECRET'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@.*@$OAUTH2_CLIENT_SECRET@"`;; - proxyBaseUrl | redirectUri | userAuthorizationUri | logoutUri ) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$GEOSERVER_LOCATION'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@^(https?://[^/]+)@$GEOSERVER_LOCATION@"`;; - baseUrl | accessTokenUri | checkTokenEndpointUrl ) - echo "DEBUG: Editing '$auth_conf_source' for tagname <$i> and replacing its value with '$GEONODE_LOCATION'" - newvalue=`echo -ne "$tagvalue" | sed -re "s@^(https?://[^/]+)@$GEONODE_LOCATION@"`;; - *) echo -n "an unknown variable has been found";; - esac - - echo "DEBUG: Found the new value for the element <$i> - '$newvalue'" - # Replacing element’s value with $SUBSTITUTION_URL - # echo -ne "<$i>$tagvalue" | xmlstarlet sel -t -m "//a" -v . -n - sed -e "s@<$i>$tagvalue<\/$i>@<$i>$newvalue<\/$i>@g" "$auth_conf_source" > "$temp_file" - cp "$temp_file" "$auth_conf_source" -done -# Writing our changes back to the original file ($auth_conf_source) -# no longer needed -# mv $temp_file $auth_conf_source - -echo "DEBUG: Finished... [Ok] --- Final xml file is \n" -cat "$auth_conf_source" diff --git a/docker/geoserver/tasks.py b/docker/geoserver/tasks.py deleted file mode 100644 index 5f6f9b32..00000000 --- a/docker/geoserver/tasks.py +++ /dev/null @@ -1,83 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2023 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### -import os -import logging -import time -import base64 -import requests -from pathlib import Path -from invoke import task - -logger = logging.getLogger(__name__) - - -@task -def configure_geoserver(ctx): - _configure_geoserver_password() - _initialized(ctx) - - -def _configure_geoserver_password(): - print( - "************************configuring Geoserver credentials*****************************" - ) - GEOSERVER_LB_PORT = os.getenv("GEOSERVER_LB_PORT", 8080) - GEOSERVER_ADMIN_USER = os.getenv("GEOSERVER_ADMIN_USER", "admin") - GEOSERVER_ADMIN_PASSWORD = os.getenv("GEOSERVER_ADMIN_PASSWORD", "geoserver") - GEOSERVER_FACTORY_PASSWORD = os.getenv("GEOSERVER_FACTORY_PASSWORD", "geoserver") - geoserver_rest_baseurl = f"http://localhost:{GEOSERVER_LB_PORT}/geoserver/rest" - basic_auth_credentials = base64.b64encode( - f"{GEOSERVER_ADMIN_USER}:{GEOSERVER_FACTORY_PASSWORD}".encode() - ).decode() - headers = { - "Content-type": "application/xml", - "Accept": "application/xml", - "Authorization": f"Basic {basic_auth_credentials}", - } - data = f""" - - {GEOSERVER_ADMIN_PASSWORD} - """ - - for _cnt in range(1, 29): - try: - response = requests.put( - f"{geoserver_rest_baseurl}/security/self/password", - data=data, - headers=headers, - ) - print(f"Response Code: {response.status_code}") - if response.status_code == 200: - print("GeoServer admin password updated SUCCESSFULLY!") - else: - logger.warning( - f"WARNING: GeoServer admin password *NOT* updated: code [{response.status_code}]" - ) - break - except Exception: - print(f"...waiting for Geoserver to pop-up...{_cnt}") - time.sleep(2) - - -def _initialized(ctx): - print("**************************init file********************************") - GEOSERVER_DATA_DIR = os.getenv("GEOSERVER_DATA_DIR", "/geoserver_data/data/") - geoserver_init_lock = Path(GEOSERVER_DATA_DIR) / "geoserver_init.lock" - ctx.run(f"date > {geoserver_init_lock}") diff --git a/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 b/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 deleted file mode 100644 index 0272932d..00000000 --- a/docker/geoserver/templates/geofence/geofence-datasource-ovr.properties.j2 +++ /dev/null @@ -1,12 +0,0 @@ -geofenceVendorAdapter.databasePlatform=org.hibernatespatial.postgis.PostgisDialect -geofenceDataSource.driverClassName=org.postgresql.Driver -geofenceDataSource.url=jdbc:postgresql://{{ DATABASE_HOST }}:{{ DATABASE_PORT }}/{{ GEONODE_GEODATABASE }} -geofenceDataSource.username={{ GEONODE_GEODATABASE_USER }} -geofenceDataSource.password={{ GEONODE_GEODATABASE_PASSWORD }} -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.default_schema]={{ GEONODE_GEODATABASE_SCHEMA }} - -# avoid hibernate transaction issues -geofenceDataSource.testOnBorrow=true -geofenceDataSource.validationQuery=SELECT 1 -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.testOnBorrow]=true -geofenceEntityManagerFactory.jpaPropertyMap[hibernate.validationQuery]=SELECT 1 \ No newline at end of file diff --git a/docker/geoserver_data/Dockerfile b/docker/geoserver_data/Dockerfile new file mode 100644 index 00000000..dced1d85 --- /dev/null +++ b/docker/geoserver_data/Dockerfile @@ -0,0 +1,2 @@ +ARG BASE_IMAGE_VERSION +FROM geonode/geoserver_data:${BASE_IMAGE_VERSION} \ No newline at end of file diff --git a/docker/geoserver_data/README.md b/docker/geoserver_data/README.md new file mode 100644 index 00000000..bdff4c97 --- /dev/null +++ b/docker/geoserver_data/README.md @@ -0,0 +1,11 @@ +# Building GeoServer Data Image + +> :bulb: **Question** +> +> Do we really have to have a data container? + + +* Base image is built here: https:// +* Customizations can be done by + * option a + * option b \ No newline at end of file diff --git a/docker/letsencrypt/Dockerfile b/docker/letsencrypt/Dockerfile index 3d003286..b8e6527d 100644 --- a/docker/letsencrypt/Dockerfile +++ b/docker/letsencrypt/Dockerfile @@ -1,18 +1,2 @@ -FROM alpine:latest - -RUN apk add --no-cache certbot - -# Installing scripts -ADD docker-entrypoint.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh - -# Installing cronjobs -ADD crontab /crontab -RUN /usr/bin/crontab /crontab && \ - rm /crontab - -# Setup the entrypoint -ENTRYPOINT ["./docker-entrypoint.sh"] - -# We run cron in foreground to update the certificates -CMD /usr/sbin/crond -f +ARG BASE_IMAGE_VERSION +FROM geonode/letsencrypt:${BASE_IMAGE_VERSION} \ No newline at end of file diff --git a/docker/letsencrypt/README.md b/docker/letsencrypt/README.md index ae1bdc03..99bfa9cc 100644 --- a/docker/letsencrypt/README.md +++ b/docker/letsencrypt/README.md @@ -1,15 +1,11 @@ -# Letsencrypt service for Geonode +# Building Lets-Encrypt Image -This service generates SSL certificates to be used by Nginx. +> :bulb: **Question** +> +> Do we really have configure letsencrypt within this setup? +> By default is should be disabled at least -## Let's Encrypt - -Upon startup, it generates one SSL certificate from Let's Encrypt using Certbot. It then starts cron (in foreground) to renew the certificates using Certbot renew. - -If for some reason getting the certificate fails, a placeholder certificate is generated. This certificate is invalid, but still allows to encrypt the data and to start the webserver. - -To avoid hitting Let's Encrypt very low rate limits when developping or doing tests, LETSENCRYPT_MODE env var can be set to "disabled" (which will completely bypass Let'sEncrypt, simulating a failure) or to "staging" (using Let'sEncrypt test certificates with higher rates). - -## Autoissued - -An auto-issued certificate is also generate to be used on the LAN if needed. It is also renewed every now and then using the same cron process than above. +* Base image is built here: https:// +* Customizations can be done by + * option a + * option b \ No newline at end of file diff --git a/docker/letsencrypt/crontab b/docker/letsencrypt/crontab deleted file mode 100644 index 5f2c1a8f..00000000 --- a/docker/letsencrypt/crontab +++ /dev/null @@ -1,8 +0,0 @@ -# +------------- minute (0 - 59) -# +------------- hour (0 - 23) -# +------------- day of month (1 - 31) -# +------------- month (1 - 12) -# +------------- day of week (0 - 6) (Sunday to Saturday; 7 is also Sunday on some systems) -# - - 0 0,12 * * * date && echo "daily " && /docker-entrypoint.sh diff --git a/docker/letsencrypt/docker-entrypoint.sh b/docker/letsencrypt/docker-entrypoint.sh deleted file mode 100644 index d1c4541b..00000000 --- a/docker/letsencrypt/docker-entrypoint.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/sh - -# Exit script in case of error -set -e - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING LETSENCRYPT ENTRYPOINT ---------------------" -date - -# We make the config dir -mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE" - -# Do not exit script in case of error -set +e - -# We run the command -if [ "$LETSENCRYPT_MODE" == "staging" ]; then - printf "\nTrying to get STAGING certificate\n" - certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --test-cert -elif [ "$LETSENCRYPT_MODE" == "production" ]; then - printf "\nTrying to get PRODUCTION certificate\n" - certbot --config-dir "/geonode-certificates/$LETSENCRYPT_MODE" certonly --webroot -w "/geonode-certificates" -d "$HTTPS_HOST" -m "$ADMIN_EMAIL" --agree-tos --non-interactive --server https://acme-v02.api.letsencrypt.org/directory -elif [ "$LETSENCRYPT_MODE" == "disabled" ]; then - printf "\nNot trying to get certificate (because LETSENCRYPT_MODE variable is set to disabled) - and stop container\n" - exit 0 -else - printf "\nNot trying to get certificate (simulating failure, because LETSENCRYPT_MODE variable was neither staging nor production\n" - /bin/false -fi - -# If the certbot comand failed, we will create a placeholder certificate -if [ ! $? -eq 0 ]; then - # Exit script in case of error - set -e - - printf "\nFailed to get the certificates !\n" - - printf "\nWaiting 30s to avoid hitting Letsencrypt rate limits before it's even possible to react\n" - sleep 30 - - exit 1 -fi - -printf "\nCertificate have been created/renewed successfully\n" - -echo "-----------------------------------------------------" -echo "FINISHED LETSENCRYPT ENTRYPOINT ---------------------" -echo "-----------------------------------------------------" - -# Run the CMD -exec "$@" diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index 70d3469e..193b269c 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,18 +1,2 @@ -FROM nginx:1.25.1-alpine - -RUN apk add --no-cache openssl inotify-tools vim - -WORKDIR /etc/nginx/ - -RUN mkdir -p /etc/nginx/html &&\ - touch /etc/nginx/html/index.html - -ADD nginx.conf.envsubst nginx.https.available.conf.envsubst ./ -ADD geonode.conf.envsubst ./sites-enabled/ - -ADD docker-autoreload.sh docker-entrypoint.sh / -ENTRYPOINT ["/docker-entrypoint.sh"] -RUN chmod +x /docker-autoreload.sh -RUN chmod +x /docker-entrypoint.sh - -CMD ["nginx", "-g", "daemon off;"] +ARG BASE_IMAGE_VERSION +FROM geonode/nginx:${BASE_IMAGE_VERSION} \ No newline at end of file diff --git a/docker/nginx/README.md b/docker/nginx/README.md new file mode 100644 index 00000000..b095f28a --- /dev/null +++ b/docker/nginx/README.md @@ -0,0 +1,6 @@ +# Building Nginx Image + +* Base image is built here: https:// +* Customizations can be done by + * option a + * option b \ No newline at end of file diff --git a/docker/nginx/docker-autoreload.sh b/docker/nginx/docker-autoreload.sh deleted file mode 100644 index 812cc76d..00000000 --- a/docker/nginx/docker-autoreload.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# This will watch the /geonode-certificates folder and run nginx -s reload whenever there are some changes. -# We use this to reload nginx config when certificates changed. - -# inspired/copied from https://github.com/kubernetes/kubernetes/blob/master/examples/https-nginx/auto-reload-nginx.sh - -while true -do - inotifywait -e create -e modify -e delete -e move -r --exclude "\\.certbot\\.lock|\\.well-known" "/geonode-certificates/$LETSENCRYPT_MODE" - echo "Changes noticed in /geonode-certificates" - - echo "Waiting 5s for additionnal changes" - sleep 5 - - echo "Creating symbolic link for WAN host" - # for some reason, the ln -f flag doesn't work below... - rm -f /certificate_symlink - if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then - echo "Certbot certificate exists, we symlink to the live cert" - ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink - else - echo "Certbot certificate does not exist, we symlink to autoissued" - ln -sf "/geonode-certificates/autoissued" /certificate_symlink - fi - - # Test nginx configuration - nginx -t - # If it passes, we reload - if [ $? -eq 0 ] - then - echo "Configuration valid, we reload..." - nginx -s reload - else - echo "Configuration not valid, we do not reload." - fi -done diff --git a/docker/nginx/docker-entrypoint.sh b/docker/nginx/docker-entrypoint.sh deleted file mode 100644 index e6bec7a1..00000000 --- a/docker/nginx/docker-entrypoint.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/sh - -# Exit script in case of error -set -e - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING NGINX ENTRYPOINT ---------------------------" -date - -# We make the config dir -mkdir -p "/geonode-certificates/$LETSENCRYPT_MODE" - -echo "Creating autoissued certificates for HTTP host" -if [ ! -f "/geonode-certificates/autoissued/privkey.pem" ] || [[ $(find /geonode-certificates/autoissued/privkey.pem -mtime +365 -print) ]]; then - echo "Autoissued certificate does not exist or is too old, we generate one" - mkdir -p "/geonode-certificates/autoissued/" - openssl req -x509 -nodes -days 1825 -newkey rsa:2048 -keyout "/geonode-certificates/autoissued/privkey.pem" -out "/geonode-certificates/autoissued/fullchain.pem" -subj "/CN=${HTTP_HOST:-HTTPS_HOST}" -else - echo "Autoissued certificate already exists" -fi - -echo "Creating symbolic link for HTTPS certificate" -# for some reason, the ln -f flag doesn't work below... -# TODO : not DRY (reuse same scripts as docker-autoreload.sh) -rm -f /certificate_symlink -if [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/fullchain.pem" ] && [ -f "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST/privkey.pem" ]; then - echo "Certbot certificate exists, we symlink to the live cert" - ln -sf "/geonode-certificates/$LETSENCRYPT_MODE/live/$HTTPS_HOST" /certificate_symlink -else - echo "Certbot certificate does not exist, we symlink to autoissued" - ln -sf "/geonode-certificates/autoissued" /certificate_symlink -fi - -if [ -z "${HTTPS_HOST}" ]; then - HTTP_SCHEME="http" -else - HTTP_SCHEME="https" -fi - -export HTTP_SCHEME=${HTTP_SCHEME:-http} -export GEONODE_LB_HOST_IP=${GEONODE_LB_HOST_IP:-django} -export GEONODE_LB_PORT=${GEONODE_LB_PORT:-8000} -export GEOSERVER_LB_HOST_IP=${GEOSERVER_LB_HOST_IP:-geoserver} -export GEOSERVER_LB_PORT=${GEOSERVER_LB_PORT:-8080} - -echo "Replacing environement variables" -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT \$RESOLVER' < /etc/nginx/nginx.conf.envsubst > /etc/nginx/nginx.conf -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT \$RESOLVER' < /etc/nginx/nginx.https.available.conf.envsubst > /etc/nginx/nginx.https.available.conf -envsubst '\$HTTP_HOST \$HTTPS_HOST \$HTTP_SCHEME \$GEONODE_LB_HOST_IP \$GEONODE_LB_PORT \$GEOSERVER_LB_HOST_IP \$GEOSERVER_LB_PORT' < /etc/nginx/sites-enabled/geonode.conf.envsubst > /etc/nginx/sites-enabled/geonode.conf - -echo "Enabling or not https configuration" -if [ -z "${HTTPS_HOST}" ]; then - echo "" > /etc/nginx/nginx.https.enabled.conf -else - ln -sf /etc/nginx/nginx.https.available.conf /etc/nginx/nginx.https.enabled.conf -fi - -echo "Loading nginx autoreloader" -sh /docker-autoreload.sh & - -echo "-----------------------------------------------------" -echo "FINISHED NGINX ENTRYPOINT ---------------------------" -echo "-----------------------------------------------------" - -# Run the CMD -exec "$@" diff --git a/docker/nginx/geonode.conf.envsubst b/docker/nginx/geonode.conf.envsubst deleted file mode 100644 index 1176ce2c..00000000 --- a/docker/nginx/geonode.conf.envsubst +++ /dev/null @@ -1,134 +0,0 @@ -include /etc/nginx/mime.types; - -# This is the main geonode conf -charset utf-8; - -# max upload size -client_max_body_size 100G; -client_body_buffer_size 256K; -client_body_timeout 600s; -large_client_header_buffers 4 64k; - -proxy_connect_timeout 600; -proxy_send_timeout 600; -proxy_read_timeout 600; -uwsgi_read_timeout 600; -send_timeout 600; - -fastcgi_hide_header Set-Cookie; - -etag on; - -# compression -gzip on; -gzip_vary on; -gzip_proxied any; -gzip_http_version 1.1; -gzip_disable "MSIE [1-6]\."; -gzip_buffers 16 8k; -gzip_min_length 1100; -gzip_comp_level 6; -gzip_types - text/css - text/javascript - text/xml - text/plain - application/xml - application/xml+rss - application/javascript - application/x-javascript - application/json; - -# GeoServer -location /geoserver { - # Using a variable is a trick to let Nginx start even if upstream host is not up yet - # (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - set $upstream $GEOSERVER_LB_HOST_IP:$GEOSERVER_LB_PORT; - - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Server $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Proto $HTTP_SCHEME; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_hide_header X-Frame-Options; - proxy_pass http://$upstream; - proxy_http_version 1.1; - proxy_redirect http://$upstream $HTTP_SCHEME://$HTTP_HOST; - proxy_request_buffering off; - client_max_body_size 0; -} - -# GeoNode -location /static/ { - alias /mnt/volumes/statics/static/; - - location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} - -location /uploaded/ { - alias /mnt/volumes/statics/uploaded/; - - location ~* \.(?:html|js|jpg|jpeg|gif|png|css|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|txt|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} - -location / { - # Using a variable is a trick to let Nginx start even if upstream host is not up yet - # (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - set $upstream $GEONODE_LB_HOST_IP:$GEONODE_LB_PORT; - - if ($request_method = OPTIONS) { - add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS"; - add_header Access-Control-Allow-Headers "Authorization, Content-Type, Accept"; - add_header Access-Control-Allow-Credentials true; - add_header Content-Length 0; - add_header Content-Type text/plain; - add_header Access-Control-Max-Age 1728000; - return 200; - } - - add_header Access-Control-Allow-Credentials false; - add_header Access-Control-Allow-Headers "Content-Type, Accept, Authorization, Origin, User-Agent"; - add_header Access-Control-Allow-Methods "GET, POST, PUT, PATCH, OPTIONS"; - - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header Origin $HTTP_SCHEME://$host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-Host $server_name; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $HTTP_SCHEME; - proxy_hide_header X-Frame-Options; - proxy_request_buffering off; - - # uwsgi_params - include /etc/nginx/uwsgi_params; - - proxy_pass http://$upstream; - # uwsgi_pass $upstream; - - # when a client closes the connection then keep the channel to uwsgi open. Otherwise uwsgi throws an IOError - uwsgi_ignore_client_abort on; - uwsgi_request_buffering off; - - location ~* \.(?:js|jpg|jpeg|gif|png|tgz|gz|rar|bz2|doc|pdf|ppt|tar|wav|bmp|ttf|rtf|swf|ico|flv|woff|woff2|svg|xml)$ { - gzip_static always; - expires 30d; - access_log off; - add_header Pragma "public"; - add_header Cache-Control "max-age=31536000, public"; - } -} diff --git a/docker/nginx/nginx.conf.envsubst b/docker/nginx/nginx.conf.envsubst deleted file mode 100644 index b6065209..00000000 --- a/docker/nginx/nginx.conf.envsubst +++ /dev/null @@ -1,39 +0,0 @@ -# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst -# not to be mistaken for nginx variables (also starting with $, but usually lowercase) - -worker_processes auto; - -events { - -} - -http { - server_names_hash_bucket_size 64; - - # Allow Nginx to resolve Docker host names (see https://sandro-keil.de/blog/2017/07/24/let-nginx-start-if-upstream-host-is-unavailable-or-down/) - resolver $RESOLVER; # it seems rancher uses 169.254.169.250 instead of 127.0.0.11 which works well in docker-compose (see /etc/resolv.conf) - - # https - listens on specific name - this uses letsencrypt cert - # this includes a symlink that links either to nginx.https.available.conf if https in enabled - # or to an empty file if https is disabled. - include nginx.https.enabled.conf; - - # http - listens to specific HTTP_HOST only - this is not encrypted (not ideal but admissible on LAN for instance) - # even if not used (HTTP_HOST empty), we must keep it as it's used for internal API calls between django and geoserver - # TODO : do not use unencrypted connection even on LAN, but is it possible to have browser not complaining about unknown authority ? - server { - listen 80; - server_name $HTTP_HOST 127.0.0.1; - - include sites-enabled/*.conf; - } - - # Default server closes the connection (we can connect only using HTTP_HOST and HTTPS_HOST) - server { - listen 80 default_server; - listen 443; - server_name _; - return 444; - } - -} diff --git a/docker/nginx/nginx.https.available.conf.envsubst b/docker/nginx/nginx.https.available.conf.envsubst deleted file mode 100644 index fcd1cb34..00000000 --- a/docker/nginx/nginx.https.available.conf.envsubst +++ /dev/null @@ -1,37 +0,0 @@ -# NOTE : $VARIABLES are env variables replaced by entrypoint.sh using envsubst -# not to be mistaken for nginx variables (also starting with $, but usually lowercase) - -# This file is to be included in the main nginx.conf configuration if HTTPS_HOST is set -ssl_session_cache shared:SSL:10m; -ssl_session_timeout 10m; - -# this is the actual HTTPS host -server { - listen 443 ssl; - server_name $HTTPS_HOST; - keepalive_timeout 70; - - ssl_certificate /certificate_symlink/fullchain.pem; - ssl_certificate_key /certificate_symlink/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers HIGH:!aNULL:!MD5; - - include sites-enabled/*.conf; -} - -# if we try to connect from http, we redirect to https -server { - listen 80; - server_name $HTTPS_HOST $HTTP_HOST; # TODO : once geoserver supports relative urls, we should allow access though both HTTP and HTTPS at the same time and hence remove HTTP_HOST from this line - - # Except for let's encrypt challenge - location /.well-known { - alias /geonode-certificates/.well-known; - include /etc/nginx/mime.types; - } - - # Redirect to https - location / { - return 302 https://$HTTPS_HOST$request_uri; # TODO : we should use 301 (permanent redirect, but not practical for debug) - } -} diff --git a/docker/postgis/Dockerfile b/docker/postgis/Dockerfile deleted file mode 100644 index 7a473874..00000000 --- a/docker/postgis/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM postgis/postgis:15-3.3-alpine -LABEL GeoNode development team - -COPY ./initdb-geonode.sh /docker-entrypoint-initdb.d/geonode.sh -RUN chmod +x /docker-entrypoint-initdb.d/geonode.sh \ No newline at end of file diff --git a/docker/postgis/initdb-geonode.sh b/docker/postgis/initdb-geonode.sh deleted file mode 100644 index 11f358bb..00000000 --- a/docker/postgis/initdb-geonode.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash -set -e - -function create_geonode_user_and_database() { - local db=$1 - local geonode_user="${GEONODE_DATABASE_USER:-$db}" - local geonode_password="$GEONODE_DATABASE_PASSWORD" - echo " Creating user and database '$db' with Geonode user: $geonode_user" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL - CREATE USER $db; - ALTER USER $geonode_user with encrypted password '$geonode_password'; - ALTER USER $geonode_user CREATEDB; - CREATE DATABASE $db; - GRANT CREATE ON SCHEMA public TO $geonode_user; - GRANT USAGE ON SCHEMA public TO $geonode_user; - GRANT ALL PRIVILEGES ON DATABASE $db TO $geonode_user; -EOSQL - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$db" -c "GRANT ALL ON SCHEMA public TO $geonode_user;" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$db" -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO $geonode_user;" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$db" -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO $geonode_user;" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$db" -c "GRANT INSERT, SELECT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO $geonode_user;" -} - -function create_geonode_user_and_geodatabase() { - local geodb=$1 - local geonode_geodb_user="${GEONODE_GEODATABASE_USER:-$geodb}" - local geonode_geodb_password="$GEONODE_GEODATABASE_PASSWORD" - - echo " Creating user and database '$geodb' with Geonode GeoDB user: $geonode_geodb_user" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL - CREATE USER $geodb; - ALTER USER $geonode_geodb_user with encrypted password '$geonode_geodb_password'; - ALTER USER $geonode_geodb_user CREATEDB; - CREATE DATABASE $geodb; - GRANT CREATE ON SCHEMA public TO $geonode_geodb_user; - GRANT USAGE ON SCHEMA public TO $geonode_geodb_user; - GRANT ALL PRIVILEGES ON DATABASE $geodb TO $geonode_geodb_user; -EOSQL - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$geodb" -c "GRANT ALL ON SCHEMA public TO $geonode_geodb_user;" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$geodb" -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO $geonode_geodb_user;" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$geodb" -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO $geonode_geodb_user;" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -d "$geodb" -c "GRANT INSERT, SELECT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO $geonode_geodb_user;" -} - -function update_database_with_postgis() { - local db=$1 - echo " Updating databse '$db' with extension" - psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$db" <<-EOSQL - CREATE EXTENSION IF NOT EXISTS postgis; - GRANT ALL ON geometry_columns TO PUBLIC; - GRANT ALL ON spatial_ref_sys TO PUBLIC; -EOSQL -} - -if [ -n "$GEONODE_DATABASE" ]; then - echo "Geonode database creation requested: $GEONODE_DATABASE" - create_geonode_user_and_database $GEONODE_DATABASE - update_database_with_postgis $GEONODE_DATABASE - echo "Geonode database created" -fi - -if [ -n "$GEONODE_GEODATABASE" ]; then - echo "Geonode geodatabase creation requested: $GEONODE_GEODATABASE" - create_geonode_user_and_geodatabase $GEONODE_GEODATABASE - update_database_with_postgis $GEONODE_GEODATABASE - echo "Geonode geodatabase created" -fi \ No newline at end of file diff --git a/docker/postgresql/Dockerfile b/docker/postgresql/Dockerfile new file mode 100644 index 00000000..1c7d2fb3 --- /dev/null +++ b/docker/postgresql/Dockerfile @@ -0,0 +1,2 @@ +ARG BASE_IMAGE_VERSION +FROM geonode/postgis:${BASE_IMAGE_VERSION} \ No newline at end of file diff --git a/docker/postgresql/README.md b/docker/postgresql/README.md new file mode 100644 index 00000000..ac9b7945 --- /dev/null +++ b/docker/postgresql/README.md @@ -0,0 +1,6 @@ +# Building PostgreSQL Image + +* Base image is built here: https:// +* Customizations can be done by + * option a + * option b \ No newline at end of file diff --git a/generated-project-vagrant-compose.sh b/generated-project-vagrant-compose.sh deleted file mode 100644 index f91f5f05..00000000 --- a/generated-project-vagrant-compose.sh +++ /dev/null @@ -1,22 +0,0 @@ - -#!/usr/bin/env bash -# this is the generated-project script to create an generated-project canary project. - -source /usr/share/virtualenvwrapper/virtualenvwrapper.sh -mkvirtualenv --python=/usr/bin/python3 generated-project -pip install Django==3.2.16 -rm -rf generated-project -django-admin startproject --template=/home/vagrant/geonode-project -e py,sh,md,rst,json,yml,ini,env,sample,properties -n monitoring-cron -n Dockerfile generated-project -cd /home/vagrant/generated-project -python create-envfile.py --geonodepwd geonode \ - --geoserverpwd geoserver \ - --pgpwd postgres \ - --dbpwd geonode \ - --geodbpwd geonode -sed -i 's/GEOSERVER_WEB_UI_LOCATION=http:\/\/localhost\/geoserver\//GEOSERVER_WEB_UI_LOCATION=http:\/\/localhost:8888\/geoserver\//' .env -sed -i 's/GEOSERVER_PUBLIC_LOCATION=http:\/\/localhost\/geoserver\//GEOSERVER_PUBLIC_LOCATION=http:\/\/localhost:8888\/geoserver\//' .env -sed -i 's/SITEURL=.*/SITEURL=http:\/\/localhost:8888\//' .env -sed -i 's/GEONODE_LB_PORT=80/GEONODE_LB_PORT=8888/' .env -chown -R vagrant:vagrant /home/vagrant/generated-project -sudo docker-compose build -sudo docker-compose up -d diff --git a/generated-project-vagrant-swarm.sh b/generated-project-vagrant-swarm.sh deleted file mode 100644 index 773370c2..00000000 --- a/generated-project-vagrant-swarm.sh +++ /dev/null @@ -1,22 +0,0 @@ - -#!/usr/bin/env bash -# this is the generated-project script to create an generated-project canary project. -sudo docker swarm init -source /usr/share/virtualenvwrapper/virtualenvwrapper.sh -mkvirtualenv --python=/usr/bin/python3 generated-project -pip install Django==3.2.16 -rm -rf generated-project -django-admin startproject --template=/home/vagrant/geonode-project -e py,sh,md,rst,json,yml,ini,env,sample,properties -n monitoring-cron -n Dockerfile generated-project -cd /home/vagrant/generated-project -python create-envfile.py --geonodepwd geonode \ - --geoserverpwd geoserver \ - --pgpwd postgres \ - --dbpwd geonode \ - --geodbpwd geonode -sed -i 's/GEOSERVER_WEB_UI_LOCATION=http:\/\/localhost\/geoserver\//GEOSERVER_WEB_UI_LOCATION=http:\/\/localhost:8888\/geoserver\//' .env -sed -i 's/GEOSERVER_PUBLIC_LOCATION=http:\/\/localhost\/geoserver\//GEOSERVER_PUBLIC_LOCATION=http:\/\/localhost:8888\/geoserver\//' .env -sed -i 's/SITEURL=.*/SITEURL=http:\/\/localhost:8888\//' .env -sed -i 's/GEONODE_LB_PORT=80/GEONODE_LB_PORT=8888/' .env -chown -R vagrant:vagrant /home/vagrant/generated-project -sudo docker-compose -f ./geonode-stack.yml build -sudo docker stack deploy -c ./geonode-stack.yml geonode-stack diff --git a/geonode-stack.yml b/geonode-stack.yml deleted file mode 100644 index 97b1b064..00000000 --- a/geonode-stack.yml +++ /dev/null @@ -1,165 +0,0 @@ -version: '3.9' - -# Common Django template for GeoNode and Celery services below -x-common-django: - &default-common-django - image: django:latest - env_file: - - .env - volumes: - # - '.:/usr/src/{{project_name}}' - - statics:/mnt/volumes/statics - - geoserver-data-dir:/geoserver_data/data - - backup-restore:/backup_restore - - data:/data - - tmp:/tmp - -# Common template for service restart policy -x-common-swarm-deploy: - &default-common-swarm-deploy - replicas: 1 - restart_policy: - condition: any - delay: 0s - max_attempts: 10 - window: 60s - -services: - - # Our custom django application. It includes Geonode. - django: - << : *default-common-django - deploy: *default-common-swarm-deploy - build: - context: ./ - dockerfile: Dockerfile - healthcheck: - test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null http://127.0.0.1:8000/" - interval: 60s - timeout: 10s - retries: 1 - start_period: 60s - environment: - IS_CELERY: 'False' - entrypoint: ["/usr/src/{{project_name}}/entrypoint.sh"] - command: "uwsgi --ini /usr/src/{{project_name}}/uwsgi.ini" - - # Celery worker that executes celery tasks created by Django. - celery: - << : *default-common-django - deploy: *default-common-swarm-deploy - depends_on: - - django - environment: - - IS_CELERY=True - entrypoint: ["/usr/src/{{project_name}}/entrypoint.sh"] - command: "celery-cmd" - - # Nginx is serving django static and media files and proxies to django and geonode - geonode: - deploy: *default-common-swarm-deploy - image: geonode/nginx:3.x - build: ./docker/nginx/ - environment: - - HTTPS_HOST=localhost - - HTTP_HOST=localhost - - HTTPS_PORT=443 - - HTTP_PORT=80 - - LETSENCRYPT_MODE=disabled - - RESOLVER=127.0.0.11 - env_file: - - .env - ports: - - "${HTTP_PORT}:80" - - "${HTTPS_PORT}:443" - volumes: - - nginx-confd:/etc/nginx - - nginx-certificates:/geonode-certificates - - statics:/mnt/volumes/statics - - # Gets and installs letsencrypt certificates - letsencrypt: - deploy: *default-common-swarm-deploy - image: geonode/letsencrypt:latest - build: ./docker/letsencrypt/ - environment: - - HTTPS_HOST=localhost - - HTTP_HOST=localhost - - ADMIN_EMAIL=admin@localhost - - LETSENCRYPT_MODE=disabled - env_file: - - .env - volumes: - - nginx-certificates:/geonode-certificates - - # Geoserver backend - geoserver: - deploy: *default-common-swarm-deploy - image: geonode/geoserver:2.20.6 - build: ./docker/geoserver/ - env_file: - - .env - healthcheck: - test: curl --fail -s http://localhost:8080/geoserver/rest/workspaces/geonode.html || exit 1 - interval: 60s - timeout: 10s - retries: 1 - start_period: 60s - volumes: - - statics:/mnt/volumes/statics - - geoserver-data-dir:/geoserver_data/data - - backup-restore:/backup_restore - - data:/data - - tmp:/tmp - - data-dir-conf: - image: geonode/geoserver_data:2.20.6 - command: /bin/true - volumes: - - geoserver-data-dir:/geoserver_data/data - - # PostGIS database. - db: - deploy: *default-common-swarm-deploy - # use geonode official postgis 13 image - image: geonode/postgis:13 - command: postgres -c "max_connections=${POSTGRESQL_MAX_CONNECTIONS}" - volumes: - - dbdata:/var/lib/postgresql/data - - dbbackups:/pg_backups - env_file: - - .env - # uncomment to enable remote connections to postgres - #ports: - # - "5432:5432" - - # Vanilla RabbitMQ service. This is needed by celery - rabbitmq: - deploy: *default-common-swarm-deploy - image: rabbitmq:3.7-alpine - volumes: - - rabbitmq:/var/lib/rabbitmq - env_file: - - .env - -volumes: - statics: - name: statics - nginx-confd: - name: nginxconfd - nginx-certificates: - name: nginxcerts - geoserver-data-dir: - name: gsdatadir - dbdata: - name: dbdata - dbbackups: - name: dbbackups - backup-restore: - name: backup-restore - data: - name: data - tmp: - name: tmp - rabbitmq: - name: rabbitmq diff --git a/geonode/fixtures/README.md b/geonode/fixtures/README.md new file mode 100644 index 00000000..87b1bdfd --- /dev/null +++ b/geonode/fixtures/README.md @@ -0,0 +1,7 @@ +# Load data + +https://docs.djangoproject.com/en/4.2/topics/db/fixtures/ + + +* Do a `python manage.py loaddata ` to load fixtures into the database. +* Offer an automatic load function for all fixtures found under this directory. diff --git a/geonode/sample_app/README.md b/geonode/sample_app/README.md new file mode 100644 index 00000000..819cab4c --- /dev/null +++ b/geonode/sample_app/README.md @@ -0,0 +1,4 @@ +# Sample App + + +This is an example app which is being configured under `INSTALLED_APPS` property you can find in the `settings.py` file. \ No newline at end of file diff --git a/geonode/sample_app/__init__.py b/geonode/sample_app/__init__.py new file mode 100644 index 00000000..789eb212 --- /dev/null +++ b/geonode/sample_app/__init__.py @@ -0,0 +1,28 @@ +import os +from django.apps import AppConfig +from django.conf.urls import include, url +from django.db.models import Max + +import logging +logger = logging.getLogger(__name__) + + +def run_setup_hooks(*args, **kwargs): + from django.conf import settings + from geonode.urls import urlpatterns + from geonode.base.models import Menu, MenuItem, MenuPlaceholder + + # implement some setup hooks, adjust urls, etc. ... + pass + + +class SampleAppConfig(AppConfig): + name = 'sample_app' + type = 'GEONODE_APP' + + def ready(self): + super().ready() + run_setup_hooks() + + +default_app_config = 'sample_app.SampleAppConfig' diff --git a/geonode/settings.py b/geonode/settings.py new file mode 100644 index 00000000..5492c750 --- /dev/null +++ b/geonode/settings.py @@ -0,0 +1,6 @@ + +# load the defaults settings +from geonode.settings import * + + +INSTALLED_APPS += ( "sample_app",) \ No newline at end of file diff --git a/playbook.yml b/playbook.yml deleted file mode 100644 index 7e0e97b3..00000000 --- a/playbook.yml +++ /dev/null @@ -1,46 +0,0 @@ -- name: Provision a GeoNode into Production - hosts: production - remote_user: ubuntu - vars: - app_name: {{ project_name }} - github_user: geonode - server_name: 0.0.0.0 - deploy_user: ubuntu - code_repository: https://github.com/-----/{{ project_name }}.git" # e.g., "https://github.com/GeoNode/{{ project_name }}.git" - branch_name: master - virtualenv_dir: "/home/ubuntu/.venvs" - site_url: "http://localhost:8000/" # The public url of the GeoNode instance - geoserver_url: "https://artifacts.geonode.org/geoserver/2.20.6/geoserver.war" # geoserver_url should match what is found in dev_config.yml - pg_max_connections: 100 - pg_shared_buffers: 128MB - tomcat_xms: "1024M" - tomcat_xmx: "2048M" - nginx_client_max_body_size: "400M" - letsencrypt: False - gather_facts: False - pre_tasks: - - name: Install python for Ansible - become: yes - become_user: root - raw: test -e /usr/bin/python || (apt -y update && apt install -y python3-minimal) - - name: 'Reconfigue Locales' - become: yes - become_user: root - shell: "{{ item }}" - with_items: - - "export LANGUAGE=en_US.UTF-8" - - "export LANG=en_US.UTF-8" - - "export LC_ALL=en_US.UTF-8" - - "locale-gen --purge en_US.UTF-8" - - "echo 'LANG=en_US.UTF-8\nLANGUAGE=en_US:en\n' > /etc/default/locale" - - name: "Install cul, vim, and unzip" - become: yes - become_user: root - apt: name="{{ item }}" state=latest - with_items: - - curl - - vim - - unzip - - setup: # aka gather_facts - roles: - - { role: GeoNode.geonode } diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index bc22e6d7..00000000 --- a/src/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -up: - # bring up the services - docker-compose up -d - -build: - docker-compose build django - docker-compose build celery - -sync: - # set up the database tablea - docker-compose run django python manage.py makemigrations --noinput - docker-compose exec django python manage.py migrate account --noinput - docker-compose run django python manage.py migrate --noinput - -wait: - sleep 5 - -logs: - docker-compose logs --follow - -down: - docker-compose down - -test: - docker-compose run django python manage.py test --failfast - -reset: down up wait sync - -hardreset: pull build reset diff --git a/src/README.md b/src/README.md deleted file mode 100644 index f76040c3..00000000 --- a/src/README.md +++ /dev/null @@ -1 +0,0 @@ -# {{ project_name|title }} diff --git a/src/celery-cmd b/src/celery-cmd deleted file mode 100755 index a1c7fbd9..00000000 --- a/src/celery-cmd +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -# A configurable celery command. -# Luca Pasquali -CELERY_BIN=${CELERY_BIN:-"$(which celery||echo celery)"} -CELERY_APP=${CELERY_APP:-"geonode.celery_app:app"} -CELERY__STATE_DB=${CELERY__STATE_DB:-"/mnt/volumes/statics/worker.state"} -# expressed in KB -CELERY__MAX_MEMORY_PER_CHILD=${CELERY__MAX_MEMORY_PER_CHILD:-"200000"} -CELERY__AUTOSCALE_VALUES=${CELERY__AUTOSCALE_VALUES:-"15,10"} -CELERY__MAX_TASKS_PER_CHILD=${CELERY__MAX_TASKS_PER_CHILD:-"10"} -CELERY__OPTS=${CELERY__OPTS:-"--without-gossip --without-mingle -Ofair -B -E"} -CELERY__BEAT_SCHEDULE=${CELERY__BEAT_SCHEDULE:-"celery.beat:PersistentScheduler"} -CELERY__LOG_LEVEL=${CELERY__LOG_LEVEL:-"INFO"} -CELERY__LOG_FILE=${CELERY__LOG_FILE:-"/var/log/celery.log"} -CELERY__WORKER_NAME=${CELERY__WORKER_NAME:-"worker1@%h"} -CELERY__WORKER_CONCURRENCY=${CELERY__WORKER_CONCURRENCY:-"4"} - -$CELERY_BIN -A $CELERY_APP worker --autoscale=$CELERY__AUTOSCALE_VALUES \ - --max-memory-per-child=$CELERY__MAX_MEMORY_PER_CHILD $CELERY__OPTS \ - --statedb=$CELERY__STATE_DB --scheduler=$CELERY__BEAT_SCHEDULE \ - --loglevel=$CELERY__LOG_LEVEL -n $CELERY__WORKER_NAME -f $CELERY__LOG_FILE \ - --concurrency=$CELERY__WORKER_CONCURRENCY --max-tasks-per-child=$CELERY__MAX_TASKS_PER_CHILD diff --git a/src/celery.sh b/src/celery.sh deleted file mode 100644 index f5746569..00000000 --- a/src/celery.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -nohup celery -A geonode.celery_app:app beat -l DEBUG -f /var/log/celery.log &>/dev/null & -nohup celery -A geonode.celery_app:app worker --without-gossip --without-mingle -Ofair -B -E --statedb=worker.state --scheduler=celery.beat:PersistentScheduler --loglevel=INFO --concurrency=2 -n worker1@%h -f /var/log/celery.log &>/dev/null & -nohup celery -A geonode.celery_app:app flower --auto_refresh=True --debug=False --broker=${BROKER_URL} --basic_auth=${ADMIN_USERNAME}:${ADMIN_PASSWORD} --address=0.0.0.0 --port=5555 &>/dev/null & \ No newline at end of file diff --git a/src/dev_config.yml b/src/dev_config.yml deleted file mode 100644 index 3fa02cd7..00000000 --- a/src/dev_config.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -GEOSERVER_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geoserver.war" -DATA_DIR_URL: "https://artifacts.geonode.org/geoserver/2.23.0/geonode-geoserver-ext-web-app-data.zip" -JETTY_RUNNER_URL: "https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.31.v20200723/jetty-runner-9.4.31.v20200723.jar" -WINDOWS: - py2exe: "http://downloads.sourceforge.net/project/py2exe/py2exe/0.6.9/py2exe-0.6.9.win32-py2.7.exe" - pyproj: "https://pyproj.googlecode.com/files/pyproj-1.9.3.win32-py2.7.exe" - lxml: "https://pypi.python.org/packages/2.7/l/lxml/lxml-3.6.0.win32-py2.7.exe" diff --git a/src/entrypoint.sh b/src/entrypoint.sh deleted file mode 100755 index 9d1d10de..00000000 --- a/src/entrypoint.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash - -# Exit script in case of error -set -e - -INVOKE_LOG_STDOUT=${INVOKE_LOG_STDOUT:-FALSE} -invoke () { - if [ $INVOKE_LOG_STDOUT = 'true' ] || [ $INVOKE_LOG_STDOUT = 'True' ] - then - /usr/local/bin/invoke $@ - else - /usr/local/bin/invoke $@ > /usr/src/{{project_name}}/invoke.log 2>&1 - fi - echo "$@ tasks done" -} - -# Start cron && memcached services -service cron restart -service memcached restart - -echo $"\n\n\n" -echo "-----------------------------------------------------" -echo "STARTING DJANGO ENTRYPOINT $(date)" -echo "-----------------------------------------------------" - -invoke update - -source $HOME/.bashrc -source $HOME/.override_env - -echo DOCKER_API_VERSION=$DOCKER_API_VERSION -echo POSTGRES_USER=$POSTGRES_USER -echo POSTGRES_PASSWORD=$POSTGRES_PASSWORD -echo DATABASE_URL=$DATABASE_URL -echo GEODATABASE_URL=$GEODATABASE_URL -echo SITEURL=$SITEURL -echo ALLOWED_HOSTS=$ALLOWED_HOSTS -echo GEOSERVER_PUBLIC_LOCATION=$GEOSERVER_PUBLIC_LOCATION -echo MONITORING_ENABLED=$MONITORING_ENABLED -echo MONITORING_HOST_NAME=$MONITORING_HOST_NAME -echo MONITORING_SERVICE_NAME=$MONITORING_SERVICE_NAME -echo MONITORING_DATA_TTL=$MONITORING_DATA_TTL - -# invoke waitfordbs - -cmd="$@" - -if [ ${IS_CELERY} = "true" ] || [ ${IS_CELERY} = "True" ] -then - echo "Executing Celery server $cmd for Production" -else - - invoke migrations - invoke prepare - - if [ ${FORCE_REINIT} = "true" ] || [ ${FORCE_REINIT} = "True" ] || [ ! -e "/mnt/volumes/statics/geonode_init.lock" ]; then - invoke updategeoip - invoke fixtures - invoke monitoringfixture - invoke initialized - invoke updateadmin - fi - - invoke statics - - echo "Executing UWSGI server $cmd for Production" -fi - -echo "-----------------------------------------------------" -echo "FINISHED DJANGO ENTRYPOINT --------------------------" -echo "-----------------------------------------------------" - -# Run the CMD -echo "got command $cmd" -exec $cmd diff --git a/src/fixtures/apikey_docker.json b/src/fixtures/apikey_docker.json deleted file mode 100644 index 1c98b668..00000000 --- a/src/fixtures/apikey_docker.json +++ /dev/null @@ -1,11 +0,0 @@ -[ - { - "fields": { - "user": 1000, - "key": "pyxW5djJ7XsjeFUXduAsGpR4xMGUwpeBGQRqTeT3", - "created": "2018-06-28T14:54:51Z" - }, - "model": "tastypie.apikey", - "pk": 1 - } -] \ No newline at end of file diff --git a/src/fixtures/default_oauth_apps.json b/src/fixtures/default_oauth_apps.json deleted file mode 100644 index 41b8bd9d..00000000 --- a/src/fixtures/default_oauth_apps.json +++ /dev/null @@ -1,21 +0,0 @@ -[ -{ - "model": "oauth2_provider.application", - "pk": 1001, - "fields": { - "skip_authorization": true, - "created": "2018-05-31T10:00:31.661Z", - "updated": "2018-05-31T11:30:31.245Z", - "algorithm": "RS256", - "redirect_uris": "http://localhost:8080/geoserver/index.html\nhttp://localhost/geoserver/index.html", - "name": "GeoServer", - "authorization_grant_type": "authorization-code", - "client_type": "confidential", - "client_id": "Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV", - "client_secret": "rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3", - "user": [ - "admin" - ] - } -} -] diff --git a/src/fixtures/default_oauth_apps_docker.json b/src/fixtures/default_oauth_apps_docker.json deleted file mode 100644 index 975680f6..00000000 --- a/src/fixtures/default_oauth_apps_docker.json +++ /dev/null @@ -1,21 +0,0 @@ -[ -{ - "model": "oauth2_provider.application", - "pk": 1001, - "fields": { - "skip_authorization": true, - "created": "2018-05-31T10:00:31.661Z", - "updated": "2018-05-31T11:30:31.245Z", - "algorithm": "RS256", - "redirect_uris": "http://geonode/geoserver", - "name": "GeoServer", - "authorization_grant_type": "authorization-code", - "client_type": "confidential", - "client_id": "Jrchz2oPY3akmzndmgUTYrs9gczlgoV20YPSvqaV", - "client_secret": "rCnp5txobUo83EpQEblM8fVj3QT5zb5qRfxNsuPzCqZaiRyIoxM4jdgMiZKFfePBHYXCLd7B8NlkfDBY9HKeIQPcy5Cp08KQNpRHQbjpLItDHv12GvkSeXp6OxaUETv3", - "user": [ - "admin" - ] - } -} -] diff --git a/src/fixtures/django_celery_beat.json b/src/fixtures/django_celery_beat.json deleted file mode 100644 index 66c2b6a6..00000000 --- a/src/fixtures/django_celery_beat.json +++ /dev/null @@ -1,72 +0,0 @@ -[ - { - "model": "django_celery_beat.intervalschedule", - "pk": 1, - "fields": { - "every": 60, - "period": "seconds" - } - }, - { - "model": "django_celery_beat.crontabschedule", - "pk": 1, - "fields": { - "minute": "0", - "hour": "4", - "day_of_week": "*", - "day_of_month": "*", - "month_of_year": "*" - } - }, - { - "model": "django_celery_beat.periodictasks", - "pk": 1, - "fields": { - "last_update": "2019-10-14T12:56:49.352Z" - } - }, - { - "model": "django_celery_beat.periodictask", - "pk": 1, - "fields": { - "name": "celery.backend_cleanup", - "task": "celery.backend_cleanup", - "interval": null, - "crontab": 1, - "solar": null, - "args": "[]", - "kwargs": "{}", - "queue": null, - "exchange": null, - "routing_key": null, - "expires": null, - "enabled": true, - "last_run_at": null, - "total_run_count": 0, - "date_changed": "2019-10-14T12:50:54.847Z", - "description": "" - } - }, - { - "model": "django_celery_beat.periodictask", - "pk": 2, - "fields": { - "name": "delayed-security-sync-task", - "task": "geonode.security.tasks.synch_guardian", - "interval": 1, - "crontab": null, - "solar": null, - "args": "[]", - "kwargs": "{}", - "queue": null, - "exchange": null, - "routing_key": null, - "expires": null, - "enabled": true, - "last_run_at": null, - "total_run_count": 0, - "date_changed": "2019-10-14T12:56:37.554Z", - "description": "" - } - } -] \ No newline at end of file diff --git a/src/fixtures/initial_data.json b/src/fixtures/initial_data.json deleted file mode 100644 index f025e795..00000000 --- a/src/fixtures/initial_data.json +++ /dev/null @@ -1,4877 +0,0 @@ -[ - { - "pk": 1, - "model": "base.topiccategory", - "fields": { - "description": "Information pertaining to earth sciences. Examples: geophysical features and processes, geology, minerals, sciences dealing with the composition, structure and origin of the earth s rocks, risks of earthquakes, volcanic activity, landslides, gravity information, soils, permafrost, hydrogeology, erosion.", - "gn_description": "Geoscientific Information", - "is_choice": true, - "fa_class": "fa-bullseye", - "identifier": "geoscientificInformation" - } - }, - { - "pk": 2, - "model": "base.topiccategory", - "fields": { - "description": "Rearing of animals and/or cultivation of plants. Examples: agriculture, irrigation, aquaculture, plantations, herding, pests and diseases affecting crops and livestock.", - "gn_description": "Farming", - "is_choice": true, - "fa_class": "fa-lemon-o", - "identifier": "farming" - } - }, - { - "pk": 3, - "model": "base.topiccategory", - "fields": { - "description": "Height above or below sea level. Examples: altitude, bathymetry, digital elevation models, slope, derived products.", - "gn_description": "Elevation", - "is_choice": true, - "fa_class": "fa-flag", - "identifier": "elevation" - } - }, - { - "pk": 4, - "model": "base.topiccategory", - "fields": { - "description": "Energy, water and waste systems and communications infrastructure and services. Examples: hydroelectricity, geothermal, solar and nuclear sources of energy, water purification and distribution, sewage collection and disposal, electricity and gas distribution, data communication, telecommunication, radio, communication networks.", - "gn_description": "Utilities Communication", - "is_choice": true, - "fa_class": "fa-phone", - "identifier": "utilitiesCommunication" - } - }, - { - "pk": 5, - "model": "base.topiccategory", - "fields": { - "description": "Features and characteristics of salt water bodies (excluding inland waters). Examples: tides, tidal waves, coastal information, reefs.", - "gn_description": "Oceans", - "is_choice": true, - "fa_class": "fa-anchor", - "identifier": "oceans" - } - }, - { - "pk": 6, - "model": "base.topiccategory", - "fields": { - "description": "Legal land descriptions. Examples: political and administrative boundaries.", - "gn_description": "Boundaries", - "is_choice": true, - "fa_class": "fa-ellipsis-h", - "identifier": "boundaries" - } - }, - { - "pk": 7, - "model": "base.topiccategory", - "fields": { - "description": "Inland water features, drainage systems and their characteristics. Examples: rivers and glaciers, salt lakes, water utilization plans, dams, currents, floods, water quality, hydrographic charts.", - "gn_description": "Inland Waters", - "is_choice": true, - "fa_class": "fa-tint", - "identifier": "inlandWaters" - } - }, - { - "pk": 8, - "model": "base.topiccategory", - "fields": { - "description": "Military bases, structures, activities. Examples: barracks, training grounds, military transportation, information collection.", - "gn_description": "Intelligence Military", - "is_choice": true, - "fa_class": "fa-fighter-jet", - "identifier": "intelligenceMilitary" - } - }, - { - "pk": 9, - "model": "base.topiccategory", - "fields": { - "description": "Environmental resources, protection and conservation. Examples: environmental pollution, waste storage and treatment, environmental impact assessment, monitoring environmental risk, nature reserves, landscape.", - "gn_description": "Environment", - "is_choice": true, - "fa_class": "fa-tree", - "identifier": "environment" - } - }, - { - "pk": 10, - "model": "base.topiccategory", - "fields": { - "description": "Positional information and services. Examples: addresses, geodetic networks, control points, postal zones and services, place names.", - "gn_description": "Location", - "is_choice": true, - "fa_class": "fa-map-marker", - "identifier": "location" - } - }, - { - "pk": 11, - "model": "base.topiccategory", - "fields": { - "description": "Economic activities, conditions and employment. Examples: production, labour, revenue, commerce, industry, tourism and ecotourism, forestry, fisheries, commercial or subsistence hunting, exploration and exploitation of resources such as minerals, oil and gas.", - "gn_description": "Economy", - "is_choice": true, - "fa_class": "fa-shopping-cart", - "identifier": "economy" - } - }, - { - "pk": 12, - "model": "base.topiccategory", - "fields": { - "description": "Information used for appropriate actions for future use of the land. Examples: land use maps, zoning maps, cadastral surveys, land ownership.", - "gn_description": "Planning Cadastre", - "is_choice": true, - "fa_class": "fa-home", - "identifier": "planningCadastre" - } - }, - { - "pk": 13, - "model": "base.topiccategory", - "fields": { - "description": "Flora and/or fauna in natural environment. Examples: wildlife, vegetation, biological sciences, ecology, wilderness, sealife, wetlands, habitat.", - "gn_description": "Biota", - "is_choice": true, - "fa_class": "fa-leaf", - "identifier": "biota" - } - }, - { - "pk": 14, - "model": "base.topiccategory", - "fields": { - "description": "Health, health services, human ecology, and safety. Examples: disease and illness, factors affecting health, hygiene, substance abuse, mental and physical health, health services.", - "gn_description": "Health", - "is_choice": true, - "fa_class": "fa-stethoscope", - "identifier": "health" - } - }, - { - "pk": 15, - "model": "base.topiccategory", - "fields": { - "description": "Base maps. Examples: land cover, topographic maps, imagery, unclassified images, annotations.", - "gn_description": "Imagery Base Maps Earth Cover", - "is_choice": true, - "fa_class": "fa-globe", - "identifier": "imageryBaseMapsEarthCover" - } - }, - { - "pk": 16, - "model": "base.topiccategory", - "fields": { - "description": "Means and aids for conveying persons and/or goods. Examples: roads, airports/airstrips, shipping routes, tunnels, nautical charts, vehicle or vessel location, aeronautical charts, railways.", - "gn_description": "Transportation", - "is_choice": true, - "fa_class": "fa-truck", - "identifier": "transportation" - } - }, - { - "pk": 17, - "model": "base.topiccategory", - "fields": { - "description": "Characteristics of society and cultures. Examples: settlements, anthropology, archaeology, education, traditional beliefs, manners and customs, demographic data, recreational areas and activities, social impact assessments, crime and justice, census information.", - "gn_description": "Society", - "is_choice": true, - "fa_class": "fa-comments", - "identifier": "society" - } - }, - { - "pk": 18, - "model": "base.topiccategory", - "fields": { - "description": "Man-made construction. Examples: buildings, museums, churches, factories, housing, monuments, shops, towers.", - "gn_description": "Structure", - "is_choice": true, - "fa_class": "fa-building", - "identifier": "structure" - } - }, - { - "pk": 19, - "model": "base.topiccategory", - "fields": { - "description": "Processes and phenomena of the atmosphere. Examples: cloud cover, weather, climate, atmospheric conditions, climate change, precipitation.", - "gn_description": "Climatology Meteorology Atmosphere", - "is_choice": true, - "fa_class": "fa-cloud", - "identifier": "climatologyMeteorologyAtmosphere" - } - }, - { - "pk": 20, - "model": "base.topiccategory", - "fields": { - "description": "Settlements, anthropology, archaeology, education, traditional beliefs, manners and customs, demographic data, recreational areas and activities, social impact assessments, crime and justice, census information. Economic activities, conditions and employment.", - "gn_description": "Population", - "is_choice": true, - "fa_class": "fa-male", - "identifier": "population" - } - }, - { - "pk": 1, - "model": "base.spatialrepresentationtype", - "fields": { - "is_choice": true, - "gn_description": "vector data is used to represent geographic data", - "identifier": "vector", - "description": "vector data is used to represent geographic data" - } - }, - { - "pk": 2, - "model": "base.spatialrepresentationtype", - "fields": { - "is_choice": true, - "gn_description": "grid data is used to represent geographic data", - "identifier": "grid", - "description": "grid data is used to represent geographic data" - } - }, - { - "pk": 3, - "model": "base.spatialrepresentationtype", - "fields": { - "is_choice": true, - "gn_description": "textual or tabular data is used to represent geographic data", - "identifier": "textTable", - "description": "textual or tabular data is used to represent geographic data" - } - }, - { - "pk": 4, - "model": "base.spatialrepresentationtype", - "fields": { - "is_choice": true, - "gn_description": "triangulated irregular network", - "identifier": "tin", - "description": "triangulated irregular network" - } - }, - { - "pk": 5, - "model": "base.spatialrepresentationtype", - "fields": { - "is_choice": true, - "gn_description": "three-dimensional view formed by the intersecting homologous rays of an overlapping pair of images", - "identifier": "stereoModel", - "description": "three-dimensional view formed by the intersecting homologous rays of an overlapping pair of images" - } - }, - { - "pk": 6, - "model": "base.spatialrepresentationtype", - "fields": { - "is_choice": true, - "gn_description": "scene from a video recording", - "identifier": "video", - "description": "scene from a video recording" - } - }, - { - "pk": 1, - "model": "base.license", - "fields": { - "identifier": "not_specified", - "name":"Not Specified", - "abbreviation":"", - "description":"The original author did not specify a license.", - "url":"", - "license_text":"Not applicable" - } - }, -{ - "pk": 2, - "model": "base.license", - "fields": { - "identifier":"varied_original", - "name":"Varied / Original", - "abbreviation":"", - "description":"This item is either licensed under multiple licenses. See the item's abstract for more information or contact the distributor.", - "url":"", - "license_text":"Not applicable" - } - }, - { - "pk": 3, - "model": "base.license", - "fields": { - "identifier":"varied_derived", - "name":"Varied / Derived", - "abbreviation":"", - "description":"The constituent parts of this item have different licenses. Go to each part to see license information.", - "url":"", - "license_text":"Not applicable" - } - }, - { - "pk": 4, - "model": "base.license", - "fields": { - "identifier":"public_domain", - "name":"Public Domain", - "abbreviation":"PD", - "description":"Works in the public domain may be used freely without the permission of the former copyright owner.", - "url":"http://www.copyright.gov/help/faq/faq-definitions.html", - "license_text":"The public domain is not a place. A work of authorship is in the “public domain” if it is no longer under copyright protection or if it failed to meet the requirements for copyright protection. Works in the public domain may be used freely without the permission of the former copyright owner." - } - }, - { - "pk": 5, - "model": "base.license", - "fields": { - "identifier":"public_domain_usg", - "name":"Public Domain / USG", - "abbreviation":"PD/USG", - "description":"This project constitutes a work of the United States Government and is not subject to domestic copyright protection under 17 USC § 105.", - "url":"https://raw.githubusercontent.com/state-hiu/cybergis-licenses/master/licenses/PUBLICDOMAIN-LICENSE-RAW.txt", - "license_text":"This project constitutes a work of the United States Government and is not subject to domestic copyright protection under 17 USC § 105." - } - }, - { - "pk": 6, - "model": "base.license", - "fields": { - "identifier":"odbl", - "name":"Open Data Commons Open Database License / OSM", - "abbreviation":"ODbL/OSM", - "description":"You are free to copy, distribute, transmit and adapt our data, as long as you credit OpenStreetMap and its contributors\nIf you alter or build upon our data, you may distribute the result only under the same licence.", - "url":"http://www.openstreetmap.org/copyright", - "license_text":"" - } - }, - { - "pk": 7, - "model": "base.license", - "fields": { - "identifier":"nextview", - "name":"NextView", - "abbreviation":"NV", - "description":"This data is licensed for use by the US Government (USG) under the NextView (NV) license and copyrighted by Digital Globe or GeoEye. The NV license allows the USG to share the imagery and Literal Imagery Derived Products (LIDP) with entities outside the USG when that entity is working directly with the USG, for the USG, or in a manner that is directly beneficial to the USG. The party receiving the data can only use the imagery or LIDP for the original purpose or only as otherwise agreed to by the USG. The party receiving the data cannot share the imagery or LIDP with a third party without express permission from the USG. At no time should this imagery or LIDP be used for other than USG-related purposes and must not be used for commercial gain. The copyright information should be maintained at all times. Your acceptance of these license terms is implied by your use.\nIn other words, you may only use NextView imagery linked from this site for digitizing OpenStreetMap data for humanitarian purposes.", - "url":"https://raw.githubusercontent.com/state-hiu/cybergis-licenses/master/licenses/NEXTVIEW-LICENSE-RAW.txt", - "license_text":"" - } - }, - { - "pk": 1, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "exclusive right to the publication, production, or sale of the rights to a literary, dramatic, musical, or artistic work, or to the use of a commercial print or label, granted by law for a specified period of time to an author, composer, artist, distributor", - "identifier": "copyright", - "description": "exclusive right to the publication, production, or sale of the rights to a literary, dramatic, musical, or artistic work, or to the use of a commercial print or label, granted by law for a specified period of time to an author, composer, artist, distributor" - } - }, - { - "pk": 6, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "rights to financial benefit from and control of distribution of non-tangible property that is a result of creativity", - "identifier": "intellectualPropertyRights", - "description": "rights to financial benefit from and control of distribution of non-tangible property that is a result of creativity" - } - }, - { - "pk": 5, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "formal permission to do something", - "identifier": "license", - "description": "formal permission to do something" - } - }, - { - "pk": 8, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "otherRestrictions", - "identifier": "limitation not listed", - "description": "otherRestrictions" - } - }, - { - "pk": 2, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "government has granted exclusive right to make, sell, use or license an invention or discovery", - "identifier": "patent", - "description": "government has granted exclusive right to make, sell, use or license an invention or discovery" - } - }, - { - "pk": 3, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "produced or sold information awaiting a patent", - "identifier": "patentPending", - "description": "produced or sold information awaiting a patent" - } - }, - { - "pk": 7, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "withheld from general circulation or disclosure", - "identifier": "restricted", - "description": "withheld from general circulation or disclosure" - } - }, - { - "pk": 4, - "model": "base.restrictioncodetype", - "fields": { - "is_choice": true, - "gn_description": "a name, symbol, or other device identifying a product, officially registered and legally restricted to the use of the owner or manufacturer", - "identifier": "trademark", - "description": "a name, symbol, or other device identifying a product, officially registered and legally restricted to the use of the owner or manufacturer" - } - }, - { - "pk": 1, - "model": "base.region", - "fields": { - "rght": 516, - "code": "GLO", - "name": "Global", - "parent": null, - "level": 0, - "lft": 1, - "tree_id": 90, - "bbox_x0": -180, - "bbox_x1": 180, - "bbox_y0": -90, - "bbox_y1": 90 - } - }, - { - "pk": 2, - "model": "base.region", - "fields": { - "rght": 212, - "code": "NAM", - "name": "North America", - "parent": 254, - "level": 2, - "lft": 203, - "tree_id": 90, - "bbox_x0": -167.276413, - "bbox_x1": -52.23304, - "bbox_y0": 5.49955, - "bbox_y1": 83.162102 - } - }, - { - "pk": 3, - "model": "base.region", - "fields": { - "rght": 202, - "code": "CAM", - "name": "Central America", - "parent": 254, - "level": 2, - "lft": 187, - "tree_id": 90, - "bbox_x0": -118.867172, - "bbox_x1": -66.869827, - "bbox_y0": -4.23048, - "bbox_y1": 32.71862 - } - }, - { - "pk": 4, - "model": "base.region", - "fields": { - "rght": 242, - "code": "SAM", - "name": "South America", - "parent": 254, - "level": 2, - "lft": 213, - "tree_id": 90, - "bbox_x0": -109.47493, - "bbox_x1": -26.33247, - "bbox_y0": -59.450451, - "bbox_y1": 13.39029 - } - }, - { - "pk": 5, - "model": "base.region", - "fields": { - "rght": 433, - "code": "EUR", - "name": "Europe", - "parent": null, - "level": 1, - "lft": 318, - "tree_id": 90, - "bbox_x0": -31.266001, - "bbox_x1": 39.869301, - "bbox_y0": 27.636311, - "bbox_y1": 81.008797 - } - }, - { - "pk": 6, - "model": "base.region", - "fields": { - "rght": 317, - "code": "ASI", - "name": "Asia", - "parent": null, - "level": 1, - "lft": 246, - "tree_id": 90, - "bbox_x0": 19.6381, - "bbox_x1": 180, - "bbox_y0": -12.56111, - "bbox_y1": 82.50045 - } - }, - { - "pk": 7, - "model": "base.region", - "fields": { - "rght": 316, - "code": "SEA", - "name": "Southeast Asia", - "parent": 6, - "level": 2, - "lft": 293, - "tree_id": 90, - "bbox_x0": 68.0327, - "bbox_x1": 141.021805, - "bbox_y0": -12.56111, - "bbox_y1": 35.504211 - } - }, - { - "pk": 8, - "model": "base.region", - "fields": { - "rght": 260, - "code": "CTA", - "name": "Central Asia", - "parent": 6, - "level": 2, - "lft": 247, - "tree_id": 90, - "bbox_x0": 44.236641, - "bbox_x1": 90.076767, - "bbox_y0": 33.890511, - "bbox_y1": 54.845139 - } - }, - { - "pk": 9, - "model": "base.region", - "fields": { - "rght": 292, - "code": "SAS", - "name": "South Asia", - "parent": 6, - "level": 2, - "lft": 277, - "tree_id": 90, - "bbox_x0": 19.6381, - "bbox_x1": 180, - "bbox_y0": -12.56111, - "bbox_y1": 82.50045 - } - }, - { - "pk": 10, - "model": "base.region", - "fields": { - "rght": 127, - "code": "AFR", - "name": "Africa", - "parent": null, - "level": 1, - "lft": 2, - "tree_id": 90, - "bbox_x0": -25.35874, - "bbox_x1": 63.525379, - "bbox_y0": -46.900452, - "bbox_y1": 37.56712 - } - }, - { - "pk": 11, - "model": "base.region", - "fields": { - "rght": 64, - "code": "NAF", - "name": "North Africa", - "parent": 10, - "level": 2, - "lft": 49, - "tree_id": 90, - "bbox_x0": -17.10317, - "bbox_x1": 38.833801, - "bbox_y0": 3.48639, - "bbox_y1": 37.56712 - } - }, - { - "pk": 12, - "model": "base.region", - "fields": { - "rght": 48, - "code": "EAF", - "name": "East Africa", - "parent": 10, - "level": 2, - "lft": 13, - "tree_id": 90, - "bbox_x0": 22.855089, - "bbox_x1": 63.94656, - "bbox_y0": -25.84763, - "bbox_y1": 17.467039 - } - }, - { - "pk": 13, - "model": "base.region", - "fields": { - "rght": 126, - "code": "WAF", - "name": "West Africa", - "parent": 10, - "level": 2, - "lft": 83, - "tree_id": 90, - "bbox_x0": -26.758421, - "bbox_x1": 24.002661, - "bbox_y0": -9.29925, - "bbox_y1": 27.702801 - } - }, - { - "pk": 14, - "model": "base.region", - "fields": { - "rght": 82, - "code": "SAF", - "name": "Southern Africa", - "parent": 10, - "level": 2, - "lft": 65, - "tree_id": 90, - "bbox_x0": 8.93107, - "bbox_x1": 42.74847, - "bbox_y0": -35.507481, - "bbox_y1": -13.27553 - } - }, - { - "pk": 15, - "model": "base.region", - "fields": { - "rght": 463, - "code": "MES", - "name": "Middle East", - "parent": null, - "level": 1, - "lft": 434, - "tree_id": 90, - "bbox_x0": 24.698099, - "bbox_x1": 63.317459, - "bbox_y0": 12.111, - "bbox_y1": 42.10751 - } - }, - { - "pk": 16, - "model": "base.region", - "fields": { - "rght": 245, - "code": "ANT", - "name": "Antarctica", - "parent": null, - "level": 1, - "lft": 244, - "tree_id": 90, - "bbox_x0": -180, - "bbox_x1": 180, - "bbox_y0": -90, - "bbox_y1": -73 - } - }, - { - "pk": 17, - "model": "base.region", - "fields": { - "rght": 249, - "code": "AFG", - "name": "Afghanistan", - "parent": 8, - "level": 3, - "lft": 248, - "tree_id": 90, - "bbox_x0": 60.478439, - "bbox_x1": 74.879433, - "bbox_y0": 29.37747, - "bbox_y1": 38.483421 - } - }, - { - "pk": 18, - "model": "base.region", - "fields": { - "rght": 320, - "code": "ALA", - "name": "Aland Islands", - "parent": 5, - "level": 2, - "lft": 319, - "tree_id": 90, - "bbox_x0": 19.262711, - "bbox_x1": 21.324409, - "bbox_y0": 59.736301, - "bbox_y1": 60.665581 - } - }, - { - "pk": 19, - "model": "base.region", - "fields": { - "rght": 322, - "code": "ALB", - "name": "Albania", - "parent": 5, - "level": 2, - "lft": 321, - "tree_id": 90, - "bbox_x0": 19.28219, - "bbox_x1": 21.057819, - "bbox_y0": 39.644489, - "bbox_y1": 42.660801 - } - }, - { - "pk": 20, - "model": "base.region", - "fields": { - "rght": 51, - "code": "DZA", - "name": "Algeria", - "parent": 11, - "level": 3, - "lft": 50, - "tree_id": 90, - "bbox_x0": -8.67386, - "bbox_x1": 11.97955, - "bbox_y0": 18.96002, - "bbox_y1": 37.093731 - } - }, - { - "pk": 21, - "model": "base.region", - "fields": { - "rght": 466, - "code": "ASM", - "name": "American Samoa", - "parent": 256, - "level": 2, - "lft": 465, - "tree_id": 90, - "bbox_x0": -171.091873, - "bbox_x1": -169.416077, - "bbox_y0": -14.38247, - "bbox_y1": -11.04969 - } - }, - { - "pk": 22, - "model": "base.region", - "fields": { - "rght": 324, - "code": "AND", - "name": "Andorra", - "parent": 5, - "level": 2, - "lft": 323, - "tree_id": 90, - "bbox_x0": 1.41382, - "bbox_x1": 1.78659, - "bbox_y0": 42.42873, - "bbox_y1": 42.65601 - } - }, - { - "pk": 23, - "model": "base.region", - "fields": { - "rght": 85, - "code": "AGO", - "name": "Angola", - "parent": 13, - "level": 3, - "lft": 84, - "tree_id": 90, - "bbox_x0": 11.6792, - "bbox_x1": 24.082109, - "bbox_y0": -18.04207, - "bbox_y1": -4.37259 - } - }, - { - "pk": 24, - "model": "base.region", - "fields": { - "rght": 131, - "code": "AIA", - "name": "Anguilla", - "parent": 255, - "level": 3, - "lft": 130, - "tree_id": 90, - "bbox_x0": -63.434872, - "bbox_x1": -62.916199, - "bbox_y0": 18.149549, - "bbox_y1": 18.61278 - } - }, - { - "pk": 25, - "model": "base.region", - "fields": { - "rght": 133, - "code": "ATG", - "name": "Antigua and Barbuda", - "parent": 255, - "level": 3, - "lft": 132, - "tree_id": 90, - "bbox_x0": -62.352402, - "bbox_x1": -61.659081, - "bbox_y0": 16.927219, - "bbox_y1": 17.72938 - } - }, - { - "pk": 26, - "model": "base.region", - "fields": { - "rght": 215, - "code": "ARG", - "name": "Argentina", - "parent": 4, - "level": 3, - "lft": 214, - "tree_id": 90, - "bbox_x0": -73.577782, - "bbox_x1": -53.637539, - "bbox_y0": -55.057362, - "bbox_y1": -21.78126 - } - }, - { - "pk": 27, - "model": "base.region", - "fields": { - "rght": 326, - "code": "ARM", - "name": "Armenia", - "parent": 5, - "level": 2, - "lft": 325, - "tree_id": 90, - "bbox_x0": 43.449749, - "bbox_x1": 46.630039, - "bbox_y0": 38.830521, - "bbox_y1": 41.30183 - } - }, - { - "pk": 28, - "model": "base.region", - "fields": { - "rght": 135, - "code": "ABW", - "name": "Aruba", - "parent": 255, - "level": 3, - "lft": 134, - "tree_id": 90, - "bbox_x0": -70.0611, - "bbox_x1": -69.8669, - "bbox_y0": 12.4061, - "bbox_y1": 12.6306 - } - }, - { - "pk": 29, - "model": "base.region", - "fields": { - "rght": 468, - "code": "AUS", - "name": "Australia", - "parent": 256, - "level": 2, - "lft": 467, - "tree_id": 90, - "bbox_x0": 112.921112, - "bbox_x1": 159.278717, - "bbox_y0": -54.640301, - "bbox_y1": -9.22882 - } - }, - { - "pk": 30, - "model": "base.region", - "fields": { - "rght": 328, - "code": "AUT", - "name": "Austria", - "parent": 5, - "level": 2, - "lft": 327, - "tree_id": 90, - "bbox_x0": 9.53079, - "bbox_x1": 17.160749, - "bbox_y0": 46.372299, - "bbox_y1": 49.02071 - } - }, - { - "pk": 31, - "model": "base.region", - "fields": { - "rght": 330, - "code": "AZE", - "name": "Azerbaijan", - "parent": 5, - "level": 2, - "lft": 329, - "tree_id": 90, - "bbox_x0": 44.7719, - "bbox_x1": 50.6078, - "bbox_y0": 38.3970, - "bbox_y1": 41.9056 - } - }, - { - "pk": 32, - "model": "base.region", - "fields": { - "rght": 137, - "code": "BHS", - "name": "Bahamas", - "parent": 255, - "level": 3, - "lft": 136, - "tree_id": 90, - "bbox_x0": -80.499229, - "bbox_x1": -72.649513, - "bbox_y0": 20.916059, - "bbox_y1": 27.933781 - } - }, - { - "pk": 33, - "model": "base.region", - "fields": { - "rght": 436, - "code": "BHR", - "name": "Bahrain", - "parent": 15, - "level": 2, - "lft": 435, - "tree_id": 90, - "bbox_x0": 50.385799, - "bbox_x1": 50.828499, - "bbox_y0": 25.5422, - "bbox_y1": 26.292391 - } - }, - { - "pk": 34, - "model": "base.region", - "fields": { - "rght": 279, - "code": "BGD", - "name": "Bangladesh", - "parent": 9, - "level": 3, - "lft": 278, - "tree_id": 90, - "bbox_x0": 88.028198, - "bbox_x1": 92.673599, - "bbox_y0": 20.585199, - "bbox_y1": 26.631701 - } - }, - { - "pk": 35, - "model": "base.region", - "fields": { - "rght": 139, - "code": "BRB", - "name": "Barbados", - "parent": 255, - "level": 3, - "lft": 138, - "tree_id": 90, - "bbox_x0": -59.648918, - "bbox_x1": -59.420368, - "bbox_y0": 13.03984, - "bbox_y1": 13.32725 - } - }, - { - "pk": 36, - "model": "base.region", - "fields": { - "rght": 332, - "code": "BLR", - "name": "Belarus", - "parent": 5, - "level": 2, - "lft": 331, - "tree_id": 90, - "bbox_x0": 23.17679, - "bbox_x1": 32.77071, - "bbox_y0": 51.256401, - "bbox_y1": 56.16571 - } - }, - { - "pk": 37, - "model": "base.region", - "fields": { - "rght": 334, - "code": "BEL", - "name": "Belgium", - "parent": 5, - "level": 2, - "lft": 333, - "tree_id": 90, - "bbox_x0": 2.54563, - "bbox_x1": 6.40791, - "bbox_y0": 49.496899, - "bbox_y1": 51.505081 - } - }, - { - "pk": 38, - "model": "base.region", - "fields": { - "rght": 189, - "code": "BLZ", - "name": "Belize", - "parent": 3, - "level": 3, - "lft": 188, - "tree_id": 90, - "bbox_x0": -89.224823, - "bbox_x1": -87.468132, - "bbox_y0": 15.8893, - "bbox_y1": 18.49655 - } - }, - { - "pk": 39, - "model": "base.region", - "fields": { - "rght": 87, - "code": "BEN", - "name": "Benin", - "parent": 13, - "level": 3, - "lft": 86, - "tree_id": 90, - "bbox_x0": 0.77456, - "bbox_x1": 3.8517, - "bbox_y0": 6.22574, - "bbox_y1": 12.41834 - } - }, - { - "pk": 40, - "model": "base.region", - "fields": { - "rght": 141, - "code": "BMU", - "name": "Bermuda", - "parent": 255, - "level": 3, - "lft": 140, - "tree_id": 90, - "bbox_x0": -64.896042, - "bbox_x1": -64.642952, - "bbox_y0": 32.230709, - "bbox_y1": 32.393829 - } - }, - { - "pk": 41, - "model": "base.region", - "fields": { - "rght": 281, - "code": "BTN", - "name": "Bhutan", - "parent": 9, - "level": 3, - "lft": 280, - "tree_id": 90, - "bbox_x0": 88.759521, - "bbox_x1": 92.125023, - "bbox_y0": 26.7075, - "bbox_y1": 28.3235 - } - }, - { - "pk": 42, - "model": "base.region", - "fields": { - "rght": 217, - "code": "BOL", - "name": "Bolivia", - "parent": 4, - "level": 3, - "lft": 216, - "tree_id": 90, - "bbox_x0": -69.640762, - "bbox_x1": -57.458092, - "bbox_y0": -22.89613, - "bbox_y1": -9.68056 - } - }, - { - "pk": 43, - "model": "base.region", - "fields": { - "rght": 336, - "code": "BIH", - "name": "Bosnia and Herzegovina", - "parent": 5, - "level": 2, - "lft": 335, - "tree_id": 90, - "bbox_x0": 15.74909, - "bbox_x1": 19.62907, - "bbox_y0": 42.56451, - "bbox_y1": 45.276001 - } - }, - { - "pk": 44, - "model": "base.region", - "fields": { - "rght": 67, - "code": "BWA", - "name": "Botswana", - "parent": 14, - "level": 3, - "lft": 66, - "tree_id": 90, - "bbox_x0": 19.999531, - "bbox_x1": 29.360781, - "bbox_y0": -26.90724, - "bbox_y1": -17.780809 - } - }, - { - "pk": 45, - "model": "base.region", - "fields": { - "rght": 219, - "code": "BRA", - "name": "Brazil", - "parent": 4, - "level": 3, - "lft": 218, - "tree_id": 90, - "bbox_x0": -73.985527, - "bbox_x1": -28.839041, - "bbox_y0": -33.750702, - "bbox_y1": 5.26486 - } - }, - { - "pk": 46, - "model": "base.region", - "fields": { - "rght": 143, - "code": "VGB", - "name": "British Virgin Islands", - "parent": 255, - "level": 3, - "lft": 142, - "tree_id": 90, - "bbox_x0": -64.783012, - "bbox_x1": -64.268761, - "bbox_y0": 18.312731, - "bbox_y1": 18.757219 - } - }, - { - "pk": 47, - "model": "base.region", - "fields": { - "rght": 295, - "code": "BRN", - "name": "Brunei Darussalam", - "parent": 7, - "level": 3, - "lft": 294, - "tree_id": 90, - "bbox_x0": 114.071457, - "bbox_x1": 115.359451, - "bbox_y0": 4.00309, - "bbox_y1": 5.04717 - } - }, - { - "pk": 48, - "model": "base.region", - "fields": { - "rght": 338, - "code": "BGR", - "name": "Bulgaria", - "parent": 5, - "level": 2, - "lft": 337, - "tree_id": 90, - "bbox_x0": 22.35741, - "bbox_x1": 28.60882, - "bbox_y0": 41.235931, - "bbox_y1": 44.227261 - } - }, - { - "pk": 49, - "model": "base.region", - "fields": { - "rght": 89, - "code": "BFA", - "name": "Burkina Faso", - "parent": 13, - "level": 3, - "lft": 88, - "tree_id": 90, - "bbox_x0": -5.51891, - "bbox_x1": 2.40539, - "bbox_y0": 9.4011, - "bbox_y1": 15.08259 - } - }, - { - "pk": 50, - "model": "base.region", - "fields": { - "rght": 15, - "code": "BDI", - "name": "Burundi", - "parent": 12, - "level": 3, - "lft": 14, - "tree_id": 90, - "bbox_x0": 28.993071, - "bbox_x1": 30.847719, - "bbox_y0": -4.46571, - "bbox_y1": -2.31012 - } - }, - { - "pk": 51, - "model": "base.region", - "fields": { - "rght": 297, - "code": "KHM", - "name": "Cambodia", - "parent": 7, - "level": 3, - "lft": 296, - "tree_id": 90, - "bbox_x0": 102.340012, - "bbox_x1": 107.627724, - "bbox_y0": 9.28325, - "bbox_y1": 14.6864 - } - }, - { - "pk": 52, - "model": "base.region", - "fields": { - "rght": 91, - "code": "CMR", - "name": "Cameroon", - "parent": 13, - "level": 3, - "lft": 90, - "tree_id": 90, - "bbox_x0": 8.49477, - "bbox_x1": 16.19211, - "bbox_y0": 1.65254, - "bbox_y1": 13.07805 - } - }, - { - "pk": 53, - "model": "base.region", - "fields": { - "rght": 205, - "code": "CAN", - "name": "Canada", - "parent": 2, - "level": 3, - "lft": 204, - "tree_id": 90, - "bbox_x0": -141.002701, - "bbox_x1": -52.620201, - "bbox_y0": 41.681019, - "bbox_y1": 83.110619 - } - }, - { - "pk": 54, - "model": "base.region", - "fields": { - "rght": 93, - "code": "CPV", - "name": "Cape Verde", - "parent": 13, - "level": 3, - "lft": 92, - "tree_id": 90, - "bbox_x0": -25.35874, - "bbox_x1": -22.666201, - "bbox_y0": 14.80221, - "bbox_y1": 17.19717 - } - }, - { - "pk": 55, - "model": "base.region", - "fields": { - "rght": 145, - "code": "CYM", - "name": "Cayman Islands", - "parent": 255, - "level": 3, - "lft": 144, - "tree_id": 90, - "bbox_x0": -81.420593, - "bbox_x1": -79.722321, - "bbox_y0": 19.262659, - "bbox_y1": 19.75738 - } - }, - { - "pk": 56, - "model": "base.region", - "fields": { - "rght": 5, - "code": "CAF", - "name": "Central African Republic", - "parent": 257, - "level": 3, - "lft": 4, - "tree_id": 90, - "bbox_x0": 14.42009, - "bbox_x1": 27.463421, - "bbox_y0": 2.22051, - "bbox_y1": 11.00756 - } - }, - { - "pk": 57, - "model": "base.region", - "fields": { - "rght": 7, - "code": "TCD", - "name": "Chad", - "parent": 257, - "level": 3, - "lft": 6, - "tree_id": 90, - "bbox_x0": 13.47592, - "bbox_x1": 24.00161, - "bbox_y0": 7.44237, - "bbox_y1": 23.478239 - } - }, - { - "pk": 58, - "model": "base.region", - "fields": { - "rght": 340, - "code": "CIL", - "name": "Channel Islands", - "parent": 5, - "level": 2, - "lft": 339, - "tree_id": 90, - "bbox_x0": -2.67545, - "bbox_x1": -2.01129, - "bbox_y0": 49.16209, - "bbox_y1": 49.7393 - } - }, - { - "pk": 59, - "model": "base.region", - "fields": { - "rght": 221, - "code": "CHL", - "name": "Chile", - "parent": 4, - "level": 3, - "lft": 220, - "tree_id": 90, - "bbox_x0": -109.47493, - "bbox_x1": -66.417549, - "bbox_y0": -56.533779, - "bbox_y1": -17.507549 - } - }, - { - "pk": 60, - "model": "base.region", - "fields": { - "rght": 263, - "code": "CHN", - "name": "China", - "parent": 258, - "level": 3, - "lft": 262, - "tree_id": 90, - "bbox_x0": 73.557701, - "bbox_x1": 134.773605, - "bbox_y0": 15.77539, - "bbox_y1": 53.5606 - } - }, - { - "pk": 61, - "model": "base.region", - "fields": { - "rght": 265, - "code": "HKG", - "name": "China - Hong Kong", - "parent": 258, - "level": 3, - "lft": 264, - "tree_id": 90, - "bbox_x0": 113.835083, - "bbox_x1": 114.441788, - "bbox_y0": 22.153549, - "bbox_y1": 22.56204 - } - }, - { - "pk": 62, - "model": "base.region", - "fields": { - "rght": 267, - "code": "MAC", - "name": "China - Macao", - "parent": 258, - "level": 3, - "lft": 266, - "tree_id": 90, - "bbox_x0": 113.528351, - "bbox_x1": 113.598297, - "bbox_y0": 22.10977, - "bbox_y1": 22.21697 - } - }, - { - "pk": 63, - "model": "base.region", - "fields": { - "rght": 223, - "code": "COL", - "name": "Colombia", - "parent": 4, - "level": 3, - "lft": 222, - "tree_id": 90, - "bbox_x0": -81.728111, - "bbox_x1": -66.869827, - "bbox_y0": -4.23048, - "bbox_y1": 13.39029 - } - }, - { - "pk": 64, - "model": "base.region", - "fields": { - "rght": 17, - "code": "COM", - "name": "Comoros", - "parent": 12, - "level": 3, - "lft": 16, - "tree_id": 90, - "bbox_x0": 43.215778, - "bbox_x1": 44.538219, - "bbox_y0": -12.41382, - "bbox_y1": -11.36238 - } - }, - { - "pk": 65, - "model": "base.region", - "fields": { - "rght": 9, - "code": "COG", - "name": "Congo", - "parent": 257, - "level": 3, - "lft": 8, - "tree_id": 90, - "bbox_x0": 11.205, - "bbox_x1": 18.64983, - "bbox_y0": -5.02831, - "bbox_y1": 3.70308 - } - }, - { - "pk": 66, - "model": "base.region", - "fields": { - "rght": 470, - "code": "COK", - "name": "Cook Islands", - "parent": 256, - "level": 2, - "lft": 469, - "tree_id": 90, - "bbox_x0": -165.858093, - "bbox_x1": -157.312119, - "bbox_y0": -21.94416, - "bbox_y1": -8.94402 - } - }, - { - "pk": 67, - "model": "base.region", - "fields": { - "rght": 191, - "code": "CRI", - "name": "Costa Rica", - "parent": 3, - "level": 3, - "lft": 190, - "tree_id": 90, - "bbox_x0": -87.083778, - "bbox_x1": -82.556, - "bbox_y0": 5.49955, - "bbox_y1": 11.21681 - } - }, - { - "pk": 68, - "model": "base.region", - "fields": { - "rght": 95, - "code": "CIV", - "name": "Cote d'Ivoire", - "parent": 13, - "level": 3, - "lft": 94, - "tree_id": 90, - "bbox_x0": -8.6017249, - "bbox_x1": -2.4930309, - "bbox_y0": 4.1642077, - "bbox_y1": 10.740015 - } - }, - { - "pk": 69, - "model": "base.region", - "fields": { - "rght": 342, - "code": "HRV", - "name": "Croatia", - "parent": 5, - "level": 2, - "lft": 341, - "tree_id": 90, - "bbox_x0": 13.48972, - "bbox_x1": 19.44722, - "bbox_y0": 42.392208, - "bbox_y1": 46.554981 - } - }, - { - "pk": 70, - "model": "base.region", - "fields": { - "rght": 147, - "code": "CUB", - "name": "Cuba", - "parent": 255, - "level": 3, - "lft": 146, - "tree_id": 90, - "bbox_x0": -84.957428, - "bbox_x1": -74.131783, - "bbox_y0": 19.828079, - "bbox_y1": 23.283779 - } - }, - { - "pk": 71, - "model": "base.region", - "fields": { - "rght": 344, - "code": "CYP", - "name": "Cyprus", - "parent": 5, - "level": 2, - "lft": 343, - "tree_id": 90, - "bbox_x0": 32.27309, - "bbox_x1": 34.597919, - "bbox_y0": 34.563511, - "bbox_y1": 35.701542 - } - }, - { - "pk": 72, - "model": "base.region", - "fields": { - "rght": 346, - "code": "CZE", - "name": "Czech Republic", - "parent": 5, - "level": 2, - "lft": 345, - "tree_id": 90, - "bbox_x0": 12.0905901, - "bbox_x1": 18.859216, - "bbox_y0": 48.5518144, - "bbox_y1": 51.0557036 - } - }, - { - "pk": 73, - "model": "base.region", - "fields": { - "rght": 269, - "code": "PRK", - "name": "Democratic People's Republic of Korea", - "parent": 258, - "level": 3, - "lft": 268, - "tree_id": 90, - "bbox_x0": 124.182739, - "bbox_x1": 130.674713, - "bbox_y0": 37.632881, - "bbox_y1": 43.006001 - } - }, - { - "pk": 74, - "model": "base.region", - "fields": { - "rght": 11, - "code": "COD", - "name": "Democratic Republic of the Congo", - "parent": 257, - "level": 3, - "lft": 10, - "tree_id": 90, - "bbox_x0": 12.20663, - "bbox_x1": 31.30591, - "bbox_y0": -13.45567, - "bbox_y1": 5.38609 - } - }, - { - "pk": 75, - "model": "base.region", - "fields": { - "rght": 348, - "code": "DNK", - "name": "Denmark", - "parent": 5, - "level": 2, - "lft": 347, - "tree_id": 90, - "bbox_x0": 8.07472, - "bbox_x1": 15.19324, - "bbox_y0": 54.559132, - "bbox_y1": 57.751949 - } - }, - { - "pk": 76, - "model": "base.region", - "fields": { - "rght": 19, - "code": "DJI", - "name": "Djibouti", - "parent": 12, - "level": 3, - "lft": 18, - "tree_id": 90, - "bbox_x0": 41.773441, - "bbox_x1": 43.450459, - "bbox_y0": 10.90991, - "bbox_y1": 12.70683 - } - }, - { - "pk": 77, - "model": "base.region", - "fields": { - "rght": 149, - "code": "DMA", - "name": "Dominica", - "parent": 255, - "level": 3, - "lft": 148, - "tree_id": 90, - "bbox_x0": -61.4841, - "bbox_x1": -61.244148, - "bbox_y0": 15.20168, - "bbox_y1": 15.6318 - } - }, - { - "pk": 78, - "model": "base.region", - "fields": { - "rght": 151, - "code": "DOM", - "name": "Dominican Republic", - "parent": 255, - "level": 3, - "lft": 150, - "tree_id": 90, - "bbox_x0": -72.003479, - "bbox_x1": -68.319992, - "bbox_y0": 17.469299, - "bbox_y1": 19.92985 - } - }, - { - "pk": 79, - "model": "base.region", - "fields": { - "rght": 225, - "code": "ECU", - "name": "Ecuador", - "parent": 4, - "level": 3, - "lft": 224, - "tree_id": 90, - "bbox_x0": -91.66124, - "bbox_x1": -75.200073, - "bbox_y0": -5.01734, - "bbox_y1": 1.45421 - } - }, - { - "pk": 80, - "model": "base.region", - "fields": { - "rght": 53, - "code": "EGY", - "name": "Egypt", - "parent": 11, - "level": 3, - "lft": 52, - "tree_id": 90, - "bbox_x0": 24.698099, - "bbox_x1": 36.89468, - "bbox_y0": 22, - "bbox_y1": 31.674179 - } - }, - { - "pk": 81, - "model": "base.region", - "fields": { - "rght": 193, - "code": "SLV", - "name": "El Salvador", - "parent": 3, - "level": 3, - "lft": 192, - "tree_id": 90, - "bbox_x0": -90.12867, - "bbox_x1": -87.682869, - "bbox_y0": 13.14867, - "bbox_y1": 14.44506 - } - }, - { - "pk": 82, - "model": "base.region", - "fields": { - "rght": 97, - "code": "GNQ", - "name": "Equatorial Guinea", - "parent": 13, - "level": 3, - "lft": 96, - "tree_id": 90, - "bbox_x0": 5.60236, - "bbox_x1": 11.33572, - "bbox_y0": -1.48378, - "bbox_y1": 3.78597 - } - }, - { - "pk": 83, - "model": "base.region", - "fields": { - "rght": 21, - "code": "ERI", - "name": "Eritrea", - "parent": 12, - "level": 3, - "lft": 20, - "tree_id": 90, - "bbox_x0": 36.43877, - "bbox_x1": 43.14864, - "bbox_y0": 12.35956, - "bbox_y1": 18.00308 - } - }, - { - "pk": 84, - "model": "base.region", - "fields": { - "rght": 350, - "code": "EST", - "name": "Estonia", - "parent": 5, - "level": 2, - "lft": 349, - "tree_id": 90, - "bbox_x0": 21.771851, - "bbox_x1": 28.20989, - "bbox_y0": 57.509312, - "bbox_y1": 59.685749 - } - }, - { - "pk": 85, - "model": "base.region", - "fields": { - "rght": 23, - "code": "ETH", - "name": "Ethiopia", - "parent": 12, - "level": 3, - "lft": 22, - "tree_id": 90, - "bbox_x0": 32.99992, - "bbox_x1": 47.986172, - "bbox_y0": 3.40242, - "bbox_y1": 14.89218 - } - }, - { - "pk": 86, - "model": "base.region", - "fields": { - "rght": 352, - "code": "FRO", - "name": "Faeroe Islands", - "parent": 5, - "level": 2, - "lft": 351, - "tree_id": 90, - "bbox_x0": -7.68124, - "bbox_x1": -6.25861, - "bbox_y0": 61.394932, - "bbox_y1": 62.400742 - } - }, - { - "pk": 87, - "model": "base.region", - "fields": { - "rght": 227, - "code": "FLK", - "name": "Falkland Islands (Malvinas)", - "parent": 4, - "level": 3, - "lft": 226, - "tree_id": 90, - "bbox_x0": -61.43404, - "bbox_x1": -57.712479, - "bbox_y0": -52.900581, - "bbox_y1": -50.966221 - } - }, - { - "pk": 88, - "model": "base.region", - "fields": { - "rght": 472, - "code": "FJI", - "name": "Fiji", - "parent": 256, - "level": 2, - "lft": 471, - "tree_id": 90, - "bbox_x0": 174.866196, - "bbox_x1": -178.203156, - "bbox_y0": -21.01712, - "bbox_y1": -12.46622 - } - }, - { - "pk": 89, - "model": "base.region", - "fields": { - "rght": 354, - "code": "FIN", - "name": "Finland", - "parent": 5, - "level": 2, - "lft": 353, - "tree_id": 90, - "bbox_x0": 20.548571, - "bbox_x1": 31.586201, - "bbox_y0": 59.764881, - "bbox_y1": 70.092308 - } - }, - { - "pk": 90, - "model": "base.region", - "fields": { - "rght": 356, - "code": "FRA", - "name": "France", - "parent": 5, - "level": 2, - "lft": 355, - "tree_id": 90, - "bbox_x0": -5.1406, - "bbox_x1": 9.55932, - "bbox_y0": 41.33374, - "bbox_y1": 51.089062 - } - }, - { - "pk": 91, - "model": "base.region", - "fields": { - "rght": 229, - "code": "GUF", - "name": "French Guiana", - "parent": 4, - "level": 3, - "lft": 228, - "tree_id": 90, - "bbox_x0": -54.542511, - "bbox_x1": -51.613941, - "bbox_y0": 2.12709, - "bbox_y1": 5.77649 - } - }, - { - "pk": 92, - "model": "base.region", - "fields": { - "rght": 474, - "code": "PYF", - "name": "French Polynesia", - "parent": 256, - "level": 2, - "lft": 473, - "tree_id": 90, - "bbox_x0": -154.700485, - "bbox_x1": -108.87291, - "bbox_y0": -27.65357, - "bbox_y1": 10.35983 - } - }, - { - "pk": 93, - "model": "base.region", - "fields": { - "rght": 99, - "code": "GAB", - "name": "Gabon", - "parent": 13, - "level": 3, - "lft": 98, - "tree_id": 90, - "bbox_x0": 8.69547, - "bbox_x1": 14.50234, - "bbox_y0": -3.9788, - "bbox_y1": 2.32261 - } - }, - { - "pk": 94, - "model": "base.region", - "fields": { - "rght": 101, - "code": "GMB", - "name": "Gambia", - "parent": 13, - "level": 3, - "lft": 100, - "tree_id": 90, - "bbox_x0": -16.82506, - "bbox_x1": -13.7978, - "bbox_y0": 13.06425, - "bbox_y1": 13.82657 - } - }, - { - "pk": 95, - "model": "base.region", - "fields": { - "rght": 358, - "code": "GEO", - "name": "Georgia", - "parent": 5, - "level": 2, - "lft": 357, - "tree_id": 90, - "bbox_x0": 40.01022, - "bbox_x1": 46.721359, - "bbox_y0": 41.038502, - "bbox_y1": 43.584549 - } - }, - { - "pk": 96, - "model": "base.region", - "fields": { - "rght": 360, - "code": "DEU", - "name": "Germany", - "parent": 5, - "level": 2, - "lft": 359, - "tree_id": 90, - "bbox_x0": 5.86624, - "bbox_x1": 15.04205, - "bbox_y0": 47.27021, - "bbox_y1": 55.05814 - } - }, - { - "pk": 97, - "model": "base.region", - "fields": { - "rght": 103, - "code": "GHA", - "name": "Ghana", - "parent": 13, - "level": 3, - "lft": 102, - "tree_id": 90, - "bbox_x0": -3.25542, - "bbox_x1": 1.19178, - "bbox_y0": 4.73672, - "bbox_y1": 11.1733 - } - }, - { - "pk": 98, - "model": "base.region", - "fields": { - "rght": 362, - "code": "GIB", - "name": "Gibraltar", - "parent": 5, - "level": 2, - "lft": 361, - "tree_id": 90, - "bbox_x0": -5.3579, - "bbox_x1": -5.33867, - "bbox_y0": 36.108219, - "bbox_y1": 36.15593 - } - }, - { - "pk": 99, - "model": "base.region", - "fields": { - "rght": 364, - "code": "GRC", - "name": "Greece", - "parent": 5, - "level": 2, - "lft": 363, - "tree_id": 90, - "bbox_x0": 19.37431, - "bbox_x1": 29.70056, - "bbox_y0": 34.809502, - "bbox_y1": 41.757111 - } - }, - { - "pk": 100, - "model": "base.region", - "fields": { - "rght": 207, - "code": "GRL", - "name": "Greenland", - "parent": 2, - "level": 3, - "lft": 206, - "tree_id": 90, - "bbox_x0": -73.263474, - "bbox_x1": -11.31232, - "bbox_y0": 59.777271, - "bbox_y1": 83.627419 - } - }, - { - "pk": 101, - "model": "base.region", - "fields": { - "rght": 153, - "code": "GRD", - "name": "Grenada", - "parent": 255, - "level": 3, - "lft": 152, - "tree_id": 90, - "bbox_x0": -61.79998, - "bbox_x1": -61.376362, - "bbox_y0": 11.98288, - "bbox_y1": 12.5415 - } - }, - { - "pk": 102, - "model": "base.region", - "fields": { - "rght": 155, - "code": "GLP", - "name": "Guadeloupe", - "parent": 255, - "level": 3, - "lft": 154, - "tree_id": 90, - "bbox_x0": -61.807159, - "bbox_x1": -61, - "bbox_y0": 15.83097, - "bbox_y1": 16.51684 - } - }, - { - "pk": 103, - "model": "base.region", - "fields": { - "rght": 476, - "code": "GUM", - "name": "Guam", - "parent": 256, - "level": 2, - "lft": 475, - "tree_id": 90, - "bbox_x0": 144.619263, - "bbox_x1": 144.953995, - "bbox_y0": 13.24059, - "bbox_y1": 13.65232 - } - }, - { - "pk": 104, - "model": "base.region", - "fields": { - "rght": 195, - "code": "GTM", - "name": "Guatemala", - "parent": 3, - "level": 3, - "lft": 194, - "tree_id": 90, - "bbox_x0": -92.241432, - "bbox_x1": -88.22319, - "bbox_y0": 13.7373, - "bbox_y1": 17.815201 - } - }, - { - "pk": 105, - "model": "base.region", - "fields": { - "rght": 366, - "code": "GGY", - "name": "Guernsey", - "parent": 5, - "level": 2, - "lft": 365, - "tree_id": 90, - "bbox_x0": -2.67545, - "bbox_x1": -2.16382, - "bbox_y0": 49.405762, - "bbox_y1": 49.7393 - } - }, - { - "pk": 106, - "model": "base.region", - "fields": { - "rght": 105, - "code": "GIN", - "name": "Guinea", - "parent": 13, - "level": 3, - "lft": 104, - "tree_id": 90, - "bbox_x0": -15.08625, - "bbox_x1": -7.64106, - "bbox_y0": 7.19355, - "bbox_y1": 12.67621 - } - }, - { - "pk": 107, - "model": "base.region", - "fields": { - "rght": 107, - "code": "GNB", - "name": "Guinea-Bissau", - "parent": 13, - "level": 3, - "lft": 106, - "tree_id": 90, - "bbox_x0": -16.717529, - "bbox_x1": -13.63652, - "bbox_y0": 10.85997, - "bbox_y1": 12.68078 - } - }, - { - "pk": 108, - "model": "base.region", - "fields": { - "rght": 231, - "code": "GUY", - "name": "Guyana", - "parent": 4, - "level": 3, - "lft": 230, - "tree_id": 90, - "bbox_x0": -61.396271, - "bbox_x1": -56.480251, - "bbox_y0": 1.17508, - "bbox_y1": 8.55756 - } - }, - { - "pk": 109, - "model": "base.region", - "fields": { - "rght": 157, - "code": "HTI", - "name": "Haiti", - "parent": 255, - "level": 3, - "lft": 156, - "tree_id": 90, - "bbox_x0": -74.478592, - "bbox_x1": -71.61335, - "bbox_y0": 18.02103, - "bbox_y1": 20.08782 - } - }, - { - "pk": 110, - "model": "base.region", - "fields": { - "rght": 368, - "code": "VAT", - "name": "Holy See (Vatican City)", - "parent": 5, - "level": 2, - "lft": 367, - "tree_id": 90, - "bbox_x0": 12.44584, - "bbox_x1": 12.45842, - "bbox_y0": 41.900211, - "bbox_y1": 41.907459 - } - }, - { - "pk": 111, - "model": "base.region", - "fields": { - "rght": 197, - "code": "HND", - "name": "Honduras", - "parent": 3, - "level": 3, - "lft": 196, - "tree_id": 90, - "bbox_x0": -89.350792, - "bbox_x1": -82.499527, - "bbox_y0": 12.98241, - "bbox_y1": 17.450451 - } - }, - { - "pk": 112, - "model": "base.region", - "fields": { - "rght": 370, - "code": "HUN", - "name": "Hungary", - "parent": 5, - "level": 2, - "lft": 369, - "tree_id": 90, - "bbox_x0": 16.11335, - "bbox_x1": 22.89657, - "bbox_y0": 45.737061, - "bbox_y1": 48.585258 - } - }, - { - "pk": 113, - "model": "base.region", - "fields": { - "rght": 372, - "code": "ISL", - "name": "Iceland", - "parent": 5, - "level": 2, - "lft": 371, - "tree_id": 90, - "bbox_x0": -24.54652, - "bbox_x1": -13.49416, - "bbox_y0": 63.295952, - "bbox_y1": 66.566193 - } - }, - { - "pk": 114, - "model": "base.region", - "fields": { - "rght": 283, - "code": "IND", - "name": "India", - "parent": 9, - "level": 3, - "lft": 282, - "tree_id": 90, - "bbox_x0": 68.032318, - "bbox_x1": 97.403023, - "bbox_y0": 6.7471, - "bbox_y1": 36.261688 - } - }, - { - "pk": 115, - "model": "base.region", - "fields": { - "rght": 299, - "code": "IDN", - "name": "Indonesia", - "parent": 7, - "level": 3, - "lft": 298, - "tree_id": 90, - "bbox_x0": 94.969833, - "bbox_x1": 141.021805, - "bbox_y0": -11.00485, - "bbox_y1": 6.07573 - } - }, - { - "pk": 116, - "model": "base.region", - "fields": { - "rght": 438, - "code": "IRN", - "name": "Iran", - "parent": 15, - "level": 2, - "lft": 437, - "tree_id": 90, - "bbox_x0": 44.047249, - "bbox_x1": 63.317459, - "bbox_y0": 25.064079, - "bbox_y1": 39.777222 - } - }, - { - "pk": 117, - "model": "base.region", - "fields": { - "rght": 440, - "code": "IRQ", - "name": "Iraq", - "parent": 15, - "level": 2, - "lft": 439, - "tree_id": 90, - "bbox_x0": 38.804001, - "bbox_x1": 48.575699, - "bbox_y0": 29.103001, - "bbox_y1": 37.378052 - } - }, - { - "pk": 118, - "model": "base.region", - "fields": { - "rght": 374, - "code": "IRL", - "name": "Ireland", - "parent": 5, - "level": 2, - "lft": 373, - "tree_id": 90, - "bbox_x0": -10.61834, - "bbox_x1": -5.9975, - "bbox_y0": 51.424511, - "bbox_y1": 55.436211 - } - }, - { - "pk": 119, - "model": "base.region", - "fields": { - "rght": 376, - "code": "IMN", - "name": "Isle of Man", - "parent": 5, - "level": 2, - "lft": 375, - "tree_id": 90, - "bbox_x0": -4.83018, - "bbox_x1": -4.31007, - "bbox_y0": 54.04464, - "bbox_y1": 54.418839 - } - }, - { - "pk": 120, - "model": "base.region", - "fields": { - "rght": 442, - "code": "ISR", - "name": "Israel", - "parent": 15, - "level": 2, - "lft": 441, - "tree_id": 90, - "bbox_x0": 34.2677, - "bbox_x1": 35.940941, - "bbox_y0": 29.4965, - "bbox_y1": 33.43338 - } - }, - { - "pk": 121, - "model": "base.region", - "fields": { - "rght": 378, - "code": "ITA", - "name": "Italy", - "parent": 5, - "level": 2, - "lft": 377, - "tree_id": 90, - "bbox_x0": 6.62665, - "bbox_x1": 18.520281, - "bbox_y0": 35.49308, - "bbox_y1": 47.091999 - } - }, - { - "pk": 122, - "model": "base.region", - "fields": { - "rght": 159, - "code": "JAM", - "name": "Jamaica", - "parent": 255, - "level": 3, - "lft": 158, - "tree_id": 90, - "bbox_x0": -78.366638, - "bbox_x1": -75.982857, - "bbox_y0": 16.949551, - "bbox_y1": 18.52697 - } - }, - { - "pk": 123, - "model": "base.region", - "fields": { - "rght": 271, - "code": "JPN", - "name": "Japan", - "parent": 258, - "level": 3, - "lft": 270, - "tree_id": 90, - "bbox_x0": 122.933647, - "bbox_x1": 153.986847, - "bbox_y0": 20.4251, - "bbox_y1": 45.557709 - } - }, - { - "pk": 124, - "model": "base.region", - "fields": { - "rght": 380, - "code": "JEY", - "name": "Jersey", - "parent": 5, - "level": 2, - "lft": 379, - "tree_id": 90, - "bbox_x0": -2.25505, - "bbox_x1": -2.01129, - "bbox_y0": 49.16209, - "bbox_y1": 49.26231 - } - }, - { - "pk": 125, - "model": "base.region", - "fields": { - "rght": 444, - "code": "JOR", - "name": "Jordan", - "parent": 15, - "level": 2, - "lft": 443, - "tree_id": 90, - "bbox_x0": 34.960232, - "bbox_x1": 39.301128, - "bbox_y0": 29.18409, - "bbox_y1": 33.374828 - } - }, - { - "pk": 126, - "model": "base.region", - "fields": { - "rght": 251, - "code": "KAZ", - "name": "Kazakhstan", - "parent": 8, - "level": 3, - "lft": 250, - "tree_id": 90, - "bbox_x0": 46.491859, - "bbox_x1": 87.312737, - "bbox_y0": 40.566689, - "bbox_y1": 55.431808 - } - }, - { - "pk": 127, - "model": "base.region", - "fields": { - "rght": 25, - "code": "KEN", - "name": "Kenya", - "parent": 12, - "level": 3, - "lft": 24, - "tree_id": 90, - "bbox_x0": 33.90884, - "bbox_x1": 41.899059, - "bbox_y0": -4.71712, - "bbox_y1": 4.62933 - } - }, - { - "pk": 128, - "model": "base.region", - "fields": { - "rght": 478, - "code": "KIR", - "name": "Kiribati", - "parent": 256, - "level": 2, - "lft": 477, - "tree_id": 90, - "bbox_x0": 158.418335, - "bbox_x1": -150.208359, - "bbox_y0": -11.43703, - "bbox_y1": 4.71956 - } - }, - { - "pk": 129, - "model": "base.region", - "fields": { - "rght": 446, - "code": "KWT", - "name": "Kuwait", - "parent": 15, - "level": 2, - "lft": 445, - "tree_id": 90, - "bbox_x0": 46.55751, - "bbox_x1": 48.78384, - "bbox_y0": 28.5245, - "bbox_y1": 30.0958 - } - }, - { - "pk": 130, - "model": "base.region", - "fields": { - "rght": 253, - "code": "KGZ", - "name": "Kyrgyzstan", - "parent": 8, - "level": 3, - "lft": 252, - "tree_id": 90, - "bbox_x0": 69.276619, - "bbox_x1": 80.28318, - "bbox_y0": 39.17284, - "bbox_y1": 43.238239 - } - }, - { - "pk": 131, - "model": "base.region", - "fields": { - "rght": 301, - "code": "LAO", - "name": "Lao People's Democratic Republic", - "parent": 7, - "level": 3, - "lft": 300, - "tree_id": 90, - "bbox_x0": 100.093048, - "bbox_x1": 107.697021, - "bbox_y0": 13.91002, - "bbox_y1": 22.500389 - } - }, - { - "pk": 132, - "model": "base.region", - "fields": { - "rght": 382, - "code": "LVA", - "name": "Latvia", - "parent": 5, - "level": 2, - "lft": 381, - "tree_id": 90, - "bbox_x0": 20.966061, - "bbox_x1": 28.244431, - "bbox_y0": 55.67276, - "bbox_y1": 58.087448 - } - }, - { - "pk": 133, - "model": "base.region", - "fields": { - "rght": 448, - "code": "LBN", - "name": "Lebanon", - "parent": 15, - "level": 2, - "lft": 447, - "tree_id": 90, - "bbox_x0": 35.10368, - "bbox_x1": 36.622791, - "bbox_y0": 33.048908, - "bbox_y1": 34.69268 - } - }, - { - "pk": 134, - "model": "base.region", - "fields": { - "rght": 69, - "code": "LSO", - "name": "Lesotho", - "parent": 14, - "level": 3, - "lft": 68, - "tree_id": 90, - "bbox_x0": 27.02906, - "bbox_x1": 29.465771, - "bbox_y0": -30.668961, - "bbox_y1": -28.57205 - } - }, - { - "pk": 135, - "model": "base.region", - "fields": { - "rght": 109, - "code": "LBR", - "name": "Liberia", - "parent": 13, - "level": 3, - "lft": 108, - "tree_id": 90, - "bbox_x0": -11.49208, - "bbox_x1": -7.36511, - "bbox_y0": 4.35305, - "bbox_y1": 8.55179 - } - }, - { - "pk": 136, - "model": "base.region", - "fields": { - "rght": 55, - "code": "LBY", - "name": "Libyan Arab Jamahiriya", - "parent": 11, - "level": 3, - "lft": 54, - "tree_id": 90, - "bbox_x0": 9.38702, - "bbox_x1": 25.15061, - "bbox_y0": 19.508039, - "bbox_y1": 33.168999 - } - }, - { - "pk": 137, - "model": "base.region", - "fields": { - "rght": 384, - "code": "LIE", - "name": "Liechtenstein", - "parent": 5, - "level": 2, - "lft": 383, - "tree_id": 90, - "bbox_x0": 9.47181, - "bbox_x1": 9.63578, - "bbox_y0": 47.04834, - "bbox_y1": 47.270649 - } - }, - { - "pk": 138, - "model": "base.region", - "fields": { - "rght": 386, - "code": "LTU", - "name": "Lithuania", - "parent": 5, - "level": 2, - "lft": 385, - "tree_id": 90, - "bbox_x0": 20.953199, - "bbox_x1": 26.835581, - "bbox_y0": 53.89748, - "bbox_y1": 56.450432 - } - }, - { - "pk": 139, - "model": "base.region", - "fields": { - "rght": 388, - "code": "LUX", - "name": "Luxembourg", - "parent": 5, - "level": 2, - "lft": 387, - "tree_id": 90, - "bbox_x0": 5.73579, - "bbox_x1": 6.53117, - "bbox_y0": 49.447689, - "bbox_y1": 50.182751 - } - }, - { - "pk": 140, - "model": "base.region", - "fields": { - "rght": 390, - "code": "MKD", - "name": "Macedonia", - "parent": 5, - "level": 2, - "lft": 389, - "tree_id": 90, - "bbox_x0": 20.4645, - "bbox_x1": 23.038071, - "bbox_y0": 40.860111, - "bbox_y1": 42.345501 - } - }, - { - "pk": 141, - "model": "base.region", - "fields": { - "rght": 27, - "code": "MDG", - "name": "Madagascar", - "parent": 12, - "level": 3, - "lft": 26, - "tree_id": 90, - "bbox_x0": 43.19138, - "bbox_x1": 50.483799, - "bbox_y0": -25.60894, - "bbox_y1": -11.94543 - } - }, - { - "pk": 142, - "model": "base.region", - "fields": { - "rght": 29, - "code": "MWI", - "name": "Malawi", - "parent": 12, - "level": 3, - "lft": 28, - "tree_id": 90, - "bbox_x0": 32.668991, - "bbox_x1": 35.920441, - "bbox_y0": -17.129459, - "bbox_y1": -9.36468 - } - }, - { - "pk": 143, - "model": "base.region", - "fields": { - "rght": 303, - "code": "MYS", - "name": "Malaysia", - "parent": 7, - "level": 3, - "lft": 302, - "tree_id": 90, - "bbox_x0": 98.935059, - "bbox_x1": 119.448433, - "bbox_y0": 0.66364, - "bbox_y1": 7.58378 - } - }, - { - "pk": 144, - "model": "base.region", - "fields": { - "rght": 285, - "code": "MDV", - "name": "Maldives", - "parent": 9, - "level": 3, - "lft": 284, - "tree_id": 90, - "bbox_x0": 72.616219, - "bbox_x1": 73.76712, - "bbox_y0": -2.90045, - "bbox_y1": 7.11712 - } - }, - { - "pk": 145, - "model": "base.region", - "fields": { - "rght": 111, - "code": "MLI", - "name": "Mali", - "parent": 13, - "level": 3, - "lft": 110, - "tree_id": 90, - "bbox_x0": -12.24261, - "bbox_x1": 4.24495, - "bbox_y0": 10.15951, - "bbox_y1": 25 - } - }, - { - "pk": 146, - "model": "base.region", - "fields": { - "rght": 392, - "code": "MLT", - "name": "Malta", - "parent": 5, - "level": 2, - "lft": 391, - "tree_id": 90, - "bbox_x0": 14.18341, - "bbox_x1": 14.5766, - "bbox_y0": 35.786282, - "bbox_y1": 36.081821 - } - }, - { - "pk": 147, - "model": "base.region", - "fields": { - "rght": 480, - "code": "MHL", - "name": "Marshall Islands", - "parent": 256, - "level": 2, - "lft": 479, - "tree_id": 90, - "bbox_x0": 162.143265, - "bbox_x1": 172.161987, - "bbox_y0": 4.57487, - "bbox_y1": 14.65516 - } - }, - { - "pk": 148, - "model": "base.region", - "fields": { - "rght": 161, - "code": "MTQ", - "name": "Martinique", - "parent": 255, - "level": 3, - "lft": 160, - "tree_id": 90, - "bbox_x0": -61.23011, - "bbox_x1": -60.81551, - "bbox_y0": 14.38244, - "bbox_y1": 14.87881 - } - }, - { - "pk": 149, - "model": "base.region", - "fields": { - "rght": 113, - "code": "MRT", - "name": "Mauritania", - "parent": 13, - "level": 3, - "lft": 112, - "tree_id": 90, - "bbox_x0": -17.066521, - "bbox_x1": -4.8352, - "bbox_y0": 14.71554, - "bbox_y1": 27.298071 - } - }, - { - "pk": 150, - "model": "base.region", - "fields": { - "rght": 31, - "code": "MUS", - "name": "Mauritius", - "parent": 12, - "level": 3, - "lft": 30, - "tree_id": 90, - "bbox_x0": 56.512711, - "bbox_x1": 63.525379, - "bbox_y0": -20.525709, - "bbox_y1": -10.31925 - } - }, - { - "pk": 151, - "model": "base.region", - "fields": { - "rght": 33, - "code": "MYT", - "name": "Mayotte", - "parent": 12, - "level": 3, - "lft": 32, - "tree_id": 90, - "bbox_x0": 45.01461, - "bbox_x1": 45.317131, - "bbox_y0": -13.00045, - "bbox_y1": -12.63383 - } - }, - { - "pk": 152, - "model": "base.region", - "fields": { - "rght": 209, - "code": "MEX", - "name": "Mexico", - "parent": 2, - "level": 3, - "lft": 208, - "tree_id": 90, - "bbox_x0": -118.867172, - "bbox_x1": -86.703392, - "bbox_y0": 14.53285, - "bbox_y1": 32.71862 - } - }, - { - "pk": 153, - "model": "base.region", - "fields": { - "rght": 482, - "code": "FSM", - "name": "Micronesia, Federated States of", - "parent": 256, - "level": 2, - "lft": 481, - "tree_id": 90, - "bbox_x0": 138.052856, - "bbox_x1": 163.034912, - "bbox_y0": 5.25984, - "bbox_y1": 10.02222 - } - }, - { - "pk": 154, - "model": "base.region", - "fields": { - "rght": 394, - "code": "MCO", - "name": "Monaco", - "parent": 5, - "level": 2, - "lft": 393, - "tree_id": 90, - "bbox_x0": 7.4091, - "bbox_x1": 7.43948, - "bbox_y0": 43.724789, - "bbox_y1": 43.7519 - } - }, - { - "pk": 155, - "model": "base.region", - "fields": { - "rght": 273, - "code": "MNG", - "name": "Mongolia", - "parent": 258, - "level": 3, - "lft": 272, - "tree_id": 90, - "bbox_x0": 87.749496, - "bbox_x1": 119.92411, - "bbox_y0": 41.567501, - "bbox_y1": 52.154099 - } - }, - { - "pk": 156, - "model": "base.region", - "fields": { - "rght": 396, - "code": "MNE", - "name": "Montenegro", - "parent": 5, - "level": 2, - "lft": 395, - "tree_id": 90, - "bbox_x0": 18.43705, - "bbox_x1": 20.41608, - "bbox_y0": 41.84808, - "bbox_y1": 43.542912 - } - }, - { - "pk": 157, - "model": "base.region", - "fields": { - "rght": 163, - "code": "MSR", - "name": "Montserrat", - "parent": 255, - "level": 3, - "lft": 162, - "tree_id": 90, - "bbox_x0": -62.24258, - "bbox_x1": -62.14642, - "bbox_y0": 16.671, - "bbox_y1": 16.81732 - } - }, - { - "pk": 158, - "model": "base.region", - "fields": { - "rght": 57, - "code": "MAR", - "name": "Morocco", - "parent": 11, - "level": 3, - "lft": 56, - "tree_id": 90, - "bbox_x0": -11.7805, - "bbox_x1": -1.02441, - "bbox_y0": 26.946489, - "bbox_y1": 35.921909 - } - }, - { - "pk": 159, - "model": "base.region", - "fields": { - "rght": 35, - "code": "MOZ", - "name": "Mozambique", - "parent": 12, - "level": 3, - "lft": 34, - "tree_id": 90, - "bbox_x0": 30.21731, - "bbox_x1": 40.844471, - "bbox_y0": -26.868679, - "bbox_y1": -10.47188 - } - }, - { - "pk": 160, - "model": "base.region", - "fields": { - "rght": 305, - "code": "MMR", - "name": "Myanmar", - "parent": 7, - "level": 3, - "lft": 304, - "tree_id": 90, - "bbox_x0": 92.189209, - "bbox_x1": 101.176788, - "bbox_y0": 9.60035, - "bbox_y1": 28.543249 - } - }, - { - "pk": 161, - "model": "base.region", - "fields": { - "rght": 71, - "code": "NMB", - "name": "Namibia", - "parent": 14, - "level": 3, - "lft": 70, - "tree_id": 90, - "bbox_x0": 11.71563, - "bbox_x1": 25.256701, - "bbox_y0": -28.97142, - "bbox_y1": -16.95989 - } - }, - { - "pk": 162, - "model": "base.region", - "fields": { - "rght": 484, - "code": "NRU", - "name": "Nauru", - "parent": 256, - "level": 2, - "lft": 483, - "tree_id": 90, - "bbox_x0": 166.899017, - "bbox_x1": 166.945267, - "bbox_y0": -0.55232, - "bbox_y1": -0.50429 - } - }, - { - "pk": 163, - "model": "base.region", - "fields": { - "rght": 287, - "code": "NPL", - "name": "Nepal", - "parent": 9, - "level": 3, - "lft": 286, - "tree_id": 90, - "bbox_x0": 80.056221, - "bbox_x1": 88.199318, - "bbox_y0": 26.356501, - "bbox_y1": 30.433001 - } - }, - { - "pk": 164, - "model": "base.region", - "fields": { - "rght": 398, - "code": "NLD", - "name": "Netherlands", - "parent": 5, - "level": 2, - "lft": 397, - "tree_id": 90, - "bbox_x0": 3.35794, - "bbox_x1": 7.2267, - "bbox_y0": 50.750401, - "bbox_y1": 53.554241 - } - }, - { - "pk": 165, - "model": "base.region", - "fields": { - "rght": 165, - "code": "NAN", - "name": "Netherlands Antilles", - "parent": 255, - "level": 3, - "lft": 164, - "tree_id": 90, - "bbox_x0": -69.157188, - "bbox_x1": -62.943661, - "bbox_y0": 11.97318, - "bbox_y1": 18.07024 - } - }, - { - "pk": 166, - "model": "base.region", - "fields": { - "rght": 486, - "code": "NCL", - "name": "New Caledonia", - "parent": 256, - "level": 2, - "lft": 485, - "tree_id": 90, - "bbox_x0": 158.332855, - "bbox_x1": 172.061417, - "bbox_y0": -22.90045, - "bbox_y1": -18.01622 - } - }, - { - "pk": 167, - "model": "base.region", - "fields": { - "rght": 488, - "code": "NZL", - "name": "New Zealand", - "parent": 256, - "level": 2, - "lft": 487, - "tree_id": 90, - "bbox_x0": 165.883804, - "bbox_x1": -175.987198, - "bbox_y0": -52.618591, - "bbox_y1": -29.20997 - } - }, - { - "pk": 168, - "model": "base.region", - "fields": { - "rght": 199, - "code": "NIC", - "name": "Nicaragua", - "parent": 3, - "level": 3, - "lft": 198, - "tree_id": 90, - "bbox_x0": -87.6903, - "bbox_x1": -82.592072, - "bbox_y0": 10.70754, - "bbox_y1": 15.0259 - } - }, - { - "pk": 169, - "model": "base.region", - "fields": { - "rght": 115, - "code": "NER", - "name": "Niger", - "parent": 13, - "level": 3, - "lft": 114, - "tree_id": 90, - "bbox_x0": 0.16625, - "bbox_x1": 15.99564, - "bbox_y0": 11.69697, - "bbox_y1": 23.525021 - } - }, - { - "pk": 170, - "model": "base.region", - "fields": { - "rght": 117, - "code": "NGA", - "name": "Nigeria", - "parent": 13, - "level": 3, - "lft": 116, - "tree_id": 90, - "bbox_x0": 2.66844, - "bbox_x1": 14.68006, - "bbox_y0": 4.27714, - "bbox_y1": 13.892 - } - }, - { - "pk": 171, - "model": "base.region", - "fields": { - "rght": 490, - "code": "NIU", - "name": "Niue", - "parent": 256, - "level": 2, - "lft": 489, - "tree_id": 90, - "bbox_x0": -169.951004, - "bbox_x1": -169.775177, - "bbox_y0": -19.152189, - "bbox_y1": -18.951059 - } - }, - { - "pk": 172, - "model": "base.region", - "fields": { - "rght": 492, - "code": "NFK", - "name": "Norfolk Island", - "parent": 256, - "level": 2, - "lft": 491, - "tree_id": 90, - "bbox_x0": 167.949493, - "bbox_x1": 168.091614, - "bbox_y0": -29.11937, - "bbox_y1": -28.99493 - } - }, - { - "pk": 173, - "model": "base.region", - "fields": { - "rght": 494, - "code": "MNP", - "name": "Northern Mariana Islands", - "parent": 256, - "level": 2, - "lft": 493, - "tree_id": 90, - "bbox_x0": 136.082855, - "bbox_x1": 146.081223, - "bbox_y0": 14.10735, - "bbox_y1": 20.41712 - } - }, - { - "pk": 174, - "model": "base.region", - "fields": { - "rght": 400, - "code": "NOR", - "name": "Norway", - "parent": 5, - "level": 2, - "lft": 399, - "tree_id": 90, - "bbox_x0": 4.43292, - "bbox_x1": 31.168409, - "bbox_y0": 57.962582, - "bbox_y1": 71.185509 - } - }, - { - "pk": 175, - "model": "base.region", - "fields": { - "rght": 450, - "code": "PSE", - "name": "Occupied Palestinian Territory", - "parent": 15, - "level": 2, - "lft": 449, - "tree_id": 90, - "bbox_x0": 34.230461, - "bbox_x1": 35.876499, - "bbox_y0": 31.223499, - "bbox_y1": 33.340099 - } - }, - { - "pk": 176, - "model": "base.region", - "fields": { - "rght": 452, - "code": "OMN", - "name": "Oman", - "parent": 15, - "level": 2, - "lft": 451, - "tree_id": 90, - "bbox_x0": 51.882011, - "bbox_x1": 59.83651, - "bbox_y0": 16.6457, - "bbox_y1": 26.50045 - } - }, - { - "pk": 177, - "model": "base.region", - "fields": { - "rght": 289, - "code": "PAK", - "name": "Pakistan", - "parent": 9, - "level": 3, - "lft": 288, - "tree_id": 90, - "bbox_x0": 60.87859, - "bbox_x1": 77.840813, - "bbox_y0": 23.786699, - "bbox_y1": 37.097 - } - }, - { - "pk": 178, - "model": "base.region", - "fields": { - "rght": 496, - "code": "PLW", - "name": "Palau", - "parent": 256, - "level": 2, - "lft": 495, - "tree_id": 90, - "bbox_x0": 131.169235, - "bbox_x1": 134.723724, - "bbox_y0": 3.00114, - "bbox_y1": 8.09291 - } - }, - { - "pk": 179, - "model": "base.region", - "fields": { - "rght": 201, - "code": "PAN", - "name": "Panama", - "parent": 3, - "level": 3, - "lft": 200, - "tree_id": 90, - "bbox_x0": -83.051453, - "bbox_x1": -77.17411, - "bbox_y0": 7.1979, - "bbox_y1": 9.65045 - } - }, - { - "pk": 180, - "model": "base.region", - "fields": { - "rght": 498, - "code": "PNG", - "name": "Papua New Guinea", - "parent": 256, - "level": 2, - "lft": 497, - "tree_id": 90, - "bbox_x0": 140.842865, - "bbox_x1": 159.48378, - "bbox_y0": -11.65785, - "bbox_y1": -0.86622 - } - }, - { - "pk": 181, - "model": "base.region", - "fields": { - "rght": 233, - "code": "PRY", - "name": "Paraguay", - "parent": 4, - "level": 3, - "lft": 232, - "tree_id": 90, - "bbox_x0": -62.647072, - "bbox_x1": -54.25935, - "bbox_y0": -27.60873, - "bbox_y1": -19.294041 - } - }, - { - "pk": 182, - "model": "base.region", - "fields": { - "rght": 235, - "code": "PER", - "name": "Peru", - "parent": 4, - "level": 3, - "lft": 234, - "tree_id": 90, - "bbox_x0": -81.326736, - "bbox_x1": -68.677979, - "bbox_y0": -18.34972, - "bbox_y1": -0.01297 - } - }, - { - "pk": 183, - "model": "base.region", - "fields": { - "rght": 307, - "code": "PHL", - "name": "Philippines", - "parent": 7, - "level": 3, - "lft": 306, - "tree_id": 90, - "bbox_x0": 116.812721, - "bbox_x1": 126.856628, - "bbox_y0": 4.46811, - "bbox_y1": 21.23415 - } - }, - { - "pk": 184, - "model": "base.region", - "fields": { - "rght": 500, - "code": "PCN", - "name": "Pitcairn", - "parent": 256, - "level": 2, - "lft": 499, - "tree_id": 90, - "bbox_x0": -130.746033, - "bbox_x1": -124.772842, - "bbox_y0": -25.07752, - "bbox_y1": -23.917271 - } - }, - { - "pk": 185, - "model": "base.region", - "fields": { - "rght": 402, - "code": "POL", - "name": "Poland", - "parent": 5, - "level": 2, - "lft": 401, - "tree_id": 90, - "bbox_x0": 14.12281, - "bbox_x1": 24.145781, - "bbox_y0": 49.002022, - "bbox_y1": 54.835812 - } - }, - { - "pk": 186, - "model": "base.region", - "fields": { - "rght": 404, - "code": "PRT", - "name": "Portugal", - "parent": 5, - "level": 2, - "lft": 403, - "tree_id": 90, - "bbox_x0": -31.266001, - "bbox_x1": -6.18931, - "bbox_y0": 30.028061, - "bbox_y1": 42.154121 - } - }, - { - "pk": 187, - "model": "base.region", - "fields": { - "rght": 167, - "code": "PRI", - "name": "Puerto Rico", - "parent": 255, - "level": 3, - "lft": 166, - "tree_id": 90, - "bbox_x0": -67.942719, - "bbox_x1": -65.219978, - "bbox_y0": 17.883039, - "bbox_y1": 18.520161 - } - }, - { - "pk": 188, - "model": "base.region", - "fields": { - "rght": 454, - "code": "QAT", - "name": "Qatar", - "parent": 15, - "level": 2, - "lft": 453, - "tree_id": 90, - "bbox_x0": 50.757011, - "bbox_x1": 52.427509, - "bbox_y0": 24.482901, - "bbox_y1": 26.177509 - } - }, - { - "pk": 189, - "model": "base.region", - "fields": { - "rght": 275, - "code": "KOR", - "name": "Republic of Korea", - "parent": 258, - "level": 3, - "lft": 274, - "tree_id": 90, - "bbox_x0": 124.608147, - "bbox_x1": 130.933899, - "bbox_y0": 33.10611, - "bbox_y1": 38.612301 - } - }, - { - "pk": 190, - "model": "base.region", - "fields": { - "rght": 406, - "code": "MDA", - "name": "Republic of Moldova", - "parent": 5, - "level": 2, - "lft": 405, - "tree_id": 90, - "bbox_x0": 26.618879, - "bbox_x1": 30.16374, - "bbox_y0": 45.468498, - "bbox_y1": 48.490162 - } - }, - { - "pk": 191, - "model": "base.region", - "fields": { - "rght": 37, - "code": "REU", - "name": "Reunion", - "parent": 12, - "level": 3, - "lft": 36, - "tree_id": 90, - "bbox_x0": 55.219082, - "bbox_x1": 55.845039, - "bbox_y0": -21.37221, - "bbox_y1": -20.85685 - } - }, - { - "pk": 192, - "model": "base.region", - "fields": { - "rght": 408, - "code": "ROU", - "name": "Romania", - "parent": 5, - "level": 2, - "lft": 407, - "tree_id": 90, - "bbox_x0": 20.269791, - "bbox_x1": 29.691, - "bbox_y0": 43.626999, - "bbox_y1": 48.266891 - } - }, - { - "pk": 193, - "model": "base.region", - "fields": { - "rght": 410, - "code": "RUS", - "name": "Russian Federation", - "parent": 5, - "level": 2, - "lft": 409, - "tree_id": 90, - "bbox_x0": 19.638861, - "bbox_x1": 180, - "bbox_y0": 41.185902, - "bbox_y1": 81.856903 - } - }, - { - "pk": 194, - "model": "base.region", - "fields": { - "rght": 39, - "code": "RWA", - "name": "Rwanda", - "parent": 12, - "level": 3, - "lft": 38, - "tree_id": 90, - "bbox_x0": 28.8568, - "bbox_x1": 30.89596, - "bbox_y0": -2.84067, - "bbox_y1": -1.05348 - } - }, - { - "pk": 195, - "model": "base.region", - "fields": { - "rght": 73, - "code": "SHN", - "name": "Saint Helena", - "parent": 14, - "level": 3, - "lft": 72, - "tree_id": 90, - "bbox_x0": -14.44153, - "bbox_x1": -5.63286, - "bbox_y0": -40.400452, - "bbox_y1": -7.87757 - } - }, - { - "pk": 196, - "model": "base.region", - "fields": { - "rght": 169, - "code": "KNA", - "name": "Saint Kitts and Nevis", - "parent": 255, - "level": 3, - "lft": 168, - "tree_id": 90, - "bbox_x0": -62.86956, - "bbox_x1": -62.543259, - "bbox_y0": 17.095341, - "bbox_y1": 17.420111 - } - }, - { - "pk": 197, - "model": "base.region", - "fields": { - "rght": 171, - "code": "LCA", - "name": "Saint Lucia", - "parent": 255, - "level": 3, - "lft": 170, - "tree_id": 90, - "bbox_x0": -61.07415, - "bbox_x1": -60.866051, - "bbox_y0": 13.70477, - "bbox_y1": 14.10324 - } - }, - { - "pk": 198, - "model": "base.region", - "fields": { - "rght": 173, - "code": "SPM", - "name": "Saint Pierre and Miquelon", - "parent": 255, - "level": 3, - "lft": 172, - "tree_id": 90, - "bbox_x0": -56.420658, - "bbox_x1": -56.157372, - "bbox_y0": 46.753269, - "bbox_y1": 47.14629 - } - }, - { - "pk": 199, - "model": "base.region", - "fields": { - "rght": 175, - "code": "VCT", - "name": "Saint Vincent and the Grenadines", - "parent": 255, - "level": 3, - "lft": 174, - "tree_id": 90, - "bbox_x0": -61.459251, - "bbox_x1": -61.11388, - "bbox_y0": 12.58101, - "bbox_y1": 13.37783 - } - }, - { - "pk": 200, - "model": "base.region", - "fields": { - "rght": 177, - "code": "BLM", - "name": "Saint-Barthelemy", - "parent": 255, - "level": 3, - "lft": 176, - "tree_id": 90, - "bbox_x0": -62.9338, - "bbox_x1": -62.78286, - "bbox_y0": 17.86622, - "bbox_y1": 17.968599 - } - }, - { - "pk": 201, - "model": "base.region", - "fields": { - "rght": 179, - "code": "MAF", - "name": "Saint-Martin (French part)", - "parent": 255, - "level": 3, - "lft": 178, - "tree_id": 90, - "bbox_x0": -63.15276, - "bbox_x1": -62.972778, - "bbox_y0": 18.052231, - "bbox_y1": 18.13069 - } - }, - { - "pk": 202, - "model": "base.region", - "fields": { - "rght": 502, - "code": "WSM", - "name": "Samoa", - "parent": 256, - "level": 2, - "lft": 501, - "tree_id": 90, - "bbox_x0": -172.798584, - "bbox_x1": -171.33287, - "bbox_y0": -14.06353, - "bbox_y1": -13.4322 - } - }, - { - "pk": 203, - "model": "base.region", - "fields": { - "rght": 412, - "code": "SMR", - "name": "San Marino", - "parent": 5, - "level": 2, - "lft": 411, - "tree_id": 90, - "bbox_x0": 12.40306, - "bbox_x1": 12.51651, - "bbox_y0": 43.893299, - "bbox_y1": 43.992168 - } - }, - { - "pk": 204, - "model": "base.region", - "fields": { - "rght": 119, - "code": "STP", - "name": "Sao Tome and Principe", - "parent": 13, - "level": 3, - "lft": 118, - "tree_id": 90, - "bbox_x0": 5.59955, - "bbox_x1": 7.46637, - "bbox_y0": -0.014, - "bbox_y1": 1.73378 - } - }, - { - "pk": 205, - "model": "base.region", - "fields": { - "rght": 456, - "code": "SAU", - "name": "Saudi Arabia", - "parent": 15, - "level": 2, - "lft": 455, - "tree_id": 90, - "bbox_x0": 34.508282, - "bbox_x1": 55.666672, - "bbox_y0": 16.261169, - "bbox_y1": 32.173481 - } - }, - { - "pk": 206, - "model": "base.region", - "fields": { - "rght": 121, - "code": "SEN", - "name": "Senegal", - "parent": 13, - "level": 3, - "lft": 120, - "tree_id": 90, - "bbox_x0": -17.535231, - "bbox_x1": -11.35588, - "bbox_y0": 12.30727, - "bbox_y1": 16.691629 - } - }, - { - "pk": 207, - "model": "base.region", - "fields": { - "rght": 414, - "code": "SRB", - "name": "Serbia", - "parent": 5, - "level": 2, - "lft": 413, - "tree_id": 90, - "bbox_x0": 18.814581, - "bbox_x1": 23.007, - "bbox_y0": 41.908611, - "bbox_y1": 46.191002 - } - }, - { - "pk": 208, - "model": "base.region", - "fields": { - "rght": 41, - "code": "SYC", - "name": "Seychelles", - "parent": 12, - "level": 3, - "lft": 40, - "tree_id": 90, - "bbox_x0": 46.199211, - "bbox_x1": 56.279499, - "bbox_y0": -10.21712, - "bbox_y1": -3.71151 - } - }, - { - "pk": 209, - "model": "base.region", - "fields": { - "rght": 123, - "code": "SLE", - "name": "Sierra Leone", - "parent": 13, - "level": 3, - "lft": 122, - "tree_id": 90, - "bbox_x0": -13.30763, - "bbox_x1": -10.28423, - "bbox_y0": 6.92868, - "bbox_y1": 10.00043 - } - }, - { - "pk": 210, - "model": "base.region", - "fields": { - "rght": 309, - "code": "SGP", - "name": "Singapore", - "parent": 7, - "level": 3, - "lft": 308, - "tree_id": 90, - "bbox_x0": 103.618248, - "bbox_x1": 104.40847, - "bbox_y0": 1.1158, - "bbox_y1": 1.47062 - } - }, - { - "pk": 211, - "model": "base.region", - "fields": { - "rght": 416, - "code": "SVK", - "name": "Slovakia", - "parent": 5, - "level": 2, - "lft": 415, - "tree_id": 90, - "bbox_x0": 16.833179, - "bbox_x1": 22.570299, - "bbox_y0": 47.728001, - "bbox_y1": 49.603001 - } - }, - { - "pk": 212, - "model": "base.region", - "fields": { - "rght": 418, - "code": "SVN", - "name": "Slovenia", - "parent": 5, - "level": 2, - "lft": 417, - "tree_id": 90, - "bbox_x0": 13.37551, - "bbox_x1": 16.59656, - "bbox_y0": 45.416, - "bbox_y1": 46.87788 - } - }, - { - "pk": 213, - "model": "base.region", - "fields": { - "rght": 504, - "code": "SLB", - "name": "Solomon Islands", - "parent": 256, - "level": 2, - "lft": 503, - "tree_id": 90, - "bbox_x0": 155.508667, - "bbox_x1": 170.200455, - "bbox_y0": -12.2919, - "bbox_y1": -5.16622 - } - }, - { - "pk": 214, - "model": "base.region", - "fields": { - "rght": 43, - "code": "SOM", - "name": "Somalia", - "parent": 12, - "level": 3, - "lft": 42, - "tree_id": 90, - "bbox_x0": 40.988628, - "bbox_x1": 51.413029, - "bbox_y0": -1.66205, - "bbox_y1": 11.9852 - } - }, - { - "pk": 215, - "model": "base.region", - "fields": { - "rght": 75, - "code": "ZAF", - "name": "South Africa", - "parent": 14, - "level": 3, - "lft": 74, - "tree_id": 90, - "bbox_x0": 16.46841, - "bbox_x1": 37.993172, - "bbox_y0": -46.990009, - "bbox_y1": -22.12472 - } - }, - { - "pk": 216, - "model": "base.region", - "fields": { - "rght": 420, - "code": "ESP", - "name": "Spain", - "parent": 5, - "level": 2, - "lft": 419, - "tree_id": 90, - "bbox_x0": -18.160789, - "bbox_x1": 4.32788, - "bbox_y0": 27.63546, - "bbox_y1": 43.789959 - } - }, - { - "pk": 217, - "model": "base.region", - "fields": { - "rght": 291, - "code": "LKA", - "name": "Sri Lanka", - "parent": 9, - "level": 3, - "lft": 290, - "tree_id": 90, - "bbox_x0": 79.516212, - "bbox_x1": 81.88121, - "bbox_y0": 5.9167, - "bbox_y1": 9.8312 - } - }, - { - "pk": 218, - "model": "base.region", - "fields": { - "rght": 59, - "code": "SDN", - "name": "Sudan", - "parent": 11, - "level": 3, - "lft": 58, - "tree_id": 90, - "bbox_x0": 21.83894, - "bbox_x1": 38.833801, - "bbox_y0": 3.48639, - "bbox_y1": 23.146891 - } - }, - { - "pk": 219, - "model": "base.region", - "fields": { - "rght": 237, - "code": "SUR", - "name": "Suriname", - "parent": 4, - "level": 3, - "lft": 236, - "tree_id": 90, - "bbox_x0": -58.086559, - "bbox_x1": -53.977489, - "bbox_y0": 1.83114, - "bbox_y1": 6.00454 - } - }, - { - "pk": 220, - "model": "base.region", - "fields": { - "rght": 422, - "code": "SJM", - "name": "Svalbard and Jan Mayen Islands", - "parent": 5, - "level": 2, - "lft": 421, - "tree_id": 90, - "bbox_x0": -9.07989, - "bbox_x1": 36.815269, - "bbox_y0": 70.82737, - "bbox_y1": 80.834061 - } - }, - { - "pk": 221, - "model": "base.region", - "fields": { - "rght": 77, - "code": "SWZ", - "name": "Swaziland", - "parent": 14, - "level": 3, - "lft": 76, - "tree_id": 90, - "bbox_x0": 30.7941, - "bbox_x1": 32.137272, - "bbox_y0": -27.317101, - "bbox_y1": -25.719641 - } - }, - { - "pk": 222, - "model": "base.region", - "fields": { - "rght": 424, - "code": "SWE", - "name": "Sweden", - "parent": 5, - "level": 2, - "lft": 423, - "tree_id": 90, - "bbox_x0": 10.9661, - "bbox_x1": 24.16634, - "bbox_y0": 55.33696, - "bbox_y1": 69.059937 - } - }, - { - "pk": 223, - "model": "base.region", - "fields": { - "rght": 426, - "code": "CHE", - "name": "Switzerland", - "parent": 5, - "level": 2, - "lft": 425, - "tree_id": 90, - "bbox_x0": 5.95587, - "bbox_x1": 10.49203, - "bbox_y0": 45.81802, - "bbox_y1": 47.80838 - } - }, - { - "pk": 224, - "model": "base.region", - "fields": { - "rght": 458, - "code": "SYR", - "name": "Syrian Arab Republic", - "parent": 15, - "level": 2, - "lft": 457, - "tree_id": 90, - "bbox_x0": 35.727001, - "bbox_x1": 42.384998, - "bbox_y0": 32.3106, - "bbox_y1": 37.319 - } - }, - { - "pk": 225, - "model": "base.region", - "fields": { - "rght": 255, - "code": "TJK", - "name": "Tajikistan", - "parent": 8, - "level": 3, - "lft": 254, - "tree_id": 90, - "bbox_x0": 67.387131, - "bbox_x1": 75.137222, - "bbox_y0": 36.674141, - "bbox_y1": 41.04224 - } - }, - { - "pk": 226, - "model": "base.region", - "fields": { - "rght": 311, - "code": "THA", - "name": "Thailand", - "parent": 7, - "level": 3, - "lft": 310, - "tree_id": 90, - "bbox_x0": 97.343964, - "bbox_x1": 105.636917, - "bbox_y0": 5.61257, - "bbox_y1": 20.464701 - } - }, - { - "pk": 227, - "model": "base.region", - "fields": { - "rght": 313, - "code": "TLS", - "name": "Timor-Leste", - "parent": 7, - "level": 3, - "lft": 312, - "tree_id": 90, - "bbox_x0": 124.075439, - "bbox_x1": 127.345337, - "bbox_y0": -9.51337, - "bbox_y1": -8.13741 - } - }, - { - "pk": 228, - "model": "base.region", - "fields": { - "rght": 125, - "code": "TGO", - "name": "Togo", - "parent": 13, - "level": 3, - "lft": 124, - "tree_id": 90, - "bbox_x0": -0.14731, - "bbox_x1": 1.80669, - "bbox_y0": 6.10441, - "bbox_y1": 11.13897 - } - }, - { - "pk": 229, - "model": "base.region", - "fields": { - "rght": 506, - "code": "TKL", - "name": "Tokelau", - "parent": 256, - "level": 2, - "lft": 505, - "tree_id": 90, - "bbox_x0": -172.517136, - "bbox_x1": -171.182083, - "bbox_y0": -9.43378, - "bbox_y1": -8.53288 - } - }, - { - "pk": 230, - "model": "base.region", - "fields": { - "rght": 508, - "code": "TON", - "name": "Tonga", - "parent": 256, - "level": 2, - "lft": 507, - "tree_id": 90, - "bbox_x0": -176.212646, - "bbox_x1": -173.702438, - "bbox_y0": -22.345711, - "bbox_y1": -15.55326 - } - }, - { - "pk": 231, - "model": "base.region", - "fields": { - "rght": 181, - "code": "TTO", - "name": "Trinidad and Tobago", - "parent": 255, - "level": 3, - "lft": 180, - "tree_id": 90, - "bbox_x0": -61.927391, - "bbox_x1": -60.49144, - "bbox_y0": 10.03648, - "bbox_y1": 11.36118 - } - }, - { - "pk": 232, - "model": "base.region", - "fields": { - "rght": 61, - "code": "TUN", - "name": "Tunisia", - "parent": 11, - "level": 3, - "lft": 60, - "tree_id": 90, - "bbox_x0": 7.52481, - "bbox_x1": 11.59827, - "bbox_y0": 30.240431, - "bbox_y1": 37.56712 - } - }, - { - "pk": 233, - "model": "base.region", - "fields": { - "rght": 428, - "code": "TUR", - "name": "Turkey", - "parent": 5, - "level": 2, - "lft": 427, - "tree_id": 90, - "bbox_x0": 25.664101, - "bbox_x1": 44.8297, - "bbox_y0": 35.809971, - "bbox_y1": 42.105499 - } - }, - { - "pk": 234, - "model": "base.region", - "fields": { - "rght": 257, - "code": "TKM", - "name": "Turkmenistan", - "parent": 8, - "level": 3, - "lft": 256, - "tree_id": 90, - "bbox_x0": 52.441429, - "bbox_x1": 66.684303, - "bbox_y0": 35.14109, - "bbox_y1": 42.795551 - } - }, - { - "pk": 235, - "model": "base.region", - "fields": { - "rght": 183, - "code": "TCA", - "name": "Turks and Caicos Islands", - "parent": 255, - "level": 3, - "lft": 182, - "tree_id": 90, - "bbox_x0": -72.483879, - "bbox_x1": -71.08033, - "bbox_y0": 21.170031, - "bbox_y1": 21.97361 - } - }, - { - "pk": 236, - "model": "base.region", - "fields": { - "rght": 510, - "code": "TUV", - "name": "Tuvalu", - "parent": 256, - "level": 2, - "lft": 509, - "tree_id": 90, - "bbox_x0": 176.06488, - "bbox_x1": 179.883789, - "bbox_y0": -10.75045, - "bbox_y1": -5.64198 - } - }, - { - "pk": 237, - "model": "base.region", - "fields": { - "rght": 45, - "code": "UGA", - "name": "Uganda", - "parent": 12, - "level": 3, - "lft": 44, - "tree_id": 90, - "bbox_x0": 29.573549, - "bbox_x1": 35.001251, - "bbox_y0": -1.47849, - "bbox_y1": 4.23403 - } - }, - { - "pk": 238, - "model": "base.region", - "fields": { - "rght": 430, - "code": "UKR", - "name": "Ukraine", - "parent": 5, - "level": 2, - "lft": 429, - "tree_id": 90, - "bbox_x0": 22.128811, - "bbox_x1": 40.218079, - "bbox_y0": 44.390411, - "bbox_y1": 52.375359 - } - }, - { - "pk": 239, - "model": "base.region", - "fields": { - "rght": 460, - "code": "ARE", - "name": "United Arab Emirates", - "parent": 15, - "level": 2, - "lft": 459, - "tree_id": 90, - "bbox_x0": 51.497978, - "bbox_x1": 56.38343, - "bbox_y0": 22.644409, - "bbox_y1": 26.28219 - } - }, - { - "pk": 240, - "model": "base.region", - "fields": { - "rght": 432, - "code": "GBR", - "name": "United Kingdom", - "parent": 5, - "level": 2, - "lft": 431, - "tree_id": 90, - "bbox_x0": -13.41393, - "bbox_x1": 1.76896, - "bbox_y0": 49.16209, - "bbox_y1": 60.854691 - } - }, - { - "pk": 241, - "model": "base.region", - "fields": { - "rght": 47, - "code": "TZA", - "name": "United Republic of Tanzania", - "parent": 12, - "level": 3, - "lft": 46, - "tree_id": 90, - "bbox_x0": 29.32716, - "bbox_x1": 40.443218, - "bbox_y0": -11.74569, - "bbox_y1": -0.99073 - } - }, - { - "pk": 242, - "model": "base.region", - "fields": { - "rght": 185, - "code": "VIR", - "name": "United States Virgin Islands", - "parent": 255, - "level": 3, - "lft": 184, - "tree_id": 90, - "bbox_x0": -65.086281, - "bbox_x1": -64.56517, - "bbox_y0": 17.681721, - "bbox_y1": 18.458139 - } - }, - { - "pk": 243, - "model": "base.region", - "fields": { - "rght": 211, - "code": "USA", - "name": "United States of America", - "parent": 2, - "level": 3, - "lft": 210, - "tree_id": 90, - "bbox_x0": -179.150558, - "bbox_x1": -66.940643, - "bbox_y0": 18.91172, - "bbox_y1": 71.441048 - } - }, - { - "pk": 244, - "model": "base.region", - "fields": { - "rght": 239, - "code": "URY", - "name": "Uruguay", - "parent": 4, - "level": 3, - "lft": 238, - "tree_id": 90, - "bbox_x0": -58.442719, - "bbox_x1": -53.073929, - "bbox_y0": -35.047939, - "bbox_y1": -30.08222 - } - }, - { - "pk": 245, - "model": "base.region", - "fields": { - "rght": 259, - "code": "UZB", - "name": "Uzbekistan", - "parent": 8, - "level": 3, - "lft": 258, - "tree_id": 90, - "bbox_x0": 55.996632, - "bbox_x1": 73.132271, - "bbox_y0": 37.18433, - "bbox_y1": 45.60519 - } - }, - { - "pk": 246, - "model": "base.region", - "fields": { - "rght": 512, - "code": "VUT", - "name": "Vanuatu", - "parent": 256, - "level": 2, - "lft": 511, - "tree_id": 90, - "bbox_x0": 166.524994, - "bbox_x1": 170.234802, - "bbox_y0": -20.25045, - "bbox_y1": -13.07345 - } - }, - { - "pk": 247, - "model": "base.region", - "fields": { - "rght": 241, - "code": "VEN", - "name": "Venezuela (Bolivarian Republic of)", - "parent": 4, - "level": 3, - "lft": 240, - "tree_id": 90, - "bbox_x0": -73.374313, - "bbox_x1": -59.803768, - "bbox_y0": 0.74368, - "bbox_y1": 12.2019 - } - }, - { - "pk": 248, - "model": "base.region", - "fields": { - "rght": 315, - "code": "VNM", - "name": "Viet Nam", - "parent": 7, - "level": 3, - "lft": 314, - "tree_id": 90, - "bbox_x0": 102.144592, - "bbox_x1": 116.521233, - "bbox_y0": 7.3116, - "bbox_y1": 23.39274 - } - }, - { - "pk": 249, - "model": "base.region", - "fields": { - "rght": 514, - "code": "WLF", - "name": "Wallis and Futuna Islands", - "parent": 256, - "level": 2, - "lft": 513, - "tree_id": 90, - "bbox_x0": -178.206787, - "bbox_x1": -176.08287, - "bbox_y0": -14.38779, - "bbox_y1": -13.17343 - } - }, - { - "pk": 250, - "model": "base.region", - "fields": { - "rght": 63, - "code": "ESH", - "name": "Western Sahara", - "parent": 11, - "level": 3, - "lft": 62, - "tree_id": 90, - "bbox_x0": -17.10317, - "bbox_x1": -8.66942, - "bbox_y0": 20.774151, - "bbox_y1": 28.219179 - } - }, - { - "pk": 251, - "model": "base.region", - "fields": { - "rght": 462, - "code": "YEM", - "name": "Yemen", - "parent": 15, - "level": 2, - "lft": 461, - "tree_id": 90, - "bbox_x0": 41.809608, - "bbox_x1": 54.535992, - "bbox_y0": 12.10717, - "bbox_y1": 19.00276 - } - }, - { - "pk": 252, - "model": "base.region", - "fields": { - "rght": 79, - "code": "ZMB", - "name": "Zambia", - "parent": 14, - "level": 3, - "lft": 78, - "tree_id": 90, - "bbox_x0": 21.99938, - "bbox_x1": 33.705711, - "bbox_y0": -18.07947, - "bbox_y1": -8.22436 - } - }, - { - "pk": 253, - "model": "base.region", - "fields": { - "rght": 81, - "code": "ZWE", - "name": "Zimbabwe", - "parent": 14, - "level": 3, - "lft": 80, - "tree_id": 90, - "bbox_x0": 25.23702, - "bbox_x1": 33.056301, - "bbox_y0": -22.41773, - "bbox_y1": -15.60883 - } - }, - { - "pk": 254, - "model": "base.region", - "fields": { - "rght": 243, - "code": "AME", - "name": "Americas", - "parent": null, - "level": 1, - "lft": 128, - "tree_id": 90, - "bbox_x0": -84.114449, - "bbox_x1": -84.097572, - "bbox_y0": 9.9313, - "bbox_y1": 9.94792 - } - }, - { - "pk": 255, - "model": "base.region", - "fields": { - "rght": 186, - "code": "CRB", - "name": "Caribbean", - "parent": 254, - "level": 2, - "lft": 129, - "tree_id": 90, - "bbox_x0": -85.260178, - "bbox_x1": -59.286541, - "bbox_y0": 10.18548, - "bbox_y1": 27.454559 - } - }, - { - "pk": 256, - "model": "base.region", - "fields": { - "rght": 515, - "code": "PAC", - "name": "Pacific", - "parent": null, - "level": 1, - "lft": 464, - "tree_id": 90, - "bbox_x0": 139.572356, - "bbox_x1": -74.531208, - "bbox_y0": -56.267241, - "bbox_y1": 62.0215969 - } - }, - { - "pk": 257, - "model": "base.region", - "fields": { - "rght": 12, - "code": "CFR", - "name": "Central Africa", - "parent": 10, - "level": 2, - "lft": 3, - "tree_id": 90, - "bbox_x0": -25.35874, - "bbox_x1": 63.525379, - "bbox_y0": -46.900452, - "bbox_y1": 37.56712 - } - }, - { - "pk": 258, - "model": "base.region", - "fields": { - "rght": 276, - "code": "EAS", - "name": "East Asia", - "parent": 6, - "level": 2, - "lft": 261, - "tree_id": 90, - "bbox_x0": 19.6381, - "bbox_x1": 180, - "bbox_y0": -12.56111, - "bbox_y1": 82.50045 - } - }, - { - "pk": 259, - "model": "base.region", - "fields": { - "rght": 59, - "code": "SSD", - "name": "South Sudan", - "parent": 11, - "level": 3, - "lft": 58, - "tree_id": 90, - "bbox_x0": 24.15192, - "bbox_x1": 35.947689, - "bbox_y0": 3.48639, - "bbox_y1": 12.21558 - } - }, - { - "model": "base.menuplaceholder", - "pk": 1, - "fields": { - "name": "TOPBAR_MENU" - } - }, - { - "model": "base.menuplaceholder", - "pk": 2, - "fields": { - "name": "TOPBAR_MENU_LEFT" - } - }, - { - "model": "base.menuplaceholder", - "pk": 3, - "fields": { - "name": "TOPBAR_MENU_RIGHT" - } - }, - { - "model": "base.menuplaceholder", - "pk": 4, - "fields": { - "name": "CARDS_MENU" - } - } -] diff --git a/src/fixtures/sample_admin.json b/src/fixtures/sample_admin.json deleted file mode 100644 index f9a16ecf..00000000 --- a/src/fixtures/sample_admin.json +++ /dev/null @@ -1,18 +0,0 @@ -[{ - "fields": { - "date_joined": "2011-06-09 15:15:27", - "email": "ad@m.in", - "first_name": "", - "groups": [], - "is_active": true, - "is_staff": true, - "is_superuser": true, - "last_login": "2011-06-09 15:45:34", - "last_name": "", - "password": "pbkdf2_sha256$30000$rjuGt0Obn8on$cxF75frIOSaitNklLZ0IJ/VonUW0fwEFVF96o0M+lGc=", - "user_permissions": [], - "username": "admin" - }, - "model": "people.Profile", - "pk": 1000 -}] \ No newline at end of file diff --git a/src/fixtures/sites_template.json b/src/fixtures/sites_template.json deleted file mode 100644 index 0e05e867..00000000 --- a/src/fixtures/sites_template.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "fields": { - "domain": "example.com", - "name": "example.com" - }, - "model": "sites.site", - "pk": 1 - } -] diff --git a/src/jetty-runner.xml b/src/jetty-runner.xml deleted file mode 100644 index 6f56792a..00000000 --- a/src/jetty-runner.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - /geoserver - geoserver - - org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern - WONTMATCH - - diff --git a/src/manage.py b/src/manage.py deleted file mode 100755 index a1cb4497..00000000 --- a/src/manage.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2017 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -import os -import sys - - -if __name__ == "__main__": - from django.core.management import execute_from_command_line - - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings") - execute_from_command_line(sys.argv) diff --git a/src/manage.sh b/src/manage.sh deleted file mode 100755 index 0559f57d..00000000 --- a/src/manage.sh +++ /dev/null @@ -1,2 +0,0 @@ -. $HOME/.override_env -/usr/bin/python /usr/src/{{project_name}}/manage.py $@ diff --git a/src/manage_dev.sh.sample b/src/manage_dev.sh.sample deleted file mode 100644 index c81b3301..00000000 --- a/src/manage_dev.sh.sample +++ /dev/null @@ -1,3 +0,0 @@ -set -a -source ../.override_dev_env -python manage.py $@ diff --git a/src/monitoring-cron b/src/monitoring-cron deleted file mode 100644 index 0fa987da..00000000 --- a/src/monitoring-cron +++ /dev/null @@ -1,3 +0,0 @@ -# */1 * * * * /usr/src/{{project_name}}/manage.sh collect_metrics -n -t xml >> /var/log/cron.log 2>&1 -# 0 * * * * /usr/src/{{project_name}}/manage.sh dispatch_metrics >> /var/log/cron.log 2>&1 -# An empty line is required at the end of this file for a valid cron file. diff --git a/src/package/support/geonode.binary b/src/package/support/geonode.binary deleted file mode 100644 index e3bb2060..00000000 --- a/src/package/support/geonode.binary +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -DJANGO_SETTINGS_MODULE=${DJANGO_SETTINGS_MODULE:-geonode.local_settings} - -if [ -n "$WORKON_HOME" ]; then - DJANGO_ADMIN_CMD=$WORKON_HOME/bin/django-admin >/dev/null 2>/dev/null -elif hash django-admin 2>/dev/null; then - DJANGO_ADMIN_CMD=django-admin -fi - -if [ -n "$DJANGO_ADMIN_CMD" ]; then - DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE $DJANGO_ADMIN_CMD $@ -else - DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE django-admin.py $@ -fi diff --git a/src/package/support/geonode.updateip b/src/package/support/geonode.updateip deleted file mode 100644 index 827a5c42..00000000 --- a/src/package/support/geonode.updateip +++ /dev/null @@ -1,213 +0,0 @@ -#!/bin/bash - -usage () { - bname="$(basename $0)" - ret="$1" - - cat < - substitute SITEURL with , append it - to ALLOWED_HOSTS in local_settings.py - and geoserver printing config lists - This is mandatory and must be the pubic extenral address you use to access GeoNode - $bname <-l|--local> - same as above but taking into account - LOCAL vs PUBLIC ip addresses (or names) - This is optional and if not specified the default is 'localhost' - $bname <-s|--secure> - HTTPS instead of HTTP protocol - $bname <-h|--help> - this help -EOF - - exit $ret -} - -if [[ $# -eq 0 ]] ; then - usage 0 - exit 0 -fi - -POSITIONAL=() -while [[ $# -gt 0 ]] -do -key="$1" - -IS_HTTPS=0 -case $key in - -h|--help) - usage 0 - ;; - -p|--public) - PUBLIC_IP="$2" - shift # past argument - shift # past value - ;; - -l|--local) - LOCAL_IP="$2" - shift # past argument - shift # past value - ;; - -s|--secure) - IS_HTTPS=1 - shift # past argument - ;; - *) # unknown option - POSITIONAL+=("$1") # save it in an array for later - shift # past argument - ;; -esac -done -set -- "${POSITIONAL[@]}" # restore positional parameters - -if [[ $UID != 0 ]]; then - echo "Please run this script with sudo:" - echo "sudo $0 $*" - exit 1 -fi - -if [ -z "$PUBLIC_IP" ]; then - echo "Public IP is mandatory!" - usage 1 -fi - -if [ -z "$LOCAL_IP" ]; then - # LOCAL_IP=$PUBLIC_IP - LOCAL_IP="localhost" -fi - -NET_PROTOCOL="http" -if [[ $IS_HTTPS != 0 ]]; then - NET_PROTOCOL="https" -fi - -# Getting the full netloc -NEW_EXT_IP="$NET_PROTOCOL://$PUBLIC_IP" -NEW_INT_IP="$NET_PROTOCOL://$LOCAL_IP" - -# Removing slash at the end of variables -NEW_EXT_IP=${NEW_EXT_IP%/} -NEW_INT_IP=${NEW_INT_IP%/} - -echo "PUBLIC_IP" $NEW_EXT_IP -echo "LOCAL_IP" $NEW_INT_IP - -GEONODE_ETC=${GEONODE_ETC:-/etc/geonode} -GEOSERVER_DATA_DIR=${GEOSERVER_DATA_DIR:-/usr/share/geoserver/data} -TOMCAT_SERVICE=${TOMCAT_SERVICE:-"invoke-rc.d tomcat8"} -APACHE_SERVICE=${APACHE_SERVICE:-"invoke-rc.d apache2"} - -# Replace SITEURL in $GEONODE_ETC/local_settings.py -echo "Replacing SITEURL value with '$NEW_EXT_IP' in $GEONODE_ETC/local_settings.py ... " | tr -d '\n' -sed -i "s@\(SITEURL[ ]*=[ ]*\).*@\1\'$NEW_EXT_IP\/'@g" $GEONODE_ETC/local_settings.py -echo "done." - -echo "Adding entry for '$PUBLIC_IP' in $GEOSERVER_DATA_DIR/printing/config.yaml ... " | tr -d '\n' -printing_config=$GEOSERVER_DATA_DIR/printing/config.yaml - -if grep -q "$PUBLIC_IP" "$printing_config" -then - echo "'$PUBLIC_IP' already found to the printing whitelist." -else - sed -i "s#hosts:#hosts:\n - !ipMatch\n ip: $PUBLIC_IP#g" $printing_config - echo "done." -fi - -# if ALLOWED_HOSTS already exists ... -# if grep -q "^[ ]*ALLOWED_HOSTS[ ]*=" "$GEONODE_ETC/local_settings.py" -# then -# if [ $IS_REPLACE -eq 1 ] -# then -# echo "Replacing ALLOWED_HOSTS in $GEONODE_ETC/local_settings.py ... " | tr -d '\n' -# sed -i "s/^\([ ]*ALLOWED_HOSTS[ ]*=\).*/\1 [ 'localhost', '$NEWIP', ]/g" "$GEONODE_ETC/local_settings.py" -# echo "done." -# else -# echo "Adding $NEWIP to ALLOWED_HOSTS in $GEONODE_ETC/local_settings.py ... " | tr -d '\n' -# items="$(grep "^[ ]*ALLOWED_HOSTS[ ]*=" "$GEONODE_ETC/local_settings.py" | \ -# sed 's/^[ ]*ALLOWED_HOSTS[ ]*=[ ]*\[//g;s/\][ ]*$//g')" -# already_found=0 -# oldifs="$IFS" -# IFS=',' -# for item in $items -# do -# item_cls="$(echo "$item" | sed "s/^[ ]*['\"]//g;s/['\"][ ]*$//g")" -# if [ "$item_cls" = "$NEWIP" ] -# then -# already_found=1 -# break -# fi -# done -# IFS="$oldifs" -# if [ $already_found -eq 0 ] -# then -# if echo "$items" | grep -q ',[ ]*$' -# then -# items="${items}'$NEWIP', " -# else -# items="${items}, '$NEWIP', " -# fi -# sed -i "s/^\([ ]*ALLOWED_HOSTS[ ]*=\).*/\1 [ $items ]/g" "$GEONODE_ETC/local_settings.py" -# echo "done." -# else -# echo "'$NEWIP' already found in ALLOWED_HOSTS list." -# fi -# fi -# else -# echo "Adding ALLOWED_HOSTS with in $GEONODE_ETC/local_settings.py ... " | tr -d '\n' -# echo "ALLOWED_HOSTS=['localhost', '$NEWIP', ]" >> $GEONODE_ETC/local_settings.py -# echo "done." -# fi - - -# silence the warnings from executing geonode command or they will pollute the commands output -if grep -q "^[ ]*SILENCED_SYSTEM_CHECKS[ ]*=" "$GEONODE_ETC/local_settings.py" -then - true -else - echo "SILENCED_SYSTEM_CHECKS = ['1_8.W001', 'fields.W340']" >> $GEONODE_ETC/local_settings.py -fi - -geonode fixsitename - -echo "Setting up oauth" -# Set oauth keys -oauth_keys=$(geonode fixoauthuri 2>&1) -client_id=`echo $oauth_keys | cut -d \, -f 1` -client_secret=`echo $oauth_keys | cut -d \, -f 2` - -# Updating OAuth2 Service Config -oauth_config="$GEOSERVER_DATA_DIR/security/filter/geonode-oauth2/config.xml" -sed -i "s|.*|$client_id|g" $oauth_config -sed -i "s|.*|$client_secret|g" $oauth_config -sed -i "s|.*|$NEW_INT_IP/o/token/|g" $oauth_config -sed -i "s|.*|$NEW_EXT_IP/o/authorize/|g" $oauth_config -sed -i "s|.*|$NEW_EXT_IP/geoserver/|g" $oauth_config -sed -i "s|.*|$NEW_INT_IP/api/o/v4/tokeninfo/|g" $oauth_config -sed -i "s|.*|$NEW_EXT_IP/account/logout/|g" $oauth_config - -# Updating REST Role Service Config -sed -i "s|.*|$NEW_INT_IP|g" "$GEOSERVER_DATA_DIR/security/role/geonode REST role service/config.xml" - -# Updating GeoServer Global Config -global_config="$GEOSERVER_DATA_DIR/global.xml" -sed -i "s|.*|$NEW_EXT_IP/geoserver|g" $global_config - -# Restart tomcat server -$TOMCAT_SERVICE restart - -echo "Waiting Tomcat Service to Restart..." -sleep 30s - -# Restart apache server -$APACHE_SERVICE restart -echo "Waiting Apache HTTPD Service to Restart..." -sleep 5s - -# Run updatelayers -geonode updatelayers -geonode set_all_datasets_alternate -geonode set_all_datasets_metadata - -# Run updatemaplayerip -geonode updatemaplayerip diff --git a/src/pavement.py b/src/pavement.py deleted file mode 100644 index f3cdbe0f..00000000 --- a/src/pavement.py +++ /dev/null @@ -1,1260 +0,0 @@ -######################################################################### -# -# Copyright (C) 2018 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -import fileinput -import glob -import os -import re -import shutil -import subprocess -import signal -import sys -import time -import pytz -import logging -import datetime -from dateutil.parser import parse as parsedate - -from urllib.parse import urlparse -from urllib.request import urlopen, Request - -import zipfile -from tqdm import tqdm -import requests -import math -import psutil - -import yaml -from paver.easy import ( - BuildFailure, - call_task, - cmdopts, - info, - needs, - path, - sh, - task, -) -from setuptools.command import easy_install - -try: - from {{ project_name }}.local_settings import * -except ImportError: - from {{ project_name }}.settings import * - -try: - from paver.path import pushd -except ImportError: - from paver.easy import pushd - -from geonode.settings import ( - on_travis, - core_tests, - internal_apps_tests, - integration_tests, - integration_server_tests, - integration_upload_tests, - integration_monitoring_tests, - integration_csw_tests, - integration_bdd_tests, - INSTALLED_APPS, - GEONODE_CORE_APPS, - GEONODE_INTERNAL_APPS, - GEONODE_APPS, - OGC_SERVER, - ASYNC_SIGNALS, - MONITORING_ENABLED, - CELERY_BEAT_SCHEDULER, -) - -try: - from geonode.settings import TEST_RUNNER_KEEPDB, TEST_RUNNER_PARALLEL - - _keepdb = "--keepdb" if TEST_RUNNER_KEEPDB else "" - _parallel = f"--parallel={TEST_RUNNER_PARALLEL}" if TEST_RUNNER_PARALLEL else "" -except Exception: - _keepdb = "" - _parallel = "" - -assert sys.version_info >= (2, 6), SystemError( - "GeoNode Build requires python 2.6 or better" -) - -dev_config = None -with open("dev_config.yml") as f: - dev_config = yaml.load(f, Loader=yaml.Loader) - - -logger = logging.getLogger(__name__) - - -def grab(src, dest, name): - src, dest, name = map(str, (src, dest, name)) - logger.info(f" src, dest, name --> {src} {dest} {name}") - - if not os.path.exists(dest): - logger.info(f"Downloading {name}") - elif not zipfile.is_zipfile(dest): - logger.info(f"Downloading {name} (corrupt file)") - elif not src.startswith("file://"): - r = requests.head(src) - file_time = datetime.datetime.fromtimestamp(os.path.getmtime(dest)) - url_time = file_time - for _k in ["last-modified", "Date"]: - if _k in r.headers: - url_time = r.headers[_k] - url_date = parsedate(url_time) - utc = pytz.utc - url_date = url_date.replace(tzinfo=utc) - file_time = file_time.replace(tzinfo=utc) - if url_date < file_time: - # Do not download if older than the local one - return - logger.info(f"Downloading updated {name}") - - # Local file does not exist or remote one is newer - if src.startswith("file://"): - src2 = src.replace("file://", "") - if not os.path.exists(src2): - logger.info(f"Source location ({src2}) does not exist") - else: - logger.info(f"Copying local file from {src2}") - shutil.copyfile(src2, dest) - else: - # urlretrieve(str(src), str(dest)) - # Streaming, so we can iterate over the response. - r = requests.get(src, stream=True, timeout=10, verify=False) - # Total size in bytes. - total_size = int(r.headers.get("content-length", 0)) - logger.info(f"Requesting {src}") - block_size = 1024 - wrote = 0 - with open("output.bin", "wb") as f: - for data in tqdm( - r.iter_content(block_size), - total=math.ceil(total_size // block_size), - unit="KB", - unit_scale=False, - ): - wrote += len(data) - f.write(data) - logger.info(f" total_size [{total_size}] / wrote [{wrote}] ") - if total_size != 0 and wrote != total_size: - logger.error( - f"ERROR, something went wrong. Data could not be written. Expected to write {wrote} but wrote {total_size} instead" - ) - else: - shutil.move("output.bin", dest) - try: - # Cleaning up - os.remove("output.bin") - except OSError: - pass - - -@task -@cmdopts( - [ - ("geoserver=", "g", "The location of the geoserver build (.war file)."), - ("jetty=", "j", "The location of the Jetty Runner (.jar file)."), - ("force_exec=", "", "Force GeoServer Setup."), - ] -) -def setup_geoserver(options): - """Prepare a testing instance of GeoServer.""" - # only start if using Geoserver backend - if "geonode.geoserver" not in INSTALLED_APPS: - return - if on_travis and not options.get("force_exec", False): - """Will make use of the docker container for the Integration Tests""" - return - else: - download_dir = path("downloaded") - if not download_dir.exists(): - download_dir.makedirs() - geoserver_dir = path("geoserver") - geoserver_bin = download_dir / os.path.basename( - urlparse(dev_config["GEOSERVER_URL"]).path - ) - jetty_runner = download_dir / os.path.basename( - urlparse(dev_config["JETTY_RUNNER_URL"]).path - ) - geoserver_data = download_dir / os.path.basename( - urlparse(dev_config["DATA_DIR_URL"]).path - ) - grab( - options.get("geoserver", dev_config["GEOSERVER_URL"]), - geoserver_bin, - "geoserver binary", - ) - grab( - options.get("jetty", dev_config["JETTY_RUNNER_URL"]), - jetty_runner, - "jetty runner", - ) - grab( - options.get("geoserver data", dev_config["DATA_DIR_URL"]), - geoserver_data, - "geoserver data-dir", - ) - - if not geoserver_dir.exists(): - geoserver_dir.makedirs() - - webapp_dir = geoserver_dir / "geoserver" - if not webapp_dir: - webapp_dir.makedirs() - - logger.info("extracting geoserver") - z = zipfile.ZipFile(geoserver_bin, "r") - z.extractall(webapp_dir) - - logger.info("extracting geoserver data dir") - z = zipfile.ZipFile(geoserver_data, "r") - z.extractall(geoserver_dir) - - _configure_data_dir() - - -def _configure_data_dir(): - try: - config = path("geoserver/data/global.xml") - with open(config) as f: - xml = f.read() - m = re.search("proxyBaseUrl>([^<]+)", xml) - xml = f"{xml[:m.start(1)]}http://localhost:8080/geoserver{xml[m.end(1):]}" - with open(config, "w") as f: - f.write(xml) - except Exception as e: - print(e) - - try: - config = path("geoserver/data/security/filter/geonode-oauth2/config.xml") - with open(config) as f: - xml = f.read() - m = re.search("accessTokenUri>([^<]+)", xml) - xml = f"{xml[:m.start(1)]}http://localhost:8000/o/token/{xml[m.end(1):]}" - m = re.search("userAuthorizationUri>([^<]+)", xml) - xml = ( - f"{xml[:m.start(1)]}http://localhost:8000/o/authorize/{xml[m.end(1):]}" - ) - m = re.search("redirectUri>([^<]+)", xml) - xml = f"{xml[:m.start(1)]}http://localhost:8080/geoserver/index.html{xml[m.end(1):]}" - m = re.search("checkTokenEndpointUrl>([^<]+)", xml) - xml = f"{xml[:m.start(1)]}http://localhost:8000/api/o/v4/tokeninfo/{xml[m.end(1):]}" - m = re.search("logoutUri>([^<]+)", xml) - xml = f"{xml[:m.start(1)]}http://localhost:8000/account/logout/{xml[m.end(1):]}" - with open(config, "w") as f: - f.write(xml) - except Exception as e: - print(e) - - try: - config = path( - "geoserver/data/security/role/geonode REST role service/config.xml" - ) - with open(config) as f: - xml = f.read() - m = re.search("baseUrl>([^<]+)", xml) - xml = f"{xml[:m.start(1)]}http://localhost:8000{xml[m.end(1):]}" - with open(config, "w") as f: - f.write(xml) - except Exception as e: - print(e) - - -@task -def static(options): - with pushd("geonode/static"): - sh("grunt production") - - -@task -@needs( - [ - "setup_geoserver", - ] -) -def setup(options): - """Get dependencies and prepare a GeoNode development environment.""" - - if MONITORING_ENABLED: - updategeoip(options) - - info( - "GeoNode development environment successfully set up." - "If you have not set up an administrative account," - ' please do so now. Use "paver start" to start up the server.' - ) - - -def grab_winfiles(url, dest, packagename): - # Add headers - headers = {"User-Agent": "Mozilla 5.10"} - request = Request(url, None, headers) - response = urlopen(request) - with open(dest, "wb") as writefile: - writefile.write(response.read()) - - -@task -def win_install_deps(options): - """ - Install all Windows Binary automatically - This can be removed as wheels become available for these packages - """ - download_dir = path("downloaded").abspath() - if not download_dir.exists(): - download_dir.makedirs() - win_packages = { - # required by transifex-client - "Py2exe": dev_config["WINDOWS"]["py2exe"], - # the wheel 1.9.4 installs but pycsw wants 1.9.3, which fails to compile - # when pycsw bumps their pyproj to 1.9.4 this can be removed. - "PyProj": dev_config["WINDOWS"]["pyproj"], - "lXML": dev_config["WINDOWS"]["lxml"], - } - failed = False - for package, url in win_packages.items(): - tempfile = download_dir / os.path.basename(url) - logger.info(f"Installing file ... {tempfile}") - grab_winfiles(url, tempfile, package) - try: - easy_install.main([tempfile]) - except Exception as e: - failed = True - logger.error("install failed with error: ", e) - os.remove(tempfile) - if failed and sys.maxsize > 2**32: - logger.error("64bit architecture is not currently supported") - logger.error("try finding the 64 binaries for py2exe, and pyproj") - elif failed: - logger.error("install failed for py2exe, and/or pyproj") - else: - print( - "Windows dependencies now complete. Run pip install -e geonode --use-mirrors" - ) - - -@task -@cmdopts([("version=", "v", "Legacy GeoNode version of the existing database.")]) -def upgradedb(options): - """ - Add 'fake' data migrations for existing tables from legacy GeoNode versions - """ - version = options.get("version") - if version in {"1.1", "1.2"}: - sh("python -W ignore manage.py migrate maps 0001 --fake") - sh("python -W ignore manage.py migrate avatar 0001 --fake") - elif version is None: - print("Please specify your GeoNode version") - else: - print(f"Upgrades from version {version} are not yet supported.") - - -@task -@cmdopts([("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE")]) -def updategeoip(options): - """ - Update geoip db - """ - if MONITORING_ENABLED: - settings = options.get("settings", "") - if settings and "DJANGO_SETTINGS_MODULE" not in settings: - settings = f"DJANGO_SETTINGS_MODULE={settings}" - - sh(f"{settings} python -W ignore manage.py updategeoip -o") - - -@task -@cmdopts([("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE")]) -def sync(options): - """ - Run the migrate and migrate management commands to create and migrate a DB - """ - settings = options.get("settings", "") - if settings and "DJANGO_SETTINGS_MODULE" not in settings: - settings = f"DJANGO_SETTINGS_MODULE={settings}" - - sh(f"{settings} python -W ignore manage.py makemigrations --noinput") - sh(f"{settings} python -W ignore manage.py migrate --noinput") - sh(f"{settings} python -W ignore manage.py loaddata sample_admin.json") - sh(f"{settings} python -W ignore manage.py loaddata default_oauth_apps.json") - sh(f"{settings} python -W ignore manage.py loaddata initial_data.json") - sh(f"{settings} python -W ignore manage.py set_all_datasets_alternate") - sh(f"{settings} python -W ignore manage.py collectstatic --noinput") - - -@task -def package(options): - """ - Creates a tarball to use for building the system elsewhere - """ - import tarfile - import geonode - - version = geonode.get_version() - # Use GeoNode's version for the package name. - pkgname = f"GeoNode-{version}-all" - - # Create the output directory. - out_pkg = path(pkgname) - out_pkg_tar = path(f"{pkgname}.tar.gz") - - # Create a distribution in zip format for the geonode python package. - dist_dir = path("dist") - dist_dir.rmtree() - sh("python setup.py sdist --formats=zip") - - with pushd("package"): - # Delete old tar files in that directory - for f in glob.glob("GeoNode*.tar.gz"): - old_package = path(f) - if old_package != out_pkg_tar: - old_package.remove() - - if out_pkg_tar.exists(): - info(f"There is already a package for version {version}") - return - - # Clean anything that is in the oupout package tree. - out_pkg.rmtree() - out_pkg.makedirs() - - support_folder = path("support") - install_file = path("install.sh") - - # And copy the default files from the package folder. - justcopy(support_folder, out_pkg / "support") - justcopy(install_file, out_pkg) - - geonode_dist = path("..") / "dist" / f"GeoNode-{version}.zip" - justcopy(geonode_dist, out_pkg) - - # Create a tar file with all files in the output package folder. - tar = tarfile.open(out_pkg_tar, "w:gz") - for file in out_pkg.walkfiles(): - tar.add(file) - - # Add the README with the license and important links to documentation. - tar.add("README", arcname=f"{out_pkg}/README.rst") - tar.close() - - # Remove all the files in the temporary output package directory. - out_pkg.rmtree() - - # Report the info about the new package. - info(f"{out_pkg_tar.abspath()} created") - - -@task -@needs(["start_geoserver", "start_django"]) -@cmdopts( - [ - ("bind=", "b", "Bind server to provided IP address and port number."), - ("java_path=", "j", "Full path to java install for Windows"), - ("foreground", "f", "Do not run in background but in foreground"), - ("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE"), - ], - share_with=["start_django", "start_geoserver"], -) -def start(options): - """ - Start GeoNode (Django, GeoServer & Client) - """ - info("GeoNode is now available.") - - -@task -def stop_django(options): - """ - Stop the GeoNode Django application - """ - if ASYNC_SIGNALS: - kill("python", "celery") - kill("celery", "worker") - kill("python", "runserver") - kill("python", "runmessaging") - - -@task -@cmdopts([("force_exec=", "", "Force GeoServer Stop.")]) -def stop_geoserver(options): - """ - Stop GeoServer - """ - # we use docker-compose for integration tests - if on_travis and not options.get("force_exec", False): - return - - # only start if using Geoserver backend - if "geonode.geoserver" not in INSTALLED_APPS: - return - kill("java", "geoserver") - - # Kill process. - try: - # proc = subprocess.Popen("ps -ef | grep -i -e '[j]ava\|geoserver' | - # awk '{print $2}'", - proc = subprocess.Popen( - "ps -ef | grep -i -e 'geoserver' | awk '{print $2}'", - shell=True, - stdout=subprocess.PIPE, - ) - for pid in map(int, proc.stdout): - info(f"Stopping geoserver (process number {pid})") - os.kill(pid, signal.SIGKILL) - - # Check if the process that we killed is alive. - killed, alive = psutil.wait_procs([psutil.Process(pid=pid)], timeout=30) - for p in alive: - p.kill() - except Exception as e: - info(e) - - -@task -@needs( - [ - "stop_geoserver", - ] -) -def stop(options): - """ - Stop GeoNode - """ - # windows needs to stop the geoserver first b/c we can't tell which python - # is running, so we kill everything - info("Stopping GeoNode ...") - stop_django(options) - - -@task -@cmdopts([("bind=", "b", "Bind server to provided IP address and port number.")]) -def start_django(options): - """ - Start the GeoNode Django application - """ - settings = options.get("settings", "") - if settings and "DJANGO_SETTINGS_MODULE" not in settings: - settings = f"DJANGO_SETTINGS_MODULE={settings}" - bind = options.get("bind", "0.0.0.0:8000") - port = bind.split(":")[1] - foreground = "" if options.get("foreground", False) else "&" - sh(f"{settings} python -W ignore manage.py runserver {bind} {foreground}") - - if ASYNC_SIGNALS: - sh( - f"{settings} celery -A geonode.celery_app:app worker --autoscale=20,10 --without-gossip --without-mingle -Ofair -B -E \ - --statedb=/tmp/worker.state --scheduler={CELERY_BEAT_SCHEDULER} --loglevel=DEBUG \ - --concurrency=10 --max-tasks-per-child=10 -n worker1@%h -f celery.log {foreground}" - ) - sh(f"{settings} python -W ignore manage.py runmessaging {foreground}") - - # wait for Django to start - started = waitfor(f"http://localhost:{port}") - if not started: - info("Django never started properly or timed out.") - sys.exit(1) - - -@task -def start_messaging(options): - """ - Start the GeoNode messaging server - """ - settings = options.get("settings", "") - if settings and "DJANGO_SETTINGS_MODULE" not in settings: - settings = f"DJANGO_SETTINGS_MODULE={settings}" - foreground = "" if options.get("foreground", False) else "&" - sh(f"{settings} python -W ignore manage.py runmessaging {foreground}") - - -@task -@cmdopts( - [ - ("java_path=", "j", "Full path to java install for Windows"), - ("force_exec=", "", "Force GeoServer Start."), - ] -) -def start_geoserver(options): - """ - Start GeoServer with GeoNode extensions - """ - # we use docker-compose for integration tests - if on_travis and not options.get("force_exec", False): - return - - # only start if using Geoserver backend - if "geonode.geoserver" not in INSTALLED_APPS: - return - - GEOSERVER_BASE_URL = OGC_SERVER["default"]["LOCATION"] - url = GEOSERVER_BASE_URL - - if urlparse(GEOSERVER_BASE_URL).hostname != "localhost": - logger.warning( - "Warning: OGC_SERVER['default']['LOCATION'] hostname is not equal to 'localhost'" - ) - - if not GEOSERVER_BASE_URL.endswith("/"): - logger.error("Error: OGC_SERVER['default']['LOCATION'] does not end with a '/'") - sys.exit(1) - - download_dir = path("downloaded").abspath() - jetty_runner = download_dir / os.path.basename(dev_config["JETTY_RUNNER_URL"]) - data_dir = path("geoserver/data").abspath() - geofence_dir = path("geoserver/data/geofence").abspath() - web_app = path("geoserver/geoserver").abspath() - log_file = path("geoserver/jetty.log").abspath() - config = path("scripts/misc/jetty-runner.xml").abspath() - jetty_port = urlparse(GEOSERVER_BASE_URL).port - - import socket - - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - socket_free = True - try: - s.bind(("127.0.0.1", jetty_port)) - except OSError as e: - socket_free = False - if e.errno == 98: - info(f"Port {jetty_port} is already in use") - else: - info( - f"Something else raised the socket.error exception while checking port {jetty_port}" - ) - print(e) - finally: - s.close() - - if socket_free: - # @todo - we should not have set workdir to the datadir but a bug in geoserver - # prevents geonode security from initializing correctly otherwise - with pushd(data_dir): - javapath = "java" - if on_travis: - sh( - "sudo apt install -y openjdk-8-jre openjdk-8-jdk;" - " sudo update-java-alternatives --set java-1.8.0-openjdk-amd64;" - ' export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::");' - " export PATH=$JAVA_HOME'bin/java':$PATH;" - ) - # import subprocess - # result = subprocess.run(['update-alternatives', '--list', 'java'], stdout=subprocess.PIPE) - # javapath = result.stdout - javapath = "/usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java" - loggernullpath = os.devnull - - # checking if our loggernullpath exists and if not, reset it to - # something manageable - if loggernullpath == "nul": - try: - open("../../downloaded/null.txt", "w+").close() - except OSError: - print( - "Chances are that you have Geoserver currently running. You " - "can either stop all servers with paver stop or start only " - "the django application with paver start_django." - ) - sys.exit(1) - loggernullpath = "../../downloaded/null.txt" - - try: - sh(("%(javapath)s -version") % locals()) - except Exception: - logger.warning( - "Java was not found in your path. Trying some other options: " - ) - javapath_opt = None - if os.environ.get("JAVA_HOME", None): - logger.info("Using the JAVA_HOME environment variable") - javapath_opt = os.path.join( - os.path.abspath(os.environ["JAVA_HOME"]), "bin", "java.exe" - ) - elif options.get("java_path"): - javapath_opt = options.get("java_path") - else: - logger.critical( - "Paver cannot find java in the Windows Environment. " - "Please provide the --java_path flag with your full path to " - "java.exe e.g. --java_path=C:/path/to/java/bin/java.exe" - ) - sys.exit(1) - # if there are spaces - javapath = f'START /B "" "{javapath_opt}"' - - sh( - "%(javapath)s -Xms512m -Xmx2048m -server -Dgwc.context.suffix=gwc -XX:+UseConcMarkSweepGC -XX:MaxPermSize=512m" - " -DGEOSERVER_DATA_DIR=%(data_dir)s" - " -DGEOSERVER_CSRF_DISABLED=true" - " -Dgeofence.dir=%(geofence_dir)s" - " -Djava.awt.headless=true" - # ' -Dgeofence-ovr=geofence-datasource-ovr.properties' - # workaround for JAI sealed jar issue and jetty classloader - # ' -Dorg.eclipse.jetty.server.webapp.parentLoaderPriority=true' - " -jar %(jetty_runner)s" - " --port %(jetty_port)i" - " --log %(log_file)s" - " %(config)s" - " > %(loggernullpath)s &" % locals() - ) - - info(f"Starting GeoServer on {url}") - - # wait for GeoServer to start - started = waitfor(url) - info(f"The logs are available at {log_file}") - - if not started: - # If applications did not start in time we will give the user a chance - # to inspect them and stop them manually. - info( - "GeoServer never started properly or timed out." - "It may still be running in the background." - ) - sys.exit(1) - - -@task -def test(options): - """ - Run GeoNode's Unit Test Suite - """ - if on_travis: - if core_tests: - _apps = GEONODE_CORE_APPS - if internal_apps_tests: - _apps = GEONODE_INTERNAL_APPS - else: - _apps = GEONODE_APPS - - _apps_to_test = [] - for _app in _apps: - if _app and len(_app) > 0 and "geonode" in _app: - _apps_to_test.append(_app) - if ( - MONITORING_ENABLED - and "geonode.monitoring" in INSTALLED_APPS - and "geonode.monitoring" not in _apps_to_test - ): - _apps_to_test.append("geonode.monitoring") - sh( - f"{options.get('prefix')} manage.py test geonode.tests.smoke \ -{('.tests '.join(_apps_to_test))}.tests --noinput {_keepdb} {_parallel}" - ) - - -@task -@cmdopts([("local=", "l", "Set to True if running bdd tests locally")]) -def test_bdd(options): - """ - Run GeoNode's BDD Test Suite - """ - local = str2bool(options.get("local", "false")) - if local: - call_task("reset_hard") - - call_task("setup") - call_task("sync") - if local: - sh("sleep 30") - - info("GeoNode is now available, running the bdd tests now.") - sh("py.test") - - -@task -def test_javascript(options): - with pushd("geonode/static/geonode"): - sh("./run-tests.sh") - - -@task -@cmdopts( - [ - ("name=", "n", "Run specific tests."), - ("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE"), - ("local=", "l", "Set to True if running bdd tests locally"), - ] -) -def test_integration(options): - """ - Run GeoNode's Integration test suite against the external apps - """ - prefix = options.get("prefix") - local = str2bool(options.get("local", "false")) - if local: - call_task("stop_geoserver") - _reset() - - name = options.get("name", None) - settings = options.get("settings", "") - success = False - try: - call_task("setup", options={"settings": settings, "force_exec": True}) - - if not settings: - settings = "REUSE_DB=1 DJANGO_SETTINGS_MODULE=geonode.settings" - - if name and name in ( - "geonode.tests.csw", - "geonode.tests.integration", - "geonode.geoserver.tests.integration", - ): - call_task("sync", options={"settings": settings}) - if local: - call_task( - "start_geoserver", - options={"settings": settings, "force_exec": True}, - ) - call_task("start", options={"settings": settings}) - if integration_server_tests: - call_task("setup_data", options={"settings": settings}) - elif "geonode.geoserver" in INSTALLED_APPS: - if local: - sh("cp geonode/upload/tests/test_settings.py geonode/") - settings = "geonode.test_settings" - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py " - "makemigrations --noinput" - ) - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py " - "migrate --noinput" - ) - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py " - "loaddata sample_admin.json" - ) - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py " - "loaddata geonode/base/fixtures/default_oauth_apps.json" - ) - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py " - "loaddata geonode/base/fixtures/initial_data.json" - ) - call_task("start_geoserver") - bind = options.get("bind", "0.0.0.0:8000") - foreground = "" if options.get("foreground", False) else "&" - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py runmessaging {foreground}" - ) - sh( - f"DJANGO_SETTINGS_MODULE={settings} python -W ignore manage.py runserver {bind} {foreground}" - ) - sh("sleep 30") - settings = f"REUSE_DB=1 DJANGO_SETTINGS_MODULE={settings}" - else: - call_task("sync", options={"settings": settings}) - - live_server_option = "" - info("Running the tests now...") - sh( - f"{settings} {prefix} manage.py test {name} -v 3 {_keepdb} --noinput {live_server_option}" - ) - - except BuildFailure as e: - info(f"Tests failed! {str(e)}") - else: - success = True - finally: - if local: - stop(options) - _reset() - - if not success: - sys.exit(1) - - -@task -@needs( - [ - "start_geoserver", - ] -) -@cmdopts( - [ - ("coverage", "c", "use this flag to generate coverage during test runs"), - ("local=", "l", "Set to True if running tests locally"), - ] -) -def run_tests(options): - """ - Executes the entire test suite. - """ - if options.get("coverage"): - prefix = 'coverage run --branch --source=geonode \ ---omit="*/__init__*,*/test*,*/wsgi*,*/version*,*/migrations*,\ -*/search_indexes*,*/management/*,*/context_processors*,*/upload/*"' - else: - prefix = "python" - local = options.get("local", "false") # travis uses default to false - - if ( - not integration_tests - and not integration_csw_tests - and not integration_bdd_tests - ): - call_task("test", options={"prefix": prefix}) - elif integration_tests: - if integration_upload_tests: - call_task( - "test_integration", - options={ - "prefix": prefix, - "name": "geonode.upload.tests.integration", - "local": local, - }, - ) - elif integration_monitoring_tests: - call_task( - "test_integration", - options={ - "prefix": prefix, - "name": "geonode.monitoring.tests.integration", - "local": local, - }, - ) - elif integration_csw_tests: - call_task( - "test_integration", - options={"prefix": prefix, "name": "geonode.tests.csw", "local": local}, - ) - elif integration_bdd_tests: - call_task("test_bdd", options={"local": local}) - elif integration_server_tests: - call_task( - "test_integration", - options={ - "prefix": prefix, - "name": "geonode.geoserver.tests.integration", - "local": local, - }, - ) - else: - call_task( - "test_integration", - options={ - "prefix": prefix, - "name": "geonode.tests.integration", - "local": local, - }, - ) - sh("flake8 geonode") - - -@task -@needs(["stop"]) -def reset(options): - """ - Reset a development environment (Database, GeoServer & Catalogue) - """ - _reset() - - -def _reset(): - from geonode import settings - - path = os.path.join(settings.PROJECT_ROOT, "development.db") - sh(f"rm -rf {path}") - sh("rm -rf {{ project_name }}/development.db") - sh("rm -rf {{ project_name }}/uploaded/*") - _configure_data_dir() - - -@needs(["reset"]) -def reset_hard(options): - """ - Reset a development environment (Database, GeoServer & Catalogue) - """ - sh("git clean -dxf") - - -@task -@cmdopts( - [ - ("type=", "t", 'Import specific data type ("vector", "raster", "time")'), - ("settings=", "s", "Specify custom DJANGO_SETTINGS_MODULE"), - ] -) -def setup_data(options): - """ - Import sample data (from gisdata package) into GeoNode - """ - import gisdata - - ctype = options.get("type", None) - - data_dir = gisdata.GOOD_DATA - - if ctype in {"vector", "raster", "time"}: - data_dir = os.path.join(gisdata.GOOD_DATA, ctype) - - settings = options.get("settings", "") - if settings and "DJANGO_SETTINGS_MODULE" not in settings: - settings = f"DJANGO_SETTINGS_MODULE={settings}" - - from geonode import settings as geonode_settings - - if not os.path.exists(geonode_settings.MEDIA_ROOT): - info("media root not available, creating...") - os.makedirs(geonode_settings.MEDIA_ROOT, exist_ok=True) - - sh( - f"{settings} python -W ignore manage.py importlayers -v2 -hh {geonode_settings.SITEURL} {data_dir}" - ) - - -@needs(["package"]) -@cmdopts( - [ - ("key=", "k", "The GPG key to sign the package"), - ("ppa=", "p", "PPA this package should be published to."), - ] -) -def deb(options): - """ - Creates debian packages. - - Example uses: - paver deb - paver deb -k 12345 - paver deb -k 12345 -p geonode/testing - """ - key = options.get("key", None) - ppa = options.get("ppa", None) - - version, simple_version = versions() - - info(f"Creating package for GeoNode version {version}") - - # Get rid of any uncommitted changes to debian/changelog - info("Getting rid of any uncommitted changes in debian/changelog") - sh("git checkout package/debian/changelog") - - # Workaround for git-dch bug - # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=594580 - sh(f"rm -rf {os.path.realpath('package')}/.git") - sh(f"ln -s {os.path.realpath('.git')} {os.path.realpath('package')}") - - with pushd("package"): - # Install requirements - # sh('sudo apt-get -y install debhelper devscripts git-buildpackage') - - # sh(('git-dch --spawn-editor=snapshot --git-author --new-version=%s' - # ' --id-length=6 --ignore-branch --release' % (simple_version))) - # In case you publish from Ubuntu Xenial (git-dch is removed from upstream) - # use the following line instead: - # sh(('gbp dch --spawn-editor=snapshot --git-author --new-version=%s' - # ' --id-length=6 --ignore-branch --release' % (simple_version))) - distribution = "bionic" - # sh(('gbp dch --distribution=%s --force-distribution --spawn-editor=snapshot --git-author --new-version=%s' - # ' --id-length=6 --ignore-branch --release' % (distribution, simple_version))) - - deb_changelog = path("debian") / "changelog" - for idx, line in enumerate(fileinput.input([deb_changelog], inplace=True)): - if idx == 0: - logger.info( - f"geonode ({simple_version}) {distribution}; urgency=high", end="" - ) - else: - print(line.replace("urgency=medium", "urgency=high"), end="") - - # Revert workaround for git-dhc bug - sh("rm -rf .git") - - if key is None and ppa is None: - print("A local installable package") - sh("debuild -uc -us -A") - elif key is None and ppa is not None: - print("A sources package, signed by daemon") - sh("debuild -S") - elif key is not None and ppa is None: - print("A signed installable package") - sh(f"debuild -k{key} -A") - elif key is not None and ppa is not None: - print("A signed, source package") - sh(f"debuild -k{key} -S") - - if ppa is not None: - sh(f"dput ppa:{ppa} geonode_{simple_version}_source.changes") - - -@task -def publish(options): - if "GPG_KEY_GEONODE" in os.environ: - key = os.environ["GPG_KEY_GEONODE"] - else: - print("You need to set the GPG_KEY_GEONODE environment variable") - return - - if "PPA_GEONODE" in os.environ: - ppa = os.environ["PPA_GEONODE"] - else: - ppa = None - - call_task( - "deb", - options={ - "key": key, - "ppa": ppa, - # 'ppa': 'geonode/testing', - # 'ppa': 'geonode/unstable', - }, - ) - - version, simple_version = versions() - if ppa: - sh("git add package/debian/changelog") - sh(f'git commit -m "Updated changelog for version {version}"') - sh(f"git tag -f {version}") - sh(f"git push origin {version}") - sh(f"git tag -f debian/{simple_version}") - sh(f"git push origin debian/{simple_version}") - # sh('git push origin master') - sh("python setup.py sdist upload -r pypi") - - -def versions(): - import geonode - from geonode.version import get_git_changeset - - raw_version = geonode.__version__ - version = geonode.get_version() - timestamp = get_git_changeset() - - major, minor, revision, stage, edition = raw_version - - branch = "dev" - - if stage == "final": - stage = "thefinal" - - if stage == "unstable": - tail = f"{branch}{timestamp}" - else: - tail = f"{stage}{edition}" - - simple_version = f"{major}.{minor}.{revision}+{tail}" - return version, simple_version - - -def kill(arg1, arg2): - """Stops a proces that contains arg1 and is filtered by arg2""" - from subprocess import Popen, PIPE - - # Wait until ready - t0 = time.time() - # Wait no more than these many seconds - time_out = 30 - running = True - - while running and time.time() - t0 < time_out: - if os.name == "nt": - p = Popen( - f'tasklist | find "{arg1}"', - shell=True, - stdin=PIPE, - stdout=PIPE, - stderr=PIPE, - close_fds=False, - ) - else: - p = Popen( - f"ps aux | grep {arg1}", - shell=True, - stdin=PIPE, - stdout=PIPE, - stderr=PIPE, - close_fds=True, - ) - - lines = p.stdout.readlines() - - running = False - for line in lines: - # this kills all java.exe and python including self in windows - if (f"{arg2}" in str(line)) or (os.name == "nt" and f"{arg1}" in str(line)): - running = True - - # Get pid - fields = line.strip().split() - - info(f"Stopping {arg1} (process number {int(fields[1])})") - if os.name == "nt": - kill = f'taskkill /F /PID "{int(fields[1])}"' - else: - kill = f"kill -9 {int(fields[1])} 2> /dev/null" - os.system(kill) - - # Give it a little more time - time.sleep(1) - - if running: - _procs = "\n".join([str(_l).strip() for _l in lines]) - raise Exception(f"Could not stop {arg1}: " f"Running processes are\n{_procs}") - - -def waitfor(url, timeout=300): - started = False - for a in range(timeout): - try: - resp = urlopen(url) - except OSError: - pass - else: - if resp.getcode() == 200: - started = True - break - time.sleep(1) - return started - - -def _copytree(src, dst, symlinks=False, ignore=None): - if not os.path.exists(dst): - os.makedirs(dst, exist_ok=True) - for item in os.listdir(src): - s = os.path.join(src, item) - d = os.path.join(dst, item) - if os.path.isdir(s): - try: - shutil.copytree(s, d, symlinks, ignore) - except Exception: - pass - elif os.path.isfile(s): - shutil.copy2(s, d) - - -def justcopy(origin, target): - if os.path.isdir(origin): - shutil.rmtree(target, ignore_errors=True) - _copytree(origin, target) - elif os.path.isfile(origin): - if not os.path.exists(target): - os.makedirs(target, exist_ok=True) - shutil.copy(origin, target) - - -def str2bool(v): - if v and len(v) > 0: - return v.lower() in ("yes", "true", "t", "1") - else: - return False diff --git a/src/paver.sh b/src/paver.sh deleted file mode 100755 index 108d6519..00000000 --- a/src/paver.sh +++ /dev/null @@ -1,2 +0,0 @@ -. $HOME/.override_env -paver $@ diff --git a/src/paver_dev.sh.sample b/src/paver_dev.sh.sample deleted file mode 100644 index 718aff7d..00000000 --- a/src/paver_dev.sh.sample +++ /dev/null @@ -1,3 +0,0 @@ -set -a -source ../.override_dev_env -paver $@ diff --git a/src/project_name/__init__.py b/src/project_name/__init__.py deleted file mode 100644 index ca5c786a..00000000 --- a/src/project_name/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2017 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -import os - -__version__ = (4, 2, 0, "dev", 0) - - -default_app_config = "{{ project_name }}.apps.AppConfig" - - -def get_version(): - import {{ project_name }}.version - - return {{ project_name }}.version.get_version(__version__) diff --git a/src/project_name/apps.py b/src/project_name/apps.py deleted file mode 100644 index 352ad83f..00000000 --- a/src/project_name/apps.py +++ /dev/null @@ -1,41 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2018 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### -import os -from django.apps import AppConfig as BaseAppConfig - - -def run_setup_hooks(*args, **kwargs): - from django.conf import settings - from .celeryapp import app as celeryapp - - LOCAL_ROOT = os.path.abspath(os.path.dirname(__file__)) - settings.TEMPLATES[0]["DIRS"].insert(0, os.path.join(LOCAL_ROOT, "templates")) - - if celeryapp not in settings.INSTALLED_APPS: - settings.INSTALLED_APPS += (celeryapp,) - - -class AppConfig(BaseAppConfig): - name = "{{ project_name }}" - label = "{{ project_name }}" - - def ready(self): - super(AppConfig, self).ready() - run_setup_hooks() diff --git a/src/project_name/br/backup.sh b/src/project_name/br/backup.sh deleted file mode 100755 index b8fcef74..00000000 --- a/src/project_name/br/backup.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh -# ########################################################## -# Run a backup -# SOURCE_URL=$SOURCE_URL TARGET_URL=$TARGET_URL ./{{project_name}}/br/backup.sh $BKP_FOLDER_NAME -# - BKP_FOLDER_NAME: -# Default value = backup_restore -# Shared Backup Folder name. -# The scripts assume it is located on "root" e.g.: /$BKP_FOLDER_NAME/ -# -# - SOURCE_URL: -# Source Server URL, the one generating the "backup" file. -# -# - TARGET_URL: -# Target Server URL, the one which must be synched. -# -# e.g.: -# docker exec -it django4{{project_name}} sh -c 'SOURCE_URL=$SOURCE_URL TARGET_URL=$TARGET_URL ./{{project_name}}/br/backup.sh $BKP_FOLDER_NAME' -# ########################################################## - -# Exit script in case of error -set -e - -echo "-----------------------------------------------------" -echo "STARTING {{project_name}} BACKUP $(date)" -echo "-----------------------------------------------------" - -if [ "$1" != "" ]; then - BKP_FOLDER_NAME="$1" -else - BKP_FOLDER_NAME="backup_restore" -fi - -cd /usr/src/{{project_name}}/ - -./manage.sh backup -i -f -c $PWD/{{project_name}}/br/settings_docker.ini --backup-dir /$BKP_FOLDER_NAME/ - -BKP_FILE_LATEST=$(find /$BKP_FOLDER_NAME/*.zip -type f -exec stat -c '%Y %n' {} \; | sort -nr | awk 'NR==1,NR==1 {print $2}') -BKP_FILE_NAME=$(echo $BKP_FILE_LATEST | tail -n 1 | grep -oP -m 1 "\/$BKP_FOLDER_NAME\/\K.*" | sed 's|.zip||') - -sed -i 's~$~ /'"$BKP_FOLDER_NAME"'/'"$BKP_FILE_NAME"'.zip~g' /$BKP_FOLDER_NAME/$BKP_FILE_NAME.md5 - -echo "-----------------------------------------------------" -cat /$BKP_FOLDER_NAME/$BKP_FILE_NAME.md5 -echo "\n" -echo "-----------------------------------------------------" diff --git a/src/project_name/br/restore.sh b/src/project_name/br/restore.sh deleted file mode 100755 index 04b8dbc8..00000000 --- a/src/project_name/br/restore.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/sh -# ########################################################## -# Run a restore -# SOURCE_URL=$SOURCE_URL TARGET_URL=$TARGET_URL ./{{project_name}}/br/restore.sh $BKP_FOLDER_NAME -# - BKP_FOLDER_NAME: -# Default value = backup_restore -# Shared Backup Folder name. -# The scripts assume it is located on "root" e.g.: /$BKP_FOLDER_NAME/ -# -# - SOURCE_URL: -# Source Server URL, the one generating the "backup" file. -# -# - TARGET_URL: -# Target Server URL, the one which must be synched. -# -# e.g.: -# docker exec -it django4{{project_name}} sh -c 'SOURCE_URL=$SOURCE_URL TARGET_URL=$TARGET_URL ./{{project_name}}/br/restore.sh $BKP_FOLDER_NAME' -# ########################################################## - -# Exit script in case of error -set -e - -echo "-----------------------------------------------------" -echo "STARTING {{project_name}} RESTORE $(date)" -echo "-----------------------------------------------------" - -if [ "$1" != "" ]; then - BKP_FOLDER_NAME="$1" -else - BKP_FOLDER_NAME="backup_restore" -fi - -if [ -z "$SOURCE_URL" ] || [ -z "$TARGET_URL" ] -then - echo "-----------------------------------------------------" - echo "ERROR: SOURCE_URL and TARGET_URL environment variables not set" - echo " e.g.: SOURCE_URL=test.webgis.adbpo.it TARGET_URL=staging.webgis.adbpo.it" - echo "-----------------------------------------------------" - exit 1 -else - echo "$SOURCE_URL --> $TARGET_URL" -fi - -cd /usr/src/{{project_name}}/ - -echo "-----------------------------------------------------" -echo " 1. BACKUP $TARGET_URL" -echo "-----------------------------------------------------" - -NEW_UUID=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) -mkdir /$BKP_FOLDER_NAME/$NEW_UUID/ -SOURCE_URL=$SOURCE_URL TARGET_URL=$TARGET_URL ./{{project_name}}/br/backup.sh $BKP_FOLDER_NAME/$NEW_UUID - -echo "-----------------------------------------------------" -echo " 2. CHECK BACKUP.md5 $TARGET_URL" -echo "-----------------------------------------------------" - -BKP_FILE_LATEST=$(find /$BKP_FOLDER_NAME/$NEW_UUID/*.zip -type f -exec stat -c '%Y %n' {} \; | sort -nr | awk 'NR==1,NR==1 {print $2}') -BKP_FILE_NAME=$(echo $BKP_FILE_LATEST | tail -n 1 | grep -oP -m 1 "\/$BKP_FOLDER_NAME\/$NEW_UUID\/\K.*" | sed 's|.zip||') - -if md5sum -c /$BKP_FOLDER_NAME/$NEW_UUID/$BKP_FILE_NAME.md5; then - - echo "-----------------------------------------------------" - echo " - Original Backup of $TARGET_URL --> /$BKP_FOLDER_NAME/$NEW_UUID/" - echo " 3. RESTORE FROM $SOURCE_URL" - echo "-----------------------------------------------------" - - RECOVERY_FILE_NAME=$BKP_FILE_NAME - BKP_FILE_LATEST=$(find /$BKP_FOLDER_NAME/*.zip -type f -exec stat -c '%Y %n' {} \; | sort -nr | awk 'NR==1,NR==1 {print $2}') - BKP_FILE_NAME=$(echo $BKP_FILE_LATEST | tail -n 1 | grep -oP -m 1 "\/$BKP_FOLDER_NAME\/\K.*" | sed 's|.zip||') - - if md5sum -c /$BKP_FOLDER_NAME/$BKP_FILE_NAME.md5; then - # The MD5 sum matched - ./manage.sh restore -l -n -f --backup-file /$BKP_FOLDER_NAME/$BKP_FILE_NAME.zip --recovery-file /$BKP_FOLDER_NAME/$NEW_UUID/$RECOVERY_FILE_NAME.zip - ./manage.sh migrate_baseurl -f --source-address=$SOURCE_URL --target-address=$TARGET_URL - ./manage.sh set_all_datasets_metadata -d -i - else - # The MD5 sum didn't match - echo "-----------------------------------------------------" - echo " - Original Backup of $TARGET_URL --> /$BKP_FOLDER_NAME/$NEW_UUID/" - echo "ERROR: The MD5 sum didn't match" - echo "-----------------------------------------------------" - exit 1 - fi -else - # The MD5 sum didn't match - echo "-----------------------------------------------------" - echo " - Original Backup of $TARGET_URL --> /$BKP_FOLDER_NAME/$NEW_UUID/" - echo "ERROR: Could not save $TARGET_URL" - echo "-----------------------------------------------------" - exit 1 -fi - -echo "-----------------------------------------------------" -echo " - Original Backup of $TARGET_URL --> /$BKP_FOLDER_NAME/$NEW_UUID/" -echo "FINISHED {{project_name}} RESTORE $(date)" -echo "-----------------------------------------------------" diff --git a/src/project_name/br/settings_docker.ini b/src/project_name/br/settings_docker.ini deleted file mode 100644 index 9284b772..00000000 --- a/src/project_name/br/settings_docker.ini +++ /dev/null @@ -1,17 +0,0 @@ -[database] -pgdump = pg_dump -pgrestore = pg_restore -psql = psql - -[geoserver] -datadir = /geoserver_data/data -# datadir_exclude_file_path = {comma separated list of paths to exclude from geoserver catalog} e.g.: /data,/data/geonode,/geonode -dumpvectordata = yes -dumprasterdata = yes -# data_dt_filter = {cmp_operator} {ISO8601} e.g. > 20019-04-05T24:00 -# data_layername_filter = {comma separated list of layernames, optionally with glob syntax} e.g.: tuscany_*,italy -# data_layername_exclude_filter = {comma separated list of layernames, optionally with glob syntax} e.g.: tuscany_*,italy - -[fixtures] -apps = contenttypes,auth,people,groups,account,guardian,admin,actstream,announcements,avatar,base,documents,geoserver,invitations,pinax_notifications,layers,maps,oauth2_provider,harvesting,services,sites,socialaccount,taggit,tastypie,upload,user_messages,geonode_themes,geoapps,favorite,geonode_client -dumps = contenttypes,auth,people,groups,account,guardian,admin,actstream,announcements,avatar,base,documents,geoserver,invitations,pinax_notifications,layers,maps,oauth2_provider,harvesting,services,sites,socialaccount,taggit,tastypie,upload,user_messages,geonode_themes,geoapps,favorite,geonode_client diff --git a/src/project_name/celeryapp.py b/src/project_name/celeryapp.py deleted file mode 100644 index f8f0a292..00000000 --- a/src/project_name/celeryapp.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2017 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -from __future__ import absolute_import - -import os -from celery import Celery - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings") - -app = Celery("{{ project_name }}") - -# Using a string here means the worker will not have to -# pickle the object when using Windows. -app.config_from_object("django.conf:settings", namespace="CELERY") -app.autodiscover_tasks() - - -@app.task(bind=True, name="{{ project_name }}.debug_task", queue="default") -def debug_task(self): - print("Request: {!r}".format(self.request)) diff --git a/src/project_name/locale/.gitkeep b/src/project_name/locale/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/project_name/settings.py b/src/project_name/settings.py deleted file mode 100644 index 09ffd15e..00000000 --- a/src/project_name/settings.py +++ /dev/null @@ -1,164 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2017 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -# Django settings for the GeoNode project. -import os -import ast - -try: - from urllib.parse import urlparse, urlunparse - from urllib.request import urlopen, Request -except ImportError: - from urllib2 import urlopen, Request - from urlparse import urlparse, urlunparse -# Load more settings from a file called local_settings.py if it exists -try: - from {{ project_name }}.local_settings import * -# from geonode.local_settings import * -except ImportError: - from geonode.settings import * - -# -# General Django development settings -# -PROJECT_NAME = "{{ project_name }}" - -# add trailing slash to site url. geoserver url will be relative to this -if not SITEURL.endswith("/"): - SITEURL = "{}/".format(SITEURL) - -SITENAME = os.getenv("SITENAME", "{{ project_name }}") - -# Defines the directory that contains the settings file as the LOCAL_ROOT -# It is used for relative settings elsewhere. -LOCAL_ROOT = os.path.abspath(os.path.dirname(__file__)) - -WSGI_APPLICATION = "{}.wsgi.application".format(PROJECT_NAME) - -# Language code for this installation. All choices can be found here: -# http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = os.getenv("LANGUAGE_CODE", "en") - -if PROJECT_NAME not in INSTALLED_APPS: - INSTALLED_APPS += (PROJECT_NAME,) - -# Location of url mappings -ROOT_URLCONF = os.getenv("ROOT_URLCONF", "{}.urls".format(PROJECT_NAME)) - -# Additional directories which hold static files -# - Give priority to local geonode-project ones -STATICFILES_DIRS = [ - os.path.join(LOCAL_ROOT, "static"), -] + STATICFILES_DIRS - -# Location of locale files -LOCALE_PATHS = (os.path.join(LOCAL_ROOT, "locale"),) + LOCALE_PATHS - -TEMPLATES[0]["DIRS"].insert(0, os.path.join(LOCAL_ROOT, "templates")) -loaders = TEMPLATES[0]["OPTIONS"].get("loaders") or [ - "django.template.loaders.filesystem.Loader", - "django.template.loaders.app_directories.Loader", -] -# loaders.insert(0, 'apptemplates.Loader') -TEMPLATES[0]["OPTIONS"]["loaders"] = loaders -TEMPLATES[0].pop("APP_DIRS", None) - -LOGGING = { - "version": 1, - "disable_existing_loggers": True, - "formatters": { - "verbose": { - "format": "%(levelname)s %(asctime)s %(module)s %(process)d " - "%(thread)d %(message)s" - }, - "simple": { - "format": "%(message)s", - }, - }, - "filters": {"require_debug_false": {"()": "django.utils.log.RequireDebugFalse"}}, - "handlers": { - "console": { - "level": "ERROR", - "class": "logging.StreamHandler", - "formatter": "simple", - }, - "mail_admins": { - "level": "ERROR", - "filters": ["require_debug_false"], - "class": "django.utils.log.AdminEmailHandler", - }, - }, - "loggers": { - "django": { - "handlers": ["console"], - "level": "ERROR", - }, - "geonode": { - "handlers": ["console"], - "level": "INFO", - }, - "geoserver-restconfig.catalog": { - "handlers": ["console"], - "level": "ERROR", - }, - "owslib": { - "handlers": ["console"], - "level": "ERROR", - }, - "pycsw": { - "handlers": ["console"], - "level": "ERROR", - }, - "celery": { - "handlers": ["console"], - "level": "DEBUG", - }, - "mapstore2_adapter.plugins.serializers": { - "handlers": ["console"], - "level": "DEBUG", - }, - "geonode_logstash.logstash": { - "handlers": ["console"], - "level": "DEBUG", - }, - }, -} - -CENTRALIZED_DASHBOARD_ENABLED = ast.literal_eval( - os.getenv("CENTRALIZED_DASHBOARD_ENABLED", "False") -) -if ( - CENTRALIZED_DASHBOARD_ENABLED - and USER_ANALYTICS_ENABLED - and "geonode_logstash" not in INSTALLED_APPS -): - INSTALLED_APPS += ("geonode_logstash",) - - CELERY_BEAT_SCHEDULE["dispatch_metrics"] = { - "task": "geonode_logstash.tasks.dispatch_metrics", - "schedule": 3600.0, - } - -LDAP_ENABLED = ast.literal_eval(os.getenv("LDAP_ENABLED", "False")) -if LDAP_ENABLED and "geonode_ldap" not in INSTALLED_APPS: - INSTALLED_APPS += ("geonode_ldap",) - -# Add your specific LDAP configuration after this comment: -# https://docs.geonode.org/en/master/advanced/contrib/#configuration diff --git a/src/project_name/static/README b/src/project_name/static/README deleted file mode 100644 index 548e6b31..00000000 --- a/src/project_name/static/README +++ /dev/null @@ -1,20 +0,0 @@ -# Introduction - -This directory is used to store static assets for your project. User media files -(FileFields/ImageFields) are not stored here. - -The convention for this directory is: - - * css/ — stores CSS files - * less/ - stores LESS files - * js/ — stores Javascript files - * img/ — stores image files - -# Gulp - -Gulp can be used to automatically build css from LESS files. The gulp process will -watch you LESS files for changes and recompile. To install gulp do -the following 2 steps: - -1. cd into the project directory and install dependencies with `npm install` -2. install gulp command line globally with `sudo npm install -g gulp` diff --git a/src/project_name/static/css/site_base.css b/src/project_name/static/css/site_base.css deleted file mode 100644 index e69de29b..00000000 diff --git a/src/project_name/static/gulpfile.js b/src/project_name/static/gulpfile.js deleted file mode 100644 index a6f9fb59..00000000 --- a/src/project_name/static/gulpfile.js +++ /dev/null @@ -1,23 +0,0 @@ -var gulp = require('gulp'); -var gutil = require('gulp-util'); -var pkg = require('./package.json'); -var concat = require('gulp-concat'); -var less = require('gulp-less'); -var del = require('del'); - -gulp.task('clean:site_base.css', [], function () { - return del([ './css/site_base.css' ]); -}); - -gulp.task('compile:site_base.css', [], function() { - return gulp.src(["./less/site_base.less"], {base: './'}) - .pipe(less({})) - .pipe(concat("site_base.css")) - .pipe(gulp.dest("./css")); -}); - -gulp.task('watch', function() { - gulp.watch("./less/**/*", ['clean:site_base.css', 'compile:site_base.css']); -}); - -gulp.task('default', ['watch', 'clean:site_base.css', 'compile:site_base.css']); diff --git a/src/project_name/static/img/README b/src/project_name/static/img/README deleted file mode 100644 index e69de29b..00000000 diff --git a/src/project_name/static/img/bing_aerial_w_labels.png b/src/project_name/static/img/bing_aerial_w_labels.png deleted file mode 100644 index 131c8b8d..00000000 Binary files a/src/project_name/static/img/bing_aerial_w_labels.png and /dev/null differ diff --git a/src/project_name/static/img/bing_canvas_dark.png b/src/project_name/static/img/bing_canvas_dark.png deleted file mode 100644 index d6434233..00000000 Binary files a/src/project_name/static/img/bing_canvas_dark.png and /dev/null differ diff --git a/src/project_name/static/img/bing_road_on_demand.png b/src/project_name/static/img/bing_road_on_demand.png deleted file mode 100644 index 0da3163e..00000000 Binary files a/src/project_name/static/img/bing_road_on_demand.png and /dev/null differ diff --git a/src/project_name/static/js/README b/src/project_name/static/js/README deleted file mode 100644 index e69de29b..00000000 diff --git a/src/project_name/static/less/site_base.less b/src/project_name/static/less/site_base.less deleted file mode 100644 index e69de29b..00000000 diff --git a/src/project_name/static/package.json b/src/project_name/static/package.json deleted file mode 100644 index 4cb6e593..00000000 --- a/src/project_name/static/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "{{ project_name }}", - "version": "0.0.1", - "author": "GeoNode Developers", - "description": "Static code and assets for {{ project_name }}", - "contributors": [ - { - } - ], - "scripts": { - "test": "jshint **.js" - }, - "license": "BSD", - "private": "false", - "dependencies": { - }, - "devDependencies": { - "del": "*", - "gulp": "^3.9.0", - "gulp-util": "*", - "gulp-concat": "*", - "gulp-less": "*", - "path": "*" - } -} diff --git a/src/project_name/templates/geonode-mapstore-client/_geonode_config.html b/src/project_name/templates/geonode-mapstore-client/_geonode_config.html deleted file mode 100644 index ba045c66..00000000 --- a/src/project_name/templates/geonode-mapstore-client/_geonode_config.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends 'geonode-mapstore-client/_geonode_config.html' %} -{% block override_local_config %} - -{% endblock %} diff --git a/src/project_name/urls.py b/src/project_name/urls.py deleted file mode 100644 index 95be19c9..00000000 --- a/src/project_name/urls.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2017 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -from geonode.urls import urlpatterns - -""" -# You can register your own urlpatterns here -urlpatterns = [ - url(r'^/?$', - homepage, - name='home'), - ] + urlpatterns -""" diff --git a/src/project_name/version.py b/src/project_name/version.py deleted file mode 100644 index 66cb45ce..00000000 --- a/src/project_name/version.py +++ /dev/null @@ -1,56 +0,0 @@ -import datetime -import os -import subprocess - - -def get_version(version=None): - "Returns a PEP 386-compliant version number from VERSION." - if version is None: - from geonode import __version__ as version - else: - assert len(version) == 5 - assert version[3] in ("unstable", "beta", "rc", "final") - - # Now build the two parts of the version number: - # main = X.Y[.Z] - # sub = .devN - for pre-alpha releases - # | {a|b|c}N - for alpha, beta and rc releases - - parts = 2 if version[2] == 0 else 3 - main = ".".join(str(x) for x in version[:parts]) - - sub = "" - if version[3] == "unstable": - git_changeset = get_git_changeset() - if git_changeset: - sub = ".dev%s" % git_changeset - - elif version[3] != "final": - mapping = {"beta": "b", "rc": "rc"} - sub = mapping[version[3]] + str(version[4]) - - return main + sub - - -def get_git_changeset(): - """Returns a numeric identifier of the latest git changeset. - - The result is the UTC timestamp of the changeset in YYYYMMDDHHMMSS format. - This value isn't guaranteed to be unique, but collisions are very unlikely, - so it's sufficient for generating the development version numbers. - """ - repo_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - git_show = subprocess.Popen( - "git show --pretty=format:%ct --quiet HEAD", - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True, - cwd=repo_dir, - universal_newlines=True, - ) - timestamp = git_show.communicate()[0].partition("\n")[0] - try: - timestamp = datetime.datetime.utcfromtimestamp(int(timestamp)) - except ValueError: - return None - return timestamp.strftime("%Y%m%d%H%M%S") diff --git a/src/project_name/wsgi.py b/src/project_name/wsgi.py deleted file mode 100644 index ac6f3ab9..00000000 --- a/src/project_name/wsgi.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2017 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### - -""" -WSGI config for {{ project_name }} project. - -This module contains the WSGI application used by Django's development server -and any production WSGI deployments. It should expose a module-level variable -named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover -this application via the ``WSGI_APPLICATION`` setting. - -Usually you will have the standard Django WSGI application here, but it also -might make sense to replace the whole Django WSGI application with a custom one -that later delegates to the Django one. For example, you could introduce WSGI -middleware here, or combine a Django application with an application of another -framework. - -""" -import os - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings") - -# This application object is used by any WSGI server configured to use this -# file. This includes Django's development server, if the WSGI_APPLICATION -# setting points here. -from django.core.wsgi import get_wsgi_application - -application = get_wsgi_application() - -# Apply WSGI middleware here. -# from helloworld.wsgi import HelloWorldApplication -# application = HelloWorldApplication(application) diff --git a/src/requirements.txt b/src/requirements.txt deleted file mode 100644 index a9bd0ef3..00000000 --- a/src/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ --e git+https://github.com/GeoNode/geonode-mapstore-client.git@master#egg=django_geonode_mapstore_client --e git+https://github.com/GeoNode/geonode-importer.git@master#egg=geonode-importer --e git+https://github.com/GeoNode/geonode.git@master#egg=GeoNode diff --git a/src/scripts/misc/apache2/geonode.conf.sample b/src/scripts/misc/apache2/geonode.conf.sample deleted file mode 100644 index 4f45a02e..00000000 --- a/src/scripts/misc/apache2/geonode.conf.sample +++ /dev/null @@ -1,108 +0,0 @@ -WSGIDaemonProcess geonode python-path=/home/geo/geonode:/home/geo/Envs/geonode/lib/python2.7/site-packages user=www-data threads=15 processes=2 - - - ServerName http://localhost - ServerAdmin webmaster@localhost - DocumentRoot /home/geo/geonode/geonode - - LimitRequestFieldSize 32760 - LimitRequestLine 32760 - - ErrorLog /var/log/apache2/error.log - LogLevel info - CustomLog /var/log/apache2/access.log combined - - WSGIProcessGroup geonode - WSGIPassAuthorization On - WSGIScriptAlias / /home/geo/geonode/geonode/wsgi.py - - Alias /static/ /home/geo/geonode/geonode/static_root/ - Alias /uploaded/ /home/geo/geonode/geonode/uploaded/ - - - - Order deny,allow - Allow from all - Require all granted - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Options Indexes FollowSymLinks - Allow from all - Require all granted - IndexOptions FancyIndexing - - - - Order allow,deny - Allow from all - - - ProxyPreserveHost On - ProxyPass /geoserver http://localhost:8080/geoserver - ProxyPassReverse /geoserver http://localhost:8080/geoserver - - diff --git a/src/scripts/misc/cleanup_pyc.sh b/src/scripts/misc/cleanup_pyc.sh deleted file mode 100644 index 4eeae2b9..00000000 --- a/src/scripts/misc/cleanup_pyc.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -# This is the script directory -# pushd $(dirname $0) - -# This is the current directory -pushd $PWD - -find . -name "*.pyc" -exec rm -f {} \; diff --git a/src/scripts/misc/jetty-runner.xml b/src/scripts/misc/jetty-runner.xml deleted file mode 100644 index c7b747cb..00000000 --- a/src/scripts/misc/jetty-runner.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - /geoserver - - /WEB-INF/web.xml - false - - org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern - WONTMATCH - - diff --git a/src/setup.py b/src/setup.py deleted file mode 100644 index 096820a5..00000000 --- a/src/setup.py +++ /dev/null @@ -1,49 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2018 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### -import os - -from distutils.core import setup - -from setuptools import find_packages - - -def read(*rnames): - return open(os.path.join(os.path.dirname(__file__), *rnames)).read() - - -setup( - name="{{ project_name }}", - version="4.0.0", - author="", - author_email="", - description="{{ project_name }}, based on GeoNode", - long_description=(read("README.md")), - # Full list of classifiers can be found at: - # http://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - "Development Status :: 1 - Planning", - ], - license="GPL", - keywords="{{ project_name }} geonode django", - url="https://github.com/{{ project_name }}/{{ project_name }}", - packages=find_packages(), - dependency_links=["git+https://github.com/GeoNode/geonode.git#egg=geonode"], - include_package_data=True, -) diff --git a/src/tasks.py b/src/tasks.py deleted file mode 100644 index 3ec6b717..00000000 --- a/src/tasks.py +++ /dev/null @@ -1,757 +0,0 @@ -# -*- coding: utf-8 -*- -######################################################################### -# -# Copyright (C) 2016 OSGeo -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -######################################################################### -import os -import re -import ast -import json -import time -import docker -import socket -import ipaddress -import logging -import datetime - -from urllib.parse import urlparse, urlunparse -from invoke import task - -BOOTSTRAP_IMAGE_CHEIP = "codenvy/che-ip:nightly" - -logger = logging.getLogger(__name__) - - -@task -def waitfordbs(ctx): - print("**************************databases*******************************") - db_host = os.getenv("DATABASE_HOST", "db") - ctx.run(f"/usr/bin/wait-for-databases {db_host}", pty=True) - - -@task -def update(ctx): - print("***************************setting env*********************************") - ctx.run("env", pty=True) - pub_host = _geonode_public_host() - print(f"Public Hostname or IP is {pub_host}") - pub_port = _geonode_public_port() - print(f"Public PORT is {pub_port}") - pub_protocol = "https" if pub_port == "443" else "http" - if pub_protocol == "https" or pub_port == "80": - pub_port = None - db_url = _update_db_connstring() - geodb_url = _update_geodb_connstring() - geonode_docker_host = None - for _cnt in range(1, 29): - try: - geonode_docker_host = str(socket.gethostbyname("geonode")) - except Exception: - print(f"...waiting for NGINX to pop-up...{_cnt}") - time.sleep(1) - - override_env = "$HOME/.override_env" - if os.path.exists(override_env): - os.remove(override_env) - else: - print(f"Can not delete the {override_env} file as it doesn't exists") - - if pub_port: - siteurl = f"{pub_protocol}://{pub_host}:{pub_port}/" - gs_pub_loc = f"http://{pub_host}:{pub_port}/geoserver/" - else: - siteurl = f"{pub_protocol}://{pub_host}/" - gs_pub_loc = f"http://{pub_host}/geoserver/" - envs = { - "local_settings": str(_localsettings()), - "siteurl": os.environ.get("SITEURL", siteurl), - "geonode_docker_host": geonode_docker_host, - "public_protocol": pub_protocol, - "public_fqdn": str(pub_host) + str(f":{pub_port}" if pub_port else ""), - "public_host": str(pub_host), - "dburl": os.environ.get("DATABASE_URL", db_url), - "geodburl": os.environ.get("GEODATABASE_URL", geodb_url), - "static_root": os.environ.get("STATIC_ROOT", "/mnt/volumes/statics/static/"), - "media_root": os.environ.get("MEDIA_ROOT", "/mnt/volumes/statics/uploaded/"), - "geoip_path": os.environ.get("GEOIP_PATH", "/mnt/volumes/statics/geoip.db"), - "monitoring": os.environ.get("MONITORING_ENABLED", False), - "monitoring_host_name": os.environ.get("MONITORING_HOST_NAME", "geonode"), - "monitoring_service_name": os.environ.get( - "MONITORING_SERVICE_NAME", "local-geonode" - ), - "monitoring_data_ttl": os.environ.get("MONITORING_DATA_TTL", 7), - "geonode_geodb_passwd": os.environ.get( - "GEONODE_GEODATABASE_PASSWORD", "geonode_data" - ), - "default_backend_datastore": os.environ.get( - "DEFAULT_BACKEND_DATASTORE", "datastore" - ), - "geonode_db_passwd": os.environ.get("GEONODE_DATABASE_PASSWORD", "geonode"), - "geonode_geodb": os.environ.get("GEONODE_GEODATABASE", "geonode_data"), - "db_url": os.environ.get( - "DATABASE_URL", "postgis://geonode:geonode@db:5432/geonode" - ), - "geodb_url": os.environ.get( - "GEODATABASE_URL", "postgis://geonode:geonode@db:5432/geonode_data" - ), - "geonode_db": os.environ.get("GEONODE_DATABASE", "geonode"), - "gs_loc": os.environ.get( - "GEOSERVER_LOCATION", "http://geoserver:8080/geoserver/" - ), - "gs_web_ui_loc": os.environ.get("GEOSERVER_WEB_UI_LOCATION", gs_pub_loc), - "gs_pub_loc": os.environ.get("GEOSERVER_PUBLIC_LOCATION", gs_pub_loc), - "gs_admin_pwd": os.environ.get("GEOSERVER_ADMIN_PASSWORD", "geoserver"), - "override_fn": override_env, - } - try: - current_allowed = ast.literal_eval( - os.getenv("ALLOWED_HOSTS") - or "['{public_fqdn}', '{public_host}', 'localhost', 'django', 'geonode',]".format( - **envs - ) - ) - except ValueError: - current_allowed = [] - current_allowed.extend([str(pub_host), f"{pub_host}:{pub_port}"]) - allowed_hosts = [str(c) for c in current_allowed] + ['"geonode"', '"django"'] - - ctx.run( - "echo export DJANGO_SETTINGS_MODULE=\ -{local_settings} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export MONITORING_ENABLED=\ -{monitoring} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export MONITORING_HOST_NAME=\ -{monitoring_host_name} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export MONITORING_SERVICE_NAME=\ -{monitoring_service_name} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export MONITORING_DATA_TTL=\ -{monitoring_data_ttl} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEOIP_PATH=\ -{geoip_path} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEONODE_GEODATABASE_PASSWORD=\ -{geonode_geodb_passwd} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export DEFAULT_BACKEND_DATASTORE=\ -{default_backend_datastore} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEONODE_DATABASE_PASSWORD=\ -{geonode_db_passwd} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEONODE_GEODATABASE=\ -{geonode_geodb} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export DATABASE_URL=\ -{db_url} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEODATABASE_URL=\ -{geodb_url} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEONODE_DATABASE=\ -{geonode_db} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEOSERVER_LOCATION=\ -{gs_loc} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEOSERVER_WEB_UI_LOCATION=\ -{gs_web_ui_loc} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEOSERVER_PUBLIC_LOCATION=\ -{gs_pub_loc} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEOSERVER_ADMIN_PASSWORD=\ -{gs_admin_pwd} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export SITEURL=\ -{siteurl} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - 'echo export ALLOWED_HOSTS=\ -"\\"{}\\"" >> {override_fn}'.format( - allowed_hosts, **envs - ), - pty=True, - ) - ctx.run( - "echo export DATABASE_URL=\ -{dburl} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEODATABASE_URL=\ -{geodburl} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export STATIC_ROOT=\ -{static_root} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export MEDIA_ROOT=\ -{media_root} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export GEOIP_PATH=\ -{geoip_path} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export LOGIN_URL=\ -{siteurl}account/login/ >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export LOGOUT_URL=\ -{siteurl}account/logout/ >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export LOGIN_REDIRECT_URL=\ -{siteurl} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run( - "echo export LOGOUT_REDIRECT_URL=\ -{siteurl} >> {override_fn}".format( - **envs - ), - pty=True, - ) - ctx.run(f"source {override_env}", pty=True) - print("****************************finalize env**********************************") - ctx.run("env", pty=True) - - -@task -def migrations(ctx): - print("**************************migrations*******************************") - ctx.run( - f"python manage.py migrate --noinput --settings={_localsettings()}", pty=True - ) - ctx.run( - f"python manage.py migrate --noinput --settings={_localsettings()} --database=datastore", - pty=True, - ) - try: - ctx.run( - f"python manage.py rebuild_index --noinput --settings={_localsettings()}", - pty=True, - ) - except Exception: - pass - - -@task -def statics(ctx): - print("**************************statics*******************************") - try: - ctx.run("mkdir -p /mnt/volumes/statics/{static,uploads}") - ctx.run( - f"python manage.py collectstatic --noinput --settings={_localsettings()}", - pty=True, - ) - except Exception: - import traceback - - traceback.print_exc() - - -@task -def prepare(ctx): - print("**********************prepare fixture***************************") - ctx.run("rm -rf /tmp/default_oauth_apps_docker.json", pty=True) - _prepare_oauth_fixture() - ctx.run("rm -rf /tmp/default_site.json", pty=True) - _prepare_site_fixture() - - -@task -def fixtures(ctx): - print("**************************fixtures********************************") - ctx.run( - f"python manage.py loaddata sample_admin \ ---settings={_localsettings()}", - pty=True, - ) - ctx.run( - f"python manage.py loaddata /tmp/default_oauth_apps_docker.json \ ---settings={_localsettings()}", - pty=True, - ) - ctx.run( - f"python manage.py loaddata /tmp/default_site.json \ ---settings={_localsettings()}", - pty=True, - ) - ctx.run( - f"python manage.py loaddata initial_data.json \ ---settings={_localsettings()}", - pty=True, - ) - - -@task -def collectstatic(ctx): - print("************************static artifacts******************************") - ctx.run( - f"django-admin.py collectstatic --noinput \ ---settings={_localsettings()}", - pty=True, - ) - - -@task -def monitoringfixture(ctx): - if ast.literal_eval(os.environ.get("MONITORING_ENABLED", "False")): - print("*******************monitoring fixture********************************") - ctx.run("rm -rf /tmp/default_monitoring_apps_docker.json", pty=True) - _prepare_monitoring_fixture() - try: - ctx.run( - f"django-admin loaddata metric_data.json \ - --settings={_localsettings()}", - pty=True, - ) - ctx.run( - f"django-admin loaddata notifications.json \ - --settings={_localsettings()}", - pty=True, - ) - ctx.run( - f"django-admin loaddata /tmp/default_monitoring_apps_docker.json \ - --settings={_localsettings()}", - pty=True, - ) - except Exception as e: - logger.error(f"ERROR installing monitoring fixture: {str(e)}") - - -@task -def updategeoip(ctx): - print("**************************update geoip*******************************") - if ast.literal_eval(os.environ.get("MONITORING_ENABLED", "False")): - ctx.run(f"django-admin.py updategeoip --settings={_localsettings()}", pty=True) - - -@task -def updateadmin(ctx): - print("***********************update admin details**************************") - ctx.run("rm -rf /tmp/django_admin_docker.json", pty=True) - _prepare_admin_fixture( - os.environ.get("ADMIN_PASSWORD", "admin"), - os.environ.get("ADMIN_EMAIL", "admin@example.org"), - ) - ctx.run( - f"django-admin.py loaddata /tmp/django_admin_docker.json \ ---settings={_localsettings()}", - pty=True, - ) - - -@task -def collectmetrics(ctx): - print("************************collect metrics******************************") - ctx.run( - f"python -W ignore manage.py collect_metrics \ ---settings={_localsettings()} -n -t xml", - pty=True, - ) - - -@task -def initialized(ctx): - print("**************************init file********************************") - ctx.run("date > /mnt/volumes/statics/geonode_init.lock") - - -def _docker_host_ip(): - try: - client = docker.from_env(version="1.24") - ip_list = client.containers.run( - BOOTSTRAP_IMAGE_CHEIP, network_mode="host" - ).split("\n") - except Exception: - import traceback - - traceback.print_exc() - ip_list = [ - "127.0.0.1", - ] - if len(ip_list) > 1: - print( - f"Docker daemon is running on more than one \ -address {ip_list}" - ) - print(f"Only the first address:{ip_list[0]} will be returned!") - else: - print( - f"Docker daemon is running at the following \ -address {ip_list[0]}" - ) - return ip_list[0] - -def _is_valid_ip(ip): - try: - ipaddress.IPv4Address(ip) - return True - except Exception as e: - return False - -def _container_exposed_port(component, instname): - port = "80" - try: - client = docker.from_env(version="1.24") - ports_dict = json.dumps( - [ - c.attrs["Config"]["ExposedPorts"] - for c in client.containers.list( - filters={ - "label": f"org.geonode.component={component}", - "status": "running", - } - ) - if str(instname) in c.name - ][0] - ) - for key in json.loads(ports_dict): - port = re.split("/tcp", key)[0] - except Exception: - import traceback - - traceback.print_exc() - return port - - -def _update_db_connstring(): - user = os.getenv("GEONODE_DATABASE", "geonode") - pwd = os.getenv("GEONODE_DATABASE_PASSWORD", "geonode") - dbname = os.getenv("GEONODE_DATABASE", "geonode") - dbhost = os.getenv("DATABASE_HOST", "db") - dbport = os.getenv("DATABASE_PORT", 5432) - connstr = f"postgis://{user}:{pwd}@{dbhost}:{dbport}/{dbname}" - return connstr - - -def _update_geodb_connstring(): - geouser = os.getenv("GEONODE_GEODATABASE", "geonode_data") - geopwd = os.getenv("GEONODE_GEODATABASE_PASSWORD", "geonode_data") - geodbname = os.getenv("GEONODE_GEODATABASE", "geonode_data") - dbhost = os.getenv("DATABASE_HOST", "db") - dbport = os.getenv("DATABASE_PORT", 5432) - geoconnstr = f"postgis://{geouser}:{geopwd}@{dbhost}:{dbport}/{geodbname}" - return geoconnstr - - -def _localsettings(): - settings = os.getenv("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings") - return settings - - -def _gs_service_availability(url): - import requests - - try: - r = requests.request("get", url, verify=False) - r.raise_for_status() # Raises a HTTPError if the status is 4xx, 5xxx - except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as e: - logger.error(f"GeoServer connection error is {e}") - return False - except requests.exceptions.HTTPError as er: - logger.error(f"GeoServer HTTP error is {er}") - return False - else: - logger.info("GeoServer API are available!") - return True - - -def _geonode_public_host(): - gn_pub_hostip = os.getenv("GEONODE_LB_HOST_IP", None) - if not gn_pub_hostip: - gn_pub_hostip = _docker_host_ip() - return gn_pub_hostip - - -def _geonode_public_host_ip(): - gn_pub_hostip = os.getenv("GEONODE_LB_HOST_IP", None) - if not gn_pub_hostip or not _is_valid_ip(gn_pub_hostip): - gn_pub_hostip = _docker_host_ip() - return gn_pub_hostip - - -def _geonode_public_port(): - gn_pub_port = os.getenv("GEONODE_LB_PORT", "") - if not gn_pub_port: - gn_pub_port = _container_exposed_port( - "nginx", os.getenv("GEONODE_INSTANCE_NAME", "geonode") - ) - elif gn_pub_port in ("80", "443"): - gn_pub_port = None - return gn_pub_port - - -def _prepare_oauth_fixture(): - upurl = urlparse(os.environ["SITEURL"]) - default_fixture = [ - { - "model": "oauth2_provider.application", - "pk": 1001, - "fields": { - "skip_authorization": True, - "created": "2018-05-31T10:00:31.661Z", - "updated": "2018-05-31T11:30:31.245Z", - "algorithm": "RS256", - "redirect_uris": f"{urlunparse(upurl)}geoserver/index.html", - "name": "GeoServer", - "authorization_grant_type": "authorization-code", - "client_type": "confidential", - "client_id": str(os.environ["OAUTH2_CLIENT_ID"]), - "client_secret": str(os.environ["OAUTH2_CLIENT_SECRET"]), - "user": ["admin"], - }, - } - ] - with open("/tmp/default_oauth_apps_docker.json", "w") as fixturefile: - json.dump(default_fixture, fixturefile) - - -def _prepare_site_fixture(): - upurl = urlparse(os.environ["SITEURL"]) - default_fixture = [ - { - "model": "sites.site", - "pk": 1, - "fields": {"domain": str(upurl.hostname), "name": str(upurl.hostname)}, - } - ] - with open("/tmp/default_site.json", "w") as fixturefile: - json.dump(default_fixture, fixturefile) - - -def _prepare_monitoring_fixture(): - # upurl = urlparse(os.environ['SITEURL']) - # net_scheme = upurl.scheme - # net_loc = upurl.netloc - pub_ip = _geonode_public_host() - print(f"Public Hostname or IP is {pub_ip}") - pub_port = _geonode_public_port() - print(f"Public PORT is {pub_port}") - try: - geonode_ip = socket.gethostbyname("geonode") - except Exception: - geonode_ip = pub_ip - try: - geoserver_ip = socket.gethostbyname("geoserver") - except Exception: - geoserver_ip = pub_ip - d = "1970-01-01 00:00:00" - default_fixture = [ - { - "fields": { - "active": True, - "ip": str(geonode_ip), - "name": str(os.environ["MONITORING_HOST_NAME"]), - }, - "model": "monitoring.host", - "pk": 1, - }, - { - "fields": {"active": True, "ip": str(geoserver_ip), "name": "geoserver"}, - "model": "monitoring.host", - "pk": 2, - }, - { - "fields": { - "name": str(os.environ["MONITORING_SERVICE_NAME"]), - "url": str(os.environ["SITEURL"]), - "notes": "", - "last_check": d, - "active": True, - "host": 1, - "check_interval": "00:01:00", - "service_type": 1, - }, - "model": "monitoring.service", - "pk": 1, - }, - { - "fields": { - "name": "geoserver-hostgeonode", - "url": str(os.environ["SITEURL"]), - "notes": "", - "last_check": d, - "active": True, - "host": 1, - "check_interval": "00:01:00", - "service_type": 3, - }, - "model": "monitoring.service", - "pk": 2, - }, - { - "fields": { - "name": "geoserver-hostgeoserver", - "url": str(os.environ["GEOSERVER_PUBLIC_LOCATION"]), - "notes": "", - "last_check": d, - "active": True, - "host": 2, - "check_interval": "00:01:00", - "service_type": 4, - }, - "model": "monitoring.service", - "pk": 3, - }, - { - "fields": { - "name": "default-geoserver", - "url": "http://geoserver:8080/geoserver/", - "notes": "", - "last_check": d, - "active": True, - "host": 2, - "check_interval": "00:01:00", - "service_type": 2, - }, - "model": "monitoring.service", - "pk": 4, - }, - ] - with open("/tmp/default_monitoring_apps_docker.json", "w") as fixturefile: - json.dump(default_fixture, fixturefile) - - -def _prepare_admin_fixture(admin_password, admin_email): - from django.contrib.auth.hashers import make_password - - d = datetime.datetime.now() - mdext_date = f"{d.isoformat()[:23]}Z" - default_fixture = [ - { - "fields": { - "date_joined": mdext_date, - "email": admin_email, - "first_name": "", - "groups": [], - "is_active": True, - "is_staff": True, - "is_superuser": True, - "last_login": mdext_date, - "last_name": "", - "password": make_password(admin_password), - "user_permissions": [], - "username": "admin", - }, - "model": "people.Profile", - "pk": 1000, - } - ] - with open("/tmp/django_admin_docker.json", "w") as fixturefile: - json.dump(default_fixture, fixturefile) diff --git a/src/uwsgi.ini b/src/uwsgi.ini deleted file mode 100644 index 7754daf2..00000000 --- a/src/uwsgi.ini +++ /dev/null @@ -1,47 +0,0 @@ -[uwsgi] -# uwsgi-socket = 0.0.0.0:8000 -http-socket = 0.0.0.0:8000 -logto = /var/log/geonode.log -# pidfile = /tmp/geonode.pid - -chdir = /usr/src/{{project_name}}/ -module = {{project_name}}.wsgi:application - -strict = false -master = true -enable-threads = true -vacuum = true ; Delete sockets during shutdown -single-interpreter = true -die-on-term = true ; Shutdown when receiving SIGTERM (default is respawn) -need-app = true -thunder-lock = true - -touch-reload = /usr/src/{{project_name}}/{{project_name}}/wsgi.py -buffer-size = 32768 - -harakiri = 600 ; forcefully kill workers after 600 seconds -py-callos-afterfork = true ; allow workers to trap signals - -max-requests = 1000 ; Restart workers after this many requests -max-worker-lifetime = 3600 ; Restart workers after this many seconds -reload-on-rss = 2048 ; Restart workers after this much resident memory -worker-reload-mercy = 60 ; How long to wait before forcefully killing workers - -cheaper-algo = busyness -processes = 128 ; Maximum number of workers allowed -cheaper = 8 ; Minimum number of workers allowed -cheaper-initial = 16 ; Workers created at startup -cheaper-overload = 1 ; Length of a cycle in seconds -cheaper-step = 16 ; How many workers to spawn at a time - -cheaper-busyness-multiplier = 30 ; How many cycles to wait before killing workers -cheaper-busyness-min = 20 ; Below this threshold, kill workers (if stable for multiplier cycles) -cheaper-busyness-max = 70 ; Above this threshold, spawn new workers -cheaper-busyness-backlog-alert = 16 ; Spawn emergency workers if more than this many requests are waiting in the queue -cheaper-busyness-backlog-step = 2 ; How many emergency workers to create if there are too many requests in the queue - -# cron = -1 -1 -1 -1 -1 sh -c '/usr/src/{{project_name}}/manage.sh collect_metrics -n -t xml'; -# cron = 0 0 -1 -1 -1 sh -c 'find /backup_restore/ -type f -mtime +30 -exec rm -f {} \;' -# Remove backup files older than 30 days except the most recent 3 files (a backup is composed by 3 files) -cron = 0 0 -1 -1 -1 sh -c 'find /backup_restore/ -maxdepth 1 -type f -mtime +30 -printf "%T@ %p\n" | sort -n | head -n -3 | awk "{ print $2 }" | xargs -r rm' -cron = 0 0 -1 -1 -1 sh -c 'find /backup_restore/ -type d -ctime +30 -exec rm -rf {} \;' diff --git a/src/wait-for-databases.sh b/src/wait-for-databases.sh deleted file mode 100755 index 2f423213..00000000 --- a/src/wait-for-databases.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -set -e - -host="$1" -shift - -until PGPASSWORD=${POSTGRES_PASSWORD} psql -h "$host" -U ${POSTGRES_USER} -P "pager=off" -c '\l'; do - >&2 echo "Postgres is unavailable - sleeping" - sleep 1 -done - -until PGPASSWORD=${GEONODE_DATABASE_PASSWORD} psql -h "$host" -U ${GEONODE_DATABASE} -d ${GEONODE_DATABASE} -P "pager=off" -c '\l'; do - >&2 echo "${GEONODE_DATABASE} is unavailable - sleeping" - sleep 1 -done - -until PGPASSWORD=${GEONODE_GEODATABASE_PASSWORD} psql -h "$host" -U ${GEONODE_GEODATABASE} -d ${GEONODE_GEODATABASE} -P "pager=off" -c '\l'; do - >&2 echo "${GEONODE_GEODATABASE} is unavailable - sleeping" - sleep 1 -done - ->&2 echo "GeoNode databases are up - executing command"