├── .dockerignore ├── .env ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── 10_bug_report.yml │ ├── 15_feature_request.yml │ └── config.yml ├── dependabot.yml └── workflows │ ├── build-latest.yaml │ └── deploy-image.yaml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── build_data ├── broker.xml ├── cluster.properties ├── community_plugins.py ├── community_plugins.txt ├── context.xml ├── controlflow.properties ├── embedded-broker.properties ├── extensions.sh ├── geowebcache-diskquota-jdbc.xml ├── geowebcache-diskquota.xml ├── google_fonts.txt ├── gwc-gs.xml ├── hazelcast_cluster │ ├── cluster.properties │ ├── hazelcast.xml │ └── web.xml ├── index.jsp ├── jdbcconfig │ ├── jdbcconfig.properties │ └── scripts │ │ ├── dropdb.h2.sql │ │ ├── dropdb.mssql.sql │ │ ├── dropdb.mysql.sql │ │ ├── dropdb.oracle.sql │ │ ├── dropdb.postgres.sql │ │ ├── initdb.h2.sql │ │ ├── initdb.mssql.sql │ │ ├── initdb.mysql.sql │ │ ├── initdb.oracle.sql │ │ └── initdb.postgres.sql ├── jdbcstore │ ├── jdbcstore.properties │ └── scripts │ │ ├── drop.h2.sql │ │ ├── drop.postgres.sql │ │ ├── init.h2.sql │ │ └── init.postgres.sql ├── jdom2-2.0.6.1.jar ├── letsencrypt-tomcat.xsl ├── log4j.properties ├── logging.properties ├── plugin_download.sh ├── required_plugins.txt ├── stable_plugins.py ├── stable_plugins.txt ├── tomcat-users.xml └── web.xml ├── clustering ├── README.md ├── activemq-docker │ ├── Dockerfile │ ├── activemq.xml │ └── setup-jars.sh ├── docker-compose-external.yml └── docker-compose.yml ├── docker-compose-build.yml ├── docker-compose-nginx.yml ├── docker-compose.yml ├── docs ├── 404.html ├── Environment-Variables │ └── index.html ├── Getting-the-image │ └── index.html ├── Kubernetes │ └── index.html ├── Mounting-Configs │ └── index.html ├── Running-the-Image │ └── index.html ├── Support-and-credits │ └── index.html ├── assets │ ├── images │ │ └── favicon.png │ ├── javascripts │ │ ├── bundle.a00a7c5e.min.js │ │ ├── bundle.a00a7c5e.min.js.map │ │ ├── lunr │ │ │ ├── min │ │ │ │ ├── lunr.ar.min.js │ │ │ │ ├── lunr.da.min.js │ │ │ │ ├── lunr.de.min.js │ │ │ │ ├── lunr.du.min.js │ │ │ │ ├── lunr.es.min.js │ │ │ │ ├── lunr.fi.min.js │ │ │ │ ├── lunr.fr.min.js │ │ │ │ ├── lunr.hi.min.js │ │ │ │ ├── lunr.hu.min.js │ │ │ │ ├── lunr.it.min.js │ │ │ │ ├── lunr.ja.min.js │ │ │ │ ├── lunr.jp.min.js │ │ │ │ ├── lunr.ko.min.js │ │ │ │ ├── lunr.multi.min.js │ │ │ │ ├── lunr.nl.min.js │ │ │ │ ├── lunr.no.min.js │ │ │ │ ├── lunr.pt.min.js │ │ │ │ ├── lunr.ro.min.js │ │ │ │ ├── lunr.ru.min.js │ │ │ │ ├── lunr.stemmer.support.min.js │ │ │ │ ├── lunr.sv.min.js │ │ │ │ ├── lunr.ta.min.js │ │ │ │ ├── lunr.th.min.js │ │ │ │ ├── lunr.tr.min.js │ │ │ │ ├── lunr.vi.min.js │ │ │ │ └── lunr.zh.min.js │ │ │ ├── tinyseg.js │ │ │ └── wordcut.js │ │ └── workers │ │ │ ├── search.db81ec45.min.js │ │ │ └── search.db81ec45.min.js.map │ └── stylesheets │ │ ├── main.0d440cfe.min.css │ │ ├── main.0d440cfe.min.css.map │ │ ├── palette.2505c338.min.css │ │ └── palette.2505c338.min.css.map ├── index.html ├── search │ └── search_index.json ├── sitemap.xml └── sitemap.xml.gz ├── resources ├── README.txt └── overlays │ └── README.txt ├── scenario_tests ├── .gitignore ├── README.md ├── backup_restore │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ ├── test_geoserver_backup.py │ │ └── test_geoserver_restore.py ├── clustering │ ├── docker-compose-external.yml │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── init.sql │ │ ├── test.sh │ │ ├── test_clustering_master.py │ │ └── test_clustering_node.py ├── context │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ └── test_context.py ├── disk-quota │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ └── test_disk_quota.py ├── gwc │ ├── docker-compose-gwc.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ └── test_gwc.py ├── jdbconfig │ ├── docker-compose-postgis-jndi.yml │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ └── test_jdbconfig.py ├── libjpeg │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ └── test_libjpeg.py ├── logging_profile │ ├── assets │ │ └── logging.xml │ ├── docker-compose.yml │ ├── test.sh │ ├── tests │ │ └── test.sh │ └── version.xml ├── login │ ├── docker-compose.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ └── test_login.py ├── stores │ ├── docker-compose-gdal.yml │ ├── docker-compose-postgis-jndi.yml │ ├── test.sh │ └── tests │ │ ├── __init__.py │ │ ├── test.sh │ │ ├── test_gdal.py │ │ └── test_jndi.py ├── test-env.sh └── utils │ └── requirements.txt ├── scripts ├── entrypoint.sh ├── env-data.sh ├── functions.sh ├── setup.sh ├── start.sh └── update_passwords.sh ├── sites-enabled └── nginx.conf └── upgrade_geoserver_version.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | docker-env/* 2 | Dockerfile 3 | .git* -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.sh text eol=lf -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [kartoza] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/10_bug_report.yml: -------------------------------------------------------------------------------- 1 | name: Bug/Crash report 2 | description: Create a bug report to help us improve docker-geoserver. 3 | labels: 4 | - 'Bug' 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this bug report correctly. 10 | 11 | Please report only issues related to the docker-geoserver. 12 | 13 | If the issue is related to an extension, you should file the issue in the [GeoServer jira](https://osgeo-org.atlassian.net/projects/GEOS/summary). 14 | 15 | 16 | - type: textarea 17 | id: what 18 | attributes: 19 | label: What is the bug or the crash? 20 | validations: 21 | required: true 22 | 23 | - type: textarea 24 | id: steps 25 | attributes: 26 | label: Steps to reproduce the issue 27 | description: | 28 | Steps, sample docker-compose to reproduce the behavior. Screencasts or screenshots are more than welcome, you can drag&drop them in the text box. 29 | 1. Go to '...' 30 | 2. Click on '...' 31 | 3. Scroll down to '...' 32 | 4. See error 33 | validations: 34 | required: true 35 | 36 | - type: textarea 37 | id: about-info 38 | attributes: 39 | label: Versions 40 | description: | 41 | Check the version of GeoServer in the UI or docker-compose. Finally paste here. 42 | Do not make a screenshot. 43 | validations: 44 | required: true 45 | 46 | 47 | - type: textarea 48 | id: additional-context 49 | attributes: 50 | label: Additional context 51 | description: | 52 | Add any other context about the problem here. 53 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/15_feature_request.yml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest a feature idea for docker-geoserver. 3 | labels: 4 | - 'Feature Request' 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | Thanks for taking the time to fill out this feature request correctly. 10 | 11 | - type: textarea 12 | id: what 13 | attributes: 14 | label: Feature description 15 | description: A clear and concise description of what you want to happen. Ex. docker-geoserver would rock even more if [...] 16 | validations: 17 | required: true 18 | 19 | - type: textarea 20 | id: Additional 21 | attributes: 22 | label: Additional context 23 | description: | 24 | Add any other context or screenshots about the feature request here. Open source is community driven, please consider a way to support this work either by getting a support contract, find someone to submit a pull request. 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | 3 | contact_links: 4 | 5 | - name: Question 6 | url: https://gis.stackexchange.com/ 7 | about: > 8 | Questions should go to the geoserver-user mailing list at https://sourceforge.net/projects/geoserver/lists/geoserver-users 9 | or other support forums such as https://gis.stackexchange.com/. 10 | GitHub issues are for bug reports and suggestions for new features. 11 | 12 | - name: GeoServer extensions issue 13 | # There must be a link to make this option valid for GitHub 14 | url: https://docs.geoserver.org/stable/en/user/extensions/index.html 15 | about: > 16 | If the issue concerns an community extension / stable extension then it can't be fixed 17 | by this docker orchestration. Please raise your issue in the dedicated bug tracker for that specific extension. 18 | Issues related to how the extensions are packaged will not be resolved here. 19 | 20 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | resources/* 2 | !resources/plugins/ 3 | resources/plugins/* 4 | !resources/plugins/README.txt 5 | !resources/overlays/ 6 | resources/overlays/* 7 | !resources/overlays/README.txt 8 | .idea 9 | btsync-media.env 10 | btsync-db.env 11 | geoserver-data 12 | scenario_tests/clustering/tests/__pycache__* 13 | scenario_tests/context/tests/__pycache__* 14 | scenario_tests/disk-quota/tests/__pycache__* 15 | scenario_tests/gwc/tests/__pycache__* 16 | scenario_tests/login/tests/__pycache__* 17 | scenario_tests/stores/tests/__pycache__* 18 | scenario_tests/libjpeg/tests/__pycache__* 19 | .DS_Store 20 | -------------------------------------------------------------------------------- /build_data/broker.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 14 | 15 | 16 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /build_data/cluster.properties: -------------------------------------------------------------------------------- 1 | CLUSTER_CONFIG_DIR=${CLUSTER_CONFIG_DIR} 2 | instanceName=${INSTANCE_STRING} 3 | readOnly=${READONLY} 4 | durable=${CLUSTER_DURABILITY} 5 | brokerURL=failover:(${BROKER_URL}) 6 | embeddedBroker=${EMBEDDED_BROKER} 7 | connection.retry=${CLUSTER_CONNECTION_RETRY_COUNT} 8 | toggleMaster=${TOGGLE_MASTER} 9 | xbeanURL=./broker.xml 10 | embeddedBrokerProperties=embedded-broker.properties 11 | topicName=VirtualTopic.geoserver 12 | connection=enabled 13 | toggleSlave=${TOGGLE_SLAVE} 14 | connection.maxwait=${CLUSTER_CONNECTION_MAX_WAIT} 15 | group=geoserver-cluster 16 | -------------------------------------------------------------------------------- /build_data/community_plugins.py: -------------------------------------------------------------------------------- 1 | # Usage python3 community_plugins.py 2.23.x 2 | import requests 3 | from bs4 import BeautifulSoup 4 | import argparse 5 | 6 | parser = argparse.ArgumentParser() 7 | parser.add_argument("version", help="GeoServer version number, e.g. 2.23.x") 8 | args = parser.parse_args() 9 | 10 | url = "https://build.geoserver.org/geoserver/%s/community-latest/" % args.version 11 | 12 | 13 | response = requests.get(url) 14 | soup = BeautifulSoup(response.content, "html.parser") 15 | 16 | plugin_list = [] 17 | for link in soup.find_all("a"): 18 | href = link.get("href") 19 | if href and href.endswith(".zip"): 20 | plugin_list.append(href.split("/")[-1]) 21 | 22 | with open('community_plugins.txt', 'w') as f: 23 | for plugin in plugin_list: 24 | _version = args.version.replace(".x", "") 25 | sub_string = "geoserver-%s-SNAPSHOT-" % _version 26 | plugin_file = plugin.replace("%s" % sub_string, "") 27 | plugin_name = plugin_file.replace(".zip", "") 28 | f.write(plugin_name + '\n') 29 | -------------------------------------------------------------------------------- /build_data/community_plugins.txt: -------------------------------------------------------------------------------- 1 | activeMQ-broker-plugin 2 | backup-restore-plugin 3 | cog-azure-plugin 4 | cog-google-plugin 5 | cog-http-plugin 6 | cog-s3-plugin 7 | colormap-plugin 8 | cov-json-plugin 9 | datadir-catalog-loader-plugin 10 | dds-plugin 11 | dyndimension-plugin 12 | elasticsearch-plugin 13 | features-autopopulate-plugin 14 | features-templating-plugin 15 | flatgeobuf-plugin 16 | gdal-wcs-plugin 17 | gdal-wps-plugin 18 | geopkg-plugin 19 | gpx-plugin 20 | graticule-plugin 21 | gsr-plugin 22 | gwc-azure-blobstore-plugin 23 | gwc-distributed-plugin 24 | gwc-mbtiles-plugin 25 | gwc-sqlite-plugin 26 | hz-cluster-plugin 27 | imagemap-plugin 28 | importer-jdbc-plugin 29 | jdbcconfig-plugin 30 | jdbc-metrics-plugin 31 | jdbcstore-plugin 32 | jms-cluster-plugin 33 | jwt-headers-plugin 34 | libdeflate-plugin 35 | mbtiles-plugin 36 | mbtiles-store-plugin 37 | mongodb-schemaless-plugin 38 | monitor-kafka-plugin 39 | ncwms-plugin 40 | netcdf-ghrsst-plugin 41 | notification-plugin 42 | ogcapi-coverages-plugin 43 | ogcapi-dggs-plugin 44 | ogcapi-features-plugin 45 | ogcapi-images-plugin 46 | ogcapi-maps-plugin 47 | ogcapi-styles-plugin 48 | ogcapi-tiled-features-plugin 49 | ogcapi-tiles-plugin 50 | ogr-datastore-plugin 51 | opensearch-eo-plugin 52 | pgraster-plugin 53 | proxy-base-ext-plugin 54 | s3-geotiff-plugin 55 | sec-keycloak-plugin 56 | sec-oauth2-geonode-plugin 57 | sec-oauth2-github-plugin 58 | sec-oauth2-google-plugin 59 | sec-oauth2-openid-connect-plugin 60 | smart-data-loader-plugin 61 | solr-plugin 62 | spatialjson-plugin 63 | stac-datastore-plugin 64 | taskmanager-core-plugin 65 | taskmanager-s3-plugin 66 | vector-mosaic-plugin 67 | vsi-plugin 68 | webp-plugin 69 | wfs-freemarker-plugin 70 | wps-longitudinal-profile-plugin 71 | wps-remote-plugin 72 | xslt-plugin -------------------------------------------------------------------------------- /build_data/context.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 36 | 38 | 39 | -------------------------------------------------------------------------------- /build_data/controlflow.properties: -------------------------------------------------------------------------------- 1 | timeout=${REQUEST_TIMEOUT} 2 | ows.global=${PARALLEL_REQUEST} 3 | ows.wms.getmap=${GETMAP} 4 | ows.wfs.getfeature.application/msexcel=${REQUEST_EXCEL} 5 | user=${SINGLE_USER} 6 | ows.gwc=${GWC_REQUEST} 7 | user.ows.wps.execute=${WPS_REQUEST} 8 | user.ows.wms.getmap=${USER_WMS_REQUEST} 9 | ip=${THROTTLE_REQUEST_PER_IP} 10 | #ip.blacklist=,,... -------------------------------------------------------------------------------- /build_data/embedded-broker.properties: -------------------------------------------------------------------------------- 1 | activemq.jmx.useJmx=false 2 | activemq.jmx.port=1098 3 | activemq.jmx.host=localhost 4 | activemq.jmx.createConnector=false 5 | activemq.transportConnectors.server.uri=${BROKER_URL}?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=true&transport.daemon=true&trace=true 6 | activemq.transportConnectors.server.discoveryURI=multicast://default 7 | activemq.broker.persistent=true 8 | activemq.base=./ 9 | activemq.broker.systemUsage.memoryUsage=128 mb 10 | activemq.broker.systemUsage.storeUsage=1 gb 11 | activemq.broker.systemUsage.tempUsage=128 mb 12 | -------------------------------------------------------------------------------- /build_data/extensions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eux 3 | 4 | 5 | VERSION=$(cat /tmp/pass.txt) 6 | GS_VERSION_LATEST="${VERSION:0:5}"x 7 | 8 | cd /work/ 9 | 10 | python3 stable_plugins.py ${VERSION} https://sourceforge.net/projects/geoserver/files/GeoServer 11 | 12 | python3 community_plugins.py ${GS_VERSION_LATEST} 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /build_data/geowebcache-diskquota-jdbc.xml: -------------------------------------------------------------------------------- 1 | 2 | PostgreSQL 3 | 4 | org.postgresql.Driver 5 | jdbc:postgresql://${HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?${SSL_PARAMETERS}&currentSchema=${POSTGRES_SCHEMA} 6 | ${POSTGRES_USER} 7 | ${POSTGRES_PASS} 8 | 1 9 | 100 10 | 10000 11 | 50 12 | 13 | -------------------------------------------------------------------------------- /build_data/geowebcache-diskquota.xml: -------------------------------------------------------------------------------- 1 | 2 | true 3 | ${DISK_QUOTA_FREQUENCY} 4 | SECONDS 5 | 2 6 | LFU 7 | 8 | ${DISK_QUOTA_SIZE} 9 | GiB 10 | 11 | ${DISK_QUOTA_BACKEND} 12 | -------------------------------------------------------------------------------- /build_data/gwc-gs.xml: -------------------------------------------------------------------------------- 1 | 2 | 1.1.0 3 | ${WMS_DIR_INTEGRATION} 4 | ${REQUIRE_TILED_PARAMETER} 5 | ${WMSC_ENABLED} 6 | ${TMS_ENABLED} 7 | ${SECURITY_ENABLED} 8 | false 9 | true 10 | class org.geowebcache.storage.blobstore.memory.guava.GuavaCacheProvider 11 | 12 | 13 | class org.geowebcache.storage.blobstore.memory.guava.GuavaCacheProvider 14 | 15 | 16 16 | NULL 17 | 4 18 | 120 19 | 20 | 21 | 22 | true 23 | true 24 | 4 25 | 4 26 | 0 27 | 28 | WebMercatorQuad 29 | EPSG:4326 30 | WebMercatorQuadx2 31 | EPSG:900913 32 | 33 | 34 | image/png 35 | image/jpeg 36 | 37 | 38 | application/vnd.mapbox-vector-tile 39 | image/png 40 | image/jpeg 41 | 42 | 43 | application/vnd.mapbox-vector-tile 44 | image/png 45 | image/jpeg 46 | 47 | -------------------------------------------------------------------------------- /build_data/hazelcast_cluster/cluster.properties: -------------------------------------------------------------------------------- 1 | enabled = true 2 | sync_method = event 3 | sync_delay = 5 4 | session_sharing = true 5 | session_sticky = false 6 | acktimeout = 2000 7 | #Disabling the hazelcast shutdown hook 8 | shutdown_hook_enable = false 9 | #Setting the hazelcast logging type to log4j 10 | logging_type = "log4j" 11 | logger.com-hazelcast.name = com.hazelcast 12 | logger.com-hazelcast.level = INFO -------------------------------------------------------------------------------- /build_data/index.jsp: -------------------------------------------------------------------------------- 1 | <% 2 | final String redirectURL = "/geoserver/web/"; 3 | response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 4 | response.setHeader("Location", redirectURL); 5 | %> 6 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/jdbcconfig.properties: -------------------------------------------------------------------------------- 1 | #Default GeoServer JDBC loader driver and connection pool options. Edit as appropriate. 2 | #Mon Feb 05 14:49:17 GMT 2024 3 | initdb=true 4 | pool.timeBetweenEvictionRunsMillis=-1L 5 | import=true 6 | pool.poolPreparedStatements=true 7 | pool.testWhileIdle=false 8 | pool.validationQuery=SELECT now() 9 | pool.minIdle=4 10 | enabled=${JDBC_CONFIG_ENABLED} 11 | pool.maxOpenPreparedStatements=50 12 | password=${POSTGRES_PASS} 13 | jdbcUrl=jdbc:postgresql://${HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?${SSL_PARAMETERS} 14 | driverClassName=org.postgresql.Driver 15 | pool.maxActive=10 16 | initScript=${GEOSERVER_DATA_DIR}/jdbcconfig/scripts/initdb.postgres.sql 17 | debugMode=false 18 | pool.testOnBorrow=true 19 | username=${POSTGRES_USER} 20 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/dropdb.h2.sql: -------------------------------------------------------------------------------- 1 | DROP VIEW IF EXISTS service; 2 | DROP VIEW IF EXISTS settings; 3 | DROP VIEW IF EXISTS global; 4 | DROP VIEW IF EXISTS layergroup_style; 5 | DROP VIEW IF EXISTS layergroup_layer; 6 | DROP VIEW IF EXISTS layergroup; 7 | DROP VIEW IF EXISTS layer_style; 8 | DROP VIEW IF EXISTS layer; 9 | DROP VIEW IF EXISTS style; 10 | DROP VIEW IF EXISTS wmslayer; 11 | DROP VIEW IF EXISTS wmsstore; 12 | DROP VIEW IF EXISTS wmtslayer; 13 | DROP VIEW IF EXISTS wmtsstore; 14 | DROP VIEW IF EXISTS coverage; 15 | DROP VIEW IF EXISTS coveragestore; 16 | DROP VIEW IF EXISTS featuretype; 17 | DROP VIEW IF EXISTS datastore; 18 | DROP VIEW IF EXISTS workspace; 19 | 20 | ? ALTER TABLE object_property DROP CONSTRAINT fk_object_property; 21 | ? ALTER TABLE property_type DROP CONSTRAINT fk_type_property_type; 22 | ? ALTER TABLE object DROP CONSTRAINT fk_object_type; 23 | ? ALTER TABLE property_type DROP CONSTRAINT fk_property_type_target_property; 24 | ? ALTER TABLE object_property DROP CONSTRAINT fk_object_property_property_type; 25 | 26 | DROP TABLE object IF EXISTS; 27 | DROP TABLE object_property IF EXISTS; 28 | DROP TABLE type IF EXISTS; 29 | DROP TABLE property_type IF EXISTS; 30 | DROP TABLE default_object IF EXISTS; 31 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/dropdb.mssql.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE OBJECT_PROPERTY DROP CONSTRAINT FK_OBJECT_PROPERTY; 2 | ALTER TABLE PROPERTY_TYPE DROP CONSTRAINT FK_TYPE_PROPERTY_TYPE; 3 | ALTER TABLE OBJECT DROP CONSTRAINT FK_OBJECT_TYPE; 4 | ALTER TABLE PROPERTY_TYPE DROP CONSTRAINT FK_PROPERTY_TYPE_TARGET_PROPERTY; 5 | ALTER TABLE OBJECT_PROPERTY DROP CONSTRAINT FK_OBJECT_PROPERTY_PROPERTY_TYPE; 6 | DROP TABLE OBJECT; 7 | DROP TABLE OBJECT_PROPERTY; 8 | DROP TABLE TYPE; 9 | DROP TABLE PROPERTY_TYPE; 10 | DROP TABLE DEFAULT_OBJECT; 11 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/dropdb.mysql.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE OBJECT_PROPERTY DROP FOREIGN KEY FK_OBJECT_PROPERTY; 2 | ALTER TABLE PROPERTY_TYPE DROP FOREIGN KEY FK_TYPE_PROPERTY_TYPE; 3 | ALTER TABLE OBJECT DROP FOREIGN KEY FK_OBJECT_TYPE; 4 | ALTER TABLE PROPERTY_TYPE DROP FOREIGN KEY FK_PROPERTY_TYPE_TARGET_PROPERTY; 5 | ALTER TABLE OBJECT_PROPERTY DROP FOREIGN KEY FK_OBJECT_PROPERTY_PROPERTY_TYPE; 6 | DROP TABLE IF EXISTS OBJECT; 7 | DROP TABLE IF EXISTS OBJECT_PROPERTY; 8 | DROP TABLE IF EXISTS TYPE; 9 | DROP TABLE IF EXISTS PROPERTY_TYPE; 10 | DROP TABLE IF EXISTS DEFAULT_OBJECT; 11 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/dropdb.oracle.sql: -------------------------------------------------------------------------------- 1 | DROP VIEW service; 2 | DROP VIEW settings; 3 | DROP VIEW global; 4 | DROP VIEW layergroup_style; 5 | DROP VIEW layergroup_layer; 6 | DROP VIEW layergroup; 7 | DROP VIEW layer_style; 8 | DROP VIEW layer; 9 | DROP VIEW style; 10 | DROP VIEW wmslayer; 11 | DROP VIEW wmsstore; 12 | DROP VIEW coverage; 13 | DROP VIEW coveragestore; 14 | DROP VIEW featuretype; 15 | DROP VIEW datastore; 16 | DROP VIEW workspace; 17 | 18 | DROP TABLE OBJECT CASCADE CONSTRAINTS; 19 | DROP TABLE OBJECT_PROPERTY CASCADE CONSTRAINTS; 20 | DROP TABLE TYPE CASCADE CONSTRAINTS; 21 | DROP TABLE PROPERTY_TYPE CASCADE CONSTRAINTS; 22 | DROP TABLE DEFAULT_OBJECT CASCADE CONSTRAINTS; 23 | DROP SEQUENCE SEQ_OBJECT; 24 | DROP SEQUENCE SEQ_TYPE; 25 | DROP SEQUENCE SEQ_PROPERTY_TYPE; 26 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/dropdb.postgres.sql: -------------------------------------------------------------------------------- 1 | DROP VIEW IF EXISTS service; 2 | DROP VIEW IF EXISTS settings; 3 | DROP VIEW IF EXISTS global; 4 | DROP VIEW IF EXISTS layergroup_style; 5 | DROP VIEW IF EXISTS layergroup_layer; 6 | DROP VIEW IF EXISTS layergroup; 7 | DROP VIEW IF EXISTS layer_style; 8 | DROP VIEW IF EXISTS layer; 9 | DROP VIEW IF EXISTS style; 10 | DROP VIEW IF EXISTS wmslayer; 11 | DROP VIEW IF EXISTS wmsstore; 12 | DROP VIEW IF EXISTS wmtslayer; 13 | DROP VIEW IF EXISTS wmtsstore; 14 | DROP VIEW IF EXISTS coverage; 15 | DROP VIEW IF EXISTS coveragestore; 16 | DROP VIEW IF EXISTS featuretype; 17 | DROP VIEW IF EXISTS datastore; 18 | DROP VIEW IF EXISTS workspace; 19 | 20 | ? ALTER TABLE object_property DROP CONSTRAINT fk_object_property; 21 | ? ALTER TABLE property_type DROP CONSTRAINT fk_type_property_type; 22 | ? ALTER TABLE object DROP CONSTRAINT fk_object_type; 23 | ? ALTER TABLE property_type DROP CONSTRAINT fk_property_type_target_property; 24 | ? ALTER TABLE object_property DROP CONSTRAINT fk_object_property_property_type; 25 | 26 | DROP TABLE IF EXISTS object CASCADE; 27 | DROP TABLE IF EXISTS object_property CASCADE; 28 | DROP TABLE IF EXISTS type CASCADE; 29 | DROP TABLE IF EXISTS property_type CASCADE; 30 | DROP TABLE IF EXISTS default_object CASCADE; 31 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/initdb.mssql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE OBJECT (OID int IDENTITY NOT NULL, TYPE_ID int NOT NULL, ID varchar(255) NOT NULL, BLOB text NOT NULL, PRIMARY KEY (OID)); 2 | CREATE TABLE OBJECT_PROPERTY (OID int NOT NULL, PROPERTY_TYPE int NOT NULL, ID varchar(255) NOT NULL, RELATED_OID int NULL, RELATED_PROPERTY_TYPE int NULL, COLINDEX int NOT NULL, VALUE varchar(max) NULL, PRIMARY KEY (OID, PROPERTY_TYPE, COLINDEX)); 3 | CREATE TABLE TYPE (OID int IDENTITY NOT NULL, TYPENAME varchar(255) NOT NULL, PRIMARY KEY (OID)); 4 | CREATE TABLE PROPERTY_TYPE (OID int IDENTITY NOT NULL, TARGET_PROPERTY int NULL, TYPE_ID int NOT NULL, NAME varchar(255) NOT NULL, COLLECTION bit NOT NULL, TEXT bit NOT NULL, PRIMARY KEY (OID)); 5 | CREATE TABLE DEFAULT_OBJECT (DEF_KEY varchar(255) NOT NULL, ID varchar(255) NOT NULL); 6 | ALTER TABLE OBJECT_PROPERTY ADD CONSTRAINT FK_OBJECT_PROPERTY FOREIGN KEY (OID) REFERENCES OBJECT (OID) ON DELETE Cascade; 7 | ALTER TABLE PROPERTY_TYPE ADD CONSTRAINT FK_TYPE_PROPERTY_TYPE FOREIGN KEY (TYPE_ID) REFERENCES TYPE (OID); 8 | ALTER TABLE OBJECT ADD CONSTRAINT FK_OBJECT_TYPE FOREIGN KEY (TYPE_ID) REFERENCES TYPE (OID); 9 | ALTER TABLE PROPERTY_TYPE ADD CONSTRAINT FK_PROPERTY_TYPE_TARGET_PROPERTY FOREIGN KEY (TARGET_PROPERTY) REFERENCES PROPERTY_TYPE (OID); 10 | ALTER TABLE OBJECT_PROPERTY ADD CONSTRAINT FK_OBJECT_PROPERTY_PROPERTY_TYPE FOREIGN KEY (PROPERTY_TYPE) REFERENCES PROPERTY_TYPE (OID); 11 | CREATE UNIQUE INDEX OBJECT_OID ON OBJECT (OID); 12 | CREATE INDEX OBJECT_TYPE_ID ON OBJECT (TYPE_ID); 13 | CREATE UNIQUE INDEX OBJECT_ID ON OBJECT (ID); 14 | CREATE INDEX OBJECT_PROPERTY_OID ON OBJECT_PROPERTY (OID); 15 | CREATE INDEX OBJECT_PROPERTY_PROPERTY_TYPE ON OBJECT_PROPERTY (PROPERTY_TYPE); 16 | CREATE INDEX OBJECT_PROPERTY_ID ON OBJECT_PROPERTY (ID); 17 | CREATE INDEX OBJECT_PROPERTY_RELATED_OID ON OBJECT_PROPERTY (RELATED_OID); 18 | CREATE INDEX OBJECT_PROPERTY_RELATED_PROPERTY_TYPE ON OBJECT_PROPERTY (RELATED_PROPERTY_TYPE); 19 | CREATE INDEX OBJECT_PROPERTY_COLINDEX ON OBJECT_PROPERTY (COLINDEX); 20 | CREATE INDEX OBJECT_PROPERTY_VALUE ON OBJECT_PROPERTY (VALUE); 21 | CREATE UNIQUE INDEX TYPE_OID ON TYPE (OID); 22 | CREATE UNIQUE INDEX TYPE_TYPENAME ON TYPE (TYPENAME); 23 | CREATE UNIQUE INDEX PROPERTY_TYPE_OID ON PROPERTY_TYPE (OID); 24 | CREATE INDEX PROPERTY_TYPE_TARGET_PROPERTY ON PROPERTY_TYPE (TARGET_PROPERTY); 25 | CREATE INDEX PROPERTY_TYPE_TYPE_ID ON PROPERTY_TYPE (TYPE_ID); 26 | CREATE INDEX PROPERTY_TYPE_NAME ON PROPERTY_TYPE (NAME); 27 | CREATE INDEX PROPERTY_TYPE_COLLECTION ON PROPERTY_TYPE (COLLECTION); 28 | CREATE UNIQUE INDEX DEFAULT_OBJECT_DEF_KEY ON DEFAULT_OBJECT (DEF_KEY); 29 | CREATE INDEX DEFAULT_OBJECT_ID ON DEFAULT_OBJECT (ID); 30 | -------------------------------------------------------------------------------- /build_data/jdbcconfig/scripts/initdb.mysql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE OBJECT (OID int(11) NOT NULL AUTO_INCREMENT, TYPE_ID int(11) NOT NULL, ID varchar(255) NOT NULL, BLOB text NOT NULL, PRIMARY KEY (OID), UNIQUE INDEX (OID), INDEX (TYPE_ID), UNIQUE INDEX (ID)); 2 | CREATE TABLE OBJECT_PROPERTY (OID int(11) NOT NULL, PROPERTY_TYPE int(11) NOT NULL, ID varchar(255) NOT NULL, RELATED_OID int(11), RELATED_PROPERTY_TYPE int(11), COLINDEX int(11) NOT NULL, VALUE varchar(1023), PRIMARY KEY (OID, PROPERTY_TYPE, COLINDEX), INDEX (OID), INDEX (PROPERTY_TYPE), INDEX (ID), INDEX (RELATED_OID), INDEX (RELATED_PROPERTY_TYPE), INDEX (COLINDEX), INDEX (VALUE)); 3 | CREATE TABLE TYPE (OID int(11) NOT NULL AUTO_INCREMENT, TYPENAME varchar(255) NOT NULL, PRIMARY KEY (OID), UNIQUE INDEX (OID), UNIQUE INDEX (TYPENAME)); 4 | CREATE TABLE PROPERTY_TYPE (OID int(11) NOT NULL AUTO_INCREMENT, TARGET_PROPERTY int(11), TYPE_ID int(11) NOT NULL, NAME varchar(255) NOT NULL, COLLECTION tinyint(1) NOT NULL, TEXT tinyint(1) NOT NULL, PRIMARY KEY (OID), UNIQUE INDEX (OID), INDEX (TARGET_PROPERTY), INDEX (TYPE_ID), INDEX (NAME), INDEX (COLLECTION)); 5 | CREATE TABLE DEFAULT_OBJECT (DEF_KEY varchar(255) NOT NULL, ID varchar(255) NOT NULL, UNIQUE INDEX (DEF_KEY), INDEX (ID)); 6 | ALTER TABLE OBJECT_PROPERTY ADD INDEX FK_OBJECT_PROPERTY (OID), ADD CONSTRAINT FK_OBJECT_PROPERTY FOREIGN KEY (OID) REFERENCES OBJECT (OID) ON DELETE Cascade; 7 | ALTER TABLE PROPERTY_TYPE ADD INDEX FK_TYPE_PROPERTY_TYPE (TYPE_ID), ADD CONSTRAINT FK_TYPE_PROPERTY_TYPE FOREIGN KEY (TYPE_ID) REFERENCES TYPE (OID); 8 | ALTER TABLE OBJECT ADD INDEX FK_OBJECT_TYPE (TYPE_ID), ADD CONSTRAINT FK_OBJECT_TYPE FOREIGN KEY (TYPE_ID) REFERENCES TYPE (OID); 9 | ALTER TABLE PROPERTY_TYPE ADD INDEX FK_PROPERTY_TYPE_TARGET_PROPERTY (TARGET_PROPERTY), ADD CONSTRAINT FK_PROPERTY_TYPE_TARGET_PROPERTY FOREIGN KEY (TARGET_PROPERTY) REFERENCES PROPERTY_TYPE (OID); 10 | ALTER TABLE OBJECT_PROPERTY ADD INDEX FK_OBJECT_PROPERTY_PROPERTY_TYPE (PROPERTY_TYPE), ADD CONSTRAINT FK_OBJECT_PROPERTY_PROPERTY_TYPE FOREIGN KEY (PROPERTY_TYPE) REFERENCES PROPERTY_TYPE (OID); 11 | -------------------------------------------------------------------------------- /build_data/jdbcstore/jdbcstore.properties: -------------------------------------------------------------------------------- 1 | #Default GeoServer JDBC loader driver and connection pool options. Edit as appropriate. 2 | #Fri Feb 09 07:18:57 GMT 2024 3 | initdb=true 4 | pool.timeBetweenEvictionRunsMillis=-1L 5 | deleteDestinationOnRename=true 6 | import=true 7 | pool.poolPreparedStatements=true 8 | pool.testWhileIdle=false 9 | pool.validationQuery=SELECT now() 10 | pool.minIdle=4 11 | ignoreDirs=${JDBC_IGNORE_PATHS} 12 | enabled=${JDBC_STORE_ENABLED} 13 | pool.maxOpenPreparedStatements=50 14 | password=${POSTGRES_PASS} 15 | jdbcUrl=jdbc:postgresql://${HOST}:${POSTGRES_PORT}/${POSTGRES_DB}?${SSL_PARAMETERS} 16 | driverClassName=org.postgresql.Driver 17 | pool.maxActive=10 18 | initScript=${GEOSERVER_DATA_DIR}/jdbcstore/scripts/init.postgres.sql 19 | pool.testOnBorrow=true 20 | username=${POSTGRES_USER} 21 | -------------------------------------------------------------------------------- /build_data/jdbcstore/scripts/drop.h2.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE resources CASCADE; 2 | -------------------------------------------------------------------------------- /build_data/jdbcstore/scripts/drop.postgres.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE resources CASCADE; 2 | -------------------------------------------------------------------------------- /build_data/jdbcstore/scripts/init.h2.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE resources 2 | ( 3 | oid integer AUTO_INCREMENT NOT NULL, 4 | name character varying NOT NULL, 5 | parent integer, 6 | last_modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 7 | content binary, 8 | CONSTRAINT resources_pkey PRIMARY KEY (oid), 9 | CONSTRAINT resources_parent_fkey FOREIGN KEY (parent) 10 | REFERENCES resources (oid) 11 | ON UPDATE RESTRICT ON DELETE CASCADE, 12 | CONSTRAINT resources_parent_name_key UNIQUE (parent, name), 13 | CONSTRAINT resources_only_one_root_check CHECK (parent IS NOT NULL OR oid = 0) 14 | ); 15 | 16 | CREATE INDEX resources_parent_name_idx 17 | ON resources (parent NULLS FIRST, name NULLS FIRST); 18 | 19 | INSERT INTO resources (oid, name, parent, content) VALUES (0, '', NULL, NULL); 20 | 21 | ALTER TABLE resources ALTER COLUMN oid RESTART WITH 1; 22 | 23 | -------------------------------------------------------------------------------- /build_data/jdbcstore/scripts/init.postgres.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE resources 2 | ( 3 | oid serial NOT NULL, 4 | name character varying NOT NULL, 5 | parent integer, 6 | last_modified timestamp without time zone NOT NULL DEFAULT timezone('UTC'::text, now()), 7 | content bytea, 8 | CONSTRAINT resources_pkey PRIMARY KEY (oid), 9 | CONSTRAINT resources_parent_fkey FOREIGN KEY (parent) 10 | REFERENCES resources (oid) 11 | ON UPDATE RESTRICT ON DELETE CASCADE, 12 | CONSTRAINT resources_parent_name_key UNIQUE (parent, name), 13 | CONSTRAINT resources_only_one_root_check CHECK (parent IS NOT NULL OR oid = 0) 14 | ); 15 | 16 | CREATE INDEX resources_parent_name_idx 17 | ON resources (parent NULLS FIRST, name NULLS FIRST); 18 | 19 | INSERT INTO resources (oid, name, parent, content) VALUES (0, '', NULL, NULL); 20 | 21 | -------------------------------------------------------------------------------- /build_data/jdom2-2.0.6.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/build_data/jdom2-2.0.6.1.jar -------------------------------------------------------------------------------- /build_data/letsencrypt-tomcat.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /build_data/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.appender.logfile = org.apache.log4j.RollingFileAppender 2 | log4j.appender.logfile.File = ${LOG_PATH} 3 | log4j.appender.logfile.Append = true 4 | log4j.appender.logfile.layout = org.apache.log4j.PatternLayout 5 | log4j.appender.logfile.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n 6 | 7 | #configure stdout 8 | log4j.appender.stdout = org.apache.log4j.ConsoleAppender 9 | log4j.appender.stdout.Target = System.out 10 | log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 11 | log4j.appender.stdout.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n 12 | 13 | log4j.rootLogger = debug, logfile, stdout 14 | 15 | -------------------------------------------------------------------------------- /build_data/logging.properties: -------------------------------------------------------------------------------- 1 | # Source: https://github.com/GoogleCloudPlatform/tomcat-runtime/pull/28/ 2 | # Copyright 2017 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed to the Apache Software Foundation (ASF) under one or more 5 | # contributor license agreements. See the NOTICE file distributed with 6 | # this work for additional information regarding copyright ownership. 7 | # The ASF licenses this file to You under the Apache License, Version 2.0 8 | # (the "License"); you may not use this file except in compliance with 9 | # the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | 19 | # Configure Tomcat to only log to stdout, rather than files. This ensures all 20 | # logs can be collected by the container runtime. 21 | 22 | handlers = java.util.logging.ConsoleHandler 23 | .handlers = java.util.logging.ConsoleHandler 24 | 25 | java.util.logging.ConsoleHandler.level = ${CONSOLE_HANDLER_LEVEL} 26 | java.util.logging.ConsoleHandler.formatter = java.util.logging.OneLineFormatter 27 | 28 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO 29 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = java.util.logging.ConsoleHandler 30 | 31 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].level = INFO 32 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/manager].handlers = java.util.logging.ConsoleHandler 33 | 34 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].level = INFO 35 | org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/host-manager].handlers = java.util.logging.ConsoleHandler 36 | -------------------------------------------------------------------------------- /build_data/plugin_download.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eux 3 | 4 | mkdir -p /work/required_plugins 5 | mkdir -p /work/stable_plugins 6 | mkdir -p /work/community_plugins 7 | mkdir -p /work/geoserver_war/ 8 | 9 | # Build a curl config to download all required plugins 10 | awk '{print "url = \"'"${STABLE_PLUGIN_BASE_URL}/${GS_VERSION}"'/extensions/geoserver-'"${GS_VERSION}"'-"$0".zip\"\noutput = \"/work/required_plugins/"$0".zip\"\n--fail\n--location\n"}' < /work/required_plugins.txt > /work/curl.cfg 11 | 12 | 13 | # Add in all stable plugins 14 | awk '{print "url = \"'"${STABLE_PLUGIN_BASE_URL}/${GS_VERSION}"'/extensions/geoserver-'"${GS_VERSION}"'-"$0".zip\"\noutput = \"/work/stable_plugins/"$0".zip\"\n--fail\n--location\n"}' < /work/stable_plugins.txt >> /work/curl.cfg 15 | 16 | 17 | 18 | # Add in all community plugins 19 | awk '{print "url = \"https://build.geoserver.org/geoserver/'"${GS_VERSION:0:5}"'x/community-latest/geoserver-'"${GS_VERSION:0:4}"'-SNAPSHOT-"$0".zip\"\noutput = \"/work/community_plugins/"$0".zip\"\n--fail\n--location\n"}' < /work/community_plugins.txt >> /work/curl.cfg 20 | 21 | 22 | if [[ "${WAR_URL}" == *\.zip ]]; then 23 | destination="/work/geoserver_war/geoserver.zip" 24 | curl --progress-bar -fLvo "${destination}" "${WAR_URL}" || exit 1 25 | else 26 | destination=/work/geoserver_war/geoserver.war 27 | curl --progress-bar -fLvo "${destination}" "${WAR_URL}" || exit 1 28 | fi 29 | 30 | # Download Jetty Services 31 | curl --progress-bar -fLvo /work/required_plugins/jetty-servlets.jar https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-servlets/11.0.9/jetty-servlets-11.0.9.jar 32 | 33 | # Download jetty-util 34 | curl --progress-bar -fLvo /work/required_plugins/jetty-util.jar https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-util/11.0.9/jetty-util-11.0.9.jar 35 | 36 | curl --progress-bar -fLvo /work/required_plugins/marlin.jar https://github.com/bourgesl/marlin-renderer/releases/download/v0_9_4_8/marlin-0.9.4.8-Unsafe-OpenJDK11.jar 37 | 38 | # Download everything! 39 | for attempt in {1..5}; do 40 | echo "Attempt $attempt of downloading plugins" 41 | if curl --progress-bar -vK /work/curl.cfg; then 42 | echo "Download successful" 43 | break 44 | else 45 | echo "Download failed, retrying in 10 seconds..." 46 | sleep 10 47 | fi 48 | done 49 | -------------------------------------------------------------------------------- /build_data/required_plugins.txt: -------------------------------------------------------------------------------- 1 | control-flow-plugin 2 | csw-iso-plugin 3 | csw-plugin 4 | gdal-plugin 5 | inspire-plugin 6 | libjpeg-turbo-plugin 7 | monitor-plugin 8 | pyramid-plugin 9 | vectortiles-plugin 10 | wps-plugin 11 | -------------------------------------------------------------------------------- /build_data/stable_plugins.py: -------------------------------------------------------------------------------- 1 | # Usage: python3 stable_plugins.py 2.23.0 https://sourceforge.net/projects/geoserver/files/GeoServer 2 | # python3 stable_plugins.py version GeoServer_Base_URL 3 | import requests 4 | from bs4 import BeautifulSoup 5 | 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser() 9 | parser.add_argument("version", help="GeoServer version number, e.g. 2.23.0") 10 | parser.add_argument("base_url", 11 | help="Base URL to download GeoServer extensions i.e, e.g." 12 | " https://sourceforge.net/projects/geoserver/files/GeoServer") 13 | args = parser.parse_args() 14 | 15 | url = '%s/%s/extensions' % (args.base_url, args.version) 16 | print(url) 17 | response = requests.get(url) 18 | soup = BeautifulSoup(response.content, 'html.parser') 19 | 20 | plugin_list = [] 21 | for link in soup.find_all('a'): 22 | href = link.get('href') 23 | 24 | if href is not None: 25 | if href.endswith('/download') and href.startswith('https'): 26 | plugin_base = href.replace("%s/" % url, "") 27 | plugin_name = plugin_base.replace('.zip/download', '') 28 | plugin_base_name = plugin_name.replace("geoserver-%s-" % args.version, "") 29 | plugin_list.append(plugin_base_name) 30 | 31 | required_plugins = set() 32 | with open('required_plugins.txt', 'r') as f: 33 | for plugin in f: 34 | plugin = plugin.strip() 35 | if plugin: 36 | required_plugins.add(plugin) 37 | 38 | with open('stable_plugins.txt', 'w') as f: 39 | for plugin in plugin_list: 40 | if plugin not in required_plugins: 41 | f.write(plugin + '\n') 42 | -------------------------------------------------------------------------------- /build_data/stable_plugins.txt: -------------------------------------------------------------------------------- 1 | app-schema-plugin 2 | authkey-plugin 3 | cas-plugin 4 | charts-plugin 5 | css-plugin 6 | db2-plugin 7 | dxf-plugin 8 | excel-plugin 9 | feature-pregeneralized-plugin 10 | geofence-plugin 11 | geofence-server-plugin 12 | geofence-wps-plugin 13 | geopkg-output-plugin 14 | grib-plugin 15 | gwc-s3-plugin 16 | h2-plugin 17 | iau-plugin 18 | importer-plugin 19 | jp2k-plugin 20 | mapml-plugin 21 | mbstyle-plugin 22 | metadata-plugin 23 | mongodb-plugin 24 | mysql-plugin 25 | netcdf-out-plugin 26 | netcdf-plugin 27 | ogr-wfs-plugin 28 | ogr-wps-plugin 29 | oracle-plugin 30 | params-extractor-plugin 31 | printing-plugin 32 | querylayer-plugin 33 | rat-plugin 34 | sldservice-plugin 35 | sqlserver-plugin 36 | wcs2_0-eo-plugin 37 | web-resource-plugin 38 | wmts-multi-dimensional-plugin 39 | wps-cluster-hazelcast-plugin 40 | wps-download-plugin 41 | wps-jdbc-plugin 42 | ysld-plugin -------------------------------------------------------------------------------- /build_data/tomcat-users.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 22 | 30 | 37 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /clustering/README.md: -------------------------------------------------------------------------------- 1 | # Clustering using JMS Plugin 2 | GeoServer supports clustering using JMS cluster plugin or using the ActiveMQ-broker. 3 | 4 | ## JMS cluster plugin 5 | This setup uses the JMS cluster plugin which uses an embedded broker. A docker-compose.yml 6 | is provided in the clustering folder which simulates the replication using 7 | a shared data directory. 8 | 9 | The environment variables associated with replication are listed below 10 | * `CLUSTERING=True` - Specified whether clustering should be activated. 11 | * `BROKER_URL=tcp://0.0.0.0:61661` - This links to the internal broker provided by the JMS cluster plugin. 12 | This value will be different for (Master-Node) 13 | * `READONLY=disabled` - Determines if the GeoServer instance is Read only 14 | * `RANDOMSTRING=87ee2a9b6802b6da_master` - Used to create a unique CLUSTER_CONFIG_DIR for each instance. Not mandatory as the container can self generate this. 15 | * `INSTANCE_STRING=d8a167a4e61b5415ec263` - Used to differentiate cluster instance names. Not mandatory as the container can self generate this. 16 | * `CLUSTER_DURABILITY=false` 17 | * `TOGGLE_MASTER=true` - Differentiates if the instance will be a Master 18 | * `TOGGLE_SLAVE=true` - Differentiates if the instance will be a Node 19 | * `EMBEDDED_BROKER=disabled` - Should be disabled for the Node 20 | * `CLUSTER_CONNECTION_RETRY_COUNT=10` - How many times try to connect to broker 21 | * `CLUSTER_CONNECTION_MAX_WAIT=500` - Wait time between connection to broker retry (in milliseconds) 22 | * `EXISTING_DATA_DIR` - If you are using an existing data directory, you need to set `CLUSTER_CONFIG_DIR` 23 | otherwise the container is will hang and not start. Additionally, it will check if all the files 24 | needed for clustering exists, otherwise it will fail. 25 | 26 | ## ActiveMQ-broker 27 | 28 | You can additionally run the clustering using an external broker. To run this 29 | you will need to build the image locally and run the stack: 30 | 31 | ```bash 32 | docker compose -f docker-compose-external.yml up -d --build 33 | ``` 34 | 35 | or run in a single step 36 | 37 | ```bash 38 | docker compose -f docker-compose-external.yml up -d 39 | ``` -------------------------------------------------------------------------------- /clustering/activemq-docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bellsoft/liberica-openjdk-alpine:13 AS activemq-prod 2 | 3 | LABEL maintainer="Alessio Fabiani " 4 | 5 | ENV ACTIVEMQ_VERSION=5.17.1 6 | ENV ACTIVEMQ=apache-activemq-$ACTIVEMQ_VERSION 7 | ENV ACTIVEMQ_HOME=/opt/activemq/ 8 | ENV ACTIVEMQ_CONF=$ACTIVEMQ_HOME/conf/ 9 | ENV ACTIVEMQ_LIB=$ACTIVEMQ_HOME/lib/optional/ 10 | 11 | 12 | RUN apk add --update curl && \ 13 | rm -rf /var/cache/apk/* && \ 14 | mkdir -p /opt && \ 15 | curl -s -S https://archive.apache.org/dist/activemq/$ACTIVEMQ_VERSION/$ACTIVEMQ-bin.tar.gz | tar -xvz -C /opt && \ 16 | mv /opt/$ACTIVEMQ $ACTIVEMQ_HOME && \ 17 | addgroup -S activemq && \ 18 | adduser -S -H -G activemq -h $ACTIVEMQ_HOME activemq && \ 19 | chown -R activemq:activemq $ACTIVEMQ_HOME && \ 20 | chown -h activemq:activemq $ACTIVEMQ_HOME 21 | 22 | ADD setup-jars.sh /setup-jars.sh 23 | RUN chmod +x /*.sh;/setup-jars.sh 24 | 25 | COPY activemq.xml $ACTIVEMQ_CONF/activemq.xml 26 | 27 | # EXPOSE 1883 5672 8161 61613 61614 61616 28 | 29 | USER activemq 30 | WORKDIR $ACTIVEMQ_HOME 31 | 32 | CMD ["/bin/sh", "-c", "bin/activemq console"] 33 | -------------------------------------------------------------------------------- /clustering/activemq-docker/setup-jars.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | wget -c --tries=2 https://repo1.maven.org/maven2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar \ 4 | -O "${ACTIVEMQ_LIB}"/slf4j-api-1.7.21.jar 5 | wget -c --tries=2 https://repo1.maven.org/maven2/org/postgresql/postgresql/42.4.0/postgresql-42.4.0.jar \ 6 | -O "${ACTIVEMQ_LIB}"/postgresql-42.4.0.jar 7 | wget -c --tries=2 https://repo1.maven.org/maven2/org/osgi/org.osgi.compendium/4.3.1/org.osgi.compendium-4.3.1.jar \ 8 | -O "${ACTIVEMQ_LIB}"/org.osgi.compendium-4.3.1.jar 9 | wget -c --tries=2 https://repo1.maven.org/maven2/org/apache/servicemix/bundles/org.apache.servicemix.bundles.commons-dbcp/1.4_3/org.apache.servicemix.bundles.commons-dbcp-1.4_3-sources.jar \ 10 | -O "${ACTIVEMQ_LIB}"/org.apache.servicemix.bundles.commons-dbcp-1.4_3-sources.jar 11 | wget -c --tries=2 https://repo1.maven.org/maven2/com/zaxxer/HikariCP/2.7.2/HikariCP-2.7.2.jar \ 12 | -O "${ACTIVEMQ_LIB}"/HikariCP-2.7.2.jar -------------------------------------------------------------------------------- /clustering/docker-compose-external.yml: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Common template for ActiveMQ services below 4 | x-common-activemq: 5 | &default-common-activemq 6 | image: kartoza/activemq-docker:manual-build 7 | build: activemq-docker 8 | restart: on-failure 9 | 10 | services: 11 | 12 | db: 13 | image: kartoza/postgis:16-3.4 14 | volumes: 15 | - geo-db-data:/var/lib/postgresql 16 | ports: 17 | - "5432" 18 | environment: 19 | - POSTGRES_DB=gis,data,sample 20 | - POSTGRES_USER=docker 21 | - POSTGRES_PASS=docker 22 | - ALLOW_IP_RANGE=0.0.0.0/0 23 | - FORCE_SSL=TRUE 24 | restart: on-failure 25 | healthcheck: 26 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker -d gis" 27 | 28 | broker1: 29 | << : *default-common-activemq 30 | environment: 31 | - JAVA_HOME=/opt/java/openjdk 32 | - HOST=db 33 | - POSTGRES_PORT=5432 34 | - POSTGRES_DB=gis 35 | - POSTGRES_USER=docker 36 | - POSTGRES_PASS=docker 37 | - ACTIVEMQ_SERVER_URI=tcp://broker1:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=false&transport.daemon=true 38 | - ACTIVEMQ_SERVER_DISCOVERYURI=multicast://default 39 | - SSL_MODE=ALLOW 40 | depends_on: 41 | db: 42 | condition: service_healthy 43 | healthcheck: 44 | test: netstat -ltn | grep -c ":61616" 45 | interval: 30s 46 | timeout: 10s 47 | retries: 10 48 | 49 | broker2: 50 | << : *default-common-activemq 51 | environment: 52 | - JAVA_HOME=/opt/java/openjdk 53 | - HOST=db 54 | - POSTGRES_PORT=5432 55 | - POSTGRES_DB=data 56 | - POSTGRES_USER=docker 57 | - POSTGRES_PASS=docker 58 | - ACTIVEMQ_SERVER_URI=tcp://broker2:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=false&transport.daemon=true 59 | - ACTIVEMQ_SERVER_DISCOVERYURI=multicast://default 60 | - SSL_MODE=ALLOW 61 | depends_on: 62 | db: 63 | condition: service_healthy 64 | broker1: 65 | condition: service_healthy 66 | healthcheck: 67 | test: netstat -ltn | grep -c ":61616" 68 | interval: 30s 69 | timeout: 10s 70 | retries: 10 71 | 72 | broker3: 73 | << : *default-common-activemq 74 | environment: 75 | - JAVA_HOME=/opt/java/openjdk 76 | - HOST=db 77 | - POSTGRES_PORT=5432 78 | - POSTGRES_DB=sample 79 | - POSTGRES_USER=docker 80 | - POSTGRES_PASS=docker 81 | - ACTIVEMQ_SERVER_URI=tcp://broker3:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=false&transport.daemon=true 82 | - ACTIVEMQ_SERVER_DISCOVERYURI=multicast://default 83 | - SSL_MODE=ALLOW 84 | depends_on: 85 | db: 86 | condition: service_healthy 87 | broker1: 88 | condition: service_healthy 89 | healthcheck: 90 | test: netstat -ltn | grep -c ":61616" 91 | interval: 30s 92 | timeout: 10s 93 | retries: 10 94 | 95 | master: 96 | image: kartoza/geoserver:2.24.0 97 | ports: 98 | - "8081:8080" 99 | environment: 100 | - CLUSTERING=true 101 | - CLUSTER_DURABILITY=false 102 | - DB_BACKEND=POSTGRES 103 | - HOST=db 104 | - POSTGRES_PORT=5432 105 | - POSTGRES_DB=gis 106 | - POSTGRES_USER=docker 107 | - POSTGRES_PASS=docker 108 | - SSL_MODE=ALLOW 109 | - BROKER_URL=failover:(tcp://broker1:61616,tcp://broker2:61616,tcp://broker3:61616) 110 | - READONLY=disabled 111 | - TOGGLE_MASTER=true 112 | - TOGGLE_SLAVE=false 113 | - EMBEDDED_BROKER=disabled 114 | - RUN_AS_ROOT=TRUE 115 | - GEOSERVER_ADMIN_USER=admin 116 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 117 | - STABLE_EXTENSIONS= 118 | - COMMUNITY_EXTENSIONS=jms-cluster-plugin 119 | volumes: 120 | - geoserver-cluster-data:/opt/geoserver/data_dir 121 | 122 | 123 | node: 124 | image: kartoza/geoserver:2.24.0 125 | ports: 126 | - "8082:8080" 127 | environment: 128 | - CLUSTERING=true 129 | - CLUSTER_DURABILITY=false 130 | - DB_BACKEND=POSTGRES 131 | - HOST=db 132 | - POSTGRES_PORT=5432 133 | - POSTGRES_DB=gis 134 | - POSTGRES_USER=docker 135 | - POSTGRES_PASS=docker 136 | - SSL_MODE=ALLOW 137 | - BROKER_URL=failover:(tcp://broker1:61616,tcp://broker2:61616,tcp://broker3:61616) 138 | - READONLY=enabled 139 | - TOGGLE_MASTER=false 140 | - TOGGLE_SLAVE=true 141 | - EMBEDDED_BROKER=disabled 142 | - RUN_AS_ROOT=TRUE 143 | - GEOSERVER_ADMIN_USER=admin 144 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 145 | - STABLE_EXTENSIONS= 146 | - COMMUNITY_EXTENSIONS=jms-cluster-plugin 147 | volumes: 148 | - geoserver-cluster-data:/opt/geoserver/data_dir 149 | 150 | volumes: 151 | geoserver-cluster-data: 152 | geo-db-data: 153 | -------------------------------------------------------------------------------- /clustering/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-cluster-data: 4 | geoserver-cluster-gwc-data: 5 | geo-db-data: 6 | 7 | services: 8 | db: 9 | image: kartoza/postgis:17-3.5 10 | volumes: 11 | - geo-db-data:/var/lib/postgresql 12 | environment: 13 | - POSTGRES_DB=gis 14 | - POSTGRES_USER=docker 15 | - POSTGRES_PASS=docker 16 | - ALLOW_IP_RANGE=0.0.0.0/0 17 | - FORCE_SSL=TRUE 18 | restart: on-failure 19 | healthcheck: 20 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker -d gis" 21 | master: 22 | image: kartoza/geoserver:2.27.1 23 | volumes: 24 | - geoserver-cluster-data:/opt/geoserver/data_dir 25 | - geoserver-cluster-gwc-data:/opt/geoserver/gwc 26 | ports: 27 | - "8081:8080" 28 | environment: 29 | - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/gwc 30 | - BROKER_URL=tcp://0.0.0.0:61661 31 | - READONLY=disabled 32 | - CLUSTER_DURABILITY=false 33 | - CLUSTERING=True 34 | - TOGGLE_MASTER=true 35 | - TOGGLE_SLAVE=true 36 | - DB_BACKEND=POSTGRES 37 | - HOST=db 38 | - POSTGRES_PORT=5432 39 | - POSTGRES_DB=gis 40 | - POSTGRES_USER=docker 41 | - POSTGRES_PASS=docker 42 | - SSL_MODE=allow 43 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 44 | - GEOSERVER_ADMIN_USER=admin 45 | # prevent some errors the option below 46 | #- ADDITIONAL_JAVA_STARTUP_OPTIONS="--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" 47 | restart: on-failure 48 | depends_on: 49 | db: 50 | condition: service_healthy 51 | healthcheck: 52 | test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u admin:'myawesomegeoserver' http://localhost:8080/geoserver/rest/about/version.xml" 53 | interval: 1m30s 54 | timeout: 10s 55 | retries: 3 56 | node: 57 | image: kartoza/geoserver:2.27.1 58 | volumes: 59 | - geoserver-cluster-data:/opt/geoserver/data_dir 60 | - geoserver-cluster-gwc-data:/opt/geoserver/gwc 61 | ports: 62 | - "8082:8080" 63 | environment: 64 | - GEOWEBCACHE_CACHE_DIR=/opt/geoserver/gwc 65 | - BROKER_URL=tcp://master:61661 66 | - READONLY=disabled 67 | - CLUSTER_DURABILITY=false 68 | - CLUSTERING=True 69 | - TOGGLE_MASTER=true 70 | - TOGGLE_SLAVE=true 71 | - EMBEDDED_BROKER=disabled 72 | - HOST=db 73 | - POSTGRES_PORT=5432 74 | - POSTGRES_DB=gis 75 | - POSTGRES_USER=docker 76 | - POSTGRES_PASS=docker 77 | - SSL_MODE=allow 78 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 79 | - GEOSERVER_ADMIN_USER=admin 80 | # prevent some errors the option below 81 | #- ADDITIONAL_JAVA_STARTUP_OPTIONS="--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" 82 | restart: on-failure 83 | depends_on: 84 | master: 85 | condition: service_started 86 | db: 87 | condition: service_healthy 88 | healthcheck: 89 | test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u admin:'myawesomegeoserver' http://localhost:8080/geoserver/rest/about/version.xml" 90 | interval: 1m30s 91 | timeout: 10s 92 | retries: 3 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docker-compose-build.yml: -------------------------------------------------------------------------------- 1 | volumes: 2 | geoserver-data: 3 | settings: 4 | services: 5 | geoserver-prod: 6 | image: kartoza/geoserver:${GS_VERSION} 7 | volumes: 8 | - geoserver-data:/opt/geoserver/data_dir 9 | - settings:/settings 10 | ports: 11 | - ${GEOSERVER_PORT}:8080 12 | restart: on-failure 13 | environment: 14 | - GEOSERVER_DATA_DIR=${GEOSERVER_DATA_DIR} 15 | - GEOWEBCACHE_CACHE_DIR=${GEOWEBCACHE_CACHE_DIR} 16 | - GEOSERVER_ADMIN_PASSWORD=${GEOSERVER_ADMIN_PASSWORD} 17 | - GEOSERVER_ADMIN_USER=${GEOSERVER_ADMIN_USER} 18 | - INITIAL_MEMORY=${INITIAL_MEMORY} 19 | - MAXIMUM_MEMORY=${MAXIMUM_MEMORY} 20 | - RECREATE_DATADIR=${RECREATE_DATADIR} 21 | - HTTP_PROXY_NAME 22 | - HTTP_PROXY_PORT 23 | - STABLE_EXTENSIONS=${STABLE_EXTENSIONS} 24 | - COMMUNITY_EXTENSIONS=${COMMUNITY_EXTENSIONS} 25 | healthcheck: 26 | test: [ "CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml" ] 27 | interval: 1m 28 | timeout: 10s 29 | retries: 3 30 | start_period: 1m 31 | build: 32 | context: . 33 | # Use yaml anchor for reusability 34 | args: &build-args-anchor 35 | IMAGE_VERSION: ${IMAGE_VERSION} 36 | JAVA_HOME: ${JAVA_HOME} 37 | GS_VERSION: ${GS_VERSION} 38 | WAR_URL: ${WAR_URL} 39 | STABLE_PLUGIN_BASE_URL: ${STABLE_PLUGIN_BASE_URL} 40 | ACTIVATE_GDAL_PLUGIN: ${ACTIVATE_GDAL_PLUGIN} 41 | target: geoserver-prod 42 | 43 | geoserver-test: 44 | image: kartoza/geoserver:manual-build 45 | build: 46 | context: . 47 | args: 48 | <<: *build-args-anchor 49 | target: geoserver-test -------------------------------------------------------------------------------- /docker-compose-nginx.yml: -------------------------------------------------------------------------------- 1 | volumes: 2 | geoserver-data: 3 | geo-db-data: 4 | 5 | services: 6 | db: 7 | image: kartoza/postgis:${POSTGIS_VERSION_TAG} 8 | volumes: 9 | - geo-db-data:/var/lib/postgresql 10 | ports: 11 | - ${POSTGRES_PORT}:5432 12 | environment: 13 | - POSTGRES_DB=${POSTGRES_DB} 14 | - POSTGRES_USER=${POSTGRES_USER} 15 | - POSTGRES_PASS=${POSTGRES_PASS} 16 | - ALLOW_IP_RANGE=${ALLOW_IP_RANGE} 17 | - FORCE_SSL=TRUE 18 | restart: on-failure 19 | healthcheck: 20 | test: "PGPASSWORD=${POSTGRES_PASS} pg_isready -h 127.0.0.1 -U ${POSTGRES_USER} -d ${POSTGRES_DB}" 21 | interval: 30s 22 | timeout: 10s 23 | retries: 3 24 | start_period: 1m 25 | 26 | geoserver: 27 | image: kartoza/geoserver:${GS_VERSION} 28 | volumes: 29 | - geoserver-data:/opt/geoserver/data_dir 30 | restart: on-failure 31 | environment: 32 | - GEOSERVER_DATA_DIR=${GEOSERVER_DATA_DIR} 33 | - GEOWEBCACHE_CACHE_DIR=${GEOWEBCACHE_CACHE_DIR} 34 | - GEOSERVER_ADMIN_PASSWORD=${GEOSERVER_ADMIN_PASSWORD} 35 | - GEOSERVER_ADMIN_USER=${GEOSERVER_ADMIN_USER} 36 | - INITIAL_MEMORY=${INITIAL_MEMORY} 37 | - MAXIMUM_MEMORY=${MAXIMUM_MEMORY} 38 | depends_on: 39 | db: 40 | condition: service_healthy 41 | healthcheck: 42 | test: [ "CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml" ] 43 | interval: 1m30s 44 | timeout: 10s 45 | retries: 3 46 | start_period: 1m 47 | 48 | nginx: 49 | image: nginx 50 | volumes: 51 | - ./sites-enabled:/etc/nginx/conf.d:ro 52 | logging: 53 | driver: json-file 54 | options: 55 | max-size: 200m 56 | max-file: '10' 57 | depends_on: 58 | - geoserver 59 | ports: 60 | - "80:80" 61 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | volumes: 2 | geoserver-data: 3 | geo-db-data: 4 | geoserver-gwc: 5 | geoserver-settings: 6 | 7 | services: 8 | db: 9 | image: kartoza/postgis:${POSTGIS_VERSION_TAG} 10 | volumes: 11 | - geo-db-data:/var/lib/postgresql 12 | ports: 13 | - "${POSTGRES_PORT}:5432" 14 | environment: 15 | - POSTGRES_DB=${POSTGRES_DB} 16 | - POSTGRES_USER=${POSTGRES_USER} 17 | - POSTGRES_PASS=${POSTGRES_PASS} 18 | - ALLOW_IP_RANGE=${ALLOW_IP_RANGE} 19 | - FORCE_SSL=TRUE 20 | restart: on-failure 21 | healthcheck: 22 | test: "pg_isready -h 127.0.0.1 -U ${POSTGRES_USER}" 23 | interval: 1m30s 24 | timeout: 10s 25 | retries: 3 26 | start_period: 1m 27 | 28 | geoserver: 29 | image: kartoza/geoserver:${GS_VERSION} 30 | volumes: 31 | - geoserver-data:/opt/geoserver/data_dir 32 | - geoserver-gwc:/opt/geoserver/gwc 33 | - geoserver-settings:/settings 34 | ports: 35 | - "${GEOSERVER_PORT}:8080" 36 | restart: on-failure 37 | environment: 38 | - GEOSERVER_DATA_DIR=${GEOSERVER_DATA_DIR} 39 | - GEOWEBCACHE_CACHE_DIR=${GEOWEBCACHE_CACHE_DIR} 40 | - GEOSERVER_ADMIN_PASSWORD=${GEOSERVER_ADMIN_PASSWORD} 41 | - GEOSERVER_ADMIN_USER=${GEOSERVER_ADMIN_USER} 42 | - INITIAL_MEMORY=${INITIAL_MEMORY} 43 | - MAXIMUM_MEMORY=${MAXIMUM_MEMORY} 44 | - STABLE_EXTENSIONS=${STABLE_EXTENSIONS} 45 | - COMMUNITY_EXTENSIONS=${COMMUNITY_EXTENSIONS} 46 | - GEOSERVER_CONTEXT_ROOT=${GEOSERVER_CONTEXT_ROOT} 47 | - ROOT_WEBAPP_REDIRECT=true 48 | - CONSOLE_HANDLER_LEVEL=${CONSOLE_HANDLER_LEVEL} 49 | depends_on: 50 | db: 51 | condition: service_healthy 52 | healthcheck: 53 | test: [ "CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml" ] 54 | interval: 1m30s 55 | timeout: 10s 56 | retries: 3 57 | start_period: 1m 58 | -------------------------------------------------------------------------------- /docs/assets/images/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/docs/assets/images/favicon.png -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.da.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `Danish` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.de.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `German` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.de=function(){this.pipeline.reset(),this.pipeline.add(e.de.trimmer,e.de.stopWordFilter,e.de.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.de.stemmer))},e.de.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.de.trimmer=e.trimmerSupport.generateTrimmer(e.de.wordCharacters),e.Pipeline.registerFunction(e.de.trimmer,"trimmer-de"),e.de.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(e,r,n){return!(!v.eq_s(1,e)||(v.ket=v.cursor,!v.in_grouping(p,97,252)))&&(v.slice_from(r),v.cursor=n,!0)}function i(){for(var r,n,i,s,t=v.cursor;;)if(r=v.cursor,v.bra=r,v.eq_s(1,"ß"))v.ket=v.cursor,v.slice_from("ss");else{if(r>=v.limit)break;v.cursor=r+1}for(v.cursor=t;;)for(n=v.cursor;;){if(i=v.cursor,v.in_grouping(p,97,252)){if(s=v.cursor,v.bra=s,e("u","U",i))break;if(v.cursor=s,e("y","Y",i))break}if(i>=v.limit)return void(v.cursor=n);v.cursor=i+1}}function s(){for(;!v.in_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}for(;!v.out_grouping(p,97,252);){if(v.cursor>=v.limit)return!0;v.cursor++}return!1}function t(){m=v.limit,l=m;var e=v.cursor+3;0<=e&&e<=v.limit&&(d=e,s()||(m=v.cursor,m=v.limit)return;v.cursor++}}}function c(){return m<=v.cursor}function u(){return l<=v.cursor}function a(){var e,r,n,i,s=v.limit-v.cursor;if(v.ket=v.cursor,(e=v.find_among_b(w,7))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:v.slice_del(),v.ket=v.cursor,v.eq_s_b(1,"s")&&(v.bra=v.cursor,v.eq_s_b(3,"nis")&&v.slice_del());break;case 3:v.in_grouping_b(g,98,116)&&v.slice_del()}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(f,4))&&(v.bra=v.cursor,c()))switch(e){case 1:v.slice_del();break;case 2:if(v.in_grouping_b(k,98,116)){var t=v.cursor-3;v.limit_backward<=t&&t<=v.limit&&(v.cursor=t,v.slice_del())}}if(v.cursor=v.limit-s,v.ket=v.cursor,(e=v.find_among_b(_,8))&&(v.bra=v.cursor,u()))switch(e){case 1:v.slice_del(),v.ket=v.cursor,v.eq_s_b(2,"ig")&&(v.bra=v.cursor,r=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-r,u()&&v.slice_del()));break;case 2:n=v.limit-v.cursor,v.eq_s_b(1,"e")||(v.cursor=v.limit-n,v.slice_del());break;case 3:if(v.slice_del(),v.ket=v.cursor,i=v.limit-v.cursor,!v.eq_s_b(2,"er")&&(v.cursor=v.limit-i,!v.eq_s_b(2,"en")))break;v.bra=v.cursor,c()&&v.slice_del();break;case 4:v.slice_del(),v.ket=v.cursor,e=v.find_among_b(b,2),e&&(v.bra=v.cursor,u()&&1==e&&v.slice_del())}}var d,l,m,h=[new r("",-1,6),new r("U",0,2),new r("Y",0,1),new r("ä",0,3),new r("ö",0,4),new r("ü",0,5)],w=[new r("e",-1,2),new r("em",-1,1),new r("en",-1,2),new r("ern",-1,1),new r("er",-1,1),new r("s",-1,3),new r("es",5,2)],f=[new r("en",-1,1),new r("er",-1,1),new r("st",-1,2),new r("est",2,1)],b=[new r("ig",-1,1),new r("lich",-1,1)],_=[new r("end",-1,1),new r("ig",-1,2),new r("ung",-1,1),new r("lich",-1,3),new r("isch",-1,2),new r("ik",-1,2),new r("heit",-1,3),new r("keit",-1,4)],p=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,8,0,32,8],g=[117,30,5],k=[117,30,4],v=new n;this.setCurrent=function(e){v.setCurrent(e)},this.getCurrent=function(){return v.getCurrent()},this.stem=function(){var e=v.cursor;return i(),v.cursor=e,t(),v.limit_backward=e,v.cursor=v.limit,a(),v.cursor=v.limit_backward,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.de.stemmer,"stemmer-de"),e.de.stopWordFilter=e.generateStopWordFilter("aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über".split(" ")),e.Pipeline.registerFunction(e.de.stopWordFilter,"stopWordFilter-de")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.du.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `Dutch` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");console.warn('[Lunr Languages] Please use the "nl" instead of the "du". The "nl" code is the standard code for Dutch language, and "du" will be removed in the next major versions.'),e.du=function(){this.pipeline.reset(),this.pipeline.add(e.du.trimmer,e.du.stopWordFilter,e.du.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.du.stemmer))},e.du.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.du.trimmer=e.trimmerSupport.generateTrimmer(e.du.wordCharacters),e.Pipeline.registerFunction(e.du.trimmer,"trimmer-du"),e.du.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){for(var e,r,i,o=C.cursor;;){if(C.bra=C.cursor,e=C.find_among(b,11))switch(C.ket=C.cursor,e){case 1:C.slice_from("a");continue;case 2:C.slice_from("e");continue;case 3:C.slice_from("i");continue;case 4:C.slice_from("o");continue;case 5:C.slice_from("u");continue;case 6:if(C.cursor>=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(r=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=r);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=r;else if(n(r))break}else if(n(r))break}function n(e){return C.cursor=e,e>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,f=_,t()||(_=C.cursor,_<3&&(_=3),t()||(f=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var e;;)if(C.bra=C.cursor,e=C.find_among(p,3))switch(C.ket=C.cursor,e){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return f<=C.cursor}function a(){var e=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-e,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var e;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.slice_del(),w=!0,a())))}function m(){var e;u()&&(e=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-e,C.eq_s_b(3,"gem")||(C.cursor=C.limit-e,C.slice_del(),a())))}function d(){var e,r,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,e=C.find_among_b(h,5))switch(C.bra=C.cursor,e){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(z,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(r=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-r,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,e=C.find_among_b(k,6))switch(C.bra=C.cursor,e){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(j,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var f,_,w,b=[new r("",-1,6),new r("á",0,1),new r("ä",0,1),new r("é",0,2),new r("ë",0,2),new r("í",0,3),new r("ï",0,3),new r("ó",0,4),new r("ö",0,4),new r("ú",0,5),new r("ü",0,5)],p=[new r("",-1,3),new r("I",0,2),new r("Y",0,1)],g=[new r("dd",-1,-1),new r("kk",-1,-1),new r("tt",-1,-1)],h=[new r("ene",-1,2),new r("se",-1,3),new r("en",-1,2),new r("heden",2,1),new r("s",-1,3)],k=[new r("end",-1,1),new r("ig",-1,2),new r("ing",-1,1),new r("lijk",-1,3),new r("baar",-1,4),new r("bar",-1,5)],v=[new r("aa",-1,-1),new r("ee",-1,-1),new r("oo",-1,-1),new r("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(e){C.setCurrent(e)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var r=C.cursor;return e(),C.cursor=r,o(),C.limit_backward=r,C.cursor=C.limit,d(),C.cursor=C.limit_backward,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.du.stemmer,"stemmer-du"),e.du.stopWordFilter=e.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),e.Pipeline.registerFunction(e.du.stopWordFilter,"stopWordFilter-du")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.hi.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.ja.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n=C.limit)break;C.cursor++;continue}break}for(C.cursor=o,C.bra=o,C.eq_s(1,"y")?(C.ket=C.cursor,C.slice_from("Y")):C.cursor=o;;)if(e=C.cursor,C.in_grouping(q,97,232)){if(i=C.cursor,C.bra=i,C.eq_s(1,"i"))C.ket=C.cursor,C.in_grouping(q,97,232)&&(C.slice_from("I"),C.cursor=e);else if(C.cursor=i,C.eq_s(1,"y"))C.ket=C.cursor,C.slice_from("Y"),C.cursor=e;else if(n(e))break}else if(n(e))break}function n(r){return C.cursor=r,r>=C.limit||(C.cursor++,!1)}function o(){_=C.limit,d=_,t()||(_=C.cursor,_<3&&(_=3),t()||(d=C.cursor))}function t(){for(;!C.in_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}for(;!C.out_grouping(q,97,232);){if(C.cursor>=C.limit)return!0;C.cursor++}return!1}function s(){for(var r;;)if(C.bra=C.cursor,r=C.find_among(p,3))switch(C.ket=C.cursor,r){case 1:C.slice_from("y");break;case 2:C.slice_from("i");break;case 3:if(C.cursor>=C.limit)return;C.cursor++}}function u(){return _<=C.cursor}function c(){return d<=C.cursor}function a(){var r=C.limit-C.cursor;C.find_among_b(g,3)&&(C.cursor=C.limit-r,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del()))}function l(){var r;w=!1,C.ket=C.cursor,C.eq_s_b(1,"e")&&(C.bra=C.cursor,u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.slice_del(),w=!0,a())))}function m(){var r;u()&&(r=C.limit-C.cursor,C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-r,C.eq_s_b(3,"gem")||(C.cursor=C.limit-r,C.slice_del(),a())))}function f(){var r,e,i,n,o,t,s=C.limit-C.cursor;if(C.ket=C.cursor,r=C.find_among_b(h,5))switch(C.bra=C.cursor,r){case 1:u()&&C.slice_from("heid");break;case 2:m();break;case 3:u()&&C.out_grouping_b(j,97,232)&&C.slice_del()}if(C.cursor=C.limit-s,l(),C.cursor=C.limit-s,C.ket=C.cursor,C.eq_s_b(4,"heid")&&(C.bra=C.cursor,c()&&(e=C.limit-C.cursor,C.eq_s_b(1,"c")||(C.cursor=C.limit-e,C.slice_del(),C.ket=C.cursor,C.eq_s_b(2,"en")&&(C.bra=C.cursor,m())))),C.cursor=C.limit-s,C.ket=C.cursor,r=C.find_among_b(k,6))switch(C.bra=C.cursor,r){case 1:if(c()){if(C.slice_del(),i=C.limit-C.cursor,C.ket=C.cursor,C.eq_s_b(2,"ig")&&(C.bra=C.cursor,c()&&(n=C.limit-C.cursor,!C.eq_s_b(1,"e")))){C.cursor=C.limit-n,C.slice_del();break}C.cursor=C.limit-i,a()}break;case 2:c()&&(o=C.limit-C.cursor,C.eq_s_b(1,"e")||(C.cursor=C.limit-o,C.slice_del()));break;case 3:c()&&(C.slice_del(),l());break;case 4:c()&&C.slice_del();break;case 5:c()&&w&&C.slice_del()}C.cursor=C.limit-s,C.out_grouping_b(z,73,232)&&(t=C.limit-C.cursor,C.find_among_b(v,4)&&C.out_grouping_b(q,97,232)&&(C.cursor=C.limit-t,C.ket=C.cursor,C.cursor>C.limit_backward&&(C.cursor--,C.bra=C.cursor,C.slice_del())))}var d,_,w,b=[new e("",-1,6),new e("á",0,1),new e("ä",0,1),new e("é",0,2),new e("ë",0,2),new e("í",0,3),new e("ï",0,3),new e("ó",0,4),new e("ö",0,4),new e("ú",0,5),new e("ü",0,5)],p=[new e("",-1,3),new e("I",0,2),new e("Y",0,1)],g=[new e("dd",-1,-1),new e("kk",-1,-1),new e("tt",-1,-1)],h=[new e("ene",-1,2),new e("se",-1,3),new e("en",-1,2),new e("heden",2,1),new e("s",-1,3)],k=[new e("end",-1,1),new e("ig",-1,2),new e("ing",-1,1),new e("lijk",-1,3),new e("baar",-1,4),new e("bar",-1,5)],v=[new e("aa",-1,-1),new e("ee",-1,-1),new e("oo",-1,-1),new e("uu",-1,-1)],q=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],z=[1,0,0,17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],j=[17,67,16,1,0,0,0,0,0,0,0,0,0,0,0,0,128],C=new i;this.setCurrent=function(r){C.setCurrent(r)},this.getCurrent=function(){return C.getCurrent()},this.stem=function(){var e=C.cursor;return r(),C.cursor=e,o(),C.limit_backward=e,C.cursor=C.limit,f(),C.cursor=C.limit_backward,s(),!0}};return function(r){return"function"==typeof r.update?r.update(function(r){return n.setCurrent(r),n.stem(),n.getCurrent()}):(n.setCurrent(r),n.stem(),n.getCurrent())}}(),r.Pipeline.registerFunction(r.nl.stemmer,"stemmer-nl"),r.nl.stopWordFilter=r.generateStopWordFilter(" aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou".split(" ")),r.Pipeline.registerFunction(r.nl.stopWordFilter,"stopWordFilter-nl")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.no.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `Norwegian` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.stemmer.support.min.js: -------------------------------------------------------------------------------- 1 | !function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursors||e>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor>1),f=0,l=o0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.sv.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Lunr languages, `Swedish` language 3 | * https://github.com/MihaiValentin/lunr-languages 4 | * 5 | * Copyright 2014, Mihai Valentin 6 | * http://www.mozilla.org/MPL/ 7 | */ 8 | /*! 9 | * based on 10 | * Snowball JavaScript Library v0.3 11 | * http://code.google.com/p/urim/ 12 | * http://snowball.tartarus.org/ 13 | * 14 | * Copyright 2010, Oleg Mazko 15 | * http://www.mozilla.org/MPL/ 16 | */ 17 | 18 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.ta.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ta=function(){this.pipeline.reset(),this.pipeline.add(e.ta.trimmer,e.ta.stopWordFilter,e.ta.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ta.stemmer))},e.ta.wordCharacters="஀-உஊ-ஏஐ-ஙச-ட஠-னப-யர-ஹ஺-ிீ-௉ொ-௏ௐ-௙௚-௟௠-௩௪-௯௰-௹௺-௿a-zA-Za-zA-Z0-90-9",e.ta.trimmer=e.trimmerSupport.generateTrimmer(e.ta.wordCharacters),e.Pipeline.registerFunction(e.ta.trimmer,"trimmer-ta"),e.ta.stopWordFilter=e.generateStopWordFilter("அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்".split(" ")),e.ta.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.ta.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.ta.stemmer,"stemmer-ta"),e.Pipeline.registerFunction(e.ta.stopWordFilter,"stopWordFilter-ta")}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.th.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[฀-๿]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.vi.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}}); -------------------------------------------------------------------------------- /docs/assets/javascripts/lunr/min/lunr.zh.min.js: -------------------------------------------------------------------------------- 1 | !function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("@node-rs/jieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 以 于 上 他 而 后 之 来 及 了 因 下 可 到 由 这 与 也 此 但 并 个 其 已 无 小 我 们 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 从 到 得 打 凡 儿 尔 该 各 给 跟 和 何 还 即 几 既 看 据 距 靠 啦 了 另 么 每 们 嘛 拿 哪 那 您 凭 且 却 让 仍 啥 如 若 使 谁 虽 随 同 所 她 哇 嗡 往 哪 些 向 沿 哟 用 于 咱 则 怎 曾 至 致 着 诸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}}); -------------------------------------------------------------------------------- /docs/assets/stylesheets/palette.2505c338.min.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["src/assets/stylesheets/palette/_scheme.scss","../../../src/assets/stylesheets/palette.scss","src/assets/stylesheets/palette/_accent.scss","src/assets/stylesheets/palette/_primary.scss","src/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"AA2BA,cAGE,6BAKE,YAAA,CAGA,mDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CACA,mDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CAGA,gDAAA,CACA,gDAAA,CAGA,4BAAA,CACA,iCAAA,CACA,kCAAA,CACA,mCAAA,CACA,mCAAA,CACA,kCAAA,CACA,iCAAA,CACA,+CAAA,CACA,6DAAA,CACA,gEAAA,CACA,4DAAA,CACA,4DAAA,CACA,6DAAA,CAGA,6CAAA,CAGA,+CAAA,CAGA,iCAAA,CAGA,uDAAA,CACA,6DAAA,CACA,2DAAA,CAGA,yDAAA,CAGA,mDAAA,CACA,mDAAA,CAGA,qDAAA,CACA,wDAAA,CAGA,0DAAA,CAKA,8DAAA,CAKA,0DCxDF,CD6DE,kHAEE,YC3DJ,CD+DE,gHAEE,eC7DJ,CDoFE,yDACE,4BClFJ,CDiFE,2DACE,4BC/EJ,CD8EE,gEACE,4BC5EJ,CD2EE,2DACE,4BCzEJ,CDwEE,yDACE,4BCtEJ,CDqEE,0DACE,4BCnEJ,CDkEE,gEACE,4BChEJ,CD+DE,0DACE,4BC7DJ,CD4DE,2OACE,4BCjDJ,CDwDA,+FAGE,iCCtDF,CACF,CCjDE,2BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD6CN,CCvDE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDoDN,CC9DE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD2DN,CCrEE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDkEN,CC5EE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDyEN,CCnFE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDgFN,CC1FE,kCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDuFN,CCjGE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD8FN,CCxGE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDqGN,CC/GE,6BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD4GN,CCtHE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDmHN,CC7HE,4BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCD6HN,CCpIE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDoIN,CC3IE,6BACE,yBAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCD2IN,CClJE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDkJN,CCzJE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDsJN,CE3JE,4BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwJN,CEnKE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFgKN,CE3KE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwKN,CEnLE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFgLN,CE3LE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwLN,CEnME,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFgMN,CE3ME,mCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwMN,CEnNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFgNN,CE3NE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwNN,CEnOE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFgON,CE3OE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwON,CEnPE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFmPN,CE3PE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCF2PN,CEnQE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFmQN,CE3QE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCF2QN,CEnRE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFgRN,CE3RE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFwRN,CEnSE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BF4RN,CE5SE,kCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BFqSN,CEtRE,sEACE,4BFyRJ,CE1RE,+DACE,4BF6RJ,CE9RE,iEACE,4BFiSJ,CElSE,gEACE,4BFqSJ,CEtSE,iEACE,4BFySJ,CEhSA,8BACE,0BAAA,CACA,sCAAA,CACA,qCAAA,CACA,+BAAA,CACA,sCAAA,CAGA,4BFiSF,CE9RE,yCACE,+BFgSJ,CE7RI,kDAEE,0CAAA,CACA,sCAAA,CAFA,UFiSN,CG7MI,mCD1EA,+CACE,0BF0RJ,CEvRI,qDACE,0BFyRN,CEpRE,iEACE,eFsRJ,CACF,CGxNI,sCDvDA,uCACE,oCFkRJ,CACF,CEzQA,8BACE,0BAAA,CACA,sCAAA,CACA,gCAAA,CACA,0BAAA,CACA,sCAAA,CAGA,4BF0QF,CEvQE,yCACE,+BFyQJ,CEtQI,kDAEE,0CAAA,CACA,sCAAA,CAFA,UF0QN,CEnQE,yCACE,qBFqQJ,CG9NI,wCDhCA,8CACE,0BFiQJ,CACF,CGtPI,mCDJA,+CACE,0BF6PJ,CE1PI,qDACE,0BF4PN,CACF,CG3OI,wCDTA,iFACE,qBFuPJ,CACF,CGnQI,sCDmBA,uCACE,qBFmPJ,CACF","file":"palette.css"} -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | None 5 | 2023-02-01 6 | daily 7 | 8 | 9 | None 10 | 2023-02-01 11 | daily 12 | 13 | 14 | None 15 | 2023-02-01 16 | daily 17 | 18 | 19 | None 20 | 2023-02-01 21 | daily 22 | 23 | 24 | None 25 | 2023-02-01 26 | daily 27 | 28 | 29 | None 30 | 2023-02-01 31 | daily 32 | 33 | 34 | None 35 | 2023-02-01 36 | daily 37 | 38 | -------------------------------------------------------------------------------- /docs/sitemap.xml.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/docs/sitemap.xml.gz -------------------------------------------------------------------------------- /resources/README.txt: -------------------------------------------------------------------------------- 1 | Resources needed in the image at build time should be placed here. 2 | -------------------------------------------------------------------------------- /resources/overlays/README.txt: -------------------------------------------------------------------------------- 1 | To include files in the container file system at arbitrary locations, build 2 | a directory structure from / here and include the files at the desired location. 3 | 4 | For example, to include a static Tomcat setenv.sh in the build, place it at: 5 | 6 | resources/overlays/usr/local/tomcat/bin/setenv.sh 7 | 8 | Other overlay examples include static GeoServer data directories, the Marlin renderer, etc. 9 | 10 | Note that overlay files will overwrite existing destination files, and that 11 | files in the overlay root will be copied to the container root 12 | (e.g. resources/overlay/somefile.txt will be copied to /somefile.txt). 13 | 14 | Be careful! 15 | -------------------------------------------------------------------------------- /scenario_tests/.gitignore: -------------------------------------------------------------------------------- 1 | docker-compose.override.yml 2 | -------------------------------------------------------------------------------- /scenario_tests/README.md: -------------------------------------------------------------------------------- 1 | # TESTING GUIDE 2 | 3 | 4 | ## TL;DR; How to run the test 5 | 6 | Go into root repo and run 7 | 8 | ``` 9 | ./build-test.sh 10 | ``` 11 | 12 | It will create a tagged image `kartoza/geoserver:${TAG:-manual-build}` 13 | 14 | Each scenario tests in this directory use this image. 15 | 16 | To run each scenario test, go into the scenario directory and run test script: 17 | 18 | ``` 19 | # Testing login scenario 20 | cd login 21 | ./test.sh 22 | ``` 23 | 24 | 25 | ## Making new tests 26 | 27 | Create new directory in this folder (`scenario_tests`). 28 | Directory should contains: 29 | 30 | - Host level test script called `test.sh` 31 | - `docker-compose.yml` file for the service setup 32 | - `.env` file if needed for `docker-compose.yml` settings 33 | - `tests` directory which contains your test scripts. The testing architecture will 34 | execute `test.sh` script in this directory (service level), if you use generic host level `test.sh` script. 35 | 36 | 37 | Explanations: 38 | 39 | Host level test script is used to set up the docker service, then run the unit test when 40 | the service is ready. You can copy and paste from existing `login` for generic script. 41 | 42 | `docker-compose.yml` file should mount your `tests` directory and provides settings 43 | needed by the service that are going to be tested. 44 | 45 | `tests` directory contains the actual test script that will be run from *inside* 46 | the service. For example, in `login` scenario `test.sh` (service level scripts) 47 | will start python unittest script with necessary variables. 48 | 49 | Add your scenario to travis config: 50 | 51 | In `env[]` list there will be a `SCENARIO` variable to set. 52 | Add your environment variable needed to run your test in `env[]` list. 53 | For example, if you have new scenario folder `my_test`, then the env key 54 | will look like this: 55 | 56 | ``` 57 | env: 58 | - SCENARIO=gwc 59 | - SCENARIO=plugins 60 | - SCENARIO=my_test EXTRA_SETTING_1=value1 EXTRA_SETTING_2=value2 EXTRA_SETTING_3=value3 61 | ``` 62 | -------------------------------------------------------------------------------- /scenario_tests/backup_restore/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | geoserver-data: 5 | geoserver-backup-dir: 6 | 7 | 8 | services: 9 | 10 | geoserver: 11 | image: 'kartoza/geoserver:${TAG:-manual-build}' 12 | restart: 'always' 13 | volumes: 14 | - geoserver-data-dir:/opt/geoserver/data_dir 15 | - geoserver-backup-dir:/settings 16 | - ./tests:/tests 17 | environment: 18 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 19 | GEOSERVER_ADMIN_USER: admin 20 | SAMPLE_DATA: true 21 | CONSOLE_HANDLER_LEVEL: WARNING 22 | COMMUNITY_EXTENSIONS: backup-restore-plugin 23 | TEST_CLASS: test_geoserver_backup.TestGeoServerBackup 24 | ports: 25 | - "8080:8080" 26 | healthcheck: 27 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 28 | interval: 1m30s 29 | timeout: 10s 30 | retries: 3 31 | 32 | restore: 33 | image: 'kartoza/geoserver:${TAG:-manual-build}' 34 | restart: 'always' 35 | volumes: 36 | - geoserver-data:/opt/geoserver/data_dir 37 | - geoserver-backup-dir:/settings 38 | - ./tests:/tests 39 | environment: 40 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 41 | GEOSERVER_ADMIN_USER: admin 42 | CONSOLE_HANDLER_LEVEL: WARNING 43 | RECREATE_DATADIR: TRUE 44 | COMMUNITY_EXTENSIONS: backup-restore-plugin 45 | TEST_CLASS: test_geoserver_restore.TestGeoServerRestore 46 | ports: 47 | - "8080" 48 | healthcheck: 49 | test: [ "CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml" ] 50 | interval: 1m30s 51 | timeout: 10s 52 | retries: 3 53 | 54 | 55 | -------------------------------------------------------------------------------- /scenario_tests/backup_restore/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ${VERSION} -f docker-compose.yml up -d 11 | 12 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 13 | ${VERSION} -f docker-compose.yml logs -f & 14 | fi 15 | 16 | 17 | services=("geoserver") 18 | 19 | for service in "${services[@]}"; do 20 | 21 | # Execute tests 22 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 23 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 24 | echo -e "\e[32m ---------------------------------------- \033[0m" 25 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 26 | ${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh 27 | 28 | done 29 | 30 | services=("restore") 31 | 32 | for service in "${services[@]}"; do 33 | 34 | # Execute tests 35 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 36 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 37 | echo -e "\e[32m ---------------------------------------- \033[0m" 38 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 39 | ${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh 40 | 41 | done 42 | 43 | ${VERSION} -f docker-compose.yml down -v 44 | -------------------------------------------------------------------------------- /scenario_tests/backup_restore/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/backup_restore/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/backup_restore/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/backup_restore/tests/test_geoserver_backup.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import requests 3 | from requests.auth import HTTPBasicAuth 4 | from os import environ, mkdir, chmod 5 | from os.path import join, exists 6 | from shutil import chown 7 | import json 8 | import time 9 | 10 | 11 | class TestGeoServerBackup(unittest.TestCase): 12 | 13 | def setUp(self): 14 | """Set up the base URL, authentication, and create the zip file.""" 15 | self.gs_url = 'http://localhost:8080/geoserver' 16 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 17 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 18 | self.username = 'geoserveruser' 19 | self.group_name = 'geoserverusers' 20 | self.backup_path = "/settings/backup/" 21 | 22 | def test_create_backup(self): 23 | """Test creating a GeoServer backup using the Backup and Restore plugin.""" 24 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 25 | base_url = f"{self.gs_url}/rest/br/backup/" 26 | if not exists(self.backup_path): 27 | mkdir(self.backup_path) 28 | backup_file = join(self.backup_path, 'geoserver.zip') 29 | # Create the empty zip file 30 | with open(backup_file, "wb") as f: 31 | pass 32 | 33 | # Change ownership of the zip file 34 | chmod(self.backup_path, 0o777) 35 | chown(backup_file, user=self.username, group=self.group_name) 36 | headers = { 37 | "Content-Type": "application/json" 38 | } 39 | 40 | payload = { 41 | "backup": { 42 | "archiveFile": backup_file, 43 | "overwrite": True, 44 | "options": {}, 45 | "filter": "name IN ('tiger')" 46 | } 47 | } 48 | 49 | # Send the POST request to trigger the backup 50 | response = requests.post(base_url, json=payload, auth=auth, headers=headers) 51 | response_data = json.loads(response.text) 52 | execution_id = response_data["backup"]["execution"]["id"] 53 | execution_url = f"{self.gs_url}/rest/br/backup/{execution_id}.json" 54 | # wait for backup to complete 55 | time.sleep(40) 56 | response_execution_request = requests.get(execution_url, auth=auth) 57 | if response_execution_request.status_code == 200: 58 | try: 59 | response_execution_json = response_execution_request.json() 60 | response_status = response_execution_json["backup"]["execution"]["status"] 61 | self.assertEqual(response_status, 'COMPLETED', "backup initiated successfully") 62 | except ValueError as e: 63 | print("Error parsing JSON:", e) 64 | print("Raw response content:", response_execution_request.text) 65 | else: 66 | print(f"Request failed with status code {response_execution_request.status_code}") 67 | print("Response content:", response_execution_request.text) 68 | 69 | # Verify the response status code 70 | self.assertEqual(response.status_code, 201, "backup initiated successfully") 71 | 72 | 73 | if __name__ == "__main__": 74 | unittest.main() 75 | -------------------------------------------------------------------------------- /scenario_tests/backup_restore/tests/test_geoserver_restore.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import unittest 3 | import requests 4 | from requests.auth import HTTPBasicAuth 5 | from os import environ, chmod 6 | from os.path import join, exists 7 | import json 8 | import time 9 | 10 | 11 | class TestGeoServerRestore(unittest.TestCase): 12 | 13 | def setUp(self): 14 | """Set up the base URL, authentication, and create the zip file.""" 15 | self.gs_url = 'http://localhost:8080/geoserver' 16 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 17 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 18 | self.backup_path = "/settings/backup/" 19 | 20 | def test_restore_backup(self): 21 | """Test restoring an existing backup of a GeoServer instance using the Backup and Restore plugin.""" 22 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 23 | base_url = f"{self.gs_url}/rest/br/restore/" 24 | backup_file = join(self.backup_path, 'geoserver.zip') 25 | chmod(self.backup_path, 0o777) 26 | if not exists(backup_file): 27 | sys.exit() 28 | 29 | headers = { 30 | "Content-Type": "application/json" 31 | } 32 | 33 | payload = { 34 | "restore": { 35 | "archiveFile": backup_file, 36 | "options": { 37 | "option": ["BK_BEST_EFFORT=true"] 38 | } 39 | } 40 | } 41 | 42 | # Send the POST request to trigger the backup 43 | response = requests.post(base_url, json=payload, auth=auth, headers=headers) 44 | response_data = json.loads(response.text) 45 | execution_id = response_data["restore"]["execution"]["id"] 46 | execution_url = f"{self.gs_url}/rest/br/restore/{execution_id}.json" 47 | # wait for backup to complete 48 | time.sleep(30) 49 | response_execution_request = requests.get(execution_url, auth=auth) 50 | if response_execution_request.status_code == 200: 51 | try: 52 | response_execution_json = response_execution_request.json() 53 | response_status = response_execution_json["restore"]["execution"]["status"] 54 | self.assertEqual(response_status, 'COMPLETED', "backup initiated successfully") 55 | except ValueError as e: 56 | print("Error parsing JSON:", e) 57 | print("Raw response content:", response_execution_request.text) 58 | else: 59 | print(f"Request failed with status code {response_execution_request.status_code}") 60 | print("Response content:", response_execution_request.text) 61 | 62 | # Verify the response status code 63 | self.assertEqual(response.status_code, 201, "backup initiated successfully") 64 | 65 | 66 | if __name__ == "__main__": 67 | unittest.main() 68 | -------------------------------------------------------------------------------- /scenario_tests/clustering/docker-compose-external.yml: -------------------------------------------------------------------------------- 1 | # Common template for ActiveMQ services below 2 | x-common-activemq: 3 | &default-common-activemq 4 | image: kartoza/activemq-docker:manual-build 5 | #build: activemq-docker 6 | restart: on-failure 7 | 8 | services: 9 | 10 | db: 11 | image: kartoza/postgis:17-3.5 12 | volumes: 13 | - geo-db-data:/var/lib/postgresql 14 | - ./tests/init.sql:/docker-entrypoint-initdb.d/init.sql 15 | environment: 16 | - POSTGRES_DB=gis,data,sample 17 | - POSTGRES_USER=docker 18 | - POSTGRES_PASS=docker 19 | - ALLOW_IP_RANGE=0.0.0.0/0 20 | - FORCE_SSL=TRUE 21 | restart: on-failure 22 | healthcheck: 23 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker" 24 | 25 | broker1: 26 | << : *default-common-activemq 27 | environment: 28 | - JAVA_HOME=/opt/java/openjdk 29 | - HOST=db 30 | - POSTGRES_PORT=5432 31 | - POSTGRES_DB=gis 32 | - POSTGRES_USER=docker 33 | - POSTGRES_PASS=docker 34 | - ACTIVEMQ_SERVER_URI=tcp://broker1:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=false&transport.daemon=true 35 | - ACTIVEMQ_SERVER_DISCOVERYURI=multicast://default 36 | - SSL_MODE=ALLOW 37 | depends_on: 38 | db: 39 | condition: service_healthy 40 | healthcheck: 41 | test: netstat -ltn | grep -c ":61616" 42 | interval: 30s 43 | timeout: 10s 44 | retries: 10 45 | 46 | broker2: 47 | << : *default-common-activemq 48 | environment: 49 | - JAVA_HOME=/opt/java/openjdk 50 | - HOST=db 51 | - POSTGRES_PORT=5432 52 | - POSTGRES_DB=data 53 | - POSTGRES_USER=docker 54 | - POSTGRES_PASS=docker 55 | - ACTIVEMQ_SERVER_URI=tcp://broker2:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=false&transport.daemon=true 56 | - ACTIVEMQ_SERVER_DISCOVERYURI=multicast://default 57 | - SSL_MODE=ALLOW 58 | depends_on: 59 | db: 60 | condition: service_healthy 61 | broker1: 62 | condition: service_healthy 63 | healthcheck: 64 | test: netstat -ltn | grep -c ":61616" 65 | interval: 30s 66 | timeout: 10s 67 | retries: 10 68 | 69 | broker3: 70 | << : *default-common-activemq 71 | environment: 72 | - JAVA_HOME=/opt/java/openjdk 73 | - HOST=db 74 | - POSTGRES_PORT=5432 75 | - POSTGRES_DB=sample 76 | - POSTGRES_USER=docker 77 | - POSTGRES_PASS=docker 78 | - ACTIVEMQ_SERVER_URI=tcp://broker3:61616?maximumConnections=1000&wireFormat.maxFrameSize=104857600&jms.useAsyncSend=false&transport.daemon=true 79 | - ACTIVEMQ_SERVER_DISCOVERYURI=multicast://default 80 | - SSL_MODE=ALLOW 81 | depends_on: 82 | db: 83 | condition: service_healthy 84 | broker1: 85 | condition: service_healthy 86 | healthcheck: 87 | test: netstat -ltn | grep -c ":61616" 88 | interval: 30s 89 | timeout: 10s 90 | retries: 10 91 | 92 | master: 93 | image: kartoza/geoserver:manual-build 94 | environment: 95 | - CLUSTERING=true 96 | - CLUSTER_DURABILITY=false 97 | - DB_BACKEND=POSTGRES 98 | - HOST=db 99 | - POSTGRES_PORT=5432 100 | - POSTGRES_DB=gis 101 | - POSTGRES_USER=docker 102 | - POSTGRES_PASS=docker 103 | #- POSTGRES_SCHEMA=gwc 104 | - SSL_MODE=ALLOW 105 | - BROKER_URL=failover:(tcp://broker1:61616,tcp://broker2:61616,tcp://broker3:61616) 106 | - READONLY=disabled 107 | - TOGGLE_MASTER=true 108 | - TOGGLE_SLAVE=false 109 | - EMBEDDED_BROKER=disabled 110 | - RUN_AS_ROOT=TRUE 111 | - GEOSERVER_ADMIN_USER=admin 112 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 113 | - CONSOLE_HANDLER_LEVEL=WARNING 114 | - STABLE_EXTENSIONS= 115 | - COMMUNITY_EXTENSIONS=jms-cluster-plugin 116 | - TEST_CLASS=test_clustering_master.GeoServerClusteringMaster 117 | volumes: 118 | - geoserver-cluster-data:/opt/geoserver/data_dir 119 | - ./tests:/tests 120 | ports: 121 | - "8081:8080" 122 | healthcheck: 123 | test: ["CMD-SHELL","curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u admin:myawesomegeoserver http://localhost:8080/geoserver/rest/about/version.xml"] 124 | interval: 1m30s 125 | timeout: 10s 126 | retries: 3 127 | 128 | 129 | node: 130 | image: kartoza/geoserver:manual-build 131 | environment: 132 | - CLUSTERING=true 133 | - CLUSTER_DURABILITY=false 134 | - DB_BACKEND=POSTGRES 135 | - HOST=db 136 | - POSTGRES_PORT=5432 137 | - POSTGRES_DB=gis 138 | - POSTGRES_USER=docker 139 | - POSTGRES_PASS=docker 140 | #- POSTGRES_SCHEMA=gwc 141 | - SSL_MODE=ALLOW 142 | - BROKER_URL=failover:(tcp://broker1:61616,tcp://broker2:61616,tcp://broker3:61616) 143 | - READONLY=enabled 144 | - TOGGLE_MASTER=false 145 | - TOGGLE_SLAVE=true 146 | - EMBEDDED_BROKER=disabled 147 | - RUN_AS_ROOT=TRUE 148 | - GEOSERVER_ADMIN_USER=admin 149 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 150 | - CONSOLE_HANDLER_LEVEL=WARNING 151 | - STABLE_EXTENSIONS= 152 | - COMMUNITY_EXTENSIONS=jms-cluster-plugin 153 | - TEST_CLASS=test_clustering_node.GeoServerClusteringNode 154 | volumes: 155 | - geoserver-cluster-data:/opt/geoserver/data_dir 156 | - ./tests:/tests 157 | ports: 158 | - "8082:8080" 159 | healthcheck: 160 | test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u admin:myawesomegeoserver http://localhost:8080/geoserver/rest/about/version.xml" 161 | interval: 1m30s 162 | timeout: 10s 163 | retries: 3 164 | 165 | volumes: 166 | geoserver-cluster-data: 167 | geo-db-data: 168 | -------------------------------------------------------------------------------- /scenario_tests/clustering/docker-compose.yml: -------------------------------------------------------------------------------- 1 | volumes: 2 | geoserver-cluster-data: 3 | geo-db-data: 4 | 5 | services: 6 | db: 7 | image: kartoza/postgis:17-3.5 8 | volumes: 9 | - geo-db-data:/var/lib/postgresql 10 | - ./tests/init.sql:/docker-entrypoint-initdb.d/init.sql 11 | environment: 12 | - POSTGRES_DB=gis 13 | - POSTGRES_USER=docker 14 | - POSTGRES_PASS=docker 15 | - ALLOW_IP_RANGE=0.0.0.0/0 16 | - FORCE_SSL=FALSE 17 | restart: on-failure 18 | healthcheck: 19 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker" 20 | master: 21 | image: 'kartoza/geoserver:${TAG:-manual-build}' 22 | volumes: 23 | - geoserver-cluster-data:/opt/geoserver/data_dir 24 | - ./tests:/tests 25 | environment: 26 | - BROKER_URL=tcp://0.0.0.0:61661 27 | - READONLY=disabled 28 | - CLUSTER_DURABILITY=false 29 | - CLUSTERING=True 30 | - TOGGLE_MASTER=true 31 | - TOGGLE_SLAVE=true 32 | - DB_BACKEND=POSTGRES 33 | - HOST=db 34 | - POSTGRES_PORT=5432 35 | - POSTGRES_DB=gis 36 | - POSTGRES_USER=docker 37 | - POSTGRES_PASS=docker 38 | - SSL_MODE=allow 39 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 40 | - GEOSERVER_ADMIN_USER=admin 41 | - CONSOLE_HANDLER_LEVEL=WARNING 42 | - TEST_CLASS=test_clustering_master.GeoServerClusteringMaster 43 | ports: 44 | - "8081:8080" 45 | restart: on-failure 46 | depends_on: 47 | db: 48 | condition: service_healthy 49 | healthcheck: 50 | test: "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u admin:'myawesomegeoserver' http://localhost:8080/geoserver/rest/about/version.xml" 51 | interval: 1m30s 52 | timeout: 10s 53 | retries: 3 54 | node: 55 | image: 'kartoza/geoserver:${TAG:-manual-build}' 56 | volumes: 57 | - geoserver-cluster-data:/opt/geoserver/data_dir 58 | - ./tests:/tests 59 | environment: 60 | - BROKER_URL=tcp://master:61661 61 | - READONLY=disabled 62 | - CLUSTER_DURABILITY=false 63 | - CLUSTERING=True 64 | - TOGGLE_MASTER=true 65 | - TOGGLE_SLAVE=true 66 | - EMBEDDED_BROKER=disabled 67 | - HOST=db 68 | - POSTGRES_PORT=5432 69 | - POSTGRES_DB=gis 70 | - POSTGRES_USER=docker 71 | - POSTGRES_PASS=docker 72 | - SSL_MODE=allow 73 | - GEOSERVER_ADMIN_PASSWORD=myawesomegeoserver 74 | - GEOSERVER_ADMIN_USER=admin 75 | - CONSOLE_HANDLER_LEVEL=WARNING 76 | - TEST_CLASS=test_clustering_node.GeoServerClusteringNode 77 | ports: 78 | - "8082:8080" 79 | restart: on-failure 80 | depends_on: 81 | master: 82 | condition: service_started 83 | db: 84 | condition: service_healthy 85 | healthcheck: 86 | test: ["CMD-SHELL","curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u admin:'myawesomegeoserver' http://localhost:8080/geoserver/rest/about/version.xml"] 87 | interval: 1m30s 88 | timeout: 10s 89 | retries: 3 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /scenario_tests/clustering/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ################################ 11 | #Test using internal jms cluster 12 | ################################ 13 | echo -e "------------------------------------------------------" 14 | echo -e "[Unit Test] Running testing using internal: JMS plugin" 15 | 16 | ${VERSION} -f docker-compose.yml up -d 17 | 18 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 19 | ${VERSION} -f docker-compose.yml logs -f & 20 | fi 21 | 22 | 23 | # Test Master 24 | services=("master") 25 | 26 | for service in "${services[@]}"; do 27 | 28 | # Execute tests 29 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 30 | test_url_availability http://localhost:8081/geoserver/rest/about/version.xml 31 | echo "Execute test for $service" 32 | ${VERSION} -f docker-compose.yml exec "${service}" /bin/bash /tests/test.sh 33 | 34 | done 35 | 36 | # Test Node 37 | services=("node") 38 | 39 | for service in "${services[@]}"; do 40 | 41 | # Execute tests 42 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 43 | test_url_availability http://localhost:8082/geoserver/rest/about/version.xml 44 | echo "Execute test for $service" 45 | ${VERSION} -f docker-compose.yml exec "${service}" /bin/bash /tests/test.sh 46 | 47 | done 48 | 49 | ${VERSION} -f docker-compose.yml down -v 50 | 51 | ############################# 52 | #Test using external ActiveMQ 53 | ############################# 54 | 55 | echo -e "------------------------------------------------------" 56 | echo -e "[Unit Test] Running testing using internal: ActiveMQ" 57 | 58 | ${VERSION} -f docker-compose-external.yml up -d 59 | 60 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 61 | ${VERSION} -f docker-compose-external.yml logs -f & 62 | fi 63 | 64 | 65 | 66 | # Test Master 67 | services=("master") 68 | 69 | for service in "${services[@]}"; do 70 | 71 | # Execute tests 72 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 73 | test_url_availability http://localhost:8081/geoserver/rest/about/version.xml 74 | echo -e "\e[32m ---------------------------------------- \033[0m" 75 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 76 | ${VERSION} -f docker-compose-external.yml exec "${service}" /bin/bash /tests/test.sh 77 | 78 | done 79 | 80 | # Test Node 81 | services=("node") 82 | 83 | for service in "${services[@]}"; do 84 | 85 | # Execute tests 86 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 87 | test_url_availability http://localhost:8082/geoserver/rest/about/version.xml 88 | echo -e "\e[32m ---------------------------------------- \033[0m" 89 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 90 | ${VERSION} -f docker-compose-external.yml exec "${service}" /bin/bash /tests/test.sh 91 | 92 | done 93 | 94 | ${VERSION} -f docker-compose-external.yml down -v -------------------------------------------------------------------------------- /scenario_tests/clustering/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/clustering/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/clustering/tests/init.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS states ( 2 | id integer not null 3 | constraint pkey primary key, 4 | geom geometry(Point, 4326), 5 | name varchar(30), 6 | alias varchar(30), 7 | description varchar(255) 8 | ); 9 | 10 | INSERT INTO states (id, geom, name, alias, description) 11 | VALUES 12 | ( 13 | 1, 14 | st_setsrid(st_point(107.6097, 6.9120), 4326), 15 | 'Bandung', 16 | 'Paris van Java', 17 | 'Asia-Africa conference was held here' 18 | ) ON CONFLICT DO NOTHING; 19 | 20 | 21 | -------------------------------------------------------------------------------- /scenario_tests/clustering/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/clustering/tests/test_clustering_master.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import environ 3 | 4 | from geo.Geoserver import Geoserver 5 | from requests import get, post, exceptions 6 | from requests.auth import HTTPBasicAuth 7 | from shutil import copy 8 | 9 | 10 | class GeoServerClusteringMaster(unittest.TestCase): 11 | 12 | def setUp(self): 13 | # Define the GeoServer URL 14 | self.gs_url = 'http://localhost:8080/geoserver' 15 | # Define the PostGIS JNDI store name 16 | self.store_name = 'gis' 17 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 18 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 19 | self.geo_workspace_name = 'demo' 20 | 21 | def test_publish_store(self): 22 | geo = Geoserver(self.gs_url, username='%s' % self.geo_username, password='%s' % self.geo_password) 23 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 24 | # create workspace 25 | geo.create_workspace(workspace='%s' % self.geo_workspace_name) 26 | geo.set_default_workspace('%s' % self.geo_workspace_name) 27 | 28 | # Create the XML payload for the JNDI store configuration 29 | xml = """ 30 | 31 | {name} 32 | PostGIS 33 | true 34 | 35 | db 36 | 5432 37 | gis 38 | docker 39 | docker 40 | public 41 | true 42 | 1000 43 | true 44 | false 45 | true 46 | 1 47 | false 48 | FAST 49 | postgis 50 | true 51 | ALLOW 52 | 53 | false 54 | 55 | """.format(name=self.store_name) 56 | 57 | # Publish the store 58 | response = post(self.gs_url + '/rest/workspaces/%s/datastores' % self.geo_workspace_name, auth=auth, 59 | headers={'Content-type': 'text/xml'}, 60 | data=xml) 61 | 62 | # Check that the response has a status code of 201 (Created) 63 | self.assertEqual(response.status_code, 201) 64 | 65 | # Check that the store exists 66 | data_source_url = '%s/rest/workspaces/%s/datastores/%s.json' % ( 67 | self.gs_url, self.geo_workspace_name, self.store_name) 68 | response = get(data_source_url, auth=auth) 69 | 70 | # Check that the response has a status code of 200 (OK) 71 | self.assertEqual(response.status_code, 200) 72 | 73 | # Publish layer into GeoServer 74 | geo.publish_featurestore(workspace='%s' 75 | % self.geo_workspace_name, store_name='%s' % self.store_name, 76 | pg_table='states') 77 | copy("/usr/local/tomcat/data/styles/default_point.sld", "/usr/local/tomcat/data/styles/states.sld") 78 | layer_sld_file = "/usr/local/tomcat/data/styles/states.sld" 79 | geo.upload_style(path=str(layer_sld_file), workspace=self.geo_workspace_name) 80 | geo.publish_style(layer_name='states', style_name='states', workspace=self.geo_workspace_name) 81 | self.assertEqual(response.status_code, 200) 82 | 83 | # Check that the layer exists 84 | layer_url = '%s/rest/workspaces/%s/layers/states.json' % ( 85 | self.gs_url, self.geo_workspace_name) 86 | response = get(layer_url, auth=auth) 87 | 88 | # Check that the response has a status code of 200 (OK) 89 | self.assertEqual(response.status_code, 200) 90 | 91 | 92 | if __name__ == '__main__': 93 | unittest.main() 94 | -------------------------------------------------------------------------------- /scenario_tests/clustering/tests/test_clustering_node.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import environ 3 | from requests import get, exceptions 4 | from requests.auth import HTTPBasicAuth 5 | 6 | 7 | class GeoServerClusteringNode(unittest.TestCase): 8 | 9 | def setUp(self): 10 | # Define the GeoServer URL 11 | self.gs_url = 'http://localhost:8080/geoserver' 12 | # Define the PostGIS store name 13 | self.store_name = 'gis' 14 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 15 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 16 | self.geo_workspace_name = 'demo' 17 | 18 | def check_workspace_exists(self, auth): 19 | rest_url = '%s/rest/workspaces/%s.json' % (self.gs_url, self.geo_workspace_name) 20 | response = get(rest_url, auth=auth) 21 | return response.status_code == 200 22 | 23 | def check_data_store_exists(self, auth): 24 | data_source_url = '%s/rest/workspaces/%s/datastores/%s.json' % ( 25 | self.gs_url, self.geo_workspace_name, self.store_name) 26 | response = get(data_source_url, auth=auth) 27 | return response.status_code == 200 28 | 29 | def check_layer_exists(self, auth, layer_name): 30 | layer_url = '%s/rest/workspaces/%s/layers/%s.json' % ( 31 | self.gs_url, self.geo_workspace_name, layer_name) 32 | response = get(layer_url, auth=auth) 33 | return response.status_code == 200 34 | 35 | def check_style_exists(self, auth, layer_name): 36 | style_url = '%s/rest/workspaces/%s/styles/%s.json' % ( 37 | self.gs_url, self.geo_workspace_name, layer_name) 38 | response = get(style_url, auth=auth) 39 | return response.status_code == 200 40 | 41 | def test_workspace_exists(self): 42 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 43 | workspace_exists = self.check_workspace_exists(auth) 44 | self.assertTrue(workspace_exists, "Workspace does not exist") 45 | 46 | def test_data_store_exists(self): 47 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 48 | data_store_exists = self.check_data_store_exists(auth) 49 | self.assertTrue(data_store_exists, "Data store does not exist") 50 | 51 | def test_layer_exists(self): 52 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 53 | layer_name = 'states' 54 | layer_exists = self.check_layer_exists(auth, layer_name) 55 | self.assertTrue(layer_exists, "Layer does not exist") 56 | 57 | def test_layer_style_exists(self): 58 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 59 | layer_name = 'states' 60 | layer_exists = self.check_style_exists(auth, layer_name) 61 | self.assertTrue(layer_exists, "Style does not exist") 62 | 63 | 64 | if __name__ == '__main__': 65 | unittest.main() 66 | -------------------------------------------------------------------------------- /scenario_tests/context/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | 5 | 6 | services: 7 | geoserver: 8 | image: 'kartoza/geoserver:${TAG:-manual-build}' 9 | restart: 'always' 10 | volumes: 11 | - geoserver-data-dir:/opt/geoserver/data_dir 12 | - ./tests:/tests 13 | ports: 14 | - "8080:8080" 15 | environment: 16 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 17 | GEOSERVER_ADMIN_USER: admin 18 | INITIAL_MEMORY: 2G 19 | MAXIMUM_MEMORY: 4G 20 | GEOSERVER_CONTEXT_ROOT: foobar 21 | CONSOLE_HANDLER_LEVEL: WARNING 22 | TEST_CLASS: test_context.TestGeoServerREST 23 | healthcheck: 24 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/foobar/rest/about/version.xml"] 25 | interval: 1m30s 26 | timeout: 10s 27 | retries: 3 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /scenario_tests/context/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | #################################### 11 | #Test using default created password 12 | ##################################### 13 | echo -e "[Unit Test] Running GEOSERVER_CONTEXT_ROOT tests with GEOSERVER_CONTEXT_ROOT set to foobar" 14 | 15 | ${VERSION} up -d 16 | 17 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 18 | ${VERSION} logs -f & 19 | fi 20 | 21 | 22 | # Set default values 23 | PASS="myawesomegeoserver" 24 | USER="admin" 25 | 26 | services=("geoserver") 27 | 28 | for service in "${services[@]}"; do 29 | 30 | 31 | # Execute tests 32 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 33 | test_url_availability http://localhost:8080/foobar/rest/about/version.xml "$PASS" "$USER" 34 | echo "Execute test for $service" 35 | ${VERSION} exec -T "${service}" /bin/bash /tests/test.sh 36 | 37 | done 38 | 39 | ${VERSION} down -v 40 | 41 | #################################### 42 | #Test using updated password 43 | ##################################### 44 | echo -e "[Unit Test] Running GEOSERVER_CONTEXT_ROOT tests with GEOSERVER_CONTEXT_ROOT set to foobar#geoserver" 45 | sed -i 's/foobar/foobar#geoserver/g' docker-compose.yml 46 | # Bring the services up again 47 | ${VERSION} up -d geoserver 48 | 49 | services=("geoserver") 50 | 51 | for service in "${services[@]}"; do 52 | 53 | # Execute tests 54 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 55 | test_url_availability http://localhost:8080/foobar/geoserver/rest/about/version.xml "$PASS" "$USER" 56 | echo -e "\e[32m ---------------------------------------- \033[0m" 57 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 58 | ${VERSION} exec -T "${service}" /bin/bash /tests/test.sh 59 | 60 | done 61 | 62 | ${VERSION} down -v 63 | sed -i 's/foobar#geoserver/foobar/g' docker-compose.yml -------------------------------------------------------------------------------- /scenario_tests/context/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/context/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/context/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/context/tests/test_context.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import unittest 3 | from os import environ 4 | 5 | 6 | class TestGeoServerREST(unittest.TestCase): 7 | 8 | def setUp(self): 9 | # Login to GeoServer and get the authentication cookies 10 | self.geo_context = environ.get('GEOSERVER_CONTEXT_ROOT').replace("#", '/') 11 | self.base_url = f'http://localhost:8080/{self.geo_context}' 12 | self.login_url = f'{self.base_url}/j_spring_security_check' 13 | self.password = environ['GEOSERVER_ADMIN_PASSWORD'] 14 | 15 | self.session = requests.Session() 16 | login_data = { 17 | 'username': 'admin', 18 | 'password': self.password, 19 | 'submit': 'Login' 20 | } 21 | response = self.session.post(self.login_url, data=login_data) 22 | self.assertEqual(response.status_code, 200) 23 | 24 | def test_rest_endpoints_accessible(self): 25 | # Test if the REST endpoints are accessible as a logged user 26 | url = f'{self.base_url}/rest/workspaces.json' 27 | response = self.session.get(url) 28 | self.assertEqual(response.status_code, 200) 29 | self.assertTrue(response.json()) 30 | 31 | def tearDown(self): 32 | # Logout from GeoServer 33 | logout_url = f'{self.base_url}/j_spring_security_logout' 34 | response = self.session.post(logout_url) 35 | self.assertEqual(response.status_code, 200) 36 | -------------------------------------------------------------------------------- /scenario_tests/disk-quota/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | postgis-data: 5 | 6 | 7 | services: 8 | db: 9 | image: kartoza/postgis:17-3.5 10 | volumes: 11 | - postgis-data:/var/lib/postgresql 12 | environment: 13 | - POSTGRES_DB=gis,gwc 14 | - POSTGRES_USER=docker 15 | - POSTGRES_PASS=docker 16 | - ALLOW_IP_RANGE=0.0.0.0/0 17 | - POSTGRES_MULTIPLE_EXTENSIONS=postgis,hstore,postgis_topology,postgis_raster,pgrouting 18 | - RUN_AS_ROOT=true 19 | - FORCE_SSL=TRUE 20 | restart: on-failure 21 | healthcheck: 22 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker" 23 | 24 | geoserver: 25 | image: 'kartoza/geoserver:${TAG:-manual-build}' 26 | restart: 'always' 27 | volumes: 28 | - geoserver-data-dir:/opt/geoserver/data_dir 29 | - ./tests:/tests 30 | environment: 31 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 32 | GEOSERVER_ADMIN_USER: admin 33 | INITIAL_MEMORY: 2G 34 | MAXIMUM_MEMORY: 4G 35 | HOST: db 36 | POSTGRES_DB: gwc 37 | POSTGRES_USER: docker 38 | POSTGRES_PASS: docker 39 | POSTGRES_PORT: 5432 40 | SSL_MODE: allow 41 | POSTGRES_SCHEMA: public 42 | DISK_QUOTA_SIZE: 5 43 | DB_BACKEND: POSTGRES 44 | SAMPLE_DATA: true 45 | CONSOLE_HANDLER_LEVEL: WARNING 46 | TEST_CLASS: test_disk_quota.TestGeoServerDISKQUOTA 47 | depends_on: 48 | db: 49 | condition: service_healthy 50 | ports: 51 | - "8080:8080" 52 | healthcheck: 53 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 54 | interval: 1m30s 55 | timeout: 10s 56 | retries: 3 57 | 58 | 59 | -------------------------------------------------------------------------------- /scenario_tests/disk-quota/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ${VERSION} -f docker-compose.yml up -d 11 | 12 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 13 | ${VERSION} -f docker-compose.yml logs -f & 14 | fi 15 | 16 | 17 | 18 | 19 | services=("geoserver") 20 | 21 | for service in "${services[@]}"; do 22 | 23 | # Execute tests 24 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 25 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 26 | echo -e "\e[32m ---------------------------------------- \033[0m" 27 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 28 | ${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh 29 | 30 | done 31 | 32 | ${VERSION} -f docker-compose.yml down -v 33 | -------------------------------------------------------------------------------- /scenario_tests/disk-quota/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/disk-quota/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/disk-quota/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/disk-quota/tests/test_disk_quota.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import environ 3 | from psycopg2 import connect, OperationalError 4 | 5 | 6 | class TestGeoServerDISKQUOTA(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.db_schema = environ.get('POSTGRES_SCHEMA', 'public') 10 | try: 11 | self.db_conn = connect( 12 | dbname=environ.get('POSTGRES_DB', 'gis'), 13 | user=environ.get('POSTGRES_USER', 'docker'), 14 | password=environ.get('POSTGRES_PASS', 'docker'), 15 | host=environ.get('HOST', 'db'), 16 | port=environ.get('POSTGRES_PORT', 5432), 17 | sslmode=environ.get('SSL_MODE', 'allow') 18 | ) 19 | except OperationalError as e: 20 | self.fail(f"Failed to connect to the database: {e}") 21 | 22 | def test_seed_vector_layer(self): 23 | 24 | with self.db_conn.cursor() as cursor: 25 | query = "SELECT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'tilepage' \ 26 | and table_schema = '%s');" % self.db_schema 27 | cursor.execute(query) 28 | table_exists = cursor.fetchone()[0] 29 | self.assertTrue(table_exists, "Table 'tilepage' does not exist") 30 | 31 | def tearDown(self): 32 | self.db_conn.close() 33 | 34 | 35 | if __name__ == '__main__': 36 | unittest.main() 37 | -------------------------------------------------------------------------------- /scenario_tests/gwc/docker-compose-gwc.yml: -------------------------------------------------------------------------------- 1 | 2 | 3 | volumes: 4 | geoserver-data-dir: 5 | 6 | services: 7 | 8 | geoserver: 9 | image: 'kartoza/geoserver:${TAG:-manual-build}' 10 | restart: 'always' 11 | volumes: 12 | - geoserver-data-dir:/opt/geoserver/data_dir 13 | - ./tests:/tests 14 | environment: 15 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 16 | GEOSERVER_ADMIN_USER: admin 17 | INITIAL_MEMORY: 2G 18 | MAXIMUM_MEMORY: 4G 19 | RECREATE_DATADIR: TRUE 20 | SAMPLE_DATA: true 21 | CONSOLE_HANDLER_LEVEL: WARNING 22 | TEST_CLASS: test_gwc.TestGeoServerGWC 23 | ports: 24 | - "8080:8080" 25 | healthcheck: 26 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 27 | interval: 1m30s 28 | timeout: 10s 29 | retries: 3 30 | 31 | 32 | -------------------------------------------------------------------------------- /scenario_tests/gwc/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ${VERSION} -f docker-compose-gwc.yml up -d 11 | 12 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 13 | ${VERSION} -f docker-compose-gwc.yml logs -f & 14 | fi 15 | 16 | 17 | 18 | 19 | services=("geoserver") 20 | 21 | for service in "${services[@]}"; do 22 | 23 | # Execute tests 24 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 25 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 26 | ${VERSION} -f docker-compose-gwc.yml ps 27 | echo -e "\e[32m ---------------------------------------- \033[0m" 28 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 29 | ${VERSION} -f docker-compose-gwc.yml exec $service /bin/bash /tests/test.sh 30 | 31 | done 32 | 33 | ${VERSION} -f docker-compose-gwc.yml down -v 34 | -------------------------------------------------------------------------------- /scenario_tests/gwc/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/gwc/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/gwc/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/gwc/tests/test_gwc.py: -------------------------------------------------------------------------------- 1 | import time 2 | import unittest 3 | from os import environ, remove 4 | from PIL import Image 5 | from requests import get, post 6 | from requests.auth import HTTPBasicAuth 7 | 8 | 9 | class TestGeoServerGWC(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # Define the GeoServer URL 13 | self.gs_url = 'http://localhost:8080/geoserver' 14 | self.store_name = 'states_shapefile' 15 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 16 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 17 | self.geo_workspace_name = 'topp' 18 | 19 | def test_seed_vector_layer(self): 20 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 21 | 22 | # Seed the vector layer 23 | 24 | layer_name = '%s:states' % self.geo_workspace_name 25 | gwc_url = f'{self.gs_url}/gwc/rest/seed/%s.xml' % layer_name 26 | 27 | # Set the GWC seed request parameters 28 | headers = {'Content-type': 'text/xml'} 29 | data = '%s43261' \ 30 | '6image/pngseed2' \ 31 | 'cql_filter:STATE_ABBR=\'TX\'' % layer_name 32 | 33 | post(gwc_url, headers=headers, data=data, auth=auth) 34 | 35 | time.sleep(30) 36 | wms_request = f'{self.gs_url}/ows?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=31.31110495617180689,\ 37 | -101.7342329829540404,32.41516971387711976,-99.82891832338629001&CRS=EPSG:4326&WIDTH=1564&HEIGHT=906\ 38 | &LAYERS=%s&STYLES=&FORMAT=image/png&DPI=96 &TILED=true \ 39 | &MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi:96&TRANSPARENT=TRUE' % layer_name 40 | response = get(wms_request) 41 | 42 | # Save the response as a JPEG file 43 | with open('output.png', 'wb') as f: 44 | f.write(response.content) 45 | 46 | try: 47 | img = Image.open('output.png') 48 | img.verify() 49 | valid_image = True 50 | except (IOError, Image.DecompressionBombError): 51 | valid_image = False 52 | remove('output.png') 53 | 54 | # Verify that the seeding was successful 55 | self.assertEqual(response.status_code, 200) 56 | self.assertTrue(valid_image) 57 | 58 | 59 | if __name__ == '__main__': 60 | unittest.main() 61 | -------------------------------------------------------------------------------- /scenario_tests/jdbconfig/docker-compose-postgis-jndi.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | postgis-data: 5 | 6 | 7 | services: 8 | db: 9 | image: kartoza/postgis:17-3.5 10 | volumes: 11 | - postgis-data:/var/lib/postgresql 12 | environment: 13 | - POSTGRES_DB=gis 14 | - POSTGRES_USER=docker 15 | - POSTGRES_PASS=docker 16 | - ALLOW_IP_RANGE=0.0.0.0/0 17 | - POSTGRES_MULTIPLE_EXTENSIONS=postgis,hstore,postgis_topology,postgis_raster,pgrouting 18 | - RUN_AS_ROOT=true 19 | restart: on-failure 20 | healthcheck: 21 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker" 22 | 23 | geoserver: 24 | image: 'kartoza/geoserver:${TAG:-manual-build}' 25 | restart: 'always' 26 | volumes: 27 | - geoserver-data-dir:/opt/geoserver/data_dir 28 | - ./tests:/tests 29 | environment: 30 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 31 | GEOSERVER_ADMIN_USER: admin 32 | INITIAL_MEMORY: 2G 33 | MAXIMUM_MEMORY: 4G 34 | POSTGRES_JNDI: TRUE 35 | POSTGRES_PORT: 5432 36 | HOST: db 37 | POSTGRES_DB: gis 38 | POSTGRES_USER: docker 39 | POSTGRES_PASS: docker 40 | RECREATE_DATADIR: TRUE 41 | CONSOLE_HANDLER_LEVEL: WARNING 42 | SAMPLE_DATA: true 43 | DB_BACKEND: POSTGRES 44 | COMMUNITY_EXTENSIONS: jdbcconfig-plugin,jdbcstore-plugin 45 | TEST_CLASS: test_jdbconfig.TestGeoServerJDBCONFIG 46 | depends_on: 47 | db: 48 | condition: service_healthy 49 | ports: 50 | - "8080:8080" 51 | healthcheck: 52 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 53 | interval: 1m30s 54 | timeout: 10s 55 | retries: 3 56 | 57 | 58 | -------------------------------------------------------------------------------- /scenario_tests/jdbconfig/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | postgis-data: 5 | 6 | 7 | services: 8 | db: 9 | image: kartoza/postgis:17-3.5 10 | volumes: 11 | - postgis-data:/var/lib/postgresql 12 | environment: 13 | - POSTGRES_DB=gis,gwc 14 | - POSTGRES_USER=docker 15 | - POSTGRES_PASS=docker 16 | - ALLOW_IP_RANGE=0.0.0.0/0 17 | - POSTGRES_MULTIPLE_EXTENSIONS=postgis,hstore,postgis_topology,postgis_raster,pgrouting 18 | - RUN_AS_ROOT=true 19 | - FORCE_SSL=TRUE 20 | restart: on-failure 21 | healthcheck: 22 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker" 23 | 24 | geoserver: 25 | image: 'kartoza/geoserver:${TAG:-manual-build}' 26 | restart: 'always' 27 | volumes: 28 | - geoserver-data-dir:/opt/geoserver/data_dir 29 | - ./tests:/tests 30 | environment: 31 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 32 | GEOSERVER_ADMIN_USER: admin 33 | HOST: db 34 | POSTGRES_DB: gis 35 | POSTGRES_USER: docker 36 | POSTGRES_PASS: docker 37 | POSTGRES_PORT: 5432 38 | SSL_MODE: allow 39 | POSTGRES_SCHEMA: public 40 | DISK_QUOTA_SIZE: 5 41 | DB_BACKEND: POSTGRES 42 | SAMPLE_DATA: true 43 | CONSOLE_HANDLER_LEVEL: WARNING 44 | COMMUNITY_EXTENSIONS: jdbcconfig-plugin,jdbcstore-plugin 45 | TEST_CLASS: test_jdbconfig.TestGeoServerJDBCONFIG 46 | depends_on: 47 | db: 48 | condition: service_healthy 49 | ports: 50 | - "8080:8080" 51 | healthcheck: 52 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 53 | interval: 1m30s 54 | timeout: 10s 55 | retries: 3 56 | 57 | 58 | -------------------------------------------------------------------------------- /scenario_tests/jdbconfig/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | 11 | ${VERSION} -f docker-compose.yml up -d 12 | 13 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 14 | ${VERSION} -f docker-compose.yml logs -f & 15 | fi 16 | 17 | 18 | 19 | 20 | services=("geoserver") 21 | 22 | for service in "${services[@]}"; do 23 | 24 | # Execute tests 25 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 26 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 27 | echo -e "\e[32m ---------------------------------------- \033[0m" 28 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 29 | ${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh 30 | 31 | done 32 | 33 | ${VERSION} -f docker-compose.yml down -v 34 | 35 | 36 | #JNDI 37 | ${VERSION} -f docker-compose-postgis-jndi.yml up -d 38 | 39 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 40 | ${VERSION} -f docker-compose-postgis-jndi.yml logs -f & 41 | fi 42 | 43 | 44 | 45 | 46 | services=("geoserver") 47 | 48 | for service in "${services[@]}"; do 49 | 50 | # Execute tests 51 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 52 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 53 | echo -e "\e[32m ---------------------------------------- \033[0m" 54 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 55 | ${VERSION} -f docker-compose-postgis-jndi.yml exec $service /bin/bash /tests/test.sh 56 | 57 | done 58 | 59 | ${VERSION} -f docker-compose-postgis-jndi.yml down -v -------------------------------------------------------------------------------- /scenario_tests/jdbconfig/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/jdbconfig/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/jdbconfig/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/jdbconfig/tests/test_jdbconfig.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import environ, remove 3 | from psycopg2 import connect, OperationalError 4 | from requests import get 5 | from PIL import Image 6 | 7 | 8 | class TestGeoServerJDBCONFIG(unittest.TestCase): 9 | 10 | def setUp(self): 11 | self.gs_url = 'http://localhost:8080/geoserver' 12 | try: 13 | self.db_conn = connect( 14 | dbname=environ.get('POSTGRES_DB', 'gis'), 15 | user=environ.get('POSTGRES_USER', 'docker'), 16 | password=environ.get('POSTGRES_PASS', 'docker'), 17 | host=environ.get('HOST', 'db'), 18 | port=environ.get('POSTGRES_PORT', 5432), 19 | sslmode=environ.get('SSL_MODE', 'allow') 20 | ) 21 | except OperationalError as e: 22 | self.fail(f"Failed to connect to the database: {e}") 23 | 24 | def test_seed_vector_layer(self): 25 | 26 | with self.db_conn.cursor() as cursor: 27 | query = "SELECT EXISTS (SELECT 1 FROM workspace WHERE name = 'topp');" 28 | cursor.execute(query) 29 | table_exists = cursor.fetchone()[0] 30 | self.assertTrue(table_exists, "Workspace 'topp' does not exist") 31 | wms_request = f'{self.gs_url}/ows?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=31.31110495617180689,\ 32 | -101.7342329829540404,32.41516971387711976,-99.82891832338629001&CRS=EPSG:4326&WIDTH=1564&HEIGHT=906\ 33 | &LAYERS=topp:states&STYLES=&FORMAT=image/png&DPI=96 &TILED=true \ 34 | &MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi:96&TRANSPARENT=TRUE' 35 | response = get(wms_request) 36 | with open('output.png', 'wb') as f: 37 | f.write(response.content) 38 | 39 | try: 40 | img = Image.open('output.png') 41 | img.verify() 42 | valid_image = True 43 | except (IOError, Image.DecompressionBombError): 44 | valid_image = False 45 | remove('output.png') 46 | 47 | # Verify that the seeding was successful 48 | self.assertEqual(response.status_code, 200) 49 | self.assertTrue(valid_image) 50 | 51 | def tearDown(self): 52 | self.db_conn.close() 53 | 54 | 55 | if __name__ == '__main__': 56 | unittest.main() 57 | -------------------------------------------------------------------------------- /scenario_tests/libjpeg/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | 5 | services: 6 | 7 | geoserver: 8 | image: 'kartoza/geoserver:${TAG:-manual-build}' 9 | restart: 'always' 10 | volumes: 11 | - geoserver-data-dir:/opt/geoserver/data_dir 12 | - ./tests:/tests 13 | environment: 14 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 15 | GEOSERVER_ADMIN_USER: admin 16 | INITIAL_MEMORY: 2G 17 | MAXIMUM_MEMORY: 4G 18 | SAMPLE_DATA: true 19 | CONSOLE_HANDLER_LEVEL: WARNING 20 | TEST_CLASS: test_libjpeg.TestGeoServerTURBO 21 | ports: 22 | - "8080:8080" 23 | healthcheck: 24 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 25 | interval: 1m30s 26 | timeout: 10s 27 | retries: 3 28 | 29 | 30 | -------------------------------------------------------------------------------- /scenario_tests/libjpeg/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ${VERSION} -f docker-compose.yml up -d 11 | 12 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 13 | ${VERSION} -f docker-compose.yml logs -f & 14 | fi 15 | 16 | 17 | 18 | 19 | services=("geoserver") 20 | 21 | for service in "${services[@]}"; do 22 | 23 | # Execute tests 24 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 25 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 26 | ${VERSION} -f docker-compose.yml ps 27 | echo -e "\e[32m ---------------------------------------- \033[0m" 28 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 29 | ${VERSION} -f docker-compose.yml exec $service /bin/bash /tests/test.sh 30 | 31 | done 32 | 33 | ${VERSION} -f docker-compose.yml down -v 34 | -------------------------------------------------------------------------------- /scenario_tests/libjpeg/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/libjpeg/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/libjpeg/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/libjpeg/tests/test_libjpeg.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from requests import get 3 | from parameterized import parameterized 4 | from PIL import Image 5 | from os import remove 6 | 7 | class TestGeoServerTURBO(unittest.TestCase): 8 | 9 | def setUp(self): 10 | # Define the GeoServer URL 11 | self.gs_url = 'http://localhost:8080/geoserver' 12 | self.geo_workspace_name = 'topp' 13 | 14 | @parameterized.expand([ 15 | ('jpeg',), 16 | ('vnd.jpeg-png',), 17 | ('vnd.jpeg-png8',), 18 | ]) 19 | def test_wms_vector_layer(self, output): 20 | layer_name = '%s:states' % self.geo_workspace_name 21 | wms_request = f'{self.gs_url}/ows?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&BBOX=31.31110495617180689,\ 22 | -101.7342329829540404,32.41516971387711976,-99.82891832338629001&CRS=EPSG:4326&WIDTH=1564&HEIGHT=906\ 23 | &LAYERS=%s&STYLES=&FORMAT=image/%s&DPI=96 &TILED=true \ 24 | &MAP_RESOLUTION=96&FORMAT_OPTIONS=dpi:96&TRANSPARENT=TRUE' % (layer_name, output) 25 | response = get(wms_request) 26 | 27 | # Save the response as a JPEG file 28 | with open('output.jpg', 'wb') as f: 29 | f.write(response.content) 30 | 31 | try: 32 | img = Image.open('output.jpg') 33 | img.verify() 34 | valid_image = True 35 | except (IOError, Image.DecompressionBombError): 36 | valid_image = False 37 | remove('output.jpg') 38 | # Verify that the wms request was successful 39 | self.assertEqual(response.status_code, 200) 40 | self.assertTrue(valid_image) 41 | 42 | 43 | if __name__ == '__main__': 44 | unittest.main() 45 | -------------------------------------------------------------------------------- /scenario_tests/logging_profile/assets/logging.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | GEOSERVER_DEVELOPER_LOGGING 4 | /opt/geoserver/data_dir/logs/geoserver.log 5 | true 6 | 7 | 8 | -------------------------------------------------------------------------------- /scenario_tests/logging_profile/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir-one: 4 | geoserver-data-dir-two: 5 | geoserver-data-dir-three: 6 | 7 | 8 | services: 9 | geoserver_one: 10 | image: 'kartoza/geoserver:${TAG:-manual-build}' 11 | restart: 'always' 12 | volumes: 13 | - geoserver-data-dir-one:/opt/geoserver/data_dir 14 | - ./tests:/tests 15 | - ./assets/logging.xml:/opt/geoserver/data_dir/logging.xml 16 | environment: 17 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 18 | GEOSERVER_ADMIN_USER: admin 19 | EXPECTED_LOGGING_PROFILE: GEOSERVER_DEVELOPER_LOGGING 20 | INITIAL_MEMORY: 2G 21 | MAXIMUM_MEMORY: 4G 22 | CONTAINER_NAME: geoserver_one 23 | CONSOLE_HANDLER_LEVEL: WARNING 24 | ports: 25 | - "8081:8080" 26 | healthcheck: 27 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 28 | interval: 1m30s 29 | timeout: 10s 30 | retries: 3 31 | 32 | geoserver_two: 33 | image: 'kartoza/geoserver:${TAG:-manual-build}' 34 | restart: 'always' 35 | volumes: 36 | - geoserver-data-dir-two:/opt/geoserver/data_dir 37 | - ./tests:/tests 38 | environment: 39 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 40 | GEOSERVER_ADMIN_USER: admin 41 | GEOSERVER_LOG_PROFILE: VERBOSE_LOGGING 42 | EXPECTED_LOGGING_PROFILE: VERBOSE_LOGGING 43 | INITIAL_MEMORY: 2G 44 | MAXIMUM_MEMORY: 4G 45 | CONTAINER_NAME: geoserver_two 46 | CONSOLE_HANDLER_LEVEL: WARNING 47 | ports: 48 | - "8082:8080" 49 | healthcheck: 50 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$$(cat /opt/geoserver/data_dir/security/pass.txt) http://localhost:8080/geoserver/rest/about/version.xml"] 51 | interval: 1m30s 52 | timeout: 10s 53 | retries: 3 54 | 55 | geoserver_three: 56 | image: 'kartoza/geoserver:${TAG:-manual-build}' 57 | restart: 'always' 58 | volumes: 59 | - geoserver-data-dir-three:/opt/geoserver/data_dir 60 | - ./tests:/tests 61 | environment: 62 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 63 | GEOSERVER_ADMIN_USER: admin 64 | EXPECTED_LOGGING_PROFILE: DEFAULT_LOGGING 65 | INITIAL_MEMORY: 2G 66 | MAXIMUM_MEMORY: 4G 67 | CONTAINER_NAME: geoserver_three 68 | CONSOLE_HANDLER_LEVEL: WARNING 69 | ports: 70 | - "8083:8080" 71 | healthcheck: 72 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$$(cat /opt/geoserver/data_dir/security/pass.txt) http://localhost:8080/geoserver/rest/about/version.xml"] 73 | interval: 1m30s 74 | timeout: 10s 75 | retries: 3 76 | 77 | -------------------------------------------------------------------------------- /scenario_tests/logging_profile/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ${VERSION} up -d 11 | 12 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 13 | ${VERSION} logs -f & 14 | fi 15 | 16 | services=("geoserver_one" "geoserver_two" "geoserver_three") 17 | for index in "${!services[@]}"; do 18 | read service <<< "${services[$index]}" 19 | PORT="808$((index +1))" 20 | 21 | sleep 30 22 | test_url_availability http://localhost:$PORT/geoserver/rest/about/version.xml 23 | echo "Execute test for $service" 24 | ${VERSION} exec -T $service /bin/bash /tests/test.sh 25 | 26 | done 27 | 28 | ${VERSION} down -v -------------------------------------------------------------------------------- /scenario_tests/logging_profile/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source /scripts/env-data.sh 4 | 5 | set -euo pipefail 6 | 7 | # Ensure EXPECTED is set 8 | : "${EXPECTED_LOGGING_PROFILE:?EXPECTED_LOGGING_PROFILE environment variable must be set}" 9 | 10 | # Extract value between ... using sed 11 | level=$(sed -n 's:.*\(.*\).*:\1:p' "${GEOSERVER_DATA_DIR}"/logging.xml) 12 | 13 | # Compare and fail if not equal 14 | if [[ "$level" != "$EXPECTED_LOGGING_PROFILE" ]]; then 15 | echo "ERROR: Logging profile level mismatch at $CONTAINER_NAME. Found: '$level', EXPECTED_LOGGING_PROFILE: '$EXPECTED_LOGGING_PROFILE'" >&2 16 | exit 1 17 | fi 18 | 19 | echo "PASS: Test case passed at $CONTAINER_NAME. Logging profile level matches EXPECTED_LOGGING_PROFILE value: $level" 20 | -------------------------------------------------------------------------------- /scenario_tests/logging_profile/version.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 03-Apr-2025 22:47 4 | 2.27.0 5 | 22e0b4aa0f2bc5f01c649ba0418ba3242c5fcbf0 6 | 7 | 8 | 02-Apr-2025 15:59 9 | 33.0 10 | 2f4be07eaece931a7f6f3cd2b903a95e4ef3a41f 11 | 12 | 13 | 1.27.0 14 | 230de11bf247f7e6ac994c7383ba6b4958fddcdf/230de11bf247f7e6ac994c7383ba6b4958fddcdf 15 | 16 | -------------------------------------------------------------------------------- /scenario_tests/login/docker-compose.yml: -------------------------------------------------------------------------------- 1 | 2 | services: 3 | geoserver: 4 | image: 'kartoza/geoserver:${TAG:-manual-build}' 5 | restart: 'always' 6 | volumes: 7 | - ./tests:/tests 8 | environment: 9 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 10 | GEOSERVER_ADMIN_USER: admin 11 | INITIAL_MEMORY: 2G 12 | MAXIMUM_MEMORY: 4G 13 | CONTAINER_NAME: geoserver 14 | CONSOLE_HANDLER_LEVEL: WARNING 15 | TEST_CLASS: test_login.TestGeoServerREST 16 | ports: 17 | - "8081:8080" 18 | healthcheck: 19 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 20 | interval: 1m30s 21 | timeout: 10s 22 | retries: 3 23 | 24 | server: 25 | image: 'kartoza/geoserver:${TAG:-manual-build}' 26 | restart: 'always' 27 | volumes: 28 | - ./tests:/tests 29 | environment: 30 | GEOSERVER_ADMIN_USER: admin 31 | INITIAL_MEMORY: 2G 32 | MAXIMUM_MEMORY: 4G 33 | CONTAINER_NAME: server 34 | CONSOLE_HANDLER_LEVEL: WARNING 35 | TEST_CLASS: test_login.TestGeoServerREST 36 | ports: 37 | - "8082:8080" 38 | healthcheck: 39 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$$(cat /opt/geoserver/data_dir/security/pass.txt) http://localhost:8080/geoserver/rest/about/version.xml"] 40 | interval: 1m30s 41 | timeout: 10s 42 | retries: 3 43 | 44 | credentials: 45 | image: 'kartoza/geoserver:${TAG:-manual-build}' 46 | restart: 'always' 47 | volumes: 48 | - ./tests:/tests 49 | environment: 50 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 51 | GEOSERVER_ADMIN_USER: myadmin 52 | INITIAL_MEMORY: 2G 53 | MAXIMUM_MEMORY: 4G 54 | CONTAINER_NAME: credentials 55 | CONSOLE_HANDLER_LEVEL: WARNING 56 | TEST_CLASS: test_login.TestGeoServerREST 57 | ports: 58 | - "8083:8080" 59 | healthcheck: 60 | test: [ "CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml" ] 61 | interval: 1m30s 62 | timeout: 10s 63 | retries: 3 64 | 65 | -------------------------------------------------------------------------------- /scenario_tests/login/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | ${VERSION} up -d 11 | 12 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 13 | ${VERSION} logs -f & 14 | fi 15 | 16 | 17 | services=("geoserver" "server" "credentials") 18 | START_PORT=8081 19 | 20 | for i in "${!services[@]}"; do 21 | service="${services[$i]}" 22 | PORT=$((START_PORT + i)) 23 | 24 | # Set default values 25 | PASS="myawesomegeoserver" 26 | USER="admin" 27 | 28 | # Service-specific overrides 29 | if [[ "$service" == "server" ]]; then 30 | PASS=$(docker compose exec server cat /opt/geoserver/data_dir/security/pass.txt) 31 | elif [[ "$service" == "credentials" ]]; then 32 | USER="myadmin" 33 | fi 34 | 35 | sleep 30 36 | echo -e "[Unit Test] Test URL availability for: \e[1;31m $service \033[0m" 37 | test_url_availability "http://localhost:$PORT/geoserver/rest/about/version.xml" "$PASS" "$USER" 38 | 39 | echo -e "\e[32m ---------------------------------------- \033[0m" 40 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 41 | ${VERSION} exec -T "$service" /bin/bash /tests/test.sh 42 | done 43 | 44 | ${VERSION} down -v 45 | 46 | -------------------------------------------------------------------------------- /scenario_tests/login/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/login/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/login/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/login/tests/test_login.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import unittest 3 | from os import environ 4 | 5 | 6 | class TestGeoServerREST(unittest.TestCase): 7 | 8 | def setUp(self): 9 | # Login to GeoServer and get the authentication cookies 10 | self.base_url = 'http://localhost:8080/geoserver' 11 | self.login_url = f'{self.base_url}/j_spring_security_check' 12 | self.container_name = environ['CONTAINER_NAME'] 13 | 14 | if self.container_name == 'geoserver': 15 | self.password = environ['GEOSERVER_ADMIN_PASSWORD'] 16 | self.username = 'admin' 17 | elif self.container_name == 'credentials': 18 | self.password = environ['GEOSERVER_ADMIN_PASSWORD'] 19 | self.username = 'myadmin' 20 | elif self.container_name == 'server': 21 | self.username = 'admin' 22 | with open('/opt/geoserver/data_dir/security/pass.txt', 'r') as file: 23 | file_pass = file.read() 24 | self.password = file_pass.replace("\n", "") 25 | self.session = requests.Session() 26 | login_data = { 27 | 'username': self.username, 28 | 'password': self.password, 29 | 'submit': 'Login' 30 | } 31 | response = self.session.post(self.login_url, data=login_data) 32 | self.assertEqual(response.status_code, 200) 33 | 34 | def test_rest_endpoints_accessible(self): 35 | # Test if the REST endpoints are accessible as a logged user 36 | url = f'{self.base_url}/rest/workspaces.json' 37 | response = self.session.get(url) 38 | self.assertEqual(response.status_code, 200) 39 | self.assertTrue(response.json()) 40 | 41 | def tearDown(self): 42 | # Logout from GeoServer 43 | logout_url = f'{self.base_url}/j_spring_security_logout' 44 | response = self.session.post(logout_url) 45 | self.assertEqual(response.status_code, 200) 46 | -------------------------------------------------------------------------------- /scenario_tests/stores/docker-compose-gdal.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | 5 | services: 6 | 7 | geoserver: 8 | image: 'kartoza/geoserver:${TAG:-manual-build}' 9 | restart: 'always' 10 | volumes: 11 | - geoserver-data-dir:/opt/geoserver/data_dir 12 | - ./tests:/tests 13 | environment: 14 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 15 | GEOSERVER_ADMIN_USER: admin 16 | CONSOLE_HANDLER_LEVEL: WARNING 17 | TEST_CLASS: test_gdal.TestGeoServerGDAL 18 | ports: 19 | - "8080:8080" 20 | healthcheck: 21 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 22 | interval: 1m30s 23 | timeout: 10s 24 | retries: 3 25 | 26 | 27 | -------------------------------------------------------------------------------- /scenario_tests/stores/docker-compose-postgis-jndi.yml: -------------------------------------------------------------------------------- 1 | 2 | volumes: 3 | geoserver-data-dir: 4 | postgis-data: 5 | 6 | 7 | services: 8 | db: 9 | image: kartoza/postgis:17-3.5 10 | volumes: 11 | - postgis-data:/var/lib/postgresql 12 | environment: 13 | - POSTGRES_DB=gis 14 | - POSTGRES_USER=docker 15 | - POSTGRES_PASS=docker 16 | - ALLOW_IP_RANGE=0.0.0.0/0 17 | - POSTGRES_MULTIPLE_EXTENSIONS=postgis,hstore,postgis_topology,postgis_raster,pgrouting 18 | - RUN_AS_ROOT=true 19 | restart: on-failure 20 | healthcheck: 21 | test: "PGPASSWORD=docker pg_isready -h 127.0.0.1 -U docker" 22 | 23 | geoserver: 24 | image: 'kartoza/geoserver:${TAG:-manual-build}' 25 | restart: 'always' 26 | volumes: 27 | - geoserver-data-dir:/opt/geoserver/data_dir 28 | - ./tests:/tests 29 | environment: 30 | GEOSERVER_ADMIN_PASSWORD: myawesomegeoserver 31 | GEOSERVER_ADMIN_USER: admin 32 | INITIAL_MEMORY: 2G 33 | MAXIMUM_MEMORY: 4G 34 | POSTGRES_JNDI: TRUE 35 | HOST: db 36 | POSTGRES_DB: gis 37 | POSTGRES_USER: docker 38 | POSTGRES_PASS: docker 39 | RECREATE_DATADIR: TRUE 40 | CONSOLE_HANDLER_LEVEL: WARNING 41 | TEST_CLASS: test_jndi.TestGeoServerJNDI 42 | depends_on: 43 | db: 44 | condition: service_healthy 45 | ports: 46 | - "8080:8080" 47 | healthcheck: 48 | test: ["CMD-SHELL", "curl --fail --silent --write-out 'HTTP CODE : %{http_code}\n' --output /dev/null -u $${GEOSERVER_ADMIN_USER}:$${GEOSERVER_ADMIN_PASSWORD} http://localhost:8080/geoserver/rest/about/version.xml"] 49 | interval: 1m30s 50 | timeout: 10s 51 | retries: 3 52 | 53 | 54 | -------------------------------------------------------------------------------- /scenario_tests/stores/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # exit immediately if test fails 4 | set -e 5 | 6 | source ../test-env.sh 7 | 8 | # Run service 9 | 10 | 11 | # JNDI store 12 | ${VERSION} -f docker-compose-postgis-jndi.yml up -d 13 | 14 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 15 | ${VERSION} -f docker-compose-postgis-jndi.yml logs -f & 16 | fi 17 | 18 | 19 | 20 | services=("geoserver") 21 | 22 | for service in "${services[@]}"; do 23 | 24 | # Execute tests 25 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 26 | echo -e "\e[32m ---------------------------------------- \033[0m" 27 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 28 | ${VERSION} -f docker-compose-postgis-jndi.yml exec $service /bin/bash /tests/test.sh 29 | 30 | done 31 | 32 | ${VERSION} -f docker-compose-postgis-jndi.yml down -v 33 | 34 | # Run GDAL 35 | ${VERSION} -f docker-compose-gdal.yml up -d 36 | 37 | if [[ -n "${PRINT_TEST_LOGS}" ]]; then 38 | ${VERSION} -f docker-compose-gdal.yml logs -f & 39 | fi 40 | 41 | 42 | 43 | 44 | services=("geoserver") 45 | 46 | for service in "${services[@]}"; do 47 | 48 | # Execute tests 49 | test_url_availability http://localhost:8080/geoserver/rest/about/version.xml 50 | echo -e "\e[32m ---------------------------------------- \033[0m" 51 | echo -e "[Unit Test] Execute test for: \e[1;31m $service \033[0m" 52 | ${VERSION} -f docker-compose-gdal.yml exec $service /bin/bash /tests/test.sh 53 | 54 | done 55 | 56 | ${VERSION} -f docker-compose-gdal.yml down -v 57 | -------------------------------------------------------------------------------- /scenario_tests/stores/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kartoza/docker-geoserver/664140445e0e1591662734410663450553b650fb/scenario_tests/stores/tests/__init__.py -------------------------------------------------------------------------------- /scenario_tests/stores/tests/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | source /scripts/env-data.sh 6 | 7 | # execute tests 8 | pushd /tests 9 | 10 | cat << EOF 11 | Settings used: 12 | 13 | GEOSERVER_ADMIN_PASSWORD: ${GEOSERVER_ADMIN_PASSWORD} 14 | GEOSERVER_ADMIN_USER: ${GEOSERVER_ADMIN_USER} 15 | EOF 16 | 17 | python3 -m unittest -v ${TEST_CLASS} 18 | -------------------------------------------------------------------------------- /scenario_tests/stores/tests/test_gdal.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import environ, chown 3 | from subprocess import check_call 4 | from requests import get, post, exceptions 5 | from requests.auth import HTTPBasicAuth 6 | from geo.Geoserver import Geoserver 7 | 8 | 9 | class TestGeoServerGDAL(unittest.TestCase): 10 | 11 | def setUp(self): 12 | # Define the GeoServer URL 13 | self.gs_url = 'http://localhost:8080/geoserver' 14 | self.store_name = 'sfdem' 15 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 16 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 17 | self.geo_workspace_name = 'kartoza' 18 | self.geo_data_dir = '/usr/local/tomcat/data/data/sf' 19 | 20 | def test_publish_gdal_store(self): 21 | # Generate tiles 22 | built_vrt = f'gdalbuildvrt {self.geo_data_dir}/sfdem.vrt {self.geo_data_dir}/sfdem.tif' 23 | check_call(built_vrt, shell=True) 24 | vrt_path = f'{self.geo_data_dir}/sfdem.vrt' 25 | chown(vrt_path, 1000, 1000) 26 | 27 | geo = Geoserver(self.gs_url, username=self.geo_username, password=self.geo_password) 28 | 29 | auth = HTTPBasicAuth(self.geo_username, self.geo_password) 30 | 31 | # Create a workspace if it doesn't exist 32 | 33 | geo.create_workspace(workspace=self.geo_workspace_name) 34 | geo.set_default_workspace(self.geo_workspace_name) 35 | 36 | # Create a GDAL store 37 | store_data = f''' 38 | 39 | {self.store_name} 40 | {self.geo_workspace_name} 41 | true 42 | VRT 43 | 44 | ''' 45 | store_url = f'{self.gs_url}/rest/workspaces/{self.geo_workspace_name}/coveragestores' 46 | response = post(store_url, data=store_data, auth=auth, headers={'Content-Type': 'application/xml'}) 47 | self.assertEqual(response.status_code, 201) 48 | 49 | # Upload the VRT file to the store 50 | vrt_upload_url = f'{self.gs_url}/rest/workspaces/{self.geo_workspace_name}/coveragestores/{self.store_name}/external.vrt?configure=first&coverageName={self.store_name}' 51 | curl_command = f'curl -u {self.geo_username}:{self.geo_password} -v -XPUT -H "Content-type: text/plain" -d "file:{vrt_path}" {vrt_upload_url}' 52 | check_call(curl_command, shell=True) 53 | 54 | # Check that the published layer exists 55 | layer_source_url = f'{self.gs_url}/{self.geo_workspace_name}/wms?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&FORMAT=image/jpeg&TRANSPARENT=true&STYLES&LAYERS={self.geo_workspace_name}:{self.store_name}&exceptions=application/vnd.ogc.se_inimage&SRS=EPSG:26713&WIDTH=768&HEIGHT=578&BBOX=594739.7048312925,4919224.415741393,602069.4450795503,4924731.264860202' 56 | response = get(layer_source_url) 57 | 58 | # Check that the response has a status code of 200 (OK) 59 | self.assertEqual(response.status_code, 200) 60 | 61 | 62 | if __name__ == '__main__': 63 | unittest.main() 64 | -------------------------------------------------------------------------------- /scenario_tests/stores/tests/test_jndi.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from os import environ 3 | 4 | from geo.Geoserver import Geoserver 5 | from requests import get, post, exceptions, delete 6 | from requests.auth import HTTPBasicAuth 7 | from subprocess import check_call 8 | 9 | 10 | class TestGeoServerJNDI(unittest.TestCase): 11 | 12 | def setUp(self): 13 | # Define the GeoServer URL 14 | self.gs_url = 'http://localhost:8080/geoserver' 15 | # Define the PostGIS JNDI store name 16 | self.jndi_store_name = 'gis' 17 | self.geo_username = environ.get('GEOSERVER_ADMIN_USER', 'admin') 18 | self.geo_password = environ.get('GEOSERVER_ADMIN_PASSWORD', 'myawesomegeoserver') 19 | self.geo_workspace_name = 'demo' 20 | 21 | def test_publish_jndi_store(self): 22 | 23 | # Import shp into DB 24 | db_importer = '''ogr2ogr -progress -append -skipfailures -a_srs "EPSG:4326" -nlt PROMOTE_TO_MULTI \ 25 | -f "PostgreSQL" PG:"dbname=gis port=5432 user=docker password=docker host=db" \ 26 | /usr/local/tomcat/data/data/shapefiles/states.shp ''' 27 | check_call(db_importer, shell=True) 28 | 29 | geo = Geoserver(self.gs_url, username='%s' % self.geo_username, password='%s' % self.geo_password) 30 | 31 | auth = HTTPBasicAuth('%s' % self.geo_username, '%s' % self.geo_password) 32 | # create workspace 33 | geo.create_workspace(workspace='%s' % self.geo_workspace_name) 34 | geo.set_default_workspace('%s' % self.geo_workspace_name) 35 | 36 | # Create the XML payload for the JNDI store configuration 37 | xml = """ 38 | 39 | {name} 40 | PostGIS (JNDI) 41 | true 42 | 43 | public 44 | true 45 | 1000 46 | true 47 | false 48 | true 49 | 1 50 | false 51 | FAST 52 | java:comp/env/jdbc/postgres 53 | postgis 54 | true 55 | 56 | false 57 | 58 | """.format(name=self.jndi_store_name) 59 | 60 | # Publish the JNDI store 61 | response = post(self.gs_url + '/rest/workspaces/%s/datastores' % self.geo_workspace_name, auth=auth, 62 | headers={'Content-type': 'text/xml'}, 63 | data=xml) 64 | 65 | # Publish layer into geoserver 66 | geo.publish_featurestore(workspace='%s' 67 | % self.geo_workspace_name, store_name='%s' % self.jndi_store_name, 68 | pg_table='states') 69 | # Check that the response has a status code of 201 (Created) 70 | self.assertEqual(response.status_code, 201) 71 | 72 | # Check that the JNDI store exists 73 | data_source_url = '%s/rest/workspaces/%s/datastores/%s.json' % ( 74 | self.gs_url, self.geo_workspace_name, self.jndi_store_name) 75 | response = get(data_source_url, auth=auth) 76 | 77 | # Check that the response has a status code of 200 (OK) 78 | self.assertEqual(response.status_code, 200) 79 | 80 | 81 | if __name__ == '__main__': 82 | unittest.main() 83 | -------------------------------------------------------------------------------- /scenario_tests/test-env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Display test environment variable 4 | 5 | cat << EOF 6 | Test environment: 7 | 8 | Compose Project : ${COMPOSE_PROJECT_NAME} 9 | Compose File : ${COMPOSE_PROJECT_FILE} 10 | Image tag : ${TAG} 11 | 12 | EOF 13 | 14 | 15 | export VERSION='docker compose' 16 | 17 | 18 | function test_url_availability() { 19 | URL=$1 20 | PASS=$2 21 | USERNAME=$3 22 | if [ -z "$2" ]; then 23 | PASS=myawesomegeoserver 24 | fi 25 | if [ -z "$2" ]; then 26 | USERNAME=admin 27 | fi 28 | timeout=300 29 | start_time=$(date +%s) 30 | 31 | while true; do 32 | current_time=$(date +%s) 33 | elapsed_time=$((current_time - start_time)) 34 | 35 | if [ $elapsed_time -ge $timeout ]; then 36 | echo "Timeout reached. Exiting trying to connect to service endpoint." 37 | exit 1 38 | fi 39 | 40 | 41 | 42 | result=$(wget -S --user ${USERNAME} --password ${PASS} --max-redirect=0 ${URL} 2>&1 | grep "HTTP/1.1 " | tail -n 1 | awk '{print $2}') 43 | 44 | if [[ $result -eq 200 ]]; then 45 | echo "Rest endpoint ${URL} is accessible with the provided credentials ${USERNAME} and password ${PASS}" 46 | if [[ -f version.xml ]];then 47 | rm version.xml 48 | fi 49 | break 50 | else 51 | echo "Access to ${URL}, with credentials username ${USERNAME} and password ${PASS} did not succeed, retrying in 5 seconds" 52 | sleep 5 53 | fi 54 | done 55 | 56 | } 57 | 58 | 59 | -------------------------------------------------------------------------------- /scenario_tests/utils/requirements.txt: -------------------------------------------------------------------------------- 1 | geoserver-rest 2 | psycopg2-binary 3 | requests 4 | parameterized 5 | pillow 6 | -------------------------------------------------------------------------------- /scripts/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Download geoserver extensions and other resources 3 | 4 | source /scripts/env-data.sh 5 | source /scripts/functions.sh 6 | 7 | resources_dir="/tmp/resources" 8 | GS_VERSION=$(cat /scripts/geoserver_version.txt) 9 | create_dir ${resources_dir}/plugins/gdal 10 | create_dir /usr/share/fonts/opentype 11 | create_dir /tomcat_apps 12 | create_dir "${CATALINA_HOME}"/postgres_config 13 | create_dir "${STABLE_PLUGINS_DIR}" 14 | create_dir "${COMMUNITY_PLUGINS_DIR}" 15 | create_dir "${GEOSERVER_HOME}" 16 | create_dir "${FONTS_DIR}" 17 | create_dir "${REQUIRED_PLUGINS_DIR}" 18 | 19 | pushd "${CATALINA_HOME}" || exit 20 | 21 | 22 | # Download geoserver and install it 23 | package_geoserver 24 | 25 | # Copy config files 26 | cp /build_data/stable_plugins.txt "${STABLE_PLUGINS_DIR}" 27 | cp /build_data/community_plugins.txt "${COMMUNITY_PLUGINS_DIR}" 28 | cp /build_data/letsencrypt-tomcat.xsl "${CATALINA_HOME}"/conf/ssl-tomcat.xsl 29 | 30 | pushd "${STABLE_PLUGINS_DIR}" || exit 31 | 32 | # Install libjpeg-turbo 33 | system_architecture=$(dpkg --print-architecture) 34 | # Fixes https://github.com/kartoza/docker-geoserver/issues/673 35 | libjpeg_version=2.1.5.1 36 | libjpeg_deb_name="libjpeg-turbo-official_${libjpeg_version}_${system_architecture}.deb" 37 | libjpeg_deb="${resources_dir}/${libjpeg_deb_name}" 38 | if [[ ! -f "${libjpeg_deb}" ]]; then 39 | curl -vfLo "${libjpeg_deb}" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/${libjpeg_version}/${libjpeg_deb_name}" 40 | fi 41 | 42 | dpkg -i "${libjpeg_deb}" 43 | 44 | pushd "${CATALINA_HOME}" || exit 45 | 46 | # Install Marlin render https://www.geocat.net/docs/geoserver-enterprise/2020.5/install/production/marlin.html 47 | cp ${REQUIRED_PLUGINS_DIR}/marlin.jar ${CATALINA_HOME}/lib/marlin.jar 48 | 49 | # Install jetty-servlets 50 | if [[ -f ${GEOSERVER_HOME}/start.jar ]]; then 51 | cp ${REQUIRED_PLUGINS_DIR}/jetty-servlets-11.0.9.jar "${GEOSERVER_HOME}"/webapps/"${GEOSERVER_CONTEXT_ROOT}"/WEB-INF/lib/ 52 | fi 53 | 54 | # Install jetty-util 55 | if [[ -f ${GEOSERVER_HOME}/start.jar ]]; then 56 | cp ${REQUIRED_PLUGINS_DIR}/jetty-util.jar "${GEOSERVER_HOME}"/webapps/"${GEOSERVER_CONTEXT_ROOT}"/WEB-INF/lib/ 57 | fi 58 | 59 | # Overlay files and directories in resources/overlays if they exist 60 | rm -f /tmp/resources/overlays/README.txt && 61 | if ls /tmp/resources/overlays/* >/dev/null 2>&1; then 62 | cp -rf /tmp/resources/overlays/* / 63 | fi 64 | 65 | 66 | # Package tomcat webapps - useful to activate later 67 | if [[ -d "${CATALINA_HOME}"/webapps.dist ]]; then 68 | mv "${CATALINA_HOME}"/webapps.dist /tomcat_apps 69 | zip -r "${REQUIRED_PLUGINS_DIR}"/tomcat_apps.zip /tomcat_apps 70 | rm -r /tomcat_apps 71 | else 72 | cp -r "${CATALINA_HOME}"/webapps/ROOT /tomcat_apps 73 | cp -r "${CATALINA_HOME}"/webapps/docs /tomcat_apps 74 | cp -r "${CATALINA_HOME}"/webapps/examples /tomcat_apps 75 | cp -r "${CATALINA_HOME}"/webapps/host-manager /tomcat_apps 76 | cp -r "${CATALINA_HOME}"/webapps/manager /tomcat_apps 77 | zip -r "${REQUIRED_PLUGINS_DIR}"/tomcat_apps.zip /tomcat_apps 78 | rm -rf /tomcat_apps 79 | fi 80 | 81 | pushd ${CATALINA_HOME}/lib || exit 82 | create_dir org/apache/catalina/util/ && \ 83 | unzip -j catalina.jar org/apache/catalina/util/ServerInfo.properties -d org/apache/catalina/util/ && \ 84 | sed -i 's/server.info=.*/server.info=Apache Tomcat/g' org/apache/catalina/util/ServerInfo.properties && \ 85 | zip -ur catalina.jar org/apache/catalina/util/ServerInfo.properties && rm -rf org 86 | # Setting restrictive umask container-wide 87 | echo "session optional pam_umask.so" >> /etc/pam.d/common-session && \ 88 | sed -i 's/UMASK.*022/UMASK 007/g' /etc/login.defs 89 | 90 | pushd /scripts || exit 91 | # Delete resources after installation 92 | rm -rf /tmp/resources 93 | 94 | # Delete resources which will be setup on first run 95 | delete_file "${CATALINA_HOME}"/conf/web.xml -------------------------------------------------------------------------------- /scripts/update_passwords.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Credits https://github.com/geosolutions-it/docker-geoserver for this script that allows a user to pass a password 4 | # or username on runtime. 5 | 6 | # Source the functions from other bash scripts 7 | 8 | source /scripts/env-data.sh 9 | source /scripts/functions.sh 10 | 11 | # Setup install directory 12 | GEOSERVER_INSTALL_DIR="$(detect_install_dir)" 13 | 14 | 15 | 16 | if [[ "${USE_DEFAULT_CREDENTIALS}" =~ [Ff][Aa][Ll][Ss][Ee] ]]; then 17 | USERS_XML=${USERS_XML:-${GEOSERVER_DATA_DIR}/security/usergroup/default/users.xml} 18 | ROLES_XML=${ROLES_XML:-${GEOSERVER_DATA_DIR}/security/role/default/roles.xml} 19 | CLASSPATH=${CLASSPATH:-${GEOSERVER_INSTALL_DIR}/webapps/${GEOSERVER_CONTEXT_ROOT}/WEB-INF/lib/} 20 | 21 | function password_reset() { 22 | if [[ ! -f ${EXTRA_CONFIG_DIR}/.security.lock ]];then 23 | cp -r ${CATALINA_HOME}/security ${GEOSERVER_DATA_DIR} 24 | sed -i '/false<\/readOnly>/a false<\/loginEnabled>' ${GEOSERVER_DATA_DIR}/security/config.xml 25 | touch ${EXTRA_CONFIG_DIR}/.security.lock 26 | else 27 | create_dir ${GEOSERVER_DATA_DIR}/security 28 | cp -r ${CATALINA_HOME}/security/role ${GEOSERVER_DATA_DIR}/security/ 29 | cp -r ${CATALINA_HOME}/security/usergroup ${GEOSERVER_DATA_DIR}/security/ 30 | cp -r ${CATALINA_HOME}/security/config.xml ${GEOSERVER_DATA_DIR}/security/ 31 | fi 32 | 33 | # Set random password if none provided 34 | file_env 'GEOSERVER_ADMIN_PASSWORD' 35 | if [[ -z ${GEOSERVER_ADMIN_PASSWORD} ]]; then 36 | generate_random_string 15 37 | GEOSERVER_ADMIN_PASSWORD=${RAND} 38 | echo $GEOSERVER_ADMIN_PASSWORD >${GEOSERVER_DATA_DIR}/security/pass.txt 39 | if [[ ${SHOW_PASSWORD} =~ [Tt][Rr][Uu][Ee] ]];then 40 | echo -e "\e[32m -------------------------------------------------------------------------------- \033[0m" 41 | echo -e "[Entrypoint] GENERATED GeoServer Random PASSWORD is: \e[1;31m $GEOSERVER_ADMIN_PASSWORD \033[0m" 42 | fi 43 | echo "GEOSERVER_ADMIN_PASSWORD" >> /tmp/set_vars.txt 44 | unset RAND 45 | fi 46 | 47 | # Get current GeoServer admin user 48 | file_env GEOSERVER_ADMIN_USER 49 | 50 | 51 | export GEOSERVER_ADMIN_DEFAULT_USER='admin' 52 | 53 | 54 | # Get encrypted admin password 55 | #export GEOSERVER_ADMIN_DEFAULT_ENCRYPTED_PASSWORD="$(sed -n 's/.*password="\([^"]*\)".*/\1/p' ${USERS_XML})" 56 | 57 | export PWD_HASH=$(make_hash $GEOSERVER_ADMIN_PASSWORD $CLASSPATH $HASHING_ALGORITHM) 58 | ESCAPED_GEOSERVER_ADMIN_USER=$(printf '%s\n' "$GEOSERVER_ADMIN_USER" | sed 's/[&/\]/\\&/g') 59 | ESCAPED_PWD_HASH=$(printf '%s\n' "$PWD_HASH" | sed 's/[&/\]/\\&/g') 60 | sed -i "s/name=\"[^\"]*\"/name=\"$ESCAPED_GEOSERVER_ADMIN_USER\"/; s/password=\"[^\"]*\"/password=\"$ESCAPED_PWD_HASH\"/" $USERS_XML 61 | 62 | # Set password encoding 63 | sed -i 's/pbePasswordEncoder/strongPbePasswordEncoder/g' ${GEOSERVER_DATA_DIR}/security/config.xml 64 | 65 | # roles.xml setup 66 | cp $ROLES_XML $ROLES_XML.orig 67 | # 68 | cat $ROLES_XML.orig | sed -e "s/ username=\"${GEOSERVER_ADMIN_DEFAULT_USER}\"/ username=\"${GEOSERVER_ADMIN_USER}\"/" > $ROLES_XML 69 | 70 | 71 | } # end password reset 72 | 73 | if [[ -f ${USERS_XML} ]]; then 74 | user_count=$(grep -o '