From 5c491a25cfe903d48b4da82b37e363722fbb90f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=81lvaro?= Date: Wed, 16 Dec 2020 16:32:32 +0100 Subject: [PATCH] Use env vars and fix tests --- .github/workflows/main.yml | 55 ++ .github/workflows/master.yml | 40 + .gitignore | 1 - .travis.yml | 63 -- README.md | 28 +- app.js | 7 +- config/environments/config.js | 411 +++++++++ docker/Dockerfile-nodejs-xenial-pg101:latest | 92 -- docker/Dockerfile-nodejs-xenial-pg1121:latest | 85 -- docker/reference.md | 33 - docker/scripts/nodejs-install.sh | 13 - docker/scripts/test-setup.sh | 14 - lib/api/api-router.js | 2 +- package-lock.json | 822 ++++++++++++++++++ package.json | 4 +- test/acceptance/multilayer-test.js | 6 +- test/acceptance/rate-limit-test.js | 18 +- test/acceptance/templates-test.js | 6 +- test/index.js | 35 +- .../analysis-backend-limits-test.js | 6 +- test/integration/template-maps-limits-test.js | 6 +- test/support/test-helper.js | 22 +- test/unit/ported/windshaft-server-test.js | 2 +- 23 files changed, 1434 insertions(+), 337 deletions(-) create mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/master.yml delete mode 100644 .travis.yml create mode 100644 config/environments/config.js delete mode 100644 docker/Dockerfile-nodejs-xenial-pg101:latest delete mode 100644 docker/Dockerfile-nodejs-xenial-pg1121:latest delete mode 100644 docker/reference.md delete mode 100644 docker/scripts/nodejs-install.sh delete mode 100644 docker/scripts/test-setup.sh diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..ddf9c97d --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,55 @@ +name: continuous integration +on: + pull_request: + paths-ignore: + - 'LICENSE' + - 'README**' + - 'HOW_TO_RELEASE**' + - 'LOGGING**' + +env: + GCLOUD_VERSION: '306.0.0' + ARTIFACTS_PROJECT_ID: cartodb-on-gcp-main-artifacts + +jobs: + build-node: + runs-on: ubuntu-18.04 + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v2 + + - name: Build image + # we tag with "latest" but we don't push it on purpose. We use it as a base for the testing image + run: | + echo ${GITHUB_SHA::7} + echo ${GITHUB_REF##*/} + docker build -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:latest -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_REF##*/} -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_SHA::7} -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_REF##*/}--${GITHUB_SHA::7} . + + - name: Build testing image + # here it uses the lastest from prev step to add the needed parts on top + run: | + docker build -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft-test:latest -f Dockerfile.test . + + - name: Setup gcloud authentication + uses: google-github-actions/setup-gcloud@master + with: + version: ${{env.GCLOUD_VERSION}} + service_account_key: ${{ secrets.ARTIFACTS_GCLOUD_ACCOUNT_BASE64 }} + + - name: Configure docker and pull images + # we pull images manually, as if done in next step using docker-compose it fails because missing openssl + run: | + gcloud auth configure-docker + docker pull gcr.io/cartodb-on-gcp-main-artifacts/postgres:latest + docker pull gcr.io/cartodb-on-gcp-main-artifacts/redis:latest + + - name: Run tests inside container + run: docker-compose -f ci/docker-compose.yml run windshaft-tests + + - name: Upload image + run: | + docker push gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_REF##*/} + docker push gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_SHA::7} + docker push gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_REF##*/}--${GITHUB_SHA::7} + \ No newline at end of file diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml new file mode 100644 index 00000000..e9a1cf92 --- /dev/null +++ b/.github/workflows/master.yml @@ -0,0 +1,40 @@ +# in this workflow we don't run the tests. Only build image, tag (also latests) and upload. The tests are not run because they are run +# on each pull request, and there is a branch protection that forces to have branch up to date before merging, so tests are always run +# with the latest code + +name: master build image +on: + push: + branches: + - master + +env: + GCLOUD_VERSION: '306.0.0' + ARTIFACTS_PROJECT_ID: cartodb-on-gcp-main-artifacts + +jobs: + build-node: + runs-on: ubuntu-18.04 + timeout-minutes: 5 + + steps: + - uses: actions/checkout@v2 + + - name: Build image + run: | + echo ${GITHUB_SHA::7} + echo ${GITHUB_REF##*/} + docker build -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:latest -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_REF##*/} -t gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_SHA::7} . + + - name: Setup gcloud authentication + uses: google-github-actions/setup-gcloud@master + with: + version: ${{env.GCLOUD_VERSION}} + service_account_key: ${{ secrets.ARTIFACTS_GCLOUD_ACCOUNT_BASE64 }} + + - name: Upload image + run: | + docker push gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_REF##*/} + docker push gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:${GITHUB_SHA::7} + docker push gcr.io/$ARTIFACTS_PROJECT_ID/windshaft:latest + \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7a2934c7..20975b84 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,5 @@ redis.pid coverage/ .DS_Store .nyc_output -Dockerfile* build_resources/ .dockerignore diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3acebfc6..00000000 --- a/.travis.yml +++ /dev/null @@ -1,63 +0,0 @@ -sudo: false - -language: node_js - -services: - - redis-server - -env: - global: - - PGUSER=postgres - - PGDATABASE=postgres - - PGOPTIONS='-c client_min_messages=NOTICE' - -jobs: - include: - - env: POSTGRESQL_VERSION="10" POSTGIS_VERSION="2.4" - dist: xenial - - env: POSTGRESQL_VERSION="11" POSTGIS_VERSION="2.5" - dist: xenial - - env: POSTGRESQL_VERSION="12" POSTGIS_VERSION="3" - dist: bionic - -node_js: - - "12" - -install: - - npm ci - -script: -# Ensure dev dependencies are installed - - sudo apt-get install -y libpangocairo-1.0-0 libpango1.0-dev pkg-config - -# Remove old packages - - sudo apt-get remove postgresql-$POSTGRESQL_VERSION postgresql-client-$POSTGRESQL_VERSION postgresql-server-dev-$POSTGRESQL_VERSION postgresql-common postgresql-client-common postgresql-$POSTGRESQL_VERSION-postgis-$POSTGIS_VERSION postgresql-$POSTGRESQL_VERSION-postgis-$POSTGIS_VERSION-scripts postgis - -# Install CARTO packages - - if [[ $POSTGRESQL_VERSION == '10' ]]; then sudo add-apt-repository -y ppa:cartodb/gis; fi; - - sudo add-apt-repository -y ppa:cartodb/postgresql-$POSTGRESQL_VERSION - - sudo apt-get -q update -# We use -t $TRAVIS_DIST to give preference to our ppa's (which are called as the ${dist}), instead of -# pgdg repos (which are called ${dist}-pgdg. Nasty but it works. - - sudo apt-get install -y --allow-unauthenticated --no-install-recommends --no-install-suggests postgresql-$POSTGRESQL_VERSION postgresql-client-$POSTGRESQL_VERSION postgresql-server-dev-$POSTGRESQL_VERSION postgresql-common postgresql-$POSTGRESQL_VERSION-postgis-$POSTGIS_VERSION postgresql-$POSTGRESQL_VERSION-postgis-$POSTGIS_VERSION-scripts postgis -t $TRAVIS_DIST -# For pre12, install plpython2. For PG12 install plpython3 - - if [[ $POSTGRESQL_VERSION != '12' ]]; then sudo apt-get install -y postgresql-plpython-$POSTGRESQL_VERSION python python-redis -t $TRAVIS_DIST; else sudo apt-get install -y postgresql-plpython3-12 python3 python3-redis -t $TRAVIS_DIST; fi; - -# Remove old clusters and create the new one - - for i in $(pg_lsclusters | tail -n +2 | awk '{print $1}'); do sudo pg_dropcluster --stop $i main; done; - - sudo rm -rf /etc/postgresql/$POSTGRESQL_VERSION /var/lib/postgresql/$POSTGRESQL_VERSION /var/ramfs/postgresql/$POSTGRESQL_VERSION - - sudo pg_createcluster -u postgres $POSTGRESQL_VERSION main --start -p 5432 -- --auth-local trust - - - git clone https://github.com/CartoDB/cartodb-postgresql.git - - cd cartodb-postgresql && make && sudo make install && cd .. - - - createdb template_postgis - - psql -c "CREATE EXTENSION postgis" template_postgis - - if [[ $POSTGRESQL_VERSION == '12' ]]; then psql -c "CREATE EXTENSION postgis_raster" template_postgis; fi; - - - cp config/environments/test.js.example config/environments/test.js - - npm test - -after_failure: - - pg_lsclusters - - sudo cat /var/log/postgresql/postgresql-$POSTGRESQL_VERSION-main.log diff --git a/README.md b/README.md index c7f7dde0..575cee52 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ The [`CARTO Maps API`](https://carto.com/developers/maps-api/) tiler. It extends Requirements: -* [`Node 10.x (npm 6.x)`](https://nodejs.org/dist/latest-v10.x/) -* [`PostgreSQL >= 10.0`](https://www.postgresql.org/download/) +* [`Node 12.x `](https://nodejs.org/dist/latest-v10.x/) +* [`PostgreSQL >= 11.0`](https://www.postgresql.org/download/) * [`PostGIS >= 2.4`](https://postgis.net/install/) * [`CARTO Postgres Extension >= 0.24.1`](https://github.com/CartoDB/cartodb-postgresql) * [`Redis >= 4`](https://redis.io/download) @@ -45,7 +45,11 @@ $ npm install ### Run -Create the `./config/environments/.js` file (there are `.example` files to start from). Look at `./lib/server-options.js` for more on config. +You can inject the configuration through environment variables at run time. Check the file `./config/environments/config.js` to see the ones you have available. + +While the migration to the new environment based configuration, you can still use the old method of copying a config file. To enabled the one with environment variables you need to pass `CARTO_WINDSHAFT_ENV_BASED_CONF=true`. You can use the docker image to run it. + +Old way: ```shell $ node app.js @@ -55,10 +59,26 @@ Where `` is the name of a configuration file under `./config/environments/` ### Test +You can easily run the tests against the dependencies from the `dev-env`. To do so, you need to build the test docker image: + +```shell +$ docker-compose build +``` + +Then you can run the tests like: + +```shell +$ docker-compose run windshaft-tests +``` + +It will mount your code inside a volume. In case you want to play and run `npm test` or something else you can do: + ```shell -$ npm test +$ docker-compose run --entrypoint bash windshaft-tests ``` +So you will have a bash shell inside the test container, with the code from your host. + ### Coverage ```shell diff --git a/app.js b/app.js index 3f6e9e35..eb65ad90 100755 --- a/app.js +++ b/app.js @@ -25,7 +25,12 @@ const argv = require('yargs') .argv; const environmentArg = argv._[0] || process.env.NODE_ENV || 'development'; -const configurationFile = path.resolve(argv.config || `./config/environments/${environmentArg}.js`); +let configFileName = environmentArg; +if (process.env.CARTO_WINDSHAFT_ENV_BASED_CONF) { + // we override the file with the one with env vars + configFileName = 'config'; +} +const configurationFile = path.resolve(argv.config || `./config/environments/${configFileName}.js`); global.environment = require(configurationFile); process.env.NODE_ENV = argv._[0] || process.env.NODE_ENV || global.environment.environment; diff --git a/config/environments/config.js b/config/environments/config.js new file mode 100644 index 00000000..52d3aa14 --- /dev/null +++ b/config/environments/config.js @@ -0,0 +1,411 @@ +var config = { + environment: process.env.NODE_ENV, + port: 8181, + host: null, // null on purpouse so it listens to whatever address docker assigns + // Size of the threadpool which can be used to run user code and get notified in the loop thread + // Its default size is 4, but it can be changed at startup time (the absolute maximum is 128). + // See http://docs.libuv.org/en/latest/threadpool.html + uv_threadpool_size: undefined, + // Time in milliseconds to force GC cycle. + // Disable by using <=0 value. + gc_interval: 10000, + // Regular expression pattern to extract username + // from hostname. Must have a single grabbing block. + user_from_host: process.env.CARTO_WINDSHAFT_USER_FROM_HOST || '^(.*)\\.cartodb\\.com$', + + // Base URLs for the APIs + // + // See https://github.com/CartoDB/Windshaft-cartodb/wiki/Unified-Map-API + // + // Note: each entry corresponds with an express' router. + // You must define at least one path. However, middlewares are optional. + routes: { + api: [{ + paths: [ + '/api/v1', + '/user/:user/api/v1' + ], + // Optional: attach middlewares at the begining of the router + // to perform custom operations. + middlewares: [ + function noop () { + return function noopMiddleware (req, res, next) { + next(); + }; + } + ], + // Base url for the Detached Maps API + // "/api/v1/map" is the new API, + map: [{ + paths: [ + '/map' + ], + middlewares: [] // Optional + }], + // Base url for the Templated Maps API + // "/api/v1/map/named" is the new API, + template: [{ + paths: [ + '/map/named' + ], + middlewares: [] // Optional + }] + }] + }, + + // Resource URLs expose endpoints to request/retrieve metadata associated to Maps: dataviews, analysis node status. + // + // This URLs depend on how `routes` and `user_from_host` are configured: the application can be + // configured to accept request with the {user} in the header host or in the request path. + // It also might depend on the configured cdn_url via `serverMetadata.cdn_url`. + // + // This template allows to make the endpoints generation more flexible, the template exposes the following params: + // 1. {{=it.cdn_url}}: will be used when `serverMetadata.cdn_url` exists. + // 2. {{=it.user}}: will use the username as extraced from `user_from_host` or `routes`. + // 3. {{=it.port}}: will use the `port` from this very same configuration file. + resources_url_templates: { + http: 'http://{{=it.cdn_url}}/{{=it.user}}/api/v1/map', + https: 'https://{{=it.cdn_url}}/{{=it.user}}/api/v1/map' + }, + // Specify the maximum length of the queue of pending connections for the HTTP server. + // The actual length will be determined by the OS through sysctl settings such as tcp_max_syn_backlog and somaxconn on Linux. + // The default value of this parameter is 511 (not 512). + // See: https://nodejs.org/docs/latest/api/net.html#net_server_listen + maxConnections: 128, + // Maximum number of templates per user. Unlimited by default. + maxUserTemplates: 1024, + // Seconds since "last creation" before a detached + // or template instance map expires. Or: how long do you want + // to be able to navigate the map without a reload ? + // Defaults to 7200 (2 hours) + mapConfigTTL: 7200, + // idle socket timeout, in milliseconds + socket_timeout: 600000, + enable_cors: true, + cache_enabled: true, + // Templated database username for authorized user + // Supported labels: 'user_id' (read from redis) + postgres_auth_user: process.env.CARTO_WINDSHAFT_DB_USER || 'cartodb_user_<%= user_id %>', + // Templated database password for authorized user + // Supported labels: 'user_id', 'user_password' (both read from redis) + postgres_auth_pass: '<%= user_password %>', + postgres: { + user: 'publicuser', + password: 'public', + host: process.env.CARTO_WINDSHAFT_POSTGRES_HOST || 'localhost', + port: process.env.CARTO_WINDSHAFT_POSTGRES_PORT || 5432, + pool: { + // maximum number of resources to create at any given time + size: 16, + // max milliseconds a resource can go unused before it should be destroyed + idleTimeout: 3000, + // frequency to check for idle resources + reapInterval: 1000 + } + }, + mapnik_version: undefined, + mapnik_tile_format: 'png8:m=h', + statsd: { + host: process.env.CARTO_WINDSHAFT_STATSD_HOST || 'localhost', + port: 8125, + prefix: process.env.CARTO_WINDSHAFT_STATSD_PREFIX || ':host.', // could be hostname, better not containing dots + cacheDns: true + // support all allowed node-statsd options + }, + renderer: { + // Milliseconds since last access before renderer cache item expires + cache_ttl: 60000, + statsInterval: 5000, // milliseconds between each report to statsd about number of renderers and mapnik pool status + mvt: { + // If enabled, MVTs will be generated with PostGIS directly + // If disabled, MVTs will be generated with Mapnik MVT + usePostGIS: true + }, + mapnik: { + // The size of the pool of internal mapnik backend + // This pool size is per mapnik renderer created in Windshaft's RendererFactory + // See https://github.com/CartoDB/Windshaft/blob/master/lib/windshaft/renderers/renderer_factory.js + // Important: check the configuration of uv_threadpool_size to use suitable value + poolSize: 8, + + // The maximum number of waiting clients of the pool of internal mapnik backend + // This maximum number is per mapnik renderer created in Windshaft's RendererFactory + poolMaxWaitingClients: 64, + + // Whether grainstore will use a child process or not to transform CartoCSS into Mapnik XML. + // This will prevent blocking the main thread. + useCartocssWorkers: false, + + // Metatile is the number of tiles-per-side that are going + // to be rendered at once. If all of them will be requested + // we'd have saved time. If only one will be used, we'd have + // wasted time. + metatile: 2, + + // tilelive-mapnik uses an internal cache to store tiles/grids + // generated when using metatile. This options allow to tune + // the behaviour for that internal cache. + metatileCache: { + // Time an object must stay in the cache until is removed + ttl: 0, + // Whether an object must be removed after the first hit + // Usually you want to use `true` here when ttl>0. + deleteOnHit: false + }, + + // Override metatile behaviour depending on the format + formatMetatile: { + png: 2, + 'grid.json': 1 + }, + + // Buffer size is the tickness in pixel of a buffer + // around the rendered (meta?)tile. + // + // This is important for labels and other marker that overlap tile boundaries. + // Setting to 128 ensures no render artifacts. + // 64 may have artifacts but is faster. + // Less important if we can turn metatiling on. + bufferSize: 64, + + // SQL queries will be wrapped with ST_SnapToGrid + // Snapping all points of the geometry to a regular grid + snapToGrid: false, + + // SQL queries will be wrapped with ST_ClipByBox2D + // Returning the portion of a geometry falling within a rectangle + // It will only work if snapToGrid is enabled + clipByBox2d: true, + + postgis: { + // Parameters to pass to datasource plugin of mapnik + // See http://github.com/mapnik/mapnik/wiki/PostGIS + user: 'publicuser', + password: 'public', + host: process.env.CARTO_WINDSHAFT_POSTGRES_HOST || '127.0.0.1', + port: process.env.CARTO_WINDSHAFT_POSTGRES_PORT || 5432, + extent: '-20037508.3,-20037508.3,20037508.3,20037508.3', + // max number of rows to return when querying data, 0 means no limit + row_limit: 65535, + /* + * Set persist_connection to false if you want + * database connections to be closed on renderer + * expiration (1 minute after last use). + * Setting to true (the default) would never + * close any connection for the server's lifetime + */ + persist_connection: false, + simplify_geometries: true, + use_overviews: true, // use overviews to retrieve raster + max_size: 500, + twkb_encoding: true + }, + + limits: { + // Time in milliseconds a render request can take before it fails, some notes: + // - 0 means no render limit + // - it considers metatiling, naive implementation: (render timeout) * (number of tiles in metatile) + render: 0, + // As the render request will finish even if timed out, whether it should be placed in the internal + // cache or it should be fully discarded. When placed in the internal cache another attempt to retrieve + // the same tile will result in an immediate response, however that will use a lot of more application + // memory. If we want to enforce this behaviour we have to implement a cache eviction policy for the + // internal cache. + cacheOnTimeout: true + }, + + // If enabled Mapnik will reuse the features retrieved from the database + // instead of requesting them once per style inside a layer + 'cache-features': true, + + // Require metrics to the renderer + metrics: false, + + // Options for markers attributes, ellipses and images caches + markers_symbolizer_caches: { + disabled: false + } + }, + http: { + timeout: 2000, // the timeout in ms for a http tile request + proxy: undefined, // the url for a proxy server + whitelist: [ // the whitelist of urlTemplates that can be used + '.*', // will enable any URL + 'http://{s}.example.com/{z}/{x}/{y}.png' + ], + // image to use as placeholder when urlTemplate is not in the whitelist + // if provided the http renderer will use it instead of throw an error + fallbackImage: { + type: 'fs', // 'fs' and 'url' supported + src: __dirname + '/../../assets/default-placeholder.png' + } + }, + torque: {} + }, + // anything analyses related + analysis: { + // batch configuration + batch: { + // Inline execution avoid the use of SQL API as batch endpoint + // When set to true it will run all analysis queries in series, with a direct connection to the DB + // This might be useful for: + // - testing + // - running an standalone server without any dependency on external services + inlineExecution: false, + // where the SQL API is running, it will use a custom Host header to specify the username. + endpoint: 'http://127.0.0.1:8080/api/v2/sql/job', + // the template to use for adding the host header in the batch api requests + hostHeaderTemplate: '{{=it.username}}.localhost.lan' + }, + // Define max execution time in ms for analyses or tags + // If analysis or tag are not found in redis this values will be used as default. + limits: { + moran: { timeout: 120000, maxNumberOfRows: 1e5 }, + cpu2x: { timeout: 60000 } + } + }, + millstone: { + // Needs to be writable by server user + cache_basedir: process.env.CARTO_WINDSHAFT_TILE_CACHE || '/home/ubuntu/tile_assets/' + }, + redis: { + host: process.env.CARTO_WINDSHAFT_REDIS_HOST || '127.0.0.1', + port: process.env.CARTO_WINDSHAFT_REDIS_PORT || 6379, + // Max number of connections in each pool. + // Users will be put on a queue when the limit is hit. + // Set to maxConnection to have no possible queues. + // There are currently 2 pools involved in serving + // windshaft-cartodb requests so multiply this number + // by 2 to know how many possible connections will be + // kept open by the servelsr. The default is 50. + max: 50, + returnToHead: true, // defines the behaviour of the pool: false => queue, true => stack + idleTimeoutMillis: 30000, // idle time before dropping connection + reapIntervalMillis: 1000, // time between cleanups + slowQueries: { + log: true, + elapsedThreshold: 200 + }, + slowPool: { + log: true, // whether a slow acquire must be logged or not + elapsedThreshold: 25 // the threshold to determine an slow acquire must be reported or not + }, + emitter: { + statusInterval: 5000 // time, in ms, between each status report is emitted from the pool, status is sent to statsd + }, + unwatchOnRelease: false, // Send unwatch on release, see http://github.com/CartoDB/Windshaft-cartodb/issues/161 + noReadyCheck: true // Check `no_ready_check` at https://github.com/mranney/node_redis/tree/v0.12.1#overloading + }, + // For more details about this options check https://nodejs.org/api/http.html#http_new_agent_options + httpAgent: { + keepAlive: true, + keepAliveMsecs: 1000, + maxSockets: 25, + maxFreeSockets: 256 + }, + varnish: { + host: process.env.CARTO_WINDSHAFT_VARNISH_PORT || 'localhost', + port: process.env.CARTO_WINDSHAFT_VARNISH_PORT || 6082, // the por for the telnet interface where varnish is listening to + http_port: 6081, // the port for the HTTP interface where varnish is listening to + purge_enabled: process.env.CARTO_WINDSHAFT_VARNISH_PURGE_ENABLED === 'true' || false, // whether the purge/invalidation mechanism is enabled in varnish or not + secret: 'xxx', + ttl: 86400, + fallbackTtl: 300, + layergroupTtl: 86400 // the max-age for cache-control header in layergroup responses + }, + // this [OPTIONAL] configuration enables invalidating by surrogate key in fastly + fastly: { + // whether the invalidation is enabled or not + enabled: false, + // the fastly api key + apiKey: 'wadus_api_key', + // the service that will get surrogate key invalidation + serviceId: 'wadus_service_id' + }, + // If useProfiler is true every response will be served with an + // X-Tiler-Profile header containing elapsed timing for various + // steps taken for producing the response. + useProfiler: false, + serverMetadata: { + cdn_url: { + http: 'api.cartocdn.com', + https: 'cartocdn.global.ssl.fastly.net' + } + }, + // Settings for the health check available at /health + health: { + enabled: process.env.CARTO_WINDSHAFT_HEALTH_ENABLED === 'true' || false, + username: 'localhost', + z: 0, + x: 0, + y: 0 + }, + disabled_file: 'pids/disabled', + + // Use this as a feature flags enabling/disabling mechanism + enabledFeatures: { + // whether it should intercept tile render errors an act based on them, enabled by default. + onTileErrorStrategy: false, + // whether the affected tables for a given SQL must query directly postgresql or use the SQL API + cdbQueryTablesFromPostgres: true, + // whether in mapconfig is available stats & metadata for each layer + layerStats: process.env.CARTO_WINDSHAFT_LAYERSTATS_ENABLED === 'true' || false, + // whether it should rate limit endpoints (global configuration) + rateLimitsEnabled: false, + // whether it should rate limit one or more endpoints (only if rateLimitsEnabled = true) + rateLimitsByEndpoint: { + anonymous: false, + static: false, + static_named: false, + dataview: false, + dataview_search: false, + analysis: false, + analysis_catalog: false, + tile: false, + attributes: false, + named_list: false, + named_create: false, + named_get: false, + named: false, + named_update: false, + named_delete: false, + named_tiles: false + } + }, + pubSubMetrics: { + enabled: process.env.CARTO_WINDSHAFT_METRICS_ENABLED === 'true' || false, + project_id: process.env.CARTO_WINDSHAFT_METRICS_PROJECT_ID || 'avid-wavelet-844', + credentials: '', + topic: process.env.CARTO_WINDSHAFT_METRICS_PROJECT_ID || 'raw-metric-events' + } +}; + +// override some defaults for tests +if (process.env.NODE_ENV === 'test') { + config.user_from_host = '(.*)'; + config.postgres_auth_pass = 'test_windshaft_cartodb_user_<%= user_id %>_pass'; + config.millstone.cache_basedir = '/tmp/tile_assets'; + config.postgres.user = 'test_windshaft_publicuser'; + config.resources_url_templates = { + http: 'http://{{=it.user}}.localhost.lan:{{=it.port}}/api/v1/map', + https: 'https://{{=it.user}}.localhost.lan:{{=it.port}}/api/v1/map' + }; + config.cache_enabled = false; + config.postgres_auth_user = 'test_windshaft_cartodb_user_<%= user_id %>'; + config.renderer.mapnik.postgis.twkb_encoding = false; + config.renderer.mapnik['cache-features'] = false; + config.renderer.http.whitelist = [ // the whitelist of urlTemplates that can be used + '.*', // will enable any URL + 'http://{s}.example.com/{z}/{x}/{y}.png', + // for testing purposes + 'http://{s}.basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png' + ]; + config.analysis.batch.inlineExecution = true; + config.redis.idleTimeoutMillis = 1; + config.redis.reapIntervalMillis = 1; + config.varnish.purge_enabled = false; + config.health.enabled = false; + config.enabledFeatures.layerStats = true; +} + +module.exports = config; diff --git a/docker/Dockerfile-nodejs-xenial-pg101:latest b/docker/Dockerfile-nodejs-xenial-pg101:latest deleted file mode 100644 index f61e60dc..00000000 --- a/docker/Dockerfile-nodejs-xenial-pg101:latest +++ /dev/null @@ -1,92 +0,0 @@ -FROM ubuntu:xenial - -# Use UTF8 to avoid encoding problems with pgsql -ENV LANG C.UTF-8 -ENV NPROCS 1 -ENV JOBS 1 -ENV CXX g++-4.9 -ENV PGUSER postgres - -# Add external repos -RUN set -ex \ - && apt-get update \ - && apt-get install -y \ - curl \ - software-properties-common \ - locales \ - && add-apt-repository -y ppa:ubuntu-toolchain-r/test \ - && add-apt-repository -y ppa:cartodb/postgresql-10 \ - && add-apt-repository -y ppa:cartodb/gis \ - && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash \ - && . ~/.nvm/nvm.sh \ - && locale-gen en_US.UTF-8 \ - && update-locale LANG=en_US.UTF-8 - -RUN set -ex \ - && apt-get update \ - && apt-get install -y \ - g++-4.9 \ - gcc-4.9 \ - git \ - libcairo2-dev \ - libgdal-dev \ - libgdal1i \ - libgdal20 \ - libgeos-dev \ - libgif-dev \ - libjpeg8-dev \ - libjson-c-dev \ - libpango1.0-dev \ - libpixman-1-dev \ - libproj-dev \ - libprotobuf-c-dev \ - libxml2-dev \ - gdal-bin \ - make \ - nodejs \ - protobuf-c-compiler \ - pkg-config \ - wget \ - zip \ - postgresql-10 \ - postgresql-10-plproxy \ - postgis=2.4.4.6+carto-1 \ - postgresql-10-postgis-2.4=2.4.4.6+carto-1 \ - postgresql-10-postgis-2.4-scripts=2.4.4.6+carto-1 \ - postgresql-10-postgis-scripts=2.4.4.6+carto-1 \ - postgresql-client-10 \ - postgresql-client-common \ - postgresql-common \ - postgresql-contrib \ - postgresql-plpython-10 \ - postgresql-server-dev-10 \ - && wget http://download.redis.io/releases/redis-4.0.8.tar.gz \ - && tar xvzf redis-4.0.8.tar.gz \ - && cd redis-4.0.8 \ - && make \ - && make install \ - && cd .. \ - && rm redis-4.0.8.tar.gz \ - && rm -R redis-4.0.8 \ - && apt-get purge -y wget protobuf-c-compiler \ - && apt-get autoremove -y - -# Configure PostgreSQL -RUN set -ex \ - && echo "listen_addresses='*'" >> /etc/postgresql/10/main/postgresql.conf \ - && echo "local all all trust" > /etc/postgresql/10/main/pg_hba.conf \ - && echo "host all all 0.0.0.0/0 trust" >> /etc/postgresql/10/main/pg_hba.conf \ - && echo "host all all ::1/128 trust" >> /etc/postgresql/10/main/pg_hba.conf \ - && /etc/init.d/postgresql start \ - && createdb template_postgis \ - && createuser publicuser \ - && psql -c "CREATE EXTENSION postgis" template_postgis \ - && /etc/init.d/postgresql stop - -WORKDIR /srv -EXPOSE 5858 - -COPY ./scripts/nodejs-install.sh /src/nodejs-install.sh -RUN chmod 777 /src/nodejs-install.sh -CMD /src/nodejs-install.sh - diff --git a/docker/Dockerfile-nodejs-xenial-pg1121:latest b/docker/Dockerfile-nodejs-xenial-pg1121:latest deleted file mode 100644 index 7fccc2a7..00000000 --- a/docker/Dockerfile-nodejs-xenial-pg1121:latest +++ /dev/null @@ -1,85 +0,0 @@ -FROM ubuntu:xenial - -# Use UTF8 to avoid encoding problems with pgsql -ENV LANG C.UTF-8 -ENV NPROCS 1 -ENV JOBS 1 -ENV CXX g++-4.9 -ENV PGUSER postgres - -# Add external repos -RUN set -ex \ - && apt-get update \ - && apt-get install -y \ - curl \ - software-properties-common \ - locales \ - && add-apt-repository -y ppa:ubuntu-toolchain-r/test \ - && add-apt-repository -y ppa:cartodb/postgresql-11 \ - && add-apt-repository -y ppa:cartodb/redis-next \ - && curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash \ - && . ~/.nvm/nvm.sh \ - && locale-gen en_US.UTF-8 \ - && update-locale LANG=en_US.UTF-8 - -RUN set -ex \ - && apt-get update \ - && apt-get install -y \ - g++-4.9 \ - gcc-4.9 \ - git \ - libcairo2-dev \ - libgdal-dev=2.3.2+dfsg-2build2~carto1 \ - libgdal20=2.3.2+dfsg-2build2~carto1 \ - libgeos-dev=3.7.1~carto1 \ - libgif-dev \ - libjpeg8-dev \ - libjson-c-dev \ - libpango1.0-dev \ - libpixman-1-dev \ - libproj-dev \ - libprotobuf-c-dev \ - libxml2-dev \ - gdal-bin=2.3.2+dfsg-2build2~carto1 \ - make \ - nodejs \ - protobuf-c-compiler \ - pkg-config \ - wget \ - zip \ - libopenscenegraph100v5 \ - libsfcgal1 \ - liblwgeom-2.5.0=2.5.1.4+carto-1 \ - postgresql-11 \ - postgresql-11-plproxy \ - postgis=2.5.1.4+carto-1 \ - postgresql-11-postgis-2.5=2.5.1.4+carto-1 \ - postgresql-11-postgis-2.5-scripts=2.5.1.4+carto-1 \ - postgresql-client-11 \ - postgresql-client-common \ - postgresql-common \ - postgresql-contrib \ - postgresql-plpython-11 \ - postgresql-server-dev-11 \ - redis=5:4.0.9-1carto1~xenial1 \ - && apt-get purge -y wget protobuf-c-compiler \ - && apt-get autoremove -y - -# Configure PostgreSQL -RUN set -ex \ - && echo "listen_addresses='*'" >> /etc/postgresql/11/main/postgresql.conf \ - && echo "local all all trust" > /etc/postgresql/11/main/pg_hba.conf \ - && echo "host all all 0.0.0.0/0 trust" >> /etc/postgresql/11/main/pg_hba.conf \ - && echo "host all all ::1/128 trust" >> /etc/postgresql/11/main/pg_hba.conf \ - && /etc/init.d/postgresql start \ - && createdb template_postgis \ - && createuser publicuser \ - && psql -c "CREATE EXTENSION postgis" template_postgis \ - && /etc/init.d/postgresql stop - -WORKDIR /srv -EXPOSE 5858 - -COPY ./scripts/nodejs-install.sh /src/nodejs-install.sh -RUN chmod 777 /src/nodejs-install.sh -CMD /src/nodejs-install.sh diff --git a/docker/reference.md b/docker/reference.md deleted file mode 100644 index ff8435bc..00000000 --- a/docker/reference.md +++ /dev/null @@ -1,33 +0,0 @@ -# Testing with Docker - -Before running the tests with docker, you'll need Docker installed and the docker image downloaded. - -## Install docker - -```shell -$ sudo apt install docker.io && sudo usermod -aG docker $(whoami) -``` - -## Download image - -```shell -docker pull carto/IMAGE -``` - -## Carto account - -* `https://hub.docker.com/r/carto/` - -## Update image - -* Edit the docker image file -* Build image: - * `docker build -t carto/IMAGE -f docker/DOCKER_FILE docker/` - -* Upload to docker hub: - * Login into docker hub: - * `docker login` - * Create tag: - * `docker tag carto/IMAGE carto/IMAGE` - * Upload: - * `docker push carto/IMAGE` diff --git a/docker/scripts/nodejs-install.sh b/docker/scripts/nodejs-install.sh deleted file mode 100644 index f86775a7..00000000 --- a/docker/scripts/nodejs-install.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -export NVM_DIR="$HOME/.nvm" -[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" - -if [ -z $NODEJS_VERSION ]; then - NODEJS_VERSION="10" - NODEJS_VERSION_OPTIONS="--lts" -fi - -nvm install $NODEJS_VERSION $NODEJS_VERSION_OPTIONS -nvm alias default $NODEJS_VERSION -nvm use default diff --git a/docker/scripts/test-setup.sh b/docker/scripts/test-setup.sh deleted file mode 100644 index 9d735d9a..00000000 --- a/docker/scripts/test-setup.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -/etc/init.d/postgresql start - -source /src/nodejs-install.sh - -# Install cartodb-postgresql extension -git clone https://github.com/CartoDB/cartodb-postgresql.git -cd cartodb-postgresql && make && make install && cd .. - -cp config/environments/test.js.example config/environments/test.js - -npm ci -npm test diff --git a/lib/api/api-router.js b/lib/api/api-router.js index 2e6b7153..83e462f8 100644 --- a/lib/api/api-router.js +++ b/lib/api/api-router.js @@ -199,8 +199,8 @@ module.exports = class ApiRouter { const apiRouter = router({ mergeParams: true }); const { paths, middlewares = [] } = route; - apiRouter.use(user(this.metadataBackend)); apiRouter.use(initLogger({ logger: this.serverOptions.logger })); + apiRouter.use(user(this.metadataBackend)); apiRouter.use(profiler({ enabled: this.serverOptions.useProfiler, statsClient: global.statsClient diff --git a/package-lock.json b/package-lock.json index f7135557..c3d88dd5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -337,6 +337,21 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", @@ -441,6 +456,49 @@ "json-schema-traverse": "^0.3.0" } }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, "ansi-colors": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", @@ -751,6 +809,117 @@ } } }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -790,6 +959,38 @@ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, "caching-transform": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", @@ -1022,6 +1223,18 @@ "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-1.1.1.tgz", "integrity": "sha1-m7lDSVkzbs51cAqq3+7ccYBtjAU=" }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, "cli-cursor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", @@ -1047,6 +1260,23 @@ "wrap-ansi": "^2.0.0" } }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + }, + "dependencies": { + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1096,6 +1326,49 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + } + } + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", @@ -1162,6 +1435,12 @@ } } }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, "d3": { "version": "3.5.17", "resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz", @@ -1250,6 +1529,12 @@ } } }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1309,12 +1594,27 @@ "resolved": "https://registry.npmjs.org/dot/-/dot-1.1.2.tgz", "integrity": "sha1-xzdwGfxOVQeYkosrmv62ar+h8vk=" }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, "double-ended-queue": { "version": "2.1.0-0", "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=", "dev": true }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -1444,6 +1744,12 @@ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.1.2.tgz", "integrity": "sha1-eV4lzrR/e6uyY9FRr77dktGOagc=" }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -2859,6 +3165,15 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -2889,6 +3204,15 @@ "is-glob": "^4.0.1" } }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "dev": true, + "requires": { + "ini": "^1.3.5" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -2962,6 +3286,42 @@ "node-forge": "^0.9.0" } }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + } + } + }, "graceful-fs": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", @@ -3134,6 +3494,12 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, "hasha": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", @@ -3160,6 +3526,12 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, "http-errors": { "version": "1.6.3", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", @@ -3224,6 +3596,12 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, "ignore-walk": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", @@ -3242,6 +3620,12 @@ "resolve-from": "^4.0.0" } }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3411,6 +3795,15 @@ "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", "dev": true }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", @@ -3440,12 +3833,40 @@ "is-extglob": "^2.1.1" } }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", + "dev": true + }, "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", @@ -3491,6 +3912,12 @@ "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3692,6 +4119,12 @@ "bignumber.js": "^7.0.0" } }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -3749,6 +4182,24 @@ "safe-buffer": "^5.0.1" } }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -3890,6 +4341,12 @@ "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, "lru-cache": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", @@ -4495,6 +4952,62 @@ "resolved": "https://registry.npmjs.org/node-statsd/-/node-statsd-0.1.1.tgz", "integrity": "sha1-J6WTSHY9CvegN6wqAx/vPwUQE9M=" }, + "nodemon": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz", + "integrity": "sha512-4I3YDSKXg6ltYpcnZeHompqac4E6JeAMpGm8tJnB9Y3T0ehasLa4139dJOcCrB93HHrUMsCrKtoAlXTqT5n4AQ==", + "dev": true, + "requires": { + "chokidar": "^3.2.2", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.3", + "update-notifier": "^4.1.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "nopt": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", @@ -4521,6 +5034,12 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", + "dev": true + }, "npm-bundled": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", @@ -5014,6 +5533,12 @@ "os-tmpdir": "^1.0.0" } }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, "p-defer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-3.0.0.tgz", @@ -5055,6 +5580,26 @@ "release-zalgo": "^1.0.0" } }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "packet-reader": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", @@ -5404,6 +5949,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -5470,6 +6021,12 @@ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -5485,6 +6042,15 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, "qs": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", @@ -5640,6 +6206,24 @@ "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", "dev": true }, + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, "release-zalgo": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", @@ -5707,6 +6291,15 @@ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -5779,6 +6372,23 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "send": { "version": "0.16.2", "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", @@ -6420,6 +7030,12 @@ "bintrees": "1.0.1" } }, + "term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true + }, "test-exclude": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", @@ -6626,6 +7242,12 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6662,6 +7284,26 @@ } } }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "requires": { + "nopt": "~1.0.10" + }, + "dependencies": { + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + } + } + }, "tough-cookie": { "version": "2.3.4", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", @@ -6725,6 +7367,12 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -6734,16 +7382,126 @@ "mime-types": "~2.1.24" } }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "dev": true, + "requires": { + "debug": "^2.2.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, "underscore": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, + "update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dev": true, + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -6761,6 +7519,15 @@ } } }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -6833,6 +7600,55 @@ "string-width": "^1.0.2 || 2" } }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, "window-size": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz", @@ -6906,6 +7722,12 @@ "signal-exit": "^3.0.2" } }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index c3df40c9..6cd3a4d6 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "mocha": "^7.2.0", "moment": "2.22.1", "nock": "9.2.6", + "nodemon": "^2.0.6", "nyc": "^14.1.1", "pino-pretty": "^4.0.0", "redis": "2.8.0", @@ -94,8 +95,7 @@ "posttest": "npm run test:teardown", "test:teardown": "NODE_ENV=test node test teardown", "cover": "nyc --reporter=lcov npm test", - "test:docker": "docker run -e \"NODEJS_VERSION=$NODE_VERSION\" -v `pwd`:/srv $DOCKER_IMAGE bash docker/scripts/test-setup.sh && docker ps --filter status=dead --filter status=exited -aq | xargs docker rm -v", - "docker:bash": "docker run -it -v `pwd`:/srv $DOCKER_IMAGE bash" + "dev": "NODE_ENV=development nodemon app.js" }, "engines": { "node": "^12.16.3", diff --git a/test/acceptance/multilayer-test.js b/test/acceptance/multilayer-test.js index d291d86e..9407c6b7 100644 --- a/test/acceptance/multilayer-test.js +++ b/test/acceptance/multilayer-test.js @@ -512,7 +512,11 @@ var QueryTables = require('cartodb-query-tables').queryTables; ] }; var statskey = 'user:localhost:mapviews'; - var redisStatsClient = redis.createClient(global.environment.redis.port); + var redisStatsClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); var expectedToken; // will be set on first post and checked on second var now = strftime('%Y%m%d', new Date()); step( diff --git a/test/acceptance/rate-limit-test.js b/test/acceptance/rate-limit-test.js index dc5d0cad..571fe760 100644 --- a/test/acceptance/rate-limit-test.js +++ b/test/acceptance/rate-limit-test.js @@ -164,7 +164,11 @@ describe('rate limit', function () { global.environment.enabledFeatures.rateLimitsEnabled = true; global.environment.enabledFeatures.rateLimitsByEndpoint.anonymous = true; - redisClient = redis.createClient(global.environment.redis.port); + redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); testClient = new TestClient(createMapConfig(), 1234); }); @@ -226,7 +230,11 @@ describe('rate limit middleware', function () { }); rateLimit = rateLimitMiddleware(userLimitsApi, RATE_LIMIT_ENDPOINTS_GROUPS.ANONYMOUS); - redisClient = redis.createClient(global.environment.redis.port); + redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); testClient = new TestClient(createMapConfig(), 1234); const count = 1; @@ -290,7 +298,11 @@ function rateLimitAndVectorTilesTest (usePostGIS) { global.environment.enabledFeatures.rateLimitsEnabled = true; global.environment.enabledFeatures.rateLimitsByEndpoint.tile = true; - redisClient = redis.createClient(global.environment.redis.port); + redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); const count = 1; const period = 1; const burst = 0; diff --git a/test/acceptance/templates-test.js b/test/acceptance/templates-test.js index fb4dca0b..119edaaf 100644 --- a/test/acceptance/templates-test.js +++ b/test/acceptance/templates-test.js @@ -1506,7 +1506,11 @@ describe('template_api', function () { layergroup: layergroup }; var statskey = 'user:localhost:mapviews'; - var redisStatsClient = redis.createClient(global.environment.redis.port); + var redisStatsClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); var templateId; // will be set on template post var now = strftime('%Y%m%d', new Date()); var errors = []; diff --git a/test/index.js b/test/index.js index d1e27973..12b86869 100644 --- a/test/index.js +++ b/test/index.js @@ -1,21 +1,24 @@ 'use strict'; const util = require('util'); -const path = require('path'); const exec = util.promisify(require('child_process').exec); if (!process.env.NODE_ENV) { console.error('Please set "NODE_ENV" variable, e.g.: "NODE_ENV=test"'); process.exit(1); } +let configFileName = process.env.NODE_ENV; +if (process.env.CARTO_WINDSHAFT_ENV_BASED_CONF) { + // we override the file with the one with env vars + configFileName = 'config'; +} -const environment = require(`../config/environments/${process.env.NODE_ENV}.js`); +const environment = require(`../config/environments/${configFileName}.js`); const REDIS_PORT = environment.redis.port; -const REDIS_CELL_PATH = path.resolve( - process.platform === 'darwin' - ? './test/support/libredis_cell.dylib' - : './test/support/libredis_cell.so' -); +const REDIS_HOST = environment.redis.host; + +const PGHOST = environment.postgres.host; +const PGPORT = environment.postgres.port; const TEST_USER_ID = 1; const TEST_USER = environment.postgres_auth_user.replace('<%= user_id %>', TEST_USER_ID); @@ -25,28 +28,28 @@ const PUBLIC_USER_PASSWORD = environment.postgres.password; const TEST_DB = `${TEST_USER}_db`; async function startRedis () { - await exec(`redis-server --port ${REDIS_PORT} --loadmodule ${REDIS_CELL_PATH} --logfile ${__dirname}/redis-server.log --daemonize yes`); + // await exec(`redis-server --port ${REDIS_PORT} --loadmodule ${REDIS_CELL_PATH} --logfile ${__dirname}/redis-server.log --daemonize yes`); } async function stopRedis () { - await exec(`redis-cli -p ${REDIS_PORT} shutdown`); + // await exec(`redis-cli -p ${REDIS_PORT} shutdown`); } async function dropDatabase () { await exec(`dropdb --if-exists ${TEST_DB}`, { - env: Object.assign({ PGUSER: 'postgres' }, process.env) + env: Object.assign({ PGUSER: 'postgres', PGHOST: PGHOST, PGPORT: PGPORT }, process.env) }); } async function createDatabase () { await exec(`createdb -T template_postgis -EUTF8 "${TEST_DB}"`, { - env: Object.assign({ PGUSER: 'postgres' }, process.env) + env: Object.assign({ PGUSER: 'postgres', PGHOST: PGHOST, PGPORT: PGPORT }, process.env) }); } async function createDatabaseExtension () { await exec(`psql -c "CREATE EXTENSION IF NOT EXISTS cartodb CASCADE;" ${TEST_DB}`, { - env: Object.assign({ PGUSER: 'postgres' }, process.env) + env: Object.assign({ PGUSER: 'postgres', PGHOST: PGHOST, PGPORT: PGPORT }, process.env) }); } @@ -71,7 +74,7 @@ async function populateDatabase () { `; await exec(populateDatabaseCmd, { - env: Object.assign({ PGUSER: 'postgres' }, process.env) + env: Object.assign({ PGUSER: 'postgres', PGHOST: PGHOST, PGPORT: PGPORT }, process.env) }); } @@ -82,13 +85,13 @@ async function populateRedis () { HMSET rails:users:localhost \ id ${TEST_USER_ID} \ database_name "${TEST_DB}" \ - database_host localhost \ + database_host "${PGHOST}" \ map_key 1234 HMSET rails:users:cartodb250user \ id ${TEST_USER_ID} \ database_name "${TEST_DB}" \ - database_host "localhost" \ + database_host "${PGHOST}" \ database_password "${TEST_PASSWORD}" \ map_key 4321 @@ -141,7 +144,7 @@ async function populateRedis () { database_password "public" `; - await exec(`echo "${commands}" | redis-cli -p ${REDIS_PORT} -n 5`); + await exec(`echo "${commands}" | redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} -n 5`); } async function main (args) { diff --git a/test/integration/analysis-backend-limits-test.js b/test/integration/analysis-backend-limits-test.js index 233507fe..fd9d7ec9 100644 --- a/test/integration/analysis-backend-limits-test.js +++ b/test/integration/analysis-backend-limits-test.js @@ -16,7 +16,11 @@ describe('analysis-backend limits', function () { var user = 'localhost'; beforeEach(function () { - redisClient = redis.createClient(global.environment.redis.port); + redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); keysToDelete = {}; var redisPool = new RedisPool(global.environment.redis); this.metadataBackend = cartodbRedis({ pool: redisPool }); diff --git a/test/integration/template-maps-limits-test.js b/test/integration/template-maps-limits-test.js index 2619a57a..d44f77af 100644 --- a/test/integration/template-maps-limits-test.js +++ b/test/integration/template-maps-limits-test.js @@ -30,7 +30,11 @@ describe('TemplateMaps limits', function () { }; } - var redisClient = redis.createClient(global.environment.redis.port); + var redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); var redisPool = new RedisPool(global.environment.redis); afterEach(function (done) { diff --git a/test/support/test-helper.js b/test/support/test-helper.js index 29692cdd..cc5f8716 100644 --- a/test/support/test-helper.js +++ b/test/support/test-helper.js @@ -10,8 +10,14 @@ var redis = require('redis'); const setICUEnvVariable = require('../../lib/utils/icu-data-env-setter'); // set environment specific variables -global.environment = require('../../config/environments/test'); -global.environment.name = 'test'; + +let configFileName = process.env.NODE_ENV; +if (process.env.CARTO_WINDSHAFT_ENV_BASED_CONF) { + // we override the file with the one with env vars + configFileName = 'config'; +} + +global.environment = require(`../../config/environments/${configFileName}.js`); process.env.NODE_ENV = 'test'; setICUEnvVariable(); @@ -82,7 +88,11 @@ var redisClient; beforeEach(function () { if (!redisClient) { - redisClient = redis.createClient(global.environment.redis.port); + redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); } }); @@ -145,7 +155,11 @@ function deleteRedisKeys (keysToDelete, callback) { } Object.keys(keysToDelete).forEach(function (k) { - var redisClient = redis.createClient(global.environment.redis.port); + var redisClient = redis.createClient( + { + port: global.environment.redis.port, + host: global.environment.redis.host + }); redisClient.select(keysToDelete[k], function () { redisClient.del(k, function (err, deletedKeysCount) { assert.ifError(err); diff --git a/test/unit/ported/windshaft-server-test.js b/test/unit/ported/windshaft-server-test.js index 14de3983..38a0aecc 100644 --- a/test/unit/ported/windshaft-server-test.js +++ b/test/unit/ported/windshaft-server-test.js @@ -8,7 +8,7 @@ var serverOptions = require('../../../lib/server-options'); describe('windshaft', function () { it('should have valid global environment', function () { - assert.strictEqual(global.environment.name, 'test'); + assert.strictEqual(global.environment.environment, 'test'); }); it('can instantiate a Windshaft object (configured express instance)', function () {